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
PCSC_API LONG SCardListReaders(SCARDCONTEXT hContext, LPCSTR mszGroups, LPSTR mszReaders, LPDWORD pcchReaders)
Returns a list of currently available readers on the system.
contained in SCARD_END_TRANSACTION Messages.
Definition: winscard_msg.h:174
#define SCARD_E_READER_UNAVAILABLE
The specified reader is not currently available for use.
Definition: pcsclite.h:103
#define PCSCLITE_SHARING_NO_CONTEXT
No application is using the reader.
Definition: eventhandler.h: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
PCSC_API LONG SCardListReaderGroups(SCARDCONTEXT hContext, LPSTR mszGroups, LPDWORD pcchGroups)
Returns a list of currently available reader groups on the system.
#define SCARD_STATE_EMPTY
Card removed.
Definition: pcsclite.h:181
get the client/server protocol version
Definition: winscard_msg.h:71
static SCONTEXTMAP * SCardGetContextTH(SCARDCONTEXT)
Get the address from the Application Context list _psContextMap for the passed context.
#define SCARD_STATE_IGNORE
Ignore this reader.
Definition: pcsclite.h:177
#define SCARD_UNKNOWN
Unknown state.
Definition: pcsclite.h:168
PCSC_API char * pcsc_stringify_error(const LONG pcscError)
Returns a human readable text for the given PC/SC error code.
Definition: error.c:56
static short isExecuted
Make sure the initialization code is executed only once.
used by SCardEstablishContext()
Definition: winscard_msg.h:55
INTERNAL LONG MessageSendWithHeader(uint32_t command, uint32_t dwClientID, uint64_t size, void *data_void)
Wrapper for the MessageSend() function.
Definition: winscard_msg.c:288
int32_t minor
IPC minor PROTOCOL_VERSION_MINOR.
Definition: winscard_msg.h:36
#define SCARD_F_COMM_ERROR
An internal communications error has been detected.
Definition: pcsclite.h:99
used by SCardEndTransaction()
Definition: winscard_msg.h:62
PCSC_API LONG SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1, LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
Creates an Application Context to the PC/SC Resource Manager.
Definition: winscard.c:173
unsigned long cbPciLength
Protocol Control Inf Length.
Definition: pcsclite.h:61
int32_t readerSharing
PCSCLITE_SHARING_* sharing status.
Definition: eventhandler.h:32
#define SCARD_E_INVALID_PARAMETER
One or more of the supplied parameters could not be properly interpreted.
Definition: pcsclite.h:84
#define SCARD_STATE_CHANGED
State has changed.
Definition: pcsclite.h:178
This handles abstract system level calls.
static LONG SCardRemoveContext(SCARDCONTEXT)
Removes an Application Context from a control vector.
#define SCARD_E_NO_SERVICE
The Smart card resource manager is not running.
Definition: pcsclite.h:109
uint32_t eventCounter
number of card events
Definition: eventhandler.h:30
#define SCARD_E_NO_READERS_AVAILABLE
Cannot find a smart card reader.
Definition: pcsclite.h:127
static LONG SCardUnlockThread(void)
Unlocks a mutex so another thread may use the client.
used by SCardConnect()
Definition: winscard_msg.h:58
#define PROTOCOL_VERSION_MAJOR
Major version of the current message protocol.
Definition: winscard_msg.h:26
#define SCARD_PROTOCOL_T1
T=1 active protocol.
Definition: pcsclite.h:153
contained in SCARD_DISCONNECT Messages.
Definition: winscard_msg.h:151
PCSC_API LONG SCardFreeMemory(SCARDCONTEXT hContext, LPCVOID pvMem)
Releases memory that has been returned from the resource manager using the SCARD_AUTOALLOCATE length ...
LONG SCardGetStatusChange(SCARDCONTEXT hContext, DWORD dwTimeout, SCARD_READERSTATE *rgReaderStates, DWORD cReaders)
Blocks execution until the current availability of the cards in a specific set of readers changes...
#define SCARD_E_INVALID_HANDLE
The supplied handle was invalid.
Definition: pcsclite.h:83
PCSC_API LONG SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr, LPDWORD pcbAttrLen)
Get an attribute from the IFD Handler (reader driver).
Definition: winscard.c:1355
#define SCARD_PRESENT
Card is present.
Definition: pcsclite.h:170
Information contained in SCARD_RELEASE_CONTEXT Messages.
Definition: winscard_msg.h:109
PCSC_API LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
Terminates a connection made through SCardConnect().
Definition: winscard.c:798
PCSC_API LONG SCardCancel(SCARDCONTEXT hContext)
Cancels all pending blocking requests on the SCardGetStatusChange() function.
int SYS_USleep(int)
Makes the current process sleep for some microseconds.
Definition: sys_unix.c:62
contained in SCARD_BEGIN_TRANSACTION Messages.
Definition: winscard_msg.h:163
const SCARD_IO_REQUEST g_rgSCardRawPci
Protocol Control Information for raw access.
Definition: libpcscspy.c:726
#define PCSCLITE_SHARING_EXCLUSIVE_CONTEXT
Reader used in exclusive mode.
Definition: eventhandler.h:54
PCSC_API LONG SCardIsValidContext(SCARDCONTEXT hContext)
Check if a SCARDCONTEXT is valid.
static LONG SCardEstablishContextTH(DWORD, LPCVOID, LPCVOID, LPSCARDCONTEXT)
Creates a communication context to the PC/SC Resource Manager.
#define INFINITE
Infinite timeout.
Definition: pcsclite.h:190
#define SCARD_STATE_UNKNOWN
Reader unknown.
Definition: pcsclite.h:179
Represents the an Application Context on the Client side.
Information contained in SCARD_ESTABLISH_CONTEXT Messages.
Definition: winscard_msg.h:97
get the readers state
Definition: winscard_msg.h:72
#define PCSCLITE_LOCK_POLL_RATE
Lock polling rate.
Definition: pcscd.h:35
#define SCARD_AUTOALLOCATE
see SCardFreeMemory()
Definition: pcsclite.h:145
Information transmitted in CMD_VERSION Messages.
Definition: winscard_msg.h:33
INTERNAL LONG MessageReceive(void *buffer_void, uint64_t buffer_size, int32_t filedes)
Called by the Client to get the reponse from the server or vice-versa.
Definition: winscard_msg.c:422
used by SCardReleaseContext()
Definition: winscard_msg.h:56
LONG SCARDCONTEXT
hContext returned by SCardEstablishContext()
Definition: pcsclite.h:31
#define SCARD_E_INVALID_VALUE
One or more of the supplied parameters values could not be properly interpreted.
Definition: pcsclite.h:97
contained in SCARD_STATUS Messages.
Definition: winscard_msg.h:197
contained in SCARD_RECONNECT Messages.
Definition: winscard_msg.h:136
unsigned long dwProtocol
Protocol identifier.
Definition: pcsclite.h:60
uint32_t timeOut
timeout in ms
Definition: winscard_msg.h:88
#define PCSCLITE_MAX_READERS_CONTEXTS
Maximum readers context (a slot is count as a reader)
Definition: pcsclite.h:195
contained in SCARD_GET_ATTRIB and Messages.
Definition: winscard_msg.h:240
prototypes of strlcpy()/strlcat() imported from OpenBSD
#define SCARD_STATE_PRESENT
Card inserted.
Definition: pcsclite.h:182
This defines some structures and #defines to be used over the transport layer.
Information contained in CMD_WAIT_READER_STATE_CHANGE Messages.
Definition: winscard_msg.h:86
DWORD dwClientID
Client Connection ID.
#define SCARD_PROTOCOL_T0
T=0 active protocol.
Definition: pcsclite.h:152
#define SCARD_STATE_ATRMATCH
ATR matches card.
Definition: pcsclite.h:183
used by SCardReconnect()
Definition: winscard_msg.h:59
PCSC_API LONG SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode, DWORD dwPreferredProtocols, DWORD dwInitialization, LPDWORD pdwActiveProtocol)
Reestablishes a connection to a reader that was previously connected to using SCardConnect().
Definition: winscard.c:497
long int time_sub(struct timeval *a, struct timeval *b)
return the difference (as long int) in µs between 2 struct timeval r = a - b
Definition: utils.c: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
PCSC_API LONG SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader, DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol)
Establishes a connection to the reader specified in * szReader.
Definition: winscard.c:209
PCSC_API LONG SCardStatus(SCARDHANDLE hCard, LPSTR mszReaderName, LPDWORD pcchReaderLen, LPDWORD pdwState, LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
Returns the current status of the reader connected to by hCard.
Definition: winscard.c:1233
PCSC_API LONG SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr, DWORD cbAttrLen)
Set an attribute of the IFD Handler.
Definition: winscard.c:1431
#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
PCSC_API LONG SCardBeginTransaction(SCARDHANDLE hCard)
Establishes a temporary exclusive access mode for doing a serie of commands in a transaction.
Definition: winscard.c:1048
used by SCardControl()
Definition: winscard_msg.h:64
This keeps a list of defines for pcsc-lite.
#define SCARD_PROTOCOL_RAW
Raw active protocol.
Definition: pcsclite.h:154
#define SCARD_STATE_INUSE
Shared Mode.
Definition: pcsclite.h:185
Protocol Control Information (PCI)
Definition: pcsclite.h:58
PCSC_API LONG SCardControl(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer, DWORD cbSendLength, LPVOID pbRecvBuffer, DWORD cbRecvLength, LPDWORD lpBytesReturned)
Sends a command directly to the IFD Handler (reader driver) to be processed by the reader...
Definition: winscard.c:1296
#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
PCSC_API LONG SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
Ends a previously begun transaction.
Definition: winscard.c:1090
PCSC_API LONG SCardTransmit(SCARDHANDLE hCard, const SCARD_IO_REQUEST *pioSendPci, LPCBYTE pbSendBuffer, DWORD cbSendLength, SCARD_IO_REQUEST *pioRecvPci, LPBYTE pbRecvBuffer, LPDWORD pcbRecvLength)
Sends an APDU to the smart card contained in the reader connected to by SCardConnect().
Definition: winscard.c:1481
const SCARD_IO_REQUEST g_rgSCardT1Pci
Protocol Control Information for T=1.
Definition: libpcscspy.c:725
#define SCARD_E_UNKNOWN_READER
The specified reader name is not recognized.
Definition: pcsclite.h:89
used by SCardStatus()
Definition: winscard_msg.h:65
#define SCARD_S_SUCCESS
error codes from http://msdn.microsoft.com/en-us/library/aa924526.aspx
Definition: pcsclite.h:80
const SCARD_IO_REQUEST g_rgSCardT0Pci
Protocol Control Information for T=0.
Definition: libpcscspy.c:724
This handles smart card reader communications.
PCSC_API LONG SCardReleaseContext(SCARDCONTEXT hContext)
Destroys a communication context to the PC/SC Resource Manager.
Definition: winscard.c:198
INTERNAL LONG MessageReceiveTimeout(uint32_t command, void *buffer_void, uint64_t buffer_size, int32_t filedes, long timeOut)
Called by the Client to get the reponse from the server or vice-versa.
Definition: winscard_msg.c:166
This handles debugging.
#define SCARD_E_TIMEOUT
The user-specified timeout value has expired.
Definition: pcsclite.h:90
#define SCARD_STATE_UNAWARE
App wants status.
Definition: pcsclite.h:176
#define SCARD_STATE_MUTE
Unresponsive card.
Definition: pcsclite.h:186