Win 7 and IOCTL_SMARTCARD_GET_ATTRIBUTE problem

I have a filter driver for smartcard. Driver is loaded. Devices added. No problem. Under some condition I want to know the name of the device.
So I send IOCTL_SMARTCARD_GET_ATTRIBUTE with next the codes: SCARD_ATTR_VENDOR_NAME/ SCARD_ATTR_VENDOR_IFD_TYPE/SCARD_ATTR_DEVICE_UNIT
to the lower devices (the same also are send by win on booting).

Under Win XP: perfect no problem (tested with 10 diff smartcard devices)
Under Win Vista: perfect no problem (tested with 10 diff smartcard devices) + I tested also with generic driver for usb smartcard from vista (usbccid.sys)
Under Win 7: problem !!!. Tested with 10 dif smartcard devices - no problem (The devices are coming with their driver ).
Tested with generic driver for usb smartcard from Win 7 problem (WUDFUsbccidDriver.dll) always I get STATUS_INVALID_DEVICE_REQUEST.

Here is the quilty code:

NTSTATUS IoCompletionReaderInfo(PDEVICE_OBJECT pDeviceObject, PIRP pIrp, PVOID pContext)
{
if(pIrp->PendingReturned == TRUE)
IoMarkIrpPending(pIrp);

PDATA_IN_OUT pDataInOut = (PDATA_IN_OUT)pContext;
if(pDataInOut != NULL)
{
pDataInOut->ulDataOut = pIrp->IoStatus.Information > pDataInOut->ulDataOut ?
pDataInOut->ulDataOut : pIrp->IoStatus.Information;
RtlCopyMemory(pDataInOut->pDataOut, (BYTE*)pIrp->AssociatedIrp.SystemBuffer, pDataInOut->ulDataOut);
}

IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return STATUS_MORE_PROCESSING_REQUIRED;
}

NTSTATUS QueryReaderInfo(IN PDEVICE_OBJECT pDevLow, ULONG ulRequest, BYTE* pBufData, ULONG& ulBuffer)
{
NTSTATUS nStatus = STATUS_INSUFFICIENT_RESOURCES;
if(pPdo != NULL && pBufData != NULL)
{
KEVENT pkEvent;
IO_STATUS_BLOCK ioStatusBlock;
PAGED_CODE();

KeInitializeEvent( &pkEvent, NotificationEvent, FALSE );
PIRP pIrp = IoBuildDeviceIoControlRequest(IOCTL_SMARTCARD_GET_ATTRIBUTE, pDevLow, &ulRequest, sizeof(ULONG), pBufData, ulBuffer, false, &pkEvent, &ioStatusBlock);

if(pIrp != NULL)
{
DATA_IN_OUT stDataOut;
stDataOut.pDataOut = pBufData;
stDataOut.ulDataOut = ulBuffer;

PIO_STACK_LOCATION pIrpStack = IoGetNextIrpStackLocation(pIrp);
// pIrpStack->Flags = 0x05;
pIrp->IoStatus.Status = STATUS_NOT_SUPPORTED ;
IoSetCompletionRoutine(pIrp, IoCompletionReaderInfo, &stDataOut, TRUE, TRUE, TRUE);

nStatus = IoCallDriver(pPdo, pIrp);

if (nStatus == STATUS_PENDING)
{
KeWaitForSingleObject( &pkEvent, Executive, KernelMode, FALSE, NULL );
nStatus = ioStatusBlock.Status;
}

if (nStatus == STATUS_SUCCESS) // here in case win 7 nStatus = STATUS_INVALID_DEVICE_REQUEST.
ulBuffer = stDataOut.ulDataOut;
}
}
return nStatus;
}

Because on the booting the win do the same I try to see which are the difference. The only thing which I sow was:
Flags from IO_STACK_LOCATION has value 0x05. No where describe what means this value. Try the same value same error STATUS_INVALID_DEVICE_REQUEST.

Did somebody meet the same problem? Is it a bug in my code? Some suggestion where to start this problem?

Just a guess. Wudfusbcciddriver.dll (or UMDF really) expects that there be a file object in the stack location you are formatting since you must first open the device to send this ioctl.

d

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@yahoo.com
Sent: Friday, February 05, 2010 1:18 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] Win 7 and IOCTL_SMARTCARD_GET_ATTRIBUTE problem

I have a filter driver for smartcard. Driver is loaded. Devices added. No problem. Under some condition I want to know the name of the device.
So I send IOCTL_SMARTCARD_GET_ATTRIBUTE with next the codes: SCARD_ATTR_VENDOR_NAME/ SCARD_ATTR_VENDOR_IFD_TYPE/SCARD_ATTR_DEVICE_UNIT
to the lower devices (the same also are send by win on booting).

Under Win XP: perfect no problem (tested with 10 diff smartcard devices) Under Win Vista: perfect no problem (tested with 10 diff smartcard devices) + I tested also with generic driver for usb smartcard from vista (usbccid.sys) Under Win 7: problem !!!. Tested with 10 dif smartcard devices - no problem (The devices are coming with their driver ).
Tested with generic driver for usb smartcard from Win 7 problem (WUDFUsbccidDriver.dll) always I get STATUS_INVALID_DEVICE_REQUEST.

Here is the quilty code:

NTSTATUS IoCompletionReaderInfo(PDEVICE_OBJECT pDeviceObject, PIRP pIrp, PVOID pContext) {
if(pIrp->PendingReturned == TRUE)
IoMarkIrpPending(pIrp);

PDATA_IN_OUT pDataInOut = (PDATA_IN_OUT)pContext;
if(pDataInOut != NULL)
{
pDataInOut->ulDataOut = pIrp->IoStatus.Information > pDataInOut->ulDataOut ?
pDataInOut->ulDataOut : pIrp->IoStatus.Information;
RtlCopyMemory(pDataInOut->pDataOut, (BYTE*)pIrp->AssociatedIrp.SystemBuffer, pDataInOut->ulDataOut);
}

IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return STATUS_MORE_PROCESSING_REQUIRED; }

NTSTATUS QueryReaderInfo(IN PDEVICE_OBJECT pDevLow, ULONG ulRequest, BYTE* pBufData, ULONG& ulBuffer) {
NTSTATUS nStatus = STATUS_INSUFFICIENT_RESOURCES;
if(pPdo != NULL && pBufData != NULL)
{
KEVENT pkEvent;
IO_STATUS_BLOCK ioStatusBlock;
PAGED_CODE();

KeInitializeEvent( &pkEvent, NotificationEvent, FALSE );
PIRP pIrp = IoBuildDeviceIoControlRequest(IOCTL_SMARTCARD_GET_ATTRIBUTE, pDevLow, &ulRequest, sizeof(ULONG), pBufData, ulBuffer, false, &pkEvent, &ioStatusBlock);

if(pIrp != NULL)
{
DATA_IN_OUT stDataOut;
stDataOut.pDataOut = pBufData;
stDataOut.ulDataOut = ulBuffer;

PIO_STACK_LOCATION pIrpStack = IoGetNextIrpStackLocation(pIrp);
// pIrpStack->Flags = 0x05;
pIrp->IoStatus.Status = STATUS_NOT_SUPPORTED ;
IoSetCompletionRoutine(pIrp, IoCompletionReaderInfo, &stDataOut, TRUE, TRUE, TRUE);

nStatus = IoCallDriver(pPdo, pIrp);

if (nStatus == STATUS_PENDING)
{
KeWaitForSingleObject( &pkEvent, Executive, KernelMode, FALSE, NULL );
nStatus = ioStatusBlock.Status;
}

if (nStatus == STATUS_SUCCESS) // here in case win 7 nStatus = STATUS_INVALID_DEVICE_REQUEST.
ulBuffer = stDataOut.ulDataOut;
}
}
return nStatus;
}

Because on the booting the win do the same I try to see which are the difference. The only thing which I sow was:
Flags from IO_STACK_LOCATION has value 0x05. No where describe what means this value. Try the same value same error STATUS_INVALID_DEVICE_REQUEST.

Did somebody meet the same problem? Is it a bug in my code? Some suggestion where to start this problem?


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

Got your point. I’ll try tomorrow and give you a feedback asap if it works.

Hi Mr. Doron

Sorry for delay. I try to implement the new fix suggest by you. So for I was not so successfully. Here is the code:

NTSTATUS IoCompletionReaderInfo(PDEVICE_OBJECT pDeviceObject, PIRP pIrp, PVOID pContext)
{
if(pIrp->PendingReturned == TRUE)
IoMarkIrpPending(pIrp);

PDATA_IN_OUT pDataInOut = (PDATA_IN_OUT)pContext;
if(pDataInOut != NULL)
{
pDataInOut->ulDataOut = pIrp->IoStatus.Information > pDataInOut->ulDataOut ?
pDataInOut->ulDataOut : pIrp->IoStatus.Information;
RtlCopyMemory(pDataInOut->pDataOut, (BYTE*)pIrp->AssociatedIrp.SystemBuffer, pDataInOut->ulDataOut);
}

IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return STATUS_MORE_PROCESSING_REQUIRED;
}

NTSTATUS QueryReaderInfo(IN PDEVICE_OBJECT pPdo, ULONG ulRequest, BYTE* pBufData, ULONG& ulBuffer)
{
NTSTATUS nStatus = STATUS_INSUFFICIENT_RESOURCES;
if(pPdo != NULL && pBufData != NULL)
{
WCHAR szData[0x100];
ULONG ulRet = 0x00;
if((nStatus = IoGetDeviceProperty(pDevExt->pPdo, DevicePropertyPhysicalDeviceObjectName, 0x100 * sizeof(WCHAR), szData, &ulRet)) == STATUS_SUCCESS)
{
// <– Get here "\Device\0000035
PFILE_OBJECT pFileObj = NULL;
PDEVICE_OBJECT pDevObj = NULL;
UNICODE_STRING strRegKey;
RtlInitUnicodeString(&strRegKey, szData);

if((nStatus = IoGetDeviceObjectPointer(&strRegKey, FILE_READ_ATTRIBUTES, &pFileObj, &pDevObj)) == STATUS_SUCCESS) // <– Hang here look like lock
{
KEVENT pkEvent;
IO_STATUS_BLOCK ioStatusBlock;
PAGED_CODE();

KeInitializeEvent( &pkEvent, NotificationEvent, FALSE );
PIRP pIrp = IoBuildDeviceIoControlRequest(IOCTL_SMARTCARD_GET_ATTRIBUTE, pPdo, &ulRequest, sizeof(ULONG), pBufData, ulBuffer, false, &pkEvent, &ioStatusBlock);

if(pIrp != NULL)
{
DATA_IN_OUT stDataOut;
stDataOut.pDataOut = pBufData;
stDataOut.ulDataOut = ulBuffer;

PIO_STACK_LOCATION pIrpStack = IoGetNextIrpStackLocation(pIrp);
pIrpStack->Flags = 0x05;
pIrp->IoStatus.Status = STATUS_NOT_SUPPORTED ;
IoSetCompletionRoutine(pIrp, IoCompletionReaderInfo, &stDataOut, TRUE, TRUE, TRUE);

nStatus = IoCallDriver(pPdo, pIrp);

if (nStatus == STATUS_PENDING)
{
KeWaitForSingleObject( &pkEvent, Executive, KernelMode, FALSE, NULL );
nStatus = ioStatusBlock.Status;
}

if (nStatus == STATUS_SUCCESS)
ulBuffer = stDataOut.ulDataOut;
}
}
}
}
return nStatus;
}

I also try in state of IoGetDeviceObjectPointer to use ZwOpenFile:

OBJECT_ATTRIBUTES stObjAttr={0};
IO_STATUS_BLOCK stIoStatus={0};
HANDLE hFile = NULL;
UNICODE_STRING szName;
RtlInitUnicodeString(&szName, szData);
InitializeObjectAttributes(&stObjAttr, &szName, OBJ_CASE_INSENSITIVE, NULL, NULL );
nStatus = ZwOpenFile(&hFile, GENERIC_READ, &stObjAttr, &stIoStatus, FILE_SHARE_WRITE | FILE_SHARE_READ, 0); // <- hang here

As it looks like the Os it’s the one which open this file in non-share mode and will release only very late on shutdown. So the IoGetDeviceObjectPointer
/ZwOpenFile will get lock until the file is release. If I can’t open the file then looks that I can’t send any kind of device io ctrl to the device. Is it true?

Two things
1 in what context are you calling your queryreaderinfo()? The iogetdeviceobjectpointer/zwreadfile should never block indefinitely, it should return with a failure code immediate if you cannot open the device. both of these require that you run at passive level and that the device stack has been fully started.

2 do not put 512 bytes (szData) on the stack, there is only 8k of stack and that is too much to put on it. Allocate out of pool (and really you should call iogetdeviceobjectproperty with null the first time to get the size, alloc, and then call it again)

d

tiny phone keyboard + fat thumbs = you do the muth

-----Original Message-----
From: xxxxx@yahoo.com
Sent: Sunday, February 07, 2010 6:03 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Win 7 and IOCTL_SMARTCARD_GET_ATTRIBUTE problem

Hi Mr. Doron

Sorry for delay. I try to implement the new fix suggest by you. So for I was not so successfully. Here is the code:

NTSTATUS IoCompletionReaderInfo(PDEVICE_OBJECT pDeviceObject, PIRP pIrp, PVOID pContext)
{
if(pIrp->PendingReturned == TRUE)
IoMarkIrpPending(pIrp);

PDATA_IN_OUT pDataInOut = (PDATA_IN_OUT)pContext;
if(pDataInOut != NULL)
{
pDataInOut->ulDataOut = pIrp->IoStatus.Information > pDataInOut->ulDataOut ?
pDataInOut->ulDataOut : pIrp->IoStatus.Information;
RtlCopyMemory(pDataInOut->pDataOut, (BYTE*)pIrp->AssociatedIrp.SystemBuffer, pDataInOut->ulDataOut);
}

IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return STATUS_MORE_PROCESSING_REQUIRED;
}

NTSTATUS QueryReaderInfo(IN PDEVICE_OBJECT pPdo, ULONG ulRequest, BYTE* pBufData, ULONG& ulBuffer)
{
NTSTATUS nStatus = STATUS_INSUFFICIENT_RESOURCES;
if(pPdo != NULL && pBufData != NULL)
{
WCHAR szData[0x100];
ULONG ulRet = 0x00;
if((nStatus = IoGetDeviceProperty(pDevExt->pPdo, DevicePropertyPhysicalDeviceObjectName, 0x100 * sizeof(WCHAR), szData, &ulRet)) == STATUS_SUCCESS)
{
// <– Get here "\Device\0000035
PFILE_OBJECT pFileObj = NULL;
PDEVICE_OBJECT pDevObj = NULL;
UNICODE_STRING strRegKey;
RtlInitUnicodeString(&strRegKey, szData);

if((nStatus = IoGetDeviceObjectPointer(&strRegKey, FILE_READ_ATTRIBUTES, &pFileObj, &pDevObj)) == STATUS_SUCCESS) // <– Hang here look like lock
{
KEVENT pkEvent;
IO_STATUS_BLOCK ioStatusBlock;
PAGED_CODE();

KeInitializeEvent( &pkEvent, NotificationEvent, FALSE );
PIRP pIrp = IoBuildDeviceIoControlRequest(IOCTL_SMARTCARD_GET_ATTRIBUTE, pPdo, &ulRequest, sizeof(ULONG), pBufData, ulBuffer, false, &pkEvent, &ioStatusBlock);

if(pIrp != NULL)
{
DATA_IN_OUT stDataOut;
stDataOut.pDataOut = pBufData;
stDataOut.ulDataOut = ulBuffer;

PIO_STACK_LOCATION pIrpStack = IoGetNextIrpStackLocation(pIrp);
pIrpStack->Flags = 0x05;
pIrp->IoStatus.Status = STATUS_NOT_SUPPORTED ;
IoSetCompletionRoutine(pIrp, IoCompletionReaderInfo, &stDataOut, TRUE, TRUE, TRUE);

nStatus = IoCallDriver(pPdo, pIrp);

if (nStatus == STATUS_PENDING)
{
KeWaitForSingleObject( &pkEvent, Executive, KernelMode, FALSE, NULL );
nStatus = ioStatusBlock.Status;
}

if (nStatus == STATUS_SUCCESS)
ulBuffer = stDataOut.ulDataOut;
}
}
}
}
return nStatus;
}

I also try in state of IoGetDeviceObjectPointer to use ZwOpenFile:

OBJECT_ATTRIBUTES stObjAttr={0};
IO_STATUS_BLOCK stIoStatus={0};
HANDLE hFile = NULL;
UNICODE_STRING szName;
RtlInitUnicodeString(&szName, szData);
InitializeObjectAttributes(&stObjAttr, &szName, OBJ_CASE_INSENSITIVE, NULL, NULL );
nStatus = ZwOpenFile(&hFile, GENERIC_READ, &stObjAttr, &stIoStatus, FILE_SHARE_WRITE | FILE_SHARE_READ, 0); // <- hang here

As it looks like the Os it’s the one which open this file in non-share mode and will release only very late on shutdown. So the IoGetDeviceObjectPointer
/ZwOpenFile will get lock until the file is release. If I can’t open the file then looks that I can’t send any kind of device io ctrl to the device. Is it true?


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

Hi Mr. Doron

  1. I’m on passive level
  2. Correct. I fix it.
  3. Found the problem. Before calling IoGetDeviceObjectPointer(&strRegKey, FILE_READ_ATTRIBUTES, &pFileObj, &pDevObj)
    I call KeWaitForSingleObject(&g_evLock, Executive, KernelMode, FALSE, NULL);. Removing KeWaitForSingleObject works with no problem (Do you have some ideea?). I’ll try to implement your suggestion and to give asap a feedback.

I have no idea why your call to kewait is not coming back, it is your logic.

d

tiny phone keyboard + fat thumbs = you do the muth

-----Original Message-----
From: xxxxx@yahoo.com
Sent: Sunday, February 07, 2010 12:01 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Win 7 and IOCTL_SMARTCARD_GET_ATTRIBUTE problem

Hi Mr. Doron

1. I’m on passive level
2. Correct. I fix it.
3. Found the problem. Before calling IoGetDeviceObjectPointer(&strRegKey, FILE_READ_ATTRIBUTES, &pFileObj, &pDevObj)
I call KeWaitForSingleObject(&g_evLock, Executive, KernelMode, FALSE, NULL);. Removing KeWaitForSingleObject works with no problem (Do you have some ideea?). I’ll try to implement your suggestion and to give asap a feedback.


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

Hi Mr. Doron

I change the code and I apply your advices:

NTSTATUS IoCompletionReaderInfo(PDEVICE_OBJECT pDeviceObject, PIRP pIrp, PVOID pContext)
{
if(pIrp->PendingReturned == TRUE)
IoMarkIrpPending(pIrp);

PDATA_IN_OUT pDataInOut = (PDATA_IN_OUT)pContext;
if(pDataInOut != NULL)
{
pDataInOut->ulDataOut = pIrp->IoStatus.Information > pDataInOut->ulDataOut ?
pDataInOut->ulDataOut : pIrp->IoStatus.Information;
RtlCopyMemory(pDataInOut->pDataOut, (BYTE*)pIrp->AssociatedIrp.SystemBuffer, pDataInOut->ulDataOut);
}

IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return STATUS_MORE_PROCESSING_REQUIRED;
}

NTSTATUS QueryReaderInfo(IN PDEVICE_EXTENSION pDevExt, ULONG ulRequest, BYTE* pBufData, ULONG& ulBuffer)
{
NTSTATUS nStatus = STATUS_INSUFFICIENT_RESOURCES;
if(pDevExt != NULL && pBufData != NULL)
{
KEVENT pkEvent;
IO_STATUS_BLOCK ioStatusBlock;
PAGED_CODE();

KeInitializeEvent( &pkEvent, NotificationEvent, FALSE );
PIRP pIrp = IoBuildDeviceIoControlRequest(IOCTL_SMARTCARD_GET_ATTRIBUTE, pDevExt->pLowerDeviceObject, &ulRequest, sizeof(ULONG), pBufData, ulBuffer, false, &pkEvent, &ioStatusBlock);

if(pIrp != NULL)
{
DATA_IN_OUT stDataOut;
stDataOut.pDataOut = pBufData;
stDataOut.ulDataOut = ulBuffer;

PIO_STACK_LOCATION pIrpStack = IoGetNextIrpStackLocation(pIrp);
// pIrpStack->Flags = 0x05;
pIrp->IoStatus.Status = STATUS_NOT_SUPPORTED ;
IoSetCompletionRoutine(pIrp, IoCompletionReaderInfo, &stDataOut, TRUE, TRUE, TRUE);

// here get the info about FILE_OBJ
PFILE_OBJECT pFileObj = NULL;
PDEVICE_OBJECT pDevObj = NULL;

WCHAR* szData = (WCHAR*)ExAllocatePoolWithTag(PagedPool, 0x100 * sizeof(WCHAR), (ULONG)“RetData”);
ULONG ulRet = 0x00;
if(IoGetDeviceProperty(pDevExt->pPdo, DevicePropertyPhysicalDeviceObjectName, 0x100 * sizeof(WCHAR), szData, &ulRet) == STATUS_SUCCESS)
{
UNICODE_STRING strRegKey;
RtlInitUnicodeString(&strRegKey, szData);
if(IoGetDeviceObjectPointer(&strRegKey, FILE_READ_ATTRIBUTES, &pFileObj, &pDevObj) == STATUS_SUCCESS)
{
pIrpStack->FileObject = pFileObj;
pIrpStack->DeviceObject = pDevObj;
}
}
ExFreePoolWithTag(szData, (ULONG)“RetData”);
nStatus = IoCallDriver(pDevExt->pLowerDeviceObject, pIrp);

if (nStatus == STATUS_PENDING)
{
KeWaitForSingleObject( &pkEvent, Executive, KernelMode, FALSE, NULL );
nStatus = ioStatusBlock.Status;
}

// here I get STATUS_CANCELLED
// if I coment // pIrpStack->DeviceObject = pDevObj; I get STATUS_LOGON_SESSION_COLLISION
if (nStatus == STATUS_SUCCESS)
ulBuffer = stDataOut.ulDataOut;

if(pFileObj != NULL)
ObDereferenceObject(pFileObj);
}
}
return nStatus;
}

Status is return is STATUS_CANCELLED. If I comment pIrpStack->DeviceObject = pDevObj; I got STATUS_LOGON_SESSION_COLLISION
IoCompletionReaderInfo is call but pIrp->IoStatus.Information = 0x00
Some new ideea?

> WCHAR* szData = (WCHAR*)ExAllocatePoolWithTag(PagedPool, 0x100 * sizeof(WCHAR), (ULONG)“RetData”);

Does not do what you think it does. You are casting (and truncating on x64) the string pointer value. There is a difference between “RetData” and ‘RetData’. The former is a string, the second is a sequence of characters forming an integer value.

if(IoGetDeviceProperty(pDevExt->pPdo, DevicePropertyPhysicalDeviceObjectName, 0x100 * sizeof(WCHAR), szData, &ulRet) == STATUS_SUCCESS)
You should never compare directly against STATUS_SUCCESS, use NT_SUCCESS() instead. If you turn on driver verifier, these checks against specific return values may fail.

pIrpStack->DeviceObject = pDevObj;
You don’t set this, IoCallDriver sets this

How about sending the IRP to pDevObj returned by IoGetDeviceObjectPointer instead of the lower object? (and also allocating the PIRP after you acquire the pDevObj value). Also, IoGetDeviceObjectPointer sends a irp_mj_cleanup to the stack before returning, it could very well be the stack does not accept io after receiving the cleanup. Try ZwOpenFile, converting the resulting handle to a pfile_object via ObReferenceObjectByHandle and sending the IOCTL that way (and then closing the handle and derefing the pfile_object)

d

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@yahoo.com
Sent: Monday, February 08, 2010 1:22 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Win 7 and IOCTL_SMARTCARD_GET_ATTRIBUTE problem

Hi Mr. Doron

I change the code and I apply your advices:

NTSTATUS IoCompletionReaderInfo(PDEVICE_OBJECT pDeviceObject, PIRP pIrp, PVOID pContext)
{
if(pIrp->PendingReturned == TRUE)
IoMarkIrpPending(pIrp);

PDATA_IN_OUT pDataInOut = (PDATA_IN_OUT)pContext;
if(pDataInOut != NULL)
{
pDataInOut->ulDataOut = pIrp->IoStatus.Information > pDataInOut->ulDataOut ?
pDataInOut->ulDataOut : pIrp->IoStatus.Information;
RtlCopyMemory(pDataInOut->pDataOut, (BYTE*)pIrp->AssociatedIrp.SystemBuffer, pDataInOut->ulDataOut);
}

IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return STATUS_MORE_PROCESSING_REQUIRED;
}

NTSTATUS QueryReaderInfo(IN PDEVICE_EXTENSION pDevExt, ULONG ulRequest, BYTE* pBufData, ULONG& ulBuffer)
{
NTSTATUS nStatus = STATUS_INSUFFICIENT_RESOURCES;
if(pDevExt != NULL && pBufData != NULL)
{
KEVENT pkEvent;
IO_STATUS_BLOCK ioStatusBlock;
PAGED_CODE();

KeInitializeEvent( &pkEvent, NotificationEvent, FALSE );
PIRP pIrp = IoBuildDeviceIoControlRequest(IOCTL_SMARTCARD_GET_ATTRIBUTE, pDevExt->pLowerDeviceObject, &ulRequest, sizeof(ULONG), pBufData, ulBuffer, false, &pkEvent, &ioStatusBlock);

if(pIrp != NULL)
{
DATA_IN_OUT stDataOut;
stDataOut.pDataOut = pBufData;
stDataOut.ulDataOut = ulBuffer;

PIO_STACK_LOCATION pIrpStack = IoGetNextIrpStackLocation(pIrp);
// pIrpStack->Flags = 0x05;
pIrp->IoStatus.Status = STATUS_NOT_SUPPORTED ;
IoSetCompletionRoutine(pIrp, IoCompletionReaderInfo, &stDataOut, TRUE, TRUE, TRUE);

// here get the info about FILE_OBJ
PFILE_OBJECT pFileObj = NULL;
PDEVICE_OBJECT pDevObj = NULL;

WCHAR* szData = (WCHAR*)ExAllocatePoolWithTag(PagedPool, 0x100 * sizeof(WCHAR), (ULONG)“RetData”);
ULONG ulRet = 0x00;
if(IoGetDeviceProperty(pDevExt->pPdo, DevicePropertyPhysicalDeviceObjectName, 0x100 * sizeof(WCHAR), szData, &ulRet) == STATUS_SUCCESS)
{
UNICODE_STRING strRegKey;
RtlInitUnicodeString(&strRegKey, szData);
if(IoGetDeviceObjectPointer(&strRegKey, FILE_READ_ATTRIBUTES, &pFileObj, &pDevObj) == STATUS_SUCCESS)
{
pIrpStack->FileObject = pFileObj;
pIrpStack->DeviceObject = pDevObj;
}
}
ExFreePoolWithTag(szData, (ULONG)“RetData”);
nStatus = IoCallDriver(pDevExt->pLowerDeviceObject, pIrp);

if (nStatus == STATUS_PENDING)
{
KeWaitForSingleObject( &pkEvent, Executive, KernelMode, FALSE, NULL );
nStatus = ioStatusBlock.Status;
}

// here I get STATUS_CANCELLED
// if I coment // pIrpStack->DeviceObject = pDevObj; I get STATUS_LOGON_SESSION_COLLISION
if (nStatus == STATUS_SUCCESS)
ulBuffer = stDataOut.ulDataOut;

if(pFileObj != NULL)
ObDereferenceObject(pFileObj);
}
}
return nStatus;
}

Status is return is STATUS_CANCELLED. If I comment pIrpStack->DeviceObject = pDevObj; I got STATUS_LOGON_SESSION_COLLISION
IoCompletionReaderInfo is call but pIrp->IoStatus.Information = 0x00
Some new ideea?


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

Hi Mr. Doron

Thank you for your advices and for your tips. Was very professional and very helpful.
Here is the code modify according your advice which works (I was able to send IOCTL_SMARTCARD_GET_ATTRIBUTE without problem).
I have only one generic question: Is it possible in case of if ZwOpenFile fails? (In Vista I meet this behaviour for several drivers).

NTSTATUS IoCompletionReaderInfo(PDEVICE_OBJECT pDeviceObject, PIRP pIrp, PVOID pContext)
{
if(pIrp->PendingReturned == TRUE)
IoMarkIrpPending(pIrp);

PDATA_IN_OUT pDataInOut = (PDATA_IN_OUT)pContext;
if(pDataInOut != NULL)
{
pDataInOut->ulDataOut = pIrp->IoStatus.Information > pDataInOut->ulDataOut ?
pDataInOut->ulDataOut : pIrp->IoStatus.Information;
RtlCopyMemory(pDataInOut->pDataOut, (BYTE*)pIrp->AssociatedIrp.SystemBuffer, pDataInOut->ulDataOut);
}

IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return STATUS_MORE_PROCESSING_REQUIRED;
}

NTSTATUS QueryReaderInfo(IN PDEVICE_EXTENSION pDevExt, ULONG ulRequest, BYTE* pBufData, ULONG& ulBuffer)
{
NTSTATUS nStatus = STATUS_INSUFFICIENT_RESOURCES;
if(pDevExt != NULL && pBufData != NULL)
{
KEVENT pkEvent;
IO_STATUS_BLOCK ioStatusBlock;
PAGED_CODE();

KeInitializeEvent( &pkEvent, NotificationEvent, FALSE );
PIRP pIrp = IoBuildDeviceIoControlRequest(IOCTL_SMARTCARD_GET_ATTRIBUTE, pDevExt->pLowerDeviceObject, &ulRequest, sizeof(ULONG), pBufData, ulBuffer, false, &pkEvent, &ioStatusBlock);

if(pIrp != NULL)
{
DATA_IN_OUT stDataOut;
stDataOut.pDataOut = pBufData;
stDataOut.ulDataOut = ulBuffer;

PIO_STACK_LOCATION pIrpStack = IoGetNextIrpStackLocation(pIrp);
pIrpStack->Flags = 0x05;
pIrp->IoStatus.Status = STATUS_NOT_SUPPORTED ;
IoSetCompletionRoutine(pIrp, IoCompletionReaderInfo, &stDataOut, TRUE, TRUE, TRUE);

// here get the info about FILE_OBJ
PFILE_OBJECT pFileObj = NULL;
PDEVICE_OBJECT pDevObj = NULL;
HANDLE hFile = NULL;

WCHAR* szData = (WCHAR*)ExAllocatePoolWithTag(PagedPool, 0x100 * sizeof(WCHAR), (ULONG)‘Data’);
ULONG ulRet = 0x00;
if(NT_SUCCESS(IoGetDeviceProperty(pDevExt->pPdo, DevicePropertyPhysicalDeviceObjectName, 0x100 * sizeof(WCHAR), szData, &ulRet)))
{
UNICODE_STRING strRegKey;
RtlInitUnicodeString(&strRegKey, szData);

OBJECT_ATTRIBUTES stObjAttr ={0};
IO_STATUS_BLOCK stIoStatus ={0};
InitializeObjectAttributes(&stObjAttr, &strRegKey, OBJ_CASE_INSENSITIVE, NULL, NULL );
if(NT_SUCCESS(ZwOpenFile(&hFile, GENERIC_READ, &stObjAttr, &stIoStatus, FILE_SHARE_WRITE | FILE_SHARE_READ, 0)))
{
if(NT_SUCCESS(ObReferenceObjectByHandle(hFile, 0, *IoFileObjectType, KernelMode,
((PVOID*)&pFileObj), NULL)))
pIrpStack->FileObject = pFileObj;

}

/*if(IoGetDeviceObjectPointer(&strRegKey, FILE_ALL_ACCESS, &pFileObj, &pDevObj) == STATUS_SUCCESS)
pIrpStack->FileObject = pFileObj;*/
}
ExFreePoolWithTag(szData, (ULONG)‘Data’);
nStatus = IoCallDriver(pDevExt->pLowerDeviceObject, pIrp);

if (nStatus == STATUS_PENDING)
{
KeWaitForSingleObject( &pkEvent, Executive, KernelMode, FALSE, NULL );
nStatus = ioStatusBlock.Status;
}

if (nStatus == STATUS_SUCCESS)
ulBuffer = stDataOut.ulDataOut;

if(hFile != NULL)
ZwClose(hFile);

if(pFileObj != NULL)
ObDereferenceObject(pFileObj);
}
}
return nStatus;
}

How does ZwOpenFile fail? what is the NTSTATUS returned? Why are you copying the buffer again in IoCompletionReaderInfo? The buffer will be copied when the lower driver completes the io request b/c you specified pBufData as the output buffer when you called IoBuildDeviceIoControlRequest

This is not necessary either

pIrpStack->Flags = 0x05;

d

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@yahoo.com
Sent: Wednesday, February 10, 2010 12:52 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Win 7 and IOCTL_SMARTCARD_GET_ATTRIBUTE problem

Hi Mr. Doron

Thank you for your advices and for your tips. Was very professional and very helpful.
Here is the code modify according your advice which works (I was able to send IOCTL_SMARTCARD_GET_ATTRIBUTE without problem).
I have only one generic question: Is it possible in case of if ZwOpenFile fails? (In Vista I meet this behaviour for several drivers).

NTSTATUS IoCompletionReaderInfo(PDEVICE_OBJECT pDeviceObject, PIRP pIrp, PVOID pContext)
{
if(pIrp->PendingReturned == TRUE)
IoMarkIrpPending(pIrp);

PDATA_IN_OUT pDataInOut = (PDATA_IN_OUT)pContext;
if(pDataInOut != NULL)
{
pDataInOut->ulDataOut = pIrp->IoStatus.Information > pDataInOut->ulDataOut ?
pDataInOut->ulDataOut : pIrp->IoStatus.Information;
RtlCopyMemory(pDataInOut->pDataOut, (BYTE*)pIrp->AssociatedIrp.SystemBuffer, pDataInOut->ulDataOut);
}

IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return STATUS_MORE_PROCESSING_REQUIRED;
}

NTSTATUS QueryReaderInfo(IN PDEVICE_EXTENSION pDevExt, ULONG ulRequest, BYTE* pBufData, ULONG& ulBuffer)
{
NTSTATUS nStatus = STATUS_INSUFFICIENT_RESOURCES;
if(pDevExt != NULL && pBufData != NULL)
{
KEVENT pkEvent;
IO_STATUS_BLOCK ioStatusBlock;
PAGED_CODE();

KeInitializeEvent( &pkEvent, NotificationEvent, FALSE );
PIRP pIrp = IoBuildDeviceIoControlRequest(IOCTL_SMARTCARD_GET_ATTRIBUTE, pDevExt->pLowerDeviceObject, &ulRequest, sizeof(ULONG), pBufData, ulBuffer, false, &pkEvent, &ioStatusBlock);

if(pIrp != NULL)
{
DATA_IN_OUT stDataOut;
stDataOut.pDataOut = pBufData;
stDataOut.ulDataOut = ulBuffer;

PIO_STACK_LOCATION pIrpStack = IoGetNextIrpStackLocation(pIrp);
pIrpStack->Flags = 0x05;
pIrp->IoStatus.Status = STATUS_NOT_SUPPORTED ;
IoSetCompletionRoutine(pIrp, IoCompletionReaderInfo, &stDataOut, TRUE, TRUE, TRUE);

// here get the info about FILE_OBJ
PFILE_OBJECT pFileObj = NULL;
PDEVICE_OBJECT pDevObj = NULL;
HANDLE hFile = NULL;

WCHAR* szData = (WCHAR*)ExAllocatePoolWithTag(PagedPool, 0x100 * sizeof(WCHAR), (ULONG)‘Data’);
ULONG ulRet = 0x00;
if(NT_SUCCESS(IoGetDeviceProperty(pDevExt->pPdo, DevicePropertyPhysicalDeviceObjectName, 0x100 * sizeof(WCHAR), szData, &ulRet)))
{
UNICODE_STRING strRegKey;
RtlInitUnicodeString(&strRegKey, szData);

OBJECT_ATTRIBUTES stObjAttr ={0};
IO_STATUS_BLOCK stIoStatus ={0};
InitializeObjectAttributes(&stObjAttr, &strRegKey, OBJ_CASE_INSENSITIVE, NULL, NULL );
if(NT_SUCCESS(ZwOpenFile(&hFile, GENERIC_READ, &stObjAttr, &stIoStatus, FILE_SHARE_WRITE | FILE_SHARE_READ, 0)))
{
if(NT_SUCCESS(ObReferenceObjectByHandle(hFile, 0, *IoFileObjectType, KernelMode,
((PVOID*)&pFileObj), NULL)))
pIrpStack->FileObject = pFileObj;

}

/*if(IoGetDeviceObjectPointer(&strRegKey, FILE_ALL_ACCESS, &pFileObj, &pDevObj) == STATUS_SUCCESS)
pIrpStack->FileObject = pFileObj;*/
}
ExFreePoolWithTag(szData, (ULONG)‘Data’);
nStatus = IoCallDriver(pDevExt->pLowerDeviceObject, pIrp);

if (nStatus == STATUS_PENDING)
{
KeWaitForSingleObject( &pkEvent, Executive, KernelMode, FALSE, NULL );
nStatus = ioStatusBlock.Status;
}

if (nStatus == STATUS_SUCCESS)
ulBuffer = stDataOut.ulDataOut;

if(hFile != NULL)
ZwClose(hFile);

if(pFileObj != NULL)
ObDereferenceObject(pFileObj);
}
}
return nStatus;
}


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer