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 1958 2006-03-21 14:00:35Z 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     LPTSTR 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, LPTSTR);
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] = (PREADER_STATE)
00332                 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, 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, 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         isExecuted = 1;
00424     }
00425 
00426 
00427     if (dwScope != SCARD_SCOPE_USER && dwScope != SCARD_SCOPE_TERMINAL &&
00428         dwScope != SCARD_SCOPE_SYSTEM && dwScope != SCARD_SCOPE_GLOBAL)
00429     {
00430         return SCARD_E_INVALID_VALUE;
00431     }
00432 
00433     /*
00434      * Try to establish an Application Context with the server
00435      */
00436     scEstablishStruct.dwScope = dwScope;
00437     scEstablishStruct.phContext = 0;
00438     scEstablishStruct.rv = 0;
00439 
00440     rv = WrapSHMWrite(SCARD_ESTABLISH_CONTEXT, dwClientID,
00441         sizeof(scEstablishStruct), PCSCLITE_MCLIENT_ATTEMPTS,
00442         (void *) &scEstablishStruct);
00443 
00444     if (rv == -1)
00445         return SCARD_E_NO_SERVICE;
00446 
00447     /*
00448      * Read the response from the server
00449      */
00450     rv = SHMClientRead(&msgStruct, dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
00451 
00452     if (rv == -1)
00453         return SCARD_F_COMM_ERROR;
00454 
00455     memcpy(&scEstablishStruct, &msgStruct.data, sizeof(scEstablishStruct));
00456 
00457     if (scEstablishStruct.rv != SCARD_S_SUCCESS)
00458         return scEstablishStruct.rv;
00459 
00460     *phContext = scEstablishStruct.phContext;
00461 
00462     /*
00463      * Allocate the new hContext - if allocator full return an error
00464      */
00465     rv = SCardAddContext(*phContext, dwClientID);
00466 
00467     return rv;
00468 }
00469 
00488 LONG SCardReleaseContext(SCARDCONTEXT hContext)
00489 {
00490     LONG rv;
00491     release_struct scReleaseStruct;
00492     sharedSegmentMsg msgStruct;
00493     DWORD dwContextIndex;
00494 
00495     PROFILE_START
00496 
00497     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
00498         return SCARD_E_NO_SERVICE;
00499 
00500     /*
00501      * Make sure this context has been opened
00502      */
00503     dwContextIndex = SCardGetContextIndice(hContext);
00504     if (dwContextIndex == -1)
00505         return SCARD_E_INVALID_HANDLE;
00506 
00507     SYS_MutexLock(psContextMap[dwContextIndex].mMutex); 
00508 
00509     scReleaseStruct.hContext = hContext;
00510     scReleaseStruct.rv = 0;
00511 
00512     rv = WrapSHMWrite(SCARD_RELEASE_CONTEXT, psContextMap[dwContextIndex].dwClientID,
00513               sizeof(scReleaseStruct),
00514               PCSCLITE_MCLIENT_ATTEMPTS, (void *) &scReleaseStruct);
00515 
00516     if (rv == -1)
00517     {
00518         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
00519         return SCARD_E_NO_SERVICE;
00520     }
00521 
00522     /*
00523      * Read a message from the server
00524      */
00525     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
00526     memcpy(&scReleaseStruct, &msgStruct.data, sizeof(scReleaseStruct));
00527 
00528     if (rv == -1)
00529     {
00530         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
00531         return SCARD_F_COMM_ERROR;
00532     }
00533     
00534     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
00535 
00536     /*
00537      * Remove the local context from the stack
00538      */
00539     SCardLockThread();
00540     SCardRemoveContext(hContext);
00541     SCardUnlockThread();
00542 
00543     PROFILE_END
00544 
00545     return scReleaseStruct.rv;
00546 }
00547 
00560 LONG SCardSetTimeout(SCARDCONTEXT hContext, DWORD dwTimeout)
00561 {
00562     /*
00563      * Deprecated
00564      */
00565 
00566     return SCARD_S_SUCCESS;
00567 }
00568 
00617 LONG SCardConnect(SCARDCONTEXT hContext, LPCTSTR szReader,
00618     DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard,
00619     LPDWORD pdwActiveProtocol)
00620 {
00621     LONG rv;
00622     connect_struct scConnectStruct;
00623     sharedSegmentMsg msgStruct;
00624     DWORD dwContextIndex;
00625 
00626     PROFILE_START
00627 
00628     /*
00629      * Check for NULL parameters
00630      */
00631     if (phCard == NULL || pdwActiveProtocol == NULL)
00632         return SCARD_E_INVALID_PARAMETER;
00633     else
00634         *phCard = 0;
00635 
00636     if (szReader == NULL)
00637         return SCARD_E_UNKNOWN_READER;
00638 
00639     /*
00640      * Check for uninitialized strings
00641      */
00642     if (strlen(szReader) > MAX_READERNAME)
00643         return SCARD_E_INVALID_VALUE;
00644 
00645     if (!(dwPreferredProtocols & SCARD_PROTOCOL_T0) &&
00646         !(dwPreferredProtocols & SCARD_PROTOCOL_T1) &&
00647         !(dwPreferredProtocols & SCARD_PROTOCOL_RAW) &&
00648         !(dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD))
00649     {
00650         return SCARD_E_INVALID_VALUE;
00651     }
00652 
00653     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
00654         return SCARD_E_NO_SERVICE;
00655 
00656     /*
00657      * Make sure this context has been opened
00658      */
00659     dwContextIndex = SCardGetContextIndice(hContext);
00660     if (dwContextIndex == -1)
00661         return SCARD_E_INVALID_HANDLE;
00662 
00663     SYS_MutexLock(psContextMap[dwContextIndex].mMutex); 
00664 
00665     strncpy(scConnectStruct.szReader, szReader, MAX_READERNAME);
00666 
00667     scConnectStruct.hContext = hContext;
00668     scConnectStruct.dwShareMode = dwShareMode;
00669     scConnectStruct.dwPreferredProtocols = dwPreferredProtocols;
00670     scConnectStruct.phCard = *phCard;
00671     scConnectStruct.pdwActiveProtocol = *pdwActiveProtocol;
00672 
00673     rv = WrapSHMWrite(SCARD_CONNECT, psContextMap[dwContextIndex].dwClientID,
00674         sizeof(scConnectStruct),
00675         PCSCLITE_CLIENT_ATTEMPTS, (void *) &scConnectStruct);
00676 
00677     if (rv == -1)
00678     {
00679         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
00680         return SCARD_E_NO_SERVICE;
00681     }
00682 
00683     /*
00684      * Read a message from the server
00685      */
00686     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
00687 
00688     memcpy(&scConnectStruct, &msgStruct.data, sizeof(scConnectStruct));
00689 
00690     if (rv == -1)
00691     {
00692         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
00693         return SCARD_F_COMM_ERROR;
00694     }
00695 
00696     *phCard = scConnectStruct.phCard;
00697     *pdwActiveProtocol = scConnectStruct.pdwActiveProtocol;
00698 
00699     if (scConnectStruct.rv == SCARD_S_SUCCESS)
00700     {
00701         /*
00702          * Keep track of the handle locally
00703          */
00704         rv = SCardAddHandle(*phCard, dwContextIndex, (LPTSTR) szReader);
00705         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
00706 
00707         PROFILE_END
00708 
00709         return rv;
00710     }
00711 
00712     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
00713 
00714     PROFILE_END
00715 
00716     return scConnectStruct.rv;
00717 }
00718 
00784 LONG SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode,
00785     DWORD dwPreferredProtocols, DWORD dwInitialization,
00786     LPDWORD pdwActiveProtocol)
00787 {
00788     LONG rv;
00789     reconnect_struct scReconnectStruct;
00790     sharedSegmentMsg msgStruct;
00791     int i;
00792     DWORD dwContextIndex, dwChannelIndex;
00793 
00794     PROFILE_START
00795 
00796     if (dwInitialization != SCARD_LEAVE_CARD &&
00797         dwInitialization != SCARD_RESET_CARD &&
00798         dwInitialization != SCARD_UNPOWER_CARD &&
00799         dwInitialization != SCARD_EJECT_CARD)
00800     {
00801         return SCARD_E_INVALID_VALUE;
00802     }
00803 
00804     if (!(dwPreferredProtocols & SCARD_PROTOCOL_T0) &&
00805         !(dwPreferredProtocols & SCARD_PROTOCOL_T1) &&
00806         !(dwPreferredProtocols & SCARD_PROTOCOL_RAW) &&
00807         !(dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD))
00808     {
00809         return SCARD_E_INVALID_VALUE;
00810     }
00811 
00812     if (pdwActiveProtocol == NULL)
00813         return SCARD_E_INVALID_PARAMETER;
00814 
00815     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
00816         return SCARD_E_NO_SERVICE;
00817 
00818     /*
00819      * Make sure this handle has been opened
00820      */
00821     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
00822 
00823     if (rv == -1)
00824         return SCARD_E_INVALID_HANDLE;
00825 
00826     SYS_MutexLock(psContextMap[dwContextIndex].mMutex); 
00827 
00828 
00829     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
00830     {
00831         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
00832 
00833         /* by default r == NULL */
00834         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
00835             break;
00836     }
00837 
00838     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
00839     {
00840         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
00841         return SCARD_E_READER_UNAVAILABLE;
00842     }
00843 
00844     scReconnectStruct.hCard = hCard;
00845     scReconnectStruct.dwShareMode = dwShareMode;
00846     scReconnectStruct.dwPreferredProtocols = dwPreferredProtocols;
00847     scReconnectStruct.dwInitialization = dwInitialization;
00848     scReconnectStruct.pdwActiveProtocol = *pdwActiveProtocol;
00849 
00850     rv = WrapSHMWrite(SCARD_RECONNECT, psContextMap[dwContextIndex].dwClientID,
00851         sizeof(scReconnectStruct),
00852         PCSCLITE_CLIENT_ATTEMPTS, (void *) &scReconnectStruct);
00853 
00854     if (rv == -1)
00855     {
00856         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
00857         return SCARD_E_NO_SERVICE;
00858     }
00859 
00860     /*
00861      * Read a message from the server
00862      */
00863     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
00864 
00865     memcpy(&scReconnectStruct, &msgStruct.data, sizeof(scReconnectStruct));
00866 
00867     if (rv == -1)
00868     {
00869         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
00870         return SCARD_F_COMM_ERROR;
00871     }
00872 
00873     *pdwActiveProtocol = scReconnectStruct.pdwActiveProtocol;
00874 
00875     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
00876 
00877     PROFILE_END
00878     
00879     return scReconnectStruct.rv;
00880 }
00881 
00912 LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
00913 {
00914     LONG rv;
00915     disconnect_struct scDisconnectStruct;
00916     sharedSegmentMsg msgStruct;
00917     DWORD dwContextIndex, dwChannelIndex;
00918 
00919     PROFILE_START
00920 
00921     if (dwDisposition != SCARD_LEAVE_CARD &&
00922         dwDisposition != SCARD_RESET_CARD &&
00923         dwDisposition != SCARD_UNPOWER_CARD &&
00924         dwDisposition != SCARD_EJECT_CARD)
00925     {
00926         return SCARD_E_INVALID_VALUE;
00927     }
00928 
00929     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
00930         return SCARD_E_NO_SERVICE;
00931 
00932     /*
00933      * Make sure this handle has been opened
00934      */
00935     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
00936 
00937     if (rv == -1)
00938         return SCARD_E_INVALID_HANDLE;
00939 
00940     SYS_MutexLock(psContextMap[dwContextIndex].mMutex); 
00941 
00942     scDisconnectStruct.hCard = hCard;
00943     scDisconnectStruct.dwDisposition = dwDisposition;
00944 
00945     rv = WrapSHMWrite(SCARD_DISCONNECT, psContextMap[dwContextIndex].dwClientID,
00946         sizeof(scDisconnectStruct),
00947         PCSCLITE_CLIENT_ATTEMPTS, (void *) &scDisconnectStruct);
00948 
00949     if (rv == -1)
00950     {
00951         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
00952         return SCARD_E_NO_SERVICE;
00953     }
00954 
00955     /*
00956      * Read a message from the server
00957      */
00958     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
00959 
00960     memcpy(&scDisconnectStruct, &msgStruct.data,
00961         sizeof(scDisconnectStruct));
00962 
00963     if (rv == -1)
00964     {
00965         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
00966         return SCARD_F_COMM_ERROR;
00967     }
00968 
00969     SCardRemoveHandle(hCard);
00970 
00971     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
00972 
00973     PROFILE_END
00974 
00975     return scDisconnectStruct.rv;
00976 }
00977 
01010 LONG SCardBeginTransaction(SCARDHANDLE hCard)
01011 {
01012 
01013     LONG rv;
01014     begin_struct scBeginStruct;
01015     int i;
01016     sharedSegmentMsg msgStruct;
01017     DWORD dwContextIndex, dwChannelIndex;
01018 
01019     PROFILE_START
01020 
01021     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
01022         return SCARD_E_NO_SERVICE;
01023 
01024     /*
01025      * Make sure this handle has been opened
01026      */
01027     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01028 
01029     if (rv == -1)
01030         return SCARD_E_INVALID_HANDLE;
01031 
01032     SYS_MutexLock(psContextMap[dwContextIndex].mMutex); 
01033 
01034     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01035     {
01036         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
01037 
01038         /* by default r == NULL */
01039         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
01040             break;
01041     }
01042 
01043     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
01044     {
01045         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
01046         return SCARD_E_READER_UNAVAILABLE;
01047     }
01048 
01049     scBeginStruct.hCard = hCard;
01050 
01051     /*
01052      * Query the server every so often until the sharing violation ends
01053      * and then hold the lock for yourself.
01054      */
01055 
01056     do
01057     {
01058         /*
01059          * Look to see if it is locked before polling the server for
01060          * admission to the readers resources
01061          */
01062         if ((readerStates[i])->lockState != 0)
01063         {
01064             int randnum = 0;
01065             int j;
01066 
01067             for (j = 0; j < 100; j++)
01068             {
01069                 /*
01070                  * This helps prevent starvation
01071                  */
01072                 randnum = SYS_RandomInt(1000, 10000);
01073                 SYS_USleep(randnum);
01074 
01075                 if ((readerStates[i])->lockState == 0)
01076                 {
01077                     break;
01078                 }
01079             }
01080         }
01081 
01082         rv = WrapSHMWrite(SCARD_BEGIN_TRANSACTION, psContextMap[dwContextIndex].dwClientID,
01083             sizeof(scBeginStruct),
01084             PCSCLITE_CLIENT_ATTEMPTS, (void *) &scBeginStruct);
01085 
01086         if (rv == -1)
01087         {
01088             
01089             SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
01090             return SCARD_E_NO_SERVICE;
01091         }
01092 
01093         /*
01094          * Read a message from the server
01095          */
01096         rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
01097 
01098 
01099         memcpy(&scBeginStruct, &msgStruct.data, sizeof(scBeginStruct));
01100 
01101         if (rv == -1)
01102         {
01103             
01104             SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
01105             return SCARD_F_COMM_ERROR;
01106         }
01107 
01108     }
01109     while (scBeginStruct.rv == SCARD_E_SHARING_VIOLATION);
01110 
01111     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
01112 
01113     PROFILE_END
01114 
01115     return scBeginStruct.rv;
01116 }
01117 
01156 LONG SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
01157 {
01158     LONG rv;
01159     end_struct scEndStruct;
01160     sharedSegmentMsg msgStruct;
01161     int randnum, i;
01162     DWORD dwContextIndex, dwChannelIndex;
01163 
01164     PROFILE_START
01165 
01166     /*
01167      * Zero out everything
01168      */
01169     randnum = 0;
01170 
01171     if (dwDisposition != SCARD_LEAVE_CARD &&
01172         dwDisposition != SCARD_RESET_CARD &&
01173         dwDisposition != SCARD_UNPOWER_CARD &&
01174         dwDisposition != SCARD_EJECT_CARD)
01175     {
01176         return SCARD_E_INVALID_VALUE;
01177     }
01178 
01179     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
01180         return SCARD_E_NO_SERVICE;
01181 
01182     /*
01183      * Make sure this handle has been opened
01184      */
01185     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01186 
01187     if (rv == -1)
01188         return SCARD_E_INVALID_HANDLE;
01189 
01190     SYS_MutexLock(psContextMap[dwContextIndex].mMutex); 
01191 
01192     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01193     {
01194         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
01195 
01196         /* by default r == NULL */
01197         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
01198             break;
01199     }
01200 
01201     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
01202     {
01203         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
01204         return SCARD_E_READER_UNAVAILABLE;
01205     }
01206 
01207     scEndStruct.hCard = hCard;
01208     scEndStruct.dwDisposition = dwDisposition;
01209 
01210     rv = WrapSHMWrite(SCARD_END_TRANSACTION, psContextMap[dwContextIndex].dwClientID,
01211         sizeof(scEndStruct),
01212         PCSCLITE_CLIENT_ATTEMPTS, (void *) &scEndStruct);
01213 
01214     if (rv == -1)
01215     {
01216         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
01217         return SCARD_E_NO_SERVICE;
01218     }
01219 
01220     /*
01221      * Read a message from the server
01222      */
01223     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
01224 
01225     memcpy(&scEndStruct, &msgStruct.data, sizeof(scEndStruct));
01226 
01227     if (rv == -1)
01228     {
01229         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
01230         return SCARD_F_COMM_ERROR;
01231     }
01232 
01233     /*
01234      * This helps prevent starvation
01235      */
01236     randnum = SYS_RandomInt(1000, 10000);
01237     SYS_USleep(randnum);
01238 
01239     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
01240 
01241     PROFILE_END
01242 
01243     return scEndStruct.rv;
01244 }
01245 
01251 LONG SCardCancelTransaction(SCARDHANDLE hCard)
01252 {
01253     LONG rv;
01254     cancel_struct scCancelStruct;
01255     sharedSegmentMsg msgStruct;
01256     int i;
01257     DWORD dwContextIndex, dwChannelIndex;
01258 
01259     PROFILE_START
01260 
01261     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
01262         return SCARD_E_NO_SERVICE;
01263 
01264     /*
01265      * Make sure this handle has been opened
01266      */
01267     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01268 
01269     if (rv == -1)
01270         return SCARD_E_INVALID_HANDLE;
01271 
01272     SYS_MutexLock(psContextMap[dwContextIndex].mMutex); 
01273 
01274     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01275     {
01276         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
01277 
01278         /* by default r == NULL */
01279         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
01280             break;
01281     }
01282 
01283     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
01284     {
01285         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
01286         return SCARD_E_READER_UNAVAILABLE;
01287     }
01288 
01289     scCancelStruct.hCard = hCard;
01290 
01291     rv = WrapSHMWrite(SCARD_CANCEL_TRANSACTION, psContextMap[dwContextIndex].dwClientID,
01292         sizeof(scCancelStruct),
01293         PCSCLITE_CLIENT_ATTEMPTS, (void *) &scCancelStruct);
01294 
01295     if (rv == -1)
01296     {
01297         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
01298         return SCARD_E_NO_SERVICE;
01299     }
01300 
01301     /*
01302      * Read a message from the server
01303      */
01304     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
01305 
01306     memcpy(&scCancelStruct, &msgStruct.data, sizeof(scCancelStruct));
01307 
01308     if (rv == -1)
01309     {
01310         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
01311         return SCARD_F_COMM_ERROR;
01312     }
01313 
01314     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
01315 
01316     PROFILE_END
01317 
01318     return scCancelStruct.rv;
01319 }
01320 
01377 LONG SCardStatus(SCARDHANDLE hCard, LPTSTR mszReaderNames,
01378     LPDWORD pcchReaderLen, LPDWORD pdwState,
01379     LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
01380 {
01381     DWORD dwReaderLen, dwAtrLen;
01382     LONG rv;
01383     int i;
01384     status_struct scStatusStruct;
01385     sharedSegmentMsg msgStruct;
01386     DWORD dwContextIndex, dwChannelIndex;
01387 
01388     PROFILE_START
01389 
01390     /*
01391      * Check for NULL parameters
01392      */
01393 
01394     if (pcchReaderLen == NULL || pcbAtrLen == NULL)
01395         return SCARD_E_INVALID_PARAMETER;
01396 
01397     /* length passed from caller */
01398     dwReaderLen = *pcchReaderLen;
01399     dwAtrLen = *pcbAtrLen;
01400 
01401     /* default output values */
01402     if (pdwState)
01403         *pdwState = 0;
01404 
01405     if (pdwProtocol)
01406         *pdwProtocol = 0;
01407 
01408     *pcchReaderLen = 0;
01409     *pcbAtrLen = 0;
01410 
01411     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
01412         return SCARD_E_NO_SERVICE;
01413 
01414     /*
01415      * Make sure this handle has been opened
01416      */
01417     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01418 
01419     if (rv == -1)
01420         return SCARD_E_INVALID_HANDLE;
01421 
01422     SYS_MutexLock(psContextMap[dwContextIndex].mMutex); 
01423 
01424     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01425     {
01426         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
01427 
01428         /* by default r == NULL */
01429         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
01430             break;
01431     }
01432 
01433     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
01434     {
01435         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
01436         return SCARD_E_READER_UNAVAILABLE;
01437     }
01438 
01439     /* initialise the structure */
01440     memset(&scStatusStruct, 0, sizeof(scStatusStruct));
01441     scStatusStruct.hCard = hCard;
01442 
01443     /* those sizes need to be initialised */
01444     scStatusStruct.pcchReaderLen = sizeof(scStatusStruct.mszReaderNames);
01445     scStatusStruct.pcbAtrLen = sizeof(scStatusStruct.pbAtr);
01446 
01447     rv = WrapSHMWrite(SCARD_STATUS, psContextMap[dwContextIndex].dwClientID,
01448         sizeof(scStatusStruct),
01449         PCSCLITE_CLIENT_ATTEMPTS, (void *) &scStatusStruct);
01450 
01451     if (rv == -1)
01452     {
01453         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
01454         return SCARD_E_NO_SERVICE;
01455     }
01456 
01457     /*
01458      * Read a message from the server
01459      */
01460     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
01461 
01462     memcpy(&scStatusStruct, &msgStruct.data, sizeof(scStatusStruct));
01463 
01464     if (rv == -1)
01465     {
01466         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
01467         return SCARD_F_COMM_ERROR;
01468     }
01469 
01470     rv = scStatusStruct.rv;
01471     if (rv != SCARD_S_SUCCESS && rv != SCARD_E_INSUFFICIENT_BUFFER)
01472     {
01473         /*
01474          * An event must have occurred
01475          */
01476         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
01477         return rv;
01478     }
01479 
01480     /*
01481      * Now continue with the client side SCardStatus
01482      */
01483 
01484     *pcchReaderLen = strlen(psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName) + 1;
01485     *pcbAtrLen = (readerStates[i])->cardAtrLength;
01486 
01487     if (pdwState)
01488         *pdwState = (readerStates[i])->readerState;
01489 
01490     if (pdwProtocol)
01491         *pdwProtocol = (readerStates[i])->cardProtocol;
01492 
01493     /* return SCARD_E_INSUFFICIENT_BUFFER only if buffer pointer is non NULL */
01494     if (mszReaderNames)
01495     {
01496         if (*pcchReaderLen > dwReaderLen)
01497             rv = SCARD_E_INSUFFICIENT_BUFFER;
01498 
01499         strncpy(mszReaderNames, 
01500             psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName, 
01501             dwReaderLen);
01502     }
01503 
01504     if (pbAtr)
01505     {
01506         if (*pcbAtrLen > dwAtrLen)
01507             rv = SCARD_E_INSUFFICIENT_BUFFER;
01508 
01509         memcpy(pbAtr, (readerStates[i])->cardAtr,
01510             min(*pcbAtrLen, dwAtrLen));
01511     }
01512     
01513     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
01514 
01515     PROFILE_END
01516 
01517     return rv;
01518 }
01519 
01605 LONG SCardGetStatusChange(SCARDCONTEXT hContext, DWORD dwTimeout,
01606     LPSCARD_READERSTATE_A rgReaderStates, DWORD cReaders)
01607 {
01608     PSCARD_READERSTATE_A currReader;
01609     PREADER_STATE rContext;
01610     DWORD dwTime = 0;
01611     DWORD dwState;
01612     DWORD dwBreakFlag = 0;
01613     int j;
01614     DWORD dwContextIndex;
01615     int currentReaderCount = 0;
01616 
01617     PROFILE_START
01618 
01619     if (rgReaderStates == NULL && cReaders > 0)
01620         return SCARD_E_INVALID_PARAMETER;
01621 
01622     if (cReaders < 0)
01623         return SCARD_E_INVALID_VALUE;
01624 
01625     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
01626         return SCARD_E_NO_SERVICE;
01627 
01628     /*
01629      * Make sure this context has been opened
01630      */
01631 
01632     dwContextIndex = SCardGetContextIndice(hContext);
01633     if (dwContextIndex == -1)
01634         return SCARD_E_INVALID_HANDLE;
01635 
01636     SYS_MutexLock(psContextMap[dwContextIndex].mMutex); 
01637 
01638     /*
01639      * Application is waiting for a reader - return the first available
01640      * reader
01641      */
01642 
01643     if (cReaders == 0)
01644     {
01645         while (1)
01646         {
01647             int i;
01648 
01649             if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
01650             {
01651                 SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
01652                 return SCARD_E_NO_SERVICE;
01653             }
01654 
01655             for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01656             {
01657                 if ((readerStates[i])->readerID != 0)
01658                 {
01659                     /*
01660                      * Reader was found
01661                      */
01662                     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
01663 
01664                     PROFILE_END
01665 
01666                     return SCARD_S_SUCCESS;
01667                 }
01668             }
01669 
01670             if (dwTimeout == 0)
01671             {
01672                 /*
01673                  * return immediately - no reader available
01674                  */
01675                 SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
01676                 return SCARD_E_READER_UNAVAILABLE;
01677             }
01678 
01679             SYS_USleep(PCSCLITE_STATUS_WAIT);
01680 
01681             if (dwTimeout != INFINITE)
01682             {
01683                 dwTime += PCSCLITE_STATUS_WAIT;
01684 
01685                 if (dwTime >= (dwTimeout * 1000))
01686                 {
01687                     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
01688 
01689                     PROFILE_END
01690 
01691                     return SCARD_E_TIMEOUT;
01692                 }
01693             }
01694         }
01695     }
01696     else
01697         if (cReaders >= PCSCLITE_MAX_READERS_CONTEXTS)
01698         {
01699             SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
01700             return SCARD_E_INVALID_VALUE;
01701         }
01702 
01703     /*
01704      * Check the integrity of the reader states structures
01705      */
01706 
01707     for (j = 0; j < cReaders; j++)
01708     {
01709         currReader = &rgReaderStates[j];
01710 
01711         if (currReader->szReader == NULL)
01712         {
01713             SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
01714             return SCARD_E_INVALID_VALUE;
01715         }
01716     }
01717 
01718     /*
01719      * End of search for readers
01720      */
01721 
01722     /*
01723      * Clear the event state for all readers
01724      */
01725     for (j = 0; j < cReaders; j++)
01726     {
01727         currReader = &rgReaderStates[j];
01728         currReader->dwEventState = 0;
01729     }
01730 
01731     /*
01732      * Now is where we start our event checking loop
01733      */
01734 
01735     Log1(PCSC_LOG_DEBUG, "Event Loop Start");
01736 
01737     psContextMap[dwContextIndex].contextBlockStatus = BLOCK_STATUS_BLOCKING;
01738 
01739     /* Get the initial reader count on the system */
01740     for (j=0; j < PCSCLITE_MAX_READERS_CONTEXTS; j++)
01741         if ((readerStates[j])->readerID != 0)
01742             currentReaderCount++;
01743 
01744     j = 0;
01745 
01746     do
01747     {
01748         int newReaderCount = 0;
01749         char ReaderCountChanged = FALSE;
01750 
01751         if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
01752         {
01753             SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
01754     
01755             PROFILE_END
01756 
01757             return SCARD_E_NO_SERVICE;
01758         }
01759 
01760         if (j == 0)
01761         {
01762             int i;
01763 
01764             for (i=0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01765                 if ((readerStates[i])->readerID != 0)
01766                     newReaderCount++;
01767 
01768             if (newReaderCount != currentReaderCount)
01769             {
01770                 Log1(PCSC_LOG_INFO, "Reader list changed");
01771                 ReaderCountChanged = TRUE;
01772                 currentReaderCount = newReaderCount;
01773             }
01774         }
01775         currReader = &rgReaderStates[j];
01776 
01777     /************ Look for IGNORED readers ****************************/
01778 
01779         if (currReader->dwCurrentState & SCARD_STATE_IGNORE)
01780         {
01781             currReader->dwEventState = SCARD_STATE_IGNORE;
01782         } else
01783         {
01784             LPTSTR lpcReaderName;
01785             int i;
01786 
01787       /************ Looks for correct readernames *********************/
01788 
01789             lpcReaderName = (char *) currReader->szReader;
01790 
01791             for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01792             {
01793                 if (strcmp(lpcReaderName,
01794                         (readerStates[i])->readerName) == 0)
01795                 {
01796                     break;
01797                 }
01798             }
01799 
01800             /*
01801              * The requested reader name is not recognized
01802              */
01803             if (i == PCSCLITE_MAX_READERS_CONTEXTS)
01804             {
01805                 if (currReader->dwCurrentState & SCARD_STATE_UNKNOWN)
01806                 {
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             } else
01820             {
01821 
01822                 /*
01823                  * The reader has come back after being away
01824                  */
01825                 if (currReader->dwCurrentState & SCARD_STATE_UNKNOWN)
01826                 {
01827                     currReader->dwEventState |= SCARD_STATE_CHANGED;
01828                     currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
01829                     dwBreakFlag = 1;
01830                 }
01831 
01832     /*****************************************************************/
01833 
01834                 /*
01835                  * Set the reader status structure
01836                  */
01837                 rContext = readerStates[i];
01838 
01839                 /*
01840                  * Now we check all the Reader States
01841                  */
01842                 dwState = rContext->readerState;
01843 
01844     /*********** Check if the reader is in the correct state ********/
01845                 if (dwState & SCARD_UNKNOWN)
01846                 {
01847                     /*
01848                      * App thinks reader is in bad state and it is
01849                      */
01850                     if (currReader->
01851                         dwCurrentState & SCARD_STATE_UNAVAILABLE)
01852                     {
01853                         currReader->dwEventState = SCARD_STATE_UNAVAILABLE;
01854                     } else
01855                     {
01856                         /*
01857                          * App thinks reader is in good state and it is
01858                          * not
01859                          */
01860                         currReader->dwEventState = SCARD_STATE_CHANGED |
01861                             SCARD_STATE_UNAVAILABLE;
01862                         dwBreakFlag = 1;
01863                     }
01864                 } else
01865                 {
01866                     /*
01867                      * App thinks reader in bad state but it is not
01868                      */
01869                     if (currReader->
01870                         dwCurrentState & SCARD_STATE_UNAVAILABLE)
01871                     {
01872                         currReader->dwEventState &=
01873                             ~SCARD_STATE_UNAVAILABLE;
01874                         currReader->dwEventState |= SCARD_STATE_CHANGED;
01875                         dwBreakFlag = 1;
01876                     }
01877                 }
01878 
01879     /********** Check for card presence in the reader **************/
01880 
01881                 if (dwState & SCARD_PRESENT)
01882                 {
01883                     /* card present but not yet powered up */
01884                     if (0 == rContext->cardAtrLength)
01885                         /* Allow the status thread to convey information */
01886                         SYS_USleep(PCSCLITE_STATUS_POLL_RATE + 10);
01887 
01888                     currReader->cbAtr = rContext->cardAtrLength;
01889                     memcpy(currReader->rgbAtr, rContext->cardAtr,
01890                         currReader->cbAtr);
01891                 } else
01892                 {
01893                     currReader->cbAtr = 0;
01894                 }
01895 
01896                 /*
01897                  * Card is now absent
01898                  */
01899                 if (dwState & SCARD_ABSENT)
01900                 {
01901                     currReader->dwEventState |= SCARD_STATE_EMPTY;
01902                     currReader->dwEventState &= ~SCARD_STATE_PRESENT;
01903                     currReader->dwEventState &= ~SCARD_STATE_UNAWARE;
01904                     currReader->dwEventState &= ~SCARD_STATE_IGNORE;
01905                     currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
01906                     currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
01907                     currReader->dwEventState &= ~SCARD_STATE_ATRMATCH;
01908                     currReader->dwEventState &= ~SCARD_STATE_MUTE;
01909                     currReader->dwEventState &= ~SCARD_STATE_INUSE;
01910 
01911                     /*
01912                      * After present the rest are assumed
01913                      */
01914                     if (currReader->dwCurrentState & SCARD_STATE_PRESENT ||
01915                         currReader->dwCurrentState & SCARD_STATE_ATRMATCH
01916                         || currReader->
01917                         dwCurrentState & SCARD_STATE_EXCLUSIVE
01918                         || currReader->dwCurrentState & SCARD_STATE_INUSE)
01919                     {
01920                         currReader->dwEventState |= SCARD_STATE_CHANGED;
01921                         dwBreakFlag = 1;
01922                     }
01923 
01924                     /*
01925                      * Card is now present
01926                      */
01927                 } else if (dwState & SCARD_PRESENT)
01928                 {
01929                     currReader->dwEventState |= SCARD_STATE_PRESENT;
01930                     currReader->dwEventState &= ~SCARD_STATE_EMPTY;
01931                     currReader->dwEventState &= ~SCARD_STATE_UNAWARE;
01932                     currReader->dwEventState &= ~SCARD_STATE_IGNORE;
01933                     currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
01934                     currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
01935                     currReader->dwEventState &= ~SCARD_STATE_MUTE;
01936 
01937                     if (currReader->dwCurrentState & SCARD_STATE_EMPTY)
01938                     {
01939                         currReader->dwEventState |= SCARD_STATE_CHANGED;
01940                         dwBreakFlag = 1;
01941                     }
01942 
01943                     if (dwState & SCARD_SWALLOWED)
01944                     {
01945                         if (currReader->dwCurrentState & SCARD_STATE_MUTE)
01946                         {
01947                             currReader->dwEventState |= SCARD_STATE_MUTE;
01948                         } else
01949                         {
01950                             currReader->dwEventState |= SCARD_STATE_MUTE;
01951                             if (currReader->dwCurrentState !=
01952                                 SCARD_STATE_UNAWARE)
01953                             {
01954                                 currReader->dwEventState |=
01955                                     SCARD_STATE_CHANGED;
01956                             }
01957                             dwBreakFlag = 1;
01958                         }
01959                     } else
01960                     {
01961                         /*
01962                          * App thinks card is mute but it is not
01963                          */
01964                         if (currReader->dwCurrentState & SCARD_STATE_MUTE)
01965                         {
01966                             currReader->dwEventState |=
01967                                 SCARD_STATE_CHANGED;
01968                             dwBreakFlag = 1;
01969                         }
01970                     }
01971                 }
01972 
01973                 /*
01974                  * Now figure out sharing modes
01975                  */
01976                 if (rContext->readerSharing == -1)
01977                 {
01978                     currReader->dwEventState |= SCARD_STATE_EXCLUSIVE;
01979                     currReader->dwEventState &= ~SCARD_STATE_INUSE;
01980                     if (currReader->dwCurrentState & SCARD_STATE_INUSE)
01981                     {
01982                         currReader->dwEventState |= SCARD_STATE_CHANGED;
01983                         dwBreakFlag = 1;
01984                     }
01985                 } else if (rContext->readerSharing >= 1)
01986                 {
01987                     /*
01988                      * A card must be inserted for it to be INUSE
01989                      */
01990                     if (dwState & SCARD_PRESENT)
01991                     {
01992                         currReader->dwEventState |= SCARD_STATE_INUSE;
01993                         currReader->dwEventState &= ~SCARD_STATE_EXCLUSIVE;
01994                         if (currReader->
01995                             dwCurrentState & SCARD_STATE_EXCLUSIVE)
01996                         {
01997                             currReader->dwEventState |=
01998                                 SCARD_STATE_CHANGED;
01999                             dwBreakFlag = 1;
02000                         }
02001                     }
02002                 } else if (rContext->readerSharing == 0)
02003                 {
02004                     currReader->dwEventState &= ~SCARD_STATE_INUSE;
02005                     currReader->dwEventState &= ~SCARD_STATE_EXCLUSIVE;
02006 
02007                     if (currReader->dwCurrentState & SCARD_STATE_INUSE)
02008                     {
02009                         currReader->dwEventState |= SCARD_STATE_CHANGED;
02010                         dwBreakFlag = 1;
02011                     } else if (currReader->
02012                         dwCurrentState & SCARD_STATE_EXCLUSIVE)
02013                     {
02014                         currReader->dwEventState |= SCARD_STATE_CHANGED;
02015                         dwBreakFlag = 1;
02016                     }
02017                 }
02018 
02019                 if (currReader->dwCurrentState == SCARD_STATE_UNAWARE)
02020                 {
02021                     /*
02022                      * Break out of the while .. loop and return status
02023                      * once all the status's for all readers is met
02024                      */
02025                     currReader->dwEventState |= SCARD_STATE_CHANGED;
02026                     dwBreakFlag = 1;
02027                 }
02028 
02029             }   /* End of SCARD_STATE_UNKNOWN */
02030 
02031         }   /* End of SCARD_STATE_IGNORE */
02032 
02033         /*
02034          * Counter and resetter
02035          */
02036         j = j + 1;
02037         if (j == cReaders)
02038         {
02039             if (!dwBreakFlag)
02040             {
02041                 /* break if the reader count changed,
02042                  * so that the calling application can update
02043                  * the reader list
02044                  */
02045                 if (ReaderCountChanged)
02046                     break;
02047             }
02048             j = 0;
02049         }
02050 
02051         /*
02052          * Declare all the break conditions
02053          */
02054 
02055         if (psContextMap[dwContextIndex].contextBlockStatus ==
02056             BLOCK_STATUS_RESUME)
02057             break;
02058 
02059         /*
02060          * Break if UNAWARE is set and all readers have been checked
02061          */
02062         if ((dwBreakFlag == 1) && (j == 0))
02063             break;
02064 
02065         /*
02066          * Timeout has occurred and all readers checked
02067          */
02068         if ((dwTimeout == 0) && (j == 0))
02069             break;
02070 
02071         if (dwTimeout != INFINITE && dwTimeout != 0)
02072         {
02073             /*
02074              * If time is greater than timeout and all readers have been
02075              * checked
02076              */
02077             if ((dwTime >= (dwTimeout * 1000)) && (j == 0))
02078             {
02079                 SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
02080                 return SCARD_E_TIMEOUT;
02081             }
02082         }
02083 
02084         /*
02085          * Only sleep once for each cycle of reader checks.
02086          */
02087         if (j == 0)
02088         {
02089             SYS_USleep(PCSCLITE_STATUS_WAIT);
02090             dwTime += PCSCLITE_STATUS_WAIT;
02091         }
02092     }
02093     while (1);
02094 
02095     Log1(PCSC_LOG_DEBUG, "Event Loop End");
02096 
02097     if (psContextMap[dwContextIndex].contextBlockStatus ==
02098             BLOCK_STATUS_RESUME)
02099     {
02100         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
02101         return SCARD_E_CANCELLED;
02102     }
02103 
02104     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
02105 
02106     PROFILE_END
02107 
02108     return SCARD_S_SUCCESS;
02109 }
02110 
02157 LONG SCardControl(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer,
02158     DWORD cbSendLength, LPVOID pbRecvBuffer, DWORD cbRecvLength,
02159     LPDWORD lpBytesReturned)
02160 {
02161     LONG rv;
02162     control_struct scControlStruct;
02163     sharedSegmentMsg msgStruct;
02164     int i;
02165     DWORD dwContextIndex, dwChannelIndex;
02166 
02167     PROFILE_START
02168 
02169     /* 0 bytes received by default */
02170     if (NULL != lpBytesReturned)
02171         *lpBytesReturned = 0;
02172 
02173     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
02174         return SCARD_E_NO_SERVICE;
02175 
02176     /*
02177      * Make sure this handle has been opened
02178      */
02179     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
02180 
02181     if (rv == -1)
02182         return SCARD_E_INVALID_HANDLE;
02183 
02184     SYS_MutexLock(psContextMap[dwContextIndex].mMutex); 
02185 
02186     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
02187     {
02188         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
02189 
02190         /* by default r == NULL */
02191         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
02192             break;
02193     }
02194 
02195     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
02196     {
02197         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
02198         return SCARD_E_READER_UNAVAILABLE;
02199     }
02200 
02201     if (cbSendLength > MAX_BUFFER_SIZE)
02202     {
02203         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
02204         return SCARD_E_INSUFFICIENT_BUFFER;
02205     }
02206 
02207     scControlStruct.hCard = hCard;
02208     scControlStruct.dwControlCode = dwControlCode;
02209     scControlStruct.cbSendLength = cbSendLength;
02210     scControlStruct.cbRecvLength = cbRecvLength;
02211     memcpy(scControlStruct.pbSendBuffer, pbSendBuffer, cbSendLength);
02212 
02213     rv = WrapSHMWrite(SCARD_CONTROL, psContextMap[dwContextIndex].dwClientID,
02214         sizeof(scControlStruct), PCSCLITE_CLIENT_ATTEMPTS, &scControlStruct);
02215 
02216     if (rv == -1)
02217     {
02218         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
02219         return SCARD_E_NO_SERVICE;
02220     }
02221 
02222     /*
02223      * Read a message from the server
02224      */
02225     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
02226 
02227     if (rv == -1)
02228     {
02229         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
02230         return SCARD_F_COMM_ERROR;
02231     }
02232 
02233     memcpy(&scControlStruct, &msgStruct.data, sizeof(scControlStruct));
02234 
02235     if (NULL != lpBytesReturned)
02236         *lpBytesReturned = scControlStruct.dwBytesReturned;
02237 
02238     if (scControlStruct.rv == SCARD_S_SUCCESS)
02239     {
02240         /*
02241          * Copy and zero it so any secret information is not leaked
02242          */
02243         memcpy(pbRecvBuffer, scControlStruct.pbRecvBuffer,
02244             scControlStruct.cbRecvLength);
02245         memset(scControlStruct.pbRecvBuffer, 0x00,
02246             sizeof(scControlStruct.pbRecvBuffer));
02247     }
02248 
02249     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
02250 
02251     PROFILE_END
02252 
02253     return scControlStruct.rv;
02254 }
02255 
02336 LONG SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr,
02337     LPDWORD pcbAttrLen)
02338 {
02339     PROFILE_START
02340 
02341     if (NULL == pcbAttrLen)
02342         return SCARD_E_INVALID_PARAMETER;
02343 
02344     /* if only get the length */
02345     if (NULL == pbAttr)
02346         /* this variable may not be set by the caller. use a reasonable size */
02347         *pcbAttrLen = MAX_BUFFER_SIZE;
02348 
02349     PROFILE_END
02350 
02351     return SCardGetSetAttrib(hCard, SCARD_GET_ATTRIB, dwAttrId, pbAttr,
02352         pcbAttrLen);
02353 }
02354 
02385 LONG SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr,
02386     DWORD cbAttrLen)
02387 {
02388     PROFILE_START
02389 
02390     if (NULL == pbAttr || 0 == cbAttrLen)
02391         return SCARD_E_INVALID_PARAMETER;
02392 
02393     PROFILE_END
02394 
02395     return SCardGetSetAttrib(hCard, SCARD_SET_ATTRIB, dwAttrId, (LPBYTE)pbAttr,
02396         &cbAttrLen);
02397 }
02398 
02399 static LONG SCardGetSetAttrib(SCARDHANDLE hCard, int command, DWORD dwAttrId,
02400     LPBYTE pbAttr, LPDWORD pcbAttrLen)
02401 {
02402     PROFILE_START
02403 
02404     LONG rv;
02405     getset_struct scGetSetStruct;
02406     sharedSegmentMsg msgStruct;
02407     int i;
02408     DWORD dwContextIndex, dwChannelIndex;
02409 
02410     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
02411         return SCARD_E_NO_SERVICE;
02412 
02413     /*
02414      * Make sure this handle has been opened
02415      */
02416     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
02417 
02418     if (rv == -1)
02419         return SCARD_E_INVALID_HANDLE;
02420 
02421     SYS_MutexLock(psContextMap[dwContextIndex].mMutex); 
02422 
02423     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
02424     {
02425         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
02426 
02427         /* by default r == NULL */
02428         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
02429             break;
02430     }
02431 
02432     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
02433     {
02434         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
02435         return SCARD_E_READER_UNAVAILABLE;
02436     }
02437 
02438     if (*pcbAttrLen > MAX_BUFFER_SIZE)
02439     {
02440         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
02441         return SCARD_E_INSUFFICIENT_BUFFER;
02442     }
02443 
02444     scGetSetStruct.hCard = hCard;
02445     scGetSetStruct.dwAttrId = dwAttrId;
02446     scGetSetStruct.cbAttrLen = *pcbAttrLen;
02447     scGetSetStruct.rv = SCARD_E_NO_SERVICE;
02448     if (SCARD_SET_ATTRIB == command)
02449         memcpy(scGetSetStruct.pbAttr, pbAttr, *pcbAttrLen);
02450 
02451     rv = WrapSHMWrite(command,
02452         psContextMap[dwContextIndex].dwClientID, sizeof(scGetSetStruct),
02453         PCSCLITE_CLIENT_ATTEMPTS, &scGetSetStruct);
02454 
02455     if (rv == -1)
02456     {
02457         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
02458         return SCARD_E_NO_SERVICE;
02459     }
02460 
02461     /*
02462      * Read a message from the server
02463      */
02464     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
02465 
02466     if (rv == -1)
02467     {
02468         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
02469         return SCARD_F_COMM_ERROR;
02470     }
02471 
02472     memcpy(&scGetSetStruct, &msgStruct.data, sizeof(scGetSetStruct));
02473 
02474     if ((SCARD_S_SUCCESS == scGetSetStruct.rv) && (SCARD_GET_ATTRIB == command))
02475     {
02476         /*
02477          * Copy and zero it so any secret information is not leaked
02478          */
02479         if (*pcbAttrLen < scGetSetStruct.cbAttrLen)
02480         {
02481             scGetSetStruct.cbAttrLen = *pcbAttrLen;
02482             scGetSetStruct.rv = SCARD_E_INSUFFICIENT_BUFFER;
02483         }
02484         else
02485             *pcbAttrLen = scGetSetStruct.cbAttrLen;
02486 
02487         if (pbAttr)
02488             memcpy(pbAttr, scGetSetStruct.pbAttr, scGetSetStruct.cbAttrLen);
02489 
02490         memset(scGetSetStruct.pbAttr, 0x00, sizeof(scGetSetStruct.pbAttr));
02491     }
02492 
02493     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
02494 
02495     PROFILE_END
02496 
02497     return scGetSetStruct.rv;
02498 }
02499 
02553 LONG SCardTransmit(SCARDHANDLE hCard, LPCSCARD_IO_REQUEST pioSendPci,
02554     LPCBYTE pbSendBuffer, DWORD cbSendLength,
02555     LPSCARD_IO_REQUEST pioRecvPci, LPBYTE pbRecvBuffer,
02556     LPDWORD pcbRecvLength)
02557 {
02558     LONG rv;
02559     transmit_struct scTransmitStruct;
02560     sharedSegmentMsg msgStruct;
02561     int i;
02562     DWORD dwContextIndex, dwChannelIndex;
02563 
02564     PROFILE_START
02565 
02566     if (pbSendBuffer == NULL || pbRecvBuffer == NULL ||
02567             pcbRecvLength == NULL || pioSendPci == NULL)
02568         return SCARD_E_INVALID_PARAMETER;
02569 
02570     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
02571         return SCARD_E_NO_SERVICE;
02572 
02573     /*
02574      * Make sure this handle has been opened
02575      */
02576     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
02577 
02578     if (rv == -1)
02579     {
02580         *pcbRecvLength = 0;
02581         return SCARD_E_INVALID_HANDLE;
02582     }
02583 
02584     SYS_MutexLock(psContextMap[dwContextIndex].mMutex); 
02585 
02586     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
02587     {
02588         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
02589 
02590         /* by default r == NULL */
02591         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
02592             break;
02593     }
02594 
02595     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
02596     {
02597         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
02598         return SCARD_E_READER_UNAVAILABLE;
02599     }
02600 
02601     if (cbSendLength > MAX_BUFFER_SIZE)
02602     {
02603         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
02604         return SCARD_E_INSUFFICIENT_BUFFER;
02605     }
02606 
02607     scTransmitStruct.hCard = hCard;
02608     scTransmitStruct.cbSendLength = cbSendLength;
02609     scTransmitStruct.pcbRecvLength = *pcbRecvLength;
02610     memcpy(&scTransmitStruct.pioSendPci, pioSendPci,
02611         sizeof(SCARD_IO_REQUEST));
02612     memcpy(scTransmitStruct.pbSendBuffer, pbSendBuffer, cbSendLength);
02613 
02614     if (pioRecvPci)
02615     {
02616         memcpy(&scTransmitStruct.pioRecvPci, pioRecvPci,
02617             sizeof(SCARD_IO_REQUEST));
02618     }
02619     else
02620         scTransmitStruct.pioRecvPci.dwProtocol = SCARD_PROTOCOL_ANY;
02621 
02622     rv = WrapSHMWrite(SCARD_TRANSMIT, psContextMap[dwContextIndex].dwClientID,
02623         sizeof(scTransmitStruct),
02624         PCSCLITE_CLIENT_ATTEMPTS, (void *) &scTransmitStruct);
02625 
02626     if (rv == -1)
02627     {
02628         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
02629         return SCARD_E_NO_SERVICE;
02630     }
02631 
02632     /*
02633      * Read a message from the server
02634      */
02635     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
02636 
02637     memcpy(&scTransmitStruct, &msgStruct.data, sizeof(scTransmitStruct));
02638 
02639     if (rv == -1)
02640     {
02641         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
02642         return SCARD_F_COMM_ERROR;
02643     }
02644 
02645     /*
02646      * Zero it and free it so any secret information cannot be leaked
02647      */
02648     memset(scTransmitStruct.pbSendBuffer, 0x00, cbSendLength);
02649 
02650     if (scTransmitStruct.rv == SCARD_S_SUCCESS)
02651     {
02652         /*
02653          * Copy and zero it so any secret information is not leaked
02654          */
02655         memcpy(pbRecvBuffer, scTransmitStruct.pbRecvBuffer,
02656             scTransmitStruct.pcbRecvLength);
02657         memset(scTransmitStruct.pbRecvBuffer, 0x00,
02658             scTransmitStruct.pcbRecvLength);
02659 
02660         if (pioRecvPci)
02661             memcpy(pioRecvPci, &scTransmitStruct.pioRecvPci,
02662                 sizeof(SCARD_IO_REQUEST));
02663     }
02664 
02665     *pcbRecvLength = scTransmitStruct.pcbRecvLength;
02666     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
02667 
02668     PROFILE_END
02669 
02670     return scTransmitStruct.rv;
02671 }
02672 
02702 LONG SCardListReaders(SCARDCONTEXT hContext, LPCTSTR mszGroups,
02703     LPTSTR mszReaders, LPDWORD pcchReaders)
02704 {
02705     DWORD dwReadersLen;
02706     int i, lastChrPtr;
02707     DWORD dwContextIndex;
02708 
02709     PROFILE_START
02710 
02711     /*
02712      * Check for NULL parameters
02713      */
02714     if (pcchReaders == NULL)
02715         return SCARD_E_INVALID_PARAMETER;
02716 
02717     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
02718         return SCARD_E_NO_SERVICE;
02719 
02720     /*
02721      * Make sure this context has been opened
02722      */
02723     dwContextIndex = SCardGetContextIndice(hContext);
02724     if (dwContextIndex == -1)
02725         return SCARD_E_INVALID_HANDLE;
02726 
02727     SYS_MutexLock(psContextMap[dwContextIndex].mMutex); 
02728 
02729     dwReadersLen = 0;
02730     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
02731         if ((readerStates[i])->readerID != 0)
02732             dwReadersLen += strlen((readerStates[i])->readerName) + 1;
02733 
02734     /* for the last NULL byte */
02735     dwReadersLen += 1;
02736 
02737     if ((mszReaders == NULL)    /* text array not allocated */
02738         || (*pcchReaders == 0)) /* size == 0 */
02739     {
02740         *pcchReaders = dwReadersLen;
02741         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
02742         return SCARD_S_SUCCESS;
02743     }
02744     
02745     if (*pcchReaders < dwReadersLen)
02746     {
02747         *pcchReaders = dwReadersLen;
02748         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
02749         return SCARD_E_INSUFFICIENT_BUFFER;
02750     }
02751 
02752     lastChrPtr = 0;
02753     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
02754     {
02755         if ((readerStates[i])->readerID != 0)
02756         {
02757             /*
02758              * Build the multi-string
02759              */
02760             strcpy(&mszReaders[lastChrPtr], (readerStates[i])->readerName);
02761             lastChrPtr += strlen((readerStates[i])->readerName)+1;
02762         }
02763     }
02764     mszReaders[lastChrPtr] = '\0';  /* Add the last null */
02765 
02766     *pcchReaders = dwReadersLen;
02767 
02768     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
02769 
02770     PROFILE_END
02771 
02772     return SCARD_S_SUCCESS;
02773 }
02774 
02806 LONG SCardListReaderGroups(SCARDCONTEXT hContext, LPTSTR mszGroups,
02807     LPDWORD pcchGroups)
02808 {
02809     LONG rv = SCARD_S_SUCCESS;
02810     DWORD dwContextIndex;
02811 
02812     PROFILE_START
02813 
02814     const char ReaderGroup[] = "SCard$DefaultReaders";
02815     const int dwGroups = strlen(ReaderGroup) + 2;
02816 
02817     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
02818         return SCARD_E_NO_SERVICE;
02819 
02820     /*
02821      * Make sure this context has been opened
02822      */
02823     dwContextIndex = SCardGetContextIndice(hContext);
02824     if (dwContextIndex == -1)
02825         return SCARD_E_INVALID_HANDLE;
02826 
02827     SYS_MutexLock(psContextMap[dwContextIndex].mMutex); 
02828 
02829     if (mszGroups)
02830     {
02831 
02832         if (*pcchGroups < dwGroups)
02833             rv = SCARD_E_INSUFFICIENT_BUFFER;
02834         else
02835         {
02836             memset(mszGroups, 0, dwGroups);
02837             memcpy(mszGroups, ReaderGroup, strlen(ReaderGroup));
02838         }
02839     }
02840 
02841     *pcchGroups = dwGroups;
02842 
02843     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
02844 
02845     PROFILE_END
02846 
02847     return rv;
02848 }
02849 
02877 LONG SCardCancel(SCARDCONTEXT hContext)
02878 {
02879     DWORD dwContextIndex;
02880 
02881     PROFILE_START
02882 
02883     dwContextIndex = SCardGetContextIndice(hContext);
02884 
02885     if (dwContextIndex == -1)
02886         return SCARD_E_INVALID_HANDLE;
02887 
02888     /*
02889      * Set the block status for this Context so blocking calls will
02890      * complete
02891      */
02892     psContextMap[dwContextIndex].contextBlockStatus = BLOCK_STATUS_RESUME;
02893 
02894     PROFILE_END
02895 
02896     return SCARD_S_SUCCESS;
02897 }
02898 
02915 static LONG SCardAddContext(SCARDCONTEXT hContext, DWORD dwClientID)
02916 {
02917     int i;
02918 
02919     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
02920     {
02921         if (psContextMap[i].hContext == 0)
02922         {
02923             psContextMap[i].hContext = hContext;
02924             psContextMap[i].dwClientID = dwClientID;
02925             psContextMap[i].contextBlockStatus = BLOCK_STATUS_RESUME;
02926             psContextMap[i].mMutex = (PCSCLITE_MUTEX_T) malloc(sizeof(PCSCLITE_MUTEX));
02927             SYS_MutexInit(psContextMap[i].mMutex);
02928             return SCARD_S_SUCCESS;
02929         }
02930     }
02931 
02932     return SCARD_E_NO_MEMORY;
02933 }
02934 
02947 static LONG SCardGetContextIndice(SCARDCONTEXT hContext)
02948 {
02949     LONG rv;
02950 
02951     SCardLockThread();
02952     rv = SCardGetContextIndiceTH(hContext);
02953     SCardUnlockThread();
02954 
02955     return rv;
02956 }
02957 
02970 static LONG SCardGetContextIndiceTH(SCARDCONTEXT hContext)
02971 {
02972     int i;
02973 
02974     /*
02975      * Find this context and return it's spot in the array
02976      */
02977     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
02978     {
02979         if ((hContext == psContextMap[i].hContext) && (hContext != 0))
02980             return i;
02981     }
02982 
02983     return -1;
02984 }
02985 
02995 static LONG SCardRemoveContext(SCARDCONTEXT hContext)
02996 {
02997     LONG  retIndice;
02998 
02999     retIndice = SCardGetContextIndiceTH(hContext);
03000 
03001     if (retIndice == -1)
03002         return SCARD_E_INVALID_HANDLE;
03003     else
03004     {
03005         int i;
03006 
03007         psContextMap[retIndice].hContext = 0;
03008         SHMClientCloseSession(psContextMap[retIndice].dwClientID);
03009         psContextMap[retIndice].dwClientID = 0;
03010         free(psContextMap[retIndice].mMutex);
03011         psContextMap[retIndice].mMutex = NULL;
03012         psContextMap[retIndice].contextBlockStatus = BLOCK_STATUS_RESUME;
03013 
03014         for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
03015         {
03016             /*
03017              * Reset the \c hCard structs to zero
03018              */
03019             psContextMap[retIndice].psChannelMap[i].hCard = 0;
03020             free(psContextMap[retIndice].psChannelMap[i].readerName);
03021             psContextMap[retIndice].psChannelMap[i].readerName = NULL;
03022         }
03023 
03024         return SCARD_S_SUCCESS;
03025     }
03026 }
03027 
03028 /*
03029  * Functions for managing hCard values returned from SCardConnect.
03030  */
03031 
03032 static LONG SCardAddHandle(SCARDHANDLE hCard, DWORD dwContextIndex,
03033     LPTSTR readerName)
03034 {
03035     int i;
03036 
03037     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
03038     {
03039         if (psContextMap[dwContextIndex].psChannelMap[i].hCard == 0)
03040         {
03041             psContextMap[dwContextIndex].psChannelMap[i].hCard = hCard;
03042             psContextMap[dwContextIndex].psChannelMap[i].readerName = strdup(readerName);
03043             return SCARD_S_SUCCESS;
03044         }
03045     }
03046 
03047     return SCARD_E_NO_MEMORY;
03048 }
03049 
03050 static LONG SCardRemoveHandle(SCARDHANDLE hCard)
03051 {
03052     DWORD dwContextIndice, dwChannelIndice;
03053     LONG rv;
03054 
03055     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndice, &dwChannelIndice);
03056 
03057     if (rv == -1)
03058         return SCARD_E_INVALID_HANDLE;
03059     else
03060     {
03061         psContextMap[dwContextIndice].psChannelMap[dwChannelIndice].hCard = 0;
03062         free(psContextMap[dwContextIndice].psChannelMap[dwChannelIndice].readerName);
03063         psContextMap[dwContextIndice].psChannelMap[dwChannelIndice].readerName = NULL;
03064         return SCARD_S_SUCCESS;
03065     }
03066 }
03067 
03068 static LONG SCardGetIndicesFromHandle(SCARDHANDLE hCard, PDWORD pdwContextIndice, PDWORD pdwChannelIndice)
03069 {
03070     LONG rv;
03071 
03072     SCardLockThread();
03073     rv = SCardGetIndicesFromHandleTH(hCard, pdwContextIndice, pdwChannelIndice);
03074     SCardUnlockThread();
03075 
03076     return rv;
03077 }
03078 
03079 static LONG SCardGetIndicesFromHandleTH(SCARDHANDLE hCard, PDWORD pdwContextIndice, PDWORD pdwChannelIndice)
03080 {
03081     int i;
03082 
03083     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
03084     {
03085         if (psContextMap[i].hContext != 0)
03086         {
03087             int j;
03088 
03089             for (j = 0; j < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; j++)
03090             {
03091                 if (psContextMap[i].psChannelMap[j].hCard == hCard)
03092                 {
03093                     *pdwContextIndice = i;
03094                     *pdwChannelIndice = j;
03095                     return SCARD_S_SUCCESS;
03096                 }
03097             }
03098             
03099         }
03100     }
03101 
03102     return -1;
03103 }
03104 
03111 inline static LONG SCardLockThread(void)
03112 {
03113     return SYS_MutexLock(&clientMutex);
03114 }
03115 
03121 inline static LONG SCardUnlockThread(void)
03122 {
03123     return SYS_MutexUnLock(&clientMutex);
03124 }
03125 
03133 static LONG SCardCheckDaemonAvailability(void)
03134 {
03135     LONG rv;
03136     struct stat statBuffer;
03137 
03138     rv = SYS_Stat(PCSCLITE_IPC_DIR, &statBuffer);
03139 
03140     if (rv != 0)
03141     {
03142         Log1(PCSC_LOG_ERROR, "PCSC Not Running");
03143         return SCARD_E_NO_SERVICE;
03144     }
03145 
03146     return SCARD_S_SUCCESS;
03147 }
03148 
03154 #ifdef __SUNPRO_C
03155 #pragma fini (SCardUnload)
03156 #endif
03157 
03158 void DESTRUCTOR SCardUnload(void)
03159 {
03160     if (!isExecuted)
03161         return;
03162 
03163     SYS_CloseFile(mapAddr);
03164     isExecuted = 0;
03165 }
03166 

Generated on Wed Jun 6 11:37:24 2007 for pcsc-lite by  doxygen 1.4.7