pcsc-lite  1.8.13
winscard_clnt.c
Go to the documentation of this file.
1 /*
2  * MUSCLE SmartCard Development ( http://pcsclite.alioth.debian.org/pcsclite.html )
3  *
4  * Copyright (C) 1999-2004
5  * David Corcoran <corcoran@musclecard.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 Redistribution and use in source and binary forms, with or without
16 modification, are permitted provided that the following conditions
17 are met:
18 
19 1. Redistributions of source code must retain the above copyright
20  notice, this list of conditions and the following disclaimer.
21 2. Redistributions in binary form must reproduce the above copyright
22  notice, this list of conditions and the following disclaimer in the
23  documentation and/or other materials provided with the distribution.
24 3. The name of the author may not be used to endorse or promote products
25  derived from this software without specific prior written permission.
26 
27 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
28 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
29 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
30 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
31 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
32 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
36 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37  *
38  * $Id: winscard_clnt.c 7004 2014-10-02 09:26:36Z rousseau $
39  */
40 
101 #include "config.h"
102 #include <stdlib.h>
103 #include <string.h>
104 #include <sys/types.h>
105 #include <fcntl.h>
106 #include <unistd.h>
107 #include <sys/un.h>
108 #include <errno.h>
109 #include <stddef.h>
110 #include <sys/time.h>
111 #include <pthread.h>
112 #include <sys/wait.h>
113 
114 #include "misc.h"
115 #include "pcscd.h"
116 #include "winscard.h"
117 #include "debuglog.h"
118 #include "strlcpycat.h"
119 
120 #include "readerfactory.h"
121 #include "eventhandler.h"
122 #include "sys_generic.h"
123 #include "winscard_msg.h"
124 #include "utils.h"
125 
126 /* Display, on stderr, a trace of the WinSCard calls with arguments and
127  * results */
128 #undef DO_TRACE
129 
130 /* Profile the execution time of WinSCard calls */
131 #undef DO_PROFILE
132 
133 
135 #define SCARD_PROTOCOL_ANY_OLD 0x1000
136 
137 #ifndef TRUE
138 #define TRUE 1
139 #define FALSE 0
140 #endif
141 
142 static char sharing_shall_block = TRUE;
143 
144 #define COLOR_RED "\33[01;31m"
145 #define COLOR_GREEN "\33[32m"
146 #define COLOR_BLUE "\33[34m"
147 #define COLOR_MAGENTA "\33[35m"
148 #define COLOR_NORMAL "\33[0m"
149 
150 #ifdef DO_TRACE
151 
152 #include <stdio.h>
153 #include <stdarg.h>
154 
155 static void trace(const char *func, const char direction, const char *fmt, ...)
156 {
157  va_list args;
158 
159  fprintf(stderr, COLOR_GREEN "%c " COLOR_BLUE "[%lX] " COLOR_GREEN "%s ",
160  direction, pthread_self(), func);
161 
162  fprintf(stderr, COLOR_MAGENTA);
163  va_start(args, fmt);
164  vfprintf(stderr, fmt, args);
165  va_end(args);
166 
167  fprintf(stderr, COLOR_NORMAL "\n");
168 }
169 
170 #define API_TRACE_IN(...) trace(__FUNCTION__, '<', __VA_ARGS__);
171 #define API_TRACE_OUT(...) trace(__FUNCTION__, '>', __VA_ARGS__);
172 #else
173 #define API_TRACE_IN(...)
174 #define API_TRACE_OUT(...)
175 #endif
176 
177 #ifdef DO_PROFILE
178 
179 #define PROFILE_FILE "/tmp/pcsc_profile"
180 #include <stdio.h>
181 #include <sys/time.h>
182 
183 /* we can profile a maximum of 5 simultaneous calls */
184 #define MAX_THREADS 5
185 pthread_t threads[MAX_THREADS];
186 struct timeval profile_time_start[MAX_THREADS];
187 FILE *profile_fd;
188 char profile_tty;
189 
190 #define PROFILE_START profile_start();
191 #define PROFILE_END(rv) profile_end(__FUNCTION__, rv);
192 
193 static void profile_start(void)
194 {
195  static char initialized = FALSE;
196  pthread_t t;
197  int i;
198 
199  if (!initialized)
200  {
201  char filename[80];
202 
203  initialized = TRUE;
204  sprintf(filename, "%s-%d", PROFILE_FILE, getuid());
205  profile_fd = fopen(filename, "a+");
206  if (NULL == profile_fd)
207  {
208  fprintf(stderr, COLOR_RED "Can't open %s: %s" COLOR_NORMAL "\n",
209  PROFILE_FILE, strerror(errno));
210  exit(-1);
211  }
212  fprintf(profile_fd, "\nStart a new profile\n");
213 
214  if (isatty(fileno(stderr)))
215  profile_tty = TRUE;
216  else
217  profile_tty = FALSE;
218  }
219 
220  t = pthread_self();
221  for (i=0; i<MAX_THREADS; i++)
222  if (pthread_equal(0, threads[i]))
223  {
224  threads[i] = t;
225  break;
226  }
227 
228  gettimeofday(&profile_time_start[i], NULL);
229 } /* profile_start */
230 
231 static void profile_end(const char *f, LONG rv)
232 {
233  struct timeval profile_time_end;
234  long d;
235  pthread_t t;
236  int i;
237 
238  gettimeofday(&profile_time_end, NULL);
239 
240  t = pthread_self();
241  for (i=0; i<MAX_THREADS; i++)
242  if (pthread_equal(t, threads[i]))
243  break;
244 
245  if (i>=MAX_THREADS)
246  {
247  fprintf(stderr, COLOR_BLUE " WARNING: no start info for %s\n", f);
248  return;
249  }
250 
251  d = time_sub(&profile_time_end, &profile_time_start[i]);
252 
253  /* free this entry */
254  threads[i] = 0;
255 
256  if (profile_tty)
257  {
258  if (rv != SCARD_S_SUCCESS)
259  fprintf(stderr,
260  COLOR_RED "RESULT %s " COLOR_MAGENTA "%ld "
261  COLOR_BLUE "0x%08lX %s" COLOR_NORMAL "\n",
262  f, d, rv, pcsc_stringify_error(rv));
263  else
264  fprintf(stderr, COLOR_RED "RESULT %s " COLOR_MAGENTA "%ld"
265  COLOR_NORMAL "\n", f, d);
266  }
267  fprintf(profile_fd, "%s %ld\n", f, d);
268  fflush(profile_fd);
269 } /* profile_end */
270 
271 #else
272 #define PROFILE_START
273 #define PROFILE_END(rv)
274 #endif
275 
281 {
282  SCARDHANDLE hCard;
283  LPSTR readerName;
284 };
285 
286 typedef struct _psChannelMap CHANNEL_MAP;
287 
288 static int CHANNEL_MAP_seeker(const void *el, const void *key)
289 {
290  const CHANNEL_MAP * channelMap = el;
291 
292  if ((el == NULL) || (key == NULL))
293  {
294  Log3(PCSC_LOG_CRITICAL,
295  "CHANNEL_MAP_seeker called with NULL pointer: el=%p, key=%p",
296  el, key);
297  return 0;
298  }
299 
300  if (channelMap->hCard == *(SCARDHANDLE *)key)
301  return 1;
302 
303  return 0;
304 }
305 
312 {
313  DWORD dwClientID;
315  pthread_mutex_t mMutex;
316  list_t channelMapList;
317  char cancellable;
318 };
319 typedef struct _psContextMap SCONTEXTMAP;
320 
321 static list_t contextMapList;
322 
323 static int SCONTEXTMAP_seeker(const void *el, const void *key)
324 {
325  const SCONTEXTMAP * contextMap = el;
326 
327  if ((el == NULL) || (key == NULL))
328  {
329  Log3(PCSC_LOG_CRITICAL,
330  "SCONTEXTMAP_seeker called with NULL pointer: el=%p, key=%p",
331  el, key);
332  return 0;
333  }
334 
335  if (contextMap->hContext == *(SCARDCONTEXT *) key)
336  return 1;
337 
338  return 0;
339 }
340 
344 static short isExecuted = 0;
345 
346 
351 static pthread_mutex_t clientMutex = PTHREAD_MUTEX_INITIALIZER;
352 
357 
364 
365 
366 static LONG SCardAddContext(SCARDCONTEXT, DWORD);
369 static LONG SCardRemoveContext(SCARDCONTEXT);
370 static LONG SCardCleanContext(SCONTEXTMAP *);
371 
372 static LONG SCardAddHandle(SCARDHANDLE, SCONTEXTMAP *, LPCSTR);
373 static LONG SCardGetContextAndChannelFromHandle(SCARDHANDLE,
374  /*@out@*/ SCONTEXTMAP * *, /*@out@*/ CHANNEL_MAP * *);
375 static LONG SCardGetContextAndChannelFromHandleTH(SCARDHANDLE,
376  /*@out@*/ SCONTEXTMAP * *, /*@out@*/ CHANNEL_MAP * *);
377 static LONG SCardRemoveHandle(SCARDHANDLE);
378 
379 static LONG SCardGetSetAttrib(SCARDHANDLE hCard, int command, DWORD dwAttrId,
380  LPBYTE pbAttr, LPDWORD pcbAttrLen);
381 
382 static LONG getReaderStates(SCONTEXTMAP * currentContextMap);
383 
384 /*
385  * Thread safety functions
386  */
393 inline static LONG SCardLockThread(void)
394 {
395  return pthread_mutex_lock(&clientMutex);
396 }
397 
403 inline static LONG SCardUnlockThread(void)
404 {
405  return pthread_mutex_unlock(&clientMutex);
406 }
407 
408 static LONG SCardEstablishContextTH(DWORD, LPCVOID, LPCVOID,
409  /*@out@*/ LPSCARDCONTEXT);
410 
444 LONG SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1,
445  LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
446 {
447  LONG rv;
448 
449  API_TRACE_IN("%ld, %p, %p", dwScope, pvReserved1, pvReserved2)
450  PROFILE_START
451 
452  /* Check if the server is running */
454  if (SCARD_E_INVALID_HANDLE == rv)
455  /* we reconnected to a daemon or we got called from a forked child */
457 
458  if (rv != SCARD_S_SUCCESS)
459  goto end;
460 
461  (void)SCardLockThread();
462  rv = SCardEstablishContextTH(dwScope, pvReserved1,
463  pvReserved2, phContext);
464  (void)SCardUnlockThread();
465 
466 end:
467  PROFILE_END(rv)
468  API_TRACE_OUT("%ld", *phContext)
469 
470  return rv;
471 }
472 
499 static LONG SCardEstablishContextTH(DWORD dwScope,
500  /*@unused@*/ LPCVOID pvReserved1,
501  /*@unused@*/ LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
502 {
503  LONG rv;
504  struct establish_struct scEstablishStruct;
505  uint32_t dwClientID = 0;
506 
507  (void)pvReserved1;
508  (void)pvReserved2;
509  if (phContext == NULL)
511  else
512  *phContext = 0;
513 
514  /*
515  * Do this only once:
516  * - Initialize context list.
517  */
518  if (isExecuted == 0)
519  {
520  int lrv;
521 
522  /* NOTE: The list will never be freed (No API call exists to
523  * "close all contexts".
524  * Applications which load and unload the library will leak
525  * the list's internal structures. */
526  lrv = list_init(&contextMapList);
527  if (lrv < 0)
528  {
529  Log2(PCSC_LOG_CRITICAL, "list_init failed with return value: %d",
530  lrv);
531  return SCARD_E_NO_MEMORY;
532  }
533 
534  lrv = list_attributes_seeker(&contextMapList,
535  SCONTEXTMAP_seeker);
536  if (lrv <0)
537  {
538  Log2(PCSC_LOG_CRITICAL,
539  "list_attributes_seeker failed with return value: %d", lrv);
540  list_destroy(&contextMapList);
541  return SCARD_E_NO_MEMORY;
542  }
543 
544  if (getenv("PCSCLITE_NO_BLOCKING"))
545  {
546  Log1(PCSC_LOG_INFO, "Disable shared blocking");
547  sharing_shall_block = FALSE;
548  }
549 
550  isExecuted = 1;
551  }
552 
553 
554  /* Establishes a connection to the server */
555  if (ClientSetupSession(&dwClientID) != 0)
556  {
557  return SCARD_E_NO_SERVICE;
558  }
559 
560  { /* exchange client/server protocol versions */
561  struct version_struct veStr;
562 
565  veStr.rv = SCARD_S_SUCCESS;
566 
567  rv = MessageSendWithHeader(CMD_VERSION, dwClientID, sizeof(veStr),
568  &veStr);
569  if (rv != SCARD_S_SUCCESS)
570  return rv;
571 
572  /* Read a message from the server */
573  rv = MessageReceive(&veStr, sizeof(veStr), dwClientID);
574  if (rv != SCARD_S_SUCCESS)
575  {
576  Log1(PCSC_LOG_CRITICAL,
577  "Your pcscd is too old and does not support CMD_VERSION");
578  return SCARD_F_COMM_ERROR;
579  }
580 
581  Log3(PCSC_LOG_INFO, "Server is protocol version %d:%d",
582  veStr.major, veStr.minor);
583 
584  if (veStr.rv != SCARD_S_SUCCESS)
585  return veStr.rv;
586  }
587 
588 again:
589  /*
590  * Try to establish an Application Context with the server
591  */
592  scEstablishStruct.dwScope = dwScope;
593  scEstablishStruct.hContext = 0;
594  scEstablishStruct.rv = SCARD_S_SUCCESS;
595 
597  sizeof(scEstablishStruct), (void *) &scEstablishStruct);
598 
599  if (rv != SCARD_S_SUCCESS)
600  return rv;
601 
602  /*
603  * Read the response from the server
604  */
605  rv = MessageReceive(&scEstablishStruct, sizeof(scEstablishStruct),
606  dwClientID);
607 
608  if (rv != SCARD_S_SUCCESS)
609  return rv;
610 
611  if (scEstablishStruct.rv != SCARD_S_SUCCESS)
612  return scEstablishStruct.rv;
613 
614  /* check we do not reuse an existing hContext */
615  if (NULL != SCardGetContextTH(scEstablishStruct.hContext))
616  /* we do not need to release the allocated context since
617  * SCardReleaseContext() does nothing on the server side */
618  goto again;
619 
620  *phContext = scEstablishStruct.hContext;
621 
622  /*
623  * Allocate the new hContext - if allocator full return an error
624  */
625  rv = SCardAddContext(*phContext, dwClientID);
626 
627  return rv;
628 }
629 
652 {
653  LONG rv;
654  struct release_struct scReleaseStruct;
655  SCONTEXTMAP * currentContextMap;
656 
657  API_TRACE_IN("%ld", hContext)
658  PROFILE_START
659 
660  /*
661  * Make sure this context has been opened
662  * and get currentContextMap
663  */
664  currentContextMap = SCardGetContext(hContext);
665  if (NULL == currentContextMap)
666  {
668  goto error;
669  }
670 
671  (void)pthread_mutex_lock(&currentContextMap->mMutex);
672 
673  /* check the context is still opened */
674  currentContextMap = SCardGetContext(hContext);
675  if (NULL == currentContextMap)
676  /* the hContext context is now invalid
677  * -> another thread may have called SCardReleaseContext
678  * so the mMutex has been unlocked */
679  {
681  goto error;
682  }
683 
684  scReleaseStruct.hContext = hContext;
685  scReleaseStruct.rv = SCARD_S_SUCCESS;
686 
688  currentContextMap->dwClientID,
689  sizeof(scReleaseStruct), (void *) &scReleaseStruct);
690 
691  if (rv != SCARD_S_SUCCESS)
692  goto end;
693 
694  /*
695  * Read a message from the server
696  */
697  rv = MessageReceive(&scReleaseStruct, sizeof(scReleaseStruct),
698  currentContextMap->dwClientID);
699 
700  if (rv != SCARD_S_SUCCESS)
701  goto end;
702 
703  rv = scReleaseStruct.rv;
704 end:
705  (void)pthread_mutex_unlock(&currentContextMap->mMutex);
706 
707  /*
708  * Remove the local context from the stack
709  */
710  (void)SCardLockThread();
711  (void)SCardRemoveContext(hContext);
712  (void)SCardUnlockThread();
713 
714 error:
715  PROFILE_END(rv)
716  API_TRACE_OUT("")
717 
718  return rv;
719 }
720 
777 LONG SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader,
778  DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard,
779  LPDWORD pdwActiveProtocol)
780 {
781  LONG rv;
782  struct connect_struct scConnectStruct;
783  SCONTEXTMAP * currentContextMap;
784 
785  PROFILE_START
786  API_TRACE_IN("%ld %s %ld %ld", hContext, szReader, dwShareMode, dwPreferredProtocols)
787 
788  /*
789  * Check for NULL parameters
790  */
791  if (phCard == NULL || pdwActiveProtocol == NULL)
793  else
794  *phCard = 0;
795 
796  if (szReader == NULL)
797  return SCARD_E_UNKNOWN_READER;
798 
799  /*
800  * Check for uninitialized strings
801  */
802  if (strlen(szReader) > MAX_READERNAME)
803  return SCARD_E_INVALID_VALUE;
804 
805  /*
806  * Make sure this context has been opened
807  */
808  currentContextMap = SCardGetContext(hContext);
809  if (NULL == currentContextMap)
810  return SCARD_E_INVALID_HANDLE;
811 
812  (void)pthread_mutex_lock(&currentContextMap->mMutex);
813 
814  /* check the context is still opened */
815  currentContextMap = SCardGetContext(hContext);
816  if (NULL == currentContextMap)
817  /* the hContext context is now invalid
818  * -> another thread may have called SCardReleaseContext
819  * so the mMutex has been unlocked */
820  return SCARD_E_INVALID_HANDLE;
821 
822  strlcpy(scConnectStruct.szReader, szReader, sizeof scConnectStruct.szReader);
823 
824  scConnectStruct.hContext = hContext;
825  scConnectStruct.dwShareMode = dwShareMode;
826  scConnectStruct.dwPreferredProtocols = dwPreferredProtocols;
827  scConnectStruct.hCard = 0;
828  scConnectStruct.dwActiveProtocol = 0;
829  scConnectStruct.rv = SCARD_S_SUCCESS;
830 
831  rv = MessageSendWithHeader(SCARD_CONNECT, currentContextMap->dwClientID,
832  sizeof(scConnectStruct), (void *) &scConnectStruct);
833 
834  if (rv != SCARD_S_SUCCESS)
835  goto end;
836 
837  /*
838  * Read a message from the server
839  */
840  rv = MessageReceive(&scConnectStruct, sizeof(scConnectStruct),
841  currentContextMap->dwClientID);
842 
843  if (rv != SCARD_S_SUCCESS)
844  goto end;
845 
846  *phCard = scConnectStruct.hCard;
847  *pdwActiveProtocol = scConnectStruct.dwActiveProtocol;
848 
849  if (scConnectStruct.rv == SCARD_S_SUCCESS)
850  {
851  /*
852  * Keep track of the handle locally
853  */
854  rv = SCardAddHandle(*phCard, currentContextMap, szReader);
855  }
856  else
857  rv = scConnectStruct.rv;
858 
859 end:
860  (void)pthread_mutex_unlock(&currentContextMap->mMutex);
861 
862  PROFILE_END(rv)
863  API_TRACE_OUT("%d", *pdwActiveProtocol)
864 
865  return rv;
866 }
867 
941 LONG SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode,
942  DWORD dwPreferredProtocols, DWORD dwInitialization,
943  LPDWORD pdwActiveProtocol)
944 {
945  LONG rv;
946  struct reconnect_struct scReconnectStruct;
947  SCONTEXTMAP * currentContextMap;
948  CHANNEL_MAP * pChannelMap;
949 
950  PROFILE_START
951 
952  if (pdwActiveProtocol == NULL)
954 
955  /*
956  * Make sure this handle has been opened
957  */
958  rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
959  &pChannelMap);
960  if (rv == -1)
961  return SCARD_E_INVALID_HANDLE;
962 
963  /* Retry loop for blocking behaviour */
964 retry:
965 
966  (void)pthread_mutex_lock(&currentContextMap->mMutex);
967 
968  /* check the handle is still valid */
969  rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
970  &pChannelMap);
971  if (rv == -1)
972  {
973  /* the hCard handle is now invalid
974  * -> another thread may have called SCardReleaseContext
975  * so the mMutex has been unlocked (and is now invalid)
976  * -> another thread may have called SCardDisconnect
977  * so the mMutex is STILL locked
978  * since we don't know just unlock the mutex */
979  (void)pthread_mutex_unlock(&currentContextMap->mMutex);
980  return SCARD_E_INVALID_HANDLE;
981  }
982 
983  scReconnectStruct.hCard = hCard;
984  scReconnectStruct.dwShareMode = dwShareMode;
985  scReconnectStruct.dwPreferredProtocols = dwPreferredProtocols;
986  scReconnectStruct.dwInitialization = dwInitialization;
987  scReconnectStruct.dwActiveProtocol = *pdwActiveProtocol;
988  scReconnectStruct.rv = SCARD_S_SUCCESS;
989 
990  rv = MessageSendWithHeader(SCARD_RECONNECT, currentContextMap->dwClientID,
991  sizeof(scReconnectStruct), (void *) &scReconnectStruct);
992 
993  if (rv != SCARD_S_SUCCESS)
994  goto end;
995 
996  /*
997  * Read a message from the server
998  */
999  rv = MessageReceive(&scReconnectStruct, sizeof(scReconnectStruct),
1000  currentContextMap->dwClientID);
1001 
1002  if (rv != SCARD_S_SUCCESS)
1003  goto end;
1004 
1005  rv = scReconnectStruct.rv;
1006 
1007  if (sharing_shall_block && (SCARD_E_SHARING_VIOLATION == rv))
1008  {
1009  (void)pthread_mutex_unlock(&currentContextMap->mMutex);
1011  goto retry;
1012  }
1013 
1014  *pdwActiveProtocol = scReconnectStruct.dwActiveProtocol;
1015 
1016 end:
1017  (void)pthread_mutex_unlock(&currentContextMap->mMutex);
1018 
1019  PROFILE_END(rv)
1020 
1021  return rv;
1022 }
1023 
1055 LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
1056 {
1057  LONG rv;
1058  struct disconnect_struct scDisconnectStruct;
1059  SCONTEXTMAP * currentContextMap;
1060  CHANNEL_MAP * pChannelMap;
1061 
1062  PROFILE_START
1063  API_TRACE_IN("%ld %ld", hCard, dwDisposition)
1064 
1065  /*
1066  * Make sure this handle has been opened
1067  */
1068  rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
1069  &pChannelMap);
1070  if (rv == -1)
1071  {
1073  goto error;
1074  }
1075 
1076  (void)pthread_mutex_lock(&currentContextMap->mMutex);
1077 
1078  /* check the handle is still valid */
1079  rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
1080  &pChannelMap);
1081  if (rv == -1)
1082  /* the hCard handle is now invalid
1083  * -> another thread may have called SCardReleaseContext
1084  * so the mMutex has been unlocked (and is now invalid)
1085  * -> another thread may have called SCardDisconnect
1086  * so the mMutex is STILL locked
1087  * since we don't know just unlock the mutex */
1088  {
1089  (void)pthread_mutex_unlock(&currentContextMap->mMutex);
1091  goto error;
1092  }
1093 
1094  scDisconnectStruct.hCard = hCard;
1095  scDisconnectStruct.dwDisposition = dwDisposition;
1096  scDisconnectStruct.rv = SCARD_S_SUCCESS;
1097 
1098  rv = MessageSendWithHeader(SCARD_DISCONNECT, currentContextMap->dwClientID,
1099  sizeof(scDisconnectStruct), (void *) &scDisconnectStruct);
1100 
1101  if (rv != SCARD_S_SUCCESS)
1102  goto end;
1103 
1104  /*
1105  * Read a message from the server
1106  */
1107  rv = MessageReceive(&scDisconnectStruct, sizeof(scDisconnectStruct),
1108  currentContextMap->dwClientID);
1109 
1110  if (rv != SCARD_S_SUCCESS)
1111  goto end;
1112 
1113  if (SCARD_S_SUCCESS == scDisconnectStruct.rv)
1114  (void)SCardRemoveHandle(hCard);
1115  rv = scDisconnectStruct.rv;
1116 
1117 end:
1118  (void)pthread_mutex_unlock(&currentContextMap->mMutex);
1119 
1120 error:
1121  PROFILE_END(rv)
1122  API_TRACE_OUT("")
1123 
1124  return rv;
1125 }
1126 
1163 {
1164 
1165  LONG rv;
1166  struct begin_struct scBeginStruct;
1167  SCONTEXTMAP * currentContextMap;
1168  CHANNEL_MAP * pChannelMap;
1169 
1170  PROFILE_START
1171 
1172  /*
1173  * Make sure this handle has been opened
1174  */
1175  rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
1176  &pChannelMap);
1177  if (rv == -1)
1178  return SCARD_E_INVALID_HANDLE;
1179 
1180  /*
1181  * Query the server every so often until the sharing violation ends
1182  * and then hold the lock for yourself.
1183  */
1184 
1185  for(;;)
1186  {
1187  (void)pthread_mutex_lock(&currentContextMap->mMutex);
1188 
1189  /* check the handle is still valid */
1190  rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
1191  &pChannelMap);
1192  if (rv == -1)
1193  {
1194  /* the hCard handle is now invalid
1195  * -> another thread may have called SCardReleaseContext
1196  * so the mMutex has been unlocked (and is now invalid)
1197  * -> another thread may have called SCardDisconnect
1198  * so the mMutex is STILL locked
1199  * since we don't know just unlock the mutex */
1200  (void)pthread_mutex_unlock(&currentContextMap->mMutex);
1201  return SCARD_E_INVALID_HANDLE;
1202  }
1203 
1204  scBeginStruct.hCard = hCard;
1205  scBeginStruct.rv = SCARD_S_SUCCESS;
1206 
1208  currentContextMap->dwClientID,
1209  sizeof(scBeginStruct), (void *) &scBeginStruct);
1210 
1211  if (rv != SCARD_S_SUCCESS)
1212  break;
1213 
1214  /*
1215  * Read a message from the server
1216  */
1217  rv = MessageReceive(&scBeginStruct, sizeof(scBeginStruct),
1218  currentContextMap->dwClientID);
1219 
1220  if (rv != SCARD_S_SUCCESS)
1221  break;
1222 
1223  rv = scBeginStruct.rv;
1224 
1225  if (SCARD_E_SHARING_VIOLATION != rv)
1226  break;
1227 
1228  (void)pthread_mutex_unlock(&currentContextMap->mMutex);
1230  }
1231 
1232  (void)pthread_mutex_unlock(&currentContextMap->mMutex);
1233 
1234  PROFILE_END(rv)
1235 
1236  return rv;
1237 }
1238 
1279 LONG SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
1280 {
1281  LONG rv;
1282  struct end_struct scEndStruct;
1283  int randnum;
1284  SCONTEXTMAP * currentContextMap;
1285  CHANNEL_MAP * pChannelMap;
1286 
1287  PROFILE_START
1288 
1289  /*
1290  * Make sure this handle has been opened
1291  */
1292  rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
1293  &pChannelMap);
1294  if (rv == -1)
1295  return SCARD_E_INVALID_HANDLE;
1296 
1297  (void)pthread_mutex_lock(&currentContextMap->mMutex);
1298 
1299  /* check the handle is still valid */
1300  rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
1301  &pChannelMap);
1302  if (rv == -1)
1303  {
1304  /* the hCard handle is now invalid
1305  * -> another thread may have called SCardReleaseContext
1306  * so the mMutex has been unlocked (and is now invalid)
1307  * -> another thread may have called SCardDisconnect
1308  * so the mMutex is STILL locked
1309  * since we don't know just unlock the mutex */
1310  (void)pthread_mutex_unlock(&currentContextMap->mMutex);
1311  return SCARD_E_INVALID_HANDLE;
1312  }
1313 
1314  scEndStruct.hCard = hCard;
1315  scEndStruct.dwDisposition = dwDisposition;
1316  scEndStruct.rv = SCARD_S_SUCCESS;
1317 
1319  currentContextMap->dwClientID,
1320  sizeof(scEndStruct), (void *) &scEndStruct);
1321 
1322  if (rv != SCARD_S_SUCCESS)
1323  goto end;
1324 
1325  /*
1326  * Read a message from the server
1327  */
1328  rv = MessageReceive(&scEndStruct, sizeof(scEndStruct),
1329  currentContextMap->dwClientID);
1330 
1331  if (rv != SCARD_S_SUCCESS)
1332  goto end;
1333 
1334  /*
1335  * This helps prevent starvation
1336  */
1337  randnum = SYS_RandomInt(1000, 10000);
1338  (void)SYS_USleep(randnum);
1339  rv = scEndStruct.rv;
1340 
1341 end:
1342  (void)pthread_mutex_unlock(&currentContextMap->mMutex);
1343 
1344  PROFILE_END(rv)
1345 
1346  return rv;
1347 }
1348 
1444 LONG SCardStatus(SCARDHANDLE hCard, LPSTR mszReaderName,
1445  LPDWORD pcchReaderLen, LPDWORD pdwState,
1446  LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
1447 {
1448  DWORD dwReaderLen, dwAtrLen;
1449  LONG rv;
1450  int i;
1451  struct status_struct scStatusStruct;
1452  SCONTEXTMAP * currentContextMap;
1453  CHANNEL_MAP * pChannelMap;
1454  char *r;
1455  char *bufReader = NULL;
1456  LPBYTE bufAtr = NULL;
1457  DWORD dummy = 0;
1458 
1459  PROFILE_START
1460 
1461  /* default output values */
1462  if (pdwState)
1463  *pdwState = 0;
1464 
1465  if (pdwProtocol)
1466  *pdwProtocol = 0;
1467 
1468  /* Check for NULL parameters */
1469  if (pcchReaderLen == NULL)
1470  pcchReaderLen = &dummy;
1471 
1472  if (pcbAtrLen == NULL)
1473  pcbAtrLen = &dummy;
1474 
1475  /* length passed from caller */
1476  dwReaderLen = *pcchReaderLen;
1477  dwAtrLen = *pcbAtrLen;
1478 
1479  *pcchReaderLen = 0;
1480  *pcbAtrLen = 0;
1481 
1482  /*
1483  * Make sure this handle has been opened
1484  */
1485  rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
1486  &pChannelMap);
1487  if (rv == -1)
1488  return SCARD_E_INVALID_HANDLE;
1489 
1490  /* Retry loop for blocking behaviour */
1491 retry:
1492 
1493  (void)pthread_mutex_lock(&currentContextMap->mMutex);
1494 
1495  /* check the handle is still valid */
1496  rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
1497  &pChannelMap);
1498  if (rv == -1)
1499  {
1500  /* the hCard handle is now invalid
1501  * -> another thread may have called SCardReleaseContext
1502  * so the mMutex has been unlocked (and is now invalid)
1503  * -> another thread may have called SCardDisconnect
1504  * so the mMutex is STILL locked
1505  * since we don't know just unlock the mutex */
1506  (void)pthread_mutex_unlock(&currentContextMap->mMutex);
1507  return SCARD_E_INVALID_HANDLE;
1508  }
1509 
1510  /* synchronize reader states with daemon */
1511  rv = getReaderStates(currentContextMap);
1512  if (rv != SCARD_S_SUCCESS)
1513  goto end;
1514 
1515  r = pChannelMap->readerName;
1516  for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
1517  {
1518  /* by default r == NULL */
1519  if (r && strcmp(r, readerStates[i].readerName) == 0)
1520  break;
1521  }
1522 
1523  if (i == PCSCLITE_MAX_READERS_CONTEXTS)
1524  {
1526  goto end;
1527  }
1528 
1529  /* initialise the structure */
1530  memset(&scStatusStruct, 0, sizeof(scStatusStruct));
1531  scStatusStruct.hCard = hCard;
1532 
1533  rv = MessageSendWithHeader(SCARD_STATUS, currentContextMap->dwClientID,
1534  sizeof(scStatusStruct), (void *) &scStatusStruct);
1535 
1536  if (rv != SCARD_S_SUCCESS)
1537  goto end;
1538 
1539  /*
1540  * Read a message from the server
1541  */
1542  rv = MessageReceive(&scStatusStruct, sizeof(scStatusStruct),
1543  currentContextMap->dwClientID);
1544 
1545  if (rv != SCARD_S_SUCCESS)
1546  goto end;
1547 
1548  rv = scStatusStruct.rv;
1549 
1550  if (sharing_shall_block && (SCARD_E_SHARING_VIOLATION == rv))
1551  {
1552  (void)pthread_mutex_unlock(&currentContextMap->mMutex);
1554  goto retry;
1555  }
1556 
1557  if (rv != SCARD_S_SUCCESS && rv != SCARD_E_INSUFFICIENT_BUFFER)
1558  {
1559  /*
1560  * An event must have occurred
1561  */
1562  goto end;
1563  }
1564 
1565  /*
1566  * Now continue with the client side SCardStatus
1567  */
1568 
1569  *pcchReaderLen = strlen(pChannelMap->readerName) + 1;
1570  *pcbAtrLen = readerStates[i].cardAtrLength;
1571 
1572  if (pdwState)
1573  *pdwState = (readerStates[i].eventCounter << 16) + readerStates[i].readerState;
1574 
1575  if (pdwProtocol)
1576  *pdwProtocol = readerStates[i].cardProtocol;
1577 
1578  if (SCARD_AUTOALLOCATE == dwReaderLen)
1579  {
1580  dwReaderLen = *pcchReaderLen;
1581  if (NULL == mszReaderName)
1582  {
1584  goto end;
1585  }
1586  bufReader = malloc(dwReaderLen);
1587  if (NULL == bufReader)
1588  {
1589  rv = SCARD_E_NO_MEMORY;
1590  goto end;
1591  }
1592  *(char **)mszReaderName = bufReader;
1593  }
1594  else
1595  bufReader = mszReaderName;
1596 
1597  /* return SCARD_E_INSUFFICIENT_BUFFER only if buffer pointer is non NULL */
1598  if (bufReader)
1599  {
1600  if (*pcchReaderLen > dwReaderLen)
1602 
1603  strncpy(bufReader, pChannelMap->readerName, dwReaderLen);
1604  }
1605 
1606  if (SCARD_AUTOALLOCATE == dwAtrLen)
1607  {
1608  dwAtrLen = *pcbAtrLen;
1609  if (NULL == pbAtr)
1610  {
1612  goto end;
1613  }
1614  bufAtr = malloc(dwAtrLen);
1615  if (NULL == bufAtr)
1616  {
1617  rv = SCARD_E_NO_MEMORY;
1618  goto end;
1619  }
1620  *(LPBYTE *)pbAtr = bufAtr;
1621  }
1622  else
1623  bufAtr = pbAtr;
1624 
1625  if (bufAtr)
1626  {
1627  if (*pcbAtrLen > dwAtrLen)
1629 
1630  memcpy(bufAtr, readerStates[i].cardAtr, min(*pcbAtrLen, dwAtrLen));
1631  }
1632 
1633 end:
1634  (void)pthread_mutex_unlock(&currentContextMap->mMutex);
1635 
1636  PROFILE_END(rv)
1637 
1638  return rv;
1639 }
1640 
1734 LONG SCardGetStatusChange(SCARDCONTEXT hContext, DWORD dwTimeout,
1735  SCARD_READERSTATE *rgReaderStates, DWORD cReaders)
1736 {
1737  SCARD_READERSTATE *currReader;
1738  READER_STATE *rContext;
1739  long dwTime;
1740  DWORD dwBreakFlag = 0;
1741  unsigned int j;
1742  SCONTEXTMAP * currentContextMap;
1743  int currentReaderCount = 0;
1744  LONG rv = SCARD_S_SUCCESS;
1745 
1746  PROFILE_START
1747  API_TRACE_IN("%ld %ld %d", hContext, dwTimeout, cReaders)
1748 #ifdef DO_TRACE
1749  for (j=0; j<cReaders; j++)
1750  {
1751  API_TRACE_IN("[%d] %s %lX %lX", j, rgReaderStates[j].szReader,
1752  rgReaderStates[j].dwCurrentState, rgReaderStates[j].dwEventState)
1753  }
1754 #endif
1755 
1756  if ((rgReaderStates == NULL && cReaders > 0)
1757  || (cReaders > PCSCLITE_MAX_READERS_CONTEXTS))
1758  {
1760  goto error;
1761  }
1762 
1763  /* Check the integrity of the reader states structures */
1764  for (j = 0; j < cReaders; j++)
1765  {
1766  if (rgReaderStates[j].szReader == NULL)
1767  return SCARD_E_INVALID_VALUE;
1768  }
1769 
1770  /* return if all readers are SCARD_STATE_IGNORE */
1771  if (cReaders > 0)
1772  {
1773  int nbNonIgnoredReaders = cReaders;
1774 
1775  for (j=0; j<cReaders; j++)
1776  if (rgReaderStates[j].dwCurrentState & SCARD_STATE_IGNORE)
1777  nbNonIgnoredReaders--;
1778 
1779  if (0 == nbNonIgnoredReaders)
1780  {
1781  rv = SCARD_S_SUCCESS;
1782  goto error;
1783  }
1784  }
1785  else
1786  {
1787  /* reader list is empty */
1788  rv = SCARD_S_SUCCESS;
1789  goto error;
1790  }
1791 
1792  /*
1793  * Make sure this context has been opened
1794  */
1795  currentContextMap = SCardGetContext(hContext);
1796  if (NULL == currentContextMap)
1797  {
1799  goto error;
1800  }
1801 
1802  (void)pthread_mutex_lock(&currentContextMap->mMutex);
1803 
1804  /* check the context is still opened */
1805  currentContextMap = SCardGetContext(hContext);
1806  if (NULL == currentContextMap)
1807  /* the hContext context is now invalid
1808  * -> another thread may have called SCardReleaseContext
1809  * so the mMutex has been unlocked */
1810  {
1812  goto error;
1813  }
1814 
1815  /* synchronize reader states with daemon */
1816  rv = getReaderStates(currentContextMap);
1817  if (rv != SCARD_S_SUCCESS)
1818  goto end;
1819 
1820  /* check all the readers are already known */
1821  for (j=0; j<cReaders; j++)
1822  {
1823  const char *readerName;
1824  int i;
1825 
1826  readerName = rgReaderStates[j].szReader;
1827  for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
1828  {
1829  if (strcmp(readerName, readerStates[i].readerName) == 0)
1830  break;
1831  }
1832 
1833  /* The requested reader name is not recognized */
1834  if (i == PCSCLITE_MAX_READERS_CONTEXTS)
1835  {
1836  /* PnP special reader? */
1837  if (strcasecmp(readerName, "\\\\?PnP?\\Notification") != 0)
1838  {
1840  goto end;
1841  }
1842  }
1843  }
1844 
1845  /* Clear the event state for all readers */
1846  for (j = 0; j < cReaders; j++)
1847  rgReaderStates[j].dwEventState = 0;
1848 
1849  /* Now is where we start our event checking loop */
1850  Log2(PCSC_LOG_DEBUG, "Event Loop Start, dwTimeout: %ld", dwTimeout);
1851 
1852  /* Get the initial reader count on the system */
1853  for (j=0; j < PCSCLITE_MAX_READERS_CONTEXTS; j++)
1854  if (readerStates[j].readerName[0] != '\0')
1855  currentReaderCount++;
1856 
1857  /* catch possible sign extension problems from 32 to 64-bits integers */
1858  if ((DWORD)-1 == dwTimeout)
1859  dwTimeout = INFINITE;
1860  if (INFINITE == dwTimeout)
1861  dwTime = 60*1000; /* "infinite" timeout */
1862  else
1863  dwTime = dwTimeout;
1864 
1865  j = 0;
1866  do
1867  {
1868  currReader = &rgReaderStates[j];
1869 
1870  /* Ignore for IGNORED readers */
1871  if (!(currReader->dwCurrentState & SCARD_STATE_IGNORE))
1872  {
1873  const char *readerName;
1874  int i;
1875 
1876  /* Looks for correct readernames */
1877  readerName = currReader->szReader;
1878  for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
1879  {
1880  if (strcmp(readerName, readerStates[i].readerName) == 0)
1881  break;
1882  }
1883 
1884  /* The requested reader name is not recognized */
1885  if (i == PCSCLITE_MAX_READERS_CONTEXTS)
1886  {
1887  /* PnP special reader? */
1888  if (strcasecmp(readerName, "\\\\?PnP?\\Notification") == 0)
1889  {
1890  int k, newReaderCount = 0;
1891 
1892  for (k=0; k < PCSCLITE_MAX_READERS_CONTEXTS; k++)
1893  if (readerStates[k].readerName[0] != '\0')
1894  newReaderCount++;
1895 
1896  if (newReaderCount != currentReaderCount)
1897  {
1898  Log1(PCSC_LOG_INFO, "Reader list changed");
1899  currentReaderCount = newReaderCount;
1900 
1901  currReader->dwEventState |= SCARD_STATE_CHANGED;
1902  dwBreakFlag = 1;
1903  }
1904  }
1905  else
1906  {
1907  currReader->dwEventState =
1909  if (!(currReader->dwCurrentState & SCARD_STATE_UNKNOWN))
1910  {
1911  currReader->dwEventState |= SCARD_STATE_CHANGED;
1912  /*
1913  * Spec says use SCARD_STATE_IGNORE but a removed USB
1914  * reader with eventState fed into currentState will
1915  * be ignored forever
1916  */
1917  dwBreakFlag = 1;
1918  }
1919  }
1920  }
1921  else
1922  {
1923  uint32_t readerState;
1924 
1925  /* The reader has come back after being away */
1926  if (currReader->dwCurrentState & SCARD_STATE_UNKNOWN)
1927  {
1928  currReader->dwEventState |= SCARD_STATE_CHANGED;
1929  currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
1930  Log0(PCSC_LOG_DEBUG);
1931  dwBreakFlag = 1;
1932  }
1933 
1934  /* Set the reader status structure */
1935  rContext = &readerStates[i];
1936 
1937  /* Now we check all the Reader States */
1938  readerState = rContext->readerState;
1939 
1940  /* only if current state has an non null event counter */
1941  if (currReader->dwCurrentState & 0xFFFF0000)
1942  {
1943  unsigned int currentCounter;
1944 
1945  currentCounter = (currReader->dwCurrentState >> 16) & 0xFFFF;
1946 
1947  /* has the event counter changed since the last call? */
1948  if (rContext->eventCounter != currentCounter)
1949  {
1950  currReader->dwEventState |= SCARD_STATE_CHANGED;
1951  Log0(PCSC_LOG_DEBUG);
1952  dwBreakFlag = 1;
1953  }
1954  }
1955 
1956  /* add an event counter in the upper word of dwEventState */
1957  currReader->dwEventState = ((currReader->dwEventState & 0xffff )
1958  | (rContext->eventCounter << 16));
1959 
1960  /* Check if the reader is in the correct state */
1961  if (readerState & SCARD_UNKNOWN)
1962  {
1963  /* reader is in bad state */
1964  currReader->dwEventState = SCARD_STATE_UNAVAILABLE;
1965  if (!(currReader->dwCurrentState & SCARD_STATE_UNAVAILABLE))
1966  {
1967  /* App thinks reader is in good state and it is not */
1968  currReader->dwEventState |= SCARD_STATE_CHANGED;
1969  Log0(PCSC_LOG_DEBUG);
1970  dwBreakFlag = 1;
1971  }
1972  }
1973  else
1974  {
1975  /* App thinks reader in bad state but it is not */
1976  if (currReader-> dwCurrentState & SCARD_STATE_UNAVAILABLE)
1977  {
1978  currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
1979  currReader->dwEventState |= SCARD_STATE_CHANGED;
1980  Log0(PCSC_LOG_DEBUG);
1981  dwBreakFlag = 1;
1982  }
1983  }
1984 
1985  /* Check for card presence in the reader */
1986  if (readerState & SCARD_PRESENT)
1987  {
1988  /* card present but not yet powered up */
1989  if (0 == rContext->cardAtrLength)
1990  /* Allow the status thread to convey information */
1992 
1993  currReader->cbAtr = rContext->cardAtrLength;
1994  memcpy(currReader->rgbAtr, rContext->cardAtr,
1995  currReader->cbAtr);
1996  }
1997  else
1998  currReader->cbAtr = 0;
1999 
2000  /* Card is now absent */
2001  if (readerState & SCARD_ABSENT)
2002  {
2003  currReader->dwEventState |= SCARD_STATE_EMPTY;
2004  currReader->dwEventState &= ~SCARD_STATE_PRESENT;
2005  currReader->dwEventState &= ~SCARD_STATE_UNAWARE;
2006  currReader->dwEventState &= ~SCARD_STATE_IGNORE;
2007  currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
2008  currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
2009  currReader->dwEventState &= ~SCARD_STATE_ATRMATCH;
2010  currReader->dwEventState &= ~SCARD_STATE_MUTE;
2011  currReader->dwEventState &= ~SCARD_STATE_INUSE;
2012 
2013  /* After present the rest are assumed */
2014  if (currReader->dwCurrentState & SCARD_STATE_PRESENT)
2015  {
2016  currReader->dwEventState |= SCARD_STATE_CHANGED;
2017  Log0(PCSC_LOG_DEBUG);
2018  dwBreakFlag = 1;
2019  }
2020  }
2021  /* Card is now present */
2022  else if (readerState & SCARD_PRESENT)
2023  {
2024  currReader->dwEventState |= SCARD_STATE_PRESENT;
2025  currReader->dwEventState &= ~SCARD_STATE_EMPTY;
2026  currReader->dwEventState &= ~SCARD_STATE_UNAWARE;
2027  currReader->dwEventState &= ~SCARD_STATE_IGNORE;
2028  currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
2029  currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
2030  currReader->dwEventState &= ~SCARD_STATE_MUTE;
2031 
2032  if (currReader->dwCurrentState & SCARD_STATE_EMPTY)
2033  {
2034  currReader->dwEventState |= SCARD_STATE_CHANGED;
2035  Log0(PCSC_LOG_DEBUG);
2036  dwBreakFlag = 1;
2037  }
2038 
2039  if (readerState & SCARD_SWALLOWED)
2040  {
2041  currReader->dwEventState |= SCARD_STATE_MUTE;
2042  if (!(currReader->dwCurrentState & SCARD_STATE_MUTE))
2043  {
2044  currReader->dwEventState |= SCARD_STATE_CHANGED;
2045  Log0(PCSC_LOG_DEBUG);
2046  dwBreakFlag = 1;
2047  }
2048  }
2049  else
2050  {
2051  /* App thinks card is mute but it is not */
2052  if (currReader->dwCurrentState & SCARD_STATE_MUTE)
2053  {
2054  currReader->dwEventState |= SCARD_STATE_CHANGED;
2055  Log0(PCSC_LOG_DEBUG);
2056  dwBreakFlag = 1;
2057  }
2058  }
2059  }
2060 
2061  /* Now figure out sharing modes */
2063  {
2064  currReader->dwEventState |= SCARD_STATE_EXCLUSIVE;
2065  currReader->dwEventState &= ~SCARD_STATE_INUSE;
2066  if (currReader->dwCurrentState & SCARD_STATE_INUSE)
2067  {
2068  currReader->dwEventState |= SCARD_STATE_CHANGED;
2069  Log0(PCSC_LOG_DEBUG);
2070  dwBreakFlag = 1;
2071  }
2072  }
2073  else if (rContext->readerSharing >= PCSCLITE_SHARING_LAST_CONTEXT)
2074  {
2075  /* A card must be inserted for it to be INUSE */
2076  if (readerState & SCARD_PRESENT)
2077  {
2078  currReader->dwEventState |= SCARD_STATE_INUSE;
2079  currReader->dwEventState &= ~SCARD_STATE_EXCLUSIVE;
2080  if (currReader-> dwCurrentState & SCARD_STATE_EXCLUSIVE)
2081  {
2082  currReader->dwEventState |= SCARD_STATE_CHANGED;
2083  Log0(PCSC_LOG_DEBUG);
2084  dwBreakFlag = 1;
2085  }
2086  }
2087  }
2088  else if (rContext->readerSharing == PCSCLITE_SHARING_NO_CONTEXT)
2089  {
2090  currReader->dwEventState &= ~SCARD_STATE_INUSE;
2091  currReader->dwEventState &= ~SCARD_STATE_EXCLUSIVE;
2092 
2093  if (currReader->dwCurrentState & SCARD_STATE_INUSE)
2094  {
2095  currReader->dwEventState |= SCARD_STATE_CHANGED;
2096  Log0(PCSC_LOG_DEBUG);
2097  dwBreakFlag = 1;
2098  }
2099  else if (currReader-> dwCurrentState
2101  {
2102  currReader->dwEventState |= SCARD_STATE_CHANGED;
2103  Log0(PCSC_LOG_DEBUG);
2104  dwBreakFlag = 1;
2105  }
2106  }
2107 
2108  if (currReader->dwCurrentState == SCARD_STATE_UNAWARE)
2109  {
2110  /*
2111  * Break out of the while .. loop and return status
2112  * once all the status's for all readers is met
2113  */
2114  currReader->dwEventState |= SCARD_STATE_CHANGED;
2115  Log0(PCSC_LOG_DEBUG);
2116  dwBreakFlag = 1;
2117  }
2118  } /* End of SCARD_STATE_UNKNOWN */
2119  } /* End of SCARD_STATE_IGNORE */
2120 
2121  /* Counter and resetter */
2122  j++;
2123  if (j == cReaders)
2124  {
2125  /* go back to the first reader */
2126  j = 0;
2127 
2128  /* Declare all the break conditions */
2129 
2130  /* Break if UNAWARE is set and all readers have been checked */
2131  if (dwBreakFlag == 1)
2132  break;
2133 
2134  /* Only sleep once for each cycle of reader checks. */
2135  {
2136  struct wait_reader_state_change waitStatusStruct;
2137  struct timeval before, after;
2138 
2139  gettimeofday(&before, NULL);
2140 
2141  waitStatusStruct.timeOut = dwTime;
2142  waitStatusStruct.rv = SCARD_S_SUCCESS;
2143 
2144  /* another thread can do SCardCancel() */
2145  currentContextMap->cancellable = TRUE;
2146 
2148  currentContextMap->dwClientID,
2149  sizeof(waitStatusStruct), &waitStatusStruct);
2150 
2151  if (rv != SCARD_S_SUCCESS)
2152  goto end;
2153 
2154  /*
2155  * Read a message from the server
2156  */
2158  &waitStatusStruct, sizeof(waitStatusStruct),
2159  currentContextMap->dwClientID, dwTime);
2160 
2161  /* another thread can do SCardCancel() */
2162  currentContextMap->cancellable = FALSE;
2163 
2164  /* timeout */
2165  if (SCARD_E_TIMEOUT == rv)
2166  {
2167  /* ask server to remove us from the event list */
2169  currentContextMap->dwClientID,
2170  sizeof(waitStatusStruct), &waitStatusStruct);
2171 
2172  if (rv != SCARD_S_SUCCESS)
2173  goto end;
2174 
2175  /* Read a message from the server */
2176  rv = MessageReceive(&waitStatusStruct,
2177  sizeof(waitStatusStruct),
2178  currentContextMap->dwClientID);
2179 
2180  if (rv != SCARD_S_SUCCESS)
2181  goto end;
2182  }
2183 
2184  if (rv != SCARD_S_SUCCESS)
2185  goto end;
2186 
2187  /* an event occurs or SCardCancel() was called */
2188  if (SCARD_S_SUCCESS != waitStatusStruct.rv)
2189  {
2190  rv = waitStatusStruct.rv;
2191  goto end;
2192  }
2193 
2194  /* synchronize reader states with daemon */
2195  rv = getReaderStates(currentContextMap);
2196  if (rv != SCARD_S_SUCCESS)
2197  goto end;
2198 
2199  if (INFINITE != dwTimeout)
2200  {
2201  long int diff;
2202 
2203  gettimeofday(&after, NULL);
2204  diff = time_sub(&after, &before);
2205  dwTime -= diff/1000;
2206  }
2207  }
2208 
2209  if (dwTimeout != INFINITE)
2210  {
2211  /* If time is greater than timeout and all readers have been
2212  * checked
2213  */
2214  if (dwTime <= 0)
2215  {
2216  rv = SCARD_E_TIMEOUT;
2217  goto end;
2218  }
2219  }
2220  }
2221  }
2222  while (1);
2223 
2224 end:
2225  Log1(PCSC_LOG_DEBUG, "Event Loop End");
2226 
2227  (void)pthread_mutex_unlock(&currentContextMap->mMutex);
2228 
2229 error:
2230  PROFILE_END(rv)
2231 #ifdef DO_TRACE
2232  for (j=0; j<cReaders; j++)
2233  {
2234  API_TRACE_OUT("[%d] %s %X %X", j, rgReaderStates[j].szReader,
2235  rgReaderStates[j].dwCurrentState, rgReaderStates[j].dwEventState)
2236  }
2237 #endif
2238 
2239  return rv;
2240 }
2241 
2292 LONG SCardControl(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer,
2293  DWORD cbSendLength, LPVOID pbRecvBuffer, DWORD cbRecvLength,
2294  LPDWORD lpBytesReturned)
2295 {
2296  LONG rv;
2297  struct control_struct scControlStruct;
2298  SCONTEXTMAP * currentContextMap;
2299  CHANNEL_MAP * pChannelMap;
2300 
2301  PROFILE_START
2302 
2303  /* 0 bytes received by default */
2304  if (NULL != lpBytesReturned)
2305  *lpBytesReturned = 0;
2306 
2307  /*
2308  * Make sure this handle has been opened
2309  */
2310  rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
2311  &pChannelMap);
2312  if (rv == -1)
2313  {
2314  PROFILE_END(SCARD_E_INVALID_HANDLE)
2315  return SCARD_E_INVALID_HANDLE;
2316  }
2317 
2318  (void)pthread_mutex_lock(&currentContextMap->mMutex);
2319 
2320  /* check the handle is still valid */
2321  rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
2322  &pChannelMap);
2323  if (rv == -1)
2324  {
2325  /* the hCard handle is now invalid
2326  * -> another thread may have called SCardReleaseContext
2327  * so the mMutex has been unlocked (and is now invalid)
2328  * -> another thread may have called SCardDisconnect
2329  * so the mMutex is STILL locked
2330  * since we don't know just unlock the mutex */
2331  (void)pthread_mutex_unlock(&currentContextMap->mMutex);
2332  return SCARD_E_INVALID_HANDLE;
2333  }
2334 
2335  if ((cbSendLength > MAX_BUFFER_SIZE_EXTENDED)
2336  || (cbRecvLength > MAX_BUFFER_SIZE_EXTENDED))
2337  {
2339  goto end;
2340  }
2341 
2342  scControlStruct.hCard = hCard;
2343  scControlStruct.dwControlCode = dwControlCode;
2344  scControlStruct.cbSendLength = cbSendLength;
2345  scControlStruct.cbRecvLength = cbRecvLength;
2346  scControlStruct.dwBytesReturned = 0;
2347  scControlStruct.rv = 0;
2348 
2349  rv = MessageSendWithHeader(SCARD_CONTROL, currentContextMap->dwClientID,
2350  sizeof(scControlStruct), &scControlStruct);
2351 
2352  if (rv != SCARD_S_SUCCESS)
2353  goto end;
2354 
2355  /* write the sent buffer */
2356  rv = MessageSend((char *)pbSendBuffer, cbSendLength,
2357  currentContextMap->dwClientID);
2358 
2359  if (rv != SCARD_S_SUCCESS)
2360  goto end;
2361 
2362  /*
2363  * Read a message from the server
2364  */
2365  rv = MessageReceive(&scControlStruct, sizeof(scControlStruct),
2366  currentContextMap->dwClientID);
2367 
2368  if (rv != SCARD_S_SUCCESS)
2369  goto end;
2370 
2371  if (SCARD_S_SUCCESS == scControlStruct.rv)
2372  {
2373  /* read the received buffer */
2374  rv = MessageReceive(pbRecvBuffer, scControlStruct.dwBytesReturned,
2375  currentContextMap->dwClientID);
2376 
2377  if (rv != SCARD_S_SUCCESS)
2378  goto end;
2379 
2380  }
2381 
2382  if (NULL != lpBytesReturned)
2383  *lpBytesReturned = scControlStruct.dwBytesReturned;
2384 
2385  rv = scControlStruct.rv;
2386 
2387 end:
2388  (void)pthread_mutex_unlock(&currentContextMap->mMutex);
2389 
2390  PROFILE_END(rv)
2391 
2392  return rv;
2393 }
2394 
2499 LONG SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr,
2500  LPDWORD pcbAttrLen)
2501 {
2502  LONG ret;
2503  unsigned char *buf = NULL;
2504 
2505  PROFILE_START
2506 
2507  if (NULL == pcbAttrLen)
2508  {
2510  goto end;
2511  }
2512 
2513  if (SCARD_AUTOALLOCATE == *pcbAttrLen)
2514  {
2515  if (NULL == pbAttr)
2517 
2518  *pcbAttrLen = MAX_BUFFER_SIZE;
2519  buf = malloc(*pcbAttrLen);
2520  if (NULL == buf)
2521  {
2522  ret = SCARD_E_NO_MEMORY;
2523  goto end;
2524  }
2525 
2526  *(unsigned char **)pbAttr = buf;
2527  }
2528  else
2529  {
2530  buf = pbAttr;
2531 
2532  /* if only get the length */
2533  if (NULL == pbAttr)
2534  /* use a reasonable size */
2535  *pcbAttrLen = MAX_BUFFER_SIZE;
2536  }
2537 
2538  ret = SCardGetSetAttrib(hCard, SCARD_GET_ATTRIB, dwAttrId, buf,
2539  pcbAttrLen);
2540 
2541 end:
2542  PROFILE_END(ret)
2543 
2544  return ret;
2545 }
2546 
2582 LONG SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr,
2583  DWORD cbAttrLen)
2584 {
2585  LONG ret;
2586 
2587  PROFILE_START
2588 
2589  if (NULL == pbAttr || 0 == cbAttrLen)
2591 
2592  ret = SCardGetSetAttrib(hCard, SCARD_SET_ATTRIB, dwAttrId, (LPBYTE)pbAttr,
2593  &cbAttrLen);
2594 
2595  PROFILE_END(ret)
2596 
2597  return ret;
2598 }
2599 
2600 static LONG SCardGetSetAttrib(SCARDHANDLE hCard, int command, DWORD dwAttrId,
2601  LPBYTE pbAttr, LPDWORD pcbAttrLen)
2602 {
2603  LONG rv;
2604  struct getset_struct scGetSetStruct;
2605  SCONTEXTMAP * currentContextMap;
2606  CHANNEL_MAP * pChannelMap;
2607 
2608  /*
2609  * Make sure this handle has been opened
2610  */
2611  rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
2612  &pChannelMap);
2613  if (rv == -1)
2614  return SCARD_E_INVALID_HANDLE;
2615 
2616  (void)pthread_mutex_lock(&currentContextMap->mMutex);
2617 
2618  /* check the handle is still valid */
2619  rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
2620  &pChannelMap);
2621  if (rv == -1)
2622  {
2623  /* the hCard handle is now invalid
2624  * -> another thread may have called SCardReleaseContext
2625  * so the mMutex has been unlocked (and is now invalid)
2626  * -> another thread may have called SCardDisconnect
2627  * so the mMutex is STILL locked
2628  * since we don't know just unlock the mutex */
2629  (void)pthread_mutex_unlock(&currentContextMap->mMutex);
2630  return SCARD_E_INVALID_HANDLE;
2631  }
2632 
2633  if (*pcbAttrLen > MAX_BUFFER_SIZE)
2634  {
2636  goto end;
2637  }
2638 
2639  scGetSetStruct.hCard = hCard;
2640  scGetSetStruct.dwAttrId = dwAttrId;
2641  scGetSetStruct.cbAttrLen = *pcbAttrLen;
2642  scGetSetStruct.rv = SCARD_E_NO_SERVICE;
2643  memset(scGetSetStruct.pbAttr, 0, sizeof(scGetSetStruct.pbAttr));
2644  if (SCARD_SET_ATTRIB == command)
2645  memcpy(scGetSetStruct.pbAttr, pbAttr, *pcbAttrLen);
2646 
2647  rv = MessageSendWithHeader(command, currentContextMap->dwClientID,
2648  sizeof(scGetSetStruct), &scGetSetStruct);
2649 
2650  if (rv != SCARD_S_SUCCESS)
2651  goto end;
2652 
2653  /*
2654  * Read a message from the server
2655  */
2656  rv = MessageReceive(&scGetSetStruct, sizeof(scGetSetStruct),
2657  currentContextMap->dwClientID);
2658 
2659  if (rv != SCARD_S_SUCCESS)
2660  goto end;
2661 
2662  if ((SCARD_S_SUCCESS == scGetSetStruct.rv) && (SCARD_GET_ATTRIB == command))
2663  {
2664  /*
2665  * Copy and zero it so any secret information is not leaked
2666  */
2667  if (*pcbAttrLen < scGetSetStruct.cbAttrLen)
2668  {
2669  scGetSetStruct.cbAttrLen = *pcbAttrLen;
2670  scGetSetStruct.rv = SCARD_E_INSUFFICIENT_BUFFER;
2671  }
2672  else
2673  *pcbAttrLen = scGetSetStruct.cbAttrLen;
2674 
2675  if (pbAttr)
2676  memcpy(pbAttr, scGetSetStruct.pbAttr, scGetSetStruct.cbAttrLen);
2677 
2678  memset(scGetSetStruct.pbAttr, 0x00, sizeof(scGetSetStruct.pbAttr));
2679  }
2680  rv = scGetSetStruct.rv;
2681 
2682 end:
2683  (void)pthread_mutex_unlock(&currentContextMap->mMutex);
2684 
2685  return rv;
2686 }
2687 
2746 LONG SCardTransmit(SCARDHANDLE hCard, const SCARD_IO_REQUEST *pioSendPci,
2747  LPCBYTE pbSendBuffer, DWORD cbSendLength,
2748  SCARD_IO_REQUEST *pioRecvPci, LPBYTE pbRecvBuffer,
2749  LPDWORD pcbRecvLength)
2750 {
2751  LONG rv;
2752  SCONTEXTMAP * currentContextMap;
2753  CHANNEL_MAP * pChannelMap;
2754  struct transmit_struct scTransmitStruct;
2755 
2756  PROFILE_START
2757 
2758  if (pbSendBuffer == NULL || pbRecvBuffer == NULL ||
2759  pcbRecvLength == NULL || pioSendPci == NULL)
2761 
2762  /*
2763  * Make sure this handle has been opened
2764  */
2765  rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
2766  &pChannelMap);
2767  if (rv == -1)
2768  {
2769  *pcbRecvLength = 0;
2770  PROFILE_END(SCARD_E_INVALID_HANDLE)
2771  return SCARD_E_INVALID_HANDLE;
2772  }
2773 
2774  /* Retry loop for blocking behaviour */
2775 retry:
2776 
2777  (void)pthread_mutex_lock(&currentContextMap->mMutex);
2778 
2779  /* check the handle is still valid */
2780  rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
2781  &pChannelMap);
2782  if (rv == -1)
2783  {
2784  /* the hCard handle is now invalid
2785  * -> another thread may have called SCardReleaseContext
2786  * so the mMutex has been unlocked (and is now invalid)
2787  * -> another thread may have called SCardDisconnect
2788  * so the mMutex is STILL locked
2789  * since we don't know just unlock the mutex */
2790  (void)pthread_mutex_unlock(&currentContextMap->mMutex);
2791  return SCARD_E_INVALID_HANDLE;
2792  }
2793 
2794  if ((cbSendLength > MAX_BUFFER_SIZE_EXTENDED)
2795  || (*pcbRecvLength > MAX_BUFFER_SIZE_EXTENDED))
2796  {
2798  goto end;
2799  }
2800 
2801  scTransmitStruct.hCard = hCard;
2802  scTransmitStruct.cbSendLength = cbSendLength;
2803  scTransmitStruct.pcbRecvLength = *pcbRecvLength;
2804  scTransmitStruct.ioSendPciProtocol = pioSendPci->dwProtocol;
2805  scTransmitStruct.ioSendPciLength = pioSendPci->cbPciLength;
2806  scTransmitStruct.rv = SCARD_S_SUCCESS;
2807 
2808  if (pioRecvPci)
2809  {
2810  scTransmitStruct.ioRecvPciProtocol = pioRecvPci->dwProtocol;
2811  scTransmitStruct.ioRecvPciLength = pioRecvPci->cbPciLength;
2812  }
2813  else
2814  {
2815  scTransmitStruct.ioRecvPciProtocol = SCARD_PROTOCOL_ANY;
2816  scTransmitStruct.ioRecvPciLength = sizeof(SCARD_IO_REQUEST);
2817  }
2818 
2819  rv = MessageSendWithHeader(SCARD_TRANSMIT, currentContextMap->dwClientID,
2820  sizeof(scTransmitStruct), (void *) &scTransmitStruct);
2821 
2822  if (rv != SCARD_S_SUCCESS)
2823  goto end;
2824 
2825  /* write the sent buffer */
2826  rv = MessageSend((void *)pbSendBuffer, cbSendLength,
2827  currentContextMap->dwClientID);
2828 
2829  if (rv != SCARD_S_SUCCESS)
2830  goto end;
2831 
2832  /*
2833  * Read a message from the server
2834  */
2835  rv = MessageReceive(&scTransmitStruct, sizeof(scTransmitStruct),
2836  currentContextMap->dwClientID);
2837 
2838  if (rv != SCARD_S_SUCCESS)
2839  goto end;
2840 
2841  if (SCARD_S_SUCCESS == scTransmitStruct.rv)
2842  {
2843  /* read the received buffer */
2844  rv = MessageReceive(pbRecvBuffer, scTransmitStruct.pcbRecvLength,
2845  currentContextMap->dwClientID);
2846 
2847  if (rv != SCARD_S_SUCCESS)
2848  goto end;
2849 
2850  if (pioRecvPci)
2851  {
2852  pioRecvPci->dwProtocol = scTransmitStruct.ioRecvPciProtocol;
2853  pioRecvPci->cbPciLength = scTransmitStruct.ioRecvPciLength;
2854  }
2855  }
2856 
2857  rv = scTransmitStruct.rv;
2858 
2859  if (sharing_shall_block && (SCARD_E_SHARING_VIOLATION == rv))
2860  {
2861  (void)pthread_mutex_unlock(&currentContextMap->mMutex);
2863  goto retry;
2864  }
2865 
2866  *pcbRecvLength = scTransmitStruct.pcbRecvLength;
2867 
2868 end:
2869  (void)pthread_mutex_unlock(&currentContextMap->mMutex);
2870 
2871  PROFILE_END(rv)
2872 
2873  return rv;
2874 }
2875 
2926 LONG SCardListReaders(SCARDCONTEXT hContext, /*@unused@*/ LPCSTR mszGroups,
2927  LPSTR mszReaders, LPDWORD pcchReaders)
2928 {
2929  DWORD dwReadersLen = 0;
2930  int i;
2931  SCONTEXTMAP * currentContextMap;
2932  LONG rv = SCARD_S_SUCCESS;
2933  char *buf = NULL;
2934 
2935  (void)mszGroups;
2936  PROFILE_START
2937  API_TRACE_IN("%ld", hContext)
2938 
2939  /*
2940  * Check for NULL parameters
2941  */
2942  if (pcchReaders == NULL)
2944 
2945  /*
2946  * Make sure this context has been opened
2947  */
2948  currentContextMap = SCardGetContext(hContext);
2949  if (NULL == currentContextMap)
2950  {
2951  PROFILE_END(SCARD_E_INVALID_HANDLE)
2952  return SCARD_E_INVALID_HANDLE;
2953  }
2954 
2955  (void)pthread_mutex_lock(&currentContextMap->mMutex);
2956 
2957  /* check the context is still opened */
2958  currentContextMap = SCardGetContext(hContext);
2959  if (NULL == currentContextMap)
2960  /* the hContext context is now invalid
2961  * -> another thread may have called SCardReleaseContext
2962  * -> so the mMutex has been unlocked */
2963  return SCARD_E_INVALID_HANDLE;
2964 
2965  /* synchronize reader states with daemon */
2966  rv = getReaderStates(currentContextMap);
2967  if (rv != SCARD_S_SUCCESS)
2968  goto end;
2969 
2970  dwReadersLen = 0;
2971  for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
2972  if (readerStates[i].readerName[0] != '\0')
2973  dwReadersLen += strlen(readerStates[i].readerName) + 1;
2974 
2975  /* for the last NULL byte */
2976  dwReadersLen += 1;
2977 
2978  if (1 == dwReadersLen)
2979  {
2981  goto end;
2982  }
2983 
2984  if (SCARD_AUTOALLOCATE == *pcchReaders)
2985  {
2986  if (NULL == mszReaders)
2987  {
2989  goto end;
2990  }
2991  buf = malloc(dwReadersLen);
2992  if (NULL == buf)
2993  {
2994  rv = SCARD_E_NO_MEMORY;
2995  goto end;
2996  }
2997  *(char **)mszReaders = buf;
2998  }
2999  else
3000  {
3001  buf = mszReaders;
3002 
3003  /* not enough place to store the reader names */
3004  if ((NULL != mszReaders) && (*pcchReaders < dwReadersLen))
3005  {
3007  goto end;
3008  }
3009  }
3010 
3011  if (mszReaders == NULL) /* text array not allocated */
3012  goto end;
3013 
3014  for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
3015  {
3016  if (readerStates[i].readerName[0] != '\0')
3017  {
3018  /*
3019  * Build the multi-string
3020  */
3021  strcpy(buf, readerStates[i].readerName);
3022  buf += strlen(readerStates[i].readerName)+1;
3023  }
3024  }
3025  *buf = '\0'; /* Add the last null */
3026 
3027 end:
3028  /* set the reader names length */
3029  *pcchReaders = dwReadersLen;
3030 
3031  (void)pthread_mutex_unlock(&currentContextMap->mMutex);
3032 
3033  PROFILE_END(rv)
3034  API_TRACE_OUT("%d", *pcchReaders)
3035 
3036  return rv;
3037 }
3038 
3052 LONG SCardFreeMemory(SCARDCONTEXT hContext, LPCVOID pvMem)
3053 {
3054  LONG rv = SCARD_S_SUCCESS;
3055  SCONTEXTMAP * currentContextMap;
3056 
3057  PROFILE_START
3058 
3059  /*
3060  * Make sure this context has been opened
3061  */
3062  currentContextMap = SCardGetContext(hContext);
3063  if (NULL == currentContextMap)
3064  return SCARD_E_INVALID_HANDLE;
3065 
3066  free((void *)pvMem);
3067 
3068  PROFILE_END(rv)
3069 
3070  return rv;
3071 }
3072 
3124 LONG SCardListReaderGroups(SCARDCONTEXT hContext, LPSTR mszGroups,
3125  LPDWORD pcchGroups)
3126 {
3127  LONG rv = SCARD_S_SUCCESS;
3128  SCONTEXTMAP * currentContextMap;
3129  char *buf = NULL;
3130 
3131  PROFILE_START
3132 
3133  /* Multi-string with two trailing \0 */
3134  const char ReaderGroup[] = "SCard$DefaultReaders\0";
3135  const unsigned int dwGroups = sizeof(ReaderGroup);
3136 
3137  /*
3138  * Make sure this context has been opened
3139  */
3140  currentContextMap = SCardGetContext(hContext);
3141  if (NULL == currentContextMap)
3142  return SCARD_E_INVALID_HANDLE;
3143 
3144  (void)pthread_mutex_lock(&currentContextMap->mMutex);
3145 
3146  /* check the context is still opened */
3147  currentContextMap = SCardGetContext(hContext);
3148  if (NULL == currentContextMap)
3149  /* the hContext context is now invalid
3150  * -> another thread may have called SCardReleaseContext
3151  * -> so the mMutex has been unlocked */
3152  return SCARD_E_INVALID_HANDLE;
3153 
3154  if (SCARD_AUTOALLOCATE == *pcchGroups)
3155  {
3156  if (NULL == mszGroups)
3157  {
3159  goto end;
3160  }
3161  buf = malloc(dwGroups);
3162  if (NULL == buf)
3163  {
3164  rv = SCARD_E_NO_MEMORY;
3165  goto end;
3166  }
3167  *(char **)mszGroups = buf;
3168  }
3169  else
3170  {
3171  buf = mszGroups;
3172 
3173  if ((NULL != mszGroups) && (*pcchGroups < dwGroups))
3174  {
3176  goto end;
3177  }
3178  }
3179 
3180  if (buf)
3181  memcpy(buf, ReaderGroup, dwGroups);
3182 
3183 end:
3184  *pcchGroups = dwGroups;
3185 
3186  (void)pthread_mutex_unlock(&currentContextMap->mMutex);
3187 
3188  PROFILE_END(rv)
3189 
3190  return rv;
3191 }
3192 
3223 {
3224  SCONTEXTMAP * currentContextMap;
3225  LONG rv = SCARD_S_SUCCESS;
3226  uint32_t dwClientID = 0;
3227  struct cancel_struct scCancelStruct;
3228 
3229  PROFILE_START
3230  API_TRACE_IN("%ld", hContext)
3231 
3232  /*
3233  * Make sure this context has been opened
3234  */
3235  currentContextMap = SCardGetContext(hContext);
3236  if (NULL == currentContextMap)
3237  {
3239  goto error;
3240  }
3241 
3242  if (! currentContextMap->cancellable)
3243  {
3244  rv = SCARD_S_SUCCESS;
3245  goto error;
3246  }
3247 
3248  /* create a new connection to the server */
3249  if (ClientSetupSession(&dwClientID) != 0)
3250  {
3251  rv = SCARD_E_NO_SERVICE;
3252  goto error;
3253  }
3254 
3255  scCancelStruct.hContext = hContext;
3256  scCancelStruct.rv = SCARD_S_SUCCESS;
3257 
3258  rv = MessageSendWithHeader(SCARD_CANCEL, dwClientID,
3259  sizeof(scCancelStruct), (void *) &scCancelStruct);
3260 
3261  if (rv != SCARD_S_SUCCESS)
3262  goto end;
3263 
3264  /*
3265  * Read a message from the server
3266  */
3267  rv = MessageReceive(&scCancelStruct, sizeof(scCancelStruct), dwClientID);
3268 
3269  if (rv != SCARD_S_SUCCESS)
3270  goto end;
3271 
3272  rv = scCancelStruct.rv;
3273 end:
3274  ClientCloseSession(dwClientID);
3275 
3276 error:
3277  PROFILE_END(rv)
3278  API_TRACE_OUT("")
3279 
3280  return rv;
3281 }
3282 
3307 {
3308  LONG rv;
3309  SCONTEXTMAP * currentContextMap;
3310 
3311  PROFILE_START
3312  API_TRACE_IN("%ld", hContext)
3313 
3314  rv = SCARD_S_SUCCESS;
3315 
3316  /*
3317  * Make sure this context has been opened
3318  */
3319  currentContextMap = SCardGetContext(hContext);
3320  if (currentContextMap == NULL)
3322 
3323  PROFILE_END(rv)
3324  API_TRACE_OUT("")
3325 
3326  return rv;
3327 }
3328 
3345 static LONG SCardAddContext(SCARDCONTEXT hContext, DWORD dwClientID)
3346 {
3347  int lrv;
3348  SCONTEXTMAP * newContextMap;
3349 
3350  newContextMap = malloc(sizeof(SCONTEXTMAP));
3351  if (NULL == newContextMap)
3352  return SCARD_E_NO_MEMORY;
3353 
3354  Log2(PCSC_LOG_DEBUG, "Allocating new SCONTEXTMAP @%p", newContextMap);
3355  newContextMap->hContext = hContext;
3356  newContextMap->dwClientID = dwClientID;
3357  newContextMap->cancellable = FALSE;
3358 
3359  (void)pthread_mutex_init(&newContextMap->mMutex, NULL);
3360 
3361  lrv = list_init(&newContextMap->channelMapList);
3362  if (lrv < 0)
3363  {
3364  Log2(PCSC_LOG_CRITICAL, "list_init failed with return value: %d", lrv);
3365  goto error;
3366  }
3367 
3368  lrv = list_attributes_seeker(&newContextMap->channelMapList,
3369  CHANNEL_MAP_seeker);
3370  if (lrv <0)
3371  {
3372  Log2(PCSC_LOG_CRITICAL,
3373  "list_attributes_seeker failed with return value: %d", lrv);
3374  list_destroy(&newContextMap->channelMapList);
3375  goto error;
3376  }
3377 
3378  lrv = list_append(&contextMapList, newContextMap);
3379  if (lrv < 0)
3380  {
3381  Log2(PCSC_LOG_CRITICAL, "list_append failed with return value: %d",
3382  lrv);
3383  list_destroy(&newContextMap->channelMapList);
3384  goto error;
3385  }
3386 
3387  return SCARD_S_SUCCESS;
3388 
3389 error:
3390 
3391  (void)pthread_mutex_destroy(&newContextMap->mMutex);
3392  free(newContextMap);
3393 
3394  return SCARD_E_NO_MEMORY;
3395 }
3396 
3410 {
3411  SCONTEXTMAP * currentContextMap;
3412 
3413  (void)SCardLockThread();
3414  currentContextMap = SCardGetContextTH(hContext);
3415  (void)SCardUnlockThread();
3416 
3417  return currentContextMap;
3418 }
3419 
3433 {
3434  return list_seek(&contextMapList, &hContext);
3435 }
3436 
3446 static LONG SCardRemoveContext(SCARDCONTEXT hContext)
3447 {
3448  SCONTEXTMAP * currentContextMap;
3449  currentContextMap = SCardGetContextTH(hContext);
3450 
3451  if (NULL == currentContextMap)
3452  return SCARD_E_INVALID_HANDLE;
3453  else
3454  return SCardCleanContext(currentContextMap);
3455 }
3456 
3457 static LONG SCardCleanContext(SCONTEXTMAP * targetContextMap)
3458 {
3459  int list_index, lrv;
3460  int listSize;
3461  CHANNEL_MAP * currentChannelMap;
3462 
3463  targetContextMap->hContext = 0;
3464  (void)ClientCloseSession(targetContextMap->dwClientID);
3465  targetContextMap->dwClientID = 0;
3466  (void)pthread_mutex_destroy(&targetContextMap->mMutex);
3467 
3468  listSize = list_size(&targetContextMap->channelMapList);
3469  for (list_index = 0; list_index < listSize; list_index++)
3470  {
3471  currentChannelMap = list_get_at(&targetContextMap->channelMapList,
3472  list_index);
3473  if (NULL == currentChannelMap)
3474  {
3475  Log2(PCSC_LOG_CRITICAL, "list_get_at failed for index %d",
3476  list_index);
3477  continue;
3478  }
3479  else
3480  {
3481  free(currentChannelMap->readerName);
3482  free(currentChannelMap);
3483  }
3484 
3485  }
3486  list_destroy(&targetContextMap->channelMapList);
3487 
3488  lrv = list_delete(&contextMapList, targetContextMap);
3489  if (lrv < 0)
3490  {
3491  Log2(PCSC_LOG_CRITICAL,
3492  "list_delete failed with return value: %d", lrv);
3493  }
3494 
3495  free(targetContextMap);
3496 
3497  return SCARD_S_SUCCESS;
3498 }
3499 
3500 /*
3501  * Functions for managing hCard values returned from SCardConnect.
3502  */
3503 
3504 static LONG SCardAddHandle(SCARDHANDLE hCard, SCONTEXTMAP * currentContextMap,
3505  LPCSTR readerName)
3506 {
3507  CHANNEL_MAP * newChannelMap;
3508  int lrv = -1;
3509 
3510  newChannelMap = malloc(sizeof(CHANNEL_MAP));
3511  if (NULL == newChannelMap)
3512  return SCARD_E_NO_MEMORY;
3513 
3514  newChannelMap->hCard = hCard;
3515  newChannelMap->readerName = strdup(readerName);
3516 
3517  lrv = list_append(&currentContextMap->channelMapList, newChannelMap);
3518  if (lrv < 0)
3519  {
3520  free(newChannelMap->readerName);
3521  free(newChannelMap);
3522  Log2(PCSC_LOG_CRITICAL, "list_append failed with return value: %d",
3523  lrv);
3524  return SCARD_E_NO_MEMORY;
3525  }
3526 
3527  return SCARD_S_SUCCESS;
3528 }
3529 
3530 static LONG SCardRemoveHandle(SCARDHANDLE hCard)
3531 {
3532  SCONTEXTMAP * currentContextMap;
3533  CHANNEL_MAP * currentChannelMap;
3534  int lrv;
3535  LONG rv;
3536 
3537  rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
3538  &currentChannelMap);
3539  if (rv == -1)
3540  return SCARD_E_INVALID_HANDLE;
3541 
3542  free(currentChannelMap->readerName);
3543 
3544  lrv = list_delete(&currentContextMap->channelMapList, currentChannelMap);
3545  if (lrv < 0)
3546  {
3547  Log2(PCSC_LOG_CRITICAL,
3548  "list_delete failed with return value: %d", lrv);
3549  }
3550 
3551  free(currentChannelMap);
3552 
3553  return SCARD_S_SUCCESS;
3554 }
3555 
3556 static LONG SCardGetContextAndChannelFromHandle(SCARDHANDLE hCard,
3557  SCONTEXTMAP **targetContextMap, CHANNEL_MAP ** targetChannelMap)
3558 {
3559  LONG rv;
3560 
3561  if (0 == hCard)
3562  return -1;
3563 
3564  (void)SCardLockThread();
3565  rv = SCardGetContextAndChannelFromHandleTH(hCard, targetContextMap,
3566  targetChannelMap);
3567  (void)SCardUnlockThread();
3568 
3569  return rv;
3570 }
3571 
3572 static LONG SCardGetContextAndChannelFromHandleTH(SCARDHANDLE hCard,
3573  SCONTEXTMAP **targetContextMap, CHANNEL_MAP ** targetChannelMap)
3574 {
3575  int listSize;
3576  int list_index;
3577  SCONTEXTMAP * currentContextMap;
3578  CHANNEL_MAP * currentChannelMap;
3579 
3580  /* Best to get the caller a crash early if we fail unsafely */
3581  *targetContextMap = NULL;
3582  *targetChannelMap = NULL;
3583 
3584  listSize = list_size(&contextMapList);
3585 
3586  for (list_index = 0; list_index < listSize; list_index++)
3587  {
3588  currentContextMap = list_get_at(&contextMapList, list_index);
3589  if (currentContextMap == NULL)
3590  {
3591  Log2(PCSC_LOG_CRITICAL, "list_get_at failed for index %d",
3592  list_index);
3593  continue;
3594  }
3595  currentChannelMap = list_seek(&currentContextMap->channelMapList,
3596  &hCard);
3597  if (currentChannelMap != NULL)
3598  {
3599  *targetContextMap = currentContextMap;
3600  *targetChannelMap = currentChannelMap;
3601  return SCARD_S_SUCCESS;
3602  }
3603  }
3604 
3605  return -1;
3606 }
3607 
3620 {
3621  LONG rv;
3622  struct stat statBuffer;
3623  char *socketName;
3624 
3625  socketName = getSocketName();
3626  rv = stat(socketName, &statBuffer);
3627 
3628  if (rv != 0)
3629  {
3630  Log3(PCSC_LOG_INFO, "PCSC Not Running: %s: %s",
3631  socketName, strerror(errno));
3632  return SCARD_E_NO_SERVICE;
3633  }
3634 
3635  return SCARD_S_SUCCESS;
3636 }
3637 
3638 static LONG getReaderStates(SCONTEXTMAP * currentContextMap)
3639 {
3640  int32_t dwClientID = currentContextMap->dwClientID;
3641  LONG rv;
3642 
3643  rv = MessageSendWithHeader(CMD_GET_READERS_STATE, dwClientID, 0, NULL);
3644  if (rv != SCARD_S_SUCCESS)
3645  return rv;
3646 
3647  /* Read a message from the server */
3648  rv = MessageReceive(&readerStates, sizeof(readerStates), dwClientID);
3649  if (rv != SCARD_S_SUCCESS)
3650  return rv;
3651 
3652  return SCARD_S_SUCCESS;
3653 }
3654 
used by SCardBeginTransaction()
Definition: winscard_msg.h:84
contained in SCARD_CONNECT Messages.
Definition: winscard_msg.h:143
list object
Definition: simclist.h:181
uint32_t cardAtrLength
ATR length.
Definition: eventhandler.h:58
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:96
contained in SCARD_CANCEL Messages.
Definition: winscard_msg.h:209
contained in SCARD_TRANSMIT Messages.
Definition: winscard_msg.h:231
#define SCARD_STATE_UNAVAILABLE
Status unavailable.
Definition: pcsclite.h:203
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:197
#define SCARD_E_READER_UNAVAILABLE
The specified reader is not currently available for use.
Definition: pcsclite.h:126
#define PCSCLITE_SHARING_NO_CONTEXT
No application is using the reader.
Definition: eventhandler.h:75
INTERNAL int ClientCloseSession(uint32_t dwClientID)
Closes the socket used by the client to communicate with the server.
Definition: winscard_msg.c:172
#define MAX_BUFFER_SIZE
Maximum Tx/Rx Buffer for short APDU.
Definition: pcsclite.h:231
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:204
get the client/server protocol version
Definition: winscard_msg.h:94
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:200
#define SCARD_UNKNOWN
Unknown state.
Definition: pcsclite.h:191
PCSC_API char * pcsc_stringify_error(const LONG pcscError)
Returns a human readable text for the given PC/SC error code.
Definition: error.c:79
static short isExecuted
Make sure the initialization code is executed only once.
used by SCardEstablishContext()
Definition: winscard_msg.h:78
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:315
int32_t minor
IPC minor PROTOCOL_VERSION_MINOR.
Definition: winscard_msg.h:59
#define SCARD_F_COMM_ERROR
An internal communications error has been detected.
Definition: pcsclite.h:122
used by SCardEndTransaction()
Definition: winscard_msg.h:85
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:84
int32_t readerSharing
PCSCLITE_SHARING_* sharing status.
Definition: eventhandler.h:55
#define SCARD_E_INVALID_PARAMETER
One or more of the supplied parameters could not be properly interpreted.
Definition: pcsclite.h:107
#define SCARD_STATE_CHANGED
State has changed.
Definition: pcsclite.h:201
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:132
uint32_t eventCounter
number of card events
Definition: eventhandler.h:53
#define SCARD_E_NO_READERS_AVAILABLE
Cannot find a smart card reader.
Definition: pcsclite.h:150
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:81
#define PROTOCOL_VERSION_MAJOR
Major version of the current message protocol.
Definition: winscard_msg.h:49
#define SCARD_PROTOCOL_T1
T=1 active protocol.
Definition: pcsclite.h:176
contained in SCARD_DISCONNECT Messages.
Definition: winscard_msg.h:174
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:106
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:193
Information contained in SCARD_RELEASE_CONTEXT Messages.
Definition: winscard_msg.h:132
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:85
contained in SCARD_BEGIN_TRANSACTION Messages.
Definition: winscard_msg.h:186
#define PCSCLITE_SHARING_EXCLUSIVE_CONTEXT
Reader used in exclusive mode.
Definition: eventhandler.h:77
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:213
#define SCARD_STATE_UNKNOWN
Reader unknown.
Definition: pcsclite.h:202
Represents the an Application Context on the Client side.
Information contained in SCARD_ESTABLISH_CONTEXT Messages.
Definition: winscard_msg.h:120
get the readers state
Definition: winscard_msg.h:95
#define PCSCLITE_LOCK_POLL_RATE
Lock polling rate.
Definition: pcscd.h:58
#define SCARD_AUTOALLOCATE
see SCardFreeMemory()
Definition: pcsclite.h:168
Information transmitted in CMD_VERSION Messages.
Definition: winscard_msg.h:56
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:449
used by SCardReleaseContext()
Definition: winscard_msg.h:79
LONG SCARDCONTEXT
hContext returned by SCardEstablishContext()
Definition: pcsclite.h:54
#define SCARD_E_INVALID_VALUE
One or more of the supplied parameters values could not be properly interpreted.
Definition: pcsclite.h:120
contained in SCARD_STATUS Messages.
Definition: winscard_msg.h:220
contained in SCARD_RECONNECT Messages.
Definition: winscard_msg.h:159
unsigned long dwProtocol
Protocol identifier.
Definition: pcsclite.h:83
uint32_t timeOut
timeout in ms
Definition: winscard_msg.h:111
#define PCSCLITE_MAX_READERS_CONTEXTS
Maximum readers context (a slot is count as a reader)
Definition: pcsclite.h:218
contained in SCARD_GET_ATTRIB and Messages.
Definition: winscard_msg.h:263
prototypes of strlcpy()/strlcat() imported from OpenBSD
#define SCARD_STATE_PRESENT
Card inserted.
Definition: pcsclite.h:205
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:109
DWORD dwClientID
Client Connection ID.
#define SCARD_PROTOCOL_T0
T=0 active protocol.
Definition: pcsclite.h:175
#define SCARD_STATE_ATRMATCH
ATR matches card.
Definition: pcsclite.h:206
used by SCardReconnect()
Definition: winscard_msg.h:82
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:137
#define MAX_BUFFER_SIZE_EXTENDED
enhanced (64K + APDU + Lc + Le + SW) Tx/Rx Buffer
Definition: pcsclite.h:232
static READER_STATE readerStates[PCSCLITE_MAX_READERS_CONTEXTS]
Area used to read status information about the readers.
used by SCardTransmit()
Definition: winscard_msg.h:86
#define PCSCLITE_STATUS_POLL_RATE
Status polling rate.
Definition: pcscd.h:57
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:180
char cancellable
We are in a cancellable call.
stop waiting for a reader state change
Definition: winscard_msg.h:97
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:207
#define SCARD_SWALLOWED
Card not powered.
Definition: pcsclite.h:194
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:57
LONG SCARDHANDLE
hCard returned by SCardConnect()
Definition: pcsclite.h:57
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:117
#define PROTOCOL_VERSION_MINOR
Minor version of the current message protocol.
Definition: winscard_msg.h:51
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:87
This keeps a list of defines for pcsc-lite.
#define SCARD_PROTOCOL_RAW
Raw active protocol.
Definition: pcsclite.h:177
#define SCARD_STATE_INUSE
Shared Mode.
Definition: pcsclite.h:208
Protocol Control Information (PCI)
Definition: pcsclite.h:81
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:114
#define SCARD_ABSENT
Card is absent.
Definition: pcsclite.h:192
uint32_t cardProtocol
SCARD_PROTOCOL_* value.
Definition: eventhandler.h:59
Define an exported public reader state structure so each application gets instant notification of cha...
Definition: eventhandler.h:50
used by SCardSetAttrib()
Definition: winscard_msg.h:93
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:351
used by SCardDisconnect()
Definition: winscard_msg.h:83
#define SCARD_E_NO_MEMORY
Not enough memory available to complete this command.
Definition: pcsclite.h:109
contained in SCARD_CONTROL Messages.
Definition: winscard_msg.h:248
This keeps track of a list of currently available reader structures.
used by SCardGetAttrib()
Definition: winscard_msg.h:92
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:54
used by SCardCancel()
Definition: winscard_msg.h:90
#define SCARD_E_INSUFFICIENT_BUFFER
The data buffer to receive returned data is too small for the returned data.
Definition: pcsclite.h:111
#define PCSCLITE_SHARING_LAST_CONTEXT
One application is using the reader.
Definition: eventhandler.h:73
int32_t major
IPC major PROTOCOL_VERSION_MAJOR.
Definition: winscard_msg.h:58
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:112
used by SCardStatus()
Definition: winscard_msg.h:88
#define SCARD_S_SUCCESS
error codes from http://msdn.microsoft.com/en-us/library/aa924526.aspx
Definition: pcsclite.h:103
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:193
This handles debugging.
#define SCARD_E_TIMEOUT
The user-specified timeout value has expired.
Definition: pcsclite.h:113
#define SCARD_STATE_UNAWARE
App wants status.
Definition: pcsclite.h:199
#define SCARD_STATE_MUTE
Unresponsive card.
Definition: pcsclite.h:209