00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00078 #include "config.h"
00079 #include <stdlib.h>
00080 #include <string.h>
00081 #include <sys/types.h>
00082 #include <fcntl.h>
00083 #include <unistd.h>
00084 #include <sys/un.h>
00085 #include <errno.h>
00086 #include <stddef.h>
00087 #include <sys/time.h>
00088 #include <pthread.h>
00089 #include <sys/wait.h>
00090
00091 #include "misc.h"
00092 #include "pcscd.h"
00093 #include "winscard.h"
00094 #include "debuglog.h"
00095 #include "strlcpycat.h"
00096
00097 #include "readerfactory.h"
00098 #include "eventhandler.h"
00099 #include "sys_generic.h"
00100 #include "winscard_msg.h"
00101 #include "utils.h"
00102
00104 #define SCARD_PROTOCOL_ANY_OLD 0x1000
00105
00106 #ifndef TRUE
00107 #define TRUE 1
00108 #define FALSE 0
00109 #endif
00110
00111 static char sharing_shall_block = TRUE;
00112
00113 #undef DO_PROFILE
00114 #ifdef DO_PROFILE
00115
00116 #define PROFILE_FILE "/tmp/pcsc_profile"
00117 #include <stdio.h>
00118 #include <sys/time.h>
00119
00120 struct timeval profile_time_start;
00121 FILE *profile_fd;
00122 char profile_tty;
00123 char fct_name[100];
00124
00125 #define PROFILE_START profile_start(__FUNCTION__);
00126 #define PROFILE_END(rv) profile_end(__FUNCTION__, rv);
00127
00128 static void profile_start(const char *f)
00129 {
00130 static char initialized = FALSE;
00131
00132 if (!initialized)
00133 {
00134 char filename[80];
00135
00136 initialized = TRUE;
00137 sprintf(filename, "%s-%d", PROFILE_FILE, getuid());
00138 profile_fd = fopen(filename, "a+");
00139 if (NULL == profile_fd)
00140 {
00141 fprintf(stderr, "\33[01;31mCan't open %s: %s\33[0m\n",
00142 PROFILE_FILE, strerror(errno));
00143 exit(-1);
00144 }
00145 fprintf(profile_fd, "\nStart a new profile\n");
00146
00147 if (isatty(fileno(stderr)))
00148 profile_tty = TRUE;
00149 else
00150 profile_tty = FALSE;
00151 }
00152
00153
00154 if (profile_tty && fct_name[0])
00155 printf("\33[01;34m WARNING: %s starts before %s finishes\33[0m\n",
00156 f, fct_name);
00157
00158 strlcpy(fct_name, f, sizeof(fct_name));
00159
00160 gettimeofday(&profile_time_start, NULL);
00161 }
00162
00163 static void profile_end(const char *f, LONG rv)
00164 {
00165 struct timeval profile_time_end;
00166 long d;
00167
00168 gettimeofday(&profile_time_end, NULL);
00169 d = time_sub(&profile_time_end, &profile_time_start);
00170
00171 if (profile_tty)
00172 {
00173 if (fct_name[0])
00174 {
00175 if (strncmp(fct_name, f, sizeof(fct_name)))
00176 printf("\33[01;34m WARNING: %s ends before %s\33[0m\n",
00177 f, fct_name);
00178 }
00179 else
00180 printf("\33[01;34m WARNING: %s ends but we lost its start\33[0m\n",
00181 f);
00182
00183
00184 fct_name[0] = '\0';
00185
00186 if (rv != SCARD_S_SUCCESS)
00187 fprintf(stderr,
00188 "\33[01;31mRESULT %s \33[35m%ld \33[34m0x%08lX %s\33[0m\n",
00189 f, d, rv, pcsc_stringify_error(rv));
00190 else
00191 fprintf(stderr, "\33[01;31mRESULT %s \33[35m%ld\33[0m\n", f, d);
00192 }
00193 fprintf(profile_fd, "%s %ld\n", f, d);
00194 fflush(profile_fd);
00195 }
00196
00197 #else
00198 #define PROFILE_START
00199 #define PROFILE_END(rv)
00200 #endif
00201
00206 struct _psChannelMap
00207 {
00208 SCARDHANDLE hCard;
00209 LPSTR readerName;
00210 };
00211
00212 typedef struct _psChannelMap CHANNEL_MAP;
00213
00214 static int CHANNEL_MAP_seeker(const void *el, const void *key)
00215 {
00216 const CHANNEL_MAP * channelMap = el;
00217
00218 if ((el == NULL) || (key == NULL))
00219 {
00220 Log3(PCSC_LOG_CRITICAL,
00221 "CHANNEL_MAP_seeker called with NULL pointer: el=%X, key=%X",
00222 el, key);
00223 }
00224
00225 if (channelMap->hCard == *(SCARDHANDLE *)key)
00226 return 1;
00227
00228 return 0;
00229 }
00230
00236 struct _psContextMap
00237 {
00238 DWORD dwClientID;
00239 SCARDCONTEXT hContext;
00240 pthread_mutex_t * mMutex;
00241 list_t channelMapList;
00242 };
00243 typedef struct _psContextMap SCONTEXTMAP;
00244
00245 static list_t contextMapList;
00246
00247 static int SCONTEXTMAP_seeker(const void *el, const void *key)
00248 {
00249 const SCONTEXTMAP * contextMap = el;
00250
00251 if ((el == NULL) || (key == NULL))
00252 {
00253 Log3(PCSC_LOG_CRITICAL,
00254 "SCONTEXTMAP_seeker called with NULL pointer: el=%X, key=%X",
00255 el, key);
00256 }
00257
00258 if (contextMap->hContext == *(SCARDCONTEXT *) key)
00259 return 1;
00260
00261 return 0;
00262 }
00263
00267 static short isExecuted = 0;
00268
00269
00273 static time_t daemon_ctime = 0;
00274 static pid_t daemon_pid = 0;
00279 static pid_t client_pid = 0;
00280
00285 static pthread_mutex_t clientMutex = PTHREAD_MUTEX_INITIALIZER;
00286
00290 static READER_STATE readerStates[PCSCLITE_MAX_READERS_CONTEXTS];
00291
00293 PCSC_API SCARD_IO_REQUEST g_rgSCardT0Pci = { SCARD_PROTOCOL_T0, sizeof(SCARD_IO_REQUEST) };
00295 PCSC_API SCARD_IO_REQUEST g_rgSCardT1Pci = { SCARD_PROTOCOL_T1, sizeof(SCARD_IO_REQUEST) };
00297 PCSC_API SCARD_IO_REQUEST g_rgSCardRawPci = { SCARD_PROTOCOL_RAW, sizeof(SCARD_IO_REQUEST) };
00298
00299
00300 static LONG SCardAddContext(SCARDCONTEXT, DWORD);
00301 static SCONTEXTMAP * SCardGetContext(SCARDCONTEXT);
00302 static SCONTEXTMAP * SCardGetContextTH(SCARDCONTEXT);
00303 static LONG SCardRemoveContext(SCARDCONTEXT);
00304 static LONG SCardCleanContext(SCONTEXTMAP *);
00305
00306 static LONG SCardAddHandle(SCARDHANDLE, SCONTEXTMAP *, LPCSTR);
00307 static LONG SCardGetContextAndChannelFromHandle(SCARDHANDLE, SCONTEXTMAP * *, CHANNEL_MAP * *);
00308 static LONG SCardGetContextAndChannelFromHandleTH(SCARDHANDLE, SCONTEXTMAP * *, CHANNEL_MAP * *);
00309 static LONG SCardRemoveHandle(SCARDHANDLE);
00310
00311 static LONG SCardGetSetAttrib(SCARDHANDLE hCard, int command, DWORD dwAttrId,
00312 LPBYTE pbAttr, LPDWORD pcbAttrLen);
00313
00314 #ifdef DO_CHECK_SAME_PROCESS
00315 static LONG SCardCheckSameProcess(void);
00316 #define CHECK_SAME_PROCESS \
00317 rv = SCardCheckSameProcess(); \
00318 if (rv != SCARD_S_SUCCESS) \
00319 return rv;
00320 #else
00321 #define CHECK_SAME_PROCESS
00322 #endif
00323
00324 static LONG getReaderStates(SCONTEXTMAP * currentContextMap);
00325
00326
00327
00328
00335 inline static LONG SCardLockThread(void)
00336 {
00337 return pthread_mutex_lock(&clientMutex);
00338 }
00339
00345 inline static LONG SCardUnlockThread(void)
00346 {
00347 return pthread_mutex_unlock(&clientMutex);
00348 }
00349
00350 static LONG SCardEstablishContextTH(DWORD, LPCVOID, LPCVOID,
00351 LPSCARDCONTEXT);
00352
00386 LONG SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1,
00387 LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
00388 {
00389 LONG rv;
00390 int daemon_launched = FALSE;
00391 int retries = 0;
00392
00393 PROFILE_START
00394
00395 again:
00396
00397 rv = SCardCheckDaemonAvailability();
00398 if (SCARD_E_INVALID_HANDLE == rv)
00399
00400 rv = SCardCheckDaemonAvailability();
00401
00402 if (SCARD_E_NO_SERVICE == rv)
00403 {
00404 launch:
00405 if (daemon_launched)
00406 {
00407 retries++;
00408 if (retries < 50)
00409 {
00410
00411 SYS_USleep(100*1000);
00412 goto again;
00413 }
00414
00415
00416 goto end;
00417 }
00418 else
00419 {
00420 int pid;
00421
00422 pid = fork();
00423
00424 if (pid < 0)
00425 {
00426 Log2(PCSC_LOG_CRITICAL, "fork failed: %s", strerror(errno));
00427 rv = SCARD_F_INTERNAL_ERROR;
00428 goto end;
00429 }
00430
00431 if (0 == pid)
00432 {
00433 int ret, i, max;
00434 char *param = getenv("PCSCLITE_PCSCD_ARGS");
00435
00436
00437
00438
00439 max = sysconf(_SC_OPEN_MAX);
00440 if (-1 == max)
00441 max = 1024;
00442 for (i=3; i<max; i++)
00443 (void)close(i);
00444
00445
00446 ret = execl(PCSCD_BINARY, "pcscd", "--auto-exit", param,
00447 (char *)NULL);
00448 Log2(PCSC_LOG_CRITICAL, "exec " PCSCD_BINARY " failed: %s",
00449 strerror(errno));
00450 exit(1);
00451 }
00452
00453
00454 daemon_launched = TRUE;
00455
00456 if (waitpid(pid, NULL, 0) < 0)
00457 Log2(PCSC_LOG_CRITICAL, "waitpid failed: %s", strerror(errno));
00458
00459 goto again;
00460 }
00461 }
00462
00463 if (rv != SCARD_S_SUCCESS)
00464 goto end;
00465
00466 (void)SCardLockThread();
00467 rv = SCardEstablishContextTH(dwScope, pvReserved1,
00468 pvReserved2, phContext);
00469 (void)SCardUnlockThread();
00470
00471
00472
00473 if (SCARD_E_NO_SERVICE == rv)
00474 {
00475 retries++;
00476 if (retries <= 1)
00477 goto launch;
00478 }
00479
00480 end:
00481 PROFILE_END(rv)
00482
00483 return rv;
00484 }
00485
00512 static LONG SCardEstablishContextTH(DWORD dwScope,
00513 LPCVOID pvReserved1,
00514 LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
00515 {
00516 LONG rv;
00517 struct establish_struct scEstablishStruct;
00518 uint32_t dwClientID = 0;
00519
00520 (void)pvReserved1;
00521 (void)pvReserved2;
00522 if (phContext == NULL)
00523 return SCARD_E_INVALID_PARAMETER;
00524 else
00525 *phContext = 0;
00526
00527
00528
00529
00530
00531 if (isExecuted == 0)
00532 {
00533 int lrv;
00534
00535
00536
00537
00538
00539 lrv = list_init(&contextMapList);
00540 if (lrv < 0)
00541 {
00542 Log2(PCSC_LOG_CRITICAL, "list_init failed with return value: %X", lrv);
00543 return SCARD_E_NO_MEMORY;
00544 }
00545
00546 lrv = list_attributes_seeker(&contextMapList,
00547 SCONTEXTMAP_seeker);
00548 if (lrv <0)
00549 {
00550 Log2(PCSC_LOG_CRITICAL,
00551 "list_attributes_seeker failed with return value: %X", lrv);
00552 list_destroy(&contextMapList);
00553 return SCARD_E_NO_MEMORY;
00554 }
00555
00556 if (getenv("PCSCLITE_NO_BLOCKING"))
00557 {
00558 Log1(PCSC_LOG_INFO, "Disable shared blocking");
00559 sharing_shall_block = FALSE;
00560 }
00561
00562 isExecuted = 1;
00563 }
00564
00565
00566
00567 if (ClientSetupSession(&dwClientID) != 0)
00568 {
00569 return SCARD_E_NO_SERVICE;
00570 }
00571
00572 {
00573 struct version_struct veStr;
00574
00575 veStr.major = PROTOCOL_VERSION_MAJOR;
00576 veStr.minor = PROTOCOL_VERSION_MINOR;
00577 veStr.rv = SCARD_S_SUCCESS;
00578
00579 if (-1 == MessageSendWithHeader(CMD_VERSION, dwClientID, sizeof(veStr),
00580 &veStr))
00581 return SCARD_E_NO_SERVICE;
00582
00583
00584 if (MessageReceive(&veStr, sizeof(veStr), dwClientID) < 0)
00585 {
00586 Log1(PCSC_LOG_CRITICAL, "Your pcscd is too old and does not support CMD_VERSION");
00587 return SCARD_F_COMM_ERROR;
00588 }
00589
00590 Log3(PCSC_LOG_INFO, "Server is protocol version %d:%d",
00591 veStr.major, veStr.minor);
00592
00593 if (veStr.rv != SCARD_S_SUCCESS)
00594 return veStr.rv;
00595 }
00596
00597 again:
00598
00599
00600
00601 scEstablishStruct.dwScope = dwScope;
00602 scEstablishStruct.hContext = 0;
00603 scEstablishStruct.rv = SCARD_S_SUCCESS;
00604
00605 rv = MessageSendWithHeader(SCARD_ESTABLISH_CONTEXT, dwClientID,
00606 sizeof(scEstablishStruct), (void *) &scEstablishStruct);
00607
00608 if (rv == -1)
00609 return SCARD_E_NO_SERVICE;
00610
00611
00612
00613
00614 rv = MessageReceive(&scEstablishStruct, sizeof(scEstablishStruct), dwClientID);
00615
00616 if (rv < 0)
00617 return SCARD_F_COMM_ERROR;
00618
00619 if (scEstablishStruct.rv != SCARD_S_SUCCESS)
00620 return scEstablishStruct.rv;
00621
00622
00623 if (NULL != SCardGetContextTH(scEstablishStruct.hContext))
00624
00625
00626 goto again;
00627
00628 *phContext = scEstablishStruct.hContext;
00629
00630
00631
00632
00633 rv = SCardAddContext(*phContext, dwClientID);
00634
00635 return rv;
00636 }
00637
00659 LONG SCardReleaseContext(SCARDCONTEXT hContext)
00660 {
00661 LONG rv;
00662 struct release_struct scReleaseStruct;
00663 SCONTEXTMAP * currentContextMap;
00664
00665 PROFILE_START
00666
00667 CHECK_SAME_PROCESS
00668
00669
00670
00671
00672
00673 currentContextMap = SCardGetContext(hContext);
00674 if (NULL == currentContextMap)
00675 {
00676 PROFILE_END(SCARD_E_INVALID_HANDLE)
00677 return SCARD_E_INVALID_HANDLE;
00678 }
00679
00680 (void)pthread_mutex_lock(currentContextMap->mMutex);
00681
00682
00683 currentContextMap = SCardGetContext(hContext);
00684 if (NULL == currentContextMap)
00685
00686
00687
00688 return SCARD_E_INVALID_HANDLE;
00689
00690 scReleaseStruct.hContext = hContext;
00691 scReleaseStruct.rv = SCARD_S_SUCCESS;
00692
00693 rv = MessageSendWithHeader(SCARD_RELEASE_CONTEXT,
00694 currentContextMap->dwClientID,
00695 sizeof(scReleaseStruct),
00696 (void *) &scReleaseStruct);
00697
00698 if (rv == -1)
00699 {
00700 rv = SCARD_E_NO_SERVICE;
00701 goto end;
00702 }
00703
00704
00705
00706
00707 rv = MessageReceive(&scReleaseStruct, sizeof(scReleaseStruct),
00708 currentContextMap->dwClientID);
00709
00710 if (rv < 0)
00711 {
00712 rv = SCARD_F_COMM_ERROR;
00713 goto end;
00714 }
00715
00716 rv = scReleaseStruct.rv;
00717 end:
00718 (void)pthread_mutex_unlock(currentContextMap->mMutex);
00719
00720
00721
00722
00723 (void)SCardLockThread();
00724 (void)SCardRemoveContext(hContext);
00725 (void)SCardUnlockThread();
00726
00727 PROFILE_END(rv)
00728
00729 return rv;
00730 }
00731
00747 LONG SCardSetTimeout( SCARDCONTEXT hContext,
00748 DWORD dwTimeout)
00749 {
00750
00751
00752
00753 (void)hContext;
00754 (void)dwTimeout;
00755 return SCARD_S_SUCCESS;
00756 }
00757
00815 LONG SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader,
00816 DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard,
00817 LPDWORD pdwActiveProtocol)
00818 {
00819 LONG rv;
00820 struct connect_struct scConnectStruct;
00821 SCONTEXTMAP * currentContextMap;
00822
00823 PROFILE_START
00824
00825
00826
00827
00828 if (phCard == NULL || pdwActiveProtocol == NULL)
00829 return SCARD_E_INVALID_PARAMETER;
00830 else
00831 *phCard = 0;
00832
00833 if (szReader == NULL)
00834 return SCARD_E_UNKNOWN_READER;
00835
00836
00837
00838
00839 if (strlen(szReader) > MAX_READERNAME)
00840 return SCARD_E_INVALID_VALUE;
00841
00842 CHECK_SAME_PROCESS
00843
00844
00845
00846
00847 currentContextMap = SCardGetContext(hContext);
00848 if (NULL == currentContextMap)
00849 return SCARD_E_INVALID_HANDLE;
00850
00851 (void)pthread_mutex_lock(currentContextMap->mMutex);
00852
00853
00854 currentContextMap = SCardGetContext(hContext);
00855 if (NULL == currentContextMap)
00856
00857
00858
00859 return SCARD_E_INVALID_HANDLE;
00860
00861 strncpy(scConnectStruct.szReader, szReader, MAX_READERNAME);
00862
00863 scConnectStruct.hContext = hContext;
00864 scConnectStruct.dwShareMode = dwShareMode;
00865 scConnectStruct.dwPreferredProtocols = dwPreferredProtocols;
00866 scConnectStruct.hCard = 0;
00867 scConnectStruct.dwActiveProtocol = 0;
00868 scConnectStruct.rv = SCARD_S_SUCCESS;
00869
00870 rv = MessageSendWithHeader(SCARD_CONNECT, currentContextMap->dwClientID,
00871 sizeof(scConnectStruct),
00872 (void *) &scConnectStruct);
00873
00874 if (rv == -1)
00875 {
00876 rv = SCARD_E_NO_SERVICE;
00877 goto end;
00878 }
00879
00880
00881
00882
00883 rv = MessageReceive(&scConnectStruct, sizeof(scConnectStruct),
00884 currentContextMap->dwClientID);
00885
00886 if (rv < 0)
00887 {
00888 rv = SCARD_F_COMM_ERROR;
00889 goto end;
00890 }
00891
00892 *phCard = scConnectStruct.hCard;
00893 *pdwActiveProtocol = scConnectStruct.dwActiveProtocol;
00894
00895 if (scConnectStruct.rv == SCARD_S_SUCCESS)
00896 {
00897
00898
00899
00900 rv = SCardAddHandle(*phCard, currentContextMap, szReader);
00901 }
00902 else
00903 rv = scConnectStruct.rv;
00904
00905 end:
00906 (void)pthread_mutex_unlock(currentContextMap->mMutex);
00907
00908 PROFILE_END(rv)
00909
00910 return rv;
00911 }
00912
00986 LONG SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode,
00987 DWORD dwPreferredProtocols, DWORD dwInitialization,
00988 LPDWORD pdwActiveProtocol)
00989 {
00990 LONG rv;
00991 struct reconnect_struct scReconnectStruct;
00992 SCONTEXTMAP * currentContextMap;
00993 CHANNEL_MAP * pChannelMap;
00994
00995 PROFILE_START
00996
00997 if (pdwActiveProtocol == NULL)
00998 return SCARD_E_INVALID_PARAMETER;
00999
01000 CHECK_SAME_PROCESS
01001
01002
01003
01004
01005 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
01006 &pChannelMap);
01007 if (rv == -1)
01008 return SCARD_E_INVALID_HANDLE;
01009
01010 (void)pthread_mutex_lock(currentContextMap->mMutex);
01011
01012
01013 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
01014 &pChannelMap);
01015 if (rv == -1)
01016
01017
01018
01019 return SCARD_E_INVALID_HANDLE;
01020
01021
01022 retry:
01023
01024 scReconnectStruct.hCard = hCard;
01025 scReconnectStruct.dwShareMode = dwShareMode;
01026 scReconnectStruct.dwPreferredProtocols = dwPreferredProtocols;
01027 scReconnectStruct.dwInitialization = dwInitialization;
01028 scReconnectStruct.dwActiveProtocol = *pdwActiveProtocol;
01029 scReconnectStruct.rv = SCARD_S_SUCCESS;
01030
01031 rv = MessageSendWithHeader(SCARD_RECONNECT,
01032 currentContextMap->dwClientID,
01033 sizeof(scReconnectStruct),
01034 (void *) &scReconnectStruct);
01035
01036 if (rv == -1)
01037 {
01038 rv = SCARD_E_NO_SERVICE;
01039 goto end;
01040 }
01041
01042
01043
01044
01045 rv = MessageReceive(&scReconnectStruct,
01046 sizeof(scReconnectStruct),
01047 currentContextMap->dwClientID);
01048
01049 if (rv < 0)
01050 {
01051 rv = SCARD_F_COMM_ERROR;
01052 goto end;
01053 }
01054
01055 rv = scReconnectStruct.rv;
01056
01057 if (sharing_shall_block && (SCARD_E_SHARING_VIOLATION == rv))
01058 {
01059 (void)SYS_USleep(PCSCLITE_LOCK_POLL_RATE);
01060 goto retry;
01061 }
01062
01063 *pdwActiveProtocol = scReconnectStruct.dwActiveProtocol;
01064
01065 end:
01066 (void)pthread_mutex_unlock(currentContextMap->mMutex);
01067
01068 PROFILE_END(rv)
01069
01070 return rv;
01071 }
01072
01104 LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
01105 {
01106 LONG rv;
01107 struct disconnect_struct scDisconnectStruct;
01108 SCONTEXTMAP * currentContextMap;
01109 CHANNEL_MAP * pChannelMap;
01110
01111 PROFILE_START
01112
01113 CHECK_SAME_PROCESS
01114
01115
01116
01117
01118 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
01119 &pChannelMap);
01120 if (rv == -1)
01121 return SCARD_E_INVALID_HANDLE;
01122
01123 (void)pthread_mutex_lock(currentContextMap->mMutex);
01124
01125
01126 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
01127 &pChannelMap);
01128 if (rv == -1)
01129
01130
01131
01132 return SCARD_E_INVALID_HANDLE;
01133
01134 scDisconnectStruct.hCard = hCard;
01135 scDisconnectStruct.dwDisposition = dwDisposition;
01136 scDisconnectStruct.rv = SCARD_S_SUCCESS;
01137
01138 rv = MessageSendWithHeader(SCARD_DISCONNECT,
01139 currentContextMap->dwClientID,
01140 sizeof(scDisconnectStruct),
01141 (void *) &scDisconnectStruct);
01142
01143 if (rv == -1)
01144 {
01145 rv = SCARD_E_NO_SERVICE;
01146 goto end;
01147 }
01148
01149
01150
01151
01152 rv = MessageReceive(&scDisconnectStruct,
01153 sizeof(scDisconnectStruct),
01154 currentContextMap->dwClientID);
01155
01156 if (rv < 0)
01157 {
01158 rv = SCARD_F_COMM_ERROR;
01159 goto end;
01160 }
01161
01162 (void)SCardRemoveHandle(hCard);
01163 rv = scDisconnectStruct.rv;
01164
01165 end:
01166 (void)pthread_mutex_unlock(currentContextMap->mMutex);
01167
01168 PROFILE_END(rv)
01169
01170 return rv;
01171 }
01172
01208 LONG SCardBeginTransaction(SCARDHANDLE hCard)
01209 {
01210
01211 LONG rv;
01212 struct begin_struct scBeginStruct;
01213 SCONTEXTMAP * currentContextMap;
01214 CHANNEL_MAP * pChannelMap;
01215
01216 PROFILE_START
01217
01218 CHECK_SAME_PROCESS
01219
01220
01221
01222
01223 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
01224 &pChannelMap);
01225 if (rv == -1)
01226 return SCARD_E_INVALID_HANDLE;
01227
01228 (void)pthread_mutex_lock(currentContextMap->mMutex);
01229
01230
01231 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
01232 &pChannelMap);
01233 if (rv == -1)
01234
01235
01236
01237 return SCARD_E_INVALID_HANDLE;
01238
01239 scBeginStruct.hCard = hCard;
01240 scBeginStruct.rv = SCARD_S_SUCCESS;
01241
01242
01243
01244
01245
01246
01247 do
01248 {
01249 rv = MessageSendWithHeader(SCARD_BEGIN_TRANSACTION,
01250 currentContextMap->dwClientID,
01251 sizeof(scBeginStruct),
01252 (void *) &scBeginStruct);
01253
01254 if (rv == -1)
01255 {
01256 rv = SCARD_E_NO_SERVICE;
01257 goto end;
01258 }
01259
01260
01261
01262
01263 rv = MessageReceive(&scBeginStruct, sizeof(scBeginStruct),
01264 currentContextMap->dwClientID);
01265
01266 if (rv < 0)
01267 {
01268 rv = SCARD_F_COMM_ERROR;
01269 goto end;
01270 }
01271
01272 rv = scBeginStruct.rv;
01273 }
01274 while (SCARD_E_SHARING_VIOLATION == rv);
01275
01276 end:
01277 (void)pthread_mutex_unlock(currentContextMap->mMutex);
01278
01279 PROFILE_END(rv)
01280
01281 return rv;
01282 }
01283
01324 LONG SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
01325 {
01326 LONG rv;
01327 struct end_struct scEndStruct;
01328 int randnum;
01329 SCONTEXTMAP * currentContextMap;
01330 CHANNEL_MAP * pChannelMap;
01331
01332 PROFILE_START
01333
01334
01335
01336
01337 randnum = 0;
01338
01339 CHECK_SAME_PROCESS
01340
01341
01342
01343
01344 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
01345 &pChannelMap);
01346 if (rv == -1)
01347 return SCARD_E_INVALID_HANDLE;
01348
01349 (void)pthread_mutex_lock(currentContextMap->mMutex);
01350
01351
01352 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
01353 &pChannelMap);
01354 if (rv == -1)
01355
01356
01357
01358 return SCARD_E_INVALID_HANDLE;
01359
01360 scEndStruct.hCard = hCard;
01361 scEndStruct.dwDisposition = dwDisposition;
01362 scEndStruct.rv = SCARD_S_SUCCESS;
01363
01364 rv = MessageSendWithHeader(SCARD_END_TRANSACTION,
01365 currentContextMap->dwClientID,
01366 sizeof(scEndStruct),
01367 (void *) &scEndStruct);
01368
01369 if (rv == -1)
01370 {
01371 rv = SCARD_E_NO_SERVICE;
01372 goto end;
01373 }
01374
01375
01376
01377
01378 rv = MessageReceive(&scEndStruct, sizeof(scEndStruct),
01379 currentContextMap->dwClientID);
01380
01381 if (rv < 0)
01382 {
01383 rv = SCARD_F_COMM_ERROR;
01384 goto end;
01385 }
01386
01387
01388
01389
01390 randnum = SYS_RandomInt(1000, 10000);
01391 (void)SYS_USleep(randnum);
01392 rv = scEndStruct.rv;
01393
01394 end:
01395 (void)pthread_mutex_unlock(currentContextMap->mMutex);
01396
01397 PROFILE_END(rv)
01398
01399 return rv;
01400 }
01401
01408 LONG SCardCancelTransaction(SCARDHANDLE hCard)
01409 {
01410 LONG rv;
01411 struct cancel_transaction_struct scCancelStruct;
01412 SCONTEXTMAP * currentContextMap;
01413 CHANNEL_MAP * pChannelMap;
01414
01415 PROFILE_START
01416
01417 CHECK_SAME_PROCESS
01418
01419
01420
01421
01422 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
01423 &pChannelMap);
01424 if (rv == -1)
01425 return SCARD_E_INVALID_HANDLE;
01426
01427 (void)pthread_mutex_lock(currentContextMap->mMutex);
01428
01429
01430 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
01431 &pChannelMap);
01432 if (rv == -1)
01433
01434
01435
01436 return SCARD_E_INVALID_HANDLE;
01437
01438 scCancelStruct.hCard = hCard;
01439
01440 rv = MessageSendWithHeader(SCARD_CANCEL_TRANSACTION,
01441 currentContextMap->dwClientID,
01442 sizeof(scCancelStruct), (void *) &scCancelStruct);
01443
01444 if (rv == -1)
01445 {
01446 rv = SCARD_E_NO_SERVICE;
01447 goto end;
01448 }
01449
01450
01451
01452
01453 rv = MessageReceive(&scCancelStruct, sizeof(scCancelStruct),
01454 currentContextMap->dwClientID);
01455
01456 if (rv < 0)
01457 {
01458 rv = SCARD_F_COMM_ERROR;
01459 goto end;
01460 }
01461 rv = scCancelStruct.rv;
01462
01463 end:
01464 (void)pthread_mutex_unlock(currentContextMap->mMutex);
01465
01466 PROFILE_END(rv)
01467
01468 return rv;
01469 }
01470
01560 LONG SCardStatus(SCARDHANDLE hCard, LPSTR mszReaderName,
01561 LPDWORD pcchReaderLen, LPDWORD pdwState,
01562 LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
01563 {
01564 DWORD dwReaderLen, dwAtrLen;
01565 LONG rv;
01566 int i;
01567 struct status_struct scStatusStruct;
01568 SCONTEXTMAP * currentContextMap;
01569 CHANNEL_MAP * pChannelMap;
01570 char *r;
01571 char *bufReader = NULL;
01572 LPBYTE bufAtr = NULL;
01573 DWORD dummy;
01574
01575 PROFILE_START
01576
01577
01578 if (pdwState)
01579 *pdwState = 0;
01580
01581 if (pdwProtocol)
01582 *pdwProtocol = 0;
01583
01584
01585 if (pcchReaderLen == NULL)
01586 pcchReaderLen = &dummy;
01587
01588 if (pcbAtrLen == NULL)
01589 pcbAtrLen = &dummy;
01590
01591
01592 dwReaderLen = *pcchReaderLen;
01593 dwAtrLen = *pcbAtrLen;
01594
01595 *pcchReaderLen = 0;
01596 *pcbAtrLen = 0;
01597
01598 CHECK_SAME_PROCESS
01599
01600
01601
01602
01603 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
01604 &pChannelMap);
01605 if (rv == -1)
01606 return SCARD_E_INVALID_HANDLE;
01607
01608 (void)pthread_mutex_lock(currentContextMap->mMutex);
01609
01610
01611 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
01612 &pChannelMap);
01613 if (rv == -1)
01614
01615
01616
01617 return SCARD_E_INVALID_HANDLE;
01618
01619
01620 rv = getReaderStates(currentContextMap);
01621 if (rv != SCARD_S_SUCCESS)
01622 goto end;
01623
01624 r = pChannelMap->readerName;
01625 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01626 {
01627
01628 if (r && strcmp(r, readerStates[i].readerName) == 0)
01629 break;
01630 }
01631
01632 if (i == PCSCLITE_MAX_READERS_CONTEXTS)
01633 {
01634 rv = SCARD_E_READER_UNAVAILABLE;
01635 goto end;
01636 }
01637
01638
01639 retry:
01640
01641
01642 memset(&scStatusStruct, 0, sizeof(scStatusStruct));
01643 scStatusStruct.hCard = hCard;
01644
01645
01646 scStatusStruct.pcchReaderLen = sizeof(scStatusStruct.mszReaderNames);
01647 scStatusStruct.pcbAtrLen = sizeof(scStatusStruct.pbAtr);
01648
01649 rv = MessageSendWithHeader(SCARD_STATUS, currentContextMap->dwClientID,
01650 sizeof(scStatusStruct),
01651 (void *) &scStatusStruct);
01652
01653 if (rv == -1)
01654 {
01655 rv = SCARD_E_NO_SERVICE;
01656 goto end;
01657 }
01658
01659
01660
01661
01662 rv = MessageReceive(&scStatusStruct, sizeof(scStatusStruct),
01663 currentContextMap->dwClientID);
01664
01665 if (rv < 0)
01666 {
01667 rv = SCARD_F_COMM_ERROR;
01668 goto end;
01669 }
01670
01671 rv = scStatusStruct.rv;
01672
01673 if (sharing_shall_block && (SCARD_E_SHARING_VIOLATION == rv))
01674 {
01675 (void)SYS_USleep(PCSCLITE_LOCK_POLL_RATE);
01676 goto retry;
01677 }
01678
01679 if (rv != SCARD_S_SUCCESS && rv != SCARD_E_INSUFFICIENT_BUFFER)
01680 {
01681
01682
01683
01684 goto end;
01685 }
01686
01687
01688
01689
01690
01691 *pcchReaderLen = strlen(pChannelMap->readerName) + 1;
01692 *pcbAtrLen = readerStates[i].cardAtrLength;
01693
01694 if (pdwState)
01695 *pdwState = readerStates[i].readerState;
01696
01697 if (pdwProtocol)
01698 *pdwProtocol = readerStates[i].cardProtocol;
01699
01700 if (SCARD_AUTOALLOCATE == dwReaderLen)
01701 {
01702 dwReaderLen = *pcchReaderLen;
01703 bufReader = malloc(dwReaderLen);
01704 if (NULL == bufReader)
01705 {
01706 rv = SCARD_E_NO_MEMORY;
01707 goto end;
01708 }
01709 if (NULL == mszReaderName)
01710 {
01711 rv = SCARD_E_INVALID_PARAMETER;
01712 goto end;
01713 }
01714 *(char **)mszReaderName = bufReader;
01715 }
01716 else
01717 bufReader = mszReaderName;
01718
01719
01720 if (bufReader)
01721 {
01722 if (*pcchReaderLen > dwReaderLen)
01723 rv = SCARD_E_INSUFFICIENT_BUFFER;
01724
01725 strncpy(bufReader,
01726 pChannelMap->readerName,
01727 dwReaderLen);
01728 }
01729
01730 if (SCARD_AUTOALLOCATE == dwAtrLen)
01731 {
01732 dwAtrLen = *pcbAtrLen;
01733 bufAtr = malloc(dwAtrLen);
01734 if (NULL == bufAtr)
01735 {
01736 rv = SCARD_E_NO_MEMORY;
01737 goto end;
01738 }
01739 if (NULL == pbAtr)
01740 {
01741 rv = SCARD_E_INVALID_PARAMETER;
01742 goto end;
01743 }
01744 *(LPBYTE *)pbAtr = bufAtr;
01745 }
01746 else
01747 bufAtr = pbAtr;
01748
01749 if (bufAtr)
01750 {
01751 if (*pcbAtrLen > dwAtrLen)
01752 rv = SCARD_E_INSUFFICIENT_BUFFER;
01753
01754 memcpy(bufAtr, readerStates[i].cardAtr, min(*pcbAtrLen, dwAtrLen));
01755 }
01756
01757 end:
01758 (void)pthread_mutex_unlock(currentContextMap->mMutex);
01759
01760 PROFILE_END(rv)
01761
01762 return rv;
01763 }
01764
01859 LONG SCardGetStatusChange(SCARDCONTEXT hContext, DWORD dwTimeout,
01860 SCARD_READERSTATE *rgReaderStates, DWORD cReaders)
01861 {
01862 SCARD_READERSTATE *currReader;
01863 READER_STATE *rContext;
01864 long dwTime;
01865 DWORD dwState;
01866 DWORD dwBreakFlag = 0;
01867 unsigned int j;
01868 SCONTEXTMAP * currentContextMap;
01869 int currentReaderCount = 0;
01870 LONG rv = SCARD_S_SUCCESS;
01871
01872 PROFILE_START
01873
01874 if ((rgReaderStates == NULL && cReaders > 0)
01875 || (cReaders > PCSCLITE_MAX_READERS_CONTEXTS))
01876 return SCARD_E_INVALID_PARAMETER;
01877
01878
01879 for (j = 0; j < cReaders; j++)
01880 {
01881 if (rgReaderStates[j].szReader == NULL)
01882 return SCARD_E_INVALID_VALUE;
01883 }
01884
01885
01886 if (cReaders > 0)
01887 {
01888 int nbNonIgnoredReaders = cReaders;
01889
01890 for (j=0; j<cReaders; j++)
01891 if (rgReaderStates[j].dwCurrentState & SCARD_STATE_IGNORE)
01892 nbNonIgnoredReaders--;
01893
01894 if (0 == nbNonIgnoredReaders)
01895 return SCARD_S_SUCCESS;
01896 }
01897 else
01898
01899 return SCARD_S_SUCCESS;
01900
01901 CHECK_SAME_PROCESS
01902
01903
01904
01905
01906 currentContextMap = SCardGetContext(hContext);
01907 if (NULL == currentContextMap)
01908 return SCARD_E_INVALID_HANDLE;
01909
01910 (void)pthread_mutex_lock(currentContextMap->mMutex);
01911
01912
01913 currentContextMap = SCardGetContext(hContext);
01914 if (NULL == currentContextMap)
01915
01916
01917
01918 return SCARD_E_INVALID_HANDLE;
01919
01920
01921 rv = getReaderStates(currentContextMap);
01922 if (rv != SCARD_S_SUCCESS)
01923 goto end;
01924
01925
01926 for (j = 0; j < cReaders; j++)
01927 rgReaderStates[j].dwEventState = 0;
01928
01929
01930 Log2(PCSC_LOG_DEBUG, "Event Loop Start, dwTimeout: %ld", dwTimeout);
01931
01932
01933 for (j=0; j < PCSCLITE_MAX_READERS_CONTEXTS; j++)
01934 if (readerStates[j].readerID != 0)
01935 currentReaderCount++;
01936
01937 if (INFINITE == dwTimeout)
01938 dwTime = 60*1000;
01939 else
01940 dwTime = dwTimeout;
01941
01942 j = 0;
01943 do
01944 {
01945 currReader = &rgReaderStates[j];
01946
01947
01948 if (!(currReader->dwCurrentState & SCARD_STATE_IGNORE))
01949 {
01950 LPSTR lpcReaderName;
01951 int i;
01952
01953
01954
01955 lpcReaderName = (char *) currReader->szReader;
01956
01957 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01958 {
01959 if (strcmp(lpcReaderName, readerStates[i].readerName) == 0)
01960 break;
01961 }
01962
01963
01964 if (i == PCSCLITE_MAX_READERS_CONTEXTS)
01965 {
01966
01967 if (strcasecmp(lpcReaderName, "\\\\?PnP?\\Notification") == 0)
01968 {
01969 int k, newReaderCount = 0;
01970
01971 for (k=0; k < PCSCLITE_MAX_READERS_CONTEXTS; k++)
01972 if (readerStates[k].readerID != 0)
01973 newReaderCount++;
01974
01975 if (newReaderCount != currentReaderCount)
01976 {
01977 Log1(PCSC_LOG_INFO, "Reader list changed");
01978 currentReaderCount = newReaderCount;
01979
01980 currReader->dwEventState |= SCARD_STATE_CHANGED;
01981 dwBreakFlag = 1;
01982 }
01983 }
01984 else
01985 {
01986 currReader->dwEventState = SCARD_STATE_UNKNOWN | SCARD_STATE_UNAVAILABLE;
01987 if (!(currReader->dwCurrentState & SCARD_STATE_UNKNOWN))
01988 {
01989 currReader->dwEventState |= SCARD_STATE_CHANGED;
01990
01991
01992
01993
01994
01995 dwBreakFlag = 1;
01996 }
01997 }
01998 }
01999 else
02000 {
02001
02002 if (currReader->dwCurrentState & SCARD_STATE_UNKNOWN)
02003 {
02004 currReader->dwEventState |= SCARD_STATE_CHANGED;
02005 currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
02006 Log0(PCSC_LOG_DEBUG);
02007 dwBreakFlag = 1;
02008 }
02009
02010
02011
02012
02013 rContext = &readerStates[i];
02014
02015
02016 dwState = rContext->readerState;
02017
02018
02019 if (currReader->dwCurrentState & 0xFFFF0000)
02020 {
02021 int currentCounter, stateCounter;
02022
02023 stateCounter = (dwState >> 16) & 0xFFFF;
02024 currentCounter = (currReader->dwCurrentState >> 16) & 0xFFFF;
02025
02026
02027 if (stateCounter != currentCounter)
02028 {
02029 currReader->dwEventState |= SCARD_STATE_CHANGED;
02030 Log0(PCSC_LOG_DEBUG);
02031 dwBreakFlag = 1;
02032 }
02033
02034
02035 currReader->dwEventState =
02036 ((currReader->dwEventState & 0xffff )
02037 | (stateCounter << 16));
02038 }
02039
02040
02041 if (dwState & SCARD_UNKNOWN)
02042 {
02043
02044 currReader->dwEventState = SCARD_STATE_UNAVAILABLE;
02045 if (!(currReader->dwCurrentState & SCARD_STATE_UNAVAILABLE))
02046 {
02047
02048 currReader->dwEventState |= SCARD_STATE_CHANGED;
02049 Log0(PCSC_LOG_DEBUG);
02050 dwBreakFlag = 1;
02051 }
02052 }
02053 else
02054 {
02055
02056 if (currReader-> dwCurrentState & SCARD_STATE_UNAVAILABLE)
02057 {
02058 currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
02059 currReader->dwEventState |= SCARD_STATE_CHANGED;
02060 Log0(PCSC_LOG_DEBUG);
02061 dwBreakFlag = 1;
02062 }
02063 }
02064
02065
02066
02067 if (dwState & SCARD_PRESENT)
02068 {
02069
02070 if (0 == rContext->cardAtrLength)
02071
02072 (void)SYS_USleep(PCSCLITE_STATUS_POLL_RATE + 10);
02073
02074 currReader->cbAtr = rContext->cardAtrLength;
02075 memcpy(currReader->rgbAtr, rContext->cardAtr,
02076 currReader->cbAtr);
02077 }
02078 else
02079 currReader->cbAtr = 0;
02080
02081
02082 if (dwState & SCARD_ABSENT)
02083 {
02084 currReader->dwEventState |= SCARD_STATE_EMPTY;
02085 currReader->dwEventState &= ~SCARD_STATE_PRESENT;
02086 currReader->dwEventState &= ~SCARD_STATE_UNAWARE;
02087 currReader->dwEventState &= ~SCARD_STATE_IGNORE;
02088 currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
02089 currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
02090 currReader->dwEventState &= ~SCARD_STATE_ATRMATCH;
02091 currReader->dwEventState &= ~SCARD_STATE_MUTE;
02092 currReader->dwEventState &= ~SCARD_STATE_INUSE;
02093
02094
02095 if (currReader->dwCurrentState & SCARD_STATE_PRESENT)
02096 {
02097 currReader->dwEventState |= SCARD_STATE_CHANGED;
02098 Log0(PCSC_LOG_DEBUG);
02099 dwBreakFlag = 1;
02100 }
02101 }
02102
02103 else if (dwState & SCARD_PRESENT)
02104 {
02105 currReader->dwEventState |= SCARD_STATE_PRESENT;
02106 currReader->dwEventState &= ~SCARD_STATE_EMPTY;
02107 currReader->dwEventState &= ~SCARD_STATE_UNAWARE;
02108 currReader->dwEventState &= ~SCARD_STATE_IGNORE;
02109 currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
02110 currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
02111 currReader->dwEventState &= ~SCARD_STATE_MUTE;
02112
02113 if (currReader->dwCurrentState & SCARD_STATE_EMPTY)
02114 {
02115 currReader->dwEventState |= SCARD_STATE_CHANGED;
02116 Log0(PCSC_LOG_DEBUG);
02117 dwBreakFlag = 1;
02118 }
02119
02120 if (dwState & SCARD_SWALLOWED)
02121 {
02122 currReader->dwEventState |= SCARD_STATE_MUTE;
02123 if (!(currReader->dwCurrentState & SCARD_STATE_MUTE))
02124 {
02125 currReader->dwEventState |= SCARD_STATE_CHANGED;
02126 Log0(PCSC_LOG_DEBUG);
02127 dwBreakFlag = 1;
02128 }
02129 }
02130 else
02131 {
02132
02133 if (currReader->dwCurrentState & SCARD_STATE_MUTE)
02134 {
02135 currReader->dwEventState |= SCARD_STATE_CHANGED;
02136 Log0(PCSC_LOG_DEBUG);
02137 dwBreakFlag = 1;
02138 }
02139 }
02140 }
02141
02142
02143 if (rContext->readerSharing == SCARD_EXCLUSIVE_CONTEXT)
02144 {
02145 currReader->dwEventState |= SCARD_STATE_EXCLUSIVE;
02146 currReader->dwEventState &= ~SCARD_STATE_INUSE;
02147 if (currReader->dwCurrentState & SCARD_STATE_INUSE)
02148 {
02149 currReader->dwEventState |= SCARD_STATE_CHANGED;
02150 Log0(PCSC_LOG_DEBUG);
02151 dwBreakFlag = 1;
02152 }
02153 }
02154 else if (rContext->readerSharing >= SCARD_LAST_CONTEXT)
02155 {
02156
02157 if (dwState & SCARD_PRESENT)
02158 {
02159 currReader->dwEventState |= SCARD_STATE_INUSE;
02160 currReader->dwEventState &= ~SCARD_STATE_EXCLUSIVE;
02161 if (currReader-> dwCurrentState & SCARD_STATE_EXCLUSIVE)
02162 {
02163 currReader->dwEventState |= SCARD_STATE_CHANGED;
02164 Log0(PCSC_LOG_DEBUG);
02165 dwBreakFlag = 1;
02166 }
02167 }
02168 }
02169 else if (rContext->readerSharing == SCARD_NO_CONTEXT)
02170 {
02171 currReader->dwEventState &= ~SCARD_STATE_INUSE;
02172 currReader->dwEventState &= ~SCARD_STATE_EXCLUSIVE;
02173
02174 if (currReader->dwCurrentState & SCARD_STATE_INUSE)
02175 {
02176 currReader->dwEventState |= SCARD_STATE_CHANGED;
02177 Log0(PCSC_LOG_DEBUG);
02178 dwBreakFlag = 1;
02179 }
02180 else if (currReader-> dwCurrentState
02181 & SCARD_STATE_EXCLUSIVE)
02182 {
02183 currReader->dwEventState |= SCARD_STATE_CHANGED;
02184 Log0(PCSC_LOG_DEBUG);
02185 dwBreakFlag = 1;
02186 }
02187 }
02188
02189 if (currReader->dwCurrentState == SCARD_STATE_UNAWARE)
02190 {
02191
02192
02193
02194
02195 currReader->dwEventState |= SCARD_STATE_CHANGED;
02196 Log0(PCSC_LOG_DEBUG);
02197 dwBreakFlag = 1;
02198 }
02199 }
02200 }
02201
02202
02203 j++;
02204 if (j == cReaders)
02205 {
02206
02207 j = 0;
02208
02209
02210
02211
02212 if (dwBreakFlag == 1)
02213 break;
02214
02215
02216 {
02217 struct wait_reader_state_change waitStatusStruct;
02218 struct timeval before, after;
02219
02220 gettimeofday(&before, NULL);
02221
02222 waitStatusStruct.timeOut = dwTime;
02223 waitStatusStruct.rv = SCARD_S_SUCCESS;
02224
02225 rv = MessageSendWithHeader(CMD_WAIT_READER_STATE_CHANGE,
02226 currentContextMap->dwClientID,
02227 sizeof(waitStatusStruct),
02228 &waitStatusStruct);
02229
02230 if (rv == -1)
02231 {
02232 rv = SCARD_E_NO_SERVICE;
02233 goto end;
02234 }
02235
02236
02237
02238
02239 rv = MessageReceiveTimeout(CMD_WAIT_READER_STATE_CHANGE,
02240 &waitStatusStruct, sizeof(waitStatusStruct),
02241 currentContextMap->dwClientID, dwTime);
02242
02243
02244 if (-2 == rv)
02245 {
02246
02247 rv = MessageSendWithHeader(CMD_STOP_WAITING_READER_STATE_CHANGE,
02248 currentContextMap->dwClientID,
02249 sizeof(waitStatusStruct),
02250 &waitStatusStruct);
02251
02252 if (rv == -1)
02253 {
02254 rv = SCARD_E_NO_SERVICE;
02255 goto end;
02256 }
02257
02258
02259 rv = MessageReceive(&waitStatusStruct,
02260 sizeof(waitStatusStruct),
02261 currentContextMap->dwClientID);
02262
02263 if (rv == -1)
02264 {
02265 rv = SCARD_E_NO_SERVICE;
02266 goto end;
02267 }
02268 }
02269
02270 if (rv < 0)
02271 {
02272 rv = SCARD_E_NO_SERVICE;
02273 goto end;
02274 }
02275
02276
02277 if (SCARD_S_SUCCESS != waitStatusStruct.rv)
02278 {
02279 rv = waitStatusStruct.rv;
02280 goto end;
02281 }
02282
02283
02284 rv = getReaderStates(currentContextMap);
02285 if (rv != SCARD_S_SUCCESS)
02286 goto end;
02287
02288 if (INFINITE != dwTimeout)
02289 {
02290 long int diff;
02291
02292 gettimeofday(&after, NULL);
02293 diff = time_sub(&after, &before);
02294 dwTime -= diff/1000;
02295 }
02296 }
02297
02298 if (dwTimeout != INFINITE)
02299 {
02300
02301
02302
02303 if (dwTime <= 0)
02304 {
02305 rv = SCARD_E_TIMEOUT;
02306 goto end;
02307 }
02308 }
02309 }
02310 }
02311 while (1);
02312
02313 end:
02314 Log1(PCSC_LOG_DEBUG, "Event Loop End");
02315
02316 (void)pthread_mutex_unlock(currentContextMap->mMutex);
02317
02318 PROFILE_END(rv)
02319
02320 return rv;
02321 }
02322
02376 LONG SCardControl(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer,
02377 DWORD cbSendLength, LPVOID pbRecvBuffer, DWORD cbRecvLength,
02378 LPDWORD lpBytesReturned)
02379 {
02380 LONG rv;
02381 struct control_struct scControlStruct;
02382 SCONTEXTMAP * currentContextMap;
02383 CHANNEL_MAP * pChannelMap;
02384
02385 PROFILE_START
02386
02387
02388 if (NULL != lpBytesReturned)
02389 *lpBytesReturned = 0;
02390
02391 CHECK_SAME_PROCESS
02392
02393
02394
02395
02396 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
02397 &pChannelMap);
02398 if (rv == -1)
02399 {
02400 PROFILE_END(SCARD_E_INVALID_HANDLE)
02401 return SCARD_E_INVALID_HANDLE;
02402 }
02403
02404 (void)pthread_mutex_lock(currentContextMap->mMutex);
02405
02406
02407 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
02408 &pChannelMap);
02409 if (rv == -1)
02410
02411
02412
02413 return SCARD_E_INVALID_HANDLE;
02414
02415 if ((cbSendLength > MAX_BUFFER_SIZE_EXTENDED)
02416 || (cbRecvLength > MAX_BUFFER_SIZE_EXTENDED))
02417 {
02418 rv = SCARD_E_INSUFFICIENT_BUFFER;
02419 goto end;
02420 }
02421
02422 scControlStruct.hCard = hCard;
02423 scControlStruct.dwControlCode = dwControlCode;
02424 scControlStruct.cbSendLength = cbSendLength;
02425 scControlStruct.cbRecvLength = cbRecvLength;
02426
02427 rv = MessageSendWithHeader(SCARD_CONTROL,
02428 currentContextMap->dwClientID,
02429 sizeof(scControlStruct), &scControlStruct);
02430
02431 if (rv == -1)
02432 {
02433 rv = SCARD_E_NO_SERVICE;
02434 goto end;
02435 }
02436
02437
02438 rv = MessageSend((char *)pbSendBuffer, cbSendLength,
02439 currentContextMap->dwClientID);
02440
02441 if (rv == -1)
02442 {
02443 rv = SCARD_E_NO_SERVICE;
02444 goto end;
02445 }
02446
02447
02448
02449
02450 rv = MessageReceive(&scControlStruct, sizeof(scControlStruct),
02451 currentContextMap->dwClientID);
02452
02453 if (rv < 0)
02454 {
02455 rv = SCARD_F_COMM_ERROR;
02456 goto end;
02457 }
02458
02459 if (SCARD_S_SUCCESS == scControlStruct.rv)
02460 {
02461
02462 rv = MessageReceive(pbRecvBuffer, scControlStruct.dwBytesReturned,
02463 currentContextMap->dwClientID);
02464
02465 if (rv < 0)
02466 {
02467 rv = SCARD_E_NO_SERVICE;
02468 goto end;
02469 }
02470
02471 }
02472
02473 if (NULL != lpBytesReturned)
02474 *lpBytesReturned = scControlStruct.dwBytesReturned;
02475
02476 rv = scControlStruct.rv;
02477
02478 end:
02479 (void)pthread_mutex_unlock(currentContextMap->mMutex);
02480
02481 PROFILE_END(rv)
02482
02483 return rv;
02484 }
02485
02590 LONG SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr,
02591 LPDWORD pcbAttrLen)
02592 {
02593 LONG ret;
02594 unsigned char *buf = NULL;
02595
02596 PROFILE_START
02597
02598 if (NULL == pcbAttrLen)
02599 return SCARD_E_INVALID_PARAMETER;
02600
02601 if (SCARD_AUTOALLOCATE == *pcbAttrLen)
02602 {
02603 if (NULL == pbAttr)
02604 return SCARD_E_INVALID_PARAMETER;
02605
02606 *pcbAttrLen = MAX_BUFFER_SIZE;
02607 buf = malloc(*pcbAttrLen);
02608 if (NULL == buf)
02609 return SCARD_E_NO_MEMORY;
02610
02611 *(unsigned char **)pbAttr = buf;
02612 }
02613 else
02614 {
02615 buf = pbAttr;
02616
02617
02618 if (NULL == pbAttr)
02619
02620 *pcbAttrLen = MAX_BUFFER_SIZE;
02621 }
02622
02623 ret = SCardGetSetAttrib(hCard, SCARD_GET_ATTRIB, dwAttrId, buf,
02624 pcbAttrLen);
02625
02626 PROFILE_END(ret)
02627
02628 return ret;
02629 }
02630
02666 LONG SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr,
02667 DWORD cbAttrLen)
02668 {
02669 LONG ret;
02670
02671 if (NULL == pbAttr || 0 == cbAttrLen)
02672 return SCARD_E_INVALID_PARAMETER;
02673
02674 ret = SCardGetSetAttrib(hCard, SCARD_SET_ATTRIB, dwAttrId, (LPBYTE)pbAttr,
02675 &cbAttrLen);
02676
02677 return ret;
02678 }
02679
02680 static LONG SCardGetSetAttrib(SCARDHANDLE hCard, int command, DWORD dwAttrId,
02681 LPBYTE pbAttr, LPDWORD pcbAttrLen)
02682 {
02683 LONG rv;
02684 struct getset_struct scGetSetStruct;
02685 SCONTEXTMAP * currentContextMap;
02686 CHANNEL_MAP * pChannelMap;
02687
02688 CHECK_SAME_PROCESS
02689
02690
02691
02692
02693 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
02694 &pChannelMap);
02695 if (rv == -1)
02696 return SCARD_E_INVALID_HANDLE;
02697
02698 (void)pthread_mutex_lock(currentContextMap->mMutex);
02699
02700
02701 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
02702 &pChannelMap);
02703 if (rv == -1)
02704
02705
02706
02707 return SCARD_E_INVALID_HANDLE;
02708
02709 if (*pcbAttrLen > MAX_BUFFER_SIZE)
02710 {
02711 rv = SCARD_E_INSUFFICIENT_BUFFER;
02712 goto end;
02713 }
02714
02715 scGetSetStruct.hCard = hCard;
02716 scGetSetStruct.dwAttrId = dwAttrId;
02717 scGetSetStruct.cbAttrLen = *pcbAttrLen;
02718 scGetSetStruct.rv = SCARD_E_NO_SERVICE;
02719 memset(scGetSetStruct.pbAttr, 0, sizeof(scGetSetStruct.pbAttr));
02720 if (SCARD_SET_ATTRIB == command)
02721 memcpy(scGetSetStruct.pbAttr, pbAttr, *pcbAttrLen);
02722
02723 rv = MessageSendWithHeader(command,
02724 currentContextMap->dwClientID, sizeof(scGetSetStruct),
02725 &scGetSetStruct);
02726
02727 if (rv == -1)
02728 {
02729 rv = SCARD_E_NO_SERVICE;
02730 goto end;
02731 }
02732
02733
02734
02735
02736 rv = MessageReceive(&scGetSetStruct, sizeof(scGetSetStruct),
02737 currentContextMap->dwClientID);
02738
02739 if (rv < 0)
02740 {
02741 rv = SCARD_F_COMM_ERROR;
02742 goto end;
02743 }
02744
02745 if ((SCARD_S_SUCCESS == scGetSetStruct.rv) && (SCARD_GET_ATTRIB == command))
02746 {
02747
02748
02749
02750 if (*pcbAttrLen < scGetSetStruct.cbAttrLen)
02751 {
02752 scGetSetStruct.cbAttrLen = *pcbAttrLen;
02753 scGetSetStruct.rv = SCARD_E_INSUFFICIENT_BUFFER;
02754 }
02755 else
02756 *pcbAttrLen = scGetSetStruct.cbAttrLen;
02757
02758 if (pbAttr)
02759 memcpy(pbAttr, scGetSetStruct.pbAttr, scGetSetStruct.cbAttrLen);
02760
02761 memset(scGetSetStruct.pbAttr, 0x00, sizeof(scGetSetStruct.pbAttr));
02762 }
02763 rv = scGetSetStruct.rv;
02764
02765 end:
02766 (void)pthread_mutex_unlock(currentContextMap->mMutex);
02767
02768 PROFILE_END(rv)
02769
02770 return rv;
02771 }
02772
02831 LONG SCardTransmit(SCARDHANDLE hCard, const SCARD_IO_REQUEST *pioSendPci,
02832 LPCBYTE pbSendBuffer, DWORD cbSendLength,
02833 SCARD_IO_REQUEST *pioRecvPci, LPBYTE pbRecvBuffer,
02834 LPDWORD pcbRecvLength)
02835 {
02836 LONG rv;
02837 SCONTEXTMAP * currentContextMap;
02838 CHANNEL_MAP * pChannelMap;
02839 struct transmit_struct scTransmitStruct;
02840
02841 PROFILE_START
02842
02843 if (pbSendBuffer == NULL || pbRecvBuffer == NULL ||
02844 pcbRecvLength == NULL || pioSendPci == NULL)
02845 return SCARD_E_INVALID_PARAMETER;
02846
02847 CHECK_SAME_PROCESS
02848
02849
02850
02851
02852 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
02853 &pChannelMap);
02854 if (rv == -1)
02855 {
02856 *pcbRecvLength = 0;
02857 PROFILE_END(SCARD_E_INVALID_HANDLE)
02858 return SCARD_E_INVALID_HANDLE;
02859 }
02860
02861 (void)pthread_mutex_lock(currentContextMap->mMutex);
02862
02863
02864 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
02865 &pChannelMap);
02866 if (rv == -1)
02867
02868
02869
02870 return SCARD_E_INVALID_HANDLE;
02871
02872 if ((cbSendLength > MAX_BUFFER_SIZE_EXTENDED)
02873 || (*pcbRecvLength > MAX_BUFFER_SIZE_EXTENDED))
02874 {
02875 rv = SCARD_E_INSUFFICIENT_BUFFER;
02876 goto end;
02877 }
02878
02879
02880 retry:
02881
02882 scTransmitStruct.hCard = hCard;
02883 scTransmitStruct.cbSendLength = cbSendLength;
02884 scTransmitStruct.pcbRecvLength = *pcbRecvLength;
02885 scTransmitStruct.ioSendPciProtocol = pioSendPci->dwProtocol;
02886 scTransmitStruct.ioSendPciLength = pioSendPci->cbPciLength;
02887 scTransmitStruct.rv = SCARD_S_SUCCESS;
02888
02889 if (pioRecvPci)
02890 {
02891 scTransmitStruct.ioRecvPciProtocol = pioRecvPci->dwProtocol;
02892 scTransmitStruct.ioRecvPciLength = pioRecvPci->cbPciLength;
02893 }
02894 else
02895 {
02896 scTransmitStruct.ioRecvPciProtocol = SCARD_PROTOCOL_ANY;
02897 scTransmitStruct.ioRecvPciLength = sizeof(SCARD_IO_REQUEST);
02898 }
02899
02900 rv = MessageSendWithHeader(SCARD_TRANSMIT,
02901 currentContextMap->dwClientID, sizeof(scTransmitStruct),
02902 (void *) &scTransmitStruct);
02903
02904 if (rv == -1)
02905 {
02906 rv = SCARD_E_NO_SERVICE;
02907 goto end;
02908 }
02909
02910
02911 rv = MessageSend((void *)pbSendBuffer, cbSendLength,
02912 currentContextMap->dwClientID);
02913
02914 if (rv == -1)
02915 {
02916 rv = SCARD_E_NO_SERVICE;
02917 goto end;
02918 }
02919
02920
02921
02922
02923 rv = MessageReceive(&scTransmitStruct, sizeof(scTransmitStruct),
02924 currentContextMap->dwClientID);
02925
02926 if (rv < 0)
02927 {
02928 rv = SCARD_F_COMM_ERROR;
02929 goto end;
02930 }
02931
02932 if (SCARD_S_SUCCESS == scTransmitStruct.rv)
02933 {
02934
02935 rv = MessageReceive(pbRecvBuffer, scTransmitStruct.pcbRecvLength,
02936 currentContextMap->dwClientID);
02937
02938 if (rv < 0)
02939 {
02940 rv = SCARD_E_NO_SERVICE;
02941 goto end;
02942 }
02943
02944 if (pioRecvPci)
02945 {
02946 pioRecvPci->dwProtocol = scTransmitStruct.ioRecvPciProtocol;
02947 pioRecvPci->cbPciLength = scTransmitStruct.ioRecvPciLength;
02948 }
02949 }
02950
02951 rv = scTransmitStruct.rv;
02952
02953 if (sharing_shall_block && (SCARD_E_SHARING_VIOLATION == rv))
02954 {
02955 (void)SYS_USleep(PCSCLITE_LOCK_POLL_RATE);
02956 goto retry;
02957 }
02958
02959 *pcbRecvLength = scTransmitStruct.pcbRecvLength;
02960
02961 end:
02962 (void)pthread_mutex_unlock(currentContextMap->mMutex);
02963
02964 PROFILE_END(rv)
02965
02966 return rv;
02967 }
02968
03019 LONG SCardListReaders(SCARDCONTEXT hContext, LPCSTR mszGroups,
03020 LPSTR mszReaders, LPDWORD pcchReaders)
03021 {
03022 DWORD dwReadersLen = 0;
03023 int i;
03024 SCONTEXTMAP * currentContextMap;
03025 LONG rv = SCARD_S_SUCCESS;
03026 char *buf = NULL;
03027
03028 (void)mszGroups;
03029 PROFILE_START
03030
03031
03032
03033
03034 if (pcchReaders == NULL)
03035 return SCARD_E_INVALID_PARAMETER;
03036
03037 CHECK_SAME_PROCESS
03038
03039
03040
03041
03042 currentContextMap = SCardGetContext(hContext);
03043 if (NULL == currentContextMap)
03044 {
03045 PROFILE_END(SCARD_E_INVALID_HANDLE)
03046 return SCARD_E_INVALID_HANDLE;
03047 }
03048
03049 (void)pthread_mutex_lock(currentContextMap->mMutex);
03050
03051
03052 currentContextMap = SCardGetContext(hContext);
03053 if (NULL == currentContextMap)
03054
03055
03056
03057 return SCARD_E_INVALID_HANDLE;
03058
03059
03060 rv = getReaderStates(currentContextMap);
03061 if (rv != SCARD_S_SUCCESS)
03062 goto end;
03063
03064 dwReadersLen = 0;
03065 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
03066 if (readerStates[i].readerID != 0)
03067 dwReadersLen += strlen(readerStates[i].readerName) + 1;
03068
03069
03070 dwReadersLen += 1;
03071
03072 if (1 == dwReadersLen)
03073 {
03074 rv = SCARD_E_NO_READERS_AVAILABLE;
03075 goto end;
03076 }
03077
03078 if (SCARD_AUTOALLOCATE == *pcchReaders)
03079 {
03080 buf = malloc(dwReadersLen);
03081 if (NULL == buf)
03082 {
03083 rv = SCARD_E_NO_MEMORY;
03084 goto end;
03085 }
03086 if (NULL == mszReaders)
03087 {
03088 rv = SCARD_E_INVALID_PARAMETER;
03089 goto end;
03090 }
03091 *(char **)mszReaders = buf;
03092 }
03093 else
03094 {
03095 buf = mszReaders;
03096
03097
03098 if ((NULL != mszReaders) && (*pcchReaders < dwReadersLen))
03099 {
03100 rv = SCARD_E_INSUFFICIENT_BUFFER;
03101 goto end;
03102 }
03103 }
03104
03105 if (mszReaders == NULL)
03106 goto end;
03107
03108 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
03109 {
03110 if (readerStates[i].readerID != 0)
03111 {
03112
03113
03114
03115 strcpy(buf, readerStates[i].readerName);
03116 buf += strlen(readerStates[i].readerName)+1;
03117 }
03118 }
03119 *buf = '\0';
03120
03121 end:
03122
03123 *pcchReaders = dwReadersLen;
03124
03125 (void)pthread_mutex_unlock(currentContextMap->mMutex);
03126
03127 PROFILE_END(rv)
03128
03129 return rv;
03130 }
03131
03145 LONG SCardFreeMemory(SCARDCONTEXT hContext, LPCVOID pvMem)
03146 {
03147 LONG rv = SCARD_S_SUCCESS;
03148 SCONTEXTMAP * currentContextMap;
03149
03150 PROFILE_START
03151
03152 CHECK_SAME_PROCESS
03153
03154
03155
03156
03157 currentContextMap = SCardGetContext(hContext);
03158 if (NULL == currentContextMap)
03159 return SCARD_E_INVALID_HANDLE;
03160
03161 free((void *)pvMem);
03162
03163 PROFILE_END(rv)
03164
03165 return rv;
03166 }
03167
03219 LONG SCardListReaderGroups(SCARDCONTEXT hContext, LPSTR mszGroups,
03220 LPDWORD pcchGroups)
03221 {
03222 LONG rv = SCARD_S_SUCCESS;
03223 SCONTEXTMAP * currentContextMap;
03224 char *buf = NULL;
03225
03226 PROFILE_START
03227
03228
03229 const char ReaderGroup[] = "SCard$DefaultReaders\0";
03230 const unsigned int dwGroups = sizeof(ReaderGroup);
03231
03232 CHECK_SAME_PROCESS
03233
03234
03235
03236
03237 currentContextMap = SCardGetContext(hContext);
03238 if (NULL == currentContextMap)
03239 return SCARD_E_INVALID_HANDLE;
03240
03241 (void)pthread_mutex_lock(currentContextMap->mMutex);
03242
03243
03244 currentContextMap = SCardGetContext(hContext);
03245 if (NULL == currentContextMap)
03246
03247
03248
03249 return SCARD_E_INVALID_HANDLE;
03250
03251 if (SCARD_AUTOALLOCATE == *pcchGroups)
03252 {
03253 buf = malloc(dwGroups);
03254 if (NULL == buf)
03255 {
03256 rv = SCARD_E_NO_MEMORY;
03257 goto end;
03258 }
03259 if (NULL == mszGroups)
03260 {
03261 rv = SCARD_E_INVALID_PARAMETER;
03262 goto end;
03263 }
03264 *(char **)mszGroups = buf;
03265 }
03266 else
03267 {
03268 buf = mszGroups;
03269
03270 if ((NULL != mszGroups) && (*pcchGroups < dwGroups))
03271 {
03272 rv = SCARD_E_INSUFFICIENT_BUFFER;
03273 goto end;
03274 }
03275 }
03276
03277 if (buf)
03278 memcpy(buf, ReaderGroup, dwGroups);
03279
03280 end:
03281 *pcchGroups = dwGroups;
03282
03283 (void)pthread_mutex_unlock(currentContextMap->mMutex);
03284
03285 PROFILE_END(rv)
03286
03287 return rv;
03288 }
03289
03319 LONG SCardCancel(SCARDCONTEXT hContext)
03320 {
03321 SCONTEXTMAP * currentContextMap;
03322 LONG rv = SCARD_S_SUCCESS;
03323 uint32_t dwClientID = 0;
03324 struct cancel_struct scCancelStruct;
03325
03326 PROFILE_START
03327
03328
03329
03330
03331 currentContextMap = SCardGetContext(hContext);
03332 if (NULL == currentContextMap)
03333 return SCARD_E_INVALID_HANDLE;
03334
03335
03336 if (ClientSetupSession(&dwClientID) != 0)
03337 {
03338 rv = SCARD_E_NO_SERVICE;
03339 goto error;
03340 }
03341
03342 scCancelStruct.hContext = hContext;
03343 scCancelStruct.rv = SCARD_S_SUCCESS;
03344
03345 rv = MessageSendWithHeader(SCARD_CANCEL,
03346 dwClientID,
03347 sizeof(scCancelStruct), (void *) &scCancelStruct);
03348
03349 if (rv == -1)
03350 {
03351 rv = SCARD_E_NO_SERVICE;
03352 goto end;
03353 }
03354
03355
03356
03357
03358 rv = MessageReceive(&scCancelStruct, sizeof(scCancelStruct),
03359 dwClientID);
03360
03361 if (rv < 0)
03362 {
03363 rv = SCARD_F_COMM_ERROR;
03364 goto end;
03365 }
03366
03367 rv = scCancelStruct.rv;
03368 end:
03369 ClientCloseSession(dwClientID);
03370
03371 error:
03372 PROFILE_END(rv)
03373
03374 return rv;
03375 }
03376
03400 LONG SCardIsValidContext(SCARDCONTEXT hContext)
03401 {
03402 LONG rv;
03403 SCONTEXTMAP * currentContextMap;
03404
03405 PROFILE_START
03406
03407 rv = SCARD_S_SUCCESS;
03408
03409
03410 CHECK_SAME_PROCESS
03411
03412
03413
03414
03415 currentContextMap = SCardGetContext(hContext);
03416 if (currentContextMap == NULL)
03417 rv = SCARD_E_INVALID_HANDLE;
03418
03419 PROFILE_END(rv)
03420
03421 return rv;
03422 }
03423
03440 static LONG SCardAddContext(SCARDCONTEXT hContext, DWORD dwClientID)
03441 {
03442 int lrv;
03443 SCONTEXTMAP * newContextMap;
03444
03445 newContextMap = malloc(sizeof(SCONTEXTMAP));
03446 if (NULL == newContextMap)
03447 return SCARD_E_NO_MEMORY;
03448
03449 Log2(PCSC_LOG_DEBUG, "Allocating new SCONTEXTMAP @%X", newContextMap);
03450 newContextMap->hContext = hContext;
03451 newContextMap->dwClientID = dwClientID;
03452
03453 newContextMap->mMutex = malloc(sizeof(pthread_mutex_t));
03454 if (NULL == newContextMap->mMutex)
03455 {
03456 Log2(PCSC_LOG_DEBUG, "Freeing SCONTEXTMAP @%X", newContextMap);
03457 free(newContextMap);
03458 return SCARD_E_NO_MEMORY;
03459 }
03460 (void)pthread_mutex_init(newContextMap->mMutex, NULL);
03461
03462 lrv = list_init(&(newContextMap->channelMapList));
03463 if (lrv < 0)
03464 {
03465 Log2(PCSC_LOG_CRITICAL, "list_init failed with return value: %X", lrv);
03466 goto error;
03467 }
03468
03469 lrv = list_attributes_seeker(&(newContextMap->channelMapList),
03470 CHANNEL_MAP_seeker);
03471 if (lrv <0)
03472 {
03473 Log2(PCSC_LOG_CRITICAL,
03474 "list_attributes_seeker failed with return value: %X", lrv);
03475 list_destroy(&(newContextMap->channelMapList));
03476 goto error;
03477 }
03478
03479 lrv = list_append(&contextMapList, newContextMap);
03480 if (lrv < 0)
03481 {
03482 Log2(PCSC_LOG_CRITICAL, "list_append failed with return value: %X",
03483 lrv);
03484 list_destroy(&(newContextMap->channelMapList));
03485 goto error;
03486 }
03487
03488 return SCARD_S_SUCCESS;
03489
03490 error:
03491
03492 (void)pthread_mutex_destroy(newContextMap->mMutex);
03493 free(newContextMap->mMutex);
03494 free(newContextMap);
03495
03496 return SCARD_E_NO_MEMORY;
03497 }
03498
03511 static SCONTEXTMAP * SCardGetContext(SCARDCONTEXT hContext)
03512 {
03513 SCONTEXTMAP * currentContextMap;
03514
03515 (void)SCardLockThread();
03516 currentContextMap = SCardGetContextTH(hContext);
03517 (void)SCardUnlockThread();
03518
03519 return currentContextMap;
03520 }
03521
03534 static SCONTEXTMAP * SCardGetContextTH(SCARDCONTEXT hContext)
03535 {
03536 return list_seek(&contextMapList, &hContext);
03537 }
03538
03548 static LONG SCardRemoveContext(SCARDCONTEXT hContext)
03549 {
03550 SCONTEXTMAP * currentContextMap;
03551 currentContextMap = SCardGetContextTH(hContext);
03552
03553 if (NULL == currentContextMap)
03554 return SCARD_E_INVALID_HANDLE;
03555 else
03556 return SCardCleanContext(currentContextMap);
03557 }
03558
03559 static LONG SCardCleanContext(SCONTEXTMAP * targetContextMap)
03560 {
03561 int list_index, lrv;
03562 int listSize;
03563 CHANNEL_MAP * currentChannelMap;
03564
03565 targetContextMap->hContext = 0;
03566 (void)ClientCloseSession(targetContextMap->dwClientID);
03567 targetContextMap->dwClientID = 0;
03568 (void)pthread_mutex_destroy(targetContextMap->mMutex);
03569 free(targetContextMap->mMutex);
03570 targetContextMap->mMutex = NULL;
03571
03572 listSize = list_size(&(targetContextMap->channelMapList));
03573 for (list_index = 0; list_index < listSize; list_index++)
03574 {
03575 currentChannelMap = list_get_at(&(targetContextMap->channelMapList),
03576 list_index);
03577 if (NULL == currentChannelMap)
03578 {
03579 Log2(PCSC_LOG_CRITICAL, "list_get_at failed for index %d",
03580 list_index);
03581 continue;
03582 }
03583 else
03584 {
03585 free(currentChannelMap->readerName);
03586 free(currentChannelMap);
03587 }
03588
03589 }
03590 list_destroy(&(targetContextMap->channelMapList));
03591
03592 lrv = list_delete(&contextMapList, targetContextMap);
03593 if (lrv < 0)
03594 {
03595 Log2(PCSC_LOG_CRITICAL,
03596 "list_delete failed with return value: %X", lrv);
03597 }
03598
03599 free(targetContextMap);
03600
03601 return SCARD_S_SUCCESS;
03602 }
03603
03604
03605
03606
03607
03608 static LONG SCardAddHandle(SCARDHANDLE hCard, SCONTEXTMAP * currentContextMap,
03609 LPCSTR readerName)
03610 {
03611 CHANNEL_MAP * newChannelMap;
03612 int lrv = -1;
03613
03614 newChannelMap = malloc(sizeof(CHANNEL_MAP));
03615 if (NULL == newChannelMap)
03616 return SCARD_E_NO_MEMORY;
03617
03618 newChannelMap->hCard = hCard;
03619 newChannelMap->readerName = strdup(readerName);
03620
03621 lrv = list_append(&(currentContextMap->channelMapList), newChannelMap);
03622 if (lrv < 0)
03623 {
03624 free(newChannelMap->readerName);
03625 free(newChannelMap);
03626 Log2(PCSC_LOG_CRITICAL, "list_append failed with return value: %X", lrv);
03627 return SCARD_E_NO_MEMORY;
03628 }
03629
03630 return SCARD_S_SUCCESS;
03631 }
03632
03633 static LONG SCardRemoveHandle(SCARDHANDLE hCard)
03634 {
03635 SCONTEXTMAP * currentContextMap;
03636 CHANNEL_MAP * currentChannelMap;
03637 int lrv;
03638 LONG rv;
03639
03640 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
03641 ¤tChannelMap);
03642 if (rv == -1)
03643 return SCARD_E_INVALID_HANDLE;
03644
03645 free(currentChannelMap->readerName);
03646
03647 lrv = list_delete(&(currentContextMap->channelMapList), currentChannelMap);
03648 if (lrv < 0)
03649 {
03650 Log2(PCSC_LOG_CRITICAL,
03651 "list_delete failed with return value: %X", lrv);
03652 }
03653
03654 free(currentChannelMap);
03655
03656 return SCARD_S_SUCCESS;
03657 }
03658
03659 static LONG SCardGetContextAndChannelFromHandle(SCARDHANDLE hCard,
03660 SCONTEXTMAP **targetContextMap, CHANNEL_MAP ** targetChannelMap)
03661 {
03662 LONG rv;
03663
03664 if (0 == hCard)
03665 return -1;
03666
03667 (void)SCardLockThread();
03668 rv = SCardGetContextAndChannelFromHandleTH(hCard, targetContextMap, targetChannelMap);
03669 (void)SCardUnlockThread();
03670
03671 return rv;
03672 }
03673
03674 static LONG SCardGetContextAndChannelFromHandleTH(SCARDHANDLE hCard,
03675 SCONTEXTMAP **targetContextMap, CHANNEL_MAP ** targetChannelMap)
03676 {
03677 int listSize;
03678 int list_index;
03679 SCONTEXTMAP * currentContextMap;
03680 CHANNEL_MAP * currentChannelMap;
03681
03682
03683 *targetContextMap = NULL;
03684 *targetChannelMap = NULL;
03685
03686 listSize = list_size(&contextMapList);
03687
03688 for (list_index = 0; list_index < listSize; list_index++)
03689 {
03690 currentContextMap = list_get_at(&contextMapList, list_index);
03691 if (currentContextMap == NULL)
03692 {
03693 Log2(PCSC_LOG_CRITICAL, "list_get_at failed for index %d", list_index);
03694 continue;
03695 }
03696 currentChannelMap = list_seek(&(currentContextMap->channelMapList),
03697 &hCard);
03698 if (currentChannelMap != NULL)
03699 {
03700 *targetContextMap = currentContextMap;
03701 *targetChannelMap = currentChannelMap;
03702 return SCARD_S_SUCCESS;
03703 }
03704 }
03705
03706 return -1;
03707 }
03708
03709 static LONG SCardInvalidateHandles(void)
03710 {
03711
03712 (void)SCardLockThread();
03713
03714 while (list_size(&contextMapList) != 0)
03715 {
03716 SCONTEXTMAP * currentContextMap;
03717
03718 currentContextMap = list_get_at(&contextMapList, 0);
03719 if (currentContextMap != NULL)
03720 (void)SCardCleanContext(currentContextMap);
03721 else
03722 Log1(PCSC_LOG_CRITICAL, "list_get_at returned NULL");
03723 }
03724
03725 (void)SCardUnlockThread();
03726
03727
03728 daemon_ctime = 0;
03729 client_pid = 0;
03730
03731 return SCARD_E_INVALID_HANDLE;
03732 }
03733
03746 LONG SCardCheckDaemonAvailability(void)
03747 {
03748 LONG rv;
03749 struct stat statBuffer;
03750 int need_restart = 0;
03751
03752 rv = stat(PCSCLITE_CSOCK_NAME, &statBuffer);
03753
03754 if (rv != 0)
03755 {
03756 Log2(PCSC_LOG_INFO, "PCSC Not Running: " PCSCLITE_CSOCK_NAME ": %s",
03757 strerror(errno));
03758 return SCARD_E_NO_SERVICE;
03759 }
03760
03761
03762
03763 if (daemon_ctime && statBuffer.st_ctime > daemon_ctime)
03764 {
03765
03766 if (GetDaemonPid() != daemon_pid)
03767 {
03768 Log1(PCSC_LOG_INFO, "PCSC restarted");
03769 need_restart = 1;
03770 }
03771 }
03772
03773
03774 if (client_pid && client_pid != getpid())
03775 {
03776 Log1(PCSC_LOG_INFO, "Client forked");
03777 need_restart = 1;
03778 }
03779
03780 if (need_restart)
03781 return SCardInvalidateHandles();
03782
03783 daemon_ctime = statBuffer.st_ctime;
03784 daemon_pid = GetDaemonPid();
03785 client_pid = getpid();
03786
03787 return SCARD_S_SUCCESS;
03788 }
03789
03790 #ifdef DO_CHECK_SAME_PROCESS
03791 static LONG SCardCheckSameProcess(void)
03792 {
03793
03794 if ((client_pid && client_pid != getpid()))
03795 {
03796 Log1(PCSC_LOG_INFO, "Client forked");
03797 return SCardInvalidateHandles();
03798 }
03799
03800 client_pid = getpid();
03801
03802 return SCARD_S_SUCCESS;
03803 }
03804 #endif
03805
03806 static LONG getReaderStates(SCONTEXTMAP * currentContextMap)
03807 {
03808 int32_t dwClientID = currentContextMap->dwClientID;
03809
03810 if (-1 == MessageSendWithHeader(CMD_GET_READERS_STATE, dwClientID, 0, NULL))
03811 return SCARD_E_NO_SERVICE;
03812
03813
03814 if (MessageReceive(&readerStates, sizeof(readerStates), dwClientID) < 0)
03815 return SCARD_F_COMM_ERROR;
03816
03817 return SCARD_S_SUCCESS;
03818 }
03819