INFO: Creation and Destruction of File Objects
ID: Q120170
|
The information in this article applies to:
-
Microsoft Win32 Device Driver Kit (DDK) for Windows NT, versions 3.1, 3.5, 3.51
SUMMARY
Each time CreateFile() or OpenFile() is called to open a device, volume,
directory, or data file, the I/O manager creates a file object. A handle to
the file object is returned to the caller if the call succeeds. Subsequent
I/O calls using the handle are considered operations on the same file
object. Among the dispatch routines that a kernel-mode driver can supply,
there are a few related to the creation and destruction of the file
objects. This article discusses the use of the file object from the
driver's perspective and the related dispatch routines.
MORE INFORMATION
A pointer to the file object is passed to the driver in the current I/O
stack location of the IRP, at IrpSp->FileObject. Because I/O requests with
the same handle have the same file object, a driver can use the file-object
pointer to identify the I/O operations that belong to one open
instantiation of a device or file.
NOTE: A driver should not use the value stored in
Irp->Tail.Overlay.OriginalFileObject. This field is owned by the I/O
manager. It may not contain the valid file object pointer intended for the
driver.
Like other objects in Windows NT, each file object has an open handle count
and a reference count. The open handle count represents the number of
handles that have been opened to the file object. The reference count
represents the number of pointers to the object that are being used in the
system. For example, when a file object is first created and a handle is
returned to the caller of CreateFile, the file object's open handle count
is set to 1. Each time the handle is duplicated or inherited, the open
handle count is incremented. Each CloseHandle() call decrements the count.
On the other hand, each time the handle is used to send an I/O request, the
I/O manager calls the object manager to increment the file object's
reference count. The reference count is decremented when each operation is
completed.
IRP_MJ_CREATE
The dispatch routine for IRP_MJ_CREATE is called when a file object
associated with the device is created. This is typically because of a call
to CreateFile() in a user-mode program or because a higher-level driver is
layering itself over a lower-level driver. A driver is required to supply a
dispatch routine for IRP_MJ_CREATE. Please see the Windows NT DDK
documentation for details.
IRP_MJ_CLEANUP
The dispatch routine for IRP_MJ_CLEANUP is called when the last handle (in
the whole system) to a file object is closed. In other words, the open
handle count for the file object goes to 0. A driver that holds pending
IRPs internally must implement a routine for IRP_MJ_CLEANUP. When the
routine is called, the driver should cancel all the pending IRPs that
belong to the file object identified by the IRP_MJ_CLEAN call. In other
words, it should cancel all the IRPs that have the same file-object pointer
as the one supplied in the current I/O stack location of the IRP for the
IRP_MJ_CLEANUP call. Of course, IRPs belonging to other file objects should
not be canceled. Also, if an outstanding IRP is completed immediately, the
driver does not have to cancel it.
NOTE: The routine for IRP_MJ_CLEANUP and the cancel routines for individual
IRPs serve different purposes. A driver with long-term IRPs should
implement both. A cancel routine is called when the system attempts to
cancel a specific IRP. This can happen without an IRP_MJ_CLEANUP call. For
example, a user-mode thread gets an file handle from another thread and
issues I/O requests with the handle. If the thread terminates with some
requests pending, the system tries to cancel the pending IRPs that belong
to the terminating thread. In this case, the cancel routines for these IRPs
are called; but no IRP_MJ_CLEANUP request is issued. Conversely,
IRP_MJ_CLEANUP can be issued with no cancel routines being called. As
explained earlier, this happens when the last handle to a file object is
closed. In this case, even if there are pending IRPs associated with the
file object, the system does not try to cancel them. The driver handles the
IRPs appropriately in the IRP_MJ_CLEANUP routine.
IRP_MJ_CLOSE
The IRP_MJ_CLOSE dispatch routine is called when a file object opened on
the driver is being removed from the system; that is, all file object
handles have been closed and the reference count of the file object is down
to 0. Certain types of drivers do not need to handle IRP_MJ_CLOSE, mainly
drivers of devices that must be available for the system to continue
running. In general, this is the place that a driver should "undo" whatever
has been done in the routine for IRP_MJ_CREATE.
As discussed earlier, the reference count is different from the open handle
count. The reference count can be a non-zero value when the open handle
count goes to 0. For example, if a user-mode program closes its last handle
to a file object while there are still I/O requests outstanding, the
related driver's IRP_MJ_CLEANUP routine is called because the open handle
reaches 0, but the IRP_MJ_CLOSE routine is not called because there are
still pointer references to the file object being used. The close routine
is not called until all of the outstanding I/O requests are completed.
Apparently, if the driver performs as planned in the IRP_MJ_CLEANUP
routine, as discussed earlier, the IRP_MJ_CLOSE routine is called at the
right time.
Additional query words:
open-handle
Keywords :
Version : WINNT:3.1,3.5,3.51;
Platform : winnt
Issue type : kbinfo
Last Reviewed: March 1, 1999