/[rdesktop]/sourceforge.net/trunk/rdesktop/scard.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /sourceforge.net/trunk/rdesktop/scard.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1311 - (hide annotations)
Wed Nov 1 21:23:08 2006 UTC (17 years, 7 months ago) by stargo
File MIME type: text/plain
File size: 69958 byte(s)
Add smartcard support for mac os x

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

  ViewVC Help
Powered by ViewVC 1.1.26