/[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 1319 - (hide annotations)
Thu Nov 2 20:48:28 2006 UTC (17 years, 7 months ago) by stargo
File MIME type: text/plain
File size: 69747 byte(s)
clean up smartcard debugging

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 stargo 1319 error("[SMART CARD: PCSC service not available]\n");
130 stargo 1309 return 0;
131     }
132     else
133     rv = SCardReleaseContext(hContext);
134    
135     count = 0;
136    
137     if (0 != pthread_mutex_init(&queueAccess, NULL))
138     {
139 stargo 1319 error("[SMART CARD: Can't initialize queue access mutex]\n");
140 stargo 1309 return 0;
141     }
142    
143     if (0 != pthread_mutex_init(&queueEmpty, NULL))
144     {
145 stargo 1319 error("[SMART CARD: Can't initialize queue control mutex]\n");
146 stargo 1309 return 0;
147     }
148    
149     if (0 != pthread_mutex_init(&hcardAccess, NULL))
150     {
151 stargo 1319 error("[SMART CARD: Can't initialize hcard list access mutex]\n");
152 stargo 1309 return 0;
153     }
154    
155     #if 0
156     if (0 != pthread_mutex_init(&sendControl, NULL))
157     {
158 stargo 1319 error("[SMART CARD: Can't initialize send control mutex]\n");
159 stargo 1309 return 0;
160     }
161     #endif
162    
163    
164     if (0 !=
165     pthread_create(&queueHandler, NULL, (void *(*)(void *)) queue_handler_function, NULL))
166     {
167 stargo 1319 error("[SMART CARD: Can't create queue handling Thread]\n");
168 stargo 1309 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 stargo 1319 DEBUG_SCARD(("Establishing PC/SC Context... \n"));
624 stargo 1309 rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
625     if (rv)
626 stargo 1319 {
627     DEBUG_SCARD(("<--ERROR SCardEstablishContext Code=0x%.8x]-->\n",
628     (unsigned int) rv));
629     }
630 stargo 1309 else
631 stargo 1319 {
632     DEBUG_SCARD(("<--SUCCESS SCardEstablishContext-->\n"));
633     }
634 stargo 1309
635     out_uint32_le(out, 0x00000004);
636     out_uint32_le(out, (SERVER_DWORD) hContext); /* must not be 0 (Seems to be pointer), don't know what is this (I use hContext as value) */
637     /* i hope it's not a pointer because i just downcasted it - jlj */
638     out_uint32_le(out, 0x00000004);
639     out_uint32_le(out, (SERVER_DWORD) hContext);
640     return rv;
641     }
642    
643     static MYPCSC_DWORD
644     TS_SCardReleaseContext(STREAM in, STREAM out)
645     {
646     MYPCSC_DWORD rv;
647     SERVER_SCARDCONTEXT hContext;
648    
649     in->p += 0x1C;
650     in_uint32_le(in, hContext);
651 stargo 1319 DEBUG_SCARD(("[CONTEXT 0x%.8x]\n", (unsigned int) hContext));
652     DEBUG_SCARD(("Releasing context... \n"));
653 stargo 1309 rv = SCardReleaseContext((MYPCSC_SCARDCONTEXT) hContext);
654 stargo 1319
655 stargo 1309 if (rv)
656 stargo 1319 {
657     DEBUG_SCARD(("<--ERROR SCardReleaseContext Code=0x%.8x-->\n", (unsigned int) rv));
658     }
659 stargo 1309 else
660 stargo 1319 {
661     DEBUG_SCARD(("<--SUCCESS SCardReleaseContext-->\n"));
662     }
663    
664 stargo 1309 return rv;
665     }
666    
667     static MYPCSC_DWORD
668     TS_SCardIsValidContext(STREAM in, STREAM out)
669     {
670     MYPCSC_DWORD rv;
671     SERVER_SCARDCONTEXT hContext;
672     char *readers;
673     DWORD readerCount = 1024;
674     PMEM_HANDLE lcHandle = NULL;
675    
676     in->p += 0x1C;
677     in_uint32_le(in, hContext);
678 stargo 1319 DEBUG_SCARD(("[CONTEXT 0x%.8x]\n", (unsigned int) hContext));
679     DEBUG_SCARD(("Checking... \n"));
680 stargo 1309 /* There is no realization of SCardIsValidContext in PC/SC Lite so we call SCardListReaders */
681    
682     readers = SC_xmalloc(&lcHandle, 1024);
683     if (!readers)
684     return SC_returnNoMemoryError(&lcHandle, in, out);
685    
686     rv = SCardListReaders((MYPCSC_SCARDCONTEXT) hContext, NULL, readers, &readerCount);
687 stargo 1319
688 stargo 1309 if (rv)
689     {
690 stargo 1319 DEBUG_SCARD(("<--ERROR SCardListReaders (no SCardIsValidContext) Code=0x%.8x-->\n",
691     (unsigned int) rv));
692 stargo 1309 rv = SCARD_E_INVALID_HANDLE;
693     }
694     else
695 stargo 1319 {
696     DEBUG_SCARD(("<--SUCCESS SCardListReaders (no SCardIsValidContext)-->\n"));
697     }
698    
699 stargo 1309 outForceAllignment(out, 8);
700     SC_xfreeallmemory(&lcHandle);
701     return rv;
702     }
703    
704    
705     static MYPCSC_DWORD
706     TS_SCardListReaders(STREAM in, STREAM out, BOOL wide)
707     {
708     #define readerArraySize 1024
709     MYPCSC_DWORD rv;
710     SERVER_SCARDCONTEXT hContext;
711     SERVER_DWORD dataLength;
712     MYPCSC_DWORD cchReaders = readerArraySize;
713     unsigned char *plen1, *plen2, *pend;
714     char *readers, *cur;
715     PMEM_HANDLE lcHandle = NULL;
716    
717     in->p += 0x2C;
718     in_uint32_le(in, hContext);
719 stargo 1319 DEBUG_SCARD(("[CONTEXT 0x%.8x]\n", (unsigned int) hContext));
720 stargo 1309 plen1 = out->p;
721     out_uint32_le(out, 0x00000000); /* Temp value for data length as 0x0 */
722     out_uint32_le(out, 0x01760650);
723     plen2 = out->p;
724     out_uint32_le(out, 0x00000000); /* Temp value for data length as 0x0 */
725    
726     dataLength = 0;
727     readers = SC_xmalloc(&lcHandle, readerArraySize);
728     if (!readers)
729     return SC_returnNoMemoryError(&lcHandle, in, out);
730    
731    
732     readers[0] = '\0';
733     readers[1] = '\0';
734     rv = SCardListReaders((MYPCSC_SCARDCONTEXT) hContext, NULL, readers, &cchReaders);
735     cur = readers;
736     if (!rv)
737     {
738     int i;
739     PSCNameMapRec tmpMap;
740 stargo 1319 #ifdef WITH_DEBUG_SCARD
741     DEBUG_SCARD(("[CALL RESULT of SCardListReaders 0x%.8x]\n", (unsigned int) rv));
742 stargo 1309 hexdump((void *) readers, cchReaders);
743     #endif
744     for (i = 0, tmpMap = nameMapList; i < nameMapCount; i++, tmpMap++)
745     {
746     dataLength += outString(out, tmpMap->alias, wide);
747     }
748    
749     int lenSC = strlen(cur);
750     if (lenSC == 0)
751     dataLength += outString(out, "\0", wide);
752     else
753     while (lenSC > 0)
754     {
755     if (!hasAlias(cur))
756     dataLength += outString(out, cur, wide);
757     cur = (void *) ((unsigned char *) cur + lenSC + 1);
758     lenSC = strlen(cur);
759     }
760     }
761    
762     dataLength += outString(out, "\0", wide);
763     outRepos(out, dataLength);
764    
765     pend = out->p;
766     out->p = plen1;
767     out_uint32_le(out, dataLength);
768     out->p = plen2;
769     out_uint32_le(out, dataLength);
770     out->p = pend;
771    
772     outForceAllignment(out, 8);
773     SC_xfreeallmemory(&lcHandle);
774     return rv;
775     }
776    
777    
778     static MYPCSC_DWORD
779     TS_SCardConnect(STREAM in, STREAM out, BOOL wide)
780     {
781     MYPCSC_DWORD rv;
782     SCARDCONTEXT hContext;
783     char *szReader;
784     SERVER_DWORD dwShareMode;
785     SERVER_DWORD dwPreferredProtocol;
786     MYPCSC_SCARDHANDLE myHCard;
787     SERVER_SCARDHANDLE hCard;
788    
789     MYPCSC_DWORD dwActiveProtocol;
790     PMEM_HANDLE lcHandle = NULL;
791    
792     in->p += 0x1C;
793     in_uint32_le(in, dwShareMode);
794     in_uint32_le(in, dwPreferredProtocol);
795 stargo 1319 DEBUG_SCARD(("[SHARE %8x]\n", (unsigned int) dwShareMode));
796     DEBUG_SCARD(("[PROTO %8x]\n", (unsigned int) dwPreferredProtocol));
797 stargo 1309 inReaderName(&lcHandle, in, &szReader, wide);
798 stargo 1319 DEBUG_SCARD(("[CONNECT TO READER \"%s\"\n", (szReader != NULL) ? (szReader) : ("NULL")));
799 stargo 1309 in->p += 0x04;
800     in_uint32_le(in, hContext);
801 stargo 1319 DEBUG_SCARD(("[CONTEXT 0x%.8x]\n", (unsigned int) hContext));
802 stargo 1309 rv = SCardConnect(hContext, szReader, (MYPCSC_DWORD) dwShareMode,
803     (MYPCSC_DWORD) dwPreferredProtocol, &myHCard, &dwActiveProtocol);
804     hCard = scHandleToServer(myHCard);
805 stargo 1319 DEBUG_SCARD(("[RECEIVED HCARD 0x%016lx]\n", (unsigned long) myHCard));
806     DEBUG_SCARD(("[MANGLED HCARD 0x%08x]\n", hCard));
807 stargo 1309 if (rv != SCARD_S_SUCCESS)
808     {
809 stargo 1319 DEBUG_SCARD(("<--ERROR SCardConnect Code=0x%.8x-->\n", (unsigned int) rv));
810 stargo 1309 }
811     else
812     {
813     char *szVendor = getVendor(szReader);
814 stargo 1319 DEBUG_SCARD(("<--SUCCESS ScardConnect-->\n"));
815 stargo 1309 if (szVendor && (strlen(szVendor) > 0))
816     {
817 stargo 1319 DEBUG_SCARD(("Set Attribute ATTR_VENDOR_NAME\n"));
818 stargo 1309 pthread_mutex_lock(&hcardAccess);
819     PSCHCardRec hcard = xmalloc(sizeof(TSCHCardRec));
820     if (hcard)
821     {
822     hcard->hCard = hCard;
823     hcard->vendor = szVendor;
824     hcard->next = NULL;
825     hcard->prev = NULL;
826    
827     if (hcardFirst)
828     {
829     hcardFirst->prev = hcard;
830     hcard->next = hcardFirst;
831     }
832     hcardFirst = hcard;
833     }
834     pthread_mutex_unlock(&hcardAccess);
835     }
836     }
837    
838     out_uint32_le(out, 0x00000000);
839     out_uint32_le(out, 0x00000000);
840     out_uint32_le(out, 0x00000004);
841     out_uint32_le(out, 0x016Cff34);
842     /* if the active protocol > 4 billion, this is trouble. odds are low */
843     out_uint32_le(out, (SERVER_DWORD) dwActiveProtocol);
844     out_uint32_le(out, 0x00000004);
845     out_uint32_le(out, hCard);
846    
847     outForceAllignment(out, 8);
848     SC_xfreeallmemory(&lcHandle);
849     return rv;
850     }
851    
852     static MYPCSC_DWORD
853     TS_SCardReconnect(STREAM in, STREAM out)
854     {
855     MYPCSC_DWORD rv;
856     SCARDCONTEXT hContext;
857     SERVER_SCARDHANDLE hCard;
858     MYPCSC_SCARDHANDLE myHCard;
859     SERVER_DWORD dwShareMode;
860     SERVER_DWORD dwPreferredProtocol;
861     SERVER_DWORD dwInitialization;
862     MYPCSC_DWORD dwActiveProtocol;
863    
864     in->p += 0x20;
865     in_uint32_le(in, dwShareMode);
866     in_uint32_le(in, dwPreferredProtocol);
867     in_uint32_le(in, dwInitialization);
868     in->p += 0x04;
869     in_uint32_le(in, hContext);
870     in->p += 0x04;
871     in_uint32_le(in, hCard);
872     myHCard = scHandleToMyPCSC(hCard);
873 stargo 1319 DEBUG_SCARD(("[SHARE = 0x%.8x]\n", (unsigned int) dwShareMode));
874     DEBUG_SCARD(("[PROTO = 0x%.8x]\n", (unsigned int) dwPreferredProtocol));
875     DEBUG_SCARD(("[INIT = 0x%.8x]\n", (unsigned int) dwInitialization));
876     DEBUG_SCARD(("[hContext = 0x%.8x]\n", (unsigned int) hContext));
877     DEBUG_SCARD(("[hCard = 0x%.8x]\n", (unsigned int) hCard));
878     DEBUG_SCARD(("[myHCard = 0x%016lx]\n", (unsigned long) myHCard));
879 stargo 1309 rv = SCardReconnect(myHCard, (MYPCSC_DWORD) dwShareMode, (MYPCSC_DWORD) dwPreferredProtocol,
880     (MYPCSC_DWORD) dwInitialization, &dwActiveProtocol);
881     if (rv != SCARD_S_SUCCESS)
882 stargo 1319 {
883     DEBUG_SCARD(("<--ERROR SCardReconnect Code=0x%.8x-->\n", (unsigned int) rv));
884     }
885 stargo 1309 else
886 stargo 1319 {
887     DEBUG_SCARD(("<--SUCCESS SCardReconnect-->\n"));
888     }
889 stargo 1309
890     outForceAllignment(out, 8);
891     out_uint32_le(out, (SERVER_DWORD) dwActiveProtocol);
892     return rv;
893     }
894    
895     static MYPCSC_DWORD
896     TS_SCardDisconnect(STREAM in, STREAM out)
897     {
898     MYPCSC_DWORD rv;
899     SERVER_SCARDCONTEXT hContext;
900     SERVER_SCARDHANDLE hCard;
901     MYPCSC_SCARDHANDLE myHCard;
902     SERVER_DWORD dwDisposition;
903    
904     in->p += 0x20;
905     in_uint32_le(in, dwDisposition);
906     in->p += 0x04;
907     in_uint32_le(in, hContext);
908     in->p += 0x04;
909     in_uint32_le(in, hCard);
910    
911 stargo 1319 DEBUG_SCARD(("[hContext = 0x%.8x]\n", (unsigned int) hContext));
912     DEBUG_SCARD(("[hCard = 0x%.8x]\n", (unsigned int) hCard));
913     DEBUG_SCARD(("[dwDisposition = 0x%.8x]\n", (unsigned int) dwDisposition));
914 stargo 1309
915     pthread_mutex_lock(&hcardAccess);
916     PSCHCardRec hcard = hcardFirst;
917     while (hcard)
918     {
919     if (hcard->hCard == hCard)
920     {
921     if (hcard->prev)
922     hcard->prev->next = hcard->next;
923     if (hcard->next)
924     hcard->next->prev = hcard->prev;
925     if (hcardFirst == hcard)
926     hcardFirst = hcard->next;
927     xfree(hcard);
928     break;
929     }
930     hcard = hcard->next;
931     }
932     pthread_mutex_unlock(&hcardAccess);
933    
934     myHCard = scHandleToMyPCSC(hCard);
935     rv = SCardDisconnect(myHCard, (MYPCSC_DWORD) dwDisposition);
936    
937     if (rv != SCARD_S_SUCCESS)
938 stargo 1319 {
939     DEBUG_SCARD(("<--ERROR SCardDisconnect Code=0x%.8x-->\n", (unsigned int) rv));
940     }
941 stargo 1309 else
942 stargo 1319 {
943     DEBUG_SCARD(("<--SUCCESS SCardDisconnect-->\n"));
944     }
945    
946 stargo 1309 outForceAllignment(out, 8);
947     return rv;
948     }
949    
950     static int
951     needStatusRecheck(MYPCSC_DWORD rv, MYPCSC_LPSCARD_READERSTATE_A rsArray, SERVER_DWORD dwCount)
952     {
953     int i, recall = 0;
954     if (rv == SCARD_S_SUCCESS)
955     {
956     MYPCSC_LPSCARD_READERSTATE_A cur;
957     for (i = 0, cur = rsArray; i < dwCount; i++, cur++)
958     {
959     if (cur->dwEventState & SCARD_STATE_UNKNOWN)
960     {
961     cur->dwCurrentState = cur->dwEventState;
962     recall++;
963     }
964     }
965     }
966     return recall;
967     }
968    
969     static BOOL
970     mappedStatus(MYPCSC_DWORD code)
971     {
972     code >>= 16;
973     code &= 0x0000FFFF;
974     return (code % 2);
975     }
976    
977     static MYPCSC_DWORD
978     incStatus(MYPCSC_DWORD code, BOOL mapped)
979     {
980     if (mapped || (code & SCARD_STATE_CHANGED))
981     {
982     MYPCSC_DWORD count = (code >> 16) & 0x0000FFFF;
983     count++;
984     if (mapped && !(count % 2))
985     count++;
986     return (code & 0x0000FFFF) | (count << 16);
987     }
988     else
989     return code;
990     }
991    
992     static void
993     copyReaderState_MyPCSCToServer(MYPCSC_LPSCARD_READERSTATE_A src, SERVER_LPSCARD_READERSTATE_A dst,
994     MYPCSC_DWORD readerCount)
995     {
996     MYPCSC_LPSCARD_READERSTATE_A srcIter;
997     SERVER_LPSCARD_READERSTATE_A dstIter;
998     MYPCSC_DWORD i;
999    
1000     for (i = 0, srcIter = src, dstIter = dst; i < readerCount; i++, srcIter++, dstIter++)
1001     {
1002     dstIter->szReader = srcIter->szReader;
1003     dstIter->pvUserData = srcIter->pvUserData;
1004     dstIter->dwCurrentState = srcIter->dwCurrentState;
1005     dstIter->dwEventState = srcIter->dwEventState;
1006     dstIter->cbAtr = srcIter->cbAtr;
1007     memcpy(dstIter->rgbAtr, srcIter->rgbAtr, MAX_ATR_SIZE * sizeof(unsigned char));
1008     }
1009     }
1010    
1011     static void
1012     copyReaderState_ServerToMyPCSC(SERVER_LPSCARD_READERSTATE_A src, MYPCSC_LPSCARD_READERSTATE_A dst,
1013     SERVER_DWORD readerCount)
1014     {
1015     SERVER_LPSCARD_READERSTATE_A srcIter;
1016     MYPCSC_LPSCARD_READERSTATE_A dstIter;
1017     SERVER_DWORD i;
1018    
1019     for (i = 0, srcIter = src, dstIter = dst; i < readerCount; i++, srcIter++, dstIter++)
1020     {
1021     dstIter->szReader = srcIter->szReader;
1022     dstIter->pvUserData = srcIter->pvUserData;
1023     dstIter->dwCurrentState = srcIter->dwCurrentState;
1024     dstIter->dwEventState = srcIter->dwEventState;
1025     dstIter->cbAtr = srcIter->cbAtr;
1026     memcpy(dstIter->rgbAtr, srcIter->rgbAtr, MAX_ATR_SIZE * sizeof(unsigned char));
1027     }
1028     }
1029    
1030    
1031     static MYPCSC_DWORD
1032     TS_SCardGetStatusChange(STREAM in, STREAM out, BOOL wide)
1033     {
1034     MYPCSC_DWORD rv;
1035     SERVER_SCARDCONTEXT hContext;
1036     SERVER_DWORD dwTimeout;
1037     SERVER_DWORD dwCount;
1038     SERVER_LPSCARD_READERSTATE_A rsArray, cur;
1039     SERVER_DWORD *stateArray = NULL, *curState;
1040     MYPCSC_LPSCARD_READERSTATE_A myRsArray;
1041     long i;
1042     PMEM_HANDLE lcHandle = NULL;
1043     #if 0
1044     BOOL mapped = False;
1045     #endif
1046    
1047     in->p += 0x18;
1048     in_uint32_le(in, dwTimeout);
1049     in_uint32_le(in, dwCount);
1050     in->p += 0x08;
1051     in_uint32_le(in, hContext);
1052     in->p += 0x04;
1053 stargo 1319
1054     DEBUG_SCARD(("[CONTEXT 0x%.8x]\n", (unsigned int) hContext));
1055     DEBUG_SCARD(("[dwTimeout 0x%.8x]\n", (unsigned int) dwTimeout));
1056     DEBUG_SCARD(("[COUNT %d]\n", (unsigned int) dwCount));
1057     DEBUG_SCARD(("[TYPE SIZE %d]\n", (unsigned int) sizeof(SERVER_SCARD_READERSTATE_A)));
1058    
1059 stargo 1309 if (dwCount > 0)
1060     {
1061     rsArray = SC_xmalloc(&lcHandle, dwCount * sizeof(SERVER_SCARD_READERSTATE_A));
1062     if (!rsArray)
1063     return SC_returnNoMemoryError(&lcHandle, in, out);
1064     memset(rsArray, 0, dwCount * sizeof(SERVER_SCARD_READERSTATE_A));
1065     stateArray = SC_xmalloc(&lcHandle, dwCount * sizeof(MYPCSC_DWORD));
1066     if (!stateArray)
1067     return SC_returnNoMemoryError(&lcHandle, in, out);
1068     /* skip two pointers at beginning of struct */
1069     for (i = 0, cur = (SERVER_LPSCARD_READERSTATE_A) ((unsigned char **) rsArray + 2);
1070     i < dwCount; i++, cur++)
1071     {
1072     in->p += 0x04;
1073     in_uint8a(in, cur, SERVER_SCARDSTATESIZE);
1074     }
1075 stargo 1319 #ifdef WITH_DEBUG_SCARD
1076     DEBUG_SCARD(("[READERS DUMP 1]------------------\n"));
1077 stargo 1309 hexdump((void *) rsArray, dwCount * sizeof(SERVER_SCARD_READERSTATE_A));
1078     #endif
1079    
1080    
1081     for (i = 0, cur = rsArray, curState = stateArray;
1082     i < dwCount; i++, cur++, curState++)
1083     {
1084     SERVER_DWORD dataLength;
1085    
1086     /* reset Current state hign bytes; */
1087     *curState = cur->dwCurrentState;
1088     cur->dwCurrentState &= 0x0000FFFF;
1089     cur->dwEventState &= 0x0000FFFF;
1090    
1091     #if 0
1092     if (cur->dwCurrentState == (SCARD_STATE_CHANGED | SCARD_STATE_PRESENT))
1093     {
1094     cur->dwCurrentState = 0x00000000;
1095     mapped = True;
1096     }
1097    
1098     if (mappedStatus(*curState))
1099     {
1100     cur->dwCurrentState &= ~SCARD_STATE_INUSE;
1101     cur->dwEventState &= ~SCARD_STATE_INUSE;
1102    
1103     if (cur->dwCurrentState & SCARD_STATE_EMPTY)
1104     {
1105     cur->dwCurrentState &= ~SCARD_STATE_EMPTY;
1106     cur->dwCurrentState |= SCARD_STATE_UNKNOWN;
1107     }
1108     }
1109     #endif
1110    
1111     in->p += 0x08;
1112     in_uint32_le(in, dataLength);
1113 stargo 1319 DEBUG_SCARD(("[%d] Data Length %d]\n", (unsigned int) i, dataLength));
1114 stargo 1309 inRepos(in,
1115     inString(&lcHandle, in, (char **) &(cur->szReader), dataLength,
1116     wide));
1117    
1118     if (strcmp(cur->szReader, "\\\\?PnP?\\Notification") == 0)
1119     cur->dwCurrentState |= SCARD_STATE_IGNORE;
1120     }
1121 stargo 1319 #ifdef WITH_DEBUG_SCARD
1122     DEBUG_SCARD(("[READERS DUMP 2]------------------\n"));
1123 stargo 1309 hexdump((void *) rsArray, dwCount * sizeof(SERVER_SCARD_READERSTATE_A));
1124     #endif
1125     }
1126     else
1127     {
1128     rsArray = NULL;
1129     stateArray = NULL;
1130     }
1131    
1132 stargo 1319 DEBUG_SCARD(("\nCalling SCardGetStatusChange...\n"));
1133 stargo 1309
1134    
1135     myRsArray = SC_xmalloc(&lcHandle, dwCount * sizeof(MYPCSC_SCARD_READERSTATE_A));
1136     if (!rsArray)
1137     return SC_returnNoMemoryError(&lcHandle, in, out);
1138     memset(myRsArray, 0, dwCount * sizeof(SERVER_SCARD_READERSTATE_A));
1139     copyReaderState_ServerToMyPCSC(rsArray, myRsArray, (SERVER_DWORD) dwCount);
1140 stargo 1319 #ifdef WITH_DEBUG_SCARD
1141     DEBUG_SCARD(("[TRANSLATION OF READERS]--------------------\n"));
1142 stargo 1309 hexdump((void *) myRsArray, dwCount * sizeof(MYPCSC_SCARD_READERSTATE_A));
1143     #endif
1144    
1145     rv = SCardGetStatusChange((MYPCSC_SCARDCONTEXT) hContext, (MYPCSC_DWORD) dwTimeout,
1146     myRsArray, (MYPCSC_DWORD) dwCount);
1147     copyReaderState_MyPCSCToServer(myRsArray, rsArray, (MYPCSC_DWORD) dwCount);
1148    
1149     if (rv != SCARD_S_SUCCESS)
1150 stargo 1319 {
1151     DEBUG_SCARD(("<--ERROR SCardGetStatusChange Code=0x%.8x-->\n", (unsigned int) rv));
1152     }
1153 stargo 1309 else
1154 stargo 1319 {
1155     DEBUG_SCARD(("<--SUCCESS SCardGetStatusChange-->\n"));
1156     }
1157 stargo 1309
1158 stargo 1319 #ifdef WITH_DEBUG_SCARD
1159 stargo 1309 if (dwCount > 0)
1160     {
1161 stargo 1319 DEBUG_SCARD(("[READERS DUMP]------------------\n"));
1162 stargo 1309 hexdump((void *) rsArray, dwCount * sizeof(SERVER_SCARD_READERSTATE_A));
1163     }
1164     #endif
1165    
1166     out_uint32_le(out, dwCount);
1167     out_uint32_le(out, 0x00084dd8);
1168     out_uint32_le(out, dwCount);
1169    
1170     for (i = 0, cur = rsArray, curState = stateArray; i < dwCount; i++, cur++, curState++)
1171     {
1172    
1173     cur->dwCurrentState = (*curState);
1174     cur->dwEventState |= (*curState) & 0xFFFF0000;
1175    
1176     #if 0
1177     if (mapped && (cur->dwCurrentState & SCARD_STATE_PRESENT)
1178     && (cur->dwCurrentState & SCARD_STATE_CHANGED)
1179     && (cur->dwEventState & SCARD_STATE_PRESENT)
1180     && (cur->dwEventState & SCARD_STATE_CHANGED))
1181     {
1182     cur->dwEventState |= SCARD_STATE_INUSE;
1183     }
1184     else if (cur->dwEventState & SCARD_STATE_UNKNOWN)
1185     {
1186     cur->dwEventState &= ~SCARD_STATE_UNKNOWN;
1187     cur->dwEventState |= SCARD_STATE_EMPTY;
1188     mapped = True;
1189     }
1190     else if ((!mapped) && (cur->dwEventState & SCARD_STATE_INUSE))
1191     {
1192     mapped = True;
1193     cur->dwEventState &= ~SCARD_STATE_INUSE;
1194     }
1195    
1196     cur->dwEventState = incStatus(cur->dwEventState, mapped);
1197     #endif
1198     cur->dwEventState = incStatus(cur->dwEventState, False);
1199    
1200     out_uint8p(out, (void *) ((unsigned char **) cur + 2),
1201     sizeof(SERVER_SCARD_READERSTATE_A) - 2 * sizeof(unsigned char *));
1202     }
1203     outForceAllignment(out, 8);
1204     SC_xfreeallmemory(&lcHandle);
1205     return rv;
1206     }
1207    
1208     static MYPCSC_DWORD
1209     TS_SCardCancel(STREAM in, STREAM out)
1210     {
1211     MYPCSC_DWORD rv;
1212     SERVER_SCARDCONTEXT hContext;
1213    
1214     in->p += 0x1C;
1215     in_uint32_le(in, hContext);
1216 stargo 1319 DEBUG_SCARD(("[CONTEXT 0x%.8x]\n", (unsigned int) hContext));
1217     DEBUG_SCARD(("Canceling... \n"));
1218 stargo 1309 rv = SCardCancel((MYPCSC_SCARDCONTEXT) hContext);
1219     if (rv != SCARD_S_SUCCESS)
1220 stargo 1319 {
1221     DEBUG_SCARD(("<--ERROR SCardCancel Code=0x%.8x-->\n", (unsigned int) rv));
1222     }
1223 stargo 1309 else
1224 stargo 1319 {
1225     DEBUG_SCARD(("<--SUCCESS SCardCancel-->\n"));
1226     }
1227 stargo 1309 outForceAllignment(out, 8);
1228     return rv;
1229     }
1230    
1231     static MYPCSC_DWORD
1232     TS_SCardLocateCardsByATR(STREAM in, STREAM out, BOOL wide)
1233     {
1234     int i, j, k;
1235     MYPCSC_DWORD rv;
1236     SERVER_SCARDCONTEXT hContext;
1237     /* The SCARD_ATRMASK_L struct doesn't contain any longs or DWORDs -
1238     no need to split into SERVER_ and MYPCSC_ */
1239     LPSCARD_ATRMASK_L pAtrMasks, cur;
1240     SERVER_DWORD atrMaskCount = 0;
1241     SERVER_DWORD readerCount = 0;
1242     SERVER_LPSCARD_READERSTATE_A rsArray, ResArray, rsCur;
1243     MYPCSC_LPSCARD_READERSTATE_A myRsArray;
1244     PMEM_HANDLE lcHandle = NULL;
1245    
1246     in->p += 0x2C;
1247     in_uint32_le(in, hContext);
1248 stargo 1319 DEBUG_SCARD(("[CONTEXT 0x%.8x]\n", (unsigned int) hContext));
1249 stargo 1309 in_uint32_le(in, atrMaskCount);
1250     pAtrMasks = SC_xmalloc(&lcHandle, atrMaskCount * sizeof(SCARD_ATRMASK_L));
1251     if (!pAtrMasks)
1252     return SC_returnNoMemoryError(&lcHandle, in, out);
1253     in_uint8a(in, pAtrMasks, atrMaskCount * sizeof(SCARD_ATRMASK_L));
1254    
1255     in_uint32_le(in, readerCount);
1256     rsArray = SC_xmalloc(&lcHandle, readerCount * sizeof(SCARD_READERSTATE_A));
1257     if (!rsArray)
1258     return SC_returnNoMemoryError(&lcHandle, in, out);
1259     memset(rsArray, 0, readerCount * sizeof(SCARD_READERSTATE_A));
1260    
1261     for (i = 0, rsCur = (SERVER_LPSCARD_READERSTATE_A) ((unsigned char **) rsArray + 2);
1262     i < readerCount; i++, rsCur++)
1263     {
1264     in_uint8s(in, 4);
1265     in_uint8a(in, rsCur, SERVER_SCARDSTATESIZE);
1266     }
1267    
1268     ResArray = SC_xmalloc(&lcHandle, readerCount * sizeof(SERVER_SCARD_READERSTATE_A));
1269     if (!ResArray)
1270     return SC_returnNoMemoryError(&lcHandle, in, out);
1271     memcpy(ResArray, rsArray, readerCount * sizeof(SERVER_SCARD_READERSTATE_A));
1272    
1273     for (i = 0, rsCur = rsArray; i < readerCount; i++, rsCur++)
1274     {
1275     inReaderName(&lcHandle, in, (char **) &rsCur->szReader, wide);
1276 stargo 1319 DEBUG_SCARD(("[CHECK READER %s]\n",
1277     (rsCur->szReader) ? (rsCur->szReader) : ("NULL")));
1278 stargo 1309 }
1279    
1280 stargo 1319 DEBUG_SCARD(("[CALL subfunction \"SCardGetStatusChange\"]\n"));
1281 stargo 1309 /* FIXME segfault here. */
1282     myRsArray = SC_xmalloc(&lcHandle, readerCount * sizeof(MYPCSC_SCARD_READERSTATE_A));
1283     if (!myRsArray)
1284     return SC_returnNoMemoryError(&lcHandle, in, out);
1285     rv = SCardGetStatusChange((MYPCSC_SCARDCONTEXT) hContext, 0x00000001, myRsArray,
1286     readerCount);
1287     copyReaderState_MyPCSCToServer(myRsArray, rsArray, readerCount);
1288     if (rv != SCARD_S_SUCCESS)
1289     {
1290 stargo 1319 DEBUG_SCARD(("<--ERROR SCardGetStatusChange (no SCardLocateCardsByATR) Code=0x%.8x-->\n", (unsigned int) rv));
1291 stargo 1309 }
1292     else
1293     {
1294 stargo 1319 DEBUG_SCARD(("<--SUCCESS SCardGetStatusChange (no SCardLocateCardsByATR)-->\n"));
1295 stargo 1309 cur = pAtrMasks;
1296     for (i = 0, cur = pAtrMasks; i < atrMaskCount; i++, cur++)
1297     {
1298     for (j = 0, rsCur = rsArray; j < readerCount; j++, rsCur++)
1299     {
1300     BOOL equal = 1;
1301     for (k = 0; k < cur->cbAtr; k++)
1302     {
1303     /* This line check if them equal */
1304     if (cur->rgbAtr[k] != rsCur->rgbAtr[k])
1305     /* Next Line was make to search with mask (some strange behavours with applications which use eToken SmartCards) */
1306     /* if((cur->rgbAtr[k]&cur->rgbMask[k])!=(rsCur->rgbAtr[k]&cur->rgbMask[k])){ */
1307     {
1308     equal = 0;
1309     break;
1310     }
1311     }
1312     if (equal)
1313     {
1314 stargo 1319 DEBUG_SCARD(("[FOUND]\n"));
1315 stargo 1309 rsCur->dwEventState |= 0x00000040; /* SCARD_STATE_ATRMATCH 0x00000040 */
1316     memcpy(ResArray + j, rsCur, sizeof(SCARD_READERSTATE_A));
1317     }
1318     }
1319     }
1320     }
1321    
1322     out_uint32_le(out, readerCount);
1323     out_uint32_le(out, 0x00084dd8);
1324     out_uint32_le(out, readerCount);
1325    
1326     for (i = 0, rsCur = rsArray; i < readerCount; i++, rsCur++)
1327     {
1328     out_uint8p(out, (void *) ((unsigned char **) rsCur + 2),
1329     sizeof(SCARD_READERSTATE_A) - 2 * sizeof(unsigned char *));
1330     }
1331    
1332     outForceAllignment(out, 8);
1333     SC_xfreeallmemory(&lcHandle);
1334     return rv;
1335     }
1336    
1337     static DWORD
1338     TS_SCardBeginTransaction(STREAM in, STREAM out)
1339     {
1340     MYPCSC_DWORD rv;
1341     SERVER_SCARDCONTEXT hCard;
1342     MYPCSC_SCARDCONTEXT myHCard;
1343    
1344     in->p += 0x30;
1345     in_uint32_le(in, hCard);
1346     myHCard = scHandleToMyPCSC(hCard);
1347 stargo 1319 DEBUG_SCARD(("[hCard = 0x%.8x]\n", (unsigned int) hCard));
1348     DEBUG_SCARD(("[myHCard = 0x%016lx]\n", (unsigned long) myHCard));
1349 stargo 1309 rv = SCardBeginTransaction(myHCard);
1350     if (rv != SCARD_S_SUCCESS)
1351 stargo 1319 {
1352     DEBUG_SCARD(("<--ERROR SCardBeginTransaction Code=0x%.8x-->\n", (unsigned int) rv));
1353     }
1354 stargo 1309 else
1355 stargo 1319 {
1356     DEBUG_SCARD(("<--SUCCESS SCardBeginTransaction-->\n"));
1357     }
1358 stargo 1309 outForceAllignment(out, 8);
1359     return rv;
1360     }
1361    
1362     static DWORD
1363     TS_SCardEndTransaction(STREAM in, STREAM out)
1364     {
1365     MYPCSC_DWORD rv;
1366     SERVER_SCARDCONTEXT hCard;
1367     MYPCSC_SCARDCONTEXT myHCard;
1368     SERVER_DWORD dwDisposition = 0;
1369    
1370     in->p += 0x20;
1371     in_uint32_le(in, dwDisposition);
1372     in->p += 0x0C;
1373     in_uint32_le(in, hCard);
1374     myHCard = scHandleToMyPCSC(hCard);
1375 stargo 1319
1376     DEBUG_SCARD(("[hCard = 0x%.8x]\n", (unsigned int) hCard));
1377     DEBUG_SCARD(("[myHCard = 0x%016lx]\n", (unsigned long) myHCard));
1378     DEBUG_SCARD(("[dwDisposition = 0x%.8x]\n", (unsigned int) dwDisposition));
1379    
1380 stargo 1309 rv = SCardEndTransaction(myHCard, (MYPCSC_DWORD) dwDisposition);
1381     if (rv != SCARD_S_SUCCESS)
1382 stargo 1319 {
1383     DEBUG_SCARD(("<--ERROR SCardEndTransaction Code=0x%.8x-->\n", (unsigned int) rv));
1384     }
1385 stargo 1309 else
1386 stargo 1319 {
1387     DEBUG_SCARD(("<--SUCCESS SCardEndTransaction-->\n"));
1388     }
1389 stargo 1309 outForceAllignment(out, 8);
1390     return rv;
1391     }
1392    
1393    
1394     static void
1395     copyIORequest_MyPCSCToServer(MYPCSC_LPSCARD_IO_REQUEST src, SERVER_LPSCARD_IO_REQUEST dst)
1396     {
1397     unsigned char *srcBytes, *dstBytes;
1398     size_t bytesToCopy = src->cbPciLength - sizeof(MYPCSC_SCARD_IO_REQUEST);
1399     srcBytes = ((unsigned char *) src + sizeof(MYPCSC_SCARD_IO_REQUEST));
1400     dstBytes = ((unsigned char *) dst + sizeof(SERVER_SCARD_IO_REQUEST));
1401     dst->dwProtocol = src->dwProtocol;
1402     dst->cbPciLength = src->cbPciLength
1403     - sizeof(MYPCSC_SCARD_IO_REQUEST) + sizeof(SERVER_SCARD_IO_REQUEST);
1404     memcpy(dstBytes, srcBytes, bytesToCopy);
1405     }
1406    
1407     static void
1408     copyIORequest_ServerToMyPCSC(SERVER_LPSCARD_IO_REQUEST src, MYPCSC_LPSCARD_IO_REQUEST dst)
1409     {
1410     unsigned char *srcBytes, *dstBytes;
1411     size_t bytesToCopy = src->cbPciLength - sizeof(SERVER_SCARD_IO_REQUEST);
1412     srcBytes = ((unsigned char *) src + sizeof(SERVER_SCARD_IO_REQUEST));
1413     dstBytes = ((unsigned char *) dst + sizeof(MYPCSC_SCARD_IO_REQUEST));
1414     dst->dwProtocol = src->dwProtocol;
1415     dst->cbPciLength = src->cbPciLength
1416     - sizeof(SERVER_SCARD_IO_REQUEST) + sizeof(MYPCSC_SCARD_IO_REQUEST);
1417     memcpy(dstBytes, srcBytes, bytesToCopy);
1418     }
1419    
1420    
1421     static DWORD
1422     TS_SCardTransmit(STREAM in, STREAM out)
1423     {
1424     MYPCSC_DWORD rv;
1425     SERVER_DWORD map[7], linkedLen;
1426     void *tmp;
1427     SERVER_SCARDCONTEXT hCard;
1428     MYPCSC_SCARDCONTEXT myHCard;
1429     SERVER_LPSCARD_IO_REQUEST pioSendPci, pioRecvPci;
1430     MYPCSC_LPSCARD_IO_REQUEST myPioSendPci, myPioRecvPci;
1431     unsigned char *sendBuf = NULL, *recvBuf = NULL;
1432     SERVER_DWORD cbSendLength, cbRecvLength;
1433     MYPCSC_DWORD myCbRecvLength;
1434     PMEM_HANDLE lcHandle = NULL;
1435    
1436     in->p += 0x14;
1437     in_uint32_le(in, map[0]);
1438     in->p += 0x04;
1439     in_uint32_le(in, map[1]);
1440     pioSendPci = SC_xmalloc(&lcHandle, sizeof(SERVER_SCARD_IO_REQUEST));
1441     if (!pioSendPci)
1442     return SC_returnNoMemoryError(&lcHandle, in, out);
1443     in_uint8a(in, pioSendPci, sizeof(SERVER_SCARD_IO_REQUEST));
1444     in_uint32_le(in, map[2]);
1445     in_uint32_le(in, cbSendLength);
1446     in_uint32_le(in, map[3]);
1447     in_uint32_le(in, map[4]);
1448     in_uint32_le(in, map[5]);
1449     in_uint32_le(in, cbRecvLength);
1450     if (map[0] & INPUT_LINKED)
1451     inSkipLinked(in);
1452    
1453     in->p += 0x04;
1454     in_uint32_le(in, hCard);
1455     myHCard = scHandleToMyPCSC(hCard);
1456    
1457     if (map[2] & INPUT_LINKED)
1458     {
1459     in_uint32_le(in, linkedLen);
1460     pioSendPci->cbPciLength = linkedLen + sizeof(SERVER_SCARD_IO_REQUEST);
1461     tmp = SC_xmalloc(&lcHandle, pioSendPci->cbPciLength);
1462     if (!tmp)
1463     return SC_returnNoMemoryError(&lcHandle, in, out);
1464     in_uint8a(in, (void *) ((unsigned char *) tmp + sizeof(SERVER_SCARD_IO_REQUEST)),
1465     linkedLen);
1466     memcpy(tmp, pioSendPci, sizeof(SERVER_SCARD_IO_REQUEST));
1467     SC_xfree(&lcHandle, pioSendPci);
1468     pioSendPci = tmp;
1469     tmp = NULL;
1470     }
1471     else
1472     pioSendPci->cbPciLength = sizeof(SERVER_SCARD_IO_REQUEST);
1473    
1474     if (map[3] & INPUT_LINKED)
1475     {
1476     in_uint32_le(in, linkedLen);
1477     sendBuf = SC_xmalloc(&lcHandle, linkedLen);
1478     if (!sendBuf)
1479     return SC_returnNoMemoryError(&lcHandle, in, out);
1480     in_uint8a(in, sendBuf, linkedLen);
1481     inRepos(in, linkedLen);
1482     }
1483     else
1484     sendBuf = NULL;
1485    
1486     if (cbRecvLength)
1487     {
1488     recvBuf = SC_xmalloc(&lcHandle, cbRecvLength);
1489     if (!recvBuf)
1490     return SC_returnNoMemoryError(&lcHandle, in, out);
1491     }
1492    
1493     if (map[4] & INPUT_LINKED)
1494     {
1495     pioRecvPci = SC_xmalloc(&lcHandle, sizeof(SERVER_SCARD_IO_REQUEST));
1496     if (!pioRecvPci)
1497     return SC_returnNoMemoryError(&lcHandle, in, out);
1498     in_uint8a(in, pioRecvPci, sizeof(SERVER_SCARD_IO_REQUEST));
1499     in_uint32_le(in, map[6]);
1500     if (map[6] & INPUT_LINKED)
1501     {
1502     in_uint32_le(in, linkedLen);
1503     pioRecvPci->cbPciLength = linkedLen + sizeof(SERVER_SCARD_IO_REQUEST);
1504     tmp = SC_xmalloc(&lcHandle, pioRecvPci->cbPciLength);
1505     if (!tmp)
1506     return SC_returnNoMemoryError(&lcHandle, in, out);
1507     in_uint8a(in,
1508     (void *) ((unsigned char *) tmp +
1509     sizeof(SERVER_SCARD_IO_REQUEST)), linkedLen);
1510     memcpy(tmp, pioRecvPci, sizeof(SERVER_SCARD_IO_REQUEST));
1511     SC_xfree(&lcHandle, pioRecvPci);
1512     pioRecvPci = tmp;
1513     tmp = NULL;
1514     }
1515     else
1516     pioRecvPci->cbPciLength = sizeof(SERVER_SCARD_IO_REQUEST);
1517     }
1518     else
1519     pioRecvPci = NULL;
1520    
1521 stargo 1319 #ifdef WITH_DEBUG_SCARD
1522     DEBUG_SCARD(("++++++++++\n"));
1523     DEBUG_SCARD(("[SEND LEN = %d]\n", (unsigned int) cbSendLength));
1524     DEBUG_SCARD(("[RECV LEN = %d]\n", (unsigned int) cbRecvLength));
1525     DEBUG_SCARD(("[hCard = 0x%.8x]\n", (unsigned int) hCard));
1526     DEBUG_SCARD(("[myHCard = 0x%016lx]\n", (unsigned long) myHCard));
1527     DEBUG_SCARD(("[pioSendPci]\n"));
1528 stargo 1309 if (pioSendPci == NULL)
1529 stargo 1319 {
1530     DEBUG_SCARD(("NULL\n"));
1531     }
1532 stargo 1309 else
1533 stargo 1319 {
1534 stargo 1309 hexdump((void *) pioSendPci, pioSendPci->cbPciLength);
1535 stargo 1319 }
1536    
1537     DEBUG_SCARD(("[pioRecvPci]\n"));
1538 stargo 1309 if (pioRecvPci == NULL)
1539 stargo 1319 {
1540     DEBUG_SCARD(("NULL\n"));
1541     }
1542 stargo 1309 else
1543 stargo 1319 {
1544 stargo 1309 hexdump((void *) pioRecvPci, pioRecvPci->cbPciLength);
1545 stargo 1319 }
1546     DEBUG_SCARD(("[sendBuf]\n"));
1547 stargo 1309 hexdump(sendBuf, cbSendLength);
1548 stargo 1319 DEBUG_SCARD(("++++++++++\n"));
1549 stargo 1309 #endif
1550    
1551     myCbRecvLength = cbRecvLength;
1552     myPioSendPci = SC_xmalloc(&lcHandle,
1553     sizeof(MYPCSC_SCARD_IO_REQUEST)
1554     + pioSendPci->cbPciLength - sizeof(SERVER_SCARD_IO_REQUEST));
1555     if (!myPioSendPci)
1556     return SC_returnNoMemoryError(&lcHandle, in, out);
1557     copyIORequest_ServerToMyPCSC(pioSendPci, myPioSendPci);
1558     /* always a send, not always a recv */
1559     if (pioRecvPci)
1560     {
1561     myPioRecvPci = SC_xmalloc(&lcHandle,
1562     sizeof(MYPCSC_SCARD_IO_REQUEST)
1563     + pioRecvPci->cbPciLength
1564     - sizeof(SERVER_SCARD_IO_REQUEST));
1565     if (!myPioRecvPci)
1566     return SC_returnNoMemoryError(&lcHandle, in, out);
1567     copyIORequest_ServerToMyPCSC(pioRecvPci, myPioRecvPci);
1568     }
1569     else
1570     {
1571     myPioRecvPci = NULL;
1572     }
1573     rv = SCardTransmit(myHCard, myPioSendPci, sendBuf, (MYPCSC_DWORD) cbSendLength,
1574     myPioRecvPci, recvBuf, &myCbRecvLength);
1575     cbRecvLength = myCbRecvLength;
1576 stargo 1317
1577     /* FIXME: handle responses with length > 448 bytes */
1578     if (cbRecvLength > 448)
1579     {
1580     warning("Card response limited from %d to 448 bytes!\n", cbRecvLength);
1581 stargo 1319 DEBUG_SCARD(("[RECV LEN %d -> %d]\n", (unsigned int) cbRecvLength, 400));
1582 stargo 1317 cbRecvLength = 448;
1583     }
1584    
1585 stargo 1309 if (pioRecvPci)
1586     {
1587     copyIORequest_MyPCSCToServer(myPioRecvPci, pioRecvPci);
1588     }
1589    
1590     if (rv != SCARD_S_SUCCESS)
1591     {
1592 stargo 1319 DEBUG_SCARD(("<--ERROR SCardTransmit Code=0x%.8x-->\n", (unsigned int) rv));
1593 stargo 1309 }
1594     else
1595     {
1596 stargo 1319 #ifdef WITH_DEBUG_SCARD
1597     DEBUG_SCARD(("<--SUCCESS SCardTransmit-->\n"));
1598     DEBUG_SCARD(("RESULT %d\n", (unsigned int) cbRecvLength));
1599 stargo 1309 hexdump(recvBuf, cbRecvLength);
1600     if (myPioRecvPci)
1601     {
1602 stargo 1319 DEBUG_SCARD(("--- myPioRecvPci ---\n"));
1603 stargo 1309 hexdump((void *) myPioRecvPci, myPioRecvPci->cbPciLength);
1604     }
1605 stargo 1319 DEBUG_SCARD(("------------------\n"));
1606 stargo 1309 #endif
1607     #if 0
1608     if ((pioRecvPci != NULL) && (pioRecvPci->cbPciLength > 0))
1609     {
1610     out_uint32_le(out, (DWORD) pioRecvPci); /* if not NULL, this 4 bytes indicates that pioRecvPci is present */
1611     }
1612     else
1613     #endif
1614     out_uint32_le(out, 0); /* pioRecvPci 0x00; */
1615    
1616     outBufferStart(out, cbRecvLength); /* start of recvBuf output */
1617    
1618     #if 0
1619     if ((pioRecvPci) && (pioRecvPci->cbPciLength > 0))
1620     {
1621     out_uint32_le(out, pioRecvPci->dwProtocol);
1622     int len = pioRecvPci->cbPciLength - sizeof(pioRecvPci);
1623     outBufferStartWithLimit(out, len, 12);
1624     outBufferFinishWithLimit(out,
1625     (char *) ((DWORD) pioRecvPci + sizeof(pioRecvPci)),
1626     len, 12);
1627     }
1628     #endif
1629    
1630     outBufferFinish(out, (char *) recvBuf, cbRecvLength);
1631     }
1632     outForceAllignment(out, 8);
1633     SC_xfreeallmemory(&lcHandle);
1634     return rv;
1635     }
1636    
1637     static MYPCSC_DWORD
1638     TS_SCardStatus(STREAM in, STREAM out, BOOL wide)
1639     {
1640     MYPCSC_DWORD rv;
1641     SERVER_SCARDCONTEXT hCard;
1642     MYPCSC_SCARDCONTEXT myHCard;
1643     SERVER_DWORD dwState = 0, dwProtocol = 0, dwReaderLen, dwAtrLen;
1644     MYPCSC_DWORD state, protocol, readerLen, atrLen;
1645     SERVER_DWORD dataLength;
1646     PMEM_HANDLE lcHandle = NULL;
1647     char *readerName;
1648     unsigned char *atr;
1649    
1650     in->p += 0x24;
1651     in_uint32_le(in, dwReaderLen);
1652     in_uint32_le(in, dwAtrLen);
1653     in->p += 0x0C;
1654     in_uint32_le(in, hCard);
1655     in->p += 0x04;
1656     myHCard = scHandleToMyPCSC(hCard);
1657    
1658 stargo 1319 DEBUG_SCARD(("[hCard 0x%.8x]\n", (unsigned int) hCard));
1659     DEBUG_SCARD(("[myHCard 0x%016lx]\n", (unsigned long) myHCard));
1660     DEBUG_SCARD(("[dwReaderLen %d]\n", (unsigned int) dwReaderLen));
1661     DEBUG_SCARD(("[dwAtrLen %d]\n", (unsigned int) dwAtrLen));
1662    
1663 stargo 1309 if (dwReaderLen <= 0 || dwReaderLen == SCARD_AUTOALLOCATE || dwReaderLen > SCARD_MAX_MEM)
1664     dwReaderLen = SCARD_MAX_MEM;
1665     if (dwAtrLen <= 0 || dwAtrLen == SCARD_AUTOALLOCATE || dwAtrLen > SCARD_MAX_MEM)
1666     dwAtrLen = SCARD_MAX_MEM;
1667    
1668     readerName = SC_xmalloc(&lcHandle, dwReaderLen + 2);
1669     if (!readerName)
1670     return SC_returnNoMemoryError(&lcHandle, in, out);
1671    
1672     atr = SC_xmalloc(&lcHandle, dwAtrLen + 1);
1673     if (!atr)
1674     return SC_returnNoMemoryError(&lcHandle, in, out);
1675    
1676     state = dwState;
1677     protocol = dwProtocol;
1678     readerLen = dwReaderLen;
1679     atrLen = dwAtrLen;
1680     rv = SCardStatus(myHCard, readerName, &readerLen, &state, &protocol, atr, &atrLen);
1681     dwAtrLen = atrLen;
1682     dwReaderLen = readerLen;
1683     dwProtocol = protocol;
1684     dwState = state;
1685    
1686    
1687     if (rv != SCARD_S_SUCCESS)
1688     {
1689 stargo 1319 DEBUG_SCARD(("<--ERROR SCardStatus Code=0x%.8x-->\n", (unsigned int) rv));
1690 stargo 1309 return SC_returnCode(rv, &lcHandle, in, out);
1691     }
1692     else
1693     {
1694 stargo 1319 #ifdef WITH_DEBUG_SCARD
1695     DEBUG_SCARD(("<--SUCCESS SCardStatus-->\n"));
1696     DEBUG_SCARD(("[dwState 0x%.8x]\n", (unsigned int) dwState));
1697     DEBUG_SCARD(("[dwProtocol 0x%.8x]\n", (unsigned int) dwProtocol));
1698     DEBUG_SCARD(("[Reader Name]\n"));
1699 stargo 1309 hexdump((unsigned char *) readerName, dwReaderLen);
1700 stargo 1319 DEBUG_SCARD(("[Atr]\n"));
1701 stargo 1309 hexdump(atr, dwAtrLen);
1702     #endif
1703     if (dwState & (SCARD_SPECIFIC | SCARD_NEGOTIABLE))
1704     dwState = 0x00000006;
1705     else
1706     #if 0
1707     if (dwState & SCARD_SPECIFIC)
1708     dwState = 0x00000006;
1709     else if (dwState & SCARD_NEGOTIABLE)
1710     dwState = 0x00000005;
1711     else
1712     #endif
1713     if (dwState & SCARD_POWERED)
1714     dwState = 0x00000004;
1715     else if (dwState & SCARD_SWALLOWED)
1716     dwState = 0x00000003;
1717     else if (dwState & SCARD_PRESENT)
1718     dwState = 0x00000002;
1719     else if (dwState & SCARD_ABSENT)
1720     dwState = 0x00000001;
1721     else
1722     dwState = 0x00000000;
1723    
1724     void *p_len1 = out->p;
1725     out_uint32_le(out, dwReaderLen);
1726     out_uint32_le(out, 0x00020000);
1727     out_uint32_le(out, dwState);
1728     out_uint32_le(out, dwProtocol);
1729     out_uint8p(out, atr, dwAtrLen);
1730     if (dwAtrLen < 32)
1731     {
1732     out_uint8s(out, 32 - dwAtrLen);
1733     }
1734     out_uint32_le(out, dwAtrLen);
1735    
1736     void *p_len2 = out->p;
1737     out_uint32_le(out, dwReaderLen);
1738     dataLength = outString(out, readerName, wide);
1739     dataLength += outString(out, "\0", wide);
1740     outRepos(out, dataLength);
1741     void *psave = out->p;
1742     out->p = p_len1;
1743     out_uint32_le(out, dataLength);
1744     out->p = p_len2;
1745     out_uint32_le(out, dataLength);
1746     out->p = psave;
1747     }
1748     outForceAllignment(out, 8);
1749     SC_xfreeallmemory(&lcHandle);
1750     return rv;
1751     }
1752    
1753     static MYPCSC_DWORD
1754     TS_SCardState(STREAM in, STREAM out)
1755     {
1756     MYPCSC_DWORD rv;
1757     SERVER_SCARDCONTEXT hCard;
1758     MYPCSC_SCARDCONTEXT myHCard;
1759     SERVER_DWORD dwState = 0, dwProtocol = 0, dwReaderLen, dwAtrLen;
1760     MYPCSC_DWORD state, protocol, readerLen, atrLen;
1761     PMEM_HANDLE lcHandle = NULL;
1762     char *readerName;
1763     unsigned char *atr;
1764    
1765     in->p += 0x24;
1766     in_uint32_le(in, dwAtrLen);
1767     in->p += 0x0C;
1768     in_uint32_le(in, hCard);
1769     in->p += 0x04;
1770     myHCard = scHandleToMyPCSC(hCard);
1771    
1772 stargo 1319 DEBUG_SCARD(("[hCard 0x%.8x]\n", (unsigned int) hCard));
1773     DEBUG_SCARD(("[myHCard 0x%.8x]\n", (unsigned int) myHCard));
1774     DEBUG_SCARD(("[dwAtrLen %d]\n", (unsigned int) dwAtrLen));
1775 stargo 1309
1776     dwReaderLen = SCARD_MAX_MEM;
1777     if (dwAtrLen <= 0 || dwAtrLen == SCARD_AUTOALLOCATE || dwAtrLen > SCARD_MAX_MEM)
1778     dwAtrLen = SCARD_MAX_MEM;
1779    
1780     readerName = SC_xmalloc(&lcHandle, dwReaderLen + 2);
1781     if (!readerName)
1782     return SC_returnNoMemoryError(&lcHandle, in, out);
1783    
1784     atr = SC_xmalloc(&lcHandle, dwAtrLen + 1);
1785     if (!atr)
1786     return SC_returnNoMemoryError(&lcHandle, in, out);
1787    
1788     state = dwState;
1789     protocol = dwProtocol;
1790     readerLen = dwReaderLen;
1791     atrLen = dwAtrLen;
1792     rv = SCardStatus(myHCard, readerName, &readerLen, &state, &protocol, atr, &atrLen);
1793     dwAtrLen = atrLen;
1794     dwReaderLen = readerLen;
1795     dwProtocol = protocol;
1796     dwState = state;
1797    
1798     if (rv != SCARD_S_SUCCESS)
1799     {
1800 stargo 1319 DEBUG_SCARD(("<--ERROR SCardStatus (no ScardState) Code=0x%.8x-->\n",
1801     (unsigned int) rv));
1802 stargo 1309 return SC_returnCode(rv, &lcHandle, in, out);
1803     }
1804     else
1805     {
1806 stargo 1319 #ifdef WITH_DEBUG_SCARD
1807     DEBUG_SCARD(("<--SUCCESS SCardStatus (no ScardState)-->\n"));
1808     DEBUG_SCARD(("[dwState 0x%.8x]\n", (unsigned int) dwState));
1809     DEBUG_SCARD(("[dwProtocol 0x%.8x]\n", (unsigned int) dwProtocol));
1810     DEBUG_SCARD(("[Atr]\n"));
1811 stargo 1309 hexdump(atr, dwAtrLen);
1812     #endif
1813     if (dwState & (SCARD_SPECIFIC | SCARD_NEGOTIABLE))
1814     dwState = 0x00000006;
1815     else
1816     #if 0
1817     if (dwState & SCARD_SPECIFIC)
1818     dwState = 0x00000006;
1819     else if (dwState & SCARD_NEGOTIABLE)
1820     dwState = 0x00000005;
1821     else
1822     #endif
1823     if (dwState & SCARD_POWERED)
1824     dwState = 0x00000004;
1825     else if (dwState & SCARD_SWALLOWED)
1826     dwState = 0x00000003;
1827     else if (dwState & SCARD_PRESENT)
1828     dwState = 0x00000002;
1829     else if (dwState & SCARD_ABSENT)
1830     dwState = 0x00000001;
1831     else
1832     dwState = 0x00000000;
1833    
1834     out_uint32_le(out, dwState);
1835     out_uint32_le(out, dwProtocol);
1836     out_uint32_le(out, dwAtrLen);
1837     out_uint32_le(out, 0x00000001);
1838     out_uint32_le(out, dwAtrLen);
1839     out_uint8p(out, atr, dwAtrLen);
1840     outRepos(out, dwAtrLen);
1841     }
1842     outForceAllignment(out, 8);
1843     SC_xfreeallmemory(&lcHandle);
1844     return rv;
1845     }
1846    
1847    
1848    
1849     #ifndef WITH_PCSC120
1850    
1851     static MYPCSC_DWORD
1852     TS_SCardListReaderGroups(STREAM in, STREAM out)
1853     {
1854     MYPCSC_DWORD rv;
1855     SERVER_SCARDCONTEXT hContext;
1856     SERVER_DWORD dwGroups;
1857     MYPCSC_DWORD groups;
1858     char *szGroups;
1859     PMEM_HANDLE lcHandle = NULL;
1860    
1861     in->p += 0x20;
1862     in_uint32_le(in, dwGroups);
1863     in->p += 0x04;
1864     in_uint32_le(in, hContext);
1865    
1866     if (dwGroups <= 0 || dwGroups == SCARD_AUTOALLOCATE || dwGroups > SCARD_MAX_MEM)
1867     dwGroups = SCARD_MAX_MEM;
1868    
1869     szGroups = SC_xmalloc(&lcHandle, dwGroups);
1870     if (!szGroups)
1871     return SC_returnNoMemoryError(&lcHandle, in, out);
1872    
1873     groups = dwGroups;
1874     rv = SCardListReaderGroups((MYPCSC_SCARDCONTEXT) hContext, szGroups, &groups);
1875     dwGroups = groups;
1876    
1877     if (rv)
1878     {
1879 stargo 1319 DEBUG_SCARD(("<--ERROR SCardListReaderGroups Code=0x%.8x-->\n", (unsigned int) rv));
1880 stargo 1309 return SC_returnCode(rv, &lcHandle, in, out);
1881     }
1882     else
1883     {
1884 stargo 1319 DEBUG_SCARD(("<--SUCCESS SCardListReaderGroups-->\n"));
1885 stargo 1309 }
1886    
1887    
1888     out_uint32_le(out, dwGroups);
1889     out_uint32_le(out, 0x00200000);
1890     out_uint32_le(out, dwGroups);
1891     out_uint8a(out, szGroups, dwGroups);
1892     outRepos(out, dwGroups);
1893     out_uint32_le(out, 0x00000000);
1894    
1895     outForceAllignment(out, 8);
1896     SC_xfreeallmemory(&lcHandle);
1897     return rv;
1898     }
1899    
1900     static MYPCSC_DWORD
1901     TS_SCardGetAttrib(STREAM in, STREAM out)
1902     {
1903     MYPCSC_DWORD rv;
1904     SERVER_SCARDCONTEXT hCard;
1905     MYPCSC_SCARDCONTEXT myHCard;
1906     SERVER_DWORD dwAttrId, dwAttrLen;
1907     MYPCSC_DWORD attrLen;
1908     unsigned char *pbAttr;
1909     PMEM_HANDLE lcHandle = NULL;
1910    
1911     in->p += 0x20;
1912     in_uint32_le(in, dwAttrId);
1913     in->p += 0x04;
1914     in_uint32_le(in, dwAttrLen);
1915     in->p += 0x0C;
1916     in_uint32_le(in, hCard);
1917     myHCard = scHandleToMyPCSC(hCard);
1918    
1919     dwAttrId = dwAttrId & 0x0000FFFF;
1920    
1921 stargo 1319 DEBUG_SCARD(("[hCard = 0x%.8x]\n", (unsigned int) hCard));
1922     DEBUG_SCARD(("[myHCard 0x%.8x]\n", (unsigned int) myHCard));
1923     DEBUG_SCARD(("[dwAttrId = 0x%.8x]\n", (unsigned int) dwAttrId));
1924     DEBUG_SCARD(("[dwAttrLen = 0x%.8x]\n", (unsigned int) dwAttrLen));
1925 stargo 1309
1926     if (dwAttrLen > MAX_BUFFER_SIZE)
1927     dwAttrLen = MAX_BUFFER_SIZE;
1928    
1929    
1930     if (dwAttrLen > SCARD_AUTOALLOCATE)
1931     pbAttr = NULL;
1932     else if ((dwAttrLen < 0) || (dwAttrLen > SCARD_MAX_MEM))
1933     {
1934     dwAttrLen = SCARD_AUTOALLOCATE;
1935     pbAttr = NULL;
1936     }
1937     else
1938     {
1939     pbAttr = SC_xmalloc(&lcHandle, dwAttrLen);
1940     if (!pbAttr)
1941     return SC_returnNoMemoryError(&lcHandle, in, out);
1942     }
1943    
1944     attrLen = dwAttrLen;
1945     rv = SCardGetAttrib(myHCard, (MYPCSC_DWORD) dwAttrId, pbAttr, &attrLen);
1946     dwAttrLen = attrLen;
1947    
1948     if (dwAttrId == 0x00000100 && rv != SCARD_S_SUCCESS)
1949     {
1950 stargo 1319 DEBUG_SCARD(("Get Attribute ATTR_VENDOR_NAME\n"));
1951 stargo 1309 pthread_mutex_lock(&hcardAccess);
1952     PSCHCardRec hcard = hcardFirst;
1953     while (hcard)
1954     {
1955     if (hcard->hCard == hCard)
1956     {
1957     dwAttrLen = strlen(hcard->vendor);
1958     memcpy(pbAttr, hcard->vendor, dwAttrLen);
1959     rv = SCARD_S_SUCCESS;
1960     break;
1961     }
1962     hcard = hcard->next;
1963     }
1964     pthread_mutex_unlock(&hcardAccess);
1965 stargo 1319 DEBUG_SCARD(("[0x%.8x]\n", (unsigned int) rv));
1966 stargo 1309 }
1967    
1968     if (rv != SCARD_S_SUCCESS)
1969     {
1970 stargo 1319 DEBUG_SCARD(("<--ERROR SCardGetAttrib Code=0x%.8x-->\n", (unsigned int) rv));
1971 stargo 1309 return SC_returnCode(rv, &lcHandle, in, out);
1972     }
1973     else
1974     {
1975 stargo 1319 #ifdef WITH_DEBUG_SCARD
1976     DEBUG_SCARD(("<--SUCCESS SCardGetAttrib-->\n"));
1977     DEBUG_SCARD(("[LENGTH %d]\n", (unsigned int) dwAttrLen));
1978     DEBUG_SCARD(("+++++++++++++++++++++\n"));
1979 stargo 1309 hexdump(pbAttr, dwAttrLen);
1980 stargo 1319 DEBUG_SCARD(("+++++++++++++++++++++\n"));
1981 stargo 1309 #endif
1982     out_uint32_le(out, dwAttrLen);
1983     out_uint32_le(out, 0x00000200);
1984     out_uint32_le(out, dwAttrLen);
1985     if (!pbAttr)
1986     {
1987     out_uint8s(out, dwAttrLen);
1988     }
1989     else
1990     {
1991     out_uint8p(out, pbAttr, dwAttrLen);
1992     }
1993     outRepos(out, dwAttrLen);
1994     out_uint32_le(out, 0x00000000);
1995     }
1996     outForceAllignment(out, 8);
1997     return rv;
1998     }
1999    
2000     static MYPCSC_DWORD
2001     TS_SCardSetAttrib(STREAM in, STREAM out)
2002     {
2003     MYPCSC_DWORD rv;
2004     SERVER_SCARDCONTEXT hCard;
2005     MYPCSC_SCARDCONTEXT myHCard;
2006     SERVER_DWORD dwAttrId;
2007     SERVER_DWORD dwAttrLen;
2008     unsigned char *pbAttr;
2009     PMEM_HANDLE lcHandle = NULL;
2010    
2011     in->p += 0x20;
2012     in_uint32_le(in, dwAttrId);
2013     in->p += 0x04;
2014     in_uint32_le(in, dwAttrLen);
2015     in->p += 0x0C;
2016     in_uint32_le(in, hCard);
2017     myHCard = scHandleToMyPCSC(hCard);
2018    
2019     dwAttrId = dwAttrId & 0x0000FFFF;
2020    
2021 stargo 1319 DEBUG_SCARD(("[hCard = 0x%.8x]\n", (unsigned int) hCard));
2022     DEBUG_SCARD(("[myHCard 0x%.8x]\n", (unsigned int) myHCard));
2023     DEBUG_SCARD(("[dwAttrId = 0x%.8x]\n", (unsigned int) dwAttrId));
2024     DEBUG_SCARD(("[dwAttrLen = 0x%.8x]\n", (unsigned int) dwAttrLen));
2025 stargo 1309
2026     if (dwAttrLen > MAX_BUFFER_SIZE)
2027     dwAttrLen = MAX_BUFFER_SIZE;
2028    
2029     pbAttr = SC_xmalloc(&lcHandle, dwAttrLen);
2030     if (!pbAttr)
2031     return SC_returnNoMemoryError(&lcHandle, in, out);
2032    
2033     in_uint8a(in, pbAttr, dwAttrLen);
2034     rv = SCardSetAttrib(myHCard, (MYPCSC_DWORD) dwAttrId, pbAttr, (MYPCSC_DWORD) dwAttrLen);
2035    
2036     if (rv)
2037 stargo 1319 {
2038     DEBUG_SCARD(("<--ERROR SCardSetAttrib Code=0x%.8x-->\n", (unsigned int) rv));
2039     }
2040 stargo 1309 else
2041 stargo 1319 {
2042     DEBUG_SCARD(("<--SUCCESS SCardSetAttrib-->\n"));
2043     }
2044    
2045 stargo 1309 out_uint32_le(out, 0x00000000);
2046     out_uint32_le(out, 0x00000200);
2047     out_uint32_le(out, 0x00000000);
2048     out_uint32_le(out, 0x00000000);
2049     outForceAllignment(out, 8);
2050     SC_xfreeallmemory(&lcHandle);
2051     return rv;
2052     }
2053    
2054     #endif
2055    
2056     static MYPCSC_DWORD
2057     TS_SCardControl(STREAM in, STREAM out)
2058     {
2059     MYPCSC_DWORD rv;
2060     SERVER_SCARDCONTEXT hContext;
2061     SERVER_SCARDHANDLE hCard;
2062     MYPCSC_SCARDHANDLE myHCard;
2063     SERVER_DWORD map[3];
2064     SERVER_DWORD dwControlCode;
2065 stargo 1311 unsigned char *pInBuffer, *pOutBuffer;
2066 stargo 1309 SERVER_DWORD nInBufferSize, nOutBufferSize, nOutBufferRealSize, nBytesReturned;
2067     MYPCSC_DWORD sc_nBytesReturned;
2068     PMEM_HANDLE lcHandle = NULL;
2069    
2070     pInBuffer = NULL;
2071     pOutBuffer = NULL;
2072    
2073     in->p += 0x14;
2074     in_uint32_le(in, map[0]);
2075     in->p += 0x04;
2076     in_uint32_le(in, map[1]);
2077     in_uint32_le(in, dwControlCode);
2078     in_uint32_le(in, nInBufferSize);
2079     in_uint32_le(in, map[2]);
2080     in->p += 0x04;
2081     in_uint32_le(in, nOutBufferSize);
2082     in->p += 0x04;
2083     in_uint32_le(in, hContext);
2084     in->p += 0x04;
2085     in_uint32_le(in, hCard);
2086     if (map[2] & INPUT_LINKED)
2087     {
2088     /* read real input size */
2089     in_uint32_le(in, nInBufferSize);
2090     pInBuffer = SC_xmalloc(&lcHandle, nInBufferSize);
2091     if (!pInBuffer)
2092     return SC_returnNoMemoryError(&lcHandle, in, out);
2093     in_uint8a(in, pInBuffer, nInBufferSize);
2094     }
2095    
2096     #if 0
2097     if (nOutBufferSize > 0)
2098     {
2099     nOutBufferRealSize = nOutBufferSize;
2100     }
2101     else
2102     #endif
2103     nOutBufferRealSize = 1024;
2104    
2105     nBytesReturned = nOutBufferRealSize;
2106    
2107     nBytesReturned = nOutBufferRealSize;
2108     pOutBuffer = SC_xmalloc(&lcHandle, nOutBufferRealSize);
2109     if (!pOutBuffer)
2110     return SC_returnNoMemoryError(&lcHandle, in, out);
2111    
2112 stargo 1319 #ifdef WITH_DEBUG_SCARD
2113     DEBUG_SCARD(("[hContext = 0x%.8x]\n", (unsigned int) hContext));
2114     DEBUG_SCARD(("[hCard = 0x%.8x]\n", (unsigned int) hCard));
2115     DEBUG_SCARD(("[dwControlCode = 0x%.8x]\n", (unsigned int) dwControlCode));
2116     DEBUG_SCARD(("[nInBufferSize = %d]\n", (unsigned int) nInBufferSize));
2117     DEBUG_SCARD(("[nOutBufferSize = %d]\n", (unsigned int) nOutBufferSize));
2118 stargo 1309 if (nInBufferSize > 0)
2119     {
2120 stargo 1319 DEBUG_SCARD(("[In buffer]\n"));
2121 stargo 1309 hexdump((unsigned char *) pInBuffer, nInBufferSize);
2122     }
2123 stargo 1319 DEBUG_SCARD(("---> Calling SCardControl\n"));
2124 stargo 1309 #endif
2125    
2126     sc_nBytesReturned = nBytesReturned;
2127     myHCard = scHandleToMyPCSC(hCard);
2128 stargo 1316 #ifdef WITH_PCSC120
2129 stargo 1309 rv = SCardControl(myHCard, pInBuffer, (MYPCSC_DWORD) nInBufferSize, pOutBuffer,
2130     &sc_nBytesReturned);
2131     #else
2132     rv = SCardControl(myHCard, (MYPCSC_DWORD) dwControlCode, pInBuffer,
2133     (MYPCSC_DWORD) nInBufferSize, pOutBuffer,
2134     (MYPCSC_DWORD) nOutBufferRealSize, &sc_nBytesReturned);
2135 stargo 1316 #endif
2136 stargo 1309 nBytesReturned = sc_nBytesReturned;
2137    
2138 stargo 1319 #ifdef WITH_DEBUG_SCARD
2139 stargo 1309 if (rv != SCARD_S_SUCCESS)
2140 stargo 1319 {
2141     DEBUG_SCARD(("<--ERROR SCardControl Code=0x%.8x-->\n", (unsigned int) rv));
2142     }
2143 stargo 1309 else
2144     {
2145 stargo 1319 DEBUG_SCARD(("<--SUCCESS SCardControl-->\n"));
2146     DEBUG_SCARD(("[LENGTH %d]\n", (unsigned int) nBytesReturned));
2147     DEBUG_SCARD(("+++++++++++++++++++++\n"));
2148 stargo 1309 hexdump((unsigned char *) pOutBuffer, nBytesReturned);
2149 stargo 1319 DEBUG_SCARD(("+++++++++++++++++++++\n"));
2150 stargo 1309 }
2151     #endif
2152    
2153     out_uint32_le(out, nBytesReturned);
2154     out_uint32_le(out, 0x00000004);
2155     out_uint32_le(out, nBytesReturned);
2156     if (nBytesReturned > 0)
2157     {
2158     out_uint8p(out, pOutBuffer, nBytesReturned);
2159     outRepos(out, nBytesReturned);
2160     }
2161    
2162     outForceAllignment(out, 8);
2163     SC_xfreeallmemory(&lcHandle);
2164     return rv;
2165     }
2166    
2167     static MYPCSC_DWORD
2168     TS_SCardAccessStartedEvent(STREAM in, STREAM out)
2169     {
2170     out_uint8s(out, 8);
2171     return SCARD_S_SUCCESS;
2172     }
2173    
2174    
2175     static NTSTATUS
2176     scard_device_control(NTHANDLE handle, uint32 request, STREAM in, STREAM out)
2177     {
2178     SERVER_DWORD Result = 0x00000000;
2179     unsigned char *psize, *pend, *pStatusCode;
2180     SERVER_DWORD addToEnd = 0;
2181 stargo 1319 #ifdef WITH_DEBUG_SCARD
2182     unsigned char *pbeg = out->p;
2183 stargo 1309
2184 stargo 1319 DEBUG_SCARD(("--------------------------------\n"));
2185     DEBUG_SCARD(("[NTHANDLE %08X]\n", handle));
2186     DEBUG_SCARD(("[REQUEST %08X]\n", request));
2187     DEBUG_SCARD(("[INPUT DUMP]--------------------\n"));
2188 stargo 1309 hexdump(in->p, in->end - in->p);
2189     #endif
2190     /* Processing request */
2191    
2192     out_uint32_le(out, 0x00081001); /* Header lines */
2193     out_uint32_le(out, 0xCCCCCCCC);
2194     psize = out->p;
2195     out_uint32_le(out, 0x00000000); /* Size of data portion */
2196     out_uint32_le(out, 0x00000000); /* Zero bytes (may be usefull) */
2197     pStatusCode = out->p;
2198     out_uint32_le(out, 0x00000000); /* Status Code */
2199    
2200     switch (request)
2201     {
2202     /* SCardEstablishContext */
2203     case SC_ESTABLISH_CONTEXT:
2204     {
2205 stargo 1319 DEBUG_SCARD(("<---SCardEstablishContext--->\n"));
2206 stargo 1309 Result = (SERVER_DWORD) TS_SCardEstablishContext(in, out);
2207     break;
2208     }
2209     /* SCardReleaseContext */
2210     case SC_RELEASE_CONTEXT:
2211     {
2212 stargo 1319 DEBUG_SCARD(("<---SCardReleaseContext--->\n"));
2213 stargo 1309 Result = (SERVER_DWORD) TS_SCardReleaseContext(in, out);
2214     break;
2215     }
2216     /* SCardIsValidContext */
2217     case SC_IS_VALID_CONTEXT:
2218     {
2219 stargo 1319 DEBUG_SCARD(("<---SCardIsValidContext--->\n"));
2220 stargo 1309 Result = (SERVER_DWORD) TS_SCardIsValidContext(in, out);
2221     break;
2222     }
2223     /* SCardListReaders */
2224     case SC_LIST_READERS: /* SCardListReadersA */
2225     case SC_LIST_READERS + 4: /* SCardListReadersW */
2226     {
2227     BOOL wide = request != SC_LIST_READERS;
2228 stargo 1319 DEBUG_SCARD(("<---SCardListReaders---> (%s)\n",
2229     (wide) ? ("WIDE") : ("ASCII")));
2230 stargo 1309 Result = (SERVER_DWORD) TS_SCardListReaders(in, out, wide);
2231     break;
2232     }
2233     /* ScardConnect */
2234     case SC_CONNECT: /* ScardConnectA */
2235     case SC_CONNECT + 4: /* SCardConnectW */
2236     {
2237     BOOL wide = request != SC_CONNECT;
2238 stargo 1319 DEBUG_SCARD(("<---SCardConnect---> (%s)\n",
2239     (wide) ? ("WIDE") : ("ASCII")));
2240 stargo 1309 Result = (SERVER_DWORD) TS_SCardConnect(in, out, wide);
2241     break;
2242     }
2243     /* ScardReconnect */
2244     case SC_RECONNECT:
2245     {
2246 stargo 1319 DEBUG_SCARD(("<---SCardReconnect--->\n"));
2247 stargo 1309 Result = (SERVER_DWORD) TS_SCardReconnect(in, out);
2248     break;
2249     }
2250     /* ScardDisconnect */
2251     case SC_DISCONNECT:
2252     {
2253 stargo 1319 DEBUG_SCARD(("<---SCardDisconnect--->\n"));
2254 stargo 1309 Result = (SERVER_DWORD) TS_SCardDisconnect(in, out);
2255     break;
2256     }
2257     /* ScardGetStatusChange */
2258     case SC_GET_STATUS_CHANGE: /* SCardGetStatusChangeA */
2259     case SC_GET_STATUS_CHANGE + 4: /* SCardGetStatusChangeW */
2260     {
2261     BOOL wide = request != SC_GET_STATUS_CHANGE;
2262 stargo 1319 DEBUG_SCARD(("<---SCardGetStatusChange---> (%s)\n",
2263     (wide) ? ("WIDE") : ("ASCII")));
2264 stargo 1309 Result = (SERVER_DWORD) TS_SCardGetStatusChange(in, out, wide);
2265     break;
2266     }
2267     /* SCardCancel */
2268     case SC_CANCEL:
2269     {
2270 stargo 1319 DEBUG_SCARD(("<---SCardCancel--->\n"));
2271 stargo 1309 Result = (SERVER_DWORD) TS_SCardCancel(in, out);
2272     break;
2273     }
2274     /* SCardLocateCardsByATR */
2275     case SC_LOCATE_CARDS_BY_ATR: /* SCardLocateCardsByATRA */
2276     case SC_LOCATE_CARDS_BY_ATR + 4: /* SCardLocateCardsByATRW */
2277     {
2278     BOOL wide = request != SC_LOCATE_CARDS_BY_ATR;
2279 stargo 1319 DEBUG_SCARD(("<---SCardLocateCardsByATR---> (%s)\n",
2280     (wide) ? ("WIDE") : ("ASCII")));
2281 stargo 1309 Result = (SERVER_DWORD) TS_SCardLocateCardsByATR(in, out, wide);
2282     break;
2283     }
2284     /* SCardBeginTransaction */
2285     case SC_BEGIN_TRANSACTION:
2286     {
2287 stargo 1319 DEBUG_SCARD(("<---SCardBeginTransaction--->\n"));
2288 stargo 1309 Result = (SERVER_DWORD) TS_SCardBeginTransaction(in, out);
2289     break;
2290     }
2291     /* SCardBeginTransaction */
2292     case SC_END_TRANSACTION:
2293     {
2294 stargo 1319 DEBUG_SCARD(("<---SCardEndTransaction--->\n"));
2295 stargo 1309 Result = (SERVER_DWORD) TS_SCardEndTransaction(in, out);
2296     break;
2297     }
2298     /* ScardTransmit */
2299     case SC_TRANSMIT:
2300     {
2301 stargo 1319 DEBUG_SCARD(("<---SCardTransmit--->\n"));
2302 stargo 1309 Result = (SERVER_DWORD) TS_SCardTransmit(in, out);
2303     break;
2304     }
2305     /* SCardControl */
2306     case SC_CONTROL:
2307     {
2308 stargo 1319 DEBUG_SCARD(("<---SCardControl--->\n"));
2309 stargo 1309 Result = (SERVER_DWORD) TS_SCardControl(in, out);
2310     break;
2311     }
2312     /* SCardGetAttrib */
2313     #ifndef WITH_PCSC120
2314     case SC_GETATTRIB:
2315     {
2316 stargo 1319 DEBUG_SCARD(("<---SCardGetAttrib--->\n"));
2317 stargo 1309 Result = (SERVER_DWORD) TS_SCardGetAttrib(in, out);
2318     break;
2319     }
2320     #endif
2321     case SC_ACCESS_STARTED_EVENT:
2322     {
2323 stargo 1319 DEBUG_SCARD(("<---SCardAccessStartedEvent-->\n"));
2324 stargo 1309 Result = (SERVER_DWORD) TS_SCardAccessStartedEvent(in, out);
2325     break;
2326     }
2327     case SC_STATUS: /* SCardStatusA */
2328     case SC_STATUS + 4: /* SCardStatusW */
2329     {
2330     BOOL wide = request != SC_STATUS;
2331 stargo 1319 DEBUG_SCARD(("<---SCardStatus---> (%s)\n",
2332     (wide) ? ("WIDE") : ("ASCII")));
2333 stargo 1309 Result = (SERVER_DWORD) TS_SCardStatus(in, out, wide);
2334     break;
2335     }
2336     case SC_STATE: /* SCardState */
2337     {
2338 stargo 1319 DEBUG_SCARD(("<---SCardState--->"));
2339 stargo 1309 Result = (SERVER_DWORD) TS_SCardState(in, out);
2340     break;
2341     }
2342     default:
2343     {
2344 stargo 1319 DEBUG_SCARD(("<---UNSUPPORTED-FUNC--->\n"));
2345 stargo 1309 Result = 0x80100014;
2346     out_uint8s(out, 256);
2347     break;
2348     }
2349     }
2350    
2351     #if 0
2352     out_uint32_le(out, 0x00000000);
2353     #endif
2354     /* Setting modified variables */
2355     pend = out->p;
2356     /* setting data size */
2357     out->p = psize;
2358     out_uint32_le(out, pend - psize - 16);
2359     /* setting status code */
2360     out->p = pStatusCode;
2361     out_uint32_le(out, Result);
2362     /* finish */
2363     out->p = pend;
2364    
2365     addToEnd = (pend - pStatusCode) % 16;
2366     if (addToEnd < 16 && addToEnd > 0)
2367     {
2368     out_uint8s(out, addToEnd);
2369     }
2370    
2371 stargo 1319 #ifdef WITH_DEBUG_SCARD
2372     DEBUG_SCARD(("[OUTPUT DUMP]-------------------\n"));
2373 stargo 1309 hexdump(pbeg, (size_t) (out->p) - (size_t) pbeg);
2374 stargo 1319 DEBUG_SCARD(("--------------------------------\n"));
2375 stargo 1309 #endif
2376     return STATUS_SUCCESS;
2377     }
2378    
2379     /* Thread functions */
2380    
2381     static STREAM
2382     duplicateStream(PMEM_HANDLE * handle, STREAM s, uint32 buffer_size, BOOL isInputStream)
2383     {
2384     STREAM d = SC_xmalloc(handle, sizeof(struct stream));
2385     if (d != NULL)
2386     {
2387     if (isInputStream)
2388     d->size = (size_t) (s->end) - (size_t) (s->data);
2389     else if (buffer_size < s->size)
2390     d->size = s->size;
2391     else
2392     d->size = buffer_size;
2393    
2394     d->data = SC_xmalloc(handle, d->size);
2395    
2396     d->end = (void *) ((size_t) (d->data) + (size_t) (s->end) - (size_t) (s->data));
2397     d->p = (void *) ((size_t) (d->data) + (size_t) (s->p) - (size_t) (s->data));
2398     d->iso_hdr =
2399     (void *) ((size_t) (d->data) + (size_t) (s->iso_hdr) - (size_t) (s->data));
2400     d->mcs_hdr =
2401     (void *) ((size_t) (d->data) + (size_t) (s->mcs_hdr) - (size_t) (s->data));
2402     d->sec_hdr =
2403     (void *) ((size_t) (d->data) + (size_t) (s->sec_hdr) - (size_t) (s->data));
2404     d->sec_hdr =
2405     (void *) ((size_t) (d->data) + (size_t) (s->sec_hdr) - (size_t) (s->data));
2406     d->rdp_hdr =
2407     (void *) ((size_t) (d->data) + (size_t) (s->rdp_hdr) - (size_t) (s->data));
2408     d->channel_hdr =
2409     (void *) ((size_t) (d->data) + (size_t) (s->channel_hdr) -
2410     (size_t) (s->data));
2411     if (isInputStream)
2412     memcpy(d->data, s->data, (size_t) (s->end) - (size_t) (s->data));
2413     else
2414     memcpy(d->data, s->data, (size_t) (s->p) - (size_t) (s->data));
2415     }
2416     return d;
2417     }
2418    
2419     static void
2420     freeStream(PMEM_HANDLE * handle, STREAM s)
2421     {
2422     if (s != NULL)
2423     {
2424     if (s->data != NULL)
2425     SC_xfree(handle, s->data);
2426     SC_xfree(handle, s);
2427     }
2428     }
2429    
2430     static PSCThreadData
2431     SC_addToQueue(NTHANDLE handle, uint32 request, STREAM in, STREAM out)
2432     {
2433     PMEM_HANDLE lcHandle = NULL;
2434     PSCThreadData data = SC_xmalloc(&lcHandle, sizeof(TSCThreadData));
2435    
2436     if (!data)
2437     return NULL;
2438     else
2439     {
2440     data->memHandle = lcHandle;
2441     data->device = curDevice;
2442     data->id = curId;
2443     data->handle = handle;
2444     data->request = request;
2445     data->in = duplicateStream(&(data->memHandle), in, 0, SC_TRUE);
2446     if (data->in == NULL)
2447     {
2448     SC_xfreeallmemory(&(data->memHandle));
2449     return NULL;
2450     }
2451     data->out =
2452     duplicateStream(&(data->memHandle), out, OUT_STREAM_SIZE + curBytesOut,
2453     SC_FALSE);
2454     if (data->out == NULL)
2455     {
2456     SC_xfreeallmemory(&(data->memHandle));
2457     return NULL;
2458     }
2459     data->next = NULL;
2460    
2461     pthread_mutex_lock(&queueAccess);
2462    
2463     if (queueLast)
2464     queueLast->next = data;
2465     queueLast = data;
2466     if (!queueFirst)
2467     queueFirst = data;
2468    
2469     pthread_mutex_unlock(&queueEmpty);
2470     pthread_mutex_unlock(&queueAccess);
2471     }
2472     return data;
2473     }
2474    
2475     static void
2476     SC_destroyThreadData(PSCThreadData data)
2477     {
2478     if (data)
2479     {
2480     PMEM_HANDLE handle = data->memHandle;
2481     SC_xfreeallmemory(&handle);
2482     }
2483     }
2484    
2485     static PSCThreadData
2486     SC_getNextInQueue()
2487     {
2488     PSCThreadData Result = NULL;
2489     pthread_mutex_lock(&queueAccess);
2490     if (queueFirst != NULL)
2491     {
2492     Result = queueFirst;
2493     queueFirst = queueFirst->next;
2494     if (!queueFirst)
2495     {
2496     queueLast = NULL;
2497     pthread_mutex_trylock(&queueEmpty);
2498     }
2499     Result->next = NULL;
2500     }
2501     pthread_mutex_unlock(&queueAccess);
2502     return Result;
2503     }
2504    
2505     static void
2506     SC_deviceControl(PSCThreadData data)
2507     {
2508     size_t buffer_len = 0;
2509     scard_device_control(data->handle, data->request, data->in, data->out);
2510     buffer_len = (size_t) data->out->p - (size_t) data->out->data;
2511     #if 0
2512     pthread_mutex_lock(&sendControl);
2513     #endif
2514     rdpdr_send_completion(data->device, data->id, 0, buffer_len, data->out->data, buffer_len);
2515     #if 0
2516     pthread_mutex_unlock(&sendControl);
2517     #endif
2518     SC_destroyThreadData(data);
2519     }
2520    
2521    
2522     static void *
2523     thread_function(PThreadListElement listElement)
2524     {
2525 stargo 1319 #ifdef WITH_DEBUG_SCARD
2526 stargo 1309 long sTime = 0;
2527     #endif
2528     if ((listElement != NULL) && (listElement->data != NULL))
2529     {
2530     while (1)
2531     {
2532 stargo 1319 #ifdef WITH_DEBUG_SCARD
2533 stargo 1309 sTime = time(NULL);
2534     #endif
2535     pthread_mutex_lock(&listElement->nodata);
2536     SC_deviceControl(listElement->data);
2537     listElement->data = NULL;
2538 stargo 1319 DEBUG_SCARD(("[HANDLING TIME %d]\n", (int) (time(NULL) - sTime)));
2539 stargo 1309 pthread_mutex_unlock(&listElement->busy);
2540     }
2541     }
2542     pthread_exit(NULL);
2543     return NULL;
2544     }
2545    
2546     static void
2547     SC_handleRequest(PSCThreadData data)
2548     {
2549     int Result = 0;
2550     PThreadListElement cur = threadList, last = threadList;
2551    
2552 stargo 1319 DEBUG_SCARD(("[THREAD COUNT %d]\n", threadCount));
2553 stargo 1309
2554     while (cur)
2555     {
2556     if (0 == pthread_mutex_trylock(&cur->busy))
2557     {
2558     cur->data = data;
2559     pthread_mutex_unlock(&cur->nodata);
2560     return;
2561     }
2562     else
2563     {
2564     last = cur;
2565     cur = cur->next;
2566     }
2567     }
2568    
2569     cur = SC_xmalloc(&threadListHandle, sizeof(TThreadListElement));
2570     if (!cur)
2571     return;
2572    
2573     threadCount++;
2574    
2575     cur->next = NULL;
2576     pthread_mutex_init(&cur->busy, NULL);
2577     pthread_mutex_init(&cur->nodata, NULL);
2578     pthread_mutex_trylock(&cur->busy);
2579     cur->data = data;
2580     pthread_mutex_unlock(&cur->nodata);
2581    
2582     Result = pthread_create(&cur->thread, NULL, (void *(*)(void *)) thread_function, cur);
2583     if (0 != Result)
2584     {
2585 stargo 1319 error("[THREAD CREATE ERROR 0x%.8x]\n", Result);
2586 stargo 1309 SC_xfree(&threadListHandle, cur);
2587     SC_destroyThreadData(data);
2588     data = NULL;
2589     }
2590     else if (last)
2591     last->next = cur;
2592     else
2593     threadList = cur;
2594     }
2595    
2596     static void *
2597     queue_handler_function(void *data)
2598     {
2599     PSCThreadData cur_data = NULL;
2600     while (1)
2601     {
2602     cur_data = SC_getNextInQueue();
2603     if (cur_data != NULL)
2604     {
2605     switch (cur_data->request)
2606     {
2607     case SC_ESTABLISH_CONTEXT:
2608     case SC_RELEASE_CONTEXT:
2609     {
2610     SC_deviceControl(cur_data);
2611     break;
2612     }
2613     default:
2614     {
2615     SC_handleRequest(cur_data);
2616     break;
2617     }
2618     }
2619     cur_data = NULL;
2620     }
2621     else
2622     pthread_mutex_lock(&queueEmpty);
2623     }
2624     return NULL;
2625     }
2626    
2627     static NTSTATUS
2628     thread_wrapper(NTHANDLE handle, uint32 request, STREAM in, STREAM out)
2629     {
2630     if (SC_addToQueue(handle, request, in, out))
2631     return STATUS_PENDING | 0xC0000000;
2632     else
2633     return STATUS_NO_SUCH_FILE;
2634     }
2635    
2636     DEVICE_FNS scard_fns = {
2637     scard_create,
2638     scard_close,
2639     scard_read,
2640     scard_write,
2641     thread_wrapper
2642     };
2643     #endif /* MAKE_PROTO */
2644    
2645     void
2646     scard_tcp_lock(void)
2647     {
2648     if (!tcp_sendcontrol_mutex)
2649     {
2650     tcp_sendcontrol_mutex = (pthread_mutex_t *) malloc(sizeof(pthread_mutex_t));
2651     pthread_mutex_init(tcp_sendcontrol_mutex, NULL);
2652     }
2653    
2654     pthread_mutex_lock(tcp_sendcontrol_mutex);
2655     }
2656    
2657     void
2658     scard_tcp_unlock(void)
2659     {
2660     pthread_mutex_unlock(tcp_sendcontrol_mutex);
2661     }
2662    
2663     STREAM
2664     scard_tcp_init(void)
2665     {
2666     STREAM result = NULL;
2667    
2668     result = &out[cur_stream_id];
2669     cur_stream_id = (cur_stream_id + 1) % STREAM_COUNT;
2670    
2671     return result;
2672     }
2673    
2674     void
2675     scard_tcp_connect(void)
2676     {
2677     int i;
2678    
2679     for (i = 0; i < STREAM_COUNT; i++)
2680     {
2681     out[i].size = 4096;
2682     out[i].data = (uint8 *) xmalloc(out[i].size);
2683     }
2684     }
2685    
2686     void
2687     scard_tcp_reset_state(void)
2688     {
2689     int i;
2690     struct stream *p;
2691    
2692     for (i = 0, p = out; i < STREAM_COUNT; i++, p++)
2693     {
2694     if (p->data != NULL)
2695     xfree(p->data);
2696     p->p = NULL;
2697     p->end = NULL;
2698     p->data = NULL;
2699     p->size = 0;
2700     p->iso_hdr = NULL;
2701     p->mcs_hdr = NULL;
2702     p->sec_hdr = NULL;
2703     p->rdp_hdr = NULL;
2704     p->channel_hdr = NULL;
2705     }
2706     }

  ViewVC Help
Powered by ViewVC 1.1.26