pcsc-lite 1.9.9
libpcscspy.c
1/*
2 Log PC/SC arguments
3 Copyright (C) 2011-2013 Ludovic Rousseau
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19#include <dlfcn.h>
20#include <stdio.h>
21#include <stdarg.h>
22#include <fcntl.h>
23#include <stdlib.h>
24#include <errno.h>
25#include <string.h>
26#include <unistd.h>
27#include <sys/time.h>
28#include <pthread.h>
29
30#include "misc.h"
31#include <winscard.h>
32
33#define DEBUG
34
35/* function prototypes */
36
37#define p_SCardEstablishContext(fct) LONG(fct)(DWORD dwScope, LPCVOID pvReserved1, LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
38
39#define p_SCardReleaseContext(fct) LONG(fct)(SCARDCONTEXT hContext)
40
41#define p_SCardIsValidContext(fct) LONG(fct) (SCARDCONTEXT hContext)
42
43#define p_SCardConnect(fct) LONG(fct) (SCARDCONTEXT hContext, LPCSTR szReader, DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol)
44
45#define p_SCardReconnect(fct) LONG(fct) (SCARDHANDLE hCard, DWORD dwShareMode, DWORD dwPreferredProtocols, DWORD dwInitialization, LPDWORD pdwActiveProtocol)
46
47#define p_SCardDisconnect(fct) LONG(fct) (SCARDHANDLE hCard, DWORD dwDisposition)
48
49#define p_SCardBeginTransaction(fct) LONG(fct) (SCARDHANDLE hCard)
50
51#define p_SCardEndTransaction(fct) LONG(fct) (SCARDHANDLE hCard, DWORD dwDisposition)
52
53#define p_SCardStatus(fct) LONG(fct) (SCARDHANDLE hCard, LPSTR mszReaderName, LPDWORD pcchReaderLen, LPDWORD pdwState, LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
54
55#define p_SCardGetStatusChange(fct) LONG(fct) (SCARDCONTEXT hContext, DWORD dwTimeout, LPSCARD_READERSTATE rgReaderStates, DWORD cReaders)
56
57#define p_SCardControl(fct) LONG(fct) (SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer, DWORD cbSendLength, LPVOID pbRecvBuffer, DWORD cbRecvLength, LPDWORD lpBytesReturned)
58
59#define p_SCardTransmit(fct) LONG(fct) (SCARDHANDLE hCard, const SCARD_IO_REQUEST * pioSendPci, LPCBYTE pbSendBuffer, DWORD cbSendLength, SCARD_IO_REQUEST * pioRecvPci, LPBYTE pbRecvBuffer, LPDWORD pcbRecvLength)
60
61#define p_SCardListReaderGroups(fct) LONG(fct) (SCARDCONTEXT hContext, LPSTR mszGroups, LPDWORD pcchGroups)
62
63#define p_SCardListReaders(fct) LONG(fct) (SCARDCONTEXT hContext, LPCSTR mszGroups, LPSTR mszReaders, LPDWORD pcchReaders)
64
65#define p_SCardFreeMemory(fct) LONG(fct) (SCARDCONTEXT hContext, LPCVOID pvMem)
66
67#define p_SCardCancel(fct) LONG(fct) (SCARDCONTEXT hContext)
68
69#define p_SCardGetAttrib(fct) LONG(fct) (SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr, LPDWORD pcbAttrLen)
70
71#define p_SCardSetAttrib(fct) LONG(fct) (SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr, DWORD cbAttrLen)
72
73#define p_pcsc_stringify_error(fct) const char *(fct)(const LONG pcscError)
74
75/* fake function to just return en error code */
76static LONG internal_error(void)
77{
79}
80
81static const char * internal_stringify_error(void)
82{
83 return "No spy pcsc_stringify_error() function";
84}
85
86#pragma GCC diagnostic push
87#pragma GCC diagnostic ignored "-Wcast-function-type"
88/* contains pointers to real functions */
89static struct
90{
91 p_SCardEstablishContext(*SCardEstablishContext);
92 p_SCardReleaseContext(*SCardReleaseContext);
93 p_SCardIsValidContext(*SCardIsValidContext);
94 p_SCardConnect(*SCardConnect);
95 p_SCardReconnect(*SCardReconnect);
96 p_SCardDisconnect(*SCardDisconnect);
97 p_SCardBeginTransaction(*SCardBeginTransaction);
98 p_SCardEndTransaction(*SCardEndTransaction);
99 p_SCardStatus(*SCardStatus);
100 p_SCardGetStatusChange(*SCardGetStatusChange);
101 p_SCardControl(*SCardControl);
102 p_SCardTransmit(*SCardTransmit);
103 p_SCardListReaderGroups(*SCardListReaderGroups);
104 p_SCardListReaders(*SCardListReaders);
105 p_SCardFreeMemory(*SCardFreeMemory);
106 p_SCardCancel(*SCardCancel);
107 p_SCardGetAttrib(*SCardGetAttrib);
108 p_SCardSetAttrib(*SCardSetAttrib);
109 p_pcsc_stringify_error(*pcsc_stringify_error);
110} spy = {
111 /* initialized with the fake internal_error() function */
112 .SCardEstablishContext = (p_SCardEstablishContext(*))internal_error,
113 .SCardReleaseContext = (p_SCardReleaseContext(*))internal_error,
114 .SCardIsValidContext = (p_SCardIsValidContext(*))internal_error,
115 .SCardConnect = (p_SCardConnect(*))internal_error,
116 .SCardReconnect = (p_SCardReconnect(*))internal_error,
117 .SCardDisconnect = (p_SCardDisconnect(*))internal_error,
118 .SCardBeginTransaction = (p_SCardBeginTransaction(*))internal_error,
119 .SCardEndTransaction = (p_SCardEndTransaction(*))internal_error,
120 .SCardStatus = (p_SCardStatus(*))internal_error,
121 .SCardGetStatusChange = (p_SCardGetStatusChange(*))internal_error,
122 .SCardControl = (p_SCardControl(*))internal_error,
123 .SCardTransmit = (p_SCardTransmit(*))internal_error,
124 .SCardListReaderGroups = (p_SCardListReaderGroups(*))internal_error,
125 .SCardListReaders = (p_SCardListReaders(*))internal_error,
126 .SCardFreeMemory = (p_SCardFreeMemory(*))internal_error,
127 .SCardCancel = (p_SCardCancel(*))internal_error,
128 .SCardGetAttrib = (p_SCardGetAttrib(*))internal_error,
129 .SCardSetAttrib = (p_SCardSetAttrib(*))internal_error,
130 .pcsc_stringify_error = (p_pcsc_stringify_error(*))internal_stringify_error
131};
132#pragma GCC diagnostic pop
133
134#define LOG log_line("%s:%d", __FILE__, __LINE__)
135
136static int Log_fd = -1;
137static void *Lib_handle = NULL;
138static pthread_mutex_t Log_fd_mutex = PTHREAD_MUTEX_INITIALIZER;
139
140#ifdef DEBUG
141static void log_line(const char *fmt, ...)
142{
143 va_list args;
144
145 va_start(args, fmt);
146 vprintf(fmt, args);
147 printf("\n");
148 va_end(args);
149}
150#else
151static void log_line(const char *fmt, ...)
152{
153}
154#endif
155
156static void spy_line_direct(char *line)
157{
158 char threadid[30];
159 ssize_t r;
160
161 /* spying disabled */
162 if (Log_fd < 0)
163 return;
164
165 snprintf(threadid, sizeof threadid, "%lX@", pthread_self());
166 pthread_mutex_lock(&Log_fd_mutex);
167 r = write(Log_fd, threadid, strlen(threadid));
168 r = write(Log_fd, line, strlen(line));
169 r = write(Log_fd, "\n", 1);
170 (void)r;
171 pthread_mutex_unlock(&Log_fd_mutex);
172}
173
174static void spy_line(const char *fmt, ...)
175{
176 va_list args;
177 char line[256];
178 int size;
179 char threadid[30];
180 ssize_t r;
181
182 /* spying disabled */
183 if (Log_fd < 0)
184 return;
185
186 va_start(args, fmt);
187 size = vsnprintf(line, sizeof line, fmt, args);
188 va_end(args);
189 if ((size_t)size >= sizeof line)
190 {
191 printf("libpcsc-spy: Buffer is too small!\n");
192 return;
193 }
194 snprintf(threadid, sizeof threadid, "%lX@", pthread_self());
195 pthread_mutex_lock(&Log_fd_mutex);
196 r = write(Log_fd, threadid, strlen(threadid));
197 r = write(Log_fd, line, size);
198 r = write(Log_fd, "\n", 1);
199 (void)r;
200 pthread_mutex_unlock(&Log_fd_mutex);
201}
202
203static void spy_enter(const char *fname)
204{
205 struct timeval profile_time;
206
207 gettimeofday(&profile_time, NULL);
208 spy_line(">|%ld|%ld|%s", profile_time.tv_sec, profile_time.tv_usec, fname);
209}
210
211static void spy_quit(const char *fname, LONG rv)
212{
213 struct timeval profile_time;
214
215 gettimeofday(&profile_time, NULL);
216 spy_line("<|%ld|%ld|%s|%s|0x%08lX", profile_time.tv_sec,
217 profile_time.tv_usec, fname, spy.pcsc_stringify_error(rv), rv);
218}
219
220#define Enter() spy_enter(__FUNCTION__)
221#define Quit() spy_quit(__FUNCTION__, rv)
222
223static void spy_long(long arg)
224{
225 spy_line("0x%08lX", arg);
226}
227
228static void spy_ptr_long(LONG *arg)
229{
230 if (arg)
231 spy_line("0x%08lX", *arg);
232 else
233 spy_line("NULL");
234}
235
236static void spy_ptr_ulong(ULONG *arg)
237{
238 if (arg)
239 spy_line("0x%08lX", *arg);
240 else
241 spy_line("NULL");
242}
243
244static void spy_pvoid(const void *ptr)
245{
246 spy_line("%p", ptr);
247}
248
249static void spy_buffer(const unsigned char *buffer, size_t length)
250{
251 spy_long(length);
252
253 if (NULL == buffer)
254 spy_line("NULL");
255 else
256 {
257 /* "78 79 7A" */
258 char log_buffer[length * 3 +1], *p;
259 size_t i;
260
261 p = log_buffer;
262 log_buffer[0] = '\0';
263 for (i=0; i<length; i++)
264 {
265 snprintf(p, 4, "%02X ", buffer[i]);
266 p += 3;
267 }
268 *p = '\0';
269
270 spy_line_direct(log_buffer);
271 }
272}
273
274static void spy_str(const char *str)
275{
276 spy_line("%s", str);
277}
278
279static void spy_n_str(const char *str, ULONG *len, int autoallocate)
280{
281 spy_ptr_ulong(len);
282 if (NULL == len)
283 {
284 spy_line("\"\"");
285 }
286 else
287 {
288 if (NULL == str)
289 {
290 spy_line("NULL");
291 }
292 else
293 {
294 const char *s = str;
295 unsigned int length = 0;
296
297 if (autoallocate)
298 s = *(char **)str;
299
300 do
301 {
302 spy_line("%s", s);
303 length += strlen(s)+1;
304 s += strlen(s)+1;
305 } while(length < *len);
306 }
307 }
308}
309
310
311static void spy_readerstate(SCARD_READERSTATE * rgReaderStates, int cReaders)
312{
313 int i;
314
315 for (i=0; i<cReaders; i++)
316 {
317 spy_str(rgReaderStates[i].szReader);
318 spy_long(rgReaderStates[i].dwCurrentState);
319 spy_long(rgReaderStates[i].dwEventState);
320 if (rgReaderStates[i].cbAtr <= MAX_ATR_SIZE)
321 spy_buffer(rgReaderStates[i].rgbAtr, rgReaderStates[i].cbAtr);
322 else
323 spy_buffer(NULL, rgReaderStates[i].cbAtr);
324 }
325}
326
327static LONG load_lib(void)
328{
329
330#define LIBPCSC_NOSPY "libpcsclite_nospy.so.1"
331#define LIBPCSC "libpcsclite.so.1"
332
333 /* first try to load the NOSPY library
334 * this is used for programs doing an explicit dlopen like
335 * Perl and Python wrappers */
336 Lib_handle = dlopen(LIBPCSC_NOSPY, RTLD_LAZY);
337 if (NULL == Lib_handle)
338 {
339 log_line("%s", dlerror());
340
341 /* load the normal library */
342 Lib_handle = dlopen(LIBPCSC, RTLD_LAZY);
343 if (NULL == Lib_handle)
344 {
345 log_line("%s", dlerror());
347 }
348 }
349
350#define get_symbol(s) do { spy.s = dlsym(Lib_handle, #s); if (NULL == spy.s) { log_line("%s", dlerror()); return SCARD_F_INTERNAL_ERROR; } } while (0)
351
352 if (SCardEstablishContext == dlsym(Lib_handle, "SCardEstablishContext"))
353 {
354 log_line("Symbols dlsym error");
356 }
357
358 get_symbol(SCardEstablishContext);
359 get_symbol(SCardReleaseContext);
360 get_symbol(SCardIsValidContext);
361 get_symbol(SCardConnect);
362 get_symbol(SCardReconnect);
363 get_symbol(SCardDisconnect);
364 get_symbol(SCardBeginTransaction);
365 get_symbol(SCardEndTransaction);
366 get_symbol(SCardStatus);
367 get_symbol(SCardGetStatusChange);
368 get_symbol(SCardControl);
369 get_symbol(SCardTransmit);
370 get_symbol(SCardListReaderGroups);
371 get_symbol(SCardListReaders);
372 /* Mac OS X do not have SCardFreeMemory() */
373 if (dlsym(Lib_handle, "SCardFreeMemory"))
374 get_symbol(SCardFreeMemory);
375 get_symbol(SCardCancel);
376 get_symbol(SCardGetAttrib);
377 get_symbol(SCardSetAttrib);
378 get_symbol(pcsc_stringify_error);
379
380 return SCARD_S_SUCCESS;
381}
382
383
384/* exported functions */
385PCSC_API p_SCardEstablishContext(SCardEstablishContext)
386{
387 LONG rv;
388 static int init = 0;
389
390 if (!init)
391 {
392 const char *home;
393 char log_pipe[128];
394
395 init = 1;
396
397 /* load the real library */
398 rv = load_lib();
399 if (rv != SCARD_S_SUCCESS)
400 return rv;
401
402 /* check if we can log */
403 home = getenv("HOME");
404 if (NULL == home)
405 home = "/tmp";
406
407 snprintf(log_pipe, sizeof log_pipe, "%s/pcsc-spy", home);
408 Log_fd = open(log_pipe, O_WRONLY);
409 if (Log_fd < 0)
410 {
411 log_line("open %s failed: %s", log_pipe, strerror(errno));
412 }
413 }
414
415 Enter();
416 spy_long(dwScope);
417 rv = spy.SCardEstablishContext(dwScope, pvReserved1, pvReserved2,
418 phContext);
419 spy_ptr_long(phContext);
420 Quit();
421 return rv;
422}
423
424PCSC_API p_SCardReleaseContext(SCardReleaseContext)
425{
426 LONG rv;
427
428 Enter();
429 spy_long(hContext);
430 rv = spy.SCardReleaseContext(hContext);
431 Quit();
432 return rv;
433}
434
435PCSC_API p_SCardIsValidContext(SCardIsValidContext)
436{
437 LONG rv;
438
439 Enter();
440 spy_long(hContext);
441 rv = spy.SCardIsValidContext(hContext);
442 Quit();
443 return rv;
444}
445
446PCSC_API p_SCardConnect(SCardConnect)
447{
448 LONG rv;
449
450 Enter();
451 spy_long(hContext);
452 spy_str(szReader);
453 spy_long(dwShareMode);
454 spy_long(dwPreferredProtocols);
455 spy_ptr_long(phCard);
456 spy_ptr_ulong(pdwActiveProtocol);
457 rv = spy.SCardConnect(hContext, szReader, dwShareMode,
458 dwPreferredProtocols, phCard, pdwActiveProtocol);
459 spy_ptr_long(phCard);
460 spy_ptr_ulong(pdwActiveProtocol);
461 Quit();
462 return rv;
463}
464
465PCSC_API p_SCardReconnect(SCardReconnect)
466{
467 LONG rv;
468
469 Enter();
470 spy_long(hCard);
471 spy_long(dwShareMode);
472 spy_long(dwPreferredProtocols);
473 spy_long(dwInitialization);
474 rv = spy.SCardReconnect(hCard, dwShareMode, dwPreferredProtocols,
475 dwInitialization, pdwActiveProtocol);
476 spy_ptr_ulong(pdwActiveProtocol);
477 Quit();
478 return rv;
479}
480
481PCSC_API p_SCardDisconnect(SCardDisconnect)
482{
483 LONG rv;
484
485 Enter();
486 spy_long(hCard);
487 spy_long(dwDisposition);
488 rv = spy.SCardDisconnect(hCard, dwDisposition);
489 Quit();
490 return rv;
491}
492
493PCSC_API p_SCardBeginTransaction(SCardBeginTransaction)
494{
495 LONG rv;
496
497 Enter();
498 spy_long(hCard);
499 rv = spy.SCardBeginTransaction(hCard);
500 Quit();
501 return rv;
502}
503
504PCSC_API p_SCardEndTransaction(SCardEndTransaction)
505{
506 LONG rv;
507
508 Enter();
509 spy_long(hCard);
510 spy_long(dwDisposition);
511 rv = spy.SCardEndTransaction(hCard, dwDisposition);
512 Quit();
513 return rv;
514}
515
516PCSC_API p_SCardStatus(SCardStatus)
517{
518 LONG rv;
519 int autoallocate_ReaderName = 0, autoallocate_Atr = 0;
520
521 if (pcchReaderLen)
522 autoallocate_ReaderName = *pcchReaderLen == SCARD_AUTOALLOCATE;
523
524 if (pcbAtrLen)
525 autoallocate_Atr = *pcbAtrLen == SCARD_AUTOALLOCATE;
526
527 Enter();
528 spy_long(hCard);
529 spy_ptr_ulong(pcchReaderLen);
530 spy_ptr_ulong(pcbAtrLen);
531 rv = spy.SCardStatus(hCard, mszReaderName, pcchReaderLen, pdwState,
532 pdwProtocol, pbAtr, pcbAtrLen);
533 spy_n_str(mszReaderName, pcchReaderLen, autoallocate_ReaderName);
534 spy_ptr_ulong(pdwState);
535 spy_ptr_ulong(pdwProtocol);
536 if (NULL == pcbAtrLen)
537 spy_line("NULL");
538 else
539 {
540 LPBYTE buffer;
541
542 if (autoallocate_Atr)
543 buffer = *(LPBYTE *)pbAtr;
544 else
545 buffer = pbAtr;
546
547 spy_buffer(buffer, *pcbAtrLen);
548 }
549 Quit();
550 return rv;
551}
552
553PCSC_API p_SCardGetStatusChange(SCardGetStatusChange)
554{
555 LONG rv;
556
557 Enter();
558 spy_long(hContext);
559 spy_long(dwTimeout);
560 spy_long(cReaders);
561 spy_readerstate(rgReaderStates, cReaders);
562 rv = spy.SCardGetStatusChange(hContext, dwTimeout, rgReaderStates,
563 cReaders);
564 spy_readerstate(rgReaderStates, cReaders);
565 Quit();
566 return rv;
567}
568
569PCSC_API p_SCardControl(SCardControl)
570{
571 LONG rv;
572
573 Enter();
574 spy_long(hCard);
575 spy_long(dwControlCode);
576 spy_buffer(pbSendBuffer, cbSendLength);
577 rv = spy.SCardControl(hCard, dwControlCode, pbSendBuffer, cbSendLength,
578 pbRecvBuffer, cbRecvLength, lpBytesReturned);
579 if (lpBytesReturned)
580 spy_buffer(pbRecvBuffer, *lpBytesReturned);
581 else
582 spy_buffer(NULL, 0);
583 Quit();
584 return rv;
585}
586
587PCSC_API p_SCardTransmit(SCardTransmit)
588{
589 LONG rv;
590
591 Enter();
592 spy_long(hCard);
593 if (pioSendPci)
594 {
595 spy_long(pioSendPci->dwProtocol);
596 spy_long(pioSendPci->cbPciLength);
597 }
598 else
599 {
600 spy_long(-1);
601 spy_long(-1);
602 }
603 spy_buffer(pbSendBuffer, cbSendLength);
604 rv = spy.SCardTransmit(hCard, pioSendPci, pbSendBuffer, cbSendLength,
605 pioRecvPci, pbRecvBuffer, pcbRecvLength);
606 if (pioRecvPci)
607 {
608 spy_long(pioRecvPci->dwProtocol);
609 spy_long(pioRecvPci->cbPciLength);
610 }
611 else
612 {
613 spy_long(-1);
614 spy_long(-1);
615 }
616 if (pcbRecvLength)
617 spy_buffer(pbRecvBuffer, *pcbRecvLength);
618 else
619 spy_buffer(NULL, 0);
620 Quit();
621 return rv;
622}
623
624PCSC_API p_SCardListReaderGroups(SCardListReaderGroups)
625{
626 LONG rv;
627 int autoallocate = 0;
628
629 if (pcchGroups)
630 autoallocate = *pcchGroups == SCARD_AUTOALLOCATE;
631
632 Enter();
633 spy_long(hContext);
634 spy_ptr_ulong(pcchGroups);
635 rv = spy.SCardListReaderGroups(hContext, mszGroups, pcchGroups);
636 if (SCARD_S_SUCCESS == rv)
637 spy_n_str(mszGroups, pcchGroups, autoallocate);
638 else
639 spy_n_str(NULL, pcchGroups, 0);
640 Quit();
641 return rv;
642}
643
644PCSC_API p_SCardListReaders(SCardListReaders)
645{
646 LONG rv;
647 int autoallocate = 0;
648
649 if (pcchReaders)
650 autoallocate = *pcchReaders == SCARD_AUTOALLOCATE;
651
652 Enter();
653 spy_long(hContext);
654 spy_str(mszGroups);
655 rv = spy.SCardListReaders(hContext, mszGroups, mszReaders, pcchReaders);
656 if (SCARD_S_SUCCESS == rv)
657 spy_n_str(mszReaders, pcchReaders, autoallocate);
658 else
659 spy_n_str(NULL, pcchReaders, 0);
660 Quit();
661 return rv;
662}
663
664PCSC_API p_SCardFreeMemory(SCardFreeMemory)
665{
666 LONG rv;
667
668 Enter();
669 spy_long(hContext);
670 spy_pvoid(pvMem);
671 rv = spy.SCardFreeMemory(hContext, pvMem);
672 Quit();
673 return rv;
674}
675
676PCSC_API p_SCardCancel(SCardCancel)
677{
678 LONG rv;
679
680 Enter();
681 spy_long(hContext);
682 rv = spy.SCardCancel(hContext);
683 Quit();
684 return rv;
685}
686
687PCSC_API p_SCardGetAttrib(SCardGetAttrib)
688{
689 LONG rv;
690 int autoallocate = 0;
691
692 if (pcbAttrLen)
693 autoallocate = *pcbAttrLen == SCARD_AUTOALLOCATE;
694
695 Enter();
696 spy_long(hCard);
697 spy_long(dwAttrId);
698 rv = spy.SCardGetAttrib(hCard, dwAttrId, pbAttr, pcbAttrLen);
699 if (NULL == pcbAttrLen)
700 spy_buffer(NULL, 0);
701 else
702 {
703 LPBYTE buffer;
704
705 if (autoallocate)
706 buffer = *(LPBYTE *)pbAttr;
707 else
708 buffer = pbAttr;
709
710 spy_buffer(buffer, *pcbAttrLen);
711 }
712 Quit();
713 return rv;
714}
715
716PCSC_API p_SCardSetAttrib(SCardSetAttrib)
717{
718 LONG rv;
719
720 Enter();
721 spy_long(hCard);
722 spy_long(dwAttrId);
723 spy_buffer(pbAttr, cbAttrLen);
724 rv = spy.SCardSetAttrib(hCard, dwAttrId, pbAttr, cbAttrLen);
725 Quit();
726 return rv;
727}
728
729PCSC_API p_pcsc_stringify_error(pcsc_stringify_error)
730{
731 return spy.pcsc_stringify_error(pcscError);
732}
733
735PCSC_API const SCARD_IO_REQUEST g_rgSCardT1Pci = { SCARD_PROTOCOL_T1, sizeof(SCARD_IO_REQUEST) };
736PCSC_API const SCARD_IO_REQUEST g_rgSCardRawPci = { SCARD_PROTOCOL_RAW, sizeof(SCARD_IO_REQUEST) };
#define SCARD_F_INTERNAL_ERROR
An internal consistency check failed.
Definition pcsclite.h:109
#define SCARD_S_SUCCESS
No error was encountered.
Definition pcsclite.h:107
#define SCARD_PROTOCOL_T1
T=1 active protocol.
Definition pcsclite.h:242
#define SCARD_PROTOCOL_T0
T=0 active protocol.
Definition pcsclite.h:241
#define SCARD_AUTOALLOCATE
see SCardFreeMemory()
Definition pcsclite.h:233
#define MAX_ATR_SIZE
Maximum ATR size.
Definition pcsclite.h:59
#define SCARD_PROTOCOL_RAW
Raw active protocol.
Definition pcsclite.h:243
const SCARD_IO_REQUEST g_rgSCardT0Pci
Protocol Control Information for T=0.
Definition libpcscspy.c:734
Protocol Control Information (PCI)
Definition pcsclite.h:80
This handles smart card reader communications.