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