Blame winpr/libwinpr/smartcard/smartcard_pcsc.c

Packit 1fb8d4
/**
Packit 1fb8d4
 * WinPR: Windows Portable Runtime
Packit 1fb8d4
 * Smart Card API
Packit 1fb8d4
 *
Packit 1fb8d4
 * Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
Packit 1fb8d4
 *
Packit 1fb8d4
 * Licensed under the Apache License, Version 2.0 (the "License");
Packit 1fb8d4
 * you may not use this file except in compliance with the License.
Packit 1fb8d4
 * You may obtain a copy of the License at
Packit 1fb8d4
 *
Packit 1fb8d4
 *     http://www.apache.org/licenses/LICENSE-2.0
Packit 1fb8d4
 *
Packit 1fb8d4
 * Unless required by applicable law or agreed to in writing, software
Packit 1fb8d4
 * distributed under the License is distributed on an "AS IS" BASIS,
Packit 1fb8d4
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Packit 1fb8d4
 * See the License for the specific language governing permissions and
Packit 1fb8d4
 * limitations under the License.
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
#ifdef HAVE_CONFIG_H
Packit 1fb8d4
#include "config.h"
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
#ifndef _WIN32
Packit 1fb8d4
Packit 1fb8d4
#ifdef __APPLE__
Packit 1fb8d4
#include <sys/types.h>
Packit 1fb8d4
#include <sys/param.h>
Packit 1fb8d4
#include <sys/sysctl.h>
Packit 1fb8d4
#include <string.h>
Packit 1fb8d4
#include <ctype.h>
Packit 1fb8d4
#include <errno.h>
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
#include <stdio.h>
Packit 1fb8d4
#include <stdlib.h>
Packit 1fb8d4
Packit 1fb8d4
#include <winpr/crt.h>
Packit 1fb8d4
#include <winpr/synch.h>
Packit 1fb8d4
#include <winpr/library.h>
Packit 1fb8d4
#include <winpr/smartcard.h>
Packit 1fb8d4
#include <winpr/collections.h>
Packit 1fb8d4
#include <winpr/environment.h>
Packit 1fb8d4
Packit 1fb8d4
#include "smartcard_pcsc.h"
Packit 1fb8d4
Packit 1fb8d4
#include "../log.h"
Packit 1fb8d4
#define TAG WINPR_TAG("smartcard")
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * PC/SC transactions:
Packit 1fb8d4
 * http://developersblog.wwpass.com/?p=180
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Smart Card Logon on Windows Vista:
Packit 1fb8d4
 * http://blogs.msdn.com/b/shivaram/archive/2007/02/26/smart-card-logon-on-windows-vista.aspx
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * The Smart Card Cryptographic Service Provider Cookbook:
Packit 1fb8d4
 * http://msdn.microsoft.com/en-us/library/ms953432.aspx
Packit 1fb8d4
 *
Packit 1fb8d4
 * SCARDCONTEXT
Packit 1fb8d4
 *
Packit 1fb8d4
 * The context is a communication channel with the smart card resource manager and
Packit 1fb8d4
 * all calls to the resource manager must go through this link.
Packit 1fb8d4
 *
Packit 1fb8d4
 * All functions that take a context as a parameter or a card handle as parameter,
Packit 1fb8d4
 * which is indirectly associated with a particular context, may be blocking calls.
Packit 1fb8d4
 * Examples of these are SCardGetStatusChange and SCardBeginTransaction, which takes
Packit 1fb8d4
 * a card handle as a parameter. If such a function blocks then all operations wanting
Packit 1fb8d4
 * to use the context are blocked as well. So, it is recommended that a CSP using
Packit 1fb8d4
 * monitoring establishes at least two contexts with the resource manager; one for
Packit 1fb8d4
 * monitoring (with SCardGetStatusChange) and one for other operations.
Packit 1fb8d4
 *
Packit 1fb8d4
 * If multiple cards are present, it is recommended that a separate context or pair
Packit 1fb8d4
 * of contexts be established for each card to prevent operations on one card from
Packit 1fb8d4
 * blocking operations on another.
Packit 1fb8d4
 *
Packit 1fb8d4
 * Example one
Packit 1fb8d4
 *
Packit 1fb8d4
 * The example below shows what can happen if a CSP using SCardGetStatusChange for
Packit 1fb8d4
 * monitoring does not establish two contexts with the resource manager.
Packit 1fb8d4
 * The context becomes unusable until SCardGetStatusChange unblocks.
Packit 1fb8d4
 *
Packit 1fb8d4
 * In this example, there is one process running called P1.
Packit 1fb8d4
 * P1 calls SCardEstablishContext, which returns the context hCtx.
Packit 1fb8d4
 * P1 calls SCardConnect (with the hCtx context) which returns a handle to the card, hCard.
Packit 1fb8d4
 * P1 calls SCardGetStatusChange (with the hCtx context) which blocks because
Packit 1fb8d4
 * there are no status changes to report.
Packit 1fb8d4
 * Until the thread running SCardGetStatusChange unblocks, another thread in P1 trying to
Packit 1fb8d4
 * perform an operation using the context hCtx (or the card hCard) will also be blocked.
Packit 1fb8d4
 *
Packit 1fb8d4
 * Example two
Packit 1fb8d4
 *
Packit 1fb8d4
 * The example below shows how transaction control ensures that operations meant to be
Packit 1fb8d4
 * performed without interruption can do so safely within a transaction.
Packit 1fb8d4
 *
Packit 1fb8d4
 * In this example, there are two different processes running; P1 and P2.
Packit 1fb8d4
 * P1 calls SCardEstablishContext, which returns the context hCtx1.
Packit 1fb8d4
 * P2 calls SCardEstablishContext, which returns the context hCtx2.
Packit 1fb8d4
 * P1 calls SCardConnect (with the hCtx1 context) which returns a handle to the card, hCard1.
Packit 1fb8d4
 * P2 calls SCardConnect (with the hCtx2 context) which returns a handle to the same card, hCard2.
Packit 1fb8d4
 * P1 calls SCardBeginTransaction (with the hCard 1 context).
Packit 1fb8d4
 * Until P1 calls SCardEndTransaction (with the hCard1 context),
Packit 1fb8d4
 * any operation using hCard2 will be blocked.
Packit 1fb8d4
 * Once an operation using hCard2 is blocked and until it's returning,
Packit 1fb8d4
 * any operation using hCtx2 (and hCard2) will also be blocked.
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
//#define DISABLE_PCSC_SCARD_AUTOALLOCATE
Packit 1fb8d4
Packit 1fb8d4
typedef struct _PCSC_SCARDCONTEXT PCSC_SCARDCONTEXT;
Packit 1fb8d4
typedef struct _PCSC_SCARDHANDLE PCSC_SCARDHANDLE;
Packit 1fb8d4
Packit 1fb8d4
struct _PCSC_SCARDCONTEXT
Packit 1fb8d4
{
Packit 1fb8d4
	SCARDHANDLE owner;
Packit 1fb8d4
	CRITICAL_SECTION lock;
Packit 1fb8d4
	SCARDCONTEXT hContext;
Packit 1fb8d4
	DWORD dwCardHandleCount;
Packit 1fb8d4
	BOOL isTransactionLocked;
Packit 1fb8d4
};
Packit 1fb8d4
Packit 1fb8d4
struct _PCSC_SCARDHANDLE
Packit 1fb8d4
{
Packit 1fb8d4
	BOOL shared;
Packit 1fb8d4
	SCARDCONTEXT hSharedContext;
Packit 1fb8d4
};
Packit 1fb8d4
Packit 1fb8d4
static HMODULE g_PCSCModule = NULL;
Packit 1fb8d4
static PCSCFunctionTable g_PCSC = { 0 };
Packit 1fb8d4
Packit 1fb8d4
static HANDLE g_StartedEvent = NULL;
Packit 1fb8d4
static int g_StartedEventRefCount = 0;
Packit 1fb8d4
Packit 1fb8d4
static BOOL g_SCardAutoAllocate = FALSE;
Packit 1fb8d4
static BOOL g_PnP_Notification = TRUE;
Packit 1fb8d4
Packit 1fb8d4
#ifdef __MACOSX__
Packit 1fb8d4
static unsigned int OSXVersion = 0;
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
Packit 1fb8d4
Packit 1fb8d4
static wListDictionary* g_CardHandles = NULL;
Packit 1fb8d4
static wListDictionary* g_CardContexts = NULL;
Packit 1fb8d4
static wListDictionary* g_MemoryBlocks = NULL;
Packit 1fb8d4
Packit 1fb8d4
char SMARTCARD_PNP_NOTIFICATION_A[] = "\\\\?PnP?\\Notification";
Packit 1fb8d4
Packit 1fb8d4
const PCSC_SCARD_IO_REQUEST g_PCSC_rgSCardT0Pci = { SCARD_PROTOCOL_T0, sizeof(PCSC_SCARD_IO_REQUEST) };
Packit 1fb8d4
const PCSC_SCARD_IO_REQUEST g_PCSC_rgSCardT1Pci = { SCARD_PROTOCOL_T1, sizeof(PCSC_SCARD_IO_REQUEST) };
Packit 1fb8d4
const PCSC_SCARD_IO_REQUEST g_PCSC_rgSCardRawPci = { PCSC_SCARD_PROTOCOL_RAW, sizeof(PCSC_SCARD_IO_REQUEST) };
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardFreeMemory_Internal(SCARDCONTEXT hContext, LPCVOID pvMem);
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardEstablishContext_Internal(DWORD dwScope,
Packit 1fb8d4
        LPCVOID pvReserved1, LPCVOID pvReserved2, LPSCARDCONTEXT phContext);
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardReleaseContext_Internal(SCARDCONTEXT hContext);
Packit 1fb8d4
Packit 1fb8d4
static LONG PCSC_MapErrorCodeToWinSCard(LONG errorCode)
Packit 1fb8d4
{
Packit 1fb8d4
	/**
Packit 1fb8d4
	 * pcsc-lite returns SCARD_E_UNEXPECTED when it
Packit 1fb8d4
	 * should return SCARD_E_UNSUPPORTED_FEATURE.
Packit 1fb8d4
	 *
Packit 1fb8d4
	 * Additionally, the pcsc-lite headers incorrectly
Packit 1fb8d4
	 * define SCARD_E_UNSUPPORTED_FEATURE to 0x8010001F,
Packit 1fb8d4
	 * when the real value should be 0x80100022.
Packit 1fb8d4
	 */
Packit 1fb8d4
	if (errorCode == SCARD_E_UNEXPECTED)
Packit 1fb8d4
		errorCode = SCARD_E_UNSUPPORTED_FEATURE;
Packit 1fb8d4
Packit 1fb8d4
	return errorCode;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static DWORD PCSC_ConvertCardStateToWinSCard(DWORD dwCardState, LONG status)
Packit 1fb8d4
{
Packit 1fb8d4
	/**
Packit 1fb8d4
	 * pcsc-lite's SCardStatus returns a bit-field, not an enumerated value.
Packit 1fb8d4
	 *
Packit 1fb8d4
	 *         State             WinSCard           pcsc-lite
Packit 1fb8d4
	 *
Packit 1fb8d4
	 *      SCARD_UNKNOWN           0                0x0001
Packit 1fb8d4
	 *      SCARD_ABSENT            1                0x0002
Packit 1fb8d4
	 *      SCARD_PRESENT           2                0x0004
Packit 1fb8d4
	 *      SCARD_SWALLOWED         3                0x0008
Packit 1fb8d4
	 *      SCARD_POWERED           4                0x0010
Packit 1fb8d4
	 *      SCARD_NEGOTIABLE        5                0x0020
Packit 1fb8d4
	 *      SCARD_SPECIFIC          6                0x0040
Packit 1fb8d4
	 *
Packit 1fb8d4
	 * pcsc-lite also never sets SCARD_SPECIFIC,
Packit 1fb8d4
	 * which is expected by some windows applications.
Packit 1fb8d4
	 */
Packit 1fb8d4
	if (status == SCARD_S_SUCCESS)
Packit 1fb8d4
	{
Packit 1fb8d4
		if ((dwCardState & PCSC_SCARD_NEGOTIABLE) || (dwCardState & PCSC_SCARD_SPECIFIC))
Packit 1fb8d4
			return SCARD_SPECIFIC;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (dwCardState & PCSC_SCARD_POWERED)
Packit 1fb8d4
		return SCARD_POWERED;
Packit 1fb8d4
Packit 1fb8d4
	if (dwCardState & PCSC_SCARD_NEGOTIABLE)
Packit 1fb8d4
		return SCARD_NEGOTIABLE;
Packit 1fb8d4
Packit 1fb8d4
	if (dwCardState & PCSC_SCARD_SPECIFIC)
Packit 1fb8d4
		return SCARD_SPECIFIC;
Packit 1fb8d4
Packit 1fb8d4
	if (dwCardState & PCSC_SCARD_ABSENT)
Packit 1fb8d4
		return SCARD_ABSENT;
Packit 1fb8d4
Packit 1fb8d4
	if (dwCardState & PCSC_SCARD_PRESENT)
Packit 1fb8d4
		return SCARD_PRESENT;
Packit 1fb8d4
Packit 1fb8d4
	if (dwCardState & PCSC_SCARD_SWALLOWED)
Packit 1fb8d4
		return SCARD_SWALLOWED;
Packit 1fb8d4
Packit 1fb8d4
	if (dwCardState & PCSC_SCARD_UNKNOWN)
Packit 1fb8d4
		return SCARD_UNKNOWN;
Packit 1fb8d4
Packit 1fb8d4
	return SCARD_UNKNOWN;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static DWORD PCSC_ConvertProtocolsToWinSCard(DWORD dwProtocols)
Packit 1fb8d4
{
Packit 1fb8d4
	/**
Packit 1fb8d4
	 * pcsc-lite uses a different value for SCARD_PROTOCOL_RAW,
Packit 1fb8d4
	 * and also has SCARD_PROTOCOL_T15 which is not in WinSCard.
Packit 1fb8d4
	 */
Packit 1fb8d4
	if (dwProtocols & PCSC_SCARD_PROTOCOL_RAW)
Packit 1fb8d4
	{
Packit 1fb8d4
		dwProtocols &= ~PCSC_SCARD_PROTOCOL_RAW;
Packit 1fb8d4
		dwProtocols |= SCARD_PROTOCOL_RAW;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (dwProtocols & PCSC_SCARD_PROTOCOL_T15)
Packit 1fb8d4
	{
Packit 1fb8d4
		dwProtocols &= ~PCSC_SCARD_PROTOCOL_T15;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return dwProtocols;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static DWORD PCSC_ConvertProtocolsFromWinSCard(DWORD dwProtocols)
Packit 1fb8d4
{
Packit 1fb8d4
	/**
Packit 1fb8d4
	 * pcsc-lite uses a different value for SCARD_PROTOCOL_RAW,
Packit 1fb8d4
	 * and it does not define WinSCard's SCARD_PROTOCOL_DEFAULT.
Packit 1fb8d4
	 */
Packit 1fb8d4
	if (dwProtocols & SCARD_PROTOCOL_RAW)
Packit 1fb8d4
	{
Packit 1fb8d4
		dwProtocols &= ~SCARD_PROTOCOL_RAW;
Packit 1fb8d4
		dwProtocols |= PCSC_SCARD_PROTOCOL_RAW;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (dwProtocols & SCARD_PROTOCOL_DEFAULT)
Packit 1fb8d4
	{
Packit 1fb8d4
		dwProtocols &= ~SCARD_PROTOCOL_DEFAULT;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (dwProtocols == SCARD_PROTOCOL_UNDEFINED)
Packit 1fb8d4
	{
Packit 1fb8d4
		dwProtocols = SCARD_PROTOCOL_Tx;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return dwProtocols;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static PCSC_SCARDCONTEXT* PCSC_GetCardContextData(SCARDCONTEXT hContext)
Packit 1fb8d4
{
Packit 1fb8d4
	PCSC_SCARDCONTEXT* pContext;
Packit 1fb8d4
Packit 1fb8d4
	if (!g_CardContexts)
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
Packit 1fb8d4
	pContext = (PCSC_SCARDCONTEXT*) ListDictionary_GetItemValue(g_CardContexts, (void*) hContext);
Packit 1fb8d4
Packit 1fb8d4
	if (!pContext)
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
Packit 1fb8d4
	return pContext;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static PCSC_SCARDCONTEXT* PCSC_EstablishCardContext(SCARDCONTEXT hContext)
Packit 1fb8d4
{
Packit 1fb8d4
	PCSC_SCARDCONTEXT* pContext;
Packit 1fb8d4
	pContext = (PCSC_SCARDCONTEXT*) calloc(1, sizeof(PCSC_SCARDCONTEXT));
Packit 1fb8d4
Packit 1fb8d4
	if (!pContext)
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
Packit 1fb8d4
	pContext->hContext = hContext;
Packit 1fb8d4
Packit 1fb8d4
	if (!InitializeCriticalSectionAndSpinCount(&(pContext->lock), 4000))
Packit 1fb8d4
		goto error_spinlock;
Packit 1fb8d4
Packit 1fb8d4
	if (!g_CardContexts)
Packit 1fb8d4
	{
Packit 1fb8d4
		g_CardContexts = ListDictionary_New(TRUE);
Packit 1fb8d4
Packit 1fb8d4
		if (!g_CardContexts)
Packit 1fb8d4
			goto errors;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (!ListDictionary_Add(g_CardContexts, (void*) hContext, (void*) pContext))
Packit 1fb8d4
		goto errors;
Packit 1fb8d4
Packit 1fb8d4
	return pContext;
Packit 1fb8d4
errors:
Packit 1fb8d4
	DeleteCriticalSection(&(pContext->lock));
Packit 1fb8d4
error_spinlock:
Packit 1fb8d4
	free(pContext);
Packit 1fb8d4
	return NULL;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static void PCSC_ReleaseCardContext(SCARDCONTEXT hContext)
Packit 1fb8d4
{
Packit 1fb8d4
	PCSC_SCARDCONTEXT* pContext;
Packit 1fb8d4
	pContext = PCSC_GetCardContextData(hContext);
Packit 1fb8d4
Packit 1fb8d4
	if (!pContext)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "PCSC_ReleaseCardContext: null pContext!");
Packit 1fb8d4
		return;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	DeleteCriticalSection(&(pContext->lock));
Packit 1fb8d4
	free(pContext);
Packit 1fb8d4
Packit 1fb8d4
	if (!g_CardContexts)
Packit 1fb8d4
		return;
Packit 1fb8d4
Packit 1fb8d4
	ListDictionary_Remove(g_CardContexts, (void*) hContext);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL PCSC_LockCardContext(SCARDCONTEXT hContext)
Packit 1fb8d4
{
Packit 1fb8d4
	PCSC_SCARDCONTEXT* pContext;
Packit 1fb8d4
	pContext = PCSC_GetCardContextData(hContext);
Packit 1fb8d4
Packit 1fb8d4
	if (!pContext)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "PCSC_LockCardContext: invalid context (%p)", (void*) hContext);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	EnterCriticalSection(&(pContext->lock));
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL PCSC_UnlockCardContext(SCARDCONTEXT hContext)
Packit 1fb8d4
{
Packit 1fb8d4
	PCSC_SCARDCONTEXT* pContext;
Packit 1fb8d4
	pContext = PCSC_GetCardContextData(hContext);
Packit 1fb8d4
Packit 1fb8d4
	if (!pContext)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "PCSC_UnlockCardContext: invalid context (%p)", (void*) hContext);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	LeaveCriticalSection(&(pContext->lock));
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static PCSC_SCARDHANDLE* PCSC_GetCardHandleData(SCARDHANDLE hCard)
Packit 1fb8d4
{
Packit 1fb8d4
	PCSC_SCARDHANDLE* pCard;
Packit 1fb8d4
Packit 1fb8d4
	if (!g_CardHandles)
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
Packit 1fb8d4
	pCard = (PCSC_SCARDHANDLE*) ListDictionary_GetItemValue(g_CardHandles, (void*) hCard);
Packit 1fb8d4
Packit 1fb8d4
	if (!pCard)
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
Packit 1fb8d4
	return pCard;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static SCARDCONTEXT PCSC_GetCardContextFromHandle(SCARDHANDLE hCard)
Packit 1fb8d4
{
Packit 1fb8d4
	PCSC_SCARDHANDLE* pCard;
Packit 1fb8d4
	pCard = PCSC_GetCardHandleData(hCard);
Packit 1fb8d4
Packit 1fb8d4
	if (!pCard)
Packit 1fb8d4
		return 0;
Packit 1fb8d4
Packit 1fb8d4
	return pCard->hSharedContext;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL PCSC_WaitForCardAccess(SCARDCONTEXT hContext, SCARDHANDLE hCard, BOOL shared)
Packit 1fb8d4
{
Packit 1fb8d4
	BOOL status = TRUE;
Packit 1fb8d4
	PCSC_SCARDHANDLE* pCard = NULL;
Packit 1fb8d4
	PCSC_SCARDCONTEXT* pContext = NULL;
Packit 1fb8d4
Packit 1fb8d4
	if (!hCard)
Packit 1fb8d4
	{
Packit 1fb8d4
		/* SCardConnect */
Packit 1fb8d4
		pContext = PCSC_GetCardContextData(hContext);
Packit 1fb8d4
Packit 1fb8d4
		if (!pContext)
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
Packit 1fb8d4
		if (!pContext->owner)
Packit 1fb8d4
			return TRUE;
Packit 1fb8d4
Packit 1fb8d4
		/* wait for card ownership */
Packit 1fb8d4
		return TRUE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	pCard = PCSC_GetCardHandleData(hCard);
Packit 1fb8d4
Packit 1fb8d4
	if (!pCard)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	shared = pCard->shared;
Packit 1fb8d4
	hContext = pCard->hSharedContext;
Packit 1fb8d4
	pContext = PCSC_GetCardContextData(hContext);
Packit 1fb8d4
Packit 1fb8d4
	if (!pContext)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (!pContext->owner)
Packit 1fb8d4
	{
Packit 1fb8d4
		/* card is not owned */
Packit 1fb8d4
		if (!shared)
Packit 1fb8d4
			pContext->owner = hCard;
Packit 1fb8d4
Packit 1fb8d4
		return TRUE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (pContext->owner == hCard)
Packit 1fb8d4
	{
Packit 1fb8d4
		/* already card owner */
Packit 1fb8d4
	}
Packit 1fb8d4
	else
Packit 1fb8d4
	{
Packit 1fb8d4
		/* wait for card ownership */
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return status;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL PCSC_ReleaseCardAccess(SCARDCONTEXT hContext, SCARDHANDLE hCard)
Packit 1fb8d4
{
Packit 1fb8d4
	PCSC_SCARDHANDLE* pCard = NULL;
Packit 1fb8d4
	PCSC_SCARDCONTEXT* pContext = NULL;
Packit 1fb8d4
Packit 1fb8d4
	if (!hCard)
Packit 1fb8d4
	{
Packit 1fb8d4
		/* release current owner */
Packit 1fb8d4
		pContext = PCSC_GetCardContextData(hContext);
Packit 1fb8d4
Packit 1fb8d4
		if (!pContext)
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
Packit 1fb8d4
		hCard = pContext->owner;
Packit 1fb8d4
Packit 1fb8d4
		if (!hCard)
Packit 1fb8d4
			return TRUE;
Packit 1fb8d4
Packit 1fb8d4
		pCard = PCSC_GetCardHandleData(hCard);
Packit 1fb8d4
Packit 1fb8d4
		if (!pCard)
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
Packit 1fb8d4
		/* release card ownership */
Packit 1fb8d4
		pContext->owner = 0;
Packit 1fb8d4
		return TRUE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	pCard = PCSC_GetCardHandleData(hCard);
Packit 1fb8d4
Packit 1fb8d4
	if (!pCard)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	hContext = pCard->hSharedContext;
Packit 1fb8d4
	pContext = PCSC_GetCardContextData(hContext);
Packit 1fb8d4
Packit 1fb8d4
	if (!pContext)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (pContext->owner == hCard)
Packit 1fb8d4
	{
Packit 1fb8d4
		/* release card ownership */
Packit 1fb8d4
		pContext->owner = 0;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static PCSC_SCARDHANDLE* PCSC_ConnectCardHandle(SCARDCONTEXT hSharedContext, SCARDHANDLE hCard)
Packit 1fb8d4
{
Packit 1fb8d4
	PCSC_SCARDHANDLE* pCard;
Packit 1fb8d4
	PCSC_SCARDCONTEXT* pContext;
Packit 1fb8d4
	pContext = PCSC_GetCardContextData(hSharedContext);
Packit 1fb8d4
Packit 1fb8d4
	if (!pContext)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "PCSC_ConnectCardHandle: null pContext!");
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	pCard = (PCSC_SCARDHANDLE*) calloc(1, sizeof(PCSC_SCARDHANDLE));
Packit 1fb8d4
Packit 1fb8d4
	if (!pCard)
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
Packit 1fb8d4
	pCard->hSharedContext = hSharedContext;
Packit 1fb8d4
Packit 1fb8d4
	if (!g_CardHandles)
Packit 1fb8d4
	{
Packit 1fb8d4
		g_CardHandles = ListDictionary_New(TRUE);
Packit 1fb8d4
Packit 1fb8d4
		if (!g_CardHandles)
Packit 1fb8d4
			goto error;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (!ListDictionary_Add(g_CardHandles, (void*) hCard, (void*) pCard))
Packit 1fb8d4
		goto error;
Packit 1fb8d4
Packit 1fb8d4
	pContext->dwCardHandleCount++;
Packit 1fb8d4
	return pCard;
Packit 1fb8d4
error:
Packit 1fb8d4
	free(pCard);
Packit 1fb8d4
	return NULL;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static void PCSC_DisconnectCardHandle(SCARDHANDLE hCard)
Packit 1fb8d4
{
Packit 1fb8d4
	PCSC_SCARDHANDLE* pCard;
Packit 1fb8d4
	PCSC_SCARDCONTEXT* pContext;
Packit 1fb8d4
	pCard = PCSC_GetCardHandleData(hCard);
Packit 1fb8d4
Packit 1fb8d4
	if (!pCard)
Packit 1fb8d4
		return;
Packit 1fb8d4
Packit 1fb8d4
	pContext = PCSC_GetCardContextData(pCard->hSharedContext);
Packit 1fb8d4
	free(pCard);
Packit 1fb8d4
Packit 1fb8d4
	if (!g_CardHandles)
Packit 1fb8d4
		return;
Packit 1fb8d4
Packit 1fb8d4
	ListDictionary_Remove(g_CardHandles, (void*) hCard);
Packit 1fb8d4
Packit 1fb8d4
	if (!pContext)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "PCSC_DisconnectCardHandle: null pContext!");
Packit 1fb8d4
		return;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	pContext->dwCardHandleCount--;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL PCSC_AddMemoryBlock(SCARDCONTEXT hContext, void* pvMem)
Packit 1fb8d4
{
Packit 1fb8d4
	if (!g_MemoryBlocks)
Packit 1fb8d4
	{
Packit 1fb8d4
		g_MemoryBlocks = ListDictionary_New(TRUE);
Packit 1fb8d4
Packit 1fb8d4
		if (!g_MemoryBlocks)
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return ListDictionary_Add(g_MemoryBlocks, pvMem, (void*) hContext);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static void* PCSC_RemoveMemoryBlock(SCARDCONTEXT hContext, void* pvMem)
Packit 1fb8d4
{
Packit 1fb8d4
	WINPR_UNUSED(hContext);
Packit 1fb8d4
Packit 1fb8d4
	if (!g_MemoryBlocks)
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
Packit 1fb8d4
	return ListDictionary_Remove(g_MemoryBlocks, pvMem);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Standard Windows Smart Card API (PCSC)
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardEstablishContext_Internal(DWORD dwScope,
Packit 1fb8d4
        LPCVOID pvReserved1, LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
Packit 1fb8d4
{
Packit 1fb8d4
	WINPR_UNUSED(dwScope); /* SCARD_SCOPE_SYSTEM is the only scope supported by pcsc-lite */
Packit 1fb8d4
	LONG status = SCARD_S_SUCCESS;
Packit 1fb8d4
Packit 1fb8d4
	if (!g_PCSC.pfnSCardEstablishContext)
Packit 1fb8d4
		return SCARD_E_NO_SERVICE;
Packit 1fb8d4
Packit 1fb8d4
	status = (LONG) g_PCSC.pfnSCardEstablishContext(SCARD_SCOPE_SYSTEM, pvReserved1, pvReserved2,
Packit 1fb8d4
	         phContext);
Packit 1fb8d4
	status = PCSC_MapErrorCodeToWinSCard(status);
Packit 1fb8d4
	return status;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardEstablishContext(DWORD dwScope,
Packit 1fb8d4
        LPCVOID pvReserved1, LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
Packit 1fb8d4
{
Packit 1fb8d4
	LONG status;
Packit 1fb8d4
	status = PCSC_SCardEstablishContext_Internal(dwScope, pvReserved1, pvReserved2, phContext);
Packit 1fb8d4
Packit 1fb8d4
	if (status == SCARD_S_SUCCESS)
Packit 1fb8d4
		PCSC_EstablishCardContext(*phContext);
Packit 1fb8d4
Packit 1fb8d4
	return status;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardReleaseContext_Internal(SCARDCONTEXT hContext)
Packit 1fb8d4
{
Packit 1fb8d4
	LONG status = SCARD_S_SUCCESS;
Packit 1fb8d4
Packit 1fb8d4
	if (!g_PCSC.pfnSCardReleaseContext)
Packit 1fb8d4
		return SCARD_E_NO_SERVICE;
Packit 1fb8d4
Packit 1fb8d4
	if (!hContext)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "SCardReleaseContext: null hContext");
Packit 1fb8d4
		return status;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	status = (LONG) g_PCSC.pfnSCardReleaseContext(hContext);
Packit 1fb8d4
	status = PCSC_MapErrorCodeToWinSCard(status);
Packit 1fb8d4
	return status;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardReleaseContext(SCARDCONTEXT hContext)
Packit 1fb8d4
{
Packit 1fb8d4
	LONG status = SCARD_S_SUCCESS;
Packit 1fb8d4
	status = PCSC_SCardReleaseContext_Internal(hContext);
Packit 1fb8d4
Packit 1fb8d4
	if (status != SCARD_S_SUCCESS)
Packit 1fb8d4
		PCSC_ReleaseCardContext(hContext);
Packit 1fb8d4
Packit 1fb8d4
	return status;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardIsValidContext(SCARDCONTEXT hContext)
Packit 1fb8d4
{
Packit 1fb8d4
	LONG status = SCARD_S_SUCCESS;
Packit 1fb8d4
Packit 1fb8d4
	if (!g_PCSC.pfnSCardIsValidContext)
Packit 1fb8d4
		return SCARD_E_NO_SERVICE;
Packit 1fb8d4
Packit 1fb8d4
	status = (LONG) g_PCSC.pfnSCardIsValidContext(hContext);
Packit 1fb8d4
	status = PCSC_MapErrorCodeToWinSCard(status);
Packit 1fb8d4
	return status;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardListReaderGroups_Internal(SCARDCONTEXT hContext,
Packit 1fb8d4
        LPSTR mszGroups, LPDWORD pcchGroups)
Packit 1fb8d4
{
Packit 1fb8d4
	LONG status = SCARD_S_SUCCESS;
Packit 1fb8d4
	BOOL pcchGroupsAlloc = FALSE;
Packit 1fb8d4
	LPSTR* pMszGroups = (LPSTR*) mszGroups;
Packit 1fb8d4
	PCSC_DWORD pcsc_cchGroups = 0;
Packit 1fb8d4
Packit 1fb8d4
	if (!pcchGroups)
Packit 1fb8d4
		return SCARD_E_INVALID_PARAMETER;
Packit 1fb8d4
Packit 1fb8d4
	if (!g_PCSC.pfnSCardListReaderGroups)
Packit 1fb8d4
		return SCARD_E_NO_SERVICE;
Packit 1fb8d4
Packit 1fb8d4
	if (*pcchGroups == SCARD_AUTOALLOCATE)
Packit 1fb8d4
		pcchGroupsAlloc = TRUE;
Packit 1fb8d4
Packit 1fb8d4
	pcsc_cchGroups = pcchGroupsAlloc ? PCSC_SCARD_AUTOALLOCATE : (PCSC_DWORD) * pcchGroups;
Packit 1fb8d4
Packit 1fb8d4
	if (pcchGroupsAlloc && !g_SCardAutoAllocate)
Packit 1fb8d4
	{
Packit 1fb8d4
		pcsc_cchGroups = 0;
Packit 1fb8d4
		status = (LONG) g_PCSC.pfnSCardListReaderGroups(hContext, NULL, &pcsc_cchGroups);
Packit 1fb8d4
Packit 1fb8d4
		if (status == SCARD_S_SUCCESS)
Packit 1fb8d4
		{
Packit 1fb8d4
			*pMszGroups = calloc(1, pcsc_cchGroups);
Packit 1fb8d4
Packit 1fb8d4
			if (!*pMszGroups)
Packit 1fb8d4
				return SCARD_E_NO_MEMORY;
Packit 1fb8d4
Packit 1fb8d4
			status = (LONG) g_PCSC.pfnSCardListReaderGroups(hContext, *pMszGroups, &pcsc_cchGroups);
Packit 1fb8d4
Packit 1fb8d4
			if (status != SCARD_S_SUCCESS)
Packit 1fb8d4
				free(*pMszGroups);
Packit 1fb8d4
			else
Packit 1fb8d4
				PCSC_AddMemoryBlock(hContext, *pMszGroups);
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
	else
Packit 1fb8d4
	{
Packit 1fb8d4
		status = (LONG) g_PCSC.pfnSCardListReaderGroups(hContext, mszGroups, &pcsc_cchGroups);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	status = PCSC_MapErrorCodeToWinSCard(status);
Packit 1fb8d4
	*pcchGroups = (DWORD) pcsc_cchGroups;
Packit 1fb8d4
	return status;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardListReaderGroupsA(SCARDCONTEXT hContext,
Packit 1fb8d4
        LPSTR mszGroups, LPDWORD pcchGroups)
Packit 1fb8d4
{
Packit 1fb8d4
	LONG status = SCARD_S_SUCCESS;
Packit 1fb8d4
Packit 1fb8d4
	if (!g_PCSC.pfnSCardListReaderGroups)
Packit 1fb8d4
		return SCARD_E_NO_SERVICE;
Packit 1fb8d4
Packit 1fb8d4
	if (!PCSC_LockCardContext(hContext))
Packit 1fb8d4
		return SCARD_E_INVALID_HANDLE;
Packit 1fb8d4
Packit 1fb8d4
	status = PCSC_SCardListReaderGroups_Internal(hContext, mszGroups, pcchGroups);
Packit 1fb8d4
Packit 1fb8d4
	if (!PCSC_UnlockCardContext(hContext))
Packit 1fb8d4
		return SCARD_E_INVALID_HANDLE;
Packit 1fb8d4
Packit 1fb8d4
	return status;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardListReaderGroupsW(SCARDCONTEXT hContext,
Packit 1fb8d4
        LPWSTR mszGroups, LPDWORD pcchGroups)
Packit 1fb8d4
{
Packit 1fb8d4
	LPSTR mszGroupsA = NULL;
Packit 1fb8d4
	LPSTR* pMszGroupsA = &mszGroupsA;
Packit 1fb8d4
	LONG status = SCARD_S_SUCCESS;
Packit 1fb8d4
Packit 1fb8d4
	if (!g_PCSC.pfnSCardListReaderGroups)
Packit 1fb8d4
		return SCARD_E_NO_SERVICE;
Packit 1fb8d4
Packit 1fb8d4
	if (!PCSC_LockCardContext(hContext))
Packit 1fb8d4
		return SCARD_E_INVALID_HANDLE;
Packit 1fb8d4
Packit 1fb8d4
	status = PCSC_SCardListReaderGroups_Internal(hContext, (LPSTR) &mszGroupsA, pcchGroups);
Packit 1fb8d4
Packit 1fb8d4
	if (status == SCARD_S_SUCCESS)
Packit 1fb8d4
	{
Packit 1fb8d4
		*pcchGroups = ConvertToUnicode(CP_UTF8, 0, *pMszGroupsA, *pcchGroups, (WCHAR**) mszGroups, 0);
Packit 1fb8d4
		PCSC_AddMemoryBlock(hContext, mszGroups);
Packit 1fb8d4
		PCSC_SCardFreeMemory_Internal(hContext, *pMszGroupsA);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (!PCSC_UnlockCardContext(hContext))
Packit 1fb8d4
		return SCARD_E_INVALID_HANDLE;
Packit 1fb8d4
Packit 1fb8d4
	return status;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardListReaders_Internal(SCARDCONTEXT hContext,
Packit 1fb8d4
        LPCSTR mszGroups, LPSTR mszReaders, LPDWORD pcchReaders)
Packit 1fb8d4
{
Packit 1fb8d4
	LONG status = SCARD_S_SUCCESS;
Packit 1fb8d4
	BOOL pcchReadersAlloc = FALSE;
Packit 1fb8d4
	LPSTR* pMszReaders = (LPSTR*) mszReaders;
Packit 1fb8d4
	PCSC_DWORD pcsc_cchReaders = 0;
Packit 1fb8d4
Packit 1fb8d4
	if (!pcchReaders)
Packit 1fb8d4
		return SCARD_E_INVALID_PARAMETER;
Packit 1fb8d4
Packit 1fb8d4
	if (!g_PCSC.pfnSCardListReaders)
Packit 1fb8d4
		return SCARD_E_NO_SERVICE;
Packit 1fb8d4
Packit 1fb8d4
	mszGroups = NULL; /* mszGroups is not supported by pcsc-lite */
Packit 1fb8d4
Packit 1fb8d4
	if (*pcchReaders == SCARD_AUTOALLOCATE)
Packit 1fb8d4
		pcchReadersAlloc = TRUE;
Packit 1fb8d4
Packit 1fb8d4
	pcsc_cchReaders = pcchReadersAlloc ? PCSC_SCARD_AUTOALLOCATE : (PCSC_DWORD) * pcchReaders;
Packit 1fb8d4
Packit 1fb8d4
	if (pcchReadersAlloc && !g_SCardAutoAllocate)
Packit 1fb8d4
	{
Packit 1fb8d4
		pcsc_cchReaders = 0;
Packit 1fb8d4
		status = (LONG) g_PCSC.pfnSCardListReaders(hContext, mszGroups, NULL, &pcsc_cchReaders);
Packit 1fb8d4
Packit 1fb8d4
		if (status == SCARD_S_SUCCESS)
Packit 1fb8d4
		{
Packit 1fb8d4
			*pMszReaders = calloc(1, pcsc_cchReaders);
Packit 1fb8d4
Packit 1fb8d4
			if (!*pMszReaders)
Packit 1fb8d4
				return SCARD_E_NO_MEMORY;
Packit 1fb8d4
Packit 1fb8d4
			status = (LONG) g_PCSC.pfnSCardListReaders(hContext, mszGroups, *pMszReaders, &pcsc_cchReaders);
Packit 1fb8d4
Packit 1fb8d4
			if (status != SCARD_S_SUCCESS)
Packit 1fb8d4
				free(*pMszReaders);
Packit 1fb8d4
			else
Packit 1fb8d4
				PCSC_AddMemoryBlock(hContext, *pMszReaders);
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
	else
Packit 1fb8d4
	{
Packit 1fb8d4
		status = (LONG) g_PCSC.pfnSCardListReaders(hContext, mszGroups, mszReaders, &pcsc_cchReaders);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	status = PCSC_MapErrorCodeToWinSCard(status);
Packit 1fb8d4
	*pcchReaders = (DWORD) pcsc_cchReaders;
Packit 1fb8d4
	return status;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardListReadersA(SCARDCONTEXT hContext,
Packit 1fb8d4
        LPCSTR mszGroups, LPSTR mszReaders, LPDWORD pcchReaders)
Packit 1fb8d4
{
Packit 1fb8d4
	BOOL nullCardContext = FALSE;
Packit 1fb8d4
	LONG status = SCARD_S_SUCCESS;
Packit 1fb8d4
Packit 1fb8d4
	if (!g_PCSC.pfnSCardListReaders)
Packit 1fb8d4
		return SCARD_E_NO_SERVICE;
Packit 1fb8d4
Packit 1fb8d4
	if (!hContext)
Packit 1fb8d4
	{
Packit 1fb8d4
		status = PCSC_SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
Packit 1fb8d4
Packit 1fb8d4
		if (status != SCARD_S_SUCCESS)
Packit 1fb8d4
			return status;
Packit 1fb8d4
Packit 1fb8d4
		nullCardContext = TRUE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (!PCSC_LockCardContext(hContext))
Packit 1fb8d4
		return SCARD_E_INVALID_HANDLE;
Packit 1fb8d4
Packit 1fb8d4
	status = PCSC_SCardListReaders_Internal(hContext, mszGroups, mszReaders, pcchReaders);
Packit 1fb8d4
Packit 1fb8d4
	if (!PCSC_UnlockCardContext(hContext))
Packit 1fb8d4
		return SCARD_E_INVALID_HANDLE;
Packit 1fb8d4
Packit 1fb8d4
	if (nullCardContext)
Packit 1fb8d4
	{
Packit 1fb8d4
		status = PCSC_SCardReleaseContext(hContext);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return status;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardListReadersW(SCARDCONTEXT hContext,
Packit 1fb8d4
        LPCWSTR mszGroups, LPWSTR mszReaders, LPDWORD pcchReaders)
Packit 1fb8d4
{
Packit 1fb8d4
	LPSTR mszGroupsA = NULL;
Packit 1fb8d4
	LPSTR mszReadersA = NULL;
Packit 1fb8d4
	LPSTR* pMszReadersA = &mszReadersA;
Packit 1fb8d4
	LONG status = SCARD_S_SUCCESS;
Packit 1fb8d4
	BOOL nullCardContext = FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (!g_PCSC.pfnSCardListReaders)
Packit 1fb8d4
		return SCARD_E_NO_SERVICE;
Packit 1fb8d4
Packit 1fb8d4
	if (!hContext)
Packit 1fb8d4
	{
Packit 1fb8d4
		status = PCSC_SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
Packit 1fb8d4
Packit 1fb8d4
		if (status != SCARD_S_SUCCESS)
Packit 1fb8d4
			return status;
Packit 1fb8d4
Packit 1fb8d4
		nullCardContext = TRUE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (!PCSC_LockCardContext(hContext))
Packit 1fb8d4
		return SCARD_E_INVALID_HANDLE;
Packit 1fb8d4
Packit 1fb8d4
	mszGroups = NULL; /* mszGroups is not supported by pcsc-lite */
Packit 1fb8d4
Packit 1fb8d4
	if (mszGroups)
Packit 1fb8d4
		ConvertFromUnicode(CP_UTF8, 0, mszGroups, -1, (char**) &mszGroupsA, 0, NULL, NULL);
Packit 1fb8d4
Packit 1fb8d4
	status = PCSC_SCardListReaders_Internal(hContext, mszGroupsA, (LPSTR) &mszReadersA, pcchReaders);
Packit 1fb8d4
Packit 1fb8d4
	if (status == SCARD_S_SUCCESS)
Packit 1fb8d4
	{
Packit 1fb8d4
		*pcchReaders = ConvertToUnicode(CP_UTF8, 0, *pMszReadersA, *pcchReaders, (WCHAR**) mszReaders, 0);
Packit 1fb8d4
		PCSC_AddMemoryBlock(hContext, mszReaders);
Packit 1fb8d4
		PCSC_SCardFreeMemory_Internal(hContext, *pMszReadersA);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	free(mszGroupsA);
Packit 1fb8d4
Packit 1fb8d4
	if (!PCSC_UnlockCardContext(hContext))
Packit 1fb8d4
		return SCARD_E_INVALID_HANDLE;
Packit 1fb8d4
Packit 1fb8d4
	if (nullCardContext)
Packit 1fb8d4
	{
Packit 1fb8d4
		status = PCSC_SCardReleaseContext(hContext);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return status;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardListCardsA(SCARDCONTEXT hContext,
Packit 1fb8d4
        LPCBYTE pbAtr, LPCGUID rgquidInterfaces, DWORD cguidInterfaceCount, CHAR* mszCards,
Packit 1fb8d4
        LPDWORD pcchCards)
Packit 1fb8d4
{
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardListCardsW(SCARDCONTEXT hContext,
Packit 1fb8d4
        LPCBYTE pbAtr, LPCGUID rgquidInterfaces, DWORD cguidInterfaceCount, WCHAR* mszCards,
Packit 1fb8d4
        LPDWORD pcchCards)
Packit 1fb8d4
{
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardListInterfacesA(SCARDCONTEXT hContext,
Packit 1fb8d4
        LPCSTR szCard, LPGUID pguidInterfaces, LPDWORD pcguidInterfaces)
Packit 1fb8d4
{
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardListInterfacesW(SCARDCONTEXT hContext,
Packit 1fb8d4
        LPCWSTR szCard, LPGUID pguidInterfaces, LPDWORD pcguidInterfaces)
Packit 1fb8d4
{
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardGetProviderIdA(SCARDCONTEXT hContext,
Packit 1fb8d4
        LPCSTR szCard, LPGUID pguidProviderId)
Packit 1fb8d4
{
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardGetProviderIdW(SCARDCONTEXT hContext,
Packit 1fb8d4
        LPCWSTR szCard, LPGUID pguidProviderId)
Packit 1fb8d4
{
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardGetCardTypeProviderNameA(SCARDCONTEXT hContext,
Packit 1fb8d4
        LPCSTR szCardName, DWORD dwProviderId, CHAR* szProvider, LPDWORD pcchProvider)
Packit 1fb8d4
{
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardGetCardTypeProviderNameW(SCARDCONTEXT hContext,
Packit 1fb8d4
        LPCWSTR szCardName, DWORD dwProviderId, WCHAR* szProvider, LPDWORD pcchProvider)
Packit 1fb8d4
{
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardIntroduceReaderGroupA(SCARDCONTEXT hContext, LPCSTR szGroupName)
Packit 1fb8d4
{
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardIntroduceReaderGroupW(SCARDCONTEXT hContext, LPCWSTR szGroupName)
Packit 1fb8d4
{
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardForgetReaderGroupA(SCARDCONTEXT hContext, LPCSTR szGroupName)
Packit 1fb8d4
{
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardForgetReaderGroupW(SCARDCONTEXT hContext, LPCWSTR szGroupName)
Packit 1fb8d4
{
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardIntroduceReaderA(SCARDCONTEXT hContext,
Packit 1fb8d4
        LPCSTR szReaderName, LPCSTR szDeviceName)
Packit 1fb8d4
{
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardIntroduceReaderW(SCARDCONTEXT hContext,
Packit 1fb8d4
        LPCWSTR szReaderName, LPCWSTR szDeviceName)
Packit 1fb8d4
{
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardForgetReaderA(SCARDCONTEXT hContext, LPCSTR szReaderName)
Packit 1fb8d4
{
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardForgetReaderW(SCARDCONTEXT hContext, LPCWSTR szReaderName)
Packit 1fb8d4
{
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardAddReaderToGroupA(SCARDCONTEXT hContext,
Packit 1fb8d4
        LPCSTR szReaderName, LPCSTR szGroupName)
Packit 1fb8d4
{
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardAddReaderToGroupW(SCARDCONTEXT hContext,
Packit 1fb8d4
        LPCWSTR szReaderName, LPCWSTR szGroupName)
Packit 1fb8d4
{
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardRemoveReaderFromGroupA(SCARDCONTEXT hContext,
Packit 1fb8d4
        LPCSTR szReaderName, LPCSTR szGroupName)
Packit 1fb8d4
{
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardRemoveReaderFromGroupW(SCARDCONTEXT hContext,
Packit 1fb8d4
        LPCWSTR szReaderName, LPCWSTR szGroupName)
Packit 1fb8d4
{
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardIntroduceCardTypeA(SCARDCONTEXT hContext,
Packit 1fb8d4
        LPCSTR szCardName, LPCGUID pguidPrimaryProvider, LPCGUID rgguidInterfaces,
Packit 1fb8d4
        DWORD dwInterfaceCount, LPCBYTE pbAtr, LPCBYTE pbAtrMask, DWORD cbAtrLen)
Packit 1fb8d4
{
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardIntroduceCardTypeW(SCARDCONTEXT hContext,
Packit 1fb8d4
        LPCWSTR szCardName, LPCGUID pguidPrimaryProvider, LPCGUID rgguidInterfaces,
Packit 1fb8d4
        DWORD dwInterfaceCount, LPCBYTE pbAtr, LPCBYTE pbAtrMask, DWORD cbAtrLen)
Packit 1fb8d4
{
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardSetCardTypeProviderNameA(SCARDCONTEXT hContext,
Packit 1fb8d4
        LPCSTR szCardName, DWORD dwProviderId, LPCSTR szProvider)
Packit 1fb8d4
{
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardSetCardTypeProviderNameW(SCARDCONTEXT hContext,
Packit 1fb8d4
        LPCWSTR szCardName, DWORD dwProviderId, LPCWSTR szProvider)
Packit 1fb8d4
{
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardForgetCardTypeA(SCARDCONTEXT hContext, LPCSTR szCardName)
Packit 1fb8d4
{
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardForgetCardTypeW(SCARDCONTEXT hContext, LPCWSTR szCardName)
Packit 1fb8d4
{
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardFreeMemory_Internal(SCARDCONTEXT hContext, LPCVOID pvMem)
Packit 1fb8d4
{
Packit 1fb8d4
	LONG status = SCARD_S_SUCCESS;
Packit 1fb8d4
Packit 1fb8d4
	if (PCSC_RemoveMemoryBlock(hContext, (void*) pvMem))
Packit 1fb8d4
	{
Packit 1fb8d4
		free((void*) pvMem);
Packit 1fb8d4
		status = SCARD_S_SUCCESS;
Packit 1fb8d4
	}
Packit 1fb8d4
	else
Packit 1fb8d4
	{
Packit 1fb8d4
		if (g_PCSC.pfnSCardFreeMemory)
Packit 1fb8d4
		{
Packit 1fb8d4
			status = (LONG) g_PCSC.pfnSCardFreeMemory(hContext, pvMem);
Packit 1fb8d4
			status = PCSC_MapErrorCodeToWinSCard(status);
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return status;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardFreeMemory(SCARDCONTEXT hContext, LPCVOID pvMem)
Packit 1fb8d4
{
Packit 1fb8d4
	LONG status = SCARD_S_SUCCESS;
Packit 1fb8d4
Packit 1fb8d4
	if (hContext)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (!PCSC_LockCardContext(hContext))
Packit 1fb8d4
			return SCARD_E_INVALID_HANDLE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	status = PCSC_SCardFreeMemory_Internal(hContext, pvMem);
Packit 1fb8d4
Packit 1fb8d4
	if (hContext)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (!PCSC_UnlockCardContext(hContext))
Packit 1fb8d4
			return SCARD_E_INVALID_HANDLE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return status;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI HANDLE WINAPI PCSC_SCardAccessStartedEvent(void)
Packit 1fb8d4
{
Packit 1fb8d4
	LONG status = 0;
Packit 1fb8d4
	SCARDCONTEXT hContext = 0;
Packit 1fb8d4
	status = PCSC_SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
Packit 1fb8d4
Packit 1fb8d4
	if (status != SCARD_S_SUCCESS)
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
Packit 1fb8d4
	status = PCSC_SCardReleaseContext(hContext);
Packit 1fb8d4
Packit 1fb8d4
	if (status != SCARD_S_SUCCESS)
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
Packit 1fb8d4
	if (!g_StartedEvent)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (!(g_StartedEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
Packit 1fb8d4
			return NULL;
Packit 1fb8d4
Packit 1fb8d4
		if (!SetEvent(g_StartedEvent))
Packit 1fb8d4
		{
Packit 1fb8d4
			CloseHandle(g_StartedEvent);
Packit 1fb8d4
			return NULL;
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	g_StartedEventRefCount++;
Packit 1fb8d4
	return g_StartedEvent;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI void WINAPI PCSC_SCardReleaseStartedEvent(void)
Packit 1fb8d4
{
Packit 1fb8d4
	g_StartedEventRefCount--;
Packit 1fb8d4
Packit 1fb8d4
	if (g_StartedEventRefCount == 0)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (g_StartedEvent)
Packit 1fb8d4
		{
Packit 1fb8d4
			CloseHandle(g_StartedEvent);
Packit 1fb8d4
			g_StartedEvent = NULL;
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardLocateCardsA(SCARDCONTEXT hContext,
Packit 1fb8d4
        LPCSTR mszCards, LPSCARD_READERSTATEA rgReaderStates, DWORD cReaders)
Packit 1fb8d4
{
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardLocateCardsW(SCARDCONTEXT hContext,
Packit 1fb8d4
        LPCWSTR mszCards, LPSCARD_READERSTATEW rgReaderStates, DWORD cReaders)
Packit 1fb8d4
{
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardLocateCardsByATRA(SCARDCONTEXT hContext,
Packit 1fb8d4
        LPSCARD_ATRMASK rgAtrMasks, DWORD cAtrs, LPSCARD_READERSTATEA rgReaderStates, DWORD cReaders)
Packit 1fb8d4
{
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardLocateCardsByATRW(SCARDCONTEXT hContext,
Packit 1fb8d4
        LPSCARD_ATRMASK rgAtrMasks, DWORD cAtrs, LPSCARD_READERSTATEW rgReaderStates, DWORD cReaders)
Packit 1fb8d4
{
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardGetStatusChange_Internal(SCARDCONTEXT hContext,
Packit 1fb8d4
        DWORD dwTimeout, LPSCARD_READERSTATEA rgReaderStates, DWORD cReaders)
Packit 1fb8d4
{
Packit 1fb8d4
	PCSC_DWORD i, j;
Packit 1fb8d4
	int* map;
Packit 1fb8d4
	PCSC_DWORD cMappedReaders;
Packit 1fb8d4
	PCSC_SCARD_READERSTATE* states;
Packit 1fb8d4
	LONG status = SCARD_S_SUCCESS;
Packit 1fb8d4
	PCSC_DWORD pcsc_dwTimeout = (PCSC_DWORD) dwTimeout;
Packit 1fb8d4
	PCSC_DWORD pcsc_cReaders = (PCSC_DWORD) cReaders;
Packit 1fb8d4
Packit 1fb8d4
	if (!g_PCSC.pfnSCardGetStatusChange)
Packit 1fb8d4
		return SCARD_E_NO_SERVICE;
Packit 1fb8d4
Packit 1fb8d4
	if (!cReaders)
Packit 1fb8d4
		return SCARD_S_SUCCESS;
Packit 1fb8d4
Packit 1fb8d4
	/* pcsc-lite interprets value 0 as INFINITE, work around the problem by using value 1 */
Packit 1fb8d4
	pcsc_dwTimeout = pcsc_dwTimeout ? pcsc_dwTimeout : 1;
Packit 1fb8d4
	/**
Packit 1fb8d4
	 * Apple's SmartCard Services (not vanilla pcsc-lite) appears to have trouble with the
Packit 1fb8d4
	 * "\\\\?PnP?\\Notification" reader name. I am always getting EXC_BAD_ACCESS with it.
Packit 1fb8d4
	 *
Packit 1fb8d4
	 * The SmartCard Services tarballs can be found here:
Packit 1fb8d4
	 * http://opensource.apple.com/tarballs/SmartCardServices/
Packit 1fb8d4
	 *
Packit 1fb8d4
	 * The "\\\\?PnP?\\Notification" string cannot be found anywhere in the sources,
Packit 1fb8d4
	 * while this string is present in the vanilla pcsc-lite sources.
Packit 1fb8d4
	 *
Packit 1fb8d4
	 * To work around this apparent lack of "\\\\?PnP?\\Notification" support,
Packit 1fb8d4
	 * we have to filter rgReaderStates to exclude the special PnP reader name.
Packit 1fb8d4
	 */
Packit 1fb8d4
	map = (int*) calloc(pcsc_cReaders, sizeof(int));
Packit 1fb8d4
Packit 1fb8d4
	if (!map)
Packit 1fb8d4
		return SCARD_E_NO_MEMORY;
Packit 1fb8d4
Packit 1fb8d4
	states = (PCSC_SCARD_READERSTATE*) calloc(pcsc_cReaders, sizeof(PCSC_SCARD_READERSTATE));
Packit 1fb8d4
Packit 1fb8d4
	if (!states)
Packit 1fb8d4
	{
Packit 1fb8d4
		free(map);
Packit 1fb8d4
		return SCARD_E_NO_MEMORY;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	for (i = j = 0; i < pcsc_cReaders; i++)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (!g_PnP_Notification)
Packit 1fb8d4
		{
Packit 1fb8d4
			if (0 == _stricmp(rgReaderStates[i].szReader, SMARTCARD_PNP_NOTIFICATION_A))
Packit 1fb8d4
			{
Packit 1fb8d4
				map[i] = -1; /* unmapped */
Packit 1fb8d4
				continue;
Packit 1fb8d4
			}
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		map[i] = j;
Packit 1fb8d4
		states[j].szReader = rgReaderStates[i].szReader;
Packit 1fb8d4
		states[j].dwCurrentState = rgReaderStates[i].dwCurrentState;
Packit 1fb8d4
		states[j].pvUserData = rgReaderStates[i].pvUserData;
Packit 1fb8d4
		states[j].dwEventState = rgReaderStates[i].dwEventState;
Packit 1fb8d4
		states[j].cbAtr = rgReaderStates[i].cbAtr;
Packit 1fb8d4
		CopyMemory(&(states[j].rgbAtr), &(rgReaderStates[i].rgbAtr), PCSC_MAX_ATR_SIZE);
Packit 1fb8d4
		j++;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	cMappedReaders = j;
Packit 1fb8d4
Packit 1fb8d4
	if (cMappedReaders > 0)
Packit 1fb8d4
	{
Packit 1fb8d4
		status = (LONG) g_PCSC.pfnSCardGetStatusChange(hContext,
Packit 1fb8d4
		         pcsc_dwTimeout, states, cMappedReaders);
Packit 1fb8d4
		status = PCSC_MapErrorCodeToWinSCard(status);
Packit 1fb8d4
	}
Packit 1fb8d4
	else
Packit 1fb8d4
	{
Packit 1fb8d4
		status = SCARD_S_SUCCESS;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	for (i = 0; i < pcsc_cReaders; i++)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (map[i] < 0)
Packit 1fb8d4
			continue; /* unmapped */
Packit 1fb8d4
Packit 1fb8d4
		j = map[i];
Packit 1fb8d4
		rgReaderStates[i].dwCurrentState = states[j].dwCurrentState;
Packit 1fb8d4
		rgReaderStates[i].cbAtr = states[j].cbAtr;
Packit 1fb8d4
		CopyMemory(&(rgReaderStates[i].rgbAtr), &(states[j].rgbAtr), PCSC_MAX_ATR_SIZE);
Packit 1fb8d4
		rgReaderStates[i].dwEventState = states[j].dwEventState;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	free(map);
Packit 1fb8d4
	free(states);
Packit 1fb8d4
	return status;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardGetStatusChangeA(SCARDCONTEXT hContext,
Packit 1fb8d4
        DWORD dwTimeout, LPSCARD_READERSTATEA rgReaderStates, DWORD cReaders)
Packit 1fb8d4
{
Packit 1fb8d4
	LONG status = SCARD_S_SUCCESS;
Packit 1fb8d4
Packit 1fb8d4
	if (!PCSC_LockCardContext(hContext))
Packit 1fb8d4
		return SCARD_E_INVALID_HANDLE;
Packit 1fb8d4
Packit 1fb8d4
	status = PCSC_SCardGetStatusChange_Internal(hContext, dwTimeout, rgReaderStates, cReaders);
Packit 1fb8d4
Packit 1fb8d4
	if (!PCSC_UnlockCardContext(hContext))
Packit 1fb8d4
		return SCARD_E_INVALID_HANDLE;
Packit 1fb8d4
Packit 1fb8d4
	return status;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardGetStatusChangeW(SCARDCONTEXT hContext,
Packit 1fb8d4
        DWORD dwTimeout, LPSCARD_READERSTATEW rgReaderStates, DWORD cReaders)
Packit 1fb8d4
{
Packit 1fb8d4
	DWORD index;
Packit 1fb8d4
	LPSCARD_READERSTATEA states;
Packit 1fb8d4
	LONG status = SCARD_S_SUCCESS;
Packit 1fb8d4
Packit 1fb8d4
	if (!g_PCSC.pfnSCardGetStatusChange)
Packit 1fb8d4
		return SCARD_E_NO_SERVICE;
Packit 1fb8d4
Packit 1fb8d4
	if (!PCSC_LockCardContext(hContext))
Packit 1fb8d4
		return SCARD_E_INVALID_HANDLE;
Packit 1fb8d4
Packit 1fb8d4
	states = (LPSCARD_READERSTATEA) calloc(cReaders, sizeof(SCARD_READERSTATEA));
Packit 1fb8d4
Packit 1fb8d4
	if (!states)
Packit 1fb8d4
	{
Packit 1fb8d4
		PCSC_UnlockCardContext(hContext);
Packit 1fb8d4
		return SCARD_E_NO_MEMORY;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	for (index = 0; index < cReaders; index++)
Packit 1fb8d4
	{
Packit 1fb8d4
		states[index].szReader = NULL;
Packit 1fb8d4
		ConvertFromUnicode(CP_UTF8, 0, rgReaderStates[index].szReader, -1,
Packit 1fb8d4
		                   (char**) & (states[index].szReader), 0, NULL, NULL);
Packit 1fb8d4
		states[index].pvUserData = rgReaderStates[index].pvUserData;
Packit 1fb8d4
		states[index].dwCurrentState = rgReaderStates[index].dwCurrentState;
Packit 1fb8d4
		states[index].dwEventState = rgReaderStates[index].dwEventState;
Packit 1fb8d4
		states[index].cbAtr = rgReaderStates[index].cbAtr;
Packit 1fb8d4
		CopyMemory(&(states[index].rgbAtr), &(rgReaderStates[index].rgbAtr), 36);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	status = PCSC_SCardGetStatusChange_Internal(hContext, dwTimeout, states, cReaders);
Packit 1fb8d4
Packit 1fb8d4
	for (index = 0; index < cReaders; index++)
Packit 1fb8d4
	{
Packit 1fb8d4
		free((void*) states[index].szReader);
Packit 1fb8d4
		rgReaderStates[index].pvUserData = states[index].pvUserData;
Packit 1fb8d4
		rgReaderStates[index].dwCurrentState = states[index].dwCurrentState;
Packit 1fb8d4
		rgReaderStates[index].dwEventState = states[index].dwEventState;
Packit 1fb8d4
		rgReaderStates[index].cbAtr = states[index].cbAtr;
Packit 1fb8d4
		CopyMemory(&(rgReaderStates[index].rgbAtr), &(states[index].rgbAtr), 36);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	free(states);
Packit 1fb8d4
Packit 1fb8d4
	if (!PCSC_UnlockCardContext(hContext))
Packit 1fb8d4
		return SCARD_E_INVALID_HANDLE;
Packit 1fb8d4
Packit 1fb8d4
	return status;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardCancel(SCARDCONTEXT hContext)
Packit 1fb8d4
{
Packit 1fb8d4
	LONG status = SCARD_S_SUCCESS;
Packit 1fb8d4
Packit 1fb8d4
	if (!g_PCSC.pfnSCardCancel)
Packit 1fb8d4
		return SCARD_E_NO_SERVICE;
Packit 1fb8d4
Packit 1fb8d4
	status = (LONG) g_PCSC.pfnSCardCancel(hContext);
Packit 1fb8d4
	status = PCSC_MapErrorCodeToWinSCard(status);
Packit 1fb8d4
	return status;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardConnect_Internal(SCARDCONTEXT hContext,
Packit 1fb8d4
        LPCSTR szReader, DWORD dwShareMode, DWORD dwPreferredProtocols,
Packit 1fb8d4
        LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol)
Packit 1fb8d4
{
Packit 1fb8d4
	BOOL shared;
Packit 1fb8d4
	char* szReaderPCSC;
Packit 1fb8d4
	LONG status = SCARD_S_SUCCESS;
Packit 1fb8d4
	PCSC_SCARDHANDLE* pCard = NULL;
Packit 1fb8d4
	PCSC_DWORD pcsc_dwShareMode = (PCSC_DWORD) dwShareMode;
Packit 1fb8d4
	PCSC_DWORD pcsc_dwPreferredProtocols = 0;
Packit 1fb8d4
	PCSC_DWORD pcsc_dwActiveProtocol = 0;
Packit 1fb8d4
Packit 1fb8d4
	if (!g_PCSC.pfnSCardConnect)
Packit 1fb8d4
		return SCARD_E_NO_SERVICE;
Packit 1fb8d4
Packit 1fb8d4
	shared = (dwShareMode == SCARD_SHARE_DIRECT) ? TRUE : FALSE;
Packit 1fb8d4
	PCSC_WaitForCardAccess(hContext, 0, shared);
Packit 1fb8d4
	szReaderPCSC = (char*) szReader;
Packit 1fb8d4
Packit 1fb8d4
	/**
Packit 1fb8d4
	 * As stated here : https://pcsclite.alioth.debian.org/api/group__API.html#ga4e515829752e0a8dbc4d630696a8d6a5
Packit 1fb8d4
	 * SCARD_PROTOCOL_UNDEFINED is valid for dwPreferredProtocols (only) if dwShareMode == SCARD_SHARE_DIRECT
Packit 1fb8d4
	 * and allows to send control commands to the reader (with SCardControl()) even if a card is not present in the reader
Packit 1fb8d4
	 */
Packit 1fb8d4
	if (pcsc_dwShareMode == SCARD_SHARE_DIRECT && dwPreferredProtocols == SCARD_PROTOCOL_UNDEFINED)
Packit 1fb8d4
		pcsc_dwPreferredProtocols = SCARD_PROTOCOL_UNDEFINED;
Packit 1fb8d4
	else
Packit 1fb8d4
		pcsc_dwPreferredProtocols = (PCSC_DWORD) PCSC_ConvertProtocolsFromWinSCard(dwPreferredProtocols);
Packit 1fb8d4
Packit 1fb8d4
	status = (LONG) g_PCSC.pfnSCardConnect(hContext, szReaderPCSC,
Packit 1fb8d4
	                                       pcsc_dwShareMode, pcsc_dwPreferredProtocols, phCard, &pcsc_dwActiveProtocol);
Packit 1fb8d4
	status = PCSC_MapErrorCodeToWinSCard(status);
Packit 1fb8d4
Packit 1fb8d4
	if (status == SCARD_S_SUCCESS)
Packit 1fb8d4
	{
Packit 1fb8d4
		pCard = PCSC_ConnectCardHandle(hContext, *phCard);
Packit 1fb8d4
		*pdwActiveProtocol = PCSC_ConvertProtocolsToWinSCard((DWORD) pcsc_dwActiveProtocol);
Packit 1fb8d4
		pCard->shared = shared;
Packit 1fb8d4
		PCSC_WaitForCardAccess(hContext, pCard->hSharedContext, shared);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return status;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardConnectA(SCARDCONTEXT hContext,
Packit 1fb8d4
        LPCSTR szReader, DWORD dwShareMode, DWORD dwPreferredProtocols,
Packit 1fb8d4
        LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol)
Packit 1fb8d4
{
Packit 1fb8d4
	LONG status = SCARD_S_SUCCESS;
Packit 1fb8d4
Packit 1fb8d4
	if (!PCSC_LockCardContext(hContext))
Packit 1fb8d4
		return SCARD_E_INVALID_HANDLE;
Packit 1fb8d4
Packit 1fb8d4
	status = PCSC_SCardConnect_Internal(hContext, szReader, dwShareMode,
Packit 1fb8d4
	                                    dwPreferredProtocols, phCard, pdwActiveProtocol);
Packit 1fb8d4
Packit 1fb8d4
	if (!PCSC_UnlockCardContext(hContext))
Packit 1fb8d4
		return SCARD_E_INVALID_HANDLE;
Packit 1fb8d4
Packit 1fb8d4
	return status;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardConnectW(SCARDCONTEXT hContext,
Packit 1fb8d4
        LPCWSTR szReader, DWORD dwShareMode, DWORD dwPreferredProtocols,
Packit 1fb8d4
        LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol)
Packit 1fb8d4
{
Packit 1fb8d4
	LPSTR szReaderA = NULL;
Packit 1fb8d4
	LONG status = SCARD_S_SUCCESS;
Packit 1fb8d4
Packit 1fb8d4
	if (!PCSC_LockCardContext(hContext))
Packit 1fb8d4
		return SCARD_E_INVALID_HANDLE;
Packit 1fb8d4
Packit 1fb8d4
	if (szReader)
Packit 1fb8d4
		ConvertFromUnicode(CP_UTF8, 0, szReader, -1, &szReaderA, 0, NULL, NULL);
Packit 1fb8d4
Packit 1fb8d4
	status = PCSC_SCardConnect_Internal(hContext, szReaderA, dwShareMode,
Packit 1fb8d4
	                                    dwPreferredProtocols, phCard, pdwActiveProtocol);
Packit 1fb8d4
	free(szReaderA);
Packit 1fb8d4
Packit 1fb8d4
	if (!PCSC_UnlockCardContext(hContext))
Packit 1fb8d4
		return SCARD_E_INVALID_HANDLE;
Packit 1fb8d4
Packit 1fb8d4
	return status;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardReconnect(SCARDHANDLE hCard,
Packit 1fb8d4
        DWORD dwShareMode, DWORD dwPreferredProtocols, DWORD dwInitialization, LPDWORD pdwActiveProtocol)
Packit 1fb8d4
{
Packit 1fb8d4
	BOOL shared;
Packit 1fb8d4
	LONG status = SCARD_S_SUCCESS;
Packit 1fb8d4
	PCSC_DWORD pcsc_dwShareMode = (PCSC_DWORD) dwShareMode;
Packit 1fb8d4
	PCSC_DWORD pcsc_dwPreferredProtocols = 0;
Packit 1fb8d4
	PCSC_DWORD pcsc_dwInitialization = (PCSC_DWORD) dwInitialization;
Packit 1fb8d4
	PCSC_DWORD pcsc_dwActiveProtocol = 0;
Packit 1fb8d4
Packit 1fb8d4
	if (!g_PCSC.pfnSCardReconnect)
Packit 1fb8d4
		return SCARD_E_NO_SERVICE;
Packit 1fb8d4
Packit 1fb8d4
	shared = (dwShareMode == SCARD_SHARE_DIRECT) ? TRUE : FALSE;
Packit 1fb8d4
	PCSC_WaitForCardAccess(0, hCard, shared);
Packit 1fb8d4
	pcsc_dwPreferredProtocols = (PCSC_DWORD) PCSC_ConvertProtocolsFromWinSCard(dwPreferredProtocols);
Packit 1fb8d4
	status = (LONG) g_PCSC.pfnSCardReconnect(hCard, pcsc_dwShareMode,
Packit 1fb8d4
	         pcsc_dwPreferredProtocols, pcsc_dwInitialization, &pcsc_dwActiveProtocol);
Packit 1fb8d4
	status = PCSC_MapErrorCodeToWinSCard(status);
Packit 1fb8d4
	*pdwActiveProtocol = PCSC_ConvertProtocolsToWinSCard((DWORD) pcsc_dwActiveProtocol);
Packit 1fb8d4
	return status;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
Packit 1fb8d4
{
Packit 1fb8d4
	LONG status = SCARD_S_SUCCESS;
Packit 1fb8d4
	PCSC_DWORD pcsc_dwDisposition = (PCSC_DWORD) dwDisposition;
Packit 1fb8d4
Packit 1fb8d4
	if (!g_PCSC.pfnSCardDisconnect)
Packit 1fb8d4
		return SCARD_E_NO_SERVICE;
Packit 1fb8d4
Packit 1fb8d4
	status = (LONG) g_PCSC.pfnSCardDisconnect(hCard, pcsc_dwDisposition);
Packit 1fb8d4
	status = PCSC_MapErrorCodeToWinSCard(status);
Packit 1fb8d4
Packit 1fb8d4
	if (status == SCARD_S_SUCCESS)
Packit 1fb8d4
	{
Packit 1fb8d4
		PCSC_DisconnectCardHandle(hCard);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	PCSC_ReleaseCardAccess(0, hCard);
Packit 1fb8d4
	return status;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardBeginTransaction(SCARDHANDLE hCard)
Packit 1fb8d4
{
Packit 1fb8d4
	LONG status = SCARD_S_SUCCESS;
Packit 1fb8d4
	PCSC_SCARDHANDLE* pCard = NULL;
Packit 1fb8d4
	PCSC_SCARDCONTEXT* pContext = NULL;
Packit 1fb8d4
Packit 1fb8d4
	if (!g_PCSC.pfnSCardBeginTransaction)
Packit 1fb8d4
		return SCARD_E_NO_SERVICE;
Packit 1fb8d4
Packit 1fb8d4
	pCard = PCSC_GetCardHandleData(hCard);
Packit 1fb8d4
Packit 1fb8d4
	if (!pCard)
Packit 1fb8d4
		return SCARD_E_INVALID_HANDLE;
Packit 1fb8d4
Packit 1fb8d4
	pContext = PCSC_GetCardContextData(pCard->hSharedContext);
Packit 1fb8d4
Packit 1fb8d4
	if (!pContext)
Packit 1fb8d4
		return SCARD_E_INVALID_HANDLE;
Packit 1fb8d4
Packit 1fb8d4
	if (pContext->isTransactionLocked)
Packit 1fb8d4
		return SCARD_S_SUCCESS; /* disable nested transactions */
Packit 1fb8d4
Packit 1fb8d4
	status = (LONG) g_PCSC.pfnSCardBeginTransaction(hCard);
Packit 1fb8d4
	status = PCSC_MapErrorCodeToWinSCard(status);
Packit 1fb8d4
	pContext->isTransactionLocked = TRUE;
Packit 1fb8d4
	return status;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
Packit 1fb8d4
{
Packit 1fb8d4
	LONG status = SCARD_S_SUCCESS;
Packit 1fb8d4
	PCSC_SCARDHANDLE* pCard = NULL;
Packit 1fb8d4
	PCSC_SCARDCONTEXT* pContext = NULL;
Packit 1fb8d4
	PCSC_DWORD pcsc_dwDisposition = (PCSC_DWORD) dwDisposition;
Packit 1fb8d4
Packit 1fb8d4
	if (!g_PCSC.pfnSCardEndTransaction)
Packit 1fb8d4
		return SCARD_E_NO_SERVICE;
Packit 1fb8d4
Packit 1fb8d4
	pCard = PCSC_GetCardHandleData(hCard);
Packit 1fb8d4
Packit 1fb8d4
	if (!pCard)
Packit 1fb8d4
		return SCARD_E_INVALID_HANDLE;
Packit 1fb8d4
Packit 1fb8d4
	pContext = PCSC_GetCardContextData(pCard->hSharedContext);
Packit 1fb8d4
Packit 1fb8d4
	if (!pContext)
Packit 1fb8d4
		return SCARD_E_INVALID_HANDLE;
Packit 1fb8d4
Packit 1fb8d4
	PCSC_ReleaseCardAccess(0, hCard);
Packit 1fb8d4
Packit 1fb8d4
	if (!pContext->isTransactionLocked)
Packit 1fb8d4
		return SCARD_S_SUCCESS; /* disable nested transactions */
Packit 1fb8d4
Packit 1fb8d4
	status = (LONG) g_PCSC.pfnSCardEndTransaction(hCard, pcsc_dwDisposition);
Packit 1fb8d4
	status = PCSC_MapErrorCodeToWinSCard(status);
Packit 1fb8d4
	pContext->isTransactionLocked = FALSE;
Packit 1fb8d4
	return status;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardCancelTransaction(SCARDHANDLE hCard)
Packit 1fb8d4
{
Packit 1fb8d4
	return SCARD_S_SUCCESS;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardState(SCARDHANDLE hCard,
Packit 1fb8d4
                                        LPDWORD pdwState, LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
Packit 1fb8d4
{
Packit 1fb8d4
	PCSC_DWORD cchReaderLen;
Packit 1fb8d4
	SCARDCONTEXT hContext = 0;
Packit 1fb8d4
	LPSTR mszReaderNames = NULL;
Packit 1fb8d4
	LONG status = SCARD_S_SUCCESS;
Packit 1fb8d4
	PCSC_SCARDHANDLE* pCard = NULL;
Packit 1fb8d4
	PCSC_DWORD pcsc_dwState = 0;
Packit 1fb8d4
	PCSC_DWORD pcsc_dwProtocol = 0;
Packit 1fb8d4
	PCSC_DWORD pcsc_cbAtrLen = (PCSC_DWORD) * pcbAtrLen;
Packit 1fb8d4
Packit 1fb8d4
	if (!g_PCSC.pfnSCardStatus)
Packit 1fb8d4
		return SCARD_E_NO_SERVICE;
Packit 1fb8d4
Packit 1fb8d4
	pCard = PCSC_GetCardHandleData(hCard);
Packit 1fb8d4
Packit 1fb8d4
	if (!pCard)
Packit 1fb8d4
		return SCARD_E_INVALID_VALUE;
Packit 1fb8d4
Packit 1fb8d4
	PCSC_WaitForCardAccess(0, hCard, pCard->shared);
Packit 1fb8d4
	hContext = PCSC_GetCardContextFromHandle(hCard);
Packit 1fb8d4
Packit 1fb8d4
	if (!hContext)
Packit 1fb8d4
		return SCARD_E_INVALID_VALUE;
Packit 1fb8d4
Packit 1fb8d4
	cchReaderLen = SCARD_AUTOALLOCATE;
Packit 1fb8d4
	status = (LONG) g_PCSC.pfnSCardStatus(hCard, (LPSTR) &mszReaderNames, &cchReaderLen,
Packit 1fb8d4
	                                      &pcsc_dwState, &pcsc_dwProtocol, pbAtr, &pcsc_cbAtrLen);
Packit 1fb8d4
	status = PCSC_MapErrorCodeToWinSCard(status);
Packit 1fb8d4
Packit 1fb8d4
	if (mszReaderNames)
Packit 1fb8d4
		PCSC_SCardFreeMemory_Internal(hContext, mszReaderNames);
Packit 1fb8d4
Packit 1fb8d4
	*pdwState = (DWORD) pcsc_dwState;
Packit 1fb8d4
	*pdwProtocol = PCSC_ConvertProtocolsToWinSCard((DWORD) pcsc_dwProtocol);
Packit 1fb8d4
	*pcbAtrLen = (DWORD) pcsc_cbAtrLen;
Packit 1fb8d4
	return status;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/*
Packit 1fb8d4
 * PCSC returns a string but Windows SCardStatus requires the return to be a multi string.
Packit 1fb8d4
 * Therefore extra length checks and additional buffer allocation is required
Packit 1fb8d4
 */
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardStatus_Internal(SCARDHANDLE hCard,
Packit 1fb8d4
        LPSTR mszReaderNames, LPDWORD pcchReaderLen, LPDWORD pdwState,
Packit 1fb8d4
        LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen, BOOL unicode)
Packit 1fb8d4
{
Packit 1fb8d4
	PCSC_SCARDHANDLE* pCard = NULL;
Packit 1fb8d4
	SCARDCONTEXT hContext;
Packit 1fb8d4
	LONG status;
Packit 1fb8d4
	PCSC_DWORD pcsc_cchReaderLen = 0;
Packit 1fb8d4
	PCSC_DWORD pcsc_cbAtrLen = 0;
Packit 1fb8d4
	PCSC_DWORD pcsc_dwState = 0;
Packit 1fb8d4
	PCSC_DWORD pcsc_dwProtocol = 0;
Packit 1fb8d4
	BOOL allocateReader = FALSE;
Packit 1fb8d4
	BOOL allocateAtr = FALSE;
Packit 1fb8d4
	LPSTR readerNames = mszReaderNames;
Packit 1fb8d4
	LPBYTE atr = pbAtr;
Packit 1fb8d4
	LPSTR tReader = NULL;
Packit 1fb8d4
	LPBYTE tATR = NULL;
Packit 1fb8d4
Packit 1fb8d4
	if (!g_PCSC.pfnSCardStatus)
Packit 1fb8d4
		return SCARD_E_NO_SERVICE;
Packit 1fb8d4
Packit 1fb8d4
	pCard = PCSC_GetCardHandleData(hCard);
Packit 1fb8d4
Packit 1fb8d4
	if (!pCard)
Packit 1fb8d4
		return SCARD_E_INVALID_VALUE;
Packit 1fb8d4
Packit 1fb8d4
	PCSC_WaitForCardAccess(0, hCard, pCard->shared);
Packit 1fb8d4
	hContext = PCSC_GetCardContextFromHandle(hCard);
Packit 1fb8d4
Packit 1fb8d4
	if (!hContext)
Packit 1fb8d4
		return SCARD_E_INVALID_VALUE;
Packit 1fb8d4
Packit 1fb8d4
	status = (LONG) g_PCSC.pfnSCardStatus(hCard, NULL, &pcsc_cchReaderLen, NULL, NULL, NULL,
Packit 1fb8d4
	                                      &pcsc_cbAtrLen);
Packit 1fb8d4
Packit 1fb8d4
	if (status != STATUS_SUCCESS)
Packit 1fb8d4
		return PCSC_MapErrorCodeToWinSCard(status);
Packit 1fb8d4
Packit 1fb8d4
	pcsc_cchReaderLen++;
Packit 1fb8d4
Packit 1fb8d4
	if (unicode)
Packit 1fb8d4
		pcsc_cchReaderLen *= 2;
Packit 1fb8d4
Packit 1fb8d4
	if (pcchReaderLen)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (*pcchReaderLen == SCARD_AUTOALLOCATE)
Packit 1fb8d4
			allocateReader = TRUE;
Packit 1fb8d4
		else if (mszReaderNames && (*pcchReaderLen < pcsc_cchReaderLen))
Packit 1fb8d4
			return SCARD_E_INSUFFICIENT_BUFFER;
Packit 1fb8d4
		else
Packit 1fb8d4
			pcsc_cchReaderLen = *pcchReaderLen;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (pcbAtrLen)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (*pcbAtrLen == SCARD_AUTOALLOCATE)
Packit 1fb8d4
			allocateAtr = TRUE;
Packit 1fb8d4
		else if (pbAtr && (*pcbAtrLen < pcsc_cbAtrLen))
Packit 1fb8d4
			return SCARD_E_INSUFFICIENT_BUFFER;
Packit 1fb8d4
		else
Packit 1fb8d4
			pcsc_cbAtrLen = *pcbAtrLen;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (allocateReader && pcsc_cchReaderLen > 0 && mszReaderNames)
Packit 1fb8d4
	{
Packit 1fb8d4
#ifdef __MACOSX__
Packit 1fb8d4
Packit 1fb8d4
		/**
Packit 1fb8d4
		     * Workaround for SCardStatus Bug in MAC OS X Yosemite
Packit 1fb8d4
		     */
Packit 1fb8d4
		if (OSXVersion == 0x10100000)
Packit 1fb8d4
			pcsc_cchReaderLen++;
Packit 1fb8d4
Packit 1fb8d4
#endif
Packit 1fb8d4
		tReader = calloc(1, pcsc_cchReaderLen);
Packit 1fb8d4
Packit 1fb8d4
		if (!tReader)
Packit 1fb8d4
		{
Packit 1fb8d4
			status = ERROR_NOT_ENOUGH_MEMORY;
Packit 1fb8d4
			goto out_fail;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		readerNames = tReader;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (allocateAtr && pcsc_cbAtrLen > 0 && pbAtr)
Packit 1fb8d4
	{
Packit 1fb8d4
		tATR = calloc(1, pcsc_cbAtrLen);
Packit 1fb8d4
Packit 1fb8d4
		if (!tATR)
Packit 1fb8d4
		{
Packit 1fb8d4
			status = ERROR_NOT_ENOUGH_MEMORY;
Packit 1fb8d4
			goto out_fail;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		atr = tATR;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	status = (LONG) g_PCSC.pfnSCardStatus(hCard, readerNames, &pcsc_cchReaderLen, &pcsc_dwState,
Packit 1fb8d4
	                                      &pcsc_dwProtocol, atr,
Packit 1fb8d4
	                                      &pcsc_cbAtrLen);
Packit 1fb8d4
Packit 1fb8d4
	if (status != STATUS_SUCCESS)
Packit 1fb8d4
		goto out_fail;
Packit 1fb8d4
Packit 1fb8d4
	if (tATR)
Packit 1fb8d4
	{
Packit 1fb8d4
		PCSC_AddMemoryBlock(hContext, tATR);
Packit 1fb8d4
		*(LPBYTE*)pbAtr = tATR;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (tReader)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (unicode)
Packit 1fb8d4
		{
Packit 1fb8d4
			LPSTR mszReaderNamesW = NULL;
Packit 1fb8d4
			int pcsc_cchReaderLenW = 0;
Packit 1fb8d4
			pcsc_cchReaderLenW = ConvertToUnicode(CP_UTF8, 0, tReader, *pcchReaderLen,
Packit 1fb8d4
			                                      (WCHAR**) &mszReaderNamesW, 0);
Packit 1fb8d4
Packit 1fb8d4
			if (pcsc_cchReaderLenW <= 0 || mszReaderNamesW == NULL)
Packit 1fb8d4
			{
Packit 1fb8d4
				status = ERROR_NOT_ENOUGH_MEMORY;
Packit 1fb8d4
				goto out_fail;
Packit 1fb8d4
			}
Packit 1fb8d4
Packit 1fb8d4
			readerNames = mszReaderNamesW;
Packit 1fb8d4
			free(tReader);
Packit 1fb8d4
			PCSC_AddMemoryBlock(hContext, mszReaderNamesW);
Packit 1fb8d4
			*(LPSTR*) mszReaderNames = mszReaderNamesW;
Packit 1fb8d4
		}
Packit 1fb8d4
		else
Packit 1fb8d4
		{
Packit 1fb8d4
			PCSC_AddMemoryBlock(hContext, tReader);
Packit 1fb8d4
			*(LPSTR*) mszReaderNames = tReader;
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	pcsc_dwState &= 0xFFFF;
Packit 1fb8d4
Packit 1fb8d4
	if (pdwState)
Packit 1fb8d4
		*pdwState = PCSC_ConvertCardStateToWinSCard((DWORD) pcsc_dwState, status);
Packit 1fb8d4
Packit 1fb8d4
	if (pdwProtocol)
Packit 1fb8d4
		*pdwProtocol = PCSC_ConvertProtocolsToWinSCard((DWORD) pcsc_dwProtocol);
Packit 1fb8d4
Packit 1fb8d4
	if (pcbAtrLen)
Packit 1fb8d4
		*pcbAtrLen = (DWORD) pcsc_cbAtrLen;
Packit 1fb8d4
Packit 1fb8d4
	if (pcchReaderLen)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (unicode)
Packit 1fb8d4
			*pcchReaderLen = (pcsc_cchReaderLen + 1) * 2;
Packit 1fb8d4
		else
Packit 1fb8d4
			*pcchReaderLen = pcsc_cchReaderLen + 1;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	/* Make sure the last byte is set */
Packit 1fb8d4
	if (readerNames)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (unicode)
Packit 1fb8d4
		{
Packit 1fb8d4
			readerNames[pcsc_cchReaderLen * 2] = '\0';
Packit 1fb8d4
			readerNames[pcsc_cchReaderLen * 2 + 1] = '\0';
Packit 1fb8d4
		}
Packit 1fb8d4
		else
Packit 1fb8d4
			readerNames[pcsc_cchReaderLen] = '\0';
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return status;
Packit 1fb8d4
out_fail:
Packit 1fb8d4
	free(tReader);
Packit 1fb8d4
	free(tATR);
Packit 1fb8d4
	return status;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardStatusA(SCARDHANDLE hCard,
Packit 1fb8d4
        LPSTR mszReaderNames, LPDWORD pcchReaderLen, LPDWORD pdwState,
Packit 1fb8d4
        LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
Packit 1fb8d4
{
Packit 1fb8d4
	return PCSC_SCardStatus_Internal(hCard, mszReaderNames, pcchReaderLen, pdwState, pdwProtocol,
Packit 1fb8d4
	                                 pbAtr, pcbAtrLen, FALSE);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardStatusW(SCARDHANDLE hCard,
Packit 1fb8d4
        LPWSTR mszReaderNames, LPDWORD pcchReaderLen, LPDWORD pdwState,
Packit 1fb8d4
        LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
Packit 1fb8d4
{
Packit 1fb8d4
	return PCSC_SCardStatus_Internal(hCard, (LPSTR) mszReaderNames, pcchReaderLen, pdwState,
Packit 1fb8d4
	                                 pdwProtocol, pbAtr, pcbAtrLen, TRUE);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardTransmit(SCARDHANDLE hCard,
Packit 1fb8d4
        LPCSCARD_IO_REQUEST pioSendPci, LPCBYTE pbSendBuffer, DWORD cbSendLength,
Packit 1fb8d4
        LPSCARD_IO_REQUEST pioRecvPci, LPBYTE pbRecvBuffer, LPDWORD pcbRecvLength)
Packit 1fb8d4
{
Packit 1fb8d4
	LONG status = SCARD_S_SUCCESS;
Packit 1fb8d4
	PCSC_SCARDHANDLE* pCard = NULL;
Packit 1fb8d4
	PCSC_DWORD cbExtraBytes = 0;
Packit 1fb8d4
	BYTE* pbExtraBytes = NULL;
Packit 1fb8d4
	BYTE* pcsc_pbExtraBytes = NULL;
Packit 1fb8d4
	PCSC_SCARD_IO_REQUEST* pcsc_pioSendPci = NULL;
Packit 1fb8d4
	PCSC_SCARD_IO_REQUEST* pcsc_pioRecvPci = NULL;
Packit 1fb8d4
	PCSC_DWORD pcsc_cbSendLength = (PCSC_DWORD) cbSendLength;
Packit 1fb8d4
	PCSC_DWORD pcsc_cbRecvLength = 0;
Packit 1fb8d4
Packit 1fb8d4
	if (!g_PCSC.pfnSCardTransmit)
Packit 1fb8d4
		return SCARD_E_NO_SERVICE;
Packit 1fb8d4
Packit 1fb8d4
	pCard = PCSC_GetCardHandleData(hCard);
Packit 1fb8d4
Packit 1fb8d4
	if (!pCard)
Packit 1fb8d4
		return SCARD_E_INVALID_VALUE;
Packit 1fb8d4
Packit 1fb8d4
	PCSC_WaitForCardAccess(0, hCard, pCard->shared);
Packit 1fb8d4
Packit 1fb8d4
	if (!pcbRecvLength)
Packit 1fb8d4
		return SCARD_E_INVALID_PARAMETER;
Packit 1fb8d4
Packit 1fb8d4
	if (*pcbRecvLength == SCARD_AUTOALLOCATE)
Packit 1fb8d4
		return SCARD_E_INVALID_PARAMETER;
Packit 1fb8d4
Packit 1fb8d4
	pcsc_cbRecvLength = (PCSC_DWORD) * pcbRecvLength;
Packit 1fb8d4
Packit 1fb8d4
	if (!pioSendPci)
Packit 1fb8d4
	{
Packit 1fb8d4
		PCSC_DWORD dwState = 0;
Packit 1fb8d4
		PCSC_DWORD cbAtrLen = 0;
Packit 1fb8d4
		PCSC_DWORD dwProtocol = 0;
Packit 1fb8d4
		PCSC_DWORD cchReaderLen = 0;
Packit 1fb8d4
		/**
Packit 1fb8d4
		 * pcsc-lite cannot have a null pioSendPci parameter, unlike WinSCard.
Packit 1fb8d4
		 * Query the current protocol and use default SCARD_IO_REQUEST for it.
Packit 1fb8d4
		 */
Packit 1fb8d4
		status = (LONG) g_PCSC.pfnSCardStatus(hCard, NULL, &cchReaderLen, &dwState, &dwProtocol, NULL,
Packit 1fb8d4
		                                      &cbAtrLen);
Packit 1fb8d4
Packit 1fb8d4
		if (status == SCARD_S_SUCCESS)
Packit 1fb8d4
		{
Packit 1fb8d4
			if (dwProtocol == SCARD_PROTOCOL_T0)
Packit 1fb8d4
				pcsc_pioSendPci = (PCSC_SCARD_IO_REQUEST*) PCSC_SCARD_PCI_T0;
Packit 1fb8d4
			else if (dwProtocol == SCARD_PROTOCOL_T1)
Packit 1fb8d4
				pcsc_pioSendPci = (PCSC_SCARD_IO_REQUEST*) PCSC_SCARD_PCI_T1;
Packit 1fb8d4
			else if (dwProtocol == PCSC_SCARD_PROTOCOL_RAW)
Packit 1fb8d4
				pcsc_pioSendPci = (PCSC_SCARD_IO_REQUEST*) PCSC_SCARD_PCI_RAW;
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
	else
Packit 1fb8d4
	{
Packit 1fb8d4
		cbExtraBytes = pioSendPci->cbPciLength - sizeof(SCARD_IO_REQUEST);
Packit 1fb8d4
		pcsc_pioSendPci = (PCSC_SCARD_IO_REQUEST*) malloc(sizeof(PCSC_SCARD_IO_REQUEST) + cbExtraBytes);
Packit 1fb8d4
Packit 1fb8d4
		if (!pcsc_pioSendPci)
Packit 1fb8d4
			return SCARD_E_NO_MEMORY;
Packit 1fb8d4
Packit 1fb8d4
		pcsc_pioSendPci->dwProtocol = (PCSC_DWORD) pioSendPci->dwProtocol;
Packit 1fb8d4
		pcsc_pioSendPci->cbPciLength = sizeof(PCSC_SCARD_IO_REQUEST) + cbExtraBytes;
Packit 1fb8d4
		pbExtraBytes = &((BYTE*) pioSendPci)[sizeof(SCARD_IO_REQUEST)];
Packit 1fb8d4
		pcsc_pbExtraBytes = &((BYTE*) pcsc_pioSendPci)[sizeof(PCSC_SCARD_IO_REQUEST)];
Packit 1fb8d4
		CopyMemory(pcsc_pbExtraBytes, pbExtraBytes, cbExtraBytes);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (pioRecvPci)
Packit 1fb8d4
	{
Packit 1fb8d4
		cbExtraBytes = pioRecvPci->cbPciLength - sizeof(SCARD_IO_REQUEST);
Packit 1fb8d4
		pcsc_pioRecvPci = (PCSC_SCARD_IO_REQUEST*) malloc(sizeof(PCSC_SCARD_IO_REQUEST) + cbExtraBytes);
Packit 1fb8d4
Packit 1fb8d4
		if (!pcsc_pioRecvPci)
Packit 1fb8d4
		{
Packit 1fb8d4
			if (pioSendPci)
Packit 1fb8d4
				free(pcsc_pioSendPci);
Packit 1fb8d4
Packit 1fb8d4
			return SCARD_E_NO_MEMORY;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		pcsc_pioRecvPci->dwProtocol = (PCSC_DWORD) pioRecvPci->dwProtocol;
Packit 1fb8d4
		pcsc_pioRecvPci->cbPciLength = sizeof(PCSC_SCARD_IO_REQUEST) + cbExtraBytes;
Packit 1fb8d4
		pbExtraBytes = &((BYTE*) pioRecvPci)[sizeof(SCARD_IO_REQUEST)];
Packit 1fb8d4
		pcsc_pbExtraBytes = &((BYTE*) pcsc_pioRecvPci)[sizeof(PCSC_SCARD_IO_REQUEST)];
Packit 1fb8d4
		CopyMemory(pcsc_pbExtraBytes, pbExtraBytes, cbExtraBytes);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	status = (LONG) g_PCSC.pfnSCardTransmit(hCard, pcsc_pioSendPci, pbSendBuffer,
Packit 1fb8d4
	                                        pcsc_cbSendLength, pcsc_pioRecvPci, pbRecvBuffer, &pcsc_cbRecvLength);
Packit 1fb8d4
	status = PCSC_MapErrorCodeToWinSCard(status);
Packit 1fb8d4
	*pcbRecvLength = (DWORD) pcsc_cbRecvLength;
Packit 1fb8d4
Packit 1fb8d4
	if (pioSendPci)
Packit 1fb8d4
		free(pcsc_pioSendPci); /* pcsc_pioSendPci is dynamically allocated only when pioSendPci is non null */
Packit 1fb8d4
Packit 1fb8d4
	if (pioRecvPci)
Packit 1fb8d4
	{
Packit 1fb8d4
		cbExtraBytes = pioRecvPci->cbPciLength - sizeof(SCARD_IO_REQUEST);
Packit 1fb8d4
		pbExtraBytes = &((BYTE*) pioRecvPci)[sizeof(SCARD_IO_REQUEST)];
Packit 1fb8d4
		pcsc_pbExtraBytes = &((BYTE*) pcsc_pioRecvPci)[sizeof(PCSC_SCARD_IO_REQUEST)];
Packit 1fb8d4
		CopyMemory(pbExtraBytes, pcsc_pbExtraBytes, cbExtraBytes); /* copy extra bytes */
Packit 1fb8d4
		free(pcsc_pioRecvPci); /* pcsc_pioRecvPci is dynamically allocated only when pioRecvPci is non null */
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return status;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardGetTransmitCount(SCARDHANDLE hCard, LPDWORD pcTransmitCount)
Packit 1fb8d4
{
Packit 1fb8d4
	WINPR_UNUSED(pcTransmitCount);
Packit 1fb8d4
	PCSC_SCARDHANDLE* pCard = NULL;
Packit 1fb8d4
	pCard = PCSC_GetCardHandleData(hCard);
Packit 1fb8d4
Packit 1fb8d4
	if (!pCard)
Packit 1fb8d4
		return SCARD_E_INVALID_VALUE;
Packit 1fb8d4
Packit 1fb8d4
	PCSC_WaitForCardAccess(0, hCard, pCard->shared);
Packit 1fb8d4
	return SCARD_S_SUCCESS;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardControl(SCARDHANDLE hCard,
Packit 1fb8d4
        DWORD dwControlCode, LPCVOID lpInBuffer, DWORD cbInBufferSize,
Packit 1fb8d4
        LPVOID lpOutBuffer, DWORD cbOutBufferSize, LPDWORD lpBytesReturned)
Packit 1fb8d4
{
Packit 1fb8d4
	DWORD IoCtlMethod = 0;
Packit 1fb8d4
	DWORD IoCtlFunction = 0;
Packit 1fb8d4
	DWORD IoCtlAccess = 0;
Packit 1fb8d4
	DWORD IoCtlDeviceType = 0;
Packit 1fb8d4
	BOOL getFeatureRequest = FALSE;
Packit 1fb8d4
	LONG status = SCARD_S_SUCCESS;
Packit 1fb8d4
	PCSC_SCARDHANDLE* pCard = NULL;
Packit 1fb8d4
	PCSC_DWORD pcsc_dwControlCode = 0;
Packit 1fb8d4
	PCSC_DWORD pcsc_cbInBufferSize = (PCSC_DWORD) cbInBufferSize;
Packit 1fb8d4
	PCSC_DWORD pcsc_cbOutBufferSize = (PCSC_DWORD) cbOutBufferSize;
Packit 1fb8d4
	PCSC_DWORD pcsc_BytesReturned = 0;
Packit 1fb8d4
Packit 1fb8d4
	if (!g_PCSC.pfnSCardControl)
Packit 1fb8d4
		return SCARD_E_NO_SERVICE;
Packit 1fb8d4
Packit 1fb8d4
	pCard = PCSC_GetCardHandleData(hCard);
Packit 1fb8d4
Packit 1fb8d4
	if (!pCard)
Packit 1fb8d4
		return SCARD_E_INVALID_VALUE;
Packit 1fb8d4
Packit 1fb8d4
	PCSC_WaitForCardAccess(0, hCard, pCard->shared);
Packit 1fb8d4
	/**
Packit 1fb8d4
	 * PCSCv2 Part 10:
Packit 1fb8d4
	 * http://www.pcscworkgroup.com/specifications/files/pcsc10_v2.02.09.pdf
Packit 1fb8d4
	 *
Packit 1fb8d4
	 * Smart Card Driver IOCTLs:
Packit 1fb8d4
	 * http://msdn.microsoft.com/en-us/library/windows/hardware/ff548988/
Packit 1fb8d4
	 *
Packit 1fb8d4
	 * Converting Windows Feature Request IOCTL code to the pcsc-lite control code:
Packit 1fb8d4
	 * http://musclecard.996296.n3.nabble.com/Converting-Windows-Feature-Request-IOCTL-code-to-the-pcsc-lite-control-code-td4906.html
Packit 1fb8d4
	 */
Packit 1fb8d4
	IoCtlMethod = METHOD_FROM_CTL_CODE(dwControlCode);
Packit 1fb8d4
	IoCtlFunction = FUNCTION_FROM_CTL_CODE(dwControlCode);
Packit 1fb8d4
	IoCtlAccess = ACCESS_FROM_CTL_CODE(dwControlCode);
Packit 1fb8d4
	IoCtlDeviceType = DEVICE_TYPE_FROM_CTL_CODE(dwControlCode);
Packit 1fb8d4
Packit 1fb8d4
	if (dwControlCode == IOCTL_SMARTCARD_GET_FEATURE_REQUEST)
Packit 1fb8d4
		getFeatureRequest = TRUE;
Packit 1fb8d4
Packit 1fb8d4
	if (IoCtlDeviceType == FILE_DEVICE_SMARTCARD)
Packit 1fb8d4
		dwControlCode = PCSC_SCARD_CTL_CODE(IoCtlFunction);
Packit 1fb8d4
Packit 1fb8d4
	pcsc_dwControlCode = (PCSC_DWORD) dwControlCode;
Packit 1fb8d4
	status = (LONG) g_PCSC.pfnSCardControl(hCard,
Packit 1fb8d4
	                                       pcsc_dwControlCode, lpInBuffer, pcsc_cbInBufferSize,
Packit 1fb8d4
	                                       lpOutBuffer, pcsc_cbOutBufferSize, &pcsc_BytesReturned);
Packit 1fb8d4
	status = PCSC_MapErrorCodeToWinSCard(status);
Packit 1fb8d4
	*lpBytesReturned = (DWORD) pcsc_BytesReturned;
Packit 1fb8d4
Packit 1fb8d4
	if (getFeatureRequest)
Packit 1fb8d4
	{
Packit 1fb8d4
		UINT32 index;
Packit 1fb8d4
		UINT32 count;
Packit 1fb8d4
		PCSC_TLV_STRUCTURE* tlv = (PCSC_TLV_STRUCTURE*) lpOutBuffer;
Packit 1fb8d4
Packit 1fb8d4
		if ((*lpBytesReturned % sizeof(PCSC_TLV_STRUCTURE)) != 0)
Packit 1fb8d4
			return SCARD_E_UNEXPECTED;
Packit 1fb8d4
Packit 1fb8d4
		count = *lpBytesReturned / sizeof(PCSC_TLV_STRUCTURE);
Packit 1fb8d4
Packit 1fb8d4
		for (index = 0; index < count; index++)
Packit 1fb8d4
		{
Packit 1fb8d4
			if (tlv[index].length != 4)
Packit 1fb8d4
				return SCARD_E_UNEXPECTED;
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return status;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardGetAttrib_Internal(SCARDHANDLE hCard, DWORD dwAttrId,
Packit 1fb8d4
        LPBYTE pbAttr, LPDWORD pcbAttrLen)
Packit 1fb8d4
{
Packit 1fb8d4
	SCARDCONTEXT hContext = 0;
Packit 1fb8d4
	BOOL pcbAttrLenAlloc = FALSE;
Packit 1fb8d4
	LPBYTE* pPbAttr = (LPBYTE*) pbAttr;
Packit 1fb8d4
	LONG status = SCARD_S_SUCCESS;
Packit 1fb8d4
	PCSC_SCARDHANDLE* pCard = NULL;
Packit 1fb8d4
	PCSC_DWORD pcsc_dwAttrId = (PCSC_DWORD) dwAttrId;
Packit 1fb8d4
	PCSC_DWORD pcsc_cbAttrLen = 0;
Packit 1fb8d4
Packit 1fb8d4
	if (!g_PCSC.pfnSCardGetAttrib)
Packit 1fb8d4
		return SCARD_E_NO_SERVICE;
Packit 1fb8d4
Packit 1fb8d4
	pCard = PCSC_GetCardHandleData(hCard);
Packit 1fb8d4
Packit 1fb8d4
	if (!pCard)
Packit 1fb8d4
		return SCARD_E_INVALID_VALUE;
Packit 1fb8d4
Packit 1fb8d4
	PCSC_WaitForCardAccess(0, hCard, pCard->shared);
Packit 1fb8d4
	hContext = PCSC_GetCardContextFromHandle(hCard);
Packit 1fb8d4
Packit 1fb8d4
	if (!hContext)
Packit 1fb8d4
		return SCARD_E_INVALID_HANDLE;
Packit 1fb8d4
Packit 1fb8d4
	if (!pbAttr || !pcbAttrLen)
Packit 1fb8d4
		return SCARD_E_INVALID_PARAMETER;
Packit 1fb8d4
Packit 1fb8d4
	if (*pcbAttrLen == SCARD_AUTOALLOCATE)
Packit 1fb8d4
		pcbAttrLenAlloc = TRUE;
Packit 1fb8d4
Packit 1fb8d4
	pcsc_cbAttrLen = pcbAttrLenAlloc ? PCSC_SCARD_AUTOALLOCATE : (PCSC_DWORD) * pcbAttrLen;
Packit 1fb8d4
Packit 1fb8d4
	if (pcbAttrLenAlloc && !g_SCardAutoAllocate)
Packit 1fb8d4
	{
Packit 1fb8d4
		pcsc_cbAttrLen = 0;
Packit 1fb8d4
		status = (LONG) g_PCSC.pfnSCardGetAttrib(hCard, pcsc_dwAttrId, NULL, &pcsc_cbAttrLen);
Packit 1fb8d4
Packit 1fb8d4
		if (status == SCARD_S_SUCCESS)
Packit 1fb8d4
		{
Packit 1fb8d4
			*pPbAttr = (BYTE*) calloc(1, pcsc_cbAttrLen);
Packit 1fb8d4
Packit 1fb8d4
			if (!*pPbAttr)
Packit 1fb8d4
				return SCARD_E_NO_MEMORY;
Packit 1fb8d4
Packit 1fb8d4
			status = (LONG) g_PCSC.pfnSCardGetAttrib(hCard, pcsc_dwAttrId, *pPbAttr, &pcsc_cbAttrLen);
Packit 1fb8d4
Packit 1fb8d4
			if (status != SCARD_S_SUCCESS)
Packit 1fb8d4
				free(*pPbAttr);
Packit 1fb8d4
			else
Packit 1fb8d4
				PCSC_AddMemoryBlock(hContext, *pPbAttr);
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
	else
Packit 1fb8d4
	{
Packit 1fb8d4
		status = (LONG) g_PCSC.pfnSCardGetAttrib(hCard, pcsc_dwAttrId, pbAttr, &pcsc_cbAttrLen);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	status = PCSC_MapErrorCodeToWinSCard(status);
Packit 1fb8d4
Packit 1fb8d4
	if (status == SCARD_S_SUCCESS)
Packit 1fb8d4
		*pcbAttrLen = (DWORD) pcsc_cbAttrLen;
Packit 1fb8d4
Packit 1fb8d4
	return status;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardGetAttrib_FriendlyName(SCARDHANDLE hCard, DWORD dwAttrId,
Packit 1fb8d4
        LPBYTE pbAttr, LPDWORD pcbAttrLen)
Packit 1fb8d4
{
Packit 1fb8d4
	int length = 0;
Packit 1fb8d4
	char* namePCSC = NULL;
Packit 1fb8d4
	DWORD cbAttrLen = 0;
Packit 1fb8d4
	char* pbAttrA = NULL;
Packit 1fb8d4
	WCHAR* pbAttrW = NULL;
Packit 1fb8d4
	SCARDCONTEXT hContext;
Packit 1fb8d4
	char* friendlyNameA = NULL;
Packit 1fb8d4
	WCHAR* friendlyNameW = NULL;
Packit 1fb8d4
	LONG status = SCARD_S_SUCCESS;
Packit 1fb8d4
	LPBYTE* pPbAttr = (LPBYTE*) pbAttr;
Packit 1fb8d4
	hContext = PCSC_GetCardContextFromHandle(hCard);
Packit 1fb8d4
Packit 1fb8d4
	if (!hContext)
Packit 1fb8d4
		return SCARD_E_INVALID_HANDLE;
Packit 1fb8d4
Packit 1fb8d4
	cbAttrLen = *pcbAttrLen;
Packit 1fb8d4
	*pcbAttrLen = SCARD_AUTOALLOCATE;
Packit 1fb8d4
	status = PCSC_SCardGetAttrib_Internal(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME_A, (LPBYTE) &pbAttrA,
Packit 1fb8d4
	                                      pcbAttrLen);
Packit 1fb8d4
Packit 1fb8d4
	if (status != SCARD_S_SUCCESS)
Packit 1fb8d4
	{
Packit 1fb8d4
		pbAttrA = NULL;
Packit 1fb8d4
		*pcbAttrLen = SCARD_AUTOALLOCATE;
Packit 1fb8d4
		status = PCSC_SCardGetAttrib_Internal(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME_W, (LPBYTE) &pbAttrW,
Packit 1fb8d4
		                                      pcbAttrLen);
Packit 1fb8d4
Packit 1fb8d4
		if (status != SCARD_S_SUCCESS)
Packit 1fb8d4
			return status;
Packit 1fb8d4
Packit 1fb8d4
		ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) pbAttrW, *pcbAttrLen, (char**) &pbAttrA, 0, NULL,
Packit 1fb8d4
		                   NULL);
Packit 1fb8d4
		namePCSC = pbAttrA;
Packit 1fb8d4
		PCSC_SCardFreeMemory_Internal(hContext, pbAttrW);
Packit 1fb8d4
	}
Packit 1fb8d4
	else
Packit 1fb8d4
	{
Packit 1fb8d4
		namePCSC = _strdup(pbAttrA);
Packit 1fb8d4
Packit 1fb8d4
		if (!namePCSC)
Packit 1fb8d4
			return SCARD_E_NO_MEMORY;
Packit 1fb8d4
Packit 1fb8d4
		PCSC_SCardFreeMemory_Internal(hContext, pbAttrA);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	length = strlen(namePCSC);
Packit 1fb8d4
	friendlyNameA = namePCSC;
Packit 1fb8d4
	namePCSC = NULL;
Packit 1fb8d4
Packit 1fb8d4
	if (dwAttrId == SCARD_ATTR_DEVICE_FRIENDLY_NAME_W)
Packit 1fb8d4
	{
Packit 1fb8d4
		/* length here includes null terminator */
Packit 1fb8d4
		length = ConvertToUnicode(CP_UTF8, 0, (char*) friendlyNameA, -1, &friendlyNameW, 0);
Packit 1fb8d4
		free(friendlyNameA);
Packit 1fb8d4
Packit 1fb8d4
		if (!friendlyNameW)
Packit 1fb8d4
		{
Packit 1fb8d4
			free(namePCSC);
Packit 1fb8d4
			return SCARD_E_NO_MEMORY;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		if (cbAttrLen == SCARD_AUTOALLOCATE)
Packit 1fb8d4
		{
Packit 1fb8d4
			*pPbAttr = (BYTE*) friendlyNameW;
Packit 1fb8d4
			*pcbAttrLen = length * 2;
Packit 1fb8d4
			PCSC_AddMemoryBlock(hContext, *pPbAttr);
Packit 1fb8d4
		}
Packit 1fb8d4
		else
Packit 1fb8d4
		{
Packit 1fb8d4
			if ((length * 2) > cbAttrLen)
Packit 1fb8d4
			{
Packit 1fb8d4
				free(friendlyNameW);
Packit 1fb8d4
				free(namePCSC);
Packit 1fb8d4
				return SCARD_E_INSUFFICIENT_BUFFER;
Packit 1fb8d4
			}
Packit 1fb8d4
			else
Packit 1fb8d4
			{
Packit 1fb8d4
				CopyMemory(pbAttr, (BYTE*) friendlyNameW, (length * 2));
Packit 1fb8d4
				*pcbAttrLen = length * 2;
Packit 1fb8d4
				free(friendlyNameW);
Packit 1fb8d4
			}
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
	else
Packit 1fb8d4
	{
Packit 1fb8d4
		if (cbAttrLen == SCARD_AUTOALLOCATE)
Packit 1fb8d4
		{
Packit 1fb8d4
			*pPbAttr = (BYTE*) friendlyNameA;
Packit 1fb8d4
			*pcbAttrLen = length;
Packit 1fb8d4
			PCSC_AddMemoryBlock(hContext, *pPbAttr);
Packit 1fb8d4
		}
Packit 1fb8d4
		else
Packit 1fb8d4
		{
Packit 1fb8d4
			if ((length + 1) > cbAttrLen)
Packit 1fb8d4
			{
Packit 1fb8d4
				free(friendlyNameA);
Packit 1fb8d4
				free(namePCSC);
Packit 1fb8d4
				return SCARD_E_INSUFFICIENT_BUFFER;
Packit 1fb8d4
			}
Packit 1fb8d4
			else
Packit 1fb8d4
			{
Packit 1fb8d4
				CopyMemory(pbAttr, (BYTE*) friendlyNameA, length + 1);
Packit 1fb8d4
				*pcbAttrLen = length;
Packit 1fb8d4
				free(friendlyNameA);
Packit 1fb8d4
			}
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	free(namePCSC);
Packit 1fb8d4
	return status;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr,
Packit 1fb8d4
        LPDWORD pcbAttrLen)
Packit 1fb8d4
{
Packit 1fb8d4
	DWORD cbAttrLen;
Packit 1fb8d4
	SCARDCONTEXT hContext;
Packit 1fb8d4
	BOOL pcbAttrLenAlloc = FALSE;
Packit 1fb8d4
	LONG status = SCARD_S_SUCCESS;
Packit 1fb8d4
	LPBYTE* pPbAttr = (LPBYTE*) pbAttr;
Packit 1fb8d4
	cbAttrLen = *pcbAttrLen;
Packit 1fb8d4
Packit 1fb8d4
	if (*pcbAttrLen == SCARD_AUTOALLOCATE)
Packit 1fb8d4
	{
Packit 1fb8d4
		pcbAttrLenAlloc = TRUE;
Packit 1fb8d4
		*pPbAttr = NULL;
Packit 1fb8d4
	}
Packit 1fb8d4
	else
Packit 1fb8d4
	{
Packit 1fb8d4
		/**
Packit 1fb8d4
		 * pcsc-lite returns SCARD_E_INSUFFICIENT_BUFFER if the given
Packit 1fb8d4
		 * buffer size is larger than PCSC_MAX_BUFFER_SIZE (264)
Packit 1fb8d4
		 */
Packit 1fb8d4
		if (*pcbAttrLen > PCSC_MAX_BUFFER_SIZE)
Packit 1fb8d4
			*pcbAttrLen = PCSC_MAX_BUFFER_SIZE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	hContext = PCSC_GetCardContextFromHandle(hCard);
Packit 1fb8d4
Packit 1fb8d4
	if (!hContext)
Packit 1fb8d4
		return SCARD_E_INVALID_HANDLE;
Packit 1fb8d4
Packit 1fb8d4
	if ((dwAttrId == SCARD_ATTR_DEVICE_FRIENDLY_NAME_A) ||
Packit 1fb8d4
	    (dwAttrId == SCARD_ATTR_DEVICE_FRIENDLY_NAME_W))
Packit 1fb8d4
	{
Packit 1fb8d4
		status = PCSC_SCardGetAttrib_FriendlyName(hCard, dwAttrId, pbAttr, pcbAttrLen);
Packit 1fb8d4
		return status;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	status = PCSC_SCardGetAttrib_Internal(hCard, dwAttrId, pbAttr, pcbAttrLen);
Packit 1fb8d4
Packit 1fb8d4
	if (status == SCARD_S_SUCCESS)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (dwAttrId == SCARD_ATTR_VENDOR_NAME)
Packit 1fb8d4
		{
Packit 1fb8d4
			const char* vendorName;
Packit 1fb8d4
Packit 1fb8d4
			/**
Packit 1fb8d4
			 * pcsc-lite adds a null terminator to the vendor name,
Packit 1fb8d4
			 * while WinSCard doesn't. Strip the null terminator.
Packit 1fb8d4
			 */
Packit 1fb8d4
Packit 1fb8d4
			if (pcbAttrLenAlloc)
Packit 1fb8d4
				vendorName = (char*) *pPbAttr;
Packit 1fb8d4
			else
Packit 1fb8d4
				vendorName = (char*) pbAttr;
Packit 1fb8d4
Packit 1fb8d4
			if (vendorName)
Packit 1fb8d4
				*pcbAttrLen = strlen(vendorName);
Packit 1fb8d4
			else
Packit 1fb8d4
				*pcbAttrLen = 0;
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
	else
Packit 1fb8d4
	{
Packit 1fb8d4
		if (dwAttrId == SCARD_ATTR_CURRENT_PROTOCOL_TYPE)
Packit 1fb8d4
		{
Packit 1fb8d4
			if (!pcbAttrLenAlloc)
Packit 1fb8d4
			{
Packit 1fb8d4
				PCSC_DWORD dwState = 0;
Packit 1fb8d4
				PCSC_DWORD cbAtrLen = 0;
Packit 1fb8d4
				PCSC_DWORD dwProtocol = 0;
Packit 1fb8d4
				PCSC_DWORD cchReaderLen = 0;
Packit 1fb8d4
				status = (LONG) g_PCSC.pfnSCardStatus(hCard, NULL, &cchReaderLen, &dwState, &dwProtocol, NULL,
Packit 1fb8d4
				                                      &cbAtrLen);
Packit 1fb8d4
Packit 1fb8d4
				if (status == SCARD_S_SUCCESS)
Packit 1fb8d4
				{
Packit 1fb8d4
					LPDWORD pdwProtocol = (LPDWORD) pbAttr;
Packit 1fb8d4
Packit 1fb8d4
					if (cbAttrLen < sizeof(DWORD))
Packit 1fb8d4
						return SCARD_E_INSUFFICIENT_BUFFER;
Packit 1fb8d4
Packit 1fb8d4
					*pdwProtocol = PCSC_ConvertProtocolsToWinSCard(dwProtocol);
Packit 1fb8d4
					*pcbAttrLen = sizeof(DWORD);
Packit 1fb8d4
				}
Packit 1fb8d4
			}
Packit 1fb8d4
		}
Packit 1fb8d4
		else if (dwAttrId == SCARD_ATTR_CHANNEL_ID)
Packit 1fb8d4
		{
Packit 1fb8d4
			if (!pcbAttrLenAlloc)
Packit 1fb8d4
			{
Packit 1fb8d4
				UINT16 channelType = 0x20; /* USB */
Packit 1fb8d4
				UINT16 channelNumber = 0;
Packit 1fb8d4
Packit 1fb8d4
				if (cbAttrLen < sizeof(DWORD))
Packit 1fb8d4
					return SCARD_E_INSUFFICIENT_BUFFER;
Packit 1fb8d4
Packit 1fb8d4
				status = SCARD_S_SUCCESS;
Packit 1fb8d4
				*((DWORD*) pbAttr) = (channelType << 16) | channelNumber;
Packit 1fb8d4
				*pcbAttrLen = sizeof(DWORD);
Packit 1fb8d4
			}
Packit 1fb8d4
		}
Packit 1fb8d4
		else if (dwAttrId == SCARD_ATTR_VENDOR_IFD_TYPE)
Packit 1fb8d4
		{
Packit 1fb8d4
		}
Packit 1fb8d4
		else if (dwAttrId == SCARD_ATTR_DEFAULT_CLK)
Packit 1fb8d4
		{
Packit 1fb8d4
		}
Packit 1fb8d4
		else if (dwAttrId == SCARD_ATTR_DEFAULT_DATA_RATE)
Packit 1fb8d4
		{
Packit 1fb8d4
		}
Packit 1fb8d4
		else if (dwAttrId == SCARD_ATTR_MAX_CLK)
Packit 1fb8d4
		{
Packit 1fb8d4
		}
Packit 1fb8d4
		else if (dwAttrId == SCARD_ATTR_MAX_DATA_RATE)
Packit 1fb8d4
		{
Packit 1fb8d4
		}
Packit 1fb8d4
		else if (dwAttrId == SCARD_ATTR_MAX_IFSD)
Packit 1fb8d4
		{
Packit 1fb8d4
		}
Packit 1fb8d4
		else if (dwAttrId == SCARD_ATTR_CHARACTERISTICS)
Packit 1fb8d4
		{
Packit 1fb8d4
		}
Packit 1fb8d4
		else if (dwAttrId == SCARD_ATTR_DEVICE_SYSTEM_NAME_A)
Packit 1fb8d4
		{
Packit 1fb8d4
		}
Packit 1fb8d4
		else if (dwAttrId == SCARD_ATTR_DEVICE_UNIT)
Packit 1fb8d4
		{
Packit 1fb8d4
		}
Packit 1fb8d4
		else if (dwAttrId == SCARD_ATTR_POWER_MGMT_SUPPORT)
Packit 1fb8d4
		{
Packit 1fb8d4
		}
Packit 1fb8d4
		else if (dwAttrId == SCARD_ATTR_CURRENT_CLK)
Packit 1fb8d4
		{
Packit 1fb8d4
		}
Packit 1fb8d4
		else if (dwAttrId == SCARD_ATTR_CURRENT_F)
Packit 1fb8d4
		{
Packit 1fb8d4
		}
Packit 1fb8d4
		else if (dwAttrId == SCARD_ATTR_CURRENT_D)
Packit 1fb8d4
		{
Packit 1fb8d4
		}
Packit 1fb8d4
		else if (dwAttrId == SCARD_ATTR_CURRENT_N)
Packit 1fb8d4
		{
Packit 1fb8d4
		}
Packit 1fb8d4
		else if (dwAttrId == SCARD_ATTR_CURRENT_CWT)
Packit 1fb8d4
		{
Packit 1fb8d4
		}
Packit 1fb8d4
		else if (dwAttrId == SCARD_ATTR_CURRENT_BWT)
Packit 1fb8d4
		{
Packit 1fb8d4
		}
Packit 1fb8d4
		else if (dwAttrId == SCARD_ATTR_CURRENT_IFSC)
Packit 1fb8d4
		{
Packit 1fb8d4
		}
Packit 1fb8d4
		else if (dwAttrId == SCARD_ATTR_CURRENT_EBC_ENCODING)
Packit 1fb8d4
		{
Packit 1fb8d4
		}
Packit 1fb8d4
		else if (dwAttrId == SCARD_ATTR_CURRENT_IFSD)
Packit 1fb8d4
		{
Packit 1fb8d4
		}
Packit 1fb8d4
		else if (dwAttrId == SCARD_ATTR_ICC_TYPE_PER_ATR)
Packit 1fb8d4
		{
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return status;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr,
Packit 1fb8d4
        DWORD cbAttrLen)
Packit 1fb8d4
{
Packit 1fb8d4
	LONG status = SCARD_S_SUCCESS;
Packit 1fb8d4
	PCSC_SCARDHANDLE* pCard = NULL;
Packit 1fb8d4
	PCSC_DWORD pcsc_dwAttrId = (PCSC_DWORD) dwAttrId;
Packit 1fb8d4
	PCSC_DWORD pcsc_cbAttrLen = (PCSC_DWORD) cbAttrLen;
Packit 1fb8d4
Packit 1fb8d4
	if (!g_PCSC.pfnSCardSetAttrib)
Packit 1fb8d4
		return SCARD_E_NO_SERVICE;
Packit 1fb8d4
Packit 1fb8d4
	pCard = PCSC_GetCardHandleData(hCard);
Packit 1fb8d4
Packit 1fb8d4
	if (!pCard)
Packit 1fb8d4
		return SCARD_E_INVALID_VALUE;
Packit 1fb8d4
Packit 1fb8d4
	PCSC_WaitForCardAccess(0, hCard, pCard->shared);
Packit 1fb8d4
	status = (LONG) g_PCSC.pfnSCardSetAttrib(hCard, pcsc_dwAttrId, pbAttr, pcsc_cbAttrLen);
Packit 1fb8d4
	status = PCSC_MapErrorCodeToWinSCard(status);
Packit 1fb8d4
	return status;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardUIDlgSelectCardA(LPOPENCARDNAMEA_EX pDlgStruc)
Packit 1fb8d4
{
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardUIDlgSelectCardW(LPOPENCARDNAMEW_EX pDlgStruc)
Packit 1fb8d4
{
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_GetOpenCardNameA(LPOPENCARDNAMEA pDlgStruc)
Packit 1fb8d4
{
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_GetOpenCardNameW(LPOPENCARDNAMEW pDlgStruc)
Packit 1fb8d4
{
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardDlgExtendedError(void)
Packit 1fb8d4
{
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardReadCacheA(SCARDCONTEXT hContext,
Packit 1fb8d4
        UUID* CardIdentifier, DWORD FreshnessCounter, LPSTR LookupName, PBYTE Data, DWORD* DataLen)
Packit 1fb8d4
{
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardReadCacheW(SCARDCONTEXT hContext,
Packit 1fb8d4
        UUID* CardIdentifier,  DWORD FreshnessCounter, LPWSTR LookupName, PBYTE Data, DWORD* DataLen)
Packit 1fb8d4
{
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardWriteCacheA(SCARDCONTEXT hContext,
Packit 1fb8d4
        UUID* CardIdentifier, DWORD FreshnessCounter, LPSTR LookupName, PBYTE Data, DWORD DataLen)
Packit 1fb8d4
{
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardWriteCacheW(SCARDCONTEXT hContext,
Packit 1fb8d4
        UUID* CardIdentifier, DWORD FreshnessCounter, LPWSTR LookupName, PBYTE Data, DWORD DataLen)
Packit 1fb8d4
{
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardGetReaderIconA(SCARDCONTEXT hContext,
Packit 1fb8d4
        LPCSTR szReaderName, LPBYTE pbIcon, LPDWORD pcbIcon)
Packit 1fb8d4
{
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardGetReaderIconW(SCARDCONTEXT hContext,
Packit 1fb8d4
        LPCWSTR szReaderName, LPBYTE pbIcon, LPDWORD pcbIcon)
Packit 1fb8d4
{
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardGetDeviceTypeIdA(SCARDCONTEXT hContext, LPCSTR szReaderName,
Packit 1fb8d4
        LPDWORD pdwDeviceTypeId)
Packit 1fb8d4
{
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardGetDeviceTypeIdW(SCARDCONTEXT hContext, LPCWSTR szReaderName,
Packit 1fb8d4
        LPDWORD pdwDeviceTypeId)
Packit 1fb8d4
{
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardGetReaderDeviceInstanceIdA(SCARDCONTEXT hContext,
Packit 1fb8d4
        LPCSTR szReaderName, LPSTR szDeviceInstanceId, LPDWORD pcchDeviceInstanceId)
Packit 1fb8d4
{
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardGetReaderDeviceInstanceIdW(SCARDCONTEXT hContext,
Packit 1fb8d4
        LPCWSTR szReaderName, LPWSTR szDeviceInstanceId, LPDWORD pcchDeviceInstanceId)
Packit 1fb8d4
{
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardListReadersWithDeviceInstanceIdA(SCARDCONTEXT hContext,
Packit 1fb8d4
        LPCSTR szDeviceInstanceId, LPSTR mszReaders, LPDWORD pcchReaders)
Packit 1fb8d4
{
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardListReadersWithDeviceInstanceIdW(SCARDCONTEXT hContext,
Packit 1fb8d4
        LPCWSTR szDeviceInstanceId, LPWSTR mszReaders, LPDWORD pcchReaders)
Packit 1fb8d4
{
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINSCARDAPI LONG WINAPI PCSC_SCardAudit(SCARDCONTEXT hContext, DWORD dwEvent)
Packit 1fb8d4
{
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
#ifdef __MACOSX__
Packit 1fb8d4
unsigned int determineMacOSXVersion(void)
Packit 1fb8d4
{
Packit 1fb8d4
	int mib[2];
Packit 1fb8d4
	size_t len = 0;
Packit 1fb8d4
	char* kernelVersion = NULL;
Packit 1fb8d4
	char* tok = NULL;
Packit 1fb8d4
	unsigned int version = 0;
Packit 1fb8d4
	long majorVersion = 0;
Packit 1fb8d4
	long minorVersion = 0;
Packit 1fb8d4
	long patchVersion = 0;
Packit 1fb8d4
	int count = 0;
Packit 1fb8d4
	mib[0] = CTL_KERN;
Packit 1fb8d4
	mib[1] = KERN_OSRELEASE;
Packit 1fb8d4
Packit 1fb8d4
	if (sysctl(mib, 2, NULL, &len, NULL, 0) != 0)
Packit 1fb8d4
		return 0;
Packit 1fb8d4
Packit 1fb8d4
	kernelVersion = calloc(len, sizeof(char));
Packit 1fb8d4
Packit 1fb8d4
	if (!kernelVersion)
Packit 1fb8d4
		return 0;
Packit 1fb8d4
Packit 1fb8d4
	if (sysctl(mib, 2, kernelVersion, &len, NULL, 0) != 0)
Packit 1fb8d4
	{
Packit 1fb8d4
		free(kernelVersion);
Packit 1fb8d4
		return 0;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	tok = strtok(kernelVersion, ".");
Packit 1fb8d4
	errno = 0;
Packit 1fb8d4
Packit 1fb8d4
	while (tok)
Packit 1fb8d4
	{
Packit 1fb8d4
		switch (count)
Packit 1fb8d4
		{
Packit 1fb8d4
			case 0:
Packit 1fb8d4
				majorVersion = strtol(tok, NULL, 0);
Packit 1fb8d4
Packit 1fb8d4
				if (errno != 0)
Packit 1fb8d4
					goto fail;
Packit 1fb8d4
Packit 1fb8d4
				break;
Packit 1fb8d4
Packit 1fb8d4
			case 1:
Packit 1fb8d4
				minorVersion = strtol(tok, NULL, 0);
Packit 1fb8d4
Packit 1fb8d4
				if (errno != 0)
Packit 1fb8d4
					goto fail;
Packit 1fb8d4
Packit 1fb8d4
				break;
Packit 1fb8d4
Packit 1fb8d4
			case 2:
Packit 1fb8d4
				patchVersion = strtol(tok, NULL, 0);
Packit 1fb8d4
Packit 1fb8d4
				if (errno != 0)
Packit 1fb8d4
					goto fail;
Packit 1fb8d4
Packit 1fb8d4
				break;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		tok = strtok(NULL, ".");
Packit 1fb8d4
		count++;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	/**
Packit 1fb8d4
	 * Source : http://en.wikipedia.org/wiki/Darwin_(operating_system)
Packit 1fb8d4
	 **/
Packit 1fb8d4
	if (majorVersion < 5)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (minorVersion < 4)
Packit 1fb8d4
			version = 0x10000000;
Packit 1fb8d4
		else
Packit 1fb8d4
			version = 0x10010000;
Packit 1fb8d4
	}
Packit 1fb8d4
	else
Packit 1fb8d4
	{
Packit 1fb8d4
		switch (majorVersion)
Packit 1fb8d4
		{
Packit 1fb8d4
			case 5:
Packit 1fb8d4
				version = 0x10010000;
Packit 1fb8d4
				break;
Packit 1fb8d4
Packit 1fb8d4
			case 6:
Packit 1fb8d4
				version = 0x10020000;
Packit 1fb8d4
				break;
Packit 1fb8d4
Packit 1fb8d4
			case 7:
Packit 1fb8d4
				version = 0x10030000;
Packit 1fb8d4
				break;
Packit 1fb8d4
Packit 1fb8d4
			case 8:
Packit 1fb8d4
				version = 0x10040000;
Packit 1fb8d4
				break;
Packit 1fb8d4
Packit 1fb8d4
			case 9:
Packit 1fb8d4
				version = 0x10050000;
Packit 1fb8d4
				break;
Packit 1fb8d4
Packit 1fb8d4
			case 10:
Packit 1fb8d4
				version = 0x10060000;
Packit 1fb8d4
				break;
Packit 1fb8d4
Packit 1fb8d4
			case 11:
Packit 1fb8d4
				version = 0x10070000;
Packit 1fb8d4
				break;
Packit 1fb8d4
Packit 1fb8d4
			case 12:
Packit 1fb8d4
				version = 0x10080000;
Packit 1fb8d4
				break;
Packit 1fb8d4
Packit 1fb8d4
			case 13:
Packit 1fb8d4
				version = 0x10090000;
Packit 1fb8d4
				break;
Packit 1fb8d4
Packit 1fb8d4
			default:
Packit 1fb8d4
				version = 0x10100000;
Packit 1fb8d4
				break;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		version |= (minorVersion << 8) | (patchVersion);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
fail:
Packit 1fb8d4
	free(kernelVersion);
Packit 1fb8d4
	return version;
Packit 1fb8d4
}
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
SCardApiFunctionTable PCSC_SCardApiFunctionTable =
Packit 1fb8d4
{
Packit 1fb8d4
	0, /* dwVersion */
Packit 1fb8d4
	0, /* dwFlags */
Packit 1fb8d4
Packit 1fb8d4
	PCSC_SCardEstablishContext, /* SCardEstablishContext */
Packit 1fb8d4
	PCSC_SCardReleaseContext, /* SCardReleaseContext */
Packit 1fb8d4
	PCSC_SCardIsValidContext, /* SCardIsValidContext */
Packit 1fb8d4
	PCSC_SCardListReaderGroupsA, /* SCardListReaderGroupsA */
Packit 1fb8d4
	PCSC_SCardListReaderGroupsW, /* SCardListReaderGroupsW */
Packit 1fb8d4
	PCSC_SCardListReadersA, /* SCardListReadersA */
Packit 1fb8d4
	PCSC_SCardListReadersW, /* SCardListReadersW */
Packit 1fb8d4
	PCSC_SCardListCardsA, /* SCardListCardsA */
Packit 1fb8d4
	PCSC_SCardListCardsW, /* SCardListCardsW */
Packit 1fb8d4
	PCSC_SCardListInterfacesA, /* SCardListInterfacesA */
Packit 1fb8d4
	PCSC_SCardListInterfacesW, /* SCardListInterfacesW */
Packit 1fb8d4
	PCSC_SCardGetProviderIdA, /* SCardGetProviderIdA */
Packit 1fb8d4
	PCSC_SCardGetProviderIdW, /* SCardGetProviderIdW */
Packit 1fb8d4
	PCSC_SCardGetCardTypeProviderNameA, /* SCardGetCardTypeProviderNameA */
Packit 1fb8d4
	PCSC_SCardGetCardTypeProviderNameW, /* SCardGetCardTypeProviderNameW */
Packit 1fb8d4
	PCSC_SCardIntroduceReaderGroupA, /* SCardIntroduceReaderGroupA */
Packit 1fb8d4
	PCSC_SCardIntroduceReaderGroupW, /* SCardIntroduceReaderGroupW */
Packit 1fb8d4
	PCSC_SCardForgetReaderGroupA, /* SCardForgetReaderGroupA */
Packit 1fb8d4
	PCSC_SCardForgetReaderGroupW, /* SCardForgetReaderGroupW */
Packit 1fb8d4
	PCSC_SCardIntroduceReaderA, /* SCardIntroduceReaderA */
Packit 1fb8d4
	PCSC_SCardIntroduceReaderW, /* SCardIntroduceReaderW */
Packit 1fb8d4
	PCSC_SCardForgetReaderA, /* SCardForgetReaderA */
Packit 1fb8d4
	PCSC_SCardForgetReaderW, /* SCardForgetReaderW */
Packit 1fb8d4
	PCSC_SCardAddReaderToGroupA, /* SCardAddReaderToGroupA */
Packit 1fb8d4
	PCSC_SCardAddReaderToGroupW, /* SCardAddReaderToGroupW */
Packit 1fb8d4
	PCSC_SCardRemoveReaderFromGroupA, /* SCardRemoveReaderFromGroupA */
Packit 1fb8d4
	PCSC_SCardRemoveReaderFromGroupW, /* SCardRemoveReaderFromGroupW */
Packit 1fb8d4
	PCSC_SCardIntroduceCardTypeA, /* SCardIntroduceCardTypeA */
Packit 1fb8d4
	PCSC_SCardIntroduceCardTypeW, /* SCardIntroduceCardTypeW */
Packit 1fb8d4
	PCSC_SCardSetCardTypeProviderNameA, /* SCardSetCardTypeProviderNameA */
Packit 1fb8d4
	PCSC_SCardSetCardTypeProviderNameW, /* SCardSetCardTypeProviderNameW */
Packit 1fb8d4
	PCSC_SCardForgetCardTypeA, /* SCardForgetCardTypeA */
Packit 1fb8d4
	PCSC_SCardForgetCardTypeW, /* SCardForgetCardTypeW */
Packit 1fb8d4
	PCSC_SCardFreeMemory, /* SCardFreeMemory */
Packit 1fb8d4
	PCSC_SCardAccessStartedEvent, /* SCardAccessStartedEvent */
Packit 1fb8d4
	PCSC_SCardReleaseStartedEvent, /* SCardReleaseStartedEvent */
Packit 1fb8d4
	PCSC_SCardLocateCardsA, /* SCardLocateCardsA */
Packit 1fb8d4
	PCSC_SCardLocateCardsW, /* SCardLocateCardsW */
Packit 1fb8d4
	PCSC_SCardLocateCardsByATRA, /* SCardLocateCardsByATRA */
Packit 1fb8d4
	PCSC_SCardLocateCardsByATRW, /* SCardLocateCardsByATRW */
Packit 1fb8d4
	PCSC_SCardGetStatusChangeA, /* SCardGetStatusChangeA */
Packit 1fb8d4
	PCSC_SCardGetStatusChangeW, /* SCardGetStatusChangeW */
Packit 1fb8d4
	PCSC_SCardCancel, /* SCardCancel */
Packit 1fb8d4
	PCSC_SCardConnectA, /* SCardConnectA */
Packit 1fb8d4
	PCSC_SCardConnectW, /* SCardConnectW */
Packit 1fb8d4
	PCSC_SCardReconnect, /* SCardReconnect */
Packit 1fb8d4
	PCSC_SCardDisconnect, /* SCardDisconnect */
Packit 1fb8d4
	PCSC_SCardBeginTransaction, /* SCardBeginTransaction */
Packit 1fb8d4
	PCSC_SCardEndTransaction, /* SCardEndTransaction */
Packit 1fb8d4
	PCSC_SCardCancelTransaction, /* SCardCancelTransaction */
Packit 1fb8d4
	PCSC_SCardState, /* SCardState */
Packit 1fb8d4
	PCSC_SCardStatusA, /* SCardStatusA */
Packit 1fb8d4
	PCSC_SCardStatusW, /* SCardStatusW */
Packit 1fb8d4
	PCSC_SCardTransmit, /* SCardTransmit */
Packit 1fb8d4
	PCSC_SCardGetTransmitCount, /* SCardGetTransmitCount */
Packit 1fb8d4
	PCSC_SCardControl, /* SCardControl */
Packit 1fb8d4
	PCSC_SCardGetAttrib, /* SCardGetAttrib */
Packit 1fb8d4
	PCSC_SCardSetAttrib, /* SCardSetAttrib */
Packit 1fb8d4
	PCSC_SCardUIDlgSelectCardA, /* SCardUIDlgSelectCardA */
Packit 1fb8d4
	PCSC_SCardUIDlgSelectCardW, /* SCardUIDlgSelectCardW */
Packit 1fb8d4
	PCSC_GetOpenCardNameA, /* GetOpenCardNameA */
Packit 1fb8d4
	PCSC_GetOpenCardNameW, /* GetOpenCardNameW */
Packit 1fb8d4
	PCSC_SCardDlgExtendedError, /* SCardDlgExtendedError */
Packit 1fb8d4
	PCSC_SCardReadCacheA, /* SCardReadCacheA */
Packit 1fb8d4
	PCSC_SCardReadCacheW, /* SCardReadCacheW */
Packit 1fb8d4
	PCSC_SCardWriteCacheA, /* SCardWriteCacheA */
Packit 1fb8d4
	PCSC_SCardWriteCacheW, /* SCardWriteCacheW */
Packit 1fb8d4
	PCSC_SCardGetReaderIconA, /* SCardGetReaderIconA */
Packit 1fb8d4
	PCSC_SCardGetReaderIconW, /* SCardGetReaderIconW */
Packit 1fb8d4
	PCSC_SCardGetDeviceTypeIdA, /* SCardGetDeviceTypeIdA */
Packit 1fb8d4
	PCSC_SCardGetDeviceTypeIdW, /* SCardGetDeviceTypeIdW */
Packit 1fb8d4
	PCSC_SCardGetReaderDeviceInstanceIdA, /* SCardGetReaderDeviceInstanceIdA */
Packit 1fb8d4
	PCSC_SCardGetReaderDeviceInstanceIdW, /* SCardGetReaderDeviceInstanceIdW */
Packit 1fb8d4
	PCSC_SCardListReadersWithDeviceInstanceIdA, /* SCardListReadersWithDeviceInstanceIdA */
Packit 1fb8d4
	PCSC_SCardListReadersWithDeviceInstanceIdW, /* SCardListReadersWithDeviceInstanceIdW */
Packit 1fb8d4
	PCSC_SCardAudit /* SCardAudit */
Packit 1fb8d4
};
Packit 1fb8d4
Packit 1fb8d4
PSCardApiFunctionTable PCSC_GetSCardApiFunctionTable(void)
Packit 1fb8d4
{
Packit 1fb8d4
	return &PCSC_SCardApiFunctionTable;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
int PCSC_InitializeSCardApi(void)
Packit 1fb8d4
{
Packit 1fb8d4
	/* Disable pcsc-lite's (poor) blocking so we can handle it ourselves */
Packit 1fb8d4
	SetEnvironmentVariableA("PCSCLITE_NO_BLOCKING", "1");
Packit 1fb8d4
#ifdef __MACOSX__
Packit 1fb8d4
	g_PCSCModule = LoadLibraryA("/System/Library/Frameworks/PCSC.framework/PCSC");
Packit 1fb8d4
	OSXVersion = determineMacOSXVersion();
Packit 1fb8d4
Packit 1fb8d4
	if (OSXVersion == 0)
Packit 1fb8d4
		return -1;
Packit 1fb8d4
Packit 1fb8d4
#else
Packit 1fb8d4
	g_PCSCModule = LoadLibraryA("libpcsclite.so.1");
Packit 1fb8d4
Packit 1fb8d4
	if (!g_PCSCModule)
Packit 1fb8d4
		g_PCSCModule = LoadLibraryA("libpcsclite.so");
Packit 1fb8d4
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
	if (!g_PCSCModule)
Packit 1fb8d4
		return -1;
Packit 1fb8d4
Packit 1fb8d4
	g_PCSC.pfnSCardEstablishContext = (void*) GetProcAddress(g_PCSCModule, "SCardEstablishContext");
Packit 1fb8d4
	g_PCSC.pfnSCardReleaseContext = (void*) GetProcAddress(g_PCSCModule, "SCardReleaseContext");
Packit 1fb8d4
	g_PCSC.pfnSCardIsValidContext = (void*) GetProcAddress(g_PCSCModule, "SCardIsValidContext");
Packit 1fb8d4
	g_PCSC.pfnSCardConnect = (void*) GetProcAddress(g_PCSCModule, "SCardConnect");
Packit 1fb8d4
	g_PCSC.pfnSCardReconnect = (void*) GetProcAddress(g_PCSCModule, "SCardReconnect");
Packit 1fb8d4
	g_PCSC.pfnSCardDisconnect = (void*) GetProcAddress(g_PCSCModule, "SCardDisconnect");
Packit 1fb8d4
	g_PCSC.pfnSCardBeginTransaction = (void*) GetProcAddress(g_PCSCModule, "SCardBeginTransaction");
Packit 1fb8d4
	g_PCSC.pfnSCardEndTransaction = (void*) GetProcAddress(g_PCSCModule, "SCardEndTransaction");
Packit 1fb8d4
	g_PCSC.pfnSCardStatus = (void*) GetProcAddress(g_PCSCModule, "SCardStatus");
Packit 1fb8d4
	g_PCSC.pfnSCardGetStatusChange = (void*) GetProcAddress(g_PCSCModule, "SCardGetStatusChange");
Packit 1fb8d4
#ifdef __MACOSX__
Packit 1fb8d4
Packit 1fb8d4
	if (OSXVersion >= 0x10050600)
Packit 1fb8d4
		g_PCSC.pfnSCardControl = (void*) GetProcAddress(g_PCSCModule, "SCardControl132");
Packit 1fb8d4
	else
Packit 1fb8d4
		g_PCSC.pfnSCardControl = (void*) GetProcAddress(g_PCSCModule, "SCardControl");
Packit 1fb8d4
Packit 1fb8d4
#else
Packit 1fb8d4
	g_PCSC.pfnSCardControl = (void*) GetProcAddress(g_PCSCModule, "SCardControl");
Packit 1fb8d4
#endif
Packit 1fb8d4
	g_PCSC.pfnSCardTransmit = (void*) GetProcAddress(g_PCSCModule, "SCardTransmit");
Packit 1fb8d4
	g_PCSC.pfnSCardListReaderGroups = (void*) GetProcAddress(g_PCSCModule, "SCardListReaderGroups");
Packit 1fb8d4
	g_PCSC.pfnSCardListReaders = (void*) GetProcAddress(g_PCSCModule, "SCardListReaders");
Packit 1fb8d4
	g_PCSC.pfnSCardCancel = (void*) GetProcAddress(g_PCSCModule, "SCardCancel");
Packit 1fb8d4
	g_PCSC.pfnSCardGetAttrib = (void*) GetProcAddress(g_PCSCModule, "SCardGetAttrib");
Packit 1fb8d4
	g_PCSC.pfnSCardSetAttrib = (void*) GetProcAddress(g_PCSCModule, "SCardSetAttrib");
Packit 1fb8d4
	g_PCSC.pfnSCardFreeMemory = NULL;
Packit 1fb8d4
#ifndef __APPLE__
Packit 1fb8d4
	g_PCSC.pfnSCardFreeMemory = (void*) GetProcAddress(g_PCSCModule, "SCardFreeMemory");
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
	if (g_PCSC.pfnSCardFreeMemory)
Packit 1fb8d4
		g_SCardAutoAllocate = TRUE;
Packit 1fb8d4
Packit 1fb8d4
#ifdef DISABLE_PCSC_SCARD_AUTOALLOCATE
Packit 1fb8d4
	g_PCSC.pfnSCardFreeMemory = NULL;
Packit 1fb8d4
	g_SCardAutoAllocate = FALSE;
Packit 1fb8d4
#endif
Packit 1fb8d4
#ifdef __APPLE__
Packit 1fb8d4
	g_PnP_Notification = FALSE;
Packit 1fb8d4
#endif
Packit 1fb8d4
	return 1;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
Packit 1fb8d4
#endif