FreeRDP/winpr/libwinpr/smartcard/smartcard_pcsc.c

2798 lines
71 KiB
C
Raw Normal View History

/**
* WinPR: Windows Portable Runtime
* Smart Card API
*
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifndef _WIN32
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <winpr/crt.h>
#include <winpr/print.h>
#include <winpr/synch.h>
#include <winpr/library.h>
#include <winpr/smartcard.h>
#include <winpr/collections.h>
#include <winpr/environment.h>
#include "smartcard_pcsc.h"
/**
* PC/SC transactions:
* http://developersblog.wwpass.com/?p=180
*/
/**
* Smart Card Logon on Windows Vista:
* http://blogs.msdn.com/b/shivaram/archive/2007/02/26/smart-card-logon-on-windows-vista.aspx
*/
/**
* The Smart Card Cryptographic Service Provider Cookbook:
* http://msdn.microsoft.com/en-us/library/ms953432.aspx
*
* SCARDCONTEXT
*
* The context is a communication channel with the smart card resource manager and
* all calls to the resource manager must go through this link.
*
* All functions that take a context as a parameter or a card handle as parameter,
* which is indirectly associated with a particular context, may be blocking calls.
* Examples of these are SCardGetStatusChange and SCardBeginTransaction, which takes
* a card handle as a parameter. If such a function blocks then all operations wanting
* to use the context are blocked as well. So, it is recommended that a CSP using
* monitoring establishes at least two contexts with the resource manager; one for
* monitoring (with SCardGetStatusChange) and one for other operations.
*
* If multiple cards are present, it is recommended that a separate context or pair
* of contexts be established for each card to prevent operations on one card from
* blocking operations on another.
*
* Example one
*
* The example below shows what can happen if a CSP using SCardGetStatusChange for
* monitoring does not establish two contexts with the resource manager.
* The context becomes unusable until SCardGetStatusChange unblocks.
*
* In this example, there is one process running called P1.
* P1 calls SCardEstablishContext, which returns the context hCtx.
* P1 calls SCardConnect (with the hCtx context) which returns a handle to the card, hCard.
* P1 calls SCardGetStatusChange (with the hCtx context) which blocks because
* there are no status changes to report.
* Until the thread running SCardGetStatusChange unblocks, another thread in P1 trying to
* perform an operation using the context hCtx (or the card hCard) will also be blocked.
*
* Example two
*
* The example below shows how transaction control ensures that operations meant to be
* performed without interruption can do so safely within a transaction.
*
* In this example, there are two different processes running; P1 and P2.
* P1 calls SCardEstablishContext, which returns the context hCtx1.
* P2 calls SCardEstablishContext, which returns the context hCtx2.
* P1 calls SCardConnect (with the hCtx1 context) which returns a handle to the card, hCard1.
* P2 calls SCardConnect (with the hCtx2 context) which returns a handle to the same card, hCard2.
* P1 calls SCardBeginTransaction (with the hCard 1 context).
* Until P1 calls SCardEndTransaction (with the hCard1 context),
* any operation using hCard2 will be blocked.
* Once an operation using hCard2 is blocked and until it's returning,
* any operation using hCtx2 (and hCard2) will also be blocked.
*/
//#define DISABLE_PCSC_SCARD_AUTOALLOCATE
struct _PCSC_SCARDCONTEXT
{
CRITICAL_SECTION lock;
SCARDCONTEXT hContext;
DWORD dwCardHandleCount;
};
typedef struct _PCSC_SCARDCONTEXT PCSC_SCARDCONTEXT;
struct _PCSC_SCARDHANDLE
{
CRITICAL_SECTION lock;
SCARDCONTEXT hSharedContext;
SCARDCONTEXT hPrivateContext;
};
typedef struct _PCSC_SCARDHANDLE PCSC_SCARDHANDLE;
struct _PCSC_READER
{
char* namePCSC;
char* nameWinSCard;
};
typedef struct _PCSC_READER PCSC_READER;
static HMODULE g_PCSCModule = NULL;
static PCSCFunctionTable g_PCSC = { 0 };
static HANDLE g_StartedEvent = NULL;
static int g_StartedEventRefCount = 0;
static BOOL g_SCardAutoAllocate = FALSE;
static BOOL g_PnP_Notification = TRUE;
static wArrayList* g_Readers = NULL;
static wListDictionary* g_CardHandles = NULL;
static wListDictionary* g_CardContexts = NULL;
static wListDictionary* g_MemoryBlocks = NULL;
char SMARTCARD_PNP_NOTIFICATION_A[] = "\\\\?PnP?\\Notification";
WCHAR SMARTCARD_PNP_NOTIFICATION_W[] = { '\\','\\','?','P','n','P','?',
'\\','N','o','t','i','f','i','c','a','t','i','o','n','\0' };
const PCSC_SCARD_IO_REQUEST g_PCSC_rgSCardT0Pci = { SCARD_PROTOCOL_T0, sizeof(PCSC_SCARD_IO_REQUEST) };
const PCSC_SCARD_IO_REQUEST g_PCSC_rgSCardT1Pci = { SCARD_PROTOCOL_T1, sizeof(PCSC_SCARD_IO_REQUEST) };
const PCSC_SCARD_IO_REQUEST g_PCSC_rgSCardRawPci = { PCSC_SCARD_PROTOCOL_RAW, sizeof(PCSC_SCARD_IO_REQUEST) };
WINSCARDAPI LONG WINAPI PCSC_SCardFreeMemory_Internal(SCARDCONTEXT hContext, LPCVOID pvMem);
WINSCARDAPI LONG WINAPI PCSC_SCardEstablishContext_Internal(DWORD dwScope,
LPCVOID pvReserved1, LPCVOID pvReserved2, LPSCARDCONTEXT phContext);
WINSCARDAPI LONG WINAPI PCSC_SCardReleaseContext_Internal(SCARDCONTEXT hContext);
LONG PCSC_MapErrorCodeToWinSCard(LONG errorCode)
{
/**
* pcsc-lite returns SCARD_E_UNEXPECTED when it
* should return SCARD_E_UNSUPPORTED_FEATURE.
*
* Additionally, the pcsc-lite headers incorrectly
* define SCARD_E_UNSUPPORTED_FEATURE to 0x8010001F,
* when the real value should be 0x80100022.
*/
if (errorCode == SCARD_E_UNEXPECTED)
errorCode = SCARD_E_UNSUPPORTED_FEATURE;
return errorCode;
}
DWORD PCSC_ConvertCardStateToWinSCard(DWORD dwCardState, LONG status)
{
/**
* pcsc-lite's SCardStatus returns a bit-field, not an enumerated value.
*
* State WinSCard pcsc-lite
*
* SCARD_UNKNOWN 0 0x0001
* SCARD_ABSENT 1 0x0002
* SCARD_PRESENT 2 0x0004
* SCARD_SWALLOWED 3 0x0008
* SCARD_POWERED 4 0x0010
* SCARD_NEGOTIABLE 5 0x0020
* SCARD_SPECIFIC 6 0x0040
*
* pcsc-lite also never sets SCARD_SPECIFIC,
* which is expected by some windows applications.
*/
if (status == SCARD_S_SUCCESS)
{
if ((dwCardState & PCSC_SCARD_NEGOTIABLE) || (dwCardState & PCSC_SCARD_SPECIFIC))
return SCARD_SPECIFIC;
}
if (dwCardState & PCSC_SCARD_POWERED)
return SCARD_POWERED;
if (dwCardState & PCSC_SCARD_NEGOTIABLE)
return SCARD_NEGOTIABLE;
if (dwCardState & PCSC_SCARD_SPECIFIC)
return SCARD_SPECIFIC;
if (dwCardState & PCSC_SCARD_ABSENT)
return SCARD_ABSENT;
if (dwCardState & PCSC_SCARD_PRESENT)
return SCARD_PRESENT;
if (dwCardState & PCSC_SCARD_SWALLOWED)
return SCARD_SWALLOWED;
if (dwCardState & PCSC_SCARD_UNKNOWN)
return SCARD_UNKNOWN;
return SCARD_UNKNOWN;
}
DWORD PCSC_ConvertProtocolsToWinSCard(DWORD dwProtocols)
{
/**
* pcsc-lite uses a different value for SCARD_PROTOCOL_RAW,
* and also has SCARD_PROTOCOL_T15 which is not in WinSCard.
*/
if (dwProtocols & PCSC_SCARD_PROTOCOL_RAW)
{
dwProtocols &= ~PCSC_SCARD_PROTOCOL_RAW;
dwProtocols |= SCARD_PROTOCOL_RAW;
}
if (dwProtocols & PCSC_SCARD_PROTOCOL_T15)
{
dwProtocols &= ~PCSC_SCARD_PROTOCOL_T15;
}
return dwProtocols;
}
DWORD PCSC_ConvertProtocolsFromWinSCard(DWORD dwProtocols)
{
/**
* pcsc-lite uses a different value for SCARD_PROTOCOL_RAW,
* and it does not define WinSCard's SCARD_PROTOCOL_DEFAULT.
*/
if (dwProtocols & SCARD_PROTOCOL_RAW)
{
dwProtocols &= ~SCARD_PROTOCOL_RAW;
dwProtocols |= PCSC_SCARD_PROTOCOL_RAW;
}
if (dwProtocols & SCARD_PROTOCOL_DEFAULT)
{
dwProtocols &= ~SCARD_PROTOCOL_DEFAULT;
}
2014-04-16 01:51:39 +04:00
if (dwProtocols == SCARD_PROTOCOL_UNDEFINED)
{
dwProtocols = SCARD_PROTOCOL_Tx;
}
return dwProtocols;
}
void PCSC_ReaderAliasFree(PCSC_READER* reader)
{
if (!reader)
return;
free(reader->namePCSC);
free(reader->nameWinSCard);
}
PCSC_SCARDCONTEXT* PCSC_GetCardContextData(SCARDCONTEXT hContext)
{
PCSC_SCARDCONTEXT* pContext;
if (!g_CardContexts)
return NULL;
pContext = (PCSC_SCARDCONTEXT*) ListDictionary_GetItemValue(g_CardContexts, (void*) hContext);
if (!pContext)
return NULL;
return pContext;
}
PCSC_SCARDCONTEXT* PCSC_EstablishCardContext(SCARDCONTEXT hContext)
{
PCSC_SCARDCONTEXT* pContext;
pContext = (PCSC_SCARDCONTEXT*) calloc(1, sizeof(PCSC_SCARDCONTEXT));
if (!pContext)
return NULL;
pContext->hContext = hContext;
InitializeCriticalSectionAndSpinCount(&(pContext->lock), 4000);
if (!g_CardContexts)
g_CardContexts = ListDictionary_New(TRUE);
if (!g_Readers)
{
g_Readers = ArrayList_New(TRUE);
ArrayList_Object(g_Readers)->fnObjectFree = (OBJECT_FREE_FN) PCSC_ReaderAliasFree;
}
ListDictionary_Add(g_CardContexts, (void*) hContext, (void*) pContext);
return pContext;
}
void PCSC_ReleaseCardContext(SCARDCONTEXT hContext)
{
PCSC_SCARDCONTEXT* pContext;
pContext = PCSC_GetCardContextData(hContext);
if (!pContext)
{
printf("PCSC_ReleaseCardContext: null pContext!\n");
return;
}
DeleteCriticalSection(&(pContext->lock));
printf("PCSC_ReleaseCardContext: %d\n", pContext->dwCardHandleCount);
free(pContext);
if (!g_CardContexts)
return;
ListDictionary_Remove(g_CardContexts, (void*) hContext);
}
BOOL PCSC_LockCardContext(SCARDCONTEXT hContext)
{
PCSC_SCARDCONTEXT* pContext;
pContext = PCSC_GetCardContextData(hContext);
if (!pContext)
{
fprintf(stderr, "PCSC_LockCardContext: invalid context (%p)\n", (void*) hContext);
return FALSE;
}
EnterCriticalSection(&(pContext->lock));
return TRUE;
}
BOOL PCSC_UnlockCardContext(SCARDCONTEXT hContext)
{
PCSC_SCARDCONTEXT* pContext;
pContext = PCSC_GetCardContextData(hContext);
if (!pContext)
{
fprintf(stderr, "PCSC_UnlockCardContext: invalid context (%p)\n", (void*) hContext);
return FALSE;
}
LeaveCriticalSection(&(pContext->lock));
return TRUE;
}
PCSC_SCARDHANDLE* PCSC_GetCardHandleData(SCARDHANDLE hCard)
{
PCSC_SCARDHANDLE* pCard;
if (!g_CardHandles)
return NULL;
pCard = (PCSC_SCARDHANDLE*) ListDictionary_GetItemValue(g_CardHandles, (void*) hCard);
if (!pCard)
return NULL;
return pCard;
}
SCARDCONTEXT PCSC_GetCardContextFromHandle(SCARDHANDLE hCard)
{
PCSC_SCARDHANDLE* pCard;
pCard = PCSC_GetCardHandleData(hCard);
if (!pCard)
return 0;
return pCard->hPrivateContext;
}
PCSC_SCARDHANDLE* PCSC_ConnectCardHandle(SCARDCONTEXT hSharedContext, SCARDCONTEXT hPrivateContext, SCARDHANDLE hCard)
{
PCSC_SCARDHANDLE* pCard;
PCSC_SCARDCONTEXT* pContext;
pContext = PCSC_GetCardContextData(hSharedContext);
if (!pContext)
{
printf("PCSC_ConnectCardHandle: null pContext!\n");
return NULL;
}
pCard = (PCSC_SCARDHANDLE*) calloc(1, sizeof(PCSC_SCARDHANDLE));
if (!pCard)
return NULL;
pCard->hSharedContext = hSharedContext;
pCard->hPrivateContext = hPrivateContext;
InitializeCriticalSectionAndSpinCount(&(pCard->lock), 4000);
pContext->dwCardHandleCount++;
printf("PCSC_ConnectCardHandle: %d\n", pContext->dwCardHandleCount);
if (!g_CardHandles)
g_CardHandles = ListDictionary_New(TRUE);
ListDictionary_Add(g_CardHandles, (void*) hCard, (void*) pCard);
return pCard;
}
void PCSC_DisconnectCardHandle(SCARDHANDLE hCard)
{
PCSC_SCARDHANDLE* pCard;
PCSC_SCARDCONTEXT* pContext;
pCard = PCSC_GetCardHandleData(hCard);
if (!pCard)
return;
DeleteCriticalSection(&(pCard->lock));
pContext = PCSC_GetCardContextData(pCard->hSharedContext);
PCSC_SCardReleaseContext_Internal(pCard->hPrivateContext);
free(pCard);
if (!g_CardHandles)
return;
ListDictionary_Remove(g_CardHandles, (void*) hCard);
if (!pContext)
{
printf("PCSC_DisconnectCardHandle: null pContext!");
return;
}
pContext->dwCardHandleCount--;
printf("PCSC_DisconnectCardHandle: %d\n", pContext->dwCardHandleCount);
}
BOOL PCSC_LockCardHandle(SCARDHANDLE hCard)
{
PCSC_SCARDHANDLE* pCard;
pCard = PCSC_GetCardHandleData(hCard);
if (!pCard)
{
fprintf(stderr, "PCSC_LockCardHandle: invalid handle (%p)\n", (void*) hCard);
return FALSE;
}
EnterCriticalSection(&(pCard->lock));
return TRUE;
}
BOOL PCSC_UnlockCardHandle(SCARDHANDLE hCard)
{
PCSC_SCARDHANDLE* pCard;
pCard = PCSC_GetCardHandleData(hCard);
if (!pCard)
{
fprintf(stderr, "PCSC_UnlockCardHandle: invalid handle (%p)\n", (void*) hCard);
return FALSE;
}
LeaveCriticalSection(&(pCard->lock));
return TRUE;
}
BOOL PCSC_LockCardTransaction(SCARDHANDLE hCard)
{
PCSC_SCARDHANDLE* pCard;
return TRUE; /* disable for now because it deadlocks */
pCard = PCSC_GetCardHandleData(hCard);
if (!pCard)
{
fprintf(stderr, "PCSC_LockCardTransaction: invalid handle (%p)\n", (void*) hCard);
return FALSE;
}
EnterCriticalSection(&(pCard->lock));
return TRUE;
}
BOOL PCSC_UnlockCardTransaction(SCARDHANDLE hCard)
{
PCSC_SCARDHANDLE* pCard;
return TRUE; /* disable for now because it deadlocks */
pCard = PCSC_GetCardHandleData(hCard);
if (!pCard)
{
2014-05-13 01:28:35 +04:00
fprintf(stderr, "PCSC_UnlockCardTransaction: invalid handle (%p)\n", (void*) hCard);
return FALSE;
}
LeaveCriticalSection(&(pCard->lock));
return TRUE;
}
char* PCSC_GetReaderNameFromAlias(char* nameWinSCard)
{
int index;
int count;
PCSC_READER* reader;
char* namePCSC = NULL;
ArrayList_Lock(g_Readers);
count = ArrayList_Count(g_Readers);
for (index = 0; index < count; index++)
{
reader = ArrayList_GetItem(g_Readers, index);
if (strcmp(nameWinSCard, reader->nameWinSCard) == 0)
{
namePCSC = reader->namePCSC;
break;
}
}
ArrayList_Unlock(g_Readers);
return namePCSC;
}
BOOL PCSC_AddReaderNameAlias(char* namePCSC, char* nameWinSCard)
{
PCSC_READER* reader;
if (PCSC_GetReaderNameFromAlias(nameWinSCard))
return TRUE;
reader = (PCSC_READER*) calloc(1, sizeof(PCSC_READER));
if (!reader)
return FALSE;
reader->namePCSC = _strdup(namePCSC);
reader->nameWinSCard = _strdup(nameWinSCard);
ArrayList_Add(g_Readers, reader);
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;
/**
* pcsc-lite reader name format:
* name [interface] (serial) index slot
*
* Athena IDProtect Key v2 [Main Interface] 00 00
*
* name: Athena IDProtect Key v2
* interface: Main Interface
* serial: N/A
* 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
*/
length = strlen(name);
if (length < 10)
return NULL;
ntokens = 0;
p = q = (char*) name;
while (*p)
{
if (*p == ' ')
{
tokens[ntokens][0] = q;
tokens[ntokens][1] = p;
q = p + 1;
ntokens++;
}
p++;
}
tokens[ntokens][0] = q;
tokens[ntokens][1] = p;
ntokens++;
if (ntokens < 2)
return NULL;
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 (*(tokens[ctoken][1] - 1) == ')')
{
while ((*(tokens[ctoken][0]) != '(') && (ctoken > 0))
ctoken--;
ctoken--;
}
if (ctoken < 1)
return NULL;
if (*(tokens[ctoken][1] - 1) == ']')
{
while ((*(tokens[ctoken][0]) != '[') && (ctoken > 0))
ctoken--;
ctoken--;
}
if (ctoken < 1)
return NULL;
p = tokens[0][0];
q = tokens[ctoken][1];
length = (q - p);
size = length + 16;
nameWinSCard = (char*) malloc(size);
if (!nameWinSCard)
return NULL;
/**
* 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_GetReaderAliasFromName(char* namePCSC)
{
char* nameWinSCard;
nameWinSCard = PCSC_ConvertReaderNameToWinSCard(namePCSC);
if (nameWinSCard)
PCSC_AddReaderNameAlias(namePCSC, nameWinSCard);
return nameWinSCard;
}
char* PCSC_ConvertReaderNamesToWinSCard(const char* names, LPDWORD pcchReaders)
{
2014-04-16 01:51:39 +04:00
int length;
char *p, *q;
DWORD cchReaders;
char* nameWinSCard;
char* namesWinSCard;
p = (char*) names;
cchReaders = *pcchReaders;
namesWinSCard = (char*) malloc(cchReaders * 2);
if (!namesWinSCard)
return NULL;
q = namesWinSCard;
p = (char*) names;
while ((p - names) < cchReaders)
{
nameWinSCard = PCSC_GetReaderAliasFromName(p);
if (nameWinSCard)
{
2014-04-16 01:51:39 +04:00
length = strlen(nameWinSCard);
CopyMemory(q, nameWinSCard, length);
free(nameWinSCard);
}
else
{
2014-04-16 01:51:39 +04:00
length = strlen(p);
CopyMemory(q, p, length);
}
2014-04-16 01:51:39 +04:00
q += length;
*q = '\0';
q++;
p += strlen(p) + 1;
}
*q = '\0';
q++;
*pcchReaders = (DWORD) (q - namesWinSCard);
return namesWinSCard;
}
char* PCSC_ConvertReaderNamesToPCSC(const char* names, LPDWORD pcchReaders)
{
2014-04-16 01:51:39 +04:00
int length;
char *p, *q;
char* namePCSC;
char* namesPCSC;
DWORD cchReaders;
p = (char*) names;
cchReaders = *pcchReaders;
namesPCSC = (char*) malloc(cchReaders * 2);
if (!namesPCSC)
return NULL;
q = namesPCSC;
p = (char*) names;
while ((p - names) < cchReaders)
{
namePCSC = PCSC_GetReaderNameFromAlias(p);
if (!namePCSC)
namePCSC = p;
2014-04-16 01:51:39 +04:00
length = strlen(namePCSC);
CopyMemory(q, namePCSC, length);
2014-04-16 01:51:39 +04:00
q += length;
*q = '\0';
q++;
p += strlen(p) + 1;
}
*q = '\0';
q++;
*pcchReaders = (DWORD) (q - namesPCSC);
return namesPCSC;
}
void PCSC_AddMemoryBlock(SCARDCONTEXT hContext, void* pvMem)
{
if (!g_MemoryBlocks)
g_MemoryBlocks = ListDictionary_New(TRUE);
ListDictionary_Add(g_MemoryBlocks, pvMem, (void*) hContext);
}
void* PCSC_RemoveMemoryBlock(SCARDCONTEXT hContext, void* pvMem)
{
if (!g_MemoryBlocks)
return NULL;
return ListDictionary_Remove(g_MemoryBlocks, pvMem);
}
void* PCSC_SCardAllocMemory(SCARDCONTEXT hContext, size_t size)
{
void* pvMem;
pvMem = malloc(size);
if (!pvMem)
return NULL;
PCSC_AddMemoryBlock(hContext, pvMem);
return pvMem;
}
/**
* Standard Windows Smart Card API (PCSC)
*/
WINSCARDAPI LONG WINAPI PCSC_SCardEstablishContext_Internal(DWORD dwScope,
LPCVOID pvReserved1, LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
{
LONG status = SCARD_S_SUCCESS;
PCSC_DWORD pcsc_dwScope = (PCSC_DWORD) dwScope;
if (!g_PCSC.pfnSCardEstablishContext)
return SCARD_E_NO_SERVICE;
2014-04-09 22:27:44 +04:00
pcsc_dwScope = SCARD_SCOPE_SYSTEM; /* this is the only scope supported by pcsc-lite */
status = (LONG) g_PCSC.pfnSCardEstablishContext(pcsc_dwScope, pvReserved1, pvReserved2, phContext);
status = PCSC_MapErrorCodeToWinSCard(status);
return status;
}
WINSCARDAPI LONG WINAPI PCSC_SCardEstablishContext(DWORD dwScope,
LPCVOID pvReserved1, LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
{
LONG status = SCARD_S_SUCCESS;
status = PCSC_SCardEstablishContext_Internal(dwScope, pvReserved1, pvReserved2, phContext);
if (status == SCARD_S_SUCCESS)
PCSC_EstablishCardContext(*phContext);
return status;
}
WINSCARDAPI LONG WINAPI PCSC_SCardReleaseContext_Internal(SCARDCONTEXT hContext)
{
LONG status = SCARD_S_SUCCESS;
if (!g_PCSC.pfnSCardReleaseContext)
return SCARD_E_NO_SERVICE;
if (!hContext)
{
fprintf(stderr, "SCardReleaseContext: null hContext\n");
return status;
}
status = (LONG) g_PCSC.pfnSCardReleaseContext(hContext);
status = PCSC_MapErrorCodeToWinSCard(status);
return status;
}
WINSCARDAPI LONG WINAPI PCSC_SCardReleaseContext(SCARDCONTEXT hContext)
{
LONG status = SCARD_S_SUCCESS;
status = PCSC_SCardReleaseContext_Internal(hContext);
if (status != SCARD_S_SUCCESS)
PCSC_ReleaseCardContext(hContext);
return status;
}
WINSCARDAPI LONG WINAPI PCSC_SCardIsValidContext(SCARDCONTEXT hContext)
{
LONG status = SCARD_S_SUCCESS;
if (!g_PCSC.pfnSCardIsValidContext)
return SCARD_E_NO_SERVICE;
status = (LONG) g_PCSC.pfnSCardIsValidContext(hContext);
status = PCSC_MapErrorCodeToWinSCard(status);
return status;
}
WINSCARDAPI LONG WINAPI PCSC_SCardListReaderGroupsA(SCARDCONTEXT hContext,
LPSTR mszGroups, LPDWORD pcchGroups)
{
LONG status = SCARD_S_SUCCESS;
PCSC_DWORD pcsc_cchGroups = (PCSC_DWORD) *pcchGroups;
if (!g_PCSC.pfnSCardListReaderGroups)
return SCARD_E_NO_SERVICE;
if (!PCSC_LockCardContext(hContext))
return SCARD_E_INVALID_HANDLE;
status = (LONG) g_PCSC.pfnSCardListReaderGroups(hContext, mszGroups, &pcsc_cchGroups);
status = PCSC_MapErrorCodeToWinSCard(status);
*pcchGroups = (DWORD) pcsc_cchGroups;
if (!PCSC_UnlockCardContext(hContext))
return SCARD_E_INVALID_HANDLE;
return status;
}
WINSCARDAPI LONG WINAPI PCSC_SCardListReaderGroupsW(SCARDCONTEXT hContext,
LPWSTR mszGroups, LPDWORD pcchGroups)
{
LONG status = SCARD_S_SUCCESS;
PCSC_DWORD pcsc_cchGroups = (PCSC_DWORD) *pcchGroups;
if (!g_PCSC.pfnSCardListReaderGroups)
return SCARD_E_NO_SERVICE;
if (!PCSC_LockCardContext(hContext))
return SCARD_E_INVALID_HANDLE;
mszGroups = NULL;
pcchGroups = 0;
/* FIXME: unicode conversion */
status = (LONG) g_PCSC.pfnSCardListReaderGroups(hContext, (LPSTR) mszGroups, &pcsc_cchGroups);
status = PCSC_MapErrorCodeToWinSCard(status);
*pcchGroups = (DWORD) pcsc_cchGroups;
if (!PCSC_UnlockCardContext(hContext))
return SCARD_E_INVALID_HANDLE;
return status;
}
WINSCARDAPI LONG WINAPI PCSC_SCardListReaders_Internal(SCARDCONTEXT hContext,
LPCSTR mszGroups, LPSTR mszReaders, LPDWORD pcchReaders)
{
LONG status = SCARD_S_SUCCESS;
char* mszReadersWinSCard = NULL;
BOOL pcchReadersAlloc = FALSE;
LPSTR* pMszReaders = (LPSTR*) mszReaders;
PCSC_DWORD pcsc_cchReaders = 0;
if (!pcchReaders)
return SCARD_E_INVALID_PARAMETER;
if (!g_PCSC.pfnSCardListReaders)
return SCARD_E_NO_SERVICE;
mszGroups = NULL; /* mszGroups is not supported by pcsc-lite */
2014-04-09 22:27:44 +04:00
if (*pcchReaders == SCARD_AUTOALLOCATE)
pcchReadersAlloc = TRUE;
pcsc_cchReaders = pcchReadersAlloc ? PCSC_SCARD_AUTOALLOCATE : (PCSC_DWORD) *pcchReaders;
if (pcchReadersAlloc && !g_SCardAutoAllocate)
{
pcsc_cchReaders = 0;
status = (LONG) g_PCSC.pfnSCardListReaders(hContext, mszGroups, NULL, &pcsc_cchReaders);
if (status == SCARD_S_SUCCESS)
{
*pMszReaders = calloc(1, pcsc_cchReaders);
if (!*pMszReaders)
return SCARD_E_NO_MEMORY;
status = (LONG) g_PCSC.pfnSCardListReaders(hContext, mszGroups, *pMszReaders, &pcsc_cchReaders);
if (status != SCARD_S_SUCCESS)
free(*pMszReaders);
else
PCSC_AddMemoryBlock(hContext, *pMszReaders);
}
}
else
{
status = (LONG) g_PCSC.pfnSCardListReaders(hContext, mszGroups, mszReaders, &pcsc_cchReaders);
}
status = PCSC_MapErrorCodeToWinSCard(status);
*pcchReaders = (DWORD) pcsc_cchReaders;
if (status == SCARD_S_SUCCESS)
{
mszReadersWinSCard = PCSC_ConvertReaderNamesToWinSCard(*pMszReaders, pcchReaders);
if (mszReadersWinSCard)
{
PCSC_SCardFreeMemory_Internal(hContext, *pMszReaders);
*pMszReaders = mszReadersWinSCard;
PCSC_AddMemoryBlock(hContext, *pMszReaders);
}
}
return status;
}
WINSCARDAPI LONG WINAPI PCSC_SCardListReadersA(SCARDCONTEXT hContext,
LPCSTR mszGroups, LPSTR mszReaders, LPDWORD pcchReaders)
{
BOOL nullCardContext = FALSE;
LONG status = SCARD_S_SUCCESS;
if (!g_PCSC.pfnSCardListReaders)
return SCARD_E_NO_SERVICE;
if (!hContext)
{
status = PCSC_SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
if (status != SCARD_S_SUCCESS)
return status;
nullCardContext = TRUE;
}
if (!PCSC_LockCardContext(hContext))
return SCARD_E_INVALID_HANDLE;
status = PCSC_SCardListReaders_Internal(hContext, mszGroups, mszReaders, pcchReaders);
if (!PCSC_UnlockCardContext(hContext))
return SCARD_E_INVALID_HANDLE;
if (nullCardContext)
{
status = PCSC_SCardReleaseContext(hContext);
}
return status;
}
WINSCARDAPI LONG WINAPI PCSC_SCardListReadersW(SCARDCONTEXT hContext,
LPCWSTR mszGroups, LPWSTR mszReaders, LPDWORD pcchReaders)
{
LPSTR mszGroupsA = NULL;
LPSTR mszReadersA = NULL;
LPSTR* pMszReadersA = &mszReadersA;
LONG status = SCARD_S_SUCCESS;
BOOL nullCardContext = FALSE;
if (!g_PCSC.pfnSCardListReaders)
return SCARD_E_NO_SERVICE;
if (!hContext)
{
status = PCSC_SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
if (status != SCARD_S_SUCCESS)
return status;
nullCardContext = TRUE;
}
if (!PCSC_LockCardContext(hContext))
return SCARD_E_INVALID_HANDLE;
mszGroups = NULL; /* mszGroups is not supported by pcsc-lite */
2014-04-09 22:27:44 +04:00
if (mszGroups)
ConvertFromUnicode(CP_UTF8, 0, mszGroups, -1, (char**) &mszGroupsA, 0, NULL, NULL);
status = PCSC_SCardListReaders_Internal(hContext, mszGroupsA, (LPSTR) &mszReadersA, pcchReaders);
if (status == SCARD_S_SUCCESS)
{
*pcchReaders = ConvertToUnicode(CP_UTF8, 0, *pMszReadersA, *pcchReaders, (WCHAR**) mszReaders, 0);
PCSC_AddMemoryBlock(hContext, mszReaders);
2014-04-07 05:09:49 +04:00
PCSC_SCardFreeMemory_Internal(hContext, *pMszReadersA);
}
free(mszGroupsA);
if (!PCSC_UnlockCardContext(hContext))
return SCARD_E_INVALID_HANDLE;
if (nullCardContext)
{
status = PCSC_SCardReleaseContext(hContext);
}
return status;
}
WINSCARDAPI LONG WINAPI PCSC_SCardListCardsA(SCARDCONTEXT hContext,
LPCBYTE pbAtr, LPCGUID rgquidInterfaces, DWORD cguidInterfaceCount, CHAR* mszCards, LPDWORD pcchCards)
{
return 0;
}
WINSCARDAPI LONG WINAPI PCSC_SCardListCardsW(SCARDCONTEXT hContext,
LPCBYTE pbAtr, LPCGUID rgquidInterfaces, DWORD cguidInterfaceCount, WCHAR* mszCards, LPDWORD pcchCards)
{
return 0;
}
WINSCARDAPI LONG WINAPI PCSC_SCardListInterfacesA(SCARDCONTEXT hContext,
LPCSTR szCard, LPGUID pguidInterfaces, LPDWORD pcguidInterfaces)
{
return 0;
}
WINSCARDAPI LONG WINAPI PCSC_SCardListInterfacesW(SCARDCONTEXT hContext,
LPCWSTR szCard, LPGUID pguidInterfaces, LPDWORD pcguidInterfaces)
{
return 0;
}
WINSCARDAPI LONG WINAPI PCSC_SCardGetProviderIdA(SCARDCONTEXT hContext,
LPCSTR szCard, LPGUID pguidProviderId)
{
return 0;
}
WINSCARDAPI LONG WINAPI PCSC_SCardGetProviderIdW(SCARDCONTEXT hContext,
LPCWSTR szCard, LPGUID pguidProviderId)
{
return 0;
}
WINSCARDAPI LONG WINAPI PCSC_SCardGetCardTypeProviderNameA(SCARDCONTEXT hContext,
LPCSTR szCardName, DWORD dwProviderId, CHAR* szProvider, LPDWORD pcchProvider)
{
return 0;
}
WINSCARDAPI LONG WINAPI PCSC_SCardGetCardTypeProviderNameW(SCARDCONTEXT hContext,
LPCWSTR szCardName, DWORD dwProviderId, WCHAR* szProvider, LPDWORD pcchProvider)
{
return 0;
}
WINSCARDAPI LONG WINAPI PCSC_SCardIntroduceReaderGroupA(SCARDCONTEXT hContext, LPCSTR szGroupName)
{
return 0;
}
WINSCARDAPI LONG WINAPI PCSC_SCardIntroduceReaderGroupW(SCARDCONTEXT hContext, LPCWSTR szGroupName)
{
return 0;
}
WINSCARDAPI LONG WINAPI PCSC_SCardForgetReaderGroupA(SCARDCONTEXT hContext, LPCSTR szGroupName)
{
return 0;
}
WINSCARDAPI LONG WINAPI PCSC_SCardForgetReaderGroupW(SCARDCONTEXT hContext, LPCWSTR szGroupName)
{
return 0;
}
WINSCARDAPI LONG WINAPI PCSC_SCardIntroduceReaderA(SCARDCONTEXT hContext,
LPCSTR szReaderName, LPCSTR szDeviceName)
{
return 0;
}
WINSCARDAPI LONG WINAPI PCSC_SCardIntroduceReaderW(SCARDCONTEXT hContext,
LPCWSTR szReaderName, LPCWSTR szDeviceName)
{
return 0;
}
WINSCARDAPI LONG WINAPI PCSC_SCardForgetReaderA(SCARDCONTEXT hContext, LPCSTR szReaderName)
{
return 0;
}
WINSCARDAPI LONG WINAPI PCSC_SCardForgetReaderW(SCARDCONTEXT hContext, LPCWSTR szReaderName)
{
return 0;
}
WINSCARDAPI LONG WINAPI PCSC_SCardAddReaderToGroupA(SCARDCONTEXT hContext,
LPCSTR szReaderName, LPCSTR szGroupName)
{
return 0;
}
WINSCARDAPI LONG WINAPI PCSC_SCardAddReaderToGroupW(SCARDCONTEXT hContext,
LPCWSTR szReaderName, LPCWSTR szGroupName)
{
return 0;
}
WINSCARDAPI LONG WINAPI PCSC_SCardRemoveReaderFromGroupA(SCARDCONTEXT hContext,
LPCSTR szReaderName, LPCSTR szGroupName)
{
return 0;
}
WINSCARDAPI LONG WINAPI PCSC_SCardRemoveReaderFromGroupW(SCARDCONTEXT hContext,
LPCWSTR szReaderName, LPCWSTR szGroupName)
{
return 0;
}
WINSCARDAPI LONG WINAPI PCSC_SCardIntroduceCardTypeA(SCARDCONTEXT hContext,
LPCSTR szCardName, LPCGUID pguidPrimaryProvider, LPCGUID rgguidInterfaces,
DWORD dwInterfaceCount, LPCBYTE pbAtr, LPCBYTE pbAtrMask, DWORD cbAtrLen)
{
return 0;
}
WINSCARDAPI LONG WINAPI PCSC_SCardIntroduceCardTypeW(SCARDCONTEXT hContext,
LPCWSTR szCardName, LPCGUID pguidPrimaryProvider, LPCGUID rgguidInterfaces,
DWORD dwInterfaceCount, LPCBYTE pbAtr, LPCBYTE pbAtrMask, DWORD cbAtrLen)
{
return 0;
}
WINSCARDAPI LONG WINAPI PCSC_SCardSetCardTypeProviderNameA(SCARDCONTEXT hContext,
LPCSTR szCardName, DWORD dwProviderId, LPCSTR szProvider)
{
return 0;
}
WINSCARDAPI LONG WINAPI PCSC_SCardSetCardTypeProviderNameW(SCARDCONTEXT hContext,
LPCWSTR szCardName, DWORD dwProviderId, LPCWSTR szProvider)
{
return 0;
}
WINSCARDAPI LONG WINAPI PCSC_SCardForgetCardTypeA(SCARDCONTEXT hContext, LPCSTR szCardName)
{
return 0;
}
WINSCARDAPI LONG WINAPI PCSC_SCardForgetCardTypeW(SCARDCONTEXT hContext, LPCWSTR szCardName)
{
return 0;
}
WINSCARDAPI LONG WINAPI PCSC_SCardFreeMemory_Internal(SCARDCONTEXT hContext, LPCVOID pvMem)
{
LONG status = SCARD_S_SUCCESS;
if (PCSC_RemoveMemoryBlock(hContext, (void*) pvMem))
{
free((void*) pvMem);
status = SCARD_S_SUCCESS;
}
else
{
if (g_PCSC.pfnSCardFreeMemory)
{
status = (LONG) g_PCSC.pfnSCardFreeMemory(hContext, pvMem);
status = PCSC_MapErrorCodeToWinSCard(status);
}
}
return status;
}
WINSCARDAPI LONG WINAPI PCSC_SCardFreeMemory(SCARDCONTEXT hContext, LPCVOID pvMem)
{
LONG status = SCARD_S_SUCCESS;
if (hContext)
{
if (!PCSC_LockCardContext(hContext))
return SCARD_E_INVALID_HANDLE;
}
status = PCSC_SCardFreeMemory_Internal(hContext, pvMem);
if (hContext)
{
if (!PCSC_UnlockCardContext(hContext))
return SCARD_E_INVALID_HANDLE;
}
return status;
}
WINSCARDAPI HANDLE WINAPI PCSC_SCardAccessStartedEvent(void)
{
LONG status = 0;
SCARDCONTEXT hContext = 0;
status = PCSC_SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
if (status != SCARD_S_SUCCESS)
return NULL;
status = PCSC_SCardReleaseContext(hContext);
if (status != SCARD_S_SUCCESS)
return NULL;
if (!g_StartedEvent)
{
g_StartedEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
SetEvent(g_StartedEvent);
}
g_StartedEventRefCount++;
return g_StartedEvent;
}
WINSCARDAPI void WINAPI PCSC_SCardReleaseStartedEvent(void)
{
g_StartedEventRefCount--;
if (g_StartedEventRefCount == 0)
{
if (g_StartedEvent)
{
CloseHandle(g_StartedEvent);
g_StartedEvent = NULL;
}
}
}
WINSCARDAPI LONG WINAPI PCSC_SCardLocateCardsA(SCARDCONTEXT hContext,
LPCSTR mszCards, LPSCARD_READERSTATEA rgReaderStates, DWORD cReaders)
{
return 0;
}
WINSCARDAPI LONG WINAPI PCSC_SCardLocateCardsW(SCARDCONTEXT hContext,
LPCWSTR mszCards, LPSCARD_READERSTATEW rgReaderStates, DWORD cReaders)
{
return 0;
}
WINSCARDAPI LONG WINAPI PCSC_SCardLocateCardsByATRA(SCARDCONTEXT hContext,
LPSCARD_ATRMASK rgAtrMasks, DWORD cAtrs, LPSCARD_READERSTATEA rgReaderStates, DWORD cReaders)
{
return 0;
}
WINSCARDAPI LONG WINAPI PCSC_SCardLocateCardsByATRW(SCARDCONTEXT hContext,
LPSCARD_ATRMASK rgAtrMasks, DWORD cAtrs, LPSCARD_READERSTATEW rgReaderStates, DWORD cReaders)
{
return 0;
}
WINSCARDAPI LONG WINAPI PCSC_SCardGetStatusChange_Internal(SCARDCONTEXT hContext,
DWORD dwTimeout, LPSCARD_READERSTATEA rgReaderStates, DWORD cReaders)
{
int i, j;
int* map;
DWORD dwEventState;
PCSC_DWORD cMappedReaders;
BOOL stateChanged = FALSE;
PCSC_SCARD_READERSTATE* states;
LONG status = SCARD_S_SUCCESS;
PCSC_DWORD pcsc_dwTimeout = (PCSC_DWORD) dwTimeout;
PCSC_DWORD pcsc_cReaders = (PCSC_DWORD) cReaders;
if (!g_PCSC.pfnSCardGetStatusChange)
return SCARD_E_NO_SERVICE;
if (!cReaders)
return SCARD_S_SUCCESS;
/**
* 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.
*
* To work around this apparent lack of "\\\\?PnP?\\Notification" support,
* we have to filter rgReaderStates to exclude the special PnP reader name.
*/
map = (int*) calloc(pcsc_cReaders, sizeof(int));
if (!map)
return SCARD_E_NO_MEMORY;
states = (PCSC_SCARD_READERSTATE*) calloc(pcsc_cReaders, sizeof(PCSC_SCARD_READERSTATE));
if (!states)
return SCARD_E_NO_MEMORY;
for (i = j = 0; i < pcsc_cReaders; i++)
{
if (!g_PnP_Notification)
{
if (strcmp(rgReaderStates[i].szReader, SMARTCARD_PNP_NOTIFICATION_A) == 0)
{
map[i] = -1; /* unmapped */
continue;
}
}
map[i] = j;
states[j].szReader = PCSC_GetReaderNameFromAlias((char*) rgReaderStates[i].szReader);
2014-04-09 22:27:44 +04:00
if (!states[j].szReader)
states[j].szReader = rgReaderStates[i].szReader;
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++;
}
cMappedReaders = j;
/**
* pcsc-lite interprets dwTimeout value 0 as INFINITE, use value 1 as a workaround
*/
if (cMappedReaders > 0)
{
status = (LONG) g_PCSC.pfnSCardGetStatusChange(hContext,
pcsc_dwTimeout ? pcsc_dwTimeout : 1,
states, cMappedReaders);
status = PCSC_MapErrorCodeToWinSCard(status);
}
else
{
status = SCARD_S_SUCCESS;
}
2014-04-09 22:27:44 +04:00
for (i = 0; i < pcsc_cReaders; i++)
{
if (map[i] < 0)
continue; /* unmapped */
j = map[i];
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;
2014-04-09 22:27:44 +04:00
}
if (rgReaderStates[i].dwCurrentState & SCARD_STATE_IGNORE)
rgReaderStates[i].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);
free(map);
return status;
}
WINSCARDAPI LONG WINAPI PCSC_SCardGetStatusChangeA(SCARDCONTEXT hContext,
DWORD dwTimeout, LPSCARD_READERSTATEA rgReaderStates, DWORD cReaders)
{
LONG status = SCARD_S_SUCCESS;
if (!PCSC_LockCardContext(hContext))
return SCARD_E_INVALID_HANDLE;
status = PCSC_SCardGetStatusChange_Internal(hContext, dwTimeout, rgReaderStates, cReaders);
if (!PCSC_UnlockCardContext(hContext))
return SCARD_E_INVALID_HANDLE;
return status;
}
WINSCARDAPI LONG WINAPI PCSC_SCardGetStatusChangeW(SCARDCONTEXT hContext,
DWORD dwTimeout, LPSCARD_READERSTATEW rgReaderStates, DWORD cReaders)
{
DWORD index;
LPSCARD_READERSTATEA states;
LONG status = SCARD_S_SUCCESS;
if (!g_PCSC.pfnSCardGetStatusChange)
return SCARD_E_NO_SERVICE;
2014-04-09 22:27:44 +04:00
if (!PCSC_LockCardContext(hContext))
return SCARD_E_INVALID_HANDLE;
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);
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;
}
WINSCARDAPI LONG WINAPI PCSC_SCardCancel(SCARDCONTEXT hContext)
{
LONG status = SCARD_S_SUCCESS;
if (!g_PCSC.pfnSCardCancel)
return SCARD_E_NO_SERVICE;
status = (LONG) g_PCSC.pfnSCardCancel(hContext);
status = PCSC_MapErrorCodeToWinSCard(status);
return status;
}
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;
SCARDCONTEXT hPrivateContext = 0;
PCSC_DWORD pcsc_dwShareMode = (PCSC_DWORD) dwShareMode;
PCSC_DWORD pcsc_dwPreferredProtocols = 0;
PCSC_DWORD pcsc_dwActiveProtocol = 0;
if (!g_PCSC.pfnSCardConnect)
return SCARD_E_NO_SERVICE;
status = PCSC_SCardEstablishContext_Internal(SCARD_SCOPE_SYSTEM, NULL, NULL, &hPrivateContext);
if (status != SCARD_S_SUCCESS)
return status;
szReaderPCSC = PCSC_GetReaderNameFromAlias((char*) szReader);
if (!szReaderPCSC)
szReaderPCSC = (char*) szReader;
pcsc_dwPreferredProtocols = (PCSC_DWORD) PCSC_ConvertProtocolsFromWinSCard(dwPreferredProtocols);
status = (LONG) g_PCSC.pfnSCardConnect(hPrivateContext, szReaderPCSC,
pcsc_dwShareMode, pcsc_dwPreferredProtocols, phCard, &pcsc_dwActiveProtocol);
status = PCSC_MapErrorCodeToWinSCard(status);
if (status == SCARD_S_SUCCESS)
{
PCSC_ConnectCardHandle(hContext, hPrivateContext, *phCard);
*pdwActiveProtocol = PCSC_ConvertProtocolsToWinSCard((DWORD) pcsc_dwActiveProtocol);
}
else
{
PCSC_SCardReleaseContext(hPrivateContext);
}
return status;
}
WINSCARDAPI LONG WINAPI PCSC_SCardConnectA(SCARDCONTEXT hContext,
LPCSTR szReader, DWORD dwShareMode, DWORD dwPreferredProtocols,
LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol)
{
LONG status = SCARD_S_SUCCESS;
if (!PCSC_LockCardContext(hContext))
return SCARD_E_INVALID_HANDLE;
status = PCSC_SCardConnect_Internal(hContext, szReader, dwShareMode,
dwPreferredProtocols, phCard, pdwActiveProtocol);
if (!PCSC_UnlockCardContext(hContext))
return SCARD_E_INVALID_HANDLE;
return status;
}
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;
if (!PCSC_LockCardContext(hContext))
return SCARD_E_INVALID_HANDLE;
if (szReader)
ConvertFromUnicode(CP_UTF8, 0, szReader, -1, &szReaderA, 0, NULL, NULL);
status = PCSC_SCardConnect_Internal(hContext, szReaderA, dwShareMode,
dwPreferredProtocols, phCard, pdwActiveProtocol);
free(szReaderA);
if (!PCSC_UnlockCardContext(hContext))
return SCARD_E_INVALID_HANDLE;
return status;
}
WINSCARDAPI LONG WINAPI PCSC_SCardReconnect(SCARDHANDLE hCard,
DWORD dwShareMode, DWORD dwPreferredProtocols, DWORD dwInitialization, LPDWORD pdwActiveProtocol)
{
LONG status = SCARD_S_SUCCESS;
PCSC_DWORD pcsc_dwShareMode = (PCSC_DWORD) dwShareMode;
PCSC_DWORD pcsc_dwPreferredProtocols = 0;
PCSC_DWORD pcsc_dwInitialization = (PCSC_DWORD) dwInitialization;
PCSC_DWORD pcsc_dwActiveProtocol = 0;
if (!g_PCSC.pfnSCardReconnect)
return SCARD_E_NO_SERVICE;
pcsc_dwPreferredProtocols = (PCSC_DWORD) PCSC_ConvertProtocolsFromWinSCard(dwPreferredProtocols);
status = (LONG) g_PCSC.pfnSCardReconnect(hCard, pcsc_dwShareMode,
pcsc_dwPreferredProtocols, pcsc_dwInitialization, &pcsc_dwActiveProtocol);
status = PCSC_MapErrorCodeToWinSCard(status);
*pdwActiveProtocol = PCSC_ConvertProtocolsToWinSCard((DWORD) pcsc_dwActiveProtocol);
return status;
}
WINSCARDAPI LONG WINAPI PCSC_SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
{
LONG status = SCARD_S_SUCCESS;
PCSC_DWORD pcsc_dwDisposition = (PCSC_DWORD) dwDisposition;
if (!g_PCSC.pfnSCardDisconnect)
return SCARD_E_NO_SERVICE;
status = (LONG) g_PCSC.pfnSCardDisconnect(hCard, pcsc_dwDisposition);
status = PCSC_MapErrorCodeToWinSCard(status);
if (status == SCARD_S_SUCCESS)
{
PCSC_DisconnectCardHandle(hCard);
}
return status;
}
WINSCARDAPI LONG WINAPI PCSC_SCardBeginTransaction(SCARDHANDLE hCard)
{
LONG status = SCARD_S_SUCCESS;
if (!g_PCSC.pfnSCardBeginTransaction)
return SCARD_E_NO_SERVICE;
status = (LONG) g_PCSC.pfnSCardBeginTransaction(hCard);
status = PCSC_MapErrorCodeToWinSCard(status);
return status;
}
WINSCARDAPI LONG WINAPI PCSC_SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
{
LONG status = SCARD_S_SUCCESS;
PCSC_DWORD pcsc_dwDisposition = (PCSC_DWORD) dwDisposition;
if (!g_PCSC.pfnSCardEndTransaction)
return SCARD_E_NO_SERVICE;
status = (LONG) g_PCSC.pfnSCardEndTransaction(hCard, pcsc_dwDisposition);
status = PCSC_MapErrorCodeToWinSCard(status);
return status;
}
WINSCARDAPI LONG WINAPI PCSC_SCardCancelTransaction(SCARDHANDLE hCard)
{
return 0;
}
WINSCARDAPI LONG WINAPI PCSC_SCardState(SCARDHANDLE hCard,
LPDWORD pdwState, LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
{
PCSC_DWORD cchReaderLen;
SCARDCONTEXT hContext = 0;
LPSTR mszReaderNames = NULL;
2014-04-07 09:19:58 +04:00
LONG status = SCARD_S_SUCCESS;
PCSC_DWORD pcsc_dwState = 0;
PCSC_DWORD pcsc_dwProtocol = 0;
PCSC_DWORD pcsc_cbAtrLen = (PCSC_DWORD) *pcbAtrLen;
2014-04-07 09:19:58 +04:00
if (!g_PCSC.pfnSCardStatus)
return SCARD_E_NO_SERVICE;
2014-04-07 09:19:58 +04:00
hContext = PCSC_GetCardContextFromHandle(hCard);
2014-04-07 09:19:58 +04:00
if (!hContext)
return SCARD_E_INVALID_VALUE;
cchReaderLen = SCARD_AUTOALLOCATE;
status = (LONG) g_PCSC.pfnSCardStatus(hCard, (LPSTR) &mszReaderNames, &cchReaderLen,
&pcsc_dwState, &pcsc_dwProtocol, pbAtr, &pcsc_cbAtrLen);
status = PCSC_MapErrorCodeToWinSCard(status);
if (mszReaderNames)
PCSC_SCardFreeMemory_Internal(hContext, mszReaderNames);
*pdwState = (DWORD) pcsc_dwState;
*pdwProtocol = PCSC_ConvertProtocolsToWinSCard((DWORD) pcsc_dwProtocol);
*pcbAtrLen = (DWORD) pcsc_cbAtrLen;
2014-04-07 09:19:58 +04:00
return status;
}
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 pcbAtrLenAlloc = FALSE;
BOOL pcchReaderLenAlloc = FALSE;
LPBYTE* pPbAtr = (LPBYTE*) pbAtr;
LPSTR* pMszReaderNames = (LPSTR*) mszReaderNames;
LONG status = SCARD_S_SUCCESS;
PCSC_DWORD pcsc_cchReaderLen = 0;
PCSC_DWORD pcsc_dwState = 0;
PCSC_DWORD pcsc_dwProtocol = 0;
PCSC_DWORD pcsc_cbAtrLen = 0;
if (!g_PCSC.pfnSCardStatus)
return SCARD_E_NO_SERVICE;
hContext = PCSC_GetCardContextFromHandle(hCard);
if (!hContext || !pcchReaderLen || !pdwState || !pdwProtocol || !pcbAtrLen)
return SCARD_E_INVALID_VALUE;
if (*pcchReaderLen == SCARD_AUTOALLOCATE)
pcchReaderLenAlloc = TRUE;
pcsc_cchReaderLen = pcchReaderLenAlloc ? PCSC_SCARD_AUTOALLOCATE : (PCSC_DWORD) *pcchReaderLen;
if (*pcbAtrLen == SCARD_AUTOALLOCATE)
pcbAtrLenAlloc = TRUE;
pcsc_cbAtrLen = pcbAtrLenAlloc ? PCSC_SCARD_AUTOALLOCATE : (PCSC_DWORD) *pcbAtrLen;
if ((pcchReaderLenAlloc || pcbAtrLenAlloc) && !g_SCardAutoAllocate)
{
if (pcchReaderLenAlloc)
pcsc_cchReaderLen = 0;
if (pcbAtrLenAlloc)
pcsc_cbAtrLen = 0;
status = (LONG) g_PCSC.pfnSCardStatus(hCard,
(pcchReaderLenAlloc) ? NULL : mszReaderNames, &pcsc_cchReaderLen,
&pcsc_dwState, &pcsc_dwProtocol,
(pcbAtrLenAlloc) ? NULL : pbAtr, &pcsc_cbAtrLen);
if (status == SCARD_S_SUCCESS)
{
if (pcchReaderLenAlloc)
{
*pMszReaderNames = (LPSTR) calloc(1, pcsc_cchReaderLen);
if (!*pMszReaderNames)
return SCARD_E_NO_MEMORY;
}
if (pcbAtrLenAlloc)
{
*pPbAtr = (BYTE*) calloc(1, pcsc_cbAtrLen);
if (!*pPbAtr)
return SCARD_E_NO_MEMORY;
}
status = (LONG) g_PCSC.pfnSCardStatus(hCard,
*pMszReaderNames, &pcsc_cchReaderLen,
&pcsc_dwState, &pcsc_dwProtocol,
pbAtr, &pcsc_cbAtrLen);
if (status != SCARD_S_SUCCESS)
{
if (pcchReaderLenAlloc)
{
free(*pMszReaderNames);
*pMszReaderNames = NULL;
}
if (pcbAtrLenAlloc)
{
free(*pPbAtr);
*pPbAtr = NULL;
}
}
else
{
if (pcchReaderLenAlloc)
PCSC_AddMemoryBlock(hContext, *pMszReaderNames);
if (pcbAtrLenAlloc)
PCSC_AddMemoryBlock(hContext, *pPbAtr);
}
}
}
else
{
status = (LONG) g_PCSC.pfnSCardStatus(hCard, mszReaderNames, &pcsc_cchReaderLen,
&pcsc_dwState, &pcsc_dwProtocol, pbAtr, &pcsc_cbAtrLen);
}
status = PCSC_MapErrorCodeToWinSCard(status);
*pcchReaderLen = (DWORD) pcsc_cchReaderLen;
mszReaderNamesWinSCard = PCSC_ConvertReaderNamesToWinSCard(*pMszReaderNames, pcchReaderLen);
if (mszReaderNamesWinSCard)
{
PCSC_SCardFreeMemory_Internal(hContext, *pMszReaderNames);
*pMszReaderNames = mszReaderNamesWinSCard;
PCSC_AddMemoryBlock(hContext, *pMszReaderNames);
}
pcsc_dwState &= 0xFFFF;
*pdwState = PCSC_ConvertCardStateToWinSCard((DWORD) pcsc_dwState, status);
*pdwProtocol = PCSC_ConvertProtocolsToWinSCard((DWORD) pcsc_dwProtocol);
*pcbAtrLen = (DWORD) pcsc_cbAtrLen;
return status;
}
WINSCARDAPI LONG WINAPI PCSC_SCardStatusA(SCARDHANDLE hCard,
LPSTR mszReaderNames, LPDWORD pcchReaderLen, LPDWORD pdwState,
LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
{
LONG status = SCARD_S_SUCCESS;
status = PCSC_SCardStatus_Internal(hCard, mszReaderNames, pcchReaderLen, pdwState, pdwProtocol, pbAtr, pcbAtrLen);
return status;
}
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)
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)
{
*pcchReaderLen = ConvertToUnicode(CP_UTF8, 0, mszReaderNamesA, *pcchReaderLen, (WCHAR**) mszReaderNames, 0);
PCSC_AddMemoryBlock(hContext, mszReaderNames);
PCSC_SCardFreeMemory_Internal(hContext, mszReaderNamesA);
}
return status;
}
WINSCARDAPI LONG WINAPI PCSC_SCardTransmit(SCARDHANDLE hCard,
LPCSCARD_IO_REQUEST pioSendPci, LPCBYTE pbSendBuffer, DWORD cbSendLength,
LPSCARD_IO_REQUEST pioRecvPci, LPBYTE pbRecvBuffer, LPDWORD pcbRecvLength)
{
LONG status = SCARD_S_SUCCESS;
PCSC_DWORD cbExtraBytes = 0;
BYTE* pbExtraBytes = NULL;
BYTE* pcsc_pbExtraBytes = NULL;
PCSC_SCARD_IO_REQUEST* pcsc_pioSendPci = NULL;
PCSC_SCARD_IO_REQUEST* pcsc_pioRecvPci = NULL;
PCSC_DWORD pcsc_cbSendLength = (PCSC_DWORD) cbSendLength;
PCSC_DWORD pcsc_cbRecvLength = 0;
if (!g_PCSC.pfnSCardTransmit)
return SCARD_E_NO_SERVICE;
if (!pcbRecvLength)
return SCARD_E_INVALID_PARAMETER;
if (*pcbRecvLength == SCARD_AUTOALLOCATE)
return SCARD_E_INVALID_PARAMETER;
pcsc_cbRecvLength = (PCSC_DWORD) *pcbRecvLength;
if (!pioSendPci)
{
PCSC_DWORD dwState = 0;
PCSC_DWORD cbAtrLen = 0;
PCSC_DWORD dwProtocol = 0;
PCSC_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 = (LONG) g_PCSC.pfnSCardStatus(hCard, NULL, &cchReaderLen, &dwState, &dwProtocol, NULL, &cbAtrLen);
if (status == SCARD_S_SUCCESS)
{
if (dwProtocol == SCARD_PROTOCOL_T0)
pcsc_pioSendPci = (PCSC_SCARD_IO_REQUEST*) PCSC_SCARD_PCI_T0;
else if (dwProtocol == SCARD_PROTOCOL_T1)
pcsc_pioSendPci = (PCSC_SCARD_IO_REQUEST*) PCSC_SCARD_PCI_T1;
else if (dwProtocol == PCSC_SCARD_PROTOCOL_RAW)
pcsc_pioSendPci = (PCSC_SCARD_IO_REQUEST*) PCSC_SCARD_PCI_RAW;
}
}
else
{
cbExtraBytes = pioSendPci->cbPciLength - sizeof(SCARD_IO_REQUEST);
pcsc_pioSendPci = (PCSC_SCARD_IO_REQUEST*) malloc(sizeof(PCSC_SCARD_IO_REQUEST) + cbExtraBytes);
if (!pcsc_pioSendPci)
return SCARD_E_NO_MEMORY;
pcsc_pioSendPci->dwProtocol = (PCSC_DWORD) pioSendPci->dwProtocol;
pcsc_pioSendPci->cbPciLength = sizeof(PCSC_SCARD_IO_REQUEST) + cbExtraBytes;
pbExtraBytes = &((BYTE*) pioSendPci)[sizeof(SCARD_IO_REQUEST)];
pcsc_pbExtraBytes = &((BYTE*) pcsc_pioSendPci)[sizeof(PCSC_SCARD_IO_REQUEST)];
CopyMemory(pcsc_pbExtraBytes, pbExtraBytes, cbExtraBytes);
}
if (pioRecvPci)
{
cbExtraBytes = pioRecvPci->cbPciLength - sizeof(SCARD_IO_REQUEST);
pcsc_pioRecvPci = (PCSC_SCARD_IO_REQUEST*) malloc(sizeof(PCSC_SCARD_IO_REQUEST) + cbExtraBytes);
if (!pcsc_pioRecvPci)
return SCARD_E_NO_MEMORY;
pcsc_pioRecvPci->dwProtocol = (PCSC_DWORD) pioRecvPci->dwProtocol;
pcsc_pioRecvPci->cbPciLength = sizeof(PCSC_SCARD_IO_REQUEST) + cbExtraBytes;
pbExtraBytes = &((BYTE*) pioRecvPci)[sizeof(SCARD_IO_REQUEST)];
pcsc_pbExtraBytes = &((BYTE*) pcsc_pioRecvPci)[sizeof(PCSC_SCARD_IO_REQUEST)];
CopyMemory(pcsc_pbExtraBytes, pbExtraBytes, cbExtraBytes);
}
status = (LONG) g_PCSC.pfnSCardTransmit(hCard, pcsc_pioSendPci, pbSendBuffer,
pcsc_cbSendLength, pcsc_pioRecvPci, pbRecvBuffer, &pcsc_cbRecvLength);
status = PCSC_MapErrorCodeToWinSCard(status);
*pcbRecvLength = (DWORD) pcsc_cbRecvLength;
if (pioSendPci)
free(pcsc_pioSendPci); /* pcsc_pioSendPci is dynamically allocated only when pioSendPci is non null */
if (pioRecvPci)
free(pcsc_pioRecvPci); /* pcsc_pioRecvPci is dynamically allocated only when pioRecvPci is non null */
return status;
}
WINSCARDAPI LONG WINAPI PCSC_SCardGetTransmitCount(SCARDHANDLE hCard, LPDWORD pcTransmitCount)
{
return 0;
}
WINSCARDAPI LONG WINAPI PCSC_SCardControl(SCARDHANDLE hCard,
DWORD dwControlCode, LPCVOID lpInBuffer, DWORD cbInBufferSize,
LPVOID lpOutBuffer, DWORD cbOutBufferSize, LPDWORD lpBytesReturned)
{
DWORD IoCtlMethod = 0;
DWORD IoCtlFunction = 0;
DWORD IoCtlAccess = 0;
DWORD IoCtlDeviceType = 0;
BOOL getFeatureRequest = FALSE;
LONG status = SCARD_S_SUCCESS;
PCSC_DWORD pcsc_dwControlCode = 0;
PCSC_DWORD pcsc_cbInBufferSize = (PCSC_DWORD) cbInBufferSize;
PCSC_DWORD pcsc_cbOutBufferSize = (PCSC_DWORD) cbOutBufferSize;
PCSC_DWORD pcsc_BytesReturned = 0;
if (!g_PCSC.pfnSCardControl)
return SCARD_E_NO_SERVICE;
IoCtlMethod = METHOD_FROM_CTL_CODE(dwControlCode);
IoCtlFunction = FUNCTION_FROM_CTL_CODE(dwControlCode);
IoCtlAccess = ACCESS_FROM_CTL_CODE(dwControlCode);
IoCtlDeviceType = DEVICE_TYPE_FROM_CTL_CODE(dwControlCode);
if (dwControlCode == PCSC_CM_IOCTL_GET_FEATURE_REQUEST)
getFeatureRequest = TRUE;
if (IoCtlDeviceType == FILE_DEVICE_SMARTCARD)
dwControlCode = PCSC_SCARD_CTL_CODE(IoCtlFunction);
pcsc_dwControlCode = (PCSC_DWORD) dwControlCode;
status = (LONG) g_PCSC.pfnSCardControl(hCard,
pcsc_dwControlCode, lpInBuffer, pcsc_cbInBufferSize,
lpOutBuffer, pcsc_cbOutBufferSize, &pcsc_BytesReturned);
status = PCSC_MapErrorCodeToWinSCard(status);
*lpBytesReturned = (DWORD) pcsc_BytesReturned;
if (getFeatureRequest)
{
UINT32 ioCtlValue;
PCSC_TLV_STRUCTURE* tlv = (PCSC_TLV_STRUCTURE*) lpOutBuffer;
void* lpOutBufferEnd = (void*) &((BYTE*) lpOutBuffer)[*lpBytesReturned];
for ( ; ((void*) tlv) < lpOutBufferEnd; tlv++)
{
ioCtlValue = _byteswap_ulong(tlv->value);
ioCtlValue -= 0x42000000; /* inverse of PCSC_SCARD_CTL_CODE() */
IoCtlMethod = METHOD_FROM_CTL_CODE(ioCtlValue);
IoCtlFunction = FUNCTION_FROM_CTL_CODE(ioCtlValue);
IoCtlAccess = ACCESS_FROM_CTL_CODE(ioCtlValue);
IoCtlDeviceType = DEVICE_TYPE_FROM_CTL_CODE(ioCtlValue);
ioCtlValue = SCARD_CTL_CODE(IoCtlFunction);
tlv->value = _byteswap_ulong(ioCtlValue);
}
}
return status;
}
WINSCARDAPI LONG WINAPI PCSC_SCardGetAttrib_Internal(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr, LPDWORD pcbAttrLen)
{
SCARDCONTEXT hContext = 0;
BOOL pcbAttrLenAlloc = FALSE;
LPBYTE* pPbAttr = (LPBYTE*) pbAttr;
LONG status = SCARD_S_SUCCESS;
PCSC_DWORD pcsc_dwAttrId = (PCSC_DWORD) dwAttrId;
PCSC_DWORD pcsc_cbAttrLen = 0;
if (!g_PCSC.pfnSCardGetAttrib)
return SCARD_E_NO_SERVICE;
hContext = PCSC_GetCardContextFromHandle(hCard);
if (!hContext)
return SCARD_E_INVALID_HANDLE;
if (!pbAttr || !pcbAttrLen)
return SCARD_E_INVALID_PARAMETER;
if (*pcbAttrLen == SCARD_AUTOALLOCATE)
pcbAttrLenAlloc = TRUE;
pcsc_cbAttrLen = pcbAttrLenAlloc ? PCSC_SCARD_AUTOALLOCATE : (PCSC_DWORD) *pcbAttrLen;
if (pcbAttrLenAlloc && !g_SCardAutoAllocate)
{
pcsc_cbAttrLen = 0;
status = (LONG) g_PCSC.pfnSCardGetAttrib(hCard, pcsc_dwAttrId, NULL, &pcsc_cbAttrLen);
if (status == SCARD_S_SUCCESS)
{
*pPbAttr = (BYTE*) calloc(1, pcsc_cbAttrLen);
if (!*pPbAttr)
return SCARD_E_NO_MEMORY;
status = (LONG) g_PCSC.pfnSCardGetAttrib(hCard, pcsc_dwAttrId, *pPbAttr, &pcsc_cbAttrLen);
if (status != SCARD_S_SUCCESS)
free(*pPbAttr);
else
PCSC_AddMemoryBlock(hContext, *pPbAttr);
}
}
else
{
status = (LONG) g_PCSC.pfnSCardGetAttrib(hCard, pcsc_dwAttrId, pbAttr, &pcsc_cbAttrLen);
}
status = PCSC_MapErrorCodeToWinSCard(status);
*pcbAttrLen = (DWORD) pcsc_cbAttrLen;
return status;
}
WINSCARDAPI LONG WINAPI PCSC_SCardGetAttrib_FriendlyName(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr, LPDWORD pcbAttrLen)
{
int length = 0;
char* namePCSC;
char* nameWinSCard;
DWORD cbAttrLen = 0;
char* pbAttrA = NULL;
WCHAR* pbAttrW = NULL;
SCARDCONTEXT hContext;
char* friendlyNameA = NULL;
WCHAR* friendlyNameW = NULL;
LONG status = SCARD_S_SUCCESS;
LPBYTE* pPbAttr = (LPBYTE*) pbAttr;
hContext = PCSC_GetCardContextFromHandle(hCard);
if (!hContext)
return SCARD_E_INVALID_HANDLE;
cbAttrLen = *pcbAttrLen;
*pcbAttrLen = SCARD_AUTOALLOCATE;
status = PCSC_SCardGetAttrib_Internal(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME_A,
(LPBYTE) &pbAttrA, pcbAttrLen);
if (status != SCARD_S_SUCCESS)
{
pbAttrA = NULL;
*pcbAttrLen = SCARD_AUTOALLOCATE;
status = PCSC_SCardGetAttrib_Internal(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME_W,
(LPBYTE) &pbAttrW, pcbAttrLen);
if (status != SCARD_S_SUCCESS)
return status;
length = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) pbAttrW,
*pcbAttrLen, (char**) &pbAttrA, 0, NULL, NULL);
namePCSC = pbAttrA;
PCSC_SCardFreeMemory_Internal(hContext, pbAttrW);
}
else
{
namePCSC = _strdup(pbAttrA);
if (!namePCSC)
return SCARD_E_NO_MEMORY;
PCSC_SCardFreeMemory_Internal(hContext, pbAttrA);
}
length = strlen(namePCSC);
nameWinSCard = PCSC_GetReaderAliasFromName(namePCSC);
if (nameWinSCard)
{
length = strlen(nameWinSCard);
friendlyNameA = _strdup(nameWinSCard);
if (!friendlyNameA)
return SCARD_E_NO_MEMORY;
}
else
{
friendlyNameA = namePCSC;
}
if (dwAttrId == SCARD_ATTR_DEVICE_FRIENDLY_NAME_W)
{
length = ConvertToUnicode(CP_UTF8, 0, (char*) friendlyNameA, -1, &friendlyNameW, 0);
free(friendlyNameA);
if (!friendlyNameW)
return SCARD_E_NO_MEMORY;
if (cbAttrLen == SCARD_AUTOALLOCATE)
{
*pPbAttr = (BYTE*) friendlyNameW;
*pcbAttrLen = length * 2;
PCSC_AddMemoryBlock(hContext, *pPbAttr);
}
else
{
if (((length + 1) * 2) > cbAttrLen)
{
free(friendlyNameW);
return SCARD_E_INSUFFICIENT_BUFFER;
}
else
{
CopyMemory(pbAttr, (BYTE*) friendlyNameW, ((length + 1) * 2));
*pcbAttrLen = length * 2;
free(friendlyNameW);
}
}
}
else
{
if (cbAttrLen == SCARD_AUTOALLOCATE)
{
*pPbAttr = (BYTE*) friendlyNameA;
*pcbAttrLen = length;
PCSC_AddMemoryBlock(hContext, *pPbAttr);
}
else
{
if ((length + 1) > cbAttrLen)
{
free(friendlyNameA);
return SCARD_E_INSUFFICIENT_BUFFER;
}
else
{
CopyMemory(pbAttr, (BYTE*) friendlyNameA, length + 1);
*pcbAttrLen = length;
free(friendlyNameA);
}
}
}
return status;
}
WINSCARDAPI LONG WINAPI PCSC_SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr, LPDWORD pcbAttrLen)
{
DWORD cbAttrLen;
SCARDCONTEXT hContext;
BOOL pcbAttrLenAlloc = FALSE;
LONG status = SCARD_S_SUCCESS;
LPBYTE* pPbAttr = (LPBYTE*) pbAttr;
cbAttrLen = *pcbAttrLen;
if (*pcbAttrLen == SCARD_AUTOALLOCATE)
pcbAttrLenAlloc = TRUE;
/**
* pcsc-lite returns SCARD_E_INSUFFICIENT_BUFFER if the given
* buffer size is larger than PCSC_MAX_BUFFER_SIZE (264)
*/
2014-04-16 01:51:39 +04:00
if (*pcbAttrLen > PCSC_MAX_BUFFER_SIZE)
*pcbAttrLen = PCSC_MAX_BUFFER_SIZE;
hContext = PCSC_GetCardContextFromHandle(hCard);
if (!hContext)
return SCARD_E_INVALID_HANDLE;
if ((dwAttrId == SCARD_ATTR_DEVICE_FRIENDLY_NAME_A) || (dwAttrId == SCARD_ATTR_DEVICE_FRIENDLY_NAME_W))
{
status = PCSC_SCardGetAttrib_FriendlyName(hCard, dwAttrId, pbAttr, pcbAttrLen);
return status;
}
status = PCSC_SCardGetAttrib_Internal(hCard, dwAttrId, pbAttr, pcbAttrLen);
if (status == SCARD_S_SUCCESS)
{
if (dwAttrId == SCARD_ATTR_VENDOR_NAME)
{
/**
* pcsc-lite adds a null terminator to the vendor name,
* while WinSCard doesn't. Strip the null terminator.
*/
if (pcbAttrLenAlloc)
*pcbAttrLen = strlen((char*) *pPbAttr);
else
*pcbAttrLen = strlen((char*) pbAttr);
}
}
2014-04-16 01:51:39 +04:00
else
{
if (dwAttrId == SCARD_ATTR_CURRENT_PROTOCOL_TYPE)
{
PCSC_DWORD dwState = 0;
PCSC_DWORD cbAtrLen = 0;
PCSC_DWORD dwProtocol = 0;
PCSC_DWORD cchReaderLen = 0;
status = (LONG) g_PCSC.pfnSCardStatus(hCard, NULL, &cchReaderLen, &dwState, &dwProtocol, NULL, &cbAtrLen);
if (status == SCARD_S_SUCCESS)
{
LPDWORD pdwProtocol = (LPDWORD) pbAttr;
if (cbAttrLen < sizeof(DWORD))
return SCARD_E_INSUFFICIENT_BUFFER;
*pdwProtocol = PCSC_ConvertProtocolsToWinSCard(dwProtocol);
*pcbAttrLen = sizeof(DWORD);
}
}
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;
}
WINSCARDAPI LONG WINAPI PCSC_SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr, DWORD cbAttrLen)
{
LONG status = SCARD_S_SUCCESS;
PCSC_DWORD pcsc_dwAttrId = (PCSC_DWORD) dwAttrId;
PCSC_DWORD pcsc_cbAttrLen = (PCSC_DWORD) cbAttrLen;
if (!g_PCSC.pfnSCardSetAttrib)
return SCARD_E_NO_SERVICE;
status = (LONG) g_PCSC.pfnSCardSetAttrib(hCard, pcsc_dwAttrId, pbAttr, pcsc_cbAttrLen);
status = PCSC_MapErrorCodeToWinSCard(status);
return status;
}
WINSCARDAPI LONG WINAPI PCSC_SCardUIDlgSelectCardA(LPOPENCARDNAMEA_EX pDlgStruc)
{
return 0;
}
WINSCARDAPI LONG WINAPI PCSC_SCardUIDlgSelectCardW(LPOPENCARDNAMEW_EX pDlgStruc)
{
return 0;
}
WINSCARDAPI LONG WINAPI PCSC_GetOpenCardNameA(LPOPENCARDNAMEA pDlgStruc)
{
return 0;
}
WINSCARDAPI LONG WINAPI PCSC_GetOpenCardNameW(LPOPENCARDNAMEW pDlgStruc)
{
return 0;
}
WINSCARDAPI LONG WINAPI PCSC_SCardDlgExtendedError(void)
{
return 0;
}
WINSCARDAPI LONG WINAPI PCSC_SCardReadCacheA(SCARDCONTEXT hContext,
UUID* CardIdentifier, DWORD FreshnessCounter, LPSTR LookupName, PBYTE Data, DWORD* DataLen)
{
return 0;
}
WINSCARDAPI LONG WINAPI PCSC_SCardReadCacheW(SCARDCONTEXT hContext,
UUID* CardIdentifier, DWORD FreshnessCounter, LPWSTR LookupName, PBYTE Data, DWORD* DataLen)
{
return 0;
}
WINSCARDAPI LONG WINAPI PCSC_SCardWriteCacheA(SCARDCONTEXT hContext,
UUID* CardIdentifier, DWORD FreshnessCounter, LPSTR LookupName, PBYTE Data, DWORD DataLen)
{
return 0;
}
WINSCARDAPI LONG WINAPI PCSC_SCardWriteCacheW(SCARDCONTEXT hContext,
UUID* CardIdentifier, DWORD FreshnessCounter, LPWSTR LookupName, PBYTE Data, DWORD DataLen)
{
return 0;
}
WINSCARDAPI LONG WINAPI PCSC_SCardGetReaderIconA(SCARDCONTEXT hContext,
LPCSTR szReaderName, LPBYTE pbIcon, LPDWORD pcbIcon)
{
return 0;
}
WINSCARDAPI LONG WINAPI PCSC_SCardGetReaderIconW(SCARDCONTEXT hContext,
LPCWSTR szReaderName, LPBYTE pbIcon, LPDWORD pcbIcon)
{
return 0;
}
WINSCARDAPI LONG WINAPI PCSC_SCardGetDeviceTypeIdA(SCARDCONTEXT hContext, LPCSTR szReaderName, LPDWORD pdwDeviceTypeId)
{
return 0;
}
WINSCARDAPI LONG WINAPI PCSC_SCardGetDeviceTypeIdW(SCARDCONTEXT hContext, LPCWSTR szReaderName, LPDWORD pdwDeviceTypeId)
{
return 0;
}
WINSCARDAPI LONG WINAPI PCSC_SCardGetReaderDeviceInstanceIdA(SCARDCONTEXT hContext,
LPCSTR szReaderName, LPSTR szDeviceInstanceId, LPDWORD pcchDeviceInstanceId)
{
return 0;
}
WINSCARDAPI LONG WINAPI PCSC_SCardGetReaderDeviceInstanceIdW(SCARDCONTEXT hContext,
LPCWSTR szReaderName, LPWSTR szDeviceInstanceId, LPDWORD pcchDeviceInstanceId)
{
return 0;
}
WINSCARDAPI LONG WINAPI PCSC_SCardListReadersWithDeviceInstanceIdA(SCARDCONTEXT hContext,
LPCSTR szDeviceInstanceId, LPSTR mszReaders, LPDWORD pcchReaders)
{
return 0;
}
WINSCARDAPI LONG WINAPI PCSC_SCardListReadersWithDeviceInstanceIdW(SCARDCONTEXT hContext,
LPCWSTR szDeviceInstanceId, LPWSTR mszReaders, LPDWORD pcchReaders)
{
return 0;
}
WINSCARDAPI LONG WINAPI PCSC_SCardAudit(SCARDCONTEXT hContext, DWORD dwEvent)
{
return 0;
}
SCardApiFunctionTable PCSC_SCardApiFunctionTable =
{
0, /* dwVersion */
0, /* dwFlags */
PCSC_SCardEstablishContext, /* SCardEstablishContext */
PCSC_SCardReleaseContext, /* SCardReleaseContext */
PCSC_SCardIsValidContext, /* SCardIsValidContext */
PCSC_SCardListReaderGroupsA, /* SCardListReaderGroupsA */
PCSC_SCardListReaderGroupsW, /* SCardListReaderGroupsW */
PCSC_SCardListReadersA, /* SCardListReadersA */
PCSC_SCardListReadersW, /* SCardListReadersW */
PCSC_SCardListCardsA, /* SCardListCardsA */
PCSC_SCardListCardsW, /* SCardListCardsW */
PCSC_SCardListInterfacesA, /* SCardListInterfacesA */
PCSC_SCardListInterfacesW, /* SCardListInterfacesW */
PCSC_SCardGetProviderIdA, /* SCardGetProviderIdA */
PCSC_SCardGetProviderIdW, /* SCardGetProviderIdW */
PCSC_SCardGetCardTypeProviderNameA, /* SCardGetCardTypeProviderNameA */
PCSC_SCardGetCardTypeProviderNameW, /* SCardGetCardTypeProviderNameW */
PCSC_SCardIntroduceReaderGroupA, /* SCardIntroduceReaderGroupA */
PCSC_SCardIntroduceReaderGroupW, /* SCardIntroduceReaderGroupW */
PCSC_SCardForgetReaderGroupA, /* SCardForgetReaderGroupA */
PCSC_SCardForgetReaderGroupW, /* SCardForgetReaderGroupW */
PCSC_SCardIntroduceReaderA, /* SCardIntroduceReaderA */
PCSC_SCardIntroduceReaderW, /* SCardIntroduceReaderW */
PCSC_SCardForgetReaderA, /* SCardForgetReaderA */
PCSC_SCardForgetReaderW, /* SCardForgetReaderW */
PCSC_SCardAddReaderToGroupA, /* SCardAddReaderToGroupA */
PCSC_SCardAddReaderToGroupW, /* SCardAddReaderToGroupW */
PCSC_SCardRemoveReaderFromGroupA, /* SCardRemoveReaderFromGroupA */
PCSC_SCardRemoveReaderFromGroupW, /* SCardRemoveReaderFromGroupW */
PCSC_SCardIntroduceCardTypeA, /* SCardIntroduceCardTypeA */
PCSC_SCardIntroduceCardTypeW, /* SCardIntroduceCardTypeW */
PCSC_SCardSetCardTypeProviderNameA, /* SCardSetCardTypeProviderNameA */
PCSC_SCardSetCardTypeProviderNameW, /* SCardSetCardTypeProviderNameW */
PCSC_SCardForgetCardTypeA, /* SCardForgetCardTypeA */
PCSC_SCardForgetCardTypeW, /* SCardForgetCardTypeW */
PCSC_SCardFreeMemory, /* SCardFreeMemory */
PCSC_SCardAccessStartedEvent, /* SCardAccessStartedEvent */
PCSC_SCardReleaseStartedEvent, /* SCardReleaseStartedEvent */
PCSC_SCardLocateCardsA, /* SCardLocateCardsA */
PCSC_SCardLocateCardsW, /* SCardLocateCardsW */
PCSC_SCardLocateCardsByATRA, /* SCardLocateCardsByATRA */
PCSC_SCardLocateCardsByATRW, /* SCardLocateCardsByATRW */
PCSC_SCardGetStatusChangeA, /* SCardGetStatusChangeA */
PCSC_SCardGetStatusChangeW, /* SCardGetStatusChangeW */
PCSC_SCardCancel, /* SCardCancel */
PCSC_SCardConnectA, /* SCardConnectA */
PCSC_SCardConnectW, /* SCardConnectW */
PCSC_SCardReconnect, /* SCardReconnect */
PCSC_SCardDisconnect, /* SCardDisconnect */
PCSC_SCardBeginTransaction, /* SCardBeginTransaction */
PCSC_SCardEndTransaction, /* SCardEndTransaction */
PCSC_SCardCancelTransaction, /* SCardCancelTransaction */
PCSC_SCardState, /* SCardState */
PCSC_SCardStatusA, /* SCardStatusA */
PCSC_SCardStatusW, /* SCardStatusW */
PCSC_SCardTransmit, /* SCardTransmit */
PCSC_SCardGetTransmitCount, /* SCardGetTransmitCount */
PCSC_SCardControl, /* SCardControl */
PCSC_SCardGetAttrib, /* SCardGetAttrib */
PCSC_SCardSetAttrib, /* SCardSetAttrib */
PCSC_SCardUIDlgSelectCardA, /* SCardUIDlgSelectCardA */
PCSC_SCardUIDlgSelectCardW, /* SCardUIDlgSelectCardW */
PCSC_GetOpenCardNameA, /* GetOpenCardNameA */
PCSC_GetOpenCardNameW, /* GetOpenCardNameW */
PCSC_SCardDlgExtendedError, /* SCardDlgExtendedError */
PCSC_SCardReadCacheA, /* SCardReadCacheA */
PCSC_SCardReadCacheW, /* SCardReadCacheW */
PCSC_SCardWriteCacheA, /* SCardWriteCacheA */
PCSC_SCardWriteCacheW, /* SCardWriteCacheW */
PCSC_SCardGetReaderIconA, /* SCardGetReaderIconA */
PCSC_SCardGetReaderIconW, /* SCardGetReaderIconW */
PCSC_SCardGetDeviceTypeIdA, /* SCardGetDeviceTypeIdA */
PCSC_SCardGetDeviceTypeIdW, /* SCardGetDeviceTypeIdW */
PCSC_SCardGetReaderDeviceInstanceIdA, /* SCardGetReaderDeviceInstanceIdA */
PCSC_SCardGetReaderDeviceInstanceIdW, /* SCardGetReaderDeviceInstanceIdW */
PCSC_SCardListReadersWithDeviceInstanceIdA, /* SCardListReadersWithDeviceInstanceIdA */
PCSC_SCardListReadersWithDeviceInstanceIdW, /* SCardListReadersWithDeviceInstanceIdW */
PCSC_SCardAudit /* SCardAudit */
};
PSCardApiFunctionTable PCSC_GetSCardApiFunctionTable(void)
{
return &PCSC_SCardApiFunctionTable;
}
extern PCSCFunctionTable g_PCSC_Link;
extern int PCSC_InitializeSCardApi_Link(void);
int PCSC_InitializeSCardApi(void)
{
/* Disable pcsc-lite's (poor) blocking so we can handle it ourselves */
SetEnvironmentVariableA("PCSCLITE_NO_BLOCKING", "1");
#ifndef DISABLE_PCSC_LINK
if (PCSC_InitializeSCardApi_Link() >= 0)
{
g_PCSC.pfnSCardEstablishContext = g_PCSC_Link.pfnSCardEstablishContext;
g_PCSC.pfnSCardReleaseContext = g_PCSC_Link.pfnSCardReleaseContext;
g_PCSC.pfnSCardIsValidContext = g_PCSC_Link.pfnSCardIsValidContext;
g_PCSC.pfnSCardConnect = g_PCSC_Link.pfnSCardConnect;
g_PCSC.pfnSCardReconnect = g_PCSC_Link.pfnSCardReconnect;
g_PCSC.pfnSCardDisconnect = g_PCSC_Link.pfnSCardDisconnect;
g_PCSC.pfnSCardBeginTransaction = g_PCSC_Link.pfnSCardBeginTransaction;
g_PCSC.pfnSCardEndTransaction = g_PCSC_Link.pfnSCardEndTransaction;
g_PCSC.pfnSCardStatus = g_PCSC_Link.pfnSCardStatus;
g_PCSC.pfnSCardGetStatusChange = g_PCSC_Link.pfnSCardGetStatusChange;
g_PCSC.pfnSCardControl = g_PCSC_Link.pfnSCardControl;
g_PCSC.pfnSCardTransmit = g_PCSC_Link.pfnSCardTransmit;
g_PCSC.pfnSCardListReaderGroups = g_PCSC_Link.pfnSCardListReaderGroups;
g_PCSC.pfnSCardListReaders = g_PCSC_Link.pfnSCardListReaders;
g_PCSC.pfnSCardFreeMemory = g_PCSC_Link.pfnSCardFreeMemory;
g_PCSC.pfnSCardCancel = g_PCSC_Link.pfnSCardCancel;
g_PCSC.pfnSCardGetAttrib = g_PCSC_Link.pfnSCardGetAttrib;
g_PCSC.pfnSCardSetAttrib = g_PCSC_Link.pfnSCardSetAttrib;
return 1;
}
#endif
#ifdef __MACOSX__
g_PCSCModule = LoadLibraryA("/System/Library/Frameworks/PCSC.framework/PCSC");
#else
g_PCSCModule = LoadLibraryA("libpcsclite.so.1");
if (!g_PCSCModule)
g_PCSCModule = LoadLibraryA("libpcsclite.so");
#endif
if (!g_PCSCModule)
return -1;
g_PCSC.pfnSCardEstablishContext = (void*) GetProcAddress(g_PCSCModule, "SCardEstablishContext");
g_PCSC.pfnSCardReleaseContext = (void*) GetProcAddress(g_PCSCModule, "SCardReleaseContext");
g_PCSC.pfnSCardIsValidContext = (void*) GetProcAddress(g_PCSCModule, "SCardIsValidContext");
g_PCSC.pfnSCardConnect = (void*) GetProcAddress(g_PCSCModule, "SCardConnect");
g_PCSC.pfnSCardReconnect = (void*) GetProcAddress(g_PCSCModule, "SCardReconnect");
g_PCSC.pfnSCardDisconnect = (void*) GetProcAddress(g_PCSCModule, "SCardDisconnect");
g_PCSC.pfnSCardBeginTransaction = (void*) GetProcAddress(g_PCSCModule, "SCardBeginTransaction");
g_PCSC.pfnSCardEndTransaction = (void*) GetProcAddress(g_PCSCModule, "SCardEndTransaction");
g_PCSC.pfnSCardStatus = (void*) GetProcAddress(g_PCSCModule, "SCardStatus");
g_PCSC.pfnSCardGetStatusChange = (void*) GetProcAddress(g_PCSCModule, "SCardGetStatusChange");
g_PCSC.pfnSCardControl = (void*) GetProcAddress(g_PCSCModule, "SCardControl");
g_PCSC.pfnSCardTransmit = (void*) GetProcAddress(g_PCSCModule, "SCardTransmit");
g_PCSC.pfnSCardListReaderGroups = (void*) GetProcAddress(g_PCSCModule, "SCardListReaderGroups");
g_PCSC.pfnSCardListReaders = (void*) GetProcAddress(g_PCSCModule, "SCardListReaders");
g_PCSC.pfnSCardCancel = (void*) GetProcAddress(g_PCSCModule, "SCardCancel");
g_PCSC.pfnSCardGetAttrib = (void*) GetProcAddress(g_PCSCModule, "SCardGetAttrib");
g_PCSC.pfnSCardSetAttrib = (void*) GetProcAddress(g_PCSCModule, "SCardSetAttrib");
g_PCSC.pfnSCardFreeMemory = NULL;
#ifndef __APPLE__
g_PCSC.pfnSCardFreeMemory = (void*) GetProcAddress(g_PCSCModule, "SCardFreeMemory");
#endif
if (g_PCSC.pfnSCardFreeMemory)
g_SCardAutoAllocate = TRUE;
#ifdef DISABLE_PCSC_SCARD_AUTOALLOCATE
g_PCSC.pfnSCardFreeMemory = NULL;
g_SCardAutoAllocate = FALSE;
#endif
#ifdef __APPLE__
g_PnP_Notification = FALSE;
#endif
return 1;
}
#endif