/[rdesktop]/jpeg/rdesktop/trunk/scard.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

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

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.26