/[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 1330 - (hide annotations)
Sat Nov 4 20:02:42 2006 UTC (17 years, 6 months ago) by stargo
File MIME type: text/plain
File size: 69979 byte(s)
add human readable error messages

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

  ViewVC Help
Powered by ViewVC 1.1.26