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