?
Solved

Filehandle to filename

Posted on 2008-10-21
6
Medium Priority
?
1,705 Views
Last Modified: 2013-12-04
Is there a way to find the filename based on a filehandle in c#?

I have a IntPtr containing a filehandle to an open file, and I want to know what the name of that file is.
I did not open the file myself, and only have a function that receives the handle. But I am only interested in processing some files, based on how they are named.

The attached code always prints [Unknown]
SafeFileHandle sh = new SafeFileHandle(InFile, false);
FileStream f = new FileStream(sh, FileAccess.Read);
System.Console.WriteLine(f.Name);

Open in new window

0
Comment
Question by:wiredpea
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
6 Comments
 
LVL 8

Expert Comment

by:rambovn
ID: 22770259
0
 
LVL 41

Accepted Solution

by:
graye earned 2000 total points
ID: 22786881
Getting the name of the file based upon it's handle is a bit difficult and requires some *very* low-level API calls.
Take a look at this VB.Net example:

Imports System.Runtime.InteropServices
Module HandleToName
    'typedef struct _UNICODE_STRING {
    '  USHORT Length;
    '  USHORT MaximumLength;
    '  PWSTR Buffer;
    '} UNICODE_STRING, *PUNICODE_STRING; 
    Structure UNICODE_STRING
        Dim Length As Short
        Dim MaximumLength As Short
        Dim Buffer As String
    End Structure
 
    'typedef struct _OBJECT_NAME_INFORMATION {
    '    UNICODE_STRING ObjectName;
    '} OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION;
    Structure OBJECT_NAME_INFORMATION
        Dim ObjectName As UNICODE_STRING
    End Structure
 
    'NTSTATUS STDCALL NtQueryObject (
    '  IN HANDLE  ObjectHandle,  
    '  IN OBJECT_INFORMATION_CLASS  ObjectInformationClass,  
    '  OUT PVOID  ObjectInformation,  
    '  IN ULONG  Length,  
    '  OUT PULONG ResultLength  OPTIONAL 
    ')  
    Declare Function NtQueryObject Lib "ntdll" ( _
        ByVal ObjectHandle As IntPtr, _
        ByVal ObjectInformationClass As Integer, _
        ByRef ObjectInformation As Byte, _
        ByVal ObjectInformationLength As Integer, _
        ByRef ReturnLength As Integer _
    ) As Integer
 
    Const ObjectNameInformation As Integer = 1
    Const STATUS_SUCCESS As Integer = 0
    Const STATUS_BUFFER_OVERFLOW As Integer = -2147483643 '&H80000005L
    Const STATUS_INFO_LENGTH_MISMATCH As Integer = -1073741820 '&HC0000004L
 
    Function GetFileName(ByVal hObject As IntPtr) As String
        Dim dwSize, ntReturn As Integer
        Dim buf(1024) As Byte
        Dim pObjectInfo As New OBJECT_NAME_INFORMATION
        Dim ans, temp As String
 
        ans = ""
        dwSize = Marshal.SizeOf(pObjectInfo)
 
        ' do a dry run...
        ntReturn = NtQueryObject(hObject, ObjectNameInformation, buf(0), dwSize, dwSize)
        If ntReturn = STATUS_BUFFER_OVERFLOW Then
            ' do it again for real
            ntReturn = NtQueryObject(hObject, ObjectNameInformation, buf(0), dwSize, dwSize)
        End If
 
        If ntReturn = STATUS_SUCCESS Then
            ' Marshalling unmanaged strings inside structures is a bit tough, so
            ' since this is a simple one, we cheat and get the parts from a byte
            ' buffer
            pObjectInfo.ObjectName.Length = BitConverter.ToInt16(buf, 0)
            pObjectInfo.ObjectName.MaximumLength = BitConverter.ToInt16(buf, 4)
            pObjectInfo.ObjectName.Buffer = System.Text.Encoding.Unicode.GetString(buf, 8, pObjectInfo.ObjectName.Length)
            ans = pObjectInfo.ObjectName.Buffer
        End If
 
        ' let's weed out a few things that we're not really interested in.  If the
        ' device doesn't map to a drive letter, then return an empty string.
        temp = TranslateToDriveLetter(ans)
        If temp <> ans Then
            Return temp
        Else
            Return ""
        End If
    End Function
End Module

Open in new window

0
 
LVL 2

Expert Comment

by:Castorix
ID: 22789331
The right api is NtQueryInformationFile()
or GetFinalPathNameByHandle()  on Vista, which is a wrapper for NtQueryInformationFile ()
0
 
LVL 41

Expert Comment

by:graye
ID: 22789696
However, NtQueryInformationFile will deadlock if it can't successfully read from a locked stream.   The above doesn't suffer from that annoying side effect
0

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

What my article will show is if you ever had to do processing to a listbox without being able to just select all the items in it. My software Visual Studio 2008 crystal report v11 My issue was I wanted to add crystal report to a form and show…
Real-time is more about the business, not the technology. In day-to-day life, to make real-time decisions like buying or investing, business needs the latest information(e.g. Gold Rate/Stock Rate). Unlike traditional days, you need not wait for a fe…
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…
This is my first video review of Microsoft Bookings, I will be doing a part two with a bit more information, but wanted to get this out to you folks.

765 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question