How check PDEVICE_OBJECT is valid

Hello,

I have to check if a kernel driver DEVICE_OBJECT is valid (valid anymore).

Is there a kernel function for this type of check?

I have only the folloing solutions…

PDEVICE_OBJECT pDevice = “Kernel Driver Device”

if (pDevice == NULL) {return FALSE;}
if (MmIsAddressValid(pDevice) == FALSE) {return FALSE;}

Maybe another funny solution…

ULONG i = 0;
ULONG size = sizeof(PDEVICE_OBJECT) / sizeof(ULONG);
ULONG64 address = (ULONG64)HardDriveDevice;
for (i = 0; i < size; i++)
{
address = address + sizeof(ULONG);
if (MmIsAddressValid((PDEVICE_OBJECT)address) == FALSE)
{
return STATUS_INVALID_HANDLE;
}
}

Is there another better way to check if the DEVICE_OBJECT is valid?

Thanks.

Why do you think that you need to do this?

If you have a PDEVICE_OBJECT pointer that you’re using, then you need to *know* it’s valid. There’s no “if”. Think about it for a moment; it’s a race condition, even if there were a way to instantaneously make such a decision (which there isn’t).

You should explain more about what you’re trying to actually accomplish and why, as it sounds like you’re a bit confused on what you should be doing right now to have started down this path (which, whatever its goal is, it’s the wrong one if you need to ask these sorts of questions).

  • S

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@hotmail.com
Sent: Saturday, November 08, 2008 9:30 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] How check PDEVICE_OBJECT is valid

Hello,

I have to check if a kernel driver DEVICE_OBJECT is valid (valid anymore).

Is there a kernel function for this type of check?

I have only the folloing solutions…

PDEVICE_OBJECT pDevice = “Kernel Driver Device”

if (pDevice == NULL) {return FALSE;}
if (MmIsAddressValid(pDevice) == FALSE) {return FALSE;}

Maybe another funny solution…

ULONG i = 0;
ULONG size = sizeof(PDEVICE_OBJECT) / sizeof(ULONG);
ULONG64 address = (ULONG64)HardDriveDevice;
for (i = 0; i < size; i++)
{
address = address + sizeof(ULONG);
if (MmIsAddressValid((PDEVICE_OBJECT)address) == FALSE)
{
return STATUS_INVALID_HANDLE;
}
}

Is there another better way to check if the DEVICE_OBJECT is valid?

Thanks.


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

If there exist a way to check the PDEVICE_OBJECT pointer I can bypass this function calls

RtlInitString(&string_name, &Devicename);
RtlAnsiStringToUnicodeString(&name, &string_name, TRUE);
IoGetDeviceObjectPointer(&name, FILE_READ_ATTRIBUTES, &pFile, &pDevice);

on every request. If there is no way to check then I have to use IoGetDeviceObjectPointer every time? but all this consumes unnecessary cpu time.

Well, what do you think IoGetDeviceObjectPointer does internally? It needs to grab a lock somewhere and assuming a valid device object exists matching the given name, it’ll reference it and drop the lock and return.

How would you improve upon that?

It would be better to redesign your program so that you don’t need to do this on “every single request”. But you would need to provide more information as to what a “request” is to even begin to determine whether this is even worth doing or not.

You certainly don’t want to “optimize out” safe code and replace it with stuff that will randomly fail. In fact, unless you know you have a performance problem and have analyzed and debugged and profiled it, you probably shouldn’t be optimizing like that (in general), anyway.

  • S

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@hotmail.com
Sent: Saturday, November 08, 2008 10:06 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] How check PDEVICE_OBJECT is valid

If there exist a way to check the PDEVICE_OBJECT pointer I can bypass this function calls

RtlInitString(&string_name, &Devicename);
RtlAnsiStringToUnicodeString(&name, &string_name, TRUE);
IoGetDeviceObjectPointer(&name, FILE_READ_ATTRIBUTES, &pFile, &pDevice);

on every request. If there is no way to check then I have to use IoGetDeviceObjectPointer every time? but all this consumes unnecessary cpu time.


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

Hello,

fortunately I have no performance problems. It was only a consideration to optimize the code.

Why I need to check on every request: because the device objects to check are hard disk devices and hand disk can be removable.

Thank you for the information.

In that case your goal is to be aware of the device’s power state.
If your driver is in the same stack with the device in question then
your driver is inherently aware of the power state.
If you are not in the same stack, it’s a different story.

What is the role of your driver and how it is positioned in the drivers
stack ?

Alexey

xxxxx@hotmail.com wrote:

Hello,

fortunately I have no performance problems. It was only a consideration to optimize the code.

Why I need to check on every request: because the device objects to check are hard disk devices and hand disk can be removable.

Thank you for the information.


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

Hello,

To resolve this problem I have created the function CheckDeviceObject().

The function will find out:

  • if the device object is valid and the device type is valid
  • if the device object is attached to the driver object
  • if the driver object knows the device object

LONG CheckDeviceObject(PDEVICE_OBJECT pDevice, DEVICE_TYPE device_type)
{
__try
{
//
// 1. Check Type of the Device Object
//
if (pDevice == NULL)
{
return -701;
}
else if (pDevice->Type != 3) // value = 3 (used by the operating system to indicate that an object is a device object)
{
return -702;
}
//
// 2. Check Device Type
//
else if (pDevice->DeviceType != device_type) // check if DEVICE_TYPE is the same
{
return -703;
}
//
// 3. Check the Driver Object of our Device Object
//
else if (pDevice->DriverObject->Type != 4) // value = 4 (used by the operating system to indicate that an object is a driver object)
{
return -704;
}
//
// 4. Finally - Now search or DeviceObject in the DriverObject
//
else
{
//
// 4.1 Check the first DeviceObject in the DriverObject
//
if (pDevice->DriverObject->DeviceObject == NULL)
{
return -705;
}
else if (pDevice->DriverObject->DeviceObject->Type != 3) // value = 3 (Used by the operating system to indicate that an object is a device object)
{
return -706;
}
//
// 4.2 Now compare our DeviceObject with the Device Objects in the List
//
else
{
PDEVICE_OBJECT check_device = pDevice->DriverObject->DeviceObject;

while(TRUE)
{
if (check_device == pDevice) // OK -> FOUND Device Object
{
return 0;
}
//
// 4.3 Search in the next Device Object
//
else
{
//
// 4.3.1 Check the next Device Object
//
if (check_device->NextDevice == NULL)
{
return -707;
}
else if (check_device->NextDevice->Type != 3) // value = 3 (Used by the operating system to indicate that an object is a device object)
{
return -708;
}
//
// 4.3.2 Search in the “next” NextDevice
//
else
{
check_device = check_device->NextDevice;
}
}
}
}
}
}
except (EXCEPTION_EXECUTE_HANDLER)
{
return -709;
}
}

Looks like great code to leave a lingering crash through one of several
ways, but since you don’t seem to want to answer why you think this is
nessecary, I am not inclined to pass on the crash paths.


Don Burn (MVP, Windows DDK)
Windows Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr
Remove StopSpam to reply

wrote in message news:xxxxx@ntdev…
> Hello,
>
> To resolve this problem I have created the function CheckDeviceObject().
>
> The function will find out:
> - if the device object is valid and the device type is valid
> - if the device object is attached to the driver object
> - if the driver object knows the device object
>
> LONG CheckDeviceObject(PDEVICE_OBJECT pDevice, DEVICE_TYPE device_type)
> {
> __try
> {
> //
> // 1. Check Type of the Device Object
> //
> if (pDevice == NULL)
> {
> return -701;
> }
> else if (pDevice->Type != 3) // value = 3 (used by the operating system to
> indicate that an object is a device object)
> {
> return -702;
> }
> //
> // 2. Check Device Type
> //
> else if (pDevice->DeviceType != device_type) // check if DEVICE_TYPE is
> the same
> {
> return -703;
> }
> //
> // 3. Check the Driver Object of our Device Object
> //
> else if (pDevice->DriverObject->Type != 4) // value = 4 (used by the
> operating system to indicate that an object is a driver object)
> {
> return -704;
> }
> //
> // 4. Finally - Now search or DeviceObject in the DriverObject
> //
> else
> {
> //
> // 4.1 Check the first DeviceObject in the DriverObject
> //
> if (pDevice->DriverObject->DeviceObject == NULL)
> {
> return -705;
> }
> else if (pDevice->DriverObject->DeviceObject->Type != 3) // value = 3
> (Used by the operating system to indicate that an object is a device
> object)
> {
> return -706;
> }
> //
> // 4.2 Now compare our DeviceObject with the Device Objects in the List
> //
> else
> {
> PDEVICE_OBJECT check_device = pDevice->DriverObject->DeviceObject;
>
> while(TRUE)
> {
> if (check_device == pDevice) // OK -> FOUND Device Object
> {
> return 0;
> }
> //
> // 4.3 Search in the next Device Object
> //
> else
> {
> //
> // 4.3.1 Check the next Device Object
> //
> if (check_device->NextDevice == NULL)
> {
> return -707;
> }
> else if (check_device->NextDevice->Type != 3) // value = 3 (Used by the
> operating system to indicate that an object is a device object)
> {
> return -708;
> }
> //
> // 4.3.2 Search in the “next” NextDevice
> //
> else
> {
> check_device = check_device->NextDevice;
> }
> }
> }
> }
> }
> }
> except (EXCEPTION_EXECUTE_HANDLER)
> {
> return -709;
> }
> }
>
>

Hi,

the driver is a stand alone driver for an application in user space that send IOCTL to the driver. It is not a filter driver.
The driver sends internal IOCTL (IoCallDriver) to other driver and for this it needs the PDEVICE_OBJECT.

For example I will only check the device object before I send the IOCTL code to another driver. In some rare cases it is possible that the object is not anymore available and the driver can not know this. For this rare case I will use this function.

I do not use this function to as a replacement of functions like SetupDiEnumDeviceInfo to enumerate object.

Why you think it is such a bad thing if I check the PDEVICE_OBJECT? It is only a short way to prevent blue screens for the rare case X.

Request sample:

IoIrp = IoBuildDeviceIoControlRequest(
IOCTL_ATA_PASS_THROUGH,
Device,
lpInBuffer,
nInBufferSize,
lpOutBuffer,
nOutBufferSize,
FALSE,
&IoEvent,
&IoStatusBlock);

To be safe the function check if the “Device Pointer” is available and valid…

I must be missing something here. If you got the device object with the
IoGetDeviceObjectPointer call, how can the device object become invalid as
long as you don’t dereference it? If you dereference it (or dereference the
file object) then you have to treat it as invalid as soon as you dereference
it.

Bill Wandel

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com]
On Behalf Of xxxxx@hotmail.com
Sent: Sunday, November 09, 2008 2:42 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] How check PDEVICE_OBJECT is valid

Hello,

To resolve this problem I have created the function CheckDeviceObject().

The function will find out:

  • if the device object is valid and the device type is valid
  • if the device object is attached to the driver object
  • if the driver object knows the device object

LONG CheckDeviceObject(PDEVICE_OBJECT pDevice, DEVICE_TYPE device_type)
{
__try
{
//
// 1. Check Type of the Device Object
//
if (pDevice == NULL)
{
return -701;
}
else if (pDevice->Type != 3)
// value = 3 (used by the operating system to indicate that an object is a
device object)
{
return -702;
}
//
// 2. Check Device Type
//
else if (pDevice->DeviceType != device_type)
// check if DEVICE_TYPE is the same
{
return -703;
}
//
// 3. Check the Driver Object of our Device Object
//
else if (pDevice->DriverObject->Type != 4)
// value = 4 (used by the operating system to indicate that an object is a
driver object)
{
return -704;
}
//
// 4. Finally - Now search or DeviceObject in the
DriverObject
//
else
{
//
// 4.1 Check the first DeviceObject in the
DriverObject
//
if (pDevice->DriverObject->DeviceObject == NULL)
{
return -705;
}
else if (pDevice->DriverObject->DeviceObject->Type
!= 3) // value = 3 (Used by the operating system to indicate that
an object is a device object)
{
return -706;
}
//
// 4.2 Now compare our DeviceObject with the
Device Objects in the List
//
else
{
PDEVICE_OBJECT check_device =
pDevice->DriverObject->DeviceObject;

while(TRUE)
{
if (check_device == pDevice)
// OK -> FOUND Device Object
{
return 0;
}
//
// 4.3 Search in the next
Device Object
//
else
{
//
// 4.3.1 Check the next
Device Object
//
if (check_device->NextDevice
== NULL)
{
return -707;
}
else if
(check_device->NextDevice->Type != 3) // value = 3 (Used by the
operating system to indicate that an object is a device object)
{
return -708;
}
//
// 4.3.2 Search in the
“next” NextDevice
//
else
{
check_device =
check_device->NextDevice;
}
}
}
}
}
}
except (EXCEPTION_EXECUTE_HANDLER)
{
return -709;
}
}


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

Bill is right. If you have used the “IoGetDeviceObjectPointer” call to get the pointer, I don’t think it should be invalid. Basically this call increases the reference count of the device object and the device object cannot be deleted until the reference count is reduced to zero i.e until you call "ObDereferenceObject’ specifically.
If you purpose is only to check if the object is valid or not then you may use the “IoGetDeviceObjectPointer” call. If the object is non existent at the time of the call itself, then the function should return “STATUS_OBJECT_NAME_INVALID”. If successful, you can rest assured that your device object is valid until you dereference it.

Hope this helps
Imtiaz

Hi,

thank you very much for the information and hints :slight_smile:

michi

xxxxx@hotmail.com wrote:

Hello,

To resolve this problem I have created the function CheckDeviceObject().

The function will find out:

  • if the device object is valid and the device type is valid
  • if the device object is attached to the driver object
  • if the driver object knows the device object

And do you REALLY believe this sequence of code is lower cost than
this? Are you sure?

RtlInitString(&string_name, &Devicename);
RtlAnsiStringToUnicodeString(&name, &string_name, TRUE);
IoGetDeviceObjectPointer(&name, FILE_READ_ATTRIBUTES, &pFile, &pDevice);

You are micro-optimizing here. First, make it work. Then, MEASURE to
figure out whether it is fast enough. The sequence you proposed is
still spoofable. Unless you are calling this 500,000 times a second,
the (possible) added cost of the RELIABLE solution is completely negligible.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Hi,

I’m not using this function and nobody should use this function because it can make blue screens in some cases.

My problem was that I closed the FileObject too early. Now I close the FileObject on driver unload or on a request and all works as expected :slight_smile:
I have not to check the device pointer anymore.

Either your driver or your application has to monitor for pnp removal events
on this device and close the handle when the device is being removed or you
are going to hang the system.

On Tue, Nov 11, 2008 at 5:25 AM, wrote:

> Hi,
>
> I’m not using this function and nobody should use this function because it
> can make blue screens in some cases.
>
> My problem was that I closed the FileObject too early. Now I close the
> FileObject on driver unload or on a request and all works as expected :slight_smile:
> I have not to check the device pointer anymore.
>
>
>
>
>
> —
> 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
>


Mark Roddy

Mark is 100% correct. To tie things up

  1. An Ob ref on the device object alone is not enough. It will keep the device object pointer valid, but it will not maintain state for you. A pnp remove can come in while you are holding the ref on the device and sending io after the pnp remove will probably lead to a bluescreen, or just a !NT_SUCESS if you are lucky

  2. An ob ref on the file object will not only keep the device object alive, it will also prevent a graceful pnp remove (e.g. disable or uninstall in device manager) from occurring. If you do not register for notifications on the file object, you will block graceful remove (which is what mark is referring to below)

  3. An ob ref on the file object will not prevent surprise removal of the device though. By holding onto the file object ref, it will prevent the surprise removed device from moving into the removed state

So, the answer here is to keep the ref on the file object for as long as you are going to use the device object pointer, but you must also register for notifications on the file object pointer using IoRegisterPlugPlayNotification, http://msdn.microsoft.com/en-us/library/aa490470.aspx . the toastmon sample shows you how to use this function. When notified of a surprise or graceful remove, you need to stop sending io to the device, wait for all pending io that you have already sent to the device to complete and then deref the file object. A lot of work in a WDM driver, the KMDF WDFIOTARGET takes care of a lot of this, if not all of it, for you.

d

From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Mark Roddy
Sent: Tuesday, November 11, 2008 6:45 AM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] How check PDEVICE_OBJECT is valid

Either your driver or your application has to monitor for pnp removal events on this device and close the handle when the device is being removed or you are going to hang the system.
On Tue, Nov 11, 2008 at 5:25 AM, > wrote:
Hi,

I’m not using this function and nobody should use this function because it can make blue screens in some cases.

My problem was that I closed the FileObject too early. Now I close the FileObject on driver unload or on a request and all works as expected :slight_smile:
I have not to check the device pointer anymore.


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


Mark Roddy
— 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


From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Doron Holan
Sent: Tuesday, November 11, 2008 7:18 PM
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] How check PDEVICE_OBJECT is valid

  1. An Ob ref on the device object alone is not enough. It
    will keep the device object pointer valid, but it will not maintain
    state for you. A pnp remove can come in while you are holding the ref
    on the device and sending io after the pnp remove will probably lead to
    a bluescreen, or just a !NT_SUCESS if you are lucky

If it leads to BSOD, it’d mean a bug in target driver. It has to
gracefully handle device removal and all IO requests coming later.
Otherwise there are unresolvable race conditions even if device removal
notification is used. Am I wrong?

I’d probably use simpler approach. Reference target device for any
request and dereference it immediatelly. At least I’d start this way and
measure if there isn’t performance bottleneck.

(if the message is badly formatted, it is because Outlook is too smart
to allow me format the message as I want…)

Best regards,

Michal Vodicka
UPEK, Inc.
[xxxxx@upek.com, http://www.upek.com http:</http:>]

No race should exist. The notification callback is synchonously called before the remove and a properly written callback will put up the right barriers to synchronously drain existing io as well as preventing new io from being sent before returning from the callback

d

Sent from my phone with no t9, all spilling mistakes are not intentional.


From: Michal Vodicka
Sent: Tuesday, November 11, 2008 11:44 AM
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] How check PDEVICE_OBJECT is valid

________________________________
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Doron Holan
Sent: Tuesday, November 11, 2008 7:18 PM
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] How check PDEVICE_OBJECT is valid

1) An Ob ref on the device object alone is not enough. It will keep the device object pointer valid, but it will not maintain state for you. A pnp remove can come in while you are holding the ref on the device and sending io after the pnp remove will probably lead to a bluescreen, or just a !NT_SUCESS if you are lucky

If it leads to BSOD, it’d mean a bug in target driver. It has to gracefully handle device removal and all IO requests coming later. Otherwise there are unresolvable race conditions even if device removal notification is used. Am I wrong?

I’d probably use simpler approach. Reference target device for any request and dereference it immediatelly. At least I’d start this way and measure if there isn’t performance bottleneck.

(if the message is badly formatted, it is because Outlook is too smart to allow me format the message as I want…)

Best regards,

Michal Vodicka
UPEK, Inc.
[xxxxx@upek.com, http://www.upek.comhttp:</http:>]


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

OK but it’d be more complicated for caller anyway. Am I right BSOD is a
bug in target driver even if caller doesn’t care about removal
notification (failed request is expected)?

Best regards,

Michal Vodicka
UPEK, Inc.
[xxxxx@upek.com, http://www.upek.com http:</http:>]


From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Doron Holan
Sent: Tuesday, November 11, 2008 9:04 PM
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] How check PDEVICE_OBJECT is valid

No race should exist. The notification callback is synchonously
called before the remove and a properly written callback will put up the
right barriers to synchronously drain existing io as well as preventing
new io from being sent before returning from the callback

d

Sent from my phone with no t9, all spilling mistakes are not
intentional.


From: Michal Vodicka
Sent: Tuesday, November 11, 2008 11:44 AM
To: Windows System Software Devs Interest List

Subject: RE: [ntdev] How check PDEVICE_OBJECT is valid

________________________________

From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Doron Holan
Sent: Tuesday, November 11, 2008 7:18 PM
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] How check PDEVICE_OBJECT is valid

1) An Ob ref on the device object alone is not
enough. It will keep the device object pointer valid, but it will not
maintain state for you. A pnp remove can come in while you are holding
the ref on the device and sending io after the pnp remove will probably
lead to a bluescreen, or just a !NT_SUCESS if you are lucky

If it leads to BSOD, it’d mean a bug in target driver. It has to
gracefully handle device removal and all IO requests coming later.
Otherwise there are unresolvable race conditions even if device removal
notification is used. Am I wrong?

I’d probably use simpler approach. Reference target device for
any request and dereference it immediatelly. At least I’d start this way
and measure if there isn’t performance bottleneck.

(if the message is badly formatted, it is because Outlook is too
smart to allow me format the message as I want…)

Best regards,

Michal Vodicka
UPEK, Inc.
[xxxxx@upek.com, http://www.upek.com
http:</http:>]


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


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