VirtualBox

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

最後變更 在這個檔案從55121是 55121,由 vboxsync 提交於 10 年 前

rdesktop 1.8.3 unmodified

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

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