FileObjectInfo - Digging into the Windows NT Internals

Environment: Windows NT 4.0/2000 only, VC6 SP3, NT4 DDK

Overview and usage

FileObjectInfo is a tool which lets you take a look at Windows NT's file objects. In contrast to NTHandleEx from www.sysinternals.com and EnTeHandle article from Fred Forester (contributed here at CodeGuru) it also shows some of the corresponding device object properties, like the actual device name.
FileObjectInfo walks the systems handle table and looks for all handles which refer to file objects. In Windows NT not only files which reside on disk are represented by a file object. File objects are also used to access communication devices, input/output devices and so on. FileObjectInfo shows information about the file objects and the device they belong to. This is especially useful, if the file object is unnamed, e.g. in case of the serial communication ports (see screenshot below).


Click here for a larger image

Click here for another view of this data - grouped by process name

Each file object is shown in one line, listing its owners process id and name, the device type/name of the device which it refers to and the actual file name (or "no name" if it is unnamed). To allow easy viewing and browsing of all file objects, you can group and sort the display columns. To group by a column use the main menus view --> group by... items. This will group all file objects with the same group name into a node of a tree view (see [6] for more information on the treeview list control used). To sort just click one of the column headings. In case you want to refresh the display, i.e. reread the systems handle table, you can use view --> refresh.
Personally i am using FileObjectInfo to find answers to questions like: "What process has opened COM1?" (Try it yourself: group by "device type" and expand the tree node FILE_DEVICE_SERIAL_PORT!).
For some notes on installing and running FileObjectInfo, see the end of this article.

Inner Workings

FileObjectInfo actually consists of two components: an application which uses some undocumented functions to get information about the systems handles and a kernel mode driver, which is responsible for peeking around in NT's internals.
The following picture shows what happens inside the application/driver combo.


Click here for a larger image

The user mode application uses a few undocumented calls into NTDLL.DLL (NtQuerySystemInformation, see [2]) to get information about all open handles and all running processes. Each entry (SYSTEM_HANDLE) of the handle list (shown as SystemHandleList in the picture above) contains some information about the handle. Of particular interest are:

  • ProcessID: Used to display the owners process name
  • ObjectType: Type of Object (e.g. OB_TYPE_FILE == File-Object)
  • *pObject: Address of the kernel mode data structure for this object
To get further information about the object which the handle refers to, i looked for a way to peek at the address provided by *pObject. However, this address is in the kermel mode address space, which cannot be accessed by user mode applications. Therfore i wrote a kernel mode device driver. The application just passes the kernel mode address to the driver and the driver peeks at the object referenced by this address.

In case of a file object (FILE_OBJECT, which is fortunately documented (!) in the DDK, see [3]) the driver uses the embedded pointer *pDeviceObject to get the refering DEVICE_OBJECT. Using this pointer it builds a structure containing the device objects name (using the officially undocumented ObQueryNameString, but see [5]) and the type of the device object. This structure is then returned to the user mode application and gets displayed in the GUI.

Some special stuff

Undocumented information classes

I mixed the information and source codes from [2] and [4] and build some new classes to easily use the undocumented NtQuerySystemInformation function. There is a common base class NtSystemInformation from which the following two classes are derived:
  • NtSystemHandleInformation: read the systems handle table
  • NtSystemProcessInformation: read the systems process table
Of generic interest might be the NtSystemProcessInformation class. It provides a fast and easy to use method to get a list of all processes (PID and name) running on the machine without using the (slow) performance counter approach or using the psapi-dll.

Embedded dynamic loaded driver

I do not like the idea of having multiple files for a small application. However, FileObjectInfo actually consists of two components: the application executable and the kernel mode device driver. Help came from an article in the Microsoft System Journal (see [1]), which described a method to embed a device driver image into the resource section of an application.
On startup FileObjectInfo extracts the driver image from its ressources and writes it to a temporary file on the hard disk. It then registers and starts the driver and removes the temporary file. From now on the driver can be used normally. When FileObjectInfo is closed (an thus the driver is no longer used) it stops and unregisters the driver.
All functions for dynamically loading and unloading a driver are contained in the file "dynamic.cpp".

Addtional ideas

At the moment, FileObjectInfo (as its name implies) is restricted to show additional information for file objects only. However, the application as well as the driver can easily be expanded to support other object types. Maybe it could be expanded to show system data structures like WinDBG or SoftIce without having to actually use a debugger.

Resources

Notes

Compiling the sources

In order to make FileObjectInfo work on Windows 2000 and Windows NT, the device driver has to be built using the NT4 DDK. The supplied Visual C++ 6 workspace will work correctly, if you set the environment variable BASEDIR to the root directory of your NT4 DDK installation.
Note: As i did not get Visual C++ to recognize the dependencies between the two projects (driver and gui) right, you should build the driver first, then build the gui.

Installing and running FileObjectInfo

To install FileObjectInfo, just copy its executable "FileObjectInfo.exe" to a directory on your local hard disk. It will not run from a network locatiton nor will it run from a location where you don't have write access (it will create a temporary file in the same directory where it is installed).
As it has to register and start a kernel mode driver, you need administrative privileges to run FileObjectInfo.


WARNING: This is experimental software which uses undocumented functions, installs a kernel mode driver and peeks around in your systems internals. Although this software works very well for me, i can't guarantee it will work this way for every possible hardware/software kombination out there.
Be warned and don't blame me, if it bluescreens...

Version History

  • August 7, 2000
    • Initial posting
  • February 9, 2001
    • Enhanced GUI
    • Some minor bug fixes
    • Created a single source and executable for both NT 4 and NT 2000

Downloads

Download source and precompiled executable - 94 Kb
Download precompiled executable only - 28 Kb


Comments

  • Name (identifier) of a device

    Posted by aphillips on 05/04/2005 11:53pm

    I am trying to find the name of a device as stored in the registry under the "Identifier" value. For example given the device name "\device\CdRom0" I want the name for the device, which is stored in HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\Scsi\Scsi Port 3\Scsi Bus 0\Target Id 0\Logical Unit Id 0 on my machine. Any ideas?

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: August 20, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT When you look at natural user interfaces as a developer, it isn't just fun and games. There are some very serious, real-world usage models of how things can help make the world a better place – things like Intel® RealSense™ technology. Check out this upcoming eSeminar and join the panel of experts, both from inside and outside of Intel, as they discuss how natural user interfaces will likely be getting adopted in a wide variety …

  • Live Event Date: August 14, 2014 @ 2:00 p.m. ET / 11:00 a.m. PT Data protection has long been considered "overhead" by many organizations in the past, many chalking it up to an insurance policy or an extended warranty you may never use. The realities of today makes data protection a must-have, as we live in a data-driven society -- the digital assets we create, share, and collaborate with others on must be managed and protected for many purposes. Check out this upcoming eSeminar and join Seagate Cloud …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds