Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

'QueryDosDevice' for the kernel mode

454 views
Skip to first unread message

Martin

unread,
May 11, 2009, 1:52:18 AM5/11/09
to
Hi guys/gals,

I've written a function for using in kernel mode which does just the
same, as QueryDosDevice for the user mode. It utilizes
ZwOpenSymbolicLinkObject/ZwQuerySymbolicLinkObject pair; here it is:

<code>

NTSTATUS my_QueryDosDevice(IN OPTIONAL PCWSTR deviceName, OUT PWSTR
targetPath, IN OUT SIZE_T& pathSize)
{
NTSTATUS status = STATUS_SUCCESS;
OBJECT_ATTRIBUTES objAttrs;
UNICODE_STRING uniDeviceName;
UNICODE_STRING uniTargetPath;
HANDLE linkHandle = NULL;

ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);

RtlInitUnicodeString(&uniDeviceName, deviceName);
InitializeObjectAttributes(&objAttrs, &uniDeviceName,
OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);

status = ZwOpenSymbolicLinkObject(&linkHandle, GENERIC_READ,
&objAttrs);

if (NT_SUCCESS(status))
{
ULONG returnedLength = 0;

RtlInitUnicodeString(&uniTargetPath, NULL);
uniTargetPath.Buffer = targetPath;
uniTargetPath.MaximumLength = static_cast<USHORT>(pathSize);
pathSize = 0;

status = ZwQuerySymbolicLinkObject(linkHandle, &uniTargetPath,
&returnedLength);
if (NT_SUCCESS(status))
{
pathSize = returnedLength;
}

ZwClose(linkHandle);
}

return status;
}

</code>

When I call it passing L"\\DosDevices\\C:" as its first parameter, the
call to ZwOpenSymbolicLinkObject always returns 0xC000003B
(STATUS_OBJECT_PATH_SYNTAX_BAD). Trying to play with path format the
return value just changes to 0xC000003A
(STATUS_OBJECT_PATH_NOT_FOUND). What am I doing wrong? Isn't the
symbolic link I'm passing for drive C: correct?

Thanks,
Martin

Doron Holan [MSFT]

unread,
May 11, 2009, 1:18:40 PM5/11/09
to
why do you need this ? you can use the symbolic name as is

--

This posting is provided "AS IS" with no warranties, and confers no rights.


"Martin" <martin.g...@gmail.com> wrote in message
news:c55a18b5-00c9-46b9...@h23g2000vbc.googlegroups.com...

Jakob Bohm

unread,
May 11, 2009, 2:27:01 PM5/11/09
to
Doron Holan [MSFT] wrote:
> why do you need this ? you can use the symbolic name as is
>

While I don't known Martin's reasons, such code in kernel mode serves
the same purpose as the QueryDosDevice API in user mode: To allow code
to use information about the RELATIONSHIP to the underlying physical
device or to take special actions based on the type of device, and the
relationship between multiple devices (e.g. to use a different code path
if two Win32 file names point to locations on the same physical disk
than if they point to locations on different "spindles", or to take
special action if a Win32 file name refers to a file on the drivers own
disk device).

Assuming that driver writers only need to perform a non-orthogonal
subset of operations on the objects at hand is a common WDK design error
causing ongoing problems for driver writers. Another example:
before the IFS kit was merged into the WDK, there was no documented way
for writers of ordinary drivers to apply secure ACLs to their device
objects, forcing MSFT to introduce an unwieldy .INF based method in
the 5.x DDK.

--
Jakob Bøhm, M.Sc.Eng. * j...@danware.dk * direct tel:+45-45-90-25-33
Netop Solutions A/S * Bregnerodvej 127 * DK-3460 Birkerod * DENMARK
http://www.netop.com * tel:+45-45-90-25-25 * fax:+45-45-90-25-26
Information in this mail is hasty, not binding and may not be right.
Information in this posting may not be the official position of Netop
Solutions A/S, only the personal opinions of the author.

Martin

unread,
May 12, 2009, 2:09:08 AM5/12/09
to
On May 11, 10:18 pm, "Doron Holan [MSFT]"

<doron.ho...@online.microsoft.com> wrote:
> why do you need this ? you can use the symbolic name as is

We have a filter driver which keeps track of all volume objects and
has a member for volume object NT device name in the device extension.
During adding volume devices it checks if the volume currently being
added is the one which corresponds to symbolic link "\DosDevices\C:"
by making plain string comparison of NT device names. Till now the NT
device name for "\DosDevices\C:" volume was obtained in the driver
entry routine, but in a weird way from the registry; now I want to
change it.

Maxim S. Shatskih

unread,
May 12, 2009, 4:39:00 AM5/12/09
to
>added is the one which corresponds to symbolic link "\DosDevices\C:"
>by making plain string comparison of NT device names.

Very weird. I would use mountdev IDs instead for this comparison and ask them by IOCTL_MOUNTDEV_QUERY_UNIQUE_ID

--
Maxim S. Shatskih
Windows DDK MVP
ma...@storagecraft.com
http://www.storagecraft.com

Martin

unread,
May 12, 2009, 6:06:24 AM5/12/09
to
On May 12, 1:39 pm, "Maxim S. Shatskih"

<ma...@storagecraft.com.no.spam> wrote:
> Very weird. I would use mountdev IDs instead for this comparison and ask them by IOCTL_MOUNTDEV_QUERY_UNIQUE_ID

Yep, that's right; anyway I've no choice of changing the logic -- can
just change the way how the NT device name for dirve C: is obtained,
as current method (if it can be called in such way) doesn't work
always.

Maxim S. Shatskih

unread,
May 12, 2009, 6:31:06 AM5/12/09
to
>just change the way how the NT device name for dirve C: is obtained,
>as current method (if it can be called in such way) doesn't work
>always.

Note: Win7 seems to have changes on this.

Also note the useful API of IoGetBootDiskInformation

Jakob Bohm

unread,
May 12, 2009, 6:37:40 AM5/12/09
to

Please beware that C: is not always the drive/partition with C:\Windows
on it, for that you should look at the native symlink \SystemRoot and
strip away the directory part.

Please beware that C: is not always the drive/partition with the used
C:\NTLDR etc. on it, to identify the correct drive for that you need to
look at some registry keys, then do the symlink mapping.

Maxim S. Shatskih

unread,
May 12, 2009, 7:15:50 AM5/12/09
to
>Please beware that C: is not always the drive/partition with C:\Windows
>on it, for that you should look at the native symlink \SystemRoot and
>strip away the directory part.

Or better:

- IoGetBootDiskInformation early on startup
- compare the disk info for each new filtered disk (storage device number and offset) with IoGetBootDiskInformation result

Martin

unread,
May 12, 2009, 8:03:40 AM5/12/09
to
On May 12, 4:15 pm, "Maxim S. Shatskih"

<ma...@storagecraft.com.no.spam> wrote:
> >Please beware that C: is not always the drive/partition with C:\Windows
> >on it, for that you should look at the native symlink \SystemRoot and
> >strip away the directory part.
>
> Or better:
>
> - IoGetBootDiskInformation early on startup
> - compare the disk info for each new filtered disk (storage device number and offset) with IoGetBootDiskInformation result

Jakob, Maxim,

Thanks for replies; yes, I know all that regarding drive C: -- it may
be neither boot nor system device. Anyway, due to the product
specificities I do need to get NT device name for exactly drive C: .
Meanwhile I tried all possible symbolic link formats, yet with no
success, same errors.

Jakob Bohm

unread,
May 12, 2009, 8:10:18 AM5/12/09
to
Maxim S. Shatskih wrote:
>> Please beware that C: is not always the drive/partition with C:\Windows
>> on it, for that you should look at the native symlink \SystemRoot and
>> strip away the directory part.
>
> Or better:
>
> - IoGetBootDiskInformation early on startup
> - compare the disk info for each new filtered disk (storage device number and offset) with IoGetBootDiskInformation result
>
OK, nice call for NT 5.01 and later. For NT 5.00 (Windows 2000) with
dynamic disks there seems to be a small problem (The _EX structure is
not supported). For NT 3.x and 4.x, the call seems to be unavailable.

Also when using this call beware that MSFT uses the terms "System disk"
and "Boot disk" in a rather counterintuitive way, so be sure to check
the right one.

Don Burn

unread,
May 12, 2009, 8:30:07 AM5/12/09
to
Your complaints are a little weird here. First there were a lot of flaws
in NT 4.0 and earlier of things you could not do easily, that is why it is
rare that people use it any more. As far as Windows 2000 not returning the
_EX data, what would you do with it? The _EX version of the structure are
extensions for GPT disks which are not supported in Windows 2000 so you
certainly cannot boot from one.

You have complained in this thread about the fact that you cannot do
everything in the kernel that you can do in user space. OS design is a
tradeoff, the designer want as little as possible in the kernel for
reliability, ease of implementation, and size issues, this has been the
case for well over 30 years in well designed OS'es.


--
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


"Jakob Bohm" <j...@danware.dk> wrote in message
news:%2381zeqv...@TK2MSFTNGP03.phx.gbl...


Maxim S. Shatskih wrote:
>> Please beware that C: is not always the drive/partition with C:\Windows
>> on it, for that you should look at the native symlink \SystemRoot and
>> strip away the directory part.
>
> Or better:
>
> - IoGetBootDiskInformation early on startup
> - compare the disk info for each new filtered disk (storage device number
> and offset) with IoGetBootDiskInformation result
>
OK, nice call for NT 5.01 and later. For NT 5.00 (Windows 2000) with
dynamic disks there seems to be a small problem (The _EX structure is
not supported). For NT 3.x and 4.x, the call seems to be unavailable.

Also when using this call beware that MSFT uses the terms "System disk"
and "Boot disk" in a rather counterintuitive way, so be sure to check
the right one.


--
Jakob B�hm, M.Sc.Eng. * j...@danware.dk * direct tel:+45-45-90-25-33


Netop Solutions A/S * Bregnerodvej 127 * DK-3460 Birkerod * DENMARK
http://www.netop.com * tel:+45-45-90-25-25 * fax:+45-45-90-25-26
Information in this mail is hasty, not binding and may not be right.
Information in this posting may not be the official position of Netop
Solutions A/S, only the personal opinions of the author.


__________ Information from ESET NOD32 Antivirus, version of virus signature
database 4067 (20090512) __________

The message was checked by ESET NOD32 Antivirus.

http://www.eset.com

__________ Information from ESET NOD32 Antivirus, version of virus signature database 4067 (20090512) __________

The message was checked by ESET NOD32 Antivirus.

http://www.eset.com


Martin

unread,
May 12, 2009, 8:41:44 AM5/12/09
to
You guys are all amazing, with deep understanding and so on. Just a
small note -- I don't know how to get the device name for drive C:
yet :)) Not the boot drive, not the system drive, but exactly drive
C: :-)

Maxim S. Shatskih

unread,
May 12, 2009, 8:43:56 AM5/12/09
to
>OK, nice call for NT 5.01 and later. For NT 5.00 (Windows 2000) with
>dynamic disks there seems to be a small problem (The _EX structure is
>not supported).

Among all DynDisks, only the mirror is bootable, and, for mirror, non-_EX structure is OK.

>For NT 3.x and 4.x, the call seems to be unavailable.

They are dead. Most software dropped NT4 support in around 2004-2006.

>Also when using this call beware that MSFT uses the terms "System disk"
>and "Boot disk" in a rather counterintuitive way

Correct. Disk Management UI contradicts the MSDN docs in this.

Maxim S. Shatskih

unread,
May 12, 2009, 8:45:12 AM5/12/09
to
>specificities I do need to get NT device name for exactly drive C: .

In kernel mode, you can use \SystemRoot\system32.. pathname style to reference the files on SystemRoot volume without knowing the drive letter.

Jakob Bohm

unread,
May 12, 2009, 9:22:29 AM5/12/09
to

OK, to get the C: drive exactly on Windows 2000 and later (and
especially on XP and later) you need to deal with the per session
splitting of the logical kernel name space, especially the "\??"
dir (aka "\DosDevices"). Some drives are defined in a real "\GLobal??"
dir shared by all sessions and some in per session
"\Sessions\NN\DosDevices" dirs for each "terminal" session number NN
(decimal).

The name strings given here are for XP (NT 5.01) and may vary amongst NT
versions. Use the DDK ObjDir utility to browse around other NT versions
yourself.

Don Burn

unread,
May 12, 2009, 9:39:54 AM5/12/09
to
But the real question is why he would want C: if it exists. Max's solution
works to find the boot disk, and the concept of C: in the kernel is
questionable, it is dependant on the context you are in which adds a
complexity that should be avoided if at all possible.

Sorry, telling him how to get C: is the programming equivalent of the guy
who asks "I was playing russian roulette, and the gun jammed, how do I unjam
it?" All you are doing is helping him cause damage.


--
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

"Jakob Bohm" <j...@danware.dk> wrote in message

news:uSKf0Sw0...@TK2MSFTNGP02.phx.gbl...

--
Jakob B�hm, M.Sc.Eng. * j...@danware.dk * direct tel:+45-45-90-25-33


Netop Solutions A/S * Bregnerodvej 127 * DK-3460 Birkerod * DENMARK
http://www.netop.com * tel:+45-45-90-25-25 * fax:+45-45-90-25-26
Information in this mail is hasty, not binding and may not be right.
Information in this posting may not be the official position of Netop
Solutions A/S, only the personal opinions of the author.

Jakob Bohm

unread,
May 12, 2009, 9:53:11 AM5/12/09
to
Don Burn wrote:
> Your complaints are a little weird here. First there were a lot of flaws
> in NT 4.0 and earlier of things you could not do easily, that is why it is
> rare that people use it any more. As far as Windows 2000 not returning the
> _EX data, what would you do with it? The _EX version of the structure are
> extensions for GPT disks which are not supported in Windows 2000 so you
> certainly cannot boot from one.
>

Operating systems don't die, they are just forgotten...

Windows 2000 DID support GPT disks, but as Maxim pointed out there were
limitations restricting their use as boot and system drives.

> You have complained in this thread about the fact that you cannot do
> everything in the kernel that you can do in user space. OS design is a
> tradeoff, the designer want as little as possible in the kernel for
> reliability, ease of implementation, and size issues, this has been the
> case for well over 30 years in well designed OS'es.
>
>

Yes, minimizing the subset of user space replicated in kernel mode is
good. I don't expect to find OLE, Clipboard, GUI, ChkDsk, Web Server
etc. in kernel mode. I don't expect kernel mode to include all the
convenience wrappers around system calls from
KERNEL32.DLL/ADVAPI32.DLL/MSVCRT*.DLL either.

What annoys me is the lack of orthogonality in the documented/exported
set of ntoskrnl entrypoints compared to what is available inside
ntoskrnl itself: Some Zw functions are not exported, some are. Some Nt
functions are not exported, some are. Some pretty basic Ps functions
are undocumented, some are documented. The exported spinlock functions
only support DISPATCH_LEVEL, for interrupt level spinlocks the
programmer must use the inflexible IoSynchronizeExecution wrapper. When
PatchGuard was introduced, the banned old (undocumented but well known)
techniques were replaced by APIs that only covered a small subset of the
calls that used to be interceptable. When XP SP2 introduced
non-executable data in i386 user mode, it was omitted in i386 kernel
mode rather than documenting an Mm function to control the execute
permission for kernel mode pages. etc. etc.


--
Jakob Bøhm, M.Sc.Eng. * j...@danware.dk * direct tel:+45-45-90-25-33

Maxim S. Shatskih

unread,
May 12, 2009, 1:53:58 PM5/12/09
to
>Windows 2000 DID support GPT disks

Dynamic - yes, GPT - no. GPT support started in some service pack for 2003 I think.

Maxim S. Shatskih

unread,
May 12, 2009, 1:56:38 PM5/12/09
to
> yet :)) Not the boot drive, not the system drive, but exactly drive
> C: :-)

What is the need in this? Why not use QueryDosDevice in user mode to get this name, and _only use the device names_ (never drive letters) in kernel code?

Martin

unread,
May 12, 2009, 3:18:31 PM5/12/09
to
On May 12, 10:56 pm, "Maxim S. Shatskih"

Max, it's inherited with a legacy code. User mode parts of the product
are strictly "attached" to drive C: (exactly C:, not boot drive and
not system drive). They create some files on it, and construct own
"file system" over locations of these files to be able to read them at
pre-boot. The driver part of the product needs to do some operations
using exactly that volume object, which contains those files -- which
is volume C: So, here are preconditions for such weird need:

1) Attachment to C: is coming from a legacy code, and we can't do
anything with this for now;
2) The driver needs to perform some operations concerning volume C:
very early (they're senseless in user mode).

So, as the driver works in terms of NT device names, I need to get NT
device name for exactly drive C: Yet I seems don't manage to do that.
RtlInitUnicodeString (before ZwOpenSymbolicLinkObject in the code) was
called using maybe all possible formats for symbolic link, including:

L"\\DosDevices\\C:"
L"\\DosDevices\\C:\\"
L"C:"
L"C:\\"
L"\\??\\C:"
L"\\??\\C:\\"
L"\\Global\\DosDevices\\C:"
L"\\Global\\DosDevices\\C:\\"

None of these works -- every time ZwOpenSymbolicLinkObject returns
STATUS_OBJECT_PATH_SYNTAX_BAD or STATUS_OBJECT_PATH_NOT_FOUND.

Pavel A.

unread,
May 12, 2009, 6:26:12 PM5/12/09
to

Then, _require_ that Windows is installed so that C: is the system or
boot disk, or both. And use what you detect as system/boot disk.

-- pa

Maxim S. Shatskih

unread,
May 13, 2009, 4:21:16 PM5/13/09
to
>2) The driver needs to perform some operations concerning volume C:
>very early (they're senseless in user mode).

Note that, if C: is not SystemRoot, then it will be mounted rather late, after the startup of the whole PnP tree.

I would do my best to update the code (including the legacy one) to use \SystemRoot instead of C:

0 new messages