/[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 1330 - (show annotations)
Sat Nov 4 20:02:42 2006 UTC (17 years, 6 months ago) by stargo
File MIME type: text/plain
File size: 69979 byte(s)
add human readable error messages

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

  ViewVC Help
Powered by ViewVC 1.1.26