2
* This handles smartcard reader communications and
3
* forwarding requests over message queues.
5
* MUSCLE SmartCard Development ( http://www.linuxnet.com )
7
* Copyright (C) 1999-2004
8
* David Corcoran <corcoran@linuxnet.com>
9
* Damien Sauveron <damien.sauveron@labri.fr>
10
* Ludovic Rousseau <ludovic.rousseau@free.fr>
12
* $Id: winscard_clnt.c,v 1.54 2005/03/02 15:12:49 rousseau Exp $
18
#include <sys/types.h>
27
#include "thread_generic.h"
29
#include "readerfactory.h"
30
#include "eventhandler.h"
31
#include "sys_generic.h"
33
#include "winscard_msg.h"
35
#define SCARD_PROTOCOL_ANY_OLD 0x1000 /* used for backward compatibility */
38
#define min(a,b) (((a) < (b)) ? (a) : (b))
47
typedef struct _psChannelMap CHANNEL_MAP, *PCHANNEL_MAP;
49
static struct _psContextMap
52
SCARDCONTEXT hContext;
53
DWORD contextBlockStatus;
54
PCSCLITE_THREAD_T TID; /* Thread owner of this context */
55
PCSCLITE_MUTEX_T mMutex; /* Mutex for this context */
56
CHANNEL_MAP psChannelMap[PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS];
57
} psContextMap[PCSCLITE_MAX_APPLICATION_CONTEXTS];
59
static short isExecuted = 0;
60
static int mapAddr = 0;
62
static PCSCLITE_MUTEX clientMutex = PTHREAD_MUTEX_INITIALIZER;
64
static PREADER_STATE readerStates[PCSCLITE_MAX_READERS_CONTEXTS];
66
SCARD_IO_REQUEST g_rgSCardT0Pci = { SCARD_PROTOCOL_T0, 8 };
67
SCARD_IO_REQUEST g_rgSCardT1Pci = { SCARD_PROTOCOL_T1, 8 };
68
SCARD_IO_REQUEST g_rgSCardRawPci = { SCARD_PROTOCOL_RAW, 8 };
71
static LONG SCardAddContext(SCARDCONTEXT, DWORD);
72
static LONG SCardGetContextIndice(SCARDCONTEXT);
73
static LONG SCardGetContextIndiceTH(SCARDCONTEXT);
74
static LONG SCardRemoveContext(SCARDCONTEXT);
76
static LONG SCardAddHandle(SCARDHANDLE, DWORD, LPTSTR);
77
static LONG SCardGetIndicesFromHandle(SCARDHANDLE, PDWORD, PDWORD);
78
static LONG SCardGetIndicesFromHandleTH(SCARDHANDLE, PDWORD, PDWORD);
79
static LONG SCardRemoveHandle(SCARDHANDLE);
81
static LONG SCardGetSetAttrib(SCARDHANDLE hCard, int command, DWORD dwAttrId,
82
LPBYTE pbAttr, LPDWORD pcbAttrLen);
84
static LONG SCardCheckDaemonAvailability(void);
87
* Thread safety functions
89
inline static LONG SCardLockThread(void);
90
inline static LONG SCardUnlockThread(void);
92
static LONG SCardEstablishContextTH(DWORD, LPCVOID, LPCVOID, LPSCARDCONTEXT);
94
LONG SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1,
95
LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
100
rv = SCardEstablishContextTH(dwScope, pvReserved1,
101
pvReserved2, phContext);
107
static LONG SCardEstablishContextTH(DWORD dwScope, LPCVOID pvReserved1,
108
LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
112
establish_struct scEstablishStruct;
113
sharedSegmentMsg msgStruct;
114
DWORD dwClientID = 0;
116
if (phContext == NULL)
117
return SCARD_E_INVALID_PARAMETER;
121
if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
122
return SCARD_E_NO_SERVICE;
134
if (getenv("MUSCLECARD_DEBUG"))
136
DebugLogSetLogType(DEBUGLOG_STDERR_DEBUG);
137
DebugLogSetLevel(PCSC_LOG_DEBUG);
141
* Do any system initilization here
146
* Set up the memory mapped reader stats structures
148
mapAddr = SYS_OpenFile(PCSCLITE_PUBSHM_FILE, O_RDONLY, 0);
151
Log2(PCSC_LOG_CRITICAL, "Cannot open public shared file: %s",
152
PCSCLITE_PUBSHM_FILE);
153
return SCARD_E_NO_SERVICE;
156
pageSize = SYS_GetPageSize();
159
* Allocate each reader structure
161
for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
163
readerStates[i] = (PREADER_STATE)
164
SYS_PublicMemoryMap(sizeof(READER_STATE),
165
mapAddr, (i * pageSize));
166
if (readerStates[i] == NULL)
168
Log1(PCSC_LOG_CRITICAL, "Cannot public memory map");
169
SYS_CloseFile(mapAddr); /* Close the memory map file */
170
return SCARD_F_INTERNAL_ERROR;
174
for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
179
* Initially set the context struct to zero
181
psContextMap[i].dwClientID = 0;
182
psContextMap[i].hContext = 0;
183
psContextMap[i].contextBlockStatus = BLOCK_STATUS_RESUME;
184
psContextMap[i].mMutex = 0;
186
for (j = 0; j < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; j++)
189
* Initially set the hcard structs to zero
191
psContextMap[i].psChannelMap[j].hCard = 0;
192
psContextMap[i].psChannelMap[j].readerName = NULL;
199
* Is there a free slot for this connection ?
202
for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
204
if (psContextMap[i].dwClientID == 0)
208
if (i == PCSCLITE_MAX_APPLICATION_CONTEXTS)
210
return SCARD_E_NO_MEMORY;
213
if (SHMClientSetupSession(&dwClientID) != 0)
215
SYS_CloseFile(mapAddr);
216
return SCARD_E_NO_SERVICE;
219
{ /* exchange client/server protocol versions */
220
sharedSegmentMsg msgStruct;
221
version_struct *veStr;
223
memset(&msgStruct, 0, sizeof(msgStruct));
224
msgStruct.mtype = CMD_VERSION;
225
msgStruct.user_id = SYS_GetUID();
226
msgStruct.group_id = SYS_GetGID();
227
msgStruct.command = 0;
228
msgStruct.date = time(NULL);
230
veStr = (version_struct *) msgStruct.data;
231
veStr->major = PROTOCOL_VERSION_MAJOR;
232
veStr->minor = PROTOCOL_VERSION_MINOR;
234
if (-1 == SHMMessageSend(&msgStruct, dwClientID,
235
PCSCLITE_MCLIENT_ATTEMPTS))
236
return SCARD_E_NO_SERVICE;
239
* Read a message from the server
241
if (-1 == SHMMessageReceive(&msgStruct, dwClientID,
242
PCSCLITE_CLIENT_ATTEMPTS))
244
Log1(PCSC_LOG_CRITICAL, "Your pcscd is too old and does not support CMD_VERSION");
245
return SCARD_F_COMM_ERROR;
248
Log3(PCSC_LOG_INFO, "Server is protocol version %d:%d",
249
veStr->major, veStr->minor);
255
if (dwScope != SCARD_SCOPE_USER && dwScope != SCARD_SCOPE_TERMINAL &&
256
dwScope != SCARD_SCOPE_SYSTEM && dwScope != SCARD_SCOPE_GLOBAL)
258
return SCARD_E_INVALID_VALUE;
261
scEstablishStruct.dwScope = dwScope;
262
scEstablishStruct.phContext = 0;
264
rv = WrapSHMWrite(SCARD_ESTABLISH_CONTEXT, dwClientID,
265
sizeof(scEstablishStruct), PCSCLITE_MCLIENT_ATTEMPTS,
266
(void *) &scEstablishStruct);
269
return SCARD_E_NO_SERVICE;
272
* Read a message from the server
274
rv = SHMClientRead(&msgStruct, dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
277
return SCARD_F_COMM_ERROR;
279
memcpy(&scEstablishStruct, &msgStruct.data, sizeof(scEstablishStruct));
281
if (scEstablishStruct.rv != SCARD_S_SUCCESS)
282
return scEstablishStruct.rv;
284
*phContext = scEstablishStruct.phContext;
287
* Allocate the new hContext - if allocator full return an error
290
rv = SCardAddContext(*phContext, dwClientID);
295
LONG SCardReleaseContext(SCARDCONTEXT hContext)
298
release_struct scReleaseStruct;
299
sharedSegmentMsg msgStruct;
300
DWORD dwContextIndex;
301
PCSCLITE_THREAD_T currentTID;
303
if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
304
return SCARD_E_NO_SERVICE;
307
* Make sure this context has been opened
309
dwContextIndex = SCardGetContextIndice(hContext);
310
if (dwContextIndex == -1)
311
return SCARD_E_INVALID_HANDLE;
313
SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
316
* Test if the thread that would release the context is the thread owning this context
318
currentTID = SYS_ThreadSelf();
319
rv = SYS_ThreadEqual(&psContextMap[dwContextIndex].TID, ¤tTID);
323
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
324
/* Perhaps there is a better error code */
325
return SCARD_F_INTERNAL_ERROR;
328
scReleaseStruct.hContext = hContext;
330
rv = WrapSHMWrite(SCARD_RELEASE_CONTEXT, psContextMap[dwContextIndex].dwClientID,
331
sizeof(scReleaseStruct),
332
PCSCLITE_MCLIENT_ATTEMPTS, (void *) &scReleaseStruct);
336
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
337
return SCARD_E_NO_SERVICE;
341
* Read a message from the server
343
rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
344
memcpy(&scReleaseStruct, &msgStruct.data, sizeof(scReleaseStruct));
348
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
349
return SCARD_F_COMM_ERROR;
352
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
355
* Remove the local context from the stack
358
SCardRemoveContext(hContext);
361
return scReleaseStruct.rv;
364
LONG SCardSetTimeout(SCARDCONTEXT hContext, DWORD dwTimeout)
370
return SCARD_S_SUCCESS;
373
LONG SCardConnect(SCARDCONTEXT hContext, LPCTSTR szReader,
374
DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard,
375
LPDWORD pdwActiveProtocol)
378
connect_struct scConnectStruct;
379
sharedSegmentMsg msgStruct;
380
DWORD dwContextIndex;
383
* Check for NULL parameters
385
if (phCard == 0 || pdwActiveProtocol == 0)
386
return SCARD_E_INVALID_PARAMETER;
391
return SCARD_E_UNKNOWN_READER;
394
* Check for uninitialized strings
396
if (strlen(szReader) > MAX_READERNAME)
397
return SCARD_E_INVALID_VALUE;
399
if (!(dwPreferredProtocols & SCARD_PROTOCOL_T0) &&
400
!(dwPreferredProtocols & SCARD_PROTOCOL_T1) &&
401
!(dwPreferredProtocols & SCARD_PROTOCOL_RAW) &&
402
!(dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD))
404
return SCARD_E_INVALID_VALUE;
407
if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
408
return SCARD_E_NO_SERVICE;
411
* Make sure this context has been opened
413
dwContextIndex = SCardGetContextIndice(hContext);
414
if (dwContextIndex == -1)
415
return SCARD_E_INVALID_HANDLE;
417
SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
419
strncpy(scConnectStruct.szReader, szReader, MAX_READERNAME);
421
scConnectStruct.hContext = hContext;
422
scConnectStruct.dwShareMode = dwShareMode;
423
scConnectStruct.dwPreferredProtocols = dwPreferredProtocols;
424
scConnectStruct.phCard = *phCard;
425
scConnectStruct.pdwActiveProtocol = *pdwActiveProtocol;
427
rv = WrapSHMWrite(SCARD_CONNECT, psContextMap[dwContextIndex].dwClientID,
428
sizeof(scConnectStruct),
429
PCSCLITE_CLIENT_ATTEMPTS, (void *) &scConnectStruct);
433
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
434
return SCARD_E_NO_SERVICE;
438
* Read a message from the server
440
rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
442
memcpy(&scConnectStruct, &msgStruct.data, sizeof(scConnectStruct));
446
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
447
return SCARD_F_COMM_ERROR;
450
*phCard = scConnectStruct.phCard;
451
*pdwActiveProtocol = scConnectStruct.pdwActiveProtocol;
453
if (scConnectStruct.rv == SCARD_S_SUCCESS)
456
* Keep track of the handle locally
458
rv = SCardAddHandle(*phCard, dwContextIndex, (LPTSTR) szReader);
459
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
463
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
464
return scConnectStruct.rv;
467
LONG SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode,
468
DWORD dwPreferredProtocols, DWORD dwInitialization,
469
LPDWORD pdwActiveProtocol)
472
reconnect_struct scReconnectStruct;
473
sharedSegmentMsg msgStruct;
475
DWORD dwContextIndex, dwChannelIndex;
477
if (dwInitialization != SCARD_LEAVE_CARD &&
478
dwInitialization != SCARD_RESET_CARD &&
479
dwInitialization != SCARD_UNPOWER_CARD &&
480
dwInitialization != SCARD_EJECT_CARD)
482
return SCARD_E_INVALID_VALUE;
485
if (!(dwPreferredProtocols & SCARD_PROTOCOL_T0) &&
486
!(dwPreferredProtocols & SCARD_PROTOCOL_T1) &&
487
!(dwPreferredProtocols & SCARD_PROTOCOL_RAW) &&
488
!(dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD))
490
return SCARD_E_INVALID_VALUE;
493
if (pdwActiveProtocol == 0)
494
return SCARD_E_INVALID_PARAMETER;
496
if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
497
return SCARD_E_NO_SERVICE;
500
* Make sure this handle has been opened
502
rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
505
return SCARD_E_INVALID_HANDLE;
507
SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
510
for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
512
char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
514
/* by default r == NULL */
515
if (r && strcmp(r, (readerStates[i])->readerName) == 0)
519
if (i == PCSCLITE_MAX_READERS_CONTEXTS)
521
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
522
return SCARD_E_READER_UNAVAILABLE;
525
scReconnectStruct.hCard = hCard;
526
scReconnectStruct.dwShareMode = dwShareMode;
527
scReconnectStruct.dwPreferredProtocols = dwPreferredProtocols;
528
scReconnectStruct.dwInitialization = dwInitialization;
529
scReconnectStruct.pdwActiveProtocol = *pdwActiveProtocol;
531
rv = WrapSHMWrite(SCARD_RECONNECT, psContextMap[dwContextIndex].dwClientID,
532
sizeof(scReconnectStruct),
533
PCSCLITE_CLIENT_ATTEMPTS, (void *) &scReconnectStruct);
537
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
538
return SCARD_E_NO_SERVICE;
542
* Read a message from the server
544
rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
546
memcpy(&scReconnectStruct, &msgStruct.data, sizeof(scReconnectStruct));
550
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
551
return SCARD_F_COMM_ERROR;
554
*pdwActiveProtocol = scReconnectStruct.pdwActiveProtocol;
556
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
558
return scReconnectStruct.rv;
561
LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
564
disconnect_struct scDisconnectStruct;
565
sharedSegmentMsg msgStruct;
566
DWORD dwContextIndex, dwChannelIndex;
568
if (dwDisposition != SCARD_LEAVE_CARD &&
569
dwDisposition != SCARD_RESET_CARD &&
570
dwDisposition != SCARD_UNPOWER_CARD &&
571
dwDisposition != SCARD_EJECT_CARD)
573
return SCARD_E_INVALID_VALUE;
576
if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
577
return SCARD_E_NO_SERVICE;
580
* Make sure this handle has been opened
582
rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
585
return SCARD_E_INVALID_HANDLE;
587
SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
589
scDisconnectStruct.hCard = hCard;
590
scDisconnectStruct.dwDisposition = dwDisposition;
592
rv = WrapSHMWrite(SCARD_DISCONNECT, psContextMap[dwContextIndex].dwClientID,
593
sizeof(scDisconnectStruct),
594
PCSCLITE_CLIENT_ATTEMPTS, (void *) &scDisconnectStruct);
598
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
599
return SCARD_E_NO_SERVICE;
603
* Read a message from the server
605
rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
607
memcpy(&scDisconnectStruct, &msgStruct.data,
608
sizeof(scDisconnectStruct));
612
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
613
return SCARD_F_COMM_ERROR;
616
SCardRemoveHandle(hCard);
618
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
620
return scDisconnectStruct.rv;
623
LONG SCardBeginTransaction(SCARDHANDLE hCard)
627
begin_struct scBeginStruct;
629
sharedSegmentMsg msgStruct;
630
DWORD dwContextIndex, dwChannelIndex;
632
if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
633
return SCARD_E_NO_SERVICE;
636
* Make sure this handle has been opened
638
rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
641
return SCARD_E_INVALID_HANDLE;
643
SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
645
for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
647
char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
649
/* by default r == NULL */
650
if (r && strcmp(r, (readerStates[i])->readerName) == 0)
654
if (i == PCSCLITE_MAX_READERS_CONTEXTS)
656
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
657
return SCARD_E_READER_UNAVAILABLE;
660
scBeginStruct.hCard = hCard;
663
* Query the server every so often until the sharing violation ends
664
* and then hold the lock for yourself.
670
* Look to see if it is locked before polling the server for
671
* admission to the readers resources
673
if ((readerStates[i])->lockState != 0)
678
for (j = 0; j < 100; j++)
681
* This helps prevent starvation
683
randnum = SYS_RandomInt(1000, 10000);
686
if ((readerStates[i])->lockState == 0)
693
rv = WrapSHMWrite(SCARD_BEGIN_TRANSACTION, psContextMap[dwContextIndex].dwClientID,
694
sizeof(scBeginStruct),
695
PCSCLITE_CLIENT_ATTEMPTS, (void *) &scBeginStruct);
700
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
701
return SCARD_E_NO_SERVICE;
705
* Read a message from the server
707
rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
710
memcpy(&scBeginStruct, &msgStruct.data, sizeof(scBeginStruct));
715
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
716
return SCARD_F_COMM_ERROR;
720
while (scBeginStruct.rv == SCARD_E_SHARING_VIOLATION);
722
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
723
return scBeginStruct.rv;
726
LONG SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
729
end_struct scEndStruct;
730
sharedSegmentMsg msgStruct;
732
DWORD dwContextIndex, dwChannelIndex;
735
* Zero out everything
739
if (dwDisposition != SCARD_LEAVE_CARD &&
740
dwDisposition != SCARD_RESET_CARD &&
741
dwDisposition != SCARD_UNPOWER_CARD &&
742
dwDisposition != SCARD_EJECT_CARD)
744
return SCARD_E_INVALID_VALUE;
747
if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
748
return SCARD_E_NO_SERVICE;
751
* Make sure this handle has been opened
753
rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
756
return SCARD_E_INVALID_HANDLE;
758
SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
760
for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
762
char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
764
/* by default r == NULL */
765
if (r && strcmp(r, (readerStates[i])->readerName) == 0)
769
if (i == PCSCLITE_MAX_READERS_CONTEXTS)
771
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
772
return SCARD_E_READER_UNAVAILABLE;
775
scEndStruct.hCard = hCard;
776
scEndStruct.dwDisposition = dwDisposition;
778
rv = WrapSHMWrite(SCARD_END_TRANSACTION, psContextMap[dwContextIndex].dwClientID,
780
PCSCLITE_CLIENT_ATTEMPTS, (void *) &scEndStruct);
784
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
785
return SCARD_E_NO_SERVICE;
789
* Read a message from the server
791
rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
793
memcpy(&scEndStruct, &msgStruct.data, sizeof(scEndStruct));
797
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
798
return SCARD_F_COMM_ERROR;
802
* This helps prevent starvation
804
randnum = SYS_RandomInt(1000, 10000);
807
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
809
return scEndStruct.rv;
812
LONG SCardCancelTransaction(SCARDHANDLE hCard)
815
cancel_struct scCancelStruct;
816
sharedSegmentMsg msgStruct;
818
DWORD dwContextIndex, dwChannelIndex;
820
if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
821
return SCARD_E_NO_SERVICE;
824
* Make sure this handle has been opened
826
rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
829
return SCARD_E_INVALID_HANDLE;
831
SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
833
for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
835
char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
837
/* by default r == NULL */
838
if (r && strcmp(r, (readerStates[i])->readerName) == 0)
842
if (i == PCSCLITE_MAX_READERS_CONTEXTS)
844
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
845
return SCARD_E_READER_UNAVAILABLE;
848
scCancelStruct.hCard = hCard;
850
rv = WrapSHMWrite(SCARD_CANCEL_TRANSACTION, psContextMap[dwContextIndex].dwClientID,
851
sizeof(scCancelStruct),
852
PCSCLITE_CLIENT_ATTEMPTS, (void *) &scCancelStruct);
856
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
857
return SCARD_E_NO_SERVICE;
861
* Read a message from the server
863
rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
865
memcpy(&scCancelStruct, &msgStruct.data, sizeof(scCancelStruct));
869
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
870
return SCARD_F_COMM_ERROR;
873
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
875
return scCancelStruct.rv;
878
LONG SCardStatus(SCARDHANDLE hCard, LPTSTR mszReaderNames,
879
LPDWORD pcchReaderLen, LPDWORD pdwState,
880
LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
882
DWORD dwReaderLen, dwAtrLen;
885
status_struct scStatusStruct;
886
sharedSegmentMsg msgStruct;
887
DWORD dwContextIndex, dwChannelIndex;
890
* Check for NULL parameters
893
if (pcchReaderLen == NULL || pcbAtrLen == NULL)
894
return SCARD_E_INVALID_PARAMETER;
896
/* length passed from caller */
897
dwReaderLen = *pcchReaderLen;
898
dwAtrLen = *pcbAtrLen;
900
/* default output values */
910
if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
911
return SCARD_E_NO_SERVICE;
914
* Make sure this handle has been opened
916
rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
919
return SCARD_E_INVALID_HANDLE;
921
SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
923
for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
925
char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
927
/* by default r == NULL */
928
if (r && strcmp(r, (readerStates[i])->readerName) == 0)
932
if (i == PCSCLITE_MAX_READERS_CONTEXTS)
934
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
935
return SCARD_E_READER_UNAVAILABLE;
938
/* initialise the structure */
939
memset(&scStatusStruct, 0, sizeof(scStatusStruct));
940
scStatusStruct.hCard = hCard;
942
/* those sizes need to be initialised */
943
scStatusStruct.pcchReaderLen = sizeof(scStatusStruct.mszReaderNames);
944
scStatusStruct.pcbAtrLen = sizeof(scStatusStruct.pbAtr);
946
rv = WrapSHMWrite(SCARD_STATUS, psContextMap[dwContextIndex].dwClientID,
947
sizeof(scStatusStruct),
948
PCSCLITE_CLIENT_ATTEMPTS, (void *) &scStatusStruct);
952
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
953
return SCARD_E_NO_SERVICE;
957
* Read a message from the server
959
rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
961
memcpy(&scStatusStruct, &msgStruct.data, sizeof(scStatusStruct));
965
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
966
return SCARD_F_COMM_ERROR;
969
rv = scStatusStruct.rv;
970
if (rv != SCARD_S_SUCCESS && rv != SCARD_E_INSUFFICIENT_BUFFER)
973
* An event must have occurred
975
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
980
* Now continue with the client side SCardStatus
983
*pcchReaderLen = strlen(psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName) + 1;
984
*pcbAtrLen = (readerStates[i])->cardAtrLength;
987
*pdwState = (readerStates[i])->readerState;
990
*pdwProtocol = (readerStates[i])->cardProtocol;
992
/* return SCARD_E_INSUFFICIENT_BUFFER only if buffer pointer is non NULL */
995
if (*pcchReaderLen > dwReaderLen)
996
rv = SCARD_E_INSUFFICIENT_BUFFER;
998
strncpy(mszReaderNames,
999
psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName,
1005
if (*pcbAtrLen > dwAtrLen)
1006
rv = SCARD_E_INSUFFICIENT_BUFFER;
1008
memcpy(pbAtr, (readerStates[i])->cardAtr,
1009
min(*pcbAtrLen, dwAtrLen));
1012
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
1017
LONG SCardGetStatusChange(SCARDCONTEXT hContext, DWORD dwTimeout,
1018
LPSCARD_READERSTATE_A rgReaderStates, DWORD cReaders)
1020
PSCARD_READERSTATE_A currReader;
1021
PREADER_STATE rContext;
1024
DWORD dwBreakFlag = 0;
1026
DWORD dwContextIndex;
1028
if (rgReaderStates == 0 && cReaders > 0)
1029
return SCARD_E_INVALID_PARAMETER;
1032
return SCARD_E_INVALID_VALUE;
1034
if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
1035
return SCARD_E_NO_SERVICE;
1038
* Make sure this context has been opened
1041
dwContextIndex = SCardGetContextIndice(hContext);
1042
if (dwContextIndex == -1)
1043
return SCARD_E_INVALID_HANDLE;
1045
SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
1048
* Application is waiting for a reader - return the first available
1058
if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
1060
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
1061
return SCARD_E_NO_SERVICE;
1064
for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
1066
if ((readerStates[i])->readerID != 0)
1071
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
1072
return SCARD_S_SUCCESS;
1079
* return immediately - no reader available
1081
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
1082
return SCARD_E_READER_UNAVAILABLE;
1085
SYS_USleep(PCSCLITE_STATUS_WAIT);
1087
if (dwTimeout != INFINITE)
1089
dwTime += PCSCLITE_STATUS_WAIT;
1091
if (dwTime >= (dwTimeout * 1000))
1093
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
1094
return SCARD_E_TIMEOUT;
1100
if (cReaders >= PCSCLITE_MAX_READERS_CONTEXTS)
1102
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
1103
return SCARD_E_INVALID_VALUE;
1107
* Check the integrity of the reader states structures
1110
for (j = 0; j < cReaders; j++)
1112
currReader = &rgReaderStates[j];
1114
if (currReader->szReader == 0)
1116
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
1117
return SCARD_E_INVALID_VALUE;
1122
* End of search for readers
1126
* Clear the event state for all readers
1128
for (j = 0; j < cReaders; j++)
1130
currReader = &rgReaderStates[j];
1131
currReader->dwEventState = 0;
1135
* Now is where we start our event checking loop
1138
Log1(PCSC_LOG_DEBUG, "Event Loop Start");
1140
psContextMap[dwContextIndex].contextBlockStatus = BLOCK_STATUS_BLOCKING;
1146
if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
1148
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
1149
return SCARD_E_NO_SERVICE;
1152
currReader = &rgReaderStates[j];
1154
/************ Look for IGNORED readers ****************************/
1156
if (currReader->dwCurrentState & SCARD_STATE_IGNORE)
1158
currReader->dwEventState = SCARD_STATE_IGNORE;
1161
LPTSTR lpcReaderName;
1164
/************ Looks for correct readernames *********************/
1166
lpcReaderName = (char *) currReader->szReader;
1168
for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
1170
if (strcmp(lpcReaderName,
1171
(readerStates[i])->readerName) == 0)
1178
* The requested reader name is not recognized
1180
if (i == PCSCLITE_MAX_READERS_CONTEXTS)
1182
if (currReader->dwCurrentState & SCARD_STATE_UNKNOWN)
1184
currReader->dwEventState = SCARD_STATE_UNKNOWN;
1187
currReader->dwEventState =
1188
SCARD_STATE_UNKNOWN | SCARD_STATE_CHANGED;
1190
* Spec says use SCARD_STATE_IGNORE but a removed USB
1191
* reader with eventState fed into currentState will
1192
* be ignored forever
1200
* The reader has come back after being away
1202
if (currReader->dwCurrentState & SCARD_STATE_UNKNOWN)
1204
currReader->dwEventState |= SCARD_STATE_CHANGED;
1205
currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
1209
/*****************************************************************/
1212
* Set the reader status structure
1214
rContext = readerStates[i];
1217
* Now we check all the Reader States
1219
dwState = rContext->readerState;
1221
/*********** Check if the reader is in the correct state ********/
1222
if (dwState & SCARD_UNKNOWN)
1225
* App thinks reader is in bad state and it is
1228
dwCurrentState & SCARD_STATE_UNAVAILABLE)
1230
currReader->dwEventState = SCARD_STATE_UNAVAILABLE;
1234
* App thinks reader is in good state and it is
1237
currReader->dwEventState = SCARD_STATE_CHANGED |
1238
SCARD_STATE_UNAVAILABLE;
1244
* App thinks reader in bad state but it is not
1247
dwCurrentState & SCARD_STATE_UNAVAILABLE)
1249
currReader->dwEventState &=
1250
~SCARD_STATE_UNAVAILABLE;
1251
currReader->dwEventState |= SCARD_STATE_CHANGED;
1256
/********** Check for card presence in the reader **************/
1258
if (dwState & SCARD_PRESENT)
1260
/* card present but not yet powered up */
1261
if (0 == rContext->cardAtrLength)
1262
/* Allow the status thread to convey information */
1263
SYS_USleep(PCSCLITE_STATUS_POLL_RATE + 10);
1265
currReader->cbAtr = rContext->cardAtrLength;
1266
memcpy(currReader->rgbAtr, rContext->cardAtr,
1270
currReader->cbAtr = 0;
1274
* Card is now absent
1276
if (dwState & SCARD_ABSENT)
1278
currReader->dwEventState |= SCARD_STATE_EMPTY;
1279
currReader->dwEventState &= ~SCARD_STATE_PRESENT;
1280
currReader->dwEventState &= ~SCARD_STATE_UNAWARE;
1281
currReader->dwEventState &= ~SCARD_STATE_IGNORE;
1282
currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
1283
currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
1284
currReader->dwEventState &= ~SCARD_STATE_ATRMATCH;
1285
currReader->dwEventState &= ~SCARD_STATE_MUTE;
1286
currReader->dwEventState &= ~SCARD_STATE_INUSE;
1289
* After present the rest are assumed
1291
if (currReader->dwCurrentState & SCARD_STATE_PRESENT ||
1292
currReader->dwCurrentState & SCARD_STATE_ATRMATCH
1294
dwCurrentState & SCARD_STATE_EXCLUSIVE
1295
|| currReader->dwCurrentState & SCARD_STATE_INUSE)
1297
currReader->dwEventState |= SCARD_STATE_CHANGED;
1302
* Card is now present
1304
} else if (dwState & SCARD_PRESENT)
1306
currReader->dwEventState |= SCARD_STATE_PRESENT;
1307
currReader->dwEventState &= ~SCARD_STATE_EMPTY;
1308
currReader->dwEventState &= ~SCARD_STATE_UNAWARE;
1309
currReader->dwEventState &= ~SCARD_STATE_IGNORE;
1310
currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
1311
currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
1312
currReader->dwEventState &= ~SCARD_STATE_MUTE;
1314
if (currReader->dwCurrentState & SCARD_STATE_EMPTY)
1316
currReader->dwEventState |= SCARD_STATE_CHANGED;
1320
if (dwState & SCARD_SWALLOWED)
1322
if (currReader->dwCurrentState & SCARD_STATE_MUTE)
1324
currReader->dwEventState |= SCARD_STATE_MUTE;
1327
currReader->dwEventState |= SCARD_STATE_MUTE;
1328
if (currReader->dwCurrentState !=
1329
SCARD_STATE_UNAWARE)
1331
currReader->dwEventState |=
1332
SCARD_STATE_CHANGED;
1339
* App thinks card is mute but it is not
1341
if (currReader->dwCurrentState & SCARD_STATE_MUTE)
1343
currReader->dwEventState |=
1344
SCARD_STATE_CHANGED;
1351
* Now figure out sharing modes
1353
if (rContext->readerSharing == -1)
1355
currReader->dwEventState |= SCARD_STATE_EXCLUSIVE;
1356
currReader->dwEventState &= ~SCARD_STATE_INUSE;
1357
if (currReader->dwCurrentState & SCARD_STATE_INUSE)
1359
currReader->dwEventState |= SCARD_STATE_CHANGED;
1362
} else if (rContext->readerSharing >= 1)
1365
* A card must be inserted for it to be INUSE
1367
if (dwState & SCARD_PRESENT)
1369
currReader->dwEventState |= SCARD_STATE_INUSE;
1370
currReader->dwEventState &= ~SCARD_STATE_EXCLUSIVE;
1372
dwCurrentState & SCARD_STATE_EXCLUSIVE)
1374
currReader->dwEventState |=
1375
SCARD_STATE_CHANGED;
1379
} else if (rContext->readerSharing == 0)
1381
currReader->dwEventState &= ~SCARD_STATE_INUSE;
1382
currReader->dwEventState &= ~SCARD_STATE_EXCLUSIVE;
1384
if (currReader->dwCurrentState & SCARD_STATE_INUSE)
1386
currReader->dwEventState |= SCARD_STATE_CHANGED;
1388
} else if (currReader->
1389
dwCurrentState & SCARD_STATE_EXCLUSIVE)
1391
currReader->dwEventState |= SCARD_STATE_CHANGED;
1396
if (currReader->dwCurrentState == SCARD_STATE_UNAWARE)
1399
* Break out of the while .. loop and return status
1400
* once all the status's for all readers is met
1402
currReader->dwEventState |= SCARD_STATE_CHANGED;
1406
} /* End of SCARD_STATE_UNKNOWN */
1408
} /* End of SCARD_STATE_IGNORE */
1411
* Counter and resetter
1418
* Declare all the break conditions
1421
if (psContextMap[dwContextIndex].contextBlockStatus ==
1422
BLOCK_STATUS_RESUME)
1426
* Break if UNAWARE is set and all readers have been checked
1428
if ((dwBreakFlag == 1) && (j == 0))
1432
* Timeout has occurred and all readers checked
1434
if ((dwTimeout == 0) && (j == 0))
1437
if (dwTimeout != INFINITE && dwTimeout != 0)
1440
* If time is greater than timeout and all readers have been
1443
if ((dwTime >= (dwTimeout * 1000)) && (j == 0))
1445
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
1446
return SCARD_E_TIMEOUT;
1451
* Only sleep once for each cycle of reader checks.
1455
SYS_USleep(PCSCLITE_STATUS_WAIT);
1456
dwTime += PCSCLITE_STATUS_WAIT;
1461
Log1(PCSC_LOG_DEBUG, "Event Loop End");
1463
if (psContextMap[dwContextIndex].contextBlockStatus ==
1464
BLOCK_STATUS_RESUME)
1466
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
1467
return SCARD_E_CANCELLED;
1470
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
1472
return SCARD_S_SUCCESS;
1475
LONG SCardControl(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer,
1476
DWORD cbSendLength, LPVOID pbRecvBuffer, DWORD cbRecvLength,
1477
LPDWORD lpBytesReturned)
1480
control_struct scControlStruct;
1481
sharedSegmentMsg msgStruct;
1483
DWORD dwContextIndex, dwChannelIndex;
1485
/* 0 bytes received by default */
1486
if (NULL != lpBytesReturned)
1487
*lpBytesReturned = 0;
1489
if (pbSendBuffer == 0)
1490
return SCARD_E_INVALID_PARAMETER;
1492
if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
1493
return SCARD_E_NO_SERVICE;
1496
* Make sure this handle has been opened
1498
rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
1501
return SCARD_E_INVALID_HANDLE;
1503
SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
1505
for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
1507
char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
1509
/* by default r == NULL */
1510
if (r && strcmp(r, (readerStates[i])->readerName) == 0)
1514
if (i == PCSCLITE_MAX_READERS_CONTEXTS)
1516
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
1517
return SCARD_E_READER_UNAVAILABLE;
1520
if (cbSendLength > MAX_BUFFER_SIZE)
1522
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
1523
return SCARD_E_INSUFFICIENT_BUFFER;
1526
scControlStruct.hCard = hCard;
1527
scControlStruct.dwControlCode = dwControlCode;
1528
scControlStruct.cbSendLength = cbSendLength;
1529
scControlStruct.cbRecvLength = cbRecvLength;
1530
memcpy(scControlStruct.pbSendBuffer, pbSendBuffer, cbSendLength);
1532
rv = WrapSHMWrite(SCARD_CONTROL, psContextMap[dwContextIndex].dwClientID,
1533
sizeof(scControlStruct), PCSCLITE_CLIENT_ATTEMPTS, &scControlStruct);
1537
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
1538
return SCARD_E_NO_SERVICE;
1542
* Read a message from the server
1544
rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
1548
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
1549
return SCARD_F_COMM_ERROR;
1552
memcpy(&scControlStruct, &msgStruct.data, sizeof(scControlStruct));
1554
if (NULL != lpBytesReturned)
1555
*lpBytesReturned = scControlStruct.dwBytesReturned;
1557
if (scControlStruct.rv == SCARD_S_SUCCESS)
1560
* Copy and zero it so any secret information is not leaked
1562
memcpy(pbRecvBuffer, scControlStruct.pbRecvBuffer,
1563
scControlStruct.cbRecvLength);
1564
memset(scControlStruct.pbRecvBuffer, 0x00,
1565
sizeof(scControlStruct.pbRecvBuffer));
1568
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
1570
return scControlStruct.rv;
1573
LONG SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr,
1576
if (NULL == pcbAttrLen)
1577
return SCARD_E_INVALID_PARAMETER;
1579
/* if only get the length */
1581
/* this variable may not be set by the caller. use a reasonable size */
1582
*pcbAttrLen = MAX_BUFFER_SIZE;
1584
return SCardGetSetAttrib(hCard, SCARD_GET_ATTRIB, dwAttrId, pbAttr,
1588
LONG SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr,
1591
if (NULL == pbAttr || 0 == cbAttrLen)
1592
return SCARD_E_INVALID_PARAMETER;
1594
return SCardGetSetAttrib(hCard, SCARD_SET_ATTRIB, dwAttrId, (LPBYTE)pbAttr,
1598
static LONG SCardGetSetAttrib(SCARDHANDLE hCard, int command, DWORD dwAttrId,
1599
LPBYTE pbAttr, LPDWORD pcbAttrLen)
1602
getset_struct scGetSetStruct;
1603
sharedSegmentMsg msgStruct;
1605
DWORD dwContextIndex, dwChannelIndex;
1607
if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
1608
return SCARD_E_NO_SERVICE;
1611
* Make sure this handle has been opened
1613
rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
1616
return SCARD_E_INVALID_HANDLE;
1618
SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
1620
for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
1622
char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
1624
/* by default r == NULL */
1625
if (r && strcmp(r, (readerStates[i])->readerName) == 0)
1629
if (i == PCSCLITE_MAX_READERS_CONTEXTS)
1631
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
1632
return SCARD_E_READER_UNAVAILABLE;
1635
if (*pcbAttrLen > MAX_BUFFER_SIZE)
1637
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
1638
return SCARD_E_INSUFFICIENT_BUFFER;
1641
scGetSetStruct.hCard = hCard;
1642
scGetSetStruct.dwAttrId = dwAttrId;
1643
scGetSetStruct.cbAttrLen = *pcbAttrLen;
1644
scGetSetStruct.rv = SCARD_E_NO_SERVICE;
1645
if (SCARD_SET_ATTRIB == command)
1646
memcpy(scGetSetStruct.pbAttr, pbAttr, *pcbAttrLen);
1648
rv = WrapSHMWrite(command,
1649
psContextMap[dwContextIndex].dwClientID, sizeof(scGetSetStruct),
1650
PCSCLITE_CLIENT_ATTEMPTS, &scGetSetStruct);
1654
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
1655
return SCARD_E_NO_SERVICE;
1659
* Read a message from the server
1661
rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
1665
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
1666
return SCARD_F_COMM_ERROR;
1669
memcpy(&scGetSetStruct, &msgStruct.data, sizeof(scGetSetStruct));
1671
if ((SCARD_S_SUCCESS == scGetSetStruct.rv) && (SCARD_GET_ATTRIB == command))
1674
* Copy and zero it so any secret information is not leaked
1676
if (*pcbAttrLen < scGetSetStruct.cbAttrLen)
1678
scGetSetStruct.cbAttrLen = *pcbAttrLen;
1679
scGetSetStruct.rv = SCARD_E_INSUFFICIENT_BUFFER;
1682
*pcbAttrLen = scGetSetStruct.cbAttrLen;
1685
memcpy(pbAttr, scGetSetStruct.pbAttr, scGetSetStruct.cbAttrLen);
1687
memset(scGetSetStruct.pbAttr, 0x00, sizeof(scGetSetStruct.pbAttr));
1690
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
1692
return scGetSetStruct.rv;
1695
LONG SCardTransmit(SCARDHANDLE hCard, LPCSCARD_IO_REQUEST pioSendPci,
1696
LPCBYTE pbSendBuffer, DWORD cbSendLength,
1697
LPSCARD_IO_REQUEST pioRecvPci, LPBYTE pbRecvBuffer,
1698
LPDWORD pcbRecvLength)
1701
transmit_struct scTransmitStruct;
1702
sharedSegmentMsg msgStruct;
1704
DWORD dwContextIndex, dwChannelIndex;
1706
if (pbSendBuffer == 0 || pbRecvBuffer == 0 ||
1707
pcbRecvLength == 0 || pioSendPci == 0)
1708
return SCARD_E_INVALID_PARAMETER;
1710
if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
1711
return SCARD_E_NO_SERVICE;
1714
* Make sure this handle has been opened
1716
rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
1721
return SCARD_E_INVALID_HANDLE;
1724
SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
1726
for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
1728
char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
1730
/* by default r == NULL */
1731
if (r && strcmp(r, (readerStates[i])->readerName) == 0)
1735
if (i == PCSCLITE_MAX_READERS_CONTEXTS)
1737
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
1738
return SCARD_E_READER_UNAVAILABLE;
1741
if (cbSendLength > MAX_BUFFER_SIZE)
1743
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
1744
return SCARD_E_INSUFFICIENT_BUFFER;
1747
scTransmitStruct.hCard = hCard;
1748
scTransmitStruct.cbSendLength = cbSendLength;
1749
scTransmitStruct.pcbRecvLength = *pcbRecvLength;
1750
memcpy(&scTransmitStruct.pioSendPci, pioSendPci,
1751
sizeof(SCARD_IO_REQUEST));
1752
memcpy(scTransmitStruct.pbSendBuffer, pbSendBuffer, cbSendLength);
1756
memcpy(&scTransmitStruct.pioRecvPci, pioRecvPci,
1757
sizeof(SCARD_IO_REQUEST));
1760
scTransmitStruct.pioRecvPci.dwProtocol = SCARD_PROTOCOL_ANY;
1762
rv = WrapSHMWrite(SCARD_TRANSMIT, psContextMap[dwContextIndex].dwClientID,
1763
sizeof(scTransmitStruct),
1764
PCSCLITE_CLIENT_ATTEMPTS, (void *) &scTransmitStruct);
1768
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
1769
return SCARD_E_NO_SERVICE;
1773
* Read a message from the server
1775
rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
1777
memcpy(&scTransmitStruct, &msgStruct.data, sizeof(scTransmitStruct));
1781
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
1782
return SCARD_F_COMM_ERROR;
1786
* Zero it and free it so any secret information cannot be leaked
1788
memset(scTransmitStruct.pbSendBuffer, 0x00, cbSendLength);
1790
if (scTransmitStruct.rv == SCARD_S_SUCCESS)
1792
*pcbRecvLength = scTransmitStruct.pcbRecvLength;
1795
* Copy and zero it so any secret information is not leaked
1797
memcpy(pbRecvBuffer, scTransmitStruct.pbRecvBuffer,
1798
scTransmitStruct.pcbRecvLength);
1799
memset(scTransmitStruct.pbRecvBuffer, 0x00,
1800
scTransmitStruct.pcbRecvLength);
1804
memcpy(pioRecvPci, &scTransmitStruct.pioRecvPci,
1805
sizeof(SCARD_IO_REQUEST));
1808
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
1810
return scTransmitStruct.rv;
1813
*pcbRecvLength = scTransmitStruct.pcbRecvLength;
1814
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
1815
return scTransmitStruct.rv;
1819
LONG SCardListReaders(SCARDCONTEXT hContext, LPCTSTR mszGroups,
1820
LPTSTR mszReaders, LPDWORD pcchReaders)
1824
DWORD dwContextIndex;
1827
* Check for NULL parameters
1829
if (pcchReaders == NULL)
1830
return SCARD_E_INVALID_PARAMETER;
1832
if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
1833
return SCARD_E_NO_SERVICE;
1836
* Make sure this context has been opened
1838
dwContextIndex = SCardGetContextIndice(hContext);
1839
if (dwContextIndex == -1)
1840
return SCARD_E_INVALID_HANDLE;
1842
SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
1845
for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
1846
if ((readerStates[i])->readerID != 0)
1847
dwReadersLen += strlen((readerStates[i])->readerName) + 1;
1849
/* for the last NULL byte */
1852
if ((mszReaders == NULL) /* text array not allocated */
1853
|| (*pcchReaders == 0)) /* size == 0 */
1855
*pcchReaders = dwReadersLen;
1856
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
1857
return SCARD_S_SUCCESS;
1860
if (*pcchReaders < dwReadersLen)
1862
*pcchReaders = dwReadersLen;
1863
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
1864
return SCARD_E_INSUFFICIENT_BUFFER;
1868
for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
1870
if ((readerStates[i])->readerID != 0)
1873
* Build the multi-string
1875
strcpy(&mszReaders[lastChrPtr], (readerStates[i])->readerName);
1876
lastChrPtr += strlen((readerStates[i])->readerName)+1;
1879
mszReaders[lastChrPtr] = '\0'; /* Add the last null */
1881
*pcchReaders = dwReadersLen;
1883
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
1884
return SCARD_S_SUCCESS;
1887
LONG SCardListReaderGroups(SCARDCONTEXT hContext, LPTSTR mszGroups,
1890
LONG rv = SCARD_S_SUCCESS;
1891
DWORD dwContextIndex;
1893
const char ReaderGroup[] = "SCard$DefaultReaders";
1894
const int dwGroups = strlen(ReaderGroup) + 2;
1896
if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
1897
return SCARD_E_NO_SERVICE;
1900
* Make sure this context has been opened
1902
dwContextIndex = SCardGetContextIndice(hContext);
1903
if (dwContextIndex == -1)
1904
return SCARD_E_INVALID_HANDLE;
1906
SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
1911
if (*pcchGroups < dwGroups)
1912
rv = SCARD_E_INSUFFICIENT_BUFFER;
1915
memset(mszGroups, 0, dwGroups);
1916
memcpy(mszGroups, ReaderGroup, strlen(ReaderGroup));
1920
*pcchGroups = dwGroups;
1922
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
1926
LONG SCardCancel(SCARDCONTEXT hContext)
1928
DWORD dwContextIndex;
1930
dwContextIndex = SCardGetContextIndice(hContext);
1932
if (dwContextIndex == -1)
1933
return SCARD_E_INVALID_HANDLE;
1935
SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
1938
* Set the block status for this Context so blocking calls will
1941
psContextMap[dwContextIndex].contextBlockStatus = BLOCK_STATUS_RESUME;
1943
SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
1945
return SCARD_S_SUCCESS;
1949
* Functions for managing instances of SCardEstablishContext These
1950
* functions keep track of Context handles and associate the blocking
1951
* variable contextBlockStatus to an hContext
1954
static LONG SCardAddContext(SCARDCONTEXT hContext, DWORD dwClientID)
1958
for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
1960
if (psContextMap[i].hContext == 0)
1962
psContextMap[i].hContext = hContext;
1963
psContextMap[i].TID = SYS_ThreadSelf();
1964
psContextMap[i].dwClientID = dwClientID;
1965
psContextMap[i].contextBlockStatus = BLOCK_STATUS_RESUME;
1966
psContextMap[i].mMutex = (PCSCLITE_MUTEX_T) malloc(sizeof(PCSCLITE_MUTEX));
1967
SYS_MutexInit(psContextMap[i].mMutex);
1968
return SCARD_S_SUCCESS;
1972
return SCARD_E_NO_MEMORY;
1975
static LONG SCardGetContextIndice(SCARDCONTEXT hContext)
1980
rv = SCardGetContextIndiceTH(hContext);
1981
SCardUnlockThread();
1987
static LONG SCardGetContextIndiceTH(SCARDCONTEXT hContext)
1992
* Find this context and return it's spot in the array
1994
for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
1996
if ((hContext == psContextMap[i].hContext) && (hContext != 0))
2003
static LONG SCardRemoveContext(SCARDCONTEXT hContext)
2007
retIndice = SCardGetContextIndiceTH(hContext);
2009
if (retIndice == -1)
2010
return SCARD_E_INVALID_HANDLE;
2015
psContextMap[retIndice].hContext = 0;
2016
SHMClientCloseSession(psContextMap[retIndice].dwClientID);
2017
psContextMap[retIndice].dwClientID = 0;
2018
free(psContextMap[retIndice].mMutex);
2019
psContextMap[retIndice].mMutex = 0;
2020
psContextMap[retIndice].contextBlockStatus = BLOCK_STATUS_RESUME;
2022
for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
2025
* Initially set the hcard structs to zero
2027
psContextMap[retIndice].psChannelMap[i].hCard = 0;
2028
free(psContextMap[retIndice].psChannelMap[i].readerName);
2029
psContextMap[retIndice].psChannelMap[i].readerName = NULL;
2032
return SCARD_S_SUCCESS;
2037
* Functions for managing hCard values returned from SCardConnect.
2040
static LONG SCardAddHandle(SCARDHANDLE hCard, DWORD dwContextIndex,
2045
for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
2047
if (psContextMap[dwContextIndex].psChannelMap[i].hCard == 0)
2049
psContextMap[dwContextIndex].psChannelMap[i].hCard = hCard;
2050
psContextMap[dwContextIndex].psChannelMap[i].readerName = strdup(readerName);
2051
return SCARD_S_SUCCESS;
2055
return SCARD_E_NO_MEMORY;
2058
static LONG SCardRemoveHandle(SCARDHANDLE hCard)
2060
DWORD dwContextIndice, dwChannelIndice;
2063
rv = SCardGetIndicesFromHandle(hCard, &dwContextIndice, &dwChannelIndice);
2066
return SCARD_E_INVALID_HANDLE;
2069
psContextMap[dwContextIndice].psChannelMap[dwChannelIndice].hCard = 0;
2070
free(psContextMap[dwContextIndice].psChannelMap[dwChannelIndice].readerName);
2071
psContextMap[dwContextIndice].psChannelMap[dwChannelIndice].readerName = NULL;
2072
return SCARD_S_SUCCESS;
2076
static LONG SCardGetIndicesFromHandle(SCARDHANDLE hCard, PDWORD pdwContextIndice, PDWORD pdwChannelIndice)
2081
rv = SCardGetIndicesFromHandleTH(hCard, pdwContextIndice, pdwChannelIndice);
2082
SCardUnlockThread();
2087
static LONG SCardGetIndicesFromHandleTH(SCARDHANDLE hCard, PDWORD pdwContextIndice, PDWORD pdwChannelIndice)
2091
for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
2093
if (psContextMap[i].hContext != 0)
2097
for (j = 0; j < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; j++)
2099
if (psContextMap[i].psChannelMap[j].hCard == hCard)
2101
*pdwContextIndice = i;
2102
*pdwChannelIndice = j;
2103
return SCARD_S_SUCCESS;
2114
* This function locks a mutex so another thread must wait to use this
2118
inline static LONG SCardLockThread(void)
2120
return SYS_MutexLock(&clientMutex);
2124
* This function unlocks a mutex so another thread may use the client
2128
inline static LONG SCardUnlockThread(void)
2130
return SYS_MutexUnLock(&clientMutex);
2133
static LONG SCardCheckDaemonAvailability(void)
2136
struct stat statBuffer;
2138
rv = SYS_Stat(PCSCLITE_IPC_DIR, &statBuffer);
2142
Log1(PCSC_LOG_ERROR, "PCSC Not Running");
2143
return SCARD_E_NO_SERVICE;
2146
return SCARD_S_SUCCESS;
2150
* free resources allocated by the library
2151
* You _shall_ call this function if you use dlopen/dlclose to load/unload the
2152
* library. Otherwise you will exhaust the ressources available.
2154
void SCardUnload(void)
2159
SYS_CloseFile(mapAddr);