/[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 1415 - (show annotations)
Tue Jul 3 14:08:06 2007 UTC (16 years, 11 months ago) by ossman_
File MIME type: text/plain
File size: 66665 byte(s)
Improve readability of smart card code.

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

  ViewVC Help
Powered by ViewVC 1.1.26