/[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 1329 - (show annotations)
Sat Nov 4 17:33:15 2006 UTC (17 years, 7 months ago) by stargo
File MIME type: text/plain
File size: 69335 byte(s)
initialize scard_mutex

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

  ViewVC Help
Powered by ViewVC 1.1.26