/[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 1368 - (show annotations)
Thu Jan 4 23:19:54 2007 UTC (17 years, 3 months ago) by stargo
File MIME type: text/plain
File size: 70256 byte(s)
ignore PCSCs idea of BOOL

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

  ViewVC Help
Powered by ViewVC 1.1.26