/[rdesktop]/jpeg/rdesktop/trunk/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 /jpeg/rdesktop/trunk/scard.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1320 - (show annotations)
Thu Nov 2 21:32:56 2006 UTC (17 years, 6 months ago) by stargo
Original Path: sourceforge.net/trunk/rdesktop/scard.c
File MIME type: text/plain
File size: 69748 byte(s)
use xmalloc for mutex allocation

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

  ViewVC Help
Powered by ViewVC 1.1.26