/[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 1373 - (hide annotations)
Mon Jan 8 12:38:34 2007 UTC (17 years, 5 months ago) by stargo
File MIME type: text/plain
File size: 70142 byte(s)
some more RD_BOOL

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

  ViewVC Help
Powered by ViewVC 1.1.26