Getting every FILE_OBJECT for a specific file path?

Let’s say I want to inspect every FILE_OBJECT for a specific path (file or folder), such as \Systemroot\Windows or \Device\HarddiskVolume3\Windows.

Is there any possible way to do this using windbg? Or printing every FILE_OBJECT (that is still active) on the machine?

I need to find if some certain files are causing a kernel mode reference leak or not, and if possible find the faulty driver.

What’s the failure scenario?

You can find all File Objects with active handles by using “!handle 0 3 0 File”. If there are no handles then you could try enabling object tracking and then dumping with “!object 0 File”

https://learn.microsoft.com/en-us/windows-hardware/drivers/debugger/maintain-a-list-of-objects-for-each-type

But in either case you’re just going to know that there is a File Object, but not necessarily who owns it or created it.

@“Scott_Noone_(OSR)” said:
What’s the failure scenario?

You can find all File Objects with active handles by using “!handle 0 3 0 File”. If there are no handles then you could try enabling object tracking and then dumping with “!object 0 File”

https://learn.microsoft.com/en-us/windows-hardware/drivers/debugger/maintain-a-list-of-objects-for-each-type

But in either case you’re just going to know that there is a File Object, but not necessarily who owns it or created it.

If I recall correctly, a FILE_OBJECT is created for every usermode (CreateFile) or kernelmode (ZwCreateFile, FltCreateFile) handle that is opened on the target file, Correct? So if there is no open handle on a particular file, I assume I can’t find any FILE_OBJECT for that file right?

Objects have both handle and reference counts, so just because there are no handles doesn’t mean that there are no objects. That’s what the object tracking option is for.

@“Scott_Noone_(OSR)” said:
Objects have both handle and reference counts, so just because there are no handles doesn’t mean that there are no objects. That’s what the object tracking option is for.

So let’s say I have a file or folder like \Systemroot\Windows, what is the proper command to use to find every FILE_OBJECT (if any) of this file? Do I have to look through the entire output of !handle 0 3 0 File?

Also another side question: In Linux kernel, there is a inode struct which represent each file (no matter the open handles), and then there’s a file structure that represents an open file descriptor (similar to FILE_OBJECT), Is there anything similar to inode struct in Windows? Or if a file is not opened by anyone, then there’s no structure that is representing it? (Not talking about the structure that the underlying filesystem driver is using, but the structure that kernel itself is using no matter the underlying filesystem)

Well, inodes in Linux live on disk. A filesystem that doesn’t have the concept has to simulate them. There is no such file-system-independent structure in Windows, because it does not have the same universal namespace concept. All you get is the FILE_OBJECT. If a file is not opened, then the kernel doesn’t need to refer to it.

@brad_H said:
Also another side question: In Linux kernel, there is a inode struct which represent each file (no matter the open handles), and then there’s a file structure that represents an open file descriptor (similar to FILE_OBJECT), Is there anything similar to inode struct in Windows? Or if a file is not opened by anyone, then there’s no structure that is representing it? (Not talking about the structure that the underlying filesystem driver is using, but the structure that kernel itself is using no matter the underlying filesystem)

I’m not sure this helps with your question but I just wanted to clarify something:

The Windows equivalent to an in memory inode is the File Control Block (FSRTL_ADVANCED_FCB_HEADER) and is stored in the FsContext field of the FILE_OBJECT. So, for example, two File Objects to the same file on disk will have the same FsContext value*. It is the job of the File System to maintain this field as it’s the only one that really knows.

1: kd> !fileobj 0xffffdd8e`36f30680

\Windows\System32\cmd.exe

Device Object: 0xffffdd8e309408a0   \Driver\volmgr
Vpb: 0xffffdd8e309d1260
Access: Read SharedRead SharedDelete 

Flags:  0x44442
	Synchronous IO
	Cache Supported
	Queue Irps to Thread
	Cleanup Complete
	Handle Created

FsContext: 0xffff800e5786e170	FsContext2: 0xffff800e5afae380
CurrentByteOffset: 0
Cache Data:
  Section Object Pointers: ffffdd8e3405a818
  Shared Cache Map: 00000000

1: kd> dt nt!_FSRTL_ADVANCED_FCB_HEADER 0xffff800e5786e170
   +0x000 NodeTypeCode     : 0n1797
   +0x002 NodeByteSize     : 0n632
   +0x004 Flags            : 0x60 '`'
   +0x005 IsFastIoPossible : 0x2 ''
   +0x006 Flags2           : 0x2 ''
   +0x007 Reserved         : 0y0000
   +0x007 Version          : 0y0100
   +0x008 Resource         : 0xffffdd8e`3405a7a0 _ERESOURCE
   +0x010 PagingIoResource : 0xffffdd8e`3405a850 _ERESOURCE
   +0x018 AllocationSize   : _LARGE_INTEGER 0x4f000
   +0x020 FileSize         : _LARGE_INTEGER 0x4f000
   +0x028 ValidDataLength  : _LARGE_INTEGER 0x4f000
   +0x030 FastMutex        : 0xffffdd8e`3405a768 _FAST_MUTEX
   +0x038 FilterContexts   : _LIST_ENTRY [ 0xffffdd8e`33e85ed8 - 0xffffdd8e`33e85ed8 ]
   +0x048 PushLock         : _EX_PUSH_LOCK
   +0x050 FileContextSupportPointer : 0xffff800e`5786e158  -> (null) 
   +0x058 Oplock           : 0xffff800e`5753f860 Void
   +0x058 ReservedForRemote : 0xffff800e`5753f860 Void
   +0x060 AePushLock       : 0xffff800e`5786e390 Void
   +0x068 BypassIoOpenCount : 0

Note that this structure only exists in memory for as long as there is a File Object around that references it. When a file is memory mapped (or used for cached I/O) the Memory Manager will reference one of the File Objects used and keep it around long after the application closes the HANDLE. These references will only ever go away when there’s sufficient memory pressure on the machine or you do something like delete the file.

*It gets more complicated for NTFS because there we support multiple streams per-file. So, NTFS creates its own structure called the Stream Control Block and puts that in FsContext. However, because of the way the OS works the Stream Control Block still starts with an FSRTL_ADVANCED_FCB_HEADER structure).

1 Like