/[rdesktop]/jpeg/rdesktop/trunk/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

Contents of /jpeg/rdesktop/trunk/scard.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1311 - (show annotations)
Wed Nov 1 21:23:08 2006 UTC (17 years, 6 months ago) by stargo
Original Path: sourceforge.net/trunk/rdesktop/scard.c
File MIME type: text/plain
File size: 69958 byte(s)
Add smartcard support for mac os x

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

  ViewVC Help
Powered by ViewVC 1.1.26