VirtualBox

source: vbox/trunk/src/VBox/RDP/client/scard.c@ 40654

Last change on this file since 40654 was 37224, checked in by vboxsync, 13 years ago

RDP/client: fix OSE

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