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

Contents of /sourceforge.net/trunk/rdesktop/scard.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1414 - (show annotations)
Thu Jun 28 12:52:13 2007 UTC (16 years, 10 months ago) by ossman_
File MIME type: text/plain
File size: 69647 byte(s)
Fix two crashes caused by improver handling of structures.

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

  ViewVC Help
Powered by ViewVC 1.1.26