ZwOpenSymbolicLinkObject and STATUS_OBJECT_TYPE_MISMATCH

Hello,

I am working on a driver component which will take a DOS path (i.e. C:\Windows\foo.exe) and convert it to the NT/Device path (i.e. \Device\HardDiskVolume3\Windows\foo.exe). To do this, I am trying to use the standard ZwOpenSymbolicLinkObjectZwQuerySymbolicLinkObject flow. When calling ZwOpenSymbolicLinkObject, I am getting a STATUS_OBJECT_TYPE_MISMATCH error.

I have minimized the issue to demonstrate what is going on in the following code snippet. Please note that this is not my production code so there is no error checking, etc.

NTSTATUS status;
UNICODE_STRING symlinkName;
OBJECT_ATTRIBUTES attributes;
HANDLE hSymlink;

// Initialize the name with some value
RtlInitUnicodeString(&symlinkName, L"\??\C:\Windows\explorer.exe");

InitializeObjectAttributes(&attributes, &symlinkName, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);

status = ZwOpenSymbolicLinkObject(&hSymlink, GENERIC_READ, &attributes);

// At this point, status is 0xC0000024

< snip >

This seems like the correct way to call this API based on public examples and other posts on this forum, but I can’t seem to figure out what is going on. Any help or pointers would be much appreciated.

Thanks

I am not certain if the post removed the double backslashes in that post or not. Maybe because explorer.exe is not a symbolic link.

You’re correct, it should be \\??\\C:\Windows\explorer.exe. Sorry for the confusion.

I’ve conducted some additional testing and the only way I can get it to resolve is by using the exact name of the symlink in object manager (i.e. \??\C:) with no path/file suffixed. Ideally, I’d like to avoid breaking paths apart and shimming in device names but I’m pretty lost at this point.

Following up in the event that someone in the future comes across this post. I was unable to find a native way to do this so I had to split the path, resolve the symlink, and then reconstitute the path. Roughly, this process looks like:

  1. Use FsRtlDissectName to split the path into parts
  2. Prepend \??\ to the first part, making it something like \??\C:
  3. Resolve this symlink using the standard ZwOpenSymbolicLinkObjectZwQuerySymbolicLinkObject workflow
  4. Combine the resolved symlink with the second file part from the first step, adding a path delimiter between them

Here’s hoping that MSFT will add DOS to NT path canonicalization in the future, but for now this seems to be what we’re stuck with.

Open the target without open symlink or stop on reparse point flags.
Query the name from the filesystem.

That is what we do, since Filter Manager decided to break name query on
cross volume symlinks in Win10 1703/9 :frowning:

Kind regards, Dejan.
https://www.alfasp.com