[Bug 39569] New: Multiple applications using ntdll.NtQueryObject 'ObjectNameInformation' info class get incorrect names for file objects

wine-bugs at winehq.org wine-bugs at winehq.org
Tue Nov 10 06:08:50 CST 2015


https://bugs.winehq.org/show_bug.cgi?id=39569

            Bug ID: 39569
           Summary: Multiple applications using ntdll.NtQueryObject
                    'ObjectNameInformation' info class get incorrect names
                    for file objects
           Product: Wine
           Version: 1.7.54
          Hardware: x86-64
                OS: Linux
            Status: NEW
          Severity: normal
          Priority: P2
         Component: ntdll
          Assignee: wine-bugs at winehq.org
          Reporter: focht at gmx.net
      Distribution: ---

Hello folks,

consider the following trace:

* explicitly removed relay excludes to show internal calls
* Wine builtin as example

--- snip ---
...
002a:Call KERNEL32.CreateFileW(00326840
L"C:\\windows\\notepad.exe",80000000,00000001,00000000,00000003,00000000,00000000)
ret=00b16742
002a:Call ntdll.RtlIsDosDeviceName_U(00326840 L"C:\\windows\\notepad.exe")
ret=7f40b89ac80d
002a:Ret  ntdll.RtlIsDosDeviceName_U() retval=00000000 ret=7f40b89ac80d
002a:Call ntdll.RtlDosPathNameToNtPathName_U(00326840
L"C:\\windows\\notepad.exe",0269d820,00000000,00000000) ret=7f40b89ac99c
002a:Ret  ntdll.RtlDosPathNameToNtPathName_U() retval=00000001 ret=7f40b89ac99c
002a:Call
ntdll.NtCreateFile(0269d808,80100000,0269d830,0269d810,00000000,00000000,00000001,f00000001,00000060,00000000,00000000)
ret=7f40b89acb9b
002a:trace:ntdll:FILE_CreateFile handle=0x269d808 access=80100000
name=L"\\??\\C:\\windows\\notepad.exe" objattr=00000040 root=(nil) sec=(nil)
io=0x269d810 alloc_size=(nil) attr=00000000 sharing=00000001 disp=1
options=00000060 ea=(nil).0x00000000
002a: create_file( access=80100000, attributes=00000040, sharing=00000001,
create=1, options=00000060, attrs=00000000,
objattr={rootdir=0000,sd={},name=L""},
filename="/home/focht/wine64/dosdevices/c:/windows/notepad.exe" )
002a: create_file() = 0 { handle=0384 }
002a:Ret  ntdll.NtCreateFile() retval=00000000 ret=7f40b89acb9b
...
002a:Ret  KERNEL32.CreateFileW() retval=00000384 ret=00b16742
...
002a:Call ntdll.NtQueryObject(00000384,00000001,00000000,00000000,0269d778)
ret=00d222ab
002a:trace:ntdll:NtQueryObject (0x384,0x00000001,(nil),0x00000000,0x269d778)
002a: get_handle_unix_name( handle=0384 )
002a: get_handle_unix_name() = 0 { name_len=52,
name="/home/focht/wine64/dosdevices/c:/windows/notepad.exe" }
002a:Ret  ntdll.NtQueryObject() retval=c0000004 ret=00d222ab
...
002a:Call ntdll.NtQueryObject(00000384,00000001,000e0da0,00002046,00000000)
ret=00d222f7
002a:trace:ntdll:NtQueryObject (0x384,0x00000001,0xe0da0,0x00002046,(nil))
002a: get_handle_unix_name( handle=0384 )
002a: get_handle_unix_name() = 0 { name_len=52,
name="/home/focht/wine64/dosdevices/c:/windows/notepad.exe" }
002a:Ret  ntdll.NtQueryObject() retval=00000000 ret=00d222f7 
...
002a:Call KERNEL32.QueryDosDeviceW(0269d260 L"c:",0269d270,00000104)
ret=00d216f4
002a:Call ntdll.RtlIsDosDeviceName_U(0269d260 L"c:") ret=7f40b8a11373
002a:Ret  ntdll.RtlIsDosDeviceName_U() retval=00000000 ret=7f40b8a11373
...
002a:Call ntdll.RtlInitUnicodeString(0269c910,027fddf0 L"\\DosDevices\\c:")
ret=7f40b8a0cfba
002a:Ret  ntdll.RtlInitUnicodeString() retval=0269c910 ret=7f40b8a0cfba
002a:Call ntdll.NtOpenSymbolicLinkObject(0269c908,00000001,0269c920)
ret=7f40b8a0cfd9
002a:trace:ntdll:NtOpenSymbolicLinkObject
(0x269c908,0x00000001,{name=L"\\DosDevices\\c:", attr=0x00000040, hRoot=(nil),
sd=(nil)}
002a: open_symlink( access=00000001, attributes=00000040, rootdir=0000,
name=L"\\DosDevices\\c:" )
002a: open_symlink() = 0 { handle=038c }
002a:Ret  ntdll.NtOpenSymbolicLinkObject() retval=00000000 ret=7f40b8a0cfd9
002a:Call ntdll.NtQuerySymbolicLinkObject(0000038c,0269c8f0,00000000)
ret=7f40b8a0d016
002a:trace:ntdll:NtQuerySymbolicLinkObject (0x38c,0x269c8f0,(nil))
002a: query_symlink( handle=038c )
002a: query_symlink() = 0 { total=46, target_name=L"\\Device\\HarddiskVolume1"
}
002a:Ret  ntdll.NtQuerySymbolicLinkObject() retval=00000000 ret=7f40b8a0d016
002a:Call ntdll.NtClose(0000038c) ret=7f40b8a0d04c
002a: close_handle( handle=038c )
002a: close_handle() = 0
002a:Ret  ntdll.NtClose() retval=00000000 ret=7f40b8a0d04c
...
002a:Ret  KERNEL32.QueryDosDeviceW() retval=00000019 ret=00d216f4 
...
002a:Call KERNEL32.CreateFileW(02086700
L"\\??\\C:\\windows\\notepad.exe",80000000,00000001,00000000,00000003,ffffffff00000000,00000000)
ret=00b71906
002a:Call ntdll.RtlIsDosDeviceName_U(02086700
L"\\??\\C:\\windows\\notepad.exe") ret=7f40b89ac80d
002a:Ret  ntdll.RtlIsDosDeviceName_U() retval=00000000 ret=7f40b89ac80d
002a:Call ntdll.RtlDosPathNameToNtPathName_U(02086700
L"\\??\\C:\\windows\\notepad.exe",0269c780,00000000,00000000) ret=7f40b89ac99c
002a:Ret  ntdll.RtlDosPathNameToNtPathName_U() retval=00000001 ret=7f40b89ac99c
002a:Call
ntdll.NtCreateFile(0269c768,80100000,0269c790,0269c770,00000000,00000000,00000001,f00000001,00000060,00000000,00000000)
ret=7f40b89acb9b
002a:trace:ntdll:FILE_CreateFile handle=0x269c768 access=80100000
name=L"\\??\\Z:\\??\\C:\\windows\\notepad.exe" objattr=00000040 root=(nil)
sec=(nil) io=0x269c770 alloc_size=(nil) attr=00000000 sharing=00000001 disp=1
options=00000060 ea=(nil).0x00000000
002a:warn:ntdll:FILE_CreateFile L"\\??\\Z:\\??\\C:\\windows\\notepad.exe" not
found (c0000033)
002a:Ret  ntdll.NtCreateFile() retval=c0000033 ret=7f40b89acb9b
002a:Call ntdll.RtlNtStatusToDosError(c0000033) ret=7f40b89acd3c
002a:Ret  ntdll.RtlNtStatusToDosError() retval=0000007b ret=7f40b89acd3c
...
002a:Ret  KERNEL32.CreateFileW() retval=ffffffffffffffff ret=00b71906 
...
002b:Call KERNEL32.CreateProcessW(02032b40
L"\\??\\C:\\windows\\notepad.exe",00000000,00000000,00000000,00000000,00000013,00000000,02061e60
L"\\??\\C:\\windows",00f6d000,00f6cef8) ret=00ef2163
002b:Call ntdll.RtlIsDosDeviceName_U(02abd720
L"\\??\\C:\\windows\\notepad.exe") ret=7f40b89ac80d
002b:Ret  ntdll.RtlIsDosDeviceName_U() retval=00000000 ret=7f40b89ac80d
002b:Call ntdll.RtlDosPathNameToNtPathName_U(02abd720
L"\\??\\C:\\windows\\notepad.exe",02abcfb0,00000000,00000000) ret=7f40b89ac99c
002b:Ret  ntdll.RtlDosPathNameToNtPathName_U() retval=00000001 ret=7f40b89ac99c
002b:Call
ntdll.NtCreateFile(02abcf98,80100000,02abcfc0,02abcfa0,00000000,00000000,00000005,00000001,00000060,00000000,00000000)
ret=7f40b89acb9b
002b:trace:ntdll:FILE_CreateFile handle=0x2abcf98 access=80100000
name=L"\\??\\Z:\\??\\C:\\windows\\notepad.exe" objattr=00000040 root=(nil)
sec=(nil) io=0x2abcfa0 alloc_size=(nil) attr=00000000 sharing=00000005 disp=1
options=00000060 ea=(nil).0x00000000
002b:warn:ntdll:FILE_CreateFile L"\\??\\Z:\\??\\C:\\windows\\notepad.exe" not
found (c0000033)
002b:Ret  ntdll.NtCreateFile() retval=c0000033 ret=7f40b89acb9b
...
002b:Call ntdll.RtlGetFullPathName_U(02abd720
L"\\??\\C:\\windows\\notepad.exe",00000410,02abd190,02abd110) ret=7f40b89dd82b
002b:Ret  ntdll.RtlGetFullPathName_U() retval=00000038 ret=7f40b89dd82b
...
002b:Ret  KERNEL32.CreateProcessW() retval=00000000 ret=00ef2163 
--- snip ---

Calling 'kernel32' API with native NT paths is obviously wrong and not intended
here.

The relay trace partially corresponds to the following source code - at least
for the preceding device/filename lookup/translation:

https://bitbucket.org/mrexodia/devicenameresolver/src/3fc6704267d469bd08633eee3fad292db3a8ac52/DeviceNameResolver.cpp?at=master#DeviceNameResolver.cpp-78

--- snip ---
...
__declspec(dllexport) bool DevicePathFromFileHandleW(HANDLE hFile, wchar_t*
szDevicePath, size_t nSize)
{
    NativeWinApi::initialize();
    ULONG ReturnLength;
    bool bRet=false;
    if(NativeWinApi::NtQueryObject(hFile, ObjectNameInformation, 0, 0,
&ReturnLength)==STATUS_INFO_LENGTH_MISMATCH)
    {
        ReturnLength+=0x2000; //on Windows XP SP3 ReturnLength will not be set
just add some buffer space to fix this
        POBJECT_NAME_INFORMATION
NameInformation=(POBJECT_NAME_INFORMATION)GlobalAlloc(0, ReturnLength);
        if(NativeWinApi::NtQueryObject(hFile, ObjectNameInformation,
NameInformation, ReturnLength, 0)==STATUS_SUCCESS)
        {
            NameInformation->Name.Buffer[NameInformation->Name.Length/2]=L'\0';
//null-terminate the UNICODE_STRING
            if(wcslen(NameInformation->Name.Buffer)<nSize)
            {
                wcscpy_s(szDevicePath, nSize/sizeof(wchar_t),
NameInformation->Name.Buffer);
                bRet=true;
            }
        }
        GlobalFree(NameInformation);
    }
    if(_wcsnicmp(szDevicePath, L"\\Device\\LanmanRedirector\\", 25) == 0) //
Win XP
    {
        wcscpy_s(szDevicePath, nSize / sizeof(wchar_t), L"\\\\");
        wcscat_s(szDevicePath, nSize / sizeof(wchar_t), &szDevicePath[25]);
    }
    else if(_wcsnicmp(szDevicePath, L"\\Device\\Mup\\", 12) == 0) // Win 7
    {
        wcscpy_s(szDevicePath, nSize / sizeof(wchar_t), L"\\\\");
        wcscat_s(szDevicePath, nSize / sizeof(wchar_t), &szDevicePath[12]);
    }
    return bRet;
}

__declspec(dllexport) bool DevicePathFromFileHandleA(HANDLE hFile, char*
szDevicePath, size_t nSize)
{
    DynBuf newDevicePathBuf(nSize*sizeof(wchar_t));
    wchar_t* newDevicePath = (wchar_t*)newDevicePathBuf.GetPtr();
    if(!DevicePathFromFileHandleW(hFile, newDevicePath, nSize*sizeof(wchar_t)))
        return false;
    if(!WideCharToMultiByte(CP_ACP, NULL, newDevicePath, -1, szDevicePath,
(int)wcslen(newDevicePath)+1, NULL, NULL))
        return false;
    return true;
}

__declspec(dllexport) bool PathFromFileHandleW(HANDLE hFile, wchar_t* szPath,
size_t nSize)
{
    typedef DWORD (WINAPI* GETFINALPATHNAMEBYHANDLEW) (
        IN HANDLE hFile,
        OUT wchar_t* lpszFilePath,
        IN DWORD cchFilePath,
        IN DWORD dwFlags
        );
    static GETFINALPATHNAMEBYHANDLEW
GetFPNBHW=(GETFINALPATHNAMEBYHANDLEW)GetProcAddress(GetModuleHandleW(L"kernel32.dll"),
"GetFinalPathNameByHandleW");
    if(GetFPNBHW && GetFPNBHW(hFile, szPath, (DWORD)(nSize/sizeof(wchar_t)),
0))
    {
        if(_wcsnicmp(szPath, L"\\\\?\\UNC\\", 8) == 0) // Server path
        {
            wcscpy_s(szPath, nSize / sizeof(wchar_t), L"\\\\");
            wcscat_s(szPath, nSize / sizeof(wchar_t), &szPath[8]);
        }
        else if(_wcsnicmp(szPath, L"\\\\?\\", 4) == 0 && szPath[5]==L':') //
Drive path
        {
            wcscpy_s(szPath, nSize/sizeof(wchar_t), &szPath[4]);
        }
        return true;
    }
    if(!DevicePathFromFileHandleW(hFile, szPath, nSize))
        return false;
    std::wstring oldPath(szPath);
    if (!DevicePathToPathW(szPath, szPath, nSize))
        wcscpy_s(szPath, nSize / sizeof(wchar_t), oldPath.c_str());
    return true;
}
...
--- snip ---

https://bitbucket.org/mrexodia/devicenameresolver/src/3fc6704267d469bd08633eee3fad292db3a8ac52/DeviceNameResolverInternal.cpp?at=master#DeviceNameResolverInternal.cpp-44

--- snip ---
...
bool DeviceNameResolver::resolveDeviceLongNameToShort(const TCHAR * sourcePath,
TCHAR * targetPath)
{
    for (unsigned int i = 0; i < deviceNameList.size(); i++)
    {
        if (!_tcsnicmp(deviceNameList.at(i).longName, sourcePath,
deviceNameList.at(i).longNameLength) &&
sourcePath[deviceNameList.at(i).longNameLength]==TEXT('\\'))
        {
            _tcscpy_s(targetPath, MAX_PATH, deviceNameList.at(i).shortName);
            _tcscat_s(targetPath, MAX_PATH, sourcePath +
deviceNameList.at(i).longNameLength);
            return true;
        }
    }
    return false;
}
...
--- snip ---

In short: Wine returns incorrect names for file objects in 'NtQueryObject'.

The app code passes 'C:\windows\notepad.exe', gets
'\\??\\C:\\windows\\notepad.exe' and tries to translate the path to short form,
removing the device name part by matching against device list.

This fails hence the app uses whatever was returned by 'NtQueryObject' as
fallback (= native NT path).

The proper object name would have been:

'\Device\HarddiskVolume1\Windows\notepad.exe'

Source:
https://source.winehq.org/git/wine.git/blob/71080cc0818e8cc3e8be0c30bcc6602be7db12d0:/dlls/ntdll/om.c#l87

Another article (just to reference the list from second answer):

https://stackoverflow.com/questions/65170/how-to-get-name-associated-with-open-handle
("How to get name associated with open HANDLE")

--- quote ---
...
// returns
// "\Device\HarddiskVolume3"                                (Harddisk Drive)
// "\Device\HarddiskVolume3\Temp"                           (Harddisk
Directory)
// "\Device\HarddiskVolume3\Temp\transparent.jpeg"          (Harddisk File)
// "\Device\Harddisk1\DP(1)0-0+6\foto.jpg"                  (USB stick)
// "\Device\TrueCryptVolumeP\Data\Passwords.txt"            (Truecrypt Volume)
// "\Device\Floppy0\Autoexec.bat"                           (Floppy disk)
// "\Device\CdRom1\VIDEO_TS\VTS_01_0.VOB"                   (DVD drive)
// "\Device\Serial1"                                        (real COM port)
// "\Device\USBSER000"                                      (virtual COM port)
// "\Device\Mup\ComputerName\C$\Boot.ini"                   (network drive
share,  Windows 7)
// "\Device\LanmanRedirector\ComputerName\C$\Boot.ini"      (network drive
share,  Windwos XP)
// "\Device\LanmanRedirector\ComputerName\Shares\Dance.m3u" (network folder
share, Windwos XP)
// "\Device\Afd"                                            (internet socket)
// "\Device\Console000F"                                    (unique name for
any Console handle)
// "\Device\NamedPipe\Pipename"                             (named pipe)
// "\BaseNamedObjects\Objectname"                           (named mutex, named
event, named semaphore)
// "\REGISTRY\MACHINE\SOFTWARE\Classes\.txt"               
(HKEY_CLASSES_ROOT\.txt)
...
--- quote ---

$ wine --version
wine-1.7.54-212-gf97ac58

Regards

-- 
Do not reply to this email, post in Bugzilla using the
above URL to reply.
You are receiving this mail because:
You are watching all bug changes.



More information about the wine-bugs mailing list