winscard_clnt.c

Go to the documentation of this file.
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 2319 2007-01-09 15:27:56Z rousseau $
00010  */
00011 
00020 #include "config.h"
00021 #include <stdlib.h>
00022 #include <string.h>
00023 #include <sys/types.h>
00024 #include <fcntl.h>
00025 #include <unistd.h>
00026 #include <sys/un.h>
00027 #include <errno.h>
00028 
00029 #include "misc.h"
00030 #include "pcsclite.h"
00031 #include "winscard.h"
00032 #include "debug.h"
00033 #include "thread_generic.h"
00034 
00035 #include "readerfactory.h"
00036 #include "eventhandler.h"
00037 #include "sys_generic.h"
00038 #include "winscard_msg.h"
00039 
00041 #define SCARD_PROTOCOL_ANY_OLD  0x1000
00042 
00043 #ifndef min
00044 #define min(a,b) (((a) < (b)) ? (a) : (b))
00045 #endif
00046 
00047 #ifndef TRUE
00048 #define TRUE 1
00049 #define FALSE 0
00050 #endif
00051 
00052 #undef DO_PROFILE
00053 #ifdef DO_PROFILE
00054 
00055 #define PROFILE_FILE "/tmp/pcsc_profile"
00056 #include <stdio.h>
00057 #include <sys/time.h>
00058 
00059 struct timeval profile_time_start;
00060 FILE *fd;
00061 char profile_tty;
00062 
00063 #define PROFILE_START profile_start(__FUNCTION__);
00064 #define PROFILE_END profile_end(__FUNCTION__);
00065 
00066 static void profile_start(const char *f)
00067 {
00068     static char initialized = FALSE;
00069 
00070     if (!initialized)
00071     {
00072         initialized = TRUE;
00073         fd = fopen(PROFILE_FILE, "a+");
00074         if (NULL == fd)
00075         {
00076             fprintf(stderr, "\33[01;31mCan't open %s: %s\33[0m\n",
00077                 PROFILE_FILE, strerror(errno));
00078             exit(-1);
00079         }
00080         fprintf(fd, "\nStart a new profile\n");
00081 
00082         if (isatty(fileno(stderr)))
00083             profile_tty = TRUE;
00084         else
00085             profile_tty = FALSE;
00086     }
00087 
00088     gettimeofday(&profile_time_start, NULL);
00089 } /* profile_start */
00090 
00091 /* r = a - b */
00092 static long int time_sub(struct timeval *a, struct timeval *b)
00093 {
00094     struct timeval r;
00095     r.tv_sec = a -> tv_sec - b -> tv_sec;
00096     r.tv_usec = a -> tv_usec - b -> tv_usec;
00097     if (r.tv_usec < 0)
00098     {
00099         r.tv_sec--;
00100         r.tv_usec += 1000000;
00101     }
00102 
00103     return r.tv_sec * 1000000 + r.tv_usec;
00104 } /* time_sub */
00105 
00106 
00107 static void profile_end(const char *f)
00108 {
00109     struct timeval profile_time_end;
00110     long d;
00111 
00112     gettimeofday(&profile_time_end, NULL);
00113     d = time_sub(&profile_time_end, &profile_time_start);
00114 
00115     if (profile_tty)
00116         fprintf(stderr, "\33[01;31mRESULT %s \33[35m%ld\33[0m\n", f, d);
00117     fprintf(fd, "%s %ld\n", f, d);
00118 } /* profile_end */
00119 
00120 #else
00121 #define PROFILE_START
00122 #define PROFILE_END
00123 #endif
00124 
00129 struct _psChannelMap
00130 {
00131     SCARDHANDLE hCard;
00132     LPSTR readerName;
00133 };
00134 
00135 typedef struct _psChannelMap CHANNEL_MAP, *PCHANNEL_MAP;
00136 
00142 static struct _psContextMap
00143 {
00144     DWORD dwClientID;               
00145     SCARDCONTEXT hContext;          
00146     DWORD contextBlockStatus;
00147     PCSCLITE_MUTEX_T mMutex;        
00148     CHANNEL_MAP psChannelMap[PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS];
00149 } psContextMap[PCSCLITE_MAX_APPLICATION_CONTEXTS];
00150 
00154 static short isExecuted = 0;
00155 
00161 static int mapAddr = 0;
00162 
00167 static PCSCLITE_MUTEX clientMutex = PTHREAD_MUTEX_INITIALIZER;
00168 
00175 static PREADER_STATE readerStates[PCSCLITE_MAX_READERS_CONTEXTS];
00176 
00177 PCSC_API SCARD_IO_REQUEST g_rgSCardT0Pci = { SCARD_PROTOCOL_T0, 8 };
00178 PCSC_API SCARD_IO_REQUEST g_rgSCardT1Pci = { SCARD_PROTOCOL_T1, 8 };
00179 PCSC_API SCARD_IO_REQUEST g_rgSCardRawPci = { SCARD_PROTOCOL_RAW, 8 };
00180 
00181 
00182 static LONG SCardAddContext(SCARDCONTEXT, DWORD);
00183 static LONG SCardGetContextIndice(SCARDCONTEXT);
00184 static LONG SCardGetContextIndiceTH(SCARDCONTEXT);
00185 static LONG SCardRemoveContext(SCARDCONTEXT);
00186 
00187 static LONG SCardAddHandle(SCARDHANDLE, DWORD, LPSTR);
00188 static LONG SCardGetIndicesFromHandle(SCARDHANDLE, PDWORD, PDWORD);
00189 static LONG SCardGetIndicesFromHandleTH(SCARDHANDLE, PDWORD, PDWORD);
00190 static LONG SCardRemoveHandle(SCARDHANDLE);
00191 
00192 static LONG SCardGetSetAttrib(SCARDHANDLE hCard, int command, DWORD dwAttrId,
00193     LPBYTE pbAttr, LPDWORD pcbAttrLen);
00194 
00195 static LONG SCardCheckDaemonAvailability(void);
00196 
00197 /*
00198  * Thread safety functions
00199  */
00200 inline static LONG SCardLockThread(void);
00201 inline static LONG SCardUnlockThread(void);
00202 
00203 static LONG SCardEstablishContextTH(DWORD, LPCVOID, LPCVOID, LPSCARDCONTEXT);
00204 
00237 LONG SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1,
00238     LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
00239 {
00240     LONG rv;
00241 
00242     PROFILE_START
00243 
00244     SCardLockThread();
00245     rv = SCardEstablishContextTH(dwScope, pvReserved1,
00246         pvReserved2, phContext);
00247     SCardUnlockThread();
00248 
00249     PROFILE_END
00250 
00251     return rv;
00252 }
00253 
00279 static LONG SCardEstablishContextTH(DWORD dwScope, LPCVOID pvReserved1,
00280     LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
00281 {
00282     LONG rv;
00283     int i;
00284     establish_struct scEstablishStruct;
00285     sharedSegmentMsg msgStruct;
00286     DWORD dwClientID = 0;
00287 
00288     if (phContext == NULL)
00289         return SCARD_E_INVALID_PARAMETER;
00290     else
00291         *phContext = 0;
00292 
00293     /* Check if the server is running */
00294     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
00295         return SCARD_E_NO_SERVICE;
00296 
00297     /*
00298      * Do this only once:
00299      * - Initialize debug of need.
00300      * - Set up the memory mapped structures for reader states.
00301      * - Allocate each reader structure.
00302      * - Initialize context struct.
00303      */
00304     if (isExecuted == 0)
00305     {
00306         int pageSize;
00307 
00308         /*
00309          * Do any system initilization here
00310          */
00311         SYS_Initialize();
00312 
00313         /*
00314          * Set up the memory mapped reader stats structures
00315          */
00316         mapAddr = SYS_OpenFile(PCSCLITE_PUBSHM_FILE, O_RDONLY, 0);
00317         if (mapAddr < 0)
00318         {
00319             Log2(PCSC_LOG_CRITICAL, "Cannot open public shared file: %s",
00320                 PCSCLITE_PUBSHM_FILE);
00321             return SCARD_E_NO_SERVICE;
00322         }
00323 
00324         pageSize = SYS_GetPageSize();
00325 
00326         /*
00327          * Allocate each reader structure in the memory map
00328          */
00329         for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
00330         {
00331             readerStates[i] =
00332                 (PREADER_STATE)SYS_PublicMemoryMap(sizeof(READER_STATE),
00333                 mapAddr, (i * pageSize));
00334             if (readerStates[i] == NULL)
00335             {
00336                 Log1(PCSC_LOG_CRITICAL, "Cannot public memory map");
00337                 SYS_CloseFile(mapAddr); /* Close the memory map file */
00338                 return SCARD_F_INTERNAL_ERROR;
00339             }
00340         }
00341 
00342         /*
00343          * Initializes the application contexts and all channels for each one
00344          */
00345         for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
00346         {
00347             int j;
00348 
00349             /*
00350              * Initially set the context struct to zero
00351              */
00352             psContextMap[i].dwClientID = 0;
00353             psContextMap[i].hContext = 0;
00354             psContextMap[i].contextBlockStatus = BLOCK_STATUS_RESUME;
00355             psContextMap[i].mMutex = NULL;
00356 
00357             for (j = 0; j < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; j++)
00358             {
00359                 /*
00360                  * Initially set the hcard structs to zero
00361                  */
00362                 psContextMap[i].psChannelMap[j].hCard = 0;
00363                 psContextMap[i].psChannelMap[j].readerName = NULL;
00364             }
00365         }
00366 
00367     }
00368 
00369     /*
00370      * Is there a free slot for this connection ?
00371      */
00372 
00373     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
00374     {
00375         if (psContextMap[i].dwClientID == 0)
00376             break;
00377     }
00378 
00379     if (i == PCSCLITE_MAX_APPLICATION_CONTEXTS)
00380     {
00381         return SCARD_E_NO_MEMORY;
00382     }
00383 
00384     /* Establishes a connection to the server */
00385     if (SHMClientSetupSession(&dwClientID) != 0)
00386     {
00387         SYS_CloseFile(mapAddr);
00388         return SCARD_E_NO_SERVICE;
00389     }
00390 
00391     {   /* exchange client/server protocol versions */
00392         sharedSegmentMsg msgStruct;
00393         version_struct *veStr;
00394 
00395         memset(&msgStruct, 0, sizeof(msgStruct));
00396         msgStruct.mtype = CMD_VERSION;
00397         msgStruct.user_id = SYS_GetUID();
00398         msgStruct.group_id = SYS_GetGID();
00399         msgStruct.command = 0;
00400         msgStruct.date = time(NULL);
00401 
00402         veStr = (version_struct *) msgStruct.data;
00403         veStr->major = PROTOCOL_VERSION_MAJOR;
00404         veStr->minor = PROTOCOL_VERSION_MINOR;
00405 
00406         if (-1 == SHMMessageSend(&msgStruct, sizeof(msgStruct), dwClientID,
00407             PCSCLITE_MCLIENT_ATTEMPTS))
00408             return SCARD_E_NO_SERVICE;
00409 
00410         /*
00411          * Read a message from the server
00412          */
00413         if (-1 == SHMMessageReceive(&msgStruct, sizeof(msgStruct), dwClientID,
00414             PCSCLITE_CLIENT_ATTEMPTS))
00415         {
00416             Log1(PCSC_LOG_CRITICAL, "Your pcscd is too old and does not support CMD_VERSION");
00417             return SCARD_F_COMM_ERROR;
00418         }
00419 
00420         Log3(PCSC_LOG_INFO, "Server is protocol version %d:%d",
00421             veStr->major, veStr->minor);
00422 
00423         if (veStr->rv != SCARD_S_SUCCESS)
00424             return veStr->rv;
00425 
00426         isExecuted = 1;
00427     }
00428 
00429 
00430     if (dwScope != SCARD_SCOPE_USER && dwScope != SCARD_SCOPE_TERMINAL &&
00431         dwScope != SCARD_SCOPE_SYSTEM && dwScope != SCARD_SCOPE_GLOBAL)
00432     {
00433         return SCARD_E_INVALID_VALUE;
00434     }
00435 
00436     /*
00437      * Try to establish an Application Context with the server
00438      */
00439     scEstablishStruct.dwScope = dwScope;
00440     scEstablishStruct.phContext = 0;
00441     scEstablishStruct.rv = 0;
00442 
00443     rv = WrapSHMWrite(SCARD_ESTABLISH_CONTEXT, dwClientID,
00444         sizeof(scEstablishStruct), PCSCLITE_MCLIENT_ATTEMPTS,
00445         (void *) &scEstablishStruct);
00446 
00447     if (rv == -1)
00448         return SCARD_E_NO_SERVICE;
00449 
00450     /*
00451      * Read the response from the server
00452      */
00453     rv = SHMClientRead(&msgStruct, dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
00454 
00455     if (rv == -1)
00456         return SCARD_F_COMM_ERROR;
00457 
00458     memcpy(&scEstablishStruct, &msgStruct.data, sizeof(scEstablishStruct));
00459 
00460     if (scEstablishStruct.rv != SCARD_S_SUCCESS)
00461         return scEstablishStruct.rv;
00462 
00463     *phContext = scEstablishStruct.phContext;
00464 
00465     /*
00466      * Allocate the new hContext - if allocator full return an error
00467      */
00468     rv = SCardAddContext(*phContext, dwClientID);
00469 
00470     return rv;
00471 }
00472 
00491 LONG SCardReleaseContext(SCARDCONTEXT hContext)
00492 {
00493     LONG rv;
00494     release_struct scReleaseStruct;
00495     sharedSegmentMsg msgStruct;
00496     LONG dwContextIndex;
00497 
00498     PROFILE_START
00499 
00500     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
00501         return SCARD_E_NO_SERVICE;
00502 
00503     /*
00504      * Make sure this context has been opened
00505      */
00506     dwContextIndex = SCardGetContextIndice(hContext);
00507     if (dwContextIndex == -1)
00508         return SCARD_E_INVALID_HANDLE;
00509 
00510     SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
00511 
00512     scReleaseStruct.hContext = hContext;
00513     scReleaseStruct.rv = 0;
00514 
00515     rv = WrapSHMWrite(SCARD_RELEASE_CONTEXT, psContextMap[dwContextIndex].dwClientID,
00516               sizeof(scReleaseStruct),
00517               PCSCLITE_MCLIENT_ATTEMPTS, (void *) &scReleaseStruct);
00518 
00519     if (rv == -1)
00520     {
00521         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00522         return SCARD_E_NO_SERVICE;
00523     }
00524 
00525     /*
00526      * Read a message from the server
00527      */
00528     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
00529     memcpy(&scReleaseStruct, &msgStruct.data, sizeof(scReleaseStruct));
00530 
00531     if (rv == -1)
00532     {
00533         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00534         return SCARD_F_COMM_ERROR;
00535     }
00536 
00537     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00538 
00539     /*
00540      * Remove the local context from the stack
00541      */
00542     SCardLockThread();
00543     SCardRemoveContext(hContext);
00544     SCardUnlockThread();
00545 
00546     PROFILE_END
00547 
00548     return scReleaseStruct.rv;
00549 }
00550 
00563 LONG SCardSetTimeout(SCARDCONTEXT hContext, DWORD dwTimeout)
00564 {
00565     /*
00566      * Deprecated
00567      */
00568 
00569     return SCARD_S_SUCCESS;
00570 }
00571 
00622 LONG SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader,
00623     DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard,
00624     LPDWORD pdwActiveProtocol)
00625 {
00626     LONG rv;
00627     connect_struct scConnectStruct;
00628     sharedSegmentMsg msgStruct;
00629     LONG dwContextIndex;
00630 
00631     PROFILE_START
00632 
00633     /*
00634      * Check for NULL parameters
00635      */
00636     if (phCard == NULL || pdwActiveProtocol == NULL)
00637         return SCARD_E_INVALID_PARAMETER;
00638     else
00639         *phCard = 0;
00640 
00641     if (szReader == NULL)
00642         return SCARD_E_UNKNOWN_READER;
00643 
00644     /*
00645      * Check for uninitialized strings
00646      */
00647     if (strlen(szReader) > MAX_READERNAME)
00648         return SCARD_E_INVALID_VALUE;
00649 
00650     if (!(dwPreferredProtocols & SCARD_PROTOCOL_T0) &&
00651         !(dwPreferredProtocols & SCARD_PROTOCOL_T1) &&
00652         !(dwPreferredProtocols & SCARD_PROTOCOL_RAW) &&
00653         !(dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD))
00654     {
00655         return SCARD_E_INVALID_VALUE;
00656     }
00657 
00658     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
00659         return SCARD_E_NO_SERVICE;
00660 
00661     /*
00662      * Make sure this context has been opened
00663      */
00664     dwContextIndex = SCardGetContextIndice(hContext);
00665     if (dwContextIndex == -1)
00666         return SCARD_E_INVALID_HANDLE;
00667 
00668     SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
00669 
00670     strncpy(scConnectStruct.szReader, szReader, MAX_READERNAME);
00671 
00672     scConnectStruct.hContext = hContext;
00673     scConnectStruct.dwShareMode = dwShareMode;
00674     scConnectStruct.dwPreferredProtocols = dwPreferredProtocols;
00675     scConnectStruct.phCard = *phCard;
00676     scConnectStruct.pdwActiveProtocol = *pdwActiveProtocol;
00677 
00678     rv = WrapSHMWrite(SCARD_CONNECT, psContextMap[dwContextIndex].dwClientID,
00679         sizeof(scConnectStruct),
00680         PCSCLITE_CLIENT_ATTEMPTS, (void *) &scConnectStruct);
00681 
00682     if (rv == -1)
00683     {
00684         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00685         return SCARD_E_NO_SERVICE;
00686     }
00687 
00688     /*
00689      * Read a message from the server
00690      */
00691     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
00692 
00693     memcpy(&scConnectStruct, &msgStruct.data, sizeof(scConnectStruct));
00694 
00695     if (rv == -1)
00696     {
00697         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00698         return SCARD_F_COMM_ERROR;
00699     }
00700 
00701     *phCard = scConnectStruct.phCard;
00702     *pdwActiveProtocol = scConnectStruct.pdwActiveProtocol;
00703 
00704     if (scConnectStruct.rv == SCARD_S_SUCCESS)
00705     {
00706         /*
00707          * Keep track of the handle locally
00708          */
00709         rv = SCardAddHandle(*phCard, dwContextIndex, (LPSTR) szReader);
00710         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00711 
00712         PROFILE_END
00713 
00714         return rv;
00715     }
00716 
00717     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00718 
00719     PROFILE_END
00720 
00721     return scConnectStruct.rv;
00722 }
00723 
00791 LONG SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode,
00792     DWORD dwPreferredProtocols, DWORD dwInitialization,
00793     LPDWORD pdwActiveProtocol)
00794 {
00795     LONG rv;
00796     reconnect_struct scReconnectStruct;
00797     sharedSegmentMsg msgStruct;
00798     int i;
00799     DWORD dwContextIndex, dwChannelIndex;
00800 
00801     PROFILE_START
00802 
00803     if (dwInitialization != SCARD_LEAVE_CARD &&
00804         dwInitialization != SCARD_RESET_CARD &&
00805         dwInitialization != SCARD_UNPOWER_CARD &&
00806         dwInitialization != SCARD_EJECT_CARD)
00807     {
00808         return SCARD_E_INVALID_VALUE;
00809     }
00810 
00811     if (!(dwPreferredProtocols & SCARD_PROTOCOL_T0) &&
00812         !(dwPreferredProtocols & SCARD_PROTOCOL_T1) &&
00813         !(dwPreferredProtocols & SCARD_PROTOCOL_RAW) &&
00814         !(dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD))
00815     {
00816         return SCARD_E_INVALID_VALUE;
00817     }
00818 
00819     if (pdwActiveProtocol == NULL)
00820         return SCARD_E_INVALID_PARAMETER;
00821 
00822     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
00823         return SCARD_E_NO_SERVICE;
00824 
00825     /*
00826      * Make sure this handle has been opened
00827      */
00828     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
00829 
00830     if (rv == -1)
00831         return SCARD_E_INVALID_HANDLE;
00832 
00833     SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
00834 
00835 
00836     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
00837     {
00838         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
00839 
00840         /* by default r == NULL */
00841         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
00842             break;
00843     }
00844 
00845     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
00846     {
00847         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00848         return SCARD_E_READER_UNAVAILABLE;
00849     }
00850 
00851     scReconnectStruct.hCard = hCard;
00852     scReconnectStruct.dwShareMode = dwShareMode;
00853     scReconnectStruct.dwPreferredProtocols = dwPreferredProtocols;
00854     scReconnectStruct.dwInitialization = dwInitialization;
00855     scReconnectStruct.pdwActiveProtocol = *pdwActiveProtocol;
00856 
00857     rv = WrapSHMWrite(SCARD_RECONNECT, psContextMap[dwContextIndex].dwClientID,
00858         sizeof(scReconnectStruct),
00859         PCSCLITE_CLIENT_ATTEMPTS, (void *) &scReconnectStruct);
00860 
00861     if (rv == -1)
00862     {
00863         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00864         return SCARD_E_NO_SERVICE;
00865     }
00866 
00867     /*
00868      * Read a message from the server
00869      */
00870     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
00871 
00872     memcpy(&scReconnectStruct, &msgStruct.data, sizeof(scReconnectStruct));
00873 
00874     if (rv == -1)
00875     {
00876         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00877         return SCARD_F_COMM_ERROR;
00878     }
00879 
00880     *pdwActiveProtocol = scReconnectStruct.pdwActiveProtocol;
00881 
00882     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00883 
00884     PROFILE_END
00885 
00886     return scReconnectStruct.rv;
00887 }
00888 
00919 LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
00920 {
00921     LONG rv;
00922     disconnect_struct scDisconnectStruct;
00923     sharedSegmentMsg msgStruct;
00924     DWORD dwContextIndex, dwChannelIndex;
00925 
00926     PROFILE_START
00927 
00928     if (dwDisposition != SCARD_LEAVE_CARD &&
00929         dwDisposition != SCARD_RESET_CARD &&
00930         dwDisposition != SCARD_UNPOWER_CARD &&
00931         dwDisposition != SCARD_EJECT_CARD)
00932     {
00933         return SCARD_E_INVALID_VALUE;
00934     }
00935 
00936     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
00937         return SCARD_E_NO_SERVICE;
00938 
00939     /*
00940      * Make sure this handle has been opened
00941      */
00942     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
00943 
00944     if (rv == -1)
00945         return SCARD_E_INVALID_HANDLE;
00946 
00947     SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
00948 
00949     scDisconnectStruct.hCard = hCard;
00950     scDisconnectStruct.dwDisposition = dwDisposition;
00951 
00952     rv = WrapSHMWrite(SCARD_DISCONNECT, psContextMap[dwContextIndex].dwClientID,
00953         sizeof(scDisconnectStruct),
00954         PCSCLITE_CLIENT_ATTEMPTS, (void *) &scDisconnectStruct);
00955 
00956     if (rv == -1)
00957     {
00958         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00959         return SCARD_E_NO_SERVICE;
00960     }
00961 
00962     /*
00963      * Read a message from the server
00964      */
00965     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
00966 
00967     memcpy(&scDisconnectStruct, &msgStruct.data,
00968         sizeof(scDisconnectStruct));
00969 
00970     if (rv == -1)
00971     {
00972         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00973         return SCARD_F_COMM_ERROR;
00974     }
00975 
00976     SCardRemoveHandle(hCard);
00977 
00978     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00979 
00980     PROFILE_END
00981 
00982     return scDisconnectStruct.rv;
00983 }
00984 
01017 LONG SCardBeginTransaction(SCARDHANDLE hCard)
01018 {
01019 
01020     LONG rv;
01021     begin_struct scBeginStruct;
01022     int i;
01023     sharedSegmentMsg msgStruct;
01024     DWORD dwContextIndex, dwChannelIndex;
01025 
01026     PROFILE_START
01027 
01028     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
01029         return SCARD_E_NO_SERVICE;
01030 
01031     /*
01032      * Make sure this handle has been opened
01033      */
01034     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01035 
01036     if (rv == -1)
01037         return SCARD_E_INVALID_HANDLE;
01038 
01039     SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
01040 
01041     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01042     {
01043         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
01044 
01045         /* by default r == NULL */
01046         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
01047             break;
01048     }
01049 
01050     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
01051     {
01052         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01053         return SCARD_E_READER_UNAVAILABLE;
01054     }
01055 
01056     scBeginStruct.hCard = hCard;
01057 
01058     /*
01059      * Query the server every so often until the sharing violation ends
01060      * and then hold the lock for yourself.
01061      */
01062 
01063     do
01064     {
01065         /*
01066          * Look to see if it is locked before polling the server for
01067          * admission to the readers resources
01068          */
01069         if ((readerStates[i])->lockState != 0)
01070         {
01071             int randnum = 0;
01072             int j;
01073 
01074             for (j = 0; j < 100; j++)
01075             {
01076                 /*
01077                  * This helps prevent starvation
01078                  */
01079                 randnum = SYS_RandomInt(1000, 10000);
01080                 SYS_USleep(randnum);
01081 
01082                 if ((readerStates[i])->lockState == 0)
01083                 {
01084                     break;
01085                 }
01086             }
01087         }
01088 
01089         rv = WrapSHMWrite(SCARD_BEGIN_TRANSACTION, psContextMap[dwContextIndex].dwClientID,
01090             sizeof(scBeginStruct),
01091             PCSCLITE_CLIENT_ATTEMPTS, (void *) &scBeginStruct);
01092 
01093         if (rv == -1)
01094         {
01095 
01096             SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01097             return SCARD_E_NO_SERVICE;
01098         }
01099 
01100         /*
01101          * Read a message from the server
01102          */
01103         rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
01104 
01105 
01106         memcpy(&scBeginStruct, &msgStruct.data, sizeof(scBeginStruct));
01107 
01108         if (rv == -1)
01109         {
01110 
01111             SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01112             return SCARD_F_COMM_ERROR;
01113         }
01114 
01115     }
01116     while (scBeginStruct.rv == SCARD_E_SHARING_VIOLATION);
01117 
01118     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01119 
01120     PROFILE_END
01121 
01122     return scBeginStruct.rv;
01123 }
01124 
01163 LONG SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
01164 {
01165     LONG rv;
01166     end_struct scEndStruct;
01167     sharedSegmentMsg msgStruct;
01168     int randnum, i;
01169     DWORD dwContextIndex, dwChannelIndex;
01170 
01171     PROFILE_START
01172 
01173     /*
01174      * Zero out everything
01175      */
01176     randnum = 0;
01177 
01178     if (dwDisposition != SCARD_LEAVE_CARD &&
01179         dwDisposition != SCARD_RESET_CARD &&
01180         dwDisposition != SCARD_UNPOWER_CARD &&
01181         dwDisposition != SCARD_EJECT_CARD)
01182     {
01183         return SCARD_E_INVALID_VALUE;
01184     }
01185 
01186     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
01187         return SCARD_E_NO_SERVICE;
01188 
01189     /*
01190      * Make sure this handle has been opened
01191      */
01192     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01193 
01194     if (rv == -1)
01195         return SCARD_E_INVALID_HANDLE;
01196 
01197     SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
01198 
01199     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01200     {
01201         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
01202 
01203         /* by default r == NULL */
01204         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
01205             break;
01206     }
01207 
01208     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
01209     {
01210         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01211         return SCARD_E_READER_UNAVAILABLE;
01212     }
01213 
01214     scEndStruct.hCard = hCard;
01215     scEndStruct.dwDisposition = dwDisposition;
01216 
01217     rv = WrapSHMWrite(SCARD_END_TRANSACTION, psContextMap[dwContextIndex].dwClientID,
01218         sizeof(scEndStruct),
01219         PCSCLITE_CLIENT_ATTEMPTS, (void *) &scEndStruct);
01220 
01221     if (rv == -1)
01222     {
01223         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01224         return SCARD_E_NO_SERVICE;
01225     }
01226 
01227     /*
01228      * Read a message from the server
01229      */
01230     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
01231 
01232     memcpy(&scEndStruct, &msgStruct.data, sizeof(scEndStruct));
01233 
01234     if (rv == -1)
01235     {
01236         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01237         return SCARD_F_COMM_ERROR;
01238     }
01239 
01240     /*
01241      * This helps prevent starvation
01242      */
01243     randnum = SYS_RandomInt(1000, 10000);
01244     SYS_USleep(randnum);
01245 
01246     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01247 
01248     PROFILE_END
01249 
01250     return scEndStruct.rv;
01251 }
01252 
01258 LONG SCardCancelTransaction(SCARDHANDLE hCard)
01259 {
01260     LONG rv;
01261     cancel_struct scCancelStruct;
01262     sharedSegmentMsg msgStruct;
01263     int i;
01264     DWORD dwContextIndex, dwChannelIndex;
01265 
01266     PROFILE_START
01267 
01268     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
01269         return SCARD_E_NO_SERVICE;
01270 
01271     /*
01272      * Make sure this handle has been opened
01273      */
01274     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01275 
01276     if (rv == -1)
01277         return SCARD_E_INVALID_HANDLE;
01278 
01279     SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
01280 
01281     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01282     {
01283         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
01284 
01285         /* by default r == NULL */
01286         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
01287             break;
01288     }
01289 
01290     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
01291     {
01292         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01293         return SCARD_E_READER_UNAVAILABLE;
01294     }
01295 
01296     scCancelStruct.hCard = hCard;
01297 
01298     rv = WrapSHMWrite(SCARD_CANCEL_TRANSACTION, psContextMap[dwContextIndex].dwClientID,
01299         sizeof(scCancelStruct),
01300         PCSCLITE_CLIENT_ATTEMPTS, (void *) &scCancelStruct);
01301 
01302     if (rv == -1)
01303     {
01304         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01305         return SCARD_E_NO_SERVICE;
01306     }
01307 
01308     /*
01309      * Read a message from the server
01310      */
01311     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
01312 
01313     memcpy(&scCancelStruct, &msgStruct.data, sizeof(scCancelStruct));
01314 
01315     if (rv == -1)
01316     {
01317         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01318         return SCARD_F_COMM_ERROR;
01319     }
01320 
01321     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01322 
01323     PROFILE_END
01324 
01325     return scCancelStruct.rv;
01326 }
01327 
01385 LONG SCardStatus(SCARDHANDLE hCard, LPSTR mszReaderNames,
01386     LPDWORD pcchReaderLen, LPDWORD pdwState,
01387     LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
01388 {
01389     DWORD dwReaderLen, dwAtrLen;
01390     LONG rv;
01391     int i;
01392     status_struct scStatusStruct;
01393     sharedSegmentMsg msgStruct;
01394     DWORD dwContextIndex, dwChannelIndex;
01395     char *r;
01396 
01397     PROFILE_START
01398 
01399     /*
01400      * Check for NULL parameters
01401      */
01402 
01403     if (pcchReaderLen == NULL || pcbAtrLen == NULL)
01404         return SCARD_E_INVALID_PARAMETER;
01405 
01406     /* length passed from caller */
01407     dwReaderLen = *pcchReaderLen;
01408     dwAtrLen = *pcbAtrLen;
01409 
01410     /* default output values */
01411     if (pdwState)
01412         *pdwState = 0;
01413 
01414     if (pdwProtocol)
01415         *pdwProtocol = 0;
01416 
01417     *pcchReaderLen = 0;
01418     *pcbAtrLen = 0;
01419 
01420     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
01421         return SCARD_E_NO_SERVICE;
01422 
01423     /*
01424      * Make sure this handle has been opened
01425      */
01426     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01427 
01428     if (rv == -1)
01429         return SCARD_E_INVALID_HANDLE;
01430 
01431     SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
01432 
01433     r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
01434     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01435     {
01436         /* by default r == NULL */
01437         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
01438             break;
01439     }
01440 
01441     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
01442     {
01443         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01444         return SCARD_E_READER_UNAVAILABLE;
01445     }
01446 
01447     /* initialise the structure */
01448     memset(&scStatusStruct, 0, sizeof(scStatusStruct));
01449     scStatusStruct.hCard = hCard;
01450 
01451     /* those sizes need to be initialised */
01452     scStatusStruct.pcchReaderLen = sizeof(scStatusStruct.mszReaderNames);
01453     scStatusStruct.pcbAtrLen = sizeof(scStatusStruct.pbAtr);
01454 
01455     rv = WrapSHMWrite(SCARD_STATUS, psContextMap[dwContextIndex].dwClientID,
01456         sizeof(scStatusStruct),
01457         PCSCLITE_CLIENT_ATTEMPTS, (void *) &scStatusStruct);
01458 
01459     if (rv == -1)
01460     {
01461         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01462         return SCARD_E_NO_SERVICE;
01463     }
01464 
01465     /*
01466      * Read a message from the server
01467      */
01468     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
01469 
01470     memcpy(&scStatusStruct, &msgStruct.data, sizeof(scStatusStruct));
01471 
01472     if (rv == -1)
01473     {
01474         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01475         return SCARD_F_COMM_ERROR;
01476     }
01477 
01478     rv = scStatusStruct.rv;
01479     if (rv != SCARD_S_SUCCESS && rv != SCARD_E_INSUFFICIENT_BUFFER)
01480     {
01481         /*
01482          * An event must have occurred
01483          */
01484         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01485         return rv;
01486     }
01487 
01488     /*
01489      * Now continue with the client side SCardStatus
01490      */
01491 
01492     *pcchReaderLen = strlen(psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName) + 1;
01493     *pcbAtrLen = (readerStates[i])->cardAtrLength;
01494 
01495     if (pdwState)
01496         *pdwState = (readerStates[i])->readerState;
01497 
01498     if (pdwProtocol)
01499         *pdwProtocol = (readerStates[i])->cardProtocol;
01500 
01501     /* return SCARD_E_INSUFFICIENT_BUFFER only if buffer pointer is non NULL */
01502     if (mszReaderNames)
01503     {
01504         if (*pcchReaderLen > dwReaderLen)
01505             rv = SCARD_E_INSUFFICIENT_BUFFER;
01506 
01507         strncpy(mszReaderNames,
01508             psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName,
01509             dwReaderLen);
01510     }
01511 
01512     if (pbAtr)
01513     {
01514         if (*pcbAtrLen > dwAtrLen)
01515             rv = SCARD_E_INSUFFICIENT_BUFFER;
01516 
01517         memcpy(pbAtr, (readerStates[i])->cardAtr,
01518             min(*pcbAtrLen, dwAtrLen));
01519     }
01520 
01521     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01522 
01523     PROFILE_END
01524 
01525     return rv;
01526 }
01527 
01613 LONG SCardGetStatusChange(SCARDCONTEXT hContext, DWORD dwTimeout,
01614     LPSCARD_READERSTATE_A rgReaderStates, DWORD cReaders)
01615 {
01616     PSCARD_READERSTATE_A currReader;
01617     PREADER_STATE rContext;
01618     DWORD dwTime = 0;
01619     DWORD dwState;
01620     DWORD dwBreakFlag = 0;
01621     int j;
01622     LONG dwContextIndex;
01623     int currentReaderCount = 0;
01624 
01625     PROFILE_START
01626 
01627     if (rgReaderStates == NULL && cReaders > 0)
01628         return SCARD_E_INVALID_PARAMETER;
01629 
01630     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
01631         return SCARD_E_NO_SERVICE;
01632 
01633     /*
01634      * Make sure this context has been opened
01635      */
01636 
01637     dwContextIndex = SCardGetContextIndice(hContext);
01638     if (dwContextIndex == -1)
01639         return SCARD_E_INVALID_HANDLE;
01640 
01641     SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
01642 
01643     /*
01644      * Application is waiting for a reader - return the first available
01645      * reader
01646      */
01647 
01648     if (cReaders == 0)
01649     {
01650         while (1)
01651         {
01652             int i;
01653 
01654             if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
01655             {
01656                 SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01657                 return SCARD_E_NO_SERVICE;
01658             }
01659 
01660             for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01661             {
01662                 if ((readerStates[i])->readerID != 0)
01663                 {
01664                     /*
01665                      * Reader was found
01666                      */
01667                     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01668 
01669                     PROFILE_END
01670 
01671                     return SCARD_S_SUCCESS;
01672                 }
01673             }
01674 
01675             if (dwTimeout == 0)
01676             {
01677                 /*
01678                  * return immediately - no reader available
01679                  */
01680                 SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01681                 return SCARD_E_READER_UNAVAILABLE;
01682             }
01683 
01684             SYS_USleep(PCSCLITE_STATUS_WAIT);
01685 
01686             if (dwTimeout != INFINITE)
01687             {
01688                 dwTime += PCSCLITE_STATUS_WAIT;
01689 
01690                 if (dwTime >= (dwTimeout * 1000))
01691                 {
01692                     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01693 
01694                     PROFILE_END
01695 
01696                     return SCARD_E_TIMEOUT;
01697                 }
01698             }
01699         }
01700     }
01701     else
01702         if (cReaders >= PCSCLITE_MAX_READERS_CONTEXTS)
01703         {
01704             SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01705             return SCARD_E_INVALID_VALUE;
01706         }
01707 
01708     /*
01709      * Check the integrity of the reader states structures
01710      */
01711 
01712     for (j = 0; j < cReaders; j++)
01713     {
01714         currReader = &rgReaderStates[j];
01715 
01716         if (currReader->szReader == NULL)
01717         {
01718             SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01719             return SCARD_E_INVALID_VALUE;
01720         }
01721     }
01722 
01723     /*
01724      * End of search for readers
01725      */
01726 
01727     /*
01728      * Clear the event state for all readers
01729      */
01730     for (j = 0; j < cReaders; j++)
01731     {
01732         currReader = &rgReaderStates[j];
01733         currReader->dwEventState = 0;
01734     }
01735 
01736     /*
01737      * Now is where we start our event checking loop
01738      */
01739 
01740     Log1(PCSC_LOG_DEBUG, "Event Loop Start");
01741 
01742     psContextMap[dwContextIndex].contextBlockStatus = BLOCK_STATUS_BLOCKING;
01743 
01744     /* Get the initial reader count on the system */
01745     for (j=0; j < PCSCLITE_MAX_READERS_CONTEXTS; j++)
01746         if ((readerStates[j])->readerID != 0)
01747             currentReaderCount++;
01748 
01749     j = 0;
01750 
01751     do
01752     {
01753         int newReaderCount = 0;
01754         char ReaderCountChanged = FALSE;
01755 
01756         if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
01757         {
01758             SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01759 
01760             PROFILE_END
01761 
01762             return SCARD_E_NO_SERVICE;
01763         }
01764 
01765         if (j == 0)
01766         {
01767             int i;
01768 
01769             for (i=0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01770                 if ((readerStates[i])->readerID != 0)
01771                     newReaderCount++;
01772 
01773             if (newReaderCount != currentReaderCount)
01774             {
01775                 Log1(PCSC_LOG_INFO, "Reader list changed");
01776                 ReaderCountChanged = TRUE;
01777                 currentReaderCount = newReaderCount;
01778             }
01779         }
01780         currReader = &rgReaderStates[j];
01781 
01782     /************ Look for IGNORED readers ****************************/
01783 
01784         if (currReader->dwCurrentState & SCARD_STATE_IGNORE)
01785             currReader->dwEventState = SCARD_STATE_IGNORE;
01786         else
01787         {
01788             LPSTR lpcReaderName;
01789             int i;
01790 
01791       /************ Looks for correct readernames *********************/
01792 
01793             lpcReaderName = (char *) currReader->szReader;
01794 
01795             for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01796             {
01797                 if (strcmp(lpcReaderName, (readerStates[i])->readerName) == 0)
01798                     break;
01799             }
01800 
01801             /*
01802              * The requested reader name is not recognized
01803              */
01804             if (i == PCSCLITE_MAX_READERS_CONTEXTS)
01805             {
01806                 if (currReader->dwCurrentState & SCARD_STATE_UNKNOWN)
01807                     currReader->dwEventState = SCARD_STATE_UNKNOWN;
01808                 else
01809                 {
01810                     currReader->dwEventState =
01811                         SCARD_STATE_UNKNOWN | SCARD_STATE_CHANGED;
01812                     /*
01813                      * Spec says use SCARD_STATE_IGNORE but a removed USB
01814                      * reader with eventState fed into currentState will
01815                      * be ignored forever
01816                      */
01817                     dwBreakFlag = 1;
01818                 }
01819             }
01820             else
01821             {
01822 
01823                 /*
01824                  * The reader has come back after being away
01825                  */
01826                 if (currReader->dwCurrentState & SCARD_STATE_UNKNOWN)
01827                 {
01828                     currReader->dwEventState |= SCARD_STATE_CHANGED;
01829                     currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
01830                     dwBreakFlag = 1;
01831                 }
01832 
01833     /*****************************************************************/
01834 
01835                 /*
01836                  * Set the reader status structure
01837                  */
01838                 rContext = readerStates[i];
01839 
01840                 /*
01841                  * Now we check all the Reader States
01842                  */
01843                 dwState = rContext->readerState;
01844 
01845     /*********** Check if the reader is in the correct state ********/
01846                 if (dwState & SCARD_UNKNOWN)
01847                 {
01848                     /*
01849                      * App thinks reader is in bad state and it is
01850                      */
01851                     if (currReader-> dwCurrentState & SCARD_STATE_UNAVAILABLE)
01852                         currReader->dwEventState = SCARD_STATE_UNAVAILABLE;
01853                     else
01854                     {
01855                         /*
01856                          * App thinks reader is in good state and it is
01857                          * not
01858                          */
01859                         currReader->dwEventState = SCARD_STATE_CHANGED |
01860                             SCARD_STATE_UNAVAILABLE;
01861                         dwBreakFlag = 1;
01862                     }
01863                 }
01864                 else
01865                 {
01866                     /*
01867                      * App thinks reader in bad state but it is not
01868                      */
01869                     if (currReader-> dwCurrentState & SCARD_STATE_UNAVAILABLE)
01870                     {
01871                         currReader->dwEventState &=
01872                             ~SCARD_STATE_UNAVAILABLE;
01873                         currReader->dwEventState |= SCARD_STATE_CHANGED;
01874                         dwBreakFlag = 1;
01875                     }
01876                 }
01877 
01878     /********** Check for card presence in the reader **************/
01879 
01880                 if (dwState & SCARD_PRESENT)
01881                 {
01882                     /* card present but not yet powered up */
01883                     if (0 == rContext->cardAtrLength)
01884                         /* Allow the status thread to convey information */
01885                         SYS_USleep(PCSCLITE_STATUS_POLL_RATE + 10);
01886 
01887                     currReader->cbAtr = rContext->cardAtrLength;
01888                     memcpy(currReader->rgbAtr, rContext->cardAtr,
01889                         currReader->cbAtr);
01890                 }
01891                 else
01892                     currReader->cbAtr = 0;
01893 
01894                 /*
01895                  * Card is now absent
01896                  */
01897                 if (dwState & SCARD_ABSENT)
01898                 {
01899                     currReader->dwEventState |= SCARD_STATE_EMPTY;
01900                     currReader->dwEventState &= ~SCARD_STATE_PRESENT;
01901                     currReader->dwEventState &= ~SCARD_STATE_UNAWARE;
01902                     currReader->dwEventState &= ~SCARD_STATE_IGNORE;
01903                     currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
01904                     currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
01905                     currReader->dwEventState &= ~SCARD_STATE_ATRMATCH;
01906                     currReader->dwEventState &= ~SCARD_STATE_MUTE;
01907                     currReader->dwEventState &= ~SCARD_STATE_INUSE;
01908 
01909                     /*
01910                      * After present the rest are assumed
01911                      */
01912                     if (currReader->dwCurrentState & SCARD_STATE_PRESENT
01913                         || currReader->dwCurrentState & SCARD_STATE_ATRMATCH
01914                         || currReader->dwCurrentState & SCARD_STATE_EXCLUSIVE
01915                         || currReader->dwCurrentState & SCARD_STATE_INUSE)
01916                     {
01917                         currReader->dwEventState |= SCARD_STATE_CHANGED;
01918                         dwBreakFlag = 1;
01919                     }
01920 
01921                     /*
01922                      * Card is now present
01923                      */
01924                 } else if (dwState & SCARD_PRESENT)
01925                 {
01926                     currReader->dwEventState |= SCARD_STATE_PRESENT;
01927                     currReader->dwEventState &= ~SCARD_STATE_EMPTY;
01928                     currReader->dwEventState &= ~SCARD_STATE_UNAWARE;
01929                     currReader->dwEventState &= ~SCARD_STATE_IGNORE;
01930                     currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
01931                     currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
01932                     currReader->dwEventState &= ~SCARD_STATE_MUTE;
01933 
01934                     if (currReader->dwCurrentState & SCARD_STATE_EMPTY)
01935                     {
01936                         currReader->dwEventState |= SCARD_STATE_CHANGED;
01937                         dwBreakFlag = 1;
01938                     }
01939 
01940                     if (dwState & SCARD_SWALLOWED)
01941                     {
01942                         if (currReader->dwCurrentState & SCARD_STATE_MUTE)
01943                             currReader->dwEventState |= SCARD_STATE_MUTE;
01944                         else
01945                         {
01946                             currReader->dwEventState |= SCARD_STATE_MUTE;
01947                             if (currReader->dwCurrentState
01948                                 != SCARD_STATE_UNAWARE)
01949                                 currReader->dwEventState |= SCARD_STATE_CHANGED;
01950                             dwBreakFlag = 1;
01951                         }
01952                     }
01953                     else
01954                     {
01955                         /*
01956                          * App thinks card is mute but it is not
01957                          */
01958                         if (currReader->dwCurrentState & SCARD_STATE_MUTE)
01959                         {
01960                             currReader->dwEventState |=
01961                                 SCARD_STATE_CHANGED;
01962                             dwBreakFlag = 1;
01963                         }
01964                     }
01965                 }
01966 
01967                 /*
01968                  * Now figure out sharing modes
01969                  */
01970                 if (rContext->readerSharing == -1)
01971                 {
01972                     currReader->dwEventState |= SCARD_STATE_EXCLUSIVE;
01973                     currReader->dwEventState &= ~SCARD_STATE_INUSE;
01974                     if (currReader->dwCurrentState & SCARD_STATE_INUSE)
01975                     {
01976                         currReader->dwEventState |= SCARD_STATE_CHANGED;
01977                         dwBreakFlag = 1;
01978                     }
01979                 }
01980                 else if (rContext->readerSharing >= 1)
01981                 {
01982                     /*
01983                      * A card must be inserted for it to be INUSE
01984                      */
01985                     if (dwState & SCARD_PRESENT)
01986                     {
01987                         currReader->dwEventState |= SCARD_STATE_INUSE;
01988                         currReader->dwEventState &= ~SCARD_STATE_EXCLUSIVE;
01989                         if (currReader-> dwCurrentState & SCARD_STATE_EXCLUSIVE)
01990                         {
01991                             currReader->dwEventState |= SCARD_STATE_CHANGED;
01992                             dwBreakFlag = 1;
01993                         }
01994                     }
01995                 }
01996                 else if (rContext->readerSharing == 0)
01997                 {
01998                     currReader->dwEventState &= ~SCARD_STATE_INUSE;
01999                     currReader->dwEventState &= ~SCARD_STATE_EXCLUSIVE;
02000 
02001                     if (currReader->dwCurrentState & SCARD_STATE_INUSE)
02002                     {
02003                         currReader->dwEventState |= SCARD_STATE_CHANGED;
02004                         dwBreakFlag = 1;
02005                     }
02006                     else if (currReader-> dwCurrentState
02007                         & SCARD_STATE_EXCLUSIVE)
02008                     {
02009                         currReader->dwEventState |= SCARD_STATE_CHANGED;
02010                         dwBreakFlag = 1;
02011                     }
02012                 }
02013 
02014                 if (currReader->dwCurrentState == SCARD_STATE_UNAWARE)
02015                 {
02016                     /*
02017                      * Break out of the while .. loop and return status
02018                      * once all the status's for all readers is met
02019                      */
02020                     currReader->dwEventState |= SCARD_STATE_CHANGED;
02021                     dwBreakFlag = 1;
02022                 }
02023 
02024             }   /* End of SCARD_STATE_UNKNOWN */
02025 
02026         }   /* End of SCARD_STATE_IGNORE */
02027 
02028         /*
02029          * Counter and resetter
02030          */
02031         j = j + 1;
02032         if (j == cReaders)
02033         {
02034             if (!dwBreakFlag)
02035             {
02036                 /* break if the reader count changed,
02037                  * so that the calling application can update
02038                  * the reader list
02039                  */
02040                 if (ReaderCountChanged)
02041                     break;
02042             }
02043             j = 0;
02044         }
02045 
02046         /*
02047          * Declare all the break conditions
02048          */
02049 
02050         if (psContextMap[dwContextIndex].contextBlockStatus
02051                 == BLOCK_STATUS_RESUME)
02052             break;
02053 
02054         /*
02055          * Break if UNAWARE is set and all readers have been checked
02056          */
02057         if ((dwBreakFlag == 1) && (j == 0))
02058             break;
02059 
02060         /*
02061          * Timeout has occurred and all readers checked
02062          */
02063         if ((dwTimeout == 0) && (j == 0))
02064             break;
02065 
02066         if (dwTimeout != INFINITE && dwTimeout != 0)
02067         {
02068             /*
02069              * If time is greater than timeout and all readers have been
02070              * checked
02071              */
02072             if ((dwTime >= (dwTimeout * 1000)) && (j == 0))
02073             {
02074                 SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02075                 return SCARD_E_TIMEOUT;
02076             }
02077         }
02078 
02079         /*
02080          * Only sleep once for each cycle of reader checks.
02081          */
02082         if (j == 0)
02083         {
02084             SYS_USleep(PCSCLITE_STATUS_WAIT);
02085             dwTime += PCSCLITE_STATUS_WAIT;
02086         }
02087     }
02088     while (1);
02089 
02090     Log1(PCSC_LOG_DEBUG, "Event Loop End");
02091 
02092     if (psContextMap[dwContextIndex].contextBlockStatus ==
02093             BLOCK_STATUS_RESUME)
02094     {
02095         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02096         return SCARD_E_CANCELLED;
02097     }
02098 
02099     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02100 
02101     PROFILE_END
02102 
02103     return SCARD_S_SUCCESS;
02104 }
02105 
02152 LONG SCardControl(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer,
02153     DWORD cbSendLength, LPVOID pbRecvBuffer, DWORD cbRecvLength,
02154     LPDWORD lpBytesReturned)
02155 {
02156     LONG rv;
02157     control_struct scControlStruct;
02158     sharedSegmentMsg msgStruct;
02159     int i;
02160     DWORD dwContextIndex, dwChannelIndex;
02161 
02162     PROFILE_START
02163 
02164     /* 0 bytes received by default */
02165     if (NULL != lpBytesReturned)
02166         *lpBytesReturned = 0;
02167 
02168     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
02169         return SCARD_E_NO_SERVICE;
02170 
02171     /*
02172      * Make sure this handle has been opened
02173      */
02174     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
02175 
02176     if (rv == -1)
02177         return SCARD_E_INVALID_HANDLE;
02178 
02179     SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
02180 
02181     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
02182     {
02183         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
02184 
02185         /* by default r == NULL */
02186         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
02187             break;
02188     }
02189 
02190     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
02191     {
02192         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02193         return SCARD_E_READER_UNAVAILABLE;
02194     }
02195 
02196     if ((cbSendLength > MAX_BUFFER_SIZE_EXTENDED)
02197         || (cbRecvLength > MAX_BUFFER_SIZE_EXTENDED))
02198     {
02199         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02200         return SCARD_E_INSUFFICIENT_BUFFER;
02201     }
02202 
02203     if ((cbSendLength > MAX_BUFFER_SIZE) || (cbRecvLength > MAX_BUFFER_SIZE))
02204     {
02205         /* extended control */
02206         unsigned char buffer[sizeof(sharedSegmentMsg) + MAX_BUFFER_SIZE_EXTENDED];
02207         control_struct_extended *scControlStructExtended = (control_struct_extended *)buffer;
02208         sharedSegmentMsg *pmsgStruct = (psharedSegmentMsg)buffer;
02209 
02210         scControlStructExtended->hCard = hCard;
02211         scControlStructExtended->dwControlCode = dwControlCode;
02212         scControlStructExtended->cbSendLength = cbSendLength;
02213         scControlStructExtended->cbRecvLength = cbRecvLength;
02214         scControlStructExtended->size = sizeof(*scControlStructExtended) + cbSendLength;
02215         memcpy(scControlStructExtended->data, pbSendBuffer, cbSendLength);
02216 
02217         rv = WrapSHMWrite(SCARD_CONTROL_EXTENDED,
02218             psContextMap[dwContextIndex].dwClientID,
02219             scControlStructExtended->size,
02220             PCSCLITE_CLIENT_ATTEMPTS, buffer);
02221 
02222         if (rv == -1)
02223         {
02224             SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02225             return SCARD_E_NO_SERVICE;
02226         }
02227 
02228         /*
02229          * Read a message from the server
02230          */
02231         /* read the first block */
02232         rv = SHMMessageReceive(buffer, sizeof(sharedSegmentMsg), psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
02233         if (rv == -1)
02234         {
02235             SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02236             return SCARD_F_COMM_ERROR;
02237         }
02238 
02239         /* we receive a sharedSegmentMsg and not a control_struct_extended */
02240         scControlStructExtended = (control_struct_extended *)&(pmsgStruct -> data);
02241 
02242         /* a second block is present */
02243         if (scControlStructExtended->size > PCSCLITE_MAX_MESSAGE_SIZE)
02244         {
02245             rv = SHMMessageReceive(buffer + sizeof(sharedSegmentMsg),
02246                 scControlStructExtended->size-PCSCLITE_MAX_MESSAGE_SIZE,
02247                 psContextMap[dwContextIndex].dwClientID,
02248                 PCSCLITE_CLIENT_ATTEMPTS);
02249             if (rv == -1)
02250             {
02251                 SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02252                 return SCARD_F_COMM_ERROR;
02253             }
02254         }
02255 
02256         if (scControlStructExtended -> rv == SCARD_S_SUCCESS)
02257         {
02258             /*
02259              * Copy and zero it so any secret information is not leaked
02260              */
02261             memcpy(pbRecvBuffer, scControlStructExtended -> data,
02262                 scControlStructExtended -> pdwBytesReturned);
02263             memset(scControlStructExtended -> data, 0x00,
02264                 scControlStructExtended -> pdwBytesReturned);
02265         }
02266 
02267         if (NULL != lpBytesReturned)
02268             *lpBytesReturned = scControlStructExtended -> pdwBytesReturned;
02269 
02270         rv = scControlStructExtended -> rv;
02271     }
02272     else
02273     {
02274         scControlStruct.hCard = hCard;
02275         scControlStruct.dwControlCode = dwControlCode;
02276         scControlStruct.cbSendLength = cbSendLength;
02277         scControlStruct.cbRecvLength = cbRecvLength;
02278         memcpy(scControlStruct.pbSendBuffer, pbSendBuffer, cbSendLength);
02279 
02280         rv = WrapSHMWrite(SCARD_CONTROL, psContextMap[dwContextIndex].dwClientID,
02281             sizeof(scControlStruct), PCSCLITE_CLIENT_ATTEMPTS, &scControlStruct);
02282 
02283         if (rv == -1)
02284         {
02285             SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02286             return SCARD_E_NO_SERVICE;
02287         }
02288 
02289         /*
02290          * Read a message from the server
02291          */
02292         rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
02293 
02294         if (rv == -1)
02295         {
02296             SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02297             return SCARD_F_COMM_ERROR;
02298         }
02299 
02300         memcpy(&scControlStruct, &msgStruct.data, sizeof(scControlStruct));
02301 
02302         if (NULL != lpBytesReturned)
02303             *lpBytesReturned = scControlStruct.dwBytesReturned;
02304 
02305         if (scControlStruct.rv == SCARD_S_SUCCESS)
02306         {
02307             /*
02308              * Copy and zero it so any secret information is not leaked
02309              */
02310             memcpy(pbRecvBuffer, scControlStruct.pbRecvBuffer,
02311                 scControlStruct.cbRecvLength);
02312             memset(scControlStruct.pbRecvBuffer, 0x00,
02313                 sizeof(scControlStruct.pbRecvBuffer));
02314         }
02315 
02316         rv = scControlStruct.rv;
02317     }
02318 
02319     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02320 
02321     PROFILE_END
02322 
02323     return rv;
02324 }
02325 
02406 LONG SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr,
02407     LPDWORD pcbAttrLen)
02408 {
02409     PROFILE_START
02410 
02411     if (NULL == pcbAttrLen)
02412         return SCARD_E_INVALID_PARAMETER;
02413 
02414     /* if only get the length */
02415     if (NULL == pbAttr)
02416         /* this variable may not be set by the caller. use a reasonable size */
02417         *pcbAttrLen = MAX_BUFFER_SIZE;
02418 
02419     PROFILE_END
02420 
02421     return SCardGetSetAttrib(hCard, SCARD_GET_ATTRIB, dwAttrId, pbAttr,
02422         pcbAttrLen);
02423 }
02424 
02455 LONG SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr,
02456     DWORD cbAttrLen)
02457 {
02458     PROFILE_START
02459 
02460     if (NULL == pbAttr || 0 == cbAttrLen)
02461         return SCARD_E_INVALID_PARAMETER;
02462 
02463     PROFILE_END
02464 
02465     return SCardGetSetAttrib(hCard, SCARD_SET_ATTRIB, dwAttrId, (LPBYTE)pbAttr,
02466         &cbAttrLen);
02467 }
02468 
02469 static LONG SCardGetSetAttrib(SCARDHANDLE hCard, int command, DWORD dwAttrId,
02470     LPBYTE pbAttr, LPDWORD pcbAttrLen)
02471 {
02472     PROFILE_START
02473 
02474     LONG rv;
02475     getset_struct scGetSetStruct;
02476     sharedSegmentMsg msgStruct;
02477     int i;
02478     DWORD dwContextIndex, dwChannelIndex;
02479 
02480     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
02481         return SCARD_E_NO_SERVICE;
02482 
02483     /*
02484      * Make sure this handle has been opened
02485      */
02486     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
02487 
02488     if (rv == -1)
02489         return SCARD_E_INVALID_HANDLE;
02490 
02491     SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
02492 
02493     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
02494     {
02495         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
02496 
02497         /* by default r == NULL */
02498         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
02499             break;
02500     }
02501 
02502     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
02503     {
02504         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02505         return SCARD_E_READER_UNAVAILABLE;
02506     }
02507 
02508     if (*pcbAttrLen > MAX_BUFFER_SIZE)
02509     {
02510         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02511         return SCARD_E_INSUFFICIENT_BUFFER;
02512     }
02513 
02514     scGetSetStruct.hCard = hCard;
02515     scGetSetStruct.dwAttrId = dwAttrId;
02516     scGetSetStruct.cbAttrLen = *pcbAttrLen;
02517     scGetSetStruct.rv = SCARD_E_NO_SERVICE;
02518     if (SCARD_SET_ATTRIB == command)
02519         memcpy(scGetSetStruct.pbAttr, pbAttr, *pcbAttrLen);
02520 
02521     rv = WrapSHMWrite(command,
02522         psContextMap[dwContextIndex].dwClientID, sizeof(scGetSetStruct),
02523         PCSCLITE_CLIENT_ATTEMPTS, &scGetSetStruct);
02524 
02525     if (rv == -1)
02526     {
02527         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02528         return SCARD_E_NO_SERVICE;
02529     }
02530 
02531     /*
02532      * Read a message from the server
02533      */
02534     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
02535 
02536     if (rv == -1)
02537     {
02538         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02539         return SCARD_F_COMM_ERROR;
02540     }
02541 
02542     memcpy(&scGetSetStruct, &msgStruct.data, sizeof(scGetSetStruct));
02543 
02544     if ((SCARD_S_SUCCESS == scGetSetStruct.rv) && (SCARD_GET_ATTRIB == command))
02545     {
02546         /*
02547          * Copy and zero it so any secret information is not leaked
02548          */
02549         if (*pcbAttrLen < scGetSetStruct.cbAttrLen)
02550         {
02551             scGetSetStruct.cbAttrLen = *pcbAttrLen;
02552             scGetSetStruct.rv = SCARD_E_INSUFFICIENT_BUFFER;
02553         }
02554         else
02555             *pcbAttrLen = scGetSetStruct.cbAttrLen;
02556 
02557         if (pbAttr)
02558             memcpy(pbAttr, scGetSetStruct.pbAttr, scGetSetStruct.cbAttrLen);
02559 
02560         memset(scGetSetStruct.pbAttr, 0x00, sizeof(scGetSetStruct.pbAttr));
02561     }
02562 
02563     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02564 
02565     PROFILE_END
02566 
02567     return scGetSetStruct.rv;
02568 }
02569 
02623 LONG SCardTransmit(SCARDHANDLE hCard, LPCSCARD_IO_REQUEST pioSendPci,
02624     LPCBYTE pbSendBuffer, DWORD cbSendLength,
02625     LPSCARD_IO_REQUEST pioRecvPci, LPBYTE pbRecvBuffer,
02626     LPDWORD pcbRecvLength)
02627 {
02628     LONG rv;
02629     int i;
02630     DWORD dwContextIndex, dwChannelIndex;
02631 
02632     PROFILE_START
02633 
02634     if (pbSendBuffer == NULL || pbRecvBuffer == NULL ||
02635             pcbRecvLength == NULL || pioSendPci == NULL)
02636         return SCARD_E_INVALID_PARAMETER;
02637 
02638     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
02639         return SCARD_E_NO_SERVICE;
02640 
02641     /*
02642      * Make sure this handle has been opened
02643      */
02644     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
02645 
02646     if (rv == -1)
02647     {
02648         *pcbRecvLength = 0;
02649         return SCARD_E_INVALID_HANDLE;
02650     }
02651 
02652     SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
02653 
02654     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
02655     {
02656         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
02657 
02658         /* by default r == NULL */
02659         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
02660             break;
02661     }
02662 
02663     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
02664     {
02665         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02666         return SCARD_E_READER_UNAVAILABLE;
02667     }
02668 
02669     if ((cbSendLength > MAX_BUFFER_SIZE_EXTENDED)
02670         || (*pcbRecvLength > MAX_BUFFER_SIZE_EXTENDED))
02671     {
02672         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02673         return SCARD_E_INSUFFICIENT_BUFFER;
02674     }
02675 
02676     if ((cbSendLength > MAX_BUFFER_SIZE) || (*pcbRecvLength > MAX_BUFFER_SIZE))
02677     {
02678         /* extended APDU */
02679         unsigned char buffer[sizeof(sharedSegmentMsg) + MAX_BUFFER_SIZE_EXTENDED];
02680         transmit_struct_extended *scTransmitStructExtended = (transmit_struct_extended *)buffer;
02681         sharedSegmentMsg *pmsgStruct = (psharedSegmentMsg)buffer;
02682 
02683         scTransmitStructExtended->hCard = hCard;
02684         scTransmitStructExtended->cbSendLength = cbSendLength;
02685         scTransmitStructExtended->pcbRecvLength = *pcbRecvLength;
02686         scTransmitStructExtended->size = sizeof(*scTransmitStructExtended) + cbSendLength;
02687         memcpy(&scTransmitStructExtended->pioSendPci, pioSendPci,
02688             sizeof(SCARD_IO_REQUEST));
02689         memcpy(scTransmitStructExtended->data, pbSendBuffer, cbSendLength);
02690 
02691         if (pioRecvPci)
02692         {
02693             memcpy(&scTransmitStructExtended->pioRecvPci, pioRecvPci,
02694                 sizeof(SCARD_IO_REQUEST));
02695         }
02696         else
02697             scTransmitStructExtended->pioRecvPci.dwProtocol = SCARD_PROTOCOL_ANY;
02698 
02699         rv = WrapSHMWrite(SCARD_TRANSMIT_EXTENDED,
02700             psContextMap[dwContextIndex].dwClientID,
02701             scTransmitStructExtended->size,
02702             PCSCLITE_CLIENT_ATTEMPTS, buffer);
02703 
02704         if (rv == -1)
02705         {
02706             SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02707             return SCARD_E_NO_SERVICE;
02708         }
02709 
02710         /*
02711          * Read a message from the server
02712          */
02713         /* read the first block */
02714         rv = SHMMessageReceive(buffer, sizeof(sharedSegmentMsg), psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
02715         if (rv == -1)
02716         {
02717             SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02718             return SCARD_F_COMM_ERROR;
02719         }
02720 
02721         /* we receive a sharedSegmentMsg and not a transmit_struct_extended */
02722         scTransmitStructExtended = (transmit_struct_extended *)&(pmsgStruct -> data);
02723 
02724         /* a second block is present */
02725         if (scTransmitStructExtended->size > PCSCLITE_MAX_MESSAGE_SIZE)
02726         {
02727             rv = SHMMessageReceive(buffer + sizeof(sharedSegmentMsg),
02728                 scTransmitStructExtended->size-PCSCLITE_MAX_MESSAGE_SIZE,
02729                 psContextMap[dwContextIndex].dwClientID,
02730                 PCSCLITE_CLIENT_ATTEMPTS);
02731             if (rv == -1)
02732             {
02733                 SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02734                 return SCARD_F_COMM_ERROR;
02735             }
02736         }
02737 
02738         if (scTransmitStructExtended -> rv == SCARD_S_SUCCESS)
02739         {
02740             /*
02741              * Copy and zero it so any secret information is not leaked
02742              */
02743             memcpy(pbRecvBuffer, scTransmitStructExtended -> data,
02744                 scTransmitStructExtended -> pcbRecvLength);
02745             memset(scTransmitStructExtended -> data, 0x00,
02746                 scTransmitStructExtended -> pcbRecvLength);
02747 
02748             if (pioRecvPci)
02749                 memcpy(pioRecvPci, &scTransmitStructExtended -> pioRecvPci,
02750                     sizeof(SCARD_IO_REQUEST));
02751         }
02752 
02753         *pcbRecvLength = scTransmitStructExtended -> pcbRecvLength;
02754         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02755 
02756         rv = scTransmitStructExtended -> rv;
02757     }
02758     else
02759     {
02760         /* short APDU */
02761         transmit_struct scTransmitStruct;
02762         sharedSegmentMsg msgStruct;
02763 
02764         scTransmitStruct.hCard = hCard;
02765         scTransmitStruct.cbSendLength = cbSendLength;
02766         scTransmitStruct.pcbRecvLength = *pcbRecvLength;
02767         memcpy(&scTransmitStruct.pioSendPci, pioSendPci,
02768             sizeof(SCARD_IO_REQUEST));
02769         memcpy(scTransmitStruct.pbSendBuffer, pbSendBuffer, cbSendLength);
02770 
02771         if (pioRecvPci)
02772         {
02773             memcpy(&scTransmitStruct.pioRecvPci, pioRecvPci,
02774                 sizeof(SCARD_IO_REQUEST));
02775         }
02776         else
02777             scTransmitStruct.pioRecvPci.dwProtocol = SCARD_PROTOCOL_ANY;
02778 
02779         rv = WrapSHMWrite(SCARD_TRANSMIT,
02780             psContextMap[dwContextIndex].dwClientID, sizeof(scTransmitStruct),
02781             PCSCLITE_CLIENT_ATTEMPTS, (void *) &scTransmitStruct);
02782 
02783         if (rv == -1)
02784         {
02785             SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02786             return SCARD_E_NO_SERVICE;
02787         }
02788 
02789         /*
02790          * Read a message from the server
02791          */
02792         rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
02793 
02794         memcpy(&scTransmitStruct, &msgStruct.data, sizeof(scTransmitStruct));
02795 
02796         if (rv == -1)
02797         {
02798             SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02799             return SCARD_F_COMM_ERROR;
02800         }
02801 
02802         /*
02803          * Zero it and free it so any secret information cannot be leaked
02804          */
02805         memset(scTransmitStruct.pbSendBuffer, 0x00, cbSendLength);
02806 
02807         if (scTransmitStruct.rv == SCARD_S_SUCCESS)
02808         {
02809             /*
02810              * Copy and zero it so any secret information is not leaked
02811              */
02812             memcpy(pbRecvBuffer, scTransmitStruct.pbRecvBuffer,
02813                 scTransmitStruct.pcbRecvLength);
02814             memset(scTransmitStruct.pbRecvBuffer, 0x00,
02815                 scTransmitStruct.pcbRecvLength);
02816 
02817             if (pioRecvPci)
02818                 memcpy(pioRecvPci, &scTransmitStruct.pioRecvPci,
02819                     sizeof(SCARD_IO_REQUEST));
02820         }
02821 
02822         *pcbRecvLength = scTransmitStruct.pcbRecvLength;
02823         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02824 
02825         rv = scTransmitStruct.rv;
02826     }
02827 
02828     PROFILE_END
02829 
02830     return rv;
02831 }
02832 
02862 LONG SCardListReaders(SCARDCONTEXT hContext, LPCSTR mszGroups,
02863     LPSTR mszReaders, LPDWORD pcchReaders)
02864 {
02865     DWORD dwReadersLen;
02866     int i, lastChrPtr;
02867     LONG dwContextIndex;
02868 
02869     PROFILE_START
02870 
02871     /*
02872      * Check for NULL parameters
02873      */
02874     if (pcchReaders == NULL)
02875         return SCARD_E_INVALID_PARAMETER;
02876 
02877     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
02878         return SCARD_E_NO_SERVICE;
02879 
02880     /*
02881      * Make sure this context has been opened
02882      */
02883     dwContextIndex = SCardGetContextIndice(hContext);
02884     if (dwContextIndex == -1)
02885         return SCARD_E_INVALID_HANDLE;
02886 
02887     SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
02888 
02889     dwReadersLen = 0;
02890     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
02891         if ((readerStates[i])->readerID != 0)
02892             dwReadersLen += strlen((readerStates[i])->readerName) + 1;
02893 
02894     /* for the last NULL byte */
02895     dwReadersLen += 1;
02896 
02897     if ((mszReaders == NULL)    /* text array not allocated */
02898         || (*pcchReaders == 0)) /* size == 0 */
02899     {
02900         *pcchReaders = dwReadersLen;
02901         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02902         return SCARD_S_SUCCESS;
02903     }
02904 
02905     if (*pcchReaders < dwReadersLen)
02906     {
02907         *pcchReaders = dwReadersLen;
02908         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02909         return SCARD_E_INSUFFICIENT_BUFFER;
02910     }
02911 
02912     lastChrPtr = 0;
02913     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
02914     {
02915         if ((readerStates[i])->readerID != 0)
02916         {
02917             /*
02918              * Build the multi-string
02919              */
02920             strcpy(&mszReaders[lastChrPtr], (readerStates[i])->readerName);
02921             lastChrPtr += strlen((readerStates[i])->readerName)+1;
02922         }
02923     }
02924     mszReaders[lastChrPtr] = '\0';  /* Add the last null */
02925 
02926     *pcchReaders = dwReadersLen;
02927 
02928     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02929 
02930     PROFILE_END
02931 
02932     return SCARD_S_SUCCESS;
02933 }
02934 
02966 LONG SCardListReaderGroups(SCARDCONTEXT hContext, LPSTR mszGroups,
02967     LPDWORD pcchGroups)
02968 {
02969     LONG rv = SCARD_S_SUCCESS;
02970     LONG dwContextIndex;
02971 
02972     PROFILE_START
02973 
02974     const char ReaderGroup[] = "SCard$DefaultReaders";
02975     const int dwGroups = strlen(ReaderGroup) + 2;
02976 
02977     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
02978         return SCARD_E_NO_SERVICE;
02979 
02980     /*
02981      * Make sure this context has been opened
02982      */
02983     dwContextIndex = SCardGetContextIndice(hContext);
02984     if (dwContextIndex == -1)
02985         return SCARD_E_INVALID_HANDLE;
02986 
02987     SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
02988 
02989     if (mszGroups)
02990     {
02991 
02992         if (*pcchGroups < dwGroups)
02993             rv = SCARD_E_INSUFFICIENT_BUFFER;
02994         else
02995         {
02996             memset(mszGroups, 0, dwGroups);
02997             memcpy(mszGroups, ReaderGroup, strlen(ReaderGroup));
02998         }
02999     }
03000 
03001     *pcchGroups = dwGroups;
03002 
03003     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
03004 
03005     PROFILE_END
03006 
03007     return rv;
03008 }
03009 
03037 LONG SCardCancel(SCARDCONTEXT hContext)
03038 {
03039     LONG dwContextIndex;
03040 
03041     PROFILE_START
03042 
03043     dwContextIndex = SCardGetContextIndice(hContext);
03044 
03045     if (dwContextIndex == -1)
03046         return SCARD_E_INVALID_HANDLE;
03047 
03048     /*
03049      * Set the block status for this Context so blocking calls will
03050      * complete
03051      */
03052     psContextMap[dwContextIndex].contextBlockStatus = BLOCK_STATUS_RESUME;
03053 
03054     PROFILE_END
03055 
03056     return SCARD_S_SUCCESS;
03057 }
03058 
03082 LONG SCardIsValidContext(SCARDCONTEXT hContext)
03083 {
03084     LONG rv;
03085     LONG dwContextIndex;
03086 
03087     PROFILE_START
03088 
03089     rv = SCARD_S_SUCCESS;
03090 
03091     /*
03092      * Make sure this context has been opened
03093      */
03094     dwContextIndex = SCardGetContextIndice(hContext);
03095     if (dwContextIndex == -1)
03096         rv = SCARD_E_INVALID_HANDLE;
03097 
03098     PROFILE_END
03099 
03100     return rv;
03101 }
03102 
03119 static LONG SCardAddContext(SCARDCONTEXT hContext, DWORD dwClientID)
03120 {
03121     int i;
03122 
03123     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
03124     {
03125         if (psContextMap[i].hContext == 0)
03126         {
03127             psContextMap[i].hContext = hContext;
03128             psContextMap[i].dwClientID = dwClientID;
03129             psContextMap[i].contextBlockStatus = BLOCK_STATUS_RESUME;
03130             psContextMap[i].mMutex = malloc(sizeof(PCSCLITE_MUTEX));
03131             SYS_MutexInit(psContextMap[i].mMutex);
03132             return SCARD_S_SUCCESS;
03133         }
03134     }
03135 
03136     return SCARD_E_NO_MEMORY;
03137 }
03138 
03151 static LONG SCardGetContextIndice(SCARDCONTEXT hContext)
03152 {
03153     LONG rv;
03154 
03155     SCardLockThread();
03156     rv = SCardGetContextIndiceTH(hContext);
03157     SCardUnlockThread();
03158 
03159     return rv;
03160 }
03161 
03174 static LONG SCardGetContextIndiceTH(SCARDCONTEXT hContext)
03175 {
03176     int i;
03177 
03178     /*
03179      * Find this context and return it's spot in the array
03180      */
03181     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
03182     {
03183         if ((hContext == psContextMap[i].hContext) && (hContext != 0))
03184             return i;
03185     }
03186 
03187     return -1;
03188 }
03189 
03199 static LONG SCardRemoveContext(SCARDCONTEXT hContext)
03200 {
03201     LONG  retIndice;
03202 
03203     retIndice = SCardGetContextIndiceTH(hContext);
03204 
03205     if (retIndice == -1)
03206         return SCARD_E_INVALID_HANDLE;
03207     else
03208     {
03209         int i;
03210 
03211         psContextMap[retIndice].hContext = 0;
03212         SHMClientCloseSession(psContextMap[retIndice].dwClientID);
03213         psContextMap[retIndice].dwClientID = 0;
03214         free(psContextMap[retIndice].mMutex);
03215         psContextMap[retIndice].mMutex = NULL;
03216         psContextMap[retIndice].contextBlockStatus = BLOCK_STATUS_RESUME;
03217 
03218         for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
03219         {
03220             /*
03221              * Reset the \c hCard structs to zero
03222              */
03223             psContextMap[retIndice].psChannelMap[i].hCard = 0;
03224             free(psContextMap[retIndice].psChannelMap[i].readerName);
03225             psContextMap[retIndice].psChannelMap[i].readerName = NULL;
03226         }
03227 
03228         return SCARD_S_SUCCESS;
03229     }
03230 }
03231 
03232 /*
03233  * Functions for managing hCard values returned from SCardConnect.
03234  */
03235 
03236 static LONG SCardAddHandle(SCARDHANDLE hCard, DWORD dwContextIndex,
03237     LPSTR readerName)
03238 {
03239     int i;
03240 
03241     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
03242     {
03243         if (psContextMap[dwContextIndex].psChannelMap[i].hCard == 0)
03244         {
03245             psContextMap[dwContextIndex].psChannelMap[i].hCard = hCard;
03246             psContextMap[dwContextIndex].psChannelMap[i].readerName = strdup(readerName);
03247             return SCARD_S_SUCCESS;
03248         }
03249     }
03250 
03251     return SCARD_E_NO_MEMORY;
03252 }
03253 
03254 static LONG SCardRemoveHandle(SCARDHANDLE hCard)
03255 {
03256     DWORD dwContextIndice, dwChannelIndice;
03257     LONG rv;
03258 
03259     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndice, &dwChannelIndice);
03260 
03261     if (rv == -1)
03262         return SCARD_E_INVALID_HANDLE;
03263     else
03264     {
03265         psContextMap[dwContextIndice].psChannelMap[dwChannelIndice].hCard = 0;
03266         free(psContextMap[dwContextIndice].psChannelMap[dwChannelIndice].readerName);
03267         psContextMap[dwContextIndice].psChannelMap[dwChannelIndice].readerName = NULL;
03268         return SCARD_S_SUCCESS;
03269     }
03270 }
03271 
03272 static LONG SCardGetIndicesFromHandle(SCARDHANDLE hCard, PDWORD pdwContextIndice, PDWORD pdwChannelIndice)
03273 {
03274     LONG rv;
03275 
03276     if (0 == hCard)
03277         return -1;
03278 
03279     SCardLockThread();
03280     rv = SCardGetIndicesFromHandleTH(hCard, pdwContextIndice, pdwChannelIndice);
03281     SCardUnlockThread();
03282 
03283     return rv;
03284 }
03285 
03286 static LONG SCardGetIndicesFromHandleTH(SCARDHANDLE hCard, PDWORD pdwContextIndice, PDWORD pdwChannelIndice)
03287 {
03288     int i;
03289 
03290     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
03291     {
03292         if (psContextMap[i].hContext != 0)
03293         {
03294             int j;
03295 
03296             for (j = 0; j < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; j++)
03297             {
03298                 if (psContextMap[i].psChannelMap[j].hCard == hCard)
03299                 {
03300                     *pdwContextIndice = i;
03301                     *pdwChannelIndice = j;
03302                     return SCARD_S_SUCCESS;
03303                 }
03304             }
03305 
03306         }
03307     }
03308 
03309     return -1;
03310 }
03311 
03318 inline static LONG SCardLockThread(void)
03319 {
03320     return SYS_MutexLock(&clientMutex);
03321 }
03322 
03328 inline static LONG SCardUnlockThread(void)
03329 {
03330     return SYS_MutexUnLock(&clientMutex);
03331 }
03332 
03340 static LONG SCardCheckDaemonAvailability(void)
03341 {
03342     LONG rv;
03343     struct stat statBuffer;
03344 
03345     rv = SYS_Stat(PCSCLITE_PUBSHM_FILE, &statBuffer);
03346 
03347     if (rv != 0)
03348     {
03349         Log1(PCSC_LOG_ERROR, "PCSC Not Running");
03350         return SCARD_E_NO_SERVICE;
03351     }
03352 
03353     return SCARD_S_SUCCESS;
03354 }
03355 
03361 #ifdef __SUNPRO_C
03362 #pragma fini (SCardUnload)
03363 #endif
03364 
03365 void DESTRUCTOR SCardUnload(void)
03366 {
03367     int i;
03368 
03369     if (!isExecuted)
03370         return;
03371 
03372     /* unmap public shared file from memory */
03373     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
03374     {
03375         if (readerStates[i] != NULL)
03376         {
03377             SYS_PublicMemoryUnmap(readerStates[i], sizeof(READER_STATE));
03378             readerStates[i] = NULL;
03379         }
03380     }
03381 
03382     SYS_CloseFile(mapAddr);
03383     isExecuted = 0;
03384 }
03385 

Generated on Mon Mar 5 22:33:03 2007 for pcsc-lite by  doxygen 1.4.7