/[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 1327 - (hide annotations)
Fri Nov 3 19:56:42 2006 UTC (17 years, 6 months ago) by stargo
File MIME type: text/plain
File size: 69516 byte(s)
make sure to lock the datapath of rdpdr_send_completion to prevent
simultaneous access to shared variables in multiple threads

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

  ViewVC Help
Powered by ViewVC 1.1.26