|
|
/*++
Copyright (C) Microsoft Corporation, 1996 - 1999
Module Name:
scredir
Abstract:
This module redirects the SCard* API calls
Author:
reidk 7/27/2000
--*/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <stdio.h>
#include <winscard.h>
#include "scredir.h"
#include "scioctl.h"
#include "calmsgs.h"
#include "calaislb.h"
#include "rdpdr.h"
//
// from secpkg.h
//
typedef NTSTATUS (NTAPI LSA_IMPERSONATE_CLIENT) (VOID); typedef LSA_IMPERSONATE_CLIENT * PLSA_IMPERSONATE_CLIENT;
#define wszWinSCardRegKeyRedirector (L"Software\\Microsoft\\SmartCard\\Redirector")
#define wszWinSCardRegVersion (L"Version")
#define wszWinSCardRegName (L"Name")
#define wszWinSCardRegNameValue (L"scredir.dll")
// This is the version number of the interface.
// The high word is the major version which must match exactly.
// The low word is the minor version. The dll must implement
// a minor version that is greater than or equal to the system
// minor version. This means that if we add a new funtion to the API,
// we increase the minor version and a remoting DLL can still be
// backward compatible. This is just like RPC version numbers
#define REDIRECTION_VERSION 0x00010000
#define ERROR_RETURN(x) lReturn = x; goto ErrorReturn;
#define MAX_SCARDCONTEXT_SIZE 32
#define MAX_SCARDHANDLE_SIZE 32
typedef struct _REDIR_LOCAL_SCARDCONTEXT { REDIR_SCARDCONTEXT Context; HANDLE hHeap; } REDIR_LOCAL_SCARDCONTEXT;
typedef struct _REDIR_LOCAL_SCARDHANDLE { REDIR_LOCAL_SCARDCONTEXT *pRedirContext; REDIR_SCARDHANDLE Handle; } REDIR_LOCAL_SCARDHANDLE;
//
// This structure is used to maintain a list of buffers that are
// used for the _SendSCardIOCTL calls
//
#define INITIAL_BUFFER_SIZE 512
typedef struct _BUFFER_LIST_STRUCT { void *pNext; BOOL fInUse; BYTE *pbBytes; unsigned long cbBytes; unsigned long cbBytesUsed; } BUFFER_LIST_STRUCT;
HMODULE g_hModule = NULL;
CRITICAL_SECTION g_CreateCS; CRITICAL_SECTION g_SetStartedEventStateCS; CRITICAL_SECTION g_StartedEventCreateCS; CRITICAL_SECTION g_ProcessDetachEventCreateCS; CRITICAL_SECTION g_BufferListCS;
HANDLE g_hRdpdrDeviceHandle = INVALID_HANDLE_VALUE; HANDLE g_hRedirStartedEvent = NULL; HANDLE g_hProcessDetachEvent = NULL; LONG g_lProcessDetachEventClients = 0;
BOOL g_fInTheProcessOfSettingStartedEvent = FALSE; HANDLE g_hRegisteredWaitHandle = NULL; HANDLE g_hWaitEvent = NULL; IO_STATUS_BLOCK g_StartedStatusBlock;
HANDLE g_hUnifiedStartedEvent = NULL;
BOOL g_fInProcessDetach = FALSE;
BUFFER_LIST_STRUCT *g_pBufferList = NULL;
#define IOCTL_RETURN_BUFFER_SIZE 256
BYTE g_rgbIOCTLReturnBuffer[IOCTL_RETURN_BUFFER_SIZE]; unsigned long g_cbIOCTLReturnBuffer;
#define _TRY_(y) __try \
{ \ y; \ } \ __except(EXCEPTION_EXECUTE_HANDLER) \ { \ ERROR_RETURN(GetExceptionCode()) \ }
#define _TRY_2(y) __try \
{ \ y; \ } \ __except(EXCEPTION_EXECUTE_HANDLER){} // do nothing
//
// Forward declarations
//
NTSTATUS _SendSCardIOCTLWithWaitForCallback( ULONG IoControlCode, PVOID InputBuffer, ULONG InputBufferLength, WAITORTIMERCALLBACK Callback);
void SafeMesHandleFree( handle_t *ph);
LONG I_DecodeLongReturn( BYTE *pb, unsigned long cb);
BOOL _SetStartedEventToCorrectState(void);
//---------------------------------------------------------------------------------------
//
// MIDL allocation routines
//
//---------------------------------------------------------------------------------------
void __RPC_FAR *__RPC_USER MIDL_user_allocate(size_t size) { void *pv;
if (NULL == (pv = (void *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size))) { SetLastError(ERROR_OUTOFMEMORY); }
return (pv); }
void __RPC_USER MIDL_user_free(void __RPC_FAR *pv) { if (pv != NULL) { HeapFree(GetProcessHeap(), 0, pv); } }
void * SCRedirAlloc(REDIR_LOCAL_SCARDCONTEXT *pRedirContext, size_t size) { return (HeapAlloc( (pRedirContext != NULL) ? pRedirContext->hHeap : GetProcessHeap(), HEAP_ZERO_MEMORY, size)); }
LONG _MakeSCardError(NTSTATUS Status) { switch (Status) { case STATUS_DEVICE_NOT_CONNECTED: return (SCARD_E_NO_SERVICE); break;
case STATUS_CANCELLED: return (SCARD_E_SYSTEM_CANCELLED); break;
default: return (SCARD_E_NO_SERVICE); } }
//---------------------------------------------------------------------------------------
//
// DllRegisterServer
//
//---------------------------------------------------------------------------------------
STDAPI DllRegisterServer(void) { HRESULT hr = ERROR_SUCCESS; HKEY hKey; DWORD dwDisposition; DWORD dwVersion = REDIRECTION_VERSION;
hr = RegCreateKeyExW( HKEY_LOCAL_MACHINE, wszWinSCardRegKeyRedirector, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dwDisposition);
if (hr == ERROR_SUCCESS) { hr = RegSetValueExW( hKey, wszWinSCardRegName, 0, REG_SZ, (BYTE *) wszWinSCardRegNameValue, (wcslen(wszWinSCardRegNameValue) + 1) * sizeof(WCHAR));
if (hr == ERROR_SUCCESS) { hr = RegSetValueExW( hKey, wszWinSCardRegVersion, 0, REG_DWORD, (BYTE *) &dwVersion, sizeof(DWORD)); }
RegCloseKey(hKey); }
return (hr); }
//---------------------------------------------------------------------------------------
//
// DllUnregisterServer
//
//---------------------------------------------------------------------------------------
STDAPI DllUnregisterServer(void) { HRESULT hr = ERROR_SUCCESS; HKEY hKey; DWORD dwDisposition; DWORD dwVersion = REDIRECTION_VERSION;
hr = RegCreateKeyExW( HKEY_LOCAL_MACHINE, wszWinSCardRegKeyRedirector, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dwDisposition);
if (hr == ERROR_SUCCESS) { RegDeleteValueW(hKey, wszWinSCardRegName); RegDeleteValueW(hKey, wszWinSCardRegVersion); RegCloseKey(hKey); }
return (hr); }
//---------------------------------------------------------------------------------------
//
// DllMain
//
//---------------------------------------------------------------------------------------
BOOL WINAPI DllMain(HMODULE hInstDLL, DWORD fdwReason, LPVOID lpvReserved) { DWORD dwTryCount = 0; DWORD dwCritSecsInitialized = 0; BUFFER_LIST_STRUCT *pTemp = NULL;
switch (fdwReason) { case DLL_PROCESS_ATTACH:
g_hModule = hInstDLL; __try { InitializeCriticalSection(&g_CreateCS); dwCritSecsInitialized++; InitializeCriticalSection(&g_SetStartedEventStateCS); dwCritSecsInitialized++; InitializeCriticalSection(&g_StartedEventCreateCS); dwCritSecsInitialized++; InitializeCriticalSection(&g_ProcessDetachEventCreateCS); dwCritSecsInitialized++; InitializeCriticalSection(&g_BufferListCS); dwCritSecsInitialized++; } __except(EXCEPTION_EXECUTE_HANDLER) { if (dwCritSecsInitialized >= 1) { DeleteCriticalSection(&g_CreateCS); }
if (dwCritSecsInitialized >= 2) { DeleteCriticalSection(&g_SetStartedEventStateCS); }
if (dwCritSecsInitialized >= 3) { DeleteCriticalSection(&g_StartedEventCreateCS); }
if (dwCritSecsInitialized >= 4) { DeleteCriticalSection(&g_ProcessDetachEventCreateCS); }
if (dwCritSecsInitialized >= 5) { DeleteCriticalSection(&g_BufferListCS); }
SetLastError(GetExceptionCode()); return (FALSE); }
break;
case DLL_PROCESS_DETACH:
g_fInProcessDetach = TRUE;
//
// The third parameter, lpvReserved, passed to DllMain
// is NULL for FreeLibrary and non-NULL for ProcessExit.
// Only clean up for FreeLibrary
//
//if (lpvReserved == NULL)
{ //
// If we are currently waiting for the started event then kill
// that wait
//
EnterCriticalSection(&g_SetStartedEventStateCS);
if (g_hRegisteredWaitHandle != NULL) { UnregisterWaitEx(g_hRegisteredWaitHandle, INVALID_HANDLE_VALUE); g_hRegisteredWaitHandle = NULL; }
if (g_hWaitEvent != NULL) { CloseHandle(g_hWaitEvent); g_hWaitEvent = NULL; }
LeaveCriticalSection(&g_SetStartedEventStateCS);
//
// If there are clients waiting on IOCTLs to complete, then let them go.
//
if (g_hProcessDetachEvent != NULL) { SetEvent(g_hProcessDetachEvent); }
if (g_hProcessDetachEvent != NULL) { //
// wait for all clients until they are done with the event
//
while ((g_lProcessDetachEventClients > 0) && (dwTryCount < 50)) { Sleep(10); dwTryCount++; }
if (dwTryCount < 50) { CloseHandle(g_hProcessDetachEvent); } }
if (g_hRdpdrDeviceHandle != INVALID_HANDLE_VALUE) { CloseHandle(g_hRdpdrDeviceHandle); }
if (g_hRedirStartedEvent != NULL) { CloseHandle(g_hRedirStartedEvent); }
//
// Free all the buffers used for the IOCTL calls
//
pTemp = g_pBufferList; while (pTemp != NULL) { g_pBufferList = (BUFFER_LIST_STRUCT *) pTemp->pNext; MIDL_user_free(pTemp->pbBytes); MIDL_user_free(pTemp); pTemp = g_pBufferList; }
DeleteCriticalSection(&g_CreateCS); DeleteCriticalSection(&g_SetStartedEventStateCS); DeleteCriticalSection(&g_StartedEventCreateCS); DeleteCriticalSection(&g_ProcessDetachEventCreateCS); DeleteCriticalSection(&g_BufferListCS); }
break; }
return (TRUE); }
//---------------------------------------------------------------------------------------
//
// GetBuffer
//
//---------------------------------------------------------------------------------------
BUFFER_LIST_STRUCT * GetBuffer(void) { BUFFER_LIST_STRUCT *pTemp = NULL; BUFFER_LIST_STRUCT *p1 = NULL; BUFFER_LIST_STRUCT *p2 = NULL;
EnterCriticalSection(&g_BufferListCS);
//
// See if there are any buffers allocated yet
//
if (g_pBufferList == NULL) { g_pBufferList = (BUFFER_LIST_STRUCT *) MIDL_user_allocate(sizeof(BUFFER_LIST_STRUCT));
if (g_pBufferList == NULL) { goto Return; }
g_pBufferList->pbBytes = (BYTE *) MIDL_user_allocate(INITIAL_BUFFER_SIZE);
if (g_pBufferList->pbBytes == NULL) { MIDL_user_free(g_pBufferList); goto Return; }
g_pBufferList->pNext = NULL; g_pBufferList->fInUse = TRUE; g_pBufferList->cbBytes = INITIAL_BUFFER_SIZE;
pTemp = g_pBufferList; goto Return; }
//
// Walk the existing list to see if a free buffer can be found
//
pTemp = g_pBufferList; while ((pTemp != NULL) && (pTemp->fInUse)) { pTemp = (BUFFER_LIST_STRUCT *)pTemp->pNext; }
if (pTemp != NULL) { pTemp->fInUse = TRUE;
//
// Get rid of any buffers that exist which aren't being used
//
p1 = pTemp; p2 = (BUFFER_LIST_STRUCT *) pTemp->pNext; while (p2 != NULL) { if (!(p2->fInUse)) { p1->pNext = p2->pNext;
MIDL_user_free(p2->pbBytes); MIDL_user_free(p2);
p2 = (BUFFER_LIST_STRUCT *) p1->pNext; } else { p1 = (BUFFER_LIST_STRUCT *) p1->pNext; p2 = (BUFFER_LIST_STRUCT *) p2->pNext; } }
goto Return; }
//
// No free buffers, so create a new one
//
pTemp = (BUFFER_LIST_STRUCT *) MIDL_user_allocate(sizeof(BUFFER_LIST_STRUCT));
if (pTemp == NULL) { goto Return; }
pTemp->pbBytes = (BYTE *) MIDL_user_allocate(INITIAL_BUFFER_SIZE);
if (pTemp->pbBytes == NULL) { MIDL_user_free(pTemp); goto Return; }
pTemp->fInUse = TRUE; pTemp->cbBytes = INITIAL_BUFFER_SIZE;
pTemp->pNext = g_pBufferList; g_pBufferList = pTemp;
Return:
LeaveCriticalSection(&g_BufferListCS); return(pTemp); }
//---------------------------------------------------------------------------------------
//
// FreeBuffer
//
//---------------------------------------------------------------------------------------
void FreeBuffer(BUFFER_LIST_STRUCT *pBuffer) { if (pBuffer != NULL) { pBuffer->fInUse = FALSE; } }
//---------------------------------------------------------------------------------------
//
// GrowBuffer
//
//---------------------------------------------------------------------------------------
BOOL GrowBuffer(BUFFER_LIST_STRUCT *pBuffer) { BYTE *pTemp; BOOL fRet = TRUE;
pTemp = pBuffer->pbBytes;
pBuffer->pbBytes = (BYTE *) MIDL_user_allocate(pBuffer->cbBytes * 2);
if (pBuffer->pbBytes == NULL) { pBuffer->pbBytes = pTemp; fRet = FALSE; } else { MIDL_user_free(pTemp); pBuffer->cbBytes = pBuffer->cbBytes * 2; }
return (fRet); }
//---------------------------------------------------------------------------------------
//
// _GetProcessDetachEventHandle
//
//---------------------------------------------------------------------------------------
HANDLE _GetProcessDetachEventHandle(void) { EnterCriticalSection(&g_ProcessDetachEventCreateCS);
if (NULL == g_hProcessDetachEvent) { try { g_hProcessDetachEvent = CreateEvent( NULL, // pointer to security attributes
TRUE, // flag for manual-reset event
FALSE, // flag for initial state
NULL); // event-object name
} catch (...) { goto Return; } }
LeaveCriticalSection(&g_ProcessDetachEventCreateCS);
Return:
if (g_hProcessDetachEvent != NULL) { InterlockedIncrement(&g_lProcessDetachEventClients); }
return (g_hProcessDetachEvent); }
void _ReleaseProcessDetachEventHandle(void) { InterlockedDecrement(&g_lProcessDetachEventClients); }
//---------------------------------------------------------------------------------------
//
// All the code below is to solve the problem of weather or not the redirect Smart
// Card Subsystem is available. It is available if we are connected to the client,
// and if the clients Smart Card Subsystem is running
//
//---------------------------------------------------------------------------------------
HANDLE _GetStartedEventHandle(void) { EnterCriticalSection(&g_StartedEventCreateCS);
if (NULL == g_hRedirStartedEvent) { g_hRedirStartedEvent = CreateEvent(NULL, TRUE, FALSE, NULL); }
LeaveCriticalSection(&g_StartedEventCreateCS);
return (g_hRedirStartedEvent); }
VOID CALLBACK AccessStartedEventIOCTLCallback( PVOID lpParameter, BOOLEAN TimerOrWaitFired) { HANDLE h = NULL; BOOL fRetry = FALSE; //OutputDebugString("SCREDIR: AccessStartedEventIOCTLCallback\n");
//
// Close the handle that was used to fire this callback
//
EnterCriticalSection(&g_SetStartedEventStateCS);
h = g_hRegisteredWaitHandle; g_hRegisteredWaitHandle = NULL;
LeaveCriticalSection(&g_SetStartedEventStateCS); //OutputDebugString("SCREDIR: AccessStartedEventIOCTLCallback - through the CS\n");
if (h != NULL) { UnregisterWait(h); }
//
// Make sure the AccessStartedEvent IOCTL completed and wasn't timed out
//
if (!TimerOrWaitFired) { //
// Make sure the AccessStartedEvent IOCTL completed successfully
//
if (g_StartedStatusBlock.Status == STATUS_SUCCESS) { //OutputDebugString("SCREDIR: AccessStartedEventIOCTLCallback - g_StartedStatusBlock.Status == STATUS_SUCCESS\n");
g_cbIOCTLReturnBuffer = (unsigned long) g_StartedStatusBlock.Information;
//
// Look at the value returned from the SCARD_IOCTL_ACCESSSTARTEDEVENT
// call to see if we should set the local started event
//
if (I_DecodeLongReturn( g_rgbIOCTLReturnBuffer, g_cbIOCTLReturnBuffer) == SCARD_S_SUCCESS) { //OutputDebugString("SCREDIR: AccessStartedEventIOCTLCallback - SetEvent\n");
SetEvent(g_hRedirStartedEvent); } } else if (g_StartedStatusBlock.Status == STATUS_CANCELLED) { //OutputDebugString("SCREDIR: AccessStartedEventIOCTLCallback - Got STATUS_CANCELLED\n");
//
// Retry
//
fRetry = TRUE; } else { char a[256]; sprintf(a, "SCREDIR: AccessStartedEventIOCTLCallback - Status = %lx\n", g_StartedStatusBlock.Status); //OutputDebugString(a);
}
} else { //OutputDebugString("SCREDIR: AccessStartedEventIOCTLCallback - Timed out\n");
}
//
// Unset the g_fInTheProcessOfSettingStartedEvent boolean
//
EnterCriticalSection(&g_SetStartedEventStateCS); g_fInTheProcessOfSettingStartedEvent = FALSE; LeaveCriticalSection(&g_SetStartedEventStateCS);
if (fRetry) { _SetStartedEventToCorrectState(); } }
VOID CALLBACK SCardOnLineIOCTLCallback( PVOID lpParameter, BOOLEAN TimerOrWaitFired) { BOOL fOperationDone = FALSE; NTSTATUS Status = STATUS_SUCCESS; BYTE rgb[4]; HANDLE h = NULL;
//
// Close the handle that was used to fire this callback
//
EnterCriticalSection(&g_SetStartedEventStateCS); h = g_hRegisteredWaitHandle; g_hRegisteredWaitHandle = NULL; LeaveCriticalSection(&g_SetStartedEventStateCS);
if (h != NULL) { UnregisterWait(h); }
//
// Make sure the online IOCTL completed and wasn't timed out
//
if (TimerOrWaitFired) { //
// Timed out, so just cancel operation
//
fOperationDone = TRUE; } else { //
// Make sure the SCardOnLine IOCTL completed successfully, then try to
// send the IOCTL which will wait on the clients started event
//
if (g_StartedStatusBlock.Status == STATUS_SUCCESS) { Status = _SendSCardIOCTLWithWaitForCallback( SCARD_IOCTL_ACCESSSTARTEDEVENT, rgb, 4, AccessStartedEventIOCTLCallback); if (Status == STATUS_SUCCESS) { //OutputDebugString("SCREDIR: SCardOnLineIOCTLCallback - _SendSCardIOCTLWithWaitForCallback(SCARD_IOCTL_ACCESSSTARTEDEVENT) - suceeded\n");
g_cbIOCTLReturnBuffer = (unsigned long) g_StartedStatusBlock.Information;
//
// Look at the value returned from the SCARD_IOCTL_ACCESSSTARTEDEVENT
// call to see if we should set the local started event
//
if (I_DecodeLongReturn( g_rgbIOCTLReturnBuffer, g_cbIOCTLReturnBuffer) == SCARD_S_SUCCESS) { SetEvent(g_hRedirStartedEvent); }
fOperationDone = TRUE; } else if (Status == STATUS_PENDING) { //OutputDebugString("SCREDIR: SCardOnLineIOCTLCallback - _SendSCardIOCTLWithWaitForCallback(SCARD_IOCTL_ACCESSSTARTEDEVENT) - PENDING\n");
//
// This OK, since the AccessStartedEventIOCTLCallback function
// will handle the return once the operation is complete
//
} else { fOperationDone = TRUE; } } else { fOperationDone = TRUE; } }
if (fOperationDone) { EnterCriticalSection(&g_SetStartedEventStateCS); g_fInTheProcessOfSettingStartedEvent = FALSE; LeaveCriticalSection(&g_SetStartedEventStateCS); } }
BOOL _SetStartedEventToCorrectState(void) { BOOL fRet = TRUE; BOOL fOperationDone = FALSE; HANDLE h = NULL; NTSTATUS Status = STATUS_SUCCESS; BYTE rgb[4];
//
// Make sure the event is created
//
if (NULL == (h = _GetStartedEventHandle())) { fRet = FALSE; goto Return; }
//
// If the event is already set then just return
//
/*if (WAIT_OBJECT_0 == WaitForSingleObject(h, 0))
{ //OutputDebugString("SCREDIR: _SetStartedEventToCorrectState - Event already set\n");
goto Return; }*/
EnterCriticalSection(&g_SetStartedEventStateCS);
//
// If we are already in the process of setting the started event, then just get out
//
if (g_fInTheProcessOfSettingStartedEvent) { //OutputDebugString("SCREDIR: _SetStartedEventToCorrectState - g_fInTheProcessOfSettingStartedEvent set\n");
LeaveCriticalSection(&g_SetStartedEventStateCS); goto Return; }
g_fInTheProcessOfSettingStartedEvent = TRUE; LeaveCriticalSection(&g_SetStartedEventStateCS);
ResetEvent(g_hRedirStartedEvent);
//
// Make the blocking call to rdpdr.sys that will only return after the
// client is connected, and the scard device announce has been processed
//
// NOTE: If this fails, then we can't do much,
//
Status = _SendSCardIOCTLWithWaitForCallback( SCARD_IOCTL_SMARTCARD_ONLINE, NULL, 0, SCardOnLineIOCTLCallback); if (Status == STATUS_SUCCESS) { //OutputDebugString("SCREDIR: _SetStartedEventToCorrectState - _SendSCardIOCTLWithWaitForCallback(SCARD_IOCTL_SMARTCARD_ONLINE) - suceeded\n");
//
// Since the SCARD_IOCTL_SMARTCARD_ONLINE succeeded immediately, we
// can just make the SCARD_IOCTL_ACCESSSTARTEDEVENT right now.
//
Status = _SendSCardIOCTLWithWaitForCallback( SCARD_IOCTL_ACCESSSTARTEDEVENT, rgb, 4, AccessStartedEventIOCTLCallback); if (Status == STATUS_SUCCESS) { //OutputDebugString("SCREDIR: _SetStartedEventToCorrectState - _SendSCardIOCTLWithWaitForCallback(SCARD_IOCTL_ACCESSSTARTEDEVENT) - suceeded\n");
g_cbIOCTLReturnBuffer = (unsigned long) g_StartedStatusBlock.Information;
//
// Look at the value returned from the SCARD_IOCTL_ACCESSSTARTEDEVENT
// call to see if we should set the local started event
//
if (I_DecodeLongReturn( g_rgbIOCTLReturnBuffer, g_cbIOCTLReturnBuffer) == SCARD_S_SUCCESS) { SetEvent(g_hRedirStartedEvent); }
fOperationDone = TRUE; } else if (Status == STATUS_PENDING) { //OutputDebugString("SCREDIR: _SetStartedEventToCorrectState - _SendSCardIOCTLWithWaitForCallback(SCARD_IOCTL_ACCESSSTARTEDEVENT) - PENDING\n");
//
// This OK, since the AccessStartedEventIOCTLCallback function
// will handle the return once the operation is complete
//
} else { fOperationDone = TRUE; } } else if (Status == STATUS_PENDING) { //OutputDebugString("SCREDIR: _SetStartedEventToCorrectState - _SendSCardIOCTLWithWaitForCallback(SCARD_IOCTL_SMARTCARD_ONLINE) - PENDING\n");
//
// This is OK, the SCardOnLineIOCTLCallback will make the next call
// to _SendSCardIOCTLWithWaitForCallback with SCARD_IOCTL_ACCESSSTARTEDEVENT
//
} else { fOperationDone = TRUE; }
if (fOperationDone) { EnterCriticalSection(&g_SetStartedEventStateCS); g_fInTheProcessOfSettingStartedEvent = FALSE; LeaveCriticalSection(&g_SetStartedEventStateCS); }
//
// Now check to see if the operation completed successfully
//
if ((Status != STATUS_PENDING) && (Status != STATUS_SUCCESS)) { fRet = FALSE; }
Return:
return (fRet); }
//---------------------------------------------------------------------------------------
//
// _CreateRdpdrDeviceHandle
//
//---------------------------------------------------------------------------------------
HANDLE _CreateRdpdrDeviceHandle() { WCHAR wszDeviceName[56];
swprintf(wszDeviceName, L"\\\\TSCLIENT\\%S", DR_SMARTCARD_SUBSYSTEM);
return (CreateFileW( wszDeviceName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_FLAG_OVERLAPPED, NULL)); }
//---------------------------------------------------------------------------------------
//
// _CreateGlobalRdpdrHandle
//
//---------------------------------------------------------------------------------------
NTSTATUS _CreateGlobalRdpdrHandle() { NTSTATUS Status = STATUS_SUCCESS;
EnterCriticalSection(&g_CreateCS);
//
// Check to see if the SCardDevice handle has been created
// yet, if not, then create it
//
if (g_hRdpdrDeviceHandle == INVALID_HANDLE_VALUE) { g_hRdpdrDeviceHandle = _CreateRdpdrDeviceHandle();
if (g_hRdpdrDeviceHandle == INVALID_HANDLE_VALUE) { Status = STATUS_OPEN_FAILED; } }
LeaveCriticalSection(&g_CreateCS);
return (Status); }
//---------------------------------------------------------------------------------------
//
// _SendSCardIOCTLWithWaitForCallback
//
//---------------------------------------------------------------------------------------
NTSTATUS _SendSCardIOCTLWithWaitForCallback( ULONG IoControlCode, PVOID InputBuffer, ULONG InputBufferLength, WAITORTIMERCALLBACK Callback) { NTSTATUS Status = STATUS_SUCCESS;
if (g_fInProcessDetach) { goto ErrorReturn; }
Status = _CreateGlobalRdpdrHandle(); if (Status != STATUS_SUCCESS) { return (Status); }
//
// Create the event which is set when the function successfully completes
//
if (g_hWaitEvent == NULL) { g_hWaitEvent = CreateEvent(NULL, TRUE, FALSE, NULL); if (g_hWaitEvent == NULL) { goto ErrorReturn; } } else { ResetEvent(g_hWaitEvent); }
Status = NtDeviceIoControlFile( g_hRdpdrDeviceHandle, g_hWaitEvent, NULL, NULL, &g_StartedStatusBlock, IoControlCode, InputBuffer, InputBufferLength, g_rgbIOCTLReturnBuffer, IOCTL_RETURN_BUFFER_SIZE);
if (Status == STATUS_PENDING) { EnterCriticalSection(&g_SetStartedEventStateCS);
//
// The g_hWaitEvent being set by the driver will trigger this registered callback
//
if (!RegisterWaitForSingleObject( &g_hRegisteredWaitHandle, g_hWaitEvent, Callback, NULL, INFINITE, WT_EXECUTEONLYONCE)) { LeaveCriticalSection(&g_SetStartedEventStateCS); goto ErrorReturn; }
LeaveCriticalSection(&g_SetStartedEventStateCS); } else if (Status == STATUS_SUCCESS) { g_cbIOCTLReturnBuffer = (unsigned long) g_StartedStatusBlock.Information; } else { g_cbIOCTLReturnBuffer = 0; }
Return:
return (Status);
ErrorReturn:
Status = STATUS_INSUFFICIENT_RESOURCES;
goto Return; }
//---------------------------------------------------------------------------------------
//
// _SendSCardIOCTL
//
//---------------------------------------------------------------------------------------
NTSTATUS _SendSCardIOCTL( ULONG IoControlCode, PVOID InputBuffer, ULONG InputBufferLength, BUFFER_LIST_STRUCT **ppOutputBuffer) { NTSTATUS Status = STATUS_SUCCESS; IO_STATUS_BLOCK StatusBlock; HANDLE rgWaitHandles[2]; DWORD dwIndex;
*ppOutputBuffer = NULL;
rgWaitHandles[0] = NULL; rgWaitHandles[1] = NULL;
//
// Make sure the handle to the rdpdr device is created
//
Status = _CreateGlobalRdpdrHandle(); if (Status != STATUS_SUCCESS) { return (Status); }
//
// Get an output buffer for the call
//
*ppOutputBuffer = GetBuffer(); if (*ppOutputBuffer == NULL) { return (STATUS_NO_MEMORY); }
//
// Create the event that will be signaled when the IOCTL is complete
//
rgWaitHandles[0] = CreateEvent(NULL, TRUE, FALSE, NULL); if (rgWaitHandles[0] == NULL) { return (STATUS_INSUFFICIENT_RESOURCES); }
while (1) { Status = NtDeviceIoControlFile( g_hRdpdrDeviceHandle, rgWaitHandles[0], NULL, NULL, &StatusBlock, IoControlCode, InputBuffer, InputBufferLength, (*ppOutputBuffer)->pbBytes, (*ppOutputBuffer)->cbBytes);
if (Status == STATUS_PENDING) { rgWaitHandles[1] = _GetProcessDetachEventHandle(); if (rgWaitHandles[1] == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; break; }
dwIndex = WaitForMultipleObjects(2, rgWaitHandles, FALSE, INFINITE); if (dwIndex != WAIT_FAILED) { dwIndex = dwIndex - WAIT_OBJECT_0;
//
// The IOCTL wait event was signaled if dwIndex == 0. Otherwise the
// process detach event was signaled
//
if (dwIndex == 0) { Status = StatusBlock.Status; } } else { Status = STATUS_UNEXPECTED_IO_ERROR; }
_ReleaseProcessDetachEventHandle(); }
if (Status == STATUS_BUFFER_TOO_SMALL) { if (!GrowBuffer(*ppOutputBuffer)) { Status = STATUS_NO_MEMORY; break; }
ResetEvent(rgWaitHandles[0]); } else { break; } }
if (Status != STATUS_SUCCESS) { //
// If we got the STATUS_DEVICE_NOT_CONNECTED error, then go back to waiting
// for a connect
//
if (Status == STATUS_DEVICE_NOT_CONNECTED) { _SetStartedEventToCorrectState(); } else if ((Status == STATUS_CANCELLED) && (g_hUnifiedStartedEvent != NULL)) { //OutputDebugString("SCREDIR: _SendSCardIOCTL: resetting g_hUnifiedStartedEvent\n");
ResetEvent(g_hUnifiedStartedEvent); _SetStartedEventToCorrectState(); }
(*ppOutputBuffer)->cbBytesUsed = 0; goto Return; }
(*ppOutputBuffer)->cbBytesUsed = (unsigned long) StatusBlock.Information;
Return:
if (rgWaitHandles[0] != NULL) { CloseHandle(rgWaitHandles[0]); }
return (Status); }
//---------------------------------------------------------------------------------------
//
// SafeMesHandleFree
//
//---------------------------------------------------------------------------------------
void SafeMesHandleFree(handle_t *ph) { if (*ph != 0) { MesHandleFree(*ph); *ph = 0; } }
//---------------------------------------------------------------------------------------
//
// _CalculateNumBytesInMultiStringA
//
//---------------------------------------------------------------------------------------
DWORD _CalculateNumBytesInMultiStringA(LPCSTR psz) { DWORD dwTotal = sizeof(char); // trailing '/0'
DWORD dwNumChars = 0; LPCSTR pszCurrent = psz;
if (psz == NULL) { return (0); }
if (pszCurrent[0] == '\0') { if (pszCurrent[1] == '\0') { return (2 * sizeof(char)); }
pszCurrent++; dwTotal += sizeof(char); }
while (pszCurrent[0] != '\0') { dwNumChars = strlen(pszCurrent) + 1; dwTotal += dwNumChars * sizeof(char); pszCurrent += dwNumChars; }
return (dwTotal); }
//---------------------------------------------------------------------------------------
//
// _CalculateNumBytesInMultiStringW
//
//---------------------------------------------------------------------------------------
DWORD _CalculateNumBytesInMultiStringW(LPCWSTR pwsz) { DWORD dwTotal = sizeof(WCHAR); // trailing L'/0'
DWORD dwNumChars = 0; LPCWSTR pwszCurrent = pwsz;
if (pwsz == NULL) { return (0); }
if (pwszCurrent[0] == L'\0') { if (pwszCurrent[1] == L'\0') { (2 * sizeof(WCHAR)); }
pwszCurrent++; dwTotal += sizeof(WCHAR); }
while (pwszCurrent[0] != L'\0') { dwNumChars = wcslen(pwszCurrent) + 1; dwTotal += dwNumChars * sizeof(WCHAR); pwszCurrent += dwNumChars; }
return (dwTotal); }
//---------------------------------------------------------------------------------------
//
// _CalculateNumBytesInAtr
//
//---------------------------------------------------------------------------------------
DWORD _CalculateNumBytesInAtr(LPCBYTE pbAtr) { DWORD dwAtrLen = 0;
if (ParseAtr(pbAtr, &dwAtrLen, NULL, NULL, 33)) { return (dwAtrLen); } else { return (0); } }
//---------------------------------------------------------------------------------------
//
// _CopyReturnToCallerBuffer
//
//---------------------------------------------------------------------------------------
#define BYTE_TYPE_RETURN 1
#define SZ_TYPE_RETURN 2
#define WSZ_TYPE_RETURN 3
LONG _CopyReturnToCallerBuffer( REDIR_LOCAL_SCARDCONTEXT *pRedirContext, LPBYTE pbReturn, DWORD cbReturn, LPBYTE pbUserBuffer, LPDWORD pcbUserBuffer, DWORD dwReturnType) { LPBYTE *ppBuf; BOOL fAutoAllocate = (*pcbUserBuffer == SCARD_AUTOALLOCATE); DWORD dwEnd; DWORD dwCallersBufferSize = *pcbUserBuffer;
//
// The number of chars or bytes, depending on the type of return.
//
if (dwReturnType == WSZ_TYPE_RETURN) { *pcbUserBuffer = cbReturn / sizeof(WCHAR); } else if (dwReturnType == SZ_TYPE_RETURN) { *pcbUserBuffer = cbReturn / sizeof(char); } else { *pcbUserBuffer = cbReturn; }
//
// If pbUserBuffer is not NULL, then the caller wants the data,
// not just the size, so give it to em'
//
if ((pbReturn != NULL) && (pbUserBuffer != NULL)) { //
// validate the data
//
if (dwReturnType == WSZ_TYPE_RETURN) { //
// If we aren't auto allocating and the users buffer is too small then
// get out. This is just extra protection to ensure that the client
// isn't ill behaved. Since the client was passed the size of our
// callers buffer the client should really fail if the buffer isn't
// big enough, but since we can't trust the client, do this extra check.
//
if ((!fAutoAllocate) && (dwCallersBufferSize < (cbReturn / sizeof(WCHAR)))) { return (SCARD_E_UNEXPECTED); }
dwEnd = cbReturn / sizeof(WCHAR);
if ((dwEnd < 2) || // must be at least two chars
(((LPWSTR) pbReturn)[dwEnd-1] != L'\0') || // last char must be '\0'
(((LPWSTR) pbReturn)[dwEnd-2] != L'\0')) // second to last char must be '\0'
{ return (SCARD_E_UNEXPECTED); } } else if (dwReturnType == SZ_TYPE_RETURN) { //
// If we aren't auto allocating and the users buffer is too small then
// get out. This is just extra protection to ensure that the client
// isn't ill behaved. Since the client was passed the size of our
// callers buffer the client should really fail if the buffer isn't
// big enough, but since we can't trust the client, do this extra check.
//
if ((!fAutoAllocate) && (dwCallersBufferSize < (cbReturn / sizeof(char)))) { return (SCARD_E_UNEXPECTED); }
dwEnd = cbReturn / sizeof(char);
if ((dwEnd < 2) || // must be at least two chars
(((LPSTR) pbReturn)[dwEnd-1] != '\0') || // last char must be '\0'
(((LPSTR) pbReturn)[dwEnd-2] != '\0')) // second to last char must be '\0'
{ return (SCARD_E_UNEXPECTED); } } else { //
// If we aren't auto allocating and the users buffer is too small then
// get out. This is just extra protection to ensure that the client
// isn't ill behaved. Since the client was passed the size of our
// callers buffer the client should really fail if the buffer isn't
// big enough, but since we can't trust the client, do this extra check.
//
if ((!fAutoAllocate) && (dwCallersBufferSize < cbReturn)) { return (SCARD_E_UNEXPECTED); } }
//
// Allocate space for caller if requested, else, copy to callers
// supplied buffer
//
if (fAutoAllocate) { ppBuf = (LPBYTE *) pbUserBuffer;
*ppBuf = (LPBYTE) SCRedirAlloc(pRedirContext, cbReturn); if (*ppBuf != NULL) { memcpy(*ppBuf, pbReturn, cbReturn); } else { return (SCARD_E_NO_MEMORY); } } else { memcpy(pbUserBuffer, pbReturn, cbReturn); } }
return (SCARD_S_SUCCESS); }
//---------------------------------------------------------------------------------------
//
// I_DecodeLongReturn
//
//---------------------------------------------------------------------------------------
LONG I_DecodeLongReturn( BYTE *pb, unsigned long cb) { handle_t h = 0; RPC_STATUS rpcStatus; Long_Return LongReturn; LONG lReturn;
rpcStatus = MesDecodeBufferHandleCreate( (char *) pb, cb, &h); if (rpcStatus != RPC_S_OK) { ERROR_RETURN(SCARD_E_UNEXPECTED); }
memset(&LongReturn, 0, sizeof(LongReturn)); _TRY_(Long_Return_Decode(h, &LongReturn))
lReturn = LongReturn.ReturnCode;
_TRY_2(Long_Return_Free(h, &LongReturn))
Return:
SafeMesHandleFree(&h);
return (lReturn);
ErrorReturn:
goto Return; }
//---------------------------------------------------------------------------------------
//
// SCardEstablishContext
//
//---------------------------------------------------------------------------------------
WINSCARDAPI LONG WINAPI SCardEstablishContext( IN DWORD dwScope, IN LPCVOID pvReserved1, IN LPCVOID pvReserved2, OUT LPSCARDCONTEXT phContext) { LONG lReturn = SCARD_S_SUCCESS; NTSTATUS Status = STATUS_SUCCESS; RPC_STATUS rpcStatus = RPC_S_OK; char *pbEncodedBuffer = NULL; unsigned long cbEncodedBuffer = 0; handle_t h = 0; BOOL fFreeDecode = FALSE; BUFFER_LIST_STRUCT *pOutputBuffer = NULL; EstablishContext_Call EstablishContextCall; EstablishContext_Return EstablishContextReturn;
//
// This event is the "smart card subsystem started" event that
// winscard.dll and scredir.dll share. scredir will Reset this event
// if it gets a STATUS_CANCELLED returned from the rdpdr driver, or if it
// gets and indication that the clients scardsvr service was stopped (it
// gets these indications via SCardEstablishContext returing SCARD_E_NO_SERVICE
// or by SCardGetStatusChange returning SCARD_E_SYSTEM_CANCELLED). It
// does this so that the event goes into the unsignalled state as soon as
// possible when a disconnect or service shutdown is detected... a STATUS_CANCELLED
// returned from rdpdr happens when a disconnect takes place
//
g_hUnifiedStartedEvent = (HANDLE) pvReserved2;
//
// Validate input params and initialize the out param
//
if (phContext == NULL) { ERROR_RETURN(SCARD_E_INVALID_PARAMETER) } else { *phContext = NULL; } if ((SCARD_SCOPE_USER != dwScope) // && (SCARD_SCOPE_TERMINAL != dwScope) // Maybe NT V5+?
&& (SCARD_SCOPE_SYSTEM != dwScope)) { ERROR_RETURN(SCARD_E_INVALID_VALUE) }
//
// Initialize encoding handle
//
rpcStatus = MesEncodeDynBufferHandleCreate( &pbEncodedBuffer, &cbEncodedBuffer, &h); if (rpcStatus != RPC_S_OK) { ERROR_RETURN(SCARD_E_UNEXPECTED) }
//
// Encode the EstablishContext params
//
EstablishContextCall.dwScope = dwScope; _TRY_(EstablishContext_Call_Encode(h, &EstablishContextCall))
//
// Make the EstablishContext call to the client
//
Status = _SendSCardIOCTL( SCARD_IOCTL_ESTABLISHCONTEXT, pbEncodedBuffer, cbEncodedBuffer, &pOutputBuffer); if (Status != STATUS_SUCCESS) { ERROR_RETURN(_MakeSCardError(Status)) } SafeMesHandleFree(&h);
//
// Decode the return
//
rpcStatus = MesDecodeBufferHandleCreate( (char *) pOutputBuffer->pbBytes, pOutputBuffer->cbBytesUsed, &h); if (rpcStatus != RPC_S_OK) { ERROR_RETURN(SCARD_E_UNEXPECTED) }
memset(&EstablishContextReturn, 0, sizeof(EstablishContextReturn)); _TRY_(EstablishContext_Return_Decode(h, &EstablishContextReturn)) fFreeDecode = TRUE;
lReturn = EstablishContextReturn.ReturnCode;
if (lReturn == SCARD_S_SUCCESS) { REDIR_LOCAL_SCARDCONTEXT *pRedirLocalContext = NULL;
//
// The value that represents the SCARDCONTEXT on the remote client
// machine is a variable size, so allocate memory for the struct
// that holds the variable length context size and pointer, plus
// the actual bytes for the context... but first, make sure the
// context is a reasonable size
//
if (EstablishContextReturn.Context.cbContext > MAX_SCARDCONTEXT_SIZE) { ERROR_RETURN(SCARD_E_UNEXPECTED) }
pRedirLocalContext = (REDIR_LOCAL_SCARDCONTEXT *) MIDL_user_allocate( sizeof(REDIR_LOCAL_SCARDCONTEXT) + EstablishContextReturn.Context.cbContext);
if (pRedirLocalContext != NULL) { pRedirLocalContext->Context.cbContext = EstablishContextReturn.Context.cbContext; pRedirLocalContext->Context.pbContext = ((BYTE *) pRedirLocalContext) + sizeof(REDIR_LOCAL_SCARDCONTEXT); memcpy( pRedirLocalContext->Context.pbContext, EstablishContextReturn.Context.pbContext, EstablishContextReturn.Context.cbContext);
pRedirLocalContext->hHeap = (HANDLE) pvReserved1;
*phContext = (SCARDCONTEXT) pRedirLocalContext; } else { lReturn = SCARD_E_NO_MEMORY; } } else if ((lReturn == SCARD_E_NO_SERVICE) && (g_hUnifiedStartedEvent != NULL)) { //
// This error indicates that the clients scardsvr service has been stopped,
// so reset the unified started event
//
//OutputDebugString("SCREDIR: SCardEstablishContext: resetting g_hUnifiedStartedEvent\n");
ResetEvent(g_hUnifiedStartedEvent); _SetStartedEventToCorrectState(); }
Return:
if (fFreeDecode) { _TRY_2(EstablishContext_Return_Free(h, &EstablishContextReturn)) }
SafeMesHandleFree(&h);
MIDL_user_free(pbEncodedBuffer);
FreeBuffer(pOutputBuffer);
return (lReturn);
ErrorReturn:
if ((phContext != NULL) && (*phContext != NULL)) { MIDL_user_free((void *) *phContext); *phContext = NULL; }
goto Return; }
//---------------------------------------------------------------------------------------
//
// I_ContextCallWithLongReturn
//
//---------------------------------------------------------------------------------------
WINSCARDAPI LONG WINAPI I_ContextCallWithLongReturn( IN SCARDCONTEXT hContext, ULONG IoControlCode) { LONG lReturn = SCARD_S_SUCCESS; NTSTATUS Status = STATUS_SUCCESS; RPC_STATUS rpcStatus = RPC_S_OK; char *pbEncodedBuffer = NULL; unsigned long cbEncodedBuffer = 0; handle_t h = 0; BUFFER_LIST_STRUCT *pOutputBuffer = NULL; Context_Call ContextCall;
if (hContext == NULL) { return (SCARD_E_INVALID_PARAMETER); }
//
// Initialize encoding handle
//
rpcStatus = MesEncodeDynBufferHandleCreate( &pbEncodedBuffer, &cbEncodedBuffer, &h); if (rpcStatus != RPC_S_OK) { ERROR_RETURN(SCARD_E_UNEXPECTED) }
//
// Encode the ContextCall params
//
ContextCall.Context = ((REDIR_LOCAL_SCARDCONTEXT *) hContext)->Context; _TRY_(Context_Call_Encode(h, &ContextCall))
//
// Make the IoControl call to the client
//
Status = _SendSCardIOCTL( IoControlCode, pbEncodedBuffer, cbEncodedBuffer, &pOutputBuffer); if (Status != STATUS_SUCCESS) { ERROR_RETURN(_MakeSCardError(Status)) }
//
// Decode the return
//
lReturn = I_DecodeLongReturn(pOutputBuffer->pbBytes, pOutputBuffer->cbBytesUsed);
Return:
SafeMesHandleFree(&h);
MIDL_user_free(pbEncodedBuffer);
FreeBuffer(pOutputBuffer);
return (lReturn);
ErrorReturn:
goto Return; }
//---------------------------------------------------------------------------------------
//
// SCardReleaseContext
//
//---------------------------------------------------------------------------------------
WINSCARDAPI LONG WINAPI SCardReleaseContext( IN SCARDCONTEXT hContext) { LONG lReturn = SCARD_S_SUCCESS;
__try { if (hContext == NULL) { return (SCARD_E_INVALID_PARAMETER); }
lReturn = I_ContextCallWithLongReturn( hContext, SCARD_IOCTL_RELEASECONTEXT);
MIDL_user_free((REDIR_LOCAL_SCARDCONTEXT *) hContext); } __except(EXCEPTION_EXECUTE_HANDLER) { return (SCARD_E_INVALID_PARAMETER); }
return (lReturn); }
//---------------------------------------------------------------------------------------
//
// SCardIsValidContext
//
//---------------------------------------------------------------------------------------
WINSCARDAPI LONG WINAPI SCardIsValidContext( IN SCARDCONTEXT hContext) { return (I_ContextCallWithLongReturn( hContext, SCARD_IOCTL_ISVALIDCONTEXT)); }
//---------------------------------------------------------------------------------------
//
// SCardListReaderGroups
//
//---------------------------------------------------------------------------------------
WINSCARDAPI LONG WINAPI I_SCardListReaderGroups( IN SCARDCONTEXT hContext, OUT LPBYTE mszGroups, IN OUT LPDWORD pcchGroups, IN BOOL fUnicode) { LONG lReturn = SCARD_S_SUCCESS; NTSTATUS Status = STATUS_SUCCESS; RPC_STATUS rpcStatus = RPC_S_OK; char *pbEncodedBuffer = NULL; unsigned long cbEncodedBuffer = 0; handle_t h = 0; BUFFER_LIST_STRUCT *pOutputBuffer = NULL; ListReaderGroups_Call ListReaderGroupsCall; ListReaderGroups_Return ListReaderGroupsReturn;
if (pcchGroups == NULL) { return (SCARD_E_INVALID_PARAMETER); }
//
// Initialize encoding handle
//
rpcStatus = MesEncodeDynBufferHandleCreate( &pbEncodedBuffer, &cbEncodedBuffer, &h); if (rpcStatus != RPC_S_OK) { ERROR_RETURN(SCARD_E_UNEXPECTED) }
//
// Encode the ListReaderGroups params
//
if (hContext != NULL) { ListReaderGroupsCall.Context = ((REDIR_LOCAL_SCARDCONTEXT *) hContext)->Context; } else { ListReaderGroupsCall.Context.pbContext = NULL; ListReaderGroupsCall.Context.cbContext = 0; } ListReaderGroupsCall.fmszGroupsIsNULL = (mszGroups == NULL); ListReaderGroupsCall.cchGroups = *pcchGroups; _TRY_(ListReaderGroups_Call_Encode(h, &ListReaderGroupsCall))
//
// Make the ListReaderGroups call to the client
//
Status = _SendSCardIOCTL( fUnicode ? SCARD_IOCTL_LISTREADERGROUPSW : SCARD_IOCTL_LISTREADERGROUPSA, pbEncodedBuffer, cbEncodedBuffer, &pOutputBuffer); if (Status != STATUS_SUCCESS) { ERROR_RETURN(_MakeSCardError(Status)) } SafeMesHandleFree(&h);
//
// Decode the return
//
rpcStatus = MesDecodeBufferHandleCreate( (char *) pOutputBuffer->pbBytes, pOutputBuffer->cbBytesUsed, &h); if (rpcStatus != RPC_S_OK) { ERROR_RETURN(SCARD_E_UNEXPECTED) }
memset(&ListReaderGroupsReturn, 0, sizeof(ListReaderGroupsReturn)); _TRY_(ListReaderGroups_Return_Decode(h, &ListReaderGroupsReturn))
//
// If successful, then copy the returned multi string
//
if (ListReaderGroupsReturn.ReturnCode == SCARD_S_SUCCESS) { lReturn = _CopyReturnToCallerBuffer( (REDIR_LOCAL_SCARDCONTEXT *) hContext, ListReaderGroupsReturn.msz, ListReaderGroupsReturn.cBytes, mszGroups, pcchGroups, fUnicode ? WSZ_TYPE_RETURN : SZ_TYPE_RETURN); } else { lReturn = ListReaderGroupsReturn.ReturnCode; }
_TRY_2(ListReaderGroups_Return_Free(h, &ListReaderGroupsReturn))
Return:
SafeMesHandleFree(&h);
MIDL_user_free(pbEncodedBuffer);
FreeBuffer(pOutputBuffer);
return (lReturn);
ErrorReturn:
goto Return; }
WINSCARDAPI LONG WINAPI SCardListReaderGroupsA( IN SCARDCONTEXT hContext, OUT LPSTR mszGroups, IN OUT LPDWORD pcchGroups) { return (I_SCardListReaderGroups( hContext, (LPBYTE) mszGroups, pcchGroups, FALSE)); }
WINSCARDAPI LONG WINAPI SCardListReaderGroupsW( IN SCARDCONTEXT hContext, OUT LPWSTR mszGroups, IN OUT LPDWORD pcchGroups) { return (I_SCardListReaderGroups( hContext, (LPBYTE) mszGroups, pcchGroups, TRUE)); }
//---------------------------------------------------------------------------------------
//
// SCardListReaders
//
//---------------------------------------------------------------------------------------
WINSCARDAPI LONG WINAPI I_SCardListReaders( IN SCARDCONTEXT hContext, IN LPCBYTE mszGroups, OUT LPBYTE mszReaders, IN OUT LPDWORD pcchReaders, IN BOOL fUnicode) { LONG lReturn = SCARD_S_SUCCESS; NTSTATUS Status = STATUS_SUCCESS; RPC_STATUS rpcStatus = RPC_S_OK; char *pbEncodedBuffer = NULL; unsigned long cbEncodedBuffer = 0; handle_t h = 0; BUFFER_LIST_STRUCT *pOutputBuffer = NULL; ListReaders_Call ListReadersCall; ListReaders_Return ListReadersReturn;
if (pcchReaders == NULL) { return (SCARD_E_INVALID_PARAMETER); }
//
// Initialize encoding handle
//
rpcStatus = MesEncodeDynBufferHandleCreate( &pbEncodedBuffer, &cbEncodedBuffer, &h); if (rpcStatus != RPC_S_OK) { ERROR_RETURN(SCARD_E_UNEXPECTED) }
//
// Encode the ListReaders params
//
if (hContext != NULL) { ListReadersCall.Context = ((REDIR_LOCAL_SCARDCONTEXT *) hContext)->Context; } else { ListReadersCall.Context.pbContext = NULL; ListReadersCall.Context.cbContext = 0; } ListReadersCall.cBytes = fUnicode ? _CalculateNumBytesInMultiStringW((LPCWSTR) mszGroups) : _CalculateNumBytesInMultiStringA((LPCSTR) mszGroups); ListReadersCall.mszGroups = mszGroups; ListReadersCall.fmszReadersIsNULL = (mszReaders == NULL); ListReadersCall.cchReaders = *pcchReaders; _TRY_(ListReaders_Call_Encode(h, &ListReadersCall))
//
// Make the ListReaders call to the client
//
Status = _SendSCardIOCTL( fUnicode ? SCARD_IOCTL_LISTREADERSW : SCARD_IOCTL_LISTREADERSA, pbEncodedBuffer, cbEncodedBuffer, &pOutputBuffer); if (Status != STATUS_SUCCESS) { ERROR_RETURN(_MakeSCardError(Status)) } SafeMesHandleFree(&h);
//
// Decode the return
//
rpcStatus = MesDecodeBufferHandleCreate( (char *) pOutputBuffer->pbBytes, pOutputBuffer->cbBytesUsed, &h); if (rpcStatus != RPC_S_OK) { ERROR_RETURN(SCARD_E_UNEXPECTED) }
memset(&ListReadersReturn, 0, sizeof(ListReadersReturn)); _TRY_(ListReaders_Return_Decode(h, &ListReadersReturn))
//
// If successful, then copy the returned multi string
//
if (ListReadersReturn.ReturnCode == SCARD_S_SUCCESS) { lReturn = _CopyReturnToCallerBuffer( (REDIR_LOCAL_SCARDCONTEXT *) hContext, ListReadersReturn.msz, ListReadersReturn.cBytes, mszReaders, pcchReaders, fUnicode ? WSZ_TYPE_RETURN : SZ_TYPE_RETURN); } else { lReturn = ListReadersReturn.ReturnCode; }
_TRY_2(ListReaders_Return_Free(h, &ListReadersReturn))
Return:
SafeMesHandleFree(&h);
MIDL_user_free(pbEncodedBuffer);
FreeBuffer(pOutputBuffer);
return (lReturn);
ErrorReturn:
goto Return; }
WINSCARDAPI LONG WINAPI SCardListReadersA( IN SCARDCONTEXT hContext, IN LPCSTR mszGroups, OUT LPSTR mszReaders, IN OUT LPDWORD pcchReaders) { return (I_SCardListReaders( hContext, (LPCBYTE) mszGroups, (LPBYTE) mszReaders, pcchReaders, FALSE)); }
WINSCARDAPI LONG WINAPI SCardListReadersW( IN SCARDCONTEXT hContext, IN LPCWSTR mszGroups, OUT LPWSTR mszReaders, IN OUT LPDWORD pcchReaders) { return (I_SCardListReaders( hContext, (LPCBYTE) mszGroups, (LPBYTE) mszReaders, pcchReaders, TRUE)); }
//---------------------------------------------------------------------------------------
//
// I_ContextAndStringCallWithLongReturn
//
//---------------------------------------------------------------------------------------
WINSCARDAPI LONG WINAPI I_ContextAndStringCallWithLongReturn( IN SCARDCONTEXT hContext, IN LPCBYTE sz, IN BOOL fUnicode, ULONG IoControlCode) { LONG lReturn = SCARD_S_SUCCESS; NTSTATUS Status = STATUS_SUCCESS; RPC_STATUS rpcStatus = RPC_S_OK; char *pbEncodedBuffer = NULL; unsigned long cbEncodedBuffer = 0; handle_t h = 0; BUFFER_LIST_STRUCT *pOutputBuffer = NULL; ContextAndStringA_Call ContextAndStringCallA; ContextAndStringW_Call ContextAndStringCallW;
if (hContext == NULL) { return (SCARD_E_INVALID_PARAMETER); } else if (sz == NULL) { return (SCARD_E_INVALID_VALUE); }
//
// Initialize encoding handle
//
rpcStatus = MesEncodeDynBufferHandleCreate( &pbEncodedBuffer, &cbEncodedBuffer, &h); if (rpcStatus != RPC_S_OK) { ERROR_RETURN(SCARD_E_UNEXPECTED) }
//
// Encode the ContextAndString params
//
ContextAndStringCallA.Context = ContextAndStringCallW.Context = ((REDIR_LOCAL_SCARDCONTEXT *) hContext)->Context;
if (fUnicode) { ContextAndStringCallW.sz = (LPCWSTR) sz; _TRY_(ContextAndStringW_Call_Encode(h, &ContextAndStringCallW)) } else { ContextAndStringCallA.sz = (LPCSTR) sz; _TRY_(ContextAndStringA_Call_Encode(h, &ContextAndStringCallA)) }
//
// Make the call to the client
//
Status = _SendSCardIOCTL( IoControlCode, pbEncodedBuffer, cbEncodedBuffer, &pOutputBuffer); if (Status != STATUS_SUCCESS) { ERROR_RETURN(_MakeSCardError(Status)) }
//
// Decode the return
//
lReturn = I_DecodeLongReturn(pOutputBuffer->pbBytes, pOutputBuffer->cbBytesUsed);
Return:
SafeMesHandleFree(&h);
MIDL_user_free(pbEncodedBuffer);
FreeBuffer(pOutputBuffer);
return (lReturn);
ErrorReturn:
goto Return; }
//---------------------------------------------------------------------------------------
//
// SCardIntroduceReaderGroup
//
//---------------------------------------------------------------------------------------
WINSCARDAPI LONG WINAPI SCardIntroduceReaderGroupA( IN SCARDCONTEXT hContext, IN LPCSTR szGroupName) { return (I_ContextAndStringCallWithLongReturn( hContext, (LPCBYTE) szGroupName, FALSE, SCARD_IOCTL_INTRODUCEREADERGROUPA)); }
WINSCARDAPI LONG WINAPI SCardIntroduceReaderGroupW( IN SCARDCONTEXT hContext, IN LPCWSTR szGroupName) { return (I_ContextAndStringCallWithLongReturn( hContext, (LPCBYTE) szGroupName, TRUE, SCARD_IOCTL_INTRODUCEREADERGROUPW)); }
//---------------------------------------------------------------------------------------
//
// SCardForgetReaderGroup
//
//---------------------------------------------------------------------------------------
WINSCARDAPI LONG WINAPI SCardForgetReaderGroupA( IN SCARDCONTEXT hContext, IN LPCSTR szGroupName) { return (I_ContextAndStringCallWithLongReturn( hContext, (LPCBYTE) szGroupName, FALSE, SCARD_IOCTL_FORGETREADERGROUPA)); }
WINSCARDAPI LONG WINAPI SCardForgetReaderGroupW( IN SCARDCONTEXT hContext, IN LPCWSTR szGroupName) { return (I_ContextAndStringCallWithLongReturn( hContext, (LPCBYTE) szGroupName, TRUE, SCARD_IOCTL_FORGETREADERGROUPW)); }
//---------------------------------------------------------------------------------------
//
// I_ContextAndTwoStringCallWithLongReturn
//
//---------------------------------------------------------------------------------------
WINSCARDAPI LONG WINAPI I_ContextAndTwoStringCallWithLongReturn( IN SCARDCONTEXT hContext, IN LPCBYTE sz1, IN LPCBYTE sz2, IN BOOL fUnicode, ULONG IoControlCode) { LONG lReturn = SCARD_S_SUCCESS; NTSTATUS Status = STATUS_SUCCESS; RPC_STATUS rpcStatus = RPC_S_OK; char *pbEncodedBuffer = NULL; unsigned long cbEncodedBuffer = 0; handle_t h = 0; BUFFER_LIST_STRUCT *pOutputBuffer = NULL; ContextAndTwoStringA_Call ContextAndTwoStringCallA; ContextAndTwoStringW_Call ContextAndTwoStringCallW;
if (hContext == NULL) { return (SCARD_E_INVALID_PARAMETER); } else if ((sz1 == NULL) || (sz2 == NULL)) { return (SCARD_E_INVALID_VALUE); }
//
// Initialize encoding handle
//
rpcStatus = MesEncodeDynBufferHandleCreate( &pbEncodedBuffer, &cbEncodedBuffer, &h); if (rpcStatus != RPC_S_OK) { ERROR_RETURN(SCARD_E_UNEXPECTED) }
//
// Encode the ContextAndTwoString params
//
ContextAndTwoStringCallA.Context = ContextAndTwoStringCallW.Context = ((REDIR_LOCAL_SCARDCONTEXT *) hContext)->Context;
if (fUnicode) { ContextAndTwoStringCallW.sz1 = (LPCWSTR) sz1; ContextAndTwoStringCallW.sz2 = (LPCWSTR) sz2; _TRY_(ContextAndTwoStringW_Call_Encode(h, &ContextAndTwoStringCallW)) } else { ContextAndTwoStringCallA.sz1 = (LPCSTR) sz1; ContextAndTwoStringCallA.sz2 = (LPCSTR) sz2; _TRY_(ContextAndTwoStringA_Call_Encode(h, &ContextAndTwoStringCallA)) }
//
// Make the call to the client
//
Status = _SendSCardIOCTL( IoControlCode, pbEncodedBuffer, cbEncodedBuffer, &pOutputBuffer); if (Status != STATUS_SUCCESS) { MesHandleFree(h); ERROR_RETURN(_MakeSCardError(Status)) }
//
// Decode the return
//
lReturn = I_DecodeLongReturn(pOutputBuffer->pbBytes, pOutputBuffer->cbBytesUsed);
Return:
SafeMesHandleFree(&h);
MIDL_user_free(pbEncodedBuffer);
FreeBuffer(pOutputBuffer);
return (lReturn);
ErrorReturn:
goto Return; }
//---------------------------------------------------------------------------------------
//
// SCardIntroduceReader
//
//---------------------------------------------------------------------------------------
WINSCARDAPI LONG WINAPI SCardIntroduceReaderA( IN SCARDCONTEXT hContext, IN LPCSTR szReaderName, IN LPCSTR szDeviceName) { return (I_ContextAndTwoStringCallWithLongReturn( hContext, (LPCBYTE) szReaderName, (LPCBYTE) szDeviceName, FALSE, SCARD_IOCTL_INTRODUCEREADERA)); }
WINSCARDAPI LONG WINAPI SCardIntroduceReaderW( IN SCARDCONTEXT hContext, IN LPCWSTR szReaderName, IN LPCWSTR szDeviceName) { return (I_ContextAndTwoStringCallWithLongReturn( hContext, (LPCBYTE) szReaderName, (LPCBYTE) szDeviceName, TRUE, SCARD_IOCTL_INTRODUCEREADERW)); }
//---------------------------------------------------------------------------------------
//
// SCardForgetReader
//
//---------------------------------------------------------------------------------------
WINSCARDAPI LONG WINAPI SCardForgetReaderA( IN SCARDCONTEXT hContext, IN LPCSTR szReaderName) { return (I_ContextAndStringCallWithLongReturn( hContext, (LPCBYTE) szReaderName, FALSE, SCARD_IOCTL_FORGETREADERA)); }
WINSCARDAPI LONG WINAPI SCardForgetReaderW( IN SCARDCONTEXT hContext, IN LPCWSTR szReaderName) { return (I_ContextAndStringCallWithLongReturn( hContext, (LPCBYTE) szReaderName, TRUE, SCARD_IOCTL_FORGETREADERW)); }
//---------------------------------------------------------------------------------------
//
// SCardAddReaderToGroup
//
//---------------------------------------------------------------------------------------
WINSCARDAPI LONG WINAPI SCardAddReaderToGroupA( IN SCARDCONTEXT hContext, IN LPCSTR szReaderName, IN LPCSTR szGroupName) { return (I_ContextAndTwoStringCallWithLongReturn( hContext, (LPCBYTE) szReaderName, (LPCBYTE) szGroupName, FALSE, SCARD_IOCTL_ADDREADERTOGROUPA)); }
WINSCARDAPI LONG WINAPI SCardAddReaderToGroupW( IN SCARDCONTEXT hContext, IN LPCWSTR szReaderName, IN LPCWSTR szGroupName) { return (I_ContextAndTwoStringCallWithLongReturn( hContext, (LPCBYTE) szReaderName, (LPCBYTE) szGroupName, TRUE, SCARD_IOCTL_ADDREADERTOGROUPW)); }
//---------------------------------------------------------------------------------------
//
// SCardRemoveReaderFromGroup
//
//---------------------------------------------------------------------------------------
WINSCARDAPI LONG WINAPI SCardRemoveReaderFromGroupA( IN SCARDCONTEXT hContext, IN LPCSTR szReaderName, IN LPCSTR szGroupName) { return (I_ContextAndTwoStringCallWithLongReturn( hContext, (LPCBYTE) szReaderName, (LPCBYTE) szGroupName, FALSE, SCARD_IOCTL_REMOVEREADERFROMGROUPA)); }
WINSCARDAPI LONG WINAPI SCardRemoveReaderFromGroupW( IN SCARDCONTEXT hContext, IN LPCWSTR szReaderName, IN LPCWSTR szGroupName) { return (I_ContextAndTwoStringCallWithLongReturn( hContext, (LPCBYTE) szReaderName, (LPCBYTE) szGroupName, TRUE, SCARD_IOCTL_REMOVEREADERFROMGROUPW)); }
//---------------------------------------------------------------------------------------
//
// _AllocAndCopyReaderState*StructsForCall and _CopyReaderState*StructsForReturn
//
//---------------------------------------------------------------------------------------
LONG _AllocAndCopyReaderStateAStructsForCall( DWORD cReaders, ReaderStateA **prgReaderStatesToEncodeA, LPSCARD_READERSTATE_A rgReaderStates) { DWORD i; ReaderStateA *rgAlloced;
rgAlloced = (ReaderStateA *) MIDL_user_allocate(cReaders * sizeof(ReaderStateA));
if (rgAlloced == NULL) { return (SCARD_E_NO_MEMORY); }
for (i=0; i<cReaders; i++) { rgAlloced[i].Common.dwCurrentState = rgReaderStates[i].dwCurrentState; rgAlloced[i].Common.dwEventState = rgReaderStates[i].dwEventState; rgAlloced[i].Common.cbAtr = rgReaderStates[i].cbAtr; memcpy( rgAlloced[i].Common.rgbAtr, rgReaderStates[i].rgbAtr, 36); rgAlloced[i].szReader = rgReaderStates[i].szReader; }
*prgReaderStatesToEncodeA = rgAlloced;
return (SCARD_S_SUCCESS); }
LONG _AllocAndCopyReaderStateWStructsForCall( DWORD cReaders, ReaderStateW **prgReaderStatesToEncodeW, LPSCARD_READERSTATE_W rgReaderStates) { DWORD i; ReaderStateW *rgAlloced;
rgAlloced = (ReaderStateW *) MIDL_user_allocate(cReaders * sizeof(ReaderStateW));
if (rgAlloced == NULL) { return (SCARD_E_NO_MEMORY); }
for (i=0; i<cReaders; i++) { rgAlloced[i].Common.dwCurrentState = rgReaderStates[i].dwCurrentState; rgAlloced[i].Common.dwEventState = rgReaderStates[i].dwEventState; rgAlloced[i].Common.cbAtr = rgReaderStates[i].cbAtr; memcpy( rgAlloced[i].Common.rgbAtr, rgReaderStates[i].rgbAtr, 36); rgAlloced[i].szReader = rgReaderStates[i].szReader; }
*prgReaderStatesToEncodeW = rgAlloced;
return (SCARD_S_SUCCESS); }
void _CopyReaderStateAStructsForReturn( DWORD cReaders, LPSCARD_READERSTATE_A rgReaderStates, ReaderState_Return *rgReaderStatesReturned) { DWORD i;
for (i=0; i<cReaders; i++) { rgReaderStates[i].dwCurrentState = rgReaderStatesReturned[i].dwCurrentState; rgReaderStates[i].dwEventState = rgReaderStatesReturned[i].dwEventState; rgReaderStates[i].cbAtr = rgReaderStatesReturned[i].cbAtr; memcpy( rgReaderStates[i].rgbAtr, rgReaderStatesReturned[i].rgbAtr, 36); } }
void _CopyReaderStateWStructsForReturn( DWORD cReaders, LPSCARD_READERSTATE_W rgReaderStates, ReaderState_Return *rgReaderStatesReturned) { DWORD i;
for (i=0; i<cReaders; i++) { rgReaderStates[i].dwCurrentState = rgReaderStatesReturned[i].dwCurrentState; rgReaderStates[i].dwEventState = rgReaderStatesReturned[i].dwEventState; rgReaderStates[i].cbAtr = rgReaderStatesReturned[i].cbAtr; memcpy( rgReaderStates[i].rgbAtr, rgReaderStatesReturned[i].rgbAtr, 36); } }
//---------------------------------------------------------------------------------------
//
// _AllocAndCopyATRMasksForCall
//
//---------------------------------------------------------------------------------------
LONG _AllocAndCopyATRMasksForCall( DWORD cAtrs, LocateCards_ATRMask **prgATRMasksToEncode, LPSCARD_ATRMASK rgAtrMasks) { DWORD i; LocateCards_ATRMask *rgAlloced;
rgAlloced = (LocateCards_ATRMask *) MIDL_user_allocate(cAtrs * sizeof(LocateCards_ATRMask));
if (rgAlloced == NULL) { return (SCARD_E_NO_MEMORY); }
for (i=0; i<cAtrs; i++) { rgAlloced[i].cbAtr = rgAtrMasks[i].cbAtr; memcpy( rgAlloced[i].rgbAtr, rgAtrMasks[i].rgbAtr, 36); memcpy( rgAlloced[i].rgbMask, rgAtrMasks[i].rgbMask, 36); }
*prgATRMasksToEncode = rgAlloced;
return (SCARD_S_SUCCESS); }
//---------------------------------------------------------------------------------------
//
// SCardLocateCardsA
//
//---------------------------------------------------------------------------------------
WINSCARDAPI LONG WINAPI SCardLocateCardsA( IN SCARDCONTEXT hContext, IN LPCSTR mszCards, IN OUT LPSCARD_READERSTATE_A rgReaderStates, IN DWORD cReaders) { LONG lReturn = SCARD_S_SUCCESS; NTSTATUS Status = STATUS_SUCCESS; RPC_STATUS rpcStatus = RPC_S_OK; char *pbEncodedBuffer = NULL; unsigned long cbEncodedBuffer = 0; handle_t h = 0; LocateCardsA_Call LocateCardsCallA; LocateCards_Return LocateCardsReturn; ReaderStateA *rgReaderStatesToEncodeA = NULL; BUFFER_LIST_STRUCT *pOutputBuffer = NULL; DWORD i;
if (hContext == NULL) { return (SCARD_E_INVALID_PARAMETER); } else if (mszCards == NULL) { return (SCARD_E_INVALID_VALUE); }
//
// Initialize encoding handle
//
rpcStatus = MesEncodeDynBufferHandleCreate( &pbEncodedBuffer, &cbEncodedBuffer, &h); if (rpcStatus != RPC_S_OK) { ERROR_RETURN(SCARD_E_UNEXPECTED) }
//
// Encode the LocateCards params
//
LocateCardsCallA.Context = ((REDIR_LOCAL_SCARDCONTEXT *) hContext)->Context; LocateCardsCallA.cBytes = _CalculateNumBytesInMultiStringA(mszCards); LocateCardsCallA.mszCards = (LPCBYTE) mszCards; LocateCardsCallA.cReaders = cReaders;
lReturn = _AllocAndCopyReaderStateAStructsForCall( cReaders, &rgReaderStatesToEncodeA, rgReaderStates); if (lReturn != SCARD_S_SUCCESS) { ERROR_RETURN(SCARD_E_NO_MEMORY) } LocateCardsCallA.rgReaderStates = rgReaderStatesToEncodeA;
_TRY_(LocateCardsA_Call_Encode(h, &LocateCardsCallA))
//
// Make the LocateCards call to the client
//
Status = _SendSCardIOCTL( SCARD_IOCTL_LOCATECARDSA, pbEncodedBuffer, cbEncodedBuffer, &pOutputBuffer); if (Status != STATUS_SUCCESS) { ERROR_RETURN(_MakeSCardError(Status)) } SafeMesHandleFree(&h);
//
// Decode the return
//
rpcStatus = MesDecodeBufferHandleCreate( (char *) pOutputBuffer->pbBytes, pOutputBuffer->cbBytesUsed, &h); if (rpcStatus != RPC_S_OK) { ERROR_RETURN(SCARD_E_UNEXPECTED) }
memset(&LocateCardsReturn, 0 , sizeof(LocateCardsReturn)); _TRY_(LocateCards_Return_Decode(h, &LocateCardsReturn))
lReturn = LocateCardsReturn.ReturnCode;
if (lReturn == SCARD_S_SUCCESS) { //
// Validate return info
//
if (cReaders != LocateCardsReturn.cReaders) { ERROR_RETURN(SCARD_E_UNEXPECTED) }
_CopyReaderStateAStructsForReturn( cReaders, rgReaderStates, LocateCardsReturn.rgReaderStates); }
_TRY_2(LocateCards_Return_Free(h, &LocateCardsReturn))
Return:
SafeMesHandleFree(&h);
MIDL_user_free(pbEncodedBuffer);
MIDL_user_free(rgReaderStatesToEncodeA);
FreeBuffer(pOutputBuffer);
return (lReturn);
ErrorReturn:
goto Return; }
//---------------------------------------------------------------------------------------
//
// SCardLocateCardsW
//
//---------------------------------------------------------------------------------------
WINSCARDAPI LONG WINAPI SCardLocateCardsW( IN SCARDCONTEXT hContext, IN LPCWSTR mszCards, IN OUT LPSCARD_READERSTATE_W rgReaderStates, IN DWORD cReaders) { LONG lReturn = SCARD_S_SUCCESS; NTSTATUS Status = STATUS_SUCCESS; RPC_STATUS rpcStatus = RPC_S_OK; char *pbEncodedBuffer = NULL; unsigned long cbEncodedBuffer = 0; handle_t h = 0; LocateCardsW_Call LocateCardsCallW; LocateCards_Return LocateCardsReturn; ReaderStateW *rgReaderStatesToEncodeW = NULL; BUFFER_LIST_STRUCT *pOutputBuffer = NULL; DWORD i;
if (hContext == NULL) { return (SCARD_E_INVALID_PARAMETER); } else if (mszCards == NULL) { return (SCARD_E_INVALID_VALUE); }
//
// Initialize encoding handle
//
rpcStatus = MesEncodeDynBufferHandleCreate( &pbEncodedBuffer, &cbEncodedBuffer, &h); if (rpcStatus != RPC_S_OK) { ERROR_RETURN(SCARD_E_UNEXPECTED) }
//
// Encode the LocateCards params
//
LocateCardsCallW.Context = ((REDIR_LOCAL_SCARDCONTEXT *) hContext)->Context; LocateCardsCallW.cBytes = _CalculateNumBytesInMultiStringW(mszCards); LocateCardsCallW.mszCards = (LPCBYTE) mszCards; LocateCardsCallW.cReaders = cReaders;
lReturn = _AllocAndCopyReaderStateWStructsForCall( cReaders, &rgReaderStatesToEncodeW, rgReaderStates); if (lReturn != SCARD_S_SUCCESS) { ERROR_RETURN(SCARD_E_NO_MEMORY) } LocateCardsCallW.rgReaderStates = rgReaderStatesToEncodeW;
_TRY_(LocateCardsW_Call_Encode(h, &LocateCardsCallW))
//
// Make the LocateCards call to the client
//
Status = _SendSCardIOCTL( SCARD_IOCTL_LOCATECARDSW, pbEncodedBuffer, cbEncodedBuffer, &pOutputBuffer); if (Status != STATUS_SUCCESS) { ERROR_RETURN(_MakeSCardError(Status)) } SafeMesHandleFree(&h);
//
// Decode the return
//
rpcStatus = MesDecodeBufferHandleCreate( (char *) pOutputBuffer->pbBytes, pOutputBuffer->cbBytesUsed, &h); if (rpcStatus != RPC_S_OK) { ERROR_RETURN(SCARD_E_UNEXPECTED) }
memset(&LocateCardsReturn, 0, sizeof(LocateCardsReturn)); _TRY_(LocateCards_Return_Decode(h, &LocateCardsReturn))
lReturn = LocateCardsReturn.ReturnCode;
if (lReturn == SCARD_S_SUCCESS) { //
// Validate return info
//
if (cReaders != LocateCardsReturn.cReaders) { ERROR_RETURN(SCARD_E_UNEXPECTED) }
_CopyReaderStateWStructsForReturn( cReaders, rgReaderStates, LocateCardsReturn.rgReaderStates); }
_TRY_2(LocateCards_Return_Free(h, &LocateCardsReturn))
Return:
SafeMesHandleFree(&h);
MIDL_user_free(pbEncodedBuffer);
MIDL_user_free(rgReaderStatesToEncodeW);
FreeBuffer(pOutputBuffer);
return (lReturn);
ErrorReturn:
goto Return; }
//---------------------------------------------------------------------------------------
//
// SCardLocateCardsByATRA
//
//---------------------------------------------------------------------------------------
WINSCARDAPI LONG WINAPI SCardLocateCardsByATRA( IN SCARDCONTEXT hContext, IN LPSCARD_ATRMASK rgAtrMasks, IN DWORD cAtrs, IN OUT LPSCARD_READERSTATE_A rgReaderStates, IN DWORD cReaders) { LONG lReturn = SCARD_S_SUCCESS; NTSTATUS Status = STATUS_SUCCESS; RPC_STATUS rpcStatus = RPC_S_OK; char *pbEncodedBuffer = NULL; unsigned long cbEncodedBuffer = 0; handle_t h = 0; LocateCardsByATRA_Call LocateCardsByATRA_Call; LocateCards_ATRMask *rgATRMasksToEncode = NULL; LocateCards_Return LocateCardsReturn; ReaderStateA *rgReaderStatesToEncodeA = NULL; BUFFER_LIST_STRUCT *pOutputBuffer = NULL; DWORD i;
if (hContext == NULL) { return (SCARD_E_INVALID_PARAMETER); }
//
// Initialize encoding handle
//
rpcStatus = MesEncodeDynBufferHandleCreate( &pbEncodedBuffer, &cbEncodedBuffer, &h); if (rpcStatus != RPC_S_OK) { ERROR_RETURN(SCARD_E_UNEXPECTED) }
//
// Encode the LocateCards params
//
LocateCardsByATRA_Call.Context = ((REDIR_LOCAL_SCARDCONTEXT *) hContext)->Context; LocateCardsByATRA_Call.cAtrs = cAtrs; LocateCardsByATRA_Call.cReaders = cReaders;
lReturn = _AllocAndCopyATRMasksForCall( cAtrs, &rgATRMasksToEncode, rgAtrMasks); if (lReturn != SCARD_S_SUCCESS) { ERROR_RETURN(SCARD_E_NO_MEMORY) } LocateCardsByATRA_Call.rgAtrMasks = rgATRMasksToEncode;
lReturn = _AllocAndCopyReaderStateAStructsForCall( cReaders, &rgReaderStatesToEncodeA, rgReaderStates); if (lReturn != SCARD_S_SUCCESS) { ERROR_RETURN(SCARD_E_NO_MEMORY) } LocateCardsByATRA_Call.rgReaderStates = rgReaderStatesToEncodeA;
_TRY_(LocateCardsByATRA_Call_Encode(h, &LocateCardsByATRA_Call))
//
// Make the LocateCards call to the client
//
Status = _SendSCardIOCTL( SCARD_IOCTL_LOCATECARDSBYATRA, pbEncodedBuffer, cbEncodedBuffer, &pOutputBuffer); if (Status != STATUS_SUCCESS) { ERROR_RETURN(_MakeSCardError(Status)) } SafeMesHandleFree(&h);
//
// Decode the return
//
rpcStatus = MesDecodeBufferHandleCreate( (char *) pOutputBuffer->pbBytes, pOutputBuffer->cbBytesUsed, &h); if (rpcStatus != RPC_S_OK) { ERROR_RETURN(SCARD_E_UNEXPECTED) }
memset(&LocateCardsReturn, 0 , sizeof(LocateCardsReturn)); _TRY_(LocateCards_Return_Decode(h, &LocateCardsReturn))
lReturn = LocateCardsReturn.ReturnCode;
if (lReturn == SCARD_S_SUCCESS) { //
// Validate return info
//
if (cReaders != LocateCardsReturn.cReaders) { ERROR_RETURN(SCARD_E_UNEXPECTED) }
_CopyReaderStateAStructsForReturn( cReaders, rgReaderStates, LocateCardsReturn.rgReaderStates); }
_TRY_2(LocateCards_Return_Free(h, &LocateCardsReturn))
Return:
SafeMesHandleFree(&h);
MIDL_user_free(pbEncodedBuffer);
MIDL_user_free(rgATRMasksToEncode);
MIDL_user_free(rgReaderStatesToEncodeA);
FreeBuffer(pOutputBuffer);
return (lReturn);
ErrorReturn:
goto Return; }
//---------------------------------------------------------------------------------------
//
// SCardLocateCardsByATRW
//
//---------------------------------------------------------------------------------------
WINSCARDAPI LONG WINAPI SCardLocateCardsByATRW( IN SCARDCONTEXT hContext, IN LPSCARD_ATRMASK rgAtrMasks, IN DWORD cAtrs, IN OUT LPSCARD_READERSTATE_W rgReaderStates, IN DWORD cReaders) { LONG lReturn = SCARD_S_SUCCESS; NTSTATUS Status = STATUS_SUCCESS; RPC_STATUS rpcStatus = RPC_S_OK; char *pbEncodedBuffer = NULL; unsigned long cbEncodedBuffer = 0; handle_t h = 0; LocateCardsByATRW_Call LocateCardsByATRW_Call; LocateCards_ATRMask *rgATRMasksToEncode = NULL; LocateCards_Return LocateCardsReturn; ReaderStateW *rgReaderStatesToEncodeW = NULL; BUFFER_LIST_STRUCT *pOutputBuffer = NULL; DWORD i;
if (hContext == NULL) { return (SCARD_E_INVALID_PARAMETER); }
//
// Initialize encoding handle
//
rpcStatus = MesEncodeDynBufferHandleCreate( &pbEncodedBuffer, &cbEncodedBuffer, &h); if (rpcStatus != RPC_S_OK) { ERROR_RETURN(SCARD_E_UNEXPECTED) }
//
// Encode the LocateCards params
//
LocateCardsByATRW_Call.Context = ((REDIR_LOCAL_SCARDCONTEXT *) hContext)->Context; LocateCardsByATRW_Call.cAtrs = cAtrs; LocateCardsByATRW_Call.cReaders = cReaders;
lReturn = _AllocAndCopyATRMasksForCall( cAtrs, &rgATRMasksToEncode, rgAtrMasks); if (lReturn != SCARD_S_SUCCESS) { ERROR_RETURN(SCARD_E_NO_MEMORY) } LocateCardsByATRW_Call.rgAtrMasks = rgATRMasksToEncode;
lReturn = _AllocAndCopyReaderStateWStructsForCall( cReaders, &rgReaderStatesToEncodeW, rgReaderStates); if (lReturn != SCARD_S_SUCCESS) { ERROR_RETURN(SCARD_E_NO_MEMORY) } LocateCardsByATRW_Call.rgReaderStates = rgReaderStatesToEncodeW;
_TRY_(LocateCardsByATRW_Call_Encode(h, &LocateCardsByATRW_Call))
//
// Make the LocateCards call to the client
//
Status = _SendSCardIOCTL( SCARD_IOCTL_LOCATECARDSBYATRW, pbEncodedBuffer, cbEncodedBuffer, &pOutputBuffer); if (Status != STATUS_SUCCESS) { ERROR_RETURN(_MakeSCardError(Status)) } SafeMesHandleFree(&h);
//
// Decode the return
//
rpcStatus = MesDecodeBufferHandleCreate( (char *) pOutputBuffer->pbBytes, pOutputBuffer->cbBytesUsed, &h); if (rpcStatus != RPC_S_OK) { ERROR_RETURN(SCARD_E_UNEXPECTED) }
memset(&LocateCardsReturn, 0 , sizeof(LocateCardsReturn)); _TRY_(LocateCards_Return_Decode(h, &LocateCardsReturn))
lReturn = LocateCardsReturn.ReturnCode;
if (lReturn == SCARD_S_SUCCESS) { //
// Validate return info
//
if (cReaders != LocateCardsReturn.cReaders) { ERROR_RETURN(SCARD_E_UNEXPECTED) }
_CopyReaderStateWStructsForReturn( cReaders, rgReaderStates, LocateCardsReturn.rgReaderStates); }
_TRY_2(LocateCards_Return_Free(h, &LocateCardsReturn))
Return:
SafeMesHandleFree(&h);
MIDL_user_free(pbEncodedBuffer);
MIDL_user_free(rgATRMasksToEncode);
MIDL_user_free(rgReaderStatesToEncodeW);
FreeBuffer(pOutputBuffer);
return (lReturn);
ErrorReturn:
goto Return; }
//---------------------------------------------------------------------------------------
//
// SCardGetStatusChangeA
//
//---------------------------------------------------------------------------------------
WINSCARDAPI LONG WINAPI SCardGetStatusChangeA( IN SCARDCONTEXT hContext, IN DWORD dwTimeout, IN OUT LPSCARD_READERSTATE_A rgReaderStates, IN DWORD cReaders) { LONG lReturn = SCARD_S_SUCCESS; NTSTATUS Status = STATUS_SUCCESS; RPC_STATUS rpcStatus = RPC_S_OK; char *pbEncodedBuffer = NULL; unsigned long cbEncodedBuffer = 0; handle_t h = 0; GetStatusChangeA_Call GetStatusChangeCallA; GetStatusChange_Return GetStatusChangeReturn; ReaderStateA *rgReaderStatesToEncodeA = NULL; BUFFER_LIST_STRUCT *pOutputBuffer = NULL; DWORD i;
if (hContext == NULL) { return (SCARD_E_INVALID_PARAMETER); }
//
// Initialize encoding handle
//
rpcStatus = MesEncodeDynBufferHandleCreate( &pbEncodedBuffer, &cbEncodedBuffer, &h); if (rpcStatus != RPC_S_OK) { ERROR_RETURN(SCARD_E_UNEXPECTED) }
//
// Encode the LocateCards params
//
GetStatusChangeCallA.Context = ((REDIR_LOCAL_SCARDCONTEXT *) hContext)->Context; GetStatusChangeCallA.dwTimeOut = dwTimeout; GetStatusChangeCallA.cReaders = cReaders;
lReturn = _AllocAndCopyReaderStateAStructsForCall( cReaders, &rgReaderStatesToEncodeA, rgReaderStates); if (lReturn != SCARD_S_SUCCESS) { ERROR_RETURN(SCARD_E_NO_MEMORY) }
GetStatusChangeCallA.rgReaderStates = rgReaderStatesToEncodeA;
_TRY_(GetStatusChangeA_Call_Encode(h, &GetStatusChangeCallA))
//
// Make the GetStatusChange call to the client
//
Status = _SendSCardIOCTL( SCARD_IOCTL_GETSTATUSCHANGEA, pbEncodedBuffer, cbEncodedBuffer, &pOutputBuffer); if (Status != STATUS_SUCCESS) { ERROR_RETURN(_MakeSCardError(Status)) } SafeMesHandleFree(&h);
//
// Decode the return
//
rpcStatus = MesDecodeBufferHandleCreate( (char *) pOutputBuffer->pbBytes, pOutputBuffer->cbBytesUsed, &h); if (rpcStatus != RPC_S_OK) { ERROR_RETURN(SCARD_E_UNEXPECTED) }
memset(&GetStatusChangeReturn, 0, sizeof(GetStatusChangeReturn)); _TRY_(GetStatusChange_Return_Decode(h, &GetStatusChangeReturn))
lReturn = GetStatusChangeReturn.ReturnCode;
if (lReturn == SCARD_S_SUCCESS) { //
// Validate return info
//
if (cReaders != GetStatusChangeReturn.cReaders) { ERROR_RETURN(SCARD_E_UNEXPECTED) }
_CopyReaderStateAStructsForReturn( cReaders, rgReaderStates, GetStatusChangeReturn.rgReaderStates); } else if ((lReturn == SCARD_E_SYSTEM_CANCELLED) && (g_hUnifiedStartedEvent != NULL)) { //
// This error indicates that the clients scardsvr service has been stopped,
// so reset the unified started event
//
//OutputDebugString("SCREDIR: SCardGetStatusChangeA: resetting g_hUnifiedStartedEvent\n");
ResetEvent(g_hUnifiedStartedEvent); _SetStartedEventToCorrectState(); }
_TRY_2(GetStatusChange_Return_Free(h, &GetStatusChangeReturn))
Return:
SafeMesHandleFree(&h);
MIDL_user_free(pbEncodedBuffer);
MIDL_user_free(rgReaderStatesToEncodeA);
FreeBuffer(pOutputBuffer);
return (lReturn);
ErrorReturn:
goto Return; }
//---------------------------------------------------------------------------------------
//
// SCardGetStatusChangew
//
//---------------------------------------------------------------------------------------
WINSCARDAPI LONG WINAPI SCardGetStatusChangeW( IN SCARDCONTEXT hContext, IN DWORD dwTimeout, IN OUT LPSCARD_READERSTATE_W rgReaderStates, IN DWORD cReaders) { LONG lReturn = SCARD_S_SUCCESS; NTSTATUS Status = STATUS_SUCCESS; RPC_STATUS rpcStatus = RPC_S_OK; char *pbEncodedBuffer = NULL; unsigned long cbEncodedBuffer = 0; handle_t h = 0; GetStatusChangeW_Call GetStatusChangeCallW; GetStatusChange_Return GetStatusChangeReturn; ReaderStateW *rgReaderStatesToEncodeW = NULL; BUFFER_LIST_STRUCT *pOutputBuffer = NULL; DWORD i;
if (hContext == NULL) { return (SCARD_E_INVALID_PARAMETER); }
//
// Initialize encoding handle
//
rpcStatus = MesEncodeDynBufferHandleCreate( &pbEncodedBuffer, &cbEncodedBuffer, &h); if (rpcStatus != RPC_S_OK) { ERROR_RETURN(SCARD_E_UNEXPECTED) }
//
// Encode the LocateCards params
//
GetStatusChangeCallW.Context = ((REDIR_LOCAL_SCARDCONTEXT *) hContext)->Context; GetStatusChangeCallW.dwTimeOut = dwTimeout; GetStatusChangeCallW.cReaders = cReaders;
lReturn = _AllocAndCopyReaderStateWStructsForCall( cReaders, &rgReaderStatesToEncodeW, rgReaderStates); if (lReturn != SCARD_S_SUCCESS) { ERROR_RETURN(SCARD_E_NO_MEMORY) }
GetStatusChangeCallW.rgReaderStates = rgReaderStatesToEncodeW;
_TRY_(GetStatusChangeW_Call_Encode(h, &GetStatusChangeCallW))
//
// Make the GetStatusChange call to the client
//
Status = _SendSCardIOCTL( SCARD_IOCTL_GETSTATUSCHANGEW, pbEncodedBuffer, cbEncodedBuffer, &pOutputBuffer); if (Status != STATUS_SUCCESS) { ERROR_RETURN(_MakeSCardError(Status)) } SafeMesHandleFree(&h);
//
// Decode the return
//
rpcStatus = MesDecodeBufferHandleCreate( (char *) pOutputBuffer->pbBytes, pOutputBuffer->cbBytesUsed, &h); if (rpcStatus != RPC_S_OK) { ERROR_RETURN(SCARD_E_UNEXPECTED) }
memset(&GetStatusChangeReturn, 0, sizeof(GetStatusChangeReturn)); _TRY_(GetStatusChange_Return_Decode(h, &GetStatusChangeReturn))
lReturn = GetStatusChangeReturn.ReturnCode;
if (lReturn == SCARD_S_SUCCESS) { //
// Validate return info
//
if (cReaders != GetStatusChangeReturn.cReaders) { ERROR_RETURN(SCARD_E_UNEXPECTED) }
_CopyReaderStateWStructsForReturn( cReaders, rgReaderStates, GetStatusChangeReturn.rgReaderStates); } else if ((lReturn == SCARD_E_SYSTEM_CANCELLED) && (g_hUnifiedStartedEvent != NULL)) { //
// This error indicates that the clients scardsvr service has been stopped,
// so reset the unified started event
//
//OutputDebugString("SCREDIR: SCardGetStatusChangeW: resetting g_hUnifiedStartedEvent\n");
ResetEvent(g_hUnifiedStartedEvent); _SetStartedEventToCorrectState(); }
_TRY_2(GetStatusChange_Return_Free(h, &GetStatusChangeReturn))
Return:
SafeMesHandleFree(&h);
MIDL_user_free(pbEncodedBuffer);
MIDL_user_free(rgReaderStatesToEncodeW);
FreeBuffer(pOutputBuffer);
return (lReturn);
ErrorReturn:
goto Return; }
WINSCARDAPI LONG WINAPI SCardCancel( IN SCARDCONTEXT hContext) { return (I_ContextCallWithLongReturn( hContext, SCARD_IOCTL_CANCEL)); }
//---------------------------------------------------------------------------------------
//
// SCardConnect
//
//---------------------------------------------------------------------------------------
WINSCARDAPI LONG WINAPI I_SCardConnect( IN SCARDCONTEXT hContext, IN LPCBYTE szReader, IN DWORD dwShareMode, IN DWORD dwPreferredProtocols, OUT LPSCARDHANDLE phCard, OUT LPDWORD pdwActiveProtocol, IN BOOL fUnicode) { LONG lReturn = SCARD_S_SUCCESS; NTSTATUS Status = STATUS_SUCCESS; RPC_STATUS rpcStatus = RPC_S_OK; char *pbEncodedBuffer = NULL; unsigned long cbEncodedBuffer = 0; handle_t h = 0; BUFFER_LIST_STRUCT *pOutputBuffer = NULL; ConnectA_Call ConnectCallA; ConnectW_Call ConnectCallW; Connect_Return ConnectReturn;
if ((hContext == NULL) || (phCard == NULL) || (pdwActiveProtocol == NULL)) { return (SCARD_E_INVALID_PARAMETER); } else if (szReader == NULL) { return (SCARD_E_INVALID_VALUE); }
//
// Initialize encoding handle
//
rpcStatus = MesEncodeDynBufferHandleCreate( &pbEncodedBuffer, &cbEncodedBuffer, &h); if (rpcStatus != RPC_S_OK) { ERROR_RETURN(SCARD_E_UNEXPECTED) }
//
// Encode the Connect params
//
ConnectCallA.Common.Context = ConnectCallW.Common.Context = ((REDIR_LOCAL_SCARDCONTEXT *) hContext)->Context; ConnectCallA.Common.dwShareMode = ConnectCallW.Common.dwShareMode = dwShareMode; ConnectCallA.Common.dwPreferredProtocols = ConnectCallW.Common.dwPreferredProtocols = dwPreferredProtocols;
if (fUnicode) { ConnectCallW.szReader = (LPCWSTR) szReader; _TRY_(ConnectW_Call_Encode(h, &ConnectCallW)) } else { ConnectCallA.szReader = (LPCSTR) szReader; _TRY_(ConnectA_Call_Encode(h, &ConnectCallA)) }
//
// Make the ListInterfaces call to the client
//
Status = _SendSCardIOCTL( fUnicode ? SCARD_IOCTL_CONNECTW : SCARD_IOCTL_CONNECTA, pbEncodedBuffer, cbEncodedBuffer, &pOutputBuffer); if (Status != STATUS_SUCCESS) { ERROR_RETURN(_MakeSCardError(Status)) } SafeMesHandleFree(&h);
//
// Decode the return
//
rpcStatus = MesDecodeBufferHandleCreate( (char *) pOutputBuffer->pbBytes, pOutputBuffer->cbBytesUsed, &h); if (rpcStatus != RPC_S_OK) { ERROR_RETURN(SCARD_E_UNEXPECTED) }
memset(&ConnectReturn, 0, sizeof(ConnectReturn)); _TRY_(Connect_Return_Decode(h, &ConnectReturn))
lReturn = ConnectReturn.ReturnCode;
if (lReturn == SCARD_S_SUCCESS) { REDIR_LOCAL_SCARDHANDLE *pRedirHandle = NULL;
//
// The value that represents the SCARDHANDLE on the remote client
// machine is a variable size, so allocate memory to for the struct
// that holds the variable length handle size and pointer, plus
// the actual bytes for the handle, it also holds the context
//
if (ConnectReturn.hCard.cbHandle > MAX_SCARDHANDLE_SIZE) { ERROR_RETURN(SCARD_E_UNEXPECTED) }
pRedirHandle = (REDIR_LOCAL_SCARDHANDLE *) MIDL_user_allocate( sizeof(REDIR_LOCAL_SCARDHANDLE) + ConnectReturn.hCard.cbHandle);
if (pRedirHandle != NULL) { pRedirHandle->pRedirContext = (REDIR_LOCAL_SCARDCONTEXT *) hContext;
pRedirHandle->Handle.Context = ((REDIR_LOCAL_SCARDCONTEXT *) hContext)->Context;
pRedirHandle->Handle.cbHandle = ConnectReturn.hCard.cbHandle; pRedirHandle->Handle.pbHandle = ((BYTE *) pRedirHandle) + sizeof(REDIR_LOCAL_SCARDHANDLE); memcpy( pRedirHandle->Handle.pbHandle, ConnectReturn.hCard.pbHandle, ConnectReturn.hCard.cbHandle);
*phCard = (SCARDHANDLE) pRedirHandle;
// The original Winscard API implements this parameter as
// Optional. We need to preserve that behavior.
if (NULL != pdwActiveProtocol) *pdwActiveProtocol = ConnectReturn.dwActiveProtocol; } else { lReturn = SCARD_E_NO_MEMORY; } }
_TRY_2(Connect_Return_Free(h, &ConnectReturn))
Return:
SafeMesHandleFree(&h);
MIDL_user_free(pbEncodedBuffer);
FreeBuffer(pOutputBuffer);
return (lReturn);
ErrorReturn:
goto Return; }
WINSCARDAPI LONG WINAPI SCardConnectA( IN SCARDCONTEXT hContext, IN LPCSTR szReader, IN DWORD dwShareMode, IN DWORD dwPreferredProtocols, OUT LPSCARDHANDLE phCard, OUT LPDWORD pdwActiveProtocol) { return (I_SCardConnect( hContext, (LPCBYTE) szReader, dwShareMode, dwPreferredProtocols, phCard, pdwActiveProtocol, FALSE)); }
WINSCARDAPI LONG WINAPI SCardConnectW( IN SCARDCONTEXT hContext, IN LPCWSTR szReader, IN DWORD dwShareMode, IN DWORD dwPreferredProtocols, OUT LPSCARDHANDLE phCard, OUT LPDWORD pdwActiveProtocol) { return (I_SCardConnect( hContext, (LPCBYTE) szReader, dwShareMode, dwPreferredProtocols, phCard, pdwActiveProtocol, TRUE)); }
//---------------------------------------------------------------------------------------
//
// SCardReconnect
//
//---------------------------------------------------------------------------------------
WINSCARDAPI LONG WINAPI SCardReconnect( IN SCARDHANDLE hCard, IN DWORD dwShareMode, IN DWORD dwPreferredProtocols, IN DWORD dwInitialization, OUT LPDWORD pdwActiveProtocol) { LONG lReturn = SCARD_S_SUCCESS; NTSTATUS Status = STATUS_SUCCESS; RPC_STATUS rpcStatus = RPC_S_OK; char *pbEncodedBuffer = NULL; unsigned long cbEncodedBuffer = 0; handle_t h = 0; BUFFER_LIST_STRUCT *pOutputBuffer = NULL; Reconnect_Call ReconnectCall; Reconnect_Return ReconnectReturn;
if ((hCard == NULL) || (pdwActiveProtocol == NULL)) { return (SCARD_E_INVALID_PARAMETER); }
//
// Initialize encoding handle
//
rpcStatus = MesEncodeDynBufferHandleCreate( &pbEncodedBuffer, &cbEncodedBuffer, &h); if (rpcStatus != RPC_S_OK) { ERROR_RETURN(SCARD_E_UNEXPECTED) }
//
// Encode the Reconnect params
//
ReconnectCall.hCard = ((REDIR_LOCAL_SCARDHANDLE *) hCard)->Handle; ReconnectCall.dwShareMode = dwShareMode; ReconnectCall.dwPreferredProtocols = dwPreferredProtocols; ReconnectCall.dwInitialization = dwInitialization;
_TRY_(Reconnect_Call_Encode(h, &ReconnectCall))
//
// Make the Reconnect call to the client
//
Status = _SendSCardIOCTL( SCARD_IOCTL_RECONNECT, pbEncodedBuffer, cbEncodedBuffer, &pOutputBuffer); if (Status != STATUS_SUCCESS) { ERROR_RETURN(_MakeSCardError(Status)) } SafeMesHandleFree(&h);
//
// Decode the return
//
rpcStatus = MesDecodeBufferHandleCreate( (char *) pOutputBuffer->pbBytes, pOutputBuffer->cbBytesUsed, &h); if (rpcStatus != RPC_S_OK) { ERROR_RETURN(SCARD_E_UNEXPECTED) }
memset(&ReconnectReturn, 0, sizeof(ReconnectReturn)); _TRY_(Reconnect_Return_Decode(h, &ReconnectReturn))
lReturn = ReconnectReturn.ReturnCode;
if (lReturn == SCARD_S_SUCCESS) { // The original Winscard API implements this parameter as
// Optional. We need to preserve that behavior.
if (NULL != pdwActiveProtocol) *pdwActiveProtocol = ReconnectReturn.dwActiveProtocol; }
_TRY_2(Reconnect_Return_Free(h, &ReconnectReturn))
Return:
SafeMesHandleFree(&h);
MIDL_user_free(pbEncodedBuffer);
FreeBuffer(pOutputBuffer);
return (lReturn);
ErrorReturn:
goto Return; }
//---------------------------------------------------------------------------------------
//
// I_HCardAndDispositionCall
//
//---------------------------------------------------------------------------------------
WINSCARDAPI LONG WINAPI I_HCardAndDispositionCall( IN SCARDHANDLE hCard, IN DWORD dwDisposition, ULONG IoControlCode) { LONG lReturn = SCARD_S_SUCCESS; NTSTATUS Status = STATUS_SUCCESS; RPC_STATUS rpcStatus = RPC_S_OK; char *pbEncodedBuffer = NULL; unsigned long cbEncodedBuffer = 0; handle_t h = 0; BUFFER_LIST_STRUCT *pOutputBuffer = NULL; HCardAndDisposition_Call HCardAndDispositionCall;
if (hCard == NULL) { return (SCARD_E_INVALID_PARAMETER); }
//
// Initialize encoding handle
//
rpcStatus = MesEncodeDynBufferHandleCreate( &pbEncodedBuffer, &cbEncodedBuffer, &h); if (rpcStatus != RPC_S_OK) { ERROR_RETURN(SCARD_E_UNEXPECTED) }
//
// Encode the Reconnect params
//
HCardAndDispositionCall.hCard = ((REDIR_LOCAL_SCARDHANDLE *) hCard)->Handle; HCardAndDispositionCall.dwDisposition = dwDisposition;
_TRY_(HCardAndDisposition_Call_Encode(h, &HCardAndDispositionCall))
//
// Make the Reconnect call to the client
//
Status = _SendSCardIOCTL( IoControlCode, pbEncodedBuffer, cbEncodedBuffer, &pOutputBuffer); if (Status != STATUS_SUCCESS) { ERROR_RETURN(_MakeSCardError(Status)) }
//
// Decode the return
//
lReturn = I_DecodeLongReturn(pOutputBuffer->pbBytes, pOutputBuffer->cbBytesUsed);
Return:
SafeMesHandleFree(&h);
MIDL_user_free(pbEncodedBuffer);
FreeBuffer(pOutputBuffer);
return (lReturn);
ErrorReturn:
goto Return; }
//---------------------------------------------------------------------------------------
//
// SCardDisconnect
//
//---------------------------------------------------------------------------------------
WINSCARDAPI LONG WINAPI SCardDisconnect( IN SCARDHANDLE hCard, IN DWORD dwDisposition) { LONG lReturn = SCARD_S_SUCCESS;
lReturn = I_HCardAndDispositionCall( hCard, dwDisposition, SCARD_IOCTL_DISCONNECT);
MIDL_user_free((REDIR_SCARDHANDLE *) hCard);
return (lReturn); }
//---------------------------------------------------------------------------------------
//
// SCardBeginTransaction
//
//---------------------------------------------------------------------------------------
WINSCARDAPI LONG WINAPI SCardBeginTransaction( IN SCARDHANDLE hCard) { return (I_HCardAndDispositionCall( hCard, 0, // SCardBeginTransaction doesn't use a dispostion, so just set to 0
SCARD_IOCTL_BEGINTRANSACTION)); }
//---------------------------------------------------------------------------------------
//
// SCardEndTransaction
//
//---------------------------------------------------------------------------------------
WINSCARDAPI LONG WINAPI SCardEndTransaction( IN SCARDHANDLE hCard, IN DWORD dwDisposition) { return (I_HCardAndDispositionCall( hCard, dwDisposition, SCARD_IOCTL_ENDTRANSACTION)); }
//---------------------------------------------------------------------------------------
//
// SCardState
//
//---------------------------------------------------------------------------------------
WINSCARDAPI LONG WINAPI SCardState( IN SCARDHANDLE hCard, OUT LPDWORD pdwState, OUT LPDWORD pdwProtocol, OUT LPBYTE pbAtr, IN OUT LPDWORD pcbAtrLen) { LONG lReturn = SCARD_S_SUCCESS; NTSTATUS Status = STATUS_SUCCESS; RPC_STATUS rpcStatus = RPC_S_OK; char *pbEncodedBuffer = NULL; unsigned long cbEncodedBuffer = 0; handle_t h = 0; BUFFER_LIST_STRUCT *pOutputBuffer = NULL; State_Call StateCall; State_Return StateReturn;
if (hCard == NULL) { return (SCARD_E_INVALID_PARAMETER); }
//
// Initialize encoding handle
//
rpcStatus = MesEncodeDynBufferHandleCreate( &pbEncodedBuffer, &cbEncodedBuffer, &h); if (rpcStatus != RPC_S_OK) { ERROR_RETURN(SCARD_E_UNEXPECTED) }
//
// Encode the Reconnect params
//
StateCall.hCard = ((REDIR_LOCAL_SCARDHANDLE *) hCard)->Handle; StateCall.fpbAtrIsNULL = (pbAtr == NULL); StateCall.cbAtrLen = *pcbAtrLen;
_TRY_(State_Call_Encode(h, &StateCall))
//
// Make the Reconnect call to the client
//
Status = _SendSCardIOCTL( SCARD_IOCTL_STATE, pbEncodedBuffer, cbEncodedBuffer, &pOutputBuffer); if (Status != STATUS_SUCCESS) { ERROR_RETURN(_MakeSCardError(Status)) } SafeMesHandleFree(&h);
//
// Decode the return
//
rpcStatus = MesDecodeBufferHandleCreate( (char *) pOutputBuffer->pbBytes, pOutputBuffer->cbBytesUsed, &h); if (rpcStatus != RPC_S_OK) { ERROR_RETURN(SCARD_E_UNEXPECTED) }
memset(&StateReturn, 0, sizeof(StateReturn)); _TRY_(State_Return_Decode(h, &StateReturn))
lReturn = StateReturn.ReturnCode;
if (lReturn == SCARD_S_SUCCESS) { //
// The original Winscard API implements each of these
// parameters as Optional. We need to preserve that behavior.
//
if (NULL != pdwState) *pdwState = StateReturn.dwState;
if (NULL != pdwProtocol) *pdwProtocol = StateReturn.dwProtocol;
if (NULL != pcbAtrLen) { lReturn = _CopyReturnToCallerBuffer( ((REDIR_LOCAL_SCARDHANDLE *) hCard)->pRedirContext, StateReturn.rgAtr, StateReturn.cbAtrLen, pbAtr, pcbAtrLen, BYTE_TYPE_RETURN); } }
_TRY_2(State_Return_Free(h, &StateReturn))
Return:
SafeMesHandleFree(&h);
MIDL_user_free(pbEncodedBuffer);
FreeBuffer(pOutputBuffer);
return (lReturn);
ErrorReturn:
goto Return; }
//---------------------------------------------------------------------------------------
//
// SCardStatus
//
//---------------------------------------------------------------------------------------
WINSCARDAPI LONG WINAPI I_SCardStatus( IN SCARDHANDLE hCard, OUT LPBYTE mszReaderNames, IN OUT LPDWORD pcchReaderLen, OUT LPDWORD pdwState, OUT LPDWORD pdwProtocol, OUT LPBYTE pbAtr, IN OUT LPDWORD pcbAtrLen, IN BOOL fUnicode) { LONG lReturn = SCARD_S_SUCCESS; NTSTATUS Status = STATUS_SUCCESS; RPC_STATUS rpcStatus = RPC_S_OK; char *pbEncodedBuffer = NULL; unsigned long cbEncodedBuffer = 0; handle_t h = 0; BUFFER_LIST_STRUCT *pOutputBuffer = NULL; Status_Call StatusCall; Status_Return StatusReturn;
if (hCard == NULL) { return (SCARD_E_INVALID_PARAMETER); }
//
// Initialize encoding handle
//
rpcStatus = MesEncodeDynBufferHandleCreate( &pbEncodedBuffer, &cbEncodedBuffer, &h); if (rpcStatus != RPC_S_OK) { ERROR_RETURN(SCARD_E_UNEXPECTED) }
//
// Encode the Reconnect params
//
StatusCall.hCard = ((REDIR_LOCAL_SCARDHANDLE *) hCard)->Handle; StatusCall.fmszReaderNamesIsNULL = (mszReaderNames == NULL); StatusCall.cchReaderLen = *pcchReaderLen; StatusCall.cbAtrLen = *pcbAtrLen;
_TRY_(Status_Call_Encode(h, &StatusCall))
//
// Make the Status call to the client
//
Status = _SendSCardIOCTL( fUnicode ? SCARD_IOCTL_STATUSW : SCARD_IOCTL_STATUSA, pbEncodedBuffer, cbEncodedBuffer, &pOutputBuffer); if (Status != STATUS_SUCCESS) { ERROR_RETURN(_MakeSCardError(Status)) } SafeMesHandleFree(&h);
//
// Decode the return
//
rpcStatus = MesDecodeBufferHandleCreate( (char *) pOutputBuffer->pbBytes, pOutputBuffer->cbBytesUsed, &h); if (rpcStatus != RPC_S_OK) { ERROR_RETURN(SCARD_E_UNEXPECTED) }
memset(&StatusReturn, 0, sizeof(StatusReturn)); _TRY_(Status_Return_Decode(h, &StatusReturn))
if (StatusReturn.cbAtrLen > sizeof(StatusReturn.pbAtr)) { ERROR_RETURN(SCARD_E_UNEXPECTED) }
lReturn = StatusReturn.ReturnCode;
if (lReturn == SCARD_S_SUCCESS) { //
// The original Winscard API implements each of these
// parameters as Optional. We need to preserve that behavior.
//
if (NULL != pcchReaderLen) { lReturn = _CopyReturnToCallerBuffer( ((REDIR_LOCAL_SCARDHANDLE *) hCard)->pRedirContext, StatusReturn.mszReaderNames, StatusReturn.cBytes, mszReaderNames, pcchReaderLen, fUnicode ? WSZ_TYPE_RETURN : SZ_TYPE_RETURN); }
if (lReturn == SCARD_S_SUCCESS) { if (NULL != pdwState) *pdwState = StatusReturn.dwState;
if (NULL != pdwProtocol) *pdwProtocol = StatusReturn.dwProtocol;
if (NULL != pcbAtrLen) { if ((NULL != pbAtr) && (*pcbAtrLen >= StatusReturn.cbAtrLen)) { memcpy( pbAtr, StatusReturn.pbAtr, StatusReturn.cbAtrLen); }
*pcbAtrLen = StatusReturn.cbAtrLen; } } }
_TRY_2(Status_Return_Free(h, &StatusReturn))
Return:
SafeMesHandleFree(&h);
MIDL_user_free(pbEncodedBuffer);
FreeBuffer(pOutputBuffer);
return (lReturn);
ErrorReturn:
goto Return; }
WINSCARDAPI LONG WINAPI SCardStatusA( IN SCARDHANDLE hCard, OUT LPSTR mszReaderNames, IN OUT LPDWORD pcchReaderLen, OUT LPDWORD pdwState, OUT LPDWORD pdwProtocol, OUT LPBYTE pbAtr, IN OUT LPDWORD pcbAtrLen) { return (I_SCardStatus( hCard, (LPBYTE) mszReaderNames, pcchReaderLen, pdwState, pdwProtocol, pbAtr, pcbAtrLen, FALSE)); }
WINSCARDAPI LONG WINAPI SCardStatusW( IN SCARDHANDLE hCard, OUT LPWSTR mszReaderNames, IN OUT LPDWORD pcchReaderLen, OUT LPDWORD pdwState, OUT LPDWORD pdwProtocol, OUT LPBYTE pbAtr, IN OUT LPDWORD pcbAtrLen) { return (I_SCardStatus( hCard, (LPBYTE) mszReaderNames, pcchReaderLen, pdwState, pdwProtocol, pbAtr, pcbAtrLen, TRUE)); }
//---------------------------------------------------------------------------------------
//
// SCardTransmit
//
//---------------------------------------------------------------------------------------
WINSCARDAPI LONG WINAPI SCardTransmit( IN SCARDHANDLE hCard, IN LPCSCARD_IO_REQUEST pioSendPci, IN LPCBYTE pbSendBuffer, IN DWORD cbSendLength, IN OUT LPSCARD_IO_REQUEST pioRecvPci, OUT LPBYTE pbRecvBuffer, IN OUT LPDWORD pcbRecvLength) { LONG lReturn = SCARD_S_SUCCESS; NTSTATUS Status = STATUS_SUCCESS; RPC_STATUS rpcStatus = RPC_S_OK; char *pbEncodedBuffer = NULL; unsigned long cbEncodedBuffer = 0; handle_t h = 0; BUFFER_LIST_STRUCT *pOutputBuffer = NULL; Transmit_Call TransmitCall; Transmit_Return TransmitReturn; SCardIO_Request ioRecvPci;
if (hCard == NULL) { return (SCARD_E_INVALID_PARAMETER); }
//
// Initialize encoding handle
//
rpcStatus = MesEncodeDynBufferHandleCreate( &pbEncodedBuffer, &cbEncodedBuffer, &h); if (rpcStatus != RPC_S_OK) { ERROR_RETURN(SCARD_E_UNEXPECTED) }
//
// Encode the Transmit params
//
TransmitCall.hCard = ((REDIR_LOCAL_SCARDHANDLE *) hCard)->Handle; TransmitCall.ioSendPci.dwProtocol = pioSendPci->dwProtocol;
TransmitCall.ioSendPci.cbExtraBytes = pioSendPci->cbPciLength - sizeof(SCARD_IO_REQUEST); if (TransmitCall.ioSendPci.cbExtraBytes != 0) { TransmitCall.ioSendPci.pbExtraBytes = ((BYTE *) pioSendPci) + sizeof(SCARD_IO_REQUEST); } else { TransmitCall.ioSendPci.pbExtraBytes = NULL; }
TransmitCall.cbSendLength = cbSendLength; TransmitCall.pbSendBuffer = pbSendBuffer;
if (pioRecvPci != NULL) { TransmitCall.pioRecvPci = &ioRecvPci; ioRecvPci.dwProtocol = pioRecvPci->dwProtocol; ioRecvPci.cbExtraBytes = pioRecvPci->cbPciLength - sizeof(SCARD_IO_REQUEST); if (ioRecvPci.cbExtraBytes != 0) { ioRecvPci.pbExtraBytes = ((LPBYTE) pioRecvPci) + sizeof(SCARD_IO_REQUEST); } else { ioRecvPci.pbExtraBytes = NULL; } } else { TransmitCall.pioRecvPci = NULL; }
TransmitCall.fpbRecvBufferIsNULL = (pbRecvBuffer == NULL); TransmitCall.cbRecvLength = *pcbRecvLength;
_TRY_(Transmit_Call_Encode(h, &TransmitCall))
//
// Make the Status call to the client
//
Status = _SendSCardIOCTL( SCARD_IOCTL_TRANSMIT, pbEncodedBuffer, cbEncodedBuffer, &pOutputBuffer); if (Status != STATUS_SUCCESS) { ERROR_RETURN(_MakeSCardError(Status)) } SafeMesHandleFree(&h);
//
// Decode the return
//
rpcStatus = MesDecodeBufferHandleCreate( (char *) pOutputBuffer->pbBytes, pOutputBuffer->cbBytesUsed, &h); if (rpcStatus != RPC_S_OK) { ERROR_RETURN(SCARD_E_UNEXPECTED) }
memset(&TransmitReturn, 0, sizeof(TransmitReturn)); _TRY_(Transmit_Return_Decode(h, &TransmitReturn))
lReturn = TransmitReturn.ReturnCode;
if (lReturn == SCARD_S_SUCCESS) { if ((pioRecvPci != NULL) && (TransmitReturn.pioRecvPci != NULL)) { pioRecvPci->dwProtocol = TransmitReturn.pioRecvPci->dwProtocol; if ((TransmitReturn.pioRecvPci->cbExtraBytes != 0) && (TransmitReturn.pioRecvPci->cbExtraBytes <= (pioSendPci->cbPciLength - sizeof(SCARD_IO_REQUEST)))) { memcpy( ((LPBYTE) pioRecvPci) + sizeof(SCARD_IO_REQUEST), TransmitReturn.pioRecvPci->pbExtraBytes, TransmitReturn.pioRecvPci->cbExtraBytes); } }
lReturn = _CopyReturnToCallerBuffer( ((REDIR_LOCAL_SCARDHANDLE *) hCard)->pRedirContext, TransmitReturn.pbRecvBuffer, TransmitReturn.cbRecvLength, pbRecvBuffer, pcbRecvLength, BYTE_TYPE_RETURN); }
_TRY_2(Transmit_Return_Free(h, &TransmitReturn))
Return:
SafeMesHandleFree(&h);
MIDL_user_free(pbEncodedBuffer);
FreeBuffer(pOutputBuffer);
return (lReturn);
ErrorReturn:
goto Return; }
//---------------------------------------------------------------------------------------
//
// SCardControl
//
//---------------------------------------------------------------------------------------
WINSCARDAPI LONG WINAPI SCardControl( IN SCARDHANDLE hCard, IN DWORD dwControlCode, IN LPCVOID pvInBuffer, IN DWORD cbInBufferSize, OUT LPVOID pvOutBuffer, IN DWORD cbOutBufferSize, OUT LPDWORD pcbBytesReturned) { LONG lReturn = SCARD_S_SUCCESS; NTSTATUS Status = STATUS_SUCCESS; RPC_STATUS rpcStatus = RPC_S_OK; char *pbEncodedBuffer = NULL; unsigned long cbEncodedBuffer = 0; handle_t h = 0; BUFFER_LIST_STRUCT *pOutputBuffer = NULL; Control_Call ControlCall; Control_Return ControlReturn;
if (hCard == NULL) { return (SCARD_E_INVALID_PARAMETER); }
//
// Initialize encoding handle
//
rpcStatus = MesEncodeDynBufferHandleCreate( &pbEncodedBuffer, &cbEncodedBuffer, &h); if (rpcStatus != RPC_S_OK) { ERROR_RETURN(SCARD_E_UNEXPECTED) }
//
// Encode the Control params
//
ControlCall.hCard = ((REDIR_LOCAL_SCARDHANDLE *) hCard)->Handle; ControlCall.dwControlCode = dwControlCode; ControlCall.cbInBufferSize = cbInBufferSize; ControlCall.pvInBuffer = (LPCBYTE) pvInBuffer; ControlCall.fpvOutBufferIsNULL = (pvOutBuffer == NULL); ControlCall.cbOutBufferSize = cbOutBufferSize;
_TRY_(Control_Call_Encode(h, &ControlCall))
//
// Make the Control call to the client
//
Status = _SendSCardIOCTL( SCARD_IOCTL_CONTROL, pbEncodedBuffer, cbEncodedBuffer, &pOutputBuffer); if (Status != STATUS_SUCCESS) { ERROR_RETURN(_MakeSCardError(Status)) } SafeMesHandleFree(&h);
//
// Decode the return
//
rpcStatus = MesDecodeBufferHandleCreate( (char *) pOutputBuffer->pbBytes, pOutputBuffer->cbBytesUsed, &h); if (rpcStatus != RPC_S_OK) { ERROR_RETURN(SCARD_E_UNEXPECTED) }
memset(&ControlReturn, 0, sizeof(ControlReturn)); _TRY_(Control_Return_Decode(h, &ControlReturn))
lReturn = ControlReturn.ReturnCode;
if (lReturn == SCARD_S_SUCCESS) { *pcbBytesReturned = ControlReturn.cbOutBufferSize; lReturn = _CopyReturnToCallerBuffer( ((REDIR_LOCAL_SCARDHANDLE *) hCard)->pRedirContext, ControlReturn.pvOutBuffer, ControlReturn.cbOutBufferSize, (LPBYTE) pvOutBuffer, pcbBytesReturned, BYTE_TYPE_RETURN); }
_TRY_2(Control_Return_Free(h, &ControlReturn))
Return:
SafeMesHandleFree(&h);
MIDL_user_free(pbEncodedBuffer);
FreeBuffer(pOutputBuffer);
return (lReturn);
ErrorReturn:
goto Return; }
//---------------------------------------------------------------------------------------
//
// SCardGetAttrib
//
//---------------------------------------------------------------------------------------
WINSCARDAPI LONG WINAPI SCardGetAttrib( IN SCARDHANDLE hCard, IN DWORD dwAttrId, OUT LPBYTE pbAttr, IN OUT LPDWORD pcbAttrLen) { LONG lReturn = SCARD_S_SUCCESS; NTSTATUS Status = STATUS_SUCCESS; RPC_STATUS rpcStatus = RPC_S_OK; char *pbEncodedBuffer = NULL; unsigned long cbEncodedBuffer = 0; handle_t h = 0; BUFFER_LIST_STRUCT *pOutputBuffer = NULL; GetAttrib_Call GetAttribCall; GetAttrib_Return GetAttribReturn;
if (hCard == NULL) { return (SCARD_E_INVALID_PARAMETER); }
//
// Initialize encoding handle
//
rpcStatus = MesEncodeDynBufferHandleCreate( &pbEncodedBuffer, &cbEncodedBuffer, &h); if (rpcStatus != RPC_S_OK) { ERROR_RETURN(SCARD_E_UNEXPECTED) }
//
// Encode the GetAttrib params
//
GetAttribCall.hCard = ((REDIR_LOCAL_SCARDHANDLE *) hCard)->Handle; GetAttribCall.dwAttrId = dwAttrId;; GetAttribCall.fpbAttrIsNULL = (pbAttr == NULL); GetAttribCall.cbAttrLen = *pcbAttrLen;
_TRY_(GetAttrib_Call_Encode(h, &GetAttribCall))
//
// Make the GetAttrib call to the client
//
Status = _SendSCardIOCTL( SCARD_IOCTL_GETATTRIB, pbEncodedBuffer, cbEncodedBuffer, &pOutputBuffer); if (Status != STATUS_SUCCESS) { ERROR_RETURN(_MakeSCardError(Status)) } SafeMesHandleFree(&h);
//
// Decode the return
//
rpcStatus = MesDecodeBufferHandleCreate( (char *) pOutputBuffer->pbBytes, pOutputBuffer->cbBytesUsed, &h); if (rpcStatus != RPC_S_OK) { ERROR_RETURN(SCARD_E_UNEXPECTED) }
memset(&GetAttribReturn, 0, sizeof(GetAttribReturn)); _TRY_(GetAttrib_Return_Decode(h, &GetAttribReturn))
lReturn = GetAttribReturn.ReturnCode;
if (lReturn == SCARD_S_SUCCESS) { lReturn = _CopyReturnToCallerBuffer( ((REDIR_LOCAL_SCARDHANDLE *) hCard)->pRedirContext, GetAttribReturn.pbAttr, GetAttribReturn.cbAttrLen, (LPBYTE) pbAttr, pcbAttrLen, BYTE_TYPE_RETURN); }
_TRY_2(GetAttrib_Return_Free(h, &GetAttribReturn))
Return:
SafeMesHandleFree(&h);
MIDL_user_free(pbEncodedBuffer);
FreeBuffer(pOutputBuffer);
return (lReturn);
ErrorReturn:
goto Return; }
//---------------------------------------------------------------------------------------
//
// SCardSetAttrib
//
//---------------------------------------------------------------------------------------
WINSCARDAPI LONG WINAPI SCardSetAttrib( IN SCARDHANDLE hCard, IN DWORD dwAttrId, IN LPCBYTE pbAttr, IN DWORD cbAttrLen) { LONG lReturn = SCARD_S_SUCCESS; NTSTATUS Status = STATUS_SUCCESS; RPC_STATUS rpcStatus = RPC_S_OK; char *pbEncodedBuffer = NULL; unsigned long cbEncodedBuffer = 0; handle_t h = 0; BUFFER_LIST_STRUCT *pOutputBuffer = NULL; SetAttrib_Call SetAttribCall;
if (hCard == NULL) { return (SCARD_E_INVALID_PARAMETER); }
//
// Initialize encoding handle
//
rpcStatus = MesEncodeDynBufferHandleCreate( &pbEncodedBuffer, &cbEncodedBuffer, &h); if (rpcStatus != RPC_S_OK) { ERROR_RETURN(SCARD_E_UNEXPECTED) }
//
// Encode the SetAttrib params
//
SetAttribCall.hCard = ((REDIR_LOCAL_SCARDHANDLE *) hCard)->Handle; SetAttribCall.dwAttrId = dwAttrId;; SetAttribCall.pbAttr = pbAttr; SetAttribCall.cbAttrLen = cbAttrLen;
_TRY_(SetAttrib_Call_Encode(h, &SetAttribCall))
//
// Make the SetAttrib call to the client
//
Status = _SendSCardIOCTL( SCARD_IOCTL_SETATTRIB, pbEncodedBuffer, cbEncodedBuffer, &pOutputBuffer); if (Status != STATUS_SUCCESS) { ERROR_RETURN(_MakeSCardError(Status)) }
//
// Decode the return
//
lReturn = I_DecodeLongReturn(pOutputBuffer->pbBytes, pOutputBuffer->cbBytesUsed);
Return:
SafeMesHandleFree(&h);
MIDL_user_free(pbEncodedBuffer);
FreeBuffer(pOutputBuffer);
return (lReturn);
ErrorReturn:
goto Return; }
//---------------------------------------------------------------------------------------
//
// SCardAccessStartedEvent
//
//---------------------------------------------------------------------------------------
WINSCARDAPI HANDLE WINAPI SCardAccessStartedEvent(void) { HANDLE h;
h = _GetStartedEventHandle();
if ((h == NULL) || !_SetStartedEventToCorrectState()) { //
// Either we couldn't create the event, or we couldn't start the thread to set
// the event, so return NULL
//
return (NULL); }
//
// Check to see if the event is already set, if not, give the thread which sets
// the event a chance to run and set the event before returning
//
if (WAIT_OBJECT_0 != WaitForSingleObject(h, 0)) { WaitForSingleObject(h, 10); }
//
// This API has old semantics where it just return the handle straight away
// instead of duplicating it.
//
return (h); }
//---------------------------------------------------------------------------------------
//
// SCardReleaseStartedEvent
//
//---------------------------------------------------------------------------------------
WINSCARDAPI void WINAPI SCardReleaseStartedEvent(void) { return; }
//---------------------------------------------------------------------------------------
//
// SCardReleaseBadContext
//
//---------------------------------------------------------------------------------------
WINSCARDAPI LONG WINAPI SCardReleaseBadContext( IN SCARDCONTEXT hContext) { MIDL_user_free((REDIR_LOCAL_SCARDCONTEXT *) hContext); return (SCARD_S_SUCCESS); }
|