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