How to get name associated with open HANDLE

Question :

How to get name associated with open HANDLE,

Answer :

What’s the easiest way to get the filename associated with an open HANDLE in Win32?

,

I tried the code posted by Mehrdad here. It works, but with limitations:

  1. It should not be used for network shares because the MountPointManager may hang for a very long time.
  2. It uses undocumented API (IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATH) I don’t like that very much
  3. It does not support USB devices that create virtual COM ports (I need that in my project)

I also studied other approaches like GetFileInformationByHandleEx() and GetFinalPathNameByHandle(), but these are useless as they return only Path + Filename but without drive. Additionally GetFinalPathNameByHandle() also has the hanging bug.

The GetMappedFileName() approach in the MSDN (posted by Max here) is also very limited:

  1. It works only with real files
  2. The file size must not be zero bytes
  3. Directories, Network and COM ports are not supported
  4. The code is clumsy

So I wrote my own code. I tested it on Win XP and on Win 7, 8, and 10. It works perfectly.

NOTE: You do NOT need any additional LIB file to compile this code!

CPP FILE:

t_NtQueryObject NtQueryObject()  {      static t_NtQueryObject f_NtQueryObject = NULL;      if (!f_NtQueryObject)      {          HMODULE h_NtDll = GetModuleHandle(L"Ntdll.dll"); // Ntdll is loaded into EVERY process!          f_NtQueryObject = (t_NtQueryObject)GetProcAddress(h_NtDll, "NtQueryObject");      }      return f_NtQueryObject;  }      // returns  // "DeviceHarddiskVolume3"                                (Harddisk Drive)  // "DeviceHarddiskVolume3Temp"                           (Harddisk Directory)  // "DeviceHarddiskVolume3Temptransparent.jpeg"          (Harddisk File)  // "DeviceHarddisk1DP(1)0-0+6foto.jpg"                  (USB stick)  // "DeviceTrueCryptVolumePDataPasswords.txt"            (Truecrypt Volume)  // "DeviceFloppy0Autoexec.bat"                           (Floppy disk)  // "DeviceCdRom1VIDEO_TSVTS_01_0.VOB"                   (DVD drive)  // "DeviceSerial1"                                        (real COM port)  // "DeviceUSBSER000"                                      (virtual COM port)  // "DeviceMupComputerNameC$Boot.ini"                   (network drive share,  Windows 7)  // "DeviceLanmanRedirectorComputerNameC$Boot.ini"      (network drive share,  Windwos XP)  // "DeviceLanmanRedirectorComputerNameSharesDance.m3u" (network folder share, Windwos XP)  // "DeviceAfd"                                            (internet socket)  // "DeviceConsole000F"                                    (unique name for any Console handle)  // "DeviceNamedPipePipename"                             (named pipe)  // "BaseNamedObjectsObjectname"                           (named mutex, named event, named semaphore)  // "REGISTRYMACHINESOFTWAREClasses.txt"                (HKEY_CLASSES_ROOT.txt)  DWORD GetNtPathFromHandle(HANDLE h_File, CString* ps_NTPath)  {      if (h_File == 0 || h_File == INVALID_HANDLE_VALUE)          return ERROR_INVALID_HANDLE;        // NtQueryObject() returns STATUS_INVALID_HANDLE for Console handles      if (IsConsoleHandle(h_File))      {          ps_NTPath->Format(L"\Device\Console%04X", (DWORD)(DWORD_PTR)h_File);          return 0;      }        BYTE  u8_Buffer[2000];      DWORD u32_ReqLength = 0;        UNICODE_STRING* pk_Info = &((OBJECT_NAME_INFORMATION*)u8_Buffer)->Name;      pk_Info->Buffer = 0;      pk_Info->Length = 0;        // IMPORTANT: The return value from NtQueryObject is bullshit! (driver bug?)      // - The function may return STATUS_NOT_SUPPORTED although it has successfully written to the buffer.      // - The function returns STATUS_SUCCESS although h_File == 0xFFFFFFFF      NtQueryObject()(h_File, ObjectNameInformation, u8_Buffer, sizeof(u8_Buffer), &u32_ReqLength);        // On error pk_Info->Buffer is NULL      if (!pk_Info->Buffer || !pk_Info->Length)          return ERROR_FILE_NOT_FOUND;        pk_Info->Buffer[pk_Info->Length /2] = 0; // Length in Bytes!        *ps_NTPath = pk_Info->Buffer;      return 0;  }    // converts  // "DeviceHarddiskVolume3"                                -> "E:"  // "DeviceHarddiskVolume3Temp"                           -> "E:Temp"  // "DeviceHarddiskVolume3Temptransparent.jpeg"          -> "E:Temptransparent.jpeg"  // "DeviceHarddisk1DP(1)0-0+6foto.jpg"                  -> "I:foto.jpg"  // "DeviceTrueCryptVolumePDataPasswords.txt"            -> "P:DataPasswords.txt"  // "DeviceFloppy0Autoexec.bat"                           -> "A:Autoexec.bat"  // "DeviceCdRom1VIDEO_TSVTS_01_0.VOB"                   -> "H:VIDEO_TSVTS_01_0.VOB"  // "DeviceSerial1"                                        -> "COM1"  // "DeviceUSBSER000"                                      -> "COM4"  // "DeviceMupComputerNameC$Boot.ini"                   -> "\ComputerNameC$Boot.ini"  // "DeviceLanmanRedirectorComputerNameC$Boot.ini"      -> "\ComputerNameC$Boot.ini"  // "DeviceLanmanRedirectorComputerNameSharesDance.m3u" -> "\ComputerNameSharesDance.m3u"  // returns an error for any other device type  DWORD GetDosPathFromNtPath(const WCHAR* u16_NTPath, CString* ps_DosPath)  {      DWORD u32_Error;        if (wcsnicmp(u16_NTPath, L"\Device\Serial", 14) == 0 || // e.g. "Serial1"          wcsnicmp(u16_NTPath, L"\Device\UsbSer", 14) == 0)   // e.g. "USBSER000"      {          HKEY h_Key;           if (u32_Error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"Hardware\DeviceMap\SerialComm", 0, KEY_QUERY_VALUE, &h_Key))              return u32_Error;            WCHAR u16_ComPort[50];            DWORD u32_Type;          DWORD u32_Size = sizeof(u16_ComPort);           if (u32_Error = RegQueryValueEx(h_Key, u16_NTPath, 0, &u32_Type, (BYTE*)u16_ComPort, &u32_Size))          {              RegCloseKey(h_Key);              return ERROR_UNKNOWN_PORT;          }            *ps_DosPath = u16_ComPort;          RegCloseKey(h_Key);          return 0;      }        if (wcsnicmp(u16_NTPath, L"\Device\LanmanRedirector\", 25) == 0) // Win XP      {          *ps_DosPath  = L"\\";          *ps_DosPath += (u16_NTPath + 25);          return 0;      }        if (wcsnicmp(u16_NTPath, L"\Device\Mup\", 12) == 0) // Win 7      {          *ps_DosPath  = L"\\";          *ps_DosPath += (u16_NTPath + 12);          return 0;      }        WCHAR u16_Drives[300];      if (!GetLogicalDriveStrings(300, u16_Drives))          return GetLastError();        WCHAR* u16_Drv = u16_Drives;      while (u16_Drv[0])      {          WCHAR* u16_Next = u16_Drv +wcslen(u16_Drv) +1;            u16_Drv[2] = 0; // the backslash is not allowed for QueryDosDevice()            WCHAR u16_NtVolume[1000];          u16_NtVolume[0] = 0;            // may return multiple strings!          // returns very weird strings for network shares          if (!QueryDosDevice(u16_Drv, u16_NtVolume, sizeof(u16_NtVolume) /2))              return GetLastError();            int s32_Len = (int)wcslen(u16_NtVolume);          if (s32_Len > 0 && wcsnicmp(u16_NTPath, u16_NtVolume, s32_Len) == 0)          {              *ps_DosPath  =  u16_Drv;              *ps_DosPath += (u16_NTPath + s32_Len);              return 0;          }            u16_Drv = u16_Next;      }      return ERROR_BAD_PATHNAME;  }  

HEADER FILE:

#pragma warning(disable: 4996) // wcsnicmp deprecated  #include     // This makro assures that INVALID_HANDLE_VALUE (0xFFFFFFFF) returns FALSE  #define IsConsoleHandle(h) (((((ULONG_PTR)h) & 0x10000003) == 0x3) ? TRUE : FALSE)    enum OBJECT_INFORMATION_CLASS   {      ObjectBasicInformation,       ObjectNameInformation,      ObjectTypeInformation,       ObjectAllInformation,       ObjectDataInformation  };    struct OBJECT_NAME_INFORMATION   {      UNICODE_STRING Name; // defined in winternl.h      WCHAR NameBuffer;  };    typedef NTSTATUS (NTAPI* t_NtQueryObject)(HANDLE Handle, OBJECT_INFORMATION_CLASS Info, PVOID Buffer, ULONG BufferSize, PULONG ReturnLength);     

That’s the answer How to get name associated with open HANDLE, Hope this helps those looking for an answer. Then we suggest to do a search for the next question and find the answer only on our site.

Disclaimer :

The answers provided above are only to be used to guide the learning process. The questions above are open-ended questions, meaning that many answers are not fixed as above. I hope this article can be useful, Thank you

Read More  Is this the proper use of a mutex?