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

1387 lines
45 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*******************************************************************************
* Copyright (c) 1997-1998 Gemplus Development
*
* Name : GNTSCR09.C (Gemplus NT Smart Card Reader module 09)
*
* Description : This is the main module which holds:
* - the main functions for a standard NT driver
*
* Compiler : Microsoft DDK for Windows NT
*
* Host : IBM PC and compatible machines under Windows NT
*
* Release : 1.00.003
*
* Last Modif : 24/01/98: V1.00.003 (Gilles PAUZIE)
* - Modifiy GDDKNT_09CreateDevice function. The IoCreateDevice
* function is now always called with FALSE parameters for the
* both compilator mode free and checked. This resolves the
* problem of the IO pending for the free mode.
* 22/12/97: V1.00.002 (Thierry Fabre)
* - Modifiy GDDKNT_Cleanup function to abort a pending io-
* request (wait for insertion/removal card).
* 22/06/97: V1.00.001 (Gilles Pauzie)
* - Start of development.
*
********************************************************************************
*
* Warning :
*
* Remark :
*
*******************************************************************************/
/*------------------------------------------------------------------------------
Include section:
- stdio.h: standards definitons.
- ntddk.h: DDK Windows NT general definitons.
- ntddser.h: DDK Windows NT serial management definitons.
------------------------------------------------------------------------------*/
#include <stdio.h>
#include <ntddk.h>
#include <ntddser.h>
/*------------------------------------------------------------------------------
- smclib.h: smart card library definitions.
------------------------------------------------------------------------------*/
#define SMARTCARD_POOL_TAG 'cGCS'
#include <smclib.h>
/*------------------------------------------------------------------------------
- gemlog.h: Gemplus error log file definitions.
- gioctl09.h: public interface definition for the IOCTL functions.
- gntscr09.h: public interface definition for this module.
- gntser.h: public interface definition for serial management
------------------------------------------------------------------------------*/
#include "gemlog.h"
#include "gemcore.h"
#include "gioctl09.h"
#include "gntscr09.h"
#include "gntser.h"
/*------------------------------------------------------------------------------
Compiler Directives:
------------------------------------------------------------------------------*/
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, DriverEntry)
#pragma alloc_text(INIT, GDDKNT_09AddDevice)
#pragma alloc_text(INIT, GDDKNT_09CreateDevice)
#endif // ALLOC_PRAGMA
/*------------------------------------------------------------------------------
Constant section:
- SC_DRIVER_VERSION defines the version of the driver
- IFD_STANDARD_BAUD_RATE defines the standard baud rate for the reader (9600)
- MAX_DEVICES is the maximum number of devices (and instances) we want
to support
- POLLING_TIMEOUT is the polling timeout for detection insertion/removal card
in milliseconds (1000 ms)
------------------------------------------------------------------------------*/
#define SC_DRIVER_VERSION 0x090
#define IFD_STANDARD_BAUD_RATE 9600
#define MAX_DEVICES 16
#define POLLING_TIMEOUT 1000
/*------------------------------------------------------------------------------
Function definition section:
------------------------------------------------------------------------------*/
/*******************************************************************************
* NTSTATUS DriverEntry
* (
* IN PDRIVER_OBJECT DriverObject,
* IN PUNICODE_STRING RegistryPath
* )
* Description :
* -------------
* This routine is called at system initialization time to initialize
* this driver.
*
* Remarks :
* -------------
* Nothing.
*
* In :
* -------------
* - DriverObject supplies the driver object.
* - RegistryPath supplies the registry path for this driver.
*
* Out :
* -------------
* Nothing.
*
* Responses :
* -------------
* STATUS_SUCCESS - We could initialize at least one device.
* STATUS_NO_SUCH_DEVICE - We could not initialize even one device.
*******************************************************************************/
NTSTATUS DriverEntry
(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{
ULONG
serialNumber,
ifdNumber,
noOfDevices = 0,
maxBaudRate,
maximalIFD,
IFDOption,
i;
NTSTATUS
status;
PSMARTCARD_EXTENSION
previousDeviceExt = NULL;
RTL_QUERY_REGISTRY_TABLE
paramTable[4];
UNICODE_STRING
driverPath;
WCHAR
buffer[MAXIMUM_FILENAME_LENGTH];
INT16
response;
USHORT
rlen;
BYTE
rbuff[HOR3GLL_BUFFER_SIZE],
sbuff[HOR3GLL_BUFFER_SIZE];
#if DBG
/*------------------------------------------------------------------------------
Initialize the debug level.
------------------------------------------------------------------------------*/
SmartcardSetDebugLevel(DEBUG_ALL);
#endif
/*------------------------------------------------------------------------------
Initialize the Driver Object with driver's entry points
------------------------------------------------------------------------------*/
DriverObject->DriverUnload = GDDKNT_09Unload;
DriverObject->MajorFunction[IRP_MJ_CREATE] = GDDKNT_09CreateClose;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = GDDKNT_09CreateClose;
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = GDDKNT_09Cleanup;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = GDDKNT_09DeviceControl;
/*------------------------------------------------------------------------------
Read in the the driver registry path:
- "MaximalBaudRate" is the maximal speed specified for the reader.
- "MaximalIFD" is the maximal number of security modules for the reader.
- "IFDOption" is the options for the reader.
------------------------------------------------------------------------------*/
maxBaudRate = 0;
RtlZeroMemory(paramTable,sizeof(paramTable));
paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
paramTable[0].Name = L"MaximalBaudRate";
paramTable[0].EntryContext = &maxBaudRate;
paramTable[0].DefaultType = REG_DWORD;
paramTable[0].DefaultData = &maxBaudRate;
paramTable[0].DefaultLength = sizeof(ULONG);
maximalIFD = 0;
paramTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
paramTable[1].Name = L"MaximalIFD";
paramTable[1].EntryContext = &maximalIFD;
paramTable[1].DefaultType = REG_DWORD;
paramTable[1].DefaultData = &maximalIFD;
paramTable[1].DefaultLength = sizeof(ULONG);
IFDOption = 0;
paramTable[2].Flags = RTL_QUERY_REGISTRY_DIRECT;
paramTable[2].Name = L"IFDOption";
paramTable[2].EntryContext = &IFDOption;
paramTable[2].DefaultType = REG_DWORD;
paramTable[2].DefaultData = &IFDOption;
paramTable[2].DefaultLength = sizeof(ULONG);
driverPath.Buffer = buffer;
driverPath.MaximumLength = sizeof(buffer);
driverPath.Length = 0;
RtlCopyUnicodeString(&driverPath,RegistryPath);
status =
RtlQueryRegistryValues(
RTL_REGISTRY_ABSOLUTE,
driverPath.Buffer,
&paramTable[0],
NULL,
NULL
);
if ((maxBaudRate != 9600lu) && (maxBaudRate != 19200lu) &&
(maxBaudRate != 38400lu) && (maxBaudRate != 76800lu)
)
{
maxBaudRate = IFD_STANDARD_BAUD_RATE;
}
/*------------------------------------------------------------------------------
For all the serial ports we search if a Gemplus Oros Based reader is
connected. If we found a reader, we create 1 device by IFD in the reader.
For example we can have 2 devices for a GCR500 (1 for the main reader,
1 for the Security Access Module).
------------------------------------------------------------------------------*/
for (serialNumber = 0;
(serialNumber < HGTSER_MAX_PORT) && (noOfDevices < MAX_DEVICES);
serialNumber++)
{
/*------------------------------------------------------------------------------
Build a string like \Device\SerialN (N is the 0 based device number)
------------------------------------------------------------------------------*/
UNICODE_STRING
serialDeviceName, deviceNo, device;
WCHAR
buffer[32];
serialDeviceName.Buffer = buffer;
serialDeviceName.MaximumLength = sizeof(buffer);
serialDeviceName.Length = 0;
RtlInitUnicodeString(&device,L"\\Device\\Serial");
RtlCopyUnicodeString(&serialDeviceName,&device);
deviceNo.Buffer =
serialDeviceName.Buffer +
serialDeviceName.Length / sizeof(WCHAR);
deviceNo.MaximumLength = 2 * sizeof(WCHAR);
deviceNo.Length = 0;
RtlIntegerToUnicodeString(serialNumber,10,&deviceNo);
serialDeviceName.Length += deviceNo.Length;
/*------------------------------------------------------------------------------
Try to create a device for all the IFD availables in the reader
------------------------------------------------------------------------------*/
for (ifdNumber=0;
(ifdNumber<maximalIFD) && (ifdNumber<MAX_IFD_BY_READER);
ifdNumber++)
{
status = GDDKNT_09AddDevice(
DriverObject,
&serialDeviceName,
noOfDevices,
serialNumber,
ifdNumber,
previousDeviceExt,
maxBaudRate
);
if (status == STATUS_SUCCESS)
{
// We have successfully created a device
PDEVICE_OBJECT deviceObject =
DriverObject->DeviceObject;
PDEVICE_EXTENSION deviceExtension =
deviceObject->DeviceExtension;
PSMARTCARD_EXTENSION smartcardExtension =
&deviceExtension->SmartcardExtension;
ASSERT(deviceObject != NULL);
ASSERT(deviceExtension != NULL);
ASSERT(smartcardExtension != NULL);
smartcardExtension->ReaderExtension->MaximalIFD = maximalIFD;
smartcardExtension->ReaderExtension->IFDOption = IFDOption;
noOfDevices++;
/*------------------------------------------------------------------------------
If is the first IFD for the reader
Save the DeviceObject for the next IFD.
Read the type of the reader
If the reader type is GCR410
No more IFD available on this port
------------------------------------------------------------------------------*/
if (ifdNumber == 0)
{
previousDeviceExt = smartcardExtension;
/*------------------------------------------------------------------------------
Read the type of the reader
------------------------------------------------------------------------------*/
sbuff[0] = HOR3GLL_IFD_CMD_INFO;
sbuff[1] = 0x01;
rlen = HOR3GLL_BUFFER_SIZE;
response = G_Oros3Exchange
(
(INT16)(noOfDevices-1),
HOR3GLL_DEFAULT_TIME,
(const WORD16)2,
(const BYTE *)sbuff,
&rlen,
rbuff
);
/*------------------------------------------------------------------------------
If the reader type is GCR410
Then
No more IFD available on this port
------------------------------------------------------------------------------*/
if ((response != G_OK) || (rlen != 2) || (rbuff[0] != 0) || (rbuff[1] == 0x01))
{
break;
}
}
}
else
{
break;
}
}
}
/*------------------------------------------------------------------------------
If we haven't found any reader on the serial, then we write a message in the
event log file.
------------------------------------------------------------------------------*/
if (noOfDevices == 0)
{
SmartcardLogError(
DriverObject,
GEM_NO_SUCH_DEVICE,
NULL,
status
);
return STATUS_NO_SUCH_DEVICE;
}
return STATUS_SUCCESS;
}
/*******************************************************************************
* NTSTATUS GDDKNT_09AddDevice
* (
* IN PDRIVER_OBJECT DriverObject,
* IN PUNICODE_STRING SerialDeviceName,
* IN ULONG DeviceNumber,
* IN ULONG SerialNumber,
* IN ULONG IFDNumber,
* IN PSMARTCARD_EXTENSION PreviousDeviceExt,
* IN ULONG MaximalBaudRate
* )
*
* Description :
* -------------
* This is the add-device routine.
*
* Remarks :
* -------------
* Nothing.
*
* In :
* -------------
* - DriverObject is a pointer to the driver object for this device.
* - SerialDeviceName holds the device name of the serial port to attach to.
* - DeviceNumber holds an ascending device number starting with 0.
* - SerialNumber holds the serial port number (0 to 3).
* - IFDNumber holds the numero of the IFD in
* the reader (0 to MAX_IFD_BY_READER).
* - PreviousDeviceExt holds the previous smart card object. It is used to
* know the serial device object.
* - MaximalBaudRate holds the maximal speed specified for the reader.
* Out :
* -------------
* Nothing.
*
* Responses :
* -------------
* STATUS_SUCCESS Device created.
*******************************************************************************/
NTSTATUS GDDKNT_09AddDevice
(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING SerialDeviceName,
IN ULONG DeviceNumber,
IN ULONG SerialNumber,
IN ULONG IFDNumber,
IN PSMARTCARD_EXTENSION PreviousDeviceExt,
IN ULONG MaximalBaudRate
)
{
UNICODE_STRING
smartcardDeviceName, deviceNo, device;
WCHAR
buffer[64];
NTSTATUS
status;
ASSERT(DriverObject != NULL);
ASSERT(SerialDeviceName != NULL);
ASSERT(DeviceNumber >= 0);
ASSERT(SerialNumber >= 0);
ASSERT(IFDNumber >= 0);
/*------------------------------------------------------------------------------
Build a device name for the smart card reader
\Device\GemSCR09pi: p (0 to 3) is the port number,
i (0 to MAX_IFD_BY_READER) is the 0 based IFD number
------------------------------------------------------------------------------*/
smartcardDeviceName.Buffer = buffer;
smartcardDeviceName.MaximumLength = sizeof(buffer);
smartcardDeviceName.Length = 0;
RtlInitUnicodeString(&device,L"\\Device\\GemSCR09");
RtlCopyUnicodeString(&smartcardDeviceName,&device);
/*------------------------------------------------------------------------------
Add the port serial number
------------------------------------------------------------------------------*/
deviceNo.Buffer =
smartcardDeviceName.Buffer + smartcardDeviceName.Length / sizeof(WCHAR);
deviceNo.MaximumLength = 2 * sizeof(WCHAR);
deviceNo.Length = 0;
RtlIntegerToUnicodeString(SerialNumber,16,&deviceNo);
smartcardDeviceName.Length += deviceNo.Length;
/*------------------------------------------------------------------------------
Add the ifd number
------------------------------------------------------------------------------*/
deviceNo.Buffer =
smartcardDeviceName.Buffer + smartcardDeviceName.Length / sizeof(WCHAR);
deviceNo.MaximumLength = 2 * sizeof(WCHAR);
deviceNo.Length = 0;
RtlIntegerToUnicodeString(IFDNumber,16,&deviceNo);
smartcardDeviceName.Length += deviceNo.Length;
/*------------------------------------------------------------------------------
Try to create a device with the just created device name
It is possible that a smart card device with this name
already exists from a previous call.
------------------------------------------------------------------------------*/
status = GDDKNT_09CreateDevice(
DriverObject,
&smartcardDeviceName,
SerialDeviceName,
DeviceNumber,
SerialNumber,
IFDNumber,
PreviousDeviceExt,
MaximalBaudRate
);
if (status == STATUS_SUCCESS)
{
PDEVICE_OBJECT
deviceObject = DriverObject->DeviceObject;
PDEVICE_EXTENSION
deviceExtension = deviceObject->DeviceExtension;
PSMARTCARD_EXTENSION
smartcardExtension = &deviceExtension->SmartcardExtension;
ASSERT(deviceObject != NULL);
ASSERT(deviceExtension != NULL);
ASSERT(smartcardExtension != NULL);
}
if (status != STATUS_OBJECT_NAME_COLLISION)
{
/*------------------------------------------------------------------------------
The corresponding serial port is already in use
So don't try to create a smart card device with a different name
------------------------------------------------------------------------------*/
return status;
}
return status;
}
/*******************************************************************************
* NTSTATUS GDDKNT_09CreateDevice
* (
* IN PDRIVER_OBJECT DriverObject,
* IN PUNICODE_STRING SmartcardDeviceName,
* IN PUNICODE_STRING SerialDeviceName,
* IN ULONG DeviceNumber,
* IN ULONG SerialNumber,
* IN ULONG IFDNumber,
* IN PSMARTCARD_EXTENSION PreviousDeviceExt,
* IN ULONG MaximalBaudRate
* )
*
* Description :
* -------------
* This routine creates an object for the physical device specified and
* sets up the deviceExtension.
*
* Remarks :
* -------------
* Nothing.
*
* In :
* -------------
* - DriverObject is a pointer to the driver object for this device.
* - SmartcardDeviceName holds the device name for this new device.
* - SerialDeviceName holds the device name of the serial port to attach to.
* - SerialNumber holds the serial port number (0 to 3).
* - IFDNumber holds the numero of the IFD in the reader (0 to MAX_IFD_BY_READER).
* - PreviousDeviceExt holds the previous smart card object. It is used to know the serial
* device object.
* - MaximalBaudRate holds the maximal speed specified for the reader.
* Out :
* -------------
* Nothing.
*
* Responses :
* -------------
* STATUS_SUCCESS Device created.
*******************************************************************************/
NTSTATUS GDDKNT_09CreateDevice
(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING SmartcardDeviceName,
IN PUNICODE_STRING SerialDeviceName,
IN ULONG DeviceNumber,
IN ULONG SerialNumber,
IN ULONG IFDNumber,
IN PSMARTCARD_EXTENSION PreviousDeviceExt,
IN ULONG MaximalBaudRate
)
{
PFILE_OBJECT
serialFileObject;
PDEVICE_OBJECT
deviceObject, serialDeviceObject;
PDEVICE_EXTENSION
deviceExtension;
NTSTATUS
status = STATUS_SUCCESS;
ULONG
i;
ASSERT(DriverObject != NULL);
ASSERT(SmartcardDeviceName != NULL);
ASSERT(SerialDeviceName != NULL);
ASSERT(DeviceNumber >= 0);
ASSERT(SerialNumber >= 0);
ASSERT(IFDNumber >= 0);
SmartcardDebug(
DEBUG_DRIVER,
("GEMSCR09!GDDKNT_09CreateDevice: DeviceNumber=%ld IFDNumber=%ld SerialDeviceName=%ws\n",
DeviceNumber,
IFDNumber,
SerialDeviceName->Buffer)
);
/*------------------------------------------------------------------------------
For the first IFD in the reader we try to get a pointer on the serial driver
If we can't have a pointer on the serial object, perhaps the serial port
is already used by an other device.
------------------------------------------------------------------------------*/
if (IFDNumber == 0)
{
status = IoGetDeviceObjectPointer(
SerialDeviceName,
FILE_ALL_ACCESS,
&serialFileObject,
&serialDeviceObject
);
SmartcardDebug(
DEBUG_DRIVER,
("GEMSCR09!GDDKNT_09CreateDevice: IoGetDeviceObjectPointer=%lX\n",status)
);
if (!NT_SUCCESS(status))
{
return status;
}
ASSERT(serialFileObject != NULL);
ASSERT(serialDeviceObject != NULL);
}
/*------------------------------------------------------------------------------
Try to create a new device smart card object
------------------------------------------------------------------------------*/
status = IoCreateDevice(
DriverObject,
sizeof(DEVICE_EXTENSION),
SmartcardDeviceName,
FILE_DEVICE_SMARTCARD,
0,
FALSE,
&deviceObject
);
SmartcardDebug(
DEBUG_DRIVER,
("GEMSCR09!GDDKNT_09CreateDevice: IoCreateDevice=%lX\n",status)
);
/*------------------------------------------------------------------------------
If we have failed to create a new device, then we write a message in the
event log file.
------------------------------------------------------------------------------*/
if (!NT_SUCCESS(status))
{
if (IFDNumber == 0)
{
ObDereferenceObject(serialFileObject);
}
SmartcardLogError(
DriverObject,
GEM_CANT_CREATE_DEVICE,
SmartcardDeviceName,
status
);
return status;
}
ASSERT(deviceObject != NULL);
/*------------------------------------------------------------------------------
Now we have a pointer on the new device and we try to allocate memory for
the ReaderExtension struct.
------------------------------------------------------------------------------*/
deviceExtension = deviceObject->DeviceExtension;
ASSERT(deviceExtension != NULL);
deviceObject->Flags = deviceObject->Flags | DO_BUFFERED_IO;
RtlZeroMemory(deviceExtension,sizeof(PDEVICE_EXTENSION));
deviceExtension->SmartcardExtension.ReaderExtension =
ExAllocatePool(
NonPagedPool,
sizeof(READER_EXTENSION)
);
if (deviceExtension->SmartcardExtension.ReaderExtension == NULL)
{
SmartcardLogError(
DriverObject,
GEM_NO_MEMORY_FOR_READER_EXTENSION,
SmartcardDeviceName,
0
);
status = STATUS_INSUFFICIENT_RESOURCES;
}
if (status == STATUS_SUCCESS)
{
SmartcardDebug(
DEBUG_DRIVER,
("GEMSCR09!GDDKNT_09CreateDevice: SmartcardExtension=%lX\n",
&(deviceExtension->SmartcardExtension))
);
/*------------------------------------------------------------------------------
Write the version of the lib we use to the smartcard extension
------------------------------------------------------------------------------*/
(deviceExtension->SmartcardExtension).Version = SMCLIB_VERSION;
/*------------------------------------------------------------------------------
Now let the lib allocate the buffer for data transmission
We can either tell the lib how big the buffer should be by assigning a
value to BufferSize or let the lib allocate the default size
------------------------------------------------------------------------------*/
deviceExtension->SmartcardExtension.SmartcardRequest.BufferSize =
MIN_BUFFER_SIZE;
deviceExtension->SmartcardExtension.SmartcardReply.BufferSize =
MIN_BUFFER_SIZE;
status = SmartcardInitialize(&deviceExtension->SmartcardExtension);
SmartcardDebug(
DEBUG_DRIVER,
("GEMSCR09!GDDKNT_09CreateDevice: SmartcardInitialize=%lX\n",status)
);
if (status != STATUS_SUCCESS)
{
SmartcardLogError(
DriverObject,
GEM_CANT_INITIALIZE_SMCLIB,
SmartcardDeviceName,
status
);
}
}
/*------------------------------------------------------------------------------
If SmartCardInitialize success
We flush the ReaderExtension struct
------------------------------------------------------------------------------*/
if (status == STATUS_SUCCESS)
{
RtlZeroMemory(
deviceExtension->SmartcardExtension.ReaderExtension,
sizeof(READER_EXTENSION)
);
/*------------------------------------------------------------------------------
Save the deviceObject
------------------------------------------------------------------------------*/
deviceExtension->SmartcardExtension.OsData->DeviceObject =
deviceObject;
/*------------------------------------------------------------------------------
Save the deviceObject and the FileObject for the connected serial port
------------------------------------------------------------------------------*/
if (IFDNumber == 0)
{
deviceExtension->SmartcardExtension.ReaderExtension->ConnectedSerialPort =
serialDeviceObject;
deviceExtension->SmartcardExtension.ReaderExtension->SerialFileObject =
serialFileObject;
}
else
{
deviceExtension->SmartcardExtension.ReaderExtension->ConnectedSerialPort =
PreviousDeviceExt->ReaderExtension->ConnectedSerialPort;
deviceExtension->SmartcardExtension.ReaderExtension->SerialFileObject =
PreviousDeviceExt->ReaderExtension->SerialFileObject;
}
/*------------------------------------------------------------------------------
Save the serial port number this device is connected to
------------------------------------------------------------------------------*/
deviceExtension->SmartcardExtension.ReaderCapabilities.Channel = SerialNumber;
/*------------------------------------------------------------------------------
Now we verify if a GemCore based reader is connected on this serial port.
------------------------------------------------------------------------------*/
status = GDDK_09OpenChannel(
&deviceExtension->SmartcardExtension,
DeviceNumber,
SerialNumber,
IFDNumber,
MaximalBaudRate
);
SmartcardDebug(
DEBUG_DRIVER,
("GEMSCR09!GDDKNT_09CreateDevice: GDDK_09OpenChannel=%lX\n",status)
);
/*------------------------------------------------------------------------------
If we have found a GemCore based reader connected on this serial port.
Then
Set up the call back functions
(nota: RDF_CARD_EJECT and RDF_READER_SWALLOW are not supported)
------------------------------------------------------------------------------*/
if (NT_SUCCESS(status))
{
deviceExtension->SmartcardExtension.ReaderFunction[RDF_TRANSMIT] =
GDDK_09Transmit;
deviceExtension->SmartcardExtension.ReaderFunction[RDF_SET_PROTOCOL] =
GDDK_09SetProtocol;
deviceExtension->SmartcardExtension.ReaderFunction[RDF_CARD_POWER] =
GDDK_09ReaderPower;
deviceExtension->SmartcardExtension.ReaderFunction[RDF_CARD_TRACKING] =
GDDK_09CardTracking;
/*------------------------------------------------------------------------------
Create a symbolic link with the SMCLIB for this new device
------------------------------------------------------------------------------*/
status = SmartcardCreateLink(
&deviceExtension->SmartcardExtension.ReaderExtension->DosDeviceName,
SmartcardDeviceName
);
if (status != STATUS_SUCCESS)
{
SmartcardLogError(
DriverObject,
GEM_CREATE_LINK_FAILED,
SmartcardDeviceName,
status
);
}
}
}
/*------------------------------------------------------------------------------
If we have failed anywhere above, we need to free the memory and the device
------------------------------------------------------------------------------*/
if (status != STATUS_SUCCESS)
{
ExFreePool(deviceExtension->SmartcardExtension.ReaderExtension);
SmartcardExit(&deviceExtension->SmartcardExtension);
IoDeleteDevice(deviceObject);
if (IFDNumber == 0)
{
ObDereferenceObject(serialFileObject);
}
}
else
{
SmartcardDebug(
DEBUG_DRIVER,
("GEMSCR09!GDDKNT_09CreateDevice: Device %ws created\n",
deviceExtension->SmartcardExtension.ReaderExtension->DosDeviceName.Buffer)
);
}
return status;
}
/*******************************************************************************
* NTSTATUS GDDKNT_09CreateClose
* (
* IN PDEVICE_OBJECT DeviceObject,
* IN PIRP Irp
* )
*
* Description :
* -------------
* This routine is called by the I/O system when the device is opened or closed.
*
* Remarks :
* -------------
* Nothing.
*
* In :
* -------------
* - DeviceObject is a pointer to the device.
* - Irp holds the Irp involved.
* Out :
* -------------
* Nothing.
*
* Responses :
* -------------
* STATUS_SUCCESS
*******************************************************************************/
NTSTATUS GDDKNT_09CreateClose
(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
NTSTATUS
status;
KEVENT
event;
LARGE_INTEGER
timeout;
PDEVICE_EXTENSION
deviceExtension = DeviceObject->DeviceExtension;
PSMARTCARD_EXTENSION
smartcardExtension = &deviceExtension->SmartcardExtension;
PIO_STACK_LOCATION
irpStack = IoGetCurrentIrpStackLocation(Irp);
ASSERT(deviceExtension != NULL);
ASSERT(smartcardExtension != NULL);
ASSERT(irpStack != NULL);
if (irpStack->MajorFunction == IRP_MJ_CREATE)
{
SmartcardDebug(
DEBUG_DRIVER,
("GEMSCR09!GDDKNT_09CreateClose: Device %ws opened\n",
smartcardExtension->ReaderExtension->DosDeviceName.Buffer)
);
if (smartcardExtension->ReaderExtension->IFDNumber == 0)
{
/*------------------------------------------------------------------------------
Update the current state of reader (card present/removed)
Initialize the Card Tracking only if the reader can support this function.
------------------------------------------------------------------------------*/
GDDK_09UpdateCardStatus(smartcardExtension);
status = GDDKNT_09InitializeCardTracking(smartcardExtension);
if (status != STATUS_SUCCESS)
{
SmartcardLogError(
DeviceObject,
GEM_CREATE_CARD_TRACKING_THREAD,
&smartcardExtension->ReaderExtension->DosDeviceName,
status
);
}
}
}
else
{
SmartcardDebug(
DEBUG_DRIVER,
("GEMSCR09!GDDKNT_09CreateClose: Device %ws closed\n",
smartcardExtension->ReaderExtension->DosDeviceName.Buffer)
);
/*------------------------------------------------------------------------------
Stop the card tracking thread
------------------------------------------------------------------------------*/
if ((smartcardExtension->ReaderExtension->IFDNumber == 0) &&
(smartcardExtension->ReaderExtension->CardStatus.Mode == RUN_IN_PROCESS))
{
smartcardExtension->ReaderExtension->CardStatus.Mode = STOP_REQUEST;
KeInitializeEvent(&event,NotificationEvent,FALSE);
while (smartcardExtension->ReaderExtension->CardStatus.Mode == STOP_REQUEST)
{
timeout.QuadPart = -((LONGLONG)100*10*1000);
status = KeWaitForSingleObject(&event,
Suspended,
KernelMode,
FALSE,
&timeout);
}
}
}
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_SUCCESS;
SmartcardDebug(DEBUG_DRIVER,("GEMSCR09!GDDKNT_09CreateClose: Exit\n"));
return STATUS_SUCCESS;
}
/*******************************************************************************
* NTSTATUS GDDKNT_09Cleanup
* (
* IN PDEVICE_OBJECT DeviceObject,
* IN PIRP Irp
* )
*
* Description :
* -------------
* This routine is called by the I/O system when the device is opened or closed.
*
* Remarks :
* -------------
* Nothing.
*
* In :
* -------------
* - DeviceObject is a pointer to the device.
* - Irp holds the Irp involved.
* Out :
* -------------
* Nothing.
*
* Responses :
* -------------
* STATUS_SUCCESS
*******************************************************************************/
NTSTATUS GDDKNT_09Cleanup
(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PDEVICE_EXTENSION
deviceExtension = DeviceObject->DeviceExtension;
PSMARTCARD_EXTENSION
smartcardExtension = &deviceExtension->SmartcardExtension;
NTSTATUS
status = STATUS_SUCCESS;
ASSERT(deviceExtension != NULL);
ASSERT(smartcardExtension != NULL);
SmartcardDebug(DEBUG_DRIVER,("GEMSCR09!GDDKNT_09Cleanup: Enter\n"));
if (Irp != NULL)
{
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_CANCELLED;
if (Irp->Cancel == TRUE)
{
IoReleaseCancelSpinLock(Irp->CancelIrql);
}
else
{
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_SUCCESS;
}
smartcardExtension->OsData->NotificationIrp = NULL;
SmartcardDebug(DEBUG_DRIVER,("GEMSCR09!GDDKNT_09Cleanup: Wait cancelled\n"));
IoCompleteRequest(Irp,IO_NO_INCREMENT);
}
SmartcardDebug(DEBUG_DRIVER,("GEMSCR09!GDDKNT_09Cleanup: Exit\n"));
return STATUS_SUCCESS;
}
/*******************************************************************************
* VOID GDDKNT_09Unload
* (
* IN PDRIVER_OBJECT DriverObject
* )
*
* Description :
* -------------
* The driver unload routine. This is called by the I/O system when the
* device is unloaded from memory.
*
* Remarks :
* -------------
* Nothing.
*
* In :
* -------------
* - DriverObject is a pointer to the driver object for this device.
* Out :
* -------------
* Nothing.
*
* Responses :
* -------------
* Nothing.
*******************************************************************************/
VOID GDDKNT_09Unload
(
IN PDRIVER_OBJECT DriverObject
)
{
PDEVICE_OBJECT
deviceObject = DriverObject->DeviceObject;
NTSTATUS
status;
WORD16
LengthOut = 0;
KEVENT
event;
LARGE_INTEGER
timeout;
ASSERT(deviceObject != NULL);
SmartcardDebug(DEBUG_DRIVER,("GEMSCR09!GDDKNT_09Unload: Enter\n"));
do
{
PDEVICE_EXTENSION deviceExtension = deviceObject->DeviceExtension;
PSMARTCARD_EXTENSION smartcardExtension = &deviceExtension->SmartcardExtension;
SmartcardDebug(
DEBUG_DRIVER,
("GEMSCR09!GDDKNT_09Unload: Unloading device %ws\n",
smartcardExtension->ReaderExtension->DosDeviceName.Buffer)
);
/*------------------------------------------------------------------------------
Close the communication with the reader
------------------------------------------------------------------------------*/
GDDK_09CloseChannel(smartcardExtension);
/*------------------------------------------------------------------------------
We do not longet need the reference to the serial reader.
------------------------------------------------------------------------------*/
ObDereferenceObject(smartcardExtension->ReaderExtension->SerialFileObject);
/*------------------------------------------------------------------------------
Delete the symbolic link of the smart card reader
------------------------------------------------------------------------------*/
IoDeleteSymbolicLink(&smartcardExtension->ReaderExtension->DosDeviceName);
/*------------------------------------------------------------------------------
Let the lib free the send/receive buffers (SmartCardExit)
------------------------------------------------------------------------------*/
SmartcardExit(smartcardExtension);
/*------------------------------------------------------------------------------
Free all allocated buffer
------------------------------------------------------------------------------*/
ExFreePool(smartcardExtension->ReaderExtension->DosDeviceName.Buffer);
ExFreePool(smartcardExtension->ReaderExtension);
/*------------------------------------------------------------------------------
Delete the device from the system
------------------------------------------------------------------------------*/
IoDeleteDevice(deviceObject);
} while(deviceObject == DriverObject->DeviceObject);
SmartcardDebug(DEBUG_DRIVER,("GEMSCR09!GDDKNT_09Unload: Exit\n"));
}
/*******************************************************************************
* NTSTATUS GDDKNT_09InitializeCardTracking
* (
* PSMARTCARD_EXTENSION SmartcardExtension
* )
*
* Description :
* -------------
* This routine initialized card tracking. It calls the serial driver to
* set a wait mask for RING tracking. After that it installs a completion
* routine to be called when RING changes state.
*
* Remarks :
* -------------
* Nothing.
*
* In :
* -------------
* - SmartcardExtension is a pointer on the SmartCardExtension structure of
* the current device.
* Out :
* -------------
* Nothing.
*
* Responses :
* -------------
* NTSTATUS
*******************************************************************************/
NTSTATUS GDDKNT_09InitializeCardTracking
(
PSMARTCARD_EXTENSION SmartcardExtension
)
{
NTSTATUS
status;
LARGE_INTEGER
timeout;
/*------------------------------------------------------------------------------
Create which will check the status of the reader (card absent/present)
------------------------------------------------------------------------------*/
SmartcardExtension->ReaderExtension->CardStatus.Mode = RUN_REQUEST;
status = PsCreateSystemThread(
&(SmartcardExtension->ReaderExtension->CardStatus.ThreadHandle),
THREAD_ALL_ACCESS,
NULL,
NULL,
NULL,
GDDKNT_09UpdateCardStatus,
SmartcardExtension);
SmartcardDebug(
DEBUG_TRACE,
("GEMSCR09!GDDKNT_09InitializeCardTracking(%d)\n",status)
);
return status;
}
/*******************************************************************************
* VOID GDDKNT_09UpdateCardStatus
* (
* IN PKDPC EventDpc,
* IN PSMARTCARD_EXTENSION SmartcardExtension,
* IN PVOID SystemArgument1,
* IN PVOID SystemArgument2
* )
*
* Description :
* -------------
* This routine is called as the deferred procedure when RxD changes its status.
* Calls the serial driver again to start new RxD tracking.
*
* Remarks :
* -------------
* Nothing.
*
* In :
* -------------
* - SmartcardExtension is a pointer on the SmartCardExtension structure of
* the current device.
* Out :
* -------------
* Nothing.
*
* Responses :
* -------------
* Nothing.
*******************************************************************************/
VOID GDDKNT_09UpdateCardStatus
(
IN PSMARTCARD_EXTENSION SmartcardExtension
)
{
NTSTATUS
status;
KIRQL
oldIrql;
KEVENT
event;
LARGE_INTEGER
timeout;
ULONG
CurrentState;
PIRP
pIrp;
/*------------------------------------------------------------------------------
Run the update card status while the function is not stopped.
------------------------------------------------------------------------------*/
SmartcardExtension->ReaderExtension->CardStatus.Mode = RUN_IN_PROCESS;
while (SmartcardExtension->ReaderExtension->CardStatus.Mode == RUN_IN_PROCESS)
{
KeInitializeEvent(&event,NotificationEvent,FALSE);
timeout.QuadPart = -((LONGLONG) POLLING_TIMEOUT*10*1000);
status = KeWaitForSingleObject(&event,
Suspended,
KernelMode,
FALSE,
&timeout);
GDDK_09LockExchange(SmartcardExtension);
/*------------------------------------------------------------------------------
Save the current state of reader (card present/removed)
and read the new state
------------------------------------------------------------------------------*/
CurrentState = SmartcardExtension->ReaderCapabilities.CurrentState;
GDDK_09UpdateCardStatus(SmartcardExtension);
/*------------------------------------------------------------------------------
Only inform the user of a card insertion/removal event
if this function isn't called due to a power down - power up cycle
------------------------------------------------------------------------------*/
if (
(((CurrentState != SCARD_ABSENT) && (SmartcardExtension->ReaderCapabilities.CurrentState == SCARD_ABSENT))
||
((CurrentState == SCARD_ABSENT) && (SmartcardExtension->ReaderCapabilities.CurrentState != SCARD_ABSENT))
)
&&
(SmartcardExtension->OsData->NotificationIrp)
)
{
/*------------------------------------------------------------------------------
If the user had setup an irp for event tracking complete that irp now
------------------------------------------------------------------------------*/
IoAcquireCancelSpinLock(&oldIrql);
IoSetCancelRoutine(SmartcardExtension->OsData->NotificationIrp,NULL);
IoReleaseCancelSpinLock(oldIrql);
SmartcardExtension->OsData->NotificationIrp->IoStatus.Information = 0;
SmartcardExtension->OsData->NotificationIrp->IoStatus.Status = STATUS_SUCCESS;
SmartcardDebug(
DEBUG_DRIVER,
("GEMSCR09!GDDKNT_09UpdateCardStatus: Completing IRP %lx",
SmartcardExtension->OsData->NotificationIrp)
);
pIrp = SmartcardExtension->OsData->NotificationIrp;
SmartcardExtension->OsData->NotificationIrp = NULL;
IoCompleteRequest(
pIrp,
IO_NO_INCREMENT
);
}
GDDK_09UnlockExchange(SmartcardExtension);
}
/*------------------------------------------------------------------------------
Stop the update card status
------------------------------------------------------------------------------*/
SmartcardDebug(
DEBUG_TRACE,
("GEMSCR09!GDDKNT_09UpdateCardStatus: PsTerminateSystemThread\n")
);
SmartcardExtension->ReaderExtension->CardStatus.Mode = STOP_IN_PROCESS;
status = PsTerminateSystemThread(STATUS_SUCCESS);
}
/*******************************************************************************
* NTSTATUS GDDKNT_09DeviceControl
* (
* PDEVICE_OBJECT pDeviceObject,
* PIRP pIrp
* )
*
* Description :
* -------------
* This routine is called when a IOCTL_SMARTCARD_ is send to the driver.
*
* Remarks :
* -------------
* Nothing.
*
* In :
* -------------
* - pDeviceObject is a pointer to the device.
* - Irp holds the Irp involved.
*
* Out :
* -------------
* Nothing.
*
* Responses :
* -------------
* NTSTATUS
*******************************************************************************/
NTSTATUS GDDKNT_09DeviceControl
(
PDEVICE_OBJECT pDeviceObject,
PIRP pIrp
)
{
NTSTATUS
status = STATUS_SUCCESS;
ULONG
ioControlCode;
PDEVICE_EXTENSION
deviceExtension = pDeviceObject->DeviceExtension;
PSMARTCARD_EXTENSION
smartcardExtension = &deviceExtension->SmartcardExtension;
PIO_STACK_LOCATION
irpStack = IoGetCurrentIrpStackLocation(pIrp);
ASSERT(deviceExtension != NULL);
ASSERT(smartcardExtension != NULL);
ASSERT(irpStack != NULL);
/*------------------------------------------------------------------------------
Read the current IOCTL.
------------------------------------------------------------------------------*/
ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
SmartcardDebug(DEBUG_TRACE,("GEMSCR09!GDDKNT_09DeviceControl: IoControlCode=%lX\n",
ioControlCode));
/*------------------------------------------------------------------------------
If the IOCTL > 0x7FFFFFFF
Then
Is a Gemplus reader specific IOCTL
------------------------------------------------------------------------------*/
if (ioControlCode > 0x7FFFFFFF)
{
status =
GDDK_09SpecificIOCTL(
smartcardExtension,
ioControlCode,
irpStack->Parameters.DeviceIoControl.InputBufferLength,
pIrp->AssociatedIrp.SystemBuffer,
irpStack->Parameters.DeviceIoControl.OutputBufferLength,
pIrp->AssociatedIrp.SystemBuffer,
smartcardExtension->IoRequest.Information
);
IoCompleteRequest(pIrp,IO_NO_INCREMENT);
pIrp->IoStatus.Status = status;
}
/*------------------------------------------------------------------------------
Else
Is a standard Smart card IOCTL
If is a GET_ATTRIBUTE/SET_ATTRIBUTE with a specific Tag
Then
Is a Specific vendor Tag
------------------------------------------------------------------------------*/
else
{
if (
(
(ioControlCode == IOCTL_SMARTCARD_GET_ATTRIBUTE) ||
(ioControlCode == IOCTL_SMARTCARD_SET_ATTRIBUTE)
)
&&
( (ULONG) irpStack->Parameters.DeviceIoControl.InputBufferLength >=
(ULONG) sizeof(ULONG)
)
&&
( SCARD_CLASS(
(ULONG) *((PULONG)pIrp->AssociatedIrp.SystemBuffer)
) == SCARD_CLASS_VENDOR_DEFINED
)
)
{
status =
GDDK_09SpecificTag(
smartcardExtension,
ioControlCode,
irpStack->Parameters.DeviceIoControl.InputBufferLength,
pIrp->AssociatedIrp.SystemBuffer,
irpStack->Parameters.DeviceIoControl.OutputBufferLength,
pIrp->AssociatedIrp.SystemBuffer,
smartcardExtension->IoRequest.Information
);
IoCompleteRequest(pIrp,IO_NO_INCREMENT);
pIrp->IoStatus.Status = status;
}
/*------------------------------------------------------------------------------
Else
Call the SmartcardDeviceControl
------------------------------------------------------------------------------*/
else
{
status = SmartcardDeviceControl(smartcardExtension,pIrp);
}
}
SmartcardDebug(DEBUG_DRIVER,
("GEMSCR09!GDDKNT_09DeviceControl: ioControlCode=%lX status=%lX\n",
ioControlCode,status
)
);
return status;
}