/[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 1414 - (hide annotations)
Thu Jun 28 12:52:13 2007 UTC (16 years, 11 months ago) by ossman_
File MIME type: text/plain
File size: 69647 byte(s)
Fix two crashes caused by improver handling of structures.

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

  ViewVC Help
Powered by ViewVC 1.1.26