Sunday, August 17, 2008

GetFinalPathNameByHandle API Hungs

GetFinalPathNameByHandle is an new API introduced in windows vista. As you can read from MSDN, the purpose of this API is to return the file name corresponding to a file handle .

Some months back, I have written a small utility OpenedFileFinder which list all the file that are opened under a certain folder. While writing this application,the main problem I came across was to get the file name from the handle. Initially I used a function called NtQueryObject(). But the problem with this API is that if we try to query the details for certain object such as pipes, directory handles etc, it will hangs. So in my application finally I have to introduce a driver to get round of this hanging problem. When I found the new GetFinalPathNameByHandle(), I was so happy and I thought at least I can avoid the driver in the vista. So I had a try on this API. But I came to find that this API also have the same hanging problem which I described earlier.

It seems the GetFinalPathNameByHandle is also using the same NtQueryObject() to get the file name and so it hangs. Any how, I have reported this bug to the microsoft connect. Let us see how they solve the problem.

Another API, that worth mentioning here is GetFileInformationByHandleEx(), which is also a new API introduced in Vista. Using this API also, I can get the file name from a handle. So I decided to check whether the same problem exists in this API also. Surprisingly it worked fine. And in MSDN also it is mentioned that it uses a driver for attaining the task. So I highly suggest every one to use GetFileInformationByHandleEx() API instead of GetFinalPathNameByHandle().

7 comments:

  1. Hi Naveen!

    Nice blog you have here. It will be difficult for Microsoft to fix the freeze with GetFileInformationByHandleEx because it ultimately calls NtQueryObject which uses KsQueryInformationFile to query the file object.

    http://msdn.microsoft.com/en-us/library/ms809536.aspx

    Named pipes are created by default in a blocking-wait mode. KsQueryInformationFile will go into a wait state resulting in a freeze in most cases. If Microsoft makes any changes to GetFileInformationByHandleEx I would be willing to bet they avoid named pipe handles.

    Best Wishes,
    -David Delaune

    ReplyDelete
  2. David,

    From the kernal mode, it doesnt havent to call function to get the file name, it can simple access FILE_OBJECT structure and fetch the necessary informations. isnt it?

    ReplyDelete
  3. Hey dude, nice blog. :) Also read your article on codeproject.

    I need your help, if you can please. I wish to see all Files opened by a particular process. I have been able to get all handles using the ZwQuerySystemInformation() API. But I am unable to get the filename/path of an open handle.

    I have tried using GetFileInformationByHandleEx() and the GetFinalPathNameByHandle(). Both give memoryaccessviolation or SafeArrayTypeMismatch error randomly and always fail. I must be doing
    something wrong. I have pondered over the code for so long and even after many google searches unable to find any good documentation for these functions with solid examples for the newbies in low level Win development.

    I would be grateful if you can send me a simple and easy to understand code in c# that just gets the filename for a user supplied handle. My email ID is count_soumik@hotmail.com.

    Waiting for your reply :) Please do help :)

    ReplyDelete
  4. @Soumik, the "Listing used files"(http://www.codeproject.com/KB/shell/OpenedFileFinder.aspx?display=PrintAll&fid=422864&df=90&mpp=25&noise=3&sort=Position&view=Quick&fr=26 ) article in codeproject shows how to get the file name for all the opened handles. I guess if you have read that, you problem will be solved. Let me know if you have anydoubt after that...

    ReplyDelete
  5. To avoid hangs, don't call GetFinalPahtNameByHandle() on pipes.

    //realHandle is the handle duplicated into the current processes space
    DWORD fileType = GetFileType(realHandle);
    if( fileType != FILE_TYPE_DISK ) {
    //don't try to get the filename via GetFinalPahtNameByHandle
    } else {
    //do try to get the filename via GetFinalPahtNameByHandle
    }
    Most likely you just want the Disk files anyways... you can get char files as well (no hangs), but kind of pointless.

    ReplyDelete
  6. How does ProcessExplorer not hang when listing the handles?
    Wouldn't it be a good idea to use the driver of ProcessExplorer instead in your application?
    Does this driver have a certificate for Windows 64 Bit ?

    ReplyDelete
  7. There is no documentation on how to use ProcessExplorer's driver. So for now, the only option left is to use our own driver.

    >>Does this driver have a certificate for Windows 64 Bit ?
    Nope. :(

    ReplyDelete