The CDO disappear

Hi,

My driver is installed as the upper filters of the class Keyboard and mouse. It creates two control device objects when the first instace of the device object is added and deletes the two control device objects when the last instance of the device object is deleted. Most of the time, the application can open the two control devices and do the IOCTLs successfully. However, sometimes the application failed in calling the CreateFile due to the error cod 2(ERROR_FILE_NOT_FOUND). In this case, I couldn’t see the two control device objects in the WinObj. It looks the the control device objects get deleted for some reason. I’m 100% sure that there is still keyboard and mouse connected to my machine. I paste my code to see whether any problems exist to cause that issue.

FilterEvtDeviceAdd
{

WdfWaitLockAcquire(pDriverContext->hDeviceCollectionLock, NULL);
status = WdfCollectionAdd(pDriverContext->hDeviceCollection,hDevice);
ulInstanceNo = WdfCollectionGetCount(pDriverContext->hDeviceCollection);
if (ulInstanceNo == 1)
{
status = RzFilter_CreateControlDevice(Driver,&kbdNTName,&kbdDosName,&pDriverContext->hKbdControlDevice);
status = RzFilter_CreateControlDevice(Driver,&mouNTName,&mouDosName,&pDriverContext->hMouControlDevice);
}
WdfWaitLockRelease(pDriverContext->hDeviceCollectionLock);

}

FilterEvtDeviceContextCleanup
{

WdfWaitLockAcquire(pDriverContext->hDeviceCollectionLock, NULL);
ulInstanceNo = WdfCollectionGetCount(pDriverContext->hDeviceCollection);
if (ulInstanceNo == 1)
{
RzFilter_DeleteControlDevice(pDriverContext->hKbdControlDevice);
pDriverContext->hKbdControlDevice = NULL;

RzFilter_DeleteControlDevice(pDriverContext->hMouControlDevice);
pDriverContext->hMouControlDevice = NULL;
}
WdfCollectionRemove(pDriverContext->hDeviceCollection, Device);
WdfWaitLockRelease(pDriverContext->hDeviceCollectionLock);

}

Thanks,
Marshall

You need to add logging and figure thus out, cdos do not get deleted behind your back

d

Bent from my Phone


From: xxxxx@hotmail.commailto:xxxxx
Sent: ?6/?30/?2013 10:01 PM
To: Windows System Software Devs Interest Listmailto:xxxxx
Subject: [ntdev] The CDO disappear

Hi,

My driver is installed as the upper filters of the class Keyboard and mouse. It creates two control device objects when the first instace of the device object is added and deletes the two control device objects when the last instance of the device object is deleted. Most of the time, the application can open the two control devices and do the IOCTLs successfully. However, sometimes the application failed in calling the CreateFile due to the error cod 2(ERROR_FILE_NOT_FOUND). In this case, I couldn’t see the two control device objects in the WinObj. It looks the the control device objects get deleted for some reason. I’m 100% sure that there is still keyboard and mouse connected to my machine. I paste my code to see whether any problems exist to cause that issue.

FilterEvtDeviceAdd
{

WdfWaitLockAcquire(pDriverContext->hDeviceCollectionLock, NULL);
status = WdfCollectionAdd(pDriverContext->hDeviceCollection,hDevice);
ulInstanceNo = WdfCollectionGetCount(pDriverContext->hDeviceCollection);
if (ulInstanceNo == 1)
{
status = RzFilter_CreateControlDevice(Driver,&kbdNTName,&kbdDosName,&pDriverContext->hKbdControlDevice);
status = RzFilter_CreateControlDevice(Driver,&mouNTName,&mouDosName,&pDriverContext->hMouControlDevice);
}
WdfWaitLockRelease(pDriverContext->hDeviceCollectionLock);

}

FilterEvtDeviceContextCleanup
{

WdfWaitLockAcquire(pDriverContext->hDeviceCollectionLock, NULL);
ulInstanceNo = WdfCollectionGetCount(pDriverContext->hDeviceCollection);
if (ulInstanceNo == 1)
{
RzFilter_DeleteControlDevice(pDriverContext->hKbdControlDevice);
pDriverContext->hKbdControlDevice = NULL;

RzFilter_DeleteControlDevice(pDriverContext->hMouControlDevice);
pDriverContext->hMouControlDevice = NULL;
}
WdfCollectionRemove(pDriverContext->hDeviceCollection, Device);
WdfWaitLockRelease(pDriverContext->hDeviceCollectionLock);

}

Thanks,
Marshall


NTDEV is sponsored by OSR

Visit the list at: http://www.osronline.com/showlists.cfm?list=ntdev

OSR is HIRING!! See http://www.osr.com/careers

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</mailto:xxxxx></mailto:xxxxx>

Hi Doron,

I have the WPP log in the code. The code I paste here is simplified for reading. However, this issue happens once in several weeks on our clients’ machine. The clients sent us the issue through our feedback system.

Per your experiences, is there any potential issue in the above code? How can I debug this kind of issue?

To work arround this issue, can I create the cdos in the DriverEntry and delete them in the EvtDriverUnload?

Thanks,
Marshall

Hi Doron,

Is it possible that creating the CDOs failed? I used the code from the toaster sample. The clients feedback that it happened after reboot.

NTSTATUS
RzFilter_CreateControlDevice(
IN WDFDRIVER hDriver,
IN PCUNICODE_STRING pszNTName,
IN PCUNICODE_STRING pszDosName,
OUT WDFDEVICE* phDevice
)
{
NTSTATUS status = STATUS_SUCCESS;
PWDFDEVICE_INIT pInit = NULL;
WDFDEVICE controlDevice = NULL;
WDF_IO_QUEUE_CONFIG ioQueueConfig = {0};
WDF_OBJECT_ATTRIBUTES deviceAttributes = {0};
WDF_OBJECT_ATTRIBUTES lockAttributes = {0};
WDF_FILEOBJECT_CONFIG fileConfig = {0};
PRZFILTER_IOCTRL_CONTEXT pContext = NULL;
WDFQUEUE queue = NULL;

PAGED_CODE();

RzTraceFuncEntry();

//
// The output parameter shouldn’t be NULL.
//
IfFalseGoToExit(
phDevice != NULL,
STATUS_INVALID_PARAMETER_4,
RZ_IOCTL,
L"NULL output parameter"
);

//
// In order to create a control device, we first need to allocate a
// WDFDEVICE_INIT structure and set all properties.
//
pInit = WdfControlDeviceInitAllocate(
hDriver,
&SDDL_DEVOBJ_SYS_ALL_ADM_RWX_WORLD_RW_RES_R
);
IfFalseGoToExit(
pInit != NULL,
STATUS_INSUFFICIENT_RESOURCES,
RZ_IOCTL,
“WdfControlDeviceInitAllocate failed”
);

//
// Set exclusive to false so that more than one app can talk to the
// control device simultaneously.
//
WdfDeviceInitSetExclusive(pInit, FALSE);

status = WdfDeviceInitAssignName(pInit, pszNTName);
IfFailGoToExit(status, RZ_IOCTL, “WdfDeviceInitAssignName failed”);

//
// We need to count the event CreateFile/CloseHandle to determine.
// whether the client application is still running. Non zero counter
// indicates the client exits.
//
WDF_FILEOBJECT_CONFIG_INIT(
&fileConfig,
RzFilter_EvtDeviceFileCreate,
RzFilter_EvtFileClose,
WDF_NO_EVENT_CALLBACK // not interested in Cleanup
);

WdfDeviceInitSetFileObjectConfig(
pInit,
&fileConfig,
WDF_NO_OBJECT_ATTRIBUTES
);

//
// Now specify the size of device extension where we track per device
// context. DeviceInit is completely initialized. So call the framework
// to create the device and attach it to the lower stack.
//
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, RZFILTER_IOCTRL_CONTEXT);

status = WdfDeviceCreate(&pInit, &deviceAttributes, &controlDevice);
IfFailGoToExit(status, RZ_IOCTL, “WdfDeviceCreate failed”);

pContext = RzFilterGetIoCtrlContext(controlDevice);
pContext->fltOvlInput = RZ_OVLINPUT_WIN32;
pContext->fltOvlState = RZ_OVLSTATE_INACTIVE;
pContext->fltVkInput = RZ_VKINPUT_WIN32;
pContext->nCounter = 0;

//
// Create the locks to synchronize the data forwarding
// and the key state forwarding
//
WDF_OBJECT_ATTRIBUTES_INIT(&lockAttributes);
lockAttributes.ParentObject = controlDevice;

status = WdfSpinLockCreate(&lockAttributes, &pContext->hInputSpinLock);
IfFailGoToExit(status, RZ_IOCTL, “WdfSpinLockCreate failed for Input Spinlock”);

//
// Create a symbolic link for the control object so that usermode can open
// the device.
//
status = WdfDeviceCreateSymbolicLink(controlDevice, pszDosName);
IfFailGoToExit(status, RZ_IOCTL, “WdfDeviceCreateSymbolicLink failed”);

//
// Configure the default queue associated with the control device object
// to be parallel so that request passed to EvtIoDeviceControl and EvtIoRead
// are not blocked.
//
WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig, WdfIoQueueDispatchParallel);
ioQueueConfig.EvtIoDeviceControl = RzFilter_EvtIoDeviceControl;
ioQueueConfig.EvtIoRead = RzFilter_EvtIoRead;

status = WdfIoQueueCreate(
controlDevice,
&ioQueueConfig,
WDF_NO_OBJECT_ATTRIBUTES,
&queue
);
IfFailGoToExit(status, RZ_IOCTL, “WdfIoQueueCreate failed”);

//
// Register a manual I/O queue for handling event read requests.
// This queue will be used for storing Requests that need to wait for an
// interrupt to occur before they can be completed.
//
// This queue is used for requests that dont directly access the device. The
// requests in this queue are serviced only when the device is in a fully
// powered state and sends an interrupt. So we can use a non-power managed
// queue to park the requests since we dont care whether the device is idle
// or fully powered up.
//
WDF_IO_QUEUE_CONFIG_INIT(&ioQueueConfig, WdfIoQueueDispatchManual);
ioQueueConfig.PowerManaged = WdfFalse;

status = WdfIoQueueCreate(
controlDevice,
&ioQueueConfig,
WDF_NO_OBJECT_ATTRIBUTES,
&pContext->hReadQueue
);
IfFailGoToExit(status, RZ_IOCTL, “WdfIoQueueCreate failed”);

//
// If the read request is not as fast as the ISR does, the ISR will
// have to push the input data to the queue so that when the next
// request comes, it can consume that data to complete.
//
status = WdfCollectionCreate(
WDF_NO_OBJECT_ATTRIBUTES,
&pContext->hDataQueue
);
IfFailGoToExit(status, RZ_IOCTL, “WdfCollectionCreate failed for the data queue”);

status = WdfSpinLockCreate(
WDF_NO_OBJECT_ATTRIBUTES,
&pContext->hDataQueueLock
);
IfFailGoToExit(status, RZ_IOCTL, “WdfWaitLockCreate failed for the data queue lock”);

//
// The Overlay hotkeys can conflict with those defined in games. To avoid that,
// we will have to eat the primary keys if users press the Overlay hotkeys. For
// this point, the Overlay needs pass the hotkey list from the user mode to the
// kernel mode so that the kernel driver can match the key pressing.
//
status = WdfCollectionCreate(
WDF_NO_OBJECT_ATTRIBUTES,
&pContext->hHotkeyList
);
IfFailGoToExit(status, RZ_IOCTL, “WdfCollectionCreate failed for the hotkey list”);

//
// Control devices must notify WDF when they are done initializing.
// I/O is rejected until this call is made.
//
WdfControlFinishInitializing(controlDevice);

*phDevice = controlDevice;

Exit:
if (!NT_SUCCESS(status))
{
if (pInit != NULL)
{
WdfDeviceInitFree(pInit);
}

if (controlDevice != NULL)
{
//
// Release the reference on the newly created object, since
// we couldn’t initialize it.
//
WdfObjectDelete(controlDevice);
controlDevice = NULL;
}

//
// Reset the OUT parameter in case it was assigned
//
if (phDevice != NULL)
{
*phDevice = NULL;
}
}

RzTraceFuncExit();
return status;
}

Hi Doron,

I’m able to repro this as below steps:

  • Run our application to open the control device.
  • Unplug all keyboards and mouse.
  • In this moment, the control device doesn’t get deleted yet because the application is still referencing the control device object.
  • Plug the keyboards and mouse again.
  • In this moment, calling WdfDeviceCreateSymbolicLink failed with status = 0xc0000035(STATUS_OBJECT_NAME_COLLISION) which causes the code to goto Exit and release the control device object.
  • Quit the application.
  • Run WinObj now and see no the control device.

How can I fix this? Should I monitor the IRP_MJ_CREATE and IRP_MJ_CLOSE?

Thanks,
Marshall

The app needs to register for handle notifications on the cdo and you need to preprocess pnp/query device relations on the cdo and answer with one of the pnp pdos as the target… Or, use raw pdos instead of cdos and you don’t have the symlink (use device interfaces) problem and notifications work without processing

d

Bent from my Phone


From: xxxxx@hotmail.commailto:xxxxx
Sent: ?7/?1/?2013 3:07 AM
To: Windows System Software Devs Interest Listmailto:xxxxx
Subject: RE:[ntdev] The CDO disappear

Hi Doron,

I’m able to repro this as below steps:

- Run our application to open the control device.
- Unplug all keyboards and mouse.
- In this moment, the control device doesn’t get deleted yet because the application is still referencing the control device object.
- Plug the keyboards and mouse again.
- In this moment, calling WdfDeviceCreateSymbolicLink failed with status = 0xc0000035(STATUS_OBJECT_NAME_COLLISION) which causes the code to goto Exit and release the control device object.
- Quit the application.
- Run WinObj now and see no the control device.

How can I fix this? Should I monitor the IRP_MJ_CREATE and IRP_MJ_CLOSE?

Thanks,
Marshall


NTDEV is sponsored by OSR

Visit the list at: http://www.osronline.com/showlists.cfm?list=ntdev

OSR is HIRING!! See http://www.osr.com/careers

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</mailto:xxxxx></mailto:xxxxx>