/[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 1429 - (hide annotations)
Thu Jan 24 08:06:02 2008 UTC (16 years, 4 months ago) by astrand
File MIME type: text/plain
File size: 67696 byte(s)
Indent fixes

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

  ViewVC Help
Powered by ViewVC 1.1.26