VirtualBox

source: vbox/trunk/src/VBox/RDP/client/scard.c@ 33656

Last change on this file since 33656 was 33656, checked in by vboxsync, 14 years ago

*: rebrand Sun (L)GPL disclaimers

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 66.6 KB
Line 
1/*
2 rdesktop: A Remote Desktop Protocol client.
3 Smart Card support
4 Copyright (C) Alexi Volkov <alexi@myrealbox.com> 2006
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19*/
20
21/*
22 * Oracle GPL Disclaimer: For the avoidance of doubt, except that if any license choice
23 * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
24 * the General Public License version 2 (GPLv2) at this time for any software where
25 * a choice of GPL license versions is made available with the language indicating
26 * that GPLv2 or any later version may be used, or where a choice of which version
27 * of the GPL is applied is otherwise unspecified.
28 */
29
30#include <stdio.h>
31#include <unistd.h>
32#include <fcntl.h>
33#include <strings.h>
34#include <sys/types.h>
35#include <time.h>
36#ifndef MAKE_PROTO
37#ifdef __APPLE__
38#include <PCSC/wintypes.h>
39#include <PCSC/pcsclite.h>
40#include <PCSC/winscard.h>
41#else
42#include <wintypes.h>
43#include <pcsclite.h>
44#include <winscard.h>
45#endif /* PCSC_OSX */
46#include "rdesktop.h"
47#include "scard.h"
48
49/* variable segment */
50
51#define SCARD_MAX_MEM 102400
52#define SCARD_AUTOALLOCATE -1
53#define OUT_STREAM_SIZE 4096
54
55#ifdef B_ENDIAN
56#define swap32(x) ((((x) & 0xff) << 24) | (((x) & 0xff00) << 8) | \
57 (((x) & 0xff0000) >> 8) | (((x) & 0xff000000) >> 24))
58
59#define swap16(x) ((((x) & 0xff) << 8) | (((x) & 0xff00) >> 8))
60#else
61#define swap32(x) (x)
62#define swap16(x) (x)
63#endif
64
65static pthread_mutex_t **scard_mutex = NULL;
66
67static uint32 curDevice = 0, curId = 0, curBytesOut = 0;
68static PSCNameMapRec nameMapList = NULL;
69static int nameMapCount = 0;
70
71static pthread_t queueHandler;
72static pthread_mutex_t queueAccess;
73static pthread_cond_t queueEmpty;
74static pthread_mutex_t hcardAccess;
75
76static PMEM_HANDLE threadListHandle = NULL;
77static PThreadListElement threadList = NULL;
78
79
80static PSCThreadData queueFirst = NULL, queueLast = NULL;
81static int threadCount = 0;
82
83static PSCHCardRec hcardFirst = NULL;
84
85static void *queue_handler_function(void *data);
86
87/* code segment */
88
89#endif /* MAKE_PROTO */
90void
91scardSetInfo(uint32 device, uint32 id, uint32 bytes_out)
92{
93 curDevice = device;
94 curId = id;
95 curBytesOut = bytes_out;
96}
97
98#ifndef MAKE_PROTO
99
100static RD_NTSTATUS
101scard_create(uint32 device_id, uint32 accessmask, uint32 sharemode, uint32 create_disposition,
102 uint32 flags_and_attributes, char *filename, RD_NTHANDLE * phandle)
103{
104 return RD_STATUS_SUCCESS;
105}
106
107static RD_NTSTATUS
108scard_close(RD_NTHANDLE handle)
109{
110 return RD_STATUS_SUCCESS;
111}
112
113static RD_NTSTATUS
114scard_read(RD_NTHANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)
115{
116 return RD_STATUS_SUCCESS;
117}
118
119static RD_NTSTATUS
120scard_write(RD_NTHANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)
121{
122 return RD_STATUS_SUCCESS;
123}
124#endif /* MAKE_PROTO */
125
126/* Enumeration of devices from rdesktop.c */
127/* returns numer of units found and initialized. */
128/* optarg looks like ':"ReaderName=ReaderAlias"' */
129/* when it arrives to this function. */
130
131int
132scard_enum_devices(uint32 * id, char *optarg)
133{
134 char *name = optarg + 1;
135 char *alias;
136 int count = 0;
137 PSCNameMapRec tmpMap;
138
139 MYPCSC_DWORD rv;
140 SCARDCONTEXT hContext;
141
142 /* code segment */
143 rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
144 if (rv != SCARD_S_SUCCESS)
145 {
146 error("scard_enum_devices: PCSC service not available\n");
147 return 0;
148 }
149 else
150 rv = SCardReleaseContext(hContext);
151
152 count = 0;
153
154 if (0 != pthread_mutex_init(&queueAccess, NULL))
155 {
156 error("scard_enum_devices: Can't initialize queue access mutex\n");
157 return 0;
158 }
159
160 if (0 != pthread_cond_init(&queueEmpty, NULL))
161 {
162 error("scard_enum_devices: Can't initialize queue control cv\n");
163 return 0;
164 }
165
166 if (0 != pthread_mutex_init(&hcardAccess, NULL))
167 {
168 error("scard_enum_devices: Can't initialize hcard list access mutex\n");
169 return 0;
170 }
171
172 if (0 !=
173 pthread_create(&queueHandler, NULL, (void *(*)(void *)) queue_handler_function, NULL))
174 {
175 error("scard_enum_devices: Can't create queue handling Thread\n");
176 return 0;
177 }
178
179 strncpy(g_rdpdr_device[*id].name, "SCARD\0\0\0", 8);
180 toupper_str(g_rdpdr_device[*id].name);
181 g_rdpdr_device[*id].local_path = "/dev/scard";
182 g_rdpdr_device[*id].pdevice_data = NULL;
183 g_rdpdr_device[*id].handle = 0;
184 g_rdpdr_device[*id].device_type = DEVICE_TYPE_SCARD;
185 count++;
186 (*id)++;
187
188 if (*optarg == ':')
189 {
190 while ((optarg = next_arg(name, ',')) && *id < RDPDR_MAX_DEVICES)
191 {
192 int len;
193 char *vendor = NULL;
194 alias = next_arg(name, '=');
195 vendor = next_arg(alias, ';');
196
197 if (strlen(name) > 0)
198 {
199 if (!strlen(alias))
200 {
201 alias = name;
202 vendor = "\0";
203 }
204
205 printf("Static/aliased Device:\n");
206 printf(" Lin name: [%s]\n", name);
207 printf(" Win name: [%s]\n", alias);
208 printf(" Vendor : [%s]\n", vendor);
209 nameMapCount++;
210
211 if (nameMapList == NULL)
212 nameMapList = xmalloc(nameMapCount * sizeof(TSCNameMapRec));
213 else
214 nameMapList =
215 xrealloc(nameMapList,
216 nameMapCount * sizeof(TSCNameMapRec));
217
218 tmpMap = nameMapList + nameMapCount - 1;
219
220 len = strlen(alias);
221 strncpy(tmpMap->alias, alias, (len > 127) ? (127) : (len));
222 len = strlen(name);
223 strncpy(tmpMap->name, name, (len > 127) ? (127) : (len));
224
225 if (vendor)
226 {
227 len = strlen(vendor);
228 if (len > 0)
229 {
230 memset(tmpMap->vendor, 0, 128);
231 strncpy(tmpMap->vendor, vendor,
232 (len > 127) ? (127) : (len));
233 }
234 else
235 tmpMap->vendor[0] = '\0';
236 }
237 else
238 tmpMap->vendor[0] = '\0';
239 }
240 name = optarg;
241 }
242 }
243
244 return count;
245}
246
247#ifndef MAKE_PROTO
248/* ---------------------------------- */
249
250/* These two functions depend heavily on the actual implementation of the smart
251 * card handle in PC/SC Lite 1.3.1. Here are the salient bits:
252 *
253 * From winscard.c:331, in SCardConnect:
254 * *phCard = RFCreateReaderHandle(rContext);
255 *
256 * RFCreateReaderHandle (readerfactory.c:1161) creates a random short (16-bit
257 * integer) and makes sure it's unique. Then it adds it to
258 * rContext->dwIdentity.
259 *
260 * From readerfactory.c:173, in RFAddReader:
261 * (sReadersContexts[dwContext])->dwIdentity =
262 * (dwContext + 1) << (sizeof(DWORD) / 2) * 8;
263 *
264 * dwContext must be less than PCSCLITE_MAX_READERS_CONTEXTS, which is defined
265 * to be 16 in the 1.3.1 release.
266 *
267 * The use of "(sizeof(DWORD) / 2) * 8" is what makes conversion necessary in
268 * order to use 64-bit card handles when talking to PC/SC Lite, and 32-bit card
269 * handles when talking with the server, without losing any data: a card handle
270 * made by a 32-bit PC/SC Lite looks like 0x00014d32, where the 4d32 is the
271 * random 16 bits, 01 is the reader context index + 1, and it's left-shifted by
272 * 16 bits (sizeof(DWORD) == 4, divided by 2 is 2, times 8 is 16.) But a 64-bit
273 * PC/SC Lite makes a card handle that looks like 0x0000000100004d32. The
274 * reader context index+1 is left-shifted 32 bits because sizeof(DWORD) is 8,
275 * not 4. This means the handle won't fit in 32 bits. (The multiplication by 8
276 * is because sizeofs are in bytes, but saying how many places to left-shift is
277 * speaking in bits.)
278 *
279 * So then. Maximum value of dwContext+1 is 17; we'll say this fits in a byte
280 * to be loose and have plenty of room. This is then left-shifted by
281 * sizeof(DWORD) / 2 * 8 - which in this file is sizeof(MYPCSC_DWORD) / 2 * 8.
282 *
283 * At any rate, if we take the handle as passed from PC/SC Lite, right-shift by
284 * sizeof(MYPCSC_DWORD) / 2, left-shift by sizeof(SERVER_DWORD) / 2, and add
285 * the lower two bytes of the value (the random number), we can fit all the
286 * information into 32 bits without losing any. Of course, any time we want to
287 * hand that back to PC/SC Lite, we'll have to expand it again. (And if
288 * sizeof(MYPCSC_DWORD) == sizeof(SERVER_DWORD), we're essentially doing
289 * nothing, which will not break anything.)
290 *
291 *
292 * - jared.jennings@eglin.af.mil, 2 Aug 2006
293 */
294
295
296static MYPCSC_SCARDHANDLE
297scHandleToMyPCSC(SERVER_SCARDHANDLE server)
298{
299 return (((MYPCSC_SCARDHANDLE) server >> (sizeof(SERVER_DWORD) * 8 / 2) & 0xffff)
300 << (sizeof(MYPCSC_DWORD) * 8 / 2)) + (server & 0xffff);
301}
302
303static SERVER_SCARDHANDLE
304scHandleToServer(MYPCSC_SCARDHANDLE mypcsc)
305{
306 return ((mypcsc >> (sizeof(MYPCSC_DWORD) * 8 / 2) & 0xffff)
307 << (sizeof(SERVER_DWORD) * 8 / 2)) + (mypcsc & 0xffff);
308}
309
310/* ---------------------------------- */
311
312static void *
313SC_xmalloc(PMEM_HANDLE * memHandle, unsigned int size)
314{
315 PMEM_HANDLE handle = NULL;
316 if (size > 0 && memHandle)
317 {
318 handle = xmalloc(size + sizeof(MEM_HANDLE));
319 if (handle)
320 {
321 handle->prevHandle = NULL;
322 handle->nextHandle = NULL;
323 handle->dataSize = size;
324 if (*memHandle)
325 {
326 handle->prevHandle = *memHandle;
327 (*memHandle)->nextHandle = handle;
328 }
329 *memHandle = handle;
330 return handle + 1;
331 }
332 else
333 return NULL;
334 }
335 else
336 return NULL;
337}
338
339static void
340SC_xfree(PMEM_HANDLE * handle, void *memptr)
341{
342 if (memptr != NULL)
343 {
344 PMEM_HANDLE lcHandle = (PMEM_HANDLE) memptr - 1;
345 if (lcHandle->dataSize > 0)
346 {
347 memset(memptr, 0, lcHandle->dataSize);
348 if (lcHandle->nextHandle)
349 lcHandle->nextHandle->prevHandle = lcHandle->prevHandle;
350 if (lcHandle->prevHandle)
351 lcHandle->prevHandle->nextHandle = lcHandle->nextHandle;
352 if (*handle == lcHandle)
353 {
354 if (lcHandle->prevHandle)
355 *handle = lcHandle->prevHandle;
356 else
357 *handle = lcHandle->nextHandle;
358 }
359 xfree(lcHandle);
360 }
361 }
362}
363
364static void
365SC_xfreeallmemory(PMEM_HANDLE * handle)
366{
367 if (handle && (*handle))
368 {
369 if ((*handle)->prevHandle)
370 {
371 (*handle)->prevHandle->nextHandle = NULL;
372 SC_xfreeallmemory(&((*handle)->prevHandle));
373 }
374 if ((*handle)->nextHandle)
375 {
376 (*handle)->nextHandle->prevHandle = NULL;
377 SC_xfreeallmemory(&((*handle)->nextHandle));
378 }
379 memset(*handle, 0, (*handle)->dataSize + sizeof(MEM_HANDLE));
380 xfree(*handle);
381 *handle = NULL;
382 }
383}
384
385/* ---------------------------------- */
386
387static char *
388getName(char *alias)
389{
390 int i;
391 PSCNameMapRec tmpMap;
392 for (i = 0, tmpMap = nameMapList; i < nameMapCount; i++, tmpMap++)
393 {
394 if (strcmp(tmpMap->alias, alias) == 0)
395 return tmpMap->name;
396 }
397 return alias;
398}
399
400static char *
401getVendor(char *name)
402{
403 int i;
404 PSCNameMapRec tmpMap;
405 for (i = 0, tmpMap = nameMapList; i < nameMapCount; i++, tmpMap++)
406 {
407 if (strcmp(tmpMap->name, name) == 0)
408 return tmpMap->vendor;
409 }
410 return NULL;
411}
412
413
414static char *
415getAlias(char *name)
416{
417 int i;
418 PSCNameMapRec tmpMap;
419 for (i = 0, tmpMap = nameMapList; i < nameMapCount; i++, tmpMap++)
420 {
421 if (strcmp(tmpMap->name, name) == 0)
422 return tmpMap->alias;
423 }
424 return name;
425}
426
427static int
428hasAlias(char *name)
429{
430 int i;
431 PSCNameMapRec tmpMap;
432 for (i = 0, tmpMap = nameMapList; i < nameMapCount; i++, tmpMap++)
433 {
434 if (strcmp(tmpMap->name, name) == 0)
435 return 1;
436 }
437 return 0;
438}
439
440static void
441inRepos(STREAM in, unsigned int read)
442{
443 SERVER_DWORD add = 4 - read % 4;
444 if (add < 4 && add > 0)
445 {
446 in_uint8s(in, add);
447 }
448}
449
450static void
451outRepos(STREAM out, unsigned int written)
452{
453 SERVER_DWORD add = (4 - written % 4) % 4;
454 if (add > 0)
455 {
456 out_uint8s(out, add);
457 }
458}
459
460
461static void
462outBufferStartWithLimit(STREAM out, int length, int highLimit)
463{
464 int header = (length < 0) ? (0) : ((length > highLimit) ? (highLimit) : (length));
465 out_uint32_le(out, header);
466 out_uint32_le(out, 0x00000001); /* Magic DWORD - any non zero */
467}
468
469
470static void
471outBufferStart(STREAM out, int length)
472{
473 outBufferStartWithLimit(out, length, 0x7FFFFFFF);
474}
475
476static void
477outBufferFinishWithLimit(STREAM out, char *buffer, unsigned int length, unsigned int highLimit)
478{
479 int header = (length < 0) ? (0) : ((length > highLimit) ? (highLimit) : (length));
480 out_uint32_le(out, header);
481
482 if (length <= 0)
483 {
484 out_uint32_le(out, 0x00000000);
485 }
486 else
487 {
488 if (header < length)
489 length = header;
490 out_uint8p(out, buffer, length);
491 outRepos(out, length);
492 }
493}
494
495static void
496outBufferFinish(STREAM out, char *buffer, unsigned int length)
497{
498 outBufferFinishWithLimit(out, buffer, length, 0x7FFFFFFF);
499}
500
501static void
502outForceAlignment(STREAM out, unsigned int seed)
503{
504 SERVER_DWORD add = (seed - (out->p - out->data) % seed) % seed;
505 if (add > 0)
506 out_uint8s(out, add);
507}
508
509static unsigned int
510inString(PMEM_HANDLE * handle, STREAM in, char **destination, SERVER_DWORD dataLength, RD_BOOL wide)
511{
512 unsigned int Result = (wide) ? (2 * dataLength) : (dataLength);
513 PMEM_HANDLE lcHandle = NULL;
514 char *buffer = SC_xmalloc(&lcHandle, Result + 2);
515 char *reader;
516
517 /* code segment */
518
519 if (wide)
520 {
521 int i;
522 in_uint8a(in, buffer, 2 * dataLength);
523 for (i = 0; i < dataLength; i++)
524 if ((buffer[2 * i] < 0) || (buffer[2 * i + 1] != 0))
525 buffer[i] = '?';
526 else
527 buffer[i] = buffer[2 * i];
528 }
529 else
530 {
531 in_uint8a(in, buffer, dataLength);
532 }
533
534 buffer[dataLength] = '\0';
535 reader = getName(buffer);
536 *destination = SC_xmalloc(handle, strlen(reader) + 1);
537 strcpy(*destination, reader);
538
539 SC_xfreeallmemory(&lcHandle);
540 return Result;
541}
542
543static unsigned int
544outString(STREAM out, char *source, RD_BOOL wide)
545{
546 PMEM_HANDLE lcHandle = NULL;
547 char *reader = getAlias(source);
548 unsigned int dataLength = strlen(reader) + 1;
549 unsigned int Result = (wide) ? (2 * dataLength) : (dataLength);
550
551 /* code segment */
552
553 if (wide)
554 {
555 int i;
556 char *buffer = SC_xmalloc(&lcHandle, Result);
557
558 for (i = 0; i < dataLength; i++)
559 {
560 if (source[i] < 0)
561 buffer[2 * i] = '?';
562 else
563 buffer[2 * i] = reader[i];
564 buffer[2 * i + 1] = '\0';
565 }
566 out_uint8p(out, buffer, 2 * dataLength);
567 }
568 else
569 {
570 out_uint8p(out, reader, dataLength);
571 }
572
573 SC_xfreeallmemory(&lcHandle);
574 return Result;
575}
576
577static void
578inReaderName(PMEM_HANDLE * handle, STREAM in, char **destination, RD_BOOL wide)
579{
580 SERVER_DWORD dataLength;
581 in->p += 0x08;
582 in_uint32_le(in, dataLength);
583 inRepos(in, inString(handle, in, destination, dataLength, wide));
584}
585
586static void
587inSkipLinked(STREAM in)
588{
589 SERVER_DWORD len;
590 in_uint32_le(in, len);
591 if (len > 0)
592 {
593 in_uint8s(in, len);
594 inRepos(in, len);
595 }
596}
597
598/* ---------------------------------- */
599/* Smart Card processing functions: */
600/* ---------------------------------- */
601
602static MYPCSC_DWORD
603SC_returnCode(MYPCSC_DWORD rc, PMEM_HANDLE * handle, STREAM in, STREAM out)
604{
605 SC_xfreeallmemory(handle);
606 out_uint8s(out, 256);
607 return rc;
608}
609
610static MYPCSC_DWORD
611SC_returnNoMemoryError(PMEM_HANDLE * handle, STREAM in, STREAM out)
612{
613 return SC_returnCode(SCARD_E_NO_MEMORY, handle, in, out);
614}
615
616static MYPCSC_DWORD
617TS_SCardEstablishContext(STREAM in, STREAM out)
618{
619 MYPCSC_DWORD rv;
620 MYPCSC_SCARDCONTEXT hContext;
621 /* code segment */
622
623 DEBUG_SCARD(("SCARD: SCardEstablishContext()\n"));
624 rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
625 if (rv)
626 {
627 DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
628 pcsc_stringify_error(rv), (unsigned int) rv));
629 }
630 else
631 {
632 DEBUG_SCARD(("SCARD: -> Success (context: 0x%08lx)\n", hContext));
633 }
634
635 out_uint32_le(out, 0x00000004);
636 out_uint32_le(out, (SERVER_DWORD) hContext); /* must not be 0 (Seems to be pointer), don't know what is this (I use hContext as value) */
637 /* i hope it's not a pointer because i just downcasted it - jlj */
638 out_uint32_le(out, 0x00000004);
639 out_uint32_le(out, (SERVER_DWORD) hContext);
640 return rv;
641}
642
643static MYPCSC_DWORD
644TS_SCardReleaseContext(STREAM in, STREAM out)
645{
646 MYPCSC_DWORD rv;
647 SERVER_SCARDCONTEXT hContext;
648
649 in->p += 0x1C;
650 in_uint32_le(in, hContext);
651 DEBUG_SCARD(("SCARD: SCardReleaseContext(context: 0x%08x)\n", (unsigned) hContext));
652 rv = SCardReleaseContext((MYPCSC_SCARDCONTEXT) hContext);
653
654 if (rv)
655 {
656 DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
657 pcsc_stringify_error(rv), (unsigned int) rv));
658 }
659 else
660 {
661 DEBUG_SCARD(("SCARD: -> Success\n"));
662 }
663
664 return rv;
665}
666
667static MYPCSC_DWORD
668TS_SCardIsValidContext(STREAM in, STREAM out)
669{
670 MYPCSC_DWORD rv;
671 SERVER_SCARDCONTEXT hContext;
672 char *readers;
673 DWORD readerCount = 1024;
674 PMEM_HANDLE lcHandle = NULL;
675
676 in->p += 0x1C;
677 in_uint32_le(in, hContext);
678 DEBUG_SCARD(("SCARD: SCardIsValidContext(context: 0x%08x)\n", (unsigned) hContext));
679 /* There is no realization of SCardIsValidContext in PC/SC Lite so we call SCardListReaders */
680
681 readers = SC_xmalloc(&lcHandle, 1024);
682 if (!readers)
683 return SC_returnNoMemoryError(&lcHandle, in, out);
684
685 rv = SCardListReaders((MYPCSC_SCARDCONTEXT) hContext, NULL, readers, &readerCount);
686
687 if (rv)
688 {
689 DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
690 pcsc_stringify_error(rv), (unsigned int) rv));
691 rv = SCARD_E_INVALID_HANDLE;
692 }
693 else
694 {
695 DEBUG_SCARD(("SCARD: -> Success\n"));
696 }
697
698 outForceAlignment(out, 8);
699 SC_xfreeallmemory(&lcHandle);
700 return rv;
701}
702
703
704static MYPCSC_DWORD
705TS_SCardListReaders(STREAM in, STREAM out, RD_BOOL wide)
706{
707#define readerArraySize 1024
708 MYPCSC_DWORD rv;
709 SERVER_SCARDCONTEXT hContext;
710 SERVER_DWORD dataLength;
711 MYPCSC_DWORD cchReaders = readerArraySize;
712 unsigned char *plen1, *plen2, *pend;
713 char *readers, *cur;
714 PMEM_HANDLE lcHandle = NULL;
715
716 in->p += 0x2C;
717 in_uint32_le(in, hContext);
718 DEBUG_SCARD(("SCARD: SCardListReaders(context: 0x%08x)\n", (unsigned) hContext));
719 plen1 = out->p;
720 out_uint32_le(out, 0x00000000); /* Temp value for data length as 0x0 */
721 out_uint32_le(out, 0x01760650);
722 plen2 = out->p;
723 out_uint32_le(out, 0x00000000); /* Temp value for data length as 0x0 */
724
725 dataLength = 0;
726 readers = SC_xmalloc(&lcHandle, readerArraySize);
727 if (!readers)
728 return SC_returnNoMemoryError(&lcHandle, in, out);
729
730
731 readers[0] = '\0';
732 readers[1] = '\0';
733 rv = SCardListReaders((MYPCSC_SCARDCONTEXT) hContext, NULL, readers, &cchReaders);
734 cur = readers;
735 if (rv != SCARD_S_SUCCESS)
736 {
737 DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
738 pcsc_stringify_error(rv), (unsigned int) rv));
739 }
740 else
741 {
742 int i;
743 PSCNameMapRec tmpMap;
744 DEBUG_SCARD(("SCARD: -> Success\n"));
745 for (i = 0, tmpMap = nameMapList; i < nameMapCount; i++, tmpMap++)
746 {
747 dataLength += outString(out, tmpMap->alias, wide);
748 }
749
750 int lenSC = strlen(cur);
751 if (lenSC == 0)
752 dataLength += outString(out, "\0", wide);
753 else
754 while (lenSC > 0)
755 {
756 if (!hasAlias(cur))
757 {
758 DEBUG_SCARD(("SCARD: \"%s\"\n", cur));
759 dataLength += outString(out, cur, wide);
760 }
761 cur = (void *) ((unsigned char *) cur + lenSC + 1);
762 lenSC = strlen(cur);
763 }
764 }
765
766 dataLength += outString(out, "\0", wide);
767 outRepos(out, dataLength);
768
769 pend = out->p;
770 out->p = plen1;
771 out_uint32_le(out, dataLength);
772 out->p = plen2;
773 out_uint32_le(out, dataLength);
774 out->p = pend;
775
776 outForceAlignment(out, 8);
777 SC_xfreeallmemory(&lcHandle);
778 return rv;
779}
780
781
782static MYPCSC_DWORD
783TS_SCardConnect(STREAM in, STREAM out, RD_BOOL wide)
784{
785 MYPCSC_DWORD rv;
786 SCARDCONTEXT hContext;
787 char *szReader;
788 SERVER_DWORD dwShareMode;
789 SERVER_DWORD dwPreferredProtocol;
790 MYPCSC_SCARDHANDLE myHCard;
791 SERVER_SCARDHANDLE hCard;
792
793 MYPCSC_DWORD dwActiveProtocol;
794 PMEM_HANDLE lcHandle = NULL;
795
796 in->p += 0x1C;
797 in_uint32_le(in, dwShareMode);
798 in_uint32_le(in, dwPreferredProtocol);
799 inReaderName(&lcHandle, in, &szReader, wide);
800 in->p += 0x04;
801 in_uint32_le(in, hContext);
802 DEBUG_SCARD(("SCARD: SCardConnect(context: 0x%08x, share: 0x%08x, proto: 0x%08x, reader: \"%s\")\n", (unsigned) hContext, (unsigned) dwShareMode, (unsigned) dwPreferredProtocol, szReader ? szReader : "NULL"));
803 rv = SCardConnect(hContext, szReader, (MYPCSC_DWORD) dwShareMode,
804 (MYPCSC_DWORD) dwPreferredProtocol, &myHCard, &dwActiveProtocol);
805 hCard = scHandleToServer(myHCard);
806 if (rv != SCARD_S_SUCCESS)
807 {
808 DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
809 pcsc_stringify_error(rv), (unsigned int) rv));
810 }
811 else
812 {
813 char *szVendor = getVendor(szReader);
814 DEBUG_SCARD(("SCARD: -> Success (hcard: 0x%08x [0x%08lx])\n",
815 (unsigned) hCard, (unsigned long) myHCard));
816 if (szVendor && (strlen(szVendor) > 0))
817 {
818 DEBUG_SCARD(("SCARD: Set Attribute ATTR_VENDOR_NAME\n"));
819 pthread_mutex_lock(&hcardAccess);
820 PSCHCardRec hcard = xmalloc(sizeof(TSCHCardRec));
821 if (hcard)
822 {
823 hcard->hCard = hCard;
824 hcard->vendor = szVendor;
825 hcard->next = NULL;
826 hcard->prev = NULL;
827
828 if (hcardFirst)
829 {
830 hcardFirst->prev = hcard;
831 hcard->next = hcardFirst;
832 }
833 hcardFirst = hcard;
834 }
835 pthread_mutex_unlock(&hcardAccess);
836 }
837 }
838
839 out_uint32_le(out, 0x00000000);
840 out_uint32_le(out, 0x00000000);
841 out_uint32_le(out, 0x00000004);
842 out_uint32_le(out, 0x016Cff34);
843 /* if the active protocol > 4 billion, this is trouble. odds are low */
844 out_uint32_le(out, (SERVER_DWORD) dwActiveProtocol);
845 out_uint32_le(out, 0x00000004);
846 out_uint32_le(out, hCard);
847
848 outForceAlignment(out, 8);
849 SC_xfreeallmemory(&lcHandle);
850 return rv;
851}
852
853static MYPCSC_DWORD
854TS_SCardReconnect(STREAM in, STREAM out)
855{
856 MYPCSC_DWORD rv;
857 SCARDCONTEXT hContext;
858 SERVER_SCARDHANDLE hCard;
859 MYPCSC_SCARDHANDLE myHCard;
860 SERVER_DWORD dwShareMode;
861 SERVER_DWORD dwPreferredProtocol;
862 SERVER_DWORD dwInitialization;
863 MYPCSC_DWORD dwActiveProtocol;
864
865 in->p += 0x20;
866 in_uint32_le(in, dwShareMode);
867 in_uint32_le(in, dwPreferredProtocol);
868 in_uint32_le(in, dwInitialization);
869 in->p += 0x04;
870 in_uint32_le(in, hContext);
871 in->p += 0x04;
872 in_uint32_le(in, hCard);
873 myHCard = scHandleToMyPCSC(hCard);
874 DEBUG_SCARD(("SCARD: SCardReconnect(context: 0x%08x, hcard: 0x%08x [0x%08lx], share: 0x%08x, proto: 0x%08x, init: 0x%08x)\n", (unsigned) hContext, (unsigned) hCard, (unsigned long) myHCard, (unsigned) dwShareMode, (unsigned) dwPreferredProtocol, (unsigned) dwInitialization));
875 rv = SCardReconnect(myHCard, (MYPCSC_DWORD) dwShareMode, (MYPCSC_DWORD) dwPreferredProtocol,
876 (MYPCSC_DWORD) dwInitialization, &dwActiveProtocol);
877 if (rv != SCARD_S_SUCCESS)
878 {
879 DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
880 pcsc_stringify_error(rv), (unsigned int) rv));
881 }
882 else
883 {
884 DEBUG_SCARD(("SCARD: -> Success (proto: 0x%08x)\n", (unsigned) dwActiveProtocol));
885 }
886
887 outForceAlignment(out, 8);
888 out_uint32_le(out, (SERVER_DWORD) dwActiveProtocol);
889 return rv;
890}
891
892static MYPCSC_DWORD
893TS_SCardDisconnect(STREAM in, STREAM out)
894{
895 MYPCSC_DWORD rv;
896 SERVER_SCARDCONTEXT hContext;
897 SERVER_SCARDHANDLE hCard;
898 MYPCSC_SCARDHANDLE myHCard;
899 SERVER_DWORD dwDisposition;
900
901 in->p += 0x20;
902 in_uint32_le(in, dwDisposition);
903 in->p += 0x04;
904 in_uint32_le(in, hContext);
905 in->p += 0x04;
906 in_uint32_le(in, hCard);
907
908 DEBUG_SCARD(("SCARD: SCardDisconnect(context: 0x%08x, hcard: 0x%08x, disposition: 0x%08x)\n", (unsigned) hContext, (unsigned) hCard, (unsigned) dwDisposition));
909
910 pthread_mutex_lock(&hcardAccess);
911 PSCHCardRec hcard = hcardFirst;
912 while (hcard)
913 {
914 if (hcard->hCard == hCard)
915 {
916 if (hcard->prev)
917 hcard->prev->next = hcard->next;
918 if (hcard->next)
919 hcard->next->prev = hcard->prev;
920 if (hcardFirst == hcard)
921 hcardFirst = hcard->next;
922 xfree(hcard);
923 break;
924 }
925 hcard = hcard->next;
926 }
927 pthread_mutex_unlock(&hcardAccess);
928
929 myHCard = scHandleToMyPCSC(hCard);
930 rv = SCardDisconnect(myHCard, (MYPCSC_DWORD) dwDisposition);
931
932 if (rv != SCARD_S_SUCCESS)
933 {
934 DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
935 pcsc_stringify_error(rv), (unsigned int) rv));
936 }
937 else
938 {
939 DEBUG_SCARD(("SCARD: -> Success\n"));
940 }
941
942 outForceAlignment(out, 8);
943 return rv;
944}
945
946static int
947needStatusRecheck(MYPCSC_DWORD rv, MYPCSC_LPSCARD_READERSTATE_A rsArray, SERVER_DWORD dwCount)
948{
949 int i, recall = 0;
950 if (rv == SCARD_S_SUCCESS)
951 {
952 MYPCSC_LPSCARD_READERSTATE_A cur;
953 for (i = 0, cur = rsArray; i < dwCount; i++, cur++)
954 {
955 if (cur->dwEventState & SCARD_STATE_UNKNOWN)
956 {
957 cur->dwCurrentState = cur->dwEventState;
958 recall++;
959 }
960 }
961 }
962 return recall;
963}
964
965static RD_BOOL
966mappedStatus(MYPCSC_DWORD code)
967{
968 code >>= 16;
969 code &= 0x0000FFFF;
970 return (code % 2);
971}
972
973static MYPCSC_DWORD
974incStatus(MYPCSC_DWORD code, RD_BOOL mapped)
975{
976 if (mapped || (code & SCARD_STATE_CHANGED))
977 {
978 MYPCSC_DWORD count = (code >> 16) & 0x0000FFFF;
979 count++;
980 if (mapped && !(count % 2))
981 count++;
982 return (code & 0x0000FFFF) | (count << 16);
983 }
984 else
985 return code;
986}
987
988static void
989copyReaderState_MyPCSCToServer(MYPCSC_LPSCARD_READERSTATE_A src, SERVER_LPSCARD_READERSTATE_A dst,
990 MYPCSC_DWORD readerCount)
991{
992 MYPCSC_LPSCARD_READERSTATE_A srcIter;
993 SERVER_LPSCARD_READERSTATE_A dstIter;
994 MYPCSC_DWORD i;
995
996 for (i = 0, srcIter = src, dstIter = dst; i < readerCount; i++, srcIter++, dstIter++)
997 {
998 dstIter->szReader = srcIter->szReader;
999 dstIter->pvUserData = srcIter->pvUserData;
1000 dstIter->dwCurrentState = srcIter->dwCurrentState;
1001 dstIter->dwEventState = srcIter->dwEventState;
1002 dstIter->cbAtr = srcIter->cbAtr;
1003 memcpy(dstIter->rgbAtr, srcIter->rgbAtr, MAX_ATR_SIZE * sizeof(unsigned char));
1004 }
1005}
1006
1007static void
1008copyReaderState_ServerToMyPCSC(SERVER_LPSCARD_READERSTATE_A src, MYPCSC_LPSCARD_READERSTATE_A dst,
1009 SERVER_DWORD readerCount)
1010{
1011 SERVER_LPSCARD_READERSTATE_A srcIter;
1012 MYPCSC_LPSCARD_READERSTATE_A dstIter;
1013 SERVER_DWORD i;
1014
1015 for (i = 0, srcIter = src, dstIter = dst; i < readerCount; i++, srcIter++, dstIter++)
1016 {
1017 dstIter->szReader = srcIter->szReader;
1018 dstIter->pvUserData = srcIter->pvUserData;
1019 dstIter->dwCurrentState = srcIter->dwCurrentState;
1020 dstIter->dwEventState = srcIter->dwEventState;
1021 dstIter->cbAtr = srcIter->cbAtr;
1022 memcpy(dstIter->rgbAtr, srcIter->rgbAtr, MAX_ATR_SIZE * sizeof(unsigned char));
1023 }
1024}
1025
1026
1027static MYPCSC_DWORD
1028TS_SCardGetStatusChange(STREAM in, STREAM out, RD_BOOL wide)
1029{
1030 MYPCSC_DWORD rv;
1031 SERVER_SCARDCONTEXT hContext;
1032 SERVER_DWORD dwTimeout;
1033 SERVER_DWORD dwCount;
1034 SERVER_LPSCARD_READERSTATE_A rsArray, cur;
1035 SERVER_DWORD *stateArray = NULL, *curState;
1036 MYPCSC_LPSCARD_READERSTATE_A myRsArray;
1037 long i;
1038 PMEM_HANDLE lcHandle = NULL;
1039#if 0
1040 RD_BOOL mapped = False;
1041#endif
1042
1043 in->p += 0x18;
1044 in_uint32_le(in, dwTimeout);
1045 in_uint32_le(in, dwCount);
1046 in->p += 0x08;
1047 in_uint32_le(in, hContext);
1048 in->p += 0x04;
1049
1050 DEBUG_SCARD(("SCARD: SCardGetStatusChange(context: 0x%08x, timeout: 0x%08x, count: %d)\n",
1051 (unsigned) hContext, (unsigned) dwTimeout, (int) dwCount));
1052
1053 if (dwCount > 0)
1054 {
1055 rsArray = SC_xmalloc(&lcHandle, dwCount * sizeof(SERVER_SCARD_READERSTATE_A));
1056 if (!rsArray)
1057 return SC_returnNoMemoryError(&lcHandle, in, out);
1058 memset(rsArray, 0, dwCount * sizeof(SERVER_SCARD_READERSTATE_A));
1059 stateArray = SC_xmalloc(&lcHandle, dwCount * sizeof(MYPCSC_DWORD));
1060 if (!stateArray)
1061 return SC_returnNoMemoryError(&lcHandle, in, out);
1062 /* skip two pointers at beginning of struct */
1063 for (i = 0, cur = (SERVER_LPSCARD_READERSTATE_A) ((unsigned char **) rsArray + 2);
1064 i < dwCount; i++, cur++)
1065 {
1066 in->p += 0x04;
1067 in_uint8a(in, cur, SERVER_SCARDSTATESIZE);
1068 }
1069
1070 for (i = 0, cur = rsArray, curState = stateArray;
1071 i < dwCount; i++, cur++, curState++)
1072 {
1073 SERVER_DWORD dataLength;
1074
1075 /* Do endian swaps... */
1076 cur->dwCurrentState = swap32(cur->dwCurrentState);
1077 cur->dwEventState = swap32(cur->dwEventState);
1078 cur->cbAtr = swap32(cur->cbAtr);
1079
1080 /* reset Current state hign bytes; */
1081 *curState = cur->dwCurrentState;
1082 cur->dwCurrentState &= 0x0000FFFF;
1083 cur->dwEventState &= 0x0000FFFF;
1084
1085#if 0
1086 if (cur->dwCurrentState == (SCARD_STATE_CHANGED | SCARD_STATE_PRESENT))
1087 {
1088 cur->dwCurrentState = 0x00000000;
1089 mapped = True;
1090 }
1091
1092 if (mappedStatus(*curState))
1093 {
1094 cur->dwCurrentState &= ~SCARD_STATE_INUSE;
1095 cur->dwEventState &= ~SCARD_STATE_INUSE;
1096
1097 if (cur->dwCurrentState & SCARD_STATE_EMPTY)
1098 {
1099 cur->dwCurrentState &= ~SCARD_STATE_EMPTY;
1100 cur->dwCurrentState |= SCARD_STATE_UNKNOWN;
1101 }
1102 }
1103#endif
1104
1105 in->p += 0x08;
1106 in_uint32_le(in, dataLength);
1107 inRepos(in,
1108 inString(&lcHandle, in, (char **) &(cur->szReader), dataLength,
1109 wide));
1110
1111 if (strcmp(cur->szReader, "\\\\?PnP?\\Notification") == 0)
1112 cur->dwCurrentState |= SCARD_STATE_IGNORE;
1113
1114 DEBUG_SCARD(("SCARD: \"%s\"\n", cur->szReader ? cur->szReader : "NULL"));
1115 DEBUG_SCARD(("SCARD: user: 0x%08x, state: 0x%08x, event: 0x%08x\n",
1116 (unsigned) cur->pvUserData, (unsigned) cur->dwCurrentState,
1117 (unsigned) cur->dwEventState));
1118 DEBUG_SCARD(("SCARD: current state: 0x%08x\n",
1119 (unsigned) *curState));
1120 }
1121 }
1122 else
1123 {
1124 rsArray = NULL;
1125 stateArray = NULL;
1126 }
1127
1128 myRsArray = SC_xmalloc(&lcHandle, dwCount * sizeof(MYPCSC_SCARD_READERSTATE_A));
1129 if (!rsArray)
1130 return SC_returnNoMemoryError(&lcHandle, in, out);
1131 memset(myRsArray, 0, dwCount * sizeof(SERVER_SCARD_READERSTATE_A));
1132 copyReaderState_ServerToMyPCSC(rsArray, myRsArray, (SERVER_DWORD) dwCount);
1133
1134 rv = SCardGetStatusChange((MYPCSC_SCARDCONTEXT) hContext, (MYPCSC_DWORD) dwTimeout,
1135 myRsArray, (MYPCSC_DWORD) dwCount);
1136 copyReaderState_MyPCSCToServer(myRsArray, rsArray, (MYPCSC_DWORD) dwCount);
1137
1138 if (rv != SCARD_S_SUCCESS)
1139 {
1140 DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
1141 pcsc_stringify_error(rv), (unsigned int) rv));
1142 }
1143 else
1144 {
1145 DEBUG_SCARD(("SCARD: -> Success\n"));
1146 }
1147
1148 out_uint32_le(out, dwCount);
1149 out_uint32_le(out, 0x00084dd8);
1150 out_uint32_le(out, dwCount);
1151
1152 for (i = 0, cur = rsArray, curState = stateArray; i < dwCount; i++, cur++, curState++)
1153 {
1154
1155 cur->dwCurrentState = (*curState);
1156 cur->dwEventState |= (*curState) & 0xFFFF0000;
1157
1158#if 0
1159 if (mapped && (cur->dwCurrentState & SCARD_STATE_PRESENT)
1160 && (cur->dwCurrentState & SCARD_STATE_CHANGED)
1161 && (cur->dwEventState & SCARD_STATE_PRESENT)
1162 && (cur->dwEventState & SCARD_STATE_CHANGED))
1163 {
1164 cur->dwEventState |= SCARD_STATE_INUSE;
1165 }
1166 else if (cur->dwEventState & SCARD_STATE_UNKNOWN)
1167 {
1168 cur->dwEventState &= ~SCARD_STATE_UNKNOWN;
1169 cur->dwEventState |= SCARD_STATE_EMPTY;
1170 mapped = True;
1171 }
1172 else if ((!mapped) && (cur->dwEventState & SCARD_STATE_INUSE))
1173 {
1174 mapped = True;
1175 cur->dwEventState &= ~SCARD_STATE_INUSE;
1176 }
1177
1178 cur->dwEventState = incStatus(cur->dwEventState, mapped);
1179#endif
1180 cur->dwEventState = incStatus(cur->dwEventState, False);
1181
1182 DEBUG_SCARD(("SCARD: \"%s\"\n", cur->szReader ? cur->szReader : "NULL"));
1183 DEBUG_SCARD(("SCARD: user: 0x%08x, state: 0x%08x, event: 0x%08x\n",
1184 (unsigned) cur->pvUserData, (unsigned) cur->dwCurrentState,
1185 (unsigned) cur->dwEventState));
1186
1187 /* Do endian swaps... */
1188 cur->dwCurrentState = swap32(cur->dwCurrentState);
1189 cur->dwEventState = swap32(cur->dwEventState);
1190 cur->cbAtr = swap32(cur->cbAtr);
1191
1192 out_uint8p(out, (void *) ((unsigned char **) cur + 2),
1193 sizeof(SERVER_SCARD_READERSTATE_A) - 2 * sizeof(unsigned char *));
1194 }
1195 outForceAlignment(out, 8);
1196 SC_xfreeallmemory(&lcHandle);
1197 return rv;
1198}
1199
1200static MYPCSC_DWORD
1201TS_SCardCancel(STREAM in, STREAM out)
1202{
1203 MYPCSC_DWORD rv;
1204 SERVER_SCARDCONTEXT hContext;
1205
1206 in->p += 0x1C;
1207 in_uint32_le(in, hContext);
1208 DEBUG_SCARD(("SCARD: SCardCancel(context: 0x%08x)\n", (unsigned) hContext));
1209 rv = SCardCancel((MYPCSC_SCARDCONTEXT) hContext);
1210 if (rv != SCARD_S_SUCCESS)
1211 {
1212 DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
1213 pcsc_stringify_error(rv), (unsigned int) rv));
1214 }
1215 else
1216 {
1217 DEBUG_SCARD(("SCARD: -> Success\n"));
1218 }
1219 outForceAlignment(out, 8);
1220 return rv;
1221}
1222
1223static MYPCSC_DWORD
1224TS_SCardLocateCardsByATR(STREAM in, STREAM out, RD_BOOL wide)
1225{
1226 int i, j, k;
1227 MYPCSC_DWORD rv;
1228 SERVER_SCARDCONTEXT hContext;
1229 /* The SCARD_ATRMASK_L struct doesn't contain any longs or DWORDs -
1230 no need to split into SERVER_ and MYPCSC_ */
1231 LPSCARD_ATRMASK_L pAtrMasks, cur;
1232 SERVER_DWORD atrMaskCount = 0;
1233 SERVER_DWORD readerCount = 0;
1234 SERVER_LPSCARD_READERSTATE_A rsArray, ResArray, rsCur;
1235 MYPCSC_LPSCARD_READERSTATE_A myRsArray;
1236 PMEM_HANDLE lcHandle = NULL;
1237
1238 in->p += 0x2C;
1239 in_uint32_le(in, hContext);
1240 in_uint32_le(in, atrMaskCount);
1241 pAtrMasks = SC_xmalloc(&lcHandle, atrMaskCount * sizeof(SCARD_ATRMASK_L));
1242 if (!pAtrMasks)
1243 return SC_returnNoMemoryError(&lcHandle, in, out);
1244 in_uint8a(in, pAtrMasks, atrMaskCount * sizeof(SCARD_ATRMASK_L));
1245
1246 in_uint32_le(in, readerCount);
1247 rsArray = SC_xmalloc(&lcHandle, readerCount * sizeof(SCARD_READERSTATE_A));
1248 if (!rsArray)
1249 return SC_returnNoMemoryError(&lcHandle, in, out);
1250 memset(rsArray, 0, readerCount * sizeof(SCARD_READERSTATE_A));
1251
1252 DEBUG_SCARD(("SCARD: SCardLocateCardsByATR(context: 0x%08x, atrs: %d, readers: %d)\n",
1253 (unsigned) hContext, (int) atrMaskCount, (int) readerCount));
1254
1255 for (i = 0, cur = pAtrMasks; i < atrMaskCount; i++, cur++)
1256 {
1257 cur->cbAtr = swap32(cur->cbAtr);
1258
1259 DEBUG_SCARD(("SCARD: ATR: "));
1260 for (j = 0; j < pAtrMasks->cbAtr; j++)
1261 {
1262 DEBUG_SCARD(("%02x%c",
1263 (unsigned) (unsigned char) cur->rgbAtr[j],
1264 (j == pAtrMasks->cbAtr - 1) ? ' ' : ':'))}
1265 DEBUG_SCARD(("\n"));
1266 DEBUG_SCARD(("SCARD: "));
1267 for (j = 0; j < pAtrMasks->cbAtr; j++)
1268 {
1269 DEBUG_SCARD(("%02x%c",
1270 (unsigned) (unsigned char) cur->rgbMask[j],
1271 (j == pAtrMasks->cbAtr - 1) ? ' ' : ':'))}
1272 DEBUG_SCARD(("\n"));
1273 }
1274
1275 for (i = 0, rsCur = (SERVER_LPSCARD_READERSTATE_A) ((unsigned char **) rsArray + 2);
1276 i < readerCount; i++, rsCur++)
1277 {
1278 in_uint8s(in, 4);
1279 in_uint8a(in, rsCur, SERVER_SCARDSTATESIZE);
1280 }
1281
1282 ResArray = SC_xmalloc(&lcHandle, readerCount * sizeof(SERVER_SCARD_READERSTATE_A));
1283 if (!ResArray)
1284 return SC_returnNoMemoryError(&lcHandle, in, out);
1285
1286 for (i = 0, rsCur = rsArray; i < readerCount; i++, rsCur++)
1287 {
1288 /* Do endian swaps... */
1289 rsCur->dwCurrentState = swap32(rsCur->dwCurrentState);
1290 rsCur->dwEventState = swap32(rsCur->dwEventState);
1291 rsCur->cbAtr = swap32(rsCur->cbAtr);
1292
1293 inReaderName(&lcHandle, in, (char **) &rsCur->szReader, wide);
1294 DEBUG_SCARD(("SCARD: \"%s\"\n", rsCur->szReader ? rsCur->szReader : "NULL"));
1295 DEBUG_SCARD(("SCARD: user: 0x%08x, state: 0x%08x, event: 0x%08x\n",
1296 (unsigned) rsCur->pvUserData, (unsigned) rsCur->dwCurrentState,
1297 (unsigned) rsCur->dwEventState));
1298 }
1299 memcpy(ResArray, rsArray, readerCount * sizeof(SERVER_SCARD_READERSTATE_A));
1300
1301 /* FIXME segfault here. */
1302 myRsArray = SC_xmalloc(&lcHandle, readerCount * sizeof(MYPCSC_SCARD_READERSTATE_A));
1303 if (!myRsArray)
1304 return SC_returnNoMemoryError(&lcHandle, in, out);
1305 copyReaderState_ServerToMyPCSC(rsArray, myRsArray, readerCount);
1306 rv = SCardGetStatusChange((MYPCSC_SCARDCONTEXT) hContext, 0x00000001, myRsArray,
1307 readerCount);
1308 copyReaderState_MyPCSCToServer(myRsArray, rsArray, readerCount);
1309 if (rv != SCARD_S_SUCCESS)
1310 {
1311 DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
1312 pcsc_stringify_error(rv), (unsigned int) rv));
1313 }
1314 else
1315 {
1316 DEBUG_SCARD(("SCARD: -> Success\n"));
1317 cur = pAtrMasks;
1318 for (i = 0, cur = pAtrMasks; i < atrMaskCount; i++, cur++)
1319 {
1320 for (j = 0, rsCur = rsArray; j < readerCount; j++, rsCur++)
1321 {
1322 RD_BOOL equal = 1;
1323 for (k = 0; k < cur->cbAtr; k++)
1324 {
1325 if ((cur->rgbAtr[k] & cur->rgbMask[k]) !=
1326 (rsCur->rgbAtr[k] & cur->rgbMask[k]))
1327 {
1328 equal = 0;
1329 break;
1330 }
1331 }
1332 if (equal)
1333 {
1334 rsCur->dwEventState |= 0x00000040; /* SCARD_STATE_ATRMATCH 0x00000040 */
1335 memcpy(ResArray + j, rsCur, sizeof(SCARD_READERSTATE_A));
1336 DEBUG_SCARD(("SCARD: \"%s\"\n",
1337 rsCur->szReader ? rsCur->szReader : "NULL"));
1338 DEBUG_SCARD(("SCARD: user: 0x%08x, state: 0x%08x, event: 0x%08x\n", (unsigned) rsCur->pvUserData, (unsigned) rsCur->dwCurrentState, (unsigned) rsCur->dwEventState));
1339 }
1340 }
1341 }
1342 }
1343
1344 out_uint32_le(out, readerCount);
1345 out_uint32_le(out, 0x00084dd8);
1346 out_uint32_le(out, readerCount);
1347
1348 for (i = 0, rsCur = ResArray; i < readerCount; i++, rsCur++)
1349 {
1350 /* Do endian swaps... */
1351 rsCur->dwCurrentState = swap32(rsCur->dwCurrentState);
1352 rsCur->dwEventState = swap32(rsCur->dwEventState);
1353 rsCur->cbAtr = swap32(rsCur->cbAtr);
1354
1355 out_uint8p(out, (void *) ((unsigned char **) rsCur + 2),
1356 sizeof(SCARD_READERSTATE_A) - 2 * sizeof(unsigned char *));
1357 }
1358
1359 outForceAlignment(out, 8);
1360 SC_xfreeallmemory(&lcHandle);
1361 return rv;
1362}
1363
1364static DWORD
1365TS_SCardBeginTransaction(STREAM in, STREAM out)
1366{
1367 MYPCSC_DWORD rv;
1368 SERVER_SCARDCONTEXT hCard;
1369 MYPCSC_SCARDCONTEXT myHCard;
1370
1371 in->p += 0x30;
1372 in_uint32_le(in, hCard);
1373 myHCard = scHandleToMyPCSC(hCard);
1374 DEBUG_SCARD(("SCARD: SCardBeginTransaction(hcard: 0x%08x [0x%08lx])\n",
1375 (unsigned) hCard, (unsigned long) myHCard));
1376 rv = SCardBeginTransaction(myHCard);
1377 if (rv != SCARD_S_SUCCESS)
1378 {
1379 DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
1380 pcsc_stringify_error(rv), (unsigned int) rv));
1381 }
1382 else
1383 {
1384 DEBUG_SCARD(("SCARD: -> Success\n"));
1385 }
1386 outForceAlignment(out, 8);
1387 return rv;
1388}
1389
1390static DWORD
1391TS_SCardEndTransaction(STREAM in, STREAM out)
1392{
1393 MYPCSC_DWORD rv;
1394 SERVER_SCARDCONTEXT hCard;
1395 MYPCSC_SCARDCONTEXT myHCard;
1396 SERVER_DWORD dwDisposition = 0;
1397
1398 in->p += 0x20;
1399 in_uint32_le(in, dwDisposition);
1400 in->p += 0x0C;
1401 in_uint32_le(in, hCard);
1402 myHCard = scHandleToMyPCSC(hCard);
1403
1404 DEBUG_SCARD(("[hCard = 0x%.8x]\n", (unsigned int) hCard));
1405 DEBUG_SCARD(("[myHCard = 0x%016lx]\n", (unsigned long) myHCard));
1406 DEBUG_SCARD(("[dwDisposition = 0x%.8x]\n", (unsigned int) dwDisposition));
1407
1408 DEBUG_SCARD(("SCARD: SCardEndTransaction(hcard: 0x%08x [0x%08lx], disposition: 0x%08x)\n",
1409 (unsigned) hCard, (unsigned long) myHCard, (unsigned) dwDisposition));
1410 rv = SCardEndTransaction(myHCard, (MYPCSC_DWORD) dwDisposition);
1411 if (rv != SCARD_S_SUCCESS)
1412 {
1413 DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
1414 pcsc_stringify_error(rv), (unsigned int) rv));
1415 }
1416 else
1417 {
1418 DEBUG_SCARD(("SCARD: -> Success\n"));
1419 }
1420 outForceAlignment(out, 8);
1421 return rv;
1422}
1423
1424
1425static void
1426copyIORequest_MyPCSCToServer(MYPCSC_LPSCARD_IO_REQUEST src, SERVER_LPSCARD_IO_REQUEST dst)
1427{
1428 unsigned char *srcBytes, *dstBytes;
1429 size_t bytesToCopy = src->cbPciLength - sizeof(MYPCSC_SCARD_IO_REQUEST);
1430 srcBytes = ((unsigned char *) src + sizeof(MYPCSC_SCARD_IO_REQUEST));
1431 dstBytes = ((unsigned char *) dst + sizeof(SERVER_SCARD_IO_REQUEST));
1432 dst->dwProtocol = swap32((uint32_t) src->dwProtocol);
1433 dst->cbPciLength = swap32((uint32_t) src->cbPciLength
1434 - sizeof(MYPCSC_SCARD_IO_REQUEST) +
1435 sizeof(SERVER_SCARD_IO_REQUEST));
1436 memcpy(dstBytes, srcBytes, bytesToCopy);
1437}
1438
1439static void
1440copyIORequest_ServerToMyPCSC(SERVER_LPSCARD_IO_REQUEST src, MYPCSC_LPSCARD_IO_REQUEST dst)
1441{
1442 unsigned char *srcBytes, *dstBytes;
1443 size_t bytesToCopy = src->cbPciLength - sizeof(SERVER_SCARD_IO_REQUEST);
1444 srcBytes = ((unsigned char *) src + sizeof(SERVER_SCARD_IO_REQUEST));
1445 dstBytes = ((unsigned char *) dst + sizeof(MYPCSC_SCARD_IO_REQUEST));
1446 dst->dwProtocol = swap32(src->dwProtocol);
1447 dst->cbPciLength = src->cbPciLength /* already correct endian */
1448 - sizeof(SERVER_SCARD_IO_REQUEST) + sizeof(MYPCSC_SCARD_IO_REQUEST);
1449 memcpy(dstBytes, srcBytes, bytesToCopy);
1450}
1451
1452
1453static DWORD
1454TS_SCardTransmit(STREAM in, STREAM out)
1455{
1456 MYPCSC_DWORD rv;
1457 SERVER_DWORD map[7], linkedLen;
1458 void *tmp;
1459 SERVER_SCARDCONTEXT hCard;
1460 MYPCSC_SCARDCONTEXT myHCard;
1461 SERVER_LPSCARD_IO_REQUEST pioSendPci, pioRecvPci;
1462 MYPCSC_LPSCARD_IO_REQUEST myPioSendPci, myPioRecvPci;
1463 unsigned char *sendBuf = NULL, *recvBuf = NULL;
1464 SERVER_DWORD cbSendLength, cbRecvLength;
1465 MYPCSC_DWORD myCbRecvLength;
1466 PMEM_HANDLE lcHandle = NULL;
1467
1468 in->p += 0x14;
1469 in_uint32_le(in, map[0]);
1470 in->p += 0x04;
1471 in_uint32_le(in, map[1]);
1472 pioSendPci = SC_xmalloc(&lcHandle, sizeof(SERVER_SCARD_IO_REQUEST));
1473 if (!pioSendPci)
1474 return SC_returnNoMemoryError(&lcHandle, in, out);
1475 in_uint8a(in, pioSendPci, sizeof(SERVER_SCARD_IO_REQUEST));
1476 in_uint32_le(in, map[2]);
1477 in_uint32_le(in, cbSendLength);
1478 in_uint32_le(in, map[3]);
1479 in_uint32_le(in, map[4]);
1480 in_uint32_le(in, map[5]);
1481 in_uint32_le(in, cbRecvLength);
1482 if (map[0] & INPUT_LINKED)
1483 inSkipLinked(in);
1484
1485 in->p += 0x04;
1486 in_uint32_le(in, hCard);
1487 myHCard = scHandleToMyPCSC(hCard);
1488
1489 if (map[2] & INPUT_LINKED)
1490 {
1491 in_uint32_le(in, linkedLen);
1492 pioSendPci->cbPciLength = linkedLen + sizeof(SERVER_SCARD_IO_REQUEST);
1493 tmp = SC_xmalloc(&lcHandle, pioSendPci->cbPciLength);
1494 if (!tmp)
1495 return SC_returnNoMemoryError(&lcHandle, in, out);
1496 in_uint8a(in, (void *) ((unsigned char *) tmp + sizeof(SERVER_SCARD_IO_REQUEST)),
1497 linkedLen);
1498 memcpy(tmp, pioSendPci, sizeof(SERVER_SCARD_IO_REQUEST));
1499 SC_xfree(&lcHandle, pioSendPci);
1500 pioSendPci = tmp;
1501 tmp = NULL;
1502 }
1503 else
1504 pioSendPci->cbPciLength = sizeof(SERVER_SCARD_IO_REQUEST);
1505
1506 if (map[3] & INPUT_LINKED)
1507 {
1508 in_uint32_le(in, linkedLen);
1509 sendBuf = SC_xmalloc(&lcHandle, linkedLen);
1510 if (!sendBuf)
1511 return SC_returnNoMemoryError(&lcHandle, in, out);
1512 in_uint8a(in, sendBuf, linkedLen);
1513 inRepos(in, linkedLen);
1514 }
1515 else
1516 sendBuf = NULL;
1517
1518 if (cbRecvLength)
1519 {
1520 recvBuf = SC_xmalloc(&lcHandle, cbRecvLength);
1521 if (!recvBuf)
1522 return SC_returnNoMemoryError(&lcHandle, in, out);
1523 }
1524
1525 if (map[4] & INPUT_LINKED)
1526 {
1527 pioRecvPci = SC_xmalloc(&lcHandle, sizeof(SERVER_SCARD_IO_REQUEST));
1528 if (!pioRecvPci)
1529 return SC_returnNoMemoryError(&lcHandle, in, out);
1530 in_uint8a(in, pioRecvPci, sizeof(SERVER_SCARD_IO_REQUEST));
1531 in_uint32_le(in, map[6]);
1532 if (map[6] & INPUT_LINKED)
1533 {
1534 in_uint32_le(in, linkedLen);
1535 pioRecvPci->cbPciLength = linkedLen + sizeof(SERVER_SCARD_IO_REQUEST);
1536 tmp = SC_xmalloc(&lcHandle, pioRecvPci->cbPciLength);
1537 if (!tmp)
1538 return SC_returnNoMemoryError(&lcHandle, in, out);
1539 in_uint8a(in,
1540 (void *) ((unsigned char *) tmp +
1541 sizeof(SERVER_SCARD_IO_REQUEST)), linkedLen);
1542 memcpy(tmp, pioRecvPci, sizeof(SERVER_SCARD_IO_REQUEST));
1543 SC_xfree(&lcHandle, pioRecvPci);
1544 pioRecvPci = tmp;
1545 tmp = NULL;
1546 }
1547 else
1548 pioRecvPci->cbPciLength = sizeof(SERVER_SCARD_IO_REQUEST);
1549 }
1550 else
1551 pioRecvPci = NULL;
1552
1553 DEBUG_SCARD(("SCARD: SCardTransmit(hcard: 0x%08x [0x%08lx], send: %d bytes, recv: %d bytes)\n", (unsigned) hCard, (unsigned long) myHCard, (int) cbSendLength, (int) cbRecvLength));
1554
1555 myCbRecvLength = cbRecvLength;
1556 myPioSendPci = SC_xmalloc(&lcHandle,
1557 sizeof(MYPCSC_SCARD_IO_REQUEST)
1558 + pioSendPci->cbPciLength - sizeof(SERVER_SCARD_IO_REQUEST));
1559 if (!myPioSendPci)
1560 return SC_returnNoMemoryError(&lcHandle, in, out);
1561 copyIORequest_ServerToMyPCSC(pioSendPci, myPioSendPci);
1562 /* always a send, not always a recv */
1563 if (pioRecvPci)
1564 {
1565 myPioRecvPci = SC_xmalloc(&lcHandle,
1566 sizeof(MYPCSC_SCARD_IO_REQUEST)
1567 + pioRecvPci->cbPciLength
1568 - sizeof(SERVER_SCARD_IO_REQUEST));
1569 if (!myPioRecvPci)
1570 return SC_returnNoMemoryError(&lcHandle, in, out);
1571 copyIORequest_ServerToMyPCSC(pioRecvPci, myPioRecvPci);
1572 }
1573 else
1574 {
1575 myPioRecvPci = NULL;
1576 }
1577 rv = SCardTransmit(myHCard, myPioSendPci, sendBuf, (MYPCSC_DWORD) cbSendLength,
1578 myPioRecvPci, recvBuf, &myCbRecvLength);
1579 cbRecvLength = myCbRecvLength;
1580
1581 /* FIXME: handle responses with length > 448 bytes */
1582 if (cbRecvLength > 448)
1583 {
1584 warning("Card response limited from %d to 448 bytes!\n", cbRecvLength);
1585 DEBUG_SCARD(("SCARD: Truncated %d to %d\n", (unsigned int) cbRecvLength, 448));
1586 cbRecvLength = 448;
1587 }
1588
1589 if (pioRecvPci)
1590 {
1591 /*
1592 * pscs-lite mishandles this structure in some cases.
1593 * make sure we only copy it if it is valid.
1594 */
1595 if (myPioRecvPci->cbPciLength >= sizeof(MYPCSC_SCARD_IO_REQUEST))
1596 copyIORequest_MyPCSCToServer(myPioRecvPci, pioRecvPci);
1597 }
1598
1599 if (rv != SCARD_S_SUCCESS)
1600 {
1601 DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
1602 pcsc_stringify_error(rv), (unsigned int) rv));
1603 }
1604 else
1605 {
1606 DEBUG_SCARD(("SCARD: -> Success (%d bytes)\n", (int) cbRecvLength));
1607#if 0
1608 if ((pioRecvPci != NULL) && (mypioRecvPci->cbPciLength > 0))
1609 {
1610 out_uint32_le(out, (DWORD) pioRecvPci); /* if not NULL, this 4 bytes indicates that pioRecvPci is present */
1611 }
1612 else
1613#endif
1614 out_uint32_le(out, 0); /* pioRecvPci 0x00; */
1615
1616 outBufferStart(out, cbRecvLength); /* start of recvBuf output */
1617
1618#if 0
1619 if ((pioRecvPci) && (mypioRecvPci->cbPciLength > 0))
1620 {
1621 out_uint32_le(out, mypioRecvPci->dwProtocol);
1622 int len = mypioRecvPci->cbPciLength - sizeof(mypioRecvPci);
1623 outBufferStartWithLimit(out, len, 12);
1624 outBufferFinishWithLimit(out,
1625 (char *) ((DWORD) pioRecvPci + sizeof(pioRecvPci)),
1626 len, 12);
1627 }
1628#endif
1629
1630 outBufferFinish(out, (char *) recvBuf, cbRecvLength);
1631 }
1632 outForceAlignment(out, 8);
1633 SC_xfreeallmemory(&lcHandle);
1634 return rv;
1635}
1636
1637static MYPCSC_DWORD
1638TS_SCardStatus(STREAM in, STREAM out, RD_BOOL wide)
1639{
1640 MYPCSC_DWORD rv;
1641 SERVER_SCARDCONTEXT hCard;
1642 MYPCSC_SCARDCONTEXT myHCard;
1643 SERVER_DWORD dwState = 0, dwProtocol = 0, dwReaderLen, dwAtrLen;
1644 MYPCSC_DWORD state, protocol, readerLen, atrLen;
1645 SERVER_DWORD dataLength;
1646 PMEM_HANDLE lcHandle = NULL;
1647 char *readerName;
1648 unsigned char *atr;
1649
1650 in->p += 0x24;
1651 in_uint32_le(in, dwReaderLen);
1652 in_uint32_le(in, dwAtrLen);
1653 in->p += 0x0C;
1654 in_uint32_le(in, hCard);
1655 in->p += 0x04;
1656 myHCard = scHandleToMyPCSC(hCard);
1657
1658 DEBUG_SCARD(("SCARD: SCardStatus(hcard: 0x%08x [0x%08lx], reader len: %d bytes, atr len: %d bytes)\n", (unsigned) hCard, (unsigned long) myHCard, (int) dwReaderLen, (int) dwAtrLen));
1659
1660 if (dwReaderLen <= 0 || dwReaderLen == SCARD_AUTOALLOCATE || dwReaderLen > SCARD_MAX_MEM)
1661 dwReaderLen = SCARD_MAX_MEM;
1662 if (dwAtrLen <= 0 || dwAtrLen == SCARD_AUTOALLOCATE || dwAtrLen > SCARD_MAX_MEM)
1663 dwAtrLen = SCARD_MAX_MEM;
1664
1665#if 1
1666 /*
1667 * Active client sometimes sends a readerlen *just* big enough
1668 * SCardStatus doesn't seem to like this. This is a workaround,
1669 * aka hack!
1670 */
1671 dwReaderLen = 200;
1672#endif
1673
1674 readerName = SC_xmalloc(&lcHandle, dwReaderLen + 2);
1675 if (!readerName)
1676 return SC_returnNoMemoryError(&lcHandle, in, out);
1677
1678 atr = SC_xmalloc(&lcHandle, dwAtrLen + 1);
1679 if (!atr)
1680 return SC_returnNoMemoryError(&lcHandle, in, out);
1681
1682 state = dwState;
1683 protocol = dwProtocol;
1684 readerLen = dwReaderLen;
1685 atrLen = dwAtrLen;
1686 rv = SCardStatus(myHCard, readerName, &readerLen, &state, &protocol, atr, &atrLen);
1687 dwAtrLen = atrLen;
1688 dwReaderLen = readerLen;
1689 dwProtocol = protocol;
1690 dwState = state;
1691
1692
1693 if (rv != SCARD_S_SUCCESS)
1694 {
1695 DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
1696 pcsc_stringify_error(rv), (unsigned int) rv));
1697 return SC_returnCode(rv, &lcHandle, in, out);
1698 }
1699 else
1700 {
1701 int i;
1702
1703 DEBUG_SCARD(("SCARD: -> Success (state: 0x%08x, proto: 0x%08x)\n",
1704 (unsigned) dwState, (unsigned) dwProtocol));
1705 DEBUG_SCARD(("SCARD: Reader: \"%s\"\n", readerName ? readerName : "NULL"));
1706 DEBUG_SCARD(("SCARD: ATR: "));
1707 for (i = 0; i < dwAtrLen; i++)
1708 {
1709 DEBUG_SCARD(("%02x%c", atr[i], (i == dwAtrLen - 1) ? ' ' : ':'));
1710 }
1711 DEBUG_SCARD(("\n"));
1712
1713 if (dwState & (SCARD_SPECIFIC | SCARD_NEGOTIABLE))
1714 dwState = 0x00000006;
1715 else
1716#if 0
1717 if (dwState & SCARD_SPECIFIC)
1718 dwState = 0x00000006;
1719 else if (dwState & SCARD_NEGOTIABLE)
1720 dwState = 0x00000005;
1721 else
1722#endif
1723 if (dwState & SCARD_POWERED)
1724 dwState = 0x00000004;
1725 else if (dwState & SCARD_SWALLOWED)
1726 dwState = 0x00000003;
1727 else if (dwState & SCARD_PRESENT)
1728 dwState = 0x00000002;
1729 else if (dwState & SCARD_ABSENT)
1730 dwState = 0x00000001;
1731 else
1732 dwState = 0x00000000;
1733
1734 void *p_len1 = out->p;
1735 out_uint32_le(out, dwReaderLen);
1736 out_uint32_le(out, 0x00020000);
1737 out_uint32_le(out, dwState);
1738 out_uint32_le(out, dwProtocol);
1739 out_uint8p(out, atr, dwAtrLen);
1740 if (dwAtrLen < 32)
1741 {
1742 out_uint8s(out, 32 - dwAtrLen);
1743 }
1744 out_uint32_le(out, dwAtrLen);
1745
1746 void *p_len2 = out->p;
1747 out_uint32_le(out, dwReaderLen);
1748 dataLength = outString(out, readerName, wide);
1749 dataLength += outString(out, "\0", wide);
1750 outRepos(out, dataLength);
1751 void *psave = out->p;
1752 out->p = p_len1;
1753 out_uint32_le(out, dataLength);
1754 out->p = p_len2;
1755 out_uint32_le(out, dataLength);
1756 out->p = psave;
1757 }
1758 outForceAlignment(out, 8);
1759 SC_xfreeallmemory(&lcHandle);
1760 return rv;
1761}
1762
1763static MYPCSC_DWORD
1764TS_SCardState(STREAM in, STREAM out)
1765{
1766 MYPCSC_DWORD rv;
1767 SERVER_SCARDCONTEXT hCard;
1768 MYPCSC_SCARDCONTEXT myHCard;
1769 SERVER_DWORD dwState = 0, dwProtocol = 0, dwReaderLen, dwAtrLen;
1770 MYPCSC_DWORD state, protocol, readerLen, atrLen;
1771 PMEM_HANDLE lcHandle = NULL;
1772 char *readerName;
1773 unsigned char *atr;
1774
1775 in->p += 0x24;
1776 in_uint32_le(in, dwAtrLen);
1777 in->p += 0x0C;
1778 in_uint32_le(in, hCard);
1779 in->p += 0x04;
1780 myHCard = scHandleToMyPCSC(hCard);
1781
1782 DEBUG_SCARD(("SCARD: SCardState(hcard: 0x%08x [0x%08lx], atr len: %d bytes)\n",
1783 (unsigned) hCard, (unsigned long) myHCard, (int) dwAtrLen));
1784
1785 dwReaderLen = SCARD_MAX_MEM;
1786 if (dwAtrLen <= 0 || dwAtrLen == SCARD_AUTOALLOCATE || dwAtrLen > SCARD_MAX_MEM)
1787 dwAtrLen = SCARD_MAX_MEM;
1788
1789 readerName = SC_xmalloc(&lcHandle, dwReaderLen + 2);
1790 if (!readerName)
1791 return SC_returnNoMemoryError(&lcHandle, in, out);
1792
1793 atr = SC_xmalloc(&lcHandle, dwAtrLen + 1);
1794 if (!atr)
1795 return SC_returnNoMemoryError(&lcHandle, in, out);
1796
1797 state = dwState;
1798 protocol = dwProtocol;
1799 readerLen = dwReaderLen;
1800 atrLen = dwAtrLen;
1801 rv = SCardStatus(myHCard, readerName, &readerLen, &state, &protocol, atr, &atrLen);
1802 dwAtrLen = atrLen;
1803 dwReaderLen = readerLen;
1804 dwProtocol = protocol;
1805 dwState = state;
1806
1807 if (rv != SCARD_S_SUCCESS)
1808 {
1809 DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
1810 pcsc_stringify_error(rv), (unsigned int) rv));
1811 return SC_returnCode(rv, &lcHandle, in, out);
1812 }
1813 else
1814 {
1815 int i;
1816
1817 DEBUG_SCARD(("SCARD: -> Success (state: 0x%08x, proto: 0x%08x)\n",
1818 (unsigned) dwState, (unsigned) dwProtocol));
1819 DEBUG_SCARD(("SCARD: ATR: "));
1820 for (i = 0; i < dwAtrLen; i++)
1821 {
1822 DEBUG_SCARD(("%02x%c", atr[i], (i == dwAtrLen - 1) ? ' ' : ':'));
1823 }
1824 DEBUG_SCARD(("\n"));
1825
1826 if (dwState & (SCARD_SPECIFIC | SCARD_NEGOTIABLE))
1827 dwState = 0x00000006;
1828 else
1829#if 0
1830 if (dwState & SCARD_SPECIFIC)
1831 dwState = 0x00000006;
1832 else if (dwState & SCARD_NEGOTIABLE)
1833 dwState = 0x00000005;
1834 else
1835#endif
1836 if (dwState & SCARD_POWERED)
1837 dwState = 0x00000004;
1838 else if (dwState & SCARD_SWALLOWED)
1839 dwState = 0x00000003;
1840 else if (dwState & SCARD_PRESENT)
1841 dwState = 0x00000002;
1842 else if (dwState & SCARD_ABSENT)
1843 dwState = 0x00000001;
1844 else
1845 dwState = 0x00000000;
1846
1847 out_uint32_le(out, dwState);
1848 out_uint32_le(out, dwProtocol);
1849 out_uint32_le(out, dwAtrLen);
1850 out_uint32_le(out, 0x00000001);
1851 out_uint32_le(out, dwAtrLen);
1852 out_uint8p(out, atr, dwAtrLen);
1853 outRepos(out, dwAtrLen);
1854 }
1855 outForceAlignment(out, 8);
1856 SC_xfreeallmemory(&lcHandle);
1857 return rv;
1858}
1859
1860
1861
1862#ifndef WITH_PCSC120
1863
1864static MYPCSC_DWORD
1865TS_SCardListReaderGroups(STREAM in, STREAM out)
1866{
1867 MYPCSC_DWORD rv;
1868 SERVER_SCARDCONTEXT hContext;
1869 SERVER_DWORD dwGroups;
1870 MYPCSC_DWORD groups;
1871 char *szGroups;
1872 PMEM_HANDLE lcHandle = NULL;
1873
1874 in->p += 0x20;
1875 in_uint32_le(in, dwGroups);
1876 in->p += 0x04;
1877 in_uint32_le(in, hContext);
1878
1879 DEBUG_SCARD(("SCARD: SCardListReaderGroups(context: 0x%08x, groups: %d)\n",
1880 (unsigned) hContext, (int) dwGroups));
1881
1882 if (dwGroups <= 0 || dwGroups == SCARD_AUTOALLOCATE || dwGroups > SCARD_MAX_MEM)
1883 dwGroups = SCARD_MAX_MEM;
1884
1885 szGroups = SC_xmalloc(&lcHandle, dwGroups);
1886 if (!szGroups)
1887 return SC_returnNoMemoryError(&lcHandle, in, out);
1888
1889 groups = dwGroups;
1890 rv = SCardListReaderGroups((MYPCSC_SCARDCONTEXT) hContext, szGroups, &groups);
1891 dwGroups = groups;
1892
1893 if (rv)
1894 {
1895 DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
1896 pcsc_stringify_error(rv), (unsigned int) rv));
1897 return SC_returnCode(rv, &lcHandle, in, out);
1898 }
1899 else
1900 {
1901 int i;
1902 char *cur;
1903
1904 DEBUG_SCARD(("SCARD: -> Success\n"));
1905 for (i = 0, cur = szGroups; i < dwGroups; i++, cur += strlen(cur) + 1)
1906 {
1907 DEBUG_SCARD(("SCARD: %s\n", cur));
1908 }
1909 }
1910
1911
1912 out_uint32_le(out, dwGroups);
1913 out_uint32_le(out, 0x00200000);
1914 out_uint32_le(out, dwGroups);
1915 out_uint8a(out, szGroups, dwGroups);
1916 outRepos(out, dwGroups);
1917 out_uint32_le(out, 0x00000000);
1918
1919 outForceAlignment(out, 8);
1920 SC_xfreeallmemory(&lcHandle);
1921 return rv;
1922}
1923
1924static MYPCSC_DWORD
1925TS_SCardGetAttrib(STREAM in, STREAM out)
1926{
1927 MYPCSC_DWORD rv;
1928 SERVER_SCARDCONTEXT hCard;
1929 MYPCSC_SCARDCONTEXT myHCard;
1930 SERVER_DWORD dwAttrId, dwAttrLen;
1931 MYPCSC_DWORD attrLen;
1932 unsigned char *pbAttr;
1933 PMEM_HANDLE lcHandle = NULL;
1934
1935 in->p += 0x20;
1936 in_uint32_le(in, dwAttrId);
1937 in->p += 0x04;
1938 in_uint32_le(in, dwAttrLen);
1939 in->p += 0x0C;
1940 in_uint32_le(in, hCard);
1941 myHCard = scHandleToMyPCSC(hCard);
1942
1943 dwAttrId = dwAttrId & 0x0000FFFF;
1944
1945 DEBUG_SCARD(("SCARD: SCardGetAttrib(hcard: 0x%08x [0x%08lx], attrib: 0x%08x (%d bytes))\n",
1946 (unsigned) hCard, (unsigned long) myHCard,
1947 (unsigned) dwAttrId, (int) dwAttrLen));
1948
1949 if (dwAttrLen > MAX_BUFFER_SIZE)
1950 dwAttrLen = MAX_BUFFER_SIZE;
1951
1952
1953 if (dwAttrLen > SCARD_AUTOALLOCATE)
1954 pbAttr = NULL;
1955 else if ((dwAttrLen < 0) || (dwAttrLen > SCARD_MAX_MEM))
1956 {
1957 dwAttrLen = SCARD_AUTOALLOCATE;
1958 pbAttr = NULL;
1959 }
1960 else
1961 {
1962 pbAttr = SC_xmalloc(&lcHandle, dwAttrLen);
1963 if (!pbAttr)
1964 return SC_returnNoMemoryError(&lcHandle, in, out);
1965 }
1966
1967 attrLen = dwAttrLen;
1968 rv = SCardGetAttrib(myHCard, (MYPCSC_DWORD) dwAttrId, pbAttr, &attrLen);
1969 dwAttrLen = attrLen;
1970
1971 if (dwAttrId == 0x00000100 && rv != SCARD_S_SUCCESS)
1972 {
1973 DEBUG_SCARD(("SCARD: Faking attribute ATTR_VENDOR_NAME\n"));
1974 pthread_mutex_lock(&hcardAccess);
1975 PSCHCardRec hcard = hcardFirst;
1976 while (hcard)
1977 {
1978 if (hcard->hCard == hCard)
1979 {
1980 dwAttrLen = strlen(hcard->vendor);
1981 memcpy(pbAttr, hcard->vendor, dwAttrLen);
1982 rv = SCARD_S_SUCCESS;
1983 break;
1984 }
1985 hcard = hcard->next;
1986 }
1987 pthread_mutex_unlock(&hcardAccess);
1988 DEBUG_SCARD(("[0x%.8x]\n", (unsigned int) rv));
1989 }
1990
1991 if (rv != SCARD_S_SUCCESS)
1992 {
1993 DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
1994 pcsc_stringify_error(rv), (unsigned int) rv));
1995 return SC_returnCode(rv, &lcHandle, in, out);
1996 }
1997 else
1998 {
1999 DEBUG_SCARD(("SCARD: -> Success (%d bytes)\n", (int) dwAttrLen));
2000
2001 out_uint32_le(out, dwAttrLen);
2002 out_uint32_le(out, 0x00000200);
2003 out_uint32_le(out, dwAttrLen);
2004 if (!pbAttr)
2005 {
2006 out_uint8s(out, dwAttrLen);
2007 }
2008 else
2009 {
2010 out_uint8p(out, pbAttr, dwAttrLen);
2011 }
2012 outRepos(out, dwAttrLen);
2013 out_uint32_le(out, 0x00000000);
2014 }
2015 outForceAlignment(out, 8);
2016 return rv;
2017}
2018
2019static MYPCSC_DWORD
2020TS_SCardSetAttrib(STREAM in, STREAM out)
2021{
2022 MYPCSC_DWORD rv;
2023 SERVER_SCARDCONTEXT hCard;
2024 MYPCSC_SCARDCONTEXT myHCard;
2025 SERVER_DWORD dwAttrId;
2026 SERVER_DWORD dwAttrLen;
2027 unsigned char *pbAttr;
2028 PMEM_HANDLE lcHandle = NULL;
2029
2030 in->p += 0x20;
2031 in_uint32_le(in, dwAttrId);
2032 in->p += 0x04;
2033 in_uint32_le(in, dwAttrLen);
2034 in->p += 0x0C;
2035 in_uint32_le(in, hCard);
2036 myHCard = scHandleToMyPCSC(hCard);
2037
2038 dwAttrId = dwAttrId & 0x0000FFFF;
2039
2040 DEBUG_SCARD(("SCARD: SCardSetAttrib(hcard: 0x%08x [0x%08lx], attrib: 0x%08x (%d bytes))\n",
2041 (unsigned) hCard, (unsigned long) myHCard,
2042 (unsigned) dwAttrId, (int) dwAttrLen));
2043
2044 if (dwAttrLen > MAX_BUFFER_SIZE)
2045 dwAttrLen = MAX_BUFFER_SIZE;
2046
2047 pbAttr = SC_xmalloc(&lcHandle, dwAttrLen);
2048 if (!pbAttr)
2049 return SC_returnNoMemoryError(&lcHandle, in, out);
2050
2051 in_uint8a(in, pbAttr, dwAttrLen);
2052 rv = SCardSetAttrib(myHCard, (MYPCSC_DWORD) dwAttrId, pbAttr, (MYPCSC_DWORD) dwAttrLen);
2053
2054 if (rv != SCARD_S_SUCCESS)
2055 {
2056 DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
2057 pcsc_stringify_error(rv), (unsigned int) rv));
2058 }
2059 else
2060 {
2061 DEBUG_SCARD(("SCARD: -> Success\n"));
2062 }
2063
2064 out_uint32_le(out, 0x00000000);
2065 out_uint32_le(out, 0x00000200);
2066 out_uint32_le(out, 0x00000000);
2067 out_uint32_le(out, 0x00000000);
2068 outForceAlignment(out, 8);
2069 SC_xfreeallmemory(&lcHandle);
2070 return rv;
2071}
2072
2073#endif
2074
2075static MYPCSC_DWORD
2076TS_SCardControl(STREAM in, STREAM out)
2077{
2078 MYPCSC_DWORD rv;
2079 SERVER_SCARDCONTEXT hContext;
2080 SERVER_SCARDHANDLE hCard;
2081 MYPCSC_SCARDHANDLE myHCard;
2082 SERVER_DWORD map[3];
2083 SERVER_DWORD dwControlCode;
2084 unsigned char *pInBuffer, *pOutBuffer;
2085 SERVER_DWORD nInBufferSize, nOutBufferSize, nOutBufferRealSize, nBytesReturned;
2086 MYPCSC_DWORD sc_nBytesReturned;
2087 PMEM_HANDLE lcHandle = NULL;
2088
2089 pInBuffer = NULL;
2090 pOutBuffer = NULL;
2091
2092 in->p += 0x14;
2093 in_uint32_le(in, map[0]);
2094 in->p += 0x04;
2095 in_uint32_le(in, map[1]);
2096 in_uint32_le(in, dwControlCode);
2097 in_uint32_le(in, nInBufferSize);
2098 in_uint32_le(in, map[2]);
2099 in->p += 0x04;
2100 in_uint32_le(in, nOutBufferSize);
2101 in->p += 0x04;
2102 in_uint32_le(in, hContext);
2103 in->p += 0x04;
2104 in_uint32_le(in, hCard);
2105 if (map[2] & INPUT_LINKED)
2106 {
2107 /* read real input size */
2108 in_uint32_le(in, nInBufferSize);
2109 pInBuffer = SC_xmalloc(&lcHandle, nInBufferSize);
2110 if (!pInBuffer)
2111 return SC_returnNoMemoryError(&lcHandle, in, out);
2112 in_uint8a(in, pInBuffer, nInBufferSize);
2113 }
2114
2115#if 0
2116 if (nOutBufferSize > 0)
2117 {
2118 nOutBufferRealSize = nOutBufferSize;
2119 }
2120 else
2121#endif
2122 nOutBufferRealSize = 1024;
2123
2124 nBytesReturned = nOutBufferRealSize;
2125
2126 nBytesReturned = nOutBufferRealSize;
2127 pOutBuffer = SC_xmalloc(&lcHandle, nOutBufferRealSize);
2128 if (!pOutBuffer)
2129 return SC_returnNoMemoryError(&lcHandle, in, out);
2130
2131 DEBUG_SCARD(("SCARD: SCardControl(context: 0x%08x, hcard: 0x%08x, code: 0x%08x, in: %d bytes, out: %d bytes)\n", (unsigned) hContext, (unsigned) hCard, (unsigned) dwControlCode, (int) nInBufferSize, (int) nOutBufferSize));
2132
2133 sc_nBytesReturned = nBytesReturned;
2134 myHCard = scHandleToMyPCSC(hCard);
2135#ifdef WITH_PCSC120
2136 rv = SCardControl(myHCard, pInBuffer, (MYPCSC_DWORD) nInBufferSize, pOutBuffer,
2137 &sc_nBytesReturned);
2138#else
2139 rv = SCardControl(myHCard, (MYPCSC_DWORD) dwControlCode, pInBuffer,
2140 (MYPCSC_DWORD) nInBufferSize, pOutBuffer,
2141 (MYPCSC_DWORD) nOutBufferRealSize, &sc_nBytesReturned);
2142#endif
2143 nBytesReturned = sc_nBytesReturned;
2144
2145 if (rv != SCARD_S_SUCCESS)
2146 {
2147 DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
2148 pcsc_stringify_error(rv), (unsigned int) rv));
2149 }
2150 else
2151 {
2152 DEBUG_SCARD(("SCARD: -> Success (out: %d bytes)\n", (int) nBytesReturned));
2153 }
2154
2155 out_uint32_le(out, nBytesReturned);
2156 out_uint32_le(out, 0x00000004);
2157 out_uint32_le(out, nBytesReturned);
2158 if (nBytesReturned > 0)
2159 {
2160 out_uint8p(out, pOutBuffer, nBytesReturned);
2161 outRepos(out, nBytesReturned);
2162 }
2163
2164 outForceAlignment(out, 8);
2165 SC_xfreeallmemory(&lcHandle);
2166 return rv;
2167}
2168
2169static MYPCSC_DWORD
2170TS_SCardAccessStartedEvent(STREAM in, STREAM out)
2171{
2172 DEBUG_SCARD(("SCARD: SCardAccessStartedEvent()\n"));
2173 out_uint8s(out, 8);
2174 return SCARD_S_SUCCESS;
2175}
2176
2177
2178static RD_NTSTATUS
2179scard_device_control(RD_NTHANDLE handle, uint32 request, STREAM in, STREAM out)
2180{
2181 SERVER_DWORD Result = 0x00000000;
2182 unsigned char *psize, *pend, *pStatusCode;
2183 SERVER_DWORD addToEnd = 0;
2184
2185 /* Processing request */
2186
2187 out_uint32_le(out, 0x00081001); /* Header lines */
2188 out_uint32_le(out, 0xCCCCCCCC);
2189 psize = out->p;
2190 out_uint32_le(out, 0x00000000); /* Size of data portion */
2191 out_uint32_le(out, 0x00000000); /* Zero bytes (may be usefull) */
2192 pStatusCode = out->p;
2193 out_uint32_le(out, 0x00000000); /* Status Code */
2194
2195 switch (request)
2196 {
2197 /* SCardEstablishContext */
2198 case SC_ESTABLISH_CONTEXT:
2199 {
2200 Result = (SERVER_DWORD) TS_SCardEstablishContext(in, out);
2201 break;
2202 }
2203 /* SCardReleaseContext */
2204 case SC_RELEASE_CONTEXT:
2205 {
2206 Result = (SERVER_DWORD) TS_SCardReleaseContext(in, out);
2207 break;
2208 }
2209 /* SCardIsValidContext */
2210 case SC_IS_VALID_CONTEXT:
2211 {
2212 Result = (SERVER_DWORD) TS_SCardIsValidContext(in, out);
2213 break;
2214 }
2215 /* SCardListReaders */
2216 case SC_LIST_READERS: /* SCardListReadersA */
2217 case SC_LIST_READERS + 4: /* SCardListReadersW */
2218 {
2219 RD_BOOL wide = request != SC_LIST_READERS;
2220 Result = (SERVER_DWORD) TS_SCardListReaders(in, out, wide);
2221 break;
2222 }
2223 /* ScardConnect */
2224 case SC_CONNECT: /* ScardConnectA */
2225 case SC_CONNECT + 4: /* SCardConnectW */
2226 {
2227 RD_BOOL wide = request != SC_CONNECT;
2228 Result = (SERVER_DWORD) TS_SCardConnect(in, out, wide);
2229 break;
2230 }
2231 /* ScardReconnect */
2232 case SC_RECONNECT:
2233 {
2234 Result = (SERVER_DWORD) TS_SCardReconnect(in, out);
2235 break;
2236 }
2237 /* ScardDisconnect */
2238 case SC_DISCONNECT:
2239 {
2240 Result = (SERVER_DWORD) TS_SCardDisconnect(in, out);
2241 break;
2242 }
2243 /* ScardGetStatusChange */
2244 case SC_GET_STATUS_CHANGE: /* SCardGetStatusChangeA */
2245 case SC_GET_STATUS_CHANGE + 4: /* SCardGetStatusChangeW */
2246 {
2247 RD_BOOL wide = request != SC_GET_STATUS_CHANGE;
2248 Result = (SERVER_DWORD) TS_SCardGetStatusChange(in, out, wide);
2249 break;
2250 }
2251 /* SCardCancel */
2252 case SC_CANCEL:
2253 {
2254 Result = (SERVER_DWORD) TS_SCardCancel(in, out);
2255 break;
2256 }
2257 /* SCardLocateCardsByATR */
2258 case SC_LOCATE_CARDS_BY_ATR: /* SCardLocateCardsByATRA */
2259 case SC_LOCATE_CARDS_BY_ATR + 4: /* SCardLocateCardsByATRW */
2260 {
2261 RD_BOOL wide = request != SC_LOCATE_CARDS_BY_ATR;
2262 Result = (SERVER_DWORD) TS_SCardLocateCardsByATR(in, out, wide);
2263 break;
2264 }
2265 /* SCardBeginTransaction */
2266 case SC_BEGIN_TRANSACTION:
2267 {
2268 Result = (SERVER_DWORD) TS_SCardBeginTransaction(in, out);
2269 break;
2270 }
2271 /* SCardBeginTransaction */
2272 case SC_END_TRANSACTION:
2273 {
2274 Result = (SERVER_DWORD) TS_SCardEndTransaction(in, out);
2275 break;
2276 }
2277 /* ScardTransmit */
2278 case SC_TRANSMIT:
2279 {
2280 Result = (SERVER_DWORD) TS_SCardTransmit(in, out);
2281 break;
2282 }
2283 /* SCardControl */
2284 case SC_CONTROL:
2285 {
2286 Result = (SERVER_DWORD) TS_SCardControl(in, out);
2287 break;
2288 }
2289 /* SCardGetAttrib */
2290#ifndef WITH_PCSC120
2291 case SC_GETATTRIB:
2292 {
2293 Result = (SERVER_DWORD) TS_SCardGetAttrib(in, out);
2294 break;
2295 }
2296#endif
2297 case SC_ACCESS_STARTED_EVENT:
2298 {
2299 Result = (SERVER_DWORD) TS_SCardAccessStartedEvent(in, out);
2300 break;
2301 }
2302 case SC_STATUS: /* SCardStatusA */
2303 case SC_STATUS + 4: /* SCardStatusW */
2304 {
2305 RD_BOOL wide = request != SC_STATUS;
2306 Result = (SERVER_DWORD) TS_SCardStatus(in, out, wide);
2307 break;
2308 }
2309 case SC_STATE: /* SCardState */
2310 {
2311 Result = (SERVER_DWORD) TS_SCardState(in, out);
2312 break;
2313 }
2314 default:
2315 {
2316 warning("SCARD: Unknown function %d\n", (int) request);
2317 Result = 0x80100014;
2318 out_uint8s(out, 256);
2319 break;
2320 }
2321 }
2322
2323#if 0
2324 out_uint32_le(out, 0x00000000);
2325#endif
2326 /* Setting modified variables */
2327 pend = out->p;
2328 /* setting data size */
2329 out->p = psize;
2330 out_uint32_le(out, pend - psize - 16);
2331 /* setting status code */
2332 out->p = pStatusCode;
2333 out_uint32_le(out, Result);
2334 /* finish */
2335 out->p = pend;
2336
2337 addToEnd = (pend - pStatusCode) % 16;
2338 if (addToEnd < 16 && addToEnd > 0)
2339 {
2340 out_uint8s(out, addToEnd);
2341 }
2342
2343 return RD_STATUS_SUCCESS;
2344}
2345
2346/* Thread functions */
2347
2348static STREAM
2349duplicateStream(PMEM_HANDLE * handle, STREAM s, uint32 buffer_size, RD_BOOL isInputStream)
2350{
2351 STREAM d = SC_xmalloc(handle, sizeof(struct stream));
2352 if (d != NULL)
2353 {
2354 if (isInputStream)
2355 d->size = (size_t) (s->end) - (size_t) (s->data);
2356 else if (buffer_size < s->size)
2357 d->size = s->size;
2358 else
2359 d->size = buffer_size;
2360
2361 d->data = SC_xmalloc(handle, d->size);
2362
2363 d->end = (void *) ((size_t) (d->data) + (size_t) (s->end) - (size_t) (s->data));
2364 d->p = (void *) ((size_t) (d->data) + (size_t) (s->p) - (size_t) (s->data));
2365 d->iso_hdr =
2366 (void *) ((size_t) (d->data) + (size_t) (s->iso_hdr) - (size_t) (s->data));
2367 d->mcs_hdr =
2368 (void *) ((size_t) (d->data) + (size_t) (s->mcs_hdr) - (size_t) (s->data));
2369 d->sec_hdr =
2370 (void *) ((size_t) (d->data) + (size_t) (s->sec_hdr) - (size_t) (s->data));
2371 d->sec_hdr =
2372 (void *) ((size_t) (d->data) + (size_t) (s->sec_hdr) - (size_t) (s->data));
2373 d->rdp_hdr =
2374 (void *) ((size_t) (d->data) + (size_t) (s->rdp_hdr) - (size_t) (s->data));
2375 d->channel_hdr =
2376 (void *) ((size_t) (d->data) + (size_t) (s->channel_hdr) -
2377 (size_t) (s->data));
2378 if (isInputStream)
2379 memcpy(d->data, s->data, (size_t) (s->end) - (size_t) (s->data));
2380 else
2381 memcpy(d->data, s->data, (size_t) (s->p) - (size_t) (s->data));
2382 }
2383 return d;
2384}
2385
2386static void
2387freeStream(PMEM_HANDLE * handle, STREAM s)
2388{
2389 if (s != NULL)
2390 {
2391 if (s->data != NULL)
2392 SC_xfree(handle, s->data);
2393 SC_xfree(handle, s);
2394 }
2395}
2396
2397static PSCThreadData
2398SC_addToQueue(RD_NTHANDLE handle, uint32 request, STREAM in, STREAM out)
2399{
2400 PMEM_HANDLE lcHandle = NULL;
2401 PSCThreadData data = SC_xmalloc(&lcHandle, sizeof(TSCThreadData));
2402
2403 if (!data)
2404 return NULL;
2405 else
2406 {
2407 data->memHandle = lcHandle;
2408 data->device = curDevice;
2409 data->id = curId;
2410 data->handle = handle;
2411 data->request = request;
2412 data->in = duplicateStream(&(data->memHandle), in, 0, SC_TRUE);
2413 if (data->in == NULL)
2414 {
2415 SC_xfreeallmemory(&(data->memHandle));
2416 return NULL;
2417 }
2418 data->out =
2419 duplicateStream(&(data->memHandle), out, OUT_STREAM_SIZE + curBytesOut,
2420 SC_FALSE);
2421 if (data->out == NULL)
2422 {
2423 SC_xfreeallmemory(&(data->memHandle));
2424 return NULL;
2425 }
2426 data->next = NULL;
2427
2428 pthread_mutex_lock(&queueAccess);
2429
2430 if (queueLast)
2431 queueLast->next = data;
2432 queueLast = data;
2433 if (!queueFirst)
2434 queueFirst = data;
2435
2436 pthread_cond_broadcast(&queueEmpty);
2437 pthread_mutex_unlock(&queueAccess);
2438 }
2439 return data;
2440}
2441
2442static void
2443SC_destroyThreadData(PSCThreadData data)
2444{
2445 if (data)
2446 {
2447 PMEM_HANDLE handle = data->memHandle;
2448 SC_xfreeallmemory(&handle);
2449 }
2450}
2451
2452static PSCThreadData
2453SC_getNextInQueue()
2454{
2455 PSCThreadData Result = NULL;
2456
2457 pthread_mutex_lock(&queueAccess);
2458
2459 while (queueFirst == NULL)
2460 pthread_cond_wait(&queueEmpty, &queueAccess);
2461
2462 Result = queueFirst;
2463 queueFirst = queueFirst->next;
2464 if (!queueFirst)
2465 {
2466 queueLast = NULL;
2467 }
2468 Result->next = NULL;
2469
2470 pthread_mutex_unlock(&queueAccess);
2471
2472 return Result;
2473}
2474
2475static void
2476SC_deviceControl(PSCThreadData data)
2477{
2478 size_t buffer_len = 0;
2479 scard_device_control(data->handle, data->request, data->in, data->out);
2480 buffer_len = (size_t) data->out->p - (size_t) data->out->data;
2481 rdpdr_send_completion(data->device, data->id, 0, buffer_len, data->out->data, buffer_len);
2482 SC_destroyThreadData(data);
2483}
2484
2485
2486static void *
2487thread_function(PThreadListElement listElement)
2488{
2489 pthread_mutex_lock(&listElement->busy);
2490 while (1)
2491 {
2492 while (listElement->data == NULL)
2493 pthread_cond_wait(&listElement->nodata, &listElement->busy);
2494
2495 SC_deviceControl(listElement->data);
2496 listElement->data = NULL;
2497 }
2498 pthread_mutex_unlock(&listElement->busy);
2499
2500 pthread_exit(NULL);
2501 return NULL;
2502}
2503
2504static void
2505SC_handleRequest(PSCThreadData data)
2506{
2507 int Result = 0;
2508 PThreadListElement cur;
2509
2510 for (cur = threadList; cur != NULL; cur = cur->next)
2511 {
2512 if (cur->data == NULL)
2513 {
2514 pthread_mutex_lock(&cur->busy);
2515 /* double check with lock held.... */
2516 if (cur->data != NULL)
2517 {
2518 pthread_mutex_unlock(&cur->busy);
2519 continue;
2520 }
2521
2522 /* Wake up thread */
2523 cur->data = data;
2524 pthread_cond_broadcast(&cur->nodata);
2525 pthread_mutex_unlock(&cur->busy);
2526 return;
2527 }
2528 }
2529
2530 cur = SC_xmalloc(&threadListHandle, sizeof(TThreadListElement));
2531 if (!cur)
2532 return;
2533
2534 threadCount++;
2535
2536 pthread_mutex_init(&cur->busy, NULL);
2537 pthread_cond_init(&cur->nodata, NULL);
2538 cur->data = data;
2539
2540 Result = pthread_create(&cur->thread, NULL, (void *(*)(void *)) thread_function, cur);
2541 if (0 != Result)
2542 {
2543 error("[THREAD CREATE ERROR 0x%.8x]\n", Result);
2544 SC_xfree(&threadListHandle, cur);
2545 SC_destroyThreadData(data);
2546 data = NULL;
2547 }
2548 cur->next = threadList;
2549 threadList = cur;
2550}
2551
2552static void *
2553queue_handler_function(void *data)
2554{
2555 PSCThreadData cur_data = NULL;
2556 while (1)
2557 {
2558 cur_data = SC_getNextInQueue();
2559 switch (cur_data->request)
2560 {
2561 case SC_ESTABLISH_CONTEXT:
2562 case SC_RELEASE_CONTEXT:
2563 {
2564 SC_deviceControl(cur_data);
2565 break;
2566 }
2567 default:
2568 {
2569 SC_handleRequest(cur_data);
2570 break;
2571 }
2572 }
2573 }
2574 return NULL;
2575}
2576
2577static RD_NTSTATUS
2578thread_wrapper(RD_NTHANDLE handle, uint32 request, STREAM in, STREAM out)
2579{
2580 if (SC_addToQueue(handle, request, in, out))
2581 return RD_STATUS_PENDING | 0xC0000000;
2582 else
2583 return RD_STATUS_NO_SUCH_FILE;
2584}
2585
2586DEVICE_FNS scard_fns = {
2587 scard_create,
2588 scard_close,
2589 scard_read,
2590 scard_write,
2591 thread_wrapper
2592};
2593#endif /* MAKE_PROTO */
2594
2595void
2596scard_lock(int lock)
2597{
2598 if (!scard_mutex)
2599 {
2600 int i;
2601
2602 scard_mutex =
2603 (pthread_mutex_t **) xmalloc(sizeof(pthread_mutex_t *) * SCARD_LOCK_LAST);
2604
2605 for (i = 0; i < SCARD_LOCK_LAST; i++)
2606 {
2607 scard_mutex[i] = NULL;
2608 }
2609 }
2610
2611 if (!scard_mutex[lock])
2612 {
2613 scard_mutex[lock] = (pthread_mutex_t *) xmalloc(sizeof(pthread_mutex_t));
2614 pthread_mutex_init(scard_mutex[lock], NULL);
2615 }
2616
2617 pthread_mutex_lock(scard_mutex[lock]);
2618}
2619
2620void
2621scard_unlock(int lock)
2622{
2623 pthread_mutex_unlock(scard_mutex[lock]);
2624}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette