diff --git a/channels/smartcard/client/smartcard_operations.c b/channels/smartcard/client/smartcard_operations.c index cb66727c7..191d84aa6 100644 --- a/channels/smartcard/client/smartcard_operations.c +++ b/channels/smartcard/client/smartcard_operations.c @@ -145,32 +145,6 @@ const char* smartcard_get_ioctl_string(UINT32 ioControlCode, BOOL funcName) return funcName ? "SCardUnknown" : "SCARD_IOCTL_UNKNOWN"; } -size_t smartcard_multi_string_length_a(const char* msz) -{ - char* p = (char*) msz; - - if (!p) - return 0; - - while ((p[0] != 0) && (p[1] != 0)) - p++; - - return (p - msz) + 1; -} - -size_t smartcard_multi_string_length_w(const WCHAR* msz) -{ - WCHAR* p = (WCHAR*) msz; - - if (!p) - return 0; - - while ((p[0] != 0) && (p[1] != 0)) - p++; - - return (p - msz) + 1; -} - static UINT32 smartcard_EstablishContext(SMARTCARD_DEVICE* smartcard, IRP* irp) { UINT32 status; @@ -363,7 +337,7 @@ static UINT32 smartcard_GetStatusChangeA(SMARTCARD_DEVICE* smartcard, IRP* irp) ret.rgReaderStates[index].dwCurrentState = call.rgReaderStates[index].dwCurrentState; ret.rgReaderStates[index].dwEventState = call.rgReaderStates[index].dwEventState; ret.rgReaderStates[index].cbAtr = call.rgReaderStates[index].cbAtr; - CopyMemory(&ret.rgReaderStates[index].rgbAtr, &call.rgReaderStates[index].rgbAtr, 32); + CopyMemory(&(ret.rgReaderStates[index].rgbAtr), &(call.rgReaderStates[index].rgbAtr), 32); } smartcard_trace_get_status_change_return(smartcard, &ret, FALSE); @@ -421,7 +395,7 @@ static UINT32 smartcard_GetStatusChangeW(SMARTCARD_DEVICE* smartcard, IRP* irp) ret.rgReaderStates[index].dwCurrentState = call.rgReaderStates[index].dwCurrentState; ret.rgReaderStates[index].dwEventState = call.rgReaderStates[index].dwEventState; ret.rgReaderStates[index].cbAtr = call.rgReaderStates[index].cbAtr; - CopyMemory(&ret.rgReaderStates[index].rgbAtr, &call.rgReaderStates[index].rgbAtr, 32); + CopyMemory(&(ret.rgReaderStates[index].rgbAtr), &(call.rgReaderStates[index].rgbAtr), 32); } smartcard_trace_get_status_change_return(smartcard, &ret, TRUE); diff --git a/channels/smartcard/client/smartcard_pack.c b/channels/smartcard/client/smartcard_pack.c index bcd997500..3b49e57b6 100644 --- a/channels/smartcard/client/smartcard_pack.c +++ b/channels/smartcard/client/smartcard_pack.c @@ -1496,7 +1496,7 @@ void smartcard_trace_get_status_change_return(SMARTCARD_DEVICE* smartcard, GetSt szCurrentState = SCardGetReaderStateString(rgReaderState->dwCurrentState); szEventState = SCardGetReaderStateString(rgReaderState->dwEventState); - rgbAtr = winpr_BinToHexString(rgReaderState->rgbAtr, rgReaderState->cbAtr, FALSE); + rgbAtr = winpr_BinToHexString((BYTE*) &(rgReaderState->rgbAtr), rgReaderState->cbAtr, FALSE); WLog_Print(smartcard->log, WLOG_DEBUG, "\t[%d]: dwCurrentState: %s (0x%08X)", @@ -2173,8 +2173,8 @@ UINT32 smartcard_unpack_transmit_call(SMARTCARD_DEVICE* smartcard, wStream* s, T Stream_Read_UINT32(s, length); /* Length (4 bytes) */ - Stream_Read_UINT16(s, ioRecvPci.dwProtocol); /* dwProtocol (2 bytes) */ - Stream_Read_UINT16(s, ioRecvPci.cbExtraBytes); /* cbExtraBytes (2 bytes) */ + Stream_Read_UINT32(s, ioRecvPci.dwProtocol); /* dwProtocol (4 bytes) */ + Stream_Read_UINT32(s, ioRecvPci.cbExtraBytes); /* cbExtraBytes (4 bytes) */ if (ioRecvPci.cbExtraBytes > 1024) { @@ -2339,8 +2339,8 @@ UINT32 smartcard_pack_transmit_return(SMARTCARD_DEVICE* smartcard, wStream* s, T Stream_EnsureRemainingCapacity(s, cbExtraBytes + 16); Stream_Write_UINT32(s, cbExtraBytes); /* Length (4 bytes) */ - Stream_Write_UINT16(s, ret->pioRecvPci->dwProtocol); /* dwProtocol (2 bytes) */ - Stream_Write_UINT16(s, cbExtraBytes); /* cbExtraBytes (2 bytes) */ + Stream_Write_UINT32(s, ret->pioRecvPci->dwProtocol); /* dwProtocol (4 bytes) */ + Stream_Write_UINT32(s, cbExtraBytes); /* cbExtraBytes (4 bytes) */ Stream_Write(s, pbExtraBytes, cbExtraBytes); smartcard_pack_write_size_align(smartcard, s, cbExtraBytes, 4); } diff --git a/winpr/include/winpr/smartcard.h b/winpr/include/winpr/smartcard.h index aa401bf58..1eb246229 100644 --- a/winpr/include/winpr/smartcard.h +++ b/winpr/include/winpr/smartcard.h @@ -227,6 +227,12 @@ #define SCARD_NEGOTIABLE 5 #define SCARD_SPECIFIC 6 +#if defined(__APPLE__) | defined(sun) +#pragma pack(1) +#else +#pragma pack(push, 1) +#endif + typedef struct _SCARD_IO_REQUEST { DWORD dwProtocol; @@ -551,6 +557,12 @@ typedef struct SCARDHANDLE hCardHandle; } OPENCARDNAMEW, *POPENCARDNAMEW, *LPOPENCARDNAMEW; +#if defined(__APPLE__) | defined(sun) +#pragma pack() +#else +#pragma pack(pop) +#endif + #ifdef UNICODE #define LPOCNCONNPROC LPOCNCONNPROCW #define SCARD_READERSTATE SCARD_READERSTATEW diff --git a/winpr/include/winpr/wtypes.h b/winpr/include/winpr/wtypes.h index af4f6cde7..5704a7263 100644 --- a/winpr/include/winpr/wtypes.h +++ b/winpr/include/winpr/wtypes.h @@ -64,12 +64,22 @@ typedef int BOOL; typedef BOOL *PBOOL, *LPBOOL; +#ifdef __APPLE__ +typedef int LONG; +typedef unsigned int DWORD; +typedef unsigned int ULONG; +#else +typedef long LONG; +typedef unsigned long DWORD; +typedef unsigned long ULONG; +#endif + typedef unsigned char BYTE, *PBYTE, *LPBYTE; typedef BYTE BOOLEAN, *PBOOLEAN; typedef unsigned short WCHAR, *PWCHAR; typedef WCHAR* BSTR; typedef char CHAR, *PCHAR; -typedef unsigned long DWORD, *PDWORD, *LPDWORD; +typedef DWORD *PDWORD, *LPDWORD; typedef unsigned int DWORD32; typedef unsigned __int64 DWORD64; typedef unsigned __int64 ULONGLONG; @@ -107,7 +117,7 @@ typedef signed __int64 INT64; #endif typedef const WCHAR* LMCSTR; typedef WCHAR* LMSTR; -typedef long LONG, *PLONG, *LPLONG; +typedef LONG *PLONG, *LPLONG; typedef signed __int64 LONGLONG; typedef __int3264 LONG_PTR, *PLONG_PTR; @@ -132,7 +142,7 @@ typedef unsigned char UINT8; typedef unsigned short UINT16; typedef unsigned int UINT32; typedef unsigned __int64 UINT64; -typedef unsigned long ULONG, *PULONG; +typedef ULONG *PULONG; typedef ULONG HRESULT; typedef ULONG SCODE; diff --git a/winpr/libwinpr/crt/test/CMakeLists.txt b/winpr/libwinpr/crt/test/CMakeLists.txt index 2e210439a..acb6b98d9 100644 --- a/winpr/libwinpr/crt/test/CMakeLists.txt +++ b/winpr/libwinpr/crt/test/CMakeLists.txt @@ -5,6 +5,7 @@ set(MODULE_PREFIX "TEST_CRT") set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c) set(${MODULE_PREFIX}_TESTS + TestTypes.c TestAlignment.c TestString.c TestUnicodeConversion.c) diff --git a/winpr/libwinpr/crt/test/TestTypes.c b/winpr/libwinpr/crt/test/TestTypes.c new file mode 100644 index 000000000..1261dc895 --- /dev/null +++ b/winpr/libwinpr/crt/test/TestTypes.c @@ -0,0 +1,112 @@ + +#include +#include +#include + +#define EXPECTED_SIZEOF_BYTE 1 +#define EXPECTED_SIZEOF_BOOLEAN 1 +#define EXPECTED_SIZEOF_CHAR 1 +#define EXPECTED_SIZEOF_UCHAR 1 +#define EXPECTED_SIZEOF_INT8 1 +#define EXPECTED_SIZEOF_UINT8 1 +#define EXPECTED_SIZEOF_INT16 2 +#define EXPECTED_SIZEOF_UINT16 2 +#define EXPECTED_SIZEOF_WORD 2 +#define EXPECTED_SIZEOF_WCHAR 2 +#define EXPECTED_SIZEOF_SHORT 2 +#define EXPECTED_SIZEOF_USHORT 2 +#define EXPECTED_SIZEOF_BOOL 4 +#define EXPECTED_SIZEOF_INT 4 +#define EXPECTED_SIZEOF_UINT 4 +#define EXPECTED_SIZEOF_INT32 4 +#define EXPECTED_SIZEOF_UINT32 4 +#define EXPECTED_SIZEOF_DWORD 4 +#define EXPECTED_SIZEOF_DWORD32 4 +#define EXPECTED_SIZEOF_LONG 4 +#define EXPECTED_SIZEOF_LONG32 4 +#define EXPECTED_SIZEOF_INT64 8 +#define EXPECTED_SIZEOF_UINT64 8 +#define EXPECTED_SIZEOF_DWORD64 8 +#define EXPECTED_SIZEOF_DWORDLONG 8 +#define EXPECTED_SIZEOF_LONG64 8 +#define EXPECTED_SIZEOF_ULONGLONG 8 +#define EXPECTED_SIZEOF_LUID 8 +#define EXPECTED_SIZEOF_FILETIME 8 +#define EXPECTED_SIZEOF_LARGE_INTEGER 8 +#define EXPECTED_SIZEOF_ULARGE_INTEGER 8 +#define EXPECTED_SIZEOF_GUID 16 +#define EXPECTED_SIZEOF_SYSTEMTIME 16 +#define EXPECTED_SIZEOF_SIZE_T sizeof(void*) +#define EXPECTED_SIZEOF_INT_PTR sizeof(void*) +#define EXPECTED_SIZEOF_UINT_PTR sizeof(void*) +#define EXPECTED_SIZEOF_DWORD_PTR sizeof(void*) +#define EXPECTED_SIZEOF_LONG_PTR sizeof(void*) +#define EXPECTED_SIZEOF_ULONG_PTR sizeof(void*) + +#define TEST_SIZEOF_TYPE(_name) \ + if (sizeof(_name) != EXPECTED_SIZEOF_ ##_name) { \ + fprintf(stderr, "sizeof(%s) mismatch: Actual: %d, Expected: %d\n", \ + #_name, (int) sizeof(_name), (int) EXPECTED_SIZEOF_ ##_name); \ + status = -1; \ + } + +int TestTypes(int argc, char* argv[]) +{ + int status = 0; + + TEST_SIZEOF_TYPE(INT8) + TEST_SIZEOF_TYPE(UINT8) + + TEST_SIZEOF_TYPE(BYTE) + TEST_SIZEOF_TYPE(BOOLEAN) + TEST_SIZEOF_TYPE(CHAR) + TEST_SIZEOF_TYPE(UCHAR) + + TEST_SIZEOF_TYPE(INT16) + TEST_SIZEOF_TYPE(UINT16) + + TEST_SIZEOF_TYPE(WORD) + TEST_SIZEOF_TYPE(WCHAR) + TEST_SIZEOF_TYPE(SHORT) + TEST_SIZEOF_TYPE(USHORT) + + /* fails on OS X */ + //TEST_SIZEOF_TYPE(BOOL) + + TEST_SIZEOF_TYPE(INT) + TEST_SIZEOF_TYPE(UINT) + TEST_SIZEOF_TYPE(DWORD) + TEST_SIZEOF_TYPE(DWORD32) + TEST_SIZEOF_TYPE(LONG) + TEST_SIZEOF_TYPE(LONG32) + + TEST_SIZEOF_TYPE(INT32) + TEST_SIZEOF_TYPE(UINT32) + + TEST_SIZEOF_TYPE(INT64) + TEST_SIZEOF_TYPE(UINT64) + + TEST_SIZEOF_TYPE(DWORD64) + TEST_SIZEOF_TYPE(DWORDLONG) + + TEST_SIZEOF_TYPE(LONG64) + TEST_SIZEOF_TYPE(ULONGLONG) + + TEST_SIZEOF_TYPE(LUID) + TEST_SIZEOF_TYPE(FILETIME) + TEST_SIZEOF_TYPE(LARGE_INTEGER) + TEST_SIZEOF_TYPE(ULARGE_INTEGER) + + TEST_SIZEOF_TYPE(GUID) + TEST_SIZEOF_TYPE(SYSTEMTIME) + + TEST_SIZEOF_TYPE(SIZE_T) + TEST_SIZEOF_TYPE(INT_PTR) + TEST_SIZEOF_TYPE(UINT_PTR) + TEST_SIZEOF_TYPE(DWORD_PTR) + TEST_SIZEOF_TYPE(LONG_PTR) + TEST_SIZEOF_TYPE(ULONG_PTR) + + return status; +} + diff --git a/winpr/libwinpr/smartcard/smartcard.h b/winpr/libwinpr/smartcard/smartcard.h index 04e795c1e..2db6367c2 100644 --- a/winpr/libwinpr/smartcard/smartcard.h +++ b/winpr/libwinpr/smartcard/smartcard.h @@ -45,7 +45,10 @@ void InitializeSCardApiStubs(void); +#ifndef _WIN32 #include "smartcard_pcsc.h" +#else #include "smartcard_winscard.h" +#endif #endif /* WINPR_SMARTCARD_PRIVATE_H */ diff --git a/winpr/libwinpr/smartcard/smartcard_link.c b/winpr/libwinpr/smartcard/smartcard_link.c index eb2fb76d1..55e39d7d3 100644 --- a/winpr/libwinpr/smartcard/smartcard_link.c +++ b/winpr/libwinpr/smartcard/smartcard_link.c @@ -21,6 +21,8 @@ #include "config.h" #endif +#ifndef _WIN32 + #include #include #include @@ -162,3 +164,5 @@ int PCSC_InitializeSCardApi_Link(void) return status; } + +#endif diff --git a/winpr/libwinpr/smartcard/smartcard_pcsc.c b/winpr/libwinpr/smartcard/smartcard_pcsc.c index eac1676cb..79ff6a50d 100644 --- a/winpr/libwinpr/smartcard/smartcard_pcsc.c +++ b/winpr/libwinpr/smartcard/smartcard_pcsc.c @@ -21,11 +21,14 @@ #include "config.h" #endif +#ifndef _WIN32 + #include #include #include #include +#include #include #include #include @@ -161,6 +164,11 @@ DWORD PCSC_ConvertProtocolsFromWinSCard(DWORD dwProtocols) dwProtocols &= ~SCARD_PROTOCOL_DEFAULT; } + if (dwProtocols == SCARD_PROTOCOL_UNDEFINED) + { + dwProtocols = SCARD_PROTOCOL_Tx; + } + return dwProtocols; } @@ -234,7 +242,7 @@ void PCSC_ReleaseCardContext(SCARDCONTEXT hContext) ListDictionary_Remove(g_CardContexts, (void*) hContext); } -void PCSC_LockCardContext(SCARDCONTEXT hContext) +BOOL PCSC_LockCardContext(SCARDCONTEXT hContext) { PCSC_SCARDCONTEXT* pContext; @@ -243,13 +251,15 @@ void PCSC_LockCardContext(SCARDCONTEXT hContext) if (!pContext) { fprintf(stderr, "PCSC_LockCardContext: invalid context (%p)\n", (void*) hContext); - return; + return FALSE; } EnterCriticalSection(&(pContext->lock)); + + return TRUE; } -void PCSC_UnlockCardContext(SCARDCONTEXT hContext) +BOOL PCSC_UnlockCardContext(SCARDCONTEXT hContext) { PCSC_SCARDCONTEXT* pContext; @@ -258,10 +268,12 @@ void PCSC_UnlockCardContext(SCARDCONTEXT hContext) if (!pContext) { fprintf(stderr, "PCSC_UnlockCardContext: invalid context (%p)\n", (void*) hContext); - return; + return FALSE; } LeaveCriticalSection(&(pContext->lock)); + + return TRUE; } char* PCSC_GetReaderNameFromAlias(char* nameWinSCard) @@ -311,23 +323,38 @@ BOOL PCSC_AddReaderNameAlias(char* namePCSC, char* nameWinSCard) return TRUE; } +static int PCSC_AtoiWithLength(const char* str, int length) +{ + int index; + int value = 0; + + for (index = 0; index < length; ++index) + { + if (!isdigit(str[index])) + return -1; + + value = value * 10 + (str[index] - '0'); + } + + return value; +} + char* PCSC_ConvertReaderNameToWinSCard(const char* name) { int slot; int index; int size; int length; + int ctoken; + int ntokens; + char *p, *q; + char* tokens[64][2]; char* nameWinSCard; - char *na1, *na2 = NULL; - char *if1, *if2 = NULL; - char *se1, *se2 = NULL; - char *in1, *in2 = NULL; - char *sl1, *sl2 = NULL; /** * pcsc-lite reader name format: - * * name [interface] (serial) index slot + * * Athena IDProtect Key v2 [Main Interface] 00 00 * * name: Athena IDProtect Key v2 @@ -336,6 +363,30 @@ char* PCSC_ConvertReaderNameToWinSCard(const char* name) * index: 00 * slot: 00 * + * Athena ASE IIIe 00 00 + * + * name: Athena ASE IIIe + * interface: N/A + * serial: N/A + * index: 00 + * slot: 00 + * + * Athena ASE IIIe [CCID Bulk Interface] 00 00 + * + * name: Athena ASE IIIe + * interface: CCID Bulk Interface + * serial: N/A + * index: 00 + * slot: 00 + * + * Gemalto PC Twin Reader (944B4BF1) 00 00 + * + * name: Gemalto PC Twin Reader + * interface: N/A + * serial: 944B4BF1 + * index: 00 + * slot: 00 + * * the serial component is optional * the index is a two digit zero-padded integer * the slot is a two digit zero-padded integer @@ -346,44 +397,72 @@ char* PCSC_ConvertReaderNameToWinSCard(const char* name) if (length < 10) return NULL; - na1 = (char*) name; - na2 = (char*) &name[length - 7]; + ntokens = 0; + p = q = (char*) name; - if1 = strchr(name, '['); + while (*p) + { + if (*p == ' ') + { + tokens[ntokens][0] = q; + tokens[ntokens][1] = p; + q = p + 1; + ntokens++; + } - if (if1) - if2 = strchr(if1 + 1, ']'); + p++; + } - se1 = strchr(name, '('); + tokens[ntokens][0] = q; + tokens[ntokens][1] = p; + ntokens++; - if (se1) - se2 = strchr(se1 + 1, ')'); - - in1 = (char*) &name[length - 5]; - in2 = (char*) &name[length - 4]; - - sl1 = (char*) &name[length - 2]; - sl2 = (char*) &name[length - 1]; - - if (!(if1 && if2)) + if (ntokens < 2) return NULL; - if (!(isdigit(*in1) && isdigit(*in2))) + slot = index = -1; + ctoken = ntokens - 1; + + slot = PCSC_AtoiWithLength(tokens[ctoken][0], (int) (tokens[ctoken][1] - tokens[ctoken][0])); + ctoken--; + + index = PCSC_AtoiWithLength(tokens[ctoken][0], (int) (tokens[ctoken][1] - tokens[ctoken][0])); + ctoken--; + + if (index < 0) + { + slot = -1; + index = slot; + ctoken++; + } + + if ((index < 0) || (slot < 0)) return NULL; - if (!(isdigit(*sl1) && isdigit(*sl2))) + if (*(tokens[ctoken][1] - 1) == ')') + { + while ((*(tokens[ctoken][0]) != '(') && (ctoken > 0)) + ctoken--; + ctoken--; + } + + if (ctoken < 1) return NULL; - na2 = if1 - 1; + if (*(tokens[ctoken][1] - 1) == ']') + { + while ((*(tokens[ctoken][0]) != '[') && (ctoken > 0)) + ctoken--; + ctoken--; + } - while ((*na2 == ' ') && (na2 > na1)) - na2--; - na2++; + if (ctoken < 1) + return NULL; - index = ((*in1 - 0x30) * 10) + (*in2 - 0x30); - slot = ((*sl1 - 0x30) * 10) + (*sl2 - 0x30); + p = tokens[0][0]; + q = tokens[ctoken][1]; - length = (na2 - na1); + length = (q - p); size = length + 16; nameWinSCard = (char*) malloc(size); @@ -391,43 +470,41 @@ char* PCSC_ConvertReaderNameToWinSCard(const char* name) if (!nameWinSCard) return NULL; - sprintf_s(nameWinSCard, size, "%.*s %d", length, na1, index); + /** + * pcsc-lite appears to use an index number based on all readers, + * while WinSCard uses an index number based on readers of the same name. + * Force an index number of 0 for now, fix later. + */ + + index = 0; + + sprintf_s(nameWinSCard, size, "%.*s %d", length, p, index); + + printf("Smart Card Reader Name Alias: %s -> %s\n", p, nameWinSCard); return nameWinSCard; } -char* PCSC_ConvertReaderNamesToWinSCard(const char* names) +char* PCSC_ConvertReaderNamesToWinSCard(const char* names, LPDWORD pcchReaders) { + int length; char *p, *q; - int plen, qlen; - int count = 0; - int total = 0; + DWORD cchReaders; char* nameWinSCard; char* namesWinSCard; p = (char*) names; - plen = strlen(p); + cchReaders = *pcchReaders; - while (plen > 0) - { - p += plen + 1; - total += plen + 1; - plen = strlen(p); - count++; - } - total++; - - namesWinSCard = (char*) malloc(total * 2); + namesWinSCard = (char*) malloc(cchReaders * 2); if (!namesWinSCard) return NULL; q = namesWinSCard; - p = (char*) names; - plen = strlen(p); - while (plen > 0) + while ((p - names) < cchReaders) { nameWinSCard = PCSC_ConvertReaderNameToWinSCard(p); @@ -435,113 +512,75 @@ char* PCSC_ConvertReaderNamesToWinSCard(const char* names) { PCSC_AddReaderNameAlias(p, nameWinSCard); - qlen = strlen(nameWinSCard); - CopyMemory(q, nameWinSCard, qlen); + length = strlen(nameWinSCard); + CopyMemory(q, nameWinSCard, length); free(nameWinSCard); } else { - qlen = strlen(p); - CopyMemory(q, p, qlen); + length = strlen(p); + CopyMemory(q, p, length); } - p += plen + 1; - - q += qlen; + q += length; *q = '\0'; q++; - plen = strlen(p); + p += strlen(p) + 1; } *q = '\0'; q++; + *pcchReaders = (DWORD) (q - namesWinSCard); + return namesWinSCard; } -char* PCSC_ConvertReaderNamesFromWinSCard(const char* names) +char* PCSC_ConvertReaderNamesToPCSC(const char* names, LPDWORD pcchReaders) { + int length; char *p, *q; - int plen, qlen; - int count = 0; - int total = 0; char* namePCSC; char* namesPCSC; + DWORD cchReaders; p = (char*) names; - plen = strlen(p); + cchReaders = *pcchReaders; - while (plen > 0) - { - p += plen + 1; - total += plen + 1; - plen = strlen(p); - count++; - } - total++; - - namesPCSC = (char*) malloc(total); + namesPCSC = (char*) malloc(cchReaders * 2); if (!namesPCSC) return NULL; q = namesPCSC; - p = (char*) names; - plen = strlen(p); - while (plen > 0) + while ((p - names) < cchReaders) { namePCSC = PCSC_GetReaderNameFromAlias(p); if (!namePCSC) namePCSC = p; - qlen = strlen(namePCSC); - CopyMemory(q, namePCSC, qlen); + length = strlen(namePCSC); + CopyMemory(q, namePCSC, length); - p += plen + 1; - - q += qlen; + q += length; *q = '\0'; q++; - plen = strlen(p); + p += strlen(p) + 1; } *q = '\0'; q++; + *pcchReaders = (DWORD) (q - namesPCSC); + return namesPCSC; } -size_t PCSC_MultiStringLengthA(const char* msz) -{ - char* p = (char*) msz; - - if (!p) - return 0; - - while ((p[0] != 0) && (p[1] != 0)) - p++; - - return (p - msz) + 1; -} - -size_t PCSC_MultiStringLengthW(const WCHAR* msz) -{ - WCHAR* p = (WCHAR*) msz; - - if (!p) - return 0; - - while ((p[0] != 0) && (p[1] != 0)) - p++; - - return (p - msz) + 1; -} - void PCSC_AddCardHandle(SCARDCONTEXT hContext, SCARDHANDLE hCard) { if (!g_CardHandles) @@ -609,16 +648,16 @@ WINSCARDAPI LONG WINAPI PCSC_SCardEstablishContext(DWORD dwScope, { LONG status = SCARD_S_SUCCESS; - if (g_PCSC.pfnSCardEstablishContext) - { - dwScope = SCARD_SCOPE_SYSTEM; /* this is the only scope supported by pcsc-lite */ + if (!g_PCSC.pfnSCardEstablishContext) + return SCARD_E_NO_SERVICE; - status = g_PCSC.pfnSCardEstablishContext(dwScope, pvReserved1, pvReserved2, phContext); - status = PCSC_MapErrorCodeToWinSCard(status); + dwScope = SCARD_SCOPE_SYSTEM; /* this is the only scope supported by pcsc-lite */ - if (!status) - PCSC_EstablishCardContext(*phContext); - } + status = g_PCSC.pfnSCardEstablishContext(dwScope, pvReserved1, pvReserved2, phContext); + status = PCSC_MapErrorCodeToWinSCard(status); + + if (!status) + PCSC_EstablishCardContext(*phContext); return status; } @@ -627,14 +666,14 @@ WINSCARDAPI LONG WINAPI PCSC_SCardReleaseContext(SCARDCONTEXT hContext) { LONG status = SCARD_S_SUCCESS; - if (g_PCSC.pfnSCardReleaseContext) - { - status = g_PCSC.pfnSCardReleaseContext(hContext); - status = PCSC_MapErrorCodeToWinSCard(status); + if (!g_PCSC.pfnSCardReleaseContext) + return SCARD_E_NO_SERVICE; - if (!status) - PCSC_ReleaseCardContext(hContext); - } + status = g_PCSC.pfnSCardReleaseContext(hContext); + status = PCSC_MapErrorCodeToWinSCard(status); + + if (!status) + PCSC_ReleaseCardContext(hContext); return status; } @@ -643,11 +682,11 @@ WINSCARDAPI LONG WINAPI PCSC_SCardIsValidContext(SCARDCONTEXT hContext) { LONG status = SCARD_S_SUCCESS; - if (g_PCSC.pfnSCardIsValidContext) - { - status = g_PCSC.pfnSCardIsValidContext(hContext); - status = PCSC_MapErrorCodeToWinSCard(status); - } + if (!g_PCSC.pfnSCardIsValidContext) + return SCARD_E_NO_SERVICE; + + status = g_PCSC.pfnSCardIsValidContext(hContext); + status = PCSC_MapErrorCodeToWinSCard(status); return status; } @@ -657,15 +696,17 @@ WINSCARDAPI LONG WINAPI PCSC_SCardListReaderGroupsA(SCARDCONTEXT hContext, { LONG status = SCARD_S_SUCCESS; - PCSC_LockCardContext(hContext); + if (!g_PCSC.pfnSCardListReaderGroups) + return SCARD_E_NO_SERVICE; - if (g_PCSC.pfnSCardListReaderGroups) - { - status = g_PCSC.pfnSCardListReaderGroups(hContext, mszGroups, pcchGroups); - status = PCSC_MapErrorCodeToWinSCard(status); - } + if (!PCSC_LockCardContext(hContext)) + return SCARD_E_INVALID_HANDLE; - PCSC_UnlockCardContext(hContext); + status = g_PCSC.pfnSCardListReaderGroups(hContext, mszGroups, pcchGroups); + status = PCSC_MapErrorCodeToWinSCard(status); + + if (!PCSC_UnlockCardContext(hContext)) + return SCARD_E_INVALID_HANDLE; return status; } @@ -675,20 +716,22 @@ WINSCARDAPI LONG WINAPI PCSC_SCardListReaderGroupsW(SCARDCONTEXT hContext, { LONG status = SCARD_S_SUCCESS; - PCSC_LockCardContext(hContext); + if (!g_PCSC.pfnSCardListReaderGroups) + return SCARD_E_NO_SERVICE; - if (g_PCSC.pfnSCardListReaderGroups) - { - mszGroups = NULL; - pcchGroups = 0; + if (!PCSC_LockCardContext(hContext)) + return SCARD_E_INVALID_HANDLE; - /* FIXME: unicode conversion */ + mszGroups = NULL; + pcchGroups = 0; - status = g_PCSC.pfnSCardListReaderGroups(hContext, (LPSTR) mszGroups, pcchGroups); - status = PCSC_MapErrorCodeToWinSCard(status); - } + /* FIXME: unicode conversion */ - PCSC_UnlockCardContext(hContext); + status = g_PCSC.pfnSCardListReaderGroups(hContext, (LPSTR) mszGroups, pcchGroups); + status = PCSC_MapErrorCodeToWinSCard(status); + + if (!PCSC_UnlockCardContext(hContext)) + return SCARD_E_INVALID_HANDLE; return status; } @@ -697,44 +740,57 @@ WINSCARDAPI LONG WINAPI PCSC_SCardListReaders_Internal(SCARDCONTEXT hContext, LPCSTR mszGroups, LPSTR mszReaders, LPDWORD pcchReaders) { LONG status = SCARD_S_SUCCESS; + char* mszReadersWinSCard = NULL; + BOOL pcchReadersWrapAlloc = FALSE; + LPSTR* pMszReaders = (LPSTR*) mszReaders; - if (g_PCSC.pfnSCardListReaders) + if (!g_PCSC.pfnSCardListReaders) + return SCARD_E_NO_SERVICE; + + mszGroups = NULL; /* mszGroups is not supported by pcsc-lite */ + + if ((*pcchReaders == SCARD_AUTOALLOCATE) && !g_SCardAutoAllocate) + pcchReadersWrapAlloc = TRUE; + + if (pcchReadersWrapAlloc) { - BOOL pcchReadersWrapAlloc = FALSE; - LPSTR* pMszReaders = (LPSTR*) mszReaders; + *pcchReaders = 0; - mszGroups = NULL; /* mszGroups is not supported by pcsc-lite */ + status = g_PCSC.pfnSCardListReaders(hContext, mszGroups, NULL, pcchReaders); - if ((*pcchReaders == SCARD_AUTOALLOCATE) && !g_SCardAutoAllocate) - pcchReadersWrapAlloc = TRUE; - - if (pcchReadersWrapAlloc) + if (status == SCARD_S_SUCCESS) { - *pcchReaders = 0; + *pMszReaders = calloc(1, *pcchReaders); - status = g_PCSC.pfnSCardListReaders(hContext, mszGroups, NULL, pcchReaders); + if (!*pMszReaders) + return SCARD_E_NO_MEMORY; - if (!status) - { - *pMszReaders = calloc(1, *pcchReaders); + status = g_PCSC.pfnSCardListReaders(hContext, mszGroups, *pMszReaders, pcchReaders); - if (!*pMszReaders) - return SCARD_E_NO_MEMORY; - - status = g_PCSC.pfnSCardListReaders(hContext, mszGroups, *pMszReaders, pcchReaders); - - if (status) - free(*pMszReaders); - else - PCSC_AddMemoryBlock(hContext, *pMszReaders); - } + if (status != SCARD_S_SUCCESS) + free(*pMszReaders); + else + PCSC_AddMemoryBlock(hContext, *pMszReaders); } - else + } + else + { + status = g_PCSC.pfnSCardListReaders(hContext, mszGroups, mszReaders, pcchReaders); + } + + status = PCSC_MapErrorCodeToWinSCard(status); + + if (status == SCARD_S_SUCCESS) + { + mszReadersWinSCard = PCSC_ConvertReaderNamesToWinSCard(*pMszReaders, pcchReaders); + + if (mszReadersWinSCard) { - status = g_PCSC.pfnSCardListReaders(hContext, mszGroups, mszReaders, pcchReaders); - } + PCSC_SCardFreeMemory_Internal(hContext, *pMszReaders); - status = PCSC_MapErrorCodeToWinSCard(status); + *pMszReaders = mszReadersWinSCard; + PCSC_AddMemoryBlock(hContext, *pMszReaders); + } } return status; @@ -745,33 +801,16 @@ WINSCARDAPI LONG WINAPI PCSC_SCardListReadersA(SCARDCONTEXT hContext, { LONG status = SCARD_S_SUCCESS; - PCSC_LockCardContext(hContext); + if (!PCSC_LockCardContext(hContext)) + return SCARD_E_INVALID_HANDLE; if (g_PCSC.pfnSCardListReaders) { - char* mszReadersWinSCard = NULL; - LPSTR* pMszReaders = (LPSTR*) mszReaders; - status = PCSC_SCardListReaders_Internal(hContext, mszGroups, mszReaders, pcchReaders); - - if (!status) - { - mszReadersWinSCard = PCSC_ConvertReaderNamesToWinSCard(*pMszReaders); - - if (mszReadersWinSCard) - { - PCSC_SCardFreeMemory_Internal(hContext, *pMszReaders); - - *pMszReaders = mszReadersWinSCard; - *pcchReaders = PCSC_MultiStringLengthA(*pMszReaders) + 2; - PCSC_AddMemoryBlock(hContext, *pMszReaders); - } - } - - status = PCSC_MapErrorCodeToWinSCard(status); } - PCSC_UnlockCardContext(hContext); + if (!PCSC_UnlockCardContext(hContext)) + return SCARD_E_INVALID_HANDLE; return status; } @@ -781,13 +820,13 @@ WINSCARDAPI LONG WINAPI PCSC_SCardListReadersW(SCARDCONTEXT hContext, { LONG status = SCARD_S_SUCCESS; - PCSC_LockCardContext(hContext); + if (!PCSC_LockCardContext(hContext)) + return SCARD_E_INVALID_HANDLE; if (g_PCSC.pfnSCardListReaders) { LPSTR mszGroupsA = NULL; LPSTR mszReadersA = NULL; - char* mszReadersWinSCard = NULL; LPSTR* pMszReadersA = &mszReadersA; mszGroups = NULL; /* mszGroups is not supported by pcsc-lite */ @@ -797,31 +836,19 @@ WINSCARDAPI LONG WINAPI PCSC_SCardListReadersW(SCARDCONTEXT hContext, status = PCSC_SCardListReaders_Internal(hContext, mszGroupsA, (LPTSTR) &mszReadersA, pcchReaders); - if (!status) + if (status == SCARD_S_SUCCESS) { - mszReadersWinSCard = PCSC_ConvertReaderNamesToWinSCard(mszReadersA); - - if (mszReadersWinSCard) - { - PCSC_SCardFreeMemory_Internal(hContext, *pMszReadersA); - - *pMszReadersA = mszReadersWinSCard; - *pcchReaders = PCSC_MultiStringLengthA(*pMszReadersA) + 2; - PCSC_AddMemoryBlock(hContext, *pMszReadersA); - } - *pcchReaders = ConvertToUnicode(CP_UTF8, 0, *pMszReadersA, *pcchReaders, (WCHAR**) mszReaders, 0); PCSC_AddMemoryBlock(hContext, mszReaders); PCSC_SCardFreeMemory_Internal(hContext, *pMszReadersA); } - status = PCSC_MapErrorCodeToWinSCard(status); - free(mszGroupsA); } - PCSC_UnlockCardContext(hContext); + if (!PCSC_UnlockCardContext(hContext)) + return SCARD_E_INVALID_HANDLE; return status; } @@ -1001,11 +1028,13 @@ WINSCARDAPI LONG WINAPI PCSC_SCardFreeMemory(SCARDCONTEXT hContext, LPCVOID pvMe { LONG status = SCARD_S_SUCCESS; - PCSC_LockCardContext(hContext); + if (!PCSC_LockCardContext(hContext)) + return SCARD_E_INVALID_HANDLE; status = PCSC_SCardFreeMemory_Internal(hContext, pvMem); - PCSC_UnlockCardContext(hContext); + if (!PCSC_UnlockCardContext(hContext)) + return SCARD_E_INVALID_HANDLE; return status; } @@ -1047,81 +1076,121 @@ WINSCARDAPI LONG WINAPI PCSC_SCardLocateCardsByATRW(SCARDCONTEXT hContext, WINSCARDAPI LONG WINAPI PCSC_SCardGetStatusChange_Internal(SCARDCONTEXT hContext, DWORD dwTimeout, LPSCARD_READERSTATEA rgReaderStates, DWORD cReaders) { + DWORD i, j; + DWORD dwEventState; + BOOL stateChanged = FALSE; + PCSC_SCARD_READERSTATE* states; LONG status = SCARD_S_SUCCESS; - if (g_PCSC.pfnSCardGetStatusChange) + if (!g_PCSC.pfnSCardGetStatusChange) + return SCARD_E_NO_SERVICE; + + /** + * FIXME: proper pcsc-lite support for "\\\\?PnP?\\Notification" + * + * Apple's SmartCard Services (not vanilla pcsc-lite) appears to have trouble with the + * "\\\\?PnP?\\Notification" reader name. I am always getting EXC_BAD_ACCESS with it. + * + * The SmartCard Services tarballs can be found here: + * http://opensource.apple.com/tarballs/SmartCardServices/ + * + * The "\\\\?PnP?\\Notification" string cannot be found anywhere in the sources, + * while this string is present in the vanilla pcsc-lite sources. + * + * For now, the current smartcard code sets dwCurrentState to SCARD_STATE_IGNORE + * when the reader name is "\\\\?PnP?\\Notification". We check for this flag and + * and ignore the reader completely when present. + */ + + states = (PCSC_SCARD_READERSTATE*) calloc(cReaders, sizeof(PCSC_SCARD_READERSTATE)); + + if (!states) + return SCARD_E_NO_MEMORY; + + for (i = j = 0; i < cReaders; i++) { - DWORD index; - DWORD dwEventState; - BOOL stateChanged = FALSE; - LPSCARD_READERSTATEA states; +#ifdef __APPLE__ + if (rgReaderStates[i].dwCurrentState == SCARD_STATE_IGNORE) + continue; +#endif + + states[j].szReader = PCSC_GetReaderNameFromAlias((char*) rgReaderStates[i].szReader); - states = (LPSCARD_READERSTATEA) calloc(cReaders, sizeof(SCARD_READERSTATEA)); + if (!states[j].szReader) + states[j].szReader = rgReaderStates[i].szReader; - if (!states) - return SCARD_E_NO_MEMORY; - - for (index = 0; index < cReaders; index++) - { - states[index].szReader = PCSC_GetReaderNameFromAlias((char*) rgReaderStates[index].szReader); - - if (!states[index].szReader) - states[index].szReader = rgReaderStates[index].szReader; - - states[index].pvUserData = rgReaderStates[index].pvUserData; - states[index].dwCurrentState = rgReaderStates[index].dwCurrentState; - states[index].dwEventState = rgReaderStates[index].dwEventState; - states[index].cbAtr = rgReaderStates[index].cbAtr; - CopyMemory(&(states[index].rgbAtr), &(rgReaderStates[index].rgbAtr), 36); - } - - /** - * pcsc-lite interprets dwTimeout value 0 as INFINITE, use value 1 as a workaround - */ - - status = g_PCSC.pfnSCardGetStatusChange(hContext, dwTimeout ? dwTimeout : 1, states, cReaders); - status = PCSC_MapErrorCodeToWinSCard(status); - - for (index = 0; index < cReaders; index++) - { - rgReaderStates[index].pvUserData = states[index].pvUserData; - rgReaderStates[index].dwCurrentState = states[index].dwCurrentState; - rgReaderStates[index].cbAtr = states[index].cbAtr; - CopyMemory(&(rgReaderStates[index].rgbAtr), &(states[index].rgbAtr), 36); - - /* pcsc-lite puts an event count in the higher bits of dwEventState */ - states[index].dwEventState &= 0xFFFF; - - dwEventState = states[index].dwEventState & ~SCARD_STATE_CHANGED; - - if (dwEventState != rgReaderStates[index].dwCurrentState) - { - rgReaderStates[index].dwEventState = states[index].dwEventState; - - if (dwEventState & SCARD_STATE_PRESENT) - { - if (!(dwEventState & SCARD_STATE_EXCLUSIVE)) - rgReaderStates[index].dwEventState |= SCARD_STATE_INUSE; - } - - stateChanged = TRUE; - } - else - { - rgReaderStates[index].dwEventState = dwEventState; - } - - if (rgReaderStates[index].dwCurrentState & SCARD_STATE_IGNORE) - rgReaderStates[index].dwEventState = SCARD_STATE_IGNORE; - } - - if ((status == SCARD_S_SUCCESS) && !stateChanged) - status = SCARD_E_TIMEOUT; - else if ((status == SCARD_E_TIMEOUT) && stateChanged) - return SCARD_S_SUCCESS; - - free(states); + states[j].dwCurrentState = rgReaderStates[i].dwCurrentState; + states[j].dwEventState = rgReaderStates[i].dwEventState; + states[j].cbAtr = rgReaderStates[i].cbAtr; + CopyMemory(&(states[j].rgbAtr), &(rgReaderStates[i].rgbAtr), PCSC_MAX_ATR_SIZE); + + j++; } + + cReaders = j; + + /** + * pcsc-lite interprets dwTimeout value 0 as INFINITE, use value 1 as a workaround + */ + + if (cReaders > 0) + { + status = g_PCSC.pfnSCardGetStatusChange(hContext, dwTimeout ? dwTimeout : 10, states, cReaders); + status = PCSC_MapErrorCodeToWinSCard(status); + } + else + { + status = SCARD_E_TIMEOUT; + } + + for (i = j = 0; i < cReaders; i++) + { +#ifdef __APPLE__ + if (rgReaderStates[i].dwCurrentState == SCARD_STATE_IGNORE) + { + rgReaderStates[i].dwEventState = SCARD_STATE_IGNORE; + continue; + } +#endif + + rgReaderStates[i].dwCurrentState = states[j].dwCurrentState; + rgReaderStates[i].cbAtr = states[j].cbAtr; + CopyMemory(&(rgReaderStates[i].rgbAtr), &(states[j].rgbAtr), PCSC_MAX_ATR_SIZE); + + /* pcsc-lite puts an event count in the higher bits of dwEventState */ + states[j].dwEventState &= 0xFFFF; + + dwEventState = states[j].dwEventState & ~SCARD_STATE_CHANGED; + + if (dwEventState != rgReaderStates[i].dwCurrentState) + { + rgReaderStates[i].dwEventState = states[j].dwEventState; + + if (dwEventState & SCARD_STATE_PRESENT) + { + if (!(dwEventState & SCARD_STATE_EXCLUSIVE)) + rgReaderStates[i].dwEventState |= SCARD_STATE_INUSE; + } + + stateChanged = TRUE; + } + else + { + rgReaderStates[i].dwEventState = dwEventState; + } + + if (rgReaderStates[i].dwCurrentState & SCARD_STATE_IGNORE) + rgReaderStates[i].dwEventState = SCARD_STATE_IGNORE; + + j++; + } + + if ((status == SCARD_S_SUCCESS) && !stateChanged) + status = SCARD_E_TIMEOUT; + else if ((status == SCARD_E_TIMEOUT) && stateChanged) + return SCARD_S_SUCCESS; + + free(states); return status; } @@ -1131,15 +1200,13 @@ WINSCARDAPI LONG WINAPI PCSC_SCardGetStatusChangeA(SCARDCONTEXT hContext, { LONG status = SCARD_S_SUCCESS; - PCSC_LockCardContext(hContext); + if (!PCSC_LockCardContext(hContext)) + return SCARD_E_INVALID_HANDLE; - if (g_PCSC.pfnSCardGetStatusChange) - { - status = PCSC_SCardGetStatusChange_Internal(hContext, dwTimeout, rgReaderStates, cReaders); - status = PCSC_MapErrorCodeToWinSCard(status); - } + status = PCSC_SCardGetStatusChange_Internal(hContext, dwTimeout, rgReaderStates, cReaders); - PCSC_UnlockCardContext(hContext); + if (!PCSC_UnlockCardContext(hContext)) + return SCARD_E_INVALID_HANDLE; return status; } @@ -1147,54 +1214,53 @@ WINSCARDAPI LONG WINAPI PCSC_SCardGetStatusChangeA(SCARDCONTEXT hContext, WINSCARDAPI LONG WINAPI PCSC_SCardGetStatusChangeW(SCARDCONTEXT hContext, DWORD dwTimeout, LPSCARD_READERSTATEW rgReaderStates, DWORD cReaders) { + DWORD index; + LPSCARD_READERSTATEA states; LONG status = SCARD_S_SUCCESS; - PCSC_LockCardContext(hContext); + if (!PCSC_LockCardContext(hContext)) + return SCARD_E_INVALID_HANDLE; - if (g_PCSC.pfnSCardGetStatusChange) + if (!g_PCSC.pfnSCardGetStatusChange) + return SCARD_E_NO_SERVICE; + + states = (LPSCARD_READERSTATEA) calloc(cReaders, sizeof(SCARD_READERSTATEA)); + + if (!states) { - DWORD index; - LPSCARD_READERSTATEA states; - - states = (LPSCARD_READERSTATEA) calloc(cReaders, sizeof(SCARD_READERSTATEA)); - - if (!states) - { - PCSC_UnlockCardContext(hContext); - return SCARD_E_NO_MEMORY; - } - - for (index = 0; index < cReaders; index++) - { - states[index].szReader = NULL; - - ConvertFromUnicode(CP_UTF8, 0, rgReaderStates[index].szReader, -1, - (char**) &states[index].szReader, 0, NULL, NULL); - - states[index].pvUserData = rgReaderStates[index].pvUserData; - states[index].dwCurrentState = rgReaderStates[index].dwCurrentState; - states[index].dwEventState = rgReaderStates[index].dwEventState; - states[index].cbAtr = rgReaderStates[index].cbAtr; - CopyMemory(&(states[index].rgbAtr), &(rgReaderStates[index].rgbAtr), 36); - } - - status = PCSC_SCardGetStatusChange_Internal(hContext, dwTimeout, states, cReaders); - status = PCSC_MapErrorCodeToWinSCard(status); - - for (index = 0; index < cReaders; index++) - { - free((void*) states[index].szReader); - rgReaderStates[index].pvUserData = states[index].pvUserData; - rgReaderStates[index].dwCurrentState = states[index].dwCurrentState; - rgReaderStates[index].dwEventState = states[index].dwEventState; - rgReaderStates[index].cbAtr = states[index].cbAtr; - CopyMemory(&(rgReaderStates[index].rgbAtr), &(states[index].rgbAtr), 36); - } - - free(states); + PCSC_UnlockCardContext(hContext); + return SCARD_E_NO_MEMORY; } - PCSC_UnlockCardContext(hContext); + for (index = 0; index < cReaders; index++) + { + states[index].szReader = NULL; + ConvertFromUnicode(CP_UTF8, 0, rgReaderStates[index].szReader, -1, + (char**) &(states[index].szReader), 0, NULL, NULL); + + states[index].pvUserData = rgReaderStates[index].pvUserData; + states[index].dwCurrentState = rgReaderStates[index].dwCurrentState; + states[index].dwEventState = rgReaderStates[index].dwEventState; + states[index].cbAtr = rgReaderStates[index].cbAtr; + CopyMemory(&(states[index].rgbAtr), &(rgReaderStates[index].rgbAtr), 36); + } + + status = PCSC_SCardGetStatusChange_Internal(hContext, dwTimeout, states, cReaders); + + for (index = 0; index < cReaders; index++) + { + free((void*) states[index].szReader); + rgReaderStates[index].pvUserData = states[index].pvUserData; + rgReaderStates[index].dwCurrentState = states[index].dwCurrentState; + rgReaderStates[index].dwEventState = states[index].dwEventState; + rgReaderStates[index].cbAtr = states[index].cbAtr; + CopyMemory(&(rgReaderStates[index].rgbAtr), &(states[index].rgbAtr), 36); + } + + free(states); + + if (!PCSC_UnlockCardContext(hContext)) + return SCARD_E_INVALID_HANDLE; return status; } @@ -1203,11 +1269,11 @@ WINSCARDAPI LONG WINAPI PCSC_SCardCancel(SCARDCONTEXT hContext) { LONG status = SCARD_S_SUCCESS; - if (g_PCSC.pfnSCardCancel) - { - status = g_PCSC.pfnSCardCancel(hContext); - status = PCSC_MapErrorCodeToWinSCard(status); - } + if (!g_PCSC.pfnSCardCancel) + return SCARD_E_NO_SERVICE; + + status = g_PCSC.pfnSCardCancel(hContext); + status = PCSC_MapErrorCodeToWinSCard(status); return status; } @@ -1216,28 +1282,27 @@ WINSCARDAPI LONG WINAPI PCSC_SCardConnect_Internal(SCARDCONTEXT hContext, LPCSTR szReader, DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol) { + char* szReaderPCSC; LONG status = SCARD_S_SUCCESS; - if (g_PCSC.pfnSCardConnect) + if (!g_PCSC.pfnSCardConnect) + return SCARD_E_NO_SERVICE; + + szReaderPCSC = PCSC_GetReaderNameFromAlias((char*) szReader); + + if (!szReaderPCSC) + szReaderPCSC = (char*) szReader; + + dwPreferredProtocols = PCSC_ConvertProtocolsFromWinSCard(dwPreferredProtocols); + + status = g_PCSC.pfnSCardConnect(hContext, szReaderPCSC, + dwShareMode, dwPreferredProtocols, phCard, pdwActiveProtocol); + status = PCSC_MapErrorCodeToWinSCard(status); + + if (status == SCARD_S_SUCCESS) { - char* szReaderPCSC; - - szReaderPCSC = PCSC_GetReaderNameFromAlias((char*) szReader); - - if (!szReaderPCSC) - szReaderPCSC = (char*) szReader; - - dwPreferredProtocols = PCSC_ConvertProtocolsFromWinSCard(dwPreferredProtocols); - - status = g_PCSC.pfnSCardConnect(hContext, szReaderPCSC, - dwShareMode, dwPreferredProtocols, phCard, pdwActiveProtocol); - status = PCSC_MapErrorCodeToWinSCard(status); - - if (status == SCARD_S_SUCCESS) - { - PCSC_AddCardHandle(hContext, *phCard); - *pdwActiveProtocol = PCSC_ConvertProtocolsToWinSCard(*pdwActiveProtocol); - } + PCSC_AddCardHandle(hContext, *phCard); + *pdwActiveProtocol = PCSC_ConvertProtocolsToWinSCard(*pdwActiveProtocol); } return status; @@ -1249,16 +1314,14 @@ WINSCARDAPI LONG WINAPI PCSC_SCardConnectA(SCARDCONTEXT hContext, { LONG status = SCARD_S_SUCCESS; - PCSC_LockCardContext(hContext); + if (!PCSC_LockCardContext(hContext)) + return SCARD_E_INVALID_HANDLE; - if (g_PCSC.pfnSCardConnect) - { - status = PCSC_SCardConnect_Internal(hContext, szReader, dwShareMode, - dwPreferredProtocols, phCard, pdwActiveProtocol); - status = PCSC_MapErrorCodeToWinSCard(status); - } + status = PCSC_SCardConnect_Internal(hContext, szReader, dwShareMode, + dwPreferredProtocols, phCard, pdwActiveProtocol); - PCSC_UnlockCardContext(hContext); + if (!PCSC_UnlockCardContext(hContext)) + return SCARD_E_INVALID_HANDLE; return status; } @@ -1267,26 +1330,22 @@ WINSCARDAPI LONG WINAPI PCSC_SCardConnectW(SCARDCONTEXT hContext, LPCWSTR szReader, DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol) { + LPSTR szReaderA = NULL; LONG status = SCARD_S_SUCCESS; - PCSC_LockCardContext(hContext); + if (!PCSC_LockCardContext(hContext)) + return SCARD_E_INVALID_HANDLE; - if (g_PCSC.pfnSCardConnect) - { - LONG status; - LPSTR szReaderA = NULL; + if (szReader) + ConvertFromUnicode(CP_UTF8, 0, szReader, -1, &szReaderA, 0, NULL, NULL); - if (szReader) - ConvertFromUnicode(CP_UTF8, 0, szReader, -1, &szReaderA, 0, NULL, NULL); + status = PCSC_SCardConnect_Internal(hContext, szReaderA, dwShareMode, + dwPreferredProtocols, phCard, pdwActiveProtocol); - status = PCSC_SCardConnect_Internal(hContext, szReaderA, dwShareMode, - dwPreferredProtocols, phCard, pdwActiveProtocol); - status = PCSC_MapErrorCodeToWinSCard(status); + free(szReaderA); - free(szReaderA); - } - - PCSC_UnlockCardContext(hContext); + if (!PCSC_UnlockCardContext(hContext)) + return SCARD_E_INVALID_HANDLE; return status; } @@ -1296,16 +1355,16 @@ WINSCARDAPI LONG WINAPI PCSC_SCardReconnect(SCARDHANDLE hCard, { LONG status = SCARD_S_SUCCESS; - if (g_PCSC.pfnSCardReconnect) - { - dwPreferredProtocols = PCSC_ConvertProtocolsFromWinSCard(dwPreferredProtocols); + if (!g_PCSC.pfnSCardReconnect) + return SCARD_E_NO_SERVICE; - status = g_PCSC.pfnSCardReconnect(hCard, dwShareMode, - dwPreferredProtocols, dwInitialization, pdwActiveProtocol); - status = PCSC_MapErrorCodeToWinSCard(status); + dwPreferredProtocols = PCSC_ConvertProtocolsFromWinSCard(dwPreferredProtocols); - *pdwActiveProtocol = PCSC_ConvertProtocolsToWinSCard(*pdwActiveProtocol); - } + status = g_PCSC.pfnSCardReconnect(hCard, dwShareMode, + dwPreferredProtocols, dwInitialization, pdwActiveProtocol); + status = PCSC_MapErrorCodeToWinSCard(status); + + *pdwActiveProtocol = PCSC_ConvertProtocolsToWinSCard(*pdwActiveProtocol); return status; } @@ -1314,14 +1373,14 @@ WINSCARDAPI LONG WINAPI PCSC_SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposit { LONG status = SCARD_S_SUCCESS; - if (g_PCSC.pfnSCardDisconnect) - { - status = g_PCSC.pfnSCardDisconnect(hCard, dwDisposition); - status = PCSC_MapErrorCodeToWinSCard(status); + if (!g_PCSC.pfnSCardDisconnect) + return SCARD_E_NO_SERVICE; - if (status == SCARD_S_SUCCESS) - PCSC_RemoveCardHandle(hCard); - } + status = g_PCSC.pfnSCardDisconnect(hCard, dwDisposition); + status = PCSC_MapErrorCodeToWinSCard(status); + + if (status == SCARD_S_SUCCESS) + PCSC_RemoveCardHandle(hCard); return status; } @@ -1330,11 +1389,11 @@ WINSCARDAPI LONG WINAPI PCSC_SCardBeginTransaction(SCARDHANDLE hCard) { LONG status = SCARD_S_SUCCESS; - if (g_PCSC.pfnSCardBeginTransaction) - { - status = g_PCSC.pfnSCardBeginTransaction(hCard); - status = PCSC_MapErrorCodeToWinSCard(status); - } + if (!g_PCSC.pfnSCardBeginTransaction) + return SCARD_E_NO_SERVICE; + + status = g_PCSC.pfnSCardBeginTransaction(hCard); + status = PCSC_MapErrorCodeToWinSCard(status); return status; } @@ -1343,11 +1402,11 @@ WINSCARDAPI LONG WINAPI PCSC_SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisp { LONG status = SCARD_S_SUCCESS; - if (g_PCSC.pfnSCardEndTransaction) - { - status = g_PCSC.pfnSCardEndTransaction(hCard, dwDisposition); - status = PCSC_MapErrorCodeToWinSCard(status); - } + if (!g_PCSC.pfnSCardEndTransaction) + return SCARD_E_NO_SERVICE; + + status = g_PCSC.pfnSCardEndTransaction(hCard, dwDisposition); + status = PCSC_MapErrorCodeToWinSCard(status); return status; } @@ -1360,26 +1419,29 @@ WINSCARDAPI LONG WINAPI PCSC_SCardCancelTransaction(SCARDHANDLE hCard) WINSCARDAPI LONG WINAPI PCSC_SCardState(SCARDHANDLE hCard, LPDWORD pdwState, LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen) { + DWORD cchReaderLen; + SCARDCONTEXT hContext = 0; + LPSTR mszReaderNames = NULL; LONG status = SCARD_S_SUCCESS; - if (g_PCSC.pfnSCardStatus) - { - SCARDCONTEXT hContext = 0; - LPSTR mszReaderNames = NULL; - DWORD cchReaderLen = SCARD_AUTOALLOCATE; + if (!g_PCSC.pfnSCardStatus) + return SCARD_E_NO_SERVICE; - status = g_PCSC.pfnSCardStatus(hCard, (LPSTR) &mszReaderNames, &cchReaderLen, - pdwState, pdwProtocol, pbAtr, pcbAtrLen); - status = PCSC_MapErrorCodeToWinSCard(status); + hContext = PCSC_GetCardContextFromHandle(hCard); - if (mszReaderNames) - { - hContext = PCSC_GetCardContextFromHandle(hCard); - PCSC_SCardFreeMemory_Internal(hContext, mszReaderNames); - } + if (!hContext) + return SCARD_E_INVALID_VALUE; - *pdwProtocol = PCSC_ConvertProtocolsToWinSCard(*pdwProtocol); - } + cchReaderLen = SCARD_AUTOALLOCATE; + + status = g_PCSC.pfnSCardStatus(hCard, (LPSTR) &mszReaderNames, &cchReaderLen, + pdwState, pdwProtocol, pbAtr, pcbAtrLen); + status = PCSC_MapErrorCodeToWinSCard(status); + + if (mszReaderNames) + PCSC_SCardFreeMemory_Internal(hContext, mszReaderNames); + + *pdwProtocol = PCSC_ConvertProtocolsToWinSCard(*pdwProtocol); return status; } @@ -1388,101 +1450,110 @@ WINSCARDAPI LONG WINAPI PCSC_SCardStatus_Internal(SCARDHANDLE hCard, LPSTR mszReaderNames, LPDWORD pcchReaderLen, LPDWORD pdwState, LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen) { + SCARDCONTEXT hContext; + char* mszReaderNamesWinSCard = NULL; + BOOL pcbAtrLenWrapAlloc = FALSE; + BOOL pcchReaderLenWrapAlloc = FALSE; + LPBYTE* pPbAtr = (LPBYTE*) pbAtr; + LPSTR* pMszReaderNames = (LPSTR*) mszReaderNames; LONG status = SCARD_S_SUCCESS; - if (g_PCSC.pfnSCardStatus) + if (!g_PCSC.pfnSCardStatus) + return SCARD_E_NO_SERVICE; + + hContext = PCSC_GetCardContextFromHandle(hCard); + + if (!hContext) + return SCARD_E_INVALID_VALUE; + + if ((*pcchReaderLen == SCARD_AUTOALLOCATE) && !g_SCardAutoAllocate) + pcchReaderLenWrapAlloc = TRUE; + + if ((*pcbAtrLen == SCARD_AUTOALLOCATE) && !g_SCardAutoAllocate) + pcbAtrLenWrapAlloc = TRUE; + + if (pcchReaderLenWrapAlloc || pcbAtrLenWrapAlloc) { - SCARDCONTEXT hContext; - char* mszReaderNamesPCSC = NULL; - BOOL pcbAtrLenWrapAlloc = FALSE; - BOOL pcchReaderLenWrapAlloc = FALSE; - LPBYTE* pPbAtr = (LPBYTE*) pbAtr; - LPSTR* pMszReaderNames = (LPSTR*) mszReaderNames; + if (pcchReaderLenWrapAlloc) + *pcchReaderLen = 0; - hContext = PCSC_GetCardContextFromHandle(hCard); + if (pcbAtrLenWrapAlloc) + *pcbAtrLen = 0; - if ((*pcbAtrLen == SCARD_AUTOALLOCATE) && !g_SCardAutoAllocate) - pcbAtrLenWrapAlloc = TRUE; + status = g_PCSC.pfnSCardStatus(hCard, + (pcchReaderLenWrapAlloc) ? NULL : mszReaderNames, pcchReaderLen, + pdwState, pdwProtocol, + (pcbAtrLenWrapAlloc) ? NULL : pbAtr, pcbAtrLen); - if ((*pcchReaderLen == SCARD_AUTOALLOCATE) && !g_SCardAutoAllocate) - pcchReaderLenWrapAlloc = TRUE; - - if (pcbAtrLenWrapAlloc || pcchReaderLenWrapAlloc) + if (status == SCARD_S_SUCCESS) { - if (pcbAtrLenWrapAlloc) - *pcbAtrLen = 0; - if (pcchReaderLenWrapAlloc) - *pcchReaderLen = 0; + { + *pMszReaderNames = (LPSTR) calloc(1, *pcchReaderLen); + + if (!*pMszReaderNames) + return SCARD_E_NO_MEMORY; + } + + if (pcbAtrLenWrapAlloc) + { + *pPbAtr = (BYTE*) calloc(1, *pcbAtrLen); + + if (!*pPbAtr) + return SCARD_E_NO_MEMORY; + } status = g_PCSC.pfnSCardStatus(hCard, - mszReaderNames, pcchReaderLen, - pdwState, pdwProtocol, (pcchReaderLenWrapAlloc) ? NULL : pbAtr, pcbAtrLen); + *pMszReaderNames, pcchReaderLen, + pdwState, pdwProtocol, + pbAtr, pcbAtrLen); - if (!status) + if (status != SCARD_S_SUCCESS) { - if (pcbAtrLenWrapAlloc) - { - *pPbAtr = (BYTE*) calloc(1, *pcbAtrLen); - - if (!*pPbAtr) - return SCARD_E_NO_MEMORY; - } - if (pcchReaderLenWrapAlloc) { - *pMszReaderNames = (LPSTR) calloc(1, *pcchReaderLen); - - if (!*pMszReaderNames) - return SCARD_E_NO_MEMORY; + free(*pMszReaderNames); + *pMszReaderNames = NULL; } - status = g_PCSC.pfnSCardStatus(hCard, - (pcchReaderLenWrapAlloc) ? *pMszReaderNames : mszReaderNames, pcchReaderLen, - pdwState, pdwProtocol, (pcbAtrLenWrapAlloc) ? *pPbAtr : pbAtr, pcbAtrLen); - - if (status) + if (pcbAtrLenWrapAlloc) { - if (pcbAtrLenWrapAlloc) - free(*pPbAtr); - - if (pcchReaderLenWrapAlloc) - free(*pMszReaderNames); - } - else - { - if (pcbAtrLenWrapAlloc) - PCSC_AddMemoryBlock(hContext, *pPbAtr); - - if (pcchReaderLenWrapAlloc) - PCSC_AddMemoryBlock(hContext, *pMszReaderNames); + free(*pPbAtr); + *pPbAtr = NULL; } } + else + { + if (pcchReaderLenWrapAlloc) + PCSC_AddMemoryBlock(hContext, *pMszReaderNames); + + if (pcbAtrLenWrapAlloc) + PCSC_AddMemoryBlock(hContext, *pPbAtr); + } } - else - { - status = g_PCSC.pfnSCardStatus(hCard, mszReaderNames, pcchReaderLen, - pdwState, pdwProtocol, pbAtr, pcbAtrLen); - } - - status = PCSC_MapErrorCodeToWinSCard(status); - - mszReaderNamesPCSC = PCSC_ConvertReaderNamesToWinSCard(*pMszReaderNames); - - if (mszReaderNamesPCSC) - { - PCSC_SCardFreeMemory_Internal(hContext, *pMszReaderNames); - - *pMszReaderNames = mszReaderNamesPCSC; - *pcchReaderLen = PCSC_MultiStringLengthA(*pMszReaderNames) + 2; - PCSC_AddMemoryBlock(hContext, *pMszReaderNames); - } - - *pdwState &= 0xFFFF; - *pdwState = PCSC_ConvertCardStateToWinSCard(*pdwState, status); - - *pdwProtocol = PCSC_ConvertProtocolsToWinSCard(*pdwProtocol); } + else + { + status = g_PCSC.pfnSCardStatus(hCard, mszReaderNames, pcchReaderLen, + pdwState, pdwProtocol, pbAtr, pcbAtrLen); + } + + status = PCSC_MapErrorCodeToWinSCard(status); + + mszReaderNamesWinSCard = PCSC_ConvertReaderNamesToWinSCard(*pMszReaderNames, pcchReaderLen); + + if (mszReaderNamesWinSCard) + { + PCSC_SCardFreeMemory_Internal(hContext, *pMszReaderNames); + + *pMszReaderNames = mszReaderNamesWinSCard; + PCSC_AddMemoryBlock(hContext, *pMszReaderNames); + } + + *pdwState &= 0xFFFF; + *pdwState = PCSC_ConvertCardStateToWinSCard(*pdwState, status); + + *pdwProtocol = PCSC_ConvertProtocolsToWinSCard(*pdwProtocol); return status; } @@ -1493,10 +1564,7 @@ WINSCARDAPI LONG WINAPI PCSC_SCardStatusA(SCARDHANDLE hCard, { LONG status = SCARD_S_SUCCESS; - if (g_PCSC.pfnSCardStatus) - { - status = PCSC_SCardStatus_Internal(hCard, mszReaderNames, pcchReaderLen, pdwState, pdwProtocol, pbAtr, pcbAtrLen); - } + status = PCSC_SCardStatus_Internal(hCard, mszReaderNames, pcchReaderLen, pdwState, pdwProtocol, pbAtr, pcbAtrLen); return status; } @@ -1505,24 +1573,26 @@ WINSCARDAPI LONG WINAPI PCSC_SCardStatusW(SCARDHANDLE hCard, LPWSTR mszReaderNames, LPDWORD pcchReaderLen, LPDWORD pdwState, LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen) { + SCARDCONTEXT hContext = 0; + LPSTR mszReaderNamesA = NULL; LONG status = SCARD_S_SUCCESS; - if (g_PCSC.pfnSCardStatus) + if (!g_PCSC.pfnSCardStatus) + return SCARD_E_NO_SERVICE; + + hContext = PCSC_GetCardContextFromHandle(hCard); + + if (!hContext) + return SCARD_E_INVALID_VALUE; + + status = PCSC_SCardStatus_Internal(hCard, (LPSTR) &mszReaderNamesA, pcchReaderLen, pdwState, pdwProtocol, pbAtr, pcbAtrLen); + + if (mszReaderNamesA) { - SCARDCONTEXT hContext = 0; - LPSTR mszReaderNamesA = NULL; + *pcchReaderLen = ConvertToUnicode(CP_UTF8, 0, mszReaderNamesA, *pcchReaderLen, (WCHAR**) mszReaderNames, 0); + PCSC_AddMemoryBlock(hContext, mszReaderNames); - hContext = PCSC_GetCardContextFromHandle(hCard); - - status = PCSC_SCardStatus_Internal(hCard, (LPSTR) &mszReaderNamesA, pcchReaderLen, pdwState, pdwProtocol, pbAtr, pcbAtrLen); - - if (mszReaderNamesA) - { - *pcchReaderLen = ConvertToUnicode(CP_UTF8, 0, mszReaderNamesA, *pcchReaderLen, (WCHAR**) mszReaderNames, 0); - PCSC_AddMemoryBlock(hContext, mszReaderNames); - - PCSC_SCardFreeMemory_Internal(hContext, mszReaderNamesA); - } + PCSC_SCardFreeMemory_Internal(hContext, mszReaderNamesA); } return status; @@ -1534,38 +1604,38 @@ WINSCARDAPI LONG WINAPI PCSC_SCardTransmit(SCARDHANDLE hCard, { LONG status = SCARD_S_SUCCESS; - if (g_PCSC.pfnSCardTransmit) + if (!g_PCSC.pfnSCardTransmit) + return SCARD_E_NO_SERVICE; + + if (!pioSendPci) { - if (!pioSendPci) + DWORD dwState = 0; + DWORD cbAtrLen = 0; + DWORD dwProtocol = 0; + DWORD cchReaderLen = 0; + + /** + * pcsc-lite cannot have a null pioSendPci parameter, unlike WinSCard. + * Query the current protocol and use default SCARD_IO_REQUEST for it. + */ + + status = g_PCSC.pfnSCardStatus(hCard, NULL, &cchReaderLen, &dwState, &dwProtocol, NULL, &cbAtrLen); + + if (status == SCARD_S_SUCCESS) { - DWORD dwState = 0; - DWORD cbAtrLen = 0; - DWORD dwProtocol = 0; - DWORD cchReaderLen = 0; - - /** - * pcsc-lite cannot have a null pioSendPci parameter, unlike WinSCard. - * Query the current protocol and use default SCARD_IO_REQUEST for it. - */ - - status = SCardStatusA(hCard, NULL, &cchReaderLen, &dwState, &dwProtocol, NULL, &cbAtrLen); - - if (status == SCARD_S_SUCCESS) - { - if (dwProtocol == SCARD_PROTOCOL_T0) - pioSendPci = SCARD_PCI_T0; - else if (dwProtocol == SCARD_PROTOCOL_T1) - pioSendPci = SCARD_PCI_T1; - else if (dwProtocol == SCARD_PROTOCOL_RAW) - pioSendPci = SCARD_PCI_RAW; - } + if (dwProtocol == SCARD_PROTOCOL_T0) + pioSendPci = SCARD_PCI_T0; + else if (dwProtocol == SCARD_PROTOCOL_T1) + pioSendPci = SCARD_PCI_T1; + else if (dwProtocol == SCARD_PROTOCOL_RAW) + pioSendPci = SCARD_PCI_RAW; } - - status = g_PCSC.pfnSCardTransmit(hCard, pioSendPci, pbSendBuffer, - cbSendLength, pioRecvPci, pbRecvBuffer, pcbRecvLength); - status = PCSC_MapErrorCodeToWinSCard(status); } + status = g_PCSC.pfnSCardTransmit(hCard, pioSendPci, pbSendBuffer, + cbSendLength, pioRecvPci, pbRecvBuffer, pcbRecvLength); + status = PCSC_MapErrorCodeToWinSCard(status); + return status; } @@ -1580,63 +1650,62 @@ WINSCARDAPI LONG WINAPI PCSC_SCardControl(SCARDHANDLE hCard, { LONG status = SCARD_S_SUCCESS; - if (g_PCSC.pfnSCardControl) - { - status = g_PCSC.pfnSCardControl(hCard, - dwControlCode, lpInBuffer, cbInBufferSize, - lpOutBuffer, cbOutBufferSize, lpBytesReturned); - status = PCSC_MapErrorCodeToWinSCard(status); - } + if (!g_PCSC.pfnSCardControl) + return SCARD_E_NO_SERVICE; + + status = g_PCSC.pfnSCardControl(hCard, + dwControlCode, lpInBuffer, cbInBufferSize, + lpOutBuffer, cbOutBufferSize, lpBytesReturned); + status = PCSC_MapErrorCodeToWinSCard(status); return status; } WINSCARDAPI LONG WINAPI PCSC_SCardGetAttrib_Internal(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr, LPDWORD pcbAttrLen) { + SCARDCONTEXT hContext = 0; + BOOL pcbAttrLenWrapAlloc = FALSE; + LPBYTE* pPbAttr = (LPBYTE*) pbAttr; LONG status = SCARD_S_SUCCESS; - if (g_PCSC.pfnSCardGetAttrib) + if (!g_PCSC.pfnSCardGetAttrib) + return SCARD_E_NO_SERVICE; + + if ((*pcbAttrLen == SCARD_AUTOALLOCATE) && !g_SCardAutoAllocate) + pcbAttrLenWrapAlloc = TRUE; + + hContext = PCSC_GetCardContextFromHandle(hCard); + + if (!hContext) + return SCARD_E_INVALID_VALUE; + + if (pcbAttrLenWrapAlloc) { - SCARDCONTEXT hContext = 0; - BOOL pcbAttrLenWrapAlloc = FALSE; - LPBYTE* pPbAttr = (LPBYTE*) pbAttr; + *pcbAttrLen = 0; - if ((*pcbAttrLen == SCARD_AUTOALLOCATE) && !g_SCardAutoAllocate) - pcbAttrLenWrapAlloc = TRUE; + status = g_PCSC.pfnSCardGetAttrib(hCard, dwAttrId, NULL, pcbAttrLen); - if (pcbAttrLenWrapAlloc) + if (status == SCARD_S_SUCCESS) { - *pcbAttrLen = 0; + *pPbAttr = (BYTE*) calloc(1, *pcbAttrLen); - status = g_PCSC.pfnSCardGetAttrib(hCard, dwAttrId, NULL, pcbAttrLen); + if (!*pPbAttr) + return SCARD_E_NO_MEMORY; - if (!status) - { - *pPbAttr = (BYTE*) calloc(1, *pcbAttrLen); + status = g_PCSC.pfnSCardGetAttrib(hCard, dwAttrId, *pPbAttr, pcbAttrLen); - if (!*pPbAttr) - return SCARD_E_NO_MEMORY; - - status = g_PCSC.pfnSCardGetAttrib(hCard, dwAttrId, *pPbAttr, pcbAttrLen); - - if (status) - { - free(*pPbAttr); - } - else - { - hContext = PCSC_GetCardContextFromHandle(hCard); - PCSC_AddMemoryBlock(hContext, *pPbAttr); - } - } + if (status != SCARD_S_SUCCESS) + free(*pPbAttr); + else + PCSC_AddMemoryBlock(hContext, *pPbAttr); } - else - { - status = g_PCSC.pfnSCardGetAttrib(hCard, dwAttrId, pbAttr, pcbAttrLen); - } - - status = PCSC_MapErrorCodeToWinSCard(status); } + else + { + status = g_PCSC.pfnSCardGetAttrib(hCard, dwAttrId, pbAttr, pcbAttrLen); + } + + status = PCSC_MapErrorCodeToWinSCard(status); return status; } @@ -1654,6 +1723,14 @@ WINSCARDAPI LONG WINAPI PCSC_SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, L if (*pcbAttrLen == SCARD_AUTOALLOCATE) attrAutoAlloc = TRUE; + /** + * pcsc-lite returns SCARD_E_INSUFFICIENT_BUFFER if the given + * buffer size is larger than PCSC_MAX_BUFFER_SIZE (264) + */ + + if (*pcbAttrLen > PCSC_MAX_BUFFER_SIZE) + *pcbAttrLen = PCSC_MAX_BUFFER_SIZE; + hContext = PCSC_GetCardContextFromHandle(hCard); status = PCSC_SCardGetAttrib_Internal(hCard, dwAttrId, pbAttr, pcbAttrLen); @@ -1673,7 +1750,7 @@ WINSCARDAPI LONG WINAPI PCSC_SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, L *pcbAttrLen = strlen((char*) pbAttr); } } - else if (status == SCARD_E_UNSUPPORTED_FEATURE) + else { if (dwAttrId == SCARD_ATTR_DEVICE_FRIENDLY_NAME_A) { @@ -1684,7 +1761,7 @@ WINSCARDAPI LONG WINAPI PCSC_SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, L status = PCSC_SCardGetAttrib_Internal(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME_W, (LPBYTE) &pbAttrW, pcbAttrLen); - if (status) + if (status == SCARD_S_SUCCESS) { int length; char* pbAttrA = NULL; @@ -1724,7 +1801,7 @@ WINSCARDAPI LONG WINAPI PCSC_SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, L status = PCSC_SCardGetAttrib_Internal(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME_A, (LPBYTE) &pbAttrA, pcbAttrLen); - if (status) + if (status == SCARD_S_SUCCESS) { int length; WCHAR* pbAttrW = NULL; @@ -1754,6 +1831,109 @@ WINSCARDAPI LONG WINAPI PCSC_SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, L } } } + else if (dwAttrId == SCARD_ATTR_CURRENT_PROTOCOL_TYPE) + { + DWORD dwState = 0; + DWORD cbAtrLen = 0; + DWORD dwProtocol = 0; + DWORD cchReaderLen = 0; + + status = g_PCSC.pfnSCardStatus(hCard, NULL, &cchReaderLen, &dwState, &dwProtocol, NULL, &cbAtrLen); + + if (status == SCARD_S_SUCCESS) + { + LPDWORD pdwProtocol = (LPDWORD) pbAttr; + + if (cbAttrLen < 4) + return SCARD_E_INSUFFICIENT_BUFFER; + + *pdwProtocol = dwProtocol; + } + } + else if (dwAttrId == SCARD_ATTR_VENDOR_IFD_TYPE) + { + + } + else if (dwAttrId == SCARD_ATTR_CHANNEL_ID) + { + + } + else if (dwAttrId == SCARD_ATTR_DEFAULT_CLK) + { + + } + else if (dwAttrId == SCARD_ATTR_DEFAULT_DATA_RATE) + { + + } + else if (dwAttrId == SCARD_ATTR_MAX_CLK) + { + + } + else if (dwAttrId == SCARD_ATTR_MAX_DATA_RATE) + { + + } + else if (dwAttrId == SCARD_ATTR_MAX_IFSD) + { + + } + else if (dwAttrId == SCARD_ATTR_CHARACTERISTICS) + { + + } + else if (dwAttrId == SCARD_ATTR_DEVICE_SYSTEM_NAME_A) + { + + } + else if (dwAttrId == SCARD_ATTR_DEVICE_UNIT) + { + + } + else if (dwAttrId == SCARD_ATTR_POWER_MGMT_SUPPORT) + { + + } + else if (dwAttrId == SCARD_ATTR_CURRENT_CLK) + { + + } + else if (dwAttrId == SCARD_ATTR_CURRENT_F) + { + + } + else if (dwAttrId == SCARD_ATTR_CURRENT_D) + { + + } + else if (dwAttrId == SCARD_ATTR_CURRENT_N) + { + + } + else if (dwAttrId == SCARD_ATTR_CURRENT_CWT) + { + + } + else if (dwAttrId == SCARD_ATTR_CURRENT_BWT) + { + + } + else if (dwAttrId == SCARD_ATTR_CURRENT_IFSC) + { + + } + else if (dwAttrId == SCARD_ATTR_CURRENT_EBC_ENCODING) + { + + } + else if (dwAttrId == SCARD_ATTR_CURRENT_IFSD) + { + + } + else if (dwAttrId == SCARD_ATTR_ICC_TYPE_PER_ATR) + { + + } } return status; @@ -1763,11 +1943,11 @@ WINSCARDAPI LONG WINAPI PCSC_SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, L { LONG status = SCARD_S_SUCCESS; - if (g_PCSC.pfnSCardSetAttrib) - { - status = g_PCSC.pfnSCardSetAttrib(hCard, dwAttrId, pbAttr, cbAttrLen); - status = PCSC_MapErrorCodeToWinSCard(status); - } + if (!g_PCSC.pfnSCardSetAttrib) + return SCARD_E_NO_SERVICE; + + status = g_PCSC.pfnSCardSetAttrib(hCard, dwAttrId, pbAttr, cbAttrLen); + status = PCSC_MapErrorCodeToWinSCard(status); return status; } @@ -1994,7 +2174,10 @@ int PCSC_InitializeSCardApi(void) #ifdef __MACOSX__ g_PCSCModule = LoadLibraryA("/System/Library/Frameworks/PCSC.framework/PCSC"); #else - g_PCSCModule = LoadLibraryA("libpcsclite.so"); + g_PCSCModule = LoadLibraryA("libpcsclite.so.1"); + + if (!g_PCSCModule) + g_PCSCModule = LoadLibraryA("libpcsclite.so"); #endif if (!g_PCSCModule) @@ -2034,3 +2217,5 @@ int PCSC_InitializeSCardApi(void) return 1; } + +#endif diff --git a/winpr/libwinpr/smartcard/smartcard_pcsc.h b/winpr/libwinpr/smartcard/smartcard_pcsc.h index 31c49b9a9..5ff24e7c7 100644 --- a/winpr/libwinpr/smartcard/smartcard_pcsc.h +++ b/winpr/libwinpr/smartcard/smartcard_pcsc.h @@ -20,6 +20,8 @@ #ifndef WINPR_SMARTCARD_PCSC_PRIVATE_H #define WINPR_SMARTCARD_PCSC_PRIVATE_H +#ifndef _WIN32 + #include #include @@ -34,6 +36,22 @@ #define PCSC_SCARD_PROTOCOL_RAW 0x00000004 #define PCSC_SCARD_PROTOCOL_T15 0x00000008 +#define PCSC_MAX_BUFFER_SIZE 264 +#define PCSC_MAX_BUFFER_SIZE_EXTENDED (4 + 3 + (1 << 16) + 3 + 2) + +#define PCSC_MAX_ATR_SIZE 33 + +typedef struct +{ + LPCSTR szReader; + LPVOID pvUserData; + DWORD dwCurrentState; + DWORD dwEventState; + DWORD cbAtr; + BYTE rgbAtr[PCSC_MAX_ATR_SIZE]; /* WinSCard: 36, PCSC: 33 */ +} +PCSC_SCARD_READERSTATE; + struct _PCSCFunctionTable { LONG (* pfnSCardEstablishContext)(DWORD dwScope, LPCVOID pvReserved1, LPCVOID pvReserved2, LPSCARDCONTEXT phContext); @@ -52,7 +70,7 @@ struct _PCSCFunctionTable LPSTR mszReaderName, LPDWORD pcchReaderLen, LPDWORD pdwState, LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen); LONG (* pfnSCardGetStatusChange)(SCARDCONTEXT hContext, - DWORD dwTimeout, LPSCARD_READERSTATEA rgReaderStates, DWORD cReaders); + DWORD dwTimeout, PCSC_SCARD_READERSTATE* rgReaderStates, DWORD cReaders); LONG (* pfnSCardControl)(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer, DWORD cbSendLength, LPVOID pbRecvBuffer, DWORD cbRecvLength, LPDWORD lpBytesReturned); @@ -72,4 +90,6 @@ typedef struct _PCSCFunctionTable PCSCFunctionTable; int PCSC_InitializeSCardApi(void); PSCardApiFunctionTable PCSC_GetSCardApiFunctionTable(void); +#endif + #endif /* WINPR_SMARTCARD_PCSC_PRIVATE_H */ diff --git a/winpr/libwinpr/smartcard/smartcard_winscard.c b/winpr/libwinpr/smartcard/smartcard_winscard.c index d7bf417e8..d185933b9 100644 --- a/winpr/libwinpr/smartcard/smartcard_winscard.c +++ b/winpr/libwinpr/smartcard/smartcard_winscard.c @@ -21,6 +21,8 @@ #include "config.h" #endif +#ifdef _WIN32 + #include #include #include @@ -203,3 +205,5 @@ int WinSCard_InitializeSCardApi(void) return 1; } + +#endif diff --git a/winpr/libwinpr/smartcard/smartcard_winscard.h b/winpr/libwinpr/smartcard/smartcard_winscard.h index 4bb83bf88..aacc9f268 100644 --- a/winpr/libwinpr/smartcard/smartcard_winscard.h +++ b/winpr/libwinpr/smartcard/smartcard_winscard.h @@ -20,6 +20,8 @@ #ifndef WINPR_SMARTCARD_WINSCARD_PRIVATE_H #define WINPR_SMARTCARD_WINSCARD_PRIVATE_H +#ifdef _WIN32 + #include #define WINSCARD_LOAD_PROC(_name, ...) \ @@ -28,4 +30,6 @@ int WinSCard_InitializeSCardApi(void); PSCardApiFunctionTable WinSCard_GetSCardApiFunctionTable(void); +#endif + #endif /* WINPR_SMARTCARD_WINSCARD_PRIVATE_H */