/[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 1326 - (show annotations)
Fri Nov 3 18:57:09 2006 UTC (17 years, 6 months ago) by stargo
File MIME type: text/plain
File size: 69400 byte(s)
reset padding to 8, as it did not fix the disconnects
enable sendControl mutex, as the rest of rdesktop is not threadsafe and
parallel access to rdpdr_send_completion might very likely result in
these disconnects

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

  ViewVC Help
Powered by ViewVC 1.1.26