/[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 1313 - (show annotations)
Wed Nov 1 21:37:56 2006 UTC (17 years, 6 months ago) by stargo
Original Path: sourceforge.net/trunk/rdesktop/scard.c
File MIME type: text/plain
File size: 70646 byte(s)
fix warnings

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

  ViewVC Help
Powered by ViewVC 1.1.26