/[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 1323 - (hide annotations)
Fri Nov 3 14:28:10 2006 UTC (17 years, 7 months ago) by stargo
File MIME type: text/plain
File size: 69506 byte(s)
Change email of Alexi Volkov
Remove smartcard banner from scard.c (ACKed by Alexi)

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

  ViewVC Help
Powered by ViewVC 1.1.26