/[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

Contents of /sourceforge.net/trunk/rdesktop/scard.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1309 - (show annotations)
Wed Nov 1 20:52:01 2006 UTC (17 years, 7 months ago) by stargo
File MIME type: text/plain
File size: 69851 byte(s)
Smartcard support by Alexi Volkov <alexi@pravex.kiev.ua> and additional
patches for smartcard-support by Jennings Jared <jared.jennings.ctr@eglin.af.mil>

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

  ViewVC Help
Powered by ViewVC 1.1.26