/[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 1322 - (hide annotations)
Thu Nov 2 23:31:58 2006 UTC (17 years, 7 months ago) by stargo
File MIME type: text/plain
File size: 69784 byte(s)
always pad

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

  ViewVC Help
Powered by ViewVC 1.1.26