Life Cycle of a File Object
A file object is created each time a device is opened. Each file object represents a single use of an individual file, and maintains state information for that use (such as current file offset). When the I/O Manager creates and opens a file object, it creates a handle to refer to the object. The IRP_MJ_CREATE, IRP_MJ_CLEANUP, and IRP_MJ_CLOSE requests define the life cycle of a file object.
IRP_MJ_CREATE Requests
An IRP_MJ_CREATE request notifies the driver that a new file object has been created. The I/O Manager typically sends an IRP_MJ_CREATE request when a user-mode application calls the CreateFile function or a kernel-mode driver calls the ZwCreateFile routine.
In an IRP_MJ_CREATE request, the current I/O stack location contains a FileObject structure, which identifies the file object to open. The FileObject structure specifies:
· The name of the file to open in the FileObject->FileName field.
· Two pointers for driver use in the FileObject->FsContext and FileObject‑>FsContext2 fields.
Note: In a WDM device stack, only the functional device object (FDO) can use the two context pointers. File system drivers use special functions to share these fields among multiple drivers.
IRP_MJ_CREATE requests arrive in the context of the thread and the process that opened or created the file. A driver can record per-caller information, if required.
In response to a create request, the operating system checks access rights as follows:
· If the request does not include a file name, the operating system checks the rights against the ACL for the device object opened by name.
· If the request includes a file name, the operating system checks security only if the FILE_DEVICE_SECURE_OPEN characteristic is set in the DeviceObject‑>Characteristics field. Otherwise, the driver is responsible for checking security.
If the request succeeds, the operating system saves the granted rights in the handle to the object for use in subsequent I/O requests. For detailed information on driver security, see the WDK.
IRP_MJ_CLEANUP Requests
An IRP_MJ_CLEANUP request notifies a driver that the last handle to a file object has been closed. This request does not indicate that the file object has been deleted.
The I/O Manager sends an IRP_MJ_CLEANUP request for a file object after the last handle to the object is closed. When a driver receives an IRP_MJ_CLEANUP request, the driver must complete any pending IRPs for the specified file object. After the IRPs have been completed, the I/O Manager destroys the file object. While the IRPs are pending, the I/O Manager cannot delete the object.
IRP_MJ_CLEANUP requests arrive in the context of the caller that attempts to close the last handle. If the driver recorded any information about the caller when the IRP_MJ_CREATE request arrived, it should release that information when it processes the IRP_MJ_CLEANUP request. However, if the file handle has been duplicated, the context for the IRP_MJ_CLEANUP request might not be the same as that for the corresponding IRP_MJ_CREATE request. Consequently, driver writers must be careful to determine the appropriate context when using process information during cleanup operations.
For example, an application can call the DuplicateHandle() function to duplicate a file handle into another process. If the new handle is closed last, after all handles in the original process, the driver will receive an IRP_MJ_CLEANUP request on a handle in the new process context. The context still represents the caller, but it is not the same as the original caller that created the file object.
IRP_MJ_CLOSE Requests
An IRP_MJ_CLOSE request notifies a driver that a file object has been deleted.
The I/O Manager sends an IRP_MJ_CLOSE request for a file object when both of the following are true:
· All handles to the file object are closed.
· No outstanding references to the object, such as those caused by a pending IRP, remain.
Unlike IRP_MJ_CREATE and IRP_MJ_CLEANUP requests, an IRP_MJ_CLOSE request does not arrive in the context of the caller.
In response to an IRP_MJ_CLOSE request, a driver should reverse whatever actions it performed in response to the corresponding IRP_MJ_CREATE request. Additional tasks depend on the design of the driver and the type of hardware it supports.