You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
6837 lines
201 KiB
6837 lines
201 KiB
/*++
|
|
|
|
Copyright (c) 1998-2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
w32drive
|
|
|
|
Abstract:
|
|
|
|
This module defines a child of the client-side RDP
|
|
device redirection, the "w32scard" W32SCard to provide
|
|
SmartCard sub-system redirection on 32bit windows
|
|
|
|
Author:
|
|
|
|
reidk
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include <precom.h>
|
|
|
|
#define TRC_GROUP TRC_GROUP_NETWORK
|
|
#define TRC_FILE "W32SCard"
|
|
#include <atrcapi.h>
|
|
|
|
#include <w32scard.h>
|
|
#include <delayimp.h>
|
|
#include "proc.h"
|
|
#include "drconfig.h"
|
|
#include "w32utl.h"
|
|
#include "utl.h"
|
|
#include "drfsfile.h"
|
|
#include "scredir.h"
|
|
#include "scioctl.h"
|
|
#include "winsmcrd.h"
|
|
|
|
|
|
#ifdef OS_WINCE
|
|
|
|
#include <wcescard.h>
|
|
|
|
#define LoadLibraryA(x) LoadLibrary(L##x)
|
|
#define pfnSCardFreeMemory(hcontext, pv)
|
|
|
|
#endif
|
|
|
|
#define _TRY_status(x) \
|
|
__try \
|
|
{ \
|
|
x; \
|
|
} \
|
|
__except(EXCEPTION_EXECUTE_HANDLER) \
|
|
{ \
|
|
status = STATUS_UNSUCCESSFUL; \
|
|
goto ErrorReturn; \
|
|
}
|
|
|
|
#define _TRY_lReturn(x) \
|
|
__try \
|
|
{ \
|
|
x; \
|
|
} \
|
|
__except(EXCEPTION_EXECUTE_HANDLER) \
|
|
{ \
|
|
lReturn = SCARD_E_UNEXPECTED; \
|
|
goto ErrorReturn; \
|
|
}
|
|
|
|
#define _TRY_2(x) __try \
|
|
{ \
|
|
x; \
|
|
} \
|
|
__except(EXCEPTION_EXECUTE_HANDLER){} // do nothing
|
|
|
|
|
|
#define SCARD_CONTEXT_LIST_ALLOC_SIZE 6
|
|
#define SCARD_THREAD_LIST_ALLOC_SIZE 6
|
|
#define SCARD_IOREQUEST_LIST_ALLOC_SIZE 6
|
|
|
|
#define ATR_COPY_SIZE 36
|
|
|
|
|
|
void
|
|
SafeMesHandleFree(handle_t *ph)
|
|
{
|
|
if (*ph != 0)
|
|
{
|
|
MesHandleFree(*ph);
|
|
*ph = 0;
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------
|
|
//
|
|
// MIDL allocation routines
|
|
//
|
|
//---------------------------------------------------------------------------------------
|
|
void __RPC_FAR *__RPC_USER MIDL_user_allocate(size_t size)
|
|
{
|
|
return (HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size));
|
|
}
|
|
|
|
void __RPC_USER MIDL_user_free(void __RPC_FAR *pv)
|
|
{
|
|
if (pv != NULL)
|
|
{
|
|
HeapFree(GetProcessHeap(), 0, pv);
|
|
}
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
//
|
|
// W32SCard Methods
|
|
//
|
|
//
|
|
|
|
W32SCard::W32SCard(
|
|
ProcObj *processObject,
|
|
ULONG deviceID,
|
|
const TCHAR *deviceName,
|
|
const TCHAR *devicePath) : W32DrDeviceAsync(processObject, deviceID, devicePath)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Constructor
|
|
|
|
Arguments:
|
|
|
|
processObject - Associated process object.
|
|
deviceName - Name of the drive.
|
|
id - Device ID for the drive.
|
|
devicePath - Path that can be opened by CreateFile
|
|
for drive.
|
|
|
|
Return Value:
|
|
|
|
NA
|
|
|
|
--*/
|
|
{
|
|
unsigned len;
|
|
DWORD i;
|
|
HRESULT hr;
|
|
|
|
DC_BEGIN_FN("W32SCard::W32SCard");
|
|
|
|
_deviceName = NULL;
|
|
_pFileObj = NULL;
|
|
_rgSCardContextList = NULL;
|
|
_dwSCardContextListSize = 0;
|
|
_rghThreadList = NULL;
|
|
_dwThreadListSize = 0;
|
|
_fInDestructor = FALSE;
|
|
_fFlushing = FALSE;
|
|
_hModWinscard = NULL;
|
|
_fCritSecsInitialized = FALSE;
|
|
_rgIORequestList = NULL;
|
|
_dwIORequestListSize = 0;
|
|
_fNewFailed = FALSE;
|
|
|
|
#ifndef OS_WINCE
|
|
_hModKernel32 = NULL;
|
|
_hStartedEvent = NULL;
|
|
_hRegisterWaitForStartedEvent = NULL;
|
|
_fCloseStartedEvent = FALSE;
|
|
_fUseRegisterWaitFuncs = FALSE;
|
|
#endif
|
|
|
|
SetDeviceProperty();
|
|
|
|
//
|
|
// Initialize the critical sections.
|
|
//
|
|
__try
|
|
{
|
|
InitializeCriticalSection(&_csContextList);
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
TRC_ERR((
|
|
TB,
|
|
_T("InitializeCriticalSection() failed - Exception Code: %lx"),
|
|
GetExceptionCode()));
|
|
|
|
goto InvalidObject;
|
|
}
|
|
|
|
__try
|
|
{
|
|
InitializeCriticalSection(&_csThreadList);
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
TRC_ERR((
|
|
TB,
|
|
_T("InitializeCriticalSection() failed - Exception Code: %lx"),
|
|
GetExceptionCode()));
|
|
|
|
DeleteCriticalSection(&_csContextList);
|
|
goto InvalidObject;
|
|
}
|
|
|
|
__try
|
|
{
|
|
InitializeCriticalSection(&_csWaitForStartedEvent);
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
TRC_ERR((
|
|
TB,
|
|
_T("InitializeCriticalSection() failed - Exception Code: %lx"),
|
|
GetExceptionCode()));
|
|
|
|
DeleteCriticalSection(&_csContextList);
|
|
DeleteCriticalSection(&_csThreadList);
|
|
goto InvalidObject;
|
|
}
|
|
|
|
_fCritSecsInitialized = TRUE;
|
|
|
|
#ifdef OS_WINCE
|
|
if ((gpCESCard = new CESCard()) == NULL)
|
|
{
|
|
TRC_ERR((TB, _T("Failed to create synchronization object") ));
|
|
goto InvalidObject;
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Load the SCard* function pointers
|
|
//
|
|
if (!BindToSCardFunctions())
|
|
{
|
|
goto InvalidObject;
|
|
}
|
|
|
|
//
|
|
// Record the drive name.
|
|
//
|
|
TRC_ASSERT((deviceName != NULL), (TB, _T("deviceName is NULL")));
|
|
len = (STRLEN(deviceName) + 1);
|
|
_deviceName = new TCHAR[len];
|
|
if (_deviceName != NULL)
|
|
{
|
|
hr = StringCchCopy(_deviceName, len, deviceName);
|
|
TRC_ASSERT(SUCCEEDED(hr),(TB,_T("Pre checked copy failed: 0x%x"), hr));
|
|
}
|
|
else
|
|
{
|
|
goto InvalidObject;
|
|
}
|
|
|
|
//
|
|
// Initial allocation for context, thread, and IORequest lists
|
|
//
|
|
_rgSCardContextList = new SCARDCONTEXT[SCARD_CONTEXT_LIST_ALLOC_SIZE];
|
|
_rghThreadList = new HANDLE[SCARD_THREAD_LIST_ALLOC_SIZE];
|
|
_rgIORequestList = new PRDPDR_IOREQUEST_PACKET[SCARD_IOREQUEST_LIST_ALLOC_SIZE];
|
|
if ((_rgSCardContextList == NULL) ||
|
|
(_rghThreadList == NULL) ||
|
|
(_rgIORequestList == NULL))
|
|
{
|
|
goto InvalidObject;
|
|
}
|
|
else
|
|
{
|
|
_dwSCardContextListSize = SCARD_CONTEXT_LIST_ALLOC_SIZE;
|
|
_dwThreadListSize = SCARD_THREAD_LIST_ALLOC_SIZE;
|
|
_dwIORequestListSize = SCARD_IOREQUEST_LIST_ALLOC_SIZE;
|
|
|
|
memset(
|
|
_rgSCardContextList,
|
|
0,
|
|
sizeof(SCARDCONTEXT) * SCARD_CONTEXT_LIST_ALLOC_SIZE);
|
|
|
|
for (i=0; i<SCARD_THREAD_LIST_ALLOC_SIZE; i++)
|
|
{
|
|
_rghThreadList[i] = NULL;
|
|
}
|
|
|
|
for (i=0; i<SCARD_IOREQUEST_LIST_ALLOC_SIZE; i++)
|
|
{
|
|
_rgIORequestList[i] = NULL;
|
|
}
|
|
}
|
|
|
|
Return:
|
|
|
|
DC_END_FN();
|
|
return;
|
|
|
|
InvalidObject:
|
|
|
|
_fNewFailed = TRUE;
|
|
SetValid(FALSE);
|
|
goto Return;
|
|
}
|
|
|
|
|
|
W32SCard::~W32SCard()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Destructor
|
|
|
|
Arguments:
|
|
|
|
NA
|
|
|
|
Return Value:
|
|
|
|
NA
|
|
|
|
--*/
|
|
{
|
|
DC_BEGIN_FN("W32SCard::~W32SCard");
|
|
|
|
_fInDestructor = TRUE;
|
|
|
|
#ifndef OS_WINCE
|
|
PVOID pv;
|
|
|
|
pv = InterlockedExchangePointer(&_hRegisterWaitForStartedEvent, NULL);
|
|
if (pv != NULL)
|
|
{
|
|
pfnUnregisterWaitEx(pv, INVALID_HANDLE_VALUE);
|
|
}
|
|
#endif
|
|
|
|
if (IsValid())
|
|
{
|
|
FlushIRPs();
|
|
}
|
|
|
|
if (_deviceName != NULL)
|
|
{
|
|
delete[]_deviceName;
|
|
}
|
|
|
|
if (_pFileObj != NULL)
|
|
{
|
|
_pFileObj->Release();
|
|
}
|
|
|
|
if (_rgSCardContextList != NULL)
|
|
{
|
|
delete[]_rgSCardContextList;
|
|
}
|
|
|
|
if (_rghThreadList != NULL)
|
|
{
|
|
delete[]_rghThreadList;
|
|
}
|
|
|
|
if (_rgIORequestList != NULL)
|
|
{
|
|
delete[]_rgIORequestList;
|
|
}
|
|
|
|
if (_hModWinscard != NULL)
|
|
{
|
|
FreeLibrary(_hModWinscard);
|
|
}
|
|
|
|
#ifndef OS_WINCE
|
|
if (_hModKernel32 != NULL)
|
|
{
|
|
FreeLibrary(_hModKernel32);
|
|
}
|
|
|
|
if (_hStartedEvent != NULL)
|
|
{
|
|
ReleaseStartedEvent();;
|
|
}
|
|
#endif
|
|
|
|
if (_fCritSecsInitialized)
|
|
{
|
|
DeleteCriticalSection(&_csContextList);
|
|
DeleteCriticalSection(&_csThreadList);
|
|
DeleteCriticalSection(&_csWaitForStartedEvent);
|
|
}
|
|
|
|
#ifdef OS_WINCE
|
|
delete gpCESCard;
|
|
#endif
|
|
|
|
DC_END_FN();
|
|
}
|
|
|
|
#ifndef OS_WINCE
|
|
extern LPCSTR g_szTscControlName;
|
|
#else
|
|
extern LPCWSTR g_szTscControlName;
|
|
#endif
|
|
|
|
HMODULE
|
|
W32SCard::AddRefCurrentModule()
|
|
{
|
|
#ifndef OS_WINCE
|
|
return (LoadLibraryA(g_szTscControlName));
|
|
#else
|
|
return LoadLibrary(g_szTscControlName);
|
|
#endif
|
|
}
|
|
|
|
|
|
VOID
|
|
W32SCard::FlushIRPs()
|
|
{
|
|
DC_BEGIN_FN("W32SCard::FlushIRPs");
|
|
|
|
DWORD i, j;
|
|
DWORD dwNumThreads = 0;
|
|
HANDLE *rgHandles = NULL;
|
|
|
|
_fFlushing = TRUE;
|
|
|
|
EnterCriticalSection(&_csContextList);
|
|
EnterCriticalSection(&_csThreadList);
|
|
|
|
//
|
|
// Clean up any oustanding threads that are blocked
|
|
//
|
|
if ((_rgSCardContextList != NULL) && (_rghThreadList != NULL))
|
|
{
|
|
//
|
|
// Count number of blocked threads
|
|
//
|
|
dwNumThreads = 0;
|
|
for (i=0; i<_dwThreadListSize; i++)
|
|
{
|
|
if (_rghThreadList[i] != NULL)
|
|
{
|
|
dwNumThreads++;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Build an array of thread handles to wait for
|
|
//
|
|
#ifdef OS_WINCE
|
|
if (dwNumThreads > 0)
|
|
#endif
|
|
rgHandles = new HANDLE[dwNumThreads];
|
|
if (rgHandles != NULL)
|
|
{
|
|
dwNumThreads = 0;
|
|
for (i=0; i<_dwThreadListSize; i++)
|
|
{
|
|
if (_rghThreadList[i] != NULL)
|
|
{
|
|
#ifndef OS_WINCE
|
|
if (!DuplicateHandle(
|
|
GetCurrentProcess(),
|
|
_rghThreadList[i],
|
|
GetCurrentProcess(),
|
|
&(rgHandles[dwNumThreads]),
|
|
0,
|
|
FALSE,
|
|
DUPLICATE_SAME_ACCESS))
|
|
{
|
|
TRC_ERR((TB, _T("DuplicateHandle failed.")));
|
|
|
|
//
|
|
// Nothing we can do... just clean up the already
|
|
// duplicated handles
|
|
//
|
|
for (j=0; j<dwNumThreads; j++)
|
|
{
|
|
CloseHandle(rgHandles[j]);
|
|
}
|
|
|
|
//
|
|
// Setting dwNumThread to 0 will cause no wait
|
|
//
|
|
dwNumThreads = 0;
|
|
|
|
break;
|
|
}
|
|
#else //CE does not support DuplicateHandle for threads
|
|
rgHandles[dwNumThreads] = _rghThreadList[i];
|
|
#endif
|
|
|
|
dwNumThreads++;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TRC_ERR((TB, _T("new failed.")));
|
|
}
|
|
|
|
//
|
|
// Cancel any outstanding calls
|
|
//
|
|
for (i=0; i<_dwSCardContextListSize; i++)
|
|
{
|
|
if (_rgSCardContextList[i] != NULL)
|
|
{
|
|
pfnSCardCancel(_rgSCardContextList[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
LeaveCriticalSection(&_csContextList);
|
|
LeaveCriticalSection(&_csThreadList);
|
|
|
|
//
|
|
// Do the wait
|
|
//
|
|
if (dwNumThreads > 0)
|
|
{
|
|
#ifndef OS_WINCE
|
|
if (WaitForMultipleObjects(
|
|
dwNumThreads,
|
|
rgHandles,
|
|
TRUE,
|
|
INFINITE) == WAIT_TIMEOUT)
|
|
{
|
|
TRC_ERR((TB, _T("WaitForMultipleObjects timed out")));
|
|
}
|
|
#else
|
|
//CE does not support waiting for all at once
|
|
for (j=0; j<dwNumThreads; j++)
|
|
{
|
|
DWORD dwWait = WaitForSingleObject(rgHandles[j], 30 * 1000);
|
|
if (dwWait != WAIT_OBJECT_0)
|
|
{
|
|
TRC_ERR((TB, _T("WaitForSingleObject 0x%08x returned 0x%08x. GLE=%d(0x%08x)"), rgHandles[j], dwWait, GetLastError(), GetLastError()));
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
//
|
|
// Close the duplicate handles
|
|
//
|
|
for (i=0; i<dwNumThreads; i++)
|
|
{
|
|
CloseHandle(rgHandles[i]);
|
|
}
|
|
|
|
#ifdef OS_WINCE
|
|
gpCESCard->FlushIRPs();
|
|
#endif
|
|
|
|
if (rgHandles != NULL)
|
|
{
|
|
delete[]rgHandles;
|
|
}
|
|
|
|
_fFlushing = FALSE;
|
|
|
|
DC_END_FN();
|
|
}
|
|
|
|
|
|
DWORD
|
|
W32SCard::Enumerate(
|
|
IN ProcObj *procObj,
|
|
IN DrDeviceMgr *deviceMgr
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Enumerate devices of this type by adding appropriate device
|
|
instances to the device manager.
|
|
|
|
Arguments:
|
|
|
|
procObj - Corresponding process object.
|
|
deviceMgr - Device manager to add devices to.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS on success. Otherwise, an error code is returned.
|
|
|
|
--*/
|
|
{
|
|
W32SCard *pScardDeviceObj = NULL;
|
|
RDPDR_VERSION serverVer;
|
|
DrFile *pFileObj = NULL;
|
|
OSVERSIONINFOA osVersion;
|
|
|
|
DC_BEGIN_FN("W32SCard::Enumerate");
|
|
|
|
//
|
|
// Make sure we are on an OS that we support
|
|
//
|
|
memset(&osVersion, 0x00, sizeof(osVersion));
|
|
osVersion.dwOSVersionInfoSize = sizeof(osVersion);
|
|
if (!GetVersionExA(&osVersion))
|
|
{
|
|
TRC_ERR((TB, _T("GetVersionEx() failed")));
|
|
return ERROR_SUCCESS; // don't blcok anything else from running
|
|
}
|
|
|
|
if (osVersion.dwMajorVersion < 5)
|
|
{
|
|
TRC_DBG((TB,_T("SmartCard redirection does not work on platforms below Win2k, bailing out")));
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
if(!procObj->GetVCMgr().GetInitData()->fEnableSCardRedirection)
|
|
{
|
|
TRC_DBG((TB,_T("SmartCard redirection disabled, bailing out")));
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
serverVer = procObj->serverVersion();
|
|
|
|
//
|
|
// If the server doesn't support scard device redirection,
|
|
// then don't bother enumerate the scard device, simply
|
|
// return success
|
|
//
|
|
if (COMPARE_VERSION(serverVer.Minor, serverVer.Major,
|
|
RDPDR_MINOR_VERSION, RDPDR_MAJOR_VERSION) < 0)
|
|
{
|
|
TRC_NRM((TB, _T("Skipping scard device enumeration")));
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
|
|
//
|
|
// Create the scard device object
|
|
//
|
|
pScardDeviceObj = new W32SCard(
|
|
procObj,
|
|
deviceMgr->GetUniqueObjectID(),
|
|
SZ_SCARD_DEVICE_NAME,
|
|
SZ_SCARD_DEVICE_NAME);
|
|
|
|
if (pScardDeviceObj == NULL)
|
|
{
|
|
TRC_ERR((TB, _T("new W32SCard() failed")));
|
|
}
|
|
else
|
|
{
|
|
if (!(pScardDeviceObj->_fNewFailed))
|
|
{
|
|
pScardDeviceObj->Initialize();
|
|
}
|
|
|
|
if (!pScardDeviceObj->IsValid())
|
|
{
|
|
TRC_ERR((TB, _T("new W32SCard object is not valid")));
|
|
delete (pScardDeviceObj);
|
|
pScardDeviceObj = NULL;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Create the single file object to be used for the Scard device object
|
|
//
|
|
// BTW, we can use INVALID_HANDLE_VALUE as the actual file handle since
|
|
// we don't really use the DrFile object except for the FileId
|
|
//
|
|
pScardDeviceObj->_pFileObj = new DrFile(
|
|
pScardDeviceObj,
|
|
DR_SMARTCARD_FILEID,
|
|
INVALID_HANDLE_VALUE);
|
|
if (pScardDeviceObj->_pFileObj == NULL)
|
|
{
|
|
TRC_ERR((TB, _T("new DrFile() failed")));
|
|
delete (pScardDeviceObj);
|
|
pScardDeviceObj = NULL;
|
|
}
|
|
else
|
|
{
|
|
pScardDeviceObj->_pFileObj->AddRef();
|
|
|
|
//
|
|
// Add the Scard device to the device manager
|
|
//
|
|
if (deviceMgr->AddObject(pScardDeviceObj) != STATUS_SUCCESS)
|
|
{
|
|
TRC_ERR((TB, _T("deviceMgr->AddObject() failed")));
|
|
delete (pScardDeviceObj);
|
|
pScardDeviceObj = NULL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
DC_END_FN();
|
|
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
ULONG
|
|
W32SCard::GetDevAnnounceDataSize()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Return the size (in bytes) of a device announce packet for
|
|
this device.
|
|
|
|
Arguments:
|
|
|
|
NA
|
|
|
|
Return Value:
|
|
|
|
The size (in bytes) of a device announce packet for this device.
|
|
|
|
--*/
|
|
{
|
|
ULONG size = 0;
|
|
|
|
DC_BEGIN_FN("W32SCard::GetDevAnnounceDataSize");
|
|
|
|
TRC_ASSERT((IsValid()), (TB, _T("Invalid W32SCard object")));
|
|
if (!IsValid()) { return 0; }
|
|
|
|
size = 0;
|
|
|
|
//
|
|
// Add the base announce size.
|
|
//
|
|
size += sizeof(RDPDR_DEVICE_ANNOUNCE);
|
|
|
|
DC_END_FN();
|
|
|
|
return size;
|
|
}
|
|
|
|
VOID W32SCard::GetDevAnnounceData(
|
|
IN PRDPDR_DEVICE_ANNOUNCE pDeviceAnnounce
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Add a device announce packet for this device to the input buffer.
|
|
|
|
Arguments:
|
|
|
|
pDeviceAnnounce - Device Announce Buf for this Device
|
|
|
|
Return Value:
|
|
|
|
NA
|
|
|
|
--*/
|
|
{
|
|
DC_BEGIN_FN("W32SCard::GetDevAnnounceData");
|
|
|
|
TRC_ASSERT((IsValid()), (TB, _T("Invalid W32SCcard object")));
|
|
if (!IsValid()) {
|
|
DC_END_FN();
|
|
return;
|
|
}
|
|
|
|
pDeviceAnnounce->DeviceId = GetID();
|
|
pDeviceAnnounce->DeviceType = GetDeviceType();
|
|
pDeviceAnnounce->DeviceDataLength = 0;
|
|
|
|
//
|
|
// Record the device name in ANSI.
|
|
//
|
|
|
|
#ifdef UNICODE
|
|
RDPConvertToAnsi(_deviceName, (LPSTR) pDeviceAnnounce->PreferredDosName,
|
|
sizeof(pDeviceAnnounce->PreferredDosName)
|
|
);
|
|
#else
|
|
STRNCPY((char *)pDeviceAnnounce->PreferredDosName, _deviceName, PREFERRED_DOS_NAME_SIZE);
|
|
pDeviceAnnounce->PreferredDosName[PREFERRED_DOS_NAME_SIZE - 1] = '\0';
|
|
#endif
|
|
|
|
DC_END_FN();
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------------------
|
|
//
|
|
// These methods implement a list that is used for tracking all open SCardContexts,
|
|
// so that if we get disconnected with an open SCardContext that has blocked calls,
|
|
// we can call SCardCancel to get the threads back before the W32SCard object is
|
|
// fully deleted
|
|
//
|
|
//---------------------------------------------------------------------------------------
|
|
BOOL
|
|
W32SCard::AddSCardContextToList(
|
|
SCARDCONTEXT SCardContext)
|
|
{
|
|
DC_BEGIN_FN("W32SCard::AddSCardContextToList");
|
|
|
|
DWORD i = 0;
|
|
DWORD dwOpenSlot = 0xffffffff;
|
|
SCARDCONTEXT *pTemp = NULL;
|
|
BOOL fRet = TRUE;
|
|
|
|
EnterCriticalSection(&_csContextList);
|
|
|
|
//
|
|
// See if there is already an entry for this context,
|
|
// and keep track of the LAST open slot in case there isn't
|
|
//
|
|
for (i=0; i<_dwSCardContextListSize; i++)
|
|
{
|
|
if (_rgSCardContextList[i] == SCardContext)
|
|
{
|
|
//
|
|
// already exists
|
|
//
|
|
goto Return;
|
|
}
|
|
else if (_rgSCardContextList[i] == NULL)
|
|
{
|
|
dwOpenSlot = i;
|
|
}
|
|
}
|
|
|
|
//
|
|
// check to see if an open slot was found
|
|
//
|
|
if (dwOpenSlot != 0xffffffff)
|
|
{
|
|
//
|
|
// found
|
|
//
|
|
_rgSCardContextList[dwOpenSlot] = SCardContext;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// need to allocate more space
|
|
//
|
|
pTemp = new SCARDCONTEXT[ _dwSCardContextListSize +
|
|
SCARD_CONTEXT_LIST_ALLOC_SIZE];
|
|
if (pTemp == NULL)
|
|
{
|
|
TRC_ERR((TB, _T("new failed")));
|
|
fRet = FALSE;
|
|
LeaveCriticalSection(&_csContextList);
|
|
goto Return;
|
|
}
|
|
|
|
memset(
|
|
pTemp,
|
|
0,
|
|
sizeof(SCARDCONTEXT) *
|
|
(_dwSCardContextListSize + SCARD_CONTEXT_LIST_ALLOC_SIZE));
|
|
|
|
//
|
|
// populate newly allocated array with all current entries
|
|
//
|
|
for (i=0; i<_dwSCardContextListSize; i++)
|
|
{
|
|
pTemp[i] = _rgSCardContextList[i];
|
|
}
|
|
|
|
//
|
|
// add the new entry
|
|
//
|
|
pTemp[_dwSCardContextListSize] = SCardContext;
|
|
|
|
//
|
|
// free old list
|
|
//
|
|
delete[]_rgSCardContextList;
|
|
|
|
//
|
|
// reset member pointer and size
|
|
//
|
|
_rgSCardContextList = pTemp;
|
|
_dwSCardContextListSize += SCARD_CONTEXT_LIST_ALLOC_SIZE;
|
|
}
|
|
|
|
LeaveCriticalSection(&_csContextList);
|
|
|
|
Return:
|
|
|
|
DC_END_FN();
|
|
|
|
return (fRet);
|
|
}
|
|
|
|
|
|
void
|
|
W32SCard::RemoveSCardContextFromList(
|
|
SCARDCONTEXT SCardContext)
|
|
{
|
|
DC_BEGIN_FN("W32SCard::RemoveSCardContextFromList");
|
|
|
|
DWORD i = 0;
|
|
|
|
EnterCriticalSection(&_csContextList);
|
|
|
|
while (i < _dwSCardContextListSize)
|
|
{
|
|
if (_rgSCardContextList[i] == SCardContext)
|
|
{
|
|
pfnSCardCancel(_rgSCardContextList[i]);
|
|
_rgSCardContextList[i] = NULL;
|
|
break;
|
|
}
|
|
|
|
i++;
|
|
}
|
|
|
|
LeaveCriticalSection(&_csContextList);
|
|
|
|
Return:
|
|
|
|
DC_END_FN();
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------------------
|
|
//
|
|
// These methods implement a list that is used for tracking all threads that are
|
|
// currently operating on a SCard* call. The list is used during the W32SCard object
|
|
// destructor to wait on all the threads to return before allowing the object to be
|
|
// completely deleted.
|
|
//
|
|
//---------------------------------------------------------------------------------------
|
|
|
|
BOOL
|
|
W32SCard::AddThreadToList(HANDLE hThread)
|
|
{
|
|
DC_BEGIN_FN("W32SCard::AddThreadToList");
|
|
|
|
DWORD i = 0;
|
|
HANDLE *rghTemp = NULL;
|
|
BOOL fRet = TRUE;
|
|
DWORD dwNewSize = 0;
|
|
|
|
EnterCriticalSection(&_csThreadList);
|
|
|
|
//
|
|
// Search for an open slot
|
|
//
|
|
while (i < _dwThreadListSize)
|
|
{
|
|
if (_rghThreadList[i] == NULL)
|
|
{
|
|
//
|
|
// open slot found
|
|
//
|
|
break;
|
|
}
|
|
|
|
i++;
|
|
}
|
|
|
|
//
|
|
// check to see if an open slot was found
|
|
//
|
|
if (i < _dwThreadListSize)
|
|
{
|
|
//
|
|
// found
|
|
//
|
|
_rghThreadList[i] = hThread;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// need to allocate more space
|
|
//
|
|
dwNewSize = _dwThreadListSize + SCARD_THREAD_LIST_ALLOC_SIZE;
|
|
rghTemp = new HANDLE[dwNewSize];
|
|
if (rghTemp == NULL)
|
|
{
|
|
TRC_ERR((TB, _T("new failed")));
|
|
fRet = FALSE;
|
|
LeaveCriticalSection(&_csThreadList);
|
|
goto Return;
|
|
}
|
|
|
|
//
|
|
// populate newly allocated array with all current thread handles
|
|
//
|
|
for (i=0; i<_dwThreadListSize; i++)
|
|
{
|
|
rghTemp[i] = _rghThreadList[i];
|
|
}
|
|
|
|
//
|
|
// Initialize new entries
|
|
//
|
|
for (i=_dwThreadListSize; i<dwNewSize; i++)
|
|
{
|
|
rghTemp[i] = NULL;
|
|
}
|
|
|
|
//
|
|
// add the new entry
|
|
//
|
|
rghTemp[_dwThreadListSize] = hThread;
|
|
|
|
//
|
|
// free old list
|
|
//
|
|
delete[]_rghThreadList;
|
|
|
|
//
|
|
// reset member pointer and size
|
|
//
|
|
_rghThreadList = rghTemp;
|
|
_dwThreadListSize += SCARD_THREAD_LIST_ALLOC_SIZE;
|
|
}
|
|
|
|
LeaveCriticalSection(&_csThreadList);
|
|
|
|
Return:
|
|
|
|
DC_END_FN();
|
|
|
|
return (fRet);
|
|
}
|
|
|
|
|
|
void
|
|
W32SCard::RemoveThreadFromList(HANDLE hThread)
|
|
{
|
|
DC_BEGIN_FN("W32SCard::RemoveThreadFromList");
|
|
|
|
DWORD i = 0;
|
|
|
|
EnterCriticalSection(&_csThreadList);
|
|
|
|
while (i < _dwThreadListSize)
|
|
{
|
|
if (_rghThreadList[i] == hThread)
|
|
{
|
|
CloseHandle(_rghThreadList[i]);
|
|
_rghThreadList[i] = NULL;
|
|
|
|
break;
|
|
}
|
|
|
|
i++;
|
|
}
|
|
|
|
LeaveCriticalSection(&_csThreadList);
|
|
|
|
Return:
|
|
|
|
DC_END_FN();
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------------------
|
|
//
|
|
// This method implements a list that is used for tracking IORequests waiting for the
|
|
// started event
|
|
//
|
|
//---------------------------------------------------------------------------------------
|
|
|
|
BOOL
|
|
W32SCard::AddIORequestToList(
|
|
PRDPDR_IOREQUEST_PACKET pIoRequestPacket)
|
|
{
|
|
DC_BEGIN_FN("W32SCard::AddIORequestToList");
|
|
|
|
DWORD i = 0;
|
|
PRDPDR_IOREQUEST_PACKET *rghTemp = NULL;
|
|
BOOL fRet = TRUE;
|
|
DWORD dwNewSize = 0;
|
|
|
|
//
|
|
// Only called in one place, which is wrapped in a CritSec, so no need for one here
|
|
//
|
|
|
|
//
|
|
// Search for an open slot
|
|
//
|
|
while (i < _dwIORequestListSize)
|
|
{
|
|
if (_rgIORequestList[i] == NULL)
|
|
{
|
|
//
|
|
// open slot found
|
|
//
|
|
break;
|
|
}
|
|
|
|
i++;
|
|
}
|
|
|
|
//
|
|
// check to see if an open slot was found
|
|
//
|
|
if (i < _dwIORequestListSize)
|
|
{
|
|
//
|
|
// found
|
|
//
|
|
_rgIORequestList[i] = pIoRequestPacket;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// need to allocate more space
|
|
//
|
|
dwNewSize = _dwIORequestListSize + SCARD_IOREQUEST_LIST_ALLOC_SIZE;
|
|
rghTemp = new PRDPDR_IOREQUEST_PACKET[dwNewSize];
|
|
if (rghTemp == NULL)
|
|
{
|
|
TRC_ERR((TB, _T("new failed")));
|
|
fRet = FALSE;
|
|
goto Return;
|
|
}
|
|
|
|
//
|
|
// populate newly allocated array with all current IoRequests
|
|
//
|
|
for (i=0; i<_dwIORequestListSize; i++)
|
|
{
|
|
rghTemp[i] = _rgIORequestList[i];
|
|
}
|
|
|
|
//
|
|
// Initialize new entries
|
|
//
|
|
for (i=_dwIORequestListSize; i<dwNewSize; i++)
|
|
{
|
|
rghTemp[i] = NULL;
|
|
}
|
|
|
|
//
|
|
// add the new entry
|
|
//
|
|
rghTemp[_dwIORequestListSize] = pIoRequestPacket;
|
|
|
|
//
|
|
// free old list
|
|
//
|
|
delete[]_rgIORequestList;
|
|
|
|
//
|
|
// reset member pointer and size
|
|
//
|
|
_rgIORequestList = rghTemp;
|
|
_dwIORequestListSize += SCARD_IOREQUEST_LIST_ALLOC_SIZE;
|
|
}
|
|
|
|
Return:
|
|
|
|
DC_END_FN();
|
|
|
|
return (fRet);
|
|
}
|
|
|
|
|
|
|
|
|
|
DWORD WINAPI
|
|
W32SCard::SCardHandleCall_ThreadProc(
|
|
LPVOID lpParameter)
|
|
{
|
|
DC_BEGIN_FN("W32SCard::SCardHandleCall_ThreadProc");
|
|
|
|
LONG lReturn = SCARD_S_SUCCESS;
|
|
SCARDHANDLECALLSTRUCT *pStruct = (SCARDHANDLECALLSTRUCT *) lpParameter;
|
|
W32SCard *pTHIS = pStruct->pTHIS;
|
|
HANDLE hThread = pStruct->hThread;
|
|
HMODULE hModExtraRefCount = pStruct->hModExtraRefCount;
|
|
|
|
pStruct = (SCARDHANDLECALLSTRUCT *) lpParameter;
|
|
|
|
//
|
|
// pStruct->hThread will be NULL if it wasn't added to the thread list...
|
|
// it wasn't added to the thread list then just get out.
|
|
//
|
|
if (pStruct->hThread == NULL)
|
|
{
|
|
FreeLibraryAndExitThread(pStruct->hModExtraRefCount, 0);
|
|
}
|
|
|
|
switch (pStruct->dwCallType)
|
|
{
|
|
case SCARD_IOCTL_CONNECTA:
|
|
TRC_DBG((TB, _T("SCARD_IOCTL_CONNECTA")));
|
|
pTHIS->Connect(
|
|
pStruct,
|
|
SCARD_IOCTL_CONNECTA);
|
|
break;
|
|
|
|
case SCARD_IOCTL_CONNECTW:
|
|
TRC_DBG((TB, _T("SCARD_IOCTL_CONNECTW")));
|
|
pTHIS->Connect(
|
|
pStruct,
|
|
SCARD_IOCTL_CONNECTW);
|
|
break;
|
|
|
|
case SCARD_IOCTL_RECONNECT:
|
|
TRC_DBG((TB, _T("SCARD_IOCTL_RECONNECT")));
|
|
pTHIS->Reconnect(
|
|
pStruct);
|
|
break;
|
|
|
|
case SCARD_IOCTL_DISCONNECT:
|
|
TRC_DBG((TB, _T("SCARD_IOCTL_DISCONNECT")));
|
|
pTHIS->HandleHCardAndDispositionCall(
|
|
pStruct,
|
|
SCARD_IOCTL_DISCONNECT);
|
|
break;
|
|
|
|
case SCARD_IOCTL_BEGINTRANSACTION:
|
|
TRC_DBG((TB, _T("SCARD_IOCTL_BEGINTRANSACTION")));
|
|
pTHIS->HandleHCardAndDispositionCall(
|
|
pStruct,
|
|
SCARD_IOCTL_BEGINTRANSACTION);
|
|
break;
|
|
|
|
case SCARD_IOCTL_ENDTRANSACTION:
|
|
TRC_DBG((TB, _T("SCARD_IOCTL_ENDTRANSACTION")));
|
|
pTHIS->HandleHCardAndDispositionCall(
|
|
pStruct,
|
|
SCARD_IOCTL_ENDTRANSACTION);
|
|
break;
|
|
|
|
#ifndef OS_WINCE
|
|
case SCARD_IOCTL_STATE:
|
|
TRC_DBG((TB, _T("SCARD_IOCTL_STATE")));
|
|
pTHIS->State(
|
|
pStruct);
|
|
break;
|
|
#endif
|
|
|
|
case SCARD_IOCTL_STATUSA:
|
|
TRC_DBG((TB, _T("SCARD_IOCTL_STATUSA")));
|
|
pTHIS->Status(
|
|
pStruct,
|
|
SCARD_IOCTL_STATUSA);
|
|
break;
|
|
|
|
case SCARD_IOCTL_STATUSW:
|
|
TRC_DBG((TB, _T("SCARD_IOCTL_STATUSW")));
|
|
pTHIS->Status(
|
|
pStruct,
|
|
SCARD_IOCTL_STATUSW);
|
|
break;
|
|
|
|
case SCARD_IOCTL_TRANSMIT:
|
|
TRC_DBG((TB, _T("SCARD_IOCTL_TRANSMIT")));
|
|
pTHIS->Transmit(
|
|
pStruct);
|
|
break;
|
|
|
|
case SCARD_IOCTL_CONTROL:
|
|
TRC_DBG((TB, _T("SCARD_IOCTL_CONTROL")));
|
|
pTHIS->Control(
|
|
pStruct);
|
|
|
|
break;
|
|
|
|
case SCARD_IOCTL_GETATTRIB:
|
|
TRC_DBG((TB, _T("SCARD_IOCTL_GETATTRIB")));
|
|
pTHIS->GetAttrib(
|
|
pStruct);
|
|
break;
|
|
|
|
case SCARD_IOCTL_SETATTRIB:
|
|
TRC_DBG((TB, _T("SCARD_IOCTL_SETATTRIB")));
|
|
pTHIS->SetAttrib(
|
|
pStruct);
|
|
break;
|
|
}
|
|
#if defined (OS_WINCE) && defined(DEBUG)
|
|
PRDPDR_DEVICE_IOREQUEST pIoRequest = &(pStruct->pIoRequestPacket->IoRequest);
|
|
TRC_DATA_DBG("Input buffer",(char *) (pIoRequest + 1), pIoRequest->Parameters.DeviceIoControl.InputBufferLength);
|
|
#endif
|
|
|
|
pTHIS->RemoveThreadFromList(hThread);
|
|
FreeLibraryAndExitThread(hModExtraRefCount, 0);
|
|
DC_END_FN();
|
|
#ifdef OS_WINCE
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
|
|
VOID
|
|
W32SCard::DefaultIORequestMsgHandleWrapper(
|
|
IN PRDPDR_IOREQUEST_PACKET pIoRequestPacket,
|
|
IN NTSTATUS serverReturnStatus
|
|
)
|
|
{
|
|
if (!_fInDestructor && !_fFlushing)
|
|
{
|
|
DefaultIORequestMsgHandle(pIoRequestPacket, serverReturnStatus);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Just drop it on the floor if we are shutting down or flushing
|
|
//
|
|
delete(pIoRequestPacket);
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
W32SCard::MsgIrpDeviceControl(
|
|
IN PRDPDR_IOREQUEST_PACKET pIoRequestPacket,
|
|
IN UINT32 packetLen
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Handle a file system control request from the server.
|
|
|
|
Arguments:
|
|
|
|
pIoRequestPacket - Server IO request packet.
|
|
packetLen - Length of the packet
|
|
|
|
Return Value:
|
|
|
|
NA
|
|
|
|
--*/
|
|
{
|
|
DC_BEGIN_FN("W32SCard::MsgIrpDeviceControl");
|
|
|
|
PRDPDR_DEVICE_IOREQUEST pIoRequest = &(pIoRequestPacket->IoRequest);
|
|
HMODULE hModExtraRefCount = NULL;
|
|
SCARDHANDLECALLSTRUCT *pStruct = NULL;
|
|
HANDLE hThread;
|
|
DWORD dwThreadId;
|
|
|
|
if (!pIoRequest->Parameters.DeviceIoControl.InputBufferLength)
|
|
{
|
|
// no data, get out
|
|
return;
|
|
}
|
|
|
|
switch(pIoRequest->Parameters.DeviceIoControl.IoControlCode)
|
|
{
|
|
case SCARD_IOCTL_ESTABLISHCONTEXT:
|
|
TRC_DBG((TB, _T("SCARD_IOCTL_ESTABLISHCONTEXT")));
|
|
EstablishContext(pIoRequestPacket);
|
|
break;
|
|
|
|
case SCARD_IOCTL_RELEASECONTEXT:
|
|
TRC_DBG((TB, _T("SCARD_IOCTL_RELEASECONTEXT")));
|
|
HandleContextCallWithLongReturn(
|
|
pIoRequestPacket,
|
|
SCARD_IOCTL_RELEASECONTEXT);
|
|
break;
|
|
|
|
case SCARD_IOCTL_ISVALIDCONTEXT:
|
|
TRC_DBG((TB, _T("SCARD_IOCTL_ISVALIDCONTEXT")));
|
|
HandleContextCallWithLongReturn(
|
|
pIoRequestPacket,
|
|
SCARD_IOCTL_ISVALIDCONTEXT);
|
|
break;
|
|
|
|
case SCARD_IOCTL_LISTREADERGROUPSA:
|
|
TRC_DBG((TB, _T("SCARD_IOCTL_LISTREADERGROUPSA")));
|
|
ListReaderGroups(
|
|
pIoRequestPacket,
|
|
SCARD_IOCTL_LISTREADERGROUPSA);
|
|
break;
|
|
|
|
case SCARD_IOCTL_LISTREADERGROUPSW:
|
|
TRC_DBG((TB, _T("SCARD_IOCTL_LISTREADERGROUPSW")));
|
|
ListReaderGroups(
|
|
pIoRequestPacket,
|
|
SCARD_IOCTL_LISTREADERGROUPSW);
|
|
break;
|
|
|
|
case SCARD_IOCTL_LISTREADERSA:
|
|
TRC_DBG((TB, _T("SCARD_IOCTL_LISTREADERSA")));
|
|
ListReaders(
|
|
pIoRequestPacket,
|
|
SCARD_IOCTL_LISTREADERSA);
|
|
break;
|
|
|
|
case SCARD_IOCTL_LISTREADERSW:
|
|
TRC_DBG((TB, _T("SCARD_IOCTL_LISTREADERSW")));
|
|
ListReaders(
|
|
pIoRequestPacket,
|
|
SCARD_IOCTL_LISTREADERSW);
|
|
break;
|
|
|
|
case SCARD_IOCTL_INTRODUCEREADERGROUPA:
|
|
TRC_DBG((TB, _T("SCARD_IOCTL_INTRODUCEREADERGROUPA")));
|
|
HandleContextAndStringCallWithLongReturn(
|
|
pIoRequestPacket,
|
|
SCARD_IOCTL_INTRODUCEREADERGROUPA);
|
|
break;
|
|
|
|
case SCARD_IOCTL_INTRODUCEREADERGROUPW:
|
|
TRC_DBG((TB, _T("SCARD_IOCTL_INTRODUCEREADERGROUPW")));
|
|
HandleContextAndStringCallWithLongReturn(
|
|
pIoRequestPacket,
|
|
SCARD_IOCTL_INTRODUCEREADERGROUPW);
|
|
break;
|
|
|
|
case SCARD_IOCTL_FORGETREADERGROUPA:
|
|
TRC_DBG((TB, _T("SCARD_IOCTL_FORGETREADERGROUPA")));
|
|
HandleContextAndStringCallWithLongReturn(
|
|
pIoRequestPacket,
|
|
SCARD_IOCTL_FORGETREADERGROUPA);
|
|
break;
|
|
|
|
case SCARD_IOCTL_FORGETREADERGROUPW:
|
|
TRC_DBG((TB, _T("SCARD_IOCTL_FORGETREADERGROUPW")));
|
|
HandleContextAndStringCallWithLongReturn(
|
|
pIoRequestPacket,
|
|
SCARD_IOCTL_FORGETREADERGROUPW);
|
|
break;
|
|
|
|
case SCARD_IOCTL_INTRODUCEREADERA:
|
|
TRC_DBG((TB, _T("SCARD_IOCTL_INTRODUCEREADERA")));
|
|
HandleContextAndTwoStringCallWithLongReturn(
|
|
pIoRequestPacket,
|
|
SCARD_IOCTL_INTRODUCEREADERA);
|
|
break;
|
|
|
|
case SCARD_IOCTL_INTRODUCEREADERW:
|
|
TRC_DBG((TB, _T("SCARD_IOCTL_INTRODUCEREADERW")));
|
|
HandleContextAndTwoStringCallWithLongReturn(
|
|
pIoRequestPacket,
|
|
SCARD_IOCTL_INTRODUCEREADERW);
|
|
break;
|
|
|
|
case SCARD_IOCTL_FORGETREADERA:
|
|
TRC_DBG((TB, _T("SCARD_IOCTL_FORGETREADERA")));
|
|
HandleContextAndStringCallWithLongReturn(
|
|
pIoRequestPacket,
|
|
SCARD_IOCTL_FORGETREADERA);
|
|
break;
|
|
|
|
case SCARD_IOCTL_FORGETREADERW:
|
|
TRC_DBG((TB, _T("SCARD_IOCTL_FORGETREADERW")));
|
|
HandleContextAndStringCallWithLongReturn(
|
|
pIoRequestPacket,
|
|
SCARD_IOCTL_FORGETREADERW);
|
|
break;
|
|
|
|
case SCARD_IOCTL_ADDREADERTOGROUPA:
|
|
TRC_DBG((TB, _T("SCARD_IOCTL_ADDREADERTOGROUPA")));
|
|
HandleContextAndTwoStringCallWithLongReturn(
|
|
pIoRequestPacket,
|
|
SCARD_IOCTL_ADDREADERTOGROUPA);
|
|
break;
|
|
|
|
case SCARD_IOCTL_ADDREADERTOGROUPW:
|
|
TRC_DBG((TB, _T("SCARD_IOCTL_ADDREADERTOGROUPW")));
|
|
HandleContextAndTwoStringCallWithLongReturn(
|
|
pIoRequestPacket,
|
|
SCARD_IOCTL_ADDREADERTOGROUPW);
|
|
break;
|
|
|
|
case SCARD_IOCTL_REMOVEREADERFROMGROUPA:
|
|
TRC_DBG((TB, _T("SCARD_IOCTL_REMOVEREADERFROMGROUPA")));
|
|
HandleContextAndTwoStringCallWithLongReturn(
|
|
pIoRequestPacket,
|
|
SCARD_IOCTL_REMOVEREADERFROMGROUPA);
|
|
break;
|
|
|
|
case SCARD_IOCTL_REMOVEREADERFROMGROUPW:
|
|
TRC_DBG((TB, _T("SCARD_IOCTL_REMOVEREADERFROMGROUPW")));
|
|
HandleContextAndTwoStringCallWithLongReturn(
|
|
pIoRequestPacket,
|
|
SCARD_IOCTL_REMOVEREADERFROMGROUPW);
|
|
break;
|
|
|
|
case SCARD_IOCTL_LOCATECARDSA:
|
|
TRC_DBG((TB, _T("SCARD_IOCTL_LOCATECARDSA")));
|
|
LocateCardsA(pIoRequestPacket);
|
|
break;
|
|
|
|
case SCARD_IOCTL_LOCATECARDSW:
|
|
TRC_DBG((TB, _T("SCARD_IOCTL_LOCATECARDSW")));
|
|
LocateCardsW(pIoRequestPacket);
|
|
break;
|
|
|
|
case SCARD_IOCTL_LOCATECARDSBYATRA:
|
|
TRC_DBG((TB, _T("SCARD_IOCTL_LOCATECARDSBYATRA")));
|
|
LocateCardsByATRA(pIoRequestPacket);
|
|
break;
|
|
|
|
case SCARD_IOCTL_LOCATECARDSBYATRW:
|
|
TRC_DBG((TB, _T("SCARD_IOCTL_LOCATECARDSBYATRW")));
|
|
LocateCardsByATRW(pIoRequestPacket);
|
|
break;
|
|
|
|
case SCARD_IOCTL_GETSTATUSCHANGEA:
|
|
TRC_DBG((TB, _T("SCARD_IOCTL_GETSTATUSCHANGEA")));
|
|
GetStatusChangeWrapper(
|
|
pIoRequestPacket,
|
|
SCARD_IOCTL_GETSTATUSCHANGEA);
|
|
break;
|
|
|
|
case SCARD_IOCTL_GETSTATUSCHANGEW:
|
|
TRC_DBG((TB, _T("SCARD_IOCTL_GETSTATUSCHANGEW")));
|
|
GetStatusChangeWrapper(
|
|
pIoRequestPacket,
|
|
SCARD_IOCTL_GETSTATUSCHANGEW);
|
|
break;
|
|
|
|
case SCARD_IOCTL_CANCEL:
|
|
TRC_DBG((TB, _T("SCARD_IOCTL_CANCEL")));
|
|
HandleContextCallWithLongReturn(
|
|
pIoRequestPacket,
|
|
SCARD_IOCTL_CANCEL);
|
|
break;
|
|
|
|
//
|
|
// Possibly blocking calls, so create a thread to make the call
|
|
//
|
|
case SCARD_IOCTL_CONNECTA:
|
|
case SCARD_IOCTL_CONNECTW:
|
|
case SCARD_IOCTL_RECONNECT:
|
|
case SCARD_IOCTL_DISCONNECT:
|
|
case SCARD_IOCTL_BEGINTRANSACTION:
|
|
case SCARD_IOCTL_ENDTRANSACTION:
|
|
#ifndef OS_WINCE
|
|
case SCARD_IOCTL_STATE:
|
|
#endif
|
|
case SCARD_IOCTL_STATUSA:
|
|
case SCARD_IOCTL_STATUSW:
|
|
case SCARD_IOCTL_TRANSMIT:
|
|
case SCARD_IOCTL_CONTROL:
|
|
case SCARD_IOCTL_GETATTRIB:
|
|
case SCARD_IOCTL_SETATTRIB:
|
|
|
|
//
|
|
// Get a ref count on our dll so that we know the dll
|
|
// code won't disappear from underneath us. The thread will
|
|
// release this ref count when it exits
|
|
//
|
|
hModExtraRefCount = AddRefCurrentModule();
|
|
if (hModExtraRefCount == NULL)
|
|
{
|
|
TRC_ERR((TB, _T("AddRefCurrentModule() failed.")));
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
//
|
|
// Allocate the struct to pass to the thread
|
|
//
|
|
pStruct = (SCARDHANDLECALLSTRUCT *)
|
|
MIDL_user_allocate(sizeof(SCARDHANDLECALLSTRUCT));
|
|
if (pStruct == NULL)
|
|
{
|
|
TRC_ERR((TB, _T("MIDL_user_allocate failed to alloc %ld bytes."), sizeof(SCARDHANDLECALLSTRUCT)));
|
|
goto ErrorReturn;
|
|
}
|
|
pStruct->pTHIS = this;
|
|
pStruct->dwCallType = pIoRequest->Parameters.DeviceIoControl.IoControlCode;
|
|
pStruct->pIoRequestPacket = pIoRequestPacket;
|
|
pStruct->hModExtraRefCount = hModExtraRefCount;
|
|
pStruct->hThread = NULL;
|
|
|
|
//
|
|
// Create a thread that will do the actual work
|
|
//
|
|
EnterCriticalSection(&_csThreadList);
|
|
|
|
//
|
|
// If the object is currently being destroyed, then don't create a new thread.
|
|
//
|
|
if (_fInDestructor)
|
|
{
|
|
LeaveCriticalSection(&_csThreadList);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
hThread = CreateThread(
|
|
NULL,
|
|
0,
|
|
SCardHandleCall_ThreadProc,
|
|
pStruct,
|
|
CREATE_SUSPENDED,
|
|
&dwThreadId);
|
|
if (hThread == NULL)
|
|
{
|
|
TRC_ERR((TB, _T("CreateThread failed with %lx."), GetLastError()));
|
|
LeaveCriticalSection(&_csThreadList);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
if (!AddThreadToList(hThread))
|
|
{
|
|
LeaveCriticalSection(&_csThreadList);
|
|
ResumeThread(hThread);
|
|
WaitForSingleObject(hThread, INFINITE);
|
|
CloseHandle(hThread);
|
|
|
|
//
|
|
// do this so we don't do an extra FreeLibrary. (since the thread actually
|
|
// got created the thread istself will do the FreeLibrary).
|
|
//
|
|
hModExtraRefCount = NULL;
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
LeaveCriticalSection(&_csThreadList);
|
|
|
|
//
|
|
// Now let the thread go
|
|
//
|
|
pStruct->hThread = hThread;
|
|
ResumeThread(hThread);
|
|
|
|
//
|
|
// return here and let the thread we just created
|
|
// make the EncodeAndChannelWriteLongReturn call,
|
|
// which will send the return the calling server
|
|
//
|
|
break;
|
|
|
|
case SCARD_IOCTL_ACCESSSTARTEDEVENT:
|
|
TRC_DBG((TB, _T("SCARD_IOCTL_ACCESSSTARTEDEVENT")));
|
|
AccessStartedEvent(
|
|
pIoRequestPacket);
|
|
break;
|
|
|
|
#ifdef OS_WINCE
|
|
default:
|
|
TRC_ERR((TB, _T("Unsupported ioctl=0x%x(%d) function = %d"), pIoRequest->Parameters.DeviceIoControl.IoControlCode,
|
|
pIoRequest->Parameters.DeviceIoControl.IoControlCode, ((pIoRequest->Parameters.DeviceIoControl.IoControlCode & 0x3FFC) >> 2)));
|
|
DefaultIORequestMsgHandleWrapper(pIoRequestPacket, STATUS_NOT_SUPPORTED);
|
|
break;
|
|
#endif
|
|
}
|
|
#if defined(OS_WINCE) && defined(DEBUG)
|
|
if (hModExtraRefCount != NULL)
|
|
{
|
|
TRC_DATA_DBG("Input buffer",(char *) (pIoRequest + 1), pIoRequest->Parameters.DeviceIoControl.InputBufferLength);
|
|
}
|
|
#endif
|
|
|
|
Return:
|
|
|
|
DC_END_FN();
|
|
|
|
return;
|
|
|
|
ErrorReturn:
|
|
|
|
if (hModExtraRefCount != NULL)
|
|
{
|
|
FreeLibrary(hModExtraRefCount);
|
|
}
|
|
|
|
MIDL_user_free(pStruct);
|
|
|
|
DefaultIORequestMsgHandleWrapper(pIoRequestPacket, STATUS_NO_MEMORY);
|
|
|
|
goto Return;
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------------------
|
|
//
|
|
// W32SCard::AllocateAndChannelWriteReplyPacket
|
|
//
|
|
//---------------------------------------------------------------------------------------
|
|
void
|
|
W32SCard::AllocateAndChannelWriteReplyPacket(
|
|
IN PRDPDR_IOREQUEST_PACKET pIoRequestPacket,
|
|
IN char *pbEncodedBuffer,
|
|
IN unsigned long cbEncodedBuffer)
|
|
{
|
|
DC_BEGIN_FN("W32SCard::AllocateAndChannelWriteReplyPacket");
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
PRDPDR_IOCOMPLETION_PACKET pReplyPacket = NULL;
|
|
ULONG replyPacketSize = 0;
|
|
|
|
//
|
|
// If we are deleting this object, then just get out.
|
|
//
|
|
if (_fInDestructor || _fFlushing)
|
|
{
|
|
delete(pIoRequestPacket);
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Check the size of the output buffer.
|
|
//
|
|
status = DrUTL_CheckIOBufOutputSize(pIoRequestPacket, cbEncodedBuffer);
|
|
|
|
//
|
|
// Allocate reply buffer
|
|
//
|
|
if (status == STATUS_SUCCESS)
|
|
{
|
|
status = DrUTL_AllocateReplyBuf(
|
|
pIoRequestPacket,
|
|
&pReplyPacket,
|
|
&replyPacketSize);
|
|
}
|
|
|
|
//
|
|
// Write reply to channel
|
|
//
|
|
if (status == STATUS_SUCCESS)
|
|
{
|
|
memcpy(
|
|
pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBuffer,
|
|
pbEncodedBuffer,
|
|
cbEncodedBuffer);
|
|
|
|
pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBufferLength
|
|
= cbEncodedBuffer;
|
|
|
|
pReplyPacket->IoCompletion.IoStatus = STATUS_SUCCESS;
|
|
|
|
//
|
|
// in DrUTL_AllocateReplyBuf the replyPacketSize is set to the max size
|
|
// allowed given the calling servers output buffer size, but we just need
|
|
// cbEncodedBuffer size. And, we know there is enough space since the
|
|
// DrUTL_CheckIOBufOutputSize call succeeded
|
|
//
|
|
replyPacketSize = cbEncodedBuffer +
|
|
(ULONG)FIELD_OFFSET(RDPDR_IOCOMPLETION_PACKET,
|
|
IoCompletion.Parameters.DeviceIoControl.OutputBuffer);
|
|
|
|
ProcessObject()->GetVCMgr().ChannelWrite(pReplyPacket, replyPacketSize);
|
|
}
|
|
else
|
|
{
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
delete(pIoRequestPacket);
|
|
|
|
Return:
|
|
|
|
DC_END_FN();
|
|
|
|
return;
|
|
|
|
ErrorReturn:
|
|
|
|
DefaultIORequestMsgHandleWrapper(pIoRequestPacket, status);
|
|
|
|
goto Return;
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------------------
|
|
//
|
|
// W32SCard::DecodeContextCall
|
|
//
|
|
//---------------------------------------------------------------------------------------
|
|
LONG
|
|
W32SCard::DecodeContextCall(
|
|
IN PRDPDR_IOREQUEST_PACKET pIoRequestPacket,
|
|
OUT SCARDCONTEXT *pSCardContext)
|
|
{
|
|
DC_BEGIN_FN("W32SCard::DecodeContextCall");
|
|
|
|
RPC_STATUS rpcStatus = RPC_S_OK;
|
|
LONG lReturn = SCARD_S_SUCCESS;
|
|
handle_t hDec = 0;
|
|
Context_Call ContextCall;
|
|
PRDPDR_DEVICE_IOREQUEST pIoRequest = &(pIoRequestPacket->IoRequest);
|
|
|
|
//
|
|
// Do the decode
|
|
//
|
|
rpcStatus = MesDecodeBufferHandleCreate(
|
|
(char *) (pIoRequest + 1), // bytes are at end of struct
|
|
pIoRequest->Parameters.DeviceIoControl.InputBufferLength,
|
|
&hDec);
|
|
if (rpcStatus != RPC_S_OK)
|
|
{
|
|
TRC_ERR((TB, _T("MesDecodeBufferHandleCreate failed with %lx."), rpcStatus));
|
|
lReturn = SCARD_E_NO_MEMORY;
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
memset(&ContextCall, 0, sizeof(ContextCall));
|
|
_TRY_lReturn(Context_Call_Decode(hDec, &ContextCall))
|
|
|
|
//
|
|
// Copy the decoded context to the callers memory
|
|
//
|
|
if (sizeof(SCARDCONTEXT) != ContextCall.Context.cbContext)
|
|
{
|
|
TRC_ERR((TB, _T("Invalid context from server")));
|
|
lReturn = SCARD_E_INVALID_PARAMETER;
|
|
goto ErrorReturn;
|
|
}
|
|
*pSCardContext = *((SCARDCONTEXT *) ContextCall.Context.pbContext);
|
|
|
|
//
|
|
// Free the resources used for decode of parameters
|
|
//
|
|
_TRY_2(Context_Call_Free(hDec, &ContextCall))
|
|
|
|
Return:
|
|
|
|
SafeMesHandleFree(&hDec);
|
|
|
|
DC_END_FN();
|
|
|
|
return (lReturn);
|
|
|
|
ErrorReturn:
|
|
|
|
goto Return;
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------------------
|
|
//
|
|
// W32SCard::DecodeContextAndStringCallA
|
|
//
|
|
//---------------------------------------------------------------------------------------
|
|
LONG
|
|
W32SCard::DecodeContextAndStringCallA(
|
|
IN PRDPDR_IOREQUEST_PACKET pIoRequestPacket,
|
|
OUT SCARDCONTEXT *pSCardContext,
|
|
OUT LPSTR *ppsz)
|
|
{
|
|
DC_BEGIN_FN("W32SCard::DecodeContextAndStringCallA");
|
|
|
|
RPC_STATUS rpcStatus = RPC_S_OK;
|
|
LONG lReturn = SCARD_S_SUCCESS;
|
|
handle_t hDec = 0;
|
|
BOOL fFreeDecode = FALSE;
|
|
ContextAndStringA_Call ContextAndStringCallA;
|
|
PRDPDR_DEVICE_IOREQUEST pIoRequest = &(pIoRequestPacket->IoRequest);
|
|
UINT cbStrLen = 0;
|
|
HRESULT hr;
|
|
|
|
//
|
|
// Decode input parameters
|
|
//
|
|
rpcStatus = MesDecodeBufferHandleCreate(
|
|
(char *) (pIoRequest + 1), // bytes are at end of struct
|
|
pIoRequest->Parameters.DeviceIoControl.InputBufferLength,
|
|
&hDec);
|
|
if (rpcStatus != RPC_S_OK)
|
|
{
|
|
TRC_ERR((TB, _T("MesDecodeBufferHandleCreate failed with %lx."), rpcStatus));
|
|
lReturn = SCARD_E_NO_MEMORY;
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
memset(&ContextAndStringCallA, 0, sizeof(ContextAndStringCallA));
|
|
_TRY_lReturn(ContextAndStringA_Call_Decode(hDec, &ContextAndStringCallA))
|
|
fFreeDecode = TRUE;
|
|
|
|
//
|
|
// Copy the contents to the callers out params
|
|
//
|
|
if (ContextAndStringCallA.Context.pbContext != NULL)
|
|
{
|
|
if (sizeof(SCARDCONTEXT) != ContextAndStringCallA.Context.cbContext)
|
|
{
|
|
TRC_ERR((TB, _T("Invalid context from server")));
|
|
lReturn = SCARD_E_INVALID_PARAMETER;
|
|
goto ErrorReturn;
|
|
}
|
|
*pSCardContext = *((SCARDCONTEXT *) ContextAndStringCallA.Context.pbContext);
|
|
}
|
|
else
|
|
{
|
|
*pSCardContext = NULL;
|
|
}
|
|
|
|
if (ContextAndStringCallA.sz == NULL)
|
|
{
|
|
TRC_ERR((TB, _T("Invalid string from server")));
|
|
lReturn = SCARD_E_INVALID_VALUE;
|
|
goto ErrorReturn;
|
|
}
|
|
cbStrLen = (strlen(ContextAndStringCallA.sz) + 1) * sizeof(char);
|
|
|
|
*ppsz = (LPSTR)
|
|
MIDL_user_allocate(cbStrLen);
|
|
|
|
if (*ppsz == NULL)
|
|
{
|
|
TRC_ERR((TB, _T("MIDL_user_allocate failed")));
|
|
lReturn = SCARD_E_NO_MEMORY;
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
hr = StringCbCopyA(*ppsz, cbStrLen, ContextAndStringCallA.sz);
|
|
TRC_ASSERT(SUCCEEDED(hr),(TB,_T("Pre checked copy failed: 0x%x"), hr));
|
|
|
|
Return:
|
|
|
|
if (fFreeDecode)
|
|
{
|
|
_TRY_2(ContextAndStringA_Call_Free(hDec, &ContextAndStringCallA))
|
|
}
|
|
SafeMesHandleFree(&hDec);
|
|
|
|
DC_END_FN();
|
|
|
|
return (lReturn);
|
|
|
|
ErrorReturn:
|
|
|
|
goto Return;
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------------------
|
|
//
|
|
// W32SCard::DecodeContextAndStringCallW
|
|
//
|
|
//---------------------------------------------------------------------------------------
|
|
LONG
|
|
W32SCard::DecodeContextAndStringCallW(
|
|
IN PRDPDR_IOREQUEST_PACKET pIoRequestPacket,
|
|
OUT SCARDCONTEXT *pSCardContext,
|
|
OUT LPWSTR *ppwsz)
|
|
{
|
|
DC_BEGIN_FN("W32SCard::DecodeContextAndStringCallW");
|
|
|
|
RPC_STATUS rpcStatus = RPC_S_OK;
|
|
LONG lReturn = SCARD_S_SUCCESS;
|
|
handle_t hDec = 0;
|
|
BOOL fFreeDecode = FALSE;
|
|
ContextAndStringW_Call ContextAndStringCallW;
|
|
PRDPDR_DEVICE_IOREQUEST pIoRequest = &(pIoRequestPacket->IoRequest);
|
|
UINT cbStrLen = 0;
|
|
HRESULT hr;
|
|
|
|
//
|
|
// Decode input parameters
|
|
//
|
|
rpcStatus = MesDecodeBufferHandleCreate(
|
|
(char *) (pIoRequest + 1), // bytes are at end of struct
|
|
pIoRequest->Parameters.DeviceIoControl.InputBufferLength,
|
|
&hDec);
|
|
if (rpcStatus != RPC_S_OK)
|
|
{
|
|
TRC_ERR((TB, _T("MesDecodeBufferHandleCreate failed with %lx."), rpcStatus));
|
|
lReturn = SCARD_E_NO_MEMORY;
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
memset(&ContextAndStringCallW, 0, sizeof(ContextAndStringCallW));
|
|
_TRY_lReturn(ContextAndStringW_Call_Decode(hDec, &ContextAndStringCallW))
|
|
fFreeDecode = TRUE;
|
|
|
|
//
|
|
// Copy the contents to the callers out params
|
|
//
|
|
if (ContextAndStringCallW.Context.pbContext != NULL)
|
|
{
|
|
if (sizeof(SCARDCONTEXT) != ContextAndStringCallW.Context.cbContext)
|
|
{
|
|
TRC_ERR((TB, _T("Invalid context from server")));
|
|
lReturn = SCARD_E_INVALID_PARAMETER;
|
|
goto ErrorReturn;
|
|
}
|
|
*pSCardContext = *((SCARDCONTEXT *) ContextAndStringCallW.Context.pbContext);
|
|
}
|
|
else
|
|
{
|
|
*pSCardContext = NULL;
|
|
}
|
|
|
|
if (ContextAndStringCallW.sz == NULL)
|
|
{
|
|
TRC_ERR((TB, _T("Invalid string from server")));
|
|
lReturn = SCARD_E_INVALID_VALUE;
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
cbStrLen = (wcslen(ContextAndStringCallW.sz) + 1) * sizeof(WCHAR);
|
|
|
|
*ppwsz = (LPWSTR)
|
|
MIDL_user_allocate(cbStrLen);
|
|
|
|
if (*ppwsz == NULL)
|
|
{
|
|
TRC_ERR((TB, _T("MIDL_user_allocate failed")));
|
|
lReturn = SCARD_E_NO_MEMORY;
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
hr = StringCbCopyW(*ppwsz, cbStrLen, ContextAndStringCallW.sz);
|
|
TRC_ASSERT(SUCCEEDED(hr),(TB,_T("Pre checked copy failed: 0x%x"), hr));
|
|
|
|
Return:
|
|
|
|
if (fFreeDecode)
|
|
{
|
|
_TRY_2(ContextAndStringW_Call_Free(hDec, &ContextAndStringCallW))
|
|
}
|
|
SafeMesHandleFree(&hDec);
|
|
|
|
DC_END_FN();
|
|
|
|
return (lReturn);
|
|
|
|
ErrorReturn:
|
|
|
|
goto Return;
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------------------
|
|
//
|
|
// W32SCard::EncodeAndChannelWriteLongReturn
|
|
//
|
|
//---------------------------------------------------------------------------------------
|
|
void
|
|
W32SCard::EncodeAndChannelWriteLongReturn(
|
|
IN PRDPDR_IOREQUEST_PACKET pIoRequestPacket,
|
|
IN LONG lReturn)
|
|
{
|
|
DC_BEGIN_FN("W32SCard::EncodeAndChannelWriteLongReturn");
|
|
|
|
RPC_STATUS rpcStatus = RPC_S_OK;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
char *pbEncodedBuffer = NULL;
|
|
unsigned long cbEncodedBuffer = 0;
|
|
handle_t hEnc = 0;
|
|
Long_Return LongReturn;
|
|
|
|
//
|
|
// Initialiaze struct to be encoded
|
|
//
|
|
LongReturn.ReturnCode = lReturn;
|
|
|
|
//
|
|
// Encode the return
|
|
//
|
|
rpcStatus = MesEncodeDynBufferHandleCreate(
|
|
&pbEncodedBuffer,
|
|
&cbEncodedBuffer,
|
|
&hEnc);
|
|
if (rpcStatus != RPC_S_OK)
|
|
{
|
|
TRC_ERR((TB, _T("MesEncodeDynBufferHandleCreate failed with %lx."), rpcStatus));
|
|
status = STATUS_NO_MEMORY;
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
_TRY_status(Long_Return_Encode(hEnc, &LongReturn))
|
|
|
|
//
|
|
// Send the return
|
|
//
|
|
AllocateAndChannelWriteReplyPacket(
|
|
pIoRequestPacket,
|
|
pbEncodedBuffer,
|
|
cbEncodedBuffer);
|
|
|
|
Return:
|
|
|
|
SafeMesHandleFree(&hEnc);
|
|
|
|
MIDL_user_free(pbEncodedBuffer);
|
|
|
|
DC_END_FN();
|
|
|
|
return;
|
|
|
|
ErrorReturn:
|
|
|
|
DefaultIORequestMsgHandleWrapper(pIoRequestPacket, status);
|
|
|
|
goto Return;
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------------------
|
|
//
|
|
// W32SCard::EstablishContext
|
|
//
|
|
//---------------------------------------------------------------------------------------
|
|
void
|
|
W32SCard::EstablishContext(
|
|
IN PRDPDR_IOREQUEST_PACKET pIoRequestPacket)
|
|
{
|
|
DC_BEGIN_FN("W32SCard::EstablishContext");
|
|
|
|
RPC_STATUS rpcStatus = RPC_S_OK;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
char *pbEncodedBuffer = NULL;
|
|
unsigned long cbEncodedBuffer = 0;
|
|
PRDPDR_IOCOMPLETION_PACKET pReplyPacket = NULL;
|
|
ULONG replyPacketSize = 0;
|
|
handle_t hDec = 0;
|
|
handle_t hEnc = 0;
|
|
BOOL fFreeDecode = FALSE;
|
|
BOOL fFreeContext = FALSE;
|
|
EstablishContext_Call EstablishContextCall;
|
|
EstablishContext_Return EstablishContextReturn;
|
|
#ifndef OS_WINCE
|
|
DWORD dwScope;
|
|
#endif
|
|
SCARDCONTEXT SCardContext;
|
|
PRDPDR_DEVICE_IOREQUEST pIoRequest = &(pIoRequestPacket->IoRequest);
|
|
|
|
//
|
|
// Decode parameters
|
|
//
|
|
rpcStatus = MesDecodeBufferHandleCreate(
|
|
(char *) (pIoRequest + 1), // bytes are at end of struct
|
|
pIoRequest->Parameters.DeviceIoControl.InputBufferLength,
|
|
&hDec);
|
|
if (rpcStatus != RPC_S_OK)
|
|
{
|
|
TRC_ERR((TB, _T("MesDecodeBufferHandleCreate failed with %lx."), rpcStatus));
|
|
status = STATUS_NO_MEMORY;
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
memset(&EstablishContextCall, 0, sizeof(EstablishContextCall));
|
|
_TRY_status(EstablishContext_Call_Decode(hDec, &EstablishContextCall))
|
|
fFreeDecode = TRUE;
|
|
|
|
//
|
|
// Make the call to the SCard subsystem
|
|
//
|
|
memset(&EstablishContextReturn, 0, sizeof(EstablishContextReturn));
|
|
EstablishContextReturn.ReturnCode =
|
|
pfnSCardEstablishContext(
|
|
EstablishContextCall.dwScope,
|
|
NULL,
|
|
NULL,
|
|
&SCardContext);
|
|
|
|
if (EstablishContextReturn.ReturnCode == SCARD_S_SUCCESS)
|
|
{
|
|
EstablishContextReturn.Context.pbContext = (BYTE *) &SCardContext;
|
|
EstablishContextReturn.Context.cbContext = sizeof(SCARDCONTEXT);
|
|
fFreeContext = TRUE;
|
|
}
|
|
|
|
//
|
|
// Encode the return
|
|
//
|
|
rpcStatus = MesEncodeDynBufferHandleCreate(
|
|
&pbEncodedBuffer,
|
|
&cbEncodedBuffer,
|
|
&hEnc);
|
|
if (rpcStatus != RPC_S_OK)
|
|
{
|
|
TRC_ERR((TB, _T("MesEncodeDynBufferHandleCreate failed with %lx."), rpcStatus));
|
|
status = STATUS_NO_MEMORY;
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
_TRY_status(EstablishContext_Return_Encode(hEnc, &EstablishContextReturn))
|
|
|
|
//
|
|
// Add the new context to the list before returing to caller
|
|
//
|
|
if (!AddSCardContextToList(SCardContext))
|
|
{
|
|
status = STATUS_NO_MEMORY;
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
AllocateAndChannelWriteReplyPacket(
|
|
pIoRequestPacket,
|
|
pbEncodedBuffer,
|
|
cbEncodedBuffer);
|
|
|
|
Return:
|
|
|
|
if (fFreeDecode)
|
|
{
|
|
_TRY_2(EstablishContext_Call_Free(hDec, &EstablishContextCall))
|
|
}
|
|
SafeMesHandleFree(&hDec);
|
|
|
|
SafeMesHandleFree(&hEnc);
|
|
|
|
MIDL_user_free(pbEncodedBuffer);
|
|
|
|
DC_END_FN();
|
|
|
|
return;
|
|
|
|
ErrorReturn:
|
|
|
|
if (fFreeContext)
|
|
{
|
|
pfnSCardReleaseContext(SCardContext);
|
|
}
|
|
|
|
DefaultIORequestMsgHandleWrapper(pIoRequestPacket, status);
|
|
|
|
goto Return;
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------------------
|
|
//
|
|
// W32SCard::HandleContextCallWithLongReturn
|
|
//
|
|
//---------------------------------------------------------------------------------------
|
|
void
|
|
W32SCard::HandleContextCallWithLongReturn(
|
|
IN PRDPDR_IOREQUEST_PACKET pIoRequestPacket,
|
|
IN DWORD dwCallType)
|
|
{
|
|
DC_BEGIN_FN("W32SCard::HandleContextCallWithLongReturn");
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
LONG lReturn = SCARD_S_SUCCESS;
|
|
SCARDCONTEXT SCardContext;
|
|
|
|
//
|
|
// Decode the context being released
|
|
//
|
|
lReturn = DecodeContextCall(pIoRequestPacket, &SCardContext);
|
|
if (lReturn == SCARD_S_SUCCESS)
|
|
{
|
|
//
|
|
// Make SCard subsystem call
|
|
//
|
|
switch(dwCallType)
|
|
{
|
|
case SCARD_IOCTL_RELEASECONTEXT:
|
|
#ifndef OS_WINCE
|
|
lReturn = pfnSCardReleaseContext(SCardContext);
|
|
#endif
|
|
RemoveSCardContextFromList(SCardContext);
|
|
#ifdef OS_WINCE
|
|
lReturn = pfnSCardReleaseContext(SCardContext); //the context must be released after you cancel any operations on the card
|
|
#endif
|
|
break;
|
|
case SCARD_IOCTL_ISVALIDCONTEXT:
|
|
lReturn = pfnSCardIsValidContext(SCardContext);
|
|
break;
|
|
|
|
case SCARD_IOCTL_CANCEL:
|
|
lReturn = pfnSCardCancel(SCardContext);
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// encode and write the return
|
|
//
|
|
EncodeAndChannelWriteLongReturn(pIoRequestPacket, lReturn);
|
|
|
|
Return:
|
|
|
|
DC_END_FN();
|
|
|
|
return;
|
|
|
|
ErrorReturn:
|
|
|
|
DefaultIORequestMsgHandleWrapper(pIoRequestPacket, status);
|
|
|
|
goto Return;
|
|
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------------------
|
|
//
|
|
// W32SCard::EncodeAndChannelWriteLongAndMultiStringReturn
|
|
//
|
|
//---------------------------------------------------------------------------------------
|
|
void
|
|
W32SCard::EncodeAndChannelWriteLongAndMultiStringReturn(
|
|
IN PRDPDR_IOREQUEST_PACKET pIoRequestPacket,
|
|
IN LONG lReturn,
|
|
IN BYTE *pb,
|
|
IN DWORD cch,
|
|
IN BOOL fUnicode)
|
|
{
|
|
DC_BEGIN_FN("W32SCard::EncodeAndChannelWriteLongAndMultiStringReturn");
|
|
|
|
RPC_STATUS rpcStatus = RPC_S_OK;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
char *pbEncodedBuffer = NULL;
|
|
unsigned long cbEncodedBuffer = 0;
|
|
handle_t h = 0;
|
|
BOOL fFree = FALSE;
|
|
struct _LongAndMultiString_Return LongAndMultiSzReturn;
|
|
|
|
//
|
|
// Initialiaze struct to be encoded
|
|
//
|
|
LongAndMultiSzReturn.ReturnCode = lReturn;
|
|
LongAndMultiSzReturn.cBytes = fUnicode ? (cch * sizeof(WCHAR)) : cch;
|
|
|
|
//
|
|
// If we are just returning the byte count then send back a junk buffer
|
|
//
|
|
if (pb == NULL)
|
|
{
|
|
LongAndMultiSzReturn.msz = (BYTE *) MIDL_user_allocate(LongAndMultiSzReturn.cBytes);
|
|
if (LongAndMultiSzReturn.msz == NULL)
|
|
{
|
|
status = STATUS_NO_MEMORY;
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
fFree = TRUE;
|
|
memset(LongAndMultiSzReturn.msz, 0, LongAndMultiSzReturn.cBytes);
|
|
}
|
|
else
|
|
{
|
|
LongAndMultiSzReturn.msz = pb;
|
|
}
|
|
|
|
|
|
//
|
|
// Encode the return
|
|
//
|
|
rpcStatus = MesEncodeDynBufferHandleCreate(
|
|
&pbEncodedBuffer,
|
|
&cbEncodedBuffer,
|
|
&h);
|
|
if (rpcStatus != RPC_S_OK)
|
|
{
|
|
TRC_ERR((TB, _T("MesEncodeDynBufferHandleCreate failed with %lx."), rpcStatus));
|
|
status = STATUS_NO_MEMORY;
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
_TRY_status(ListReaderGroups_Return_Encode(h, &LongAndMultiSzReturn))
|
|
|
|
//
|
|
// Send the return
|
|
//
|
|
AllocateAndChannelWriteReplyPacket(
|
|
pIoRequestPacket,
|
|
pbEncodedBuffer,
|
|
cbEncodedBuffer);
|
|
|
|
Return:
|
|
|
|
if (fFree)
|
|
{
|
|
MIDL_user_free(LongAndMultiSzReturn.msz);
|
|
}
|
|
|
|
SafeMesHandleFree(&h);
|
|
|
|
MIDL_user_free(pbEncodedBuffer);
|
|
|
|
DC_END_FN();
|
|
|
|
return;
|
|
|
|
ErrorReturn:
|
|
|
|
DefaultIORequestMsgHandleWrapper(pIoRequestPacket, status);
|
|
|
|
goto Return;
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------------------
|
|
//
|
|
// W32SCard::ListReaderGroups
|
|
//
|
|
//---------------------------------------------------------------------------------------
|
|
void
|
|
W32SCard::ListReaderGroups(
|
|
IN PRDPDR_IOREQUEST_PACKET pIoRequestPacket,
|
|
IN DWORD dwCallType)
|
|
{
|
|
DC_BEGIN_FN("W32SCard::ListReaderGroups");
|
|
|
|
LONG lReturn = SCARD_S_SUCCESS;
|
|
RPC_STATUS rpcStatus = RPC_S_OK;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
handle_t hDec = 0;
|
|
SCARDCONTEXT SCardContext;
|
|
ListReaderGroups_Call ListReaderGroupsCall;
|
|
DWORD cch = 0;
|
|
BYTE *pb = NULL;
|
|
BOOL fFreeDecode = FALSE;
|
|
BOOL fDoAllocationLocally = FALSE;
|
|
PRDPDR_DEVICE_IOREQUEST pIoRequest = &(pIoRequestPacket->IoRequest);
|
|
|
|
//
|
|
// Decode parameters
|
|
//
|
|
rpcStatus = MesDecodeBufferHandleCreate(
|
|
(char *) (pIoRequest + 1), // bytes are at end of struct
|
|
pIoRequest->Parameters.DeviceIoControl.InputBufferLength,
|
|
&hDec);
|
|
if (rpcStatus != RPC_S_OK)
|
|
{
|
|
TRC_ERR((TB, _T("MesDecodeBufferHandleCreate failed with %lx."), rpcStatus));
|
|
status = STATUS_NO_MEMORY;
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
memset(&ListReaderGroupsCall, 0, sizeof(ListReaderGroupsCall));
|
|
_TRY_status(ListReaderGroups_Call_Decode(hDec, &ListReaderGroupsCall))
|
|
fFreeDecode = TRUE;
|
|
|
|
if (ListReaderGroupsCall.Context.pbContext != NULL)
|
|
{
|
|
if (sizeof(SCARDCONTEXT) == ListReaderGroupsCall.Context.cbContext)
|
|
{
|
|
SCardContext = *((SCARDCONTEXT *) ListReaderGroupsCall.Context.pbContext);
|
|
}
|
|
else
|
|
{
|
|
TRC_ERR((TB, _T("Invalid context sent from server.")));
|
|
lReturn = SCARD_E_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SCardContext = NULL;
|
|
}
|
|
|
|
cch = ListReaderGroupsCall.cchGroups;
|
|
|
|
if (lReturn == SCARD_S_SUCCESS)
|
|
{
|
|
|
|
//
|
|
// Allocate if not in SCARD_AUTOALLOCATE mode and not a size only call
|
|
//
|
|
fDoAllocationLocally =
|
|
(!ListReaderGroupsCall.fmszGroupsIsNULL &&
|
|
(cch != SCARD_AUTOALLOCATE));
|
|
|
|
#ifdef OS_WINCE
|
|
if (!fDoAllocationLocally)
|
|
{
|
|
lReturn = pfnSCardListReaderGroupsW(
|
|
SCardContext,
|
|
NULL,
|
|
&cch);
|
|
if ((lReturn == SCARD_S_SUCCESS) && (cch > 0))
|
|
fDoAllocationLocally = TRUE;
|
|
else
|
|
{
|
|
TRC_ERR((TB, _T("SCardListReaderGroupsW failed")));
|
|
status = STATUS_UNSUCCESSFUL;
|
|
goto ErrorReturn;
|
|
}
|
|
}
|
|
#endif
|
|
//
|
|
// Make the ListReaderGroups call
|
|
//
|
|
if (dwCallType == SCARD_IOCTL_LISTREADERGROUPSA)
|
|
{
|
|
LPSTR psz = NULL;
|
|
|
|
if (fDoAllocationLocally)
|
|
{
|
|
psz = (LPSTR) MIDL_user_allocate(cch * sizeof(CHAR));
|
|
if (psz == NULL)
|
|
{
|
|
TRC_ERR((TB, _T("MIDL_user_allocate failed")));
|
|
status = STATUS_NO_MEMORY;
|
|
goto ErrorReturn;
|
|
}
|
|
}
|
|
|
|
lReturn = pfnSCardListReaderGroupsA(
|
|
SCardContext,
|
|
(cch == SCARD_AUTOALLOCATE) ? (LPSTR) &psz : psz,
|
|
&cch);
|
|
|
|
pb = (LPBYTE) psz;
|
|
}
|
|
else
|
|
{
|
|
LPWSTR pwsz = NULL;
|
|
|
|
if (fDoAllocationLocally)
|
|
{
|
|
pwsz = (LPWSTR) MIDL_user_allocate(cch * sizeof(WCHAR));
|
|
if (pwsz == NULL)
|
|
{
|
|
TRC_ERR((TB, _T("MIDL_user_allocate failed")));
|
|
status = STATUS_NO_MEMORY;
|
|
goto ErrorReturn;
|
|
}
|
|
}
|
|
|
|
lReturn = pfnSCardListReaderGroupsW(
|
|
SCardContext,
|
|
(cch == SCARD_AUTOALLOCATE) ? (LPWSTR) &pwsz : pwsz,
|
|
&cch);
|
|
|
|
pb = (LPBYTE) pwsz;
|
|
}
|
|
}
|
|
|
|
//
|
|
// If anything failed, make sure we don't return a string
|
|
//
|
|
if (lReturn != SCARD_S_SUCCESS)
|
|
{
|
|
if (fDoAllocationLocally)
|
|
{
|
|
MIDL_user_free(pb);
|
|
}
|
|
pb = NULL;
|
|
cch = 0;
|
|
}
|
|
|
|
//
|
|
// write the return to the channel
|
|
//
|
|
EncodeAndChannelWriteLongAndMultiStringReturn(
|
|
pIoRequestPacket,
|
|
lReturn,
|
|
pb,
|
|
cch,
|
|
(dwCallType == SCARD_IOCTL_LISTREADERGROUPSA) ? FALSE : TRUE);
|
|
|
|
Return:
|
|
|
|
if (pb != NULL)
|
|
{
|
|
//
|
|
// Check to see whether we allocated or SCard allcated for us
|
|
//
|
|
if (fDoAllocationLocally)
|
|
{
|
|
MIDL_user_free(pb);
|
|
}
|
|
else
|
|
{
|
|
pfnSCardFreeMemory(SCardContext, pb);
|
|
}
|
|
}
|
|
|
|
if (fFreeDecode)
|
|
{
|
|
_TRY_2(ListReaderGroups_Call_Free(hDec, &ListReaderGroupsCall))
|
|
}
|
|
SafeMesHandleFree(&hDec);
|
|
|
|
DC_END_FN();
|
|
|
|
return;
|
|
|
|
ErrorReturn:
|
|
|
|
DefaultIORequestMsgHandleWrapper(pIoRequestPacket, status);
|
|
|
|
goto Return;
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------------------
|
|
//
|
|
// W32SCard::ListReaderGroups
|
|
//
|
|
//---------------------------------------------------------------------------------------
|
|
void
|
|
W32SCard::ListReaders(
|
|
IN PRDPDR_IOREQUEST_PACKET pIoRequestPacket,
|
|
IN DWORD dwCallType)
|
|
{
|
|
DC_BEGIN_FN("W32SCard::ListReaders");
|
|
|
|
LONG lReturn = SCARD_S_SUCCESS;
|
|
RPC_STATUS rpcStatus = RPC_S_OK;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
handle_t hDec = 0;
|
|
SCARDCONTEXT SCardContext;
|
|
ListReaders_Call ListReadersCall;
|
|
DWORD cch = 0;
|
|
BYTE *pb = NULL;
|
|
BOOL fFreeDecode = FALSE;
|
|
BOOL fDoAllocationLocally = FALSE;
|
|
PRDPDR_DEVICE_IOREQUEST pIoRequest = &(pIoRequestPacket->IoRequest);
|
|
|
|
//
|
|
// Decode parameters
|
|
//
|
|
rpcStatus = MesDecodeBufferHandleCreate(
|
|
(char *) (pIoRequest + 1), // bytes are at end of struct
|
|
pIoRequest->Parameters.DeviceIoControl.InputBufferLength,
|
|
&hDec);
|
|
if (rpcStatus != RPC_S_OK)
|
|
{
|
|
TRC_ERR((TB, _T("MesDecodeBufferHandleCreate failed with %lx."), rpcStatus));
|
|
status = STATUS_NO_MEMORY;
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
memset(&ListReadersCall, 0, sizeof(ListReadersCall));
|
|
_TRY_status(ListReaders_Call_Decode(hDec, &ListReadersCall))
|
|
fFreeDecode = TRUE;
|
|
|
|
if (ListReadersCall.Context.pbContext != NULL)
|
|
{
|
|
if (sizeof(SCARDCONTEXT) == ListReadersCall.Context.cbContext)
|
|
{
|
|
SCardContext = *((SCARDCONTEXT *) ListReadersCall.Context.pbContext);
|
|
}
|
|
else
|
|
{
|
|
TRC_ERR((TB, _T("Invalid context sent from server.")));
|
|
lReturn = SCARD_E_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SCardContext = NULL;
|
|
}
|
|
|
|
cch = ListReadersCall.cchReaders;
|
|
|
|
if (lReturn == SCARD_S_SUCCESS)
|
|
{
|
|
//
|
|
// Allocate if not in SCARD_AUTOALLOCATE mode and not a size only call
|
|
//
|
|
fDoAllocationLocally =
|
|
(!ListReadersCall.fmszReadersIsNULL &&
|
|
(cch != SCARD_AUTOALLOCATE));
|
|
|
|
//
|
|
// Make the ListReaders call
|
|
//
|
|
if (dwCallType == SCARD_IOCTL_LISTREADERSA)
|
|
{
|
|
LPSTR psz = NULL;
|
|
|
|
#ifdef OS_WINCE
|
|
if (!fDoAllocationLocally)
|
|
{
|
|
lReturn = pfnSCardListReadersA(
|
|
SCardContext,
|
|
(LPSTR) ListReadersCall.mszGroups,
|
|
NULL,
|
|
&cch);
|
|
if ((lReturn == SCARD_S_SUCCESS) && (cch > 0))
|
|
fDoAllocationLocally = TRUE;
|
|
else
|
|
{
|
|
TRC_DBG((TB, _T("SCardListReadersA failed")));
|
|
status = STATUS_UNSUCCESSFUL;
|
|
goto ErrorReturn;
|
|
}
|
|
}
|
|
#endif
|
|
if (fDoAllocationLocally)
|
|
{
|
|
psz = (LPSTR) MIDL_user_allocate(cch * sizeof(CHAR));
|
|
if (psz == NULL)
|
|
{
|
|
TRC_ERR((TB, _T("MIDL_user_allocate failed")));
|
|
status = STATUS_NO_MEMORY;
|
|
goto ErrorReturn;
|
|
}
|
|
}
|
|
|
|
lReturn = pfnSCardListReadersA(
|
|
SCardContext,
|
|
(LPSTR) ListReadersCall.mszGroups,
|
|
(cch == SCARD_AUTOALLOCATE) ? (LPSTR) &psz : psz,
|
|
&cch);
|
|
|
|
pb = (LPBYTE) psz;
|
|
}
|
|
else
|
|
{
|
|
LPWSTR pwsz = NULL;
|
|
|
|
#ifdef OS_WINCE
|
|
if (!fDoAllocationLocally)
|
|
{
|
|
lReturn = pfnSCardListReadersW(
|
|
SCardContext,
|
|
SCARD_ALL_READERS,
|
|
NULL,
|
|
&cch);
|
|
if ((lReturn == SCARD_S_SUCCESS) && (cch > 0))
|
|
fDoAllocationLocally = TRUE;
|
|
else
|
|
{
|
|
TRC_NRM((TB, _T("SCardListReadersW failed")));
|
|
status = STATUS_UNSUCCESSFUL;
|
|
goto ErrorReturn;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (fDoAllocationLocally)
|
|
{
|
|
pwsz = (LPWSTR) MIDL_user_allocate(cch * sizeof(WCHAR));
|
|
if (pwsz == NULL)
|
|
{
|
|
TRC_ERR((TB, _T("MIDL_user_allocate failed")));
|
|
status = STATUS_NO_MEMORY;
|
|
goto ErrorReturn;
|
|
}
|
|
}
|
|
|
|
lReturn = pfnSCardListReadersW(
|
|
SCardContext,
|
|
#ifndef OS_WINCE
|
|
(LPWSTR) ListReadersCall.mszGroups,
|
|
#else
|
|
SCARD_ALL_READERS,
|
|
#endif
|
|
(cch == SCARD_AUTOALLOCATE) ? (LPWSTR) &pwsz : pwsz,
|
|
&cch);
|
|
|
|
pb = (LPBYTE) pwsz;
|
|
}
|
|
}
|
|
|
|
//
|
|
// If anything failed, make sure we don't return a string
|
|
//
|
|
if (lReturn != SCARD_S_SUCCESS)
|
|
{
|
|
if (fDoAllocationLocally)
|
|
{
|
|
MIDL_user_free(pb);
|
|
}
|
|
pb = NULL;
|
|
cch = 0;
|
|
}
|
|
|
|
//
|
|
// write the return to the channel
|
|
//
|
|
EncodeAndChannelWriteLongAndMultiStringReturn(
|
|
pIoRequestPacket,
|
|
lReturn,
|
|
pb,
|
|
cch,
|
|
(dwCallType == SCARD_IOCTL_LISTREADERSA) ? FALSE : TRUE);
|
|
|
|
Return:
|
|
|
|
if (pb != NULL)
|
|
{
|
|
//
|
|
// Check to see whether we allocated or SCard allcated for us
|
|
//
|
|
if (fDoAllocationLocally)
|
|
{
|
|
MIDL_user_free(pb);
|
|
}
|
|
else
|
|
{
|
|
#ifndef OS_WINCE
|
|
pfnSCardFreeMemory(SCardContext, pb);
|
|
#else
|
|
TRC_ASSERT(FALSE, (TB, _T("Shouldnt get here")));
|
|
#endif
|
|
}
|
|
}
|
|
|
|
if (fFreeDecode)
|
|
{
|
|
_TRY_2(ListReaders_Call_Free(hDec, &ListReadersCall))
|
|
}
|
|
SafeMesHandleFree(&hDec);
|
|
|
|
DC_END_FN();
|
|
|
|
return;
|
|
|
|
ErrorReturn:
|
|
|
|
DefaultIORequestMsgHandleWrapper(pIoRequestPacket, status);
|
|
|
|
goto Return;
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------------------
|
|
//
|
|
// W32SCard::HandleContextAndStringCallWithLongReturn
|
|
//
|
|
//---------------------------------------------------------------------------------------
|
|
void
|
|
W32SCard::HandleContextAndStringCallWithLongReturn(
|
|
IN PRDPDR_IOREQUEST_PACKET pIoRequestPacket,
|
|
IN DWORD dwCallType)
|
|
{
|
|
DC_BEGIN_FN("W32SCard::HandleContextAndStringCallWithLongReturn");
|
|
|
|
LONG lReturn = SCARD_S_SUCCESS;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
SCARDCONTEXT SCardContext;
|
|
LPSTR sz = NULL;
|
|
LPWSTR wsz = NULL;
|
|
BOOL fASCIICall;
|
|
PRDPDR_DEVICE_IOREQUEST pIoRequest = &(pIoRequestPacket->IoRequest);
|
|
|
|
fASCIICall = ( (dwCallType == SCARD_IOCTL_INTRODUCEREADERGROUPA) ||
|
|
(dwCallType == SCARD_IOCTL_FORGETREADERGROUPA) ||
|
|
(dwCallType == SCARD_IOCTL_FORGETREADERA));
|
|
|
|
//
|
|
// Decode input params
|
|
//
|
|
if (fASCIICall)
|
|
{
|
|
lReturn = DecodeContextAndStringCallA(
|
|
pIoRequestPacket,
|
|
&SCardContext,
|
|
&sz);
|
|
}
|
|
else
|
|
{
|
|
lReturn = DecodeContextAndStringCallW(
|
|
pIoRequestPacket,
|
|
&SCardContext,
|
|
&wsz);
|
|
}
|
|
|
|
if (lReturn == SCARD_S_SUCCESS)
|
|
{
|
|
//
|
|
// Make the SCard* call
|
|
//
|
|
switch (dwCallType)
|
|
{
|
|
case SCARD_IOCTL_INTRODUCEREADERGROUPA:
|
|
|
|
lReturn = pfnSCardIntroduceReaderGroupA(
|
|
SCardContext,
|
|
sz);
|
|
break;
|
|
|
|
case SCARD_IOCTL_INTRODUCEREADERGROUPW:
|
|
|
|
lReturn = pfnSCardIntroduceReaderGroupW(
|
|
SCardContext,
|
|
wsz);
|
|
|
|
break;
|
|
|
|
case SCARD_IOCTL_FORGETREADERGROUPA:
|
|
|
|
lReturn = pfnSCardForgetReaderGroupA(
|
|
SCardContext,
|
|
sz);
|
|
break;
|
|
|
|
case SCARD_IOCTL_FORGETREADERGROUPW:
|
|
|
|
lReturn = pfnSCardForgetReaderGroupW(
|
|
SCardContext,
|
|
wsz);
|
|
|
|
break;
|
|
|
|
case SCARD_IOCTL_FORGETREADERA:
|
|
|
|
lReturn = pfnSCardForgetReaderA(
|
|
SCardContext,
|
|
sz);
|
|
break;
|
|
|
|
case SCARD_IOCTL_FORGETREADERW:
|
|
|
|
lReturn = pfnSCardForgetReaderW(
|
|
SCardContext,
|
|
wsz);
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// send the return
|
|
//
|
|
EncodeAndChannelWriteLongReturn(pIoRequestPacket, lReturn);
|
|
|
|
Return:
|
|
|
|
MIDL_user_free(sz);
|
|
MIDL_user_free(wsz);
|
|
|
|
DC_END_FN();
|
|
|
|
return;
|
|
|
|
ErrorReturn:
|
|
|
|
DefaultIORequestMsgHandleWrapper(pIoRequestPacket, status);
|
|
|
|
goto Return;
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------------------
|
|
//
|
|
// W32SCard::HandleContextAndTwoStringCallWithLongReturn
|
|
//
|
|
//---------------------------------------------------------------------------------------
|
|
void
|
|
W32SCard::HandleContextAndTwoStringCallWithLongReturn(
|
|
IN PRDPDR_IOREQUEST_PACKET pIoRequestPacket,
|
|
IN DWORD dwCallType)
|
|
{
|
|
DC_BEGIN_FN("W32SCard::HandleContextAndTwoStringCallWithLongReturn");
|
|
|
|
RPC_STATUS rpcStatus = RPC_S_OK;
|
|
LONG lReturn = SCARD_S_SUCCESS;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
SCARDCONTEXT SCardContext;
|
|
handle_t hDec = 0;
|
|
ContextAndTwoStringA_Call ContextAndTwoStringCallA;
|
|
ContextAndTwoStringW_Call ContextAndTwoStringCallW;
|
|
BOOL fASCIICall;
|
|
PRDPDR_DEVICE_IOREQUEST pIoRequest = &(pIoRequestPacket->IoRequest);
|
|
|
|
//
|
|
// Decode input parameters
|
|
//
|
|
rpcStatus = MesDecodeBufferHandleCreate(
|
|
(char *) (pIoRequest + 1), // bytes are at end of struct
|
|
pIoRequest->Parameters.DeviceIoControl.InputBufferLength,
|
|
&hDec);
|
|
if (rpcStatus != RPC_S_OK)
|
|
{
|
|
TRC_ERR((TB, _T("MesDecodeBufferHandleCreate failed with %lx."), rpcStatus));
|
|
status = STATUS_NO_MEMORY;
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
fASCIICall = ( (dwCallType == SCARD_IOCTL_INTRODUCEREADERA) ||
|
|
(dwCallType == SCARD_IOCTL_ADDREADERTOGROUPA) ||
|
|
(dwCallType == SCARD_IOCTL_REMOVEREADERFROMGROUPA));
|
|
|
|
if (fASCIICall)
|
|
{
|
|
memset(&ContextAndTwoStringCallA, 0, sizeof(ContextAndTwoStringCallA));
|
|
_TRY_status(ContextAndTwoStringA_Call_Decode(hDec, &ContextAndTwoStringCallA))
|
|
|
|
if (sizeof(SCARDCONTEXT) == ContextAndTwoStringCallA.Context.cbContext)
|
|
{
|
|
SCardContext = *((SCARDCONTEXT *) ContextAndTwoStringCallA.Context.pbContext);
|
|
}
|
|
else
|
|
{
|
|
TRC_ERR((TB, _T("Invalid context sent from server.")));
|
|
lReturn = SCARD_E_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
memset(&ContextAndTwoStringCallW, 0, sizeof(ContextAndTwoStringCallW));
|
|
_TRY_status(ContextAndTwoStringW_Call_Decode(hDec, &ContextAndTwoStringCallW))
|
|
|
|
if (sizeof(SCARDCONTEXT) == ContextAndTwoStringCallW.Context.cbContext)
|
|
{
|
|
SCardContext = *((SCARDCONTEXT *) ContextAndTwoStringCallW.Context.pbContext);
|
|
}
|
|
else
|
|
{
|
|
TRC_ERR((TB, _T("Invalid context sent from server.")));
|
|
lReturn = SCARD_E_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Check for NULL input strings
|
|
//
|
|
switch (dwCallType)
|
|
{
|
|
case SCARD_IOCTL_INTRODUCEREADERA:
|
|
case SCARD_IOCTL_ADDREADERTOGROUPA:
|
|
case SCARD_IOCTL_REMOVEREADERFROMGROUPA:
|
|
|
|
if ((ContextAndTwoStringCallA.sz1 == NULL) ||
|
|
(ContextAndTwoStringCallA.sz2 == NULL))
|
|
{
|
|
lReturn = SCARD_E_INVALID_VALUE;
|
|
}
|
|
break;
|
|
|
|
case SCARD_IOCTL_INTRODUCEREADERW:
|
|
case SCARD_IOCTL_ADDREADERTOGROUPW:
|
|
case SCARD_IOCTL_REMOVEREADERFROMGROUPW:
|
|
|
|
if ((ContextAndTwoStringCallW.sz1 == NULL) ||
|
|
(ContextAndTwoStringCallW.sz2 == NULL))
|
|
{
|
|
lReturn = SCARD_E_INVALID_VALUE;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
if (lReturn == SCARD_S_SUCCESS)
|
|
{
|
|
//
|
|
// Make the SCard* call
|
|
//
|
|
switch (dwCallType)
|
|
{
|
|
case SCARD_IOCTL_INTRODUCEREADERA:
|
|
|
|
lReturn = pfnSCardIntroduceReaderA(
|
|
SCardContext,
|
|
ContextAndTwoStringCallA.sz1,
|
|
ContextAndTwoStringCallA.sz2);
|
|
break;
|
|
|
|
case SCARD_IOCTL_INTRODUCEREADERW:
|
|
|
|
lReturn = pfnSCardIntroduceReaderW(
|
|
SCardContext,
|
|
ContextAndTwoStringCallW.sz1,
|
|
ContextAndTwoStringCallW.sz2);
|
|
|
|
break;
|
|
|
|
case SCARD_IOCTL_ADDREADERTOGROUPA:
|
|
|
|
lReturn = pfnSCardAddReaderToGroupA(
|
|
SCardContext,
|
|
ContextAndTwoStringCallA.sz1,
|
|
ContextAndTwoStringCallA.sz2);
|
|
|
|
break;
|
|
|
|
case SCARD_IOCTL_ADDREADERTOGROUPW:
|
|
|
|
lReturn = pfnSCardAddReaderToGroupW(
|
|
SCardContext,
|
|
ContextAndTwoStringCallW.sz1,
|
|
ContextAndTwoStringCallW.sz2);
|
|
|
|
break;
|
|
|
|
case SCARD_IOCTL_REMOVEREADERFROMGROUPA:
|
|
|
|
lReturn = pfnSCardRemoveReaderFromGroupA(
|
|
SCardContext,
|
|
ContextAndTwoStringCallA.sz1,
|
|
ContextAndTwoStringCallA.sz2);
|
|
|
|
break;
|
|
|
|
case SCARD_IOCTL_REMOVEREADERFROMGROUPW:
|
|
|
|
lReturn = pfnSCardRemoveReaderFromGroupW(
|
|
SCardContext,
|
|
ContextAndTwoStringCallW.sz1,
|
|
ContextAndTwoStringCallW.sz2);
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Free up resources used for decode
|
|
//
|
|
if (fASCIICall)
|
|
{
|
|
_TRY_2(ContextAndTwoStringA_Call_Free(hDec, &ContextAndTwoStringCallA))
|
|
}
|
|
else
|
|
{
|
|
_TRY_2(ContextAndTwoStringW_Call_Free(hDec, &ContextAndTwoStringCallW))
|
|
}
|
|
|
|
//
|
|
// send the return
|
|
//
|
|
EncodeAndChannelWriteLongReturn(pIoRequestPacket, lReturn);
|
|
|
|
Return:
|
|
|
|
SafeMesHandleFree(&hDec);
|
|
|
|
DC_END_FN();
|
|
|
|
return;
|
|
|
|
ErrorReturn:
|
|
|
|
DefaultIORequestMsgHandleWrapper(pIoRequestPacket, status);
|
|
|
|
goto Return;
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------------------
|
|
//
|
|
// W32SCard::AllocateAndCopyReaderStateStructsForCall*
|
|
//
|
|
//---------------------------------------------------------------------------------------
|
|
LONG
|
|
W32SCard::AllocateAndCopyReaderStateStructsForCallA(
|
|
IN DWORD cReaders,
|
|
IN ReaderStateA *rgReaderStatesFromDecode,
|
|
OUT LPSCARD_READERSTATE_A *prgReadersStatesForSCardCall)
|
|
{
|
|
DC_BEGIN_FN("W32SCard::AllocateAndCopyReaderStateStructsForCallA");
|
|
|
|
LPSCARD_READERSTATE_A rgReadersStatesForSCardCall = NULL;
|
|
DWORD i;
|
|
|
|
rgReadersStatesForSCardCall = (LPSCARD_READERSTATE_A)
|
|
MIDL_user_allocate(cReaders * sizeof(SCARD_READERSTATE_A));
|
|
if (rgReadersStatesForSCardCall == NULL)
|
|
{
|
|
TRC_ERR((TB, _T("MIDL_user_allocate failed")));
|
|
return (SCARD_E_NO_MEMORY);
|
|
}
|
|
|
|
memset(rgReadersStatesForSCardCall, 0, cReaders * sizeof(SCARD_READERSTATE_A));
|
|
|
|
for (i=0; i<cReaders; i++)
|
|
{
|
|
rgReadersStatesForSCardCall[i].dwCurrentState =
|
|
rgReaderStatesFromDecode[i].Common.dwCurrentState;
|
|
rgReadersStatesForSCardCall[i].dwEventState =
|
|
rgReaderStatesFromDecode[i].Common.dwEventState;
|
|
rgReadersStatesForSCardCall[i].cbAtr =
|
|
rgReaderStatesFromDecode[i].Common.cbAtr;
|
|
memcpy(
|
|
rgReadersStatesForSCardCall[i].rgbAtr,
|
|
rgReaderStatesFromDecode[i].Common.rgbAtr,
|
|
ATR_COPY_SIZE);
|
|
|
|
//
|
|
// just reference string in decoded struct instead of copying.
|
|
// this means the decode can't be free'd until the SCard* call is made
|
|
//
|
|
rgReadersStatesForSCardCall[i].szReader =
|
|
rgReaderStatesFromDecode[i].szReader;
|
|
}
|
|
|
|
*prgReadersStatesForSCardCall = rgReadersStatesForSCardCall;
|
|
|
|
DC_END_FN();
|
|
|
|
return (SCARD_S_SUCCESS);
|
|
}
|
|
|
|
LONG
|
|
W32SCard::AllocateAndCopyReaderStateStructsForCallW(
|
|
IN DWORD cReaders,
|
|
IN ReaderStateW *rgReaderStatesFromDecode,
|
|
OUT LPSCARD_READERSTATE_W *prgReadersStatesForSCardCall)
|
|
{
|
|
DC_BEGIN_FN("W32SCard::AllocateAndCopyReaderStateStructsForCallW");
|
|
|
|
LPSCARD_READERSTATE_W rgReadersStatesForSCardCall = NULL;
|
|
DWORD i;
|
|
|
|
rgReadersStatesForSCardCall = (LPSCARD_READERSTATE_W)
|
|
MIDL_user_allocate(cReaders * sizeof(SCARD_READERSTATE_W));
|
|
if (rgReadersStatesForSCardCall == NULL)
|
|
{
|
|
TRC_ERR((TB, _T("MIDL_user_allocate failed")));
|
|
return (SCARD_E_NO_MEMORY);
|
|
}
|
|
|
|
memset(rgReadersStatesForSCardCall, 0, cReaders * sizeof(SCARD_READERSTATE_W));
|
|
|
|
for (i=0; i<cReaders; i++)
|
|
{
|
|
rgReadersStatesForSCardCall[i].dwCurrentState =
|
|
rgReaderStatesFromDecode[i].Common.dwCurrentState;
|
|
rgReadersStatesForSCardCall[i].dwEventState =
|
|
rgReaderStatesFromDecode[i].Common.dwEventState;
|
|
rgReadersStatesForSCardCall[i].cbAtr =
|
|
rgReaderStatesFromDecode[i].Common.cbAtr;
|
|
memcpy(
|
|
rgReadersStatesForSCardCall[i].rgbAtr,
|
|
rgReaderStatesFromDecode[i].Common.rgbAtr,
|
|
ATR_COPY_SIZE);
|
|
|
|
//
|
|
// just reference string in decoded struct instead of copying.
|
|
// this means the decode can't be free'd until the SCard* call is made
|
|
//
|
|
rgReadersStatesForSCardCall[i].szReader =
|
|
rgReaderStatesFromDecode[i].szReader;
|
|
}
|
|
|
|
*prgReadersStatesForSCardCall = rgReadersStatesForSCardCall;
|
|
|
|
DC_END_FN();
|
|
|
|
return (SCARD_S_SUCCESS);
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------------------
|
|
//
|
|
// W32SCard::AllocateAndCopyATRMasksForCall
|
|
//
|
|
//---------------------------------------------------------------------------------------
|
|
LONG
|
|
W32SCard::AllocateAndCopyATRMasksForCall(
|
|
IN DWORD cAtrs,
|
|
IN LocateCards_ATRMask *rgATRMasksFromDecode,
|
|
OUT SCARD_ATRMASK **prgATRMasksForCall)
|
|
{
|
|
DC_BEGIN_FN("W32SCard::AllocateAndCopyATRMasksForCall");
|
|
|
|
SCARD_ATRMASK *rgATRMasksForCall = NULL;
|
|
DWORD i;
|
|
|
|
rgATRMasksForCall = (SCARD_ATRMASK *)
|
|
MIDL_user_allocate(cAtrs * sizeof(SCARD_ATRMASK));
|
|
if (rgATRMasksForCall == NULL)
|
|
{
|
|
TRC_ERR((TB, _T("MIDL_user_allocate failed")));
|
|
return (SCARD_E_NO_MEMORY);
|
|
}
|
|
|
|
memset(rgATRMasksForCall, 0, cAtrs * sizeof(SCARD_ATRMASK));
|
|
|
|
for (i=0; i<cAtrs; i++)
|
|
{
|
|
rgATRMasksForCall[i].cbAtr = rgATRMasksFromDecode[i].cbAtr;
|
|
|
|
memcpy(
|
|
rgATRMasksForCall[i].rgbAtr,
|
|
rgATRMasksFromDecode[i].rgbAtr,
|
|
ATR_COPY_SIZE);
|
|
|
|
memcpy(
|
|
rgATRMasksForCall[i].rgbMask,
|
|
rgATRMasksFromDecode[i].rgbMask,
|
|
ATR_COPY_SIZE);
|
|
}
|
|
|
|
*prgATRMasksForCall = rgATRMasksForCall;
|
|
|
|
DC_END_FN();
|
|
|
|
return (SCARD_S_SUCCESS);
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------------------
|
|
//
|
|
// W32SCard::AllocateAndCopyReaderStateStructsForReturn*
|
|
//
|
|
//---------------------------------------------------------------------------------------
|
|
LONG
|
|
W32SCard::AllocateAndCopyReaderStateStructsForReturnA(
|
|
IN DWORD cReaders,
|
|
IN LPSCARD_READERSTATE_A rgReaderStatesFromSCardCall,
|
|
OUT ReaderState_Return **prgReaderStatesForReturn)
|
|
{
|
|
DC_BEGIN_FN("W32SCard::AllocateAndCopyReaderStateStructsForReturnA");
|
|
|
|
ReaderState_Return *rgReaderStatesForReturn = NULL;
|
|
DWORD i;
|
|
|
|
rgReaderStatesForReturn = (ReaderState_Return *)
|
|
MIDL_user_allocate(cReaders * sizeof(ReaderState_Return));
|
|
if (rgReaderStatesForReturn == NULL)
|
|
{
|
|
TRC_ERR((TB, _T("MIDL_user_allocate failed")));
|
|
return (SCARD_E_NO_MEMORY);
|
|
}
|
|
|
|
for (i=0; i<cReaders; i++)
|
|
{
|
|
rgReaderStatesForReturn[i].dwCurrentState =
|
|
rgReaderStatesFromSCardCall[i].dwCurrentState;
|
|
rgReaderStatesForReturn[i].dwEventState =
|
|
rgReaderStatesFromSCardCall[i].dwEventState;
|
|
rgReaderStatesForReturn[i].cbAtr =
|
|
rgReaderStatesFromSCardCall[i].cbAtr;
|
|
memcpy(
|
|
rgReaderStatesForReturn[i].rgbAtr,
|
|
rgReaderStatesFromSCardCall[i].rgbAtr,
|
|
ATR_COPY_SIZE);
|
|
}
|
|
|
|
*prgReaderStatesForReturn = rgReaderStatesForReturn;
|
|
|
|
DC_END_FN();
|
|
|
|
return (SCARD_S_SUCCESS);
|
|
}
|
|
|
|
LONG
|
|
W32SCard::AllocateAndCopyReaderStateStructsForReturnW(
|
|
IN DWORD cReaders,
|
|
IN LPSCARD_READERSTATE_W rgReaderStatesFromSCardCall,
|
|
OUT ReaderState_Return **prgReaderStatesForReturn)
|
|
{
|
|
DC_BEGIN_FN("W32SCard::AllocateAndCopyReaderStateStructsForReturnW");
|
|
|
|
ReaderState_Return *rgReaderStatesForReturn = NULL;
|
|
DWORD i;
|
|
|
|
rgReaderStatesForReturn = (ReaderState_Return *)
|
|
MIDL_user_allocate(cReaders * sizeof(ReaderState_Return));
|
|
if (rgReaderStatesForReturn == NULL)
|
|
{
|
|
TRC_ERR((TB, _T("MIDL_user_allocate failed")));
|
|
return (SCARD_E_NO_MEMORY);
|
|
}
|
|
|
|
for (i=0; i<cReaders; i++)
|
|
{
|
|
rgReaderStatesForReturn[i].dwCurrentState =
|
|
rgReaderStatesFromSCardCall[i].dwCurrentState;
|
|
rgReaderStatesForReturn[i].dwEventState =
|
|
rgReaderStatesFromSCardCall[i].dwEventState;
|
|
rgReaderStatesForReturn[i].cbAtr =
|
|
rgReaderStatesFromSCardCall[i].cbAtr;
|
|
memcpy(
|
|
rgReaderStatesForReturn[i].rgbAtr,
|
|
rgReaderStatesFromSCardCall[i].rgbAtr,
|
|
ATR_COPY_SIZE);
|
|
}
|
|
|
|
*prgReaderStatesForReturn = rgReaderStatesForReturn;
|
|
|
|
DC_END_FN();
|
|
|
|
return (SCARD_S_SUCCESS);
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------------------
|
|
//
|
|
// W32SCard::LocateCardsA
|
|
//
|
|
//---------------------------------------------------------------------------------------
|
|
void
|
|
W32SCard::LocateCardsA(
|
|
IN PRDPDR_IOREQUEST_PACKET pIoRequestPacket)
|
|
{
|
|
DC_BEGIN_FN("W32SCard::LocateCardsA");
|
|
|
|
RPC_STATUS rpcStatus = RPC_S_OK;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
char *pbEncodedBuffer = NULL;
|
|
unsigned long cbEncodedBuffer = 0;
|
|
handle_t hDec = 0;
|
|
handle_t hEnc = 0;
|
|
SCARDCONTEXT SCardContext;
|
|
LocateCardsA_Call LocateCardsCallA;
|
|
LocateCards_Return LocateCardsReturn;
|
|
LPSCARD_READERSTATE_A rgReaderStatesA = NULL;
|
|
BOOL fFreeDecode = FALSE;
|
|
PRDPDR_DEVICE_IOREQUEST pIoRequest = &(pIoRequestPacket->IoRequest);
|
|
|
|
memset(&LocateCardsReturn, 0, sizeof(LocateCardsReturn));
|
|
LocateCardsReturn.ReturnCode = SCARD_S_SUCCESS;
|
|
|
|
//
|
|
// Decode input parameters
|
|
//
|
|
rpcStatus = MesDecodeBufferHandleCreate(
|
|
(char *) (pIoRequest + 1), // bytes are at end of struct
|
|
pIoRequest->Parameters.DeviceIoControl.InputBufferLength,
|
|
&hDec);
|
|
if (rpcStatus != RPC_S_OK)
|
|
{
|
|
TRC_ERR((TB, _T("MesDecodeBufferHandleCreate failed with %lx."), rpcStatus));
|
|
status = STATUS_NO_MEMORY;
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
//
|
|
// Decode and copy the input params
|
|
//
|
|
memset(&LocateCardsCallA, 0, sizeof(LocateCardsCallA));
|
|
_TRY_status(LocateCardsA_Call_Decode(hDec, &LocateCardsCallA))
|
|
fFreeDecode = TRUE;
|
|
|
|
if (sizeof(SCARDCONTEXT) == LocateCardsCallA.Context.cbContext)
|
|
{
|
|
SCardContext = *((SCARDCONTEXT *) LocateCardsCallA.Context.pbContext);
|
|
}
|
|
else
|
|
{
|
|
TRC_ERR((TB, _T("Invalid context sent from server.")));
|
|
LocateCardsReturn.ReturnCode = SCARD_E_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (LocateCardsReturn.ReturnCode == SCARD_S_SUCCESS)
|
|
{
|
|
LocateCardsReturn.ReturnCode =
|
|
AllocateAndCopyReaderStateStructsForCallA(
|
|
LocateCardsCallA.cReaders,
|
|
LocateCardsCallA.rgReaderStates,
|
|
&rgReaderStatesA);
|
|
}
|
|
|
|
if (LocateCardsReturn.ReturnCode == SCARD_S_SUCCESS)
|
|
{
|
|
//
|
|
// Make the call
|
|
//
|
|
LocateCardsReturn.ReturnCode =
|
|
pfnSCardLocateCardsA(
|
|
SCardContext,
|
|
(LPCSTR) LocateCardsCallA.mszCards,
|
|
rgReaderStatesA,
|
|
LocateCardsCallA.cReaders);
|
|
}
|
|
|
|
//
|
|
// encode the return
|
|
//
|
|
rpcStatus = MesEncodeDynBufferHandleCreate(
|
|
&pbEncodedBuffer,
|
|
&cbEncodedBuffer,
|
|
&hEnc);
|
|
if (rpcStatus != RPC_S_OK)
|
|
{
|
|
TRC_ERR((TB, _T("MesEncodeDynBufferHandleCreate failed with %lx."), rpcStatus));
|
|
status = STATUS_NO_MEMORY;
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
if (LocateCardsReturn.ReturnCode == SCARD_S_SUCCESS)
|
|
{
|
|
LocateCardsReturn.ReturnCode =
|
|
AllocateAndCopyReaderStateStructsForReturnA(
|
|
LocateCardsCallA.cReaders,
|
|
rgReaderStatesA,
|
|
&(LocateCardsReturn.rgReaderStates));
|
|
|
|
if (LocateCardsReturn.ReturnCode == SCARD_S_SUCCESS)
|
|
{
|
|
LocateCardsReturn.cReaders = LocateCardsCallA.cReaders;
|
|
}
|
|
}
|
|
_TRY_status(LocateCards_Return_Encode(hEnc, &LocateCardsReturn))
|
|
|
|
//
|
|
// Send return
|
|
//
|
|
AllocateAndChannelWriteReplyPacket(
|
|
pIoRequestPacket,
|
|
pbEncodedBuffer,
|
|
cbEncodedBuffer);
|
|
|
|
Return:
|
|
|
|
if (fFreeDecode)
|
|
{
|
|
_TRY_2(LocateCardsA_Call_Free(hDec, &LocateCardsCallA))
|
|
}
|
|
SafeMesHandleFree(&hDec);
|
|
|
|
SafeMesHandleFree(&hEnc);
|
|
|
|
MIDL_user_free(rgReaderStatesA);
|
|
MIDL_user_free(LocateCardsReturn.rgReaderStates);
|
|
MIDL_user_free(pbEncodedBuffer);
|
|
|
|
DC_END_FN();
|
|
|
|
return;
|
|
|
|
ErrorReturn:
|
|
|
|
DefaultIORequestMsgHandleWrapper(pIoRequestPacket, status);
|
|
|
|
goto Return;
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------------------
|
|
//
|
|
// W32SCard::LocateCardsW
|
|
//
|
|
//---------------------------------------------------------------------------------------
|
|
void
|
|
W32SCard::LocateCardsW(
|
|
IN PRDPDR_IOREQUEST_PACKET pIoRequestPacket)
|
|
{
|
|
DC_BEGIN_FN("W32SCard::LocateCardsW");
|
|
|
|
RPC_STATUS rpcStatus = RPC_S_OK;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
char *pbEncodedBuffer = NULL;
|
|
unsigned long cbEncodedBuffer = 0;
|
|
handle_t hDec = 0;
|
|
handle_t hEnc = 0;
|
|
SCARDCONTEXT SCardContext;
|
|
LocateCardsW_Call LocateCardsCallW;
|
|
LocateCards_Return LocateCardsReturn;
|
|
LPSCARD_READERSTATE_W rgReaderStatesW = NULL;
|
|
BOOL fFreeDecode = FALSE;
|
|
PRDPDR_DEVICE_IOREQUEST pIoRequest = &(pIoRequestPacket->IoRequest);
|
|
|
|
memset(&LocateCardsReturn, 0, sizeof(LocateCardsReturn));
|
|
LocateCardsReturn.ReturnCode = SCARD_S_SUCCESS;
|
|
|
|
//
|
|
// Decode input parameters
|
|
//
|
|
rpcStatus = MesDecodeBufferHandleCreate(
|
|
(char *) (pIoRequest + 1), // bytes are at end of struct
|
|
pIoRequest->Parameters.DeviceIoControl.InputBufferLength,
|
|
&hDec);
|
|
if (rpcStatus != RPC_S_OK)
|
|
{
|
|
TRC_ERR((TB, _T("MesDecodeBufferHandleCreate failed with %lx."), rpcStatus));
|
|
status = STATUS_NO_MEMORY;
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
//
|
|
// Decode and copy the input params
|
|
//
|
|
memset(&LocateCardsCallW, 0, sizeof(LocateCardsCallW));
|
|
_TRY_status(LocateCardsW_Call_Decode(hDec, &LocateCardsCallW))
|
|
fFreeDecode = TRUE;
|
|
|
|
if (sizeof(SCARDCONTEXT) == LocateCardsCallW.Context.cbContext)
|
|
{
|
|
SCardContext = *((SCARDCONTEXT *) LocateCardsCallW.Context.pbContext);
|
|
}
|
|
else
|
|
{
|
|
TRC_ERR((TB, _T("Invalid context sent from server.")));
|
|
LocateCardsReturn.ReturnCode = SCARD_E_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (LocateCardsReturn.ReturnCode == SCARD_S_SUCCESS)
|
|
{
|
|
LocateCardsReturn.ReturnCode =
|
|
AllocateAndCopyReaderStateStructsForCallW(
|
|
LocateCardsCallW.cReaders,
|
|
LocateCardsCallW.rgReaderStates,
|
|
&rgReaderStatesW);
|
|
}
|
|
|
|
if (LocateCardsReturn.ReturnCode == SCARD_S_SUCCESS)
|
|
{
|
|
//
|
|
// Make the call
|
|
//
|
|
LocateCardsReturn.ReturnCode =
|
|
pfnSCardLocateCardsW(
|
|
SCardContext,
|
|
(LPCWSTR) LocateCardsCallW.mszCards,
|
|
rgReaderStatesW,
|
|
LocateCardsCallW.cReaders);
|
|
}
|
|
|
|
//
|
|
// encode the return
|
|
//
|
|
rpcStatus = MesEncodeDynBufferHandleCreate(
|
|
&pbEncodedBuffer,
|
|
&cbEncodedBuffer,
|
|
&hEnc);
|
|
if (rpcStatus != RPC_S_OK)
|
|
{
|
|
TRC_ERR((TB, _T("MesEncodeDynBufferHandleCreate failed with %lx."), rpcStatus));
|
|
status = STATUS_NO_MEMORY;
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
if (LocateCardsReturn.ReturnCode == SCARD_S_SUCCESS)
|
|
{
|
|
LocateCardsReturn.ReturnCode =
|
|
AllocateAndCopyReaderStateStructsForReturnW(
|
|
LocateCardsCallW.cReaders,
|
|
rgReaderStatesW,
|
|
&(LocateCardsReturn.rgReaderStates));
|
|
|
|
if (LocateCardsReturn.ReturnCode == SCARD_S_SUCCESS)
|
|
{
|
|
LocateCardsReturn.cReaders = LocateCardsCallW.cReaders;
|
|
}
|
|
}
|
|
_TRY_status(LocateCards_Return_Encode(hEnc, &LocateCardsReturn))
|
|
|
|
//
|
|
// Send return
|
|
//
|
|
AllocateAndChannelWriteReplyPacket(
|
|
pIoRequestPacket,
|
|
pbEncodedBuffer,
|
|
cbEncodedBuffer);
|
|
|
|
Return:
|
|
|
|
if (fFreeDecode)
|
|
{
|
|
_TRY_2(LocateCardsW_Call_Free(hDec, &LocateCardsCallW))
|
|
}
|
|
SafeMesHandleFree(&hDec);
|
|
|
|
SafeMesHandleFree(&hEnc);
|
|
|
|
MIDL_user_free(rgReaderStatesW);
|
|
MIDL_user_free(LocateCardsReturn.rgReaderStates);
|
|
MIDL_user_free(pbEncodedBuffer);
|
|
|
|
DC_END_FN();
|
|
|
|
return;
|
|
|
|
ErrorReturn:
|
|
|
|
DefaultIORequestMsgHandleWrapper(pIoRequestPacket, status);
|
|
|
|
goto Return;
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------------------
|
|
//
|
|
// W32SCard::LocateCardsByATRA
|
|
//
|
|
//---------------------------------------------------------------------------------------
|
|
void
|
|
W32SCard::LocateCardsByATRA(
|
|
IN PRDPDR_IOREQUEST_PACKET pIoRequestPacket)
|
|
{
|
|
DC_BEGIN_FN("W32SCard::LocateCardsByATRA");
|
|
|
|
RPC_STATUS rpcStatus = RPC_S_OK;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
char *pbEncodedBuffer = NULL;
|
|
unsigned long cbEncodedBuffer = 0;
|
|
handle_t hDec = 0;
|
|
handle_t hEnc = 0;
|
|
SCARDCONTEXT SCardContext;
|
|
LocateCardsByATRA_Call LocateCardsByATRCallA;
|
|
LocateCards_Return LocateCardsReturn;
|
|
LPSCARD_READERSTATE_A rgReaderStatesA = NULL;
|
|
SCARD_ATRMASK *rgATRMasksForCall = NULL;
|
|
PRDPDR_DEVICE_IOREQUEST pIoRequest = &(pIoRequestPacket->IoRequest);
|
|
|
|
memset(&LocateCardsReturn, 0, sizeof(LocateCardsReturn));
|
|
LocateCardsReturn.ReturnCode = SCARD_S_SUCCESS;
|
|
|
|
//
|
|
// Decode input parameters
|
|
//
|
|
rpcStatus = MesDecodeBufferHandleCreate(
|
|
(char *) (pIoRequest + 1), // bytes are at end of struct
|
|
pIoRequest->Parameters.DeviceIoControl.InputBufferLength,
|
|
&hDec);
|
|
if (rpcStatus != RPC_S_OK)
|
|
{
|
|
TRC_ERR((TB, _T("MesDecodeBufferHandleCreate failed with %lx."), rpcStatus));
|
|
status = STATUS_NO_MEMORY;
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
//
|
|
// Decode and copy the input params
|
|
//
|
|
memset(&LocateCardsByATRCallA, 0, sizeof(LocateCardsByATRCallA));
|
|
_TRY_status(LocateCardsByATRA_Call_Decode(hDec, &LocateCardsByATRCallA))
|
|
|
|
if (sizeof(SCARDCONTEXT) == LocateCardsByATRCallA.Context.cbContext)
|
|
{
|
|
SCardContext = *((SCARDCONTEXT *) LocateCardsByATRCallA.Context.pbContext);
|
|
}
|
|
else
|
|
{
|
|
TRC_ERR((TB, _T("Invalid context sent from server.")));
|
|
LocateCardsReturn.ReturnCode = SCARD_E_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (LocateCardsReturn.ReturnCode == SCARD_S_SUCCESS)
|
|
{
|
|
LocateCardsReturn.ReturnCode =
|
|
AllocateAndCopyATRMasksForCall(
|
|
LocateCardsByATRCallA.cAtrs,
|
|
LocateCardsByATRCallA.rgAtrMasks,
|
|
&rgATRMasksForCall);
|
|
}
|
|
|
|
if (LocateCardsReturn.ReturnCode == SCARD_S_SUCCESS)
|
|
{
|
|
LocateCardsReturn.ReturnCode =
|
|
AllocateAndCopyReaderStateStructsForCallA(
|
|
LocateCardsByATRCallA.cReaders,
|
|
LocateCardsByATRCallA.rgReaderStates,
|
|
&rgReaderStatesA);
|
|
}
|
|
|
|
if (LocateCardsReturn.ReturnCode == SCARD_S_SUCCESS)
|
|
{
|
|
//
|
|
// Make the call... if it is available
|
|
//
|
|
#ifndef OS_WINCE
|
|
if (pfnSCardLocateCardsByATRW != NULL)
|
|
#else
|
|
if (pfnSCardLocateCardsByATRA != NULL)
|
|
#endif
|
|
{
|
|
LocateCardsReturn.ReturnCode =
|
|
pfnSCardLocateCardsByATRA(
|
|
SCardContext,
|
|
rgATRMasksForCall,
|
|
LocateCardsByATRCallA.cAtrs,
|
|
rgReaderStatesA,
|
|
LocateCardsByATRCallA.cReaders);
|
|
}
|
|
else
|
|
{
|
|
LocateCardsReturn.ReturnCode = ERROR_CALL_NOT_IMPLEMENTED;
|
|
}
|
|
}
|
|
|
|
//
|
|
// encode the return
|
|
//
|
|
rpcStatus = MesEncodeDynBufferHandleCreate(
|
|
&pbEncodedBuffer,
|
|
&cbEncodedBuffer,
|
|
&hEnc);
|
|
if (rpcStatus != RPC_S_OK)
|
|
{
|
|
TRC_ERR((TB, _T("MesEncodeDynBufferHandleCreate failed with %lx."), rpcStatus));
|
|
status = STATUS_NO_MEMORY;
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
if (LocateCardsReturn.ReturnCode == SCARD_S_SUCCESS)
|
|
{
|
|
LocateCardsReturn.ReturnCode =
|
|
AllocateAndCopyReaderStateStructsForReturnA(
|
|
LocateCardsByATRCallA.cReaders,
|
|
rgReaderStatesA,
|
|
&(LocateCardsReturn.rgReaderStates));
|
|
|
|
if (LocateCardsReturn.ReturnCode == SCARD_S_SUCCESS)
|
|
{
|
|
LocateCardsReturn.cReaders = LocateCardsByATRCallA.cReaders;
|
|
}
|
|
}
|
|
|
|
_TRY_status(LocateCards_Return_Encode(hEnc, &LocateCardsReturn))
|
|
|
|
//
|
|
// Send return
|
|
//
|
|
AllocateAndChannelWriteReplyPacket(
|
|
pIoRequestPacket,
|
|
pbEncodedBuffer,
|
|
cbEncodedBuffer);
|
|
|
|
Return:
|
|
|
|
SafeMesHandleFree(&hDec);
|
|
|
|
SafeMesHandleFree(&hEnc);
|
|
|
|
MIDL_user_free(rgReaderStatesA);
|
|
MIDL_user_free(LocateCardsReturn.rgReaderStates);
|
|
MIDL_user_free(rgATRMasksForCall);
|
|
MIDL_user_free(pbEncodedBuffer);
|
|
|
|
DC_END_FN();
|
|
|
|
return;
|
|
|
|
ErrorReturn:
|
|
|
|
DefaultIORequestMsgHandleWrapper(pIoRequestPacket, status);
|
|
|
|
goto Return;
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------------------
|
|
//
|
|
// W32SCard::LocateCardsByATRW
|
|
//
|
|
//---------------------------------------------------------------------------------------
|
|
void
|
|
W32SCard::LocateCardsByATRW(
|
|
IN PRDPDR_IOREQUEST_PACKET pIoRequestPacket)
|
|
{
|
|
DC_BEGIN_FN("W32SCard::LocateCardsByATRW");
|
|
|
|
RPC_STATUS rpcStatus = RPC_S_OK;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
char *pbEncodedBuffer = NULL;
|
|
unsigned long cbEncodedBuffer = 0;
|
|
handle_t hDec = 0;
|
|
handle_t hEnc = 0;
|
|
SCARDCONTEXT SCardContext;
|
|
LocateCardsByATRW_Call LocateCardsByATRCallW;
|
|
LocateCards_Return LocateCardsReturn;
|
|
LPSCARD_READERSTATE_W rgReaderStatesW = NULL;
|
|
SCARD_ATRMASK *rgATRMasksForCall = NULL;
|
|
PRDPDR_DEVICE_IOREQUEST pIoRequest = &(pIoRequestPacket->IoRequest);
|
|
|
|
memset(&LocateCardsReturn, 0, sizeof(LocateCardsReturn));
|
|
LocateCardsReturn.ReturnCode = SCARD_S_SUCCESS;
|
|
|
|
//
|
|
// Decode input parameters
|
|
//
|
|
rpcStatus = MesDecodeBufferHandleCreate(
|
|
(char *) (pIoRequest + 1), // bytes are at end of struct
|
|
pIoRequest->Parameters.DeviceIoControl.InputBufferLength,
|
|
&hDec);
|
|
if (rpcStatus != RPC_S_OK)
|
|
{
|
|
TRC_ERR((TB, _T("MesDecodeBufferHandleCreate failed with %lx."), rpcStatus));
|
|
status = STATUS_NO_MEMORY;
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
//
|
|
// Decode and copy the input params
|
|
//
|
|
memset(&LocateCardsByATRCallW, 0, sizeof(LocateCardsByATRCallW));
|
|
_TRY_status(LocateCardsByATRW_Call_Decode(hDec, &LocateCardsByATRCallW))
|
|
|
|
if (sizeof(SCARDCONTEXT) == LocateCardsByATRCallW.Context.cbContext)
|
|
{
|
|
SCardContext = *((SCARDCONTEXT *) LocateCardsByATRCallW.Context.pbContext);
|
|
}
|
|
else
|
|
{
|
|
TRC_ERR((TB, _T("Invalid context sent from server.")));
|
|
LocateCardsReturn.ReturnCode = SCARD_E_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (LocateCardsReturn.ReturnCode == SCARD_S_SUCCESS)
|
|
{
|
|
LocateCardsReturn.ReturnCode =
|
|
AllocateAndCopyATRMasksForCall(
|
|
LocateCardsByATRCallW.cAtrs,
|
|
LocateCardsByATRCallW.rgAtrMasks,
|
|
&rgATRMasksForCall);
|
|
}
|
|
|
|
if (LocateCardsReturn.ReturnCode == SCARD_S_SUCCESS)
|
|
{
|
|
LocateCardsReturn.ReturnCode =
|
|
AllocateAndCopyReaderStateStructsForCallW(
|
|
LocateCardsByATRCallW.cReaders,
|
|
LocateCardsByATRCallW.rgReaderStates,
|
|
&rgReaderStatesW);
|
|
}
|
|
|
|
if (LocateCardsReturn.ReturnCode == SCARD_S_SUCCESS)
|
|
{
|
|
//
|
|
// Make the call... if it is available
|
|
//
|
|
if (pfnSCardLocateCardsByATRW != NULL)
|
|
{
|
|
LocateCardsReturn.ReturnCode =
|
|
pfnSCardLocateCardsByATRW(
|
|
SCardContext,
|
|
rgATRMasksForCall,
|
|
LocateCardsByATRCallW.cAtrs,
|
|
rgReaderStatesW,
|
|
LocateCardsByATRCallW.cReaders);
|
|
}
|
|
else
|
|
{
|
|
LocateCardsReturn.ReturnCode = ERROR_CALL_NOT_IMPLEMENTED;
|
|
}
|
|
}
|
|
|
|
//
|
|
// encode the return
|
|
//
|
|
rpcStatus = MesEncodeDynBufferHandleCreate(
|
|
&pbEncodedBuffer,
|
|
&cbEncodedBuffer,
|
|
&hEnc);
|
|
if (rpcStatus != RPC_S_OK)
|
|
{
|
|
TRC_ERR((TB, _T("MesEncodeDynBufferHandleCreate failed with %lx."), rpcStatus));
|
|
status = STATUS_NO_MEMORY;
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
if (LocateCardsReturn.ReturnCode == SCARD_S_SUCCESS)
|
|
{
|
|
LocateCardsReturn.ReturnCode =
|
|
AllocateAndCopyReaderStateStructsForReturnW(
|
|
LocateCardsByATRCallW.cReaders,
|
|
rgReaderStatesW,
|
|
&(LocateCardsReturn.rgReaderStates));
|
|
|
|
if (LocateCardsReturn.ReturnCode == SCARD_S_SUCCESS)
|
|
{
|
|
LocateCardsReturn.cReaders = LocateCardsByATRCallW.cReaders;
|
|
}
|
|
}
|
|
|
|
_TRY_status(LocateCards_Return_Encode(hEnc, &LocateCardsReturn))
|
|
|
|
//
|
|
// Send return
|
|
//
|
|
AllocateAndChannelWriteReplyPacket(
|
|
pIoRequestPacket,
|
|
pbEncodedBuffer,
|
|
cbEncodedBuffer);
|
|
|
|
Return:
|
|
|
|
SafeMesHandleFree(&hDec);
|
|
|
|
SafeMesHandleFree(&hEnc);
|
|
|
|
MIDL_user_free(rgReaderStatesW);
|
|
MIDL_user_free(LocateCardsReturn.rgReaderStates);
|
|
MIDL_user_free(rgATRMasksForCall);
|
|
MIDL_user_free(pbEncodedBuffer);
|
|
|
|
DC_END_FN();
|
|
|
|
return;
|
|
|
|
ErrorReturn:
|
|
|
|
DefaultIORequestMsgHandleWrapper(pIoRequestPacket, status);
|
|
|
|
goto Return;
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------------
|
|
//
|
|
// W32SCard::GetStatusChangeThreadProc and W32SCard::GetStatusChangeWrapper
|
|
//
|
|
//---------------------------------------------------------------------------------------
|
|
typedef struct _GETSTATUSCHANGESTRUCT
|
|
{
|
|
W32SCard *pTHIS;
|
|
PRDPDR_IOREQUEST_PACKET pIoRequestPacket;
|
|
DWORD dwCallType;
|
|
HMODULE hModExtraRefCount;
|
|
HANDLE hThread;
|
|
} GETSTATUSCHANGESTRUCT;
|
|
|
|
|
|
DWORD WINAPI
|
|
W32SCard::GetStatusChangeThreadProc(
|
|
LPVOID lpParameter)
|
|
{
|
|
GETSTATUSCHANGESTRUCT *pGetStatusChangeStruct = (GETSTATUSCHANGESTRUCT *) lpParameter;
|
|
W32SCard *pTHIS = pGetStatusChangeStruct->pTHIS;
|
|
HANDLE hThread = NULL;
|
|
HMODULE hModExtraRefCount = NULL;
|
|
|
|
//
|
|
// pGetStatusChangeStruct->hThread will be NULL if it wasn't added to the thread
|
|
// list... if it wasn't added to the thread list then just get out.
|
|
//
|
|
if (pGetStatusChangeStruct->hThread == NULL)
|
|
{
|
|
FreeLibraryAndExitThread(pGetStatusChangeStruct->hModExtraRefCount, 0);
|
|
}
|
|
|
|
if (pGetStatusChangeStruct->dwCallType == SCARD_IOCTL_GETSTATUSCHANGEA)
|
|
{
|
|
pTHIS->GetStatusChangeA(pGetStatusChangeStruct->pIoRequestPacket);
|
|
}
|
|
else
|
|
{
|
|
pTHIS->GetStatusChangeW(pGetStatusChangeStruct->pIoRequestPacket);
|
|
}
|
|
|
|
hThread = pGetStatusChangeStruct->hThread;
|
|
hModExtraRefCount = pGetStatusChangeStruct->hModExtraRefCount;
|
|
MIDL_user_free(pGetStatusChangeStruct);
|
|
|
|
pTHIS->RemoveThreadFromList(hThread);
|
|
FreeLibraryAndExitThread(hModExtraRefCount, 0);
|
|
#ifdef OS_WINCE
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
|
|
void
|
|
W32SCard::GetStatusChangeWrapper(
|
|
IN PRDPDR_IOREQUEST_PACKET pIoRequestPacket,
|
|
IN DWORD dwCallType)
|
|
{
|
|
DC_BEGIN_FN("W32SCard::GetStatusChangeWrapper");
|
|
|
|
LONG lReturn = SCARD_S_SUCCESS;
|
|
HMODULE hModExtraRefCount = NULL;
|
|
GETSTATUSCHANGESTRUCT *pGetStatusChangeStruct = NULL;
|
|
DWORD dwThreadId;
|
|
HANDLE hThread;
|
|
|
|
//
|
|
// Get a ref count on our dll so that we know the dll
|
|
// code won't disappear from underneath us. The thread will
|
|
// release this ref count when it exits
|
|
//
|
|
hModExtraRefCount = AddRefCurrentModule();
|
|
if (hModExtraRefCount == NULL)
|
|
{
|
|
lReturn = SCARD_E_UNEXPECTED;
|
|
goto ImmediateReturn;
|
|
}
|
|
|
|
//
|
|
// Create a thread to the actual work of the GetStatusChange call
|
|
//
|
|
// Need to do this since the call can block
|
|
//
|
|
pGetStatusChangeStruct = (GETSTATUSCHANGESTRUCT *)
|
|
MIDL_user_allocate(sizeof(GETSTATUSCHANGESTRUCT));
|
|
if (pGetStatusChangeStruct == NULL)
|
|
{
|
|
TRC_ERR((TB, _T("MIDL_user_allocate failed")));
|
|
lReturn = SCARD_E_NO_MEMORY;
|
|
goto ImmediateReturn;
|
|
}
|
|
pGetStatusChangeStruct->pTHIS = this;
|
|
pGetStatusChangeStruct->pIoRequestPacket = pIoRequestPacket;
|
|
pGetStatusChangeStruct->dwCallType = dwCallType;
|
|
pGetStatusChangeStruct->hModExtraRefCount = hModExtraRefCount;
|
|
pGetStatusChangeStruct->hThread = NULL;
|
|
|
|
EnterCriticalSection(&_csThreadList);
|
|
|
|
//
|
|
// If the object is currently being destroyed, then don't create a new thread.
|
|
//
|
|
if (_fInDestructor)
|
|
{
|
|
LeaveCriticalSection(&_csThreadList);
|
|
goto ImmediateReturn;
|
|
}
|
|
|
|
hThread = CreateThread(
|
|
NULL,
|
|
0,
|
|
GetStatusChangeThreadProc,
|
|
pGetStatusChangeStruct,
|
|
CREATE_SUSPENDED,
|
|
&dwThreadId);
|
|
if (hThread == NULL)
|
|
{
|
|
lReturn = SCARD_E_UNEXPECTED;
|
|
LeaveCriticalSection(&_csThreadList);
|
|
goto ImmediateReturn;
|
|
}
|
|
|
|
if (!AddThreadToList(hThread))
|
|
{
|
|
LeaveCriticalSection(&_csThreadList);
|
|
ResumeThread(hThread);
|
|
WaitForSingleObject(hThread, INFINITE);
|
|
CloseHandle(hThread);
|
|
goto ImmediateReturn;
|
|
}
|
|
|
|
LeaveCriticalSection(&_csThreadList);
|
|
|
|
//
|
|
// Now let the thread go
|
|
//
|
|
pGetStatusChangeStruct->hThread = hThread;
|
|
ResumeThread(hThread);
|
|
|
|
//
|
|
// Return here and let the thread that was just created
|
|
// do the real work.
|
|
//
|
|
Return:
|
|
|
|
DC_END_FN();
|
|
|
|
return;
|
|
|
|
ImmediateReturn:
|
|
|
|
if (hModExtraRefCount != NULL)
|
|
{
|
|
FreeLibrary(hModExtraRefCount);
|
|
}
|
|
|
|
MIDL_user_free(pGetStatusChangeStruct);
|
|
|
|
EncodeAndChannelWriteLongReturn(
|
|
pIoRequestPacket,
|
|
lReturn);
|
|
|
|
goto Return;
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------------------
|
|
//
|
|
// W32SCard::GetStatusChangeA
|
|
//
|
|
//---------------------------------------------------------------------------------------
|
|
void
|
|
W32SCard::GetStatusChangeA(
|
|
IN PRDPDR_IOREQUEST_PACKET pIoRequestPacket)
|
|
{
|
|
DC_BEGIN_FN("W32SCard::GetStatusChangeA");
|
|
|
|
RPC_STATUS rpcStatus = RPC_S_OK;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
char *pbEncodedBuffer = NULL;
|
|
unsigned long cbEncodedBuffer = 0;
|
|
handle_t hDec = 0;
|
|
handle_t hEnc = 0;
|
|
SCARDCONTEXT SCardContext;
|
|
GetStatusChangeA_Call GetStatusChangeCallA;
|
|
GetStatusChange_Return GetStatusChangeReturn;
|
|
LPSCARD_READERSTATE_A rgReaderStatesA = NULL;
|
|
BOOL fFreeDecode = FALSE;
|
|
PRDPDR_DEVICE_IOREQUEST pIoRequest = &(pIoRequestPacket->IoRequest);
|
|
|
|
memset(&GetStatusChangeReturn, 0, sizeof(GetStatusChangeReturn));
|
|
GetStatusChangeReturn.ReturnCode = SCARD_S_SUCCESS;
|
|
|
|
//
|
|
// Decode input parameters
|
|
//
|
|
rpcStatus = MesDecodeBufferHandleCreate(
|
|
(char *) (pIoRequest + 1), // bytes are at end of struct
|
|
pIoRequest->Parameters.DeviceIoControl.InputBufferLength,
|
|
&hDec);
|
|
if (rpcStatus != RPC_S_OK)
|
|
{
|
|
TRC_ERR((TB, _T("MesDecodeBufferHandleCreate failed with %lx."), rpcStatus));
|
|
status = STATUS_NO_MEMORY;
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
//
|
|
// Decode and copy the input params
|
|
//
|
|
memset(&GetStatusChangeCallA, 0, sizeof(GetStatusChangeCallA));
|
|
_TRY_status(GetStatusChangeA_Call_Decode(hDec, &GetStatusChangeCallA))
|
|
fFreeDecode = TRUE;
|
|
|
|
if (sizeof(SCARDCONTEXT) == GetStatusChangeCallA.Context.cbContext)
|
|
{
|
|
SCardContext = *((SCARDCONTEXT *) GetStatusChangeCallA.Context.pbContext);
|
|
}
|
|
else
|
|
{
|
|
TRC_ERR((TB, _T("Invalid context sent from server.")));
|
|
GetStatusChangeReturn.ReturnCode = SCARD_E_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (GetStatusChangeReturn.ReturnCode == SCARD_S_SUCCESS)
|
|
{
|
|
GetStatusChangeReturn.ReturnCode =
|
|
AllocateAndCopyReaderStateStructsForCallA(
|
|
GetStatusChangeCallA.cReaders,
|
|
GetStatusChangeCallA.rgReaderStates,
|
|
&rgReaderStatesA);
|
|
}
|
|
|
|
if (GetStatusChangeReturn.ReturnCode == SCARD_S_SUCCESS)
|
|
{
|
|
//
|
|
// Make the call
|
|
//
|
|
GetStatusChangeReturn.ReturnCode =
|
|
pfnSCardGetStatusChangeA(
|
|
SCardContext,
|
|
GetStatusChangeCallA.dwTimeOut,
|
|
rgReaderStatesA,
|
|
GetStatusChangeCallA.cReaders);
|
|
}
|
|
#ifdef OS_WINCE
|
|
if (GetStatusChangeReturn.ReturnCode != SCARD_S_SUCCESS)
|
|
{
|
|
for (DWORD i=0; i<GetStatusChangeCallA.cReaders; i++)
|
|
{
|
|
if (strcmp(rgReaderStatesA[i].szReader, SCPNP_NOTIFICATIONA) == 0)
|
|
{
|
|
rgReaderStatesA[i].dwEventState = SCARD_STATE_CHANGED | 0x00010000; //the desktop returns this value. what is it defined to?
|
|
GetStatusChangeReturn.ReturnCode = SCARD_S_SUCCESS;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// encode the return
|
|
//
|
|
rpcStatus = MesEncodeDynBufferHandleCreate(
|
|
&pbEncodedBuffer,
|
|
&cbEncodedBuffer,
|
|
&hEnc);
|
|
if (rpcStatus != RPC_S_OK)
|
|
{
|
|
TRC_ERR((TB, _T("MesEncodeDynBufferHandleCreate failed with %lx."), rpcStatus));
|
|
status = STATUS_NO_MEMORY;
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
if (GetStatusChangeReturn.ReturnCode == SCARD_S_SUCCESS)
|
|
{
|
|
GetStatusChangeReturn.ReturnCode
|
|
= AllocateAndCopyReaderStateStructsForReturnA(
|
|
GetStatusChangeCallA.cReaders,
|
|
rgReaderStatesA,
|
|
&(GetStatusChangeReturn.rgReaderStates));
|
|
|
|
if (GetStatusChangeReturn.ReturnCode == SCARD_S_SUCCESS)
|
|
{
|
|
GetStatusChangeReturn.cReaders = GetStatusChangeCallA.cReaders;
|
|
}
|
|
}
|
|
_TRY_status(GetStatusChange_Return_Encode(hEnc, &GetStatusChangeReturn))
|
|
|
|
//
|
|
// Send return
|
|
//
|
|
AllocateAndChannelWriteReplyPacket(
|
|
pIoRequestPacket,
|
|
pbEncodedBuffer,
|
|
cbEncodedBuffer);
|
|
|
|
Return:
|
|
|
|
if (fFreeDecode)
|
|
{
|
|
_TRY_2(GetStatusChangeA_Call_Free(hDec, &GetStatusChangeCallA))
|
|
}
|
|
SafeMesHandleFree(&hDec);
|
|
|
|
SafeMesHandleFree(&hEnc);
|
|
|
|
MIDL_user_free(rgReaderStatesA);
|
|
MIDL_user_free(GetStatusChangeReturn.rgReaderStates);
|
|
MIDL_user_free(pbEncodedBuffer);
|
|
|
|
DC_END_FN();
|
|
|
|
return;
|
|
|
|
ErrorReturn:
|
|
|
|
DefaultIORequestMsgHandleWrapper(pIoRequestPacket, status);
|
|
|
|
goto Return;
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------------------
|
|
//
|
|
// W32SCard::GetStatusChangeW
|
|
//
|
|
//---------------------------------------------------------------------------------------
|
|
void
|
|
W32SCard::GetStatusChangeW(
|
|
IN PRDPDR_IOREQUEST_PACKET pIoRequestPacket)
|
|
{
|
|
DC_BEGIN_FN("W32SCard::GetStatusChangeW");
|
|
|
|
RPC_STATUS rpcStatus = RPC_S_OK;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
char *pbEncodedBuffer = NULL;
|
|
unsigned long cbEncodedBuffer = 0;
|
|
handle_t hDec = 0;
|
|
handle_t hEnc = 0;
|
|
SCARDCONTEXT SCardContext;
|
|
GetStatusChangeW_Call GetStatusChangeCallW;
|
|
GetStatusChange_Return GetStatusChangeReturn;
|
|
LPSCARD_READERSTATE_W rgReaderStatesW = NULL;
|
|
BOOL fFreeDecode = FALSE;
|
|
PRDPDR_DEVICE_IOREQUEST pIoRequest = &(pIoRequestPacket->IoRequest);
|
|
|
|
memset(&GetStatusChangeReturn, 0, sizeof(GetStatusChangeReturn));
|
|
GetStatusChangeReturn.ReturnCode = SCARD_S_SUCCESS;
|
|
|
|
//
|
|
// Decode input parameters
|
|
//
|
|
rpcStatus = MesDecodeBufferHandleCreate(
|
|
(char *) (pIoRequest + 1), // bytes are at end of struct
|
|
pIoRequest->Parameters.DeviceIoControl.InputBufferLength,
|
|
&hDec);
|
|
if (rpcStatus != RPC_S_OK)
|
|
{
|
|
TRC_ERR((TB, _T("MesDecodeBufferHandleCreate failed with %lx."), rpcStatus));
|
|
status = STATUS_NO_MEMORY;
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
//
|
|
// Decode and copy the input params
|
|
//
|
|
memset(&GetStatusChangeCallW, 0, sizeof(GetStatusChangeCallW));
|
|
_TRY_status(GetStatusChangeW_Call_Decode(hDec, &GetStatusChangeCallW))
|
|
fFreeDecode = TRUE;
|
|
|
|
if (sizeof(SCARDCONTEXT) == GetStatusChangeCallW.Context.cbContext)
|
|
{
|
|
SCardContext = *((SCARDCONTEXT *) GetStatusChangeCallW.Context.pbContext);
|
|
}
|
|
else
|
|
{
|
|
TRC_ERR((TB, _T("Invalid context sent from server.")));
|
|
GetStatusChangeReturn.ReturnCode = SCARD_E_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (GetStatusChangeReturn.ReturnCode == SCARD_S_SUCCESS)
|
|
{
|
|
GetStatusChangeReturn.ReturnCode =
|
|
AllocateAndCopyReaderStateStructsForCallW(
|
|
GetStatusChangeCallW.cReaders,
|
|
GetStatusChangeCallW.rgReaderStates,
|
|
&rgReaderStatesW);
|
|
}
|
|
|
|
if (GetStatusChangeReturn.ReturnCode == SCARD_S_SUCCESS)
|
|
{
|
|
//
|
|
// Make the call
|
|
//
|
|
GetStatusChangeReturn.ReturnCode =
|
|
pfnSCardGetStatusChangeW(
|
|
SCardContext,
|
|
GetStatusChangeCallW.dwTimeOut,
|
|
rgReaderStatesW,
|
|
GetStatusChangeCallW.cReaders);
|
|
}
|
|
|
|
#ifdef OS_WINCE
|
|
if (GetStatusChangeReturn.ReturnCode != SCARD_S_SUCCESS)
|
|
{
|
|
for (DWORD i=0; i<GetStatusChangeCallW.cReaders; i++)
|
|
{
|
|
if (lstrcmp(rgReaderStatesW[i].szReader, SCPNP_NOTIFICATION) == 0)
|
|
{
|
|
rgReaderStatesW[i].dwEventState = SCARD_STATE_CHANGED | 0x00010000; //the desktop returns this value. what is it defined to?
|
|
GetStatusChangeReturn.ReturnCode = SCARD_S_SUCCESS;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// encode the return
|
|
//
|
|
rpcStatus = MesEncodeDynBufferHandleCreate(
|
|
&pbEncodedBuffer,
|
|
&cbEncodedBuffer,
|
|
&hEnc);
|
|
if (rpcStatus != RPC_S_OK)
|
|
{
|
|
TRC_ERR((TB, _T("MesEncodeDynBufferHandleCreate failed with %lx."), rpcStatus));
|
|
status = STATUS_NO_MEMORY;
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
if (GetStatusChangeReturn.ReturnCode == SCARD_S_SUCCESS)
|
|
{
|
|
GetStatusChangeReturn.ReturnCode =
|
|
AllocateAndCopyReaderStateStructsForReturnW(
|
|
GetStatusChangeCallW.cReaders,
|
|
rgReaderStatesW,
|
|
&(GetStatusChangeReturn.rgReaderStates));
|
|
|
|
if (GetStatusChangeReturn.ReturnCode == SCARD_S_SUCCESS)
|
|
{
|
|
GetStatusChangeReturn.cReaders = GetStatusChangeCallW.cReaders;
|
|
}
|
|
}
|
|
|
|
_TRY_status(GetStatusChange_Return_Encode(hEnc, &GetStatusChangeReturn))
|
|
|
|
//
|
|
// Send return
|
|
//
|
|
AllocateAndChannelWriteReplyPacket(
|
|
pIoRequestPacket,
|
|
pbEncodedBuffer,
|
|
cbEncodedBuffer);
|
|
|
|
Return:
|
|
|
|
if (fFreeDecode)
|
|
{
|
|
_TRY_2(GetStatusChangeW_Call_Free(hDec, &GetStatusChangeCallW))
|
|
}
|
|
SafeMesHandleFree(&hDec);
|
|
|
|
SafeMesHandleFree(&hEnc);
|
|
|
|
MIDL_user_free(rgReaderStatesW);
|
|
MIDL_user_free(GetStatusChangeReturn.rgReaderStates);
|
|
MIDL_user_free(pbEncodedBuffer);
|
|
|
|
DC_END_FN();
|
|
|
|
return;
|
|
|
|
ErrorReturn:
|
|
|
|
DefaultIORequestMsgHandleWrapper(pIoRequestPacket, status);
|
|
|
|
goto Return;
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------------------
|
|
//
|
|
// W32SCard::Connect
|
|
//
|
|
//---------------------------------------------------------------------------------------
|
|
void
|
|
W32SCard::Connect(
|
|
IN SCARDHANDLECALLSTRUCT *pSCardHandleCall,
|
|
IN DWORD dwCallType)
|
|
{
|
|
DC_BEGIN_FN("W32SCard::Connect");
|
|
|
|
RPC_STATUS rpcStatus = RPC_S_OK;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
char *pbEncodedBuffer = NULL;
|
|
unsigned long cbEncodedBuffer = 0;
|
|
handle_t hDec = 0;
|
|
handle_t hEnc = 0;
|
|
SCARDCONTEXT SCardContext;
|
|
ConnectA_Call ConnectCallA;
|
|
ConnectW_Call ConnectCallW;
|
|
Connect_Return ConnectReturn;
|
|
BOOL fFreeDecode = FALSE;
|
|
BOOL fFreeHandle = FALSE;
|
|
SCARDHANDLE SCardHandle;
|
|
PRDPDR_IOREQUEST_PACKET pIoRequestPacket = pSCardHandleCall->pIoRequestPacket;
|
|
PRDPDR_DEVICE_IOREQUEST pIoRequest = &(pIoRequestPacket->IoRequest);
|
|
|
|
memset(&ConnectReturn, 0, sizeof(ConnectReturn));
|
|
ConnectReturn.ReturnCode = SCARD_S_SUCCESS;
|
|
|
|
//
|
|
// Decode input parameters
|
|
//
|
|
rpcStatus = MesDecodeBufferHandleCreate(
|
|
(char *) (pIoRequest + 1), // bytes are at end of struct
|
|
pIoRequest->Parameters.DeviceIoControl.InputBufferLength,
|
|
&hDec);
|
|
if (rpcStatus != RPC_S_OK)
|
|
{
|
|
TRC_ERR((TB, _T("MesDecodeBufferHandleCreate failed with %lx."), rpcStatus));
|
|
status = STATUS_NO_MEMORY;
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
//
|
|
// Decode input params and make the call to SCard*
|
|
//
|
|
if (dwCallType == SCARD_IOCTL_CONNECTA)
|
|
{
|
|
memset(&ConnectCallA, 0, sizeof(ConnectCallA));
|
|
_TRY_status(ConnectA_Call_Decode(hDec, &ConnectCallA))
|
|
fFreeDecode = TRUE;
|
|
|
|
if (sizeof(SCARDCONTEXT) != ConnectCallA.Common.Context.cbContext)
|
|
{
|
|
TRC_ERR((TB, _T("Invalid parameter sent from server.")));
|
|
ConnectReturn.ReturnCode = SCARD_E_INVALID_PARAMETER;
|
|
}
|
|
else if (ConnectCallA.szReader == NULL)
|
|
{
|
|
TRC_ERR((TB, _T("Invalid parameter sent from server.")));
|
|
ConnectReturn.ReturnCode = SCARD_E_INVALID_VALUE;
|
|
}
|
|
else
|
|
{
|
|
SCardContext = *((SCARDCONTEXT *) ConnectCallA.Common.Context.pbContext);
|
|
|
|
ConnectReturn.ReturnCode =
|
|
pfnSCardConnectA(
|
|
SCardContext,
|
|
ConnectCallA.szReader,
|
|
ConnectCallA.Common.dwShareMode,
|
|
ConnectCallA.Common.dwPreferredProtocols,
|
|
&SCardHandle,
|
|
&ConnectReturn.dwActiveProtocol);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
memset(&ConnectCallW, 0, sizeof(ConnectCallW));
|
|
_TRY_status(ConnectW_Call_Decode(hDec, &ConnectCallW))
|
|
fFreeDecode = TRUE;
|
|
|
|
if (sizeof(SCARDCONTEXT) != ConnectCallW.Common.Context.cbContext)
|
|
{
|
|
TRC_ERR((TB, _T("Invalid parameter sent from server.")));
|
|
ConnectReturn.ReturnCode = SCARD_E_INVALID_PARAMETER;
|
|
}
|
|
else if (ConnectCallW.szReader == NULL)
|
|
{
|
|
TRC_ERR((TB, _T("Invalid parameter sent from server.")));
|
|
ConnectReturn.ReturnCode = SCARD_E_INVALID_VALUE;
|
|
}
|
|
else
|
|
{
|
|
SCardContext = *((SCARDCONTEXT *) ConnectCallW.Common.Context.pbContext);
|
|
|
|
ConnectReturn.ReturnCode =
|
|
pfnSCardConnectW(
|
|
SCardContext,
|
|
ConnectCallW.szReader,
|
|
ConnectCallW.Common.dwShareMode,
|
|
ConnectCallW.Common.dwPreferredProtocols,
|
|
&SCardHandle,
|
|
&ConnectReturn.dwActiveProtocol);
|
|
}
|
|
}
|
|
|
|
if (ConnectReturn.ReturnCode == SCARD_S_SUCCESS)
|
|
{
|
|
ConnectReturn.hCard.Context.pbContext = 0;
|
|
ConnectReturn.hCard.Context.pbContext = NULL;
|
|
ConnectReturn.hCard.pbHandle = (BYTE *) &SCardHandle;
|
|
ConnectReturn.hCard.cbHandle = sizeof(SCARDHANDLE);
|
|
fFreeHandle = TRUE;
|
|
}
|
|
|
|
//
|
|
// encode the return
|
|
//
|
|
rpcStatus = MesEncodeDynBufferHandleCreate(
|
|
&pbEncodedBuffer,
|
|
&cbEncodedBuffer,
|
|
&hEnc);
|
|
if (rpcStatus != RPC_S_OK)
|
|
{
|
|
TRC_ERR((TB, _T("MesEncodeDynBufferHandleCreate failed with %lx."), rpcStatus));
|
|
status = STATUS_NO_MEMORY;
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
_TRY_status(Connect_Return_Encode(hEnc, &ConnectReturn))
|
|
|
|
//
|
|
// Send return
|
|
//
|
|
AllocateAndChannelWriteReplyPacket(
|
|
pIoRequestPacket,
|
|
pbEncodedBuffer,
|
|
cbEncodedBuffer);
|
|
|
|
Return:
|
|
|
|
if (fFreeDecode)
|
|
{
|
|
if (dwCallType == SCARD_IOCTL_CONNECTA)
|
|
{
|
|
_TRY_2(ConnectA_Call_Free(hDec, &ConnectCallA))
|
|
}
|
|
else
|
|
{
|
|
_TRY_2(ConnectW_Call_Free(hDec, &ConnectCallW))
|
|
}
|
|
}
|
|
SafeMesHandleFree(&hDec);
|
|
|
|
SafeMesHandleFree(&hEnc);
|
|
|
|
MIDL_user_free(pbEncodedBuffer);
|
|
|
|
MIDL_user_free(pSCardHandleCall);
|
|
|
|
DC_END_FN();
|
|
|
|
return;
|
|
|
|
ErrorReturn:
|
|
|
|
if (fFreeHandle)
|
|
{
|
|
pfnSCardDisconnect(SCardHandle, SCARD_LEAVE_CARD);
|
|
}
|
|
|
|
DefaultIORequestMsgHandleWrapper(pIoRequestPacket, status);
|
|
|
|
goto Return;
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------------------
|
|
//
|
|
// W32SCard::Reconnect
|
|
//
|
|
//---------------------------------------------------------------------------------------
|
|
void
|
|
W32SCard::Reconnect(
|
|
IN SCARDHANDLECALLSTRUCT *pSCardHandleCall)
|
|
{
|
|
DC_BEGIN_FN("W32SCard::Reconnect");
|
|
|
|
RPC_STATUS rpcStatus = RPC_S_OK;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
char *pbEncodedBuffer = NULL;
|
|
unsigned long cbEncodedBuffer = 0;
|
|
handle_t hDec = 0;
|
|
handle_t hEnc = 0;
|
|
SCARDHANDLE SCardHandle;
|
|
Reconnect_Call ReconnectCall;
|
|
Reconnect_Return ReconnectReturn;
|
|
BOOL fFreeDecode = FALSE;
|
|
PRDPDR_IOREQUEST_PACKET pIoRequestPacket = pSCardHandleCall->pIoRequestPacket;
|
|
PRDPDR_DEVICE_IOREQUEST pIoRequest = &(pIoRequestPacket->IoRequest);
|
|
|
|
memset(&ReconnectReturn, 0, sizeof(ReconnectReturn));
|
|
ReconnectReturn.ReturnCode = SCARD_S_SUCCESS;
|
|
|
|
//
|
|
// Decode input parameters
|
|
//
|
|
rpcStatus = MesDecodeBufferHandleCreate(
|
|
(char *) (pIoRequest + 1), // bytes are at end of struct
|
|
pIoRequest->Parameters.DeviceIoControl.InputBufferLength,
|
|
&hDec);
|
|
if (rpcStatus != RPC_S_OK)
|
|
{
|
|
TRC_ERR((TB, _T("MesDecodeBufferHandleCreate failed with %lx."), rpcStatus));
|
|
status = STATUS_NO_MEMORY;
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
//
|
|
// Decode input params and make the call to SCard*
|
|
//
|
|
memset(&ReconnectCall, 0, sizeof(ReconnectCall));
|
|
_TRY_status(Reconnect_Call_Decode(hDec, &ReconnectCall))
|
|
fFreeDecode = TRUE;
|
|
|
|
if (sizeof(SCARDHANDLE) == ReconnectCall.hCard.cbHandle)
|
|
{
|
|
SCardHandle = *((SCARDHANDLE *) ReconnectCall.hCard.pbHandle);
|
|
|
|
ReconnectReturn.ReturnCode =
|
|
pfnSCardReconnect(
|
|
SCardHandle,
|
|
ReconnectCall.dwShareMode,
|
|
ReconnectCall.dwPreferredProtocols,
|
|
ReconnectCall.dwInitialization,
|
|
&ReconnectReturn.dwActiveProtocol);
|
|
}
|
|
else
|
|
{
|
|
TRC_ERR((TB, _T("Invalid handle sent from server.")));
|
|
ReconnectReturn.ReturnCode = SCARD_E_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// encode the return
|
|
//
|
|
rpcStatus = MesEncodeDynBufferHandleCreate(
|
|
&pbEncodedBuffer,
|
|
&cbEncodedBuffer,
|
|
&hEnc);
|
|
if (rpcStatus != RPC_S_OK)
|
|
{
|
|
TRC_ERR((TB, _T("MesEncodeDynBufferHandleCreate failed with %lx."), rpcStatus));
|
|
status = STATUS_NO_MEMORY;
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
_TRY_status(Reconnect_Return_Encode(hEnc, &ReconnectReturn))
|
|
|
|
//
|
|
// Send return
|
|
//
|
|
AllocateAndChannelWriteReplyPacket(
|
|
pIoRequestPacket,
|
|
pbEncodedBuffer,
|
|
cbEncodedBuffer);
|
|
|
|
Return:
|
|
|
|
if (fFreeDecode)
|
|
{
|
|
_TRY_2(Reconnect_Call_Free(hDec, &ReconnectCall))
|
|
}
|
|
SafeMesHandleFree(&hDec);
|
|
|
|
SafeMesHandleFree(&hEnc);
|
|
|
|
MIDL_user_free(pbEncodedBuffer);
|
|
|
|
MIDL_user_free(pSCardHandleCall);
|
|
|
|
DC_END_FN();
|
|
|
|
return;
|
|
|
|
ErrorReturn:
|
|
|
|
DefaultIORequestMsgHandleWrapper(pIoRequestPacket, status);
|
|
|
|
goto Return;
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------------------
|
|
//
|
|
// W32SCard::HandleHCardAndDispositionCall
|
|
//
|
|
//---------------------------------------------------------------------------------------
|
|
void
|
|
W32SCard::HandleHCardAndDispositionCall(
|
|
IN SCARDHANDLECALLSTRUCT *pSCardHandleCall,
|
|
IN DWORD dwCallType)
|
|
{
|
|
DC_BEGIN_FN("W32SCard::HandleHCardAndDispositionCall");
|
|
|
|
LONG lReturn = SCARD_S_SUCCESS;
|
|
RPC_STATUS rpcStatus = RPC_S_OK;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
handle_t hDec = 0;
|
|
SCARDHANDLE SCardHandle;
|
|
DWORD dwDisposition;
|
|
HCardAndDisposition_Call HCardAndDispositionCall;
|
|
PRDPDR_IOREQUEST_PACKET pIoRequestPacket = pSCardHandleCall->pIoRequestPacket;
|
|
PRDPDR_DEVICE_IOREQUEST pIoRequest = &(pIoRequestPacket->IoRequest);
|
|
|
|
//
|
|
// Decode input parameters
|
|
//
|
|
rpcStatus = MesDecodeBufferHandleCreate(
|
|
(char *) (pIoRequest + 1), // bytes are at end of struct
|
|
pIoRequest->Parameters.DeviceIoControl.InputBufferLength,
|
|
&hDec);
|
|
if (rpcStatus != RPC_S_OK)
|
|
{
|
|
TRC_ERR((TB, _T("MesDecodeBufferHandleCreate failed with %lx."), rpcStatus));
|
|
status = STATUS_NO_MEMORY;
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
memset(&HCardAndDispositionCall, 0, sizeof(HCardAndDispositionCall));
|
|
_TRY_status(HCardAndDisposition_Call_Decode(hDec, &HCardAndDispositionCall))
|
|
|
|
if (sizeof(SCARDHANDLE) == HCardAndDispositionCall.hCard.cbHandle)
|
|
{
|
|
SCardHandle = *((SCARDHANDLE *) HCardAndDispositionCall.hCard.pbHandle);
|
|
dwDisposition = HCardAndDispositionCall.dwDisposition;
|
|
}
|
|
else
|
|
{
|
|
TRC_ERR((TB, _T("Invalid handle sent from server.")));
|
|
lReturn = SCARD_E_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// Free up resources used by decode
|
|
//
|
|
_TRY_2(HCardAndDisposition_Call_Free(hDec, &HCardAndDispositionCall))
|
|
SafeMesHandleFree(&hDec);
|
|
|
|
if (lReturn == SCARD_S_SUCCESS)
|
|
{
|
|
//
|
|
// Make SCard subsystem call
|
|
//
|
|
switch(dwCallType)
|
|
{
|
|
case SCARD_IOCTL_DISCONNECT:
|
|
lReturn = pfnSCardDisconnect(SCardHandle, dwDisposition);
|
|
break;
|
|
case SCARD_IOCTL_BEGINTRANSACTION:
|
|
lReturn = pfnSCardBeginTransaction(SCardHandle);
|
|
break;
|
|
case SCARD_IOCTL_ENDTRANSACTION:
|
|
lReturn = pfnSCardEndTransaction(SCardHandle, dwDisposition);
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// encode and write the return
|
|
//
|
|
EncodeAndChannelWriteLongReturn(pIoRequestPacket, lReturn);
|
|
|
|
Return:
|
|
|
|
MIDL_user_free(pSCardHandleCall);
|
|
|
|
DC_END_FN();
|
|
|
|
return;
|
|
|
|
ErrorReturn:
|
|
|
|
DefaultIORequestMsgHandleWrapper(pIoRequestPacket, status);
|
|
|
|
goto Return;
|
|
|
|
}
|
|
|
|
#ifndef OS_WINCE
|
|
//---------------------------------------------------------------------------------------
|
|
//
|
|
// W32SCard::State
|
|
//
|
|
//---------------------------------------------------------------------------------------
|
|
void
|
|
W32SCard::State(
|
|
IN SCARDHANDLECALLSTRUCT *pSCardHandleCall)
|
|
{
|
|
DC_BEGIN_FN("W32SCard::State");
|
|
|
|
RPC_STATUS rpcStatus = RPC_S_OK;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
char *pbEncodedBuffer = NULL;
|
|
unsigned long cbEncodedBuffer = 0;
|
|
handle_t hDec = 0;
|
|
handle_t hEnc = 0;
|
|
SCARDCONTEXT SCardContext;
|
|
SCARDHANDLE SCardHandle;
|
|
State_Call StateCall;
|
|
State_Return StateReturn;
|
|
BOOL fFreeDecode = FALSE;
|
|
DWORD cbAtr = 0;
|
|
BOOL fDoAllocationLocally = FALSE;
|
|
LPBYTE pbAtr = NULL;
|
|
BOOL fFree = FALSE;
|
|
PRDPDR_IOREQUEST_PACKET pIoRequestPacket = pSCardHandleCall->pIoRequestPacket;
|
|
PRDPDR_DEVICE_IOREQUEST pIoRequest = &(pIoRequestPacket->IoRequest);
|
|
|
|
memset(&StateReturn, 0, sizeof(StateReturn));
|
|
StateReturn.ReturnCode = SCARD_S_SUCCESS;
|
|
|
|
//
|
|
// Decode input parameters
|
|
//
|
|
rpcStatus = MesDecodeBufferHandleCreate(
|
|
(char *) (pIoRequest + 1), // bytes are at end of struct
|
|
pIoRequest->Parameters.DeviceIoControl.InputBufferLength,
|
|
&hDec);
|
|
if (rpcStatus != RPC_S_OK)
|
|
{
|
|
TRC_ERR((TB, _T("MesDecodeBufferHandleCreate failed with %lx."), rpcStatus));
|
|
status = STATUS_NO_MEMORY;
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
//
|
|
// Decode input params
|
|
//
|
|
memset(&StateCall, 0, sizeof(StateCall));
|
|
_TRY_status(State_Call_Decode(hDec, &StateCall))
|
|
fFreeDecode = TRUE;
|
|
|
|
if (sizeof(SCARDHANDLE) == StateCall.hCard.cbHandle)
|
|
{
|
|
SCardContext = *((SCARDCONTEXT *) StateCall.hCard.Context.pbContext);
|
|
SCardHandle = *((SCARDHANDLE *) StateCall.hCard.pbHandle);
|
|
cbAtr = StateCall.cbAtrLen;
|
|
}
|
|
else
|
|
{
|
|
TRC_ERR((TB, _T("Invalid handle sent from server.")));
|
|
StateReturn.ReturnCode = SCARD_E_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (StateReturn.ReturnCode == SCARD_S_SUCCESS)
|
|
{
|
|
//
|
|
// Allocate if not in SCARD_AUTOALLOCATE mode and not a size only call
|
|
//
|
|
fDoAllocationLocally =
|
|
(!StateCall.fpbAtrIsNULL &&
|
|
(cbAtr != SCARD_AUTOALLOCATE));
|
|
|
|
if (fDoAllocationLocally)
|
|
{
|
|
pbAtr = (LPBYTE) MIDL_user_allocate(cbAtr * sizeof(BYTE));
|
|
if (pbAtr == NULL)
|
|
{
|
|
TRC_ERR((TB, _T("MIDL_user_allocate failed")));
|
|
StateReturn.ReturnCode = SCARD_E_NO_MEMORY;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (StateReturn.ReturnCode == SCARD_S_SUCCESS)
|
|
{
|
|
//
|
|
// Make the call
|
|
//
|
|
StateReturn.ReturnCode =
|
|
pfnSCardState(
|
|
SCardHandle,
|
|
&StateReturn.dwState,
|
|
&StateReturn.dwProtocol,
|
|
(cbAtr == SCARD_AUTOALLOCATE) ? (LPBYTE) &pbAtr : pbAtr,
|
|
&cbAtr);
|
|
}
|
|
|
|
if (StateReturn.ReturnCode == SCARD_S_SUCCESS)
|
|
{
|
|
StateReturn.cbAtrLen = cbAtr;
|
|
|
|
//
|
|
// If we are just returning the byte count then send back a junk buffer
|
|
//
|
|
if (pbAtr == NULL)
|
|
{
|
|
StateReturn.rgAtr = (BYTE *) MIDL_user_allocate(cbAtr);
|
|
if (StateReturn.rgAtr == NULL)
|
|
{
|
|
status = STATUS_NO_MEMORY;
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
fFree = TRUE;
|
|
memset(StateReturn.rgAtr, 0, cbAtr);
|
|
}
|
|
else
|
|
{
|
|
StateReturn.rgAtr = pbAtr;
|
|
}
|
|
}
|
|
|
|
//
|
|
// encode the return
|
|
//
|
|
rpcStatus = MesEncodeDynBufferHandleCreate(
|
|
&pbEncodedBuffer,
|
|
&cbEncodedBuffer,
|
|
&hEnc);
|
|
if (rpcStatus != RPC_S_OK)
|
|
{
|
|
TRC_ERR((TB, _T("MesEncodeDynBufferHandleCreate failed with %lx."), rpcStatus));
|
|
status = STATUS_NO_MEMORY;
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
_TRY_status(State_Return_Encode(hEnc, &StateReturn))
|
|
|
|
//
|
|
// Send return
|
|
//
|
|
AllocateAndChannelWriteReplyPacket(
|
|
pIoRequestPacket,
|
|
pbEncodedBuffer,
|
|
cbEncodedBuffer);
|
|
|
|
Return:
|
|
|
|
if (fFree)
|
|
{
|
|
MIDL_user_free(StateReturn.rgAtr);
|
|
}
|
|
|
|
if (pbAtr != NULL)
|
|
{
|
|
//
|
|
// Check to see whether we allocated or SCard allcated for us
|
|
//
|
|
if (fDoAllocationLocally)
|
|
{
|
|
MIDL_user_free(pbAtr);
|
|
}
|
|
else
|
|
{
|
|
pfnSCardFreeMemory(SCardContext, pbAtr);
|
|
}
|
|
}
|
|
|
|
if (fFreeDecode)
|
|
{
|
|
_TRY_2(State_Call_Free(hDec, &StateCall))
|
|
}
|
|
SafeMesHandleFree(&hDec);
|
|
|
|
SafeMesHandleFree(&hEnc);
|
|
|
|
MIDL_user_free(pbEncodedBuffer);
|
|
|
|
MIDL_user_free(pSCardHandleCall);
|
|
|
|
DC_END_FN();
|
|
|
|
return;
|
|
|
|
ErrorReturn:
|
|
|
|
DefaultIORequestMsgHandleWrapper(pIoRequestPacket, status);
|
|
|
|
goto Return;
|
|
}
|
|
#endif
|
|
|
|
//---------------------------------------------------------------------------------------
|
|
//
|
|
// W32SCard::Status
|
|
//
|
|
//---------------------------------------------------------------------------------------
|
|
void
|
|
W32SCard::Status(
|
|
IN SCARDHANDLECALLSTRUCT *pSCardHandleCall,
|
|
IN DWORD dwCallType)
|
|
{
|
|
DC_BEGIN_FN("W32SCard::Status");
|
|
|
|
RPC_STATUS rpcStatus = RPC_S_OK;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
char *pbEncodedBuffer = NULL;
|
|
unsigned long cbEncodedBuffer = 0;
|
|
handle_t hDec = 0;
|
|
handle_t hEnc = 0;
|
|
SCARDCONTEXT SCardContext;
|
|
SCARDHANDLE SCardHandle;
|
|
Status_Call StatusCall;
|
|
Status_Return StatusReturn;
|
|
BOOL fFreeDecode = FALSE;
|
|
DWORD cchReaderLen = 0;
|
|
BOOL fDoAllocationLocally = FALSE;
|
|
LPBYTE psz = NULL;
|
|
BOOL fFree = FALSE;
|
|
PRDPDR_IOREQUEST_PACKET pIoRequestPacket = pSCardHandleCall->pIoRequestPacket;
|
|
PRDPDR_DEVICE_IOREQUEST pIoRequest = &(pIoRequestPacket->IoRequest);
|
|
|
|
memset(&StatusReturn, 0, sizeof(StatusReturn));
|
|
StatusReturn.ReturnCode = SCARD_S_SUCCESS;
|
|
|
|
//
|
|
// Decode input parameters
|
|
//
|
|
rpcStatus = MesDecodeBufferHandleCreate(
|
|
(char *) (pIoRequest + 1), // bytes are at end of struct
|
|
pIoRequest->Parameters.DeviceIoControl.InputBufferLength,
|
|
&hDec);
|
|
if (rpcStatus != RPC_S_OK)
|
|
{
|
|
TRC_ERR((TB, _T("MesDecodeBufferHandleCreate failed with %lx."), rpcStatus));
|
|
status = STATUS_NO_MEMORY;
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
memset(&StatusCall, 0, sizeof(StatusCall));
|
|
_TRY_status(Status_Call_Decode(hDec, &StatusCall))
|
|
fFreeDecode = TRUE;
|
|
|
|
if (sizeof(SCARDHANDLE) == StatusCall.hCard.cbHandle)
|
|
{
|
|
SCardContext = *((SCARDCONTEXT *) StatusCall.hCard.Context.pbContext);
|
|
SCardHandle = *((SCARDHANDLE *) StatusCall.hCard.pbHandle);
|
|
cchReaderLen = StatusCall.cchReaderLen;
|
|
}
|
|
else
|
|
{
|
|
TRC_ERR((TB, _T("Invalid handle sent from server.")));
|
|
StatusReturn.ReturnCode = SCARD_E_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (StatusReturn.ReturnCode == SCARD_S_SUCCESS)
|
|
{
|
|
//
|
|
// Allocate if not in SCARD_AUTOALLOCATE mode and not a size only call
|
|
//
|
|
fDoAllocationLocally =
|
|
(!StatusCall.fmszReaderNamesIsNULL &&
|
|
(cchReaderLen != SCARD_AUTOALLOCATE));
|
|
|
|
#ifdef OS_WINCE
|
|
if (!fDoAllocationLocally)
|
|
{
|
|
StatusReturn.cbAtrLen = ATR_SIZE;
|
|
|
|
StatusReturn.ReturnCode =
|
|
pfnSCardStatusW(
|
|
SCardHandle,
|
|
NULL,
|
|
&cchReaderLen,
|
|
&StatusReturn.dwState,
|
|
&StatusReturn.dwProtocol,
|
|
(LPBYTE) &StatusReturn.pbAtr,
|
|
&StatusReturn.cbAtrLen);
|
|
|
|
if ((StatusReturn.ReturnCode == SCARD_S_SUCCESS) && (cchReaderLen > 0))
|
|
fDoAllocationLocally = TRUE;
|
|
else
|
|
{
|
|
TRC_ERR((TB, _T("SCardStatusW failed")));
|
|
status = STATUS_UNSUCCESSFUL;
|
|
goto ErrorReturn;
|
|
}
|
|
}
|
|
#endif
|
|
if (fDoAllocationLocally)
|
|
{
|
|
DWORD dwCharSize = (dwCallType == SCARD_IOCTL_STATUSA) ?
|
|
sizeof(char) : sizeof(WCHAR);
|
|
|
|
psz = (LPBYTE) MIDL_user_allocate(cchReaderLen * dwCharSize);
|
|
if (psz == NULL)
|
|
{
|
|
TRC_ERR((TB, _T("MIDL_user_allocate failed")));
|
|
StatusReturn.ReturnCode = SCARD_E_NO_MEMORY;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (StatusReturn.ReturnCode == SCARD_S_SUCCESS)
|
|
{
|
|
//
|
|
// Make the call
|
|
//
|
|
StatusReturn.cbAtrLen = ATR_SIZE;
|
|
|
|
if (dwCallType == SCARD_IOCTL_STATUSA)
|
|
{
|
|
StatusReturn.ReturnCode =
|
|
pfnSCardStatusA(
|
|
SCardHandle,
|
|
(cchReaderLen == SCARD_AUTOALLOCATE) ? (LPSTR) &psz : (LPSTR) psz,
|
|
&cchReaderLen,
|
|
&StatusReturn.dwState,
|
|
&StatusReturn.dwProtocol,
|
|
(LPBYTE) &StatusReturn.pbAtr,
|
|
&StatusReturn.cbAtrLen);
|
|
|
|
if (StatusReturn.ReturnCode == SCARD_S_SUCCESS)
|
|
{
|
|
StatusReturn.cBytes = cchReaderLen * sizeof(char);
|
|
StatusReturn.mszReaderNames = psz;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
StatusReturn.ReturnCode =
|
|
pfnSCardStatusW(
|
|
SCardHandle,
|
|
(cchReaderLen == SCARD_AUTOALLOCATE) ? (LPWSTR) &psz : (LPWSTR) psz,
|
|
&cchReaderLen,
|
|
&StatusReturn.dwState,
|
|
&StatusReturn.dwProtocol,
|
|
(LPBYTE) &StatusReturn.pbAtr,
|
|
&StatusReturn.cbAtrLen);
|
|
|
|
if (StatusReturn.ReturnCode == SCARD_S_SUCCESS)
|
|
{
|
|
StatusReturn.cBytes = cchReaderLen * sizeof(WCHAR);
|
|
StatusReturn.mszReaderNames = psz;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (StatusReturn.ReturnCode == SCARD_S_SUCCESS)
|
|
{
|
|
//
|
|
// If we are just returning the byte count then send back a junk buffer
|
|
//
|
|
if (StatusReturn.mszReaderNames == NULL)
|
|
{
|
|
StatusReturn.mszReaderNames = (BYTE *) MIDL_user_allocate(StatusReturn.cBytes);
|
|
if (StatusReturn.mszReaderNames == NULL)
|
|
{
|
|
status = STATUS_NO_MEMORY;
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
fFree = TRUE;
|
|
memset(StatusReturn.mszReaderNames, 0, StatusReturn.cBytes);
|
|
}
|
|
}
|
|
|
|
//
|
|
// encode the return
|
|
//
|
|
rpcStatus = MesEncodeDynBufferHandleCreate(
|
|
&pbEncodedBuffer,
|
|
&cbEncodedBuffer,
|
|
&hEnc);
|
|
if (rpcStatus != RPC_S_OK)
|
|
{
|
|
TRC_ERR((TB, _T("MesEncodeDynBufferHandleCreate failed with %lx."), rpcStatus));
|
|
status = STATUS_NO_MEMORY;
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
_TRY_status(Status_Return_Encode(hEnc, &StatusReturn))
|
|
|
|
//
|
|
// Send return
|
|
//
|
|
AllocateAndChannelWriteReplyPacket(
|
|
pIoRequestPacket,
|
|
pbEncodedBuffer,
|
|
cbEncodedBuffer);
|
|
|
|
Return:
|
|
|
|
if (fFree)
|
|
{
|
|
MIDL_user_free(StatusReturn.mszReaderNames);
|
|
}
|
|
|
|
if (psz != NULL)
|
|
{
|
|
//
|
|
// Check to see whether we allocated or SCard allcated for us
|
|
//
|
|
if (fDoAllocationLocally)
|
|
{
|
|
MIDL_user_free(psz);
|
|
}
|
|
else
|
|
{
|
|
#ifndef OS_WINCE
|
|
pfnSCardFreeMemory(SCardContext, psz);
|
|
#else
|
|
TRC_ASSERT(FALSE, (TB, _T("Shouldnt get here")));
|
|
#endif
|
|
}
|
|
}
|
|
|
|
if (fFreeDecode)
|
|
{
|
|
_TRY_2(Status_Call_Free(hDec, &StatusCall))
|
|
}
|
|
SafeMesHandleFree(&hDec);
|
|
|
|
SafeMesHandleFree(&hEnc);
|
|
|
|
MIDL_user_free(pbEncodedBuffer);
|
|
|
|
MIDL_user_free(pSCardHandleCall);
|
|
|
|
DC_END_FN();
|
|
|
|
return;
|
|
|
|
ErrorReturn:
|
|
|
|
DefaultIORequestMsgHandleWrapper(pIoRequestPacket, status);
|
|
|
|
goto Return;
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------------------
|
|
//
|
|
// W32SCard::Transmit
|
|
//
|
|
//---------------------------------------------------------------------------------------
|
|
void
|
|
W32SCard::Transmit(
|
|
IN SCARDHANDLECALLSTRUCT *pSCardHandleCall)
|
|
{
|
|
DC_BEGIN_FN("W32SCard::Transmit");
|
|
|
|
RPC_STATUS rpcStatus = RPC_S_OK;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
char *pbEncodedBuffer = NULL;
|
|
unsigned long cbEncodedBuffer = 0;
|
|
handle_t hDec = 0;
|
|
handle_t hEnc = 0;
|
|
SCARDCONTEXT SCardContext;
|
|
SCARDHANDLE SCardHandle;
|
|
Transmit_Call TransmitCall;
|
|
Transmit_Return TransmitReturn;
|
|
BOOL fFreeDecode = FALSE;
|
|
BOOL fDoAllocationLocally = FALSE;
|
|
SCARD_IO_REQUEST *pSendPci = NULL;
|
|
SCARD_IO_REQUEST *pRecvPci = NULL;
|
|
SCardIO_Request *pReturnRecvPci = NULL;
|
|
DWORD cbRecvLength;
|
|
BYTE *pbRecvBuffer = NULL;
|
|
BOOL fFree = FALSE;
|
|
PRDPDR_IOREQUEST_PACKET pIoRequestPacket = pSCardHandleCall->pIoRequestPacket;
|
|
PRDPDR_DEVICE_IOREQUEST pIoRequest = &(pIoRequestPacket->IoRequest);
|
|
|
|
memset(&TransmitReturn, 0, sizeof(TransmitReturn));
|
|
TransmitReturn.ReturnCode = SCARD_S_SUCCESS;
|
|
|
|
//
|
|
// Decode input parameters
|
|
//
|
|
rpcStatus = MesDecodeBufferHandleCreate(
|
|
(char *) (pIoRequest + 1), // bytes are at end of struct
|
|
pIoRequest->Parameters.DeviceIoControl.InputBufferLength,
|
|
&hDec);
|
|
if (rpcStatus != RPC_S_OK)
|
|
{
|
|
TRC_ERR((TB, _T("MesDecodeBufferHandleCreate failed with %lx."), rpcStatus));
|
|
status = STATUS_NO_MEMORY;
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
//
|
|
// Decode and setup the input params
|
|
//
|
|
memset(&TransmitCall, 0, sizeof(TransmitCall));
|
|
_TRY_status(Transmit_Call_Decode(hDec, &TransmitCall))
|
|
fFreeDecode = TRUE;
|
|
|
|
if (sizeof(SCARDHANDLE) == TransmitCall.hCard.cbHandle)
|
|
{
|
|
SCardContext = *((SCARDCONTEXT *) TransmitCall.hCard.Context.pbContext);
|
|
SCardHandle = *((SCARDHANDLE *) TransmitCall.hCard.pbHandle);
|
|
cbRecvLength = TransmitCall.cbRecvLength;
|
|
}
|
|
else
|
|
{
|
|
TRC_ERR((TB, _T("Invalid handle sent from server.")));
|
|
TransmitReturn.ReturnCode = SCARD_E_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// setup the pSendPci param of the call based on callers input
|
|
//
|
|
if (TransmitReturn.ReturnCode == SCARD_S_SUCCESS)
|
|
{
|
|
pSendPci = (LPSCARD_IO_REQUEST)
|
|
MIDL_user_allocate( sizeof(SCARD_IO_REQUEST) +
|
|
TransmitCall.ioSendPci.cbExtraBytes);
|
|
if (pSendPci != NULL)
|
|
{
|
|
pSendPci->dwProtocol = TransmitCall.ioSendPci.dwProtocol;
|
|
pSendPci->cbPciLength = sizeof(SCARD_IO_REQUEST) +
|
|
TransmitCall.ioSendPci.cbExtraBytes;
|
|
if (TransmitCall.ioSendPci.cbExtraBytes != 0)
|
|
{
|
|
memcpy(
|
|
((LPBYTE) pSendPci) + sizeof(SCARD_IO_REQUEST),
|
|
TransmitCall.ioSendPci.pbExtraBytes,
|
|
TransmitCall.ioSendPci.cbExtraBytes);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TRC_ERR((TB, _T("MIDL_user_allocate failed")));
|
|
TransmitReturn.ReturnCode = SCARD_E_NO_MEMORY;
|
|
}
|
|
}
|
|
|
|
//
|
|
// setup the pRecvPci param of the call based on callers input
|
|
//
|
|
if (TransmitReturn.ReturnCode == SCARD_S_SUCCESS)
|
|
{
|
|
if (TransmitCall.pioRecvPci != NULL)
|
|
{
|
|
pRecvPci = (LPSCARD_IO_REQUEST)
|
|
MIDL_user_allocate( sizeof(SCARD_IO_REQUEST) +
|
|
TransmitCall.pioRecvPci->cbExtraBytes);
|
|
if (pRecvPci != NULL)
|
|
{
|
|
pRecvPci->dwProtocol = TransmitCall.pioRecvPci->dwProtocol;
|
|
pRecvPci->cbPciLength = sizeof(SCARD_IO_REQUEST) +
|
|
TransmitCall.pioRecvPci->cbExtraBytes;
|
|
if (TransmitCall.ioSendPci.cbExtraBytes != 0)
|
|
{
|
|
memcpy(
|
|
((LPBYTE) pRecvPci) + sizeof(SCARD_IO_REQUEST),
|
|
TransmitCall.pioRecvPci->pbExtraBytes,
|
|
TransmitCall.pioRecvPci->cbExtraBytes);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TRC_ERR((TB, _T("MIDL_user_allocate failed")));
|
|
TransmitReturn.ReturnCode = SCARD_E_NO_MEMORY;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Allocate if not in SCARD_AUTOALLOCATE mode and not a size only call
|
|
//
|
|
if (TransmitReturn.ReturnCode == SCARD_S_SUCCESS)
|
|
{
|
|
fDoAllocationLocally =
|
|
(!TransmitCall.fpbRecvBufferIsNULL &&
|
|
(cbRecvLength != SCARD_AUTOALLOCATE));
|
|
|
|
#ifdef OS_WINCE
|
|
if (!fDoAllocationLocally)
|
|
{
|
|
TransmitReturn.ReturnCode =
|
|
pfnSCardTransmit(
|
|
SCardHandle,
|
|
pSendPci,
|
|
TransmitCall.pbSendBuffer,
|
|
TransmitCall.cbSendLength,
|
|
pRecvPci,
|
|
NULL,
|
|
&cbRecvLength);
|
|
|
|
if ((TransmitReturn.ReturnCode == SCARD_S_SUCCESS) && (cbRecvLength > 0))
|
|
fDoAllocationLocally = TRUE;
|
|
else
|
|
{
|
|
TRC_ERR((TB, _T("SCardTransmit failed")));
|
|
status = STATUS_UNSUCCESSFUL;
|
|
goto ErrorReturn;
|
|
}
|
|
}
|
|
#endif
|
|
if (fDoAllocationLocally)
|
|
{
|
|
pbRecvBuffer = (LPBYTE) MIDL_user_allocate(cbRecvLength * sizeof(BYTE));
|
|
if (pbRecvBuffer == NULL)
|
|
{
|
|
TRC_ERR((TB, _T("MIDL_user_allocate failed")));
|
|
TransmitReturn.ReturnCode = SCARD_E_NO_MEMORY;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Make the call
|
|
//
|
|
if (TransmitReturn.ReturnCode == SCARD_S_SUCCESS)
|
|
{
|
|
TransmitReturn.ReturnCode =
|
|
pfnSCardTransmit(
|
|
SCardHandle,
|
|
pSendPci,
|
|
TransmitCall.pbSendBuffer,
|
|
TransmitCall.cbSendLength,
|
|
pRecvPci,
|
|
(cbRecvLength == SCARD_AUTOALLOCATE) ?
|
|
(LPBYTE) &pbRecvBuffer : pbRecvBuffer,
|
|
&cbRecvLength);
|
|
}
|
|
|
|
//
|
|
// copy over the output the return struct to be encoded
|
|
//
|
|
if (TransmitReturn.ReturnCode == SCARD_S_SUCCESS)
|
|
{
|
|
if (pRecvPci != NULL)
|
|
{
|
|
//
|
|
// Allocate space for struct plus the extra bytes at the end of it
|
|
// if needed
|
|
//
|
|
pReturnRecvPci = (SCardIO_Request *)
|
|
MIDL_user_allocate(
|
|
sizeof(SCardIO_Request) +
|
|
pRecvPci->cbPciLength);
|
|
|
|
if (pReturnRecvPci != NULL)
|
|
{
|
|
pReturnRecvPci->dwProtocol = pRecvPci->dwProtocol;
|
|
pReturnRecvPci->cbExtraBytes = pRecvPci->cbPciLength -
|
|
sizeof(SCARD_IO_REQUEST);
|
|
if (pReturnRecvPci->cbExtraBytes != 0)
|
|
{
|
|
//
|
|
// put bytes at end of struct since we allocated enough space for it
|
|
//
|
|
memcpy(
|
|
((LPBYTE) pReturnRecvPci) + sizeof(SCardIO_Request),
|
|
((LPBYTE) pRecvPci) + sizeof(SCARD_IO_REQUEST),
|
|
pReturnRecvPci->cbExtraBytes);
|
|
}
|
|
|
|
TransmitReturn.pioRecvPci = pReturnRecvPci;
|
|
}
|
|
else
|
|
{
|
|
TRC_ERR((TB, _T("MIDL_user_allocate failed")));
|
|
TransmitReturn.ReturnCode = SCARD_E_NO_MEMORY;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TransmitReturn.pioRecvPci = NULL;
|
|
}
|
|
|
|
TransmitReturn.cbRecvLength = cbRecvLength;
|
|
TransmitReturn.pbRecvBuffer = pbRecvBuffer;
|
|
}
|
|
|
|
if (TransmitReturn.ReturnCode == SCARD_S_SUCCESS)
|
|
{
|
|
//
|
|
// If we are just returning the byte count then send back a junk buffer
|
|
//
|
|
if (TransmitReturn.pbRecvBuffer == NULL)
|
|
{
|
|
TransmitReturn.pbRecvBuffer = (BYTE *) MIDL_user_allocate(TransmitReturn.cbRecvLength);
|
|
if (TransmitReturn.pbRecvBuffer == NULL)
|
|
{
|
|
status = STATUS_NO_MEMORY;
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
fFree = TRUE;
|
|
memset(TransmitReturn.pbRecvBuffer, 0, TransmitReturn.cbRecvLength);
|
|
}
|
|
}
|
|
|
|
//
|
|
// encode the return
|
|
//
|
|
rpcStatus = MesEncodeDynBufferHandleCreate(
|
|
&pbEncodedBuffer,
|
|
&cbEncodedBuffer,
|
|
&hEnc);
|
|
if (rpcStatus != RPC_S_OK)
|
|
{
|
|
TRC_ERR((TB, _T("MesEncodeDynBufferHandleCreate failed with %lx."), rpcStatus));
|
|
status = STATUS_NO_MEMORY;
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
_TRY_status(Transmit_Return_Encode(hEnc, &TransmitReturn))
|
|
|
|
//
|
|
// Send return
|
|
//
|
|
AllocateAndChannelWriteReplyPacket(
|
|
pIoRequestPacket,
|
|
pbEncodedBuffer,
|
|
cbEncodedBuffer);
|
|
|
|
Return:
|
|
|
|
if (fFree)
|
|
{
|
|
MIDL_user_free(TransmitReturn.pbRecvBuffer);
|
|
}
|
|
|
|
MIDL_user_free(pSendPci);
|
|
MIDL_user_free(pRecvPci);
|
|
MIDL_user_free(pReturnRecvPci);
|
|
|
|
if (pbRecvBuffer != NULL)
|
|
{
|
|
//
|
|
// Check to see whether we allocated or SCard allcated for us
|
|
//
|
|
if (fDoAllocationLocally)
|
|
{
|
|
MIDL_user_free(pbRecvBuffer);
|
|
}
|
|
else
|
|
{
|
|
#ifndef OS_WINCE
|
|
pfnSCardFreeMemory(SCardContext, pbRecvBuffer);
|
|
#else
|
|
TRC_ASSERT(FALSE, (TB, _T("Shouldnt get here")));
|
|
#endif
|
|
}
|
|
}
|
|
|
|
if (fFreeDecode)
|
|
{
|
|
_TRY_2(Transmit_Call_Free(hDec, &TransmitCall))
|
|
}
|
|
SafeMesHandleFree(&hDec);
|
|
|
|
SafeMesHandleFree(&hEnc);
|
|
|
|
MIDL_user_free(pbEncodedBuffer);
|
|
|
|
MIDL_user_free(pSCardHandleCall);
|
|
|
|
DC_END_FN();
|
|
|
|
return;
|
|
|
|
ErrorReturn:
|
|
|
|
DefaultIORequestMsgHandleWrapper(pIoRequestPacket, status);
|
|
|
|
goto Return;
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------------------
|
|
//
|
|
// W32SCard::Control
|
|
//
|
|
//---------------------------------------------------------------------------------------
|
|
void
|
|
W32SCard::Control(
|
|
IN SCARDHANDLECALLSTRUCT *pSCardHandleCall)
|
|
{
|
|
DC_BEGIN_FN("W32SCard::Control");
|
|
|
|
RPC_STATUS rpcStatus = RPC_S_OK;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
char *pbEncodedBuffer = NULL;
|
|
unsigned long cbEncodedBuffer = 0;
|
|
handle_t hDec = 0;
|
|
handle_t hEnc = 0;
|
|
SCARDCONTEXT SCardContext;
|
|
SCARDHANDLE SCardHandle;
|
|
Control_Call ControlCall;
|
|
Control_Return ControlReturn;
|
|
BOOL fFreeDecode = FALSE;
|
|
BOOL fDoAllocationLocally = FALSE;
|
|
DWORD cbBytesReturned = 0;
|
|
LPVOID lpOutBuffer = NULL;
|
|
BOOL fFree = FALSE;
|
|
PRDPDR_IOREQUEST_PACKET pIoRequestPacket = pSCardHandleCall->pIoRequestPacket;
|
|
PRDPDR_DEVICE_IOREQUEST pIoRequest = &(pIoRequestPacket->IoRequest);
|
|
|
|
memset(&ControlReturn, 0, sizeof(ControlReturn));
|
|
ControlReturn.ReturnCode = SCARD_S_SUCCESS;
|
|
|
|
//
|
|
// Decode input parameters
|
|
//
|
|
rpcStatus = MesDecodeBufferHandleCreate(
|
|
(char *) (pIoRequest + 1), // bytes are at end of struct
|
|
pIoRequest->Parameters.DeviceIoControl.InputBufferLength,
|
|
&hDec);
|
|
if (rpcStatus != RPC_S_OK)
|
|
{
|
|
TRC_ERR((TB, _T("MesDecodeBufferHandleCreate failed with %lx."), rpcStatus));
|
|
status = STATUS_NO_MEMORY;
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
//
|
|
// Decode input params
|
|
//
|
|
memset(&ControlCall, 0, sizeof(ControlCall));
|
|
_TRY_status(Control_Call_Decode(hDec, &ControlCall))
|
|
fFreeDecode = TRUE;
|
|
|
|
if (sizeof(SCARDHANDLE) == ControlCall.hCard.cbHandle)
|
|
{
|
|
SCardContext = *((SCARDCONTEXT *) ControlCall.hCard.Context.pbContext);
|
|
SCardHandle = *((SCARDHANDLE *) ControlCall.hCard.pbHandle);
|
|
cbBytesReturned = ControlCall.cbOutBufferSize;
|
|
}
|
|
else
|
|
{
|
|
TRC_ERR((TB, _T("Invalid handle sent from server.")));
|
|
ControlReturn.ReturnCode = SCARD_E_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// Allocate if not in SCARD_AUTOALLOCATE mode and not a size only call
|
|
//
|
|
if (ControlReturn.ReturnCode == SCARD_S_SUCCESS)
|
|
{
|
|
fDoAllocationLocally =
|
|
(!ControlCall.fpvOutBufferIsNULL &&
|
|
(cbBytesReturned != SCARD_AUTOALLOCATE));
|
|
|
|
#ifdef OS_WINCE
|
|
if (!fDoAllocationLocally)
|
|
{
|
|
ControlReturn.ReturnCode =
|
|
pfnSCardControl(
|
|
SCardHandle,
|
|
ControlCall.dwControlCode,
|
|
ControlCall.pvInBuffer,
|
|
ControlCall.cbInBufferSize,
|
|
NULL,
|
|
cbBytesReturned,
|
|
&cbBytesReturned);
|
|
|
|
if ((ControlReturn.ReturnCode == SCARD_S_SUCCESS) && (cbBytesReturned > 0))
|
|
fDoAllocationLocally = TRUE;
|
|
else
|
|
{
|
|
TRC_ERR((TB, _T("SCardControl failed")));
|
|
status = STATUS_UNSUCCESSFUL;
|
|
goto ErrorReturn;
|
|
}
|
|
}
|
|
#endif
|
|
if (fDoAllocationLocally)
|
|
{
|
|
lpOutBuffer = (LPVOID) MIDL_user_allocate(cbBytesReturned * sizeof(BYTE));
|
|
if (lpOutBuffer == NULL)
|
|
{
|
|
TRC_ERR((TB, _T("MIDL_user_allocate failed")));
|
|
ControlReturn.ReturnCode = SCARD_E_NO_MEMORY;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Make the call
|
|
//
|
|
if (ControlReturn.ReturnCode == SCARD_S_SUCCESS)
|
|
{
|
|
ControlReturn.ReturnCode =
|
|
pfnSCardControl(
|
|
SCardHandle,
|
|
ControlCall.dwControlCode,
|
|
ControlCall.pvInBuffer,
|
|
ControlCall.cbInBufferSize,
|
|
(cbBytesReturned == SCARD_AUTOALLOCATE) ? (LPVOID) &lpOutBuffer : lpOutBuffer,
|
|
cbBytesReturned,
|
|
&cbBytesReturned);
|
|
}
|
|
|
|
if (ControlReturn.ReturnCode == SCARD_S_SUCCESS)
|
|
{
|
|
ControlReturn.cbOutBufferSize = cbBytesReturned;
|
|
|
|
//
|
|
// If we are just returning the byte count then send back a junk buffer
|
|
//
|
|
if (lpOutBuffer == NULL)
|
|
{
|
|
ControlReturn.pvOutBuffer = (BYTE *) MIDL_user_allocate(cbBytesReturned);
|
|
if (ControlReturn.pvOutBuffer == NULL)
|
|
{
|
|
status = STATUS_NO_MEMORY;
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
fFree = TRUE;
|
|
memset(ControlReturn.pvOutBuffer, 0, cbBytesReturned);
|
|
}
|
|
else
|
|
{
|
|
ControlReturn.pvOutBuffer = (LPBYTE) lpOutBuffer;
|
|
}
|
|
}
|
|
|
|
//
|
|
// encode the return
|
|
//
|
|
rpcStatus = MesEncodeDynBufferHandleCreate(
|
|
&pbEncodedBuffer,
|
|
&cbEncodedBuffer,
|
|
&hEnc);
|
|
if (rpcStatus != RPC_S_OK)
|
|
{
|
|
TRC_ERR((TB, _T("MesEncodeDynBufferHandleCreate failed with %lx."), rpcStatus));
|
|
status = STATUS_NO_MEMORY;
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
_TRY_status(Control_Return_Encode(hEnc, &ControlReturn))
|
|
|
|
//
|
|
// Send return
|
|
//
|
|
AllocateAndChannelWriteReplyPacket(
|
|
pIoRequestPacket,
|
|
pbEncodedBuffer,
|
|
cbEncodedBuffer);
|
|
|
|
Return:
|
|
|
|
if (fFree)
|
|
{
|
|
MIDL_user_free(ControlReturn.pvOutBuffer);
|
|
}
|
|
|
|
if (lpOutBuffer != NULL)
|
|
{
|
|
//
|
|
// Check to see whether we allocated or SCard allcated for us
|
|
//
|
|
if (fDoAllocationLocally)
|
|
{
|
|
MIDL_user_free(lpOutBuffer);
|
|
}
|
|
else
|
|
{
|
|
#ifndef OS_WINCE
|
|
pfnSCardFreeMemory(SCardContext, lpOutBuffer);
|
|
#else
|
|
TRC_ASSERT(FALSE, (TB, _T("Shouldnt get here")));
|
|
#endif
|
|
}
|
|
}
|
|
|
|
if (fFreeDecode)
|
|
{
|
|
_TRY_2(Control_Call_Free(hDec, &ControlCall))
|
|
}
|
|
SafeMesHandleFree(&hDec);
|
|
|
|
SafeMesHandleFree(&hEnc);
|
|
|
|
MIDL_user_free(pbEncodedBuffer);
|
|
|
|
MIDL_user_free(pSCardHandleCall);
|
|
|
|
DC_END_FN();
|
|
|
|
return;
|
|
|
|
ErrorReturn:
|
|
|
|
DefaultIORequestMsgHandleWrapper(pIoRequestPacket, status);
|
|
|
|
goto Return;
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------------------
|
|
//
|
|
// W32SCard::GetAttrib
|
|
//
|
|
//---------------------------------------------------------------------------------------
|
|
void
|
|
W32SCard::GetAttrib(
|
|
IN SCARDHANDLECALLSTRUCT *pSCardHandleCall)
|
|
{
|
|
DC_BEGIN_FN("W32SCard::GetAttrib");
|
|
|
|
RPC_STATUS rpcStatus = RPC_S_OK;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
char *pbEncodedBuffer = NULL;
|
|
unsigned long cbEncodedBuffer = 0;
|
|
handle_t hDec = 0;
|
|
handle_t hEnc = 0;
|
|
SCARDCONTEXT SCardContext;
|
|
SCARDHANDLE SCardHandle;
|
|
GetAttrib_Call GetAttribCall;
|
|
GetAttrib_Return GetAttribReturn;
|
|
BOOL fFreeDecode = FALSE;
|
|
DWORD cbAttrLen = 0;
|
|
BOOL fDoAllocationLocally = FALSE;
|
|
LPBYTE pbAttr = NULL;
|
|
BOOL fFree = FALSE;
|
|
PRDPDR_IOREQUEST_PACKET pIoRequestPacket = pSCardHandleCall->pIoRequestPacket;
|
|
PRDPDR_DEVICE_IOREQUEST pIoRequest = &(pIoRequestPacket->IoRequest);
|
|
|
|
memset(&GetAttribReturn, 0, sizeof(GetAttribReturn));
|
|
GetAttribReturn.ReturnCode = SCARD_S_SUCCESS;
|
|
|
|
//
|
|
// Decode input parameters
|
|
//
|
|
rpcStatus = MesDecodeBufferHandleCreate(
|
|
(char *) (pIoRequest + 1), // bytes are at end of struct
|
|
pIoRequest->Parameters.DeviceIoControl.InputBufferLength,
|
|
&hDec);
|
|
if (rpcStatus != RPC_S_OK)
|
|
{
|
|
TRC_ERR((TB, _T("MesDecodeBufferHandleCreate failed with %lx."), rpcStatus));
|
|
status = STATUS_NO_MEMORY;
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
memset(&GetAttribCall, 0, sizeof(GetAttribCall));
|
|
_TRY_status(GetAttrib_Call_Decode(hDec, &GetAttribCall))
|
|
fFreeDecode = TRUE;
|
|
|
|
if (sizeof(SCARDHANDLE) == GetAttribCall.hCard.cbHandle)
|
|
{
|
|
SCardContext = *((SCARDCONTEXT *) GetAttribCall.hCard.Context.pbContext);
|
|
SCardHandle = *((SCARDHANDLE *) GetAttribCall.hCard.pbHandle);
|
|
cbAttrLen = GetAttribCall.cbAttrLen;
|
|
}
|
|
else
|
|
{
|
|
TRC_ERR((TB, _T("Invalid handle sent from server.")));
|
|
GetAttribReturn.ReturnCode = SCARD_E_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (GetAttribReturn.ReturnCode == SCARD_S_SUCCESS)
|
|
{
|
|
//
|
|
// Allocate if not in SCARD_AUTOALLOCATE mode and not a size only call
|
|
//
|
|
fDoAllocationLocally =
|
|
(!GetAttribCall.fpbAttrIsNULL &&
|
|
(cbAttrLen != SCARD_AUTOALLOCATE));
|
|
|
|
#ifdef OS_WINCE
|
|
if (!fDoAllocationLocally)
|
|
{
|
|
GetAttribReturn.ReturnCode =
|
|
pfnSCardGetAttrib(
|
|
SCardHandle,
|
|
GetAttribCall.dwAttrId,
|
|
NULL,
|
|
&cbAttrLen);
|
|
|
|
if ((GetAttribReturn.ReturnCode == SCARD_S_SUCCESS) && (cbAttrLen > 0))
|
|
fDoAllocationLocally = TRUE;
|
|
else
|
|
{
|
|
TRC_ERR((TB, _T("SCardGetAttrib failed")));
|
|
status = STATUS_UNSUCCESSFUL;
|
|
goto ErrorReturn;
|
|
}
|
|
}
|
|
#endif
|
|
if (fDoAllocationLocally)
|
|
{
|
|
pbAttr = (LPBYTE) MIDL_user_allocate(cbAttrLen);
|
|
if (pbAttr == NULL)
|
|
{
|
|
TRC_ERR((TB, _T("MIDL_user_allocate failed")));
|
|
GetAttribReturn.ReturnCode = SCARD_E_NO_MEMORY;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Make the call
|
|
//
|
|
if (GetAttribReturn.ReturnCode == SCARD_S_SUCCESS)
|
|
{
|
|
GetAttribReturn.ReturnCode =
|
|
pfnSCardGetAttrib(
|
|
SCardHandle,
|
|
GetAttribCall.dwAttrId,
|
|
(cbAttrLen == SCARD_AUTOALLOCATE) ? (LPBYTE) &pbAttr : pbAttr,
|
|
&cbAttrLen);
|
|
|
|
if (GetAttribReturn.ReturnCode == SCARD_S_SUCCESS)
|
|
{
|
|
GetAttribReturn.cbAttrLen = cbAttrLen;
|
|
|
|
//
|
|
// If we are just returning the byte count then send back a junk buffer
|
|
//
|
|
if (pbAttr == NULL)
|
|
{
|
|
GetAttribReturn.pbAttr = (BYTE *) MIDL_user_allocate(cbAttrLen);
|
|
if (GetAttribReturn.pbAttr == NULL)
|
|
{
|
|
status = STATUS_NO_MEMORY;
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
fFree = TRUE;
|
|
memset(GetAttribReturn.pbAttr, 0, cbAttrLen);
|
|
}
|
|
else
|
|
{
|
|
GetAttribReturn.pbAttr = pbAttr;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// encode the return
|
|
//
|
|
rpcStatus = MesEncodeDynBufferHandleCreate(
|
|
&pbEncodedBuffer,
|
|
&cbEncodedBuffer,
|
|
&hEnc);
|
|
if (rpcStatus != RPC_S_OK)
|
|
{
|
|
TRC_ERR((TB, _T("MesEncodeDynBufferHandleCreate failed with %lx."), rpcStatus));
|
|
status = STATUS_NO_MEMORY;
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
_TRY_status(GetAttrib_Return_Encode(hEnc, &GetAttribReturn))
|
|
|
|
//
|
|
// Send return
|
|
//
|
|
AllocateAndChannelWriteReplyPacket(
|
|
pIoRequestPacket,
|
|
pbEncodedBuffer,
|
|
cbEncodedBuffer);
|
|
|
|
Return:
|
|
|
|
if (fFree)
|
|
{
|
|
MIDL_user_free(GetAttribReturn.pbAttr);
|
|
}
|
|
|
|
if (pbAttr != NULL)
|
|
{
|
|
//
|
|
// Check to see whether we allocated or SCard allcated for us
|
|
//
|
|
if (fDoAllocationLocally)
|
|
{
|
|
MIDL_user_free(pbAttr);
|
|
}
|
|
else
|
|
{
|
|
#ifndef OS_WINCE
|
|
pfnSCardFreeMemory(SCardContext, pbAttr);
|
|
#else
|
|
TRC_ASSERT(FALSE, (TB, _T("Shouldnt get here")));
|
|
#endif
|
|
}
|
|
}
|
|
|
|
if (fFreeDecode)
|
|
{
|
|
_TRY_2(GetAttrib_Call_Free(hDec, &GetAttribCall))
|
|
}
|
|
SafeMesHandleFree(&hDec);
|
|
|
|
SafeMesHandleFree(&hEnc);
|
|
|
|
MIDL_user_free(pbEncodedBuffer);
|
|
|
|
MIDL_user_free(pSCardHandleCall);
|
|
|
|
DC_END_FN();
|
|
|
|
return;
|
|
|
|
ErrorReturn:
|
|
|
|
DefaultIORequestMsgHandleWrapper(pIoRequestPacket, status);
|
|
|
|
goto Return;
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------------------
|
|
//
|
|
// W32SCard::SetAttrib
|
|
//
|
|
//---------------------------------------------------------------------------------------
|
|
void
|
|
W32SCard::SetAttrib(
|
|
IN SCARDHANDLECALLSTRUCT *pSCardHandleCall)
|
|
{
|
|
DC_BEGIN_FN("W32SCard::SetAttrib");
|
|
|
|
LONG lReturn = SCARD_S_SUCCESS;
|
|
RPC_STATUS rpcStatus = RPC_S_OK;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
handle_t hDec = 0;
|
|
SCARDCONTEXT SCardContext;
|
|
SCARDHANDLE SCardHandle;
|
|
SetAttrib_Call SetAttribCall;
|
|
BOOL fFreeDecode = FALSE;
|
|
PRDPDR_IOREQUEST_PACKET pIoRequestPacket = pSCardHandleCall->pIoRequestPacket;
|
|
PRDPDR_DEVICE_IOREQUEST pIoRequest = &(pIoRequestPacket->IoRequest);
|
|
|
|
//
|
|
// Decode input parameters
|
|
//
|
|
rpcStatus = MesDecodeBufferHandleCreate(
|
|
(char *) (pIoRequest + 1), // bytes are at end of struct
|
|
pIoRequest->Parameters.DeviceIoControl.InputBufferLength,
|
|
&hDec);
|
|
if (rpcStatus != RPC_S_OK)
|
|
{
|
|
TRC_ERR((TB, _T("MesDecodeBufferHandleCreate failed with %lx."), rpcStatus));
|
|
status = STATUS_NO_MEMORY;
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
memset(&SetAttribCall, 0, sizeof(SetAttribCall));
|
|
_TRY_status(SetAttrib_Call_Decode(hDec, &SetAttribCall))
|
|
fFreeDecode = TRUE;
|
|
|
|
if (sizeof(SCARDHANDLE) == SetAttribCall.hCard.cbHandle)
|
|
{
|
|
SCardContext = *((SCARDCONTEXT *) SetAttribCall.hCard.Context.pbContext);
|
|
SCardHandle = *((SCARDHANDLE *) SetAttribCall.hCard.pbHandle);
|
|
}
|
|
else
|
|
{
|
|
TRC_ERR((TB, _T("Invalid handle sent from server.")));
|
|
lReturn = SCARD_E_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// Make the call
|
|
//
|
|
if (lReturn == SCARD_S_SUCCESS)
|
|
{
|
|
lReturn =
|
|
pfnSCardSetAttrib(
|
|
SCardHandle,
|
|
SetAttribCall.dwAttrId,
|
|
SetAttribCall.pbAttr,
|
|
SetAttribCall.cbAttrLen);
|
|
}
|
|
|
|
//
|
|
// Send return
|
|
//
|
|
EncodeAndChannelWriteLongReturn(
|
|
pIoRequestPacket,
|
|
lReturn);
|
|
|
|
Return:
|
|
|
|
if (fFreeDecode)
|
|
{
|
|
_TRY_2(SetAttrib_Call_Free(hDec, &SetAttribCall))
|
|
}
|
|
SafeMesHandleFree(&hDec);
|
|
|
|
MIDL_user_free(pSCardHandleCall);
|
|
|
|
DC_END_FN();
|
|
|
|
return;
|
|
|
|
ErrorReturn:
|
|
|
|
DefaultIORequestMsgHandleWrapper(pIoRequestPacket, status);
|
|
|
|
goto Return;
|
|
}
|
|
|
|
|
|
|
|
#ifndef OS_WINCE
|
|
//---------------------------------------------------------------------------------------
|
|
//
|
|
// W32SCard::AccessStartedEvent + supporting WaitForStartedEvent
|
|
//
|
|
//---------------------------------------------------------------------------------------
|
|
void
|
|
W32SCard::WaitForStartedEvent(
|
|
BOOLEAN TimerOrWaitFired)
|
|
{
|
|
DC_BEGIN_FN("W32SCard::WaitForStartedEvent");
|
|
|
|
LONG lReturn = SCARD_E_UNEXPECTED;
|
|
DWORD i;
|
|
PVOID pv;
|
|
|
|
//
|
|
// If TimerOrWaitFired is FALSE, that means the event was set...
|
|
// otherwise it timed out.
|
|
//
|
|
if (!TimerOrWaitFired)
|
|
{
|
|
lReturn = SCARD_S_SUCCESS;
|
|
}
|
|
|
|
EnterCriticalSection(&_csWaitForStartedEvent);
|
|
|
|
pv = InterlockedExchangePointer(&_hRegisterWaitForStartedEvent, NULL);
|
|
if (pv != NULL)
|
|
{
|
|
pfnUnregisterWaitEx(pv, NULL);
|
|
}
|
|
|
|
//
|
|
// Loop for each outstanding wait and send return
|
|
//
|
|
for (i=0; i<_dwIORequestListSize; i++)
|
|
{
|
|
if (_rgIORequestList[i] != NULL)
|
|
{
|
|
EncodeAndChannelWriteLongReturn(
|
|
_rgIORequestList[i],
|
|
lReturn);
|
|
|
|
_rgIORequestList[i] = NULL;
|
|
}
|
|
}
|
|
|
|
LeaveCriticalSection(&_csWaitForStartedEvent);
|
|
|
|
Return:
|
|
|
|
DC_END_FN();
|
|
}
|
|
|
|
VOID CALLBACK
|
|
WaitForStartedEventCallback(
|
|
PVOID lpParameter,
|
|
BOOLEAN TimerOrWaitFired)
|
|
{
|
|
W32SCard *pTHIS = (W32SCard *) lpParameter;
|
|
pTHIS->WaitForStartedEvent(TimerOrWaitFired);
|
|
}
|
|
|
|
typedef HANDLE (WINAPI FN_SCARDACCESSSTARTEDEVENT)(VOID);
|
|
typedef FN_SCARDACCESSSTARTEDEVENT *PFN_SCARDACCESSSTARTEDEVENT;
|
|
|
|
void
|
|
W32SCard::GetStartedEvent()
|
|
{
|
|
DC_BEGIN_FN("W32SCard::GetStartedEvent");
|
|
|
|
HMODULE hMod = NULL;
|
|
PFN_SCARDACCESSSTARTEDEVENT pSCardAccessStartedEvent= NULL;
|
|
HANDLE hEvent = NULL;
|
|
|
|
hMod = LoadLibraryA("winscard.dll");
|
|
|
|
if (hMod == NULL)
|
|
{
|
|
goto Return;
|
|
}
|
|
|
|
pSCardAccessStartedEvent = (PFN_SCARDACCESSSTARTEDEVENT)
|
|
GetProcAddress(hMod, "SCardAccessStartedEvent");
|
|
|
|
if (pSCardAccessStartedEvent != NULL)
|
|
{
|
|
_hStartedEvent = pSCardAccessStartedEvent();
|
|
}
|
|
else
|
|
{
|
|
TRC_ERR(( TB,
|
|
_T("GetProcAddress(SCardAccessStartedEvent) failed - LastError: %lx."),
|
|
GetLastError()));
|
|
}
|
|
|
|
FreeLibrary(hMod);
|
|
|
|
Return:
|
|
|
|
DC_END_FN();
|
|
}
|
|
|
|
typedef VOID (WINAPI FN_SCARDRELEASESTARTEDEVENT)(VOID);
|
|
typedef FN_SCARDRELEASESTARTEDEVENT *PFN_SCARDRELEASESTARTEDEVENT;
|
|
|
|
void
|
|
W32SCard::ReleaseStartedEvent()
|
|
{
|
|
DC_BEGIN_FN("W32SCard::ReleaseStartedEvent");
|
|
|
|
HMODULE hMod = NULL;
|
|
PFN_SCARDRELEASESTARTEDEVENT pSCardReleaseStartedEvent = NULL;
|
|
|
|
hMod = LoadLibraryA("winscard.dll");
|
|
|
|
if (hMod == NULL)
|
|
{
|
|
goto Return;
|
|
}
|
|
|
|
pSCardReleaseStartedEvent = (PFN_SCARDRELEASESTARTEDEVENT)
|
|
GetProcAddress(hMod, "SCardReleaseStartedEvent");
|
|
|
|
if (pSCardReleaseStartedEvent != NULL)
|
|
{
|
|
pSCardReleaseStartedEvent();
|
|
}
|
|
else
|
|
{
|
|
TRC_ERR(( TB,
|
|
_T("GetProcAddress(SCardReleaseStartedEvent) failed - LastError: %lx."),
|
|
GetLastError()));
|
|
}
|
|
|
|
FreeLibrary(hMod);
|
|
|
|
Return:
|
|
|
|
DC_END_FN();
|
|
}
|
|
#endif
|
|
|
|
|
|
void
|
|
W32SCard::AccessStartedEvent(
|
|
IN PRDPDR_IOREQUEST_PACKET pIoRequestPacket)
|
|
{
|
|
DC_BEGIN_FN("W32SCard::AccessStartedEvent");
|
|
|
|
LONG lReturn = SCARD_S_SUCCESS;
|
|
|
|
//
|
|
// Make sure only one thread registers at a time
|
|
//
|
|
EnterCriticalSection(&_csWaitForStartedEvent);
|
|
|
|
#ifndef OS_WINCE
|
|
|
|
//
|
|
// First, make sure we can get the started event
|
|
//
|
|
if (_hStartedEvent == NULL)
|
|
{
|
|
GetStartedEvent();
|
|
}
|
|
|
|
if (_hStartedEvent == NULL)
|
|
{
|
|
//
|
|
// Couldn't even get the event, so return error
|
|
//
|
|
lReturn = SCARD_E_NO_SERVICE;
|
|
goto ImmediateReturn;
|
|
}
|
|
|
|
//
|
|
// Now, check to see if the event is already signaled, if so,
|
|
// then just return success, otherwise, register a wait callback
|
|
// on the event so we don't block this thread
|
|
//
|
|
if (WaitForSingleObject(_hStartedEvent, 0) == WAIT_OBJECT_0)
|
|
{
|
|
//
|
|
// It is signaled, so return success
|
|
//
|
|
lReturn = SCARD_S_SUCCESS;
|
|
goto ImmediateReturn;
|
|
}
|
|
|
|
//
|
|
// If the object is currently being destroyed, then don't create a new thread.
|
|
//
|
|
if (_fInDestructor)
|
|
{
|
|
goto ImmediateReturn;
|
|
}
|
|
|
|
//
|
|
// Only allow one wait to be registered. The single wait callback will
|
|
// notify all waiting requests
|
|
//
|
|
if ((_hRegisterWaitForStartedEvent == NULL) && _fUseRegisterWaitFuncs)
|
|
{
|
|
if (!pfnRegisterWaitForSingleObject(
|
|
&_hRegisterWaitForStartedEvent,
|
|
_hStartedEvent,
|
|
WaitForStartedEventCallback,
|
|
this,
|
|
INFINITE,
|
|
WT_EXECUTEONLYONCE))
|
|
{
|
|
lReturn = SCARD_E_NO_SERVICE;
|
|
goto ImmediateReturn;
|
|
}
|
|
}
|
|
else if (!_fUseRegisterWaitFuncs)
|
|
{
|
|
lReturn = SCARD_E_UNEXPECTED;
|
|
goto ImmediateReturn;
|
|
}
|
|
#else
|
|
lReturn = SCARD_S_SUCCESS;
|
|
goto ImmediateReturn;
|
|
#endif
|
|
|
|
//
|
|
// Add this pIoRequestPacket to the list
|
|
//
|
|
if (!AddIORequestToList(pIoRequestPacket))
|
|
{
|
|
lReturn = SCARD_E_UNEXPECTED;
|
|
goto ImmediateReturn;
|
|
}
|
|
|
|
//
|
|
// return here and let the wait we just registered
|
|
// make the EncodeAndChannelWriteLongReturn call,
|
|
// which will send the return the calling server
|
|
//
|
|
Return:
|
|
|
|
LeaveCriticalSection(&_csWaitForStartedEvent);
|
|
|
|
DC_END_FN();
|
|
return;
|
|
|
|
ImmediateReturn:
|
|
|
|
EncodeAndChannelWriteLongReturn(
|
|
pIoRequestPacket,
|
|
lReturn);
|
|
|
|
goto Return;
|
|
}
|
|
|
|
|
|
HANDLE
|
|
W32SCard::StartFSFunc(
|
|
IN W32DRDEV_ASYNCIO_PARAMS *params,
|
|
OUT DWORD *status
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Start a generic asynchronous File System IO operation.
|
|
|
|
Arguments:
|
|
|
|
params - Context for the IO request.
|
|
status - Return status for IO request in the form of a windows
|
|
error code.
|
|
|
|
Return Value:
|
|
|
|
Returns a handle to an object that will be signalled when the read
|
|
completes, if it is not completed in this function. Otherwise, NULL
|
|
is returned.
|
|
|
|
--*/
|
|
{
|
|
#ifndef OS_WINCE
|
|
PRDPDR_DEVICE_IOREQUEST pIoRequest;
|
|
DrFile* pFile;
|
|
ULONG irpMajor;
|
|
#endif
|
|
|
|
DC_BEGIN_FN("W32SCard::StartFSFunc");
|
|
|
|
*status = ERROR_SUCCESS;
|
|
|
|
DC_END_FN();
|
|
return NULL;
|
|
}
|
|
|
|
|
|
DWORD
|
|
W32SCard::AsyncNotifyChangeDir(
|
|
IN W32DRDEV_ASYNCIO_PARAMS *params
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Directory change notification Function
|
|
|
|
Arguments:
|
|
|
|
params - Context for the IO request.
|
|
|
|
Return Value:
|
|
|
|
Always returns 0.
|
|
|
|
--*/
|
|
{
|
|
DC_BEGIN_FN("W32SCard::AsyncNotifyChangeDir");
|
|
|
|
|
|
DC_END_FN();
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
|
|
DWORD
|
|
W32SCard::AsyncDirCtrlFunc(
|
|
IN W32DRDEV_ASYNCIO_PARAMS *params
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Asynchrous Directory Control Function
|
|
|
|
Arguments:
|
|
|
|
params - Context for the IO request.
|
|
|
|
Return Value:
|
|
|
|
Always returns 0.
|
|
|
|
--*/
|
|
{
|
|
DC_BEGIN_FN("W32SCard::AsyncDirCtrlFunc");
|
|
|
|
DC_END_FN();
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
|
|
BOOL
|
|
W32SCard::BindToSCardFunctions()
|
|
{
|
|
#ifndef OS_WINCE
|
|
int i;
|
|
#endif
|
|
BOOL fRet = TRUE;
|
|
|
|
//
|
|
// Load winscard dll if it exists
|
|
//
|
|
_hModWinscard = LoadLibraryA("winscard.dll");
|
|
if (_hModWinscard != NULL)
|
|
{
|
|
//
|
|
// get the function pointers
|
|
//
|
|
#ifndef OS_WINCE
|
|
pfnSCardEstablishContext = (PFN_SCardEstablishContext) GetProcAddress(_hModWinscard, "SCardEstablishContext");
|
|
pfnSCardReleaseContext = (PFN_SCardReleaseContext) GetProcAddress(_hModWinscard, "SCardReleaseContext");
|
|
pfnSCardIsValidContext = (PFN_SCardIsValidContext) GetProcAddress(_hModWinscard, "SCardIsValidContext");
|
|
pfnSCardListReaderGroupsA = (PFN_SCardListReaderGroupsA) GetProcAddress(_hModWinscard, "SCardListReaderGroupsA");
|
|
pfnSCardListReaderGroupsW = (PFN_SCardListReaderGroupsW) GetProcAddress(_hModWinscard, "SCardListReaderGroupsW");
|
|
pfnSCardListReadersA = (PFN_SCardListReadersA) GetProcAddress(_hModWinscard, "SCardListReadersA");
|
|
pfnSCardListReadersW = (PFN_SCardListReadersW) GetProcAddress(_hModWinscard, "SCardListReadersW");
|
|
pfnSCardIntroduceReaderGroupA = (PFN_SCardIntroduceReaderGroupA) GetProcAddress(_hModWinscard, "SCardIntroduceReaderGroupA");
|
|
pfnSCardIntroduceReaderGroupW = (PFN_SCardIntroduceReaderGroupW) GetProcAddress(_hModWinscard, "SCardIntroduceReaderGroupW");
|
|
pfnSCardForgetReaderGroupA = (PFN_SCardForgetReaderGroupA) GetProcAddress(_hModWinscard, "SCardForgetReaderGroupA");
|
|
pfnSCardForgetReaderGroupW = (PFN_SCardForgetReaderGroupW) GetProcAddress(_hModWinscard, "SCardForgetReaderGroupW");
|
|
pfnSCardIntroduceReaderA = (PFN_SCardIntroduceReaderA) GetProcAddress(_hModWinscard, "SCardIntroduceReaderA");
|
|
pfnSCardIntroduceReaderW = (PFN_SCardIntroduceReaderW) GetProcAddress(_hModWinscard, "SCardIntroduceReaderW");
|
|
pfnSCardForgetReaderA = (PFN_SCardForgetReaderA) GetProcAddress(_hModWinscard, "SCardForgetReaderA");
|
|
pfnSCardForgetReaderW = (PFN_SCardForgetReaderW) GetProcAddress(_hModWinscard, "SCardForgetReaderW");
|
|
pfnSCardAddReaderToGroupA = (PFN_SCardAddReaderToGroupA) GetProcAddress(_hModWinscard, "SCardAddReaderToGroupA");
|
|
pfnSCardAddReaderToGroupW = (PFN_SCardAddReaderToGroupW) GetProcAddress(_hModWinscard, "SCardAddReaderToGroupW");
|
|
pfnSCardRemoveReaderFromGroupA = (PFN_SCardRemoveReaderFromGroupA) GetProcAddress(_hModWinscard, "SCardRemoveReaderFromGroupA");
|
|
pfnSCardRemoveReaderFromGroupW = (PFN_SCardRemoveReaderFromGroupW) GetProcAddress(_hModWinscard, "SCardRemoveReaderFromGroupW");
|
|
pfnSCardFreeMemory = (PFN_SCardFreeMemory) GetProcAddress(_hModWinscard, "SCardFreeMemory");
|
|
pfnSCardLocateCardsA = (PFN_SCardLocateCardsA) GetProcAddress(_hModWinscard, "SCardLocateCardsA");
|
|
pfnSCardLocateCardsW = (PFN_SCardLocateCardsW) GetProcAddress(_hModWinscard, "SCardLocateCardsW");
|
|
pfnSCardLocateCardsByATRA = (PFN_SCardLocateCardsByATRA) GetProcAddress(_hModWinscard, "SCardLocateCardsByATRA");
|
|
pfnSCardLocateCardsByATRW = (PFN_SCardLocateCardsByATRW) GetProcAddress(_hModWinscard, "SCardLocateCardsByATRW");
|
|
pfnSCardGetStatusChangeA = (PFN_SCardGetStatusChangeA) GetProcAddress(_hModWinscard, "SCardGetStatusChangeA");
|
|
pfnSCardGetStatusChangeW = (PFN_SCardGetStatusChangeW) GetProcAddress(_hModWinscard, "SCardGetStatusChangeW");
|
|
pfnSCardCancel = (PFN_SCardCancel) GetProcAddress(_hModWinscard, "SCardCancel");
|
|
pfnSCardConnectA = (PFN_SCardConnectA) GetProcAddress(_hModWinscard, "SCardConnectA");
|
|
pfnSCardConnectW = (PFN_SCardConnectW) GetProcAddress(_hModWinscard, "SCardConnectW");
|
|
pfnSCardReconnect = (PFN_SCardReconnect) GetProcAddress(_hModWinscard, "SCardReconnect");
|
|
pfnSCardDisconnect = (PFN_SCardDisconnect) GetProcAddress(_hModWinscard, "SCardDisconnect");
|
|
pfnSCardBeginTransaction = (PFN_SCardBeginTransaction) GetProcAddress(_hModWinscard, "SCardBeginTransaction");
|
|
pfnSCardEndTransaction = (PFN_SCardEndTransaction) GetProcAddress(_hModWinscard, "SCardEndTransaction");
|
|
pfnSCardState = (PFN_SCardState) GetProcAddress(_hModWinscard, "SCardState");
|
|
pfnSCardStatusA = (PFN_SCardStatusA) GetProcAddress(_hModWinscard, "SCardStatusA");
|
|
pfnSCardStatusW = (PFN_SCardStatusW) GetProcAddress(_hModWinscard, "SCardStatusW");
|
|
pfnSCardTransmit = (PFN_SCardTransmit) GetProcAddress(_hModWinscard, "SCardTransmit");
|
|
pfnSCardControl = (PFN_SCardControl) GetProcAddress(_hModWinscard, "SCardControl");
|
|
pfnSCardGetAttrib = (PFN_SCardGetAttrib) GetProcAddress(_hModWinscard, "SCardGetAttrib");
|
|
pfnSCardSetAttrib = (PFN_SCardSetAttrib) GetProcAddress(_hModWinscard, "SCardSetAttrib");
|
|
|
|
#else
|
|
pfnSCardListReadersA = SCardListReadersA;
|
|
pfnSCardLocateCardsA = SCardLocateCardsA;
|
|
pfnSCardLocateCardsByATRA = SCardLocateCardsByATRA;
|
|
pfnSCardGetStatusChangeA = SCardGetStatusChangeA;
|
|
pfnSCardConnectA = SCardConnectA;
|
|
pfnSCardStatusA = SCardStatusA;
|
|
pfnSCardIntroduceReaderA = SCardIntroduceReaderA;
|
|
pfnSCardForgetReaderA = SCardForgetReaderA;
|
|
|
|
pfnSCardListReaderGroupsA = SCardListReaderGroupsA;
|
|
pfnSCardListReaderGroupsW = SCardListReaderGroupsW;
|
|
pfnSCardIntroduceReaderGroupA = SCardIntroduceReaderGroupA;
|
|
pfnSCardIntroduceReaderGroupW = SCardIntroduceReaderGroupW;
|
|
pfnSCardForgetReaderGroupA = SCardForgetReaderGroupA;
|
|
pfnSCardForgetReaderGroupW = SCardForgetReaderGroupW;
|
|
pfnSCardAddReaderToGroupA = SCardAddReaderToGroupA;
|
|
pfnSCardAddReaderToGroupW = SCardAddReaderToGroupW;
|
|
pfnSCardRemoveReaderFromGroupA = SCardRemoveReaderFromGroupA;
|
|
pfnSCardRemoveReaderFromGroupW = SCardRemoveReaderFromGroupW;
|
|
|
|
pfnSCardConnectW = CESCardConnect;
|
|
pfnSCardReconnect = CESCardReconnect;
|
|
pfnSCardDisconnect = CESCardDisconnect;
|
|
pfnSCardBeginTransaction = CESCardBeginTransaction;
|
|
pfnSCardEndTransaction = CESCardEndTransaction;
|
|
pfnSCardTransmit = CESCardTransmit;
|
|
pfnSCardStatusW = CESCardStatus;
|
|
pfnSCardControl = CESCardControl;
|
|
pfnSCardGetAttrib = CESCardGetAttrib;
|
|
pfnSCardSetAttrib = CESCardSetAttrib;
|
|
|
|
gpfnSCardConnectW = (PFN_SCardConnectW) GetProcAddress(_hModWinscard, L"SCardConnectW");
|
|
gpfnSCardReconnect = (PFN_SCardReconnect) GetProcAddress(_hModWinscard, L"SCardReconnect");
|
|
gpfnSCardDisconnect = (PFN_SCardDisconnect) GetProcAddress(_hModWinscard, L"SCardDisconnect");
|
|
gpfnSCardBeginTransaction = (PFN_SCardBeginTransaction) GetProcAddress(_hModWinscard, L"SCardBeginTransaction");
|
|
gpfnSCardEndTransaction = (PFN_SCardEndTransaction) GetProcAddress(_hModWinscard, L"SCardEndTransaction");
|
|
gpfnSCardTransmit = (PFN_SCardTransmit) GetProcAddress(_hModWinscard, L"SCardTransmit");
|
|
gpfnSCardStatusW = (PFN_SCardStatusW) GetProcAddress(_hModWinscard, L"SCardStatusW");
|
|
gpfnSCardControl = (PFN_SCardControl) GetProcAddress(_hModWinscard, L"SCardControl");
|
|
gpfnSCardGetAttrib = (PFN_SCardGetAttrib) GetProcAddress(_hModWinscard, L"SCardGetAttrib");
|
|
gpfnSCardSetAttrib = (PFN_SCardSetAttrib) GetProcAddress(_hModWinscard, L"SCardSetAttrib");
|
|
|
|
pfnSCardEstablishContext = (PFN_SCardEstablishContext) GetProcAddress(_hModWinscard, L"SCardEstablishContext");
|
|
pfnSCardReleaseContext = (PFN_SCardReleaseContext) GetProcAddress(_hModWinscard, L"SCardReleaseContext");
|
|
pfnSCardIsValidContext = (PFN_SCardIsValidContext) GetProcAddress(_hModWinscard, L"SCardIsValidContext");
|
|
pfnSCardListReadersW = (PFN_SCardListReadersW) GetProcAddress(_hModWinscard, L"SCardListReadersW");
|
|
pfnSCardIntroduceReaderW = (PFN_SCardIntroduceReaderW) GetProcAddress(_hModWinscard, L"SCardIntroduceReaderW");
|
|
pfnSCardForgetReaderW = (PFN_SCardForgetReaderW) GetProcAddress(_hModWinscard, L"SCardForgetReaderW");
|
|
pfnSCardLocateCardsW = (PFN_SCardLocateCardsW) GetProcAddress(_hModWinscard, L"SCardLocateCardsW");
|
|
pfnSCardLocateCardsByATRW = (PFN_SCardLocateCardsByATRW) GetProcAddress(_hModWinscard, L"SCardLocateCardsByATRW");
|
|
pfnSCardGetStatusChangeW = (PFN_SCardGetStatusChangeW) GetProcAddress(_hModWinscard, L"SCardGetStatusChangeW");
|
|
pfnSCardCancel = (PFN_SCardCancel) GetProcAddress(_hModWinscard, L"SCardCancel");
|
|
|
|
gpfnSCardEstablishContext = pfnSCardEstablishContext;
|
|
gpfnSCardReleaseContext = pfnSCardReleaseContext;
|
|
|
|
gpfnSCardListReadersW = pfnSCardListReadersW;
|
|
gpfnSCardIntroduceReaderW = pfnSCardIntroduceReaderW;
|
|
gpfnSCardForgetReaderW = pfnSCardForgetReaderW;
|
|
gpfnSCardLocateCardsW = pfnSCardLocateCardsW;
|
|
gpfnSCardLocateCardsByATRW = pfnSCardLocateCardsByATRW;
|
|
gpfnSCardGetStatusChangeW = pfnSCardGetStatusChangeW;
|
|
#endif
|
|
|
|
//
|
|
// Note, don't check the pfnSCardLocateCardsByATR* API's since they aren't required.
|
|
//
|
|
|
|
if ((pfnSCardEstablishContext == NULL) ||
|
|
(pfnSCardReleaseContext == NULL) ||
|
|
(pfnSCardIsValidContext == NULL) ||
|
|
#ifndef OS_WINCE
|
|
(pfnSCardFreeMemory == NULL) ||
|
|
(pfnSCardState == NULL) ||
|
|
#endif
|
|
(pfnSCardListReaderGroupsA == NULL) ||
|
|
(pfnSCardListReaderGroupsW == NULL) ||
|
|
(pfnSCardListReadersA == NULL) ||
|
|
(pfnSCardListReadersW == NULL) ||
|
|
(pfnSCardIntroduceReaderGroupA == NULL) ||
|
|
(pfnSCardIntroduceReaderGroupW == NULL) ||
|
|
(pfnSCardForgetReaderGroupA == NULL) ||
|
|
(pfnSCardForgetReaderGroupW == NULL) ||
|
|
(pfnSCardIntroduceReaderA == NULL) ||
|
|
(pfnSCardIntroduceReaderW == NULL) ||
|
|
(pfnSCardForgetReaderA == NULL) ||
|
|
(pfnSCardForgetReaderW == NULL) ||
|
|
(pfnSCardAddReaderToGroupA == NULL) ||
|
|
(pfnSCardAddReaderToGroupW == NULL) ||
|
|
(pfnSCardRemoveReaderFromGroupA == NULL) ||
|
|
(pfnSCardRemoveReaderFromGroupW == NULL) ||
|
|
(pfnSCardLocateCardsA == NULL) ||
|
|
(pfnSCardLocateCardsW == NULL) ||
|
|
(pfnSCardGetStatusChangeA == NULL) ||
|
|
(pfnSCardGetStatusChangeW == NULL) ||
|
|
(pfnSCardCancel == NULL) ||
|
|
(pfnSCardConnectA == NULL) ||
|
|
(pfnSCardStatusA == NULL) ||
|
|
#ifndef OS_WINCE
|
|
(pfnSCardConnectW == NULL) ||
|
|
(pfnSCardReconnect == NULL) ||
|
|
(pfnSCardDisconnect == NULL) ||
|
|
(pfnSCardBeginTransaction == NULL) ||
|
|
(pfnSCardEndTransaction == NULL) ||
|
|
(pfnSCardTransmit == NULL) ||
|
|
(pfnSCardStatusW == NULL) ||
|
|
(pfnSCardControl == NULL) ||
|
|
(pfnSCardGetAttrib == NULL) ||
|
|
(pfnSCardSetAttrib == NULL))
|
|
#else
|
|
(gpfnSCardConnectW == NULL) ||
|
|
(gpfnSCardReconnect == NULL) ||
|
|
(gpfnSCardDisconnect == NULL) ||
|
|
(gpfnSCardBeginTransaction == NULL) ||
|
|
(gpfnSCardEndTransaction == NULL) ||
|
|
(gpfnSCardTransmit == NULL) ||
|
|
(gpfnSCardStatusW == NULL) ||
|
|
(gpfnSCardControl == NULL) ||
|
|
(gpfnSCardGetAttrib == NULL) ||
|
|
(gpfnSCardSetAttrib == NULL))
|
|
#endif
|
|
{
|
|
fRet = FALSE;
|
|
}
|
|
|
|
#ifndef OS_WINCE
|
|
_hModKernel32 = LoadLibraryA("kernel32.dll");
|
|
|
|
if (_hModKernel32 != NULL)
|
|
{
|
|
pfnRegisterWaitForSingleObject = (PFN_RegisterWaitForSingleObject)
|
|
GetProcAddress(_hModKernel32, "RegisterWaitForSingleObject");
|
|
|
|
pfnUnregisterWaitEx = (PFN_UnregisterWaitEx)
|
|
GetProcAddress(_hModKernel32, "UnregisterWaitEx");
|
|
|
|
if ((pfnRegisterWaitForSingleObject != NULL) &&
|
|
(pfnUnregisterWaitEx != NULL))
|
|
{
|
|
_fUseRegisterWaitFuncs = TRUE;
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
fRet = FALSE;
|
|
}
|
|
|
|
return (fRet);
|
|
}
|
|
|
|
|
|
//
|
|
// RPCRT4 stubs for dload failure
|
|
//
|
|
RPC_STATUS RPC_ENTRY
|
|
DLoadStub_MesDecodeBufferHandleCreate(
|
|
char * pBuffer,
|
|
unsigned long BufferSize,
|
|
handle_t * pHandle )
|
|
{
|
|
return (RPC_S_OUT_OF_MEMORY);
|
|
}
|
|
|
|
RPC_STATUS RPC_ENTRY
|
|
DLoadStub_MesEncodeDynBufferHandleCreate(
|
|
char * * pBuffer,
|
|
unsigned long * pEncodedSize,
|
|
handle_t * pHandle )
|
|
{
|
|
return (RPC_S_OUT_OF_MEMORY);
|
|
}
|
|
|
|
void RPC_ENTRY
|
|
DLoadStub_NdrMesTypeEncode2(
|
|
handle_t Handle,
|
|
const MIDL_TYPE_PICKLING_INFO * pPicklingInfo,
|
|
const MIDL_STUB_DESC * pStubDesc,
|
|
PFORMAT_STRING pFormatString,
|
|
const void * pObject )
|
|
{
|
|
throw (RPC_S_OUT_OF_MEMORY);
|
|
return;
|
|
}
|
|
|
|
void RPC_ENTRY
|
|
DLoadStub_NdrMesTypeDecode2(
|
|
handle_t Handle,
|
|
const MIDL_TYPE_PICKLING_INFO * pPicklingInfo,
|
|
const MIDL_STUB_DESC * pStubDesc,
|
|
PFORMAT_STRING pFormatString,
|
|
void * pObject )
|
|
{
|
|
throw (RPC_S_OUT_OF_MEMORY);
|
|
return;
|
|
}
|
|
|
|
void RPC_ENTRY
|
|
DLoadStub_NdrMesTypeFree2(
|
|
handle_t Handle,
|
|
const MIDL_TYPE_PICKLING_INFO * pPicklingInfo,
|
|
const MIDL_STUB_DESC * pStubDesc,
|
|
PFORMAT_STRING pFormatString,
|
|
void * pObject )
|
|
{
|
|
throw (RPC_S_OUT_OF_MEMORY);
|
|
return;
|
|
}
|
|
|
|
RPC_STATUS RPC_ENTRY
|
|
DLoadStub_MesHandleFree( handle_t Handle )
|
|
{
|
|
return (RPC_S_OUT_OF_MEMORY);
|
|
}
|
|
|
|
FARPROC WINAPI GetRPCRT4Stubs(LPCSTR szProcName)
|
|
{
|
|
DC_BEGIN_FN("W32SCard::GetRPCRT4Stubs");
|
|
|
|
if (0 == _stricmp(szProcName, "MesDecodeBufferHandleCreate"))
|
|
return (FARPROC)DLoadStub_MesDecodeBufferHandleCreate;
|
|
|
|
if (0 == _stricmp(szProcName, "MesEncodeDynBufferHandleCreate"))
|
|
return (FARPROC)DLoadStub_MesEncodeDynBufferHandleCreate;
|
|
|
|
if (0 == _stricmp(szProcName, "NdrMesTypeEncode2"))
|
|
return (FARPROC)DLoadStub_NdrMesTypeEncode2;
|
|
|
|
if (0 == _stricmp(szProcName, "NdrMesTypeDecode2"))
|
|
return (FARPROC)DLoadStub_NdrMesTypeDecode2;
|
|
|
|
if (0 == _stricmp(szProcName, "NdrMesTypeFree2"))
|
|
return (FARPROC)DLoadStub_NdrMesTypeFree2;
|
|
|
|
if (0 == _stricmp(szProcName, "MesHandleFree"))
|
|
return (FARPROC)DLoadStub_MesHandleFree;
|
|
|
|
TRC_ERR(( TB,
|
|
_T("RPCRT4 stub =%s= is missing. Fix it NOW!"),
|
|
szProcName));
|
|
|
|
DC_END_FN();
|
|
|
|
return (FARPROC) NULL;
|
|
}
|
|
|
|
|
|
//
|
|
// Dload error handler
|
|
//
|
|
FARPROC WINAPI DliHook(unsigned dliNotify, PDelayLoadInfo pdli)
|
|
{
|
|
DC_BEGIN_FN("W32SCard::DliHook");
|
|
|
|
FARPROC fp = 0;
|
|
|
|
switch (dliNotify)
|
|
{
|
|
case dliFailLoadLib:
|
|
{
|
|
if (0 == _stricmp("rpcrt4.dll", pdli->szDll))
|
|
{
|
|
fp = (FARPROC) -1;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case dliFailGetProc:
|
|
{
|
|
SetLastError(ERROR_PROC_NOT_FOUND);
|
|
|
|
if (0 == _stricmp("rpcrt4.dll", pdli->szDll))
|
|
{
|
|
if (pdli->dlp.fImportByName)
|
|
{
|
|
fp = GetRPCRT4Stubs(pdli->dlp.szProcName);
|
|
}
|
|
else
|
|
{
|
|
TRC_ERR(( TB,
|
|
_T("RPCRT4 ordinal stub =%lx= is missing. Fix it NOW!"),
|
|
pdli->dlp.dwOrdinal));
|
|
|
|
fp = (FARPROC) NULL;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
DC_END_FN();
|
|
|
|
return fp;
|
|
}
|
|
|
|
PfnDliHook __pfnDliFailureHook2 = DliHook;
|
|
|
|
|
|
|