00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00021 #include "config.h"
00022 #include <stdlib.h>
00023 #include <string.h>
00024 #include <sys/types.h>
00025 #include <fcntl.h>
00026 #include <unistd.h>
00027 #include <sys/un.h>
00028 #include <errno.h>
00029 #include <stddef.h>
00030
00031 #include "misc.h"
00032 #include "pcscd.h"
00033 #include "winscard.h"
00034 #include "debug.h"
00035 #include "thread_generic.h"
00036 #include "strlcpycat.h"
00037
00038 #include "readerfactory.h"
00039 #include "eventhandler.h"
00040 #include "sys_generic.h"
00041 #include "winscard_msg.h"
00042 #include "utils.h"
00043
00045 #define SCARD_PROTOCOL_ANY_OLD 0x1000
00046
00047 #ifndef TRUE
00048 #define TRUE 1
00049 #define FALSE 0
00050 #endif
00051
00052 #undef DO_PROFILE
00053 #ifdef DO_PROFILE
00054
00055 #define PROFILE_FILE "/tmp/pcsc_profile"
00056 #include <stdio.h>
00057 #include <sys/time.h>
00058
00059 struct timeval profile_time_start;
00060 FILE *fd;
00061 char profile_tty;
00062 char fct_name[100];
00063
00064 #define PROFILE_START profile_start(__FUNCTION__);
00065 #define PROFILE_END(rv) profile_end(__FUNCTION__, rv);
00066
00067 static void profile_start(const char *f)
00068 {
00069 static char initialized = FALSE;
00070
00071 if (!initialized)
00072 {
00073 char filename[80];
00074
00075 initialized = TRUE;
00076 sprintf(filename, "%s-%d", PROFILE_FILE, getuid());
00077 fd = fopen(filename, "a+");
00078 if (NULL == fd)
00079 {
00080 fprintf(stderr, "\33[01;31mCan't open %s: %s\33[0m\n",
00081 PROFILE_FILE, strerror(errno));
00082 exit(-1);
00083 }
00084 fprintf(fd, "\nStart a new profile\n");
00085
00086 if (isatty(fileno(stderr)))
00087 profile_tty = TRUE;
00088 else
00089 profile_tty = FALSE;
00090 }
00091
00092
00093 if (profile_tty && fct_name[0])
00094 printf("\33[01;34m WARNING: %s starts before %s finishes\33[0m\n",
00095 f, fct_name);
00096
00097 strlcpy(fct_name, f, sizeof(fct_name));
00098
00099 gettimeofday(&profile_time_start, NULL);
00100 }
00101
00102
00103 static long int time_sub(struct timeval *a, struct timeval *b)
00104 {
00105 struct timeval r;
00106 r.tv_sec = a -> tv_sec - b -> tv_sec;
00107 r.tv_usec = a -> tv_usec - b -> tv_usec;
00108 if (r.tv_usec < 0)
00109 {
00110 r.tv_sec--;
00111 r.tv_usec += 1000000;
00112 }
00113
00114 return r.tv_sec * 1000000 + r.tv_usec;
00115 }
00116
00117
00118 static void profile_end(const char *f, LONG rv)
00119 {
00120 struct timeval profile_time_end;
00121 long d;
00122
00123 gettimeofday(&profile_time_end, NULL);
00124 d = time_sub(&profile_time_end, &profile_time_start);
00125
00126 if (profile_tty)
00127 {
00128 if (fct_name[0])
00129 {
00130 if (strncmp(fct_name, f, sizeof(fct_name)))
00131 printf("\33[01;34m WARNING: %s ends before %s\33[0m\n",
00132 f, fct_name);
00133 }
00134 else
00135 printf("\33[01;34m WARNING: %s ends but we lost its start\33[0m\n",
00136 f);
00137
00138
00139 fct_name[0] = '\0';
00140
00141 if (rv != SCARD_S_SUCCESS)
00142 fprintf(stderr,
00143 "\33[01;31mRESULT %s \33[35m%ld \33[34m0x%08lX %s\33[0m\n",
00144 f, d, rv, pcsc_stringify_error(rv));
00145 else
00146 fprintf(stderr, "\33[01;31mRESULT %s \33[35m%ld\33[0m\n", f, d);
00147 }
00148 fprintf(fd, "%s %ld\n", f, d);
00149 fflush(fd);
00150 }
00151
00152 #else
00153 #define PROFILE_START
00154 #define PROFILE_END(rv)
00155 #endif
00156
00161 struct _psChannelMap
00162 {
00163 SCARDHANDLE hCard;
00164 LPSTR readerName;
00165 };
00166
00167 typedef struct _psChannelMap CHANNEL_MAP, *PCHANNEL_MAP;
00168
00174 static struct _psContextMap
00175 {
00176 DWORD dwClientID;
00177 SCARDCONTEXT hContext;
00178 DWORD contextBlockStatus;
00179 PCSCLITE_MUTEX_T mMutex;
00180 CHANNEL_MAP psChannelMap[PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS];
00181 } psContextMap[PCSCLITE_MAX_APPLICATION_CONTEXTS];
00182
00186 static short isExecuted = 0;
00187
00188
00192 static time_t daemon_ctime = 0;
00193 static pid_t daemon_pid = 0;
00198 static pid_t client_pid = 0;
00199
00205 static int mapAddr = 0;
00206
00211 static PCSCLITE_MUTEX clientMutex = PTHREAD_MUTEX_INITIALIZER;
00212
00219 static PREADER_STATE readerStates[PCSCLITE_MAX_READERS_CONTEXTS];
00220
00221 PCSC_API SCARD_IO_REQUEST g_rgSCardT0Pci = { SCARD_PROTOCOL_T0, 8 };
00222 PCSC_API SCARD_IO_REQUEST g_rgSCardT1Pci = { SCARD_PROTOCOL_T1, 8 };
00223 PCSC_API SCARD_IO_REQUEST g_rgSCardRawPci = { SCARD_PROTOCOL_RAW, 8 };
00224
00225
00226 static LONG SCardAddContext(SCARDCONTEXT, DWORD);
00227 static LONG SCardGetContextIndice(SCARDCONTEXT);
00228 static LONG SCardGetContextIndiceTH(SCARDCONTEXT);
00229 static LONG SCardRemoveContext(SCARDCONTEXT);
00230 static LONG SCardCleanContext(LONG indice);
00231
00232 static LONG SCardAddHandle(SCARDHANDLE, DWORD, LPCSTR);
00233 static LONG SCardGetIndicesFromHandle(SCARDHANDLE, PDWORD, PDWORD);
00234 static LONG SCardGetIndicesFromHandleTH(SCARDHANDLE, PDWORD, PDWORD);
00235 static LONG SCardRemoveHandle(SCARDHANDLE);
00236
00237 static LONG SCardGetSetAttrib(SCARDHANDLE hCard, int command, DWORD dwAttrId,
00238 LPBYTE pbAttr, LPDWORD pcbAttrLen);
00239
00240 void DESTRUCTOR SCardUnload(void);
00241
00242
00243
00244
00251 inline static LONG SCardLockThread(void)
00252 {
00253 return SYS_MutexLock(&clientMutex);
00254 }
00255
00261 inline static LONG SCardUnlockThread(void)
00262 {
00263 return SYS_MutexUnLock(&clientMutex);
00264 }
00265
00266 static LONG SCardEstablishContextTH(DWORD, LPCVOID, LPCVOID, LPSCARDCONTEXT);
00267
00302 LONG SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1,
00303 LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
00304 {
00305 LONG rv;
00306
00307 PROFILE_START
00308
00309
00310 rv = SCardCheckDaemonAvailability();
00311 if (SCARD_E_INVALID_HANDLE == rv)
00312
00313 rv = SCardCheckDaemonAvailability();
00314
00315 if (rv != SCARD_S_SUCCESS)
00316 return rv;
00317
00318 SCardLockThread();
00319 rv = SCardEstablishContextTH(dwScope, pvReserved1,
00320 pvReserved2, phContext);
00321 SCardUnlockThread();
00322
00323 PROFILE_END(rv)
00324
00325 return rv;
00326 }
00327
00354 static LONG SCardEstablishContextTH(DWORD dwScope, LPCVOID pvReserved1,
00355 LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
00356 {
00357 LONG rv;
00358 int i;
00359 establish_struct scEstablishStruct;
00360 sharedSegmentMsg msgStruct;
00361 uint32_t dwClientID = 0;
00362
00363 if (phContext == NULL)
00364 return SCARD_E_INVALID_PARAMETER;
00365 else
00366 *phContext = 0;
00367
00368
00369
00370
00371
00372
00373
00374
00375 if (isExecuted == 0)
00376 {
00377 int pageSize;
00378
00379
00380
00381
00382 SYS_Initialize();
00383
00384
00385
00386
00387 mapAddr = SYS_OpenFile(PCSCLITE_PUBSHM_FILE, O_RDONLY, 0);
00388 if (mapAddr < 0)
00389 {
00390 Log3(PCSC_LOG_CRITICAL, "Cannot open public shared file %s: %s",
00391 PCSCLITE_PUBSHM_FILE, strerror(errno));
00392 return SCARD_E_NO_SERVICE;
00393 }
00394
00395
00396
00397
00398 fcntl(mapAddr, F_SETFD, FD_CLOEXEC);
00399
00400 pageSize = SYS_GetPageSize();
00401
00402
00403
00404
00405 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
00406 {
00407 readerStates[i] =
00408 (PREADER_STATE)SYS_PublicMemoryMap(sizeof(READER_STATE),
00409 mapAddr, (i * pageSize));
00410 if (readerStates[i] == NULL)
00411 {
00412 Log2(PCSC_LOG_CRITICAL, "Cannot public memory map: %s",
00413 strerror(errno));
00414 SYS_CloseFile(mapAddr);
00415 return SCARD_F_INTERNAL_ERROR;
00416 }
00417 }
00418
00419
00420
00421
00422 for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
00423 {
00424 int j;
00425
00426
00427
00428
00429 psContextMap[i].dwClientID = 0;
00430 psContextMap[i].hContext = 0;
00431 psContextMap[i].contextBlockStatus = BLOCK_STATUS_RESUME;
00432 psContextMap[i].mMutex = NULL;
00433
00434 for (j = 0; j < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; j++)
00435 {
00436
00437
00438
00439 psContextMap[i].psChannelMap[j].hCard = 0;
00440 psContextMap[i].psChannelMap[j].readerName = NULL;
00441 }
00442 }
00443
00444 }
00445
00446
00447
00448
00449
00450 for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
00451 {
00452 if (psContextMap[i].dwClientID == 0)
00453 break;
00454 }
00455
00456 if (i == PCSCLITE_MAX_APPLICATION_CONTEXTS)
00457 {
00458 return SCARD_E_NO_MEMORY;
00459 }
00460
00461
00462 if (SHMClientSetupSession(&dwClientID) != 0)
00463 {
00464 SYS_CloseFile(mapAddr);
00465 return SCARD_E_NO_SERVICE;
00466 }
00467
00468 {
00469 version_struct *veStr;
00470
00471 memset(&msgStruct, 0, sizeof(msgStruct));
00472 msgStruct.mtype = CMD_VERSION;
00473 msgStruct.user_id = SYS_GetUID();
00474 msgStruct.group_id = SYS_GetGID();
00475 msgStruct.command = 0;
00476 msgStruct.date = time(NULL);
00477
00478 veStr = (version_struct *) msgStruct.data;
00479 veStr->major = PROTOCOL_VERSION_MAJOR;
00480 veStr->minor = PROTOCOL_VERSION_MINOR;
00481
00482 if (-1 == SHMMessageSend(&msgStruct, sizeof(msgStruct), dwClientID,
00483 PCSCLITE_MCLIENT_ATTEMPTS))
00484 return SCARD_E_NO_SERVICE;
00485
00486
00487
00488
00489 if (-1 == SHMMessageReceive(&msgStruct, sizeof(msgStruct), dwClientID,
00490 PCSCLITE_CLIENT_ATTEMPTS))
00491 {
00492 Log1(PCSC_LOG_CRITICAL, "Your pcscd is too old and does not support CMD_VERSION");
00493 return SCARD_F_COMM_ERROR;
00494 }
00495
00496 Log3(PCSC_LOG_INFO, "Server is protocol version %d:%d",
00497 veStr->major, veStr->minor);
00498
00499 if (veStr->rv != SCARD_S_SUCCESS)
00500 return veStr->rv;
00501
00502 isExecuted = 1;
00503 }
00504
00505
00506 if (dwScope != SCARD_SCOPE_USER && dwScope != SCARD_SCOPE_TERMINAL &&
00507 dwScope != SCARD_SCOPE_SYSTEM && dwScope != SCARD_SCOPE_GLOBAL)
00508 {
00509 return SCARD_E_INVALID_VALUE;
00510 }
00511
00512
00513
00514
00515 scEstablishStruct.dwScope = dwScope;
00516 scEstablishStruct.phContext = 0;
00517 scEstablishStruct.rv = SCARD_S_SUCCESS;
00518
00519 rv = WrapSHMWrite(SCARD_ESTABLISH_CONTEXT, dwClientID,
00520 sizeof(scEstablishStruct), PCSCLITE_MCLIENT_ATTEMPTS,
00521 (void *) &scEstablishStruct);
00522
00523 if (rv == -1)
00524 return SCARD_E_NO_SERVICE;
00525
00526
00527
00528
00529 rv = SHMClientRead(&msgStruct, dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
00530
00531 if (rv == -1)
00532 return SCARD_F_COMM_ERROR;
00533
00534 memcpy(&scEstablishStruct, &msgStruct.data, sizeof(scEstablishStruct));
00535
00536 if (scEstablishStruct.rv != SCARD_S_SUCCESS)
00537 return scEstablishStruct.rv;
00538
00539 *phContext = scEstablishStruct.phContext;
00540
00541
00542
00543
00544 rv = SCardAddContext(*phContext, dwClientID);
00545
00546 return rv;
00547 }
00548
00571 LONG SCardReleaseContext(SCARDCONTEXT hContext)
00572 {
00573 LONG rv;
00574 release_struct scReleaseStruct;
00575 sharedSegmentMsg msgStruct;
00576 LONG dwContextIndex;
00577
00578 PROFILE_START
00579
00580
00581
00582
00583
00584 dwContextIndex = SCardGetContextIndice(hContext);
00585 if (dwContextIndex == -1)
00586 return SCARD_E_INVALID_HANDLE;
00587
00588 rv = SCardCheckDaemonAvailability();
00589 if (rv != SCARD_S_SUCCESS)
00590 {
00591
00592
00593
00594 SCardLockThread();
00595 SCardRemoveContext(hContext);
00596 SCardUnlockThread();
00597
00598 return rv;
00599 }
00600
00601 SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
00602
00603 scReleaseStruct.hContext = hContext;
00604 scReleaseStruct.rv = SCARD_S_SUCCESS;
00605
00606 rv = WrapSHMWrite(SCARD_RELEASE_CONTEXT,
00607 psContextMap[dwContextIndex].dwClientID,
00608 sizeof(scReleaseStruct),
00609 PCSCLITE_MCLIENT_ATTEMPTS, (void *) &scReleaseStruct);
00610
00611 if (rv == -1)
00612 {
00613 SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00614 return SCARD_E_NO_SERVICE;
00615 }
00616
00617
00618
00619
00620 rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
00621 PCSCLITE_CLIENT_ATTEMPTS);
00622 memcpy(&scReleaseStruct, &msgStruct.data, sizeof(scReleaseStruct));
00623
00624 if (rv == -1)
00625 {
00626 SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00627 return SCARD_F_COMM_ERROR;
00628 }
00629
00630 SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00631
00632
00633
00634
00635 SCardLockThread();
00636 SCardRemoveContext(hContext);
00637 SCardUnlockThread();
00638
00639 PROFILE_END(scReleaseStruct.rv)
00640
00641 return scReleaseStruct.rv;
00642 }
00643
00657 LONG SCardSetTimeout(SCARDCONTEXT hContext, DWORD dwTimeout)
00658 {
00659
00660
00661
00662
00663 return SCARD_S_SUCCESS;
00664 }
00665
00718 LONG SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader,
00719 DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard,
00720 LPDWORD pdwActiveProtocol)
00721 {
00722 LONG rv;
00723 connect_struct scConnectStruct;
00724 sharedSegmentMsg msgStruct;
00725 LONG dwContextIndex;
00726
00727 PROFILE_START
00728
00729
00730
00731
00732 if (phCard == NULL || pdwActiveProtocol == NULL)
00733 return SCARD_E_INVALID_PARAMETER;
00734 else
00735 *phCard = 0;
00736
00737 if (szReader == NULL)
00738 return SCARD_E_UNKNOWN_READER;
00739
00740
00741
00742
00743 if (strlen(szReader) > MAX_READERNAME)
00744 return SCARD_E_INVALID_VALUE;
00745
00746 if (!(dwPreferredProtocols & SCARD_PROTOCOL_T0) &&
00747 !(dwPreferredProtocols & SCARD_PROTOCOL_T1) &&
00748 !(dwPreferredProtocols & SCARD_PROTOCOL_RAW) &&
00749 !(dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD))
00750 {
00751 return SCARD_E_INVALID_VALUE;
00752 }
00753
00754 rv = SCardCheckDaemonAvailability();
00755 if (rv != SCARD_S_SUCCESS)
00756 return rv;
00757
00758
00759
00760
00761 dwContextIndex = SCardGetContextIndice(hContext);
00762 if (dwContextIndex == -1)
00763 return SCARD_E_INVALID_HANDLE;
00764
00765 SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
00766
00767 strncpy(scConnectStruct.szReader, szReader, MAX_READERNAME);
00768
00769 scConnectStruct.hContext = hContext;
00770 scConnectStruct.dwShareMode = dwShareMode;
00771 scConnectStruct.dwPreferredProtocols = dwPreferredProtocols;
00772 scConnectStruct.phCard = 0;
00773 scConnectStruct.pdwActiveProtocol = 0;
00774 scConnectStruct.rv = SCARD_S_SUCCESS;
00775
00776 rv = WrapSHMWrite(SCARD_CONNECT, psContextMap[dwContextIndex].dwClientID,
00777 sizeof(scConnectStruct),
00778 PCSCLITE_CLIENT_ATTEMPTS, (void *) &scConnectStruct);
00779
00780 if (rv == -1)
00781 {
00782 SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00783 return SCARD_E_NO_SERVICE;
00784 }
00785
00786
00787
00788
00789 rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
00790 PCSCLITE_CLIENT_ATTEMPTS);
00791
00792 memcpy(&scConnectStruct, &msgStruct.data, sizeof(scConnectStruct));
00793
00794 if (rv == -1)
00795 {
00796 SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00797 return SCARD_F_COMM_ERROR;
00798 }
00799
00800 *phCard = scConnectStruct.phCard;
00801 *pdwActiveProtocol = scConnectStruct.pdwActiveProtocol;
00802
00803 if (scConnectStruct.rv == SCARD_S_SUCCESS)
00804 {
00805
00806
00807
00808 rv = SCardAddHandle(*phCard, dwContextIndex, szReader);
00809 SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00810
00811 PROFILE_END(rv)
00812
00813 return rv;
00814 }
00815
00816 SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00817
00818 PROFILE_END(scConnectStruct.rv)
00819
00820 return scConnectStruct.rv;
00821 }
00822
00888 LONG SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode,
00889 DWORD dwPreferredProtocols, DWORD dwInitialization,
00890 LPDWORD pdwActiveProtocol)
00891 {
00892 LONG rv;
00893 reconnect_struct scReconnectStruct;
00894 sharedSegmentMsg msgStruct;
00895 int i;
00896 DWORD dwContextIndex, dwChannelIndex;
00897
00898 PROFILE_START
00899
00900 if (dwInitialization != SCARD_LEAVE_CARD &&
00901 dwInitialization != SCARD_RESET_CARD &&
00902 dwInitialization != SCARD_UNPOWER_CARD &&
00903 dwInitialization != SCARD_EJECT_CARD)
00904 {
00905 return SCARD_E_INVALID_VALUE;
00906 }
00907
00908 if (!(dwPreferredProtocols & SCARD_PROTOCOL_T0) &&
00909 !(dwPreferredProtocols & SCARD_PROTOCOL_T1) &&
00910 !(dwPreferredProtocols & SCARD_PROTOCOL_RAW) &&
00911 !(dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD))
00912 {
00913 return SCARD_E_INVALID_VALUE;
00914 }
00915
00916 if (pdwActiveProtocol == NULL)
00917 return SCARD_E_INVALID_PARAMETER;
00918
00919 rv = SCardCheckDaemonAvailability();
00920 if (rv != SCARD_S_SUCCESS)
00921 return rv;
00922
00923
00924
00925
00926 rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
00927
00928 if (rv == -1)
00929 return SCARD_E_INVALID_HANDLE;
00930
00931 SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
00932
00933
00934 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
00935 {
00936 char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
00937
00938
00939 if (r && strcmp(r, (readerStates[i])->readerName) == 0)
00940 break;
00941 }
00942
00943 if (i == PCSCLITE_MAX_READERS_CONTEXTS)
00944 {
00945 SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00946 return SCARD_E_READER_UNAVAILABLE;
00947 }
00948
00949 do
00950 {
00951 scReconnectStruct.hCard = hCard;
00952 scReconnectStruct.dwShareMode = dwShareMode;
00953 scReconnectStruct.dwPreferredProtocols = dwPreferredProtocols;
00954 scReconnectStruct.dwInitialization = dwInitialization;
00955 scReconnectStruct.pdwActiveProtocol = *pdwActiveProtocol;
00956 scReconnectStruct.rv = SCARD_S_SUCCESS;
00957
00958 rv = WrapSHMWrite(SCARD_RECONNECT, psContextMap[dwContextIndex].dwClientID,
00959 sizeof(scReconnectStruct),
00960 PCSCLITE_CLIENT_ATTEMPTS, (void *) &scReconnectStruct);
00961
00962 if (rv == -1)
00963 {
00964 SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00965 return SCARD_E_NO_SERVICE;
00966 }
00967
00968
00969
00970
00971 rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
00972 PCSCLITE_CLIENT_ATTEMPTS);
00973
00974 memcpy(&scReconnectStruct, &msgStruct.data, sizeof(scReconnectStruct));
00975
00976 if (rv == -1)
00977 {
00978 SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00979 return SCARD_F_COMM_ERROR;
00980 }
00981 } while (SCARD_E_SHARING_VIOLATION == scReconnectStruct.rv);
00982
00983 *pdwActiveProtocol = scReconnectStruct.pdwActiveProtocol;
00984
00985 SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00986
00987 PROFILE_END(scReconnectStruct.rv)
00988
00989 return scReconnectStruct.rv;
00990 }
00991
01023 LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
01024 {
01025 LONG rv;
01026 disconnect_struct scDisconnectStruct;
01027 sharedSegmentMsg msgStruct;
01028 DWORD dwContextIndex, dwChannelIndex;
01029
01030 PROFILE_START
01031
01032 if (dwDisposition != SCARD_LEAVE_CARD &&
01033 dwDisposition != SCARD_RESET_CARD &&
01034 dwDisposition != SCARD_UNPOWER_CARD &&
01035 dwDisposition != SCARD_EJECT_CARD)
01036 {
01037 return SCARD_E_INVALID_VALUE;
01038 }
01039
01040 rv = SCardCheckDaemonAvailability();
01041 if (rv != SCARD_S_SUCCESS)
01042 return rv;
01043
01044
01045
01046
01047 rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01048
01049 if (rv == -1)
01050 return SCARD_E_INVALID_HANDLE;
01051
01052 SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
01053
01054 scDisconnectStruct.hCard = hCard;
01055 scDisconnectStruct.dwDisposition = dwDisposition;
01056 scDisconnectStruct.rv = SCARD_S_SUCCESS;
01057
01058 rv = WrapSHMWrite(SCARD_DISCONNECT, psContextMap[dwContextIndex].dwClientID,
01059 sizeof(scDisconnectStruct),
01060 PCSCLITE_CLIENT_ATTEMPTS, (void *) &scDisconnectStruct);
01061
01062 if (rv == -1)
01063 {
01064 SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01065 return SCARD_E_NO_SERVICE;
01066 }
01067
01068
01069
01070
01071 rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
01072 PCSCLITE_CLIENT_ATTEMPTS);
01073
01074 memcpy(&scDisconnectStruct, &msgStruct.data,
01075 sizeof(scDisconnectStruct));
01076
01077 if (rv == -1)
01078 {
01079 SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01080 return SCARD_F_COMM_ERROR;
01081 }
01082
01083 SCardRemoveHandle(hCard);
01084
01085 SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01086
01087 PROFILE_END(scDisconnectStruct.rv)
01088
01089 return scDisconnectStruct.rv;
01090 }
01091
01127 LONG SCardBeginTransaction(SCARDHANDLE hCard)
01128 {
01129
01130 LONG rv;
01131 begin_struct scBeginStruct;
01132 int i;
01133 sharedSegmentMsg msgStruct;
01134 DWORD dwContextIndex, dwChannelIndex;
01135
01136 PROFILE_START
01137
01138 rv = SCardCheckDaemonAvailability();
01139 if (rv != SCARD_S_SUCCESS)
01140 return rv;
01141
01142
01143
01144
01145 rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01146
01147 if (rv == -1)
01148 return SCARD_E_INVALID_HANDLE;
01149
01150 SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
01151
01152 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01153 {
01154 char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
01155
01156
01157 if (r && strcmp(r, (readerStates[i])->readerName) == 0)
01158 break;
01159 }
01160
01161 if (i == PCSCLITE_MAX_READERS_CONTEXTS)
01162 {
01163 SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01164 return SCARD_E_READER_UNAVAILABLE;
01165 }
01166
01167 scBeginStruct.hCard = hCard;
01168 scBeginStruct.rv = SCARD_S_SUCCESS;
01169
01170
01171
01172
01173
01174
01175 do
01176 {
01177 rv = WrapSHMWrite(SCARD_BEGIN_TRANSACTION, psContextMap[dwContextIndex].dwClientID,
01178 sizeof(scBeginStruct),
01179 PCSCLITE_CLIENT_ATTEMPTS, (void *) &scBeginStruct);
01180
01181 if (rv == -1)
01182 {
01183
01184 SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01185 return SCARD_E_NO_SERVICE;
01186 }
01187
01188
01189
01190
01191 rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
01192 PCSCLITE_CLIENT_ATTEMPTS);
01193
01194 memcpy(&scBeginStruct, &msgStruct.data, sizeof(scBeginStruct));
01195
01196 if (rv == -1)
01197 {
01198
01199 SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01200 return SCARD_F_COMM_ERROR;
01201 }
01202
01203 }
01204 while (scBeginStruct.rv == SCARD_E_SHARING_VIOLATION);
01205
01206 SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01207
01208 PROFILE_END(scBeginStruct.rv);
01209
01210 return scBeginStruct.rv;
01211 }
01212
01253 LONG SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
01254 {
01255 LONG rv;
01256 end_struct scEndStruct;
01257 sharedSegmentMsg msgStruct;
01258 int randnum, i;
01259 DWORD dwContextIndex, dwChannelIndex;
01260
01261 PROFILE_START
01262
01263
01264
01265
01266 randnum = 0;
01267
01268 if (dwDisposition != SCARD_LEAVE_CARD &&
01269 dwDisposition != SCARD_RESET_CARD &&
01270 dwDisposition != SCARD_UNPOWER_CARD &&
01271 dwDisposition != SCARD_EJECT_CARD)
01272 {
01273 return SCARD_E_INVALID_VALUE;
01274 }
01275
01276 rv = SCardCheckDaemonAvailability();
01277 if (rv != SCARD_S_SUCCESS)
01278 return rv;
01279
01280
01281
01282
01283 rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01284
01285 if (rv == -1)
01286 return SCARD_E_INVALID_HANDLE;
01287
01288 SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
01289
01290 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01291 {
01292 char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
01293
01294
01295 if (r && strcmp(r, (readerStates[i])->readerName) == 0)
01296 break;
01297 }
01298
01299 if (i == PCSCLITE_MAX_READERS_CONTEXTS)
01300 {
01301 SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01302 return SCARD_E_READER_UNAVAILABLE;
01303 }
01304
01305 scEndStruct.hCard = hCard;
01306 scEndStruct.dwDisposition = dwDisposition;
01307 scEndStruct.rv = SCARD_S_SUCCESS;
01308
01309 rv = WrapSHMWrite(SCARD_END_TRANSACTION,
01310 psContextMap[dwContextIndex].dwClientID,
01311 sizeof(scEndStruct),
01312 PCSCLITE_CLIENT_ATTEMPTS, (void *) &scEndStruct);
01313
01314 if (rv == -1)
01315 {
01316 SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01317 return SCARD_E_NO_SERVICE;
01318 }
01319
01320
01321
01322
01323 rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
01324 PCSCLITE_CLIENT_ATTEMPTS);
01325
01326 memcpy(&scEndStruct, &msgStruct.data, sizeof(scEndStruct));
01327
01328 if (rv == -1)
01329 {
01330 SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01331 return SCARD_F_COMM_ERROR;
01332 }
01333
01334
01335
01336
01337 randnum = SYS_RandomInt(1000, 10000);
01338 SYS_USleep(randnum);
01339
01340 SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01341
01342 PROFILE_END(scEndStruct.rv)
01343
01344 return scEndStruct.rv;
01345 }
01346
01353 LONG SCardCancelTransaction(SCARDHANDLE hCard)
01354 {
01355 LONG rv;
01356 cancel_struct scCancelStruct;
01357 sharedSegmentMsg msgStruct;
01358 int i;
01359 DWORD dwContextIndex, dwChannelIndex;
01360
01361 PROFILE_START
01362
01363 rv = SCardCheckDaemonAvailability();
01364 if (rv != SCARD_S_SUCCESS)
01365 return rv;
01366
01367
01368
01369
01370 rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01371
01372 if (rv == -1)
01373 return SCARD_E_INVALID_HANDLE;
01374
01375 SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
01376
01377 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01378 {
01379 char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
01380
01381
01382 if (r && strcmp(r, (readerStates[i])->readerName) == 0)
01383 break;
01384 }
01385
01386 if (i == PCSCLITE_MAX_READERS_CONTEXTS)
01387 {
01388 SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01389 return SCARD_E_READER_UNAVAILABLE;
01390 }
01391
01392 scCancelStruct.hCard = hCard;
01393
01394 rv = WrapSHMWrite(SCARD_CANCEL_TRANSACTION,
01395 psContextMap[dwContextIndex].dwClientID,
01396 sizeof(scCancelStruct),
01397 PCSCLITE_CLIENT_ATTEMPTS, (void *) &scCancelStruct);
01398
01399 if (rv == -1)
01400 {
01401 SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01402 return SCARD_E_NO_SERVICE;
01403 }
01404
01405
01406
01407
01408 rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
01409 PCSCLITE_CLIENT_ATTEMPTS);
01410
01411 memcpy(&scCancelStruct, &msgStruct.data, sizeof(scCancelStruct));
01412
01413 if (rv == -1)
01414 {
01415 SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01416 return SCARD_F_COMM_ERROR;
01417 }
01418
01419 SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01420
01421 PROFILE_END(scCancelStruct.rv)
01422
01423 return scCancelStruct.rv;
01424 }
01425
01487 LONG SCardStatus(SCARDHANDLE hCard, LPSTR mszReaderNames,
01488 LPDWORD pcchReaderLen, LPDWORD pdwState,
01489 LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
01490 {
01491 DWORD dwReaderLen, dwAtrLen;
01492 LONG rv;
01493 int i;
01494 status_struct scStatusStruct;
01495 sharedSegmentMsg msgStruct;
01496 DWORD dwContextIndex, dwChannelIndex;
01497 char *r;
01498
01499 PROFILE_START
01500
01501
01502
01503
01504
01505 if (pcchReaderLen == NULL || pcbAtrLen == NULL)
01506 return SCARD_E_INVALID_PARAMETER;
01507
01508
01509 dwReaderLen = *pcchReaderLen;
01510 dwAtrLen = *pcbAtrLen;
01511
01512
01513 if (pdwState)
01514 *pdwState = 0;
01515
01516 if (pdwProtocol)
01517 *pdwProtocol = 0;
01518
01519 *pcchReaderLen = 0;
01520 *pcbAtrLen = 0;
01521
01522 rv = SCardCheckDaemonAvailability();
01523 if (rv != SCARD_S_SUCCESS)
01524 return rv;
01525
01526
01527
01528
01529 rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01530
01531 if (rv == -1)
01532 return SCARD_E_INVALID_HANDLE;
01533
01534 SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
01535
01536 r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
01537 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01538 {
01539
01540 if (r && strcmp(r, (readerStates[i])->readerName) == 0)
01541 break;
01542 }
01543
01544 if (i == PCSCLITE_MAX_READERS_CONTEXTS)
01545 {
01546 SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01547 return SCARD_E_READER_UNAVAILABLE;
01548 }
01549
01550
01551 memset(&scStatusStruct, 0, sizeof(scStatusStruct));
01552 scStatusStruct.hCard = hCard;
01553
01554
01555 scStatusStruct.pcchReaderLen = sizeof(scStatusStruct.mszReaderNames);
01556 scStatusStruct.pcbAtrLen = sizeof(scStatusStruct.pbAtr);
01557
01558 rv = WrapSHMWrite(SCARD_STATUS, psContextMap[dwContextIndex].dwClientID,
01559 sizeof(scStatusStruct),
01560 PCSCLITE_CLIENT_ATTEMPTS, (void *) &scStatusStruct);
01561
01562 if (rv == -1)
01563 {
01564 SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01565 return SCARD_E_NO_SERVICE;
01566 }
01567
01568
01569
01570
01571 rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
01572 PCSCLITE_CLIENT_ATTEMPTS);
01573
01574 memcpy(&scStatusStruct, &msgStruct.data, sizeof(scStatusStruct));
01575
01576 if (rv == -1)
01577 {
01578 SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01579 return SCARD_F_COMM_ERROR;
01580 }
01581
01582 rv = scStatusStruct.rv;
01583 if (rv != SCARD_S_SUCCESS && rv != SCARD_E_INSUFFICIENT_BUFFER)
01584 {
01585
01586
01587
01588 SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01589 return rv;
01590 }
01591
01592
01593
01594
01595
01596 *pcchReaderLen = strlen(psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName) + 1;
01597 *pcbAtrLen = (readerStates[i])->cardAtrLength;
01598
01599 if (pdwState)
01600 *pdwState = (readerStates[i])->readerState;
01601
01602 if (pdwProtocol)
01603 *pdwProtocol = (readerStates[i])->cardProtocol;
01604
01605
01606 if (mszReaderNames)
01607 {
01608 if (*pcchReaderLen > dwReaderLen)
01609 rv = SCARD_E_INSUFFICIENT_BUFFER;
01610
01611 strncpy(mszReaderNames,
01612 psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName,
01613 dwReaderLen);
01614 }
01615
01616 if (pbAtr)
01617 {
01618 if (*pcbAtrLen > dwAtrLen)
01619 rv = SCARD_E_INSUFFICIENT_BUFFER;
01620
01621 memcpy(pbAtr, (readerStates[i])->cardAtr,
01622 min(*pcbAtrLen, dwAtrLen));
01623 }
01624
01625 SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01626
01627 PROFILE_END(rv)
01628
01629 return rv;
01630 }
01631
01719 LONG SCardGetStatusChange(SCARDCONTEXT hContext, DWORD dwTimeout,
01720 LPSCARD_READERSTATE_A rgReaderStates, DWORD cReaders)
01721 {
01722 PSCARD_READERSTATE_A currReader;
01723 PREADER_STATE rContext;
01724 DWORD dwTime = 0;
01725 DWORD dwState;
01726 DWORD dwBreakFlag = 0;
01727 int j;
01728 LONG dwContextIndex;
01729 int currentReaderCount = 0;
01730 LONG rv;
01731
01732 PROFILE_START
01733
01734 if (rgReaderStates == NULL && cReaders > 0)
01735 return SCARD_E_INVALID_PARAMETER;
01736
01737 rv = SCardCheckDaemonAvailability();
01738 if (rv != SCARD_S_SUCCESS)
01739 return rv;
01740
01741
01742
01743
01744
01745 dwContextIndex = SCardGetContextIndice(hContext);
01746 if (dwContextIndex == -1)
01747 return SCARD_E_INVALID_HANDLE;
01748
01749 SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
01750
01751
01752
01753
01754
01755
01756 if (cReaders == 0)
01757