IoCreateDevice fails with error "c0000035"

Hi,

I am working on an upper volume filter driver.
I am getting error as “c0000035” which means “STATUS_OBJECT_NAME_COLLISION” when trying to create device with name.
How can I create device with name for all the partitions?

Note: There are 2 disk, each with 3 partitions.

I want to access the driver from my user app that is why want to create the device with name. When specifying NULL in third parameter of “IoCreateDevice” the driver is properly loaded with all the partitions.
Below is my code,

************************************************************

NTSTATUS
sampledriverAddDevice(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject
)

{
NTSTATUS status;
IO_STATUS_BLOCK ioStatus;
PDEVICE_OBJECT filterDeviceObject;
PDEVICE_EXTENSION deviceExtension;
CCHAR ntNameBuffer[sampledriver_MAXSTR];
STRING ntNameString;
UNICODE_STRING ntUnicodeString;
PIRP irp;
STORAGE_DEVICE_NUMBER number;
ULONG registrationFlag = 0;
PWMILIB_CONTEXT wmilibContext;
PCHAR buffer;
ULONG buffersize;
UNICODE_STRING linkString;

PAGED_CODE();

//
// Create a filter device object for this device (partition).
//

DebugPrint((0, “sampledriverAddDevice: Driver %X Device %X\n”,
DriverObject, PhysicalDeviceObject));

RtlInitUnicodeString( &ntUnicodeString, NT_DEVICE_NAME );

status = IoCreateDevice(DriverObject,
DEVICE_EXTENSION_SIZE,
&ntUnicodeString,
FILE_DEVICE_DISK,
0,
FALSE,
&filterDeviceObject);

if (!NT_SUCCESS(status)) {
DbgPrint(“sampledriverAddDevice: Cannot create filterDeviceObject: %x\n”, status); \Here I am getting error as “c0000035”
return status;
}
else
{
DbgPrint(“sampledriverAddDevice: Created filterDeviceObject\n: %x\n”, status);
}

RtlInitUnicodeString( &linkString, NT_DOSDEVICE_NAME );
status = IoCreateSymbolicLink( &linkString, &ntUnicodeString );

if (!NT_SUCCESS(status)) {

//
// Remove the existing symbol link and try and create it again.
// If this fails then quit.
//
DbgPrint(“sample!DriverEntry: IoCreateSymbolicLink failed: %x\n”, status);

IoDeleteSymbolicLink( &linkString );
status = IoCreateSymbolicLink( &linkString, &ntUnicodeString );

if (!NT_SUCCESS(status)) {

DbgPrint(“sample!DriverEntry: IoCreateSymbolicLink failed: %x\n”, status);

IoDeleteDevice(filterDeviceObject);
return status;
}
}

filterDeviceObject->Flags |= DO_DIRECT_IO;

deviceExtension = (PDEVICE_EXTENSION) filterDeviceObject->DeviceExtension;
deviceExtension->IOFirstTime = TRUE;

//
// Attaches the device object to the highest device object in the chain and
// return the previously highest device object, which is passed to
// IoCallDriver when pass IRPs down the device stack
//

deviceExtension->PhysicalDeviceObject = PhysicalDeviceObject;

deviceExtension->TargetDeviceObject =
IoAttachDeviceToDeviceStack(filterDeviceObject, PhysicalDeviceObject);

if (deviceExtension->TargetDeviceObject == NULL) {
IoDeleteDevice(filterDeviceObject);
DebugPrint((1, “sampledriverAddDevice: Unable to attach %X to target %X\n”,
filterDeviceObject, PhysicalDeviceObject));
DbgPrint( “sampledriverAddDevice: Unable to attach %X to target %X\n”,
filterDeviceObject, PhysicalDeviceObject);
return STATUS_NO_SUCH_DEVICE;
}

//
// Save the filter device object in the device extension
//
deviceExtension->DeviceObject = filterDeviceObject;

deviceExtension->PhysicalDeviceName.Buffer
= deviceExtension->PhysicalDeviceNameBuffer;

KeInitializeEvent(&deviceExtension->PagingPathCountEvent,
NotificationEvent, TRUE);

//
// default to DO_POWER_PAGABLE
//

filterDeviceObject->Flags |= DO_POWER_PAGABLE;

//
// Clear the DO_DEVICE_INITIALIZING flag
//

filterDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;

return STATUS_SUCCESS;

} // end sampledriverAddDevice()

******************************************************

This is what I got in windbg,

**********************************************************

sampledriverAddDevice: Driver 80786724 Device 80786724
sampledriverAddDevice: Created filterDeviceObject : 0

sampledriverAddDevice: Driver 80786724 Device 80786724
sampledriverAddDevice: Cannot create filterDeviceObject: c0000035
sampledriverAddDevice: Driver 80786724 Device 80786724
sampledriverAddDevice: Cannot create filterDeviceObject: c0000035
sampledriverAddDevice: Driver 80786724 Device 80786724
sampledriverAddDevice: Cannot create filterDeviceObject: c0000035
sampledriverRegisterDevice: Device name \Device\Harddisk0\Partition1

*** WARNING: Unable to verify timestamp for ntdll.dll
*** ERROR: Module load completed but symbols could not be loaded for ntdll.dll

************************************************************

The error is pretty clear, you can’t create multiple device objects with the
same name.

See the kbfiltr sample in the WDK for an example of creating sideband device
objects for use in communicating with your individual filter instances.

-scott
OSR

wrote in message news:xxxxx@ntdev…

Hi,

I am working on an upper volume filter driver.
I am getting error as “c0000035” which means “STATUS_OBJECT_NAME_COLLISION”
when trying to create device with name.
How can I create device with name for all the partitions?

Note: There are 2 disk, each with 3 partitions.

I want to access the driver from my user app that is why want to create the
device with name. When specifying NULL in third parameter of
“IoCreateDevice” the driver is properly loaded with all the partitions.
Below is my code,

************************************************************

NTSTATUS
sampledriverAddDevice(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject
)

{
NTSTATUS status;
IO_STATUS_BLOCK ioStatus;
PDEVICE_OBJECT filterDeviceObject;
PDEVICE_EXTENSION deviceExtension;
CCHAR ntNameBuffer[sampledriver_MAXSTR];
STRING ntNameString;
UNICODE_STRING ntUnicodeString;
PIRP irp;
STORAGE_DEVICE_NUMBER number;
ULONG registrationFlag = 0;
PWMILIB_CONTEXT wmilibContext;
PCHAR buffer;
ULONG buffersize;
UNICODE_STRING linkString;

PAGED_CODE();

//
// Create a filter device object for this device (partition).
//

DebugPrint((0, “sampledriverAddDevice: Driver %X Device %X\n”,
DriverObject, PhysicalDeviceObject));

RtlInitUnicodeString( &ntUnicodeString, NT_DEVICE_NAME );

status = IoCreateDevice(DriverObject,
DEVICE_EXTENSION_SIZE,
&ntUnicodeString,
FILE_DEVICE_DISK,
0,
FALSE,
&filterDeviceObject);

if (!NT_SUCCESS(status)) {
DbgPrint(“sampledriverAddDevice: Cannot create filterDeviceObject: %x\n”,
status); \Here I am getting error as “c0000035”
return status;
}
else
{
DbgPrint(“sampledriverAddDevice: Created filterDeviceObject\n: %x\n”,
status);
}

RtlInitUnicodeString( &linkString, NT_DOSDEVICE_NAME );
status = IoCreateSymbolicLink( &linkString, &ntUnicodeString );

if (!NT_SUCCESS(status)) {

//
// Remove the existing symbol link and try and create it again.
// If this fails then quit.
//
DbgPrint(“sample!DriverEntry: IoCreateSymbolicLink failed: %x\n”, status);

IoDeleteSymbolicLink( &linkString );
status = IoCreateSymbolicLink( &linkString, &ntUnicodeString );

if (!NT_SUCCESS(status)) {

DbgPrint(“sample!DriverEntry: IoCreateSymbolicLink failed: %x\n”, status);

IoDeleteDevice(filterDeviceObject);
return status;
}
}

filterDeviceObject->Flags |= DO_DIRECT_IO;

deviceExtension = (PDEVICE_EXTENSION)
filterDeviceObject->DeviceExtension;
deviceExtension->IOFirstTime = TRUE;

//
// Attaches the device object to the highest device object in the chain
and
// return the previously highest device object, which is passed to
// IoCallDriver when pass IRPs down the device stack
//

deviceExtension->PhysicalDeviceObject = PhysicalDeviceObject;

deviceExtension->TargetDeviceObject =
IoAttachDeviceToDeviceStack(filterDeviceObject,
PhysicalDeviceObject);

if (deviceExtension->TargetDeviceObject == NULL) {
IoDeleteDevice(filterDeviceObject);
DebugPrint((1, “sampledriverAddDevice: Unable to attach %X to target
%X\n”,
filterDeviceObject, PhysicalDeviceObject));
DbgPrint( “sampledriverAddDevice: Unable to attach %X to target %X\n”,
filterDeviceObject, PhysicalDeviceObject);
return STATUS_NO_SUCH_DEVICE;
}

//
// Save the filter device object in the device extension
//
deviceExtension->DeviceObject = filterDeviceObject;

deviceExtension->PhysicalDeviceName.Buffer
= deviceExtension->PhysicalDeviceNameBuffer;

KeInitializeEvent(&deviceExtension->PagingPathCountEvent,
NotificationEvent, TRUE);

//
// default to DO_POWER_PAGABLE
//

filterDeviceObject->Flags |= DO_POWER_PAGABLE;

//
// Clear the DO_DEVICE_INITIALIZING flag
//

filterDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;

return STATUS_SUCCESS;

} // end sampledriverAddDevice()

******************************************************

This is what I got in windbg,

**********************************************************

sampledriverAddDevice: Driver 80786724 Device 80786724
sampledriverAddDevice: Created filterDeviceObject : 0

sampledriverAddDevice: Driver 80786724 Device 80786724
sampledriverAddDevice: Cannot create filterDeviceObject: c0000035
sampledriverAddDevice: Driver 80786724 Device 80786724
sampledriverAddDevice: Cannot create filterDeviceObject: c0000035
sampledriverAddDevice: Driver 80786724 Device 80786724
sampledriverAddDevice: Cannot create filterDeviceObject: c0000035
sampledriverRegisterDevice: Device name \Device\Harddisk0\Partition1

*** WARNING: Unable to verify timestamp for ntdll.dll
*** ERROR: Module load completed but symbols could not be loaded for
ntdll.dll

************************************************************

Hi,

Thanks for replying.
But “kbfiltr” is a class filter and I am working on an upper volume filter. I am working on the code of “diskperf”. So is the same thing I can do in Upper Volume Filter that the Kbfiltr does?

Andrew, do you see your AddDevice routine called twice? If so, you have trouble using the same name (NT_DEVICE_NAME) for multiple DOs. To avoid the error you have to modify the string somehow (adding interlock incremented number is usually Ok), or to register device interface(IoRegisterDeviceInterface) and enable it (IoSetDeviceInterfaceState). Usermode application should access the DO using the interface then.

It’s a generic technique, so it doesn’t matter that it’s a keyboard filter.

Note that the fact that it’s a KMDF filter makes the raw PDO trick that it
uses viable. If you were to try to do this from a WDM filter like diskperf
it would be far more complicated (as an aside, you should seriously consider
switching to KMDF for your filter).

-scott
OSR

wrote in message news:xxxxx@ntdev…

Hi,

Thanks for replying.
But “kbfiltr” is a class filter and I am working on an upper volume filter.
I am working on the code of “diskperf”. So is the same thing I can do in
Upper Volume Filter that the Kbfiltr does?

Hi @Mikae and @Scott Noone, Thanks for your replies.

I have created the device object by naming it and now the error “c0000035” has gone.
I have used “InterlockedIncrement” to increment the counter for each partition.
Now what I want to know is how can I know which device object name belongs to which partition?
For eg: If I want to communicate the driver from my user application and get the details of “D:” in my user application, how can I know what is the device name of “D:” that the driver has named.

Below is my driver code,

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

NTSTATUS
sampledriverAddDevice(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject
)

{
NTSTATUS status;
IO_STATUS_BLOCK ioStatus;
PDEVICE_OBJECT filterDeviceObject;
PDEVICE_EXTENSION deviceExtension;
CCHAR ntNameBuffer[sampledriver_MAXSTR];
STRING ntNameString;
UNICODE_STRING ntUnicodeString;
PIRP irp;
STORAGE_DEVICE_NUMBER number;
ULONG registrationFlag = 0;
PWMILIB_CONTEXT wmilibContext;
PCHAR buffer;
ULONG buffersize;
UNICODE_STRING linkString;
WCHAR name[32];
WCHAR linkname[32];
LONG devindex;

PAGED_CODE();

//
// Create a filter device object for this device (partition).
//

DebugPrint((0, “sampledriverAddDevice: Driver %X Device %X\n”,
DriverObject, PhysicalDeviceObject));
//lastindex = -1;
devindex = InterlockedIncrement(&lastindex);

_snwprintf(name, arraysize(name), L"\Device\sample%2.2d",devindex);

RtlInitUnicodeString( &ntUnicodeString, name );

status = IoCreateDevice(DriverObject,
DEVICE_EXTENSION_SIZE,
&ntUnicodeString,
FILE_DEVICE_DISK,
0,
FALSE,
&filterDeviceObject);

if (!NT_SUCCESS(status)) {
DbgPrint(“sampledriverAddDevice: Cannot create filterDeviceObject: %x\n”, status);
return status;
}

_snwprintf(linkname, arraysize(linkname), L"\DosDevices\sample%2.2d",devindex);
RtlInitUnicodeString( &linkString, linkname );
status = IoCreateSymbolicLink( &linkString, &ntUnicodeString );

DbgPrint(“sample!DriverEntry: IoCreateSymbolicLink: %x\n”, status);

if (!NT_SUCCESS(status)) {

//
// Remove the existing symbol link and try and create it again.
// If this fails then quit.
//
DbgPrint(“sample!DriverEntry: IoCreateSymbolicLink failed: %x\n”, status);

IoDeleteSymbolicLink( &linkString );
status = IoCreateSymbolicLink( &linkString, &ntUnicodeString );

if (!NT_SUCCESS(status)) {

DbgPrint(“sample!DriverEntry: IoCreateSymbolicLink failed: %x\n”, status);

IoDeleteDevice(filterDeviceObject);
return status;
}
}

filterDeviceObject->Flags |= DO_DIRECT_IO;

deviceExtension = (PDEVICE_EXTENSION) filterDeviceObject->DeviceExtension;
deviceExtension->IOFirstTime = TRUE;

//
// Attaches the device object to the highest device object in the chain and
// return the previously highest device object, which is passed to
// IoCallDriver when pass IRPs down the device stack
//

deviceExtension->PhysicalDeviceObject = PhysicalDeviceObject;

deviceExtension->TargetDeviceObject =
IoAttachDeviceToDeviceStack(filterDeviceObject, PhysicalDeviceObject);

if (deviceExtension->TargetDeviceObject == NULL) {
IoDeleteDevice(filterDeviceObject);
DbgPrint( “sampledriverAddDevice: Unable to attach %X to target %X\n”,
filterDeviceObject, PhysicalDeviceObject);
return STATUS_NO_SUCH_DEVICE;
}

//
// Save the filter device object in the device extension
//
deviceExtension->DeviceObject = filterDeviceObject;

deviceExtension->PhysicalDeviceName.Buffer
= deviceExtension->PhysicalDeviceNameBuffer;

KeInitializeEvent(&deviceExtension->PagingPathCountEvent,
NotificationEvent, TRUE);

//
// default to DO_POWER_PAGABLE
//

filterDeviceObject->Flags |= DO_POWER_PAGABLE;

//
// Clear the DO_DEVICE_INITIALIZING flag
//

filterDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;

return STATUS_SUCCESS;

} // end sampledriverAddDevice()

Also want to ask is “naming the device object” while creating it is better or to “register device interface” is better?

So what I do here is maintain pointers between the device extensions, the filter extension and your control extension. You want to also identify the device extensions so that when your Irp handler gets called you know whether it is for the filter of for your control device. (And you will have as many of these pairings as your AddDevice gets called dont forget).

So when your app talks to your control device you have a pointer to the filter device extension and thus all the proporties of it.

Hi,

Thanks for your reply.
Can you please explain in a more simplified way as I am a newbie?

Andrew, choosing between device interface may depend on user mode application. In the case of interface you don’t care about naming device objects (unless you create PDO AFAIR). The OS does it for you. User mode application in turn registers for interface changes and gets notified whenever a device arrives or departs by opening the device, closing it and so on. So, it is event based approach. Naming device objects manually doesn’t imply any notifications, so the application should find devices by itself, e.g. by trying to open all possible names of device. No notifications in this case. You can combine both approaches dependently on your needs.

About drive letters: you probably want to map volumes to disks? If so, search the forum, there are replies how to do it. If something else, explain your goal then.

Sorry, a typo:

gets notified whenever a device arrives or departs by opening the device, closing it and so on.

*gets notified whenever a device arrives or departs and reacts by opening the device, closing it and so on.

SO at adddevice you create the filter DO and do an attach to device stack. AT the same time you create a DO (control) with a symbolic link that can be opened by user mode to control the driver. Both DOs IRPs go to the same handler, so in the device extension the first field I have is a type field that says whether it is a filter DO or a control DO. The Irp handler then looks at the first field and checks the type, either filter or control and does the right thing with the irp. If it is filter it might just send it doen the stack to the attachec PDO. If it is a control DO Irp then it is something from the user mode that opened your symbolic link and you want to do somthing usefull with it and not send it down.

The second field in the device extension is a pointer to the other extension. So the filter DO has a poointer to the control DO and vice versa. So when you get a control Irp you have access to the filter DO, and its lower PDO in order to send down Irps you create or do other usefull stuff.

I hope thats answered your question a bit.