Solved

Filehandle to filename

Posted on 2008-10-21
6
1,658 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
  • 2
6 Comments
 
LVL 8

Expert Comment

by:rambovn
ID: 22770259
0
 
LVL 41

Accepted Solution

by:
graye earned 500 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

Are your AD admin tools letting you down?

Managing Active Directory can get complicated.  Often, the native tools for managing AD are just not up to the task.  The largest Active Directory installations in the world have relied on one tool to manage their day-to-day administration tasks: Hyena. Start your trial today.

Question has a verified solution.

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

Entering time in Microsoft Access can be difficult. An input mask often bothers users more than helping them and won't catch all typing errors. This article shows how to create a textbox for 24-hour time input with full validation politely catching …
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…

831 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