31
31
#include "winscard.h"
33
33
#include "thread_generic.h"
34
#include "strlcpycat.h"
35
36
#include "readerfactory.h"
36
37
#include "eventhandler.h"
37
38
#include "sys_generic.h"
38
39
#include "winscard_msg.h"
40
42
/** used for backward compatibility */
41
43
#define SCARD_PROTOCOL_ANY_OLD 0x1000
44
#define min(a,b) (((a) < (b)) ? (a) : (b))
59
57
struct timeval profile_time_start;
63
62
#define PROFILE_START profile_start(__FUNCTION__);
64
#define PROFILE_END profile_end(__FUNCTION__);
63
#define PROFILE_END(rv) profile_end(__FUNCTION__, rv);
66
65
static void profile_start(const char *f)
88
87
profile_tty = FALSE;
90
/* PROFILE_END was not called before? */
91
if (profile_tty && fct_name[0])
92
printf("\33[01;34m WARNING: %s starts before %s finishes\33[0m\n",
95
strlcpy(fct_name, f, sizeof(fct_name));
91
97
gettimeofday(&profile_time_start, NULL);
92
98
} /* profile_start */
116
122
d = time_sub(&profile_time_end, &profile_time_start);
119
fprintf(stderr, "\33[01;31mRESULT %s \33[35m%ld\33[0m\n", f, d);
128
if (strncmp(fct_name, f, sizeof(fct_name)))
129
printf("\33[01;34m WARNING: %s ends before %s\33[0m\n",
133
printf("\33[01;34m WARNING: %s ends but we lost its start\33[0m\n",
136
/* allow to detect missing PROFILE_END calls */
139
if (rv != SCARD_S_SUCCESS)
141
"\33[01;31mRESULT %s \33[35m%ld \33[34m0x%08lX %s\33[0m\n",
142
f, d, rv, pcsc_stringify_error(rv));
144
fprintf(stderr, "\33[01;31mRESULT %s \33[35m%ld\33[0m\n", f, d);
120
146
fprintf(fd, "%s %ld\n", f, d);
122
148
} /* profile_end */
125
151
#define PROFILE_START
152
#define PROFILE_END(rv)
158
184
static short isExecuted = 0;
188
* creation time of pcscd PCSCLITE_PUBSHM_FILE file
190
static time_t daemon_ctime = 0;
191
static pid_t daemon_pid = 0;
161
194
* Memory mapped address used to read status information about the readers.
162
195
* Each element in the vector \ref readerStates makes references to a part of
187
220
static LONG SCardGetContextIndice(SCARDCONTEXT);
188
221
static LONG SCardGetContextIndiceTH(SCARDCONTEXT);
189
222
static LONG SCardRemoveContext(SCARDCONTEXT);
223
static LONG SCardCleanContext(LONG indice);
191
225
static LONG SCardAddHandle(SCARDHANDLE, DWORD, LPSTR);
192
226
static LONG SCardGetIndicesFromHandle(SCARDHANDLE, PDWORD, PDWORD);
196
230
static LONG SCardGetSetAttrib(SCARDHANDLE hCard, int command, DWORD dwAttrId,
197
231
LPBYTE pbAttr, LPDWORD pcbAttrLen);
199
static LONG SCardCheckDaemonAvailability(void);
233
LONG SCardCheckDaemonAvailability(void);
235
void DESTRUCTOR SCardUnload(void);
202
238
* Thread safety functions
325
361
return SCARD_E_NO_SERVICE;
364
/* close on exec so that child processes do not inherits the file
365
* descriptor. The child process will call SCardEstablishContext()
367
fcntl(mapAddr, F_SETFD, FD_CLOEXEC);
328
369
pageSize = SYS_GetPageSize();
713
754
rv = SCardAddHandle(*phCard, dwContextIndex, (LPSTR) szReader);
714
755
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
721
762
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
764
PROFILE_END(scConnectStruct.rv)
725
766
return scConnectStruct.rv;
852
893
return SCARD_E_READER_UNAVAILABLE;
855
scReconnectStruct.hCard = hCard;
856
scReconnectStruct.dwShareMode = dwShareMode;
857
scReconnectStruct.dwPreferredProtocols = dwPreferredProtocols;
858
scReconnectStruct.dwInitialization = dwInitialization;
859
scReconnectStruct.pdwActiveProtocol = *pdwActiveProtocol;
861
rv = WrapSHMWrite(SCARD_RECONNECT, psContextMap[dwContextIndex].dwClientID,
862
sizeof(scReconnectStruct),
863
PCSCLITE_CLIENT_ATTEMPTS, (void *) &scReconnectStruct);
867
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
868
return SCARD_E_NO_SERVICE;
872
* Read a message from the server
874
rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
876
memcpy(&scReconnectStruct, &msgStruct.data, sizeof(scReconnectStruct));
880
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
881
return SCARD_F_COMM_ERROR;
898
scReconnectStruct.hCard = hCard;
899
scReconnectStruct.dwShareMode = dwShareMode;
900
scReconnectStruct.dwPreferredProtocols = dwPreferredProtocols;
901
scReconnectStruct.dwInitialization = dwInitialization;
902
scReconnectStruct.pdwActiveProtocol = *pdwActiveProtocol;
904
rv = WrapSHMWrite(SCARD_RECONNECT, psContextMap[dwContextIndex].dwClientID,
905
sizeof(scReconnectStruct),
906
PCSCLITE_CLIENT_ATTEMPTS, (void *) &scReconnectStruct);
910
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
911
return SCARD_E_NO_SERVICE;
915
* Read a message from the server
917
rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
919
memcpy(&scReconnectStruct, &msgStruct.data, sizeof(scReconnectStruct));
923
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
924
return SCARD_F_COMM_ERROR;
926
} while (SCARD_E_SHARING_VIOLATION == scReconnectStruct.rv);
884
928
*pdwActiveProtocol = scReconnectStruct.pdwActiveProtocol;
886
930
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
932
PROFILE_END(scReconnectStruct.rv)
890
934
return scReconnectStruct.rv;
1736
1780
if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
1738
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
1782
if (psContextMap[dwContextIndex].mMutex)
1783
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
1785
PROFILE_END(SCARD_E_NO_SERVICE)
1742
1787
return SCARD_E_NO_SERVICE;
1821
1866
* Now we check all the Reader States
1823
1868
dwState = rContext->readerState;
1870
int currentCounter, stateCounter;
1872
stateCounter = (dwState >> 16) & 0xFFFF;
1873
currentCounter = (currReader->dwCurrentState >> 16) & 0xFFFF;
1875
/* has the event counter changed since the last call? */
1876
if (stateCounter != currentCounter)
1877
currReader->dwEventState |= SCARD_STATE_CHANGED;
1879
/* add an event counter in the upper word of dwEventState */
1880
currReader->dwEventState =
1881
((currReader->dwEventState & 0xffff )
1882
| (stateCounter << 16));
1825
1885
/*********** Check if the reader is in the correct state ********/
1826
1886
if (dwState & SCARD_UNKNOWN)
1890
1950
* After present the rest are assumed
1892
if (currReader->dwCurrentState & SCARD_STATE_PRESENT
1893
|| currReader->dwCurrentState & SCARD_STATE_ATRMATCH
1894
|| currReader->dwCurrentState & SCARD_STATE_EXCLUSIVE
1895
|| currReader->dwCurrentState & SCARD_STATE_INUSE)
1952
if (currReader->dwCurrentState & SCARD_STATE_PRESENT)
1897
1954
currReader->dwEventState |= SCARD_STATE_CHANGED;
1898
1955
dwBreakFlag = 1;
2396
2457
/* this variable may not be set by the caller. use a reasonable size */
2397
2458
*pcbAttrLen = MAX_BUFFER_SIZE;
2401
return SCardGetSetAttrib(hCard, SCARD_GET_ATTRIB, dwAttrId, pbAttr,
2460
ret = SCardGetSetAttrib(hCard, SCARD_GET_ATTRIB, dwAttrId, pbAttr,
2435
2498
LONG SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr,
2436
2499
DWORD cbAttrLen)
2440
2505
if (NULL == pbAttr || 0 == cbAttrLen)
2441
2506
return SCARD_E_INVALID_PARAMETER;
2445
return SCardGetSetAttrib(hCard, SCARD_SET_ATTRIB, dwAttrId, (LPBYTE)pbAttr,
2508
ret = SCardGetSetAttrib(hCard, SCARD_SET_ATTRIB, dwAttrId, (LPBYTE)pbAttr,
2449
2516
static LONG SCardGetSetAttrib(SCARDHANDLE hCard, int command, DWORD dwAttrId,
2450
2517
LPBYTE pbAttr, LPDWORD pcbAttrLen)
2455
2520
getset_struct scGetSetStruct;
2456
2521
sharedSegmentMsg msgStruct;
3185
3254
if (retIndice == -1)
3186
3255
return SCARD_E_INVALID_HANDLE;
3257
return SCardCleanContext(retIndice);
3260
static LONG SCardCleanContext(LONG indice)
3264
psContextMap[indice].hContext = 0;
3265
SHMClientCloseSession(psContextMap[indice].dwClientID);
3266
psContextMap[indice].dwClientID = 0;
3267
free(psContextMap[indice].mMutex);
3268
psContextMap[indice].mMutex = NULL;
3269
psContextMap[indice].contextBlockStatus = BLOCK_STATUS_RESUME;
3271
for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
3191
psContextMap[retIndice].hContext = 0;
3192
SHMClientCloseSession(psContextMap[retIndice].dwClientID);
3193
psContextMap[retIndice].dwClientID = 0;
3194
free(psContextMap[retIndice].mMutex);
3195
psContextMap[retIndice].mMutex = NULL;
3196
psContextMap[retIndice].contextBlockStatus = BLOCK_STATUS_RESUME;
3198
for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
3201
* Reset the \c hCard structs to zero
3203
psContextMap[retIndice].psChannelMap[i].hCard = 0;
3204
free(psContextMap[retIndice].psChannelMap[i].readerName);
3205
psContextMap[retIndice].psChannelMap[i].readerName = NULL;
3208
return SCARD_S_SUCCESS;
3274
* Reset the \c hCard structs to zero
3276
psContextMap[indice].psChannelMap[i].hCard = 0;
3277
free(psContextMap[indice].psChannelMap[i].readerName);
3278
psContextMap[indice].psChannelMap[i].readerName = NULL;
3281
return SCARD_S_SUCCESS;
3330
3402
return SCARD_E_NO_SERVICE;
3407
/* when the _first_ reader is connected the ctime changes
3408
* I don't know why yet */
3409
if (statBuffer.st_ctime > daemon_ctime)
3413
new_pid = GetDaemonPid();
3415
/* so we also check the daemon pid to be sure it is a new pcscd */
3416
if (new_pid != daemon_pid)
3420
Log1(PCSC_LOG_ERROR, "PCSC restarted");
3422
/* invalid all handles */
3425
for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
3426
if (psContextMap[i].hContext)
3427
SCardCleanContext(i);
3429
SCardUnlockThread();
3431
/* reset pcscd status */
3437
return SCARD_E_NO_SERVICE;
3440
daemon_ctime = statBuffer.st_ctime;
3445
daemon_ctime = statBuffer.st_ctime;
3446
daemon_pid = GetDaemonPid();
3333
3449
return SCARD_S_SUCCESS;