/[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 1322 - (show annotations)
Thu Nov 2 23:31:58 2006 UTC (17 years, 7 months ago) by stargo
File MIME type: text/plain
File size: 69784 byte(s)
always pad

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