pcsc-lite 1.5.5
|
00001 /* 00002 * MUSCLE SmartCard Development ( http://www.linuxnet.com ) 00003 * 00004 * Copyright (C) 1999-2004 00005 * David Corcoran <corcoran@linuxnet.com> 00006 * Damien Sauveron <damien.sauveron@labri.fr> 00007 * Ludovic Rousseau <ludovic.rousseau@free.fr> 00008 * 00009 * $Id: winscard_clnt.c 4333 2009-07-21 11:36:36Z rousseau $ 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 /* r = a - b */ 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 } /* time_sub */ 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 /* PROFILE_END was not called before? */ 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 } /* profile_start */ 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 /* allow to detect missing PROFILE_END calls */ 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 } /* profile_end */ 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, /*@out@*/ PDWORD, 00235 /*@out@*/ PDWORD); 00236 static LONG SCardGetIndicesFromHandleTH(SCARDHANDLE, /*@out@*/ PDWORD, 00237 /*@out@*/ 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 * Thread safety functions 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 /*@out@*/ LPSCARDCONTEXT); 00271 00305 LONG SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1, 00306 LPCVOID pvReserved2, LPSCARDCONTEXT phContext) 00307 { 00308 LONG rv; 00309 00310 PROFILE_START 00311 00312 /* Check if the server is running */ 00313 rv = SCardCheckDaemonAvailability(); 00314 if (SCARD_E_INVALID_HANDLE == rv) 00315 /* we reconnected to a daemon or we got called from a forked child */ 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 /*@unused@*/ LPCVOID pvReserved1, 00359 /*@unused@*/ 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 * Do this only once: 00376 * - Initialize debug of need. 00377 * - Set up the memory mapped structures for reader states. 00378 * - Allocate each reader structure. 00379 * - Initialize context struct. 00380 */ 00381 if (isExecuted == 0) 00382 { 00383 int pageSize; 00384 00385 /* 00386 * Do any system initilization here 00387 */ 00388 (void)SYS_Initialize(); 00389 00390 /* 00391 * Set up the memory mapped reader stats structures 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 /* close on exec so that child processes do not inherits the file 00402 * descriptor. The child process will call SCardEstablishContext() 00403 * if needed. */ 00404 (void)fcntl(mapAddr, F_SETFD, FD_CLOEXEC); 00405 00406 pageSize = SYS_GetPageSize(); 00407 00408 /* 00409 * Allocate each reader structure in the memory map 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); /* Close the memory map file */ 00421 return SCARD_F_INTERNAL_ERROR; 00422 } 00423 } 00424 00425 /* 00426 * Initializes the application contexts and all channels for each one 00427 */ 00428 for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++) 00429 { 00430 int j; 00431 00432 /* 00433 * Initially set the context struct to zero 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 * Initially set the hcard structs to zero 00444 */ 00445 psContextMap[i].psChannelMap[j].hCard = 0; 00446 psContextMap[i].psChannelMap[j].readerName = NULL; 00447 } 00448 } 00449 00450 } 00451 00452 /* 00453 * Is there a free slot for this connection ? 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 /* Establishes a connection to the server */ 00468 if (SHMClientSetupSession(&dwClientID) != 0) 00469 { 00470 (void)SYS_CloseFile(mapAddr); 00471 return SCARD_E_NO_SERVICE; 00472 } 00473 00474 { /* exchange client/server protocol versions */ 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 * Read a message from the server 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 * Try to establish an Application Context with the server 00514 */ 00515 scEstablishStruct.dwScope = dwScope; 00516 scEstablishStruct.hContext = 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 * Read the response from the server 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 /* check we do not reuse an existing phContext */ 00540 if (-1 != SCardGetContextIndiceTH(scEstablishStruct.hContext)) 00541 /* we do not need to release the allocated context since 00542 * SCardReleaseContext() does nothing on the server side */ 00543 goto again; 00544 00545 *phContext = scEstablishStruct.hContext; 00546 00547 /* 00548 * Allocate the new hContext - if allocator full return an error 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 * Make sure this context has been opened 00587 * and get dwContextIndex 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 * Remove the local context from the stack 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 /* check the context is still opened */ 00609 dwContextIndex = SCardGetContextIndice(hContext); 00610 if (dwContextIndex == -1) 00611 /* the context is now invalid 00612 * -> another thread may have called SCardReleaseContext 00613 * -> so the mMutex has been unlocked */ 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 * Read a message from the server 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 * Remove the local context from the stack 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(/*@unused@*/ SCARDCONTEXT hContext, 00673 /*@unused@*/ DWORD dwTimeout) 00674 { 00675 /* 00676 * Deprecated 00677 */ 00678 (void)hContext; 00679 (void)dwTimeout; 00680 return SCARD_S_SUCCESS; 00681 } 00682 00734 LONG SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader, 00735 DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard, 00736 LPDWORD pdwActiveProtocol) 00737 { 00738 LONG rv; 00739 connect_struct scConnectStruct; 00740 sharedSegmentMsg msgStruct; 00741 LONG dwContextIndex; 00742 00743 PROFILE_START 00744 00745 /* 00746 * Check for NULL parameters 00747 */ 00748 if (phCard == NULL || pdwActiveProtocol == NULL) 00749 return SCARD_E_INVALID_PARAMETER; 00750 else 00751 *phCard = 0; 00752 00753 if (szReader == NULL) 00754 return SCARD_E_UNKNOWN_READER; 00755 00756 /* 00757 * Check for uninitialized strings 00758 */ 00759 if (strlen(szReader) > MAX_READERNAME) 00760 return SCARD_E_INVALID_VALUE; 00761 00762 rv = SCardCheckDaemonAvailability(); 00763 if (rv != SCARD_S_SUCCESS) 00764 return rv; 00765 00766 /* 00767 * Make sure this context has been opened 00768 */ 00769 dwContextIndex = SCardGetContextIndice(hContext); 00770 if (dwContextIndex == -1) 00771 return SCARD_E_INVALID_HANDLE; 00772 00773 (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex); 00774 00775 /* check the context is still opened */ 00776 dwContextIndex = SCardGetContextIndice(hContext); 00777 if (dwContextIndex == -1) 00778 /* the context is now invalid 00779 * -> another thread may have called SCardReleaseContext 00780 * -> so the mMutex has been unlocked */ 00781 return SCARD_E_INVALID_HANDLE; 00782 00783 strncpy(scConnectStruct.szReader, szReader, MAX_READERNAME); 00784 00785 scConnectStruct.hContext = hContext; 00786 scConnectStruct.dwShareMode = dwShareMode; 00787 scConnectStruct.dwPreferredProtocols = dwPreferredProtocols; 00788 scConnectStruct.hCard = 0; 00789 scConnectStruct.dwActiveProtocol = 0; 00790 scConnectStruct.rv = SCARD_S_SUCCESS; 00791 00792 rv = WrapSHMWrite(SCARD_CONNECT, psContextMap[dwContextIndex].dwClientID, 00793 sizeof(scConnectStruct), 00794 PCSCLITE_CLIENT_ATTEMPTS, (void *) &scConnectStruct); 00795 00796 if (rv == -1) 00797 { 00798 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 00799 return SCARD_E_NO_SERVICE; 00800 } 00801 00802 /* 00803 * Read a message from the server 00804 */ 00805 rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, 00806 PCSCLITE_CLIENT_ATTEMPTS); 00807 00808 memcpy(&scConnectStruct, &msgStruct.data, sizeof(scConnectStruct)); 00809 00810 if (rv == -1) 00811 { 00812 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 00813 return SCARD_F_COMM_ERROR; 00814 } 00815 00816 *phCard = scConnectStruct.hCard; 00817 *pdwActiveProtocol = scConnectStruct.dwActiveProtocol; 00818 00819 if (scConnectStruct.rv == SCARD_S_SUCCESS) 00820 { 00821 /* 00822 * Keep track of the handle locally 00823 */ 00824 rv = SCardAddHandle(*phCard, dwContextIndex, szReader); 00825 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 00826 00827 PROFILE_END(rv) 00828 00829 return rv; 00830 } 00831 00832 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 00833 00834 PROFILE_END(scConnectStruct.rv) 00835 00836 return scConnectStruct.rv; 00837 } 00838 00906 LONG SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode, 00907 DWORD dwPreferredProtocols, DWORD dwInitialization, 00908 LPDWORD pdwActiveProtocol) 00909 { 00910 LONG rv; 00911 reconnect_struct scReconnectStruct; 00912 sharedSegmentMsg msgStruct; 00913 int i; 00914 DWORD dwContextIndex, dwChannelIndex; 00915 00916 PROFILE_START 00917 00918 if (pdwActiveProtocol == NULL) 00919 return SCARD_E_INVALID_PARAMETER; 00920 00921 rv = SCardCheckDaemonAvailability(); 00922 if (rv != SCARD_S_SUCCESS) 00923 return rv; 00924 00925 /* 00926 * Make sure this handle has been opened 00927 */ 00928 rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex); 00929 if (rv == -1) 00930 return SCARD_E_INVALID_HANDLE; 00931 00932 (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex); 00933 00934 /* check the handle is still valid */ 00935 rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex); 00936 if (rv == -1) 00937 /* the handle is now invalid 00938 * -> another thread may have called SCardReleaseContext 00939 * -> so the mMutex has been unlocked */ 00940 return SCARD_E_INVALID_HANDLE; 00941 00942 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++) 00943 { 00944 char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName; 00945 00946 /* by default r == NULL */ 00947 if (r && strcmp(r, (readerStates[i])->readerName) == 0) 00948 break; 00949 } 00950 00951 if (i == PCSCLITE_MAX_READERS_CONTEXTS) 00952 { 00953 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 00954 return SCARD_E_READER_UNAVAILABLE; 00955 } 00956 00957 do 00958 { 00959 scReconnectStruct.hCard = hCard; 00960 scReconnectStruct.dwShareMode = dwShareMode; 00961 scReconnectStruct.dwPreferredProtocols = dwPreferredProtocols; 00962 scReconnectStruct.dwInitialization = dwInitialization; 00963 scReconnectStruct.dwActiveProtocol = *pdwActiveProtocol; 00964 scReconnectStruct.rv = SCARD_S_SUCCESS; 00965 00966 rv = WrapSHMWrite(SCARD_RECONNECT, psContextMap[dwContextIndex].dwClientID, 00967 sizeof(scReconnectStruct), 00968 PCSCLITE_CLIENT_ATTEMPTS, (void *) &scReconnectStruct); 00969 00970 if (rv == -1) 00971 { 00972 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 00973 return SCARD_E_NO_SERVICE; 00974 } 00975 00976 /* 00977 * Read a message from the server 00978 */ 00979 rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, 00980 PCSCLITE_CLIENT_ATTEMPTS); 00981 00982 memcpy(&scReconnectStruct, &msgStruct.data, sizeof(scReconnectStruct)); 00983 00984 if (rv == -1) 00985 { 00986 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 00987 return SCARD_F_COMM_ERROR; 00988 } 00989 } while (SCARD_E_SHARING_VIOLATION == scReconnectStruct.rv); 00990 00991 *pdwActiveProtocol = scReconnectStruct.dwActiveProtocol; 00992 00993 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 00994 00995 PROFILE_END(scReconnectStruct.rv) 00996 00997 return scReconnectStruct.rv; 00998 } 00999 01030 LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition) 01031 { 01032 LONG rv; 01033 disconnect_struct scDisconnectStruct; 01034 sharedSegmentMsg msgStruct; 01035 DWORD dwContextIndex, dwChannelIndex; 01036 01037 PROFILE_START 01038 01039 rv = SCardCheckDaemonAvailability(); 01040 if (rv != SCARD_S_SUCCESS) 01041 return rv; 01042 01043 /* 01044 * Make sure this handle has been opened 01045 */ 01046 rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex); 01047 if (rv == -1) 01048 return SCARD_E_INVALID_HANDLE; 01049 01050 (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex); 01051 01052 /* check the handle is still valid */ 01053 rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex); 01054 if (rv == -1) 01055 /* the handle is now invalid 01056 * -> another thread may have called SCardReleaseContext 01057 * -> so the mMutex has been unlocked */ 01058 return SCARD_E_INVALID_HANDLE; 01059 01060 scDisconnectStruct.hCard = hCard; 01061 scDisconnectStruct.dwDisposition = dwDisposition; 01062 scDisconnectStruct.rv = SCARD_S_SUCCESS; 01063 01064 rv = WrapSHMWrite(SCARD_DISCONNECT, psContextMap[dwContextIndex].dwClientID, 01065 sizeof(scDisconnectStruct), 01066 PCSCLITE_CLIENT_ATTEMPTS, (void *) &scDisconnectStruct); 01067 01068 if (rv == -1) 01069 { 01070 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 01071 return SCARD_E_NO_SERVICE; 01072 } 01073 01074 /* 01075 * Read a message from the server 01076 */ 01077 rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, 01078 PCSCLITE_CLIENT_ATTEMPTS); 01079 01080 memcpy(&scDisconnectStruct, &msgStruct.data, 01081 sizeof(scDisconnectStruct)); 01082 01083 if (rv == -1) 01084 { 01085 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 01086 return SCARD_F_COMM_ERROR; 01087 } 01088 01089 (void)SCardRemoveHandle(hCard); 01090 01091 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 01092 01093 PROFILE_END(scDisconnectStruct.rv) 01094 01095 return scDisconnectStruct.rv; 01096 } 01097 01133 LONG SCardBeginTransaction(SCARDHANDLE hCard) 01134 { 01135 01136 LONG rv; 01137 begin_struct scBeginStruct; 01138 int i; 01139 sharedSegmentMsg msgStruct; 01140 DWORD dwContextIndex, dwChannelIndex; 01141 01142 PROFILE_START 01143 01144 rv = SCardCheckDaemonAvailability(); 01145 if (rv != SCARD_S_SUCCESS) 01146 return rv; 01147 01148 /* 01149 * Make sure this handle has been opened 01150 */ 01151 rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex); 01152 if (rv == -1) 01153 return SCARD_E_INVALID_HANDLE; 01154 01155 (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex); 01156 01157 /* check the handle is still valid */ 01158 rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex); 01159 if (rv == -1) 01160 /* the handle is now invalid 01161 * -> another thread may have called SCardReleaseContext 01162 * -> so the mMutex has been unlocked */ 01163 return SCARD_E_INVALID_HANDLE; 01164 01165 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++) 01166 { 01167 char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName; 01168 01169 /* by default r == NULL */ 01170 if (r && strcmp(r, (readerStates[i])->readerName) == 0) 01171 break; 01172 } 01173 01174 if (i == PCSCLITE_MAX_READERS_CONTEXTS) 01175 { 01176 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 01177 return SCARD_E_READER_UNAVAILABLE; 01178 } 01179 01180 scBeginStruct.hCard = hCard; 01181 scBeginStruct.rv = SCARD_S_SUCCESS; 01182 01183 /* 01184 * Query the server every so often until the sharing violation ends 01185 * and then hold the lock for yourself. 01186 */ 01187 01188 do 01189 { 01190 rv = WrapSHMWrite(SCARD_BEGIN_TRANSACTION, psContextMap[dwContextIndex].dwClientID, 01191 sizeof(scBeginStruct), 01192 PCSCLITE_CLIENT_ATTEMPTS, (void *) &scBeginStruct); 01193 01194 if (rv == -1) 01195 { 01196 01197 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 01198 return SCARD_E_NO_SERVICE; 01199 } 01200 01201 /* 01202 * Read a message from the server 01203 */ 01204 rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, 01205 PCSCLITE_CLIENT_ATTEMPTS); 01206 01207 memcpy(&scBeginStruct, &msgStruct.data, sizeof(scBeginStruct)); 01208 01209 if (rv == -1) 01210 { 01211 01212 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 01213 return SCARD_F_COMM_ERROR; 01214 } 01215 01216 } 01217 while (scBeginStruct.rv == SCARD_E_SHARING_VIOLATION); 01218 01219 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 01220 01221 PROFILE_END(scBeginStruct.rv); 01222 01223 return scBeginStruct.rv; 01224 } 01225 01266 LONG SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition) 01267 { 01268 LONG rv; 01269 end_struct scEndStruct; 01270 sharedSegmentMsg msgStruct; 01271 int randnum, i; 01272 DWORD dwContextIndex, dwChannelIndex; 01273 01274 PROFILE_START 01275 01276 /* 01277 * Zero out everything 01278 */ 01279 randnum = 0; 01280 01281 rv = SCardCheckDaemonAvailability(); 01282 if (rv != SCARD_S_SUCCESS) 01283 return rv; 01284 01285 /* 01286 * Make sure this handle has been opened 01287 */ 01288 rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex); 01289 if (rv == -1) 01290 return SCARD_E_INVALID_HANDLE; 01291 01292 (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex); 01293 01294 /* check the handle is still valid */ 01295 rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex); 01296 if (rv == -1) 01297 /* the handle is now invalid 01298 * -> another thread may have called SCardReleaseContext 01299 * -> so the mMutex has been unlocked */ 01300 return SCARD_E_INVALID_HANDLE; 01301 01302 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++) 01303 { 01304 char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName; 01305 01306 /* by default r == NULL */ 01307 if (r && strcmp(r, (readerStates[i])->readerName) == 0) 01308 break; 01309 } 01310 01311 if (i == PCSCLITE_MAX_READERS_CONTEXTS) 01312 { 01313 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 01314 return SCARD_E_READER_UNAVAILABLE; 01315 } 01316 01317 scEndStruct.hCard = hCard; 01318 scEndStruct.dwDisposition = dwDisposition; 01319 scEndStruct.rv = SCARD_S_SUCCESS; 01320 01321 rv = WrapSHMWrite(SCARD_END_TRANSACTION, 01322 psContextMap[dwContextIndex].dwClientID, 01323 sizeof(scEndStruct), 01324 PCSCLITE_CLIENT_ATTEMPTS, (void *) &scEndStruct); 01325 01326 if (rv == -1) 01327 { 01328 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 01329 return SCARD_E_NO_SERVICE; 01330 } 01331 01332 /* 01333 * Read a message from the server 01334 */ 01335 rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, 01336 PCSCLITE_CLIENT_ATTEMPTS); 01337 01338 memcpy(&scEndStruct, &msgStruct.data, sizeof(scEndStruct)); 01339 01340 if (rv == -1) 01341 { 01342 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 01343 return SCARD_F_COMM_ERROR; 01344 } 01345 01346 /* 01347 * This helps prevent starvation 01348 */ 01349 randnum = SYS_RandomInt(1000, 10000); 01350 (void)SYS_USleep(randnum); 01351 01352 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 01353 01354 PROFILE_END(scEndStruct.rv) 01355 01356 return scEndStruct.rv; 01357 } 01358 01365 LONG SCardCancelTransaction(SCARDHANDLE hCard) 01366 { 01367 LONG rv; 01368 cancel_struct scCancelStruct; 01369 sharedSegmentMsg msgStruct; 01370 int i; 01371 DWORD dwContextIndex, dwChannelIndex; 01372 01373 PROFILE_START 01374 01375 rv = SCardCheckDaemonAvailability(); 01376 if (rv != SCARD_S_SUCCESS) 01377 return rv; 01378 01379 /* 01380 * Make sure this handle has been opened 01381 */ 01382 rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex); 01383 if (rv == -1) 01384 return SCARD_E_INVALID_HANDLE; 01385 01386 (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex); 01387 01388 /* check the handle is still valid */ 01389 rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex); 01390 if (rv == -1) 01391 /* the handle is now invalid 01392 * -> another thread may have called SCardReleaseContext 01393 * -> so the mMutex has been unlocked */ 01394 return SCARD_E_INVALID_HANDLE; 01395 01396 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++) 01397 { 01398 char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName; 01399 01400 /* by default r == NULL */ 01401 if (r && strcmp(r, (readerStates[i])->readerName) == 0) 01402 break; 01403 } 01404 01405 if (i == PCSCLITE_MAX_READERS_CONTEXTS) 01406 { 01407 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 01408 return SCARD_E_READER_UNAVAILABLE; 01409 } 01410 01411 scCancelStruct.hCard = hCard; 01412 01413 rv = WrapSHMWrite(SCARD_CANCEL_TRANSACTION, 01414 psContextMap[dwContextIndex].dwClientID, 01415 sizeof(scCancelStruct), 01416 PCSCLITE_CLIENT_ATTEMPTS, (void *) &scCancelStruct); 01417 01418 if (rv == -1) 01419 { 01420 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 01421 return SCARD_E_NO_SERVICE; 01422 } 01423 01424 /* 01425 * Read a message from the server 01426 */ 01427 rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, 01428 PCSCLITE_CLIENT_ATTEMPTS); 01429 01430 memcpy(&scCancelStruct, &msgStruct.data, sizeof(scCancelStruct)); 01431 01432 if (rv == -1) 01433 { 01434 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 01435 return SCARD_F_COMM_ERROR; 01436 } 01437 01438 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 01439 01440 PROFILE_END(scCancelStruct.rv) 01441 01442 return scCancelStruct.rv; 01443 } 01444 01532 LONG SCardStatus(SCARDHANDLE hCard, LPSTR mszReaderName, 01533 LPDWORD pcchReaderLen, LPDWORD pdwState, 01534 LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen) 01535 { 01536 DWORD dwReaderLen, dwAtrLen; 01537 LONG rv; 01538 int i; 01539 status_struct scStatusStruct; 01540 sharedSegmentMsg msgStruct; 01541 DWORD dwContextIndex, dwChannelIndex; 01542 char *r; 01543 char *bufReader = NULL; 01544 LPBYTE bufAtr = NULL; 01545 DWORD dummy; 01546 01547 PROFILE_START 01548 01549 /* default output values */ 01550 if (pdwState) 01551 *pdwState = 0; 01552 01553 if (pdwProtocol) 01554 *pdwProtocol = 0; 01555 01556 /* Check for NULL parameters */ 01557 if (pcchReaderLen == NULL) 01558 pcchReaderLen = &dummy; 01559 01560 if (pcbAtrLen == NULL) 01561 pcbAtrLen = &dummy; 01562 01563 /* length passed from caller */ 01564 dwReaderLen = *pcchReaderLen; 01565 dwAtrLen = *pcbAtrLen; 01566 01567 *pcchReaderLen = 0; 01568 *pcbAtrLen = 0; 01569 01570 rv = SCardCheckDaemonAvailability(); 01571 if (rv != SCARD_S_SUCCESS) 01572 return rv; 01573 01574 /* 01575 * Make sure this handle has been opened 01576 */ 01577 rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex); 01578 if (rv == -1) 01579 return SCARD_E_INVALID_HANDLE; 01580 01581 (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex); 01582 01583 /* check the handle is still valid */ 01584 rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex); 01585 if (rv == -1) 01586 /* the handle is now invalid 01587 * -> another thread may have called SCardReleaseContext 01588 * -> so the mMutex has been unlocked */ 01589 return SCARD_E_INVALID_HANDLE; 01590 01591 r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName; 01592 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++) 01593 { 01594 /* by default r == NULL */ 01595 if (r && strcmp(r, (readerStates[i])->readerName) == 0) 01596 break; 01597 } 01598 01599 if (i == PCSCLITE_MAX_READERS_CONTEXTS) 01600 { 01601 rv = SCARD_E_READER_UNAVAILABLE; 01602 goto end; 01603 } 01604 01605 /* initialise the structure */ 01606 memset(&scStatusStruct, 0, sizeof(scStatusStruct)); 01607 scStatusStruct.hCard = hCard; 01608 01609 /* those sizes need to be initialised */ 01610 scStatusStruct.pcchReaderLen = sizeof(scStatusStruct.mszReaderNames); 01611 scStatusStruct.pcbAtrLen = sizeof(scStatusStruct.pbAtr); 01612 01613 rv = WrapSHMWrite(SCARD_STATUS, psContextMap[dwContextIndex].dwClientID, 01614 sizeof(scStatusStruct), 01615 PCSCLITE_CLIENT_ATTEMPTS, (void *) &scStatusStruct); 01616 01617 if (rv == -1) 01618 { 01619 rv = SCARD_E_NO_SERVICE; 01620 goto end; 01621 } 01622 01623 /* 01624 * Read a message from the server 01625 */ 01626 rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, 01627 PCSCLITE_CLIENT_ATTEMPTS); 01628 01629 memcpy(&scStatusStruct, &msgStruct.data, sizeof(scStatusStruct)); 01630 01631 if (rv == -1) 01632 { 01633 rv = SCARD_F_COMM_ERROR; 01634 goto end; 01635 } 01636 01637 rv = scStatusStruct.rv; 01638 if (rv != SCARD_S_SUCCESS && rv != SCARD_E_INSUFFICIENT_BUFFER) 01639 { 01640 /* 01641 * An event must have occurred 01642 */ 01643 goto end; 01644 } 01645 01646 /* 01647 * Now continue with the client side SCardStatus 01648 */ 01649 01650 *pcchReaderLen = strlen(psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName) + 1; 01651 *pcbAtrLen = (readerStates[i])->cardAtrLength; 01652 01653 if (pdwState) 01654 *pdwState = (readerStates[i])->readerState; 01655 01656 if (pdwProtocol) 01657 *pdwProtocol = (readerStates[i])->cardProtocol; 01658 01659 if (SCARD_AUTOALLOCATE == dwReaderLen) 01660 { 01661 dwReaderLen = *pcchReaderLen; 01662 bufReader = malloc(dwReaderLen); 01663 if (NULL == bufReader) 01664 { 01665 rv = SCARD_E_NO_MEMORY; 01666 goto end; 01667 } 01668 if (NULL == mszReaderName) 01669 { 01670 rv = SCARD_E_INVALID_PARAMETER; 01671 goto end; 01672 } 01673 *(char **)mszReaderName = bufReader; 01674 } 01675 else 01676 bufReader = mszReaderName; 01677 01678 /* return SCARD_E_INSUFFICIENT_BUFFER only if buffer pointer is non NULL */ 01679 if (bufReader) 01680 { 01681 if (*pcchReaderLen > dwReaderLen) 01682 rv = SCARD_E_INSUFFICIENT_BUFFER; 01683 01684 strncpy(bufReader, 01685 psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName, 01686 dwReaderLen); 01687 } 01688 01689 if (SCARD_AUTOALLOCATE == dwAtrLen) 01690 { 01691 dwAtrLen = *pcbAtrLen; 01692 bufAtr = malloc(dwAtrLen); 01693 if (NULL == bufAtr) 01694 { 01695 rv = SCARD_E_NO_MEMORY; 01696 goto end; 01697 } 01698 if (NULL == pbAtr) 01699 { 01700 rv = SCARD_E_INVALID_PARAMETER; 01701 goto end; 01702 } 01703 *(LPBYTE *)pbAtr = bufAtr; 01704 } 01705 else 01706 bufAtr = pbAtr; 01707 01708 if (bufAtr) 01709 { 01710 if (*pcbAtrLen > dwAtrLen) 01711 rv = SCARD_E_INSUFFICIENT_BUFFER; 01712 01713 memcpy(bufAtr, (readerStates[i])->cardAtr, min(*pcbAtrLen, dwAtrLen)); 01714 } 01715 01716 end: 01717 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 01718 01719 PROFILE_END(rv) 01720 01721 return rv; 01722 } 01723 01724 static long WaitForPcscdEvent(SCARDCONTEXT hContext, long dwTime) 01725 { 01726 char filename[FILENAME_MAX]; 01727 char buf[1]; 01728 int fd, r; 01729 struct timeval tv, *ptv = NULL; 01730 struct timeval before, after; 01731 fd_set read_fd; 01732 01733 if (INFINITE != dwTime) 01734 { 01735 if (dwTime < 0) 01736 return 0; 01737 gettimeofday(&before, NULL); 01738 tv.tv_sec = dwTime/1000; 01739 tv.tv_usec = dwTime*1000 - tv.tv_sec*1000000; 01740 ptv = &tv; 01741 } 01742 01743 (void)snprintf(filename, sizeof(filename), "%s/event.%d.%ld", 01744 PCSCLITE_EVENTS_DIR, SYS_GetPID(), hContext); 01745 r = mkfifo(filename, 0644); 01746 if (-1 == r) 01747 { 01748 Log2(PCSC_LOG_CRITICAL, "Can't create event fifo: %s", strerror(errno)); 01749 goto exit; 01750 } 01751 01752 fd = SYS_OpenFile(filename, O_RDONLY | O_NONBLOCK, 0); 01753 01754 /* the file may have been removed between the mkfifo() and open() */ 01755 if (-1 != fd) 01756 { 01757 FD_ZERO(&read_fd); 01758 FD_SET(fd, &read_fd); 01759 01760 (void)select(fd+1, &read_fd, NULL, NULL, ptv); 01761 01762 (void)SYS_ReadFile(fd, buf, 1); 01763 (void)SYS_CloseFile(fd); 01764 } 01765 01766 (void)SYS_RemoveFile(filename); 01767 01768 if (INFINITE != dwTime) 01769 { 01770 long int diff; 01771 01772 gettimeofday(&after, NULL); 01773 diff = time_sub(&after, &before); 01774 dwTime -= diff/1000; 01775 } 01776 01777 exit: 01778 return dwTime; 01779 } 01780 01872 LONG SCardGetStatusChange(SCARDCONTEXT hContext, DWORD dwTimeout, 01873 LPSCARD_READERSTATE_A rgReaderStates, DWORD cReaders) 01874 { 01875 PSCARD_READERSTATE_A currReader; 01876 PREADER_STATE rContext; 01877 long dwTime = dwTimeout; 01878 DWORD dwState; 01879 DWORD dwBreakFlag = 0; 01880 int j; 01881 LONG dwContextIndex; 01882 int currentReaderCount = 0; 01883 LONG rv = SCARD_S_SUCCESS; 01884 01885 PROFILE_START 01886 01887 if ((rgReaderStates == NULL && cReaders > 0) 01888 || (cReaders > PCSCLITE_MAX_READERS_CONTEXTS)) 01889 return SCARD_E_INVALID_PARAMETER; 01890 01891 /* Check the integrity of the reader states structures */ 01892 for (j = 0; j < cReaders; j++) 01893 { 01894 if (rgReaderStates[j].szReader == NULL) 01895 return SCARD_E_INVALID_VALUE; 01896 } 01897 01898 /* return if all readers are SCARD_STATE_IGNORE */ 01899 if (cReaders > 0) 01900 { 01901 int nbNonIgnoredReaders = cReaders; 01902 01903 for (j=0; j<cReaders; j++) 01904 if (rgReaderStates[j].dwCurrentState & SCARD_STATE_IGNORE) 01905 nbNonIgnoredReaders--; 01906 01907 if (0 == nbNonIgnoredReaders) 01908 return SCARD_S_SUCCESS; 01909 } 01910 01911 rv = SCardCheckDaemonAvailability(); 01912 if (rv != SCARD_S_SUCCESS) 01913 return rv; 01914 01915 /* 01916 * Make sure this context has been opened 01917 */ 01918 dwContextIndex = SCardGetContextIndice(hContext); 01919 if (dwContextIndex == -1) 01920 return SCARD_E_INVALID_HANDLE; 01921 01922 (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex); 01923 01924 /* check the context is still opened */ 01925 dwContextIndex = SCardGetContextIndice(hContext); 01926 if (dwContextIndex == -1) 01927 /* the context is now invalid 01928 * -> another thread may have called SCardReleaseContext 01929 * -> so the mMutex has been unlocked */ 01930 return SCARD_E_INVALID_HANDLE; 01931 01932 /* 01933 * Application is waiting for a reader - return the first available 01934 * reader 01935 * This is DEPRECATED. Use the special reader name \\?PnP?\Notification 01936 * instead 01937 */ 01938 if (cReaders == 0) 01939 { 01940 while (1) 01941 { 01942 int i; 01943 01944 rv = SCardCheckDaemonAvailability(); 01945 if (rv != SCARD_S_SUCCESS) 01946 goto end; 01947 01948 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++) 01949 { 01950 if ((readerStates[i])->readerID != 0) 01951 { 01952 /* Reader was found */ 01953 rv = SCARD_S_SUCCESS; 01954 goto end; 01955 } 01956 } 01957 01958 if (dwTimeout == 0) 01959 { 01960 /* return immediately - no reader available */ 01961 rv = SCARD_E_READER_UNAVAILABLE; 01962 goto end; 01963 } 01964 01965 dwTime = WaitForPcscdEvent(hContext, dwTime); 01966 if (dwTimeout != INFINITE) 01967 { 01968 if (dwTime <= 0) 01969 { 01970 rv = SCARD_E_TIMEOUT; 01971 goto end; 01972 } 01973 } 01974 } 01975 } 01976 01977 /* 01978 * End of search for readers 01979 */ 01980 01981 /* Clear the event state for all readers */ 01982 for (j = 0; j < cReaders; j++) 01983 rgReaderStates[j].dwEventState = 0; 01984 01985 /* Now is where we start our event checking loop */ 01986 Log1(PCSC_LOG_DEBUG, "Event Loop Start"); 01987 01988 psContextMap[dwContextIndex].contextBlockStatus = BLOCK_STATUS_BLOCKING; 01989 01990 /* Get the initial reader count on the system */ 01991 for (j=0; j < PCSCLITE_MAX_READERS_CONTEXTS; j++) 01992 if ((readerStates[j])->readerID != 0) 01993 currentReaderCount++; 01994 01995 j = 0; 01996 do 01997 { 01998 rv = SCardCheckDaemonAvailability(); 01999 if (rv != SCARD_S_SUCCESS) 02000 { 02001 if (psContextMap[dwContextIndex].mMutex) 02002 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 02003 02004 PROFILE_END(rv) 02005 02006 return rv; 02007 } 02008 02009 currReader = &rgReaderStates[j]; 02010 02011 /* Ignore for IGNORED readers */ 02012 if (!(currReader->dwCurrentState & SCARD_STATE_IGNORE)) 02013 { 02014 LPSTR lpcReaderName; 02015 int i; 02016 02017 /************ Looks for correct readernames *********************/ 02018 02019 lpcReaderName = (char *) currReader->szReader; 02020 02021 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++) 02022 { 02023 if (strcmp(lpcReaderName, (readerStates[i])->readerName) == 0) 02024 break; 02025 } 02026 02027 /* The requested reader name is not recognized */ 02028 if (i == PCSCLITE_MAX_READERS_CONTEXTS) 02029 { 02030 /* PnP special reader? */ 02031 if (strcasecmp(lpcReaderName, "\\\\?PnP?\\Notification") == 0) 02032 { 02033 int k, newReaderCount = 0; 02034 02035 for (k=0; k < PCSCLITE_MAX_READERS_CONTEXTS; k++) 02036 if ((readerStates[k])->readerID != 0) 02037 newReaderCount++; 02038 02039 if (newReaderCount != currentReaderCount) 02040 { 02041 Log1(PCSC_LOG_INFO, "Reader list changed"); 02042 currentReaderCount = newReaderCount; 02043 02044 currReader->dwEventState |= SCARD_STATE_CHANGED; 02045 dwBreakFlag = 1; 02046 } 02047 } 02048 else 02049 { 02050 currReader->dwEventState = SCARD_STATE_UNKNOWN | SCARD_STATE_UNAVAILABLE; 02051 if (!(currReader->dwCurrentState & SCARD_STATE_UNKNOWN)) 02052 { 02053 currReader->dwEventState |= SCARD_STATE_CHANGED; 02054 /* 02055 * Spec says use SCARD_STATE_IGNORE but a removed USB 02056 * reader with eventState fed into currentState will 02057 * be ignored forever 02058 */ 02059 dwBreakFlag = 1; 02060 } 02061 } 02062 } 02063 else 02064 { 02065 /* The reader has come back after being away */ 02066 if (currReader->dwCurrentState & SCARD_STATE_UNKNOWN) 02067 { 02068 currReader->dwEventState |= SCARD_STATE_CHANGED; 02069 currReader->dwEventState &= ~SCARD_STATE_UNKNOWN; 02070 Log0(PCSC_LOG_DEBUG); 02071 dwBreakFlag = 1; 02072 } 02073 02074 /*****************************************************************/ 02075 02076 /* Set the reader status structure */ 02077 rContext = readerStates[i]; 02078 02079 /* Now we check all the Reader States */ 02080 dwState = rContext->readerState; 02081 02082 /* only if current state has an non null event counter */ 02083 if (currReader->dwCurrentState & 0xFFFF0000) 02084 { 02085 int currentCounter, stateCounter; 02086 02087 stateCounter = (dwState >> 16) & 0xFFFF; 02088 currentCounter = (currReader->dwCurrentState >> 16) & 0xFFFF; 02089 02090 /* has the event counter changed since the last call? */ 02091 if (stateCounter != currentCounter) 02092 { 02093 currReader->dwEventState |= SCARD_STATE_CHANGED; 02094 Log0(PCSC_LOG_DEBUG); 02095 dwBreakFlag = 1; 02096 } 02097 02098 /* add an event counter in the upper word of dwEventState */ 02099 currReader->dwEventState = 02100 ((currReader->dwEventState & 0xffff ) 02101 | (stateCounter << 16)); 02102 } 02103 02104 /*********** Check if the reader is in the correct state ********/ 02105 if (dwState & SCARD_UNKNOWN) 02106 { 02107 /* reader is in bad state */ 02108 currReader->dwEventState = SCARD_STATE_UNAVAILABLE; 02109 if (!(currReader->dwCurrentState & SCARD_STATE_UNAVAILABLE)) 02110 { 02111 /* App thinks reader is in good state and it is not */ 02112 currReader->dwEventState |= SCARD_STATE_CHANGED; 02113 Log0(PCSC_LOG_DEBUG); 02114 dwBreakFlag = 1; 02115 } 02116 } 02117 else 02118 { 02119 /* App thinks reader in bad state but it is not */ 02120 if (currReader-> dwCurrentState & SCARD_STATE_UNAVAILABLE) 02121 { 02122 currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE; 02123 currReader->dwEventState |= SCARD_STATE_CHANGED; 02124 Log0(PCSC_LOG_DEBUG); 02125 dwBreakFlag = 1; 02126 } 02127 } 02128 02129 /********** Check for card presence in the reader **************/ 02130 02131 if (dwState & SCARD_PRESENT) 02132 { 02133 /* card present but not yet powered up */ 02134 if (0 == rContext->cardAtrLength) 02135 /* Allow the status thread to convey information */ 02136 (void)SYS_USleep(PCSCLITE_STATUS_POLL_RATE + 10); 02137 02138 currReader->cbAtr = rContext->cardAtrLength; 02139 memcpy(currReader->rgbAtr, rContext->cardAtr, 02140 currReader->cbAtr); 02141 } 02142 else 02143 currReader->cbAtr = 0; 02144 02145 /* Card is now absent */ 02146 if (dwState & SCARD_ABSENT) 02147 { 02148 currReader->dwEventState |= SCARD_STATE_EMPTY; 02149 currReader->dwEventState &= ~SCARD_STATE_PRESENT; 02150 currReader->dwEventState &= ~SCARD_STATE_UNAWARE; 02151 currReader->dwEventState &= ~SCARD_STATE_IGNORE; 02152 currReader->dwEventState &= ~SCARD_STATE_UNKNOWN; 02153 currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE; 02154 currReader->dwEventState &= ~SCARD_STATE_ATRMATCH; 02155 currReader->dwEventState &= ~SCARD_STATE_MUTE; 02156 currReader->dwEventState &= ~SCARD_STATE_INUSE; 02157 02158 /* After present the rest are assumed */ 02159 if (currReader->dwCurrentState & SCARD_STATE_PRESENT) 02160 { 02161 currReader->dwEventState |= SCARD_STATE_CHANGED; 02162 Log0(PCSC_LOG_DEBUG); 02163 dwBreakFlag = 1; 02164 } 02165 } 02166 /* Card is now present */ 02167 else if (dwState & SCARD_PRESENT) 02168 { 02169 currReader->dwEventState |= SCARD_STATE_PRESENT; 02170 currReader->dwEventState &= ~SCARD_STATE_EMPTY; 02171 currReader->dwEventState &= ~SCARD_STATE_UNAWARE; 02172 currReader->dwEventState &= ~SCARD_STATE_IGNORE; 02173 currReader->dwEventState &= ~SCARD_STATE_UNKNOWN; 02174 currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE; 02175 currReader->dwEventState &= ~SCARD_STATE_MUTE; 02176 02177 if (currReader->dwCurrentState & SCARD_STATE_EMPTY) 02178 { 02179 currReader->dwEventState |= SCARD_STATE_CHANGED; 02180 Log0(PCSC_LOG_DEBUG); 02181 dwBreakFlag = 1; 02182 } 02183 02184 if (dwState & SCARD_SWALLOWED) 02185 { 02186 currReader->dwEventState |= SCARD_STATE_MUTE; 02187 if (!(currReader->dwCurrentState & SCARD_STATE_MUTE)) 02188 { 02189 currReader->dwEventState |= SCARD_STATE_CHANGED; 02190 Log0(PCSC_LOG_DEBUG); 02191 dwBreakFlag = 1; 02192 } 02193 } 02194 else 02195 { 02196 /* App thinks card is mute but it is not */ 02197 if (currReader->dwCurrentState & SCARD_STATE_MUTE) 02198 { 02199 currReader->dwEventState |= SCARD_STATE_CHANGED; 02200 Log0(PCSC_LOG_DEBUG); 02201 dwBreakFlag = 1; 02202 } 02203 } 02204 } 02205 02206 /* Now figure out sharing modes */ 02207 if (rContext->readerSharing == -1) 02208 { 02209 currReader->dwEventState |= SCARD_STATE_EXCLUSIVE; 02210 currReader->dwEventState &= ~SCARD_STATE_INUSE; 02211 if (currReader->dwCurrentState & SCARD_STATE_INUSE) 02212 { 02213 currReader->dwEventState |= SCARD_STATE_CHANGED; 02214 Log0(PCSC_LOG_DEBUG); 02215 dwBreakFlag = 1; 02216 } 02217 } 02218 else if (rContext->readerSharing >= 1) 02219 { 02220 /* A card must be inserted for it to be INUSE */ 02221 if (dwState & SCARD_PRESENT) 02222 { 02223 currReader->dwEventState |= SCARD_STATE_INUSE; 02224 currReader->dwEventState &= ~SCARD_STATE_EXCLUSIVE; 02225 if (currReader-> dwCurrentState & SCARD_STATE_EXCLUSIVE) 02226 { 02227 currReader->dwEventState |= SCARD_STATE_CHANGED; 02228 Log0(PCSC_LOG_DEBUG); 02229 dwBreakFlag = 1; 02230 } 02231 } 02232 } 02233 else if (rContext->readerSharing == 0) 02234 { 02235 currReader->dwEventState &= ~SCARD_STATE_INUSE; 02236 currReader->dwEventState &= ~SCARD_STATE_EXCLUSIVE; 02237 02238 if (currReader->dwCurrentState & SCARD_STATE_INUSE) 02239 { 02240 currReader->dwEventState |= SCARD_STATE_CHANGED; 02241 Log0(PCSC_LOG_DEBUG); 02242 dwBreakFlag = 1; 02243 } 02244 else if (currReader-> dwCurrentState 02245 & SCARD_STATE_EXCLUSIVE) 02246 { 02247 currReader->dwEventState |= SCARD_STATE_CHANGED; 02248 Log0(PCSC_LOG_DEBUG); 02249 dwBreakFlag = 1; 02250 } 02251 } 02252 02253 if (currReader->dwCurrentState == SCARD_STATE_UNAWARE) 02254 { 02255 /* 02256 * Break out of the while .. loop and return status 02257 * once all the status's for all readers is met 02258 */ 02259 currReader->dwEventState |= SCARD_STATE_CHANGED; 02260 Log0(PCSC_LOG_DEBUG); 02261 dwBreakFlag = 1; 02262 } 02263 } /* End of SCARD_STATE_UNKNOWN */ 02264 } /* End of SCARD_STATE_IGNORE */ 02265 02266 /* Counter and resetter */ 02267 j++; 02268 if (j == cReaders) 02269 { 02270 /* go back to the first reader */ 02271 j = 0; 02272 02273 /* Declare all the break conditions */ 02274 02275 /* Break if UNAWARE is set and all readers have been checked */ 02276 if (dwBreakFlag == 1) 02277 break; 02278 02279 if (BLOCK_STATUS_RESUME 02280 == psContextMap[dwContextIndex].contextBlockStatus) 02281 break; 02282 02283 /* Only sleep once for each cycle of reader checks. */ 02284 dwTime = WaitForPcscdEvent(hContext, dwTime); 02285 02286 if (dwTimeout != INFINITE) 02287 { 02288 /* If time is greater than timeout and all readers have been 02289 * checked 02290 */ 02291 if (dwTime <= 0) 02292 { 02293 rv = SCARD_E_TIMEOUT; 02294 goto end; 02295 } 02296 } 02297 } 02298 } 02299 while (1); 02300 02301 if (psContextMap[dwContextIndex].contextBlockStatus == BLOCK_STATUS_RESUME) 02302 rv = SCARD_E_CANCELLED; 02303 02304 end: 02305 Log1(PCSC_LOG_DEBUG, "Event Loop End"); 02306 02307 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 02308 02309 PROFILE_END(rv) 02310 02311 return rv; 02312 } 02313 02365 LONG SCardControl(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer, 02366 DWORD cbSendLength, LPVOID pbRecvBuffer, DWORD cbRecvLength, 02367 LPDWORD lpBytesReturned) 02368 { 02369 LONG rv; 02370 control_struct scControlStruct; 02371 sharedSegmentMsg msgStruct; 02372 int i; 02373 DWORD dwContextIndex, dwChannelIndex; 02374 02375 PROFILE_START 02376 02377 /* 0 bytes received by default */ 02378 if (NULL != lpBytesReturned) 02379 *lpBytesReturned = 0; 02380 02381 rv = SCardCheckDaemonAvailability(); 02382 if (rv != SCARD_S_SUCCESS) 02383 return rv; 02384 02385 /* 02386 * Make sure this handle has been opened 02387 */ 02388 rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex); 02389 if (rv == -1) 02390 return SCARD_E_INVALID_HANDLE; 02391 02392 (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex); 02393 02394 /* check the handle is still valid */ 02395 rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex); 02396 if (rv == -1) 02397 /* the handle is now invalid 02398 * -> another thread may have called SCardReleaseContext 02399 * -> so the mMutex has been unlocked */ 02400 return SCARD_E_INVALID_HANDLE; 02401 02402 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++) 02403 { 02404 char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName; 02405 02406 /* by default r == NULL */ 02407 if (r && strcmp(r, (readerStates[i])->readerName) == 0) 02408 break; 02409 } 02410 02411 if (i == PCSCLITE_MAX_READERS_CONTEXTS) 02412 { 02413 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 02414 return SCARD_E_READER_UNAVAILABLE; 02415 } 02416 02417 if ((cbSendLength > MAX_BUFFER_SIZE_EXTENDED) 02418 || (cbRecvLength > MAX_BUFFER_SIZE_EXTENDED)) 02419 { 02420 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 02421 return SCARD_E_INSUFFICIENT_BUFFER; 02422 } 02423 02424 if ((cbSendLength > MAX_BUFFER_SIZE) || (cbRecvLength > MAX_BUFFER_SIZE)) 02425 { 02426 /* extended control */ 02427 unsigned char buffer[sizeof(sharedSegmentMsg) + MAX_BUFFER_SIZE_EXTENDED]; 02428 control_struct_extended *scControlStructExtended = (control_struct_extended *)buffer; 02429 sharedSegmentMsg *pmsgStruct = (psharedSegmentMsg)buffer; 02430 02431 scControlStructExtended->hCard = hCard; 02432 scControlStructExtended->dwControlCode = dwControlCode; 02433 scControlStructExtended->cbSendLength = cbSendLength; 02434 scControlStructExtended->cbRecvLength = cbRecvLength; 02435 scControlStructExtended->dwBytesReturned = 0; 02436 scControlStructExtended->rv = SCARD_S_SUCCESS; 02437 /* The size of data to send is the size of 02438 * struct control_struct_extended WITHOUT the data[] field 02439 * plus the effective data[] size 02440 */ 02441 scControlStructExtended->size = sizeof(*scControlStructExtended) 02442 - (sizeof(control_struct_extended) - offsetof(control_struct_extended, data)) 02443 + cbSendLength; 02444 memcpy(scControlStructExtended->data, pbSendBuffer, cbSendLength); 02445 02446 rv = WrapSHMWrite(SCARD_CONTROL_EXTENDED, 02447 psContextMap[dwContextIndex].dwClientID, 02448 scControlStructExtended->size, 02449 PCSCLITE_CLIENT_ATTEMPTS, buffer); 02450 02451 if (rv == -1) 02452 { 02453 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 02454 return SCARD_E_NO_SERVICE; 02455 } 02456 02457 /* 02458 * Read a message from the server 02459 */ 02460 /* read the first block */ 02461 rv = SHMMessageReceive(buffer, sizeof(sharedSegmentMsg), 02462 psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS); 02463 if (rv == -1) 02464 { 02465 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 02466 return SCARD_F_COMM_ERROR; 02467 } 02468 02469 /* we receive a sharedSegmentMsg and not a control_struct_extended */ 02470 scControlStructExtended = (control_struct_extended *)&(pmsgStruct -> data); 02471 02472 /* a second block is present */ 02473 if (scControlStructExtended->size > PCSCLITE_MAX_MESSAGE_SIZE) 02474 { 02475 rv = SHMMessageReceive(buffer + sizeof(sharedSegmentMsg), 02476 scControlStructExtended->size-PCSCLITE_MAX_MESSAGE_SIZE, 02477 psContextMap[dwContextIndex].dwClientID, 02478 PCSCLITE_CLIENT_ATTEMPTS); 02479 if (rv == -1) 02480 { 02481 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 02482 return SCARD_F_COMM_ERROR; 02483 } 02484 } 02485 02486 if (scControlStructExtended -> rv == SCARD_S_SUCCESS) 02487 { 02488 /* 02489 * Copy and zero it so any secret information is not leaked 02490 */ 02491 memcpy(pbRecvBuffer, scControlStructExtended -> data, 02492 scControlStructExtended -> dwBytesReturned); 02493 memset(scControlStructExtended -> data, 0x00, 02494 scControlStructExtended -> dwBytesReturned); 02495 } 02496 02497 if (NULL != lpBytesReturned) 02498 *lpBytesReturned = scControlStructExtended -> dwBytesReturned; 02499 02500 rv = scControlStructExtended -> rv; 02501 } 02502 else 02503 { 02504 scControlStruct.hCard = hCard; 02505 scControlStruct.dwControlCode = dwControlCode; 02506 scControlStruct.cbSendLength = cbSendLength; 02507 scControlStruct.cbRecvLength = cbRecvLength; 02508 memcpy(scControlStruct.pbSendBuffer, pbSendBuffer, cbSendLength); 02509 02510 rv = WrapSHMWrite(SCARD_CONTROL, 02511 psContextMap[dwContextIndex].dwClientID, 02512 sizeof(scControlStruct), PCSCLITE_CLIENT_ATTEMPTS, &scControlStruct); 02513 02514 if (rv == -1) 02515 { 02516 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 02517 return SCARD_E_NO_SERVICE; 02518 } 02519 02520 /* 02521 * Read a message from the server 02522 */ 02523 rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, 02524 PCSCLITE_CLIENT_ATTEMPTS); 02525 02526 if (rv == -1) 02527 { 02528 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 02529 return SCARD_F_COMM_ERROR; 02530 } 02531 02532 memcpy(&scControlStruct, &msgStruct.data, sizeof(scControlStruct)); 02533 02534 if (NULL != lpBytesReturned) 02535 *lpBytesReturned = scControlStruct.dwBytesReturned; 02536 02537 if (scControlStruct.rv == SCARD_S_SUCCESS) 02538 { 02539 /* 02540 * Copy and zero it so any secret information is not leaked 02541 */ 02542 memcpy(pbRecvBuffer, scControlStruct.pbRecvBuffer, 02543 scControlStruct.cbRecvLength); 02544 memset(scControlStruct.pbRecvBuffer, 0x00, 02545 sizeof(scControlStruct.pbRecvBuffer)); 02546 } 02547 02548 rv = scControlStruct.rv; 02549 } 02550 02551 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 02552 02553 PROFILE_END(rv) 02554 02555 return rv; 02556 } 02557 02658 LONG SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr, 02659 LPDWORD pcbAttrLen) 02660 { 02661 LONG ret; 02662 unsigned char *buf = NULL; 02663 02664 PROFILE_START 02665 02666 if (NULL == pcbAttrLen) 02667 return SCARD_E_INVALID_PARAMETER; 02668 02669 if (SCARD_AUTOALLOCATE == *pcbAttrLen) 02670 { 02671 if (NULL == pbAttr) 02672 return SCARD_E_INVALID_PARAMETER; 02673 02674 *pcbAttrLen = MAX_BUFFER_SIZE; 02675 buf = malloc(*pcbAttrLen); 02676 if (NULL == buf) 02677 return SCARD_E_NO_MEMORY; 02678 02679 *(unsigned char **)pbAttr = buf; 02680 } 02681 else 02682 { 02683 buf = pbAttr; 02684 02685 /* if only get the length */ 02686 if (NULL == pbAttr) 02687 /* use a reasonable size */ 02688 *pcbAttrLen = MAX_BUFFER_SIZE; 02689 } 02690 02691 ret = SCardGetSetAttrib(hCard, SCARD_GET_ATTRIB, dwAttrId, buf, 02692 pcbAttrLen); 02693 02694 PROFILE_END(ret) 02695 02696 return ret; 02697 } 02698 02732 LONG SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr, 02733 DWORD cbAttrLen) 02734 { 02735 LONG ret; 02736 02737 PROFILE_START 02738 02739 if (NULL == pbAttr || 0 == cbAttrLen) 02740 return SCARD_E_INVALID_PARAMETER; 02741 02742 ret = SCardGetSetAttrib(hCard, SCARD_SET_ATTRIB, dwAttrId, (LPBYTE)pbAttr, 02743 &cbAttrLen); 02744 02745 PROFILE_END(ret) 02746 02747 return ret; 02748 } 02749 02750 static LONG SCardGetSetAttrib(SCARDHANDLE hCard, int command, DWORD dwAttrId, 02751 LPBYTE pbAttr, LPDWORD pcbAttrLen) 02752 { 02753 LONG rv; 02754 getset_struct scGetSetStruct; 02755 sharedSegmentMsg msgStruct; 02756 int i; 02757 DWORD dwContextIndex, dwChannelIndex; 02758 02759 rv = SCardCheckDaemonAvailability(); 02760 if (rv != SCARD_S_SUCCESS) 02761 return rv; 02762 02763 /* 02764 * Make sure this handle has been opened 02765 */ 02766 rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex); 02767 if (rv == -1) 02768 return SCARD_E_INVALID_HANDLE; 02769 02770 (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex); 02771 02772 /* check the handle is still valid */ 02773 rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex); 02774 if (rv == -1) 02775 /* the handle is now invalid 02776 * -> another thread may have called SCardReleaseContext 02777 * -> so the mMutex has been unlocked */ 02778 return SCARD_E_INVALID_HANDLE; 02779 02780 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++) 02781 { 02782 char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName; 02783 02784 /* by default r == NULL */ 02785 if (r && strcmp(r, (readerStates[i])->readerName) == 0) 02786 break; 02787 } 02788 02789 if (i == PCSCLITE_MAX_READERS_CONTEXTS) 02790 { 02791 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 02792 return SCARD_E_READER_UNAVAILABLE; 02793 } 02794 02795 if (*pcbAttrLen > MAX_BUFFER_SIZE) 02796 { 02797 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 02798 return SCARD_E_INSUFFICIENT_BUFFER; 02799 } 02800 02801 scGetSetStruct.hCard = hCard; 02802 scGetSetStruct.dwAttrId = dwAttrId; 02803 scGetSetStruct.cbAttrLen = *pcbAttrLen; 02804 scGetSetStruct.rv = SCARD_E_NO_SERVICE; 02805 memset(scGetSetStruct.pbAttr, 0, sizeof(scGetSetStruct.pbAttr)); 02806 if (SCARD_SET_ATTRIB == command) 02807 memcpy(scGetSetStruct.pbAttr, pbAttr, *pcbAttrLen); 02808 02809 rv = WrapSHMWrite(command, 02810 psContextMap[dwContextIndex].dwClientID, sizeof(scGetSetStruct), 02811 PCSCLITE_CLIENT_ATTEMPTS, &scGetSetStruct); 02812 02813 if (rv == -1) 02814 { 02815 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 02816 return SCARD_E_NO_SERVICE; 02817 } 02818 02819 /* 02820 * Read a message from the server 02821 */ 02822 rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, 02823 PCSCLITE_CLIENT_ATTEMPTS); 02824 02825 if (rv == -1) 02826 { 02827 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 02828 return SCARD_F_COMM_ERROR; 02829 } 02830 02831 memcpy(&scGetSetStruct, &msgStruct.data, sizeof(scGetSetStruct)); 02832 02833 if ((SCARD_S_SUCCESS == scGetSetStruct.rv) && (SCARD_GET_ATTRIB == command)) 02834 { 02835 /* 02836 * Copy and zero it so any secret information is not leaked 02837 */ 02838 if (*pcbAttrLen < scGetSetStruct.cbAttrLen) 02839 { 02840 scGetSetStruct.cbAttrLen = *pcbAttrLen; 02841 scGetSetStruct.rv = SCARD_E_INSUFFICIENT_BUFFER; 02842 } 02843 else 02844 *pcbAttrLen = scGetSetStruct.cbAttrLen; 02845 02846 if (pbAttr) 02847 memcpy(pbAttr, scGetSetStruct.pbAttr, scGetSetStruct.cbAttrLen); 02848 02849 memset(scGetSetStruct.pbAttr, 0x00, sizeof(scGetSetStruct.pbAttr)); 02850 } 02851 02852 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 02853 02854 return scGetSetStruct.rv; 02855 } 02856 02915 LONG SCardTransmit(SCARDHANDLE hCard, LPCSCARD_IO_REQUEST pioSendPci, 02916 LPCBYTE pbSendBuffer, DWORD cbSendLength, 02917 LPSCARD_IO_REQUEST pioRecvPci, LPBYTE pbRecvBuffer, 02918 LPDWORD pcbRecvLength) 02919 { 02920 LONG rv; 02921 int i; 02922 DWORD dwContextIndex, dwChannelIndex; 02923 02924 PROFILE_START 02925 02926 if (pbSendBuffer == NULL || pbRecvBuffer == NULL || 02927 pcbRecvLength == NULL || pioSendPci == NULL) 02928 return SCARD_E_INVALID_PARAMETER; 02929 02930 rv = SCardCheckDaemonAvailability(); 02931 if (rv != SCARD_S_SUCCESS) 02932 return rv; 02933 02934 /* 02935 * Make sure this handle has been opened 02936 */ 02937 rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex); 02938 if (rv == -1) 02939 { 02940 *pcbRecvLength = 0; 02941 return SCARD_E_INVALID_HANDLE; 02942 } 02943 02944 (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex); 02945 02946 /* check the handle is still valid */ 02947 rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex); 02948 if (rv == -1) 02949 /* the handle is now invalid 02950 * -> another thread may have called SCardReleaseContext 02951 * -> so the mMutex has been unlocked */ 02952 return SCARD_E_INVALID_HANDLE; 02953 02954 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++) 02955 { 02956 char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName; 02957 02958 /* by default r == NULL */ 02959 if (r && strcmp(r, (readerStates[i])->readerName) == 0) 02960 break; 02961 } 02962 02963 if (i == PCSCLITE_MAX_READERS_CONTEXTS) 02964 { 02965 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 02966 return SCARD_E_READER_UNAVAILABLE; 02967 } 02968 02969 if ((cbSendLength > MAX_BUFFER_SIZE_EXTENDED) 02970 || (*pcbRecvLength > MAX_BUFFER_SIZE_EXTENDED)) 02971 { 02972 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 02973 return SCARD_E_INSUFFICIENT_BUFFER; 02974 } 02975 02976 if ((cbSendLength > MAX_BUFFER_SIZE) || (*pcbRecvLength > MAX_BUFFER_SIZE)) 02977 { 02978 /* extended APDU */ 02979 unsigned char buffer[sizeof(sharedSegmentMsg) + MAX_BUFFER_SIZE_EXTENDED]; 02980 transmit_struct_extended *scTransmitStructExtended = (transmit_struct_extended *)buffer; 02981 sharedSegmentMsg *pmsgStruct = (psharedSegmentMsg)buffer; 02982 02983 scTransmitStructExtended->hCard = hCard; 02984 scTransmitStructExtended->cbSendLength = cbSendLength; 02985 scTransmitStructExtended->pcbRecvLength = *pcbRecvLength; 02986 /* The size of data to send is the size of 02987 * struct control_struct_extended WITHOUT the data[] field 02988 * plus the effective data[] size 02989 */ 02990 scTransmitStructExtended->size = sizeof(*scTransmitStructExtended) 02991 - (sizeof(transmit_struct_extended) - offsetof(transmit_struct_extended, data)) 02992 + cbSendLength; 02993 scTransmitStructExtended->ioSendPciProtocol = pioSendPci->dwProtocol; 02994 scTransmitStructExtended->ioSendPciLength = pioSendPci->cbPciLength; 02995 memcpy(scTransmitStructExtended->data, pbSendBuffer, cbSendLength); 02996 scTransmitStructExtended->rv = SCARD_S_SUCCESS; 02997 02998 if (pioRecvPci) 02999 { 03000 scTransmitStructExtended->ioRecvPciProtocol = pioRecvPci->dwProtocol; 03001 scTransmitStructExtended->ioRecvPciLength = pioRecvPci->cbPciLength; 03002 } 03003 else 03004 { 03005 scTransmitStructExtended->ioRecvPciProtocol = SCARD_PROTOCOL_ANY; 03006 scTransmitStructExtended->ioRecvPciLength = sizeof(SCARD_IO_REQUEST); 03007 } 03008 03009 rv = WrapSHMWrite(SCARD_TRANSMIT_EXTENDED, 03010 psContextMap[dwContextIndex].dwClientID, 03011 scTransmitStructExtended->size, 03012 PCSCLITE_CLIENT_ATTEMPTS, buffer); 03013 03014 if (rv == -1) 03015 { 03016 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 03017 return SCARD_E_NO_SERVICE; 03018 } 03019 03020 /* 03021 * Read a message from the server 03022 */ 03023 /* read the first block */ 03024 rv = SHMMessageReceive(buffer, sizeof(sharedSegmentMsg), psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS); 03025 if (rv == -1) 03026 { 03027 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 03028 return SCARD_F_COMM_ERROR; 03029 } 03030 03031 /* we receive a sharedSegmentMsg and not a transmit_struct_extended */ 03032 scTransmitStructExtended = (transmit_struct_extended *)&(pmsgStruct -> data); 03033 03034 /* a second block is present */ 03035 if (scTransmitStructExtended->size > PCSCLITE_MAX_MESSAGE_SIZE) 03036 { 03037 rv = SHMMessageReceive(buffer + sizeof(sharedSegmentMsg), 03038 scTransmitStructExtended->size-PCSCLITE_MAX_MESSAGE_SIZE, 03039 psContextMap[dwContextIndex].dwClientID, 03040 PCSCLITE_CLIENT_ATTEMPTS); 03041 if (rv == -1) 03042 { 03043 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 03044 return SCARD_F_COMM_ERROR; 03045 } 03046 } 03047 03048 if (scTransmitStructExtended -> rv == SCARD_S_SUCCESS) 03049 { 03050 /* 03051 * Copy and zero it so any secret information is not leaked 03052 */ 03053 memcpy(pbRecvBuffer, scTransmitStructExtended -> data, 03054 scTransmitStructExtended -> pcbRecvLength); 03055 memset(scTransmitStructExtended -> data, 0x00, 03056 scTransmitStructExtended -> pcbRecvLength); 03057 03058 if (pioRecvPci) 03059 { 03060 pioRecvPci->dwProtocol = scTransmitStructExtended->ioRecvPciProtocol; 03061 pioRecvPci->cbPciLength = scTransmitStructExtended->ioRecvPciLength; 03062 } 03063 } 03064 03065 *pcbRecvLength = scTransmitStructExtended -> pcbRecvLength; 03066 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 03067 03068 rv = scTransmitStructExtended -> rv; 03069 } 03070 else 03071 { 03072 /* short APDU */ 03073 transmit_struct scTransmitStruct; 03074 sharedSegmentMsg msgStruct; 03075 03076 scTransmitStruct.hCard = hCard; 03077 scTransmitStruct.cbSendLength = cbSendLength; 03078 scTransmitStruct.pcbRecvLength = *pcbRecvLength; 03079 scTransmitStruct.ioSendPciProtocol = pioSendPci->dwProtocol; 03080 scTransmitStruct.ioSendPciLength = pioSendPci->cbPciLength; 03081 memcpy(scTransmitStruct.pbSendBuffer, pbSendBuffer, cbSendLength); 03082 memset(scTransmitStruct.pbSendBuffer+cbSendLength, 0, sizeof(scTransmitStruct.pbSendBuffer)-cbSendLength); 03083 memset(scTransmitStruct.pbRecvBuffer, 0, sizeof(scTransmitStruct.pbRecvBuffer)); 03084 scTransmitStruct.rv = SCARD_S_SUCCESS; 03085 03086 if (pioRecvPci) 03087 { 03088 scTransmitStruct.ioRecvPciProtocol = pioRecvPci->dwProtocol; 03089 scTransmitStruct.ioRecvPciLength = pioRecvPci->cbPciLength; 03090 } 03091 else 03092 { 03093 scTransmitStruct.ioRecvPciProtocol = SCARD_PROTOCOL_ANY; 03094 scTransmitStruct.ioRecvPciLength = sizeof(SCARD_IO_REQUEST); 03095 } 03096 03097 rv = WrapSHMWrite(SCARD_TRANSMIT, 03098 psContextMap[dwContextIndex].dwClientID, sizeof(scTransmitStruct), 03099 PCSCLITE_CLIENT_ATTEMPTS, (void *) &scTransmitStruct); 03100 03101 if (rv == -1) 03102 { 03103 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 03104 return SCARD_E_NO_SERVICE; 03105 } 03106 03107 /* 03108 * Read a message from the server 03109 */ 03110 rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, 03111 PCSCLITE_CLIENT_ATTEMPTS); 03112 03113 memcpy(&scTransmitStruct, &msgStruct.data, sizeof(scTransmitStruct)); 03114 03115 if (rv == -1) 03116 { 03117 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 03118 return SCARD_F_COMM_ERROR; 03119 } 03120 03121 /* 03122 * Zero it and free it so any secret information cannot be leaked 03123 */ 03124 memset(scTransmitStruct.pbSendBuffer, 0x00, cbSendLength); 03125 03126 if (scTransmitStruct.rv == SCARD_S_SUCCESS) 03127 { 03128 /* 03129 * Copy and zero it so any secret information is not leaked 03130 */ 03131 memcpy(pbRecvBuffer, scTransmitStruct.pbRecvBuffer, 03132 scTransmitStruct.pcbRecvLength); 03133 memset(scTransmitStruct.pbRecvBuffer, 0x00, 03134 scTransmitStruct.pcbRecvLength); 03135 03136 if (pioRecvPci) 03137 { 03138 pioRecvPci->dwProtocol = scTransmitStruct.ioRecvPciProtocol; 03139 pioRecvPci->cbPciLength = scTransmitStruct.ioRecvPciLength; 03140 } 03141 } 03142 03143 *pcbRecvLength = scTransmitStruct.pcbRecvLength; 03144 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 03145 03146 rv = scTransmitStruct.rv; 03147 } 03148 03149 PROFILE_END(rv) 03150 03151 return rv; 03152 } 03153 03202 LONG SCardListReaders(SCARDCONTEXT hContext, /*@unused@*/ LPCSTR mszGroups, 03203 LPSTR mszReaders, LPDWORD pcchReaders) 03204 { 03205 DWORD dwReadersLen; 03206 int i; 03207 LONG dwContextIndex; 03208 LONG rv = SCARD_S_SUCCESS; 03209 char *buf = NULL; 03210 03211 (void)mszGroups; 03212 PROFILE_START 03213 03214 /* 03215 * Check for NULL parameters 03216 */ 03217 if (pcchReaders == NULL) 03218 return SCARD_E_INVALID_PARAMETER; 03219 03220 rv = SCardCheckDaemonAvailability(); 03221 if (rv != SCARD_S_SUCCESS) 03222 return rv; 03223 03224 /* 03225 * Make sure this context has been opened 03226 */ 03227 dwContextIndex = SCardGetContextIndice(hContext); 03228 if (dwContextIndex == -1) 03229 return SCARD_E_INVALID_HANDLE; 03230 03231 (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex); 03232 03233 /* check the context is still opened */ 03234 dwContextIndex = SCardGetContextIndice(hContext); 03235 if (dwContextIndex == -1) 03236 /* the context is now invalid 03237 * -> another thread may have called SCardReleaseContext 03238 * -> so the mMutex has been unlocked */ 03239 return SCARD_E_INVALID_HANDLE; 03240 03241 dwReadersLen = 0; 03242 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++) 03243 if ((readerStates[i])->readerID != 0) 03244 dwReadersLen += strlen((readerStates[i])->readerName) + 1; 03245 03246 /* for the last NULL byte */ 03247 dwReadersLen += 1; 03248 03249 if (1 == dwReadersLen) 03250 { 03251 rv = SCARD_E_NO_READERS_AVAILABLE; 03252 goto end; 03253 } 03254 03255 if (SCARD_AUTOALLOCATE == *pcchReaders) 03256 { 03257 buf = malloc(dwReadersLen); 03258 if (NULL == buf) 03259 { 03260 rv = SCARD_E_NO_MEMORY; 03261 goto end; 03262 } 03263 if (NULL == mszReaders) 03264 { 03265 rv = SCARD_E_INVALID_PARAMETER; 03266 goto end; 03267 } 03268 *(char **)mszReaders = buf; 03269 } 03270 else 03271 { 03272 buf = mszReaders; 03273 03274 /* not enough place to store the reader names */ 03275 if ((NULL != mszReaders) && (*pcchReaders < dwReadersLen)) 03276 { 03277 rv = SCARD_E_INSUFFICIENT_BUFFER; 03278 goto end; 03279 } 03280 } 03281 03282 if (mszReaders == NULL) /* text array not allocated */ 03283 goto end; 03284 03285 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++) 03286 { 03287 if ((readerStates[i])->readerID != 0) 03288 { 03289 /* 03290 * Build the multi-string 03291 */ 03292 strcpy(buf, (readerStates[i])->readerName); 03293 buf += strlen((readerStates[i])->readerName)+1; 03294 } 03295 } 03296 *buf = '\0'; /* Add the last null */ 03297 03298 end: 03299 /* set the reader names length */ 03300 *pcchReaders = dwReadersLen; 03301 03302 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 03303 03304 PROFILE_END(rv) 03305 03306 return rv; 03307 } 03308 03321 LONG SCardFreeMemory(SCARDCONTEXT hContext, LPCVOID pvMem) 03322 { 03323 LONG rv = SCARD_S_SUCCESS; 03324 LONG dwContextIndex; 03325 03326 PROFILE_START 03327 03328 rv = SCardCheckDaemonAvailability(); 03329 if (rv != SCARD_S_SUCCESS) 03330 return rv; 03331 03332 /* 03333 * Make sure this context has been opened 03334 */ 03335 dwContextIndex = SCardGetContextIndice(hContext); 03336 if (dwContextIndex == -1) 03337 return SCARD_E_INVALID_HANDLE; 03338 03339 free((void *)pvMem); 03340 03341 PROFILE_END(rv) 03342 03343 return rv; 03344 } 03345 03395 LONG SCardListReaderGroups(SCARDCONTEXT hContext, LPSTR mszGroups, 03396 LPDWORD pcchGroups) 03397 { 03398 LONG rv = SCARD_S_SUCCESS; 03399 LONG dwContextIndex; 03400 char *buf = NULL; 03401 03402 PROFILE_START 03403 03404 /* Multi-string with two trailing \0 */ 03405 const char ReaderGroup[] = "SCard$DefaultReaders\0"; 03406 const int dwGroups = sizeof(ReaderGroup); 03407 03408 rv = SCardCheckDaemonAvailability(); 03409 if (rv != SCARD_S_SUCCESS) 03410 return rv; 03411 03412 /* 03413 * Make sure this context has been opened 03414 */ 03415 dwContextIndex = SCardGetContextIndice(hContext); 03416 if (dwContextIndex == -1) 03417 return SCARD_E_INVALID_HANDLE; 03418 03419 (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex); 03420 03421 /* check the context is still opened */ 03422 dwContextIndex = SCardGetContextIndice(hContext); 03423 if (dwContextIndex == -1) 03424 /* the context is now invalid 03425 * -> another thread may have called SCardReleaseContext 03426 * -> so the mMutex has been unlocked */ 03427 return SCARD_E_INVALID_HANDLE; 03428 03429 if (SCARD_AUTOALLOCATE == *pcchGroups) 03430 { 03431 buf = malloc(dwGroups); 03432 if (NULL == buf) 03433 { 03434 rv = SCARD_E_NO_MEMORY; 03435 goto end; 03436 } 03437 if (NULL == mszGroups) 03438 { 03439 rv = SCARD_E_INVALID_PARAMETER; 03440 goto end; 03441 } 03442 *(char **)mszGroups = buf; 03443 } 03444 else 03445 { 03446 buf = mszGroups; 03447 03448 if ((NULL != mszGroups) && (*pcchGroups < dwGroups)) 03449 { 03450 rv = SCARD_E_INSUFFICIENT_BUFFER; 03451 goto end; 03452 } 03453 } 03454 03455 if (buf) 03456 memcpy(buf, ReaderGroup, dwGroups); 03457 03458 end: 03459 *pcchGroups = dwGroups; 03460 03461 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 03462 03463 PROFILE_END(rv) 03464 03465 return rv; 03466 } 03467 03495 LONG SCardCancel(SCARDCONTEXT hContext) 03496 { 03497 LONG dwContextIndex; 03498 LONG rv = SCARD_S_SUCCESS; 03499 03500 PROFILE_START 03501 03502 dwContextIndex = SCardGetContextIndice(hContext); 03503 if (dwContextIndex == -1) 03504 return SCARD_E_INVALID_HANDLE; 03505 03506 /* 03507 * Set the block status for this Context so blocking calls will 03508 * complete 03509 */ 03510 psContextMap[dwContextIndex].contextBlockStatus = BLOCK_STATUS_RESUME; 03511 03512 if (StatSynchronizeContext(hContext)) 03513 rv = SCARD_F_INTERNAL_ERROR; 03514 03515 PROFILE_END(rv) 03516 03517 return rv; 03518 } 03519 03543 LONG SCardIsValidContext(SCARDCONTEXT hContext) 03544 { 03545 LONG rv; 03546 LONG dwContextIndex; 03547 03548 PROFILE_START 03549 03550 rv = SCARD_S_SUCCESS; 03551 03552 /* Check if the _same_ server is running */ 03553 rv = SCardCheckDaemonAvailability(); 03554 if (rv != SCARD_S_SUCCESS) 03555 return rv; 03556 03557 /* 03558 * Make sure this context has been opened 03559 */ 03560 dwContextIndex = SCardGetContextIndice(hContext); 03561 if (dwContextIndex == -1) 03562 rv = SCARD_E_INVALID_HANDLE; 03563 03564 PROFILE_END(rv) 03565 03566 return rv; 03567 } 03568 03585 static LONG SCardAddContext(SCARDCONTEXT hContext, DWORD dwClientID) 03586 { 03587 int i; 03588 03589 for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++) 03590 { 03591 if (psContextMap[i].hContext == 0) 03592 { 03593 psContextMap[i].hContext = hContext; 03594 psContextMap[i].dwClientID = dwClientID; 03595 psContextMap[i].contextBlockStatus = BLOCK_STATUS_RESUME; 03596 psContextMap[i].mMutex = malloc(sizeof(PCSCLITE_MUTEX)); 03597 (void)SYS_MutexInit(psContextMap[i].mMutex); 03598 return SCARD_S_SUCCESS; 03599 } 03600 } 03601 03602 return SCARD_E_NO_MEMORY; 03603 } 03604 03617 static LONG SCardGetContextIndice(SCARDCONTEXT hContext) 03618 { 03619 LONG rv; 03620 03621 (void)SCardLockThread(); 03622 rv = SCardGetContextIndiceTH(hContext); 03623 (void)SCardUnlockThread(); 03624 03625 return rv; 03626 } 03627 03640 static LONG SCardGetContextIndiceTH(SCARDCONTEXT hContext) 03641 { 03642 int i; 03643 03644 /* 03645 * Find this context and return its spot in the array 03646 */ 03647 for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++) 03648 { 03649 if ((hContext == psContextMap[i].hContext) && (hContext != 0)) 03650 return i; 03651 } 03652 03653 return -1; 03654 } 03655 03665 static LONG SCardRemoveContext(SCARDCONTEXT hContext) 03666 { 03667 LONG retIndice; 03668 03669 retIndice = SCardGetContextIndiceTH(hContext); 03670 03671 if (retIndice == -1) 03672 return SCARD_E_INVALID_HANDLE; 03673 else 03674 return SCardCleanContext(retIndice); 03675 } 03676 03677 static LONG SCardCleanContext(LONG indice) 03678 { 03679 int i; 03680 03681 psContextMap[indice].hContext = 0; 03682 (void)SHMClientCloseSession(psContextMap[indice].dwClientID); 03683 psContextMap[indice].dwClientID = 0; 03684 free(psContextMap[indice].mMutex); 03685 psContextMap[indice].mMutex = NULL; 03686 psContextMap[indice].contextBlockStatus = BLOCK_STATUS_RESUME; 03687 03688 for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++) 03689 { 03690 /* 03691 * Reset the \c hCard structs to zero 03692 */ 03693 psContextMap[indice].psChannelMap[i].hCard = 0; 03694 free(psContextMap[indice].psChannelMap[i].readerName); 03695 psContextMap[indice].psChannelMap[i].readerName = NULL; 03696 } 03697 03698 return SCARD_S_SUCCESS; 03699 } 03700 03701 /* 03702 * Functions for managing hCard values returned from SCardConnect. 03703 */ 03704 03705 static LONG SCardAddHandle(SCARDHANDLE hCard, DWORD dwContextIndex, 03706 LPCSTR readerName) 03707 { 03708 int i; 03709 03710 for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++) 03711 { 03712 if (psContextMap[dwContextIndex].psChannelMap[i].hCard == 0) 03713 { 03714 psContextMap[dwContextIndex].psChannelMap[i].hCard = hCard; 03715 psContextMap[dwContextIndex].psChannelMap[i].readerName = strdup(readerName); 03716 return SCARD_S_SUCCESS; 03717 } 03718 } 03719 03720 return SCARD_E_NO_MEMORY; 03721 } 03722 03723 static LONG SCardRemoveHandle(SCARDHANDLE hCard) 03724 { 03725 DWORD dwContextIndice, dwChannelIndice; 03726 LONG rv; 03727 03728 rv = SCardGetIndicesFromHandle(hCard, &dwContextIndice, &dwChannelIndice); 03729 if (rv == -1) 03730 return SCARD_E_INVALID_HANDLE; 03731 else 03732 { 03733 psContextMap[dwContextIndice].psChannelMap[dwChannelIndice].hCard = 0; 03734 free(psContextMap[dwContextIndice].psChannelMap[dwChannelIndice].readerName); 03735 psContextMap[dwContextIndice].psChannelMap[dwChannelIndice].readerName = NULL; 03736 return SCARD_S_SUCCESS; 03737 } 03738 } 03739 03740 static LONG SCardGetIndicesFromHandle(SCARDHANDLE hCard, 03741 PDWORD pdwContextIndice, PDWORD pdwChannelIndice) 03742 { 03743 LONG rv; 03744 03745 if (0 == hCard) 03746 return -1; 03747 03748 (void)SCardLockThread(); 03749 rv = SCardGetIndicesFromHandleTH(hCard, pdwContextIndice, pdwChannelIndice); 03750 (void)SCardUnlockThread(); 03751 03752 return rv; 03753 } 03754 03755 static LONG SCardGetIndicesFromHandleTH(SCARDHANDLE hCard, 03756 PDWORD pdwContextIndice, PDWORD pdwChannelIndice) 03757 { 03758 int i; 03759 03760 for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++) 03761 { 03762 if (psContextMap[i].hContext != 0) 03763 { 03764 int j; 03765 03766 for (j = 0; j < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; j++) 03767 { 03768 if (psContextMap[i].psChannelMap[j].hCard == hCard) 03769 { 03770 *pdwContextIndice = i; 03771 *pdwChannelIndice = j; 03772 return SCARD_S_SUCCESS; 03773 } 03774 } 03775 03776 } 03777 } 03778 03779 return -1; 03780 } 03781 03790 LONG SCardCheckDaemonAvailability(void) 03791 { 03792 LONG rv; 03793 struct stat statBuffer; 03794 int need_restart = 0; 03795 03796 rv = SYS_Stat(PCSCLITE_PUBSHM_FILE, &statBuffer); 03797 03798 if (rv != 0) 03799 { 03800 Log2(PCSC_LOG_INFO, "PCSC Not Running: " PCSCLITE_PUBSHM_FILE ": %s", 03801 strerror(errno)); 03802 return SCARD_E_NO_SERVICE; 03803 } 03804 03805 /* when the _first_ reader is connected the ctime changes 03806 * I don't know why yet */ 03807 if (daemon_ctime && statBuffer.st_ctime > daemon_ctime) 03808 { 03809 /* so we also check the daemon pid to be sure it is a new pcscd */ 03810 if (GetDaemonPid() != daemon_pid) 03811 { 03812 Log1(PCSC_LOG_INFO, "PCSC restarted"); 03813 need_restart = 1; 03814 } 03815 } 03816 03817 /* after fork() need to restart */ 03818 if (client_pid && client_pid != getpid()) 03819 { 03820 Log1(PCSC_LOG_INFO, "Client forked"); 03821 need_restart = 1; 03822 } 03823 03824 if (need_restart) 03825 { 03826 int i; 03827 03828 /* invalid all handles */ 03829 (void)SCardLockThread(); 03830 03831 for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++) 03832 if (psContextMap[i].hContext) 03833 (void)SCardCleanContext(i); 03834 03835 (void)SCardUnlockThread(); 03836 03837 /* reset pcscd status */ 03838 daemon_ctime = 0; 03839 client_pid = 0; 03840 03841 /* reset the lib */ 03842 SCardUnload(); 03843 03844 return SCARD_E_INVALID_HANDLE; 03845 } 03846 03847 daemon_ctime = statBuffer.st_ctime; 03848 daemon_pid = GetDaemonPid(); 03849 client_pid = getpid(); 03850 03851 return SCARD_S_SUCCESS; 03852 } 03853 03860 #ifdef __SUNPRO_C 03861 #pragma fini (SCardUnload) 03862 #endif 03863 03864 void DESTRUCTOR SCardUnload(void) 03865 { 03866 int i; 03867 03868 if (!isExecuted) 03869 return; 03870 03871 /* unmap public shared file from memory */ 03872 for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++) 03873 { 03874 if (readerStates[i] != NULL) 03875 { 03876 SYS_PublicMemoryUnmap(readerStates[i], sizeof(READER_STATE)); 03877 readerStates[i] = NULL; 03878 } 03879 } 03880 03881 (void)SYS_CloseFile(mapAddr); 03882 isExecuted = 0; 03883 } 03884