/[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 1368 - (hide annotations)
Thu Jan 4 23:19:54 2007 UTC (17 years, 5 months ago) by stargo
File MIME type: text/plain
File size: 70256 byte(s)
ignore PCSCs idea of BOOL

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

  ViewVC Help
Powered by ViewVC 1.1.26