/[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 1317 - (hide annotations)
Thu Nov 2 11:09:35 2006 UTC (17 years, 7 months ago) by stargo
File MIME type: text/plain
File size: 70604 byte(s)
move response-limitation to a more appropriate place

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

  ViewVC Help
Powered by ViewVC 1.1.26