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 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.
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
- [1] James Finnegan, Pop Open a Privileged Set of APIs with Windows NT Kernel Mode Drivers, Microsoft System Journal, March 1998
- [2] Sven B. Schreiber, Inside Windows NT System Data, Windows Developer Journal, November 1999
- [3] Windows NT DDK, can be freely downloaded from Microsofts web site
- [4] Fred Forester, EnTeHandle article on CodeGuru
- [5] System Internals source code, www.sysinternals.com
- [6] Multi column tree control by David Lantsman, published here
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