Smart card driver is not getting listed.

  • Thread starter Thread starter Pham Tho Anh Minh
  • Start date Start date
P

Pham Tho Anh Minh

Guest
Dear experts,

I am developing a virtual smart card reader but I am sticking on make it visible to Smart Card Resource Manager.
My source code is based on this guide smart card design guide and Windows-driver-samples\smartcrd.

However, I just make it very simple as I can understand.

SmartcardDeviceControl return STATUS_DEVICE_BUSY(0x80000011) for IoControlCode IOCTL_SMARTCARD_IS_ABSENT(0x31002C or 3211308 in decimal) in callback routine EvtIoDeviceControl.

My source code:

NTSTATUS
DriverEntry(
_In_ PDRIVER_OBJECT DriverObject,
_In_ PUNICODE_STRING RegistryPath
)
{
WDF_DRIVER_CONFIG config;
NTSTATUS status;
SmartcardSetDebugLevel(DEBUG_ALL);
SmartcardDebug(
DEBUG_TRACE,
("VPJSCReader!DriverEntry: Enter - KMDF Version Built %s %s\n",
__DATE__, __TIME__)
);
WDF_DRIVER_CONFIG_INIT(&config,
VPJSCReaderEvtDeviceAdd
);
status = WdfDriverCreate(DriverObject,
RegistryPath,
WDF_NO_OBJECT_ATTRIBUTES,
&config,
WDF_NO_HANDLE
);
if (!NT_SUCCESS(status)) {
KdPrint(("WdfDriverCreate failed with status 0x%x\n", status));
return status;
}
SmartcardDebug(
DEBUG_TRACE,
("VPJSCReader!DriverEntry: Exit %x\n",
status)
);
return status;
}
NTSTATUS
VPJSCReaderEvtDeviceAdd(
_In_ WDFDRIVER Driver,
_Inout_ PWDFDEVICE_INIT DeviceInit
)
{
NTSTATUS status;
UNREFERENCED_PARAMETER(Driver);
PAGED_CODE();
SmartcardDebug(
DEBUG_TRACE,
("VPJSCReader!VPJSCReaderEvtDeviceAdd: Enter\n")
);
status = VPJSCReaderCreateDevice(DeviceInit);
SmartcardDebug(
DEBUG_TRACE,
("VPJSCReader!VPJSCReaderEvtDeviceAdd: Exit\n")
);
return status;
}
NTSTATUS
VPJSCReaderCreateDevice(
_Inout_ PWDFDEVICE_INIT DeviceInit
)
{
WDF_OBJECT_ATTRIBUTES deviceAttributes;
PDEVICE_CONTEXT deviceContext = NULL;
WDFDEVICE device;
NTSTATUS status;
PAGED_CODE();
WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_SMARTCARD);
WdfDeviceInitSetExclusive(DeviceInit, TRUE);
WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoBuffered);
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_CONTEXT);
deviceAttributes.EvtCleanupCallback = VPJSCReaderEvtDriverContextCleanup;
status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device);
if (NT_SUCCESS(status)) {
deviceContext = DeviceGetContext(device);
deviceContext->Device = device;
InterlockedIncrement((PLONG)& deviceContext->DeviceInstanceNo);
status = WdfDeviceCreateDeviceInterface(
device,
&SmartCardReaderGuid,
NULL // ReferenceString
);
if (NT_SUCCESS(status)) {
status = VPJSCReaderQueueInitialize(device);
}
}
if (!NT_SUCCESS(status)) {
return status;
}
return VPJSCReaderRegisterWithSmcLib(deviceContext);
}
NTSTATUS
VPJSCReaderRegisterWithSmcLib(
PDEVICE_CONTEXT DeviceContext
) {
PREADER_EXTENSION ReaderExtension;
PSMARTCARD_EXTENSION SmartcardExtension;
NTSTATUS status;
PAGED_CODE();
// set up the device extension.
SmartcardExtension = &DeviceContext->SmartcardExtension;
// allocate the reader extension
ReaderExtension = ExAllocatePoolWithTag(
NonPagedPoolNx,
sizeof(READER_EXTENSION),
SMARTCARD_POOL_TAG
);
if (ReaderExtension == NULL) {
SmartcardLogError(
WdfDriverWdmGetDriverObject(WdfGetDriver()),
STATUS_INSUFFICIENT_RESOURCES,
NULL,
0
);
status = STATUS_INSUFFICIENT_RESOURCES;
return status;
}
RtlZeroMemory(ReaderExtension, sizeof(READER_EXTENSION));
SmartcardExtension->ReaderExtension = ReaderExtension;
// setup smartcard extension - callback's
SmartcardExtension->ReaderFunction[RDF_CARD_POWER] = CBCardPower;
SmartcardExtension->ReaderFunction[RDF_TRANSMIT] = CBTransmit;
SmartcardExtension->ReaderFunction[RDF_CARD_TRACKING] = CBCardTracking;
SmartcardExtension->ReaderFunction[RDF_SET_PROTOCOL] = CBSetProtocol;
RtlCopyMemory( SmartcardExtension->VendorAttr.VendorName.Buffer, VPJSC_VENDOR_NAME, sizeof(VPJSC_VENDOR_NAME));
SmartcardExtension->VendorAttr.VendorName.Length = sizeof(VPJSC_VENDOR_NAME);
RtlCopyMemory(SmartcardExtension->VendorAttr.IfdType.Buffer, VPJSC_IFD_TYPE, sizeof(VPJSC_IFD_TYPE));
SmartcardExtension->VendorAttr.IfdType.Length = sizeof(VPJSC_IFD_TYPE);
SmartcardExtension->VendorAttr.UnitNo = DeviceContext->DeviceInstanceNo;
SmartcardExtension->VendorAttr.IfdVersion.BuildNumber = 0;
// store firmware revision in ifd version
SmartcardExtension->VendorAttr.IfdVersion.VersionMajor = 0;
SmartcardExtension->VendorAttr.IfdVersion.VersionMinor = 0;
SmartcardExtension->VendorAttr.IfdSerialNo.Length = 0;
// setup smartcard extension - reader capabilities
SmartcardExtension->ReaderCapabilities.SupportedProtocols = SCARD_PROTOCOL_T0;
SmartcardExtension->ReaderCapabilities.ReaderType = SCARD_READER_TYPE_VENDOR;
SmartcardExtension->ReaderCapabilities.MechProperties = 0;
SmartcardExtension->ReaderCapabilities.Channel = 0;
SmartcardExtension->ReaderCapabilities.CLKFrequency.Default = 4000;
SmartcardExtension->ReaderCapabilities.CLKFrequency.Max = 4000;
// reader could support higher data rates
SmartcardExtension->ReaderCapabilities.DataRatesSupported.List = 0;
SmartcardExtension->ReaderCapabilities.DataRatesSupported.Entries = 0;
SmartcardExtension->ReaderCapabilities.DataRate.Default = 9600;
SmartcardExtension->ReaderCapabilities.DataRate.Max = 9600;
SmartcardExtension->Version = SMCLIB_VERSION;
SmartcardExtension->SmartcardRequest.BufferSize = MIN_BUFFER_SIZE;
SmartcardExtension->SmartcardReply.BufferSize = MIN_BUFFER_SIZE;
SmartcardExtension->ReaderCapabilities.CurrentState = SCARD_ABSENT;
status = SmartcardInitialize(SmartcardExtension);
if (status != STATUS_SUCCESS) {
SmartcardLogError(
WdfDriverWdmGetDriverObject(WdfGetDriver()),
STATUS_INSUFFICIENT_RESOURCES,
NULL,
0
);
return status;
}
SmartcardExtension->OsData->DeviceObject = WdfDeviceWdmGetDeviceObject(DeviceContext->Device);
return status;
}

NTSTATUS
CBCardPower(
PSMARTCARD_EXTENSION SmartcardExtension
) {
UNREFERENCED_PARAMETER(SmartcardExtension);
SmartcardDebug(DEBUG_TRACE,("VPJSCReader!CBCardPower: Entry\n"));
return STATUS_NO_MEDIA;
}
NTSTATUS
CBSetProtocol(
PSMARTCARD_EXTENSION SmartcardExtension
) {
UNREFERENCED_PARAMETER(SmartcardExtension);
SmartcardDebug(DEBUG_TRACE, ("VPJSCReader!CBSetProtocol: Entry\n"));
return STATUS_NO_MEDIA;
}
NTSTATUS
CBTransmit(
PSMARTCARD_EXTENSION SmartcardExtension
) {
UNREFERENCED_PARAMETER(SmartcardExtension);
SmartcardDebug(DEBUG_TRACE, ("VPJSCReader!CBTransmit: Entry\n"));
return STATUS_NO_MEDIA;
}
NTSTATUS
CBCardTracking(
PSMARTCARD_EXTENSION SmartcardExtension
) {
UNREFERENCED_PARAMETER(SmartcardExtension);
SmartcardDebug(DEBUG_TRACE, ("VPJSCReader!CBCardTracking: Entry\n"));
return STATUS_SUCCESS;
}


_Function_class_(IO_COMPLETION_ROUTINE)
NTSTATUS
VPJSCReaderLibComplete(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
{
UNREFERENCED_PARAMETER(DeviceObject);

KdPrint(("VPJSCReaderLibComplete called: status %x, Context %p\n", Irp->IoStatus.Status, Context));

WdfRequestComplete((WDFREQUEST)Context, Irp->IoStatus.Status);

return STATUS_MORE_PROCESSING_REQUIRED;
}

VOID
VPJSCReaderEvtIoDeviceControl(
_In_ WDFQUEUE Queue,
_In_ WDFREQUEST Request,
_In_ size_t OutputBufferLength,
_In_ size_t InputBufferLength,
_In_ ULONG IoControlCode
)
{
PDEVICE_CONTEXT deviceExtension;
PIRP irp;

KdPrint(("VPJSCReaderEvtIoDeviceControl Queue 0x%p, Request 0x%p OutputBufferLength %d InputBufferLength %d IoControlCode %d\n",
Queue, Request, (int) OutputBufferLength, (int) InputBufferLength, IoControlCode));

deviceExtension = DeviceGetContext(WdfIoQueueGetDevice(Queue));

irp = WdfRequestWdmGetIrp(Request);

SET_REQUEST_IN_IRP(irp, Request);

IoCopyCurrentIrpStackLocationToNext(irp);

IoSetCompletionRoutine(irp,
VPJSCReaderLibComplete,
Request,
TRUE,
TRUE,
TRUE
);

IoSetNextIrpStackLocation(irp);

(VOID)SmartcardDeviceControl(&(deviceExtension->SmartcardExtension), irp);

return;
}

And this is how I install the driver.
devcon install VPJSCReader.inf root\VPJSCReader
Device node created. Install is complete when drivers are installed...
Updating drivers for root\VPJSCReader from c:\Users\minh\Downloads\VPJSCReader\VPJSCReader.inf.
Drivers installed successfully.

Here is debugger's log.
VPJSCReader!DriverEntry: Enter - KMDF Version Built Oct 14 2019 08:50:44
VPJSCReader!DriverEntry: Exit 0
VPJSCReader!VPJSCReaderEvtDeviceAdd: Enter
VPJSCReader!VPJSCReaderEvtDeviceAdd: Exit
VPJSCReaderEvtIoDeviceControl Queue 0x00001B78487674E8, Request 0x00001B784F5051D8 OutputBufferLength 4 InputBufferLength 4 IoControlCode 3211272
VPJSCReaderLibComplete called: status 0, Context 00001B784F5051D8
VPJSCReaderEvtIoDeviceControl Queue 0x00001B78487674E8, Request 0x00001B784F5051D8 OutputBufferLength 36 InputBufferLength 4 IoControlCode 3211272
VPJSCReaderLibComplete called: status 0, Context 00001B784F5051D8
VPJSCReaderEvtIoDeviceControl Queue 0x00001B78487674E8, Request 0x00001B784F5051D8 OutputBufferLength 36 InputBufferLength 4 IoControlCode 3211272
VPJSCReaderLibComplete called: status 0, Context 00001B784F5051D8
VPJSCReaderEvtIoDeviceControl Queue 0x00001B78487674E8, Request 0x00001B784F5051D8 OutputBufferLength 4 InputBufferLength 4 IoControlCode 3211272
VPJSCReaderLibComplete called: status 0, Context 00001B784F5051D8
VPJSCReaderEvtIoDeviceControl Queue 0x00001B78487674E8, Request 0x00001B784F5051D8 OutputBufferLength 4 InputBufferLength 4 IoControlCode 3211272
VPJSCReaderLibComplete called: status 0, Context 00001B784F5051D8
VPJSCReaderEvtIoDeviceControl Queue 0x00001B78487674E8, Request 0x00001B784F5051D8 OutputBufferLength 0 InputBufferLength 0 IoControlCode 3211304
VPJSCReader!CBCardTracking: Entry
VPJSCReaderLibComplete called: status 0, Context 00001B784F5051D8
VPJSCReaderEvtIoDeviceControl Queue 0x00001B78487674E8, Request 0x00001B784F5051D8 OutputBufferLength 4 InputBufferLength 0 IoControlCode 3211320
VPJSCReaderLibComplete called: status 0, Context 00001B784F5051D8
VPJSCReaderEvtIoDeviceControl Queue 0x00001B78487674E8, Request 0x00001B784F5051D8 OutputBufferLength 0 InputBufferLength 0 IoControlCode 3211308
VPJSCReaderLibComplete called: status 80000011, Context 00001B784F5051D8
VPJSCReaderEvtIoDeviceControl Queue 0x00001B78487674E8, Request 0x00001B784F5051D8 OutputBufferLength 0 InputBufferLength 0 IoControlCode 3211308
VPJSCReaderLibComplete called: status 80000011, Context 00001B784F5051D8
VPJSCReaderEvtIoDeviceControl Queue 0x00001B78487674E8, Request 0x00001B784F5051D8 OutputBufferLength 0 InputBufferLength 0 IoControlCode 3211308
VPJSCReaderLibComplete called: status 80000011, Context 00001B784F5051D8
In the last three IO request, it return status 80000011.

And here what I receive after SmartcardDeviceControl is called(I am using WinDbg to get these information).
----------------------------------------
For IoControlCode = IOCTL_SMARTCARD_IS_PRESENT, it returns Irp->IoStatus.Status = STATUS_SUCCESS => same as my expectation.
For IoControlCode = IOCTL_SMARTCARD_GET_STATE, it returns Irp->IoStatus.Status = STATUS_SUCCESS, state via Output Buffer = SCARD_ABSENT => same as my expectation.
For IoControlCode = IOCTL_SMARTCARD_IS_ABSENT, it returns Irp->IoStatus.Status= STATUS_DEVICE_BUSY, not same as my expectation. It should be STATUS_SUCCESS.

-------------------------------------

I think this problem here is a cause that prevent my reader listed by SCardListReaders. Any idea is welcome!






However, I just make it very simple as I can understand.

SmartcardDeviceControl return STATUS_DEVICE_BUSY(0x80000011) for IoControlCode IOCTL_SMARTCARD_IS_ABSENT(0x31002C or 3211308 in decimal) in callback routine EvtIoDeviceControl.

I guess this is a problem prevent my reader visible to Smart Card Resource Manager but I don't know how to fix it.
I am new in this field. Any guidance would be really helpful.

My source code.

Continue reading...
 
Back
Top