VirtualBox

source: vbox/trunk/src/VBox/RDP/client-1.8.3/scard.c@ 55963

Last change on this file since 55963 was 55123, checked in by vboxsync, 10 years ago

rdesktop 1.8.3 modified for VBox

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette