windows-nt/Source/XPSP1/NT/drivers/smartcrd/smclib/vxd/smcvxd.c
2020-09-26 16:20:57 +08:00

1377 lines
30 KiB
C

/*++
Copyright (c) 1997 Microsoft Corporation
Module Name:
smcvxd.c
Abstract:
This is the Windows 9x specific driver file for the smart card library.
The smart card library is actually more a library as a driver.
It contains support functions for smart card driver/reader systems.
This driver should be loaded through an entry in the registry.
Environment:
Windows 9x Static VxD
Notes:
Revision History:
- Created June 1997 by Klaus Schutz
--*/
#define _ISO_TABLES_
#define WIN40SERVICES
#include "..\..\inc\smclib.h"
#define REGISTRY_PATH_LEN 128
static PUCHAR DevicePath = "System\\CurrentControlSet\\Services\\VxD\\Smclib\\Devices";
static BOOLEAN DriverInitialized;
#include "errmap.h"
DWORD
_stdcall
SMCLIB_Init(void)
/*++
Routine Description:
This function will be called by the Windows Kernel upon init of this driver
Arguments:
-
Return Value:
VXD_SUCCESS - This driver loaded successfully
VXD_FAILURE - Load was not successful
--*/
{
if (DriverInitialized == FALSE) {
HANDLE hKey;
ULONG i;
DriverInitialized = TRUE;
SmartcardDebug(
DEBUG_DRIVER,
("%s(SMCLIB_Init): Enter. %s %s\n",
DRIVER_NAME,
__DATE__,
__TIME__)
);
//
// Delete old device names
//
if(_RegOpenKey(
HKEY_LOCAL_MACHINE,
DevicePath,
&hKey
) != ERROR_SUCCESS) {
SmartcardDebug(
DEBUG_ERROR,
("%s(SMCLIB_Init): Unable to open registry key\n",
DRIVER_NAME)
);
} else {
_RegDeleteKey(
hKey,
""
);
_RegCloseKey(hKey);
}
//
// Create new device sub-key
//
_RegCreateKey(
HKEY_LOCAL_MACHINE,
DevicePath,
&hKey
);
_RegCloseKey(hKey);
}
return(VXD_SUCCESS);
}
ULONG
SMCLIB_MapNtStatusToWinError(
NTSTATUS status
)
/*++
Routine Description:
Maps a NT status code to a Win32 error value
Arguments:
status - nt status code to map to a Win32 error value
Return Value:
Win32 error value
--*/
{
ULONG i;
for (i = 0;i < sizeof(CodePairs) / sizeof(CodePairs[0]); i += 2) {
if (CodePairs[i] == status) {
return CodePairs[i + 1];
}
}
SmartcardDebug(
DEBUG_ERROR,
("%s(MapNtStatusToWinError): NTSTATUS %lx unknown\n",
DRIVER_NAME,
status)
);
//
// We were unable to map the error code
//
return ERROR_GEN_FAILURE;
}
void
SMCLIB_Assert(
PVOID FailedAssertion,
PVOID FileName,
ULONG LineNumber,
PCHAR Message
)
/*++
Routine Description:
This is a simple assert function that gets called using the ASSERT
macro. Windows 9x does not offer this functionality
Arguments:
FailedAssertion - The assertion we tested
FileName - Yes, this is the name of the source file
LineNumber - What might this be ?
Message - An additional message supplied using ASSERTMSG
Return Value:
-
--*/
{
#ifdef DEBUG
Debug_Printf(
"Assertion Failed: %s in %s(%ld)",
FailedAssertion,
FileName,
LineNumber
);
if (Message)
Debug_Printf(" %s",Message);
Debug_Printf("\n");
#endif
}
//#ifdef _vmm_add_ddb_to_do
BOOL
VXDINLINE
_VMM_Add_DDB(
struct VxD_Desc_Block *pDeviceDDB
)
/*++
Routine Description:
This routine is used to create a new device instance for a driver
that supports multiple instances - like a serial based driver that
supports more than one device -
Arguments:
pDeviceDDB - The DDB struct that is to be added to the system
Return Value:
TRUE - Yope, it worked
FALSE - Out of business (May be the device name already exists)
--*/
{
_asm mov edi, pDeviceDDB
VxDCall(VMM_Add_DDB)
_asm {
mov eax, 1
jnc exit
mov eax, 0
exit:
}
}
BOOL
VXDINLINE
_VMM_Remove_DDB(
struct VxD_Desc_Block *pDeviceDDB
)
/*++
Routine Description:
Removes a DDB (device) that was created using VMM_Add_DDB
Arguments:
The address of the DDB to remove
Return Value:
TRUE - OK, DDB removed otherwise FALSE
--*/
{
_asm mov edi, pDeviceDDB
VxDCall(VMM_Remove_DDB)
_asm {
mov eax, 1
jnc exit
mov eax, 0
exit:
}
}
//#endif
PVMMDDB
SMCLIB_VxD_CreateDevice(
char *Device,
void (*ControlProc)(void)
)
/*++
Routine Description:
Creates a new device. This routine allows a driver to create additional devices.
Arguments:
Device - Name of the device to be created. At most 8 characters
ControlProc - Address of the VxD control procedure. (NOT the DeviceIoControl function!)
Return Value:
The newly created DDB if successful or NULL otherwise
--*/
{
PVMMDDB pDDB;
UCHAR DeviceName[9];
ASSERT(Device != NULL);
ASSERT(strlen(Device) <= 8);
ASSERT(ControlProc != NULL);
if (strlen(Device) > 8) {
return NULL;
}
_Sprintf(DeviceName, "%-8s", Device);
//
// Allocate space for the VxD description block
//
pDDB = (PVMMDDB) _HeapAllocate(
sizeof(struct VxD_Desc_Block),
HEAPZEROINIT
);
if (pDDB)
{
pDDB->DDB_SDK_Version = DDK_VERSION;
pDDB->DDB_Req_Device_Number = UNDEFINED_DEVICE_ID;
pDDB->DDB_Dev_Major_Version = 1;
pDDB->DDB_Dev_Minor_Version = 0;
memcpy(pDDB->DDB_Name, DeviceName, 8);
pDDB->DDB_Init_Order = UNDEFINED_INIT_ORDER;
pDDB->DDB_Control_Proc = (ULONG) ControlProc;
pDDB->DDB_Reference_Data = 0;
pDDB->DDB_Prev = 'Prev';
pDDB->DDB_Size = sizeof(struct VxD_Desc_Block);
pDDB->DDB_Reserved1 = 'Rsv1';
pDDB->DDB_Reserved2 = 'Rsv2';
pDDB->DDB_Reserved3 = 'Rsv3';
//
// Now create the DDB
//
if (!_VMM_Add_DDB(pDDB)) {
_HeapFree(pDDB, 0);
return NULL;
}
}
return pDDB;
}
BOOL
SMCLIB_VxD_DeleteDevice(
PVMMDDB pDDB
)
/*++
Routine Description:
Deleted a device. This function can be used to delete
a device that was created using VxD_CreateDevice
Arguments:
pDDB - The DDB to be deleted
Return Value:
TRUE - device successfully deleted
FALSE - device not deleted
--*/
{
ASSERT(pDDB != NULL);
if(pDDB == NULL || !_VMM_Remove_DDB(pDDB)) {
return FALSE;
}
_HeapFree(pDDB, 0);
return TRUE;
}
DWORD
_stdcall
VxD_PageLock(
DWORD lpMem,
DWORD cbSize
)
/*++
Routine Description:
This function lock the page
Arguments:
lpMem - pointer to the datablock which has to be locked
cbSize - length of the datablock
Return Value:
- pointer to the locked datablock
--*/
{
DWORD LinPageNum;
DWORD LinOffset;
DWORD nPages;
DWORD dwRet;
LinOffset = lpMem & 0xfff; // page offset of memory to map
LinPageNum = lpMem >> 12; // generate page number
// Calculate # of pages to map globally
nPages = ((lpMem + cbSize) >> 12) - LinPageNum + 1;
//
// Return global mapping of passed in pointer, as this new pointer
// is how the memory must be accessed out of context.
//
dwRet = _LinPageLock(LinPageNum, nPages, PAGEMAPGLOBAL | PAGEMARKDIRTY);
ASSERT(dwRet != 0);
SmartcardDebug(
DEBUG_ERROR,
("%s!VxD_PageLock: LinPageNum = %lx, nPages = %lx, dwRet = %lx\n",
DRIVER_NAME,
LinPageNum,
nPages,
dwRet)
);
return (dwRet + LinOffset);
}
void
_stdcall
VxD_PageUnlock(
DWORD lpMem,
DWORD cbSize
)
/*++
Routine Description:
This function unlocks a datablock
Arguments:
lpMem - pointer to the datablock which has to be unlocked
cbSize - length of the datablock
Return Value:
-
--*/
{
DWORD LinPageNum;
DWORD nPages;
DWORD dwRet;
LinPageNum = lpMem >> 12;
nPages = ((lpMem + cbSize) >> 12) - LinPageNum + 1;
SmartcardDebug(
DEBUG_ERROR,
("%s!VxD_PageUnlock: LinPageNum = %lx, nPages = %lx\n",
DRIVER_NAME,
LinPageNum,
nPages)
);
// Free globally mapped memory
dwRet = _LinPageUnlock(LinPageNum, nPages, PAGEMAPGLOBAL);
ASSERT(dwRet != 0);
}
void
SMCLIB_SmartcardCompleteCardTracking(
PSMARTCARD_EXTENSION SmartcardExtension
)
/*++
Routine Description:
This routine calls i/o completion for the pending
card tracking operation. It also unlocks the previously
locked memory that was used for the overlapped strucutre
Arguments:
SmartcardExtension
Return Value:
-
--*/
{
if (SmartcardExtension->OsData->NotificationOverlappedData) {
DWORD O_Internal = SmartcardExtension->OsData->NotificationOverlappedData->O_Internal;
SmartcardDebug(
DEBUG_ERROR,
("%s(SmartcardCompleteCardTracking): Completing %lx\n",
DRIVER_NAME,
SmartcardExtension->OsData->NotificationOverlappedData)
);
//
// set number of bytes returned to 0
//
SmartcardExtension->OsData->NotificationOverlappedData->O_InternalHigh = 0;
_asm mov ebx, O_Internal
VxDCall(VWIN32_DIOCCompletionRoutine)
_HeapFree(
SmartcardExtension->OsData->NotificationOverlappedData,
0
);
SmartcardExtension->OsData->NotificationOverlappedData = NULL;
}
}
void
SMCLIB_SmartcardCompleteRequest(
PSMARTCARD_EXTENSION SmartcardExtension
)
/*++
Routine Description:
This routine calls i/o completion for a pending
io operation. It also unlocks the previously
locked memory that was used for the overlapped structure
Arguments:
SmartcardExtension
Return Value:
-
--*/
{
DWORD O_Internal = SmartcardExtension->OsData->CurrentOverlappedData->O_Internal;
_asm mov ebx, O_Internal
VxDCall(VWIN32_DIOCCompletionRoutine)
VxD_PageUnlock(
(DWORD) SmartcardExtension->OsData->CurrentOverlappedData,
sizeof(OVERLAPPED)
);
VxD_PageUnlock(
(DWORD) SmartcardExtension->IoRequest.RequestBuffer,
SmartcardExtension->IoRequest.RequestBufferLength
);
VxD_PageUnlock(
(DWORD) SmartcardExtension->IoRequest.ReplyBuffer,
SmartcardExtension->IoRequest.ReplyBufferLength
);
SmartcardExtension->OsData->CurrentDiocParams = NULL;
}
NTSTATUS
SMCLIB_SmartcardCreateLink(
PUCHAR LinkName,
PUCHAR DeviceName
)
/*++
Routine Description:
This routine creates a symbolic link name for the given device name.
It means it creates a 'STRING-value' in the registry ..VxD\smclib\devices
like SCReader[0-9] = DeviceName.
The smart card resource manager uses these entries in order to figure out
what smart card devices are currently running.
We do this because we don't have the ability to create a dynamic device
name like we can do in Windows NT.
Arguments:
LinkName - receives the created link name
DeviceName - the device name for which the link should be created
Return Value:
NTSTATUS
--*/
{
PUCHAR Value;
ULONG i;
HANDLE hKey;
if (DriverInitialized == FALSE) {
SMCLIB_Init();
}
SmartcardDebug(
DEBUG_TRACE,
("%s(SmartcardCreateLink): Enter\n",
DRIVER_NAME)
);
ASSERT(LinkName != NULL);
ASSERT(DeviceName != NULL);
ASSERT(strlen(DeviceName) <= 12);
if (LinkName == NULL) {
return STATUS_INVALID_PARAMETER_1;
}
if (DeviceName == NULL) {
return STATUS_INVALID_PARAMETER_2;
}
//
// Open the key where the device names are stored
//
if(_RegOpenKey(
HKEY_LOCAL_MACHINE,
DevicePath,
&hKey
) != ERROR_SUCCESS) {
return STATUS_UNSUCCESSFUL;
}
//
// Allocate a buffer for enumeration of the registry
//
Value = (PUCHAR) _HeapAllocate(REGISTRY_PATH_LEN, 0);
if (Value == NULL) {
SmartcardDebug(
DEBUG_ERROR,
("%s(SmartcardCreateLink): Allocation failed\n",
DRIVER_NAME)
);
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// Now find a free device name
//
for (i = 0; i < MAXIMUM_SMARTCARD_READERS ; i++) {
_Sprintf(
Value,
"SCReader%d",
i
);
//
// Check for existence of the key
//
if(_RegQueryValueEx(
hKey,
Value,
NULL,
NULL,
NULL,
NULL
) != ERROR_SUCCESS) {
break;
}
}
//
// Free the buffer since we don't need it anymore
//
_HeapFree(Value, 0);
if (i >= MAXIMUM_SMARTCARD_READERS) {
SmartcardDebug(
DEBUG_ERROR,
("%s(SmartcardCreateLink): Can't create link: Too many readers\n",
DRIVER_NAME)
);
return STATUS_UNSUCCESSFUL;
}
//
// Create the link name...
//
_Sprintf(
LinkName,
"SCReader%d",
i
);
//
// ...and store it in the registry
//
_RegSetValueEx(
hKey,
LinkName,
NULL,
REG_SZ,
DeviceName,
strlen(DeviceName)
);
_RegCloseKey(hKey);
SmartcardDebug(
DEBUG_DRIVER,
("%s(SmartcardCreateLink): Link %s created for Driver %s\n",
DRIVER_NAME,
LinkName,
DeviceName)
);
SmartcardDebug(
DEBUG_TRACE,
("%s(SmartcardCreateLink): Exit\n",
DRIVER_NAME)
);
return STATUS_SUCCESS;
}
NTSTATUS
SMCLIB_SmartcardDeleteLink(
PUCHAR LinkName
)
/*++
Routine Description:
Deletes the link previously created with SmartcardCreateLink()
This routine deletes the symbolic link name that is stored in the
registry. A driver ususally calls this function upon unload.
Arguments:
LinkName - The link that is to be deleted
Return Value:
NTSTATUS
--*/
{
HANDLE hKey;
NTSTATUS status;
SmartcardDebug(
DEBUG_TRACE,
("%s(SmartcardDeleteLink): Enter\n",
DRIVER_NAME)
);
ASSERT(LinkName);
ASSERT(strlen(LinkName) <= 10);
//
// Open the key where the device names are stored
//
if(_RegOpenKey(
HKEY_LOCAL_MACHINE,
DevicePath,
&hKey
) != ERROR_SUCCESS) {
return STATUS_UNSUCCESSFUL;
}
if(_RegDeleteValue(
hKey,
LinkName
) == ERROR_SUCCESS) {
SmartcardDebug(
DEBUG_DRIVER,
("%s(SmartcardDeleteLink): Link %s deleted\n",
DRIVER_NAME,
LinkName)
);
status = STATUS_SUCCESS;
} else {
SmartcardDebug(
DEBUG_ERROR,
("%s(SmartcardDeleteLink): Can't delete link %s\n",
DRIVER_NAME,
LinkName)
);
status = STATUS_UNSUCCESSFUL;
}
_RegCloseKey(hKey);
SmartcardDebug(
DEBUG_TRACE,
("%s(SmartcardDeleteLink): Exit",
DRIVER_NAME)
);
return status;
}
NTSTATUS
SMCLIB_SmartcardInitialize(
PSMARTCARD_EXTENSION SmartcardExtension
)
/*++
Routine Description:
This function allocated the send and receive buffers for smart card
data. It also sets the pointer to 2 ISO tables to make them accessible
to the driver
Arguments:
SmartcardExtension
Return Value:
NTSTATUS
--*/
{
NTSTATUS status = STATUS_SUCCESS;
SmartcardDebug(
DEBUG_TRACE,
("%s(SmartcardInitialize): Enter - Version %lx, %s %s\n",
DRIVER_NAME,
SMCLIB_VERSION,
__DATE__,
__TIME__)
);
ASSERT(SmartcardExtension != NULL);
ASSERT(SmartcardExtension->OsData == NULL);
if (SmartcardExtension == NULL) {
return STATUS_INVALID_PARAMETER;
}
if (SmartcardExtension->Version < SMCLIB_VERSION_REQUIRED) {
SmartcardDebug(
DEBUG_ERROR,
("%s(SmartcardInitialize): Invalid Version in SMARTCARD_EXTENSION. Must be %lx\n",
DRIVER_NAME,
SMCLIB_VERSION)
);
return STATUS_UNSUCCESSFUL;
}
if (SmartcardExtension->SmartcardRequest.BufferSize < MIN_BUFFER_SIZE) {
SmartcardDebug(
DEBUG_ERROR,
("%s(SmartcardInitialize): WARNING: SmartcardRequest.BufferSize (%ld) < MIN_BUFFER_SIZE (%ld)\n",
DRIVER_NAME,
SmartcardExtension->SmartcardRequest.BufferSize,
MIN_BUFFER_SIZE)
);
SmartcardExtension->SmartcardRequest.BufferSize = MIN_BUFFER_SIZE;
}
if (SmartcardExtension->SmartcardReply.BufferSize < MIN_BUFFER_SIZE) {
SmartcardDebug(
DEBUG_ERROR,
("%s(SmartcardInitialize): WARNING: SmartcardReply.BufferSize (%ld) < MIN_BUFFER_SIZE (%ld)\n",
DRIVER_NAME,
SmartcardExtension->SmartcardReply.BufferSize,
MIN_BUFFER_SIZE)
);
SmartcardExtension->SmartcardReply.BufferSize = MIN_BUFFER_SIZE;
}
SmartcardExtension->SmartcardRequest.Buffer = _HeapAllocate(
SmartcardExtension->SmartcardRequest.BufferSize,
0
);
SmartcardExtension->SmartcardReply.Buffer = _HeapAllocate(
SmartcardExtension->SmartcardReply.BufferSize,
0
);
SmartcardExtension->OsData = _HeapAllocate(
sizeof(OS_DEP_DATA),
0
);
//
// Check if one of the above allocations failed
//
if (SmartcardExtension->SmartcardRequest.Buffer == NULL ||
SmartcardExtension->SmartcardReply.Buffer == NULL ||
SmartcardExtension->OsData == NULL) {
status = STATUS_INSUFFICIENT_RESOURCES;
if (SmartcardExtension->SmartcardRequest.Buffer) {
_HeapFree(SmartcardExtension->SmartcardRequest.Buffer, 0);
}
if (SmartcardExtension->SmartcardReply.Buffer) {
_HeapFree(SmartcardExtension->SmartcardReply.Buffer, 0);
}
if (SmartcardExtension->OsData == NULL) {
_HeapFree(SmartcardExtension->OsData, 0);
}
}
if (status != STATUS_SUCCESS) {
return status;
}
memset(SmartcardExtension->OsData, 0, sizeof(OS_DEP_DATA));
//
// Create mutex that is used to synch access to the driver
//
SmartcardExtension->OsData->Mutex = _CreateMutex(0, 0);
//
// Make the 2 ISO tables accessible to the driver
//
SmartcardExtension->CardCapabilities.ClockRateConversion =
&ClockRateConversion[0];
SmartcardExtension->CardCapabilities.BitRateAdjustment =
&BitRateAdjustment[0];
SmartcardDebug(
DEBUG_TRACE,
("%s(SmartcardInitialize): Exit\n",
DRIVER_NAME)
);
return status;
}
VOID
SMCLIB_SmartcardExit(
PSMARTCARD_EXTENSION SmartcardExtension
)
/*++
Routine Description:
This routine frees the send and receive buffer.
It is usually called when the driver unloads.
Arguments:
SmartcardExtension
Return Value:
NTSTATUS
--*/
{
SmartcardDebug(
DEBUG_TRACE,
("%s(SmartcardExit): Enter\n",
DRIVER_NAME)
);
if (SmartcardExtension->SmartcardRequest.Buffer) {
_HeapFree(SmartcardExtension->SmartcardRequest.Buffer, 0);
}
if (SmartcardExtension->SmartcardReply.Buffer) {
_HeapFree(SmartcardExtension->SmartcardReply.Buffer, 0);
}
if (SmartcardExtension->OsData) {
_HeapFree(SmartcardExtension->OsData, 0);
}
SmartcardDebug(
DEBUG_TRACE,
("%s(SmartcardExit): Exit\n",
DRIVER_NAME)
);
}
VOID
SMCLIB_SmartcardLogError(
)
/*++
Routine Description:
This routine allocates an error log entry, copies the supplied data
to it, and requests that it be written to the error log file.
Arguments:
Return Value:
--*/
{
SmartcardDebug(
DEBUG_ERROR,
("%s(SmartcardLogError): Not yet implemented\n",
DRIVER_NAME)
);
}
NTSTATUS
SMCLIB_SmartcardDeviceControl(
PSMARTCARD_EXTENSION SmartcardExtension,
DIOCPARAMETERS *lpDiocParams
)
/*++
Routine Description:
The routine is the general device control dispatch function for VxD drivers.
Arguments:
SmartcardExtension - The pointer to the smart card datae
lpDiocParams - struct containing the caller parameter
Return Value:
NTSTATUS
--*/
{
NTSTATUS status = STATUS_SUCCESS;
ASSERT(SmartcardExtension != NULL);
if (SmartcardExtension == NULL) {
return STATUS_INVALID_PARAMETER_1;
}
ASSERT(lpDiocParams != NULL);
if (lpDiocParams == NULL) {
return STATUS_INVALID_PARAMETER_2;
}
ASSERT(lpDiocParams->lpoOverlapped != 0);
if (lpDiocParams->lpoOverlapped == 0) {
return STATUS_INVALID_PARAMETER;
}
// Check the version that the driver requires
ASSERT(SmartcardExtension->Version >= SMCLIB_VERSION_REQUIRED);
if (SmartcardExtension->Version < SMCLIB_VERSION_REQUIRED) {
return STATUS_INVALID_PARAMETER;
}
// Synchronize access to the driver
_EnterMutex(
SmartcardExtension->OsData->Mutex,
BLOCK_SVC_INTS | BLOCK_THREAD_IDLE
);
if (status == STATUS_SUCCESS) {
SmartcardDebug(
DEBUG_IOCTL,
("SMCLIB(SmartcardDeviceControl): Ioctl = %s, DIOCP = %lx\n",
MapIoControlCodeToString(lpDiocParams->dwIoControlCode),
lpDiocParams)
);
// Return if device is busy
if (SmartcardExtension->OsData->CurrentDiocParams != NULL) {
SmartcardDebug(
DEBUG_IOCTL,
("%s(SmartcardDeviceControl): Device is busy\n",
DRIVER_NAME)
);
status = STATUS_DEVICE_BUSY;
}
}
if (status == STATUS_SUCCESS) {
if (lpDiocParams->lpcbBytesReturned) {
// Default number of bytes returned
*(PULONG) lpDiocParams->lpcbBytesReturned = 0;
}
switch (lpDiocParams->dwIoControlCode) {
//
// We have to check for _IS_ABSENT and _IS_PRESENT first,
// since these are (the only allowed) asynchronous requests
//
case IOCTL_SMARTCARD_IS_ABSENT:
case IOCTL_SMARTCARD_IS_PRESENT:
if (SmartcardExtension->ReaderFunction[RDF_CARD_TRACKING] == NULL) {
status = STATUS_NOT_SUPPORTED;
break;
}
// Now check if the driver is already processing notification
if (SmartcardExtension->OsData->NotificationOverlappedData != NULL) {
status = STATUS_DEVICE_BUSY;
break;
}
//
// Lock the overlapped structure that has to be notified
// about the completion into memory
//
SmartcardExtension->OsData->NotificationOverlappedData =
_HeapAllocate( sizeof(OVERLAPPED), HEAPZEROINIT );
if (SmartcardExtension->OsData->NotificationOverlappedData == NULL) {
return STATUS_INSUFFICIENT_RESOURCES;
}
memcpy(
SmartcardExtension->OsData->NotificationOverlappedData,
(PVOID) lpDiocParams->lpoOverlapped,
sizeof(OVERLAPPED)
);
if (lpDiocParams->dwIoControlCode == IOCTL_SMARTCARD_IS_ABSENT) {
//
// If the card is already (or still) absent, we can return immediatly.
// Otherwise we must statrt event tracking.
//
if (SmartcardExtension->ReaderCapabilities.CurrentState > SCARD_ABSENT) {
status = SmartcardExtension->ReaderFunction[RDF_CARD_TRACKING](
SmartcardExtension
);
}
} else {
//
// If the card is already (or still) present, we can return immediatly.
// Otherwise we must statrt event tracking.
//
if (SmartcardExtension->ReaderCapabilities.CurrentState <= SCARD_ABSENT) {
status = SmartcardExtension->ReaderFunction[RDF_CARD_TRACKING](
SmartcardExtension
);
}
}
if (status != STATUS_PENDING) {
//
// Unlock the overlapped structure again since the driver
// doesn't need it anymore
//
_HeapFree(
SmartcardExtension->OsData->NotificationOverlappedData,
0
);
SmartcardExtension->OsData->NotificationOverlappedData = NULL;
}
break;
default:
// Check if buffers are properly allocated
ASSERT(SmartcardExtension->SmartcardRequest.Buffer);
ASSERT(SmartcardExtension->SmartcardReply.Buffer);
SmartcardExtension->OsData->CurrentDiocParams = lpDiocParams;
// Get major io control code
SmartcardExtension->MajorIoControlCode =
lpDiocParams->dwIoControlCode;
if (lpDiocParams->lpvInBuffer) {
//
// Transfer minor io control code, even if it doesn't make sense for
// this particular major code
//
SmartcardExtension->MinorIoControlCode =
*(PULONG) (lpDiocParams->lpvInBuffer);
// Lock memory and save pointer to and length of request buffer
SmartcardExtension->IoRequest.RequestBuffer = (PUCHAR) VxD_PageLock(
lpDiocParams->lpvInBuffer,
lpDiocParams->cbInBuffer
);
SmartcardExtension->IoRequest.RequestBufferLength =
lpDiocParams->cbInBuffer;
} else {
SmartcardExtension->IoRequest.RequestBuffer = NULL;
SmartcardExtension->IoRequest.RequestBufferLength = 0;
}
if (lpDiocParams->lpvOutBuffer) {
// Lock memory an save pointer to and length of reply buffer
SmartcardExtension->IoRequest.ReplyBuffer = (PUCHAR) VxD_PageLock(
lpDiocParams->lpvOutBuffer,
lpDiocParams->cbOutBuffer
);
SmartcardExtension->IoRequest.ReplyBufferLength =
lpDiocParams->cbOutBuffer;
} else {
SmartcardExtension->IoRequest.ReplyBuffer = NULL;
SmartcardExtension->IoRequest.ReplyBufferLength = 0;
}
// Lock overlapped struct into memory
SmartcardExtension->OsData->CurrentOverlappedData =
(OVERLAPPED *) VxD_PageLock(
lpDiocParams->lpoOverlapped,
sizeof(OVERLAPPED)
);
if (SmartcardExtension->OsData->CurrentOverlappedData) {
//
// Pointer to variable that receives the actual number
// of bytes returned. Since we don't know yet if the
// driver will return STATUS_PENDING, we use the
// overlapped data to store the number of bytes returned
//
SmartcardExtension->IoRequest.Information =
&SmartcardExtension->OsData->CurrentOverlappedData->O_InternalHigh;
// Set the default number of bytes returned to 0
*SmartcardExtension->IoRequest.Information = 0;
// Process the ioctl-request
status = SmartcardDeviceIoControl(SmartcardExtension);
if (status != STATUS_PENDING) {
if(lpDiocParams->lpcbBytesReturned) {
*(PULONG) (lpDiocParams->lpcbBytesReturned) =
*(SmartcardExtension->IoRequest.Information);
}
//
// The driver satisfied the call immediatly. So we don't use the overlapped
// data to return information to the caller. We can transfer the 'number
// of bytes returned' directly
//
if (SmartcardExtension->OsData->CurrentOverlappedData) {
// Unlock all memory
VxD_PageUnlock(
(DWORD) SmartcardExtension->OsData->CurrentOverlappedData,
sizeof(OVERLAPPED)
);
}
if (SmartcardExtension->IoRequest.RequestBuffer) {
VxD_PageUnlock(
(DWORD) SmartcardExtension->IoRequest.RequestBuffer,
SmartcardExtension->IoRequest.RequestBufferLength
);
}
if (SmartcardExtension->IoRequest.ReplyBuffer) {
VxD_PageUnlock(
(DWORD) SmartcardExtension->IoRequest.ReplyBuffer,
SmartcardExtension->IoRequest.ReplyBufferLength
);
}
//
// If the devcie is not busy, we can set the
// current parameters back to NULL
//
SmartcardExtension->OsData->CurrentDiocParams = NULL;
}
} else {
status = STATUS_INSUFFICIENT_RESOURCES;
}
break;
}
}
SmartcardDebug(
DEBUG_IOCTL,
("SMCLIB(SmartcardDeviceControl): Exit\n")
);
_LeaveMutex(SmartcardExtension->OsData->Mutex);
return status;
}
DWORD
_stdcall
SMCLIB_DeviceIoControl(
DWORD dwService,
DWORD dwDDB,
DWORD hDevice,
DIOCPARAMETERS *lpDIOCParms
)
{
return 0;
}
SMCLIB_Get_Version()
{
return SMCLIB_VERSION;
}