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 #include <sys/time.h>
00031
00032 #include "misc.h"
00033 #include "pcscd.h"
00034 #include "winscard.h"
00035 #include "debug.h"
00036 #include "thread_generic.h"
00037 #include "strlcpycat.h"
00038
00039 #include "readerfactory.h"
00040 #include "eventhandler.h"
00041 #include "sys_generic.h"
00042 #include "winscard_msg.h"
00043 #include "utils.h"
00044
00046 #define SCARD_PROTOCOL_ANY_OLD 0x1000
00047
00048 #ifndef TRUE
00049 #define TRUE 1
00050 #define FALSE 0
00051 #endif
00052
00053
00054 static long int time_sub(struct timeval *a, struct timeval *b)
00055 {
00056 struct timeval r;
00057 r.tv_sec = a -> tv_sec - b -> tv_sec;
00058 r.tv_usec = a -> tv_usec - b -> tv_usec;
00059 if (r.tv_usec < 0)
00060 {
00061 r.tv_sec--;
00062 r.tv_usec += 1000000;
00063 }
00064
00065 return r.tv_sec * 1000000 + r.tv_usec;
00066 }
00067
00068
00069 #undef DO_PROFILE
00070 #ifdef DO_PROFILE
00071
00072 #define PROFILE_FILE "/tmp/pcsc_profile"
00073 #include <stdio.h>
00074 #include <sys/time.h>
00075
00076 struct timeval profile_time_start;
00077 FILE *profile_fd;
00078 char profile_tty;
00079 char fct_name[100];
00080
00081 #define PROFILE_START profile_start(__FUNCTION__);
00082 #define PROFILE_END(rv) profile_end(__FUNCTION__, rv);
00083
00084 static void profile_start(const char *f)
00085 {
00086 static char initialized = FALSE;
00087
00088 if (!initialized)
00089 {
00090 char filename[80];
00091
00092 initialized = TRUE;
00093 sprintf(filename, "%s-%d", PROFILE_FILE, getuid());
00094 profile_fd = fopen(filename, "a+");
00095 if (NULL == profile_fd)
00096 {
00097 fprintf(stderr, "\33[01;31mCan't open %s: %s\33[0m\n",
00098 PROFILE_FILE, strerror(errno));
00099 exit(-1);
00100 }
00101 fprintf(profile_fd, "\nStart a new profile\n");
00102
00103 if (isatty(fileno(stderr)))
00104 profile_tty = TRUE;
00105 else
00106 profile_tty = FALSE;
00107 }
00108
00109
00110 if (profile_tty && fct_name[0])
00111 printf("\33[01;34m WARNING: %s starts before %s finishes\33[0m\n",
00112 f, fct_name);
00113
00114 strlcpy(fct_name, f, sizeof(fct_name));
00115
00116 gettimeofday(&profile_time_start, NULL);
00117 }
00118
00119 static void profile_end(const char *f, LONG rv)
00120 {
00121 struct timeval profile_time_end;
00122 long d;
00123
00124 gettimeofday(&profile_time_end, NULL);
00125 d = time_sub(&profile_time_end, &profile_time_start);
00126
00127 if (profile_tty)
00128 {
00129 if (fct_name[0])
00130 {
00131 if (strncmp(fct_name, f, sizeof(fct_name)))
00132 printf("\33[01;34m WARNING: %s ends before %s\33[0m\n",
00133 f, fct_name);
00134 }
00135 else
00136 printf("\33[01;34m WARNING: %s ends but we lost its start\33[0m\n",
00137 f);
00138
00139
00140 fct_name[0] = '\0';
00141
00142 if (rv != SCARD_S_SUCCESS)
00143 fprintf(stderr,
00144 "\33[01;31mRESULT %s \33[35m%ld \33[34m0x%08lX %s\33[0m\n",
00145 f, d, rv, pcsc_stringify_error(rv));
00146 else
00147 fprintf(stderr, "\33[01;31mRESULT %s \33[35m%ld\33[0m\n", f, d);
00148 }
00149 fprintf(profile_fd, "%s %ld\n", f, d);
00150 fflush(profile_fd);
00151 }
00152
00153 #else
00154 #define PROFILE_START
00155 #define PROFILE_END(rv)
00156 #endif
00157
00162 struct _psChannelMap
00163 {
00164 SCARDHANDLE hCard;
00165 LPSTR readerName;
00166 };
00167
00168 typedef struct _psChannelMap CHANNEL_MAP, *PCHANNEL_MAP;
00169
00175 static struct _psContextMap
00176 {
00177 DWORD dwClientID;
00178 SCARDCONTEXT hContext;
00179 DWORD contextBlockStatus;
00180 PCSCLITE_MUTEX_T mMutex;
00181 CHANNEL_MAP psChannelMap[PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS];
00182 } psContextMap[PCSCLITE_MAX_APPLICATION_CONTEXTS];
00183
00187 static short isExecuted = 0;
00188
00189
00193 static time_t daemon_ctime = 0;
00194 static pid_t daemon_pid = 0;
00199 static pid_t client_pid = 0;
00200
00206 static int mapAddr = 0;
00207
00212 static PCSCLITE_MUTEX clientMutex = PTHREAD_MUTEX_INITIALIZER;
00213
00220 static PREADER_STATE readerStates[PCSCLITE_MAX_READERS_CONTEXTS];
00221
00222 PCSC_API SCARD_IO_REQUEST g_rgSCardT0Pci = { SCARD_PROTOCOL_T0, 8 };
00223 PCSC_API SCARD_IO_REQUEST g_rgSCardT1Pci = { SCARD_PROTOCOL_T1, 8 };
00224 PCSC_API SCARD_IO_REQUEST g_rgSCardRawPci = { SCARD_PROTOCOL_RAW, 8 };
00227 static LONG SCardAddContext(SCARDCONTEXT, DWORD);
00228 static LONG SCardGetContextIndice(SCARDCONTEXT);
00229 static LONG SCardGetContextIndiceTH(SCARDCONTEXT);
00230 static LONG SCardRemoveContext(SCARDCONTEXT);
00231 static LONG SCardCleanContext(LONG indice);
00232
00233 static LONG SCardAddHandle(SCARDHANDLE, DWORD, LPCSTR);
00234 static LONG SCardGetIndicesFromHandle(SCARDHANDLE, PDWORD,
00235 PDWORD);
00236 static LONG SCardGetIndicesFromHandleTH(SCARDHANDLE, PDWORD,
00237 PDWORD);
00238 static LONG SCardRemoveHandle(SCARDHANDLE);
00239
00240 static LONG SCardGetSetAttrib(SCARDHANDLE hCard, int command, DWORD dwAttrId,
00241 LPBYTE pbAttr, LPDWORD pcbAttrLen);
00242
00243 void DESTRUCTOR SCardUnload(void);
00244
00245
00246
00247
00254 inline static LONG SCardLockThread(void)
00255 {
00256 return SYS_MutexLock(&clientMutex);
00257 }
00258
00264 inline static LONG SCardUnlockThread(void)
00265 {
00266 return SYS_MutexUnLock(&clientMutex);
00267 }
00268
00269 static LONG SCardEstablishContextTH(DWORD, LPCVOID, LPCVOID,
00270 LPSCARDCONTEXT);
00271
00305 LONG SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1,
00306 LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
00307 {
00308 LONG rv;
00309
00310 PROFILE_START
00311
00312
00313 rv = SCardCheckDaemonAvailability();
00314 if (SCARD_E_INVALID_HANDLE == rv)
00315
00316 rv = SCardCheckDaemonAvailability();
00317
00318 if (rv != SCARD_S_SUCCESS)
00319 return rv;
00320
00321 (void)SCardLockThread();
00322 rv = SCardEstablishContextTH(dwScope, pvReserved1,
00323 pvReserved2, phContext);
00324 (void)SCardUnlockThread();
00325
00326 PROFILE_END(rv)
00327
00328 return rv;
00329 }
00330
00357 static LONG SCardEstablishContextTH(DWORD dwScope,
00358 LPCVOID pvReserved1,
00359 LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
00360 {
00361 LONG rv;
00362 int i;
00363 establish_struct scEstablishStruct;
00364 sharedSegmentMsg msgStruct;
00365 uint32_t dwClientID = 0;
00366
00367 (void)pvReserved1;
00368 (void)pvReserved2;
00369 if (phContext == NULL)
00370 return SCARD_E_INVALID_PARAMETER;
00371 else
00372 *phContext = 0;
00373
00374
00375
00376
00377
00378
00379
00380
00381 if (isExecuted == 0)
00382 {
00383 int pageSize;
00384
00385
00386
00387
00388 (void)SYS_Initialize();
00389
00390
00391
00392
00393 mapAddr = SYS_OpenFile(PCSCLITE_PUBSHM_FILE, O_RDONLY, 0);
00394 if (mapAddr < 0)
00395 {
00396 Log3(PCSC_LOG_CRITICAL, "Cannot open public shared file %s: %s",
00397 PCSCLITE_PUBSHM_FILE, strerror(errno));
00398 return SCARD_E_NO_SERVICE;
00399 }
00400
00401
00402
00403
00404 (void)fcntl(mapAddr, F_SETFD, FD_CLOEXEC);
00405
00406 pageSize = SYS_GetPageSize();
00407
00408
00409
00410
00411 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
00412 {
00413 readerStates[i] =
00414 (PREADER_STATE)SYS_PublicMemoryMap(sizeof(READER_STATE),
00415 mapAddr, (i * pageSize));
00416 if (readerStates[i] == NULL)
00417 {
00418 Log2(PCSC_LOG_CRITICAL, "Cannot public memory map: %s",
00419 strerror(errno));
00420 (void)SYS_CloseFile(mapAddr);
00421 return SCARD_F_INTERNAL_ERROR;
00422 }
00423 }
00424
00425
00426
00427
00428 for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
00429 {
00430 int j;
00431
00432
00433
00434
00435 psContextMap[i].dwClientID = 0;
00436 psContextMap[i].hContext = 0;
00437 psContextMap[i].contextBlockStatus = BLOCK_STATUS_RESUME;
00438 psContextMap[i].mMutex = NULL;
00439
00440 for (j = 0; j < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; j++)
00441 {
00442
00443
00444
00445 psContextMap[i].psChannelMap[j].hCard = 0;
00446 psContextMap[i].psChannelMap[j].readerName = NULL;
00447 }
00448 }
00449
00450 }
00451
00452
00453
00454
00455
00456 for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
00457 {
00458 if (psContextMap[i].dwClientID == 0)
00459 break;
00460 }
00461
00462 if (i == PCSCLITE_MAX_APPLICATION_CONTEXTS)
00463 {
00464 return SCARD_E_NO_MEMORY;
00465 }
00466
00467
00468 if (SHMClientSetupSession(&dwClientID) != 0)
00469 {
00470 (void)SYS_CloseFile(mapAddr);
00471 return SCARD_E_NO_SERVICE;
00472 }
00473
00474 {
00475 version_struct *veStr;
00476
00477 memset(&msgStruct, 0, sizeof(msgStruct));
00478 msgStruct.mtype = CMD_VERSION;
00479 msgStruct.user_id = SYS_GetUID();
00480 msgStruct.group_id = SYS_GetGID();
00481 msgStruct.command = 0;
00482 msgStruct.date = time(NULL);
00483
00484 veStr = &msgStruct.veStr;
00485 veStr->major = PROTOCOL_VERSION_MAJOR;
00486 veStr->minor = PROTOCOL_VERSION_MINOR;
00487
00488 if (-1 == SHMMessageSend(&msgStruct, sizeof(msgStruct), dwClientID,
00489 PCSCLITE_MCLIENT_ATTEMPTS))
00490 return SCARD_E_NO_SERVICE;
00491
00492
00493
00494
00495 if (-1 == SHMMessageReceive(&msgStruct, sizeof(msgStruct), dwClientID,
00496 PCSCLITE_CLIENT_ATTEMPTS))
00497 {
00498 Log1(PCSC_LOG_CRITICAL, "Your pcscd is too old and does not support CMD_VERSION");
00499 return SCARD_F_COMM_ERROR;
00500 }
00501
00502 Log3(PCSC_LOG_INFO, "Server is protocol version %d:%d",
00503 veStr->major, veStr->minor);
00504
00505 if (veStr->rv != SCARD_S_SUCCESS)
00506 return veStr->rv;
00507
00508 isExecuted = 1;
00509 }
00510
00511 again:
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
00540 if (-1 != SCardGetContextIndiceTH(scEstablishStruct.phContext))
00541
00542
00543 goto again;
00544
00545 *phContext = scEstablishStruct.phContext;
00546
00547
00548
00549
00550 rv = SCardAddContext(*phContext, dwClientID);
00551
00552 return rv;
00553 }
00554
00576 LONG SCardReleaseContext(SCARDCONTEXT hContext)
00577 {
00578 LONG rv;
00579 release_struct scReleaseStruct;
00580 sharedSegmentMsg msgStruct;
00581 LONG dwContextIndex;
00582
00583 PROFILE_START
00584
00585
00586
00587
00588
00589 dwContextIndex = SCardGetContextIndice(hContext);
00590 if (dwContextIndex == -1)
00591 return SCARD_E_INVALID_HANDLE;
00592
00593 rv = SCardCheckDaemonAvailability();
00594 if (rv != SCARD_S_SUCCESS)
00595 {
00596
00597
00598
00599 (void)SCardLockThread();
00600 (void)SCardRemoveContext(hContext);
00601 (void)SCardUnlockThread();
00602
00603 return rv;
00604 }
00605
00606 (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
00607
00608
00609 dwContextIndex = SCardGetContextIndice(hContext);
00610 if (dwContextIndex == -1)
00611
00612
00613
00614 return SCARD_E_INVALID_HANDLE;
00615
00616 scReleaseStruct.hContext = hContext;
00617 scReleaseStruct.rv = SCARD_S_SUCCESS;
00618
00619 rv = WrapSHMWrite(SCARD_RELEASE_CONTEXT,
00620 psContextMap[dwContextIndex].dwClientID,
00621 sizeof(scReleaseStruct),
00622 PCSCLITE_MCLIENT_ATTEMPTS, (void *) &scReleaseStruct);
00623
00624 if (rv == -1)
00625 {
00626 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00627 return SCARD_E_NO_SERVICE;
00628 }
00629
00630
00631
00632
00633 rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
00634 PCSCLITE_CLIENT_ATTEMPTS);
00635 memcpy(&scReleaseStruct, &msgStruct.data, sizeof(scReleaseStruct));
00636
00637 if (rv == -1)
00638 {
00639 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00640 return SCARD_F_COMM_ERROR;
00641 }
00642
00643 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00644
00645
00646
00647
00648 (void)SCardLockThread();
00649 (void)SCardRemoveContext(hContext);
00650 (void)SCardUnlockThread();
00651
00652 PROFILE_END(scReleaseStruct.rv)
00653
00654 return scReleaseStruct.rv;
00655 }
00656
00672 LONG SCardSetTimeout( SCARDCONTEXT hContext,
00673 DWORD dwTimeout)
00674 {
00675
00676
00677
00678 (void)hContext;
00679 (void)dwTimeout;
00680 return SCARD_S_SUCCESS;
00681 }
00682
00733 LONG SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader,
00734 DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard,
00735 LPDWORD pdwActiveProtocol)
00736 {
00737 LONG rv;
00738 connect_struct scConnectStruct;
00739 sharedSegmentMsg msgStruct;
00740 LONG dwContextIndex;
00741
00742 PROFILE_START
00743
00744
00745
00746
00747 if (phCard == NULL || pdwActiveProtocol == NULL)
00748 return SCARD_E_INVALID_PARAMETER;
00749 else
00750 *phCard = 0;
00751
00752 if (szReader == NULL)
00753 return SCARD_E_UNKNOWN_READER;
00754
00755
00756
00757
00758 if (strlen(szReader) > MAX_READERNAME)
00759 return SCARD_E_INVALID_VALUE;
00760
00761 rv = SCardCheckDaemonAvailability();
00762 if (rv != SCARD_S_SUCCESS)
00763 return rv;
00764
00765
00766
00767
00768 dwContextIndex = SCardGetContextIndice(hContext);
00769 if (dwContextIndex == -1)
00770 return SCARD_E_INVALID_HANDLE;
00771
00772 (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
00773
00774
00775 dwContextIndex = SCardGetContextIndice(hContext);
00776 if (dwContextIndex == -1)
00777
00778
00779
00780 return SCARD_E_INVALID_HANDLE;
00781
00782 strncpy(scConnectStruct.szReader, szReader, MAX_READERNAME);
00783
00784 scConnectStruct.hContext = hContext;
00785 scConnectStruct.dwShareMode = dwShareMode;
00786 scConnectStruct.dwPreferredProtocols = dwPreferredProtocols;
00787 scConnectStruct.phCard = 0;
00788 scConnectStruct.pdwActiveProtocol = 0;
00789 scConnectStruct.rv = SCARD_S_SUCCESS;
00790
00791 rv = WrapSHMWrite(SCARD_CONNECT, psContextMap[dwContextIndex].dwClientID,
00792 sizeof(scConnectStruct),
00793 PCSCLITE_CLIENT_ATTEMPTS, (void *) &scConnectStruct);
00794
00795 if (rv == -1)
00796 {
00797 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00798 return SCARD_E_NO_SERVICE;
00799 }
00800
00801
00802
00803
00804 rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
00805 PCSCLITE_CLIENT_ATTEMPTS);
00806
00807 memcpy(&scConnectStruct, &msgStruct.data, sizeof(scConnectStruct));
00808
00809 if (rv == -1)
00810 {
00811 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00812 return SCARD_F_COMM_ERROR;
00813 }
00814
00815 *phCard = scConnectStruct.phCard;
00816 *pdwActiveProtocol = scConnectStruct.pdwActiveProtocol;
00817
00818 if (scConnectStruct.rv == SCARD_S_SUCCESS)
00819 {
00820
00821
00822
00823 rv = SCardAddHandle(*phCard, dwContextIndex, szReader);
00824 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00825
00826 PROFILE_END(rv)
00827
00828 return rv;
00829 }
00830
00831 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00832
00833 PROFILE_END(scConnectStruct.rv)
00834
00835 return scConnectStruct.rv;
00836 }
00837
00905 LONG SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode,
00906 DWORD dwPreferredProtocols, DWORD dwInitialization,
00907 LPDWORD pdwActiveProtocol)
00908 {
00909 LONG rv;
00910 reconnect_struct scReconnectStruct;
00911 sharedSegmentMsg msgStruct;
00912 int i;
00913 DWORD dwContextIndex, dwChannelIndex;
00914
00915 PROFILE_START
00916
00917 if (pdwActiveProtocol == NULL)
00918 return SCARD_E_INVALID_PARAMETER;
00919
00920 rv = SCardCheckDaemonAvailability();
00921 if (rv != SCARD_S_SUCCESS)
00922 return rv;
00923
00924
00925
00926
00927 rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
00928 if (rv == -1)
00929 return SCARD_E_INVALID_HANDLE;
00930
00931 (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
00932
00933
00934 rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
00935 if (rv == -1)
00936
00937
00938
00939 return SCARD_E_INVALID_HANDLE;
00940
00941 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
00942 {
00943 char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
00944
00945
00946 if (r && strcmp(r, (readerStates[i])->readerName) == 0)
00947 break;
00948 }
00949
00950 if (i == PCSCLITE_MAX_READERS_CONTEXTS)
00951 {
00952 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00953 return SCARD_E_READER_UNAVAILABLE;
00954 }
00955
00956 do
00957 {
00958 scReconnectStruct.hCard = hCard;
00959 scReconnectStruct.dwShareMode = dwShareMode;
00960 scReconnectStruct.dwPreferredProtocols = dwPreferredProtocols;
00961 scReconnectStruct.dwInitialization = dwInitialization;
00962 scReconnectStruct.pdwActiveProtocol = *pdwActiveProtocol;
00963 scReconnectStruct.rv = SCARD_S_SUCCESS;
00964
00965 rv = WrapSHMWrite(SCARD_RECONNECT, psContextMap[dwContextIndex].dwClientID,
00966 sizeof(scReconnectStruct),
00967 PCSCLITE_CLIENT_ATTEMPTS, (void *) &scReconnectStruct);
00968
00969 if (rv == -1)
00970 {
00971 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00972 return SCARD_E_NO_SERVICE;
00973 }
00974
00975
00976
00977
00978 rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
00979 PCSCLITE_CLIENT_ATTEMPTS);
00980
00981 memcpy(&scReconnectStruct, &msgStruct.data, sizeof(scReconnectStruct));
00982
00983 if (rv == -1)
00984 {
00985 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00986 return SCARD_F_COMM_ERROR;
00987 }
00988 } while (SCARD_E_SHARING_VIOLATION == scReconnectStruct.rv);
00989
00990 *pdwActiveProtocol = scReconnectStruct.pdwActiveProtocol;
00991
00992 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00993
00994 PROFILE_END(scReconnectStruct.rv)
00995
00996 return scReconnectStruct.rv;
00997 }
00998
01029 LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
01030 {
01031 LONG rv;
01032 disconnect_struct scDisconnectStruct;
01033 sharedSegmentMsg msgStruct;
01034 DWORD dwContextIndex, dwChannelIndex;
01035
01036 PROFILE_START
01037
01038 rv = SCardCheckDaemonAvailability();
01039 if (rv != SCARD_S_SUCCESS)
01040 return rv;
01041
01042
01043
01044
01045 rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01046 if (rv == -1)
01047 return SCARD_E_INVALID_HANDLE;
01048
01049 (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
01050
01051
01052 rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01053 if (rv == -1)
01054
01055
01056
01057 return SCARD_E_INVALID_HANDLE;
01058
01059 scDisconnectStruct.hCard = hCard;
01060 scDisconnectStruct.dwDisposition = dwDisposition;
01061 scDisconnectStruct.rv = SCARD_S_SUCCESS;
01062
01063 rv = WrapSHMWrite(SCARD_DISCONNECT, psContextMap[dwContextIndex].dwClientID,
01064 sizeof(scDisconnectStruct),
01065 PCSCLITE_CLIENT_ATTEMPTS, (void *) &scDisconnectStruct);
01066
01067 if (rv == -1)
01068 {
01069 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01070 return SCARD_E_NO_SERVICE;
01071 }
01072
01073
01074
01075
01076 rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
01077 PCSCLITE_CLIENT_ATTEMPTS);
01078
01079 memcpy(&scDisconnectStruct, &msgStruct.data,
01080 sizeof(scDisconnectStruct));
01081
01082 if (rv == -1)
01083 {
01084 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01085 return SCARD_F_COMM_ERROR;
01086 }
01087
01088 (void)SCardRemoveHandle(hCard);
01089
01090 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01091
01092 PROFILE_END(scDisconnectStruct.rv)
01093
01094 return scDisconnectStruct.rv;
01095 }
01096
01132 LONG SCardBeginTransaction(SCARDHANDLE hCard)
01133 {
01134
01135 LONG rv;
01136 begin_struct scBeginStruct;
01137 int i;
01138 sharedSegmentMsg msgStruct;
01139 DWORD dwContextIndex, dwChannelIndex;
01140
01141 PROFILE_START
01142
01143 rv = SCardCheckDaemonAvailability();
01144 if (rv != SCARD_S_SUCCESS)
01145 return rv;
01146
01147
01148
01149
01150 rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01151 if (rv == -1)
01152 return SCARD_E_INVALID_HANDLE;
01153
01154 (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
01155
01156
01157 rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01158 if (rv == -1)
01159
01160
01161
01162 return SCARD_E_INVALID_HANDLE;
01163
01164 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01165 {
01166 char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
01167
01168
01169 if (r && strcmp(r, (readerStates[i])->readerName) == 0)
01170 break;
01171 }
01172
01173 if (i == PCSCLITE_MAX_READERS_CONTEXTS)
01174 {
01175 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01176 return SCARD_E_READER_UNAVAILABLE;
01177 }
01178
01179 scBeginStruct.hCard = hCard;
01180 scBeginStruct.rv = SCARD_S_SUCCESS;
01181
01182
01183
01184
01185
01186
01187 do
01188 {
01189 rv = WrapSHMWrite(SCARD_BEGIN_TRANSACTION, psContextMap[dwContextIndex].dwClientID,
01190 sizeof(scBeginStruct),
01191 PCSCLITE_CLIENT_ATTEMPTS, (void *) &scBeginStruct);
01192
01193 if (rv == -1)
01194 {
01195
01196 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01197 return SCARD_E_NO_SERVICE;
01198 }
01199
01200
01201
01202
01203 rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
01204 PCSCLITE_CLIENT_ATTEMPTS);
01205
01206 memcpy(&scBeginStruct, &msgStruct.data, sizeof(scBeginStruct));
01207
01208 if (rv == -1)
01209 {
01210
01211 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01212 return SCARD_F_COMM_ERROR;
01213 }
01214
01215 }
01216 while (scBeginStruct.rv == SCARD_E_SHARING_VIOLATION);
01217
01218 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01219
01220 PROFILE_END(scBeginStruct.rv);
01221
01222 return scBeginStruct.rv;
01223 }
01224
01265 LONG SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
01266 {
01267 LONG rv;
01268 end_struct scEndStruct;
01269 sharedSegmentMsg msgStruct;
01270 int randnum, i;
01271 DWORD dwContextIndex, dwChannelIndex;
01272
01273 PROFILE_START
01274
01275
01276
01277
01278 randnum = 0;
01279
01280 rv = SCardCheckDaemonAvailability();
01281 if (rv != SCARD_S_SUCCESS)
01282 return rv;
01283
01284
01285
01286
01287 rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01288 if (rv == -1)
01289 return SCARD_E_INVALID_HANDLE;
01290
01291 (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
01292
01293
01294 rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01295 if (rv == -1)
01296
01297
01298
01299 return SCARD_E_INVALID_HANDLE;
01300
01301 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01302 {
01303 char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
01304
01305
01306 if (r && strcmp(r, (readerStates[i])->readerName) == 0)
01307 break;
01308 }
01309
01310 if (i == PCSCLITE_MAX_READERS_CONTEXTS)
01311 {
01312 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01313 return SCARD_E_READER_UNAVAILABLE;
01314 }
01315
01316 scEndStruct.hCard = hCard;
01317 scEndStruct.dwDisposition = dwDisposition;
01318 scEndStruct.rv = SCARD_S_SUCCESS;
01319
01320 rv = WrapSHMWrite(SCARD_END_TRANSACTION,
01321 psContextMap[dwContextIndex].dwClientID,
01322 sizeof(scEndStruct),
01323 PCSCLITE_CLIENT_ATTEMPTS, (void *) &scEndStruct);
01324
01325 if (rv == -1)
01326 {
01327 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01328 return SCARD_E_NO_SERVICE;
01329 }
01330
01331
01332
01333
01334 rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
01335 PCSCLITE_CLIENT_ATTEMPTS);
01336
01337 memcpy(&scEndStruct, &msgStruct.data, sizeof(scEndStruct));
01338
01339 if (rv == -1)
01340 {
01341 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01342 return SCARD_F_COMM_ERROR;
01343 }
01344
01345
01346
01347
01348 randnum = SYS_RandomInt(1000, 10000);
01349 (void)SYS_USleep(randnum);
01350
01351 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01352
01353 PROFILE_END(scEndStruct.rv)
01354
01355 return scEndStruct.rv;
01356 }
01357
01364 LONG SCardCancelTransaction(SCARDHANDLE hCard)
01365 {
01366 LONG rv;
01367 cancel_struct scCancelStruct;
01368 sharedSegmentMsg msgStruct;
01369 int i;
01370 DWORD dwContextIndex, dwChannelIndex;
01371
01372 PROFILE_START
01373
01374 rv = SCardCheckDaemonAvailability();
01375 if (rv != SCARD_S_SUCCESS)
01376 return rv;
01377
01378
01379
01380
01381 rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01382 if (rv == -1)
01383 return SCARD_E_INVALID_HANDLE;
01384
01385 (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
01386
01387
01388 rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01389 if (rv == -1)
01390
01391
01392
01393 return SCARD_E_INVALID_HANDLE;
01394
01395 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01396 {
01397 char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
01398
01399
01400 if (r && strcmp(r, (readerStates[i])->readerName) == 0)
01401 break;
01402 }
01403
01404 if (i == PCSCLITE_MAX_READERS_CONTEXTS)
01405 {
01406 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01407 return SCARD_E_READER_UNAVAILABLE;
01408 }
01409
01410 scCancelStruct.hCard = hCard;
01411
01412 rv = WrapSHMWrite(SCARD_CANCEL_TRANSACTION,
01413 psContextMap[dwContextIndex].dwClientID,
01414 sizeof(scCancelStruct),
01415 PCSCLITE_CLIENT_ATTEMPTS, (void *) &scCancelStruct);
01416
01417 if (rv == -1)
01418 {
01419 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01420 return SCARD_E_NO_SERVICE;
01421 }
01422
01423
01424
01425
01426 rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
01427 PCSCLITE_CLIENT_ATTEMPTS);
01428
01429 memcpy(&scCancelStruct, &msgStruct.data, sizeof(scCancelStruct));
01430
01431 if (rv == -1)
01432 {
01433 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01434 return SCARD_F_COMM_ERROR;
01435 }
01436
01437 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01438
01439 PROFILE_END(scCancelStruct.rv)
01440
01441 return scCancelStruct.rv;
01442 }
01443
01531 LONG SCardStatus(SCARDHANDLE hCard, LPSTR mszReaderName,
01532 LPDWORD pcchReaderLen, LPDWORD pdwState,
01533 LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
01534 {
01535 DWORD dwReaderLen, dwAtrLen;
01536 LONG rv;
01537 int i;
01538 status_struct scStatusStruct;
01539 sharedSegmentMsg msgStruct;
01540 DWORD dwContextIndex, dwChannelIndex;
01541 char *r;
01542 char *bufReader = NULL;
01543 LPBYTE bufAtr = NULL;
01544 DWORD dummy;
01545
01546 PROFILE_START
01547
01548
01549 if (pdwState)
01550 *pdwState = 0;
01551
01552 if (pdwProtocol)
01553 *pdwProtocol = 0;
01554
01555
01556 if (pcchReaderLen == NULL)
01557 pcchReaderLen = &dummy;
01558
01559 if (pcbAtrLen == NULL)
01560 pcbAtrLen = &dummy;
01561
01562
01563 dwReaderLen = *pcchReaderLen;
01564 dwAtrLen = *pcbAtrLen;
01565
01566 *pcchReaderLen = 0;
01567 *pcbAtrLen = 0;
01568
01569 rv = SCardCheckDaemonAvailability();
01570 if (rv != SCARD_S_SUCCESS)
01571 return rv;
01572
01573
01574
01575
01576 rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01577 if (rv == -1)
01578 return SCARD_E_INVALID_HANDLE;
01579
01580 (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
01581
01582
01583 rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01584 if (rv == -1)
01585
01586
01587
01588 return SCARD_E_INVALID_HANDLE;
01589
01590 r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
01591 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01592 {
01593
01594 if (r && strcmp(r, (readerStates[i])->readerName) == 0)
01595 break;
01596 }
01597
01598 if (i == PCSCLITE_MAX_READERS_CONTEXTS)
01599 {
01600 rv = SCARD_E_READER_UNAVAILABLE;
01601 goto end;
01602 }
01603
01604
01605 memset(&scStatusStruct, 0, sizeof(scStatusStruct));
01606 scStatusStruct.hCard = hCard;
01607
01608
01609 scStatusStruct.pcchReaderLen = sizeof(scStatusStruct.mszReaderNames);
01610 scStatusStruct.pcbAtrLen = sizeof(scStatusStruct.pbAtr);
01611
01612 rv = WrapSHMWrite(SCARD_STATUS, psContextMap[dwContextIndex].dwClientID,
01613 sizeof(scStatusStruct),
01614 PCSCLITE_CLIENT_ATTEMPTS, (void *) &scStatusStruct);
01615
01616 if (rv == -1)
01617 {
01618 rv = SCARD_E_NO_SERVICE;
01619 goto end;
01620 }
01621
01622
01623
01624
01625 rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
01626 PCSCLITE_CLIENT_ATTEMPTS);
01627
01628 memcpy(&scStatusStruct, &msgStruct.data, sizeof(scStatusStruct));
01629
01630 if (rv == -1)
01631 {
01632 rv = SCARD_F_COMM_ERROR;
01633 goto end;
01634 }
01635
01636 rv = scStatusStruct.rv;
01637 if (rv != SCARD_S_SUCCESS && rv != SCARD_E_INSUFFICIENT_BUFFER)
01638 {
01639
01640
01641
01642 goto end;
01643 }
01644
01645
01646
01647
01648
01649 *pcchReaderLen = strlen(psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName) + 1;
01650 *pcbAtrLen = (readerStates[i])->cardAtrLength;
01651
01652 if (pdwState)
01653 *pdwState = (readerStates[i])->readerState;
01654
01655 if (pdwProtocol)
01656 *pdwProtocol = (readerStates[i])->cardProtocol;
01657
01658 if (SCARD_AUTOALLOCATE == dwReaderLen)
01659 {
01660 dwReaderLen = *pcchReaderLen;
01661 bufReader = malloc(dwReaderLen);
01662 if (NULL == bufReader)
01663 {
01664 rv = SCARD_E_NO_MEMORY;
01665 goto end;
01666 }
01667 if (NULL == mszReaderName)
01668 {
01669 rv = SCARD_E_INVALID_PARAMETER;
01670 goto end;
01671 }
01672 *(char **)mszReaderName = bufReader;
01673 }
01674 else
01675 bufReader = mszReaderName;
01676
01677
01678 if (bufReader)
01679 {
01680 if (*pcchReaderLen > dwReaderLen)
01681 rv = SCARD_E_INSUFFICIENT_BUFFER;
01682
01683 strncpy(bufReader,
01684 psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName,
01685 dwReaderLen);
01686 }
01687
01688 if (SCARD_AUTOALLOCATE == dwAtrLen)
01689 {
01690 dwAtrLen = *pcbAtrLen;
01691 bufAtr = malloc(dwAtrLen);
01692 if (NULL == bufAtr)
01693 {
01694 rv = SCARD_E_NO_MEMORY;
01695 goto end;
01696 }
01697 if (NULL == pbAtr)
01698 {
01699 rv = SCARD_E_INVALID_PARAMETER;
01700 goto end;
01701 }
01702 *(LPBYTE *)pbAtr = bufAtr;
01703 }
01704 else
01705 bufAtr = pbAtr;
01706
01707 if (bufAtr)
01708 {
01709 if (*pcbAtrLen > dwAtrLen)
01710 rv = SCARD_E_INSUFFICIENT_BUFFER;
01711
01712 memcpy(bufAtr, (readerStates[i])->cardAtr, min(*pcbAtrLen, dwAtrLen));
01713 }
01714
01715 end:
01716 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01717
01718 PROFILE_END(rv)
01719
01720 return rv;
01721 }
01722
01723 static long WaitForPcscdEvent(SCARDCONTEXT hContext, long dwTime)
01724 {
01725 char filename[FILENAME_MAX];
01726 char buf[1];
01727 int fd, r;
01728 struct timeval tv, *ptv = NULL;
01729 struct timeval before, after;
01730 fd_set read_fd;
01731
01732 if (INFINITE != dwTime)
01733 {
01734 if (dwTime < 0)
01735 return 0;
01736 gettimeofday(&before, NULL);
01737 tv.tv_sec = dwTime/1000;
01738 tv.tv_usec = dwTime*1000 - tv.tv_sec*1000000;
01739 ptv = &tv;
01740 }
01741
01742 (void)snprintf(filename, sizeof(filename), "%s/event.%d.%ld",
01743 PCSCLITE_EVENTS_DIR, SYS_GetPID(), hContext);
01744 r = mkfifo(filename, 0644);
01745 if (-1 == r)
01746 {
01747 Log2(PCSC_LOG_CRITICAL, "Can't create event fifo: %s", strerror(errno));
01748 goto exit;
01749 }
01750
01751 fd = SYS_OpenFile(filename, O_RDONLY | O_NONBLOCK, 0);
01752
01753
01754 if (-1 != fd)
01755 {
01756 FD_ZERO(&read_fd);
01757 FD_SET(fd, &read_fd);
01758
01759 (void)select(fd+1, &read_fd, NULL, NULL, ptv);
01760
01761 (void)SYS_ReadFile(fd, buf, 1);
01762 (void)SYS_CloseFile(fd);
01763 }
01764
01765 (void)SYS_RemoveFile(filename);
01766
01767 if (INFINITE != dwTime)
01768 {
01769 long int diff;
01770
01771 gettimeofday(&after, NULL);
01772 diff = time_sub(&after, &before);
01773 dwTime -= diff/1000;
01774 }
01775
01776 exit:
01777 return dwTime;
01778 }
01779
01871 LONG SCardGetStatusChange(SCARDCONTEXT hContext, DWORD dwTimeout,
01872 LPSCARD_READERSTATE_A rgReaderStates, DWORD cReaders)
01873 {
01874 PSCARD_READERSTATE_A currReader;
01875 PREADER_STATE rContext;
01876 long dwTime = dwTimeout;
01877 DWORD dwState;
01878 DWORD dwBreakFlag = 0;
01879 int j;
01880 LONG dwContextIndex;
01881 int currentReaderCount = 0;
01882 LONG rv = SCARD_S_SUCCESS;
01883
01884 PROFILE_START
01885
01886 if ((rgReaderStates == NULL && cReaders > 0)
01887 || (cReaders > PCSCLITE_MAX_READERS_CONTEXTS))
01888 return SCARD_E_INVALID_PARAMETER;
01889
01890
01891 for (j = 0; j < cReaders; j++)
01892 {
01893 if (rgReaderStates[j].szReader == NULL)
01894 return SCARD_E_INVALID_VALUE;
01895 }
01896
01897
01898 if (cReaders > 0)
01899 {
01900 int nbNonIgnoredReaders = cReaders;
01901
01902 for (j=0; j<cReaders; j++)
01903 if (rgReaderStates[j].dwCurrentState & SCARD_STATE_IGNORE)
01904 nbNonIgnoredReaders--;
01905
01906 if (0 == nbNonIgnoredReaders)
01907 return SCARD_S_SUCCESS;
01908 }
01909
01910 rv = SCardCheckDaemonAvailability();
01911 if (rv != SCARD_S_SUCCESS)
01912 return rv;
01913
01914
01915
01916
01917 dwContextIndex = SCardGetContextIndice(hContext);
01918 if (dwContextIndex == -1)
01919 return SCARD_E_INVALID_HANDLE;
01920
01921 (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
01922
01923
01924 dwContextIndex = SCardGetContextIndice(hContext);
01925 if (dwContextIndex == -1)
01926
01927
01928
01929 return SCARD_E_INVALID_HANDLE;
01930
01931
01932
01933
01934
01935
01936
01937 if (cReaders == 0)
01938 {
01939 while (1)
01940 {
01941 int i;
01942
01943 rv = SCardCheckDaemonAvailability();
01944 if (rv != SCARD_S_SUCCESS)
01945 goto end;
01946
01947 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01948 {
01949 if ((readerStates[i])->readerID != 0)
01950 {
01951
01952 rv = SCARD_S_SUCCESS;
01953 goto end;
01954 }
01955 }
01956
01957 if (dwTimeout == 0)
01958 {
01959
01960 rv = SCARD_E_READER_UNAVAILABLE;
01961 goto end;
01962 }
01963
01964 dwTime = WaitForPcscdEvent(hContext, dwTime);
01965 if (dwTimeout != INFINITE)
01966 {
01967 if (dwTime <= 0)
01968 {
01969 rv = SCARD_E_TIMEOUT;
01970 goto end;
01971 }
01972 }
01973 }
01974 }
01975
01976
01977
01978
01979
01980
01981 for (j = 0; j < cReaders; j++)
01982 rgReaderStates[j].dwEventState = 0;
01983
01984
01985 Log1(PCSC_LOG_DEBUG, "Event Loop Start");
01986
01987 psContextMap[dwContextIndex].contextBlockStatus = BLOCK_STATUS_BLOCKING;
01988
01989
01990 for (j=0; j < PCSCLITE_MAX_READERS_CONTEXTS; j++)
01991 if ((readerStates[j])->readerID != 0)
01992 currentReaderCount++;
01993
01994 j = 0;
01995 do
01996 {
01997 rv = SCardCheckDaemonAvailability();
01998 if (rv != SCARD_S_SUCCESS)
01999 {
02000 if (psContextMap[dwContextIndex].mMutex)
02001 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02002
02003 PROFILE_END(rv)
02004
02005 return rv;
02006 }
02007
02008 currReader = &rgReaderStates[j];
02009
02010
02011 if (!(currReader->dwCurrentState & SCARD_STATE_IGNORE))
02012 {
02013 LPSTR lpcReaderName;
02014 int i;
02015
02016
02017
02018 lpcReaderName = (char *) currReader->szReader;
02019
02020 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
02021 {
02022 if (strcmp(lpcReaderName, (readerStates[i])->readerName) == 0)
02023 break;
02024 }
02025
02026
02027 if (i == PCSCLITE_MAX_READERS_CONTEXTS)
02028 {
02029
02030 if (strcasecmp(lpcReaderName, "\\\\?PnP?\\Notification") == 0)
02031 {
02032 int k, newReaderCount = 0;
02033
02034 for (k=0; k < PCSCLITE_MAX_READERS_CONTEXTS; k++)
02035 if ((readerStates[k])->readerID != 0)
02036 newReaderCount++;
02037
02038 if (newReaderCount != currentReaderCount)
02039 {
02040 Log1(PCSC_LOG_INFO, "Reader list changed");
02041 currentReaderCount = newReaderCount;
02042
02043 currReader->dwEventState |= SCARD_STATE_CHANGED;
02044 dwBreakFlag = 1;
02045 }
02046 }
02047 else
02048 {
02049 currReader->dwEventState = SCARD_STATE_UNKNOWN | SCARD_STATE_UNAVAILABLE;
02050 if (!(currReader->dwCurrentState & SCARD_STATE_UNKNOWN))
02051 {
02052 currReader->dwEventState |= SCARD_STATE_CHANGED;
02053
02054
02055
02056
02057
02058 dwBreakFlag = 1;
02059 }
02060 }
02061 }
02062 else
02063 {
02064
02065 if (currReader->dwCurrentState & SCARD_STATE_UNKNOWN)
02066 {
02067 currReader->dwEventState |= SCARD_STATE_CHANGED;
02068 currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
02069 Log0(PCSC_LOG_DEBUG);
02070 dwBreakFlag = 1;
02071 }
02072
02073
02074
02075
02076 rContext = readerStates[i];
02077
02078
02079 dwState = rContext->readerState;
02080
02081
02082 if (currReader->dwCurrentState & 0xFFFF0000)
02083 {
02084 int currentCounter, stateCounter;
02085
02086 stateCounter = (dwState >> 16) & 0xFFFF;
02087 currentCounter = (currReader->dwCurrentState >> 16) & 0xFFFF;
02088
02089
02090 if (stateCounter != currentCounter)
02091 {
02092 currReader->dwEventState |= SCARD_STATE_CHANGED;
02093 Log0(PCSC_LOG_DEBUG);
02094 dwBreakFlag = 1;
02095 }
02096
02097
02098 currReader->dwEventState =
02099 ((currReader->dwEventState & 0xffff )
02100 | (stateCounter << 16));
02101 }
02102
02103
02104 if (dwState & SCARD_UNKNOWN)
02105 {
02106
02107 currReader->dwEventState = SCARD_STATE_UNAVAILABLE;
02108 if (!(currReader->dwCurrentState & SCARD_STATE_UNAVAILABLE))
02109 {
02110
02111 currReader->dwEventState |= SCARD_STATE_CHANGED;
02112 Log0(PCSC_LOG_DEBUG);
02113 dwBreakFlag = 1;
02114 }
02115 }
02116 else
02117 {
02118
02119 if (currReader-> dwCurrentState & SCARD_STATE_UNAVAILABLE)
02120 {
02121 currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
02122 currReader->dwEventState |= SCARD_STATE_CHANGED;
02123 Log0(PCSC_LOG_DEBUG);
02124 dwBreakFlag = 1;
02125 }
02126 }
02127
02128
02129
02130 if (dwState & SCARD_PRESENT)
02131 {
02132
02133 if (0 == rContext->cardAtrLength)
02134
02135 (void)SYS_USleep(PCSCLITE_STATUS_POLL_RATE + 10);
02136
02137 currReader->cbAtr = rContext->cardAtrLength;
02138 memcpy(currReader->rgbAtr, rContext->cardAtr,
02139 currReader->cbAtr);
02140 }
02141 else
02142 currReader->cbAtr = 0;
02143
02144
02145 if (dwState & SCARD_ABSENT)
02146 {
02147 currReader->dwEventState |= SCARD_STATE_EMPTY;
02148 currReader->dwEventState &= ~SCARD_STATE_PRESENT;
02149 currReader->dwEventState &= ~SCARD_STATE_UNAWARE;
02150 currReader->dwEventState &= ~SCARD_STATE_IGNORE;
02151 currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
02152 currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
02153 currReader->dwEventState &= ~SCARD_STATE_ATRMATCH;
02154 currReader->dwEventState &= ~SCARD_STATE_MUTE;
02155 currReader->dwEventState &= ~SCARD_STATE_INUSE;
02156
02157
02158 if (currReader->dwCurrentState & SCARD_STATE_PRESENT)
02159 {
02160 currReader->dwEventState |= SCARD_STATE_CHANGED;
02161 Log0(PCSC_LOG_DEBUG);
02162 dwBreakFlag = 1;
02163 }
02164 }
02165
02166 else if (dwState & SCARD_PRESENT)
02167 {
02168 currReader->dwEventState |= SCARD_STATE_PRESENT;
02169 currReader->dwEventState &= ~SCARD_STATE_EMPTY;
02170 currReader->dwEventState &= ~SCARD_STATE_UNAWARE;
02171 currReader->dwEventState &= ~SCARD_STATE_IGNORE;
02172 currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
02173 currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
02174 currReader->dwEventState &= ~SCARD_STATE_MUTE;
02175
02176 if (currReader->dwCurrentState & SCARD_STATE_EMPTY)
02177 {
02178 currReader->dwEventState |= SCARD_STATE_CHANGED;
02179 Log0(PCSC_LOG_DEBUG);
02180 dwBreakFlag = 1;
02181 }
02182
02183 if (dwState & SCARD_SWALLOWED)
02184 {
02185 currReader->dwEventState |= SCARD_STATE_MUTE;
02186 if (!(currReader->dwCurrentState & SCARD_STATE_MUTE))
02187 {
02188 currReader->dwEventState |= SCARD_STATE_CHANGED;
02189 Log0(PCSC_LOG_DEBUG);
02190 dwBreakFlag = 1;
02191 }
02192 }
02193 else
02194 {
02195
02196 if (currReader->dwCurrentState & SCARD_STATE_MUTE)
02197 {
02198 currReader->dwEventState |= SCARD_STATE_CHANGED;
02199 Log0(PCSC_LOG_DEBUG);
02200 dwBreakFlag = 1;
02201 }
02202 }
02203 }
02204
02205
02206 if (rContext->readerSharing == -1)
02207 {
02208 currReader->dwEventState |= SCARD_STATE_EXCLUSIVE;
02209 currReader->dwEventState &= ~SCARD_STATE_INUSE;
02210 if (currReader->dwCurrentState & SCARD_STATE_INUSE)
02211 {
02212 currReader->dwEventState |= SCARD_STATE_CHANGED;
02213 Log0(PCSC_LOG_DEBUG);
02214 dwBreakFlag = 1;
02215 }
02216 }
02217 else if (rContext->readerSharing >= 1)
02218 {
02219
02220 if (dwState & SCARD_PRESENT)
02221 {
02222 currReader->dwEventState |= SCARD_STATE_INUSE;
02223 currReader->dwEventState &= ~SCARD_STATE_EXCLUSIVE;
02224 if (currReader-> dwCurrentState & SCARD_STATE_EXCLUSIVE)
02225 {
02226 currReader->dwEventState |= SCARD_STATE_CHANGED;
02227 Log0(PCSC_LOG_DEBUG);
02228 dwBreakFlag = 1;
02229 }
02230 }
02231 }
02232 else if (rContext->readerSharing == 0)
02233 {
02234 currReader->dwEventState &= ~SCARD_STATE_INUSE;
02235 currReader->dwEventState &= ~SCARD_STATE_EXCLUSIVE;
02236
02237 if (currReader->dwCurrentState & SCARD_STATE_INUSE)
02238 {
02239 currReader->dwEventState |= SCARD_STATE_CHANGED;
02240 Log0(PCSC_LOG_DEBUG);
02241 dwBreakFlag = 1;
02242 }
02243 else if (currReader-> dwCurrentState
02244 & SCARD_STATE_EXCLUSIVE)
02245 {
02246 currReader->dwEventState |= SCARD_STATE_CHANGED;
02247 Log0(PCSC_LOG_DEBUG);
02248 dwBreakFlag = 1;
02249 }
02250 }
02251
02252 if (currReader->dwCurrentState == SCARD_STATE_UNAWARE)
02253 {
02254
02255
02256
02257
02258 currReader->dwEventState |= SCARD_STATE_CHANGED;
02259 Log0(PCSC_LOG_DEBUG);
02260 dwBreakFlag = 1;
02261 }
02262 }
02263 }
02264
02265
02266 j++;
02267 if (j == cReaders)
02268 {
02269
02270 j = 0;
02271
02272
02273
02274
02275 if (dwBreakFlag == 1)
02276 break;
02277
02278 if (BLOCK_STATUS_RESUME
02279 == psContextMap[dwContextIndex].contextBlockStatus)
02280 break;
02281
02282
02283 dwTime = WaitForPcscdEvent(hContext, dwTime);
02284
02285 if (dwTimeout != INFINITE)
02286 {
02287
02288
02289
02290 if (dwTime <= 0)
02291 {
02292 rv = SCARD_E_TIMEOUT;
02293 goto end;
02294 }
02295 }
02296 }
02297 }
02298 while (1);
02299
02300 if (psContextMap[dwContextIndex].contextBlockStatus == BLOCK_STATUS_RESUME)
02301 rv = SCARD_E_CANCELLED;
02302
02303 end:
02304 Log1(PCSC_LOG_DEBUG, "Event Loop End");
02305
02306 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02307
02308 PROFILE_END(rv)
02309
02310 return rv;
02311 }
02312
02364 LONG SCardControl(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer,
02365 DWORD cbSendLength, LPVOID pbRecvBuffer, DWORD cbRecvLength,
02366 LPDWORD lpBytesReturned)
02367 {
02368 LONG rv;
02369 control_struct scControlStruct;
02370 sharedSegmentMsg msgStruct;
02371 int i;
02372 DWORD dwContextIndex, dwChannelIndex;
02373
02374 PROFILE_START
02375
02376
02377 if (NULL != lpBytesReturned)
02378 *lpBytesReturned = 0;
02379
02380 rv = SCardCheckDaemonAvailability();
02381 if (rv != SCARD_S_SUCCESS)
02382 return rv;
02383
02384
02385
02386
02387 rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
02388 if (rv == -1)
02389 return SCARD_E_INVALID_HANDLE;
02390
02391 (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
02392
02393
02394 rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
02395 if (rv == -1)
02396
02397
02398
02399 return SCARD_E_INVALID_HANDLE;
02400
02401 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
02402 {
02403 char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
02404
02405
02406 if (r && strcmp(r, (readerStates[i])->readerName) == 0)
02407 break;
02408 }
02409
02410 if (i == PCSCLITE_MAX_READERS_CONTEXTS)
02411 {
02412 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02413 return SCARD_E_READER_UNAVAILABLE;
02414 }
02415
02416 if ((cbSendLength > MAX_BUFFER_SIZE_EXTENDED)
02417 || (cbRecvLength > MAX_BUFFER_SIZE_EXTENDED))
02418 {
02419 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02420 return SCARD_E_INSUFFICIENT_BUFFER;
02421 }
02422
02423 if ((cbSendLength > MAX_BUFFER_SIZE) || (cbRecvLength > MAX_BUFFER_SIZE))
02424 {
02425
02426 unsigned char buffer[sizeof(sharedSegmentMsg) + MAX_BUFFER_SIZE_EXTENDED];
02427 control_struct_extended *scControlStructExtended = (control_struct_extended *)buffer;
02428 sharedSegmentMsg *pmsgStruct = (psharedSegmentMsg)buffer;
02429
02430 scControlStructExtended->hCard = hCard;
02431 scControlStructExtended->dwControlCode = dwControlCode;
02432 scControlStructExtended->cbSendLength = cbSendLength;
02433 scControlStructExtended->cbRecvLength = cbRecvLength;
02434 scControlStructExtended->pdwBytesReturned = 0;
02435 scControlStructExtended->rv = SCARD_S_SUCCESS;
02436
02437
02438
02439
02440 scControlStructExtended->size = sizeof(*scControlStructExtended)
02441 - (sizeof(control_struct_extended) - offsetof(control_struct_extended, data))
02442 + cbSendLength;
02443 memcpy(scControlStructExtended->data, pbSendBuffer, cbSendLength);
02444
02445 rv = WrapSHMWrite(SCARD_CONTROL_EXTENDED,
02446 psContextMap[dwContextIndex].dwClientID,
02447 scControlStructExtended->size,
02448 PCSCLITE_CLIENT_ATTEMPTS, buffer);
02449
02450 if (rv == -1)
02451 {
02452 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02453 return SCARD_E_NO_SERVICE;
02454 }
02455
02456
02457
02458
02459
02460 rv = SHMMessageReceive(buffer, sizeof(sharedSegmentMsg),
02461 psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
02462 if (rv == -1)
02463 {
02464 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02465 return SCARD_F_COMM_ERROR;
02466 }
02467
02468
02469 scControlStructExtended = (control_struct_extended *)&(pmsgStruct -> data);
02470
02471
02472 if (scControlStructExtended->size > PCSCLITE_MAX_MESSAGE_SIZE)
02473 {
02474 rv = SHMMessageReceive(buffer + sizeof(sharedSegmentMsg),
02475 scControlStructExtended->size-PCSCLITE_MAX_MESSAGE_SIZE,
02476 psContextMap[dwContextIndex].dwClientID,
02477 PCSCLITE_CLIENT_ATTEMPTS);
02478 if (rv == -1)
02479 {
02480 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02481 return SCARD_F_COMM_ERROR;
02482 }
02483 }
02484
02485 if (scControlStructExtended -> rv == SCARD_S_SUCCESS)
02486 {
02487
02488
02489
02490 memcpy(pbRecvBuffer, scControlStructExtended -> data,
02491 scControlStructExtended -> pdwBytesReturned);
02492 memset(scControlStructExtended -> data, 0x00,
02493 scControlStructExtended -> pdwBytesReturned);
02494 }
02495
02496 if (NULL != lpBytesReturned)
02497 *lpBytesReturned = scControlStructExtended -> pdwBytesReturned;
02498
02499 rv = scControlStructExtended -> rv;
02500 }
02501 else
02502 {
02503 scControlStruct.hCard = hCard;
02504 scControlStruct.dwControlCode = dwControlCode;
02505 scControlStruct.cbSendLength = cbSendLength;
02506 scControlStruct.cbRecvLength = cbRecvLength;
02507 memcpy(scControlStruct.pbSendBuffer, pbSendBuffer, cbSendLength);
02508
02509 rv = WrapSHMWrite(SCARD_CONTROL,
02510 psContextMap[dwContextIndex].dwClientID,
02511 sizeof(scControlStruct), PCSCLITE_CLIENT_ATTEMPTS, &scControlStruct);
02512
02513 if (rv == -1)
02514 {
02515 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02516 return SCARD_E_NO_SERVICE;
02517 }
02518
02519
02520
02521
02522 rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
02523 PCSCLITE_CLIENT_ATTEMPTS);
02524
02525 if (rv == -1)
02526 {
02527 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02528 return SCARD_F_COMM_ERROR;
02529 }
02530
02531 memcpy(&scControlStruct, &msgStruct.data, sizeof(scControlStruct));
02532
02533 if (NULL != lpBytesReturned)
02534 *lpBytesReturned = scControlStruct.dwBytesReturned;
02535
02536 if (scControlStruct.rv == SCARD_S_SUCCESS)
02537 {
02538
02539
02540
02541 memcpy(pbRecvBuffer, scControlStruct.pbRecvBuffer,
02542 scControlStruct.cbRecvLength);
02543 memset(scControlStruct.pbRecvBuffer, 0x00,
02544 sizeof(scControlStruct.pbRecvBuffer));
02545 }
02546
02547 rv = scControlStruct.rv;
02548 }
02549
02550 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02551
02552 PROFILE_END(rv)
02553
02554 return rv;
02555 }
02556
02657 LONG SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr,
02658 LPDWORD pcbAttrLen)
02659 {
02660 LONG ret;
02661 unsigned char *buf = NULL;
02662
02663 PROFILE_START
02664
02665 if (NULL == pcbAttrLen)
02666 return SCARD_E_INVALID_PARAMETER;
02667
02668 if (SCARD_AUTOALLOCATE == *pcbAttrLen)
02669 {
02670 if (NULL == pbAttr)
02671 return SCARD_E_INVALID_PARAMETER;
02672
02673 *pcbAttrLen = MAX_BUFFER_SIZE;
02674 buf = malloc(*pcbAttrLen);
02675 if (NULL == buf)
02676 return SCARD_E_NO_MEMORY;
02677
02678 *(unsigned char **)pbAttr = buf;
02679 }
02680 else
02681 {
02682 buf = pbAttr;
02683
02684
02685 if (NULL == pbAttr)
02686
02687 *pcbAttrLen = MAX_BUFFER_SIZE;
02688 }
02689
02690 ret = SCardGetSetAttrib(hCard, SCARD_GET_ATTRIB, dwAttrId, buf,
02691 pcbAttrLen);
02692
02693 PROFILE_END(ret)
02694
02695 return ret;
02696 }
02697
02731 LONG SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr,
02732 DWORD cbAttrLen)
02733 {
02734 LONG ret;
02735
02736 PROFILE_START
02737
02738 if (NULL == pbAttr || 0 == cbAttrLen)
02739 return SCARD_E_INVALID_PARAMETER;
02740
02741 ret = SCardGetSetAttrib(hCard, SCARD_SET_ATTRIB, dwAttrId, (LPBYTE)pbAttr,
02742 &cbAttrLen);
02743
02744 PROFILE_END(ret)
02745
02746 return ret;
02747 }
02748
02749 static LONG SCardGetSetAttrib(SCARDHANDLE hCard, int command, DWORD dwAttrId,
02750 LPBYTE pbAttr, LPDWORD pcbAttrLen)
02751 {
02752 LONG rv;
02753 getset_struct scGetSetStruct;
02754 sharedSegmentMsg msgStruct;
02755 int i;
02756 DWORD dwContextIndex, dwChannelIndex;
02757
02758 rv = SCardCheckDaemonAvailability();
02759 if (rv != SCARD_S_SUCCESS)
02760 return rv;
02761
02762
02763
02764
02765 rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
02766 if (rv == -1)
02767 return SCARD_E_INVALID_HANDLE;
02768
02769 (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
02770
02771
02772 rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
02773 if (rv == -1)
02774
02775
02776
02777 return SCARD_E_INVALID_HANDLE;
02778
02779 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
02780 {
02781 char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
02782
02783
02784 if (r && strcmp(r, (readerStates[i])->readerName) == 0)
02785 break;
02786 }
02787
02788 if (i == PCSCLITE_MAX_READERS_CONTEXTS)
02789 {
02790 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02791 return SCARD_E_READER_UNAVAILABLE;
02792 }
02793
02794 if (*pcbAttrLen > MAX_BUFFER_SIZE)
02795 {
02796 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02797 return SCARD_E_INSUFFICIENT_BUFFER;
02798 }
02799
02800 scGetSetStruct.hCard = hCard;
02801 scGetSetStruct.dwAttrId = dwAttrId;
02802 scGetSetStruct.cbAttrLen = *pcbAttrLen;
02803 scGetSetStruct.rv = SCARD_E_NO_SERVICE;
02804 memset(scGetSetStruct.pbAttr, 0, sizeof(scGetSetStruct.pbAttr));
02805 if (SCARD_SET_ATTRIB == command)
02806 memcpy(scGetSetStruct.pbAttr, pbAttr, *pcbAttrLen);
02807
02808 rv = WrapSHMWrite(command,
02809 psContextMap[dwContextIndex].dwClientID, sizeof(scGetSetStruct),
02810 PCSCLITE_CLIENT_ATTEMPTS, &scGetSetStruct);
02811
02812 if (rv == -1)
02813 {
02814 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02815 return SCARD_E_NO_SERVICE;
02816 }
02817
02818
02819
02820
02821 rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
02822 PCSCLITE_CLIENT_ATTEMPTS);
02823
02824 if (rv == -1)
02825 {
02826 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02827 return SCARD_F_COMM_ERROR;
02828 }
02829
02830 memcpy(&scGetSetStruct, &msgStruct.data, sizeof(scGetSetStruct));
02831
02832 if ((SCARD_S_SUCCESS == scGetSetStruct.rv) && (SCARD_GET_ATTRIB == command))
02833 {
02834
02835
02836
02837 if (*pcbAttrLen < scGetSetStruct.cbAttrLen)
02838 {
02839 scGetSetStruct.cbAttrLen = *pcbAttrLen;
02840 scGetSetStruct.rv = SCARD_E_INSUFFICIENT_BUFFER;
02841 }
02842 else
02843 *pcbAttrLen = scGetSetStruct.cbAttrLen;
02844
02845 if (pbAttr)
02846 memcpy(pbAttr, scGetSetStruct.pbAttr, scGetSetStruct.cbAttrLen);
02847
02848 memset(scGetSetStruct.pbAttr, 0x00, sizeof(scGetSetStruct.pbAttr));
02849 }
02850
02851 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02852
02853 return scGetSetStruct.rv;
02854 }
02855
02914 LONG SCardTransmit(SCARDHANDLE hCard, LPCSCARD_IO_REQUEST pioSendPci,
02915 LPCBYTE pbSendBuffer, DWORD cbSendLength,
02916 LPSCARD_IO_REQUEST pioRecvPci, LPBYTE pbRecvBuffer,
02917 LPDWORD pcbRecvLength)
02918 {
02919 LONG rv;
02920 int i;
02921 DWORD dwContextIndex, dwChannelIndex;
02922
02923 PROFILE_START
02924
02925 if (pbSendBuffer == NULL || pbRecvBuffer == NULL ||
02926 pcbRecvLength == NULL || pioSendPci == NULL)
02927 return SCARD_E_INVALID_PARAMETER;
02928
02929 rv = SCardCheckDaemonAvailability();
02930 if (rv != SCARD_S_SUCCESS)
02931 return rv;
02932
02933
02934
02935
02936 rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
02937 if (rv == -1)
02938 {
02939 *pcbRecvLength = 0;
02940 return SCARD_E_INVALID_HANDLE;
02941 }
02942
02943 (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
02944
02945
02946 rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
02947 if (rv == -1)
02948
02949
02950
02951 return SCARD_E_INVALID_HANDLE;
02952
02953 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
02954 {
02955 char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
02956
02957
02958 if (r && strcmp(r, (readerStates[i])->readerName) == 0)
02959 break;
02960 }
02961
02962 if (i == PCSCLITE_MAX_READERS_CONTEXTS)
02963 {
02964 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02965 return SCARD_E_READER_UNAVAILABLE;
02966 }
02967
02968 if ((cbSendLength > MAX_BUFFER_SIZE_EXTENDED)
02969 || (*pcbRecvLength > MAX_BUFFER_SIZE_EXTENDED))
02970 {
02971 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02972 return SCARD_E_INSUFFICIENT_BUFFER;
02973 }
02974
02975 if ((cbSendLength > MAX_BUFFER_SIZE) || (*pcbRecvLength > MAX_BUFFER_SIZE))
02976 {
02977
02978 unsigned char buffer[sizeof(sharedSegmentMsg) + MAX_BUFFER_SIZE_EXTENDED];
02979 transmit_struct_extended *scTransmitStructExtended = (transmit_struct_extended *)buffer;
02980 sharedSegmentMsg *pmsgStruct = (psharedSegmentMsg)buffer;
02981
02982 scTransmitStructExtended->hCard = hCard;
02983 scTransmitStructExtended->cbSendLength = cbSendLength;
02984 scTransmitStructExtended->pcbRecvLength = *pcbRecvLength;
02985
02986
02987
02988
02989 scTransmitStructExtended->size = sizeof(*scTransmitStructExtended)
02990 - (sizeof(transmit_struct_extended) - offsetof(transmit_struct_extended, data))
02991 + cbSendLength;
02992 scTransmitStructExtended->pioSendPciProtocol = pioSendPci->dwProtocol;
02993 scTransmitStructExtended->pioSendPciLength = pioSendPci->cbPciLength;
02994 memcpy(scTransmitStructExtended->data, pbSendBuffer, cbSendLength);
02995 scTransmitStructExtended->rv = SCARD_S_SUCCESS;
02996
02997 if (pioRecvPci)
02998 {
02999 scTransmitStructExtended->pioRecvPciProtocol = pioRecvPci->dwProtocol;
03000 scTransmitStructExtended->pioRecvPciLength = pioRecvPci->cbPciLength;
03001 }
03002 else
03003 {
03004 scTransmitStructExtended->pioRecvPciProtocol = SCARD_PROTOCOL_ANY;
03005 scTransmitStructExtended->pioRecvPciLength = sizeof(SCARD_IO_REQUEST);
03006 }
03007
03008 rv = WrapSHMWrite(SCARD_TRANSMIT_EXTENDED,
03009 psContextMap[dwContextIndex].dwClientID,
03010 scTransmitStructExtended->size,
03011 PCSCLITE_CLIENT_ATTEMPTS, buffer);
03012
03013 if (rv == -1)
03014 {
03015 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
03016 return SCARD_E_NO_SERVICE;
03017 }
03018
03019
03020
03021
03022
03023 rv = SHMMessageReceive(buffer, sizeof(sharedSegmentMsg), psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
03024 if (rv == -1)
03025 {
03026 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
03027 return SCARD_F_COMM_ERROR;
03028 }
03029
03030
03031 scTransmitStructExtended = (transmit_struct_extended *)&(pmsgStruct -> data);
03032
03033
03034 if (scTransmitStructExtended->size > PCSCLITE_MAX_MESSAGE_SIZE)
03035 {
03036 rv = SHMMessageReceive(buffer + sizeof(sharedSegmentMsg),
03037 scTransmitStructExtended->size-PCSCLITE_MAX_MESSAGE_SIZE,
03038 psContextMap[dwContextIndex].dwClientID,
03039 PCSCLITE_CLIENT_ATTEMPTS);
03040 if (rv == -1)
03041 {
03042 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
03043 return SCARD_F_COMM_ERROR;
03044 }
03045 }
03046
03047 if (scTransmitStructExtended -> rv == SCARD_S_SUCCESS)
03048 {
03049
03050
03051
03052 memcpy(pbRecvBuffer, scTransmitStructExtended -> data,
03053 scTransmitStructExtended -> pcbRecvLength);
03054 memset(scTransmitStructExtended -> data, 0x00,
03055 scTransmitStructExtended -> pcbRecvLength);
03056
03057 if (pioRecvPci)
03058 {
03059 pioRecvPci->dwProtocol = scTransmitStructExtended->pioRecvPciProtocol;
03060 pioRecvPci->cbPciLength = scTransmitStructExtended->pioRecvPciLength;
03061 }
03062 }
03063
03064 *pcbRecvLength = scTransmitStructExtended -> pcbRecvLength;
03065 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
03066
03067 rv = scTransmitStructExtended -> rv;
03068 }
03069 else
03070 {
03071
03072 transmit_struct scTransmitStruct;
03073 sharedSegmentMsg msgStruct;
03074
03075 scTransmitStruct.hCard = hCard;
03076 scTransmitStruct.cbSendLength = cbSendLength;
03077 scTransmitStruct.pcbRecvLength = *pcbRecvLength;
03078 scTransmitStruct.pioSendPciProtocol = pioSendPci->dwProtocol;
03079 scTransmitStruct.pioSendPciLength = pioSendPci->cbPciLength;
03080 memcpy(scTransmitStruct.pbSendBuffer, pbSendBuffer, cbSendLength);
03081 memset(scTransmitStruct.pbSendBuffer+cbSendLength, 0, sizeof(scTransmitStruct.pbSendBuffer)-cbSendLength);
03082 memset(scTransmitStruct.pbRecvBuffer, 0, sizeof(scTransmitStruct.pbRecvBuffer));
03083 scTransmitStruct.rv = SCARD_S_SUCCESS;
03084
03085 if (pioRecvPci)
03086 {
03087 scTransmitStruct.pioRecvPciProtocol = pioRecvPci->dwProtocol;
03088 scTransmitStruct.pioRecvPciLength = pioRecvPci->cbPciLength;
03089 }
03090 else
03091 {
03092 scTransmitStruct.pioRecvPciProtocol = SCARD_PROTOCOL_ANY;
03093 scTransmitStruct.pioRecvPciLength = sizeof(SCARD_IO_REQUEST);
03094 }
03095
03096 rv = WrapSHMWrite(SCARD_TRANSMIT,
03097 psContextMap[dwContextIndex].dwClientID, sizeof(scTransmitStruct),
03098 PCSCLITE_CLIENT_ATTEMPTS, (void *) &scTransmitStruct);
03099
03100 if (rv == -1)
03101 {
03102 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
03103 return SCARD_E_NO_SERVICE;
03104 }
03105
03106
03107
03108
03109 rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
03110 PCSCLITE_CLIENT_ATTEMPTS);
03111
03112 memcpy(&scTransmitStruct, &msgStruct.data, sizeof(scTransmitStruct));
03113
03114 if (rv == -1)
03115 {
03116 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
03117 return SCARD_F_COMM_ERROR;
03118 }
03119
03120
03121
03122
03123 memset(scTransmitStruct.pbSendBuffer, 0x00, cbSendLength);
03124
03125 if (scTransmitStruct.rv == SCARD_S_SUCCESS)
03126 {
03127
03128
03129
03130 memcpy(pbRecvBuffer, scTransmitStruct.pbRecvBuffer,
03131 scTransmitStruct.pcbRecvLength);
03132 memset(scTransmitStruct.pbRecvBuffer, 0x00,
03133 scTransmitStruct.pcbRecvLength);
03134
03135 if (pioRecvPci)
03136 {
03137 pioRecvPci->dwProtocol = scTransmitStruct.pioRecvPciProtocol;
03138 pioRecvPci->cbPciLength = scTransmitStruct.pioRecvPciLength;
03139 }
03140 }
03141
03142 *pcbRecvLength = scTransmitStruct.pcbRecvLength;
03143 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
03144
03145 rv = scTransmitStruct.rv;
03146 }
03147
03148 PROFILE_END(rv)
03149
03150 return rv;
03151 }
03152
03201 LONG SCardListReaders(SCARDCONTEXT hContext, LPCSTR mszGroups,
03202 LPSTR mszReaders, LPDWORD pcchReaders)
03203 {
03204 DWORD dwReadersLen;
03205 int i;
03206 LONG dwContextIndex;
03207 LONG rv = SCARD_S_SUCCESS;
03208 char *buf = NULL;
03209
03210 (void)mszGroups;
03211 PROFILE_START
03212
03213
03214
03215
03216 if (pcchReaders == NULL)
03217 return SCARD_E_INVALID_PARAMETER;
03218
03219 rv = SCardCheckDaemonAvailability();
03220 if (rv != SCARD_S_SUCCESS)
03221 return rv;
03222
03223
03224
03225
03226 dwContextIndex = SCardGetContextIndice(hContext);
03227 if (dwContextIndex == -1)
03228 return SCARD_E_INVALID_HANDLE;
03229
03230 (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
03231
03232
03233 dwContextIndex = SCardGetContextIndice(hContext);
03234 if (dwContextIndex == -1)
03235
03236
03237
03238 return SCARD_E_INVALID_HANDLE;
03239
03240 dwReadersLen = 0;
03241 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
03242 if ((readerStates[i])->readerID != 0)
03243 dwReadersLen += strlen((readerStates[i])->readerName) + 1;
03244
03245
03246 dwReadersLen += 1;
03247
03248 if (1 == dwReadersLen)
03249 {
03250 rv = SCARD_E_NO_READERS_AVAILABLE;
03251 goto end;
03252 }
03253
03254 if (SCARD_AUTOALLOCATE == *pcchReaders)
03255 {
03256 buf = malloc(dwReadersLen);
03257 if (NULL == buf)
03258 {
03259 rv = SCARD_E_NO_MEMORY;
03260 goto end;
03261 }
03262 if (NULL == mszReaders)
03263 {
03264 rv = SCARD_E_INVALID_PARAMETER;
03265 goto end;
03266 }
03267 *(char **)mszReaders = buf;
03268 }
03269 else
03270 {
03271 buf = mszReaders;
03272
03273
03274 if ((NULL != mszReaders) && (*pcchReaders < dwReadersLen))
03275 {
03276 rv = SCARD_E_INSUFFICIENT_BUFFER;
03277 goto end;
03278 }
03279 }
03280
03281 if (mszReaders == NULL)
03282 goto end;
03283
03284 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
03285 {
03286 if ((readerStates[i])->readerID != 0)
03287 {
03288
03289
03290
03291 strcpy(buf, (readerStates[i])->readerName);
03292 buf += strlen((readerStates[i])->readerName)+1;
03293 }
03294 }
03295 *buf = '\0';
03296
03297 end:
03298
03299 *pcchReaders = dwReadersLen;
03300
03301 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
03302
03303 PROFILE_END(rv)
03304
03305 return rv;
03306 }
03307
03320 LONG SCardFreeMemory(SCARDCONTEXT hContext, LPCVOID pvMem)
03321 {
03322 LONG rv = SCARD_S_SUCCESS;
03323 LONG dwContextIndex;
03324
03325 PROFILE_START
03326
03327 rv = SCardCheckDaemonAvailability();
03328 if (rv != SCARD_S_SUCCESS)
03329 return rv;
03330
03331
03332
03333
03334 dwContextIndex = SCardGetContextIndice(hContext);
03335 if (dwContextIndex == -1)
03336 return SCARD_E_INVALID_HANDLE;
03337
03338 free((void *)pvMem);
03339
03340 PROFILE_END(rv)
03341
03342 return rv;
03343 }
03344
03394 LONG SCardListReaderGroups(SCARDCONTEXT hContext, LPSTR mszGroups,
03395 LPDWORD pcchGroups)
03396 {
03397 LONG rv = SCARD_S_SUCCESS;
03398 LONG dwContextIndex;
03399 char *buf = NULL;
03400
03401 PROFILE_START
03402
03403
03404 const char ReaderGroup[] = "SCard$DefaultReaders\0";
03405 const int dwGroups = sizeof(ReaderGroup);
03406
03407 rv = SCardCheckDaemonAvailability();
03408 if (rv != SCARD_S_SUCCESS)
03409 return rv;
03410
03411
03412
03413
03414 dwContextIndex = SCardGetContextIndice(hContext);
03415 if (dwContextIndex == -1)
03416 return SCARD_E_INVALID_HANDLE;
03417
03418 (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
03419
03420
03421 dwContextIndex = SCardGetContextIndice(hContext);
03422 if (dwContextIndex == -1)
03423
03424
03425
03426 return SCARD_E_INVALID_HANDLE;
03427
03428 if (SCARD_AUTOALLOCATE == *pcchGroups)
03429 {
03430 buf = malloc(dwGroups);
03431 if (NULL == buf)
03432 {
03433 rv = SCARD_E_NO_MEMORY;
03434 goto end;
03435 }
03436 if (NULL == mszGroups)
03437 {
03438 rv = SCARD_E_INVALID_PARAMETER;
03439 goto end;
03440 }
03441 *(char **)mszGroups = buf;
03442 }
03443 else
03444 {
03445 buf = mszGroups;
03446
03447 if ((NULL != mszGroups) && (*pcchGroups < dwGroups))
03448 {
03449 rv = SCARD_E_INSUFFICIENT_BUFFER;
03450 goto end;
03451 }
03452 }
03453
03454 if (buf)
03455 memcpy(buf, ReaderGroup, dwGroups);
03456
03457 end:
03458 *pcchGroups = dwGroups;
03459
03460 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
03461
03462 PROFILE_END(rv)
03463
03464 return rv;
03465 }
03466
03494 LONG SCardCancel(SCARDCONTEXT hContext)
03495 {
03496 LONG dwContextIndex;
03497 LONG rv = SCARD_S_SUCCESS;
03498
03499 PROFILE_START
03500
03501 dwContextIndex = SCardGetContextIndice(hContext);
03502 if (dwContextIndex == -1)
03503 return SCARD_E_INVALID_HANDLE;
03504
03505
03506
03507
03508
03509 psContextMap[dwContextIndex].contextBlockStatus = BLOCK_STATUS_RESUME;
03510
03511 if (StatSynchronizeContext(hContext))
03512 rv = SCARD_F_INTERNAL_ERROR;
03513
03514 PROFILE_END(rv)
03515
03516 return rv;
03517 }
03518
03542 LONG SCardIsValidContext(SCARDCONTEXT hContext)
03543 {
03544 LONG rv;
03545 LONG dwContextIndex;
03546
03547 PROFILE_START
03548
03549 rv = SCARD_S_SUCCESS;
03550
03551
03552 rv = SCardCheckDaemonAvailability();
03553 if (rv != SCARD_S_SUCCESS)
03554 return rv;
03555
03556
03557
03558
03559 dwContextIndex = SCardGetContextIndice(hContext);
03560 if (dwContextIndex == -1)
03561 rv = SCARD_E_INVALID_HANDLE;
03562
03563 PROFILE_END(rv)
03564
03565 return rv;
03566 }
03567
03584 static LONG SCardAddContext(SCARDCONTEXT hContext, DWORD dwClientID)
03585 {
03586 int i;
03587
03588 for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
03589 {
03590 if (psContextMap[i].hContext == 0)
03591 {
03592 psContextMap[i].hContext = hContext;
03593 psContextMap[i].dwClientID = dwClientID;
03594 psContextMap[i].contextBlockStatus = BLOCK_STATUS_RESUME;
03595 psContextMap[i].mMutex = malloc(sizeof(PCSCLITE_MUTEX));
03596 (void)SYS_MutexInit(psContextMap[i].mMutex);
03597 return SCARD_S_SUCCESS;
03598 }
03599 }
03600
03601 return SCARD_E_NO_MEMORY;
03602 }
03603
03616 static LONG SCardGetContextIndice(SCARDCONTEXT hContext)
03617 {
03618 LONG rv;
03619
03620 (void)SCardLockThread();
03621 rv = SCardGetContextIndiceTH(hContext);
03622 (void)SCardUnlockThread();
03623
03624 return rv;
03625 }
03626
03639 static LONG SCardGetContextIndiceTH(SCARDCONTEXT hContext)
03640 {
03641 int i;
03642
03643
03644
03645
03646 for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
03647 {
03648 if ((hContext == psContextMap[i].hContext) && (hContext != 0))
03649 return i;
03650 }
03651
03652 return -1;
03653 }
03654
03664 static LONG SCardRemoveContext(SCARDCONTEXT hContext)
03665 {
03666 LONG retIndice;
03667
03668 retIndice = SCardGetContextIndiceTH(hContext);
03669
03670 if (retIndice == -1)
03671 return SCARD_E_INVALID_HANDLE;
03672 else
03673 return SCardCleanContext(retIndice);
03674 }
03675
03676 static LONG SCardCleanContext(LONG indice)
03677 {
03678 int i;
03679
03680 psContextMap[indice].hContext = 0;
03681 (void)SHMClientCloseSession(psContextMap[indice].dwClientID);
03682 psContextMap[indice].dwClientID = 0;
03683 free(psContextMap[indice].mMutex);
03684 psContextMap[indice].mMutex = NULL;
03685 psContextMap[indice].contextBlockStatus = BLOCK_STATUS_RESUME;
03686
03687 for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
03688 {
03689
03690
03691
03692 psContextMap[indice].psChannelMap[i].hCard = 0;
03693 free(psContextMap[indice].psChannelMap[i].readerName);
03694 psContextMap[indice].psChannelMap[i].readerName = NULL;
03695 }
03696
03697 return SCARD_S_SUCCESS;
03698 }
03699
03700
03701
03702
03703
03704 static LONG SCardAddHandle(SCARDHANDLE hCard, DWORD dwContextIndex,
03705 LPCSTR readerName)
03706 {
03707 int i;
03708
03709 for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
03710 {
03711 if (psContextMap[dwContextIndex].psChannelMap[i].hCard == 0)
03712 {
03713 psContextMap[dwContextIndex].psChannelMap[i].hCard = hCard;
03714 psContextMap[dwContextIndex].psChannelMap[i].readerName = strdup(readerName);
03715 return SCARD_S_SUCCESS;
03716 }
03717 }
03718
03719 return SCARD_E_NO_MEMORY;
03720 }
03721
03722 static LONG SCardRemoveHandle(SCARDHANDLE hCard)
03723 {
03724 DWORD dwContextIndice, dwChannelIndice;
03725 LONG rv;
03726
03727 rv = SCardGetIndicesFromHandle(hCard, &dwContextIndice, &dwChannelIndice);
03728 if (rv == -1)
03729 return SCARD_E_INVALID_HANDLE;
03730 else
03731 {
03732 psContextMap[dwContextIndice].psChannelMap[dwChannelIndice].hCard = 0;
03733 free(psContextMap[dwContextIndice].psChannelMap[dwChannelIndice].readerName);
03734 psContextMap[dwContextIndice].psChannelMap[dwChannelIndice].readerName = NULL;
03735 return SCARD_S_SUCCESS;
03736 }
03737 }
03738
03739 static LONG SCardGetIndicesFromHandle(SCARDHANDLE hCard,
03740 PDWORD pdwContextIndice, PDWORD pdwChannelIndice)
03741 {
03742 LONG rv;
03743
03744 if (0 == hCard)
03745 return -1;
03746
03747 (void)SCardLockThread();
03748 rv = SCardGetIndicesFromHandleTH(hCard, pdwContextIndice, pdwChannelIndice);
03749 (void)SCardUnlockThread();
03750
03751 return rv;
03752 }
03753
03754 static LONG SCardGetIndicesFromHandleTH(SCARDHANDLE hCard,
03755 PDWORD pdwContextIndice, PDWORD pdwChannelIndice)
03756 {
03757 int i;
03758
03759 for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
03760 {
03761 if (psContextMap[i].hContext != 0)
03762 {
03763 int j;
03764
03765 for (j = 0; j < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; j++)
03766 {
03767 if (psContextMap[i].psChannelMap[j].hCard == hCard)
03768 {
03769 *pdwContextIndice = i;
03770 *pdwChannelIndice = j;
03771 return SCARD_S_SUCCESS;
03772 }
03773 }
03774
03775 }
03776 }
03777
03778 return -1;
03779 }
03780
03789 LONG SCardCheckDaemonAvailability(void)
03790 {
03791 LONG rv;
03792 struct stat statBuffer;
03793 int need_restart = 0;
03794
03795 rv = SYS_Stat(PCSCLITE_PUBSHM_FILE, &statBuffer);
03796
03797 if (rv != 0)
03798 {
03799 Log2(PCSC_LOG_INFO, "PCSC Not Running: " PCSCLITE_PUBSHM_FILE ": %s",
03800 strerror(errno));
03801 return SCARD_E_NO_SERVICE;
03802 }
03803
03804
03805
03806 if (daemon_ctime && statBuffer.st_ctime > daemon_ctime)
03807 {
03808
03809 if (GetDaemonPid() != daemon_pid)
03810 {
03811 Log1(PCSC_LOG_INFO, "PCSC restarted");
03812 need_restart = 1;
03813 }
03814 }
03815
03816
03817 if (client_pid && client_pid != getpid())
03818 {
03819 Log1(PCSC_LOG_INFO, "Client forked");
03820 need_restart = 1;
03821 }
03822
03823 if (need_restart)
03824 {
03825 int i;
03826
03827
03828 (void)SCardLockThread();
03829
03830 for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
03831 if (psContextMap[i].hContext)
03832 (void)SCardCleanContext(i);
03833
03834 (void)SCardUnlockThread();
03835
03836
03837 daemon_ctime = 0;
03838 client_pid = 0;
03839
03840
03841 SCardUnload();
03842
03843 return SCARD_E_INVALID_HANDLE;
03844 }
03845
03846 daemon_ctime = statBuffer.st_ctime;
03847 daemon_pid = GetDaemonPid();
03848 client_pid = getpid();
03849
03850 return SCARD_S_SUCCESS;
03851 }
03852
03859 #ifdef __SUNPRO_C
03860 #pragma fini (SCardUnload)
03861 #endif
03862
03863 void DESTRUCTOR SCardUnload(void)
03864 {
03865 int i;
03866
03867 if (!isExecuted)
03868 return;
03869
03870
03871 for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
03872 {
03873 if (readerStates[i] != NULL)
03874 {
03875 SYS_PublicMemoryUnmap(readerStates[i], sizeof(READER_STATE));
03876 readerStates[i] = NULL;
03877 }
03878 }
03879
03880 (void)SYS_CloseFile(mapAddr);
03881 isExecuted = 0;
03882 }
03883