/[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 1415 - (hide annotations)
Tue Jul 3 14:08:06 2007 UTC (16 years, 11 months ago) by ossman_
File MIME type: text/plain
File size: 66665 byte(s)
Improve readability of smart card code.

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 ossman_ 1415 error("scard_enum_devices: 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 ossman_ 1415 error("scard_enum_devices: Can't initialize queue access mutex\n");
138 stargo 1309 return 0;
139     }
140    
141     if (0 != pthread_mutex_init(&queueEmpty, NULL))
142     {
143 ossman_ 1415 error("scard_enum_devices: Can't initialize queue control mutex\n");
144 stargo 1309 return 0;
145     }
146    
147     if (0 != pthread_mutex_init(&hcardAccess, NULL))
148     {
149 ossman_ 1415 error("scard_enum_devices: 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 ossman_ 1415 error("scard_enum_devices: 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 ossman_ 1415 DEBUG_SCARD(("SCARD: SCardEstablishContext()\n"));
605 stargo 1309 rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
606     if (rv)
607 stargo 1319 {
608 ossman_ 1415 DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
609     pcsc_stringify_error(rv), (unsigned int) rv));
610 stargo 1319 }
611 stargo 1309 else
612 stargo 1319 {
613 ossman_ 1415 DEBUG_SCARD(("SCARD: -> Success (context: 0x%08x)\n", (unsigned) hContext));
614 stargo 1319 }
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 ossman_ 1415 DEBUG_SCARD(("SCARD: SCardReleaseContext(context: 0x%08x)\n", (unsigned) hContext));
633 stargo 1309 rv = SCardReleaseContext((MYPCSC_SCARDCONTEXT) hContext);
634 stargo 1319
635 stargo 1309 if (rv)
636 stargo 1319 {
637 ossman_ 1415 DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
638     pcsc_stringify_error(rv), (unsigned int) rv));
639 stargo 1319 }
640 stargo 1309 else
641 stargo 1319 {
642 ossman_ 1415 DEBUG_SCARD(("SCARD: -> Success\n"));
643 stargo 1319 }
644    
645 stargo 1309 return rv;
646     }
647    
648     static MYPCSC_DWORD
649     TS_SCardIsValidContext(STREAM in, STREAM out)
650     {
651     MYPCSC_DWORD rv;
652     SERVER_SCARDCONTEXT hContext;
653     char *readers;
654     DWORD readerCount = 1024;
655     PMEM_HANDLE lcHandle = NULL;
656    
657     in->p += 0x1C;
658     in_uint32_le(in, hContext);
659 ossman_ 1415 DEBUG_SCARD(("SCARD: SCardIsValidContext(context: 0x%08x)\n", (unsigned) hContext));
660 stargo 1309 /* There is no realization of SCardIsValidContext in PC/SC Lite so we call SCardListReaders */
661    
662     readers = SC_xmalloc(&lcHandle, 1024);
663     if (!readers)
664     return SC_returnNoMemoryError(&lcHandle, in, out);
665    
666     rv = SCardListReaders((MYPCSC_SCARDCONTEXT) hContext, NULL, readers, &readerCount);
667 stargo 1319
668 stargo 1309 if (rv)
669     {
670 ossman_ 1415 DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
671     pcsc_stringify_error(rv), (unsigned int) rv));
672 stargo 1309 rv = SCARD_E_INVALID_HANDLE;
673     }
674     else
675 stargo 1319 {
676 ossman_ 1415 DEBUG_SCARD(("SCARD: -> Success\n"));
677 stargo 1319 }
678    
679 stargo 1326 outForceAlignment(out, 8);
680 stargo 1309 SC_xfreeallmemory(&lcHandle);
681     return rv;
682     }
683    
684    
685     static MYPCSC_DWORD
686 jsorg71 1372 TS_SCardListReaders(STREAM in, STREAM out, RD_BOOL wide)
687 stargo 1309 {
688     #define readerArraySize 1024
689     MYPCSC_DWORD rv;
690     SERVER_SCARDCONTEXT hContext;
691     SERVER_DWORD dataLength;
692     MYPCSC_DWORD cchReaders = readerArraySize;
693     unsigned char *plen1, *plen2, *pend;
694     char *readers, *cur;
695     PMEM_HANDLE lcHandle = NULL;
696    
697     in->p += 0x2C;
698     in_uint32_le(in, hContext);
699 ossman_ 1415 DEBUG_SCARD(("SCARD: SCardListReaders(context: 0x%08x)\n", (unsigned) hContext));
700 stargo 1309 plen1 = out->p;
701     out_uint32_le(out, 0x00000000); /* Temp value for data length as 0x0 */
702     out_uint32_le(out, 0x01760650);
703     plen2 = out->p;
704     out_uint32_le(out, 0x00000000); /* Temp value for data length as 0x0 */
705    
706     dataLength = 0;
707     readers = SC_xmalloc(&lcHandle, readerArraySize);
708     if (!readers)
709     return SC_returnNoMemoryError(&lcHandle, in, out);
710    
711    
712     readers[0] = '\0';
713     readers[1] = '\0';
714     rv = SCardListReaders((MYPCSC_SCARDCONTEXT) hContext, NULL, readers, &cchReaders);
715     cur = readers;
716 ossman_ 1415 if (rv != SCARD_S_SUCCESS)
717 stargo 1309 {
718 ossman_ 1415 DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
719     pcsc_stringify_error(rv), (unsigned int) rv));
720     }
721     else
722     {
723 stargo 1309 int i;
724     PSCNameMapRec tmpMap;
725 ossman_ 1415 DEBUG_SCARD(("SCARD: -> Success\n"));
726 stargo 1309 for (i = 0, tmpMap = nameMapList; i < nameMapCount; i++, tmpMap++)
727     {
728     dataLength += outString(out, tmpMap->alias, wide);
729     }
730    
731     int lenSC = strlen(cur);
732     if (lenSC == 0)
733     dataLength += outString(out, "\0", wide);
734     else
735     while (lenSC > 0)
736     {
737     if (!hasAlias(cur))
738 ossman_ 1415 {
739     DEBUG_SCARD(("SCARD: \"%s\"\n", cur));
740 stargo 1309 dataLength += outString(out, cur, wide);
741 ossman_ 1415 }
742 stargo 1309 cur = (void *) ((unsigned char *) cur + lenSC + 1);
743     lenSC = strlen(cur);
744     }
745     }
746    
747     dataLength += outString(out, "\0", wide);
748     outRepos(out, dataLength);
749    
750     pend = out->p;
751     out->p = plen1;
752     out_uint32_le(out, dataLength);
753     out->p = plen2;
754     out_uint32_le(out, dataLength);
755     out->p = pend;
756    
757 stargo 1326 outForceAlignment(out, 8);
758 stargo 1309 SC_xfreeallmemory(&lcHandle);
759     return rv;
760     }
761    
762    
763     static MYPCSC_DWORD
764 jsorg71 1372 TS_SCardConnect(STREAM in, STREAM out, RD_BOOL wide)
765 stargo 1309 {
766     MYPCSC_DWORD rv;
767     SCARDCONTEXT hContext;
768     char *szReader;
769     SERVER_DWORD dwShareMode;
770     SERVER_DWORD dwPreferredProtocol;
771     MYPCSC_SCARDHANDLE myHCard;
772     SERVER_SCARDHANDLE hCard;
773    
774     MYPCSC_DWORD dwActiveProtocol;
775     PMEM_HANDLE lcHandle = NULL;
776    
777     in->p += 0x1C;
778     in_uint32_le(in, dwShareMode);
779     in_uint32_le(in, dwPreferredProtocol);
780     inReaderName(&lcHandle, in, &szReader, wide);
781     in->p += 0x04;
782     in_uint32_le(in, hContext);
783 ossman_ 1415 DEBUG_SCARD(("SCARD: SCardConnect(context: 0x%08x, share: 0x%08x, proto: 0x%08x, reader: \"%s\")\n", (unsigned) hContext, (unsigned) dwShareMode, (unsigned) dwPreferredProtocol, szReader ? szReader : "NULL"));
784 stargo 1309 rv = SCardConnect(hContext, szReader, (MYPCSC_DWORD) dwShareMode,
785     (MYPCSC_DWORD) dwPreferredProtocol, &myHCard, &dwActiveProtocol);
786     hCard = scHandleToServer(myHCard);
787     if (rv != SCARD_S_SUCCESS)
788     {
789 ossman_ 1415 DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
790     pcsc_stringify_error(rv), (unsigned int) rv));
791 stargo 1309 }
792     else
793     {
794     char *szVendor = getVendor(szReader);
795 ossman_ 1415 DEBUG_SCARD(("SCARD: -> Success (hcard: 0x%08x [0x%08lx])\n",
796     (unsigned) hCard, (unsigned long) myHCard));
797 stargo 1309 if (szVendor && (strlen(szVendor) > 0))
798     {
799 ossman_ 1415 DEBUG_SCARD(("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 ossman_ 1415 DEBUG_SCARD(("SCARD: SCardReconnect(context: 0x%08x, hcard: 0x%08x [0x%08lx], share: 0x%08x, proto: 0x%08x, init: 0x%08x)\n", (unsigned) hContext, (unsigned) hCard, (unsigned long) myHCard, (unsigned) dwShareMode, (unsigned) dwPreferredProtocol, (unsigned) dwInitialization));
856 stargo 1309 rv = SCardReconnect(myHCard, (MYPCSC_DWORD) dwShareMode, (MYPCSC_DWORD) dwPreferredProtocol,
857     (MYPCSC_DWORD) dwInitialization, &dwActiveProtocol);
858     if (rv != SCARD_S_SUCCESS)
859 stargo 1319 {
860 ossman_ 1415 DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
861     pcsc_stringify_error(rv), (unsigned int) rv));
862 stargo 1319 }
863 stargo 1309 else
864 stargo 1319 {
865 ossman_ 1415 DEBUG_SCARD(("SCARD: -> Success (proto: 0x%08x)\n", (unsigned) dwActiveProtocol));
866 stargo 1319 }
867 stargo 1309
868 stargo 1326 outForceAlignment(out, 8);
869 stargo 1309 out_uint32_le(out, (SERVER_DWORD) dwActiveProtocol);
870     return rv;
871     }
872    
873     static MYPCSC_DWORD
874     TS_SCardDisconnect(STREAM in, STREAM out)
875     {
876     MYPCSC_DWORD rv;
877     SERVER_SCARDCONTEXT hContext;
878     SERVER_SCARDHANDLE hCard;
879     MYPCSC_SCARDHANDLE myHCard;
880     SERVER_DWORD dwDisposition;
881    
882     in->p += 0x20;
883     in_uint32_le(in, dwDisposition);
884     in->p += 0x04;
885     in_uint32_le(in, hContext);
886     in->p += 0x04;
887     in_uint32_le(in, hCard);
888    
889 ossman_ 1415 DEBUG_SCARD(("SCARD: SCardDisconnect(context: 0x%08x, hcard: 0x%08x, disposition: 0x%08x)\n", (unsigned) hContext, (unsigned) hCard, (unsigned) dwDisposition));
890 stargo 1309
891     pthread_mutex_lock(&hcardAccess);
892     PSCHCardRec hcard = hcardFirst;
893     while (hcard)
894     {
895     if (hcard->hCard == hCard)
896     {
897     if (hcard->prev)
898     hcard->prev->next = hcard->next;
899     if (hcard->next)
900     hcard->next->prev = hcard->prev;
901     if (hcardFirst == hcard)
902     hcardFirst = hcard->next;
903     xfree(hcard);
904     break;
905     }
906     hcard = hcard->next;
907     }
908     pthread_mutex_unlock(&hcardAccess);
909    
910     myHCard = scHandleToMyPCSC(hCard);
911     rv = SCardDisconnect(myHCard, (MYPCSC_DWORD) dwDisposition);
912    
913     if (rv != SCARD_S_SUCCESS)
914 stargo 1319 {
915 ossman_ 1415 DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
916     pcsc_stringify_error(rv), (unsigned int) rv));
917 stargo 1319 }
918 stargo 1309 else
919 stargo 1319 {
920 ossman_ 1415 DEBUG_SCARD(("SCARD: -> Success\n"));
921 stargo 1319 }
922    
923 stargo 1326 outForceAlignment(out, 8);
924 stargo 1309 return rv;
925     }
926    
927     static int
928     needStatusRecheck(MYPCSC_DWORD rv, MYPCSC_LPSCARD_READERSTATE_A rsArray, SERVER_DWORD dwCount)
929     {
930     int i, recall = 0;
931     if (rv == SCARD_S_SUCCESS)
932     {
933     MYPCSC_LPSCARD_READERSTATE_A cur;
934     for (i = 0, cur = rsArray; i < dwCount; i++, cur++)
935     {
936     if (cur->dwEventState & SCARD_STATE_UNKNOWN)
937     {
938     cur->dwCurrentState = cur->dwEventState;
939     recall++;
940     }
941     }
942     }
943     return recall;
944     }
945    
946 stargo 1373 static RD_BOOL
947 stargo 1309 mappedStatus(MYPCSC_DWORD code)
948     {
949     code >>= 16;
950     code &= 0x0000FFFF;
951     return (code % 2);
952     }
953    
954     static MYPCSC_DWORD
955 jsorg71 1372 incStatus(MYPCSC_DWORD code, RD_BOOL mapped)
956 stargo 1309 {
957     if (mapped || (code & SCARD_STATE_CHANGED))
958     {
959     MYPCSC_DWORD count = (code >> 16) & 0x0000FFFF;
960     count++;
961     if (mapped && !(count % 2))
962     count++;
963     return (code & 0x0000FFFF) | (count << 16);
964     }
965     else
966     return code;
967     }
968    
969     static void
970     copyReaderState_MyPCSCToServer(MYPCSC_LPSCARD_READERSTATE_A src, SERVER_LPSCARD_READERSTATE_A dst,
971     MYPCSC_DWORD readerCount)
972     {
973     MYPCSC_LPSCARD_READERSTATE_A srcIter;
974     SERVER_LPSCARD_READERSTATE_A dstIter;
975     MYPCSC_DWORD i;
976    
977     for (i = 0, srcIter = src, dstIter = dst; i < readerCount; i++, srcIter++, dstIter++)
978     {
979     dstIter->szReader = srcIter->szReader;
980     dstIter->pvUserData = srcIter->pvUserData;
981     dstIter->dwCurrentState = srcIter->dwCurrentState;
982     dstIter->dwEventState = srcIter->dwEventState;
983     dstIter->cbAtr = srcIter->cbAtr;
984     memcpy(dstIter->rgbAtr, srcIter->rgbAtr, MAX_ATR_SIZE * sizeof(unsigned char));
985     }
986     }
987    
988     static void
989     copyReaderState_ServerToMyPCSC(SERVER_LPSCARD_READERSTATE_A src, MYPCSC_LPSCARD_READERSTATE_A dst,
990     SERVER_DWORD readerCount)
991     {
992     SERVER_LPSCARD_READERSTATE_A srcIter;
993     MYPCSC_LPSCARD_READERSTATE_A dstIter;
994     SERVER_DWORD i;
995    
996     for (i = 0, srcIter = src, dstIter = dst; i < readerCount; i++, srcIter++, dstIter++)
997     {
998     dstIter->szReader = srcIter->szReader;
999     dstIter->pvUserData = srcIter->pvUserData;
1000     dstIter->dwCurrentState = srcIter->dwCurrentState;
1001     dstIter->dwEventState = srcIter->dwEventState;
1002     dstIter->cbAtr = srcIter->cbAtr;
1003     memcpy(dstIter->rgbAtr, srcIter->rgbAtr, MAX_ATR_SIZE * sizeof(unsigned char));
1004     }
1005     }
1006    
1007    
1008     static MYPCSC_DWORD
1009 jsorg71 1372 TS_SCardGetStatusChange(STREAM in, STREAM out, RD_BOOL wide)
1010 stargo 1309 {
1011     MYPCSC_DWORD rv;
1012     SERVER_SCARDCONTEXT hContext;
1013     SERVER_DWORD dwTimeout;
1014     SERVER_DWORD dwCount;
1015     SERVER_LPSCARD_READERSTATE_A rsArray, cur;
1016     SERVER_DWORD *stateArray = NULL, *curState;
1017     MYPCSC_LPSCARD_READERSTATE_A myRsArray;
1018     long i;
1019     PMEM_HANDLE lcHandle = NULL;
1020     #if 0
1021 jsorg71 1372 RD_BOOL mapped = False;
1022 stargo 1309 #endif
1023    
1024     in->p += 0x18;
1025     in_uint32_le(in, dwTimeout);
1026     in_uint32_le(in, dwCount);
1027     in->p += 0x08;
1028     in_uint32_le(in, hContext);
1029     in->p += 0x04;
1030 stargo 1319
1031 ossman_ 1415 DEBUG_SCARD(("SCARD: SCardGetStatusChange(context: 0x%08x, timeout: 0x%08x, count: %d)\n",
1032     (unsigned) hContext, (unsigned) dwTimeout, (int) dwCount));
1033 stargo 1319
1034 stargo 1309 if (dwCount > 0)
1035     {
1036     rsArray = SC_xmalloc(&lcHandle, dwCount * sizeof(SERVER_SCARD_READERSTATE_A));
1037     if (!rsArray)
1038     return SC_returnNoMemoryError(&lcHandle, in, out);
1039     memset(rsArray, 0, dwCount * sizeof(SERVER_SCARD_READERSTATE_A));
1040     stateArray = SC_xmalloc(&lcHandle, dwCount * sizeof(MYPCSC_DWORD));
1041     if (!stateArray)
1042     return SC_returnNoMemoryError(&lcHandle, in, out);
1043     /* skip two pointers at beginning of struct */
1044     for (i = 0, cur = (SERVER_LPSCARD_READERSTATE_A) ((unsigned char **) rsArray + 2);
1045     i < dwCount; i++, cur++)
1046     {
1047     in->p += 0x04;
1048     in_uint8a(in, cur, SERVER_SCARDSTATESIZE);
1049     }
1050    
1051     for (i = 0, cur = rsArray, curState = stateArray;
1052     i < dwCount; i++, cur++, curState++)
1053     {
1054     SERVER_DWORD dataLength;
1055    
1056     /* reset Current state hign bytes; */
1057     *curState = cur->dwCurrentState;
1058     cur->dwCurrentState &= 0x0000FFFF;
1059     cur->dwEventState &= 0x0000FFFF;
1060    
1061     #if 0
1062     if (cur->dwCurrentState == (SCARD_STATE_CHANGED | SCARD_STATE_PRESENT))
1063     {
1064     cur->dwCurrentState = 0x00000000;
1065     mapped = True;
1066     }
1067    
1068     if (mappedStatus(*curState))
1069     {
1070     cur->dwCurrentState &= ~SCARD_STATE_INUSE;
1071     cur->dwEventState &= ~SCARD_STATE_INUSE;
1072    
1073     if (cur->dwCurrentState & SCARD_STATE_EMPTY)
1074     {
1075     cur->dwCurrentState &= ~SCARD_STATE_EMPTY;
1076     cur->dwCurrentState |= SCARD_STATE_UNKNOWN;
1077     }
1078     }
1079     #endif
1080    
1081     in->p += 0x08;
1082     in_uint32_le(in, dataLength);
1083     inRepos(in,
1084     inString(&lcHandle, in, (char **) &(cur->szReader), dataLength,
1085     wide));
1086    
1087     if (strcmp(cur->szReader, "\\\\?PnP?\\Notification") == 0)
1088     cur->dwCurrentState |= SCARD_STATE_IGNORE;
1089 ossman_ 1415
1090     DEBUG_SCARD(("SCARD: \"%s\"\n", cur->szReader ? cur->szReader : "NULL"));
1091     DEBUG_SCARD(("SCARD: user: 0x%08x, state: 0x%08x, event: 0x%08x\n",
1092     (unsigned) cur->pvUserData, (unsigned) cur->dwCurrentState,
1093     (unsigned) cur->dwEventState));
1094     DEBUG_SCARD(("SCARD: current state: 0x%08x\n",
1095     (unsigned) *curState));
1096 stargo 1309 }
1097     }
1098     else
1099     {
1100     rsArray = NULL;
1101     stateArray = NULL;
1102     }
1103    
1104     myRsArray = SC_xmalloc(&lcHandle, dwCount * sizeof(MYPCSC_SCARD_READERSTATE_A));
1105     if (!rsArray)
1106     return SC_returnNoMemoryError(&lcHandle, in, out);
1107     memset(myRsArray, 0, dwCount * sizeof(SERVER_SCARD_READERSTATE_A));
1108     copyReaderState_ServerToMyPCSC(rsArray, myRsArray, (SERVER_DWORD) dwCount);
1109    
1110     rv = SCardGetStatusChange((MYPCSC_SCARDCONTEXT) hContext, (MYPCSC_DWORD) dwTimeout,
1111     myRsArray, (MYPCSC_DWORD) dwCount);
1112     copyReaderState_MyPCSCToServer(myRsArray, rsArray, (MYPCSC_DWORD) dwCount);
1113    
1114     if (rv != SCARD_S_SUCCESS)
1115 stargo 1319 {
1116 ossman_ 1415 DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
1117     pcsc_stringify_error(rv), (unsigned int) rv));
1118 stargo 1319 }
1119 stargo 1309 else
1120 stargo 1319 {
1121 ossman_ 1415 DEBUG_SCARD(("SCARD: -> Success\n"));
1122 stargo 1319 }
1123 stargo 1309
1124     out_uint32_le(out, dwCount);
1125     out_uint32_le(out, 0x00084dd8);
1126     out_uint32_le(out, dwCount);
1127    
1128     for (i = 0, cur = rsArray, curState = stateArray; i < dwCount; i++, cur++, curState++)
1129     {
1130    
1131     cur->dwCurrentState = (*curState);
1132     cur->dwEventState |= (*curState) & 0xFFFF0000;
1133    
1134     #if 0
1135     if (mapped && (cur->dwCurrentState & SCARD_STATE_PRESENT)
1136     && (cur->dwCurrentState & SCARD_STATE_CHANGED)
1137     && (cur->dwEventState & SCARD_STATE_PRESENT)
1138     && (cur->dwEventState & SCARD_STATE_CHANGED))
1139     {
1140     cur->dwEventState |= SCARD_STATE_INUSE;
1141     }
1142     else if (cur->dwEventState & SCARD_STATE_UNKNOWN)
1143     {
1144     cur->dwEventState &= ~SCARD_STATE_UNKNOWN;
1145     cur->dwEventState |= SCARD_STATE_EMPTY;
1146     mapped = True;
1147     }
1148     else if ((!mapped) && (cur->dwEventState & SCARD_STATE_INUSE))
1149     {
1150     mapped = True;
1151     cur->dwEventState &= ~SCARD_STATE_INUSE;
1152     }
1153    
1154     cur->dwEventState = incStatus(cur->dwEventState, mapped);
1155     #endif
1156     cur->dwEventState = incStatus(cur->dwEventState, False);
1157    
1158 ossman_ 1415 DEBUG_SCARD(("SCARD: \"%s\"\n", cur->szReader ? cur->szReader : "NULL"));
1159     DEBUG_SCARD(("SCARD: user: 0x%08x, state: 0x%08x, event: 0x%08x\n",
1160     (unsigned) cur->pvUserData, (unsigned) cur->dwCurrentState,
1161     (unsigned) cur->dwEventState));
1162    
1163 stargo 1309 out_uint8p(out, (void *) ((unsigned char **) cur + 2),
1164     sizeof(SERVER_SCARD_READERSTATE_A) - 2 * sizeof(unsigned char *));
1165     }
1166 stargo 1326 outForceAlignment(out, 8);
1167 stargo 1309 SC_xfreeallmemory(&lcHandle);
1168     return rv;
1169     }
1170    
1171     static MYPCSC_DWORD
1172     TS_SCardCancel(STREAM in, STREAM out)
1173     {
1174     MYPCSC_DWORD rv;
1175     SERVER_SCARDCONTEXT hContext;
1176    
1177     in->p += 0x1C;
1178     in_uint32_le(in, hContext);
1179 ossman_ 1415 DEBUG_SCARD(("SCARD: SCardCancel(context: 0x%08x)\n", (unsigned) hContext));
1180 stargo 1309 rv = SCardCancel((MYPCSC_SCARDCONTEXT) hContext);
1181     if (rv != SCARD_S_SUCCESS)
1182 stargo 1319 {
1183 ossman_ 1415 DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
1184     pcsc_stringify_error(rv), (unsigned int) rv));
1185 stargo 1319 }
1186 stargo 1309 else
1187 stargo 1319 {
1188 ossman_ 1415 DEBUG_SCARD(("SCARD: -> Success\n"));
1189 stargo 1319 }
1190 stargo 1326 outForceAlignment(out, 8);
1191 stargo 1309 return rv;
1192     }
1193    
1194     static MYPCSC_DWORD
1195 jsorg71 1372 TS_SCardLocateCardsByATR(STREAM in, STREAM out, RD_BOOL wide)
1196 stargo 1309 {
1197     int i, j, k;
1198     MYPCSC_DWORD rv;
1199     SERVER_SCARDCONTEXT hContext;
1200     /* The SCARD_ATRMASK_L struct doesn't contain any longs or DWORDs -
1201     no need to split into SERVER_ and MYPCSC_ */
1202     LPSCARD_ATRMASK_L pAtrMasks, cur;
1203     SERVER_DWORD atrMaskCount = 0;
1204     SERVER_DWORD readerCount = 0;
1205     SERVER_LPSCARD_READERSTATE_A rsArray, ResArray, rsCur;
1206     MYPCSC_LPSCARD_READERSTATE_A myRsArray;
1207     PMEM_HANDLE lcHandle = NULL;
1208    
1209     in->p += 0x2C;
1210     in_uint32_le(in, hContext);
1211     in_uint32_le(in, atrMaskCount);
1212     pAtrMasks = SC_xmalloc(&lcHandle, atrMaskCount * sizeof(SCARD_ATRMASK_L));
1213     if (!pAtrMasks)
1214     return SC_returnNoMemoryError(&lcHandle, in, out);
1215     in_uint8a(in, pAtrMasks, atrMaskCount * sizeof(SCARD_ATRMASK_L));
1216    
1217     in_uint32_le(in, readerCount);
1218     rsArray = SC_xmalloc(&lcHandle, readerCount * sizeof(SCARD_READERSTATE_A));
1219     if (!rsArray)
1220     return SC_returnNoMemoryError(&lcHandle, in, out);
1221     memset(rsArray, 0, readerCount * sizeof(SCARD_READERSTATE_A));
1222    
1223 ossman_ 1415 DEBUG_SCARD(("SCARD: SCardLocateCardsByATR(context: 0x%08x, atrs: %d, readers: %d)\n",
1224     (unsigned) hContext, (int) atrMaskCount, (int) readerCount));
1225    
1226     for (i = 0, cur = pAtrMasks; i < atrMaskCount; i++, cur++)
1227     {
1228     DEBUG_SCARD(("SCARD: ATR: "));
1229     for (j = 0; j < pAtrMasks->cbAtr; j++)
1230     {
1231     DEBUG_SCARD(("%02x%c",
1232     (unsigned) (unsigned char) cur->rgbAtr[j],
1233     (j == pAtrMasks->cbAtr - 1) ? ' ' : ':'))}
1234     DEBUG_SCARD(("\n"));
1235     DEBUG_SCARD(("SCARD: "));
1236     for (j = 0; j < pAtrMasks->cbAtr; j++)
1237     {
1238     DEBUG_SCARD(("%02x%c",
1239     (unsigned) (unsigned char) cur->rgbMask[j],
1240     (j == pAtrMasks->cbAtr - 1) ? ' ' : ':'))}
1241     DEBUG_SCARD(("\n"));
1242     }
1243    
1244 stargo 1309 for (i = 0, rsCur = (SERVER_LPSCARD_READERSTATE_A) ((unsigned char **) rsArray + 2);
1245     i < readerCount; i++, rsCur++)
1246     {
1247     in_uint8s(in, 4);
1248     in_uint8a(in, rsCur, SERVER_SCARDSTATESIZE);
1249     }
1250    
1251     ResArray = SC_xmalloc(&lcHandle, readerCount * sizeof(SERVER_SCARD_READERSTATE_A));
1252     if (!ResArray)
1253     return SC_returnNoMemoryError(&lcHandle, in, out);
1254     memcpy(ResArray, rsArray, readerCount * sizeof(SERVER_SCARD_READERSTATE_A));
1255    
1256     for (i = 0, rsCur = rsArray; i < readerCount; i++, rsCur++)
1257     {
1258     inReaderName(&lcHandle, in, (char **) &rsCur->szReader, wide);
1259 ossman_ 1415 DEBUG_SCARD(("SCARD: \"%s\"\n", rsCur->szReader ? rsCur->szReader : "NULL"));
1260     DEBUG_SCARD(("SCARD: user: 0x%08x, state: 0x%08x, event: 0x%08x\n",
1261     (unsigned) rsCur->pvUserData, (unsigned) rsCur->dwCurrentState,
1262     (unsigned) rsCur->dwEventState));
1263 stargo 1309 }
1264    
1265     /* FIXME segfault here. */
1266     myRsArray = SC_xmalloc(&lcHandle, readerCount * sizeof(MYPCSC_SCARD_READERSTATE_A));
1267     if (!myRsArray)
1268     return SC_returnNoMemoryError(&lcHandle, in, out);
1269 ossman_ 1414 copyReaderState_ServerToMyPCSC(rsArray, myRsArray, readerCount);
1270 stargo 1309 rv = SCardGetStatusChange((MYPCSC_SCARDCONTEXT) hContext, 0x00000001, myRsArray,
1271     readerCount);
1272     copyReaderState_MyPCSCToServer(myRsArray, rsArray, readerCount);
1273     if (rv != SCARD_S_SUCCESS)
1274     {
1275 ossman_ 1415 DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
1276     pcsc_stringify_error(rv), (unsigned int) rv));
1277 stargo 1309 }
1278     else
1279     {
1280 ossman_ 1415 DEBUG_SCARD(("SCARD: -> Success\n"));
1281 stargo 1309 cur = pAtrMasks;
1282     for (i = 0, cur = pAtrMasks; i < atrMaskCount; i++, cur++)
1283     {
1284     for (j = 0, rsCur = rsArray; j < readerCount; j++, rsCur++)
1285     {
1286 jsorg71 1372 RD_BOOL equal = 1;
1287 stargo 1309 for (k = 0; k < cur->cbAtr; k++)
1288     {
1289     /* This line check if them equal */
1290     if (cur->rgbAtr[k] != rsCur->rgbAtr[k])
1291     /* Next Line was make to search with mask (some strange behavours with applications which use eToken SmartCards) */
1292     /* if((cur->rgbAtr[k]&cur->rgbMask[k])!=(rsCur->rgbAtr[k]&cur->rgbMask[k])){ */
1293     {
1294     equal = 0;
1295     break;
1296     }
1297     }
1298     if (equal)
1299     {
1300     rsCur->dwEventState |= 0x00000040; /* SCARD_STATE_ATRMATCH 0x00000040 */
1301     memcpy(ResArray + j, rsCur, sizeof(SCARD_READERSTATE_A));
1302 ossman_ 1415 DEBUG_SCARD(("SCARD: \"%s\"\n",
1303     rsCur->szReader ? rsCur->szReader : "NULL"));
1304     DEBUG_SCARD(("SCARD: user: 0x%08x, state: 0x%08x, event: 0x%08x\n", (unsigned) rsCur->pvUserData, (unsigned) rsCur->dwCurrentState, (unsigned) rsCur->dwEventState));
1305 stargo 1309 }
1306     }
1307     }
1308     }
1309    
1310     out_uint32_le(out, readerCount);
1311     out_uint32_le(out, 0x00084dd8);
1312     out_uint32_le(out, readerCount);
1313    
1314     for (i = 0, rsCur = rsArray; i < readerCount; i++, rsCur++)
1315     {
1316     out_uint8p(out, (void *) ((unsigned char **) rsCur + 2),
1317     sizeof(SCARD_READERSTATE_A) - 2 * sizeof(unsigned char *));
1318     }
1319    
1320 stargo 1326 outForceAlignment(out, 8);
1321 stargo 1309 SC_xfreeallmemory(&lcHandle);
1322     return rv;
1323     }
1324    
1325     static DWORD
1326     TS_SCardBeginTransaction(STREAM in, STREAM out)
1327     {
1328     MYPCSC_DWORD rv;
1329     SERVER_SCARDCONTEXT hCard;
1330     MYPCSC_SCARDCONTEXT myHCard;
1331    
1332     in->p += 0x30;
1333     in_uint32_le(in, hCard);
1334     myHCard = scHandleToMyPCSC(hCard);
1335 ossman_ 1415 DEBUG_SCARD(("SCARD: SCardBeginTransaction(hcard: 0x%08x [0x%08lx])\n",
1336     (unsigned) hCard, (unsigned long) myHCard));
1337 stargo 1309 rv = SCardBeginTransaction(myHCard);
1338     if (rv != SCARD_S_SUCCESS)
1339 stargo 1319 {
1340 ossman_ 1415 DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
1341     pcsc_stringify_error(rv), (unsigned int) rv));
1342 stargo 1319 }
1343 stargo 1309 else
1344 stargo 1319 {
1345 ossman_ 1415 DEBUG_SCARD(("SCARD: -> Success\n"));
1346 stargo 1319 }
1347 stargo 1326 outForceAlignment(out, 8);
1348 stargo 1309 return rv;
1349     }
1350    
1351     static DWORD
1352     TS_SCardEndTransaction(STREAM in, STREAM out)
1353     {
1354     MYPCSC_DWORD rv;
1355     SERVER_SCARDCONTEXT hCard;
1356     MYPCSC_SCARDCONTEXT myHCard;
1357     SERVER_DWORD dwDisposition = 0;
1358    
1359     in->p += 0x20;
1360     in_uint32_le(in, dwDisposition);
1361     in->p += 0x0C;
1362     in_uint32_le(in, hCard);
1363     myHCard = scHandleToMyPCSC(hCard);
1364 stargo 1319
1365     DEBUG_SCARD(("[hCard = 0x%.8x]\n", (unsigned int) hCard));
1366     DEBUG_SCARD(("[myHCard = 0x%016lx]\n", (unsigned long) myHCard));
1367     DEBUG_SCARD(("[dwDisposition = 0x%.8x]\n", (unsigned int) dwDisposition));
1368    
1369 ossman_ 1415 DEBUG_SCARD(("SCARD: SCardEndTransaction(hcard: 0x%08x [0x%08lx], disposition: 0x%08x)\n",
1370     (unsigned) hCard, (unsigned long) myHCard, (unsigned) dwDisposition));
1371 stargo 1309 rv = SCardEndTransaction(myHCard, (MYPCSC_DWORD) dwDisposition);
1372     if (rv != SCARD_S_SUCCESS)
1373 stargo 1319 {
1374 ossman_ 1415 DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
1375     pcsc_stringify_error(rv), (unsigned int) rv));
1376 stargo 1319 }
1377 stargo 1309 else
1378 stargo 1319 {
1379 ossman_ 1415 DEBUG_SCARD(("SCARD: -> Success\n"));
1380 stargo 1319 }
1381 stargo 1326 outForceAlignment(out, 8);
1382 stargo 1309 return rv;
1383     }
1384    
1385    
1386     static void
1387     copyIORequest_MyPCSCToServer(MYPCSC_LPSCARD_IO_REQUEST src, SERVER_LPSCARD_IO_REQUEST dst)
1388     {
1389     unsigned char *srcBytes, *dstBytes;
1390     size_t bytesToCopy = src->cbPciLength - sizeof(MYPCSC_SCARD_IO_REQUEST);
1391     srcBytes = ((unsigned char *) src + sizeof(MYPCSC_SCARD_IO_REQUEST));
1392     dstBytes = ((unsigned char *) dst + sizeof(SERVER_SCARD_IO_REQUEST));
1393     dst->dwProtocol = src->dwProtocol;
1394     dst->cbPciLength = src->cbPciLength
1395     - sizeof(MYPCSC_SCARD_IO_REQUEST) + sizeof(SERVER_SCARD_IO_REQUEST);
1396     memcpy(dstBytes, srcBytes, bytesToCopy);
1397     }
1398    
1399     static void
1400     copyIORequest_ServerToMyPCSC(SERVER_LPSCARD_IO_REQUEST src, MYPCSC_LPSCARD_IO_REQUEST dst)
1401     {
1402     unsigned char *srcBytes, *dstBytes;
1403     size_t bytesToCopy = src->cbPciLength - sizeof(SERVER_SCARD_IO_REQUEST);
1404     srcBytes = ((unsigned char *) src + sizeof(SERVER_SCARD_IO_REQUEST));
1405     dstBytes = ((unsigned char *) dst + sizeof(MYPCSC_SCARD_IO_REQUEST));
1406     dst->dwProtocol = src->dwProtocol;
1407     dst->cbPciLength = src->cbPciLength
1408     - sizeof(SERVER_SCARD_IO_REQUEST) + sizeof(MYPCSC_SCARD_IO_REQUEST);
1409     memcpy(dstBytes, srcBytes, bytesToCopy);
1410     }
1411    
1412    
1413     static DWORD
1414     TS_SCardTransmit(STREAM in, STREAM out)
1415     {
1416     MYPCSC_DWORD rv;
1417     SERVER_DWORD map[7], linkedLen;
1418     void *tmp;
1419     SERVER_SCARDCONTEXT hCard;
1420     MYPCSC_SCARDCONTEXT myHCard;
1421     SERVER_LPSCARD_IO_REQUEST pioSendPci, pioRecvPci;
1422     MYPCSC_LPSCARD_IO_REQUEST myPioSendPci, myPioRecvPci;
1423     unsigned char *sendBuf = NULL, *recvBuf = NULL;
1424     SERVER_DWORD cbSendLength, cbRecvLength;
1425     MYPCSC_DWORD myCbRecvLength;
1426     PMEM_HANDLE lcHandle = NULL;
1427    
1428     in->p += 0x14;
1429     in_uint32_le(in, map[0]);
1430     in->p += 0x04;
1431     in_uint32_le(in, map[1]);
1432     pioSendPci = SC_xmalloc(&lcHandle, sizeof(SERVER_SCARD_IO_REQUEST));
1433     if (!pioSendPci)
1434     return SC_returnNoMemoryError(&lcHandle, in, out);
1435     in_uint8a(in, pioSendPci, sizeof(SERVER_SCARD_IO_REQUEST));
1436     in_uint32_le(in, map[2]);
1437     in_uint32_le(in, cbSendLength);
1438     in_uint32_le(in, map[3]);
1439     in_uint32_le(in, map[4]);
1440     in_uint32_le(in, map[5]);
1441     in_uint32_le(in, cbRecvLength);
1442     if (map[0] & INPUT_LINKED)
1443     inSkipLinked(in);
1444    
1445     in->p += 0x04;
1446     in_uint32_le(in, hCard);
1447     myHCard = scHandleToMyPCSC(hCard);
1448    
1449     if (map[2] & INPUT_LINKED)
1450     {
1451     in_uint32_le(in, linkedLen);
1452     pioSendPci->cbPciLength = linkedLen + sizeof(SERVER_SCARD_IO_REQUEST);
1453     tmp = SC_xmalloc(&lcHandle, pioSendPci->cbPciLength);
1454     if (!tmp)
1455     return SC_returnNoMemoryError(&lcHandle, in, out);
1456     in_uint8a(in, (void *) ((unsigned char *) tmp + sizeof(SERVER_SCARD_IO_REQUEST)),
1457     linkedLen);
1458     memcpy(tmp, pioSendPci, sizeof(SERVER_SCARD_IO_REQUEST));
1459     SC_xfree(&lcHandle, pioSendPci);
1460     pioSendPci = tmp;
1461     tmp = NULL;
1462     }
1463     else
1464     pioSendPci->cbPciLength = sizeof(SERVER_SCARD_IO_REQUEST);
1465    
1466     if (map[3] & INPUT_LINKED)
1467     {
1468     in_uint32_le(in, linkedLen);
1469     sendBuf = SC_xmalloc(&lcHandle, linkedLen);
1470     if (!sendBuf)
1471     return SC_returnNoMemoryError(&lcHandle, in, out);
1472     in_uint8a(in, sendBuf, linkedLen);
1473     inRepos(in, linkedLen);
1474     }
1475     else
1476     sendBuf = NULL;
1477    
1478     if (cbRecvLength)
1479     {
1480     recvBuf = SC_xmalloc(&lcHandle, cbRecvLength);
1481     if (!recvBuf)
1482     return SC_returnNoMemoryError(&lcHandle, in, out);
1483     }
1484    
1485     if (map[4] & INPUT_LINKED)
1486     {
1487     pioRecvPci = SC_xmalloc(&lcHandle, sizeof(SERVER_SCARD_IO_REQUEST));
1488     if (!pioRecvPci)
1489     return SC_returnNoMemoryError(&lcHandle, in, out);
1490     in_uint8a(in, pioRecvPci, sizeof(SERVER_SCARD_IO_REQUEST));
1491     in_uint32_le(in, map[6]);
1492     if (map[6] & INPUT_LINKED)
1493     {
1494     in_uint32_le(in, linkedLen);
1495     pioRecvPci->cbPciLength = linkedLen + sizeof(SERVER_SCARD_IO_REQUEST);
1496     tmp = SC_xmalloc(&lcHandle, pioRecvPci->cbPciLength);
1497     if (!tmp)
1498     return SC_returnNoMemoryError(&lcHandle, in, out);
1499     in_uint8a(in,
1500     (void *) ((unsigned char *) tmp +
1501     sizeof(SERVER_SCARD_IO_REQUEST)), linkedLen);
1502     memcpy(tmp, pioRecvPci, sizeof(SERVER_SCARD_IO_REQUEST));
1503     SC_xfree(&lcHandle, pioRecvPci);
1504     pioRecvPci = tmp;
1505     tmp = NULL;
1506     }
1507     else
1508     pioRecvPci->cbPciLength = sizeof(SERVER_SCARD_IO_REQUEST);
1509     }
1510     else
1511     pioRecvPci = NULL;
1512    
1513 ossman_ 1415 DEBUG_SCARD(("SCARD: SCardTransmit(hcard: 0x%08x [0x%08lx], send: %d bytes, recv: %d bytes)\n", (unsigned) hCard, (unsigned long) myHCard, (int) cbSendLength, (int) cbRecvLength));
1514 stargo 1319
1515 stargo 1309 myCbRecvLength = cbRecvLength;
1516     myPioSendPci = SC_xmalloc(&lcHandle,
1517     sizeof(MYPCSC_SCARD_IO_REQUEST)
1518     + pioSendPci->cbPciLength - sizeof(SERVER_SCARD_IO_REQUEST));
1519     if (!myPioSendPci)
1520     return SC_returnNoMemoryError(&lcHandle, in, out);
1521     copyIORequest_ServerToMyPCSC(pioSendPci, myPioSendPci);
1522     /* always a send, not always a recv */
1523     if (pioRecvPci)
1524     {
1525     myPioRecvPci = SC_xmalloc(&lcHandle,
1526     sizeof(MYPCSC_SCARD_IO_REQUEST)
1527     + pioRecvPci->cbPciLength
1528     - sizeof(SERVER_SCARD_IO_REQUEST));
1529     if (!myPioRecvPci)
1530     return SC_returnNoMemoryError(&lcHandle, in, out);
1531     copyIORequest_ServerToMyPCSC(pioRecvPci, myPioRecvPci);
1532     }
1533     else
1534     {
1535     myPioRecvPci = NULL;
1536     }
1537     rv = SCardTransmit(myHCard, myPioSendPci, sendBuf, (MYPCSC_DWORD) cbSendLength,
1538     myPioRecvPci, recvBuf, &myCbRecvLength);
1539     cbRecvLength = myCbRecvLength;
1540 stargo 1317
1541     /* FIXME: handle responses with length > 448 bytes */
1542     if (cbRecvLength > 448)
1543     {
1544     warning("Card response limited from %d to 448 bytes!\n", cbRecvLength);
1545 ossman_ 1415 DEBUG_SCARD(("SCARD: Truncated %d to %d\n", (unsigned int) cbRecvLength, 448));
1546 stargo 1317 cbRecvLength = 448;
1547     }
1548    
1549 stargo 1309 if (pioRecvPci)
1550     {
1551 ossman_ 1414 /*
1552     * pscs-lite mishandles this structure in some cases.
1553     * make sure we only copy it if it is valid.
1554     */
1555     if (myPioRecvPci->cbPciLength >= sizeof(MYPCSC_SCARD_IO_REQUEST))
1556     copyIORequest_MyPCSCToServer(myPioRecvPci, pioRecvPci);
1557 stargo 1309 }
1558    
1559     if (rv != SCARD_S_SUCCESS)
1560     {
1561 ossman_ 1415 DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
1562     pcsc_stringify_error(rv), (unsigned int) rv));
1563 stargo 1309 }
1564     else
1565     {
1566 ossman_ 1415 DEBUG_SCARD(("SCARD: -> Success (%d bytes)\n", (int) cbRecvLength));
1567 stargo 1309 #if 0
1568     if ((pioRecvPci != NULL) && (pioRecvPci->cbPciLength > 0))
1569     {
1570     out_uint32_le(out, (DWORD) pioRecvPci); /* if not NULL, this 4 bytes indicates that pioRecvPci is present */
1571     }
1572     else
1573     #endif
1574     out_uint32_le(out, 0); /* pioRecvPci 0x00; */
1575    
1576     outBufferStart(out, cbRecvLength); /* start of recvBuf output */
1577    
1578     #if 0
1579     if ((pioRecvPci) && (pioRecvPci->cbPciLength > 0))
1580     {
1581     out_uint32_le(out, pioRecvPci->dwProtocol);
1582     int len = pioRecvPci->cbPciLength - sizeof(pioRecvPci);
1583     outBufferStartWithLimit(out, len, 12);
1584     outBufferFinishWithLimit(out,
1585     (char *) ((DWORD) pioRecvPci + sizeof(pioRecvPci)),
1586     len, 12);
1587     }
1588     #endif
1589    
1590     outBufferFinish(out, (char *) recvBuf, cbRecvLength);
1591     }
1592 stargo 1326 outForceAlignment(out, 8);
1593 stargo 1309 SC_xfreeallmemory(&lcHandle);
1594     return rv;
1595     }
1596    
1597     static MYPCSC_DWORD
1598 jsorg71 1372 TS_SCardStatus(STREAM in, STREAM out, RD_BOOL wide)
1599 stargo 1309 {
1600     MYPCSC_DWORD rv;
1601     SERVER_SCARDCONTEXT hCard;
1602     MYPCSC_SCARDCONTEXT myHCard;
1603     SERVER_DWORD dwState = 0, dwProtocol = 0, dwReaderLen, dwAtrLen;
1604     MYPCSC_DWORD state, protocol, readerLen, atrLen;
1605     SERVER_DWORD dataLength;
1606     PMEM_HANDLE lcHandle = NULL;
1607     char *readerName;
1608     unsigned char *atr;
1609    
1610     in->p += 0x24;
1611     in_uint32_le(in, dwReaderLen);
1612     in_uint32_le(in, dwAtrLen);
1613     in->p += 0x0C;
1614     in_uint32_le(in, hCard);
1615     in->p += 0x04;
1616     myHCard = scHandleToMyPCSC(hCard);
1617    
1618 ossman_ 1415 DEBUG_SCARD(("SCARD: SCardStatus(hcard: 0x%08x [0x%08lx], reader len: %d bytes, atr len: %d bytes)\n", (unsigned) hCard, (unsigned long) myHCard, (int) dwReaderLen, (int) dwAtrLen));
1619 stargo 1319
1620 stargo 1309 if (dwReaderLen <= 0 || dwReaderLen == SCARD_AUTOALLOCATE || dwReaderLen > SCARD_MAX_MEM)
1621     dwReaderLen = SCARD_MAX_MEM;
1622     if (dwAtrLen <= 0 || dwAtrLen == SCARD_AUTOALLOCATE || dwAtrLen > SCARD_MAX_MEM)
1623     dwAtrLen = SCARD_MAX_MEM;
1624    
1625     readerName = SC_xmalloc(&lcHandle, dwReaderLen + 2);
1626     if (!readerName)
1627     return SC_returnNoMemoryError(&lcHandle, in, out);
1628    
1629     atr = SC_xmalloc(&lcHandle, dwAtrLen + 1);
1630     if (!atr)
1631     return SC_returnNoMemoryError(&lcHandle, in, out);
1632    
1633     state = dwState;
1634     protocol = dwProtocol;
1635     readerLen = dwReaderLen;
1636     atrLen = dwAtrLen;
1637     rv = SCardStatus(myHCard, readerName, &readerLen, &state, &protocol, atr, &atrLen);
1638     dwAtrLen = atrLen;
1639     dwReaderLen = readerLen;
1640     dwProtocol = protocol;
1641     dwState = state;
1642    
1643    
1644     if (rv != SCARD_S_SUCCESS)
1645     {
1646 ossman_ 1415 DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
1647     pcsc_stringify_error(rv), (unsigned int) rv));
1648 stargo 1309 return SC_returnCode(rv, &lcHandle, in, out);
1649     }
1650     else
1651     {
1652 ossman_ 1415 int i;
1653    
1654     DEBUG_SCARD(("SCARD: -> Success (state: 0x%08x, proto: 0x%08x)\n",
1655     (unsigned) dwState, (unsigned) dwProtocol));
1656     DEBUG_SCARD(("SCARD: Reader: \"%s\"\n", readerName ? readerName : "NULL"));
1657     DEBUG_SCARD(("SCARD: ATR: "));
1658     for (i = 0; i < dwAtrLen; i++)
1659     {
1660     DEBUG_SCARD(("%02x%c", atr[i], (i == dwAtrLen - 1) ? ' ' : ':'));
1661     }
1662     DEBUG_SCARD(("\n"));
1663    
1664 stargo 1309 if (dwState & (SCARD_SPECIFIC | SCARD_NEGOTIABLE))
1665     dwState = 0x00000006;
1666     else
1667     #if 0
1668     if (dwState & SCARD_SPECIFIC)
1669     dwState = 0x00000006;
1670     else if (dwState & SCARD_NEGOTIABLE)
1671     dwState = 0x00000005;
1672     else
1673     #endif
1674     if (dwState & SCARD_POWERED)
1675     dwState = 0x00000004;
1676     else if (dwState & SCARD_SWALLOWED)
1677     dwState = 0x00000003;
1678     else if (dwState & SCARD_PRESENT)
1679     dwState = 0x00000002;
1680     else if (dwState & SCARD_ABSENT)
1681     dwState = 0x00000001;
1682     else
1683     dwState = 0x00000000;
1684    
1685     void *p_len1 = out->p;
1686     out_uint32_le(out, dwReaderLen);
1687     out_uint32_le(out, 0x00020000);
1688     out_uint32_le(out, dwState);
1689     out_uint32_le(out, dwProtocol);
1690     out_uint8p(out, atr, dwAtrLen);
1691     if (dwAtrLen < 32)
1692     {
1693     out_uint8s(out, 32 - dwAtrLen);
1694     }
1695     out_uint32_le(out, dwAtrLen);
1696    
1697     void *p_len2 = out->p;
1698     out_uint32_le(out, dwReaderLen);
1699     dataLength = outString(out, readerName, wide);
1700     dataLength += outString(out, "\0", wide);
1701     outRepos(out, dataLength);
1702     void *psave = out->p;
1703     out->p = p_len1;
1704     out_uint32_le(out, dataLength);
1705     out->p = p_len2;
1706     out_uint32_le(out, dataLength);
1707     out->p = psave;
1708     }
1709 stargo 1326 outForceAlignment(out, 8);
1710 stargo 1309 SC_xfreeallmemory(&lcHandle);
1711     return rv;
1712     }
1713    
1714     static MYPCSC_DWORD
1715     TS_SCardState(STREAM in, STREAM out)
1716     {
1717     MYPCSC_DWORD rv;
1718     SERVER_SCARDCONTEXT hCard;
1719     MYPCSC_SCARDCONTEXT myHCard;
1720     SERVER_DWORD dwState = 0, dwProtocol = 0, dwReaderLen, dwAtrLen;
1721     MYPCSC_DWORD state, protocol, readerLen, atrLen;
1722     PMEM_HANDLE lcHandle = NULL;
1723     char *readerName;
1724     unsigned char *atr;
1725    
1726     in->p += 0x24;
1727     in_uint32_le(in, dwAtrLen);
1728     in->p += 0x0C;
1729     in_uint32_le(in, hCard);
1730     in->p += 0x04;
1731     myHCard = scHandleToMyPCSC(hCard);
1732    
1733 ossman_ 1415 DEBUG_SCARD(("SCARD: SCardState(hcard: 0x%08x [0x%08lx], atr len: %d bytes)\n",
1734     (unsigned) hCard, (unsigned long) myHCard, (int) dwAtrLen));
1735 stargo 1309
1736     dwReaderLen = SCARD_MAX_MEM;
1737     if (dwAtrLen <= 0 || dwAtrLen == SCARD_AUTOALLOCATE || dwAtrLen > SCARD_MAX_MEM)
1738     dwAtrLen = SCARD_MAX_MEM;
1739    
1740     readerName = SC_xmalloc(&lcHandle, dwReaderLen + 2);
1741     if (!readerName)
1742     return SC_returnNoMemoryError(&lcHandle, in, out);
1743    
1744     atr = SC_xmalloc(&lcHandle, dwAtrLen + 1);
1745     if (!atr)
1746     return SC_returnNoMemoryError(&lcHandle, in, out);
1747    
1748     state = dwState;
1749     protocol = dwProtocol;
1750     readerLen = dwReaderLen;
1751     atrLen = dwAtrLen;
1752     rv = SCardStatus(myHCard, readerName, &readerLen, &state, &protocol, atr, &atrLen);
1753     dwAtrLen = atrLen;
1754     dwReaderLen = readerLen;
1755     dwProtocol = protocol;
1756     dwState = state;
1757    
1758     if (rv != SCARD_S_SUCCESS)
1759     {
1760 ossman_ 1415 DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
1761     pcsc_stringify_error(rv), (unsigned int) rv));
1762 stargo 1309 return SC_returnCode(rv, &lcHandle, in, out);
1763     }
1764     else
1765     {
1766 ossman_ 1415 int i;
1767    
1768     DEBUG_SCARD(("SCARD: -> Success (state: 0x%08x, proto: 0x%08x)\n",
1769     (unsigned) dwState, (unsigned) dwProtocol));
1770     DEBUG_SCARD(("SCARD: ATR: "));
1771     for (i = 0; i < dwAtrLen; i++)
1772     {
1773     DEBUG_SCARD(("%02x%c", atr[i], (i == dwAtrLen - 1) ? ' ' : ':'));
1774     }
1775     DEBUG_SCARD(("\n"));
1776    
1777 stargo 1309 if (dwState & (SCARD_SPECIFIC | SCARD_NEGOTIABLE))
1778     dwState = 0x00000006;
1779     else
1780     #if 0
1781     if (dwState & SCARD_SPECIFIC)
1782     dwState = 0x00000006;
1783     else if (dwState & SCARD_NEGOTIABLE)
1784     dwState = 0x00000005;
1785     else
1786     #endif
1787     if (dwState & SCARD_POWERED)
1788     dwState = 0x00000004;
1789     else if (dwState & SCARD_SWALLOWED)
1790     dwState = 0x00000003;
1791     else if (dwState & SCARD_PRESENT)
1792     dwState = 0x00000002;
1793     else if (dwState & SCARD_ABSENT)
1794     dwState = 0x00000001;
1795     else
1796     dwState = 0x00000000;
1797    
1798     out_uint32_le(out, dwState);
1799     out_uint32_le(out, dwProtocol);
1800     out_uint32_le(out, dwAtrLen);
1801     out_uint32_le(out, 0x00000001);
1802     out_uint32_le(out, dwAtrLen);
1803     out_uint8p(out, atr, dwAtrLen);
1804     outRepos(out, dwAtrLen);
1805     }
1806 stargo 1326 outForceAlignment(out, 8);
1807 stargo 1309 SC_xfreeallmemory(&lcHandle);
1808     return rv;
1809     }
1810    
1811    
1812    
1813     #ifndef WITH_PCSC120
1814    
1815     static MYPCSC_DWORD
1816     TS_SCardListReaderGroups(STREAM in, STREAM out)
1817     {
1818     MYPCSC_DWORD rv;
1819     SERVER_SCARDCONTEXT hContext;
1820     SERVER_DWORD dwGroups;
1821     MYPCSC_DWORD groups;
1822     char *szGroups;
1823     PMEM_HANDLE lcHandle = NULL;
1824    
1825     in->p += 0x20;
1826     in_uint32_le(in, dwGroups);
1827     in->p += 0x04;
1828     in_uint32_le(in, hContext);
1829    
1830 ossman_ 1415 DEBUG_SCARD(("SCARD: SCardListReaderGroups(context: 0x%08x, groups: %d)\n",
1831     (unsigned) hContext, (int) dwGroups));
1832    
1833 stargo 1309 if (dwGroups <= 0 || dwGroups == SCARD_AUTOALLOCATE || dwGroups > SCARD_MAX_MEM)
1834     dwGroups = SCARD_MAX_MEM;
1835    
1836     szGroups = SC_xmalloc(&lcHandle, dwGroups);
1837     if (!szGroups)
1838     return SC_returnNoMemoryError(&lcHandle, in, out);
1839    
1840     groups = dwGroups;
1841     rv = SCardListReaderGroups((MYPCSC_SCARDCONTEXT) hContext, szGroups, &groups);
1842     dwGroups = groups;
1843    
1844     if (rv)
1845     {
1846 ossman_ 1415 DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
1847     pcsc_stringify_error(rv), (unsigned int) rv));
1848 stargo 1309 return SC_returnCode(rv, &lcHandle, in, out);
1849     }
1850     else
1851     {
1852 ossman_ 1415 int i;
1853     char *cur;
1854    
1855     DEBUG_SCARD(("SCARD: -> Success\n"));
1856     for (i = 0, cur = szGroups; i < dwGroups; i++, cur += strlen(cur) + 1)
1857     {
1858     DEBUG_SCARD(("SCARD: %s\n", cur));
1859     }
1860 stargo 1309 }
1861    
1862    
1863     out_uint32_le(out, dwGroups);
1864     out_uint32_le(out, 0x00200000);
1865     out_uint32_le(out, dwGroups);
1866     out_uint8a(out, szGroups, dwGroups);
1867     outRepos(out, dwGroups);
1868     out_uint32_le(out, 0x00000000);
1869    
1870 stargo 1326 outForceAlignment(out, 8);
1871 stargo 1309 SC_xfreeallmemory(&lcHandle);
1872     return rv;
1873     }
1874    
1875     static MYPCSC_DWORD
1876     TS_SCardGetAttrib(STREAM in, STREAM out)
1877     {
1878     MYPCSC_DWORD rv;
1879     SERVER_SCARDCONTEXT hCard;
1880     MYPCSC_SCARDCONTEXT myHCard;
1881     SERVER_DWORD dwAttrId, dwAttrLen;
1882     MYPCSC_DWORD attrLen;
1883     unsigned char *pbAttr;
1884     PMEM_HANDLE lcHandle = NULL;
1885    
1886     in->p += 0x20;
1887     in_uint32_le(in, dwAttrId);
1888     in->p += 0x04;
1889     in_uint32_le(in, dwAttrLen);
1890     in->p += 0x0C;
1891     in_uint32_le(in, hCard);
1892     myHCard = scHandleToMyPCSC(hCard);
1893    
1894     dwAttrId = dwAttrId & 0x0000FFFF;
1895    
1896 ossman_ 1415 DEBUG_SCARD(("SCARD: SCardGetAttrib(hcard: 0x%08x [0x%08lx], attrib: 0x%08x (%d bytes))\n",
1897     (unsigned) hCard, (unsigned long) myHCard,
1898     (unsigned) dwAttrId, (int) dwAttrLen));
1899 stargo 1309
1900     if (dwAttrLen > MAX_BUFFER_SIZE)
1901     dwAttrLen = MAX_BUFFER_SIZE;
1902    
1903    
1904     if (dwAttrLen > SCARD_AUTOALLOCATE)
1905     pbAttr = NULL;
1906     else if ((dwAttrLen < 0) || (dwAttrLen > SCARD_MAX_MEM))
1907     {
1908     dwAttrLen = SCARD_AUTOALLOCATE;
1909     pbAttr = NULL;
1910     }
1911     else
1912     {
1913     pbAttr = SC_xmalloc(&lcHandle, dwAttrLen);
1914     if (!pbAttr)
1915     return SC_returnNoMemoryError(&lcHandle, in, out);
1916     }
1917    
1918     attrLen = dwAttrLen;
1919     rv = SCardGetAttrib(myHCard, (MYPCSC_DWORD) dwAttrId, pbAttr, &attrLen);
1920     dwAttrLen = attrLen;
1921    
1922     if (dwAttrId == 0x00000100 && rv != SCARD_S_SUCCESS)
1923     {
1924 ossman_ 1415 DEBUG_SCARD(("SCARD: Faking attribute ATTR_VENDOR_NAME\n"));
1925 stargo 1309 pthread_mutex_lock(&hcardAccess);
1926     PSCHCardRec hcard = hcardFirst;
1927     while (hcard)
1928     {
1929     if (hcard->hCard == hCard)
1930     {
1931     dwAttrLen = strlen(hcard->vendor);
1932     memcpy(pbAttr, hcard->vendor, dwAttrLen);
1933     rv = SCARD_S_SUCCESS;
1934     break;
1935     }
1936     hcard = hcard->next;
1937     }
1938     pthread_mutex_unlock(&hcardAccess);
1939 stargo 1319 DEBUG_SCARD(("[0x%.8x]\n", (unsigned int) rv));
1940 stargo 1309 }
1941    
1942     if (rv != SCARD_S_SUCCESS)
1943     {
1944 ossman_ 1415 DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
1945     pcsc_stringify_error(rv), (unsigned int) rv));
1946 stargo 1309 return SC_returnCode(rv, &lcHandle, in, out);
1947     }
1948     else
1949     {
1950 ossman_ 1415 DEBUG_SCARD(("SCARD: -> Success (%d bytes)\n", (int) dwAttrLen));
1951    
1952 stargo 1309 out_uint32_le(out, dwAttrLen);
1953     out_uint32_le(out, 0x00000200);
1954     out_uint32_le(out, dwAttrLen);
1955     if (!pbAttr)
1956     {
1957     out_uint8s(out, dwAttrLen);
1958     }
1959     else
1960     {
1961     out_uint8p(out, pbAttr, dwAttrLen);
1962     }
1963     outRepos(out, dwAttrLen);
1964     out_uint32_le(out, 0x00000000);
1965     }
1966 stargo 1326 outForceAlignment(out, 8);
1967 stargo 1309 return rv;
1968     }
1969    
1970     static MYPCSC_DWORD
1971     TS_SCardSetAttrib(STREAM in, STREAM out)
1972     {
1973     MYPCSC_DWORD rv;
1974     SERVER_SCARDCONTEXT hCard;
1975     MYPCSC_SCARDCONTEXT myHCard;
1976     SERVER_DWORD dwAttrId;
1977     SERVER_DWORD dwAttrLen;
1978     unsigned char *pbAttr;
1979     PMEM_HANDLE lcHandle = NULL;
1980    
1981     in->p += 0x20;
1982     in_uint32_le(in, dwAttrId);
1983     in->p += 0x04;
1984     in_uint32_le(in, dwAttrLen);
1985     in->p += 0x0C;
1986     in_uint32_le(in, hCard);
1987     myHCard = scHandleToMyPCSC(hCard);
1988    
1989     dwAttrId = dwAttrId & 0x0000FFFF;
1990    
1991 ossman_ 1415 DEBUG_SCARD(("SCARD: SCardSetAttrib(hcard: 0x%08x [0x%08lx], attrib: 0x%08x (%d bytes))\n",
1992     (unsigned) hCard, (unsigned long) myHCard,
1993     (unsigned) dwAttrId, (int) dwAttrLen));
1994 stargo 1309
1995     if (dwAttrLen > MAX_BUFFER_SIZE)
1996     dwAttrLen = MAX_BUFFER_SIZE;
1997    
1998     pbAttr = SC_xmalloc(&lcHandle, dwAttrLen);
1999     if (!pbAttr)
2000     return SC_returnNoMemoryError(&lcHandle, in, out);
2001    
2002     in_uint8a(in, pbAttr, dwAttrLen);
2003     rv = SCardSetAttrib(myHCard, (MYPCSC_DWORD) dwAttrId, pbAttr, (MYPCSC_DWORD) dwAttrLen);
2004    
2005 ossman_ 1415 if (rv != SCARD_S_SUCCESS)
2006 stargo 1319 {
2007 ossman_ 1415 DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
2008     pcsc_stringify_error(rv), (unsigned int) rv));
2009 stargo 1319 }
2010 stargo 1309 else
2011 stargo 1319 {
2012 ossman_ 1415 DEBUG_SCARD(("SCARD: -> Success\n"));
2013 stargo 1319 }
2014    
2015 stargo 1309 out_uint32_le(out, 0x00000000);
2016     out_uint32_le(out, 0x00000200);
2017     out_uint32_le(out, 0x00000000);
2018     out_uint32_le(out, 0x00000000);
2019 stargo 1326 outForceAlignment(out, 8);
2020 stargo 1309 SC_xfreeallmemory(&lcHandle);
2021     return rv;
2022     }
2023    
2024     #endif
2025    
2026     static MYPCSC_DWORD
2027     TS_SCardControl(STREAM in, STREAM out)
2028     {
2029     MYPCSC_DWORD rv;
2030     SERVER_SCARDCONTEXT hContext;
2031     SERVER_SCARDHANDLE hCard;
2032     MYPCSC_SCARDHANDLE myHCard;
2033     SERVER_DWORD map[3];
2034     SERVER_DWORD dwControlCode;
2035 stargo 1311 unsigned char *pInBuffer, *pOutBuffer;
2036 stargo 1309 SERVER_DWORD nInBufferSize, nOutBufferSize, nOutBufferRealSize, nBytesReturned;
2037     MYPCSC_DWORD sc_nBytesReturned;
2038     PMEM_HANDLE lcHandle = NULL;
2039    
2040     pInBuffer = NULL;
2041     pOutBuffer = NULL;
2042    
2043     in->p += 0x14;
2044     in_uint32_le(in, map[0]);
2045     in->p += 0x04;
2046     in_uint32_le(in, map[1]);
2047     in_uint32_le(in, dwControlCode);
2048     in_uint32_le(in, nInBufferSize);
2049     in_uint32_le(in, map[2]);
2050     in->p += 0x04;
2051     in_uint32_le(in, nOutBufferSize);
2052     in->p += 0x04;
2053     in_uint32_le(in, hContext);
2054     in->p += 0x04;
2055     in_uint32_le(in, hCard);
2056     if (map[2] & INPUT_LINKED)
2057     {
2058     /* read real input size */
2059     in_uint32_le(in, nInBufferSize);
2060     pInBuffer = SC_xmalloc(&lcHandle, nInBufferSize);
2061     if (!pInBuffer)
2062     return SC_returnNoMemoryError(&lcHandle, in, out);
2063     in_uint8a(in, pInBuffer, nInBufferSize);
2064     }
2065    
2066     #if 0
2067     if (nOutBufferSize > 0)
2068     {
2069     nOutBufferRealSize = nOutBufferSize;
2070     }
2071     else
2072     #endif
2073     nOutBufferRealSize = 1024;
2074    
2075     nBytesReturned = nOutBufferRealSize;
2076    
2077     nBytesReturned = nOutBufferRealSize;
2078     pOutBuffer = SC_xmalloc(&lcHandle, nOutBufferRealSize);
2079     if (!pOutBuffer)
2080     return SC_returnNoMemoryError(&lcHandle, in, out);
2081    
2082 ossman_ 1415 DEBUG_SCARD(("SCARD: SCardControl(context: 0x%08x, hcard: 0x%08x, code: 0x%08x, in: %d bytes, out: %d bytes)\n", (unsigned) hContext, (unsigned) hCard, (unsigned) dwControlCode, (int) nInBufferSize, (int) nOutBufferSize));
2083 stargo 1309
2084     sc_nBytesReturned = nBytesReturned;
2085     myHCard = scHandleToMyPCSC(hCard);
2086 stargo 1316 #ifdef WITH_PCSC120
2087 stargo 1309 rv = SCardControl(myHCard, pInBuffer, (MYPCSC_DWORD) nInBufferSize, pOutBuffer,
2088     &sc_nBytesReturned);
2089     #else
2090     rv = SCardControl(myHCard, (MYPCSC_DWORD) dwControlCode, pInBuffer,
2091     (MYPCSC_DWORD) nInBufferSize, pOutBuffer,
2092     (MYPCSC_DWORD) nOutBufferRealSize, &sc_nBytesReturned);
2093 stargo 1316 #endif
2094 stargo 1309 nBytesReturned = sc_nBytesReturned;
2095    
2096     if (rv != SCARD_S_SUCCESS)
2097 stargo 1319 {
2098 ossman_ 1415 DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
2099     pcsc_stringify_error(rv), (unsigned int) rv));
2100 stargo 1319 }
2101 stargo 1309 else
2102     {
2103 ossman_ 1415 DEBUG_SCARD(("SCARD: -> Success (out: %d bytes)\n", (int) nBytesReturned));
2104 stargo 1309 }
2105    
2106     out_uint32_le(out, nBytesReturned);
2107     out_uint32_le(out, 0x00000004);
2108     out_uint32_le(out, nBytesReturned);
2109     if (nBytesReturned > 0)
2110     {
2111     out_uint8p(out, pOutBuffer, nBytesReturned);
2112     outRepos(out, nBytesReturned);
2113     }
2114    
2115 stargo 1326 outForceAlignment(out, 8);
2116 stargo 1309 SC_xfreeallmemory(&lcHandle);
2117     return rv;
2118     }
2119    
2120     static MYPCSC_DWORD
2121     TS_SCardAccessStartedEvent(STREAM in, STREAM out)
2122     {
2123 ossman_ 1415 DEBUG_SCARD(("SCARD: SCardAccessStartedEvent()\n"));
2124 stargo 1309 out_uint8s(out, 8);
2125     return SCARD_S_SUCCESS;
2126     }
2127    
2128    
2129 stargo 1367 static RD_NTSTATUS
2130     scard_device_control(RD_NTHANDLE handle, uint32 request, STREAM in, STREAM out)
2131 stargo 1309 {
2132     SERVER_DWORD Result = 0x00000000;
2133     unsigned char *psize, *pend, *pStatusCode;
2134     SERVER_DWORD addToEnd = 0;
2135    
2136     /* Processing request */
2137    
2138     out_uint32_le(out, 0x00081001); /* Header lines */
2139     out_uint32_le(out, 0xCCCCCCCC);
2140     psize = out->p;
2141     out_uint32_le(out, 0x00000000); /* Size of data portion */
2142     out_uint32_le(out, 0x00000000); /* Zero bytes (may be usefull) */
2143     pStatusCode = out->p;
2144     out_uint32_le(out, 0x00000000); /* Status Code */
2145    
2146     switch (request)
2147     {
2148     /* SCardEstablishContext */
2149     case SC_ESTABLISH_CONTEXT:
2150     {
2151     Result = (SERVER_DWORD) TS_SCardEstablishContext(in, out);
2152     break;
2153     }
2154     /* SCardReleaseContext */
2155     case SC_RELEASE_CONTEXT:
2156     {
2157     Result = (SERVER_DWORD) TS_SCardReleaseContext(in, out);
2158     break;
2159     }
2160     /* SCardIsValidContext */
2161     case SC_IS_VALID_CONTEXT:
2162     {
2163     Result = (SERVER_DWORD) TS_SCardIsValidContext(in, out);
2164     break;
2165     }
2166     /* SCardListReaders */
2167     case SC_LIST_READERS: /* SCardListReadersA */
2168     case SC_LIST_READERS + 4: /* SCardListReadersW */
2169     {
2170 stargo 1373 RD_BOOL wide = request != SC_LIST_READERS;
2171 stargo 1309 Result = (SERVER_DWORD) TS_SCardListReaders(in, out, wide);
2172     break;
2173     }
2174     /* ScardConnect */
2175     case SC_CONNECT: /* ScardConnectA */
2176     case SC_CONNECT + 4: /* SCardConnectW */
2177     {
2178 jsorg71 1372 RD_BOOL wide = request != SC_CONNECT;
2179 stargo 1309 Result = (SERVER_DWORD) TS_SCardConnect(in, out, wide);
2180     break;
2181     }
2182     /* ScardReconnect */
2183     case SC_RECONNECT:
2184     {
2185     Result = (SERVER_DWORD) TS_SCardReconnect(in, out);
2186     break;
2187     }
2188     /* ScardDisconnect */
2189     case SC_DISCONNECT:
2190     {
2191     Result = (SERVER_DWORD) TS_SCardDisconnect(in, out);
2192     break;
2193     }
2194     /* ScardGetStatusChange */
2195     case SC_GET_STATUS_CHANGE: /* SCardGetStatusChangeA */
2196     case SC_GET_STATUS_CHANGE + 4: /* SCardGetStatusChangeW */
2197     {
2198 jsorg71 1372 RD_BOOL wide = request != SC_GET_STATUS_CHANGE;
2199 stargo 1309 Result = (SERVER_DWORD) TS_SCardGetStatusChange(in, out, wide);
2200     break;
2201     }
2202     /* SCardCancel */
2203     case SC_CANCEL:
2204     {
2205     Result = (SERVER_DWORD) TS_SCardCancel(in, out);
2206     break;
2207     }
2208     /* SCardLocateCardsByATR */
2209     case SC_LOCATE_CARDS_BY_ATR: /* SCardLocateCardsByATRA */
2210     case SC_LOCATE_CARDS_BY_ATR + 4: /* SCardLocateCardsByATRW */
2211     {
2212 jsorg71 1372 RD_BOOL wide = request != SC_LOCATE_CARDS_BY_ATR;
2213 stargo 1309 Result = (SERVER_DWORD) TS_SCardLocateCardsByATR(in, out, wide);
2214     break;
2215     }
2216     /* SCardBeginTransaction */
2217     case SC_BEGIN_TRANSACTION:
2218     {
2219     Result = (SERVER_DWORD) TS_SCardBeginTransaction(in, out);
2220     break;
2221     }
2222     /* SCardBeginTransaction */
2223     case SC_END_TRANSACTION:
2224     {
2225     Result = (SERVER_DWORD) TS_SCardEndTransaction(in, out);
2226     break;
2227     }
2228     /* ScardTransmit */
2229     case SC_TRANSMIT:
2230     {
2231     Result = (SERVER_DWORD) TS_SCardTransmit(in, out);
2232     break;
2233     }
2234     /* SCardControl */
2235     case SC_CONTROL:
2236     {
2237     Result = (SERVER_DWORD) TS_SCardControl(in, out);
2238     break;
2239     }
2240     /* SCardGetAttrib */
2241     #ifndef WITH_PCSC120
2242     case SC_GETATTRIB:
2243     {
2244     Result = (SERVER_DWORD) TS_SCardGetAttrib(in, out);
2245     break;
2246     }
2247     #endif
2248     case SC_ACCESS_STARTED_EVENT:
2249     {
2250     Result = (SERVER_DWORD) TS_SCardAccessStartedEvent(in, out);
2251     break;
2252     }
2253     case SC_STATUS: /* SCardStatusA */
2254     case SC_STATUS + 4: /* SCardStatusW */
2255     {
2256 jsorg71 1372 RD_BOOL wide = request != SC_STATUS;
2257 stargo 1309 Result = (SERVER_DWORD) TS_SCardStatus(in, out, wide);
2258     break;
2259     }
2260     case SC_STATE: /* SCardState */
2261     {
2262     Result = (SERVER_DWORD) TS_SCardState(in, out);
2263     break;
2264     }
2265     default:
2266     {
2267 ossman_ 1415 warning("SCARD: Unknown function %d\n", (int) request);
2268 stargo 1309 Result = 0x80100014;
2269     out_uint8s(out, 256);
2270     break;
2271     }
2272     }
2273    
2274     #if 0
2275     out_uint32_le(out, 0x00000000);
2276     #endif
2277     /* Setting modified variables */
2278     pend = out->p;
2279     /* setting data size */
2280     out->p = psize;
2281     out_uint32_le(out, pend - psize - 16);
2282     /* setting status code */
2283     out->p = pStatusCode;
2284     out_uint32_le(out, Result);
2285     /* finish */
2286     out->p = pend;
2287    
2288     addToEnd = (pend - pStatusCode) % 16;
2289     if (addToEnd < 16 && addToEnd > 0)
2290     {
2291     out_uint8s(out, addToEnd);
2292     }
2293    
2294 stargo 1367 return RD_STATUS_SUCCESS;
2295 stargo 1309 }
2296    
2297     /* Thread functions */
2298    
2299     static STREAM
2300 jsorg71 1372 duplicateStream(PMEM_HANDLE * handle, STREAM s, uint32 buffer_size, RD_BOOL isInputStream)
2301 stargo 1309 {
2302     STREAM d = SC_xmalloc(handle, sizeof(struct stream));
2303     if (d != NULL)
2304     {
2305     if (isInputStream)
2306     d->size = (size_t) (s->end) - (size_t) (s->data);
2307     else if (buffer_size < s->size)
2308     d->size = s->size;
2309     else
2310     d->size = buffer_size;
2311    
2312     d->data = SC_xmalloc(handle, d->size);
2313    
2314     d->end = (void *) ((size_t) (d->data) + (size_t) (s->end) - (size_t) (s->data));
2315     d->p = (void *) ((size_t) (d->data) + (size_t) (s->p) - (size_t) (s->data));
2316     d->iso_hdr =
2317     (void *) ((size_t) (d->data) + (size_t) (s->iso_hdr) - (size_t) (s->data));
2318     d->mcs_hdr =
2319     (void *) ((size_t) (d->data) + (size_t) (s->mcs_hdr) - (size_t) (s->data));
2320     d->sec_hdr =
2321     (void *) ((size_t) (d->data) + (size_t) (s->sec_hdr) - (size_t) (s->data));
2322     d->sec_hdr =
2323     (void *) ((size_t) (d->data) + (size_t) (s->sec_hdr) - (size_t) (s->data));
2324     d->rdp_hdr =
2325     (void *) ((size_t) (d->data) + (size_t) (s->rdp_hdr) - (size_t) (s->data));
2326     d->channel_hdr =
2327     (void *) ((size_t) (d->data) + (size_t) (s->channel_hdr) -
2328     (size_t) (s->data));
2329     if (isInputStream)
2330     memcpy(d->data, s->data, (size_t) (s->end) - (size_t) (s->data));
2331     else
2332     memcpy(d->data, s->data, (size_t) (s->p) - (size_t) (s->data));
2333     }
2334     return d;
2335     }
2336    
2337     static void
2338     freeStream(PMEM_HANDLE * handle, STREAM s)
2339     {
2340     if (s != NULL)
2341     {
2342     if (s->data != NULL)
2343     SC_xfree(handle, s->data);
2344     SC_xfree(handle, s);
2345     }
2346     }
2347    
2348     static PSCThreadData
2349 stargo 1367 SC_addToQueue(RD_NTHANDLE handle, uint32 request, STREAM in, STREAM out)
2350 stargo 1309 {
2351     PMEM_HANDLE lcHandle = NULL;
2352     PSCThreadData data = SC_xmalloc(&lcHandle, sizeof(TSCThreadData));
2353    
2354     if (!data)
2355     return NULL;
2356     else
2357     {
2358     data->memHandle = lcHandle;
2359     data->device = curDevice;
2360     data->id = curId;
2361     data->handle = handle;
2362     data->request = request;
2363     data->in = duplicateStream(&(data->memHandle), in, 0, SC_TRUE);
2364     if (data->in == NULL)
2365     {
2366     SC_xfreeallmemory(&(data->memHandle));
2367     return NULL;
2368     }
2369     data->out =
2370     duplicateStream(&(data->memHandle), out, OUT_STREAM_SIZE + curBytesOut,
2371     SC_FALSE);
2372     if (data->out == NULL)
2373     {
2374     SC_xfreeallmemory(&(data->memHandle));
2375     return NULL;
2376     }
2377     data->next = NULL;
2378    
2379     pthread_mutex_lock(&queueAccess);
2380    
2381     if (queueLast)
2382     queueLast->next = data;
2383     queueLast = data;
2384     if (!queueFirst)
2385     queueFirst = data;
2386    
2387     pthread_mutex_unlock(&queueEmpty);
2388     pthread_mutex_unlock(&queueAccess);
2389     }
2390     return data;
2391     }
2392    
2393     static void
2394     SC_destroyThreadData(PSCThreadData data)
2395     {
2396     if (data)
2397     {
2398     PMEM_HANDLE handle = data->memHandle;
2399     SC_xfreeallmemory(&handle);
2400     }
2401     }
2402    
2403     static PSCThreadData
2404     SC_getNextInQueue()
2405     {
2406     PSCThreadData Result = NULL;
2407     pthread_mutex_lock(&queueAccess);
2408     if (queueFirst != NULL)
2409     {
2410     Result = queueFirst;
2411     queueFirst = queueFirst->next;
2412     if (!queueFirst)
2413     {
2414     queueLast = NULL;
2415     pthread_mutex_trylock(&queueEmpty);
2416     }
2417     Result->next = NULL;
2418     }
2419     pthread_mutex_unlock(&queueAccess);
2420     return Result;
2421     }
2422    
2423     static void
2424     SC_deviceControl(PSCThreadData data)
2425     {
2426     size_t buffer_len = 0;
2427     scard_device_control(data->handle, data->request, data->in, data->out);
2428     buffer_len = (size_t) data->out->p - (size_t) data->out->data;
2429     rdpdr_send_completion(data->device, data->id, 0, buffer_len, data->out->data, buffer_len);
2430     SC_destroyThreadData(data);
2431     }
2432    
2433    
2434     static void *
2435     thread_function(PThreadListElement listElement)
2436     {
2437     if ((listElement != NULL) && (listElement->data != NULL))
2438     {
2439     while (1)
2440     {
2441     pthread_mutex_lock(&listElement->nodata);
2442     SC_deviceControl(listElement->data);
2443     listElement->data = NULL;
2444     pthread_mutex_unlock(&listElement->busy);
2445     }
2446     }
2447     pthread_exit(NULL);
2448     return NULL;
2449     }
2450    
2451     static void
2452     SC_handleRequest(PSCThreadData data)
2453     {
2454     int Result = 0;
2455     PThreadListElement cur = threadList, last = threadList;
2456    
2457     while (cur)
2458     {
2459     if (0 == pthread_mutex_trylock(&cur->busy))
2460     {
2461     cur->data = data;
2462     pthread_mutex_unlock(&cur->nodata);
2463     return;
2464     }
2465     else
2466     {
2467     last = cur;
2468     cur = cur->next;
2469     }
2470     }
2471    
2472     cur = SC_xmalloc(&threadListHandle, sizeof(TThreadListElement));
2473     if (!cur)
2474     return;
2475    
2476     threadCount++;
2477    
2478     cur->next = NULL;
2479     pthread_mutex_init(&cur->busy, NULL);
2480     pthread_mutex_init(&cur->nodata, NULL);
2481     pthread_mutex_trylock(&cur->busy);
2482     cur->data = data;
2483     pthread_mutex_unlock(&cur->nodata);
2484    
2485     Result = pthread_create(&cur->thread, NULL, (void *(*)(void *)) thread_function, cur);
2486     if (0 != Result)
2487     {
2488 stargo 1319 error("[THREAD CREATE ERROR 0x%.8x]\n", Result);
2489 stargo 1309 SC_xfree(&threadListHandle, cur);
2490     SC_destroyThreadData(data);
2491     data = NULL;
2492     }
2493     else if (last)
2494     last->next = cur;
2495     else
2496     threadList = cur;
2497     }
2498    
2499     static void *
2500     queue_handler_function(void *data)
2501     {
2502     PSCThreadData cur_data = NULL;
2503     while (1)
2504     {
2505     cur_data = SC_getNextInQueue();
2506     if (cur_data != NULL)
2507     {
2508     switch (cur_data->request)
2509     {
2510     case SC_ESTABLISH_CONTEXT:
2511     case SC_RELEASE_CONTEXT:
2512     {
2513     SC_deviceControl(cur_data);
2514     break;
2515     }
2516     default:
2517     {
2518     SC_handleRequest(cur_data);
2519     break;
2520     }
2521     }
2522     cur_data = NULL;
2523     }
2524     else
2525     pthread_mutex_lock(&queueEmpty);
2526     }
2527     return NULL;
2528     }
2529    
2530 stargo 1367 static RD_NTSTATUS
2531     thread_wrapper(RD_NTHANDLE handle, uint32 request, STREAM in, STREAM out)
2532 stargo 1309 {
2533     if (SC_addToQueue(handle, request, in, out))
2534 stargo 1367 return RD_STATUS_PENDING | 0xC0000000;
2535 stargo 1309 else
2536 stargo 1367 return RD_STATUS_NO_SUCH_FILE;
2537 stargo 1309 }
2538    
2539     DEVICE_FNS scard_fns = {
2540     scard_create,
2541     scard_close,
2542     scard_read,
2543     scard_write,
2544     thread_wrapper
2545     };
2546     #endif /* MAKE_PROTO */
2547    
2548     void
2549 stargo 1328 scard_lock(int lock)
2550 stargo 1309 {
2551 stargo 1328 if (!scard_mutex)
2552 stargo 1309 {
2553 stargo 1329 int i;
2554    
2555 stargo 1328 scard_mutex =
2556     (pthread_mutex_t **) xmalloc(sizeof(pthread_mutex_t *) * SCARD_LOCK_LAST);
2557 stargo 1329
2558     for (i = 0; i < SCARD_LOCK_LAST; i++)
2559     {
2560     scard_mutex[i] = NULL;
2561     }
2562 stargo 1309 }
2563    
2564 stargo 1328 if (!scard_mutex[lock])
2565 stargo 1327 {
2566 stargo 1328 scard_mutex[lock] = (pthread_mutex_t *) xmalloc(sizeof(pthread_mutex_t));
2567     pthread_mutex_init(scard_mutex[lock], NULL);
2568 stargo 1327 }
2569    
2570 stargo 1328 pthread_mutex_lock(scard_mutex[lock]);
2571 stargo 1327 }
2572    
2573     void
2574 stargo 1328 scard_unlock(int lock)
2575 stargo 1327 {
2576 stargo 1328 pthread_mutex_unlock(scard_mutex[lock]);
2577 stargo 1327 }

  ViewVC Help
Powered by ViewVC 1.1.26