pcsc-lite  1.8.10
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 6734 2013-08-23 08:19:08Z 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 LONG SCardGetSetAttrib(SCARDHANDLE hCard, int command, DWORD dwAttrId,
357  LPBYTE pbAttr, LPDWORD pcbAttrLen);
358 
359 static LONG getReaderStates(SCONTEXTMAP * currentContextMap);
360 
361 /*
362  * Thread safety functions
363  */
370 inline static LONG SCardLockThread(void)
371 {
372  return pthread_mutex_lock(&clientMutex);
373 }
374 
380 inline static LONG SCardUnlockThread(void)
381 {
382  return pthread_mutex_unlock(&clientMutex);
383 }
384 
385 static LONG SCardEstablishContextTH(DWORD, LPCVOID, LPCVOID,
386  /*@out@*/ LPSCARDCONTEXT);
387 
421 LONG SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1,
422  LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
423 {
424  LONG rv;
425 
426  API_TRACE_IN("%ld, %p, %p", dwScope, pvReserved1, pvReserved2)
427  PROFILE_START
428 
429  /* Check if the server is running */
431  if (SCARD_E_INVALID_HANDLE == rv)
432  /* we reconnected to a daemon or we got called from a forked child */
434 
435  if (rv != SCARD_S_SUCCESS)
436  goto end;
437 
438  (void)SCardLockThread();
439  rv = SCardEstablishContextTH(dwScope, pvReserved1,
440  pvReserved2, phContext);
441  (void)SCardUnlockThread();
442 
443 end:
444  PROFILE_END(rv)
445  API_TRACE_OUT("%ld", *phContext)
446 
447  return rv;
448 }
449 
476 static LONG SCardEstablishContextTH(DWORD dwScope,
477  /*@unused@*/ LPCVOID pvReserved1,
478  /*@unused@*/ LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
479 {
480  LONG rv;
481  struct establish_struct scEstablishStruct;
482  uint32_t dwClientID = 0;
483 
484  (void)pvReserved1;
485  (void)pvReserved2;
486  if (phContext == NULL)
488  else
489  *phContext = 0;
490 
491  /*
492  * Do this only once:
493  * - Initialize context list.
494  */
495  if (isExecuted == 0)
496  {
497  int lrv;
498 
499  /* NOTE: The list will never be freed (No API call exists to
500  * "close all contexts".
501  * Applications which load and unload the library will leak
502  * the list's internal structures. */
503  lrv = list_init(&contextMapList);
504  if (lrv < 0)
505  {
506  Log2(PCSC_LOG_CRITICAL, "list_init failed with return value: %d",
507  lrv);
508  return SCARD_E_NO_MEMORY;
509  }
510 
511  lrv = list_attributes_seeker(&contextMapList,
512  SCONTEXTMAP_seeker);
513  if (lrv <0)
514  {
515  Log2(PCSC_LOG_CRITICAL,
516  "list_attributes_seeker failed with return value: %d", lrv);
517  list_destroy(&contextMapList);
518  return SCARD_E_NO_MEMORY;
519  }
520 
521  if (getenv("PCSCLITE_NO_BLOCKING"))
522  {
523  Log1(PCSC_LOG_INFO, "Disable shared blocking");
524  sharing_shall_block = FALSE;
525  }
526 
527  isExecuted = 1;
528  }
529 
530 
531  /* Establishes a connection to the server */
532  if (ClientSetupSession(&dwClientID) != 0)
533  {
534  return SCARD_E_NO_SERVICE;
535  }
536 
537  { /* exchange client/server protocol versions */
538  struct version_struct veStr;
539 
542  veStr.rv = SCARD_S_SUCCESS;
543 
544  rv = MessageSendWithHeader(CMD_VERSION, dwClientID, sizeof(veStr),
545  &veStr);
546  if (rv != SCARD_S_SUCCESS)
547  return rv;
548 
549  /* Read a message from the server */
550  rv = MessageReceive(&veStr, sizeof(veStr), dwClientID);
551  if (rv != SCARD_S_SUCCESS)
552  {
553  Log1(PCSC_LOG_CRITICAL,
554  "Your pcscd is too old and does not support CMD_VERSION");
555  return SCARD_F_COMM_ERROR;
556  }
557 
558  Log3(PCSC_LOG_INFO, "Server is protocol version %d:%d",
559  veStr.major, veStr.minor);
560 
561  if (veStr.rv != SCARD_S_SUCCESS)
562  return veStr.rv;
563  }
564 
565 again:
566  /*
567  * Try to establish an Application Context with the server
568  */
569  scEstablishStruct.dwScope = dwScope;
570  scEstablishStruct.hContext = 0;
571  scEstablishStruct.rv = SCARD_S_SUCCESS;
572 
574  sizeof(scEstablishStruct), (void *) &scEstablishStruct);
575 
576  if (rv != SCARD_S_SUCCESS)
577  return rv;
578 
579  /*
580  * Read the response from the server
581  */
582  rv = MessageReceive(&scEstablishStruct, sizeof(scEstablishStruct),
583  dwClientID);
584 
585  if (rv != SCARD_S_SUCCESS)
586  return rv;
587 
588  if (scEstablishStruct.rv != SCARD_S_SUCCESS)
589  return scEstablishStruct.rv;
590 
591  /* check we do not reuse an existing hContext */
592  if (NULL != SCardGetContextTH(scEstablishStruct.hContext))
593  /* we do not need to release the allocated context since
594  * SCardReleaseContext() does nothing on the server side */
595  goto again;
596 
597  *phContext = scEstablishStruct.hContext;
598 
599  /*
600  * Allocate the new hContext - if allocator full return an error
601  */
602  rv = SCardAddContext(*phContext, dwClientID);
603 
604  return rv;
605 }
606 
629 {
630  LONG rv;
631  struct release_struct scReleaseStruct;
632  SCONTEXTMAP * currentContextMap;
633 
634  API_TRACE_IN("%ld", hContext)
635  PROFILE_START
636 
637  /*
638  * Make sure this context has been opened
639  * and get currentContextMap
640  */
641  currentContextMap = SCardGetContext(hContext);
642  if (NULL == currentContextMap)
643  {
645  goto error;
646  }
647 
648  (void)pthread_mutex_lock(&currentContextMap->mMutex);
649 
650  /* check the context is still opened */
651  currentContextMap = SCardGetContext(hContext);
652  if (NULL == currentContextMap)
653  /* the hContext context is now invalid
654  * -> another thread may have called SCardReleaseContext
655  * so the mMutex has been unlocked */
656  {
658  goto error;
659  }
660 
661  scReleaseStruct.hContext = hContext;
662  scReleaseStruct.rv = SCARD_S_SUCCESS;
663 
665  currentContextMap->dwClientID,
666  sizeof(scReleaseStruct), (void *) &scReleaseStruct);
667 
668  if (rv != SCARD_S_SUCCESS)
669  goto end;
670 
671  /*
672  * Read a message from the server
673  */
674  rv = MessageReceive(&scReleaseStruct, sizeof(scReleaseStruct),
675  currentContextMap->dwClientID);
676 
677  if (rv != SCARD_S_SUCCESS)
678  goto end;
679 
680  rv = scReleaseStruct.rv;
681 end:
682  (void)pthread_mutex_unlock(&currentContextMap->mMutex);
683 
684  /*
685  * Remove the local context from the stack
686  */
687  (void)SCardLockThread();
688  (void)SCardRemoveContext(hContext);
689  (void)SCardUnlockThread();
690 
691 error:
692  PROFILE_END(rv)
693  API_TRACE_OUT("")
694 
695  return rv;
696 }
697 
754 LONG SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader,
755  DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard,
756  LPDWORD pdwActiveProtocol)
757 {
758  LONG rv;
759  struct connect_struct scConnectStruct;
760  SCONTEXTMAP * currentContextMap;
761 
762  PROFILE_START
763  API_TRACE_IN("%ld %s %ld %ld", hContext, szReader, dwShareMode, dwPreferredProtocols)
764 
765  /*
766  * Check for NULL parameters
767  */
768  if (phCard == NULL || pdwActiveProtocol == NULL)
770  else
771  *phCard = 0;
772 
773  if (szReader == NULL)
774  return SCARD_E_UNKNOWN_READER;
775 
776  /*
777  * Check for uninitialized strings
778  */
779  if (strlen(szReader) > MAX_READERNAME)
780  return SCARD_E_INVALID_VALUE;
781 
782  /*
783  * Make sure this context has been opened
784  */
785  currentContextMap = SCardGetContext(hContext);
786  if (NULL == currentContextMap)
787  return SCARD_E_INVALID_HANDLE;
788 
789  (void)pthread_mutex_lock(&currentContextMap->mMutex);
790 
791  /* check the context is still opened */
792  currentContextMap = SCardGetContext(hContext);
793  if (NULL == currentContextMap)
794  /* the hContext context is now invalid
795  * -> another thread may have called SCardReleaseContext
796  * so the mMutex has been unlocked */
797  return SCARD_E_INVALID_HANDLE;
798 
799  strlcpy(scConnectStruct.szReader, szReader, sizeof scConnectStruct.szReader);
800 
801  scConnectStruct.hContext = hContext;
802  scConnectStruct.dwShareMode = dwShareMode;
803  scConnectStruct.dwPreferredProtocols = dwPreferredProtocols;
804  scConnectStruct.hCard = 0;
805  scConnectStruct.dwActiveProtocol = 0;
806  scConnectStruct.rv = SCARD_S_SUCCESS;
807 
808  rv = MessageSendWithHeader(SCARD_CONNECT, currentContextMap->dwClientID,
809  sizeof(scConnectStruct), (void *) &scConnectStruct);
810 
811  if (rv != SCARD_S_SUCCESS)
812  goto end;
813 
814  /*
815  * Read a message from the server
816  */
817  rv = MessageReceive(&scConnectStruct, sizeof(scConnectStruct),
818  currentContextMap->dwClientID);
819 
820  if (rv != SCARD_S_SUCCESS)
821  goto end;
822 
823  *phCard = scConnectStruct.hCard;
824  *pdwActiveProtocol = scConnectStruct.dwActiveProtocol;
825 
826  if (scConnectStruct.rv == SCARD_S_SUCCESS)
827  {
828  /*
829  * Keep track of the handle locally
830  */
831  rv = SCardAddHandle(*phCard, currentContextMap, szReader);
832  }
833  else
834  rv = scConnectStruct.rv;
835 
836 end:
837  (void)pthread_mutex_unlock(&currentContextMap->mMutex);
838 
839  PROFILE_END(rv)
840  API_TRACE_OUT("%d", *pdwActiveProtocol)
841 
842  return rv;
843 }
844 
918 LONG SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode,
919  DWORD dwPreferredProtocols, DWORD dwInitialization,
920  LPDWORD pdwActiveProtocol)
921 {
922  LONG rv;
923  struct reconnect_struct scReconnectStruct;
924  SCONTEXTMAP * currentContextMap;
925  CHANNEL_MAP * pChannelMap;
926 
927  PROFILE_START
928 
929  if (pdwActiveProtocol == NULL)
931 
932  /*
933  * Make sure this handle has been opened
934  */
935  rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
936  &pChannelMap);
937  if (rv == -1)
938  return SCARD_E_INVALID_HANDLE;
939 
940  /* Retry loop for blocking behaviour */
941 retry:
942 
943  (void)pthread_mutex_lock(&currentContextMap->mMutex);
944 
945  /* check the handle is still valid */
946  rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
947  &pChannelMap);
948  if (rv == -1)
949  {
950  /* the hCard handle is now invalid
951  * -> another thread may have called SCardReleaseContext
952  * so the mMutex has been unlocked (and is now invalid)
953  * -> another thread may have called SCardDisconnect
954  * so the mMutex is STILL locked
955  * since we don't know just unlock the mutex */
956  (void)pthread_mutex_unlock(&currentContextMap->mMutex);
957  return SCARD_E_INVALID_HANDLE;
958  }
959 
960  scReconnectStruct.hCard = hCard;
961  scReconnectStruct.dwShareMode = dwShareMode;
962  scReconnectStruct.dwPreferredProtocols = dwPreferredProtocols;
963  scReconnectStruct.dwInitialization = dwInitialization;
964  scReconnectStruct.dwActiveProtocol = *pdwActiveProtocol;
965  scReconnectStruct.rv = SCARD_S_SUCCESS;
966 
967  rv = MessageSendWithHeader(SCARD_RECONNECT, currentContextMap->dwClientID,
968  sizeof(scReconnectStruct), (void *) &scReconnectStruct);
969 
970  if (rv != SCARD_S_SUCCESS)
971  goto end;
972 
973  /*
974  * Read a message from the server
975  */
976  rv = MessageReceive(&scReconnectStruct, sizeof(scReconnectStruct),
977  currentContextMap->dwClientID);
978 
979  if (rv != SCARD_S_SUCCESS)
980  goto end;
981 
982  rv = scReconnectStruct.rv;
983 
984  if (sharing_shall_block && (SCARD_E_SHARING_VIOLATION == rv))
985  {
986  (void)pthread_mutex_unlock(&currentContextMap->mMutex);
988  goto retry;
989  }
990 
991  *pdwActiveProtocol = scReconnectStruct.dwActiveProtocol;
992 
993 end:
994  (void)pthread_mutex_unlock(&currentContextMap->mMutex);
995 
996  PROFILE_END(rv)
997 
998  return rv;
999 }
1000 
1032 LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
1033 {
1034  LONG rv;
1035  struct disconnect_struct scDisconnectStruct;
1036  SCONTEXTMAP * currentContextMap;
1037  CHANNEL_MAP * pChannelMap;
1038 
1039  PROFILE_START
1040  API_TRACE_IN("%ld %ld", hCard, dwDisposition)
1041 
1042  /*
1043  * Make sure this handle has been opened
1044  */
1045  rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
1046  &pChannelMap);
1047  if (rv == -1)
1048  {
1050  goto error;
1051  }
1052 
1053  (void)pthread_mutex_lock(&currentContextMap->mMutex);
1054 
1055  /* check the handle is still valid */
1056  rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
1057  &pChannelMap);
1058  if (rv == -1)
1059  /* the hCard handle is now invalid
1060  * -> another thread may have called SCardReleaseContext
1061  * so the mMutex has been unlocked (and is now invalid)
1062  * -> another thread may have called SCardDisconnect
1063  * so the mMutex is STILL locked
1064  * since we don't know just unlock the mutex */
1065  {
1066  (void)pthread_mutex_unlock(&currentContextMap->mMutex);
1068  goto error;
1069  }
1070 
1071  scDisconnectStruct.hCard = hCard;
1072  scDisconnectStruct.dwDisposition = dwDisposition;
1073  scDisconnectStruct.rv = SCARD_S_SUCCESS;
1074 
1075  rv = MessageSendWithHeader(SCARD_DISCONNECT, currentContextMap->dwClientID,
1076  sizeof(scDisconnectStruct), (void *) &scDisconnectStruct);
1077 
1078  if (rv != SCARD_S_SUCCESS)
1079  goto end;
1080 
1081  /*
1082  * Read a message from the server
1083  */
1084  rv = MessageReceive(&scDisconnectStruct, sizeof(scDisconnectStruct),
1085  currentContextMap->dwClientID);
1086 
1087  if (rv != SCARD_S_SUCCESS)
1088  goto end;
1089 
1090  if (SCARD_S_SUCCESS == scDisconnectStruct.rv)
1091  (void)SCardRemoveHandle(hCard);
1092  rv = scDisconnectStruct.rv;
1093 
1094 end:
1095  (void)pthread_mutex_unlock(&currentContextMap->mMutex);
1096 
1097 error:
1098  PROFILE_END(rv)
1099  API_TRACE_OUT("")
1100 
1101  return rv;
1102 }
1103 
1140 {
1141 
1142  LONG rv;
1143  struct begin_struct scBeginStruct;
1144  SCONTEXTMAP * currentContextMap;
1145  CHANNEL_MAP * pChannelMap;
1146 
1147  PROFILE_START
1148 
1149  /*
1150  * Make sure this handle has been opened
1151  */
1152  rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
1153  &pChannelMap);
1154  if (rv == -1)
1155  return SCARD_E_INVALID_HANDLE;
1156 
1157  /*
1158  * Query the server every so often until the sharing violation ends
1159  * and then hold the lock for yourself.
1160  */
1161 
1162  for(;;)
1163  {
1164  (void)pthread_mutex_lock(&currentContextMap->mMutex);
1165 
1166  /* check the handle is still valid */
1167  rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
1168  &pChannelMap);
1169  if (rv == -1)
1170  {
1171  /* the hCard handle is now invalid
1172  * -> another thread may have called SCardReleaseContext
1173  * so the mMutex has been unlocked (and is now invalid)
1174  * -> another thread may have called SCardDisconnect
1175  * so the mMutex is STILL locked
1176  * since we don't know just unlock the mutex */
1177  (void)pthread_mutex_unlock(&currentContextMap->mMutex);
1178  return SCARD_E_INVALID_HANDLE;
1179  }
1180 
1181  scBeginStruct.hCard = hCard;
1182  scBeginStruct.rv = SCARD_S_SUCCESS;
1183 
1185  currentContextMap->dwClientID,
1186  sizeof(scBeginStruct), (void *) &scBeginStruct);
1187 
1188  if (rv != SCARD_S_SUCCESS)
1189  break;
1190 
1191  /*
1192  * Read a message from the server
1193  */
1194  rv = MessageReceive(&scBeginStruct, sizeof(scBeginStruct),
1195  currentContextMap->dwClientID);
1196 
1197  if (rv != SCARD_S_SUCCESS)
1198  break;
1199 
1200  rv = scBeginStruct.rv;
1201 
1202  if (SCARD_E_SHARING_VIOLATION != rv)
1203  break;
1204 
1205  (void)pthread_mutex_unlock(&currentContextMap->mMutex);
1207  }
1208 
1209  (void)pthread_mutex_unlock(&currentContextMap->mMutex);
1210 
1211  PROFILE_END(rv)
1212 
1213  return rv;
1214 }
1215 
1256 LONG SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
1257 {
1258  LONG rv;
1259  struct end_struct scEndStruct;
1260  int randnum;
1261  SCONTEXTMAP * currentContextMap;
1262  CHANNEL_MAP * pChannelMap;
1263 
1264  PROFILE_START
1265 
1266  /*
1267  * Make sure this handle has been opened
1268  */
1269  rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
1270  &pChannelMap);
1271  if (rv == -1)
1272  return SCARD_E_INVALID_HANDLE;
1273 
1274  (void)pthread_mutex_lock(&currentContextMap->mMutex);
1275 
1276  /* check the handle is still valid */
1277  rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
1278  &pChannelMap);
1279  if (rv == -1)
1280  {
1281  /* the hCard handle is now invalid
1282  * -> another thread may have called SCardReleaseContext
1283  * so the mMutex has been unlocked (and is now invalid)
1284  * -> another thread may have called SCardDisconnect
1285  * so the mMutex is STILL locked
1286  * since we don't know just unlock the mutex */
1287  (void)pthread_mutex_unlock(&currentContextMap->mMutex);
1288  return SCARD_E_INVALID_HANDLE;
1289  }
1290 
1291  scEndStruct.hCard = hCard;
1292  scEndStruct.dwDisposition = dwDisposition;
1293  scEndStruct.rv = SCARD_S_SUCCESS;
1294 
1296  currentContextMap->dwClientID,
1297  sizeof(scEndStruct), (void *) &scEndStruct);
1298 
1299  if (rv != SCARD_S_SUCCESS)
1300  goto end;
1301 
1302  /*
1303  * Read a message from the server
1304  */
1305  rv = MessageReceive(&scEndStruct, sizeof(scEndStruct),
1306  currentContextMap->dwClientID);
1307 
1308  if (rv != SCARD_S_SUCCESS)
1309  goto end;
1310 
1311  /*
1312  * This helps prevent starvation
1313  */
1314  randnum = SYS_RandomInt(1000, 10000);
1315  (void)SYS_USleep(randnum);
1316  rv = scEndStruct.rv;
1317 
1318 end:
1319  (void)pthread_mutex_unlock(&currentContextMap->mMutex);
1320 
1321  PROFILE_END(rv)
1322 
1323  return rv;
1324 }
1325 
1421 LONG SCardStatus(SCARDHANDLE hCard, LPSTR mszReaderName,
1422  LPDWORD pcchReaderLen, LPDWORD pdwState,
1423  LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
1424 {
1425  DWORD dwReaderLen, dwAtrLen;
1426  LONG rv;
1427  int i;
1428  struct status_struct scStatusStruct;
1429  SCONTEXTMAP * currentContextMap;
1430  CHANNEL_MAP * pChannelMap;
1431  char *r;
1432  char *bufReader = NULL;
1433  LPBYTE bufAtr = NULL;
1434  DWORD dummy = 0;
1435 
1436  PROFILE_START
1437 
1438  /* default output values */
1439  if (pdwState)
1440  *pdwState = 0;
1441 
1442  if (pdwProtocol)
1443  *pdwProtocol = 0;
1444 
1445  /* Check for NULL parameters */
1446  if (pcchReaderLen == NULL)
1447  pcchReaderLen = &dummy;
1448 
1449  if (pcbAtrLen == NULL)
1450  pcbAtrLen = &dummy;
1451 
1452  /* length passed from caller */
1453  dwReaderLen = *pcchReaderLen;
1454  dwAtrLen = *pcbAtrLen;
1455 
1456  *pcchReaderLen = 0;
1457  *pcbAtrLen = 0;
1458 
1459  /*
1460  * Make sure this handle has been opened
1461  */
1462  rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
1463  &pChannelMap);
1464  if (rv == -1)
1465  return SCARD_E_INVALID_HANDLE;
1466 
1467  /* Retry loop for blocking behaviour */
1468 retry:
1469 
1470  (void)pthread_mutex_lock(&currentContextMap->mMutex);
1471 
1472  /* check the handle is still valid */
1473  rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
1474  &pChannelMap);
1475  if (rv == -1)
1476  {
1477  /* the hCard handle is now invalid
1478  * -> another thread may have called SCardReleaseContext
1479  * so the mMutex has been unlocked (and is now invalid)
1480  * -> another thread may have called SCardDisconnect
1481  * so the mMutex is STILL locked
1482  * since we don't know just unlock the mutex */
1483  (void)pthread_mutex_unlock(&currentContextMap->mMutex);
1484  return SCARD_E_INVALID_HANDLE;
1485  }
1486 
1487  /* synchronize reader states with daemon */
1488  rv = getReaderStates(currentContextMap);
1489  if (rv != SCARD_S_SUCCESS)
1490  goto end;
1491 
1492  r = pChannelMap->readerName;
1493  for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
1494  {
1495  /* by default r == NULL */
1496  if (r && strcmp(r, readerStates[i].readerName) == 0)
1497  break;
1498  }
1499 
1500  if (i == PCSCLITE_MAX_READERS_CONTEXTS)
1501  {
1503  goto end;
1504  }
1505 
1506  /* initialise the structure */
1507  memset(&scStatusStruct, 0, sizeof(scStatusStruct));
1508  scStatusStruct.hCard = hCard;
1509 
1510  rv = MessageSendWithHeader(SCARD_STATUS, currentContextMap->dwClientID,
1511  sizeof(scStatusStruct), (void *) &scStatusStruct);
1512 
1513  if (rv != SCARD_S_SUCCESS)
1514  goto end;
1515 
1516  /*
1517  * Read a message from the server
1518  */
1519  rv = MessageReceive(&scStatusStruct, sizeof(scStatusStruct),
1520  currentContextMap->dwClientID);
1521 
1522  if (rv != SCARD_S_SUCCESS)
1523  goto end;
1524 
1525  rv = scStatusStruct.rv;
1526 
1527  if (sharing_shall_block && (SCARD_E_SHARING_VIOLATION == rv))
1528  {
1529  (void)pthread_mutex_unlock(&currentContextMap->mMutex);
1531  goto retry;
1532  }
1533 
1534  if (rv != SCARD_S_SUCCESS && rv != SCARD_E_INSUFFICIENT_BUFFER)
1535  {
1536  /*
1537  * An event must have occurred
1538  */
1539  goto end;
1540  }
1541 
1542  /*
1543  * Now continue with the client side SCardStatus
1544  */
1545 
1546  *pcchReaderLen = strlen(pChannelMap->readerName) + 1;
1547  *pcbAtrLen = readerStates[i].cardAtrLength;
1548 
1549  if (pdwState)
1550  *pdwState = (readerStates[i].eventCounter << 16) + readerStates[i].readerState;
1551 
1552  if (pdwProtocol)
1553  *pdwProtocol = readerStates[i].cardProtocol;
1554 
1555  if (SCARD_AUTOALLOCATE == dwReaderLen)
1556  {
1557  dwReaderLen = *pcchReaderLen;
1558  if (NULL == mszReaderName)
1559  {
1561  goto end;
1562  }
1563  bufReader = malloc(dwReaderLen);
1564  if (NULL == bufReader)
1565  {
1566  rv = SCARD_E_NO_MEMORY;
1567  goto end;
1568  }
1569  *(char **)mszReaderName = bufReader;
1570  }
1571  else
1572  bufReader = mszReaderName;
1573 
1574  /* return SCARD_E_INSUFFICIENT_BUFFER only if buffer pointer is non NULL */
1575  if (bufReader)
1576  {
1577  if (*pcchReaderLen > dwReaderLen)
1579 
1580  strncpy(bufReader, pChannelMap->readerName, dwReaderLen);
1581  }
1582 
1583  if (SCARD_AUTOALLOCATE == dwAtrLen)
1584  {
1585  dwAtrLen = *pcbAtrLen;
1586  if (NULL == pbAtr)
1587  {
1589  goto end;
1590  }
1591  bufAtr = malloc(dwAtrLen);
1592  if (NULL == bufAtr)
1593  {
1594  rv = SCARD_E_NO_MEMORY;
1595  goto end;
1596  }
1597  *(LPBYTE *)pbAtr = bufAtr;
1598  }
1599  else
1600  bufAtr = pbAtr;
1601 
1602  if (bufAtr)
1603  {
1604  if (*pcbAtrLen > dwAtrLen)
1606 
1607  memcpy(bufAtr, readerStates[i].cardAtr, min(*pcbAtrLen, dwAtrLen));
1608  }
1609 
1610 end:
1611  (void)pthread_mutex_unlock(&currentContextMap->mMutex);
1612 
1613  PROFILE_END(rv)
1614 
1615  return rv;
1616 }
1617 
1711 LONG SCardGetStatusChange(SCARDCONTEXT hContext, DWORD dwTimeout,
1712  SCARD_READERSTATE *rgReaderStates, DWORD cReaders)
1713 {
1714  SCARD_READERSTATE *currReader;
1715  READER_STATE *rContext;
1716  long dwTime;
1717  DWORD dwBreakFlag = 0;
1718  unsigned int j;
1719  SCONTEXTMAP * currentContextMap;
1720  int currentReaderCount = 0;
1721  LONG rv = SCARD_S_SUCCESS;
1722 
1723  PROFILE_START
1724  API_TRACE_IN("%ld %ld %d", hContext, dwTimeout, cReaders)
1725 #ifdef DO_TRACE
1726  for (j=0; j<cReaders; j++)
1727  {
1728  API_TRACE_IN("[%d] %s %lX %lX", j, rgReaderStates[j].szReader,
1729  rgReaderStates[j].dwCurrentState, rgReaderStates[j].dwEventState)
1730  }
1731 #endif
1732 
1733  if ((rgReaderStates == NULL && cReaders > 0)
1734  || (cReaders > PCSCLITE_MAX_READERS_CONTEXTS))
1735  {
1737  goto error;
1738  }
1739 
1740  /* Check the integrity of the reader states structures */
1741  for (j = 0; j < cReaders; j++)
1742  {
1743  if (rgReaderStates[j].szReader == NULL)
1744  return SCARD_E_INVALID_VALUE;
1745  }
1746 
1747  /* return if all readers are SCARD_STATE_IGNORE */
1748  if (cReaders > 0)
1749  {
1750  int nbNonIgnoredReaders = cReaders;
1751 
1752  for (j=0; j<cReaders; j++)
1753  if (rgReaderStates[j].dwCurrentState & SCARD_STATE_IGNORE)
1754  nbNonIgnoredReaders--;
1755 
1756  if (0 == nbNonIgnoredReaders)
1757  {
1758  rv = SCARD_S_SUCCESS;
1759  goto error;
1760  }
1761  }
1762  else
1763  {
1764  /* reader list is empty */
1765  rv = SCARD_S_SUCCESS;
1766  goto error;
1767  }
1768 
1769  /*
1770  * Make sure this context has been opened
1771  */
1772  currentContextMap = SCardGetContext(hContext);
1773  if (NULL == currentContextMap)
1774  {
1776  goto error;
1777  }
1778 
1779  (void)pthread_mutex_lock(&currentContextMap->mMutex);
1780 
1781  /* check the context is still opened */
1782  currentContextMap = SCardGetContext(hContext);
1783  if (NULL == currentContextMap)
1784  /* the hContext context is now invalid
1785  * -> another thread may have called SCardReleaseContext
1786  * so the mMutex has been unlocked */
1787  {
1789  goto error;
1790  }
1791 
1792  /* synchronize reader states with daemon */
1793  rv = getReaderStates(currentContextMap);
1794  if (rv != SCARD_S_SUCCESS)
1795  goto end;
1796 
1797  /* check all the readers are already known */
1798  for (j=0; j<cReaders; j++)
1799  {
1800  const char *readerName;
1801  int i;
1802 
1803  readerName = rgReaderStates[j].szReader;
1804  for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
1805  {
1806  if (strcmp(readerName, readerStates[i].readerName) == 0)
1807  break;
1808  }
1809 
1810  /* The requested reader name is not recognized */
1811  if (i == PCSCLITE_MAX_READERS_CONTEXTS)
1812  {
1813  /* PnP special reader? */
1814  if (strcasecmp(readerName, "\\\\?PnP?\\Notification") != 0)
1815  {
1817  goto end;
1818  }
1819  }
1820  }
1821 
1822  /* Clear the event state for all readers */
1823  for (j = 0; j < cReaders; j++)
1824  rgReaderStates[j].dwEventState = 0;
1825 
1826  /* Now is where we start our event checking loop */
1827  Log2(PCSC_LOG_DEBUG, "Event Loop Start, dwTimeout: %ld", dwTimeout);
1828 
1829  /* Get the initial reader count on the system */
1830  for (j=0; j < PCSCLITE_MAX_READERS_CONTEXTS; j++)
1831  if (readerStates[j].readerName[0] != '\0')
1832  currentReaderCount++;
1833 
1834  /* catch possible sign extension problems from 32 to 64-bits integers */
1835  if ((DWORD)-1 == dwTimeout)
1836  dwTimeout = INFINITE;
1837  if (INFINITE == dwTimeout)
1838  dwTime = 60*1000; /* "infinite" timeout */
1839  else
1840  dwTime = dwTimeout;
1841 
1842  j = 0;
1843  do
1844  {
1845  currReader = &rgReaderStates[j];
1846 
1847  /* Ignore for IGNORED readers */
1848  if (!(currReader->dwCurrentState & SCARD_STATE_IGNORE))
1849  {
1850  const char *readerName;
1851  int i;
1852 
1853  /* Looks for correct readernames */
1854  readerName = currReader->szReader;
1855  for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
1856  {
1857  if (strcmp(readerName, readerStates[i].readerName) == 0)
1858  break;
1859  }
1860 
1861  /* The requested reader name is not recognized */
1862  if (i == PCSCLITE_MAX_READERS_CONTEXTS)
1863  {
1864  /* PnP special reader? */
1865  if (strcasecmp(readerName, "\\\\?PnP?\\Notification") == 0)
1866  {
1867  int k, newReaderCount = 0;
1868 
1869  for (k=0; k < PCSCLITE_MAX_READERS_CONTEXTS; k++)
1870  if (readerStates[k].readerName[0] != '\0')
1871  newReaderCount++;
1872 
1873  if (newReaderCount != currentReaderCount)
1874  {
1875  Log1(PCSC_LOG_INFO, "Reader list changed");
1876  currentReaderCount = newReaderCount;
1877 
1878  currReader->dwEventState |= SCARD_STATE_CHANGED;
1879  dwBreakFlag = 1;
1880  }
1881  }
1882  else
1883  {
1884  currReader->dwEventState =
1886  if (!(currReader->dwCurrentState & SCARD_STATE_UNKNOWN))
1887  {
1888  currReader->dwEventState |= SCARD_STATE_CHANGED;
1889  /*
1890  * Spec says use SCARD_STATE_IGNORE but a removed USB
1891  * reader with eventState fed into currentState will
1892  * be ignored forever
1893  */
1894  dwBreakFlag = 1;
1895  }
1896  }
1897  }
1898  else
1899  {
1900  uint32_t readerState;
1901 
1902  /* The reader has come back after being away */
1903  if (currReader->dwCurrentState & SCARD_STATE_UNKNOWN)
1904  {
1905  currReader->dwEventState |= SCARD_STATE_CHANGED;
1906  currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
1907  Log0(PCSC_LOG_DEBUG);
1908  dwBreakFlag = 1;
1909  }
1910 
1911  /* Set the reader status structure */
1912  rContext = &readerStates[i];
1913 
1914  /* Now we check all the Reader States */
1915  readerState = rContext->readerState;
1916 
1917  /* only if current state has an non null event counter */
1918  if (currReader->dwCurrentState & 0xFFFF0000)
1919  {
1920  unsigned int currentCounter;
1921 
1922  currentCounter = (currReader->dwCurrentState >> 16) & 0xFFFF;
1923 
1924  /* has the event counter changed since the last call? */
1925  if (rContext->eventCounter != currentCounter)
1926  {
1927  currReader->dwEventState |= SCARD_STATE_CHANGED;
1928  Log0(PCSC_LOG_DEBUG);
1929  dwBreakFlag = 1;
1930  }
1931  }
1932 
1933  /* add an event counter in the upper word of dwEventState */
1934  currReader->dwEventState = ((currReader->dwEventState & 0xffff )
1935  | (rContext->eventCounter << 16));
1936 
1937  /* Check if the reader is in the correct state */
1938  if (readerState & SCARD_UNKNOWN)
1939  {
1940  /* reader is in bad state */
1941  currReader->dwEventState = SCARD_STATE_UNAVAILABLE;
1942  if (!(currReader->dwCurrentState & SCARD_STATE_UNAVAILABLE))
1943  {
1944  /* App thinks reader is in good state and it is not */
1945  currReader->dwEventState |= SCARD_STATE_CHANGED;
1946  Log0(PCSC_LOG_DEBUG);
1947  dwBreakFlag = 1;
1948  }
1949  }
1950  else
1951  {
1952  /* App thinks reader in bad state but it is not */
1953  if (currReader-> dwCurrentState & SCARD_STATE_UNAVAILABLE)
1954  {
1955  currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
1956  currReader->dwEventState |= SCARD_STATE_CHANGED;
1957  Log0(PCSC_LOG_DEBUG);
1958  dwBreakFlag = 1;
1959  }
1960  }
1961 
1962  /* Check for card presence in the reader */
1963  if (readerState & SCARD_PRESENT)
1964  {
1965  /* card present but not yet powered up */
1966  if (0 == rContext->cardAtrLength)
1967  /* Allow the status thread to convey information */
1969 
1970  currReader->cbAtr = rContext->cardAtrLength;
1971  memcpy(currReader->rgbAtr, rContext->cardAtr,
1972  currReader->cbAtr);
1973  }
1974  else
1975  currReader->cbAtr = 0;
1976 
1977  /* Card is now absent */
1978  if (readerState & SCARD_ABSENT)
1979  {
1980  currReader->dwEventState |= SCARD_STATE_EMPTY;
1981  currReader->dwEventState &= ~SCARD_STATE_PRESENT;
1982  currReader->dwEventState &= ~SCARD_STATE_UNAWARE;
1983  currReader->dwEventState &= ~SCARD_STATE_IGNORE;
1984  currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
1985  currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
1986  currReader->dwEventState &= ~SCARD_STATE_ATRMATCH;
1987  currReader->dwEventState &= ~SCARD_STATE_MUTE;
1988  currReader->dwEventState &= ~SCARD_STATE_INUSE;
1989 
1990  /* After present the rest are assumed */
1991  if (currReader->dwCurrentState & SCARD_STATE_PRESENT)
1992  {
1993  currReader->dwEventState |= SCARD_STATE_CHANGED;
1994  Log0(PCSC_LOG_DEBUG);
1995  dwBreakFlag = 1;
1996  }
1997  }
1998  /* Card is now present */
1999  else if (readerState & SCARD_PRESENT)
2000  {
2001  currReader->dwEventState |= SCARD_STATE_PRESENT;
2002  currReader->dwEventState &= ~SCARD_STATE_EMPTY;
2003  currReader->dwEventState &= ~SCARD_STATE_UNAWARE;
2004  currReader->dwEventState &= ~SCARD_STATE_IGNORE;
2005  currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
2006  currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
2007  currReader->dwEventState &= ~SCARD_STATE_MUTE;
2008 
2009  if (currReader->dwCurrentState & SCARD_STATE_EMPTY)
2010  {
2011  currReader->dwEventState |= SCARD_STATE_CHANGED;
2012  Log0(PCSC_LOG_DEBUG);
2013  dwBreakFlag = 1;
2014  }
2015 
2016  if (readerState & SCARD_SWALLOWED)
2017  {
2018  currReader->dwEventState |= SCARD_STATE_MUTE;
2019  if (!(currReader->dwCurrentState & SCARD_STATE_MUTE))
2020  {
2021  currReader->dwEventState |= SCARD_STATE_CHANGED;
2022  Log0(PCSC_LOG_DEBUG);
2023  dwBreakFlag = 1;
2024  }
2025  }
2026  else
2027  {
2028  /* App thinks card is mute but it is not */
2029  if (currReader->dwCurrentState & SCARD_STATE_MUTE)
2030  {
2031  currReader->dwEventState |= SCARD_STATE_CHANGED;
2032  Log0(PCSC_LOG_DEBUG);
2033  dwBreakFlag = 1;
2034  }
2035  }
2036  }
2037 
2038  /* Now figure out sharing modes */
2040  {
2041  currReader->dwEventState |= SCARD_STATE_EXCLUSIVE;
2042  currReader->dwEventState &= ~SCARD_STATE_INUSE;
2043  if (currReader->dwCurrentState & SCARD_STATE_INUSE)
2044  {
2045  currReader->dwEventState |= SCARD_STATE_CHANGED;
2046  Log0(PCSC_LOG_DEBUG);
2047  dwBreakFlag = 1;
2048  }
2049  }
2050  else if (rContext->readerSharing >= PCSCLITE_SHARING_LAST_CONTEXT)
2051  {
2052  /* A card must be inserted for it to be INUSE */
2053  if (readerState & SCARD_PRESENT)
2054  {
2055  currReader->dwEventState |= SCARD_STATE_INUSE;
2056  currReader->dwEventState &= ~SCARD_STATE_EXCLUSIVE;
2057  if (currReader-> dwCurrentState & SCARD_STATE_EXCLUSIVE)
2058  {
2059  currReader->dwEventState |= SCARD_STATE_CHANGED;
2060  Log0(PCSC_LOG_DEBUG);
2061  dwBreakFlag = 1;
2062  }
2063  }
2064  }
2065  else if (rContext->readerSharing == PCSCLITE_SHARING_NO_CONTEXT)
2066  {
2067  currReader->dwEventState &= ~SCARD_STATE_INUSE;
2068  currReader->dwEventState &= ~SCARD_STATE_EXCLUSIVE;
2069 
2070  if (currReader->dwCurrentState & SCARD_STATE_INUSE)
2071  {
2072  currReader->dwEventState |= SCARD_STATE_CHANGED;
2073  Log0(PCSC_LOG_DEBUG);
2074  dwBreakFlag = 1;
2075  }
2076  else if (currReader-> dwCurrentState
2078  {
2079  currReader->dwEventState |= SCARD_STATE_CHANGED;
2080  Log0(PCSC_LOG_DEBUG);
2081  dwBreakFlag = 1;
2082  }
2083  }
2084 
2085  if (currReader->dwCurrentState == SCARD_STATE_UNAWARE)
2086  {
2087  /*
2088  * Break out of the while .. loop and return status
2089  * once all the status's for all readers is met
2090  */
2091  currReader->dwEventState |= SCARD_STATE_CHANGED;
2092  Log0(PCSC_LOG_DEBUG);
2093  dwBreakFlag = 1;
2094  }
2095  } /* End of SCARD_STATE_UNKNOWN */
2096  } /* End of SCARD_STATE_IGNORE */
2097 
2098  /* Counter and resetter */
2099  j++;
2100  if (j == cReaders)
2101  {
2102  /* go back to the first reader */
2103  j = 0;
2104 
2105  /* Declare all the break conditions */
2106 
2107  /* Break if UNAWARE is set and all readers have been checked */
2108  if (dwBreakFlag == 1)
2109  break;
2110 
2111  /* Only sleep once for each cycle of reader checks. */
2112  {
2113  struct wait_reader_state_change waitStatusStruct;
2114  struct timeval before, after;
2115 
2116  gettimeofday(&before, NULL);
2117 
2118  waitStatusStruct.timeOut = dwTime;
2119  waitStatusStruct.rv = SCARD_S_SUCCESS;
2120 
2121  /* another thread can do SCardCancel() */
2122  currentContextMap->cancellable = TRUE;
2123 
2125  currentContextMap->dwClientID,
2126  sizeof(waitStatusStruct), &waitStatusStruct);
2127 
2128  if (rv != SCARD_S_SUCCESS)
2129  goto end;
2130 
2131  /*
2132  * Read a message from the server
2133  */
2135  &waitStatusStruct, sizeof(waitStatusStruct),
2136  currentContextMap->dwClientID, dwTime);
2137 
2138  /* another thread can do SCardCancel() */
2139  currentContextMap->cancellable = FALSE;
2140 
2141  /* timeout */
2142  if (SCARD_E_TIMEOUT == rv)
2143  {
2144  /* ask server to remove us from the event list */
2146  currentContextMap->dwClientID,
2147  sizeof(waitStatusStruct), &waitStatusStruct);
2148 
2149  if (rv != SCARD_S_SUCCESS)
2150  goto end;
2151 
2152  /* Read a message from the server */
2153  rv = MessageReceive(&waitStatusStruct,
2154  sizeof(waitStatusStruct),
2155  currentContextMap->dwClientID);
2156 
2157  if (rv != SCARD_S_SUCCESS)
2158  goto end;
2159  }
2160 
2161  if (rv != SCARD_S_SUCCESS)
2162  goto end;
2163 
2164  /* an event occurs or SCardCancel() was called */
2165  if (SCARD_S_SUCCESS != waitStatusStruct.rv)
2166  {
2167  rv = waitStatusStruct.rv;
2168  goto end;
2169  }
2170 
2171  /* synchronize reader states with daemon */
2172  rv = getReaderStates(currentContextMap);
2173  if (rv != SCARD_S_SUCCESS)
2174  goto end;
2175 
2176  if (INFINITE != dwTimeout)
2177  {
2178  long int diff;
2179 
2180  gettimeofday(&after, NULL);
2181  diff = time_sub(&after, &before);
2182  dwTime -= diff/1000;
2183  }
2184  }
2185 
2186  if (dwTimeout != INFINITE)
2187  {
2188  /* If time is greater than timeout and all readers have been
2189  * checked
2190  */
2191  if (dwTime <= 0)
2192  {
2193  rv = SCARD_E_TIMEOUT;
2194  goto end;
2195  }
2196  }
2197  }
2198  }
2199  while (1);
2200 
2201 end:
2202  Log1(PCSC_LOG_DEBUG, "Event Loop End");
2203 
2204  (void)pthread_mutex_unlock(&currentContextMap->mMutex);
2205 
2206 error:
2207  PROFILE_END(rv)
2208 #ifdef DO_TRACE
2209  for (j=0; j<cReaders; j++)
2210  {
2211  API_TRACE_OUT("[%d] %s %X %X", j, rgReaderStates[j].szReader,
2212  rgReaderStates[j].dwCurrentState, rgReaderStates[j].dwEventState)
2213  }
2214 #endif
2215 
2216  return rv;
2217 }
2218 
2269 LONG SCardControl(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer,
2270  DWORD cbSendLength, LPVOID pbRecvBuffer, DWORD cbRecvLength,
2271  LPDWORD lpBytesReturned)
2272 {
2273  LONG rv;
2274  struct control_struct scControlStruct;
2275  SCONTEXTMAP * currentContextMap;
2276  CHANNEL_MAP * pChannelMap;
2277 
2278  PROFILE_START
2279 
2280  /* 0 bytes received by default */
2281  if (NULL != lpBytesReturned)
2282  *lpBytesReturned = 0;
2283 
2284  /*
2285  * Make sure this handle has been opened
2286  */
2287  rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
2288  &pChannelMap);
2289  if (rv == -1)
2290  {
2291  PROFILE_END(SCARD_E_INVALID_HANDLE)
2292  return SCARD_E_INVALID_HANDLE;
2293  }
2294 
2295  (void)pthread_mutex_lock(&currentContextMap->mMutex);
2296 
2297  /* check the handle is still valid */
2298  rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
2299  &pChannelMap);
2300  if (rv == -1)
2301  {
2302  /* the hCard handle is now invalid
2303  * -> another thread may have called SCardReleaseContext
2304  * so the mMutex has been unlocked (and is now invalid)
2305  * -> another thread may have called SCardDisconnect
2306  * so the mMutex is STILL locked
2307  * since we don't know just unlock the mutex */
2308  (void)pthread_mutex_unlock(&currentContextMap->mMutex);
2309  return SCARD_E_INVALID_HANDLE;
2310  }
2311 
2312  if ((cbSendLength > MAX_BUFFER_SIZE_EXTENDED)
2313  || (cbRecvLength > MAX_BUFFER_SIZE_EXTENDED))
2314  {
2316  goto end;
2317  }
2318 
2319  scControlStruct.hCard = hCard;
2320  scControlStruct.dwControlCode = dwControlCode;
2321  scControlStruct.cbSendLength = cbSendLength;
2322  scControlStruct.cbRecvLength = cbRecvLength;
2323  scControlStruct.dwBytesReturned = 0;
2324  scControlStruct.rv = 0;
2325 
2326  rv = MessageSendWithHeader(SCARD_CONTROL, currentContextMap->dwClientID,
2327  sizeof(scControlStruct), &scControlStruct);
2328 
2329  if (rv != SCARD_S_SUCCESS)
2330  goto end;
2331 
2332  /* write the sent buffer */
2333  rv = MessageSend((char *)pbSendBuffer, cbSendLength,
2334  currentContextMap->dwClientID);
2335 
2336  if (rv != SCARD_S_SUCCESS)
2337  goto end;
2338 
2339  /*
2340  * Read a message from the server
2341  */
2342  rv = MessageReceive(&scControlStruct, sizeof(scControlStruct),
2343  currentContextMap->dwClientID);
2344 
2345  if (rv != SCARD_S_SUCCESS)
2346  goto end;
2347 
2348  if (SCARD_S_SUCCESS == scControlStruct.rv)
2349  {
2350  /* read the received buffer */
2351  rv = MessageReceive(pbRecvBuffer, scControlStruct.dwBytesReturned,
2352  currentContextMap->dwClientID);
2353 
2354  if (rv != SCARD_S_SUCCESS)
2355  goto end;
2356 
2357  }
2358 
2359  if (NULL != lpBytesReturned)
2360  *lpBytesReturned = scControlStruct.dwBytesReturned;
2361 
2362  rv = scControlStruct.rv;
2363 
2364 end:
2365  (void)pthread_mutex_unlock(&currentContextMap->mMutex);
2366 
2367  PROFILE_END(rv)
2368 
2369  return rv;
2370 }
2371 
2476 LONG SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr,
2477  LPDWORD pcbAttrLen)
2478 {
2479  LONG ret;
2480  unsigned char *buf = NULL;
2481 
2482  PROFILE_START
2483 
2484  if (NULL == pcbAttrLen)
2485  {
2487  goto end;
2488  }
2489 
2490  if (SCARD_AUTOALLOCATE == *pcbAttrLen)
2491  {
2492  if (NULL == pbAttr)
2494 
2495  *pcbAttrLen = MAX_BUFFER_SIZE;
2496  buf = malloc(*pcbAttrLen);
2497  if (NULL == buf)
2498  {
2499  ret = SCARD_E_NO_MEMORY;
2500  goto end;
2501  }
2502 
2503  *(unsigned char **)pbAttr = buf;
2504  }
2505  else
2506  {
2507  buf = pbAttr;
2508 
2509  /* if only get the length */
2510  if (NULL == pbAttr)
2511  /* use a reasonable size */
2512  *pcbAttrLen = MAX_BUFFER_SIZE;
2513  }
2514 
2515  ret = SCardGetSetAttrib(hCard, SCARD_GET_ATTRIB, dwAttrId, buf,
2516  pcbAttrLen);
2517 
2518 end:
2519  PROFILE_END(ret)
2520 
2521  return ret;
2522 }
2523 
2559 LONG SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr,
2560  DWORD cbAttrLen)
2561 {
2562  LONG ret;
2563 
2564  PROFILE_START
2565 
2566  if (NULL == pbAttr || 0 == cbAttrLen)
2568 
2569  ret = SCardGetSetAttrib(hCard, SCARD_SET_ATTRIB, dwAttrId, (LPBYTE)pbAttr,
2570  &cbAttrLen);
2571 
2572  PROFILE_END(ret)
2573 
2574  return ret;
2575 }
2576 
2577 static LONG SCardGetSetAttrib(SCARDHANDLE hCard, int command, DWORD dwAttrId,
2578  LPBYTE pbAttr, LPDWORD pcbAttrLen)
2579 {
2580  LONG rv;
2581  struct getset_struct scGetSetStruct;
2582  SCONTEXTMAP * currentContextMap;
2583  CHANNEL_MAP * pChannelMap;
2584 
2585  /*
2586  * Make sure this handle has been opened
2587  */
2588  rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
2589  &pChannelMap);
2590  if (rv == -1)
2591  return SCARD_E_INVALID_HANDLE;
2592 
2593  (void)pthread_mutex_lock(&currentContextMap->mMutex);
2594 
2595  /* check the handle is still valid */
2596  rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
2597  &pChannelMap);
2598  if (rv == -1)
2599  {
2600  /* the hCard handle is now invalid
2601  * -> another thread may have called SCardReleaseContext
2602  * so the mMutex has been unlocked (and is now invalid)
2603  * -> another thread may have called SCardDisconnect
2604  * so the mMutex is STILL locked
2605  * since we don't know just unlock the mutex */
2606  (void)pthread_mutex_unlock(&currentContextMap->mMutex);
2607  return SCARD_E_INVALID_HANDLE;
2608  }
2609 
2610  if (*pcbAttrLen > MAX_BUFFER_SIZE)
2611  {
2613  goto end;
2614  }
2615 
2616  scGetSetStruct.hCard = hCard;
2617  scGetSetStruct.dwAttrId = dwAttrId;
2618  scGetSetStruct.cbAttrLen = *pcbAttrLen;
2619  scGetSetStruct.rv = SCARD_E_NO_SERVICE;
2620  memset(scGetSetStruct.pbAttr, 0, sizeof(scGetSetStruct.pbAttr));
2621  if (SCARD_SET_ATTRIB == command)
2622  memcpy(scGetSetStruct.pbAttr, pbAttr, *pcbAttrLen);
2623 
2624  rv = MessageSendWithHeader(command, currentContextMap->dwClientID,
2625  sizeof(scGetSetStruct), &scGetSetStruct);
2626 
2627  if (rv != SCARD_S_SUCCESS)
2628  goto end;
2629 
2630  /*
2631  * Read a message from the server
2632  */
2633  rv = MessageReceive(&scGetSetStruct, sizeof(scGetSetStruct),
2634  currentContextMap->dwClientID);
2635 
2636  if (rv != SCARD_S_SUCCESS)
2637  goto end;
2638 
2639  if ((SCARD_S_SUCCESS == scGetSetStruct.rv) && (SCARD_GET_ATTRIB == command))
2640  {
2641  /*
2642  * Copy and zero it so any secret information is not leaked
2643  */
2644  if (*pcbAttrLen < scGetSetStruct.cbAttrLen)
2645  {
2646  scGetSetStruct.cbAttrLen = *pcbAttrLen;
2647  scGetSetStruct.rv = SCARD_E_INSUFFICIENT_BUFFER;
2648  }
2649  else
2650  *pcbAttrLen = scGetSetStruct.cbAttrLen;
2651 
2652  if (pbAttr)
2653  memcpy(pbAttr, scGetSetStruct.pbAttr, scGetSetStruct.cbAttrLen);
2654 
2655  memset(scGetSetStruct.pbAttr, 0x00, sizeof(scGetSetStruct.pbAttr));
2656  }
2657  rv = scGetSetStruct.rv;
2658 
2659 end:
2660  (void)pthread_mutex_unlock(&currentContextMap->mMutex);
2661 
2662  return rv;
2663 }
2664 
2723 LONG SCardTransmit(SCARDHANDLE hCard, const SCARD_IO_REQUEST *pioSendPci,
2724  LPCBYTE pbSendBuffer, DWORD cbSendLength,
2725  SCARD_IO_REQUEST *pioRecvPci, LPBYTE pbRecvBuffer,
2726  LPDWORD pcbRecvLength)
2727 {
2728  LONG rv;
2729  SCONTEXTMAP * currentContextMap;
2730  CHANNEL_MAP * pChannelMap;
2731  struct transmit_struct scTransmitStruct;
2732 
2733  PROFILE_START
2734 
2735  if (pbSendBuffer == NULL || pbRecvBuffer == NULL ||
2736  pcbRecvLength == NULL || pioSendPci == NULL)
2738 
2739  /*
2740  * Make sure this handle has been opened
2741  */
2742  rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
2743  &pChannelMap);
2744  if (rv == -1)
2745  {
2746  *pcbRecvLength = 0;
2747  PROFILE_END(SCARD_E_INVALID_HANDLE)
2748  return SCARD_E_INVALID_HANDLE;
2749  }
2750 
2751  /* Retry loop for blocking behaviour */
2752 retry:
2753 
2754  (void)pthread_mutex_lock(&currentContextMap->mMutex);
2755 
2756  /* check the handle is still valid */
2757  rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
2758  &pChannelMap);
2759  if (rv == -1)
2760  {
2761  /* the hCard handle is now invalid
2762  * -> another thread may have called SCardReleaseContext
2763  * so the mMutex has been unlocked (and is now invalid)
2764  * -> another thread may have called SCardDisconnect
2765  * so the mMutex is STILL locked
2766  * since we don't know just unlock the mutex */
2767  (void)pthread_mutex_unlock(&currentContextMap->mMutex);
2768  return SCARD_E_INVALID_HANDLE;
2769  }
2770 
2771  if ((cbSendLength > MAX_BUFFER_SIZE_EXTENDED)
2772  || (*pcbRecvLength > MAX_BUFFER_SIZE_EXTENDED))
2773  {
2775  goto end;
2776  }
2777 
2778  scTransmitStruct.hCard = hCard;
2779  scTransmitStruct.cbSendLength = cbSendLength;
2780  scTransmitStruct.pcbRecvLength = *pcbRecvLength;
2781  scTransmitStruct.ioSendPciProtocol = pioSendPci->dwProtocol;
2782  scTransmitStruct.ioSendPciLength = pioSendPci->cbPciLength;
2783  scTransmitStruct.rv = SCARD_S_SUCCESS;
2784 
2785  if (pioRecvPci)
2786  {
2787  scTransmitStruct.ioRecvPciProtocol = pioRecvPci->dwProtocol;
2788  scTransmitStruct.ioRecvPciLength = pioRecvPci->cbPciLength;
2789  }
2790  else
2791  {
2792  scTransmitStruct.ioRecvPciProtocol = SCARD_PROTOCOL_ANY;
2793  scTransmitStruct.ioRecvPciLength = sizeof(SCARD_IO_REQUEST);
2794  }
2795 
2796  rv = MessageSendWithHeader(SCARD_TRANSMIT, currentContextMap->dwClientID,
2797  sizeof(scTransmitStruct), (void *) &scTransmitStruct);
2798 
2799  if (rv != SCARD_S_SUCCESS)
2800  goto end;
2801 
2802  /* write the sent buffer */
2803  rv = MessageSend((void *)pbSendBuffer, cbSendLength,
2804  currentContextMap->dwClientID);
2805 
2806  if (rv != SCARD_S_SUCCESS)
2807  goto end;
2808 
2809  /*
2810  * Read a message from the server
2811  */
2812  rv = MessageReceive(&scTransmitStruct, sizeof(scTransmitStruct),
2813  currentContextMap->dwClientID);
2814 
2815  if (rv != SCARD_S_SUCCESS)
2816  goto end;
2817 
2818  if (SCARD_S_SUCCESS == scTransmitStruct.rv)
2819  {
2820  /* read the received buffer */
2821  rv = MessageReceive(pbRecvBuffer, scTransmitStruct.pcbRecvLength,
2822  currentContextMap->dwClientID);
2823 
2824  if (rv != SCARD_S_SUCCESS)
2825  goto end;
2826 
2827  if (pioRecvPci)
2828  {
2829  pioRecvPci->dwProtocol = scTransmitStruct.ioRecvPciProtocol;
2830  pioRecvPci->cbPciLength = scTransmitStruct.ioRecvPciLength;
2831  }
2832  }
2833 
2834  rv = scTransmitStruct.rv;
2835 
2836  if (sharing_shall_block && (SCARD_E_SHARING_VIOLATION == rv))
2837  {
2838  (void)pthread_mutex_unlock(&currentContextMap->mMutex);
2840  goto retry;
2841  }
2842 
2843  *pcbRecvLength = scTransmitStruct.pcbRecvLength;
2844 
2845 end:
2846  (void)pthread_mutex_unlock(&currentContextMap->mMutex);
2847 
2848  PROFILE_END(rv)
2849 
2850  return rv;
2851 }
2852 
2903 LONG SCardListReaders(SCARDCONTEXT hContext, /*@unused@*/ LPCSTR mszGroups,
2904  LPSTR mszReaders, LPDWORD pcchReaders)
2905 {
2906  DWORD dwReadersLen = 0;
2907  int i;
2908  SCONTEXTMAP * currentContextMap;
2909  LONG rv = SCARD_S_SUCCESS;
2910  char *buf = NULL;
2911 
2912  (void)mszGroups;
2913  PROFILE_START
2914  API_TRACE_IN("%ld", hContext)
2915 
2916  /*
2917  * Check for NULL parameters
2918  */
2919  if (pcchReaders == NULL)
2921 
2922  /*
2923  * Make sure this context has been opened
2924  */
2925  currentContextMap = SCardGetContext(hContext);
2926  if (NULL == currentContextMap)
2927  {
2928  PROFILE_END(SCARD_E_INVALID_HANDLE)
2929  return SCARD_E_INVALID_HANDLE;
2930  }
2931 
2932  (void)pthread_mutex_lock(&currentContextMap->mMutex);
2933 
2934  /* check the context is still opened */
2935  currentContextMap = SCardGetContext(hContext);
2936  if (NULL == currentContextMap)
2937  /* the hContext context is now invalid
2938  * -> another thread may have called SCardReleaseContext
2939  * -> so the mMutex has been unlocked */
2940  return SCARD_E_INVALID_HANDLE;
2941 
2942  /* synchronize reader states with daemon */
2943  rv = getReaderStates(currentContextMap);
2944  if (rv != SCARD_S_SUCCESS)
2945  goto end;
2946 
2947  dwReadersLen = 0;
2948  for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
2949  if (readerStates[i].readerName[0] != '\0')
2950  dwReadersLen += strlen(readerStates[i].readerName) + 1;
2951 
2952  /* for the last NULL byte */
2953  dwReadersLen += 1;
2954 
2955  if (1 == dwReadersLen)
2956  {
2958  goto end;
2959  }
2960 
2961  if (SCARD_AUTOALLOCATE == *pcchReaders)
2962  {
2963  buf = malloc(dwReadersLen);
2964  if (NULL == buf)
2965  {
2966  rv = SCARD_E_NO_MEMORY;
2967  goto end;
2968  }
2969  if (NULL == mszReaders)
2970  {
2972  goto end;
2973  }
2974  *(char **)mszReaders = buf;
2975  }
2976  else
2977  {
2978  buf = mszReaders;
2979 
2980  /* not enough place to store the reader names */
2981  if ((NULL != mszReaders) && (*pcchReaders < dwReadersLen))
2982  {
2984  goto end;
2985  }
2986  }
2987 
2988  if (mszReaders == NULL) /* text array not allocated */
2989  goto end;
2990 
2991  for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
2992  {
2993  if (readerStates[i].readerName[0] != '\0')
2994  {
2995  /*
2996  * Build the multi-string
2997  */
2998  strcpy(buf, readerStates[i].readerName);
2999  buf += strlen(readerStates[i].readerName)+1;
3000  }
3001  }
3002  *buf = '\0'; /* Add the last null */
3003 
3004 end:
3005  /* set the reader names length */
3006  *pcchReaders = dwReadersLen;
3007 
3008  (void)pthread_mutex_unlock(&currentContextMap->mMutex);
3009 
3010  PROFILE_END(rv)
3011  API_TRACE_OUT("%d", *pcchReaders)
3012 
3013  return rv;
3014 }
3015 
3029 LONG SCardFreeMemory(SCARDCONTEXT hContext, LPCVOID pvMem)
3030 {
3031  LONG rv = SCARD_S_SUCCESS;
3032  SCONTEXTMAP * currentContextMap;
3033 
3034  PROFILE_START
3035 
3036  /*
3037  * Make sure this context has been opened
3038  */
3039  currentContextMap = SCardGetContext(hContext);
3040  if (NULL == currentContextMap)
3041  return SCARD_E_INVALID_HANDLE;
3042 
3043  free((void *)pvMem);
3044 
3045  PROFILE_END(rv)
3046 
3047  return rv;
3048 }
3049 
3101 LONG SCardListReaderGroups(SCARDCONTEXT hContext, LPSTR mszGroups,
3102  LPDWORD pcchGroups)
3103 {
3104  LONG rv = SCARD_S_SUCCESS;
3105  SCONTEXTMAP * currentContextMap;
3106  char *buf = NULL;
3107 
3108  PROFILE_START
3109 
3110  /* Multi-string with two trailing \0 */
3111  const char ReaderGroup[] = "SCard$DefaultReaders\0";
3112  const unsigned int dwGroups = sizeof(ReaderGroup);
3113 
3114  /*
3115  * Make sure this context has been opened
3116  */
3117  currentContextMap = SCardGetContext(hContext);
3118  if (NULL == currentContextMap)
3119  return SCARD_E_INVALID_HANDLE;
3120 
3121  (void)pthread_mutex_lock(&currentContextMap->mMutex);
3122 
3123  /* check the context is still opened */
3124  currentContextMap = SCardGetContext(hContext);
3125  if (NULL == currentContextMap)
3126  /* the hContext context is now invalid
3127  * -> another thread may have called SCardReleaseContext
3128  * -> so the mMutex has been unlocked */
3129  return SCARD_E_INVALID_HANDLE;
3130 
3131  if (SCARD_AUTOALLOCATE == *pcchGroups)
3132  {
3133  if (NULL == mszGroups)
3134  {
3136  goto end;
3137  }
3138  buf = malloc(dwGroups);
3139  if (NULL == buf)
3140  {
3141  rv = SCARD_E_NO_MEMORY;
3142  goto end;
3143  }
3144  *(char **)mszGroups = buf;
3145  }
3146  else
3147  {
3148  buf = mszGroups;
3149 
3150  if ((NULL != mszGroups) && (*pcchGroups < dwGroups))
3151  {
3153  goto end;
3154  }
3155  }
3156 
3157  if (buf)
3158  memcpy(buf, ReaderGroup, dwGroups);
3159 
3160 end:
3161  *pcchGroups = dwGroups;
3162 
3163  (void)pthread_mutex_unlock(&currentContextMap->mMutex);
3164 
3165  PROFILE_END(rv)
3166 
3167  return rv;
3168 }
3169 
3200 {
3201  SCONTEXTMAP * currentContextMap;
3202  LONG rv = SCARD_S_SUCCESS;
3203  uint32_t dwClientID = 0;
3204  struct cancel_struct scCancelStruct;
3205 
3206  PROFILE_START
3207  API_TRACE_IN("%ld", hContext)
3208 
3209  /*
3210  * Make sure this context has been opened
3211  */
3212  currentContextMap = SCardGetContext(hContext);
3213  if (NULL == currentContextMap)
3214  {
3216  goto error;
3217  }
3218 
3219  if (! currentContextMap->cancellable)
3220  {
3221  rv = SCARD_S_SUCCESS;
3222  goto error;
3223  }
3224 
3225  /* create a new connection to the server */
3226  if (ClientSetupSession(&dwClientID) != 0)
3227  {
3228  rv = SCARD_E_NO_SERVICE;
3229  goto error;
3230  }
3231 
3232  scCancelStruct.hContext = hContext;
3233  scCancelStruct.rv = SCARD_S_SUCCESS;
3234 
3235  rv = MessageSendWithHeader(SCARD_CANCEL, dwClientID,
3236  sizeof(scCancelStruct), (void *) &scCancelStruct);
3237 
3238  if (rv != SCARD_S_SUCCESS)
3239  goto end;
3240 
3241  /*
3242  * Read a message from the server
3243  */
3244  rv = MessageReceive(&scCancelStruct, sizeof(scCancelStruct), dwClientID);
3245 
3246  if (rv != SCARD_S_SUCCESS)
3247  goto end;
3248 
3249  rv = scCancelStruct.rv;
3250 end:
3251  ClientCloseSession(dwClientID);
3252 
3253 error:
3254  PROFILE_END(rv)
3255  API_TRACE_OUT("")
3256 
3257  return rv;
3258 }
3259 
3284 {
3285  LONG rv;
3286  SCONTEXTMAP * currentContextMap;
3287 
3288  PROFILE_START
3289  API_TRACE_IN("%ld", hContext)
3290 
3291  rv = SCARD_S_SUCCESS;
3292 
3293  /*
3294  * Make sure this context has been opened
3295  */
3296  currentContextMap = SCardGetContext(hContext);
3297  if (currentContextMap == NULL)
3299 
3300  PROFILE_END(rv)
3301  API_TRACE_OUT("")
3302 
3303  return rv;
3304 }
3305 
3322 static LONG SCardAddContext(SCARDCONTEXT hContext, DWORD dwClientID)
3323 {
3324  int lrv;
3325  SCONTEXTMAP * newContextMap;
3326 
3327  newContextMap = malloc(sizeof(SCONTEXTMAP));
3328  if (NULL == newContextMap)
3329  return SCARD_E_NO_MEMORY;
3330 
3331  Log2(PCSC_LOG_DEBUG, "Allocating new SCONTEXTMAP @%p", newContextMap);
3332  newContextMap->hContext = hContext;
3333  newContextMap->dwClientID = dwClientID;
3334  newContextMap->cancellable = FALSE;
3335 
3336  (void)pthread_mutex_init(&newContextMap->mMutex, NULL);
3337 
3338  lrv = list_init(&newContextMap->channelMapList);
3339  if (lrv < 0)
3340  {
3341  Log2(PCSC_LOG_CRITICAL, "list_init failed with return value: %d", lrv);
3342  goto error;
3343  }
3344 
3345  lrv = list_attributes_seeker(&newContextMap->channelMapList,
3346  CHANNEL_MAP_seeker);
3347  if (lrv <0)
3348  {
3349  Log2(PCSC_LOG_CRITICAL,
3350  "list_attributes_seeker failed with return value: %d", lrv);
3351  list_destroy(&newContextMap->channelMapList);
3352  goto error;
3353  }
3354 
3355  lrv = list_append(&contextMapList, newContextMap);
3356  if (lrv < 0)
3357  {
3358  Log2(PCSC_LOG_CRITICAL, "list_append failed with return value: %d",
3359  lrv);
3360  list_destroy(&newContextMap->channelMapList);
3361  goto error;
3362  }
3363 
3364  return SCARD_S_SUCCESS;
3365 
3366 error:
3367 
3368  (void)pthread_mutex_destroy(&newContextMap->mMutex);
3369  free(newContextMap);
3370 
3371  return SCARD_E_NO_MEMORY;
3372 }
3373 
3387 {
3388  SCONTEXTMAP * currentContextMap;
3389 
3390  (void)SCardLockThread();
3391  currentContextMap = SCardGetContextTH(hContext);
3392  (void)SCardUnlockThread();
3393 
3394  return currentContextMap;
3395 }
3396 
3410 {
3411  return list_seek(&contextMapList, &hContext);
3412 }
3413 
3423 static LONG SCardRemoveContext(SCARDCONTEXT hContext)
3424 {
3425  SCONTEXTMAP * currentContextMap;
3426  currentContextMap = SCardGetContextTH(hContext);
3427 
3428  if (NULL == currentContextMap)
3429  return SCARD_E_INVALID_HANDLE;
3430  else
3431  return SCardCleanContext(currentContextMap);
3432 }
3433 
3434 static LONG SCardCleanContext(SCONTEXTMAP * targetContextMap)
3435 {
3436  int list_index, lrv;
3437  int listSize;
3438  CHANNEL_MAP * currentChannelMap;
3439 
3440  targetContextMap->hContext = 0;
3441  (void)ClientCloseSession(targetContextMap->dwClientID);
3442  targetContextMap->dwClientID = 0;
3443  (void)pthread_mutex_destroy(&targetContextMap->mMutex);
3444 
3445  listSize = list_size(&targetContextMap->channelMapList);
3446  for (list_index = 0; list_index < listSize; list_index++)
3447  {
3448  currentChannelMap = list_get_at(&targetContextMap->channelMapList,
3449  list_index);
3450  if (NULL == currentChannelMap)
3451  {
3452  Log2(PCSC_LOG_CRITICAL, "list_get_at failed for index %d",
3453  list_index);
3454  continue;
3455  }
3456  else
3457  {
3458  free(currentChannelMap->readerName);
3459  free(currentChannelMap);
3460  }
3461 
3462  }
3463  list_destroy(&targetContextMap->channelMapList);
3464 
3465  lrv = list_delete(&contextMapList, targetContextMap);
3466  if (lrv < 0)
3467  {
3468  Log2(PCSC_LOG_CRITICAL,
3469  "list_delete failed with return value: %d", lrv);
3470  }
3471 
3472  free(targetContextMap);
3473 
3474  return SCARD_S_SUCCESS;
3475 }
3476 
3477 /*
3478  * Functions for managing hCard values returned from SCardConnect.
3479  */
3480 
3481 static LONG SCardAddHandle(SCARDHANDLE hCard, SCONTEXTMAP * currentContextMap,
3482  LPCSTR readerName)
3483 {
3484  CHANNEL_MAP * newChannelMap;
3485  int lrv = -1;
3486 
3487  newChannelMap = malloc(sizeof(CHANNEL_MAP));
3488  if (NULL == newChannelMap)
3489  return SCARD_E_NO_MEMORY;
3490 
3491  newChannelMap->hCard = hCard;
3492  newChannelMap->readerName = strdup(readerName);
3493 
3494  lrv = list_append(&currentContextMap->channelMapList, newChannelMap);
3495  if (lrv < 0)
3496  {
3497  free(newChannelMap->readerName);
3498  free(newChannelMap);
3499  Log2(PCSC_LOG_CRITICAL, "list_append failed with return value: %d",
3500  lrv);
3501  return SCARD_E_NO_MEMORY;
3502  }
3503 
3504  return SCARD_S_SUCCESS;
3505 }
3506 
3507 static LONG SCardRemoveHandle(SCARDHANDLE hCard)
3508 {
3509  SCONTEXTMAP * currentContextMap;
3510  CHANNEL_MAP * currentChannelMap;
3511  int lrv;
3512  LONG rv;
3513 
3514  rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
3515  &currentChannelMap);
3516  if (rv == -1)
3517  return SCARD_E_INVALID_HANDLE;
3518 
3519  free(currentChannelMap->readerName);
3520 
3521  lrv = list_delete(&currentContextMap->channelMapList, currentChannelMap);
3522  if (lrv < 0)
3523  {
3524  Log2(PCSC_LOG_CRITICAL,
3525  "list_delete failed with return value: %d", lrv);
3526  }
3527 
3528  free(currentChannelMap);
3529 
3530  return SCARD_S_SUCCESS;
3531 }
3532 
3533 static LONG SCardGetContextAndChannelFromHandle(SCARDHANDLE hCard,
3534  SCONTEXTMAP **targetContextMap, CHANNEL_MAP ** targetChannelMap)
3535 {
3536  LONG rv;
3537 
3538  if (0 == hCard)
3539  return -1;
3540 
3541  (void)SCardLockThread();
3542  rv = SCardGetContextAndChannelFromHandleTH(hCard, targetContextMap,
3543  targetChannelMap);
3544  (void)SCardUnlockThread();
3545 
3546  return rv;
3547 }
3548 
3549 static LONG SCardGetContextAndChannelFromHandleTH(SCARDHANDLE hCard,
3550  SCONTEXTMAP **targetContextMap, CHANNEL_MAP ** targetChannelMap)
3551 {
3552  int listSize;
3553  int list_index;
3554  SCONTEXTMAP * currentContextMap;
3555  CHANNEL_MAP * currentChannelMap;
3556 
3557  /* Best to get the caller a crash early if we fail unsafely */
3558  *targetContextMap = NULL;
3559  *targetChannelMap = NULL;
3560 
3561  listSize = list_size(&contextMapList);
3562 
3563  for (list_index = 0; list_index < listSize; list_index++)
3564  {
3565  currentContextMap = list_get_at(&contextMapList, list_index);
3566  if (currentContextMap == NULL)
3567  {
3568  Log2(PCSC_LOG_CRITICAL, "list_get_at failed for index %d",
3569  list_index);
3570  continue;
3571  }
3572  currentChannelMap = list_seek(&currentContextMap->channelMapList,
3573  &hCard);
3574  if (currentChannelMap != NULL)
3575  {
3576  *targetContextMap = currentContextMap;
3577  *targetChannelMap = currentChannelMap;
3578  return SCARD_S_SUCCESS;
3579  }
3580  }
3581 
3582  return -1;
3583 }
3584 
3597 {
3598  LONG rv;
3599  struct stat statBuffer;
3600  char *socketName;
3601 
3602  socketName = getSocketName();
3603  rv = stat(socketName, &statBuffer);
3604 
3605  if (rv != 0)
3606  {
3607  Log3(PCSC_LOG_INFO, "PCSC Not Running: %s: %s",
3608  socketName, strerror(errno));
3609  return SCARD_E_NO_SERVICE;
3610  }
3611 
3612  return SCARD_S_SUCCESS;
3613 }
3614 
3615 static LONG getReaderStates(SCONTEXTMAP * currentContextMap)
3616 {
3617  int32_t dwClientID = currentContextMap->dwClientID;
3618  LONG rv;
3619 
3620  rv = MessageSendWithHeader(CMD_GET_READERS_STATE, dwClientID, 0, NULL);
3621  if (rv != SCARD_S_SUCCESS)
3622  return rv;
3623 
3624  /* Read a message from the server */
3625  rv = MessageReceive(&readerStates, sizeof(readerStates), dwClientID);
3626  if (rv != SCARD_S_SUCCESS)
3627  return rv;
3628 
3629  return SCARD_S_SUCCESS;
3630 }
3631 
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:52
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:54
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
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:114
#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
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
pthread_mutex_t mMutex
Mutex for this context.
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:50
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