pcsc-lite  1.8.8
winscard_clnt.c
Go to the documentation of this file.
1 /*
2  * MUSCLE SmartCard Development ( http://www.linuxnet.com )
3  *
4  * Copyright (C) 1999-2004
5  * David Corcoran <corcoran@linuxnet.com>
6  * Copyright (C) 2003-2004
7  * Damien Sauveron <damien.sauveron@labri.fr>
8  * Copyright (C) 2005
9  * Martin Paljak <martin@paljak.pri.ee>
10  * Copyright (C) 2002-2011
11  * Ludovic Rousseau <ludovic.rousseau@free.fr>
12  * Copyright (C) 2009
13  * Jean-Luc Giraud <jlgiraud@googlemail.com>
14  *
15  * $Id: winscard_clnt.c 6444 2012-08-24 08:10:23Z rousseau $
16  */
17 
78 #include "config.h"
79 #include <stdlib.h>
80 #include <string.h>
81 #include <sys/types.h>
82 #include <fcntl.h>
83 #include <unistd.h>
84 #include <sys/un.h>
85 #include <errno.h>
86 #include <stddef.h>
87 #include <sys/time.h>
88 #include <pthread.h>
89 #include <sys/wait.h>
90 
91 #include "misc.h"
92 #include "pcscd.h"
93 #include "winscard.h"
94 #include "debuglog.h"
95 #include "strlcpycat.h"
96 
97 #include "readerfactory.h"
98 #include "eventhandler.h"
99 #include "sys_generic.h"
100 #include "winscard_msg.h"
101 #include "utils.h"
102 
103 /* Display, on stderr, a trace of the WinSCard calls with arguments and
104  * results */
105 #undef DO_TRACE
106 
107 /* Profile the execution time of WinSCard calls */
108 #undef DO_PROFILE
109 
110 
112 #define SCARD_PROTOCOL_ANY_OLD 0x1000
113 
114 #ifndef TRUE
115 #define TRUE 1
116 #define FALSE 0
117 #endif
118 
119 static char sharing_shall_block = TRUE;
120 
121 #define COLOR_RED "\33[01;31m"
122 #define COLOR_GREEN "\33[32m"
123 #define COLOR_BLUE "\33[34m"
124 #define COLOR_MAGENTA "\33[35m"
125 #define COLOR_NORMAL "\33[0m"
126 
127 #define TIMEOUT_TIME 3 /* time to wait for an answer to the server on first connection (in seconds) */
128 
129 #ifdef DO_TRACE
130 
131 #include <stdio.h>
132 #include <stdarg.h>
133 
134 static void trace(const char *func, const char direction, const char *fmt, ...)
135 {
136  va_list args;
137 
138  fprintf(stderr, COLOR_GREEN "%c " COLOR_BLUE "[%lX] " COLOR_GREEN "%s ",
139  direction, pthread_self(), func);
140 
141  fprintf(stderr, COLOR_MAGENTA);
142  va_start(args, fmt);
143  vfprintf(stderr, fmt, args);
144  va_end(args);
145 
146  fprintf(stderr, COLOR_NORMAL "\n");
147 }
148 
149 #define API_TRACE_IN(...) trace(__FUNCTION__, '<', __VA_ARGS__);
150 #define API_TRACE_OUT(...) trace(__FUNCTION__, '>', __VA_ARGS__);
151 #else
152 #define API_TRACE_IN(...)
153 #define API_TRACE_OUT(...)
154 #endif
155 
156 #ifdef DO_PROFILE
157 
158 #define PROFILE_FILE "/tmp/pcsc_profile"
159 #include <stdio.h>
160 #include <sys/time.h>
161 
162 /* we can profile a maximum of 5 simultaneous calls */
163 #define MAX_THREADS 5
164 pthread_t threads[MAX_THREADS];
165 struct timeval profile_time_start[MAX_THREADS];
166 FILE *profile_fd;
167 char profile_tty;
168 
169 #define PROFILE_START profile_start();
170 #define PROFILE_END(rv) profile_end(__FUNCTION__, rv);
171 
172 static void profile_start(void)
173 {
174  static char initialized = FALSE;
175  pthread_t t;
176  int i;
177 
178  if (!initialized)
179  {
180  char filename[80];
181 
182  initialized = TRUE;
183  sprintf(filename, "%s-%d", PROFILE_FILE, getuid());
184  profile_fd = fopen(filename, "a+");
185  if (NULL == profile_fd)
186  {
187  fprintf(stderr, COLOR_RED "Can't open %s: %s" COLOR_NORMAL "\n",
188  PROFILE_FILE, strerror(errno));
189  exit(-1);
190  }
191  fprintf(profile_fd, "\nStart a new profile\n");
192 
193  if (isatty(fileno(stderr)))
194  profile_tty = TRUE;
195  else
196  profile_tty = FALSE;
197  }
198 
199  t = pthread_self();
200  for (i=0; i<MAX_THREADS; i++)
201  if (pthread_equal(0, threads[i]))
202  {
203  threads[i] = t;
204  break;
205  }
206 
207  gettimeofday(&profile_time_start[i], NULL);
208 } /* profile_start */
209 
210 static void profile_end(const char *f, LONG rv)
211 {
212  struct timeval profile_time_end;
213  long d;
214  pthread_t t;
215  int i;
216 
217  gettimeofday(&profile_time_end, NULL);
218 
219  t = pthread_self();
220  for (i=0; i<MAX_THREADS; i++)
221  if (pthread_equal(t, threads[i]))
222  break;
223 
224  if (i>=MAX_THREADS)
225  {
226  fprintf(stderr, COLOR_BLUE " WARNING: no start info for %s\n", f);
227  return;
228  }
229 
230  d = time_sub(&profile_time_end, &profile_time_start[i]);
231 
232  /* free this entry */
233  threads[i] = 0;
234 
235  if (profile_tty)
236  {
237  if (rv != SCARD_S_SUCCESS)
238  fprintf(stderr,
239  COLOR_RED "RESULT %s " COLOR_MAGENTA "%ld "
240  COLOR_BLUE "0x%08lX %s" COLOR_NORMAL "\n",
241  f, d, rv, pcsc_stringify_error(rv));
242  else
243  fprintf(stderr, COLOR_RED "RESULT %s " COLOR_MAGENTA "%ld"
244  COLOR_NORMAL "\n", f, d);
245  }
246  fprintf(profile_fd, "%s %ld\n", f, d);
247  fflush(profile_fd);
248 } /* profile_end */
249 
250 #else
251 #define PROFILE_START
252 #define PROFILE_END(rv)
253 #endif
254 
260 {
261  SCARDHANDLE hCard;
262  LPSTR readerName;
263 };
264 
265 typedef struct _psChannelMap CHANNEL_MAP;
266 
267 static int CHANNEL_MAP_seeker(const void *el, const void *key)
268 {
269  const CHANNEL_MAP * channelMap = el;
270 
271  if ((el == NULL) || (key == NULL))
272  {
273  Log3(PCSC_LOG_CRITICAL,
274  "CHANNEL_MAP_seeker called with NULL pointer: el=%p, key=%p",
275  el, key);
276  return 0;
277  }
278 
279  if (channelMap->hCard == *(SCARDHANDLE *)key)
280  return 1;
281 
282  return 0;
283 }
284 
291 {
292  DWORD dwClientID;
294  pthread_mutex_t * mMutex;
295  list_t channelMapList;
296  char cancellable;
297 };
298 typedef struct _psContextMap SCONTEXTMAP;
299 
300 static list_t contextMapList;
301 
302 static int SCONTEXTMAP_seeker(const void *el, const void *key)
303 {
304  const SCONTEXTMAP * contextMap = el;
305 
306  if ((el == NULL) || (key == NULL))
307  {
308  Log3(PCSC_LOG_CRITICAL,
309  "SCONTEXTMAP_seeker called with NULL pointer: el=%p, key=%p",
310  el, key);
311  return 0;
312  }
313 
314  if (contextMap->hContext == *(SCARDCONTEXT *) key)
315  return 1;
316 
317  return 0;
318 }
319 
323 static short isExecuted = 0;
324 
325 
330 static pthread_mutex_t clientMutex = PTHREAD_MUTEX_INITIALIZER;
331 
336 
343 
344 
345 static LONG SCardAddContext(SCARDCONTEXT, DWORD);
348 static LONG SCardRemoveContext(SCARDCONTEXT);
349 static LONG SCardCleanContext(SCONTEXTMAP *);
350 
351 static LONG SCardAddHandle(SCARDHANDLE, SCONTEXTMAP *, LPCSTR);
352 static LONG SCardGetContextAndChannelFromHandle(SCARDHANDLE,
353  /*@out@*/ SCONTEXTMAP * *, /*@out@*/ CHANNEL_MAP * *);
354 static LONG SCardGetContextAndChannelFromHandleTH(SCARDHANDLE,
355  /*@out@*/ SCONTEXTMAP * *, /*@out@*/ CHANNEL_MAP * *);
356 static LONG SCardRemoveHandle(SCARDHANDLE);
357 
358 static void SCardInvalidateHandles(void);
359 static LONG SCardGetSetAttrib(SCARDHANDLE hCard, int command, DWORD dwAttrId,
360  LPBYTE pbAttr, LPDWORD pcbAttrLen);
361 
362 static LONG getReaderStates(SCONTEXTMAP * currentContextMap);
363 
364 /*
365  * Thread safety functions
366  */
373 inline static LONG SCardLockThread(void)
374 {
375  return pthread_mutex_lock(&clientMutex);
376 }
377 
383 inline static LONG SCardUnlockThread(void)
384 {
385  return pthread_mutex_unlock(&clientMutex);
386 }
387 
388 static LONG SCardEstablishContextTH(DWORD, LPCVOID, LPCVOID,
389  /*@out@*/ LPSCARDCONTEXT);
390 
424 LONG SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1,
425  LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
426 {
427  LONG rv;
428  static int first_time = TRUE;
429 
430  API_TRACE_IN("%ld, %p, %p", dwScope, pvReserved1, pvReserved2)
431  PROFILE_START
432 
433  /* Some setup for the first execution */
434  if (first_time)
435  {
436  first_time = FALSE;
437 
438  /* Invalidate all the handles in the son after a fork */
439  pthread_atfork(NULL, NULL, SCardInvalidateHandles);
440  }
441 
442  /* Check if the server is running */
444  if (SCARD_E_INVALID_HANDLE == rv)
445  /* we reconnected to a daemon or we got called from a forked child */
447 
448  if (rv != SCARD_S_SUCCESS)
449  goto end;
450 
451  (void)SCardLockThread();
452  rv = SCardEstablishContextTH(dwScope, pvReserved1,
453  pvReserved2, phContext);
454  (void)SCardUnlockThread();
455 
456 end:
457  PROFILE_END(rv)
458  API_TRACE_OUT("%ld", *phContext)
459 
460  return rv;
461 }
462 
489 static LONG SCardEstablishContextTH(DWORD dwScope,
490  /*@unused@*/ LPCVOID pvReserved1,
491  /*@unused@*/ LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
492 {
493  LONG rv;
494  struct establish_struct scEstablishStruct;
495  uint32_t dwClientID = 0;
496 
497  (void)pvReserved1;
498  (void)pvReserved2;
499  if (phContext == NULL)
501  else
502  *phContext = 0;
503 
504  /*
505  * Do this only once:
506  * - Initialize context list.
507  */
508  if (isExecuted == 0)
509  {
510  int lrv;
511 
512  /* NOTE: The list will never be freed (No API call exists to
513  * "close all contexts".
514  * Applications which load and unload the library will leak
515  * the list's internal structures. */
516  lrv = list_init(&contextMapList);
517  if (lrv < 0)
518  {
519  Log2(PCSC_LOG_CRITICAL, "list_init failed with return value: %d",
520  lrv);
521  return SCARD_E_NO_MEMORY;
522  }
523 
524  lrv = list_attributes_seeker(&contextMapList,
525  SCONTEXTMAP_seeker);
526  if (lrv <0)
527  {
528  Log2(PCSC_LOG_CRITICAL,
529  "list_attributes_seeker failed with return value: %d", lrv);
530  list_destroy(&contextMapList);
531  return SCARD_E_NO_MEMORY;
532  }
533 
534  if (getenv("PCSCLITE_NO_BLOCKING"))
535  {
536  Log1(PCSC_LOG_INFO, "Disable shared blocking");
537  sharing_shall_block = FALSE;
538  }
539 
540  isExecuted = 1;
541  }
542 
543 
544  /* Establishes a connection to the server */
545  if (ClientSetupSession(&dwClientID) != 0)
546  {
547  return SCARD_E_NO_SERVICE;
548  }
549 
550  { /* exchange client/server protocol versions */
551  struct version_struct veStr;
552 
555  veStr.rv = SCARD_S_SUCCESS;
556 
557  rv = MessageSendWithHeader(CMD_VERSION, dwClientID, sizeof(veStr),
558  &veStr);
559  if (rv != SCARD_S_SUCCESS)
560  return rv;
561 
562  /* Read a message from the server */
563  rv = MessageReceiveTimeout(CMD_VERSION, &veStr, sizeof(veStr),
564  dwClientID, TIMEOUT_TIME*1000L);
565  if (rv != SCARD_S_SUCCESS)
566  {
567  Log1(PCSC_LOG_CRITICAL,
568  "Your pcscd is too old and does not support CMD_VERSION");
569  return SCARD_F_COMM_ERROR;
570  }
571 
572  Log3(PCSC_LOG_INFO, "Server is protocol version %d:%d",
573  veStr.major, veStr.minor);
574 
575  if (veStr.rv != SCARD_S_SUCCESS)
576  return veStr.rv;
577  }
578 
579 again:
580  /*
581  * Try to establish an Application Context with the server
582  */
583  scEstablishStruct.dwScope = dwScope;
584  scEstablishStruct.hContext = 0;
585  scEstablishStruct.rv = SCARD_S_SUCCESS;
586 
588  sizeof(scEstablishStruct), (void *) &scEstablishStruct);
589 
590  if (rv != SCARD_S_SUCCESS)
591  return rv;
592 
593  /*
594  * Read the response from the server
595  */
596  rv = MessageReceive(&scEstablishStruct, sizeof(scEstablishStruct),
597  dwClientID);
598 
599  if (rv != SCARD_S_SUCCESS)
600  return rv;
601 
602  if (scEstablishStruct.rv != SCARD_S_SUCCESS)
603  return scEstablishStruct.rv;
604 
605  /* check we do not reuse an existing hContext */
606  if (NULL != SCardGetContextTH(scEstablishStruct.hContext))
607  /* we do not need to release the allocated context since
608  * SCardReleaseContext() does nothing on the server side */
609  goto again;
610 
611  *phContext = scEstablishStruct.hContext;
612 
613  /*
614  * Allocate the new hContext - if allocator full return an error
615  */
616  rv = SCardAddContext(*phContext, dwClientID);
617 
618  return rv;
619 }
620 
643 {
644  LONG rv;
645  struct release_struct scReleaseStruct;
646  SCONTEXTMAP * currentContextMap;
647 
648  API_TRACE_IN("%ld", hContext)
649  PROFILE_START
650 
651  /*
652  * Make sure this context has been opened
653  * and get currentContextMap
654  */
655  currentContextMap = SCardGetContext(hContext);
656  if (NULL == currentContextMap)
657  {
659  goto error;
660  }
661 
662  (void)pthread_mutex_lock(currentContextMap->mMutex);
663 
664  /* check the context is still opened */
665  currentContextMap = SCardGetContext(hContext);
666  if (NULL == currentContextMap)
667  /* the context is now invalid
668  * -> another thread may have called SCardReleaseContext
669  * -> so the mMutex has been unlocked */
670  {
672  goto error;
673  }
674 
675  scReleaseStruct.hContext = hContext;
676  scReleaseStruct.rv = SCARD_S_SUCCESS;
677 
679  currentContextMap->dwClientID,
680  sizeof(scReleaseStruct), (void *) &scReleaseStruct);
681 
682  if (rv != SCARD_S_SUCCESS)
683  goto end;
684 
685  /*
686  * Read a message from the server
687  */
688  rv = MessageReceive(&scReleaseStruct, sizeof(scReleaseStruct),
689  currentContextMap->dwClientID);
690 
691  if (rv != SCARD_S_SUCCESS)
692  goto end;
693 
694  rv = scReleaseStruct.rv;
695 end:
696  (void)pthread_mutex_unlock(currentContextMap->mMutex);
697 
698  /*
699  * Remove the local context from the stack
700  */
701  (void)SCardLockThread();
702  (void)SCardRemoveContext(hContext);
703  (void)SCardUnlockThread();
704 
705 error:
706  PROFILE_END(rv)
707  API_TRACE_OUT("")
708 
709  return rv;
710 }
711 
768 LONG SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader,
769  DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard,
770  LPDWORD pdwActiveProtocol)
771 {
772  LONG rv;
773  struct connect_struct scConnectStruct;
774  SCONTEXTMAP * currentContextMap;
775 
776  PROFILE_START
777  API_TRACE_IN("%ld %s %ld %ld", hContext, szReader, dwShareMode, dwPreferredProtocols)
778 
779  /*
780  * Check for NULL parameters
781  */
782  if (phCard == NULL || pdwActiveProtocol == NULL)
784  else
785  *phCard = 0;
786 
787  if (szReader == NULL)
788  return SCARD_E_UNKNOWN_READER;
789 
790  /*
791  * Check for uninitialized strings
792  */
793  if (strlen(szReader) > MAX_READERNAME)
794  return SCARD_E_INVALID_VALUE;
795 
796  /*
797  * Make sure this context has been opened
798  */
799  currentContextMap = SCardGetContext(hContext);
800  if (NULL == currentContextMap)
801  return SCARD_E_INVALID_HANDLE;
802 
803  (void)pthread_mutex_lock(currentContextMap->mMutex);
804 
805  /* check the context is still opened */
806  currentContextMap = SCardGetContext(hContext);
807  if (NULL == currentContextMap)
808  /* the context is now invalid
809  * -> another thread may have called SCardReleaseContext
810  * -> so the mMutex has been unlocked */
811  return SCARD_E_INVALID_HANDLE;
812 
813  strlcpy(scConnectStruct.szReader, szReader, sizeof scConnectStruct.szReader);
814 
815  scConnectStruct.hContext = hContext;
816  scConnectStruct.dwShareMode = dwShareMode;
817  scConnectStruct.dwPreferredProtocols = dwPreferredProtocols;
818  scConnectStruct.hCard = 0;
819  scConnectStruct.dwActiveProtocol = 0;
820  scConnectStruct.rv = SCARD_S_SUCCESS;
821 
822  rv = MessageSendWithHeader(SCARD_CONNECT, currentContextMap->dwClientID,
823  sizeof(scConnectStruct), (void *) &scConnectStruct);
824 
825  if (rv != SCARD_S_SUCCESS)
826  goto end;
827 
828  /*
829  * Read a message from the server
830  */
831  rv = MessageReceive(&scConnectStruct, sizeof(scConnectStruct),
832  currentContextMap->dwClientID);
833 
834  if (rv != SCARD_S_SUCCESS)
835  goto end;
836 
837  *phCard = scConnectStruct.hCard;
838  *pdwActiveProtocol = scConnectStruct.dwActiveProtocol;
839 
840  if (scConnectStruct.rv == SCARD_S_SUCCESS)
841  {
842  /*
843  * Keep track of the handle locally
844  */
845  rv = SCardAddHandle(*phCard, currentContextMap, szReader);
846  }
847  else
848  rv = scConnectStruct.rv;
849 
850 end:
851  (void)pthread_mutex_unlock(currentContextMap->mMutex);
852 
853  PROFILE_END(rv)
854  API_TRACE_OUT("%d", *pdwActiveProtocol)
855 
856  return rv;
857 }
858 
932 LONG SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode,
933  DWORD dwPreferredProtocols, DWORD dwInitialization,
934  LPDWORD pdwActiveProtocol)
935 {
936  LONG rv;
937  struct reconnect_struct scReconnectStruct;
938  SCONTEXTMAP * currentContextMap;
939  CHANNEL_MAP * pChannelMap;
940 
941  PROFILE_START
942 
943  if (pdwActiveProtocol == NULL)
945 
946  /*
947  * Make sure this handle has been opened
948  */
949  rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
950  &pChannelMap);
951  if (rv == -1)
952  return SCARD_E_INVALID_HANDLE;
953 
954  /* Retry loop for blocking behaviour */
955 retry:
956 
957  (void)pthread_mutex_lock(currentContextMap->mMutex);
958 
959  /* check the handle is still valid */
960  rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
961  &pChannelMap);
962  if (rv == -1)
963  /* the handle is now invalid
964  * -> another thread may have called SCardReleaseContext
965  * -> so the mMutex has been unlocked */
966  return SCARD_E_INVALID_HANDLE;
967 
968  scReconnectStruct.hCard = hCard;
969  scReconnectStruct.dwShareMode = dwShareMode;
970  scReconnectStruct.dwPreferredProtocols = dwPreferredProtocols;
971  scReconnectStruct.dwInitialization = dwInitialization;
972  scReconnectStruct.dwActiveProtocol = *pdwActiveProtocol;
973  scReconnectStruct.rv = SCARD_S_SUCCESS;
974 
975  rv = MessageSendWithHeader(SCARD_RECONNECT, currentContextMap->dwClientID,
976  sizeof(scReconnectStruct), (void *) &scReconnectStruct);
977 
978  if (rv != SCARD_S_SUCCESS)
979  goto end;
980 
981  /*
982  * Read a message from the server
983  */
984  rv = MessageReceive(&scReconnectStruct, sizeof(scReconnectStruct),
985  currentContextMap->dwClientID);
986 
987  if (rv != SCARD_S_SUCCESS)
988  goto end;
989 
990  rv = scReconnectStruct.rv;
991 
992  if (sharing_shall_block && (SCARD_E_SHARING_VIOLATION == rv))
993  {
994  (void)pthread_mutex_unlock(currentContextMap->mMutex);
996  goto retry;
997  }
998 
999  *pdwActiveProtocol = scReconnectStruct.dwActiveProtocol;
1000 
1001 end:
1002  (void)pthread_mutex_unlock(currentContextMap->mMutex);
1003 
1004  PROFILE_END(rv)
1005 
1006  return rv;
1007 }
1008 
1040 LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
1041 {
1042  LONG rv;
1043  struct disconnect_struct scDisconnectStruct;
1044  SCONTEXTMAP * currentContextMap;
1045  CHANNEL_MAP * pChannelMap;
1046 
1047  PROFILE_START
1048  API_TRACE_IN("%ld %ld", hCard, dwDisposition)
1049 
1050  /*
1051  * Make sure this handle has been opened
1052  */
1053  rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
1054  &pChannelMap);
1055  if (rv == -1)
1056  {
1058  goto error;
1059  }
1060 
1061  (void)pthread_mutex_lock(currentContextMap->mMutex);
1062 
1063  /* check the handle is still valid */
1064  rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
1065  &pChannelMap);
1066  if (rv == -1)
1067  /* the handle is now invalid
1068  * -> another thread may have called SCardReleaseContext
1069  * -> so the mMutex has been unlocked */
1070  {
1072  goto error;
1073  }
1074 
1075  scDisconnectStruct.hCard = hCard;
1076  scDisconnectStruct.dwDisposition = dwDisposition;
1077  scDisconnectStruct.rv = SCARD_S_SUCCESS;
1078 
1079  rv = MessageSendWithHeader(SCARD_DISCONNECT, currentContextMap->dwClientID,
1080  sizeof(scDisconnectStruct), (void *) &scDisconnectStruct);
1081 
1082  if (rv != SCARD_S_SUCCESS)
1083  goto end;
1084 
1085  /*
1086  * Read a message from the server
1087  */
1088  rv = MessageReceive(&scDisconnectStruct, sizeof(scDisconnectStruct),
1089  currentContextMap->dwClientID);
1090 
1091  if (rv != SCARD_S_SUCCESS)
1092  goto end;
1093 
1094  if (SCARD_S_SUCCESS == scDisconnectStruct.rv)
1095  (void)SCardRemoveHandle(hCard);
1096  rv = scDisconnectStruct.rv;
1097 
1098 end:
1099  (void)pthread_mutex_unlock(currentContextMap->mMutex);
1100 
1101 error:
1102  PROFILE_END(rv)
1103  API_TRACE_OUT("")
1104 
1105  return rv;
1106 }
1107 
1144 {
1145 
1146  LONG rv;
1147  struct begin_struct scBeginStruct;
1148  SCONTEXTMAP * currentContextMap;
1149  CHANNEL_MAP * pChannelMap;
1150 
1151  PROFILE_START
1152 
1153  /*
1154  * Make sure this handle has been opened
1155  */
1156  rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
1157  &pChannelMap);
1158  if (rv == -1)
1159  return SCARD_E_INVALID_HANDLE;
1160 
1161  /*
1162  * Query the server every so often until the sharing violation ends
1163  * and then hold the lock for yourself.
1164  */
1165 
1166  for(;;)
1167  {
1168  (void)pthread_mutex_lock(currentContextMap->mMutex);
1169 
1170  /* check the handle is still valid */
1171  rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
1172  &pChannelMap);
1173  if (rv == -1)
1174  /* the handle is now invalid
1175  * -> another thread may have called SCardReleaseContext
1176  * -> so the mMutex has been unlocked */
1177  return SCARD_E_INVALID_HANDLE;
1178 
1179  scBeginStruct.hCard = hCard;
1180  scBeginStruct.rv = SCARD_S_SUCCESS;
1181 
1183  currentContextMap->dwClientID,
1184  sizeof(scBeginStruct), (void *) &scBeginStruct);
1185 
1186  if (rv != SCARD_S_SUCCESS)
1187  break;
1188 
1189  /*
1190  * Read a message from the server
1191  */
1192  rv = MessageReceive(&scBeginStruct, sizeof(scBeginStruct),
1193  currentContextMap->dwClientID);
1194 
1195  if (rv != SCARD_S_SUCCESS)
1196  break;
1197 
1198  rv = scBeginStruct.rv;
1199 
1200  if (SCARD_E_SHARING_VIOLATION != rv)
1201  break;
1202 
1203  (void)pthread_mutex_unlock(currentContextMap->mMutex);
1205  }
1206 
1207  (void)pthread_mutex_unlock(currentContextMap->mMutex);
1208 
1209  PROFILE_END(rv)
1210 
1211  return rv;
1212 }
1213 
1254 LONG SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
1255 {
1256  LONG rv;
1257  struct end_struct scEndStruct;
1258  int randnum;
1259  SCONTEXTMAP * currentContextMap;
1260  CHANNEL_MAP * pChannelMap;
1261 
1262  PROFILE_START
1263 
1264  /*
1265  * Make sure this handle has been opened
1266  */
1267  rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
1268  &pChannelMap);
1269  if (rv == -1)
1270  return SCARD_E_INVALID_HANDLE;
1271 
1272  (void)pthread_mutex_lock(currentContextMap->mMutex);
1273 
1274  /* check the handle is still valid */
1275  rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
1276  &pChannelMap);
1277  if (rv == -1)
1278  /* the handle is now invalid
1279  * -> another thread may have called SCardReleaseContext
1280  * -> so the mMutex has been unlocked */
1281  return SCARD_E_INVALID_HANDLE;
1282 
1283  scEndStruct.hCard = hCard;
1284  scEndStruct.dwDisposition = dwDisposition;
1285  scEndStruct.rv = SCARD_S_SUCCESS;
1286 
1288  currentContextMap->dwClientID,
1289  sizeof(scEndStruct), (void *) &scEndStruct);
1290 
1291  if (rv != SCARD_S_SUCCESS)
1292  goto end;
1293 
1294  /*
1295  * Read a message from the server
1296  */
1297  rv = MessageReceive(&scEndStruct, sizeof(scEndStruct),
1298  currentContextMap->dwClientID);
1299 
1300  if (rv != SCARD_S_SUCCESS)
1301  goto end;
1302 
1303  /*
1304  * This helps prevent starvation
1305  */
1306  randnum = SYS_RandomInt(1000, 10000);
1307  (void)SYS_USleep(randnum);
1308  rv = scEndStruct.rv;
1309 
1310 end:
1311  (void)pthread_mutex_unlock(currentContextMap->mMutex);
1312 
1313  PROFILE_END(rv)
1314 
1315  return rv;
1316 }
1317 
1413 LONG SCardStatus(SCARDHANDLE hCard, LPSTR mszReaderName,
1414  LPDWORD pcchReaderLen, LPDWORD pdwState,
1415  LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
1416 {
1417  DWORD dwReaderLen, dwAtrLen;
1418  LONG rv;
1419  int i;
1420  struct status_struct scStatusStruct;
1421  SCONTEXTMAP * currentContextMap;
1422  CHANNEL_MAP * pChannelMap;
1423  char *r;
1424  char *bufReader = NULL;
1425  LPBYTE bufAtr = NULL;
1426  DWORD dummy = 0;
1427 
1428  PROFILE_START
1429 
1430  /* default output values */
1431  if (pdwState)
1432  *pdwState = 0;
1433 
1434  if (pdwProtocol)
1435  *pdwProtocol = 0;
1436 
1437  /* Check for NULL parameters */
1438  if (pcchReaderLen == NULL)
1439  pcchReaderLen = &dummy;
1440 
1441  if (pcbAtrLen == NULL)
1442  pcbAtrLen = &dummy;
1443 
1444  /* length passed from caller */
1445  dwReaderLen = *pcchReaderLen;
1446  dwAtrLen = *pcbAtrLen;
1447 
1448  *pcchReaderLen = 0;
1449  *pcbAtrLen = 0;
1450 
1451  /*
1452  * Make sure this handle has been opened
1453  */
1454  rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
1455  &pChannelMap);
1456  if (rv == -1)
1457  return SCARD_E_INVALID_HANDLE;
1458 
1459  /* Retry loop for blocking behaviour */
1460 retry:
1461 
1462  (void)pthread_mutex_lock(currentContextMap->mMutex);
1463 
1464  /* check the handle is still valid */
1465  rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
1466  &pChannelMap);
1467  if (rv == -1)
1468  /* the handle is now invalid
1469  * -> another thread may have called SCardReleaseContext
1470  * -> so the mMutex has been unlocked */
1471  return SCARD_E_INVALID_HANDLE;
1472 
1473  /* synchronize reader states with daemon */
1474  rv = getReaderStates(currentContextMap);
1475  if (rv != SCARD_S_SUCCESS)
1476  goto end;
1477 
1478  r = pChannelMap->readerName;
1479  for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
1480  {
1481  /* by default r == NULL */
1482  if (r && strcmp(r, readerStates[i].readerName) == 0)
1483  break;
1484  }
1485 
1486  if (i == PCSCLITE_MAX_READERS_CONTEXTS)
1487  {
1489  goto end;
1490  }
1491 
1492  /* initialise the structure */
1493  memset(&scStatusStruct, 0, sizeof(scStatusStruct));
1494  scStatusStruct.hCard = hCard;
1495 
1496  rv = MessageSendWithHeader(SCARD_STATUS, currentContextMap->dwClientID,
1497  sizeof(scStatusStruct), (void *) &scStatusStruct);
1498 
1499  if (rv != SCARD_S_SUCCESS)
1500  goto end;
1501 
1502  /*
1503  * Read a message from the server
1504  */
1505  rv = MessageReceive(&scStatusStruct, sizeof(scStatusStruct),
1506  currentContextMap->dwClientID);
1507 
1508  if (rv != SCARD_S_SUCCESS)
1509  goto end;
1510 
1511  rv = scStatusStruct.rv;
1512 
1513  if (sharing_shall_block && (SCARD_E_SHARING_VIOLATION == rv))
1514  {
1515  (void)pthread_mutex_unlock(currentContextMap->mMutex);
1517  goto retry;
1518  }
1519 
1520  if (rv != SCARD_S_SUCCESS && rv != SCARD_E_INSUFFICIENT_BUFFER)
1521  {
1522  /*
1523  * An event must have occurred
1524  */
1525  goto end;
1526  }
1527 
1528  /*
1529  * Now continue with the client side SCardStatus
1530  */
1531 
1532  *pcchReaderLen = strlen(pChannelMap->readerName) + 1;
1533  *pcbAtrLen = readerStates[i].cardAtrLength;
1534 
1535  if (pdwState)
1536  *pdwState = (readerStates[i].eventCounter << 16) + readerStates[i].readerState;
1537 
1538  if (pdwProtocol)
1539  *pdwProtocol = readerStates[i].cardProtocol;
1540 
1541  if (SCARD_AUTOALLOCATE == dwReaderLen)
1542  {
1543  dwReaderLen = *pcchReaderLen;
1544  if (NULL == mszReaderName)
1545  {
1547  goto end;
1548  }
1549  bufReader = malloc(dwReaderLen);
1550  if (NULL == bufReader)
1551  {
1552  rv = SCARD_E_NO_MEMORY;
1553  goto end;
1554  }
1555  *(char **)mszReaderName = bufReader;
1556  }
1557  else
1558  bufReader = mszReaderName;
1559 
1560  /* return SCARD_E_INSUFFICIENT_BUFFER only if buffer pointer is non NULL */
1561  if (bufReader)
1562  {
1563  if (*pcchReaderLen > dwReaderLen)
1565 
1566  strncpy(bufReader, pChannelMap->readerName, dwReaderLen);
1567  }
1568 
1569  if (SCARD_AUTOALLOCATE == dwAtrLen)
1570  {
1571  dwAtrLen = *pcbAtrLen;
1572  if (NULL == pbAtr)
1573  {
1575  goto end;
1576  }
1577  bufAtr = malloc(dwAtrLen);
1578  if (NULL == bufAtr)
1579  {
1580  rv = SCARD_E_NO_MEMORY;
1581  goto end;
1582  }
1583  *(LPBYTE *)pbAtr = bufAtr;
1584  }
1585  else
1586  bufAtr = pbAtr;
1587 
1588  if (bufAtr)
1589  {
1590  if (*pcbAtrLen > dwAtrLen)
1592 
1593  memcpy(bufAtr, readerStates[i].cardAtr, min(*pcbAtrLen, dwAtrLen));
1594  }
1595 
1596 end:
1597  (void)pthread_mutex_unlock(currentContextMap->mMutex);
1598 
1599  PROFILE_END(rv)
1600 
1601  return rv;
1602 }
1603 
1697 LONG SCardGetStatusChange(SCARDCONTEXT hContext, DWORD dwTimeout,
1698  SCARD_READERSTATE *rgReaderStates, DWORD cReaders)
1699 {
1700  SCARD_READERSTATE *currReader;
1701  READER_STATE *rContext;
1702  long dwTime;
1703  DWORD dwBreakFlag = 0;
1704  unsigned int j;
1705  SCONTEXTMAP * currentContextMap;
1706  int currentReaderCount = 0;
1707  LONG rv = SCARD_S_SUCCESS;
1708 
1709  PROFILE_START
1710  API_TRACE_IN("%ld %ld %d", hContext, dwTimeout, cReaders)
1711 #ifdef DO_TRACE
1712  for (j=0; j<cReaders; j++)
1713  {
1714  API_TRACE_IN("[%d] %s %lX %lX", j, rgReaderStates[j].szReader,
1715  rgReaderStates[j].dwCurrentState, rgReaderStates[j].dwEventState)
1716  }
1717 #endif
1718 
1719  if ((rgReaderStates == NULL && cReaders > 0)
1720  || (cReaders > PCSCLITE_MAX_READERS_CONTEXTS))
1721  {
1723  goto error;
1724  }
1725 
1726  /* Check the integrity of the reader states structures */
1727  for (j = 0; j < cReaders; j++)
1728  {
1729  if (rgReaderStates[j].szReader == NULL)
1730  return SCARD_E_INVALID_VALUE;
1731  }
1732 
1733  /* return if all readers are SCARD_STATE_IGNORE */
1734  if (cReaders > 0)
1735  {
1736  int nbNonIgnoredReaders = cReaders;
1737 
1738  for (j=0; j<cReaders; j++)
1739  if (rgReaderStates[j].dwCurrentState & SCARD_STATE_IGNORE)
1740  nbNonIgnoredReaders--;
1741 
1742  if (0 == nbNonIgnoredReaders)
1743  {
1744  rv = SCARD_S_SUCCESS;
1745  goto error;
1746  }
1747  }
1748  else
1749  {
1750  /* reader list is empty */
1751  rv = SCARD_S_SUCCESS;
1752  goto error;
1753  }
1754 
1755  /*
1756  * Make sure this context has been opened
1757  */
1758  currentContextMap = SCardGetContext(hContext);
1759  if (NULL == currentContextMap)
1760  {
1762  goto error;
1763  }
1764 
1765  (void)pthread_mutex_lock(currentContextMap->mMutex);
1766 
1767  /* check the context is still opened */
1768  currentContextMap = SCardGetContext(hContext);
1769  if (NULL == currentContextMap)
1770  /* the context is now invalid
1771  * -> another thread may have called SCardReleaseContext
1772  * -> so the mMutex has been unlocked */
1773  {
1775  goto error;
1776  }
1777 
1778  /* synchronize reader states with daemon */
1779  rv = getReaderStates(currentContextMap);
1780  if (rv != SCARD_S_SUCCESS)
1781  goto end;
1782 
1783  /* check all the readers are already known */
1784  for (j=0; j<cReaders; j++)
1785  {
1786  const char *readerName;
1787  int i;
1788 
1789  readerName = rgReaderStates[j].szReader;
1790  for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
1791  {
1792  if (strcmp(readerName, readerStates[i].readerName) == 0)
1793  break;
1794  }
1795 
1796  /* The requested reader name is not recognized */
1797  if (i == PCSCLITE_MAX_READERS_CONTEXTS)
1798  {
1799  /* PnP special reader? */
1800  if (strcasecmp(readerName, "\\\\?PnP?\\Notification") != 0)
1801  {
1803  goto end;
1804  }
1805  }
1806  }
1807 
1808  /* Clear the event state for all readers */
1809  for (j = 0; j < cReaders; j++)
1810  rgReaderStates[j].dwEventState = 0;
1811 
1812  /* Now is where we start our event checking loop */
1813  Log2(PCSC_LOG_DEBUG, "Event Loop Start, dwTimeout: %ld", dwTimeout);
1814 
1815  /* Get the initial reader count on the system */
1816  for (j=0; j < PCSCLITE_MAX_READERS_CONTEXTS; j++)
1817  if (readerStates[j].readerName[0] != '\0')
1818  currentReaderCount++;
1819 
1820  /* catch possible sign extension problems from 32 to 64-bits integers */
1821  if ((DWORD)-1 == dwTimeout)
1822  dwTimeout = INFINITE;
1823  if (INFINITE == dwTimeout)
1824  dwTime = 60*1000; /* "infinite" timeout */
1825  else
1826  dwTime = dwTimeout;
1827 
1828  j = 0;
1829  do
1830  {
1831  currReader = &rgReaderStates[j];
1832 
1833  /* Ignore for IGNORED readers */
1834  if (!(currReader->dwCurrentState & SCARD_STATE_IGNORE))
1835  {
1836  const char *readerName;
1837  int i;
1838 
1839  /* Looks for correct readernames */
1840  readerName = currReader->szReader;
1841  for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
1842  {
1843  if (strcmp(readerName, readerStates[i].readerName) == 0)
1844  break;
1845  }
1846 
1847  /* The requested reader name is not recognized */
1848  if (i == PCSCLITE_MAX_READERS_CONTEXTS)
1849  {
1850  /* PnP special reader? */
1851  if (strcasecmp(readerName, "\\\\?PnP?\\Notification") == 0)
1852  {
1853  int k, newReaderCount = 0;
1854 
1855  for (k=0; k < PCSCLITE_MAX_READERS_CONTEXTS; k++)
1856  if (readerStates[k].readerName[0] != '\0')
1857  newReaderCount++;
1858 
1859  if (newReaderCount != currentReaderCount)
1860  {
1861  Log1(PCSC_LOG_INFO, "Reader list changed");
1862  currentReaderCount = newReaderCount;
1863 
1864  currReader->dwEventState |= SCARD_STATE_CHANGED;
1865  dwBreakFlag = 1;
1866  }
1867  }
1868  else
1869  {
1870  currReader->dwEventState =
1872  if (!(currReader->dwCurrentState & SCARD_STATE_UNKNOWN))
1873  {
1874  currReader->dwEventState |= SCARD_STATE_CHANGED;
1875  /*
1876  * Spec says use SCARD_STATE_IGNORE but a removed USB
1877  * reader with eventState fed into currentState will
1878  * be ignored forever
1879  */
1880  dwBreakFlag = 1;
1881  }
1882  }
1883  }
1884  else
1885  {
1886  uint32_t readerState;
1887 
1888  /* The reader has come back after being away */
1889  if (currReader->dwCurrentState & SCARD_STATE_UNKNOWN)
1890  {
1891  currReader->dwEventState |= SCARD_STATE_CHANGED;
1892  currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
1893  Log0(PCSC_LOG_DEBUG);
1894  dwBreakFlag = 1;
1895  }
1896 
1897  /* Set the reader status structure */
1898  rContext = &readerStates[i];
1899 
1900  /* Now we check all the Reader States */
1901  readerState = rContext->readerState;
1902 
1903  /* only if current state has an non null event counter */
1904  if (currReader->dwCurrentState & 0xFFFF0000)
1905  {
1906  unsigned int currentCounter;
1907 
1908  currentCounter = (currReader->dwCurrentState >> 16) & 0xFFFF;
1909 
1910  /* has the event counter changed since the last call? */
1911  if (rContext->eventCounter != currentCounter)
1912  {
1913  currReader->dwEventState |= SCARD_STATE_CHANGED;
1914  Log0(PCSC_LOG_DEBUG);
1915  dwBreakFlag = 1;
1916  }
1917  }
1918 
1919  /* add an event counter in the upper word of dwEventState */
1920  currReader->dwEventState = ((currReader->dwEventState & 0xffff )
1921  | (rContext->eventCounter << 16));
1922 
1923  /* Check if the reader is in the correct state */
1924  if (readerState & SCARD_UNKNOWN)
1925  {
1926  /* reader is in bad state */
1927  currReader->dwEventState = SCARD_STATE_UNAVAILABLE;
1928  if (!(currReader->dwCurrentState & SCARD_STATE_UNAVAILABLE))
1929  {
1930  /* App thinks reader is in good state and it is not */
1931  currReader->dwEventState |= SCARD_STATE_CHANGED;
1932  Log0(PCSC_LOG_DEBUG);
1933  dwBreakFlag = 1;
1934  }
1935  }
1936  else
1937  {
1938  /* App thinks reader in bad state but it is not */
1939  if (currReader-> dwCurrentState & SCARD_STATE_UNAVAILABLE)
1940  {
1941  currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
1942  currReader->dwEventState |= SCARD_STATE_CHANGED;
1943  Log0(PCSC_LOG_DEBUG);
1944  dwBreakFlag = 1;
1945  }
1946  }
1947 
1948  /* Check for card presence in the reader */
1949  if (readerState & SCARD_PRESENT)
1950  {
1951  /* card present but not yet powered up */
1952  if (0 == rContext->cardAtrLength)
1953  /* Allow the status thread to convey information */
1955 
1956  currReader->cbAtr = rContext->cardAtrLength;
1957  memcpy(currReader->rgbAtr, rContext->cardAtr,
1958  currReader->cbAtr);
1959  }
1960  else
1961  currReader->cbAtr = 0;
1962 
1963  /* Card is now absent */
1964  if (readerState & SCARD_ABSENT)
1965  {
1966  currReader->dwEventState |= SCARD_STATE_EMPTY;
1967  currReader->dwEventState &= ~SCARD_STATE_PRESENT;
1968  currReader->dwEventState &= ~SCARD_STATE_UNAWARE;
1969  currReader->dwEventState &= ~SCARD_STATE_IGNORE;
1970  currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
1971  currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
1972  currReader->dwEventState &= ~SCARD_STATE_ATRMATCH;
1973  currReader->dwEventState &= ~SCARD_STATE_MUTE;
1974  currReader->dwEventState &= ~SCARD_STATE_INUSE;
1975 
1976  /* After present the rest are assumed */
1977  if (currReader->dwCurrentState & SCARD_STATE_PRESENT)
1978  {
1979  currReader->dwEventState |= SCARD_STATE_CHANGED;
1980  Log0(PCSC_LOG_DEBUG);
1981  dwBreakFlag = 1;
1982  }
1983  }
1984  /* Card is now present */
1985  else if (readerState & SCARD_PRESENT)
1986  {
1987  currReader->dwEventState |= SCARD_STATE_PRESENT;
1988  currReader->dwEventState &= ~SCARD_STATE_EMPTY;
1989  currReader->dwEventState &= ~SCARD_STATE_UNAWARE;
1990  currReader->dwEventState &= ~SCARD_STATE_IGNORE;
1991  currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
1992  currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
1993  currReader->dwEventState &= ~SCARD_STATE_MUTE;
1994 
1995  if (currReader->dwCurrentState & SCARD_STATE_EMPTY)
1996  {
1997  currReader->dwEventState |= SCARD_STATE_CHANGED;
1998  Log0(PCSC_LOG_DEBUG);
1999  dwBreakFlag = 1;
2000  }
2001 
2002  if (readerState & SCARD_SWALLOWED)
2003  {
2004  currReader->dwEventState |= SCARD_STATE_MUTE;
2005  if (!(currReader->dwCurrentState & SCARD_STATE_MUTE))
2006  {
2007  currReader->dwEventState |= SCARD_STATE_CHANGED;
2008  Log0(PCSC_LOG_DEBUG);
2009  dwBreakFlag = 1;
2010  }
2011  }
2012  else
2013  {
2014  /* App thinks card is mute but it is not */
2015  if (currReader->dwCurrentState & SCARD_STATE_MUTE)
2016  {
2017  currReader->dwEventState |= SCARD_STATE_CHANGED;
2018  Log0(PCSC_LOG_DEBUG);
2019  dwBreakFlag = 1;
2020  }
2021  }
2022  }
2023 
2024  /* Now figure out sharing modes */
2026  {
2027  currReader->dwEventState |= SCARD_STATE_EXCLUSIVE;
2028  currReader->dwEventState &= ~SCARD_STATE_INUSE;
2029  if (currReader->dwCurrentState & SCARD_STATE_INUSE)
2030  {
2031  currReader->dwEventState |= SCARD_STATE_CHANGED;
2032  Log0(PCSC_LOG_DEBUG);
2033  dwBreakFlag = 1;
2034  }
2035  }
2036  else if (rContext->readerSharing >= PCSCLITE_SHARING_LAST_CONTEXT)
2037  {
2038  /* A card must be inserted for it to be INUSE */
2039  if (readerState & SCARD_PRESENT)
2040  {
2041  currReader->dwEventState |= SCARD_STATE_INUSE;
2042  currReader->dwEventState &= ~SCARD_STATE_EXCLUSIVE;
2043  if (currReader-> dwCurrentState & SCARD_STATE_EXCLUSIVE)
2044  {
2045  currReader->dwEventState |= SCARD_STATE_CHANGED;
2046  Log0(PCSC_LOG_DEBUG);
2047  dwBreakFlag = 1;
2048  }
2049  }
2050  }
2051  else if (rContext->readerSharing == PCSCLITE_SHARING_NO_CONTEXT)
2052  {
2053  currReader->dwEventState &= ~SCARD_STATE_INUSE;
2054  currReader->dwEventState &= ~SCARD_STATE_EXCLUSIVE;
2055 
2056  if (currReader->dwCurrentState & SCARD_STATE_INUSE)
2057  {
2058  currReader->dwEventState |= SCARD_STATE_CHANGED;
2059  Log0(PCSC_LOG_DEBUG);
2060  dwBreakFlag = 1;
2061  }
2062  else if (currReader-> dwCurrentState
2064  {
2065  currReader->dwEventState |= SCARD_STATE_CHANGED;
2066  Log0(PCSC_LOG_DEBUG);
2067  dwBreakFlag = 1;
2068  }
2069  }
2070 
2071  if (currReader->dwCurrentState == SCARD_STATE_UNAWARE)
2072  {
2073  /*
2074  * Break out of the while .. loop and return status
2075  * once all the status's for all readers is met
2076  */
2077  currReader->dwEventState |= SCARD_STATE_CHANGED;
2078  Log0(PCSC_LOG_DEBUG);
2079  dwBreakFlag = 1;
2080  }
2081  } /* End of SCARD_STATE_UNKNOWN */
2082  } /* End of SCARD_STATE_IGNORE */
2083 
2084  /* Counter and resetter */
2085  j++;
2086  if (j == cReaders)
2087  {
2088  /* go back to the first reader */
2089  j = 0;
2090 
2091  /* Declare all the break conditions */
2092 
2093  /* Break if UNAWARE is set and all readers have been checked */
2094  if (dwBreakFlag == 1)
2095  break;
2096 
2097  /* Only sleep once for each cycle of reader checks. */
2098  {
2099  struct wait_reader_state_change waitStatusStruct;
2100  struct timeval before, after;
2101 
2102  gettimeofday(&before, NULL);
2103 
2104  waitStatusStruct.timeOut = dwTime;
2105  waitStatusStruct.rv = SCARD_S_SUCCESS;
2106 
2107  /* another thread can do SCardCancel() */
2108  currentContextMap->cancellable = TRUE;
2109 
2111  currentContextMap->dwClientID,
2112  sizeof(waitStatusStruct), &waitStatusStruct);
2113 
2114  if (rv != SCARD_S_SUCCESS)
2115  goto end;
2116 
2117  /*
2118  * Read a message from the server
2119  */
2121  &waitStatusStruct, sizeof(waitStatusStruct),
2122  currentContextMap->dwClientID, dwTime);
2123 
2124  /* another thread can do SCardCancel() */
2125  currentContextMap->cancellable = FALSE;
2126 
2127  /* timeout */
2128  if (SCARD_E_TIMEOUT == rv)
2129  {
2130  /* ask server to remove us from the event list */
2132  currentContextMap->dwClientID,
2133  sizeof(waitStatusStruct), &waitStatusStruct);
2134 
2135  if (rv != SCARD_S_SUCCESS)
2136  goto end;
2137 
2138  /* Read a message from the server */
2139  rv = MessageReceive(&waitStatusStruct,
2140  sizeof(waitStatusStruct),
2141  currentContextMap->dwClientID);
2142 
2143  if (rv != SCARD_S_SUCCESS)
2144  goto end;
2145  }
2146 
2147  if (rv != SCARD_S_SUCCESS)
2148  goto end;
2149 
2150  /* an event occurs or SCardCancel() was called */
2151  if (SCARD_S_SUCCESS != waitStatusStruct.rv)
2152  {
2153  rv = waitStatusStruct.rv;
2154  goto end;
2155  }
2156 
2157  /* synchronize reader states with daemon */
2158  rv = getReaderStates(currentContextMap);
2159  if (rv != SCARD_S_SUCCESS)
2160  goto end;
2161 
2162  if (INFINITE != dwTimeout)
2163  {
2164  long int diff;
2165 
2166  gettimeofday(&after, NULL);
2167  diff = time_sub(&after, &before);
2168  dwTime -= diff/1000;
2169  }
2170  }
2171 
2172  if (dwTimeout != INFINITE)
2173  {
2174  /* If time is greater than timeout and all readers have been
2175  * checked
2176  */
2177  if (dwTime <= 0)
2178  {
2179  rv = SCARD_E_TIMEOUT;
2180  goto end;
2181  }
2182  }
2183  }
2184  }
2185  while (1);
2186 
2187 end:
2188  Log1(PCSC_LOG_DEBUG, "Event Loop End");
2189 
2190  (void)pthread_mutex_unlock(currentContextMap->mMutex);
2191 
2192 error:
2193  PROFILE_END(rv)
2194 #ifdef DO_TRACE
2195  for (j=0; j<cReaders; j++)
2196  {
2197  API_TRACE_OUT("[%d] %s %X %X", j, rgReaderStates[j].szReader,
2198  rgReaderStates[j].dwCurrentState, rgReaderStates[j].dwEventState)
2199  }
2200 #endif
2201 
2202  return rv;
2203 }
2204 
2255 LONG SCardControl(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer,
2256  DWORD cbSendLength, LPVOID pbRecvBuffer, DWORD cbRecvLength,
2257  LPDWORD lpBytesReturned)
2258 {
2259  LONG rv;
2260  struct control_struct scControlStruct;
2261  SCONTEXTMAP * currentContextMap;
2262  CHANNEL_MAP * pChannelMap;
2263 
2264  PROFILE_START
2265 
2266  /* 0 bytes received by default */
2267  if (NULL != lpBytesReturned)
2268  *lpBytesReturned = 0;
2269 
2270  /*
2271  * Make sure this handle has been opened
2272  */
2273  rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
2274  &pChannelMap);
2275  if (rv == -1)
2276  {
2277  PROFILE_END(SCARD_E_INVALID_HANDLE)
2278  return SCARD_E_INVALID_HANDLE;
2279  }
2280 
2281  (void)pthread_mutex_lock(currentContextMap->mMutex);
2282 
2283  /* check the handle is still valid */
2284  rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
2285  &pChannelMap);
2286  if (rv == -1)
2287  /* the handle is now invalid
2288  * -> another thread may have called SCardReleaseContext
2289  * -> so the mMutex has been unlocked */
2290  return SCARD_E_INVALID_HANDLE;
2291 
2292  if ((cbSendLength > MAX_BUFFER_SIZE_EXTENDED)
2293  || (cbRecvLength > MAX_BUFFER_SIZE_EXTENDED))
2294  {
2296  goto end;
2297  }
2298 
2299  scControlStruct.hCard = hCard;
2300  scControlStruct.dwControlCode = dwControlCode;
2301  scControlStruct.cbSendLength = cbSendLength;
2302  scControlStruct.cbRecvLength = cbRecvLength;
2303  scControlStruct.dwBytesReturned = 0;
2304  scControlStruct.rv = 0;
2305 
2306  rv = MessageSendWithHeader(SCARD_CONTROL, currentContextMap->dwClientID,
2307  sizeof(scControlStruct), &scControlStruct);
2308 
2309  if (rv != SCARD_S_SUCCESS)
2310  goto end;
2311 
2312  /* write the sent buffer */
2313  rv = MessageSend((char *)pbSendBuffer, cbSendLength,
2314  currentContextMap->dwClientID);
2315 
2316  if (rv != SCARD_S_SUCCESS)
2317  goto end;
2318 
2319  /*
2320  * Read a message from the server
2321  */
2322  rv = MessageReceive(&scControlStruct, sizeof(scControlStruct),
2323  currentContextMap->dwClientID);
2324 
2325  if (rv != SCARD_S_SUCCESS)
2326  goto end;
2327 
2328  if (SCARD_S_SUCCESS == scControlStruct.rv)
2329  {
2330  /* read the received buffer */
2331  rv = MessageReceive(pbRecvBuffer, scControlStruct.dwBytesReturned,
2332  currentContextMap->dwClientID);
2333 
2334  if (rv != SCARD_S_SUCCESS)
2335  goto end;
2336 
2337  }
2338 
2339  if (NULL != lpBytesReturned)
2340  *lpBytesReturned = scControlStruct.dwBytesReturned;
2341 
2342  rv = scControlStruct.rv;
2343 
2344 end:
2345  (void)pthread_mutex_unlock(currentContextMap->mMutex);
2346 
2347  PROFILE_END(rv)
2348 
2349  return rv;
2350 }
2351 
2456 LONG SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr,
2457  LPDWORD pcbAttrLen)
2458 {
2459  LONG ret;
2460  unsigned char *buf = NULL;
2461 
2462  PROFILE_START
2463 
2464  if (NULL == pcbAttrLen)
2465  {
2467  goto end;
2468  }
2469 
2470  if (SCARD_AUTOALLOCATE == *pcbAttrLen)
2471  {
2472  if (NULL == pbAttr)
2474 
2475  *pcbAttrLen = MAX_BUFFER_SIZE;
2476  buf = malloc(*pcbAttrLen);
2477  if (NULL == buf)
2478  {
2479  ret = SCARD_E_NO_MEMORY;
2480  goto end;
2481  }
2482 
2483  *(unsigned char **)pbAttr = buf;
2484  }
2485  else
2486  {
2487  buf = pbAttr;
2488 
2489  /* if only get the length */
2490  if (NULL == pbAttr)
2491  /* use a reasonable size */
2492  *pcbAttrLen = MAX_BUFFER_SIZE;
2493  }
2494 
2495  ret = SCardGetSetAttrib(hCard, SCARD_GET_ATTRIB, dwAttrId, buf,
2496  pcbAttrLen);
2497 
2498 end:
2499  PROFILE_END(ret)
2500 
2501  return ret;
2502 }
2503 
2539 LONG SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr,
2540  DWORD cbAttrLen)
2541 {
2542  LONG ret;
2543 
2544  PROFILE_START
2545 
2546  if (NULL == pbAttr || 0 == cbAttrLen)
2548 
2549  ret = SCardGetSetAttrib(hCard, SCARD_SET_ATTRIB, dwAttrId, (LPBYTE)pbAttr,
2550  &cbAttrLen);
2551 
2552  PROFILE_END(ret)
2553 
2554  return ret;
2555 }
2556 
2557 static LONG SCardGetSetAttrib(SCARDHANDLE hCard, int command, DWORD dwAttrId,
2558  LPBYTE pbAttr, LPDWORD pcbAttrLen)
2559 {
2560  LONG rv;
2561  struct getset_struct scGetSetStruct;
2562  SCONTEXTMAP * currentContextMap;
2563  CHANNEL_MAP * pChannelMap;
2564 
2565  /*
2566  * Make sure this handle has been opened
2567  */
2568  rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
2569  &pChannelMap);
2570  if (rv == -1)
2571  return SCARD_E_INVALID_HANDLE;
2572 
2573  (void)pthread_mutex_lock(currentContextMap->mMutex);
2574 
2575  /* check the handle is still valid */
2576  rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
2577  &pChannelMap);
2578  if (rv == -1)
2579  /* the handle is now invalid
2580  * -> another thread may have called SCardReleaseContext
2581  * -> so the mMutex has been unlocked */
2582  return SCARD_E_INVALID_HANDLE;
2583 
2584  if (*pcbAttrLen > MAX_BUFFER_SIZE)
2585  {
2587  goto end;
2588  }
2589 
2590  scGetSetStruct.hCard = hCard;
2591  scGetSetStruct.dwAttrId = dwAttrId;
2592  scGetSetStruct.cbAttrLen = *pcbAttrLen;
2593  scGetSetStruct.rv = SCARD_E_NO_SERVICE;
2594  memset(scGetSetStruct.pbAttr, 0, sizeof(scGetSetStruct.pbAttr));
2595  if (SCARD_SET_ATTRIB == command)
2596  memcpy(scGetSetStruct.pbAttr, pbAttr, *pcbAttrLen);
2597 
2598  rv = MessageSendWithHeader(command, currentContextMap->dwClientID,
2599  sizeof(scGetSetStruct), &scGetSetStruct);
2600 
2601  if (rv != SCARD_S_SUCCESS)
2602  goto end;
2603 
2604  /*
2605  * Read a message from the server
2606  */
2607  rv = MessageReceive(&scGetSetStruct, sizeof(scGetSetStruct),
2608  currentContextMap->dwClientID);
2609 
2610  if (rv != SCARD_S_SUCCESS)
2611  goto end;
2612 
2613  if ((SCARD_S_SUCCESS == scGetSetStruct.rv) && (SCARD_GET_ATTRIB == command))
2614  {
2615  /*
2616  * Copy and zero it so any secret information is not leaked
2617  */
2618  if (*pcbAttrLen < scGetSetStruct.cbAttrLen)
2619  {
2620  scGetSetStruct.cbAttrLen = *pcbAttrLen;
2621  scGetSetStruct.rv = SCARD_E_INSUFFICIENT_BUFFER;
2622  }
2623  else
2624  *pcbAttrLen = scGetSetStruct.cbAttrLen;
2625 
2626  if (pbAttr)
2627  memcpy(pbAttr, scGetSetStruct.pbAttr, scGetSetStruct.cbAttrLen);
2628 
2629  memset(scGetSetStruct.pbAttr, 0x00, sizeof(scGetSetStruct.pbAttr));
2630  }
2631  rv = scGetSetStruct.rv;
2632 
2633 end:
2634  (void)pthread_mutex_unlock(currentContextMap->mMutex);
2635 
2636  return rv;
2637 }
2638 
2697 LONG SCardTransmit(SCARDHANDLE hCard, const SCARD_IO_REQUEST *pioSendPci,
2698  LPCBYTE pbSendBuffer, DWORD cbSendLength,
2699  SCARD_IO_REQUEST *pioRecvPci, LPBYTE pbRecvBuffer,
2700  LPDWORD pcbRecvLength)
2701 {
2702  LONG rv;
2703  SCONTEXTMAP * currentContextMap;
2704  CHANNEL_MAP * pChannelMap;
2705  struct transmit_struct scTransmitStruct;
2706 
2707  PROFILE_START
2708 
2709  if (pbSendBuffer == NULL || pbRecvBuffer == NULL ||
2710  pcbRecvLength == NULL || pioSendPci == NULL)
2712 
2713  /*
2714  * Make sure this handle has been opened
2715  */
2716  rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
2717  &pChannelMap);
2718  if (rv == -1)
2719  {
2720  *pcbRecvLength = 0;
2721  PROFILE_END(SCARD_E_INVALID_HANDLE)
2722  return SCARD_E_INVALID_HANDLE;
2723  }
2724 
2725  /* Retry loop for blocking behaviour */
2726 retry:
2727 
2728  (void)pthread_mutex_lock(currentContextMap->mMutex);
2729 
2730  /* check the handle is still valid */
2731  rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
2732  &pChannelMap);
2733  if (rv == -1)
2734  /* the handle is now invalid
2735  * -> another thread may have called SCardReleaseContext
2736  * -> so the mMutex has been unlocked */
2737  return SCARD_E_INVALID_HANDLE;
2738 
2739  if ((cbSendLength > MAX_BUFFER_SIZE_EXTENDED)
2740  || (*pcbRecvLength > MAX_BUFFER_SIZE_EXTENDED))
2741  {
2743  goto end;
2744  }
2745 
2746  scTransmitStruct.hCard = hCard;
2747  scTransmitStruct.cbSendLength = cbSendLength;
2748  scTransmitStruct.pcbRecvLength = *pcbRecvLength;
2749  scTransmitStruct.ioSendPciProtocol = pioSendPci->dwProtocol;
2750  scTransmitStruct.ioSendPciLength = pioSendPci->cbPciLength;
2751  scTransmitStruct.rv = SCARD_S_SUCCESS;
2752 
2753  if (pioRecvPci)
2754  {
2755  scTransmitStruct.ioRecvPciProtocol = pioRecvPci->dwProtocol;
2756  scTransmitStruct.ioRecvPciLength = pioRecvPci->cbPciLength;
2757  }
2758  else
2759  {
2760  scTransmitStruct.ioRecvPciProtocol = SCARD_PROTOCOL_ANY;
2761  scTransmitStruct.ioRecvPciLength = sizeof(SCARD_IO_REQUEST);
2762  }
2763 
2764  rv = MessageSendWithHeader(SCARD_TRANSMIT, currentContextMap->dwClientID,
2765  sizeof(scTransmitStruct), (void *) &scTransmitStruct);
2766 
2767  if (rv != SCARD_S_SUCCESS)
2768  goto end;
2769 
2770  /* write the sent buffer */
2771  rv = MessageSend((void *)pbSendBuffer, cbSendLength,
2772  currentContextMap->dwClientID);
2773 
2774  if (rv != SCARD_S_SUCCESS)
2775  goto end;
2776 
2777  /*
2778  * Read a message from the server
2779  */
2780  rv = MessageReceive(&scTransmitStruct, sizeof(scTransmitStruct),
2781  currentContextMap->dwClientID);
2782 
2783  if (rv != SCARD_S_SUCCESS)
2784  goto end;
2785 
2786  if (SCARD_S_SUCCESS == scTransmitStruct.rv)
2787  {
2788  /* read the received buffer */
2789  rv = MessageReceive(pbRecvBuffer, scTransmitStruct.pcbRecvLength,
2790  currentContextMap->dwClientID);
2791 
2792  if (rv != SCARD_S_SUCCESS)
2793  goto end;
2794 
2795  if (pioRecvPci)
2796  {
2797  pioRecvPci->dwProtocol = scTransmitStruct.ioRecvPciProtocol;
2798  pioRecvPci->cbPciLength = scTransmitStruct.ioRecvPciLength;
2799  }
2800  }
2801 
2802  rv = scTransmitStruct.rv;
2803 
2804  if (sharing_shall_block && (SCARD_E_SHARING_VIOLATION == rv))
2805  {
2806  (void)pthread_mutex_unlock(currentContextMap->mMutex);
2808  goto retry;
2809  }
2810 
2811  *pcbRecvLength = scTransmitStruct.pcbRecvLength;
2812 
2813 end:
2814  (void)pthread_mutex_unlock(currentContextMap->mMutex);
2815 
2816  PROFILE_END(rv)
2817 
2818  return rv;
2819 }
2820 
2871 LONG SCardListReaders(SCARDCONTEXT hContext, /*@unused@*/ LPCSTR mszGroups,
2872  LPSTR mszReaders, LPDWORD pcchReaders)
2873 {
2874  DWORD dwReadersLen = 0;
2875  int i;
2876  SCONTEXTMAP * currentContextMap;
2877  LONG rv = SCARD_S_SUCCESS;
2878  char *buf = NULL;
2879 
2880  (void)mszGroups;
2881  PROFILE_START
2882  API_TRACE_IN("%ld", hContext)
2883 
2884  /*
2885  * Check for NULL parameters
2886  */
2887  if (pcchReaders == NULL)
2889 
2890  /*
2891  * Make sure this context has been opened
2892  */
2893  currentContextMap = SCardGetContext(hContext);
2894  if (NULL == currentContextMap)
2895  {
2896  PROFILE_END(SCARD_E_INVALID_HANDLE)
2897  return SCARD_E_INVALID_HANDLE;
2898  }
2899 
2900  (void)pthread_mutex_lock(currentContextMap->mMutex);
2901 
2902  /* check the context is still opened */
2903  currentContextMap = SCardGetContext(hContext);
2904  if (NULL == currentContextMap)
2905  /* the context is now invalid
2906  * -> another thread may have called SCardReleaseContext
2907  * -> so the mMutex has been unlocked */
2908  return SCARD_E_INVALID_HANDLE;
2909 
2910  /* synchronize reader states with daemon */
2911  rv = getReaderStates(currentContextMap);
2912  if (rv != SCARD_S_SUCCESS)
2913  goto end;
2914 
2915  dwReadersLen = 0;
2916  for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
2917  if (readerStates[i].readerName[0] != '\0')
2918  dwReadersLen += strlen(readerStates[i].readerName) + 1;
2919 
2920  /* for the last NULL byte */
2921  dwReadersLen += 1;
2922 
2923  if (1 == dwReadersLen)
2924  {
2926  goto end;
2927  }
2928 
2929  if (SCARD_AUTOALLOCATE == *pcchReaders)
2930  {
2931  buf = malloc(dwReadersLen);
2932  if (NULL == buf)
2933  {
2934  rv = SCARD_E_NO_MEMORY;
2935  goto end;
2936  }
2937  if (NULL == mszReaders)
2938  {
2940  goto end;
2941  }
2942  *(char **)mszReaders = buf;
2943  }
2944  else
2945  {
2946  buf = mszReaders;
2947 
2948  /* not enough place to store the reader names */
2949  if ((NULL != mszReaders) && (*pcchReaders < dwReadersLen))
2950  {
2952  goto end;
2953  }
2954  }
2955 
2956  if (mszReaders == NULL) /* text array not allocated */
2957  goto end;
2958 
2959  for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
2960  {
2961  if (readerStates[i].readerName[0] != '\0')
2962  {
2963  /*
2964  * Build the multi-string
2965  */
2966  strcpy(buf, readerStates[i].readerName);
2967  buf += strlen(readerStates[i].readerName)+1;
2968  }
2969  }
2970  *buf = '\0'; /* Add the last null */
2971 
2972 end:
2973  /* set the reader names length */
2974  *pcchReaders = dwReadersLen;
2975 
2976  (void)pthread_mutex_unlock(currentContextMap->mMutex);
2977 
2978  PROFILE_END(rv)
2979  API_TRACE_OUT("%d", *pcchReaders)
2980 
2981  return rv;
2982 }
2983 
2997 LONG SCardFreeMemory(SCARDCONTEXT hContext, LPCVOID pvMem)
2998 {
2999  LONG rv = SCARD_S_SUCCESS;
3000  SCONTEXTMAP * currentContextMap;
3001 
3002  PROFILE_START
3003 
3004  /*
3005  * Make sure this context has been opened
3006  */
3007  currentContextMap = SCardGetContext(hContext);
3008  if (NULL == currentContextMap)
3009  return SCARD_E_INVALID_HANDLE;
3010 
3011  free((void *)pvMem);
3012 
3013  PROFILE_END(rv)
3014 
3015  return rv;
3016 }
3017 
3069 LONG SCardListReaderGroups(SCARDCONTEXT hContext, LPSTR mszGroups,
3070  LPDWORD pcchGroups)
3071 {
3072  LONG rv = SCARD_S_SUCCESS;
3073  SCONTEXTMAP * currentContextMap;
3074  char *buf = NULL;
3075 
3076  PROFILE_START
3077 
3078  /* Multi-string with two trailing \0 */
3079  const char ReaderGroup[] = "SCard$DefaultReaders\0";
3080  const unsigned int dwGroups = sizeof(ReaderGroup);
3081 
3082  /*
3083  * Make sure this context has been opened
3084  */
3085  currentContextMap = SCardGetContext(hContext);
3086  if (NULL == currentContextMap)
3087  return SCARD_E_INVALID_HANDLE;
3088 
3089  (void)pthread_mutex_lock(currentContextMap->mMutex);
3090 
3091  /* check the context is still opened */
3092  currentContextMap = SCardGetContext(hContext);
3093  if (NULL == currentContextMap)
3094  /* the context is now invalid
3095  * -> another thread may have called SCardReleaseContext
3096  * -> so the mMutex has been unlocked */
3097  return SCARD_E_INVALID_HANDLE;
3098 
3099  if (SCARD_AUTOALLOCATE == *pcchGroups)
3100  {
3101  if (NULL == mszGroups)
3102  {
3104  goto end;
3105  }
3106  buf = malloc(dwGroups);
3107  if (NULL == buf)
3108  {
3109  rv = SCARD_E_NO_MEMORY;
3110  goto end;
3111  }
3112  *(char **)mszGroups = buf;
3113  }
3114  else
3115  {
3116  buf = mszGroups;
3117 
3118  if ((NULL != mszGroups) && (*pcchGroups < dwGroups))
3119  {
3121  goto end;
3122  }
3123  }
3124 
3125  if (buf)
3126  memcpy(buf, ReaderGroup, dwGroups);
3127 
3128 end:
3129  *pcchGroups = dwGroups;
3130 
3131  (void)pthread_mutex_unlock(currentContextMap->mMutex);
3132 
3133  PROFILE_END(rv)
3134 
3135  return rv;
3136 }
3137 
3168 {
3169  SCONTEXTMAP * currentContextMap;
3170  LONG rv = SCARD_S_SUCCESS;
3171  uint32_t dwClientID = 0;
3172  struct cancel_struct scCancelStruct;
3173 
3174  PROFILE_START
3175  API_TRACE_IN("%ld", hContext)
3176 
3177  /*
3178  * Make sure this context has been opened
3179  */
3180  currentContextMap = SCardGetContext(hContext);
3181  if (NULL == currentContextMap)
3182  {
3184  goto error;
3185  }
3186 
3187  if (! currentContextMap->cancellable)
3188  {
3189  rv = SCARD_S_SUCCESS;
3190  goto error;
3191  }
3192 
3193  /* create a new connection to the server */
3194  if (ClientSetupSession(&dwClientID) != 0)
3195  {
3196  rv = SCARD_E_NO_SERVICE;
3197  goto error;
3198  }
3199 
3200  scCancelStruct.hContext = hContext;
3201  scCancelStruct.rv = SCARD_S_SUCCESS;
3202 
3203  rv = MessageSendWithHeader(SCARD_CANCEL, dwClientID,
3204  sizeof(scCancelStruct), (void *) &scCancelStruct);
3205 
3206  if (rv != SCARD_S_SUCCESS)
3207  goto end;
3208 
3209  /*
3210  * Read a message from the server
3211  */
3212  rv = MessageReceive(&scCancelStruct, sizeof(scCancelStruct), dwClientID);
3213 
3214  if (rv != SCARD_S_SUCCESS)
3215  goto end;
3216 
3217  rv = scCancelStruct.rv;
3218 end:
3219  ClientCloseSession(dwClientID);
3220 
3221 error:
3222  PROFILE_END(rv)
3223  API_TRACE_OUT("")
3224 
3225  return rv;
3226 }
3227 
3252 {
3253  LONG rv;
3254  SCONTEXTMAP * currentContextMap;
3255 
3256  PROFILE_START
3257  API_TRACE_IN("%ld", hContext)
3258 
3259  rv = SCARD_S_SUCCESS;
3260 
3261  /*
3262  * Make sure this context has been opened
3263  */
3264  currentContextMap = SCardGetContext(hContext);
3265  if (currentContextMap == NULL)
3267 
3268  PROFILE_END(rv)
3269  API_TRACE_OUT("")
3270 
3271  return rv;
3272 }
3273 
3290 static LONG SCardAddContext(SCARDCONTEXT hContext, DWORD dwClientID)
3291 {
3292  int lrv;
3293  SCONTEXTMAP * newContextMap;
3294 
3295  newContextMap = malloc(sizeof(SCONTEXTMAP));
3296  if (NULL == newContextMap)
3297  return SCARD_E_NO_MEMORY;
3298 
3299  Log2(PCSC_LOG_DEBUG, "Allocating new SCONTEXTMAP @%p", newContextMap);
3300  newContextMap->hContext = hContext;
3301  newContextMap->dwClientID = dwClientID;
3302  newContextMap->cancellable = FALSE;
3303 
3304  newContextMap->mMutex = malloc(sizeof(pthread_mutex_t));
3305  if (NULL == newContextMap->mMutex)
3306  {
3307  Log2(PCSC_LOG_DEBUG, "Freeing SCONTEXTMAP @%p", newContextMap);
3308  free(newContextMap);
3309  return SCARD_E_NO_MEMORY;
3310  }
3311  (void)pthread_mutex_init(newContextMap->mMutex, NULL);
3312 
3313  lrv = list_init(&newContextMap->channelMapList);
3314  if (lrv < 0)
3315  {
3316  Log2(PCSC_LOG_CRITICAL, "list_init failed with return value: %d", lrv);
3317  goto error;
3318  }
3319 
3320  lrv = list_attributes_seeker(&newContextMap->channelMapList,
3321  CHANNEL_MAP_seeker);
3322  if (lrv <0)
3323  {
3324  Log2(PCSC_LOG_CRITICAL,
3325  "list_attributes_seeker failed with return value: %d", lrv);
3326  list_destroy(&newContextMap->channelMapList);
3327  goto error;
3328  }
3329 
3330  lrv = list_append(&contextMapList, newContextMap);
3331  if (lrv < 0)
3332  {
3333  Log2(PCSC_LOG_CRITICAL, "list_append failed with return value: %d",
3334  lrv);
3335  list_destroy(&newContextMap->channelMapList);
3336  goto error;
3337  }
3338 
3339  return SCARD_S_SUCCESS;
3340 
3341 error:
3342 
3343  (void)pthread_mutex_destroy(newContextMap->mMutex);
3344  free(newContextMap->mMutex);
3345  free(newContextMap);
3346 
3347  return SCARD_E_NO_MEMORY;
3348 }
3349 
3363 {
3364  SCONTEXTMAP * currentContextMap;
3365 
3366  (void)SCardLockThread();
3367  currentContextMap = SCardGetContextTH(hContext);
3368  (void)SCardUnlockThread();
3369 
3370  return currentContextMap;
3371 }
3372 
3386 {
3387  return list_seek(&contextMapList, &hContext);
3388 }
3389 
3399 static LONG SCardRemoveContext(SCARDCONTEXT hContext)
3400 {
3401  SCONTEXTMAP * currentContextMap;
3402  currentContextMap = SCardGetContextTH(hContext);
3403 
3404  if (NULL == currentContextMap)
3405  return SCARD_E_INVALID_HANDLE;
3406  else
3407  return SCardCleanContext(currentContextMap);
3408 }
3409 
3410 static LONG SCardCleanContext(SCONTEXTMAP * targetContextMap)
3411 {
3412  int list_index, lrv;
3413  int listSize;
3414  CHANNEL_MAP * currentChannelMap;
3415 
3416  targetContextMap->hContext = 0;
3417  (void)ClientCloseSession(targetContextMap->dwClientID);
3418  targetContextMap->dwClientID = 0;
3419  (void)pthread_mutex_destroy(targetContextMap->mMutex);
3420  free(targetContextMap->mMutex);
3421  targetContextMap->mMutex = NULL;
3422 
3423  listSize = list_size(&targetContextMap->channelMapList);
3424  for (list_index = 0; list_index < listSize; list_index++)
3425  {
3426  currentChannelMap = list_get_at(&targetContextMap->channelMapList,
3427  list_index);
3428  if (NULL == currentChannelMap)
3429  {
3430  Log2(PCSC_LOG_CRITICAL, "list_get_at failed for index %d",
3431  list_index);
3432  continue;
3433  }
3434  else
3435  {
3436  free(currentChannelMap->readerName);
3437  free(currentChannelMap);
3438  }
3439 
3440  }
3441  list_destroy(&targetContextMap->channelMapList);
3442 
3443  lrv = list_delete(&contextMapList, targetContextMap);
3444  if (lrv < 0)
3445  {
3446  Log2(PCSC_LOG_CRITICAL,
3447  "list_delete failed with return value: %d", lrv);
3448  }
3449 
3450  free(targetContextMap);
3451 
3452  return SCARD_S_SUCCESS;
3453 }
3454 
3455 /*
3456  * Functions for managing hCard values returned from SCardConnect.
3457  */
3458 
3459 static LONG SCardAddHandle(SCARDHANDLE hCard, SCONTEXTMAP * currentContextMap,
3460  LPCSTR readerName)
3461 {
3462  CHANNEL_MAP * newChannelMap;
3463  int lrv = -1;
3464 
3465  newChannelMap = malloc(sizeof(CHANNEL_MAP));
3466  if (NULL == newChannelMap)
3467  return SCARD_E_NO_MEMORY;
3468 
3469  newChannelMap->hCard = hCard;
3470  newChannelMap->readerName = strdup(readerName);
3471 
3472  lrv = list_append(&currentContextMap->channelMapList, newChannelMap);
3473  if (lrv < 0)
3474  {
3475  free(newChannelMap->readerName);
3476  free(newChannelMap);
3477  Log2(PCSC_LOG_CRITICAL, "list_append failed with return value: %d",
3478  lrv);
3479  return SCARD_E_NO_MEMORY;
3480  }
3481 
3482  return SCARD_S_SUCCESS;
3483 }
3484 
3485 static LONG SCardRemoveHandle(SCARDHANDLE hCard)
3486 {
3487  SCONTEXTMAP * currentContextMap;
3488  CHANNEL_MAP * currentChannelMap;
3489  int lrv;
3490  LONG rv;
3491 
3492  rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
3493  &currentChannelMap);
3494  if (rv == -1)
3495  return SCARD_E_INVALID_HANDLE;
3496 
3497  free(currentChannelMap->readerName);
3498 
3499  lrv = list_delete(&currentContextMap->channelMapList, currentChannelMap);
3500  if (lrv < 0)
3501  {
3502  Log2(PCSC_LOG_CRITICAL,
3503  "list_delete failed with return value: %d", lrv);
3504  }
3505 
3506  free(currentChannelMap);
3507 
3508  return SCARD_S_SUCCESS;
3509 }
3510 
3511 static LONG SCardGetContextAndChannelFromHandle(SCARDHANDLE hCard,
3512  SCONTEXTMAP **targetContextMap, CHANNEL_MAP ** targetChannelMap)
3513 {
3514  LONG rv;
3515 
3516  if (0 == hCard)
3517  return -1;
3518 
3519  (void)SCardLockThread();
3520  rv = SCardGetContextAndChannelFromHandleTH(hCard, targetContextMap,
3521  targetChannelMap);
3522  (void)SCardUnlockThread();
3523 
3524  return rv;
3525 }
3526 
3527 static LONG SCardGetContextAndChannelFromHandleTH(SCARDHANDLE hCard,
3528  SCONTEXTMAP **targetContextMap, CHANNEL_MAP ** targetChannelMap)
3529 {
3530  int listSize;
3531  int list_index;
3532  SCONTEXTMAP * currentContextMap;
3533  CHANNEL_MAP * currentChannelMap;
3534 
3535  /* Best to get the caller a crash early if we fail unsafely */
3536  *targetContextMap = NULL;
3537  *targetChannelMap = NULL;
3538 
3539  listSize = list_size(&contextMapList);
3540 
3541  for (list_index = 0; list_index < listSize; list_index++)
3542  {
3543  currentContextMap = list_get_at(&contextMapList, list_index);
3544  if (currentContextMap == NULL)
3545  {
3546  Log2(PCSC_LOG_CRITICAL, "list_get_at failed for index %d",
3547  list_index);
3548  continue;
3549  }
3550  currentChannelMap = list_seek(&currentContextMap->channelMapList,
3551  &hCard);
3552  if (currentChannelMap != NULL)
3553  {
3554  *targetContextMap = currentContextMap;
3555  *targetChannelMap = currentChannelMap;
3556  return SCARD_S_SUCCESS;
3557  }
3558  }
3559 
3560  return -1;
3561 }
3562 
3575 {
3576  LONG rv;
3577  struct stat statBuffer;
3578  char *socketName;
3579 
3580  socketName = getSocketName();
3581  rv = stat(socketName, &statBuffer);
3582 
3583  if (rv != 0)
3584  {
3585  Log3(PCSC_LOG_INFO, "PCSC Not Running: %s: %s",
3586  socketName, strerror(errno));
3587  return SCARD_E_NO_SERVICE;
3588  }
3589 
3590  return SCARD_S_SUCCESS;
3591 }
3592 
3593 static void SCardInvalidateHandles(void)
3594 {
3595  /* invalid all handles */
3596  (void)SCardLockThread();
3597 
3598  while (list_size(&contextMapList) != 0)
3599  {
3600  SCONTEXTMAP * currentContextMap;
3601 
3602  currentContextMap = list_get_at(&contextMapList, 0);
3603  if (currentContextMap != NULL)
3604  (void)SCardCleanContext(currentContextMap);
3605  else
3606  Log1(PCSC_LOG_CRITICAL, "list_get_at returned NULL");
3607  }
3608 
3609  (void)SCardUnlockThread();
3610 }
3611 
3612 static LONG getReaderStates(SCONTEXTMAP * currentContextMap)
3613 {
3614  int32_t dwClientID = currentContextMap->dwClientID;
3615  LONG rv;
3616 
3617  rv = MessageSendWithHeader(CMD_GET_READERS_STATE, dwClientID, 0, NULL);
3618  if (rv != SCARD_S_SUCCESS)
3619  return rv;
3620 
3621  /* Read a message from the server */
3622  rv = MessageReceive(&readerStates, sizeof(readerStates), dwClientID);
3623  if (rv != SCARD_S_SUCCESS)
3624  return rv;
3625 
3626  return SCARD_S_SUCCESS;
3627 }
3628 
used by SCardBeginTransaction()
Definition: winscard_msg.h:61
contained in SCARD_CONNECT Messages.
Definition: winscard_msg.h:120
list object
Definition: simclist.h:181
uint32_t cardAtrLength
ATR length.
Definition: eventhandler.h:35
static SCONTEXTMAP * SCardGetContext(SCARDCONTEXT)
Get the index from the Application Context vector _psContextMap for the passed context.
wait for a reader state change
Definition: winscard_msg.h:73
contained in SCARD_CANCEL Messages.
Definition: winscard_msg.h:186
contained in SCARD_TRANSMIT Messages.
Definition: winscard_msg.h:208
#define SCARD_STATE_UNAVAILABLE
Status unavailable.
Definition: pcsclite.h:180
PCSC_API LONG SCardListReaders(SCARDCONTEXT hContext, LPCSTR mszGroups, LPSTR mszReaders, LPDWORD pcchReaders)
Returns a list of currently available readers on the system.
contained in SCARD_END_TRANSACTION Messages.
Definition: winscard_msg.h:174
#define SCARD_E_READER_UNAVAILABLE
The specified reader is not currently available for use.
Definition: pcsclite.h:103
#define PCSCLITE_SHARING_NO_CONTEXT
No application is using the reader.
Definition: eventhandler.h:51
INTERNAL int ClientCloseSession(uint32_t dwClientID)
Closes the socket used by the client to communicate with the server.
Definition: winscard_msg.c:145
#define MAX_BUFFER_SIZE
Maximum Tx/Rx Buffer for short APDU.
Definition: pcsclite.h:208
PCSC_API LONG SCardListReaderGroups(SCARDCONTEXT hContext, LPSTR mszGroups, LPDWORD pcchGroups)
Returns a list of currently available reader groups on the system.
#define SCARD_STATE_EMPTY
Card removed.
Definition: pcsclite.h:181
get the client/server protocol version
Definition: winscard_msg.h:71
static SCONTEXTMAP * SCardGetContextTH(SCARDCONTEXT)
Get the address from the Application Context list _psContextMap for the passed context.
#define SCARD_STATE_IGNORE
Ignore this reader.
Definition: pcsclite.h:177
#define SCARD_UNKNOWN
Unknown state.
Definition: pcsclite.h:168
PCSC_API char * pcsc_stringify_error(const LONG pcscError)
Returns a human readable text for the given PC/SC error code.
Definition: error.c:56
static short isExecuted
Make sure the initialization code is executed only once.
used by SCardEstablishContext()
Definition: winscard_msg.h:55
INTERNAL LONG MessageSendWithHeader(uint32_t command, uint32_t dwClientID, uint64_t size, void *data_void)
Wrapper for the MessageSend() function.
Definition: winscard_msg.c:288
int32_t minor
IPC minor PROTOCOL_VERSION_MINOR.
Definition: winscard_msg.h:36
#define SCARD_F_COMM_ERROR
An internal communications error has been detected.
Definition: pcsclite.h:99
used by SCardEndTransaction()
Definition: winscard_msg.h:62
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:173
unsigned long cbPciLength
Protocol Control Inf Length.
Definition: pcsclite.h:61
int32_t readerSharing
PCSCLITE_SHARING_* sharing status.
Definition: eventhandler.h:32
#define SCARD_E_INVALID_PARAMETER
One or more of the supplied parameters could not be properly interpreted.
Definition: pcsclite.h:84
#define SCARD_STATE_CHANGED
State has changed.
Definition: pcsclite.h:178
This handles abstract system level calls.
static LONG SCardRemoveContext(SCARDCONTEXT)
Removes an Application Context from a control vector.
#define SCARD_E_NO_SERVICE
The Smart card resource manager is not running.
Definition: pcsclite.h:109
uint32_t eventCounter
number of card events
Definition: eventhandler.h:30
#define SCARD_E_NO_READERS_AVAILABLE
Cannot find a smart card reader.
Definition: pcsclite.h:127
static LONG SCardUnlockThread(void)
Unlocks a mutex so another thread may use the client.
used by SCardConnect()
Definition: winscard_msg.h:58
#define PROTOCOL_VERSION_MAJOR
Major version of the current message protocol.
Definition: winscard_msg.h:26
#define SCARD_PROTOCOL_T1
T=1 active protocol.
Definition: pcsclite.h:153
contained in SCARD_DISCONNECT Messages.
Definition: winscard_msg.h:151
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...
#define SCARD_E_INVALID_HANDLE
The supplied handle was invalid.
Definition: pcsclite.h:83
PCSC_API LONG SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr, LPDWORD pcbAttrLen)
Get an attribute from the IFD Handler (reader driver).
Definition: winscard.c:1349
#define SCARD_PRESENT
Card is present.
Definition: pcsclite.h:170
Information contained in SCARD_RELEASE_CONTEXT Messages.
Definition: winscard_msg.h:109
PCSC_API LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
Terminates a connection made through SCardConnect().
Definition: winscard.c:799
PCSC_API LONG SCardCancel(SCARDCONTEXT hContext)
Cancels all pending blocking requests on the SCardGetStatusChange() function.
int SYS_USleep(int)
Makes the current process sleep for some microseconds.
Definition: sys_unix.c:62
contained in SCARD_BEGIN_TRANSACTION Messages.
Definition: winscard_msg.h:163
const SCARD_IO_REQUEST g_rgSCardRawPci
Protocol Control Information for raw access.
Definition: libpcscspy.c:722
#define PCSCLITE_SHARING_EXCLUSIVE_CONTEXT
Reader used in exclusive mode.
Definition: eventhandler.h:53
PCSC_API LONG SCardIsValidContext(SCARDCONTEXT hContext)
Check if a SCARDCONTEXT is valid.
static LONG SCardEstablishContextTH(DWORD, LPCVOID, LPCVOID, LPSCARDCONTEXT)
Creates a communication context to the PC/SC Resource Manager.
#define INFINITE
Infinite timeout.
Definition: pcsclite.h:190
#define SCARD_STATE_UNKNOWN
Reader unknown.
Definition: pcsclite.h:179
Represents the an Application Context on the Client side.
Information contained in SCARD_ESTABLISH_CONTEXT Messages.
Definition: winscard_msg.h:97
get the readers state
Definition: winscard_msg.h:72
#define PCSCLITE_LOCK_POLL_RATE
Lock polling rate.
Definition: pcscd.h:35
#define SCARD_AUTOALLOCATE
see SCardFreeMemory()
Definition: pcsclite.h:145
Information transmitted in CMD_VERSION Messages.
Definition: winscard_msg.h:33
INTERNAL LONG MessageReceive(void *buffer_void, uint64_t buffer_size, int32_t filedes)
Called by the Client to get the reponse from the server or vice-versa.
Definition: winscard_msg.c:422
used by SCardReleaseContext()
Definition: winscard_msg.h:56
LONG SCARDCONTEXT
hContext returned by SCardEstablishContext()
Definition: pcsclite.h:31
#define SCARD_E_INVALID_VALUE
One or more of the supplied parameters values could not be properly interpreted.
Definition: pcsclite.h:97
contained in SCARD_STATUS Messages.
Definition: winscard_msg.h:197
contained in SCARD_RECONNECT Messages.
Definition: winscard_msg.h:136
unsigned long dwProtocol
Protocol identifier.
Definition: pcsclite.h:60
uint32_t timeOut
timeout in ms
Definition: winscard_msg.h:88
#define PCSCLITE_MAX_READERS_CONTEXTS
Maximum readers context (a slot is count as a reader)
Definition: pcsclite.h:195
contained in SCARD_GET_ATTRIB and Messages.
Definition: winscard_msg.h:240
prototypes of strlcpy()/strlcat() imported from OpenBSD
#define SCARD_STATE_PRESENT
Card inserted.
Definition: pcsclite.h:182
This defines some structures and #defines to be used over the transport layer.
Information contained in CMD_WAIT_READER_STATE_CHANGE Messages.
Definition: winscard_msg.h:86
DWORD dwClientID
Client Connection ID.
#define SCARD_PROTOCOL_T0
T=0 active protocol.
Definition: pcsclite.h:152
#define SCARD_STATE_ATRMATCH
ATR matches card.
Definition: pcsclite.h:183
used by SCardReconnect()
Definition: winscard_msg.h:59
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:497
long int time_sub(struct timeval *a, struct timeval *b)
return the difference (as long int) in µs between 2 struct timeval r = a - b
Definition: utils.c:106
#define MAX_BUFFER_SIZE_EXTENDED
enhanced (64K + APDU + Lc + Le + SW) Tx/Rx Buffer
Definition: pcsclite.h:209
static READER_STATE readerStates[PCSCLITE_MAX_READERS_CONTEXTS]
Area used to read status information about the readers.
used by SCardTransmit()
Definition: winscard_msg.h:63
#define PCSCLITE_STATUS_POLL_RATE
Status polling rate.
Definition: pcscd.h:34
Represents an Application Context Channel.
This handles card insertion/removal events, updates ATR, protocol, and status information.
SCARDCONTEXT hContext
Application Context ID.
#define SCARD_PROTOCOL_ANY
IFD determines prot.
Definition: pcsclite.h:157
char cancellable
We are in a cancellable call.
stop waiting for a reader state change
Definition: winscard_msg.h:74
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:209
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:1227
PCSC_API LONG SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr, DWORD cbAttrLen)
Set an attribute of the IFD Handler.
Definition: winscard.c:1425
#define SCARD_STATE_EXCLUSIVE
Exclusive Mode.
Definition: pcsclite.h:184
#define SCARD_SWALLOWED
Card not powered.
Definition: pcsclite.h:171
static LONG SCardAddContext(SCARDCONTEXT, DWORD)
Functions for managing instances of SCardEstablishContext() These functions keep track of Context han...
UCHAR cardAtr[MAX_ATR_SIZE]
ATR.
Definition: eventhandler.h:34
LONG SCARDHANDLE
hCard returned by SCardConnect()
Definition: pcsclite.h:34
static LONG SCardLockThread(void)
Locks a mutex so another thread must wait to use this function.
LONG SCardCheckDaemonAvailability(void)
Checks if the server is running.
INTERNAL int ClientSetupSession(uint32_t *pdwClientID)
Prepares a communication channel for the client to talk to the server.
Definition: winscard_msg.c:90
#define PROTOCOL_VERSION_MINOR
Minor version of the current message protocol.
Definition: winscard_msg.h:28
pthread_mutex_t * mMutex
Mutex for this context.
PCSC_API LONG SCardBeginTransaction(SCARDHANDLE hCard)
Establishes a temporary exclusive access mode for doing a serie of commands in a transaction.
Definition: winscard.c:1049
used by SCardControl()
Definition: winscard_msg.h:64
This keeps a list of defines for pcsc-lite.
#define SCARD_PROTOCOL_RAW
Raw active protocol.
Definition: pcsclite.h:154
#define SCARD_STATE_INUSE
Shared Mode.
Definition: pcsclite.h:185
Protocol Control Information (PCI)
Definition: pcsclite.h:58
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:1290
#define SCARD_E_SHARING_VIOLATION
The smart card cannot be accessed because of other connections outstanding.
Definition: pcsclite.h:91
#define SCARD_ABSENT
Card is absent.
Definition: pcsclite.h:169
uint32_t cardProtocol
SCARD_PROTOCOL_* value.
Definition: eventhandler.h:36
Define an exported public reader state structure so each application gets instant notification of cha...
Definition: eventhandler.h:27
used by SCardSetAttrib()
Definition: winscard_msg.h:70
INTERNAL LONG MessageSend(void *buffer_void, uint64_t buffer_size, int32_t filedes)
Sends a menssage from client to server or vice-versa.
Definition: winscard_msg.c:324
used by SCardDisconnect()
Definition: winscard_msg.h:60
#define SCARD_E_NO_MEMORY
Not enough memory available to complete this command.
Definition: pcsclite.h:86
contained in SCARD_CONTROL Messages.
Definition: winscard_msg.h:225
This keeps track of a list of currently available reader structures.
used by SCardGetAttrib()
Definition: winscard_msg.h:69
static pthread_mutex_t clientMutex
Ensure that some functions be accessed in thread-safe mode.
uint32_t readerState
SCARD_* bit field.
Definition: eventhandler.h:31
used by SCardCancel()
Definition: winscard_msg.h:67
#define SCARD_E_INSUFFICIENT_BUFFER
The data buffer to receive returned data is too small for the returned data.
Definition: pcsclite.h:88
#define PCSCLITE_SHARING_LAST_CONTEXT
One application is using the reader.
Definition: eventhandler.h:49
int32_t major
IPC major PROTOCOL_VERSION_MAJOR.
Definition: winscard_msg.h:35
PCSC_API LONG SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
Ends a previously begun transaction.
Definition: winscard.c:1091
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:1475
const SCARD_IO_REQUEST g_rgSCardT1Pci
Protocol Control Information for T=1.
Definition: libpcscspy.c:721
#define SCARD_E_UNKNOWN_READER
The specified reader name is not recognized.
Definition: pcsclite.h:89
used by SCardStatus()
Definition: winscard_msg.h:65
#define SCARD_S_SUCCESS
error codes from http://msdn.microsoft.com/en-us/library/aa924526.aspx
Definition: pcsclite.h:80
const SCARD_IO_REQUEST g_rgSCardT0Pci
Protocol Control Information for T=0.
Definition: libpcscspy.c:720
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:198
INTERNAL LONG MessageReceiveTimeout(uint32_t command, void *buffer_void, uint64_t buffer_size, int32_t filedes, long timeOut)
Called by the Client to get the reponse from the server or vice-versa.
Definition: winscard_msg.c:166
This handles debugging.
#define SCARD_E_TIMEOUT
The user-specified timeout value has expired.
Definition: pcsclite.h:90
#define SCARD_STATE_UNAWARE
App wants status.
Definition: pcsclite.h:176
#define SCARD_STATE_MUTE
Unresponsive card.
Definition: pcsclite.h:186