NtUserMessageCall 내부에서의 메세지 처리
함수원형
__declspec(naked) LRESULT __stdcall NtUserMessageCall( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, ULONG_PTR xParam, DWORD xpfnProc, BOOL bAnsi ) |
NtUserMessageCall 은… SendMessage 에 해당하는 시스템 서비스던가…? 기억력 감퇴;;
어찌되었든, NtUserMessageCall 에서의 메시지 처리는 xpfnProc 인자를 통해 이뤄집니다.
해당 인자는 Message를 처리해야 하는 win32k 의 처리 procedure 를 가리킵니다.
확인을 해보면,
가령 NtUserMessageCall 을 호출하는 RealDefWindowProcWorker 의 경우
.text:77D7AEB2 loc_77D7AEB2: ; CODE XREF: RealDefWindowProcWorker(x,x,x,x,x)-81C1j .text:77D7AEB2 ; RealDefWindowProcWorker(x,x,x,x,x)+B2C9j ... .text:77D7AEB2 push [ebp+lpMultiByteStr] .text:77D7AEB5 push 2B0h // FNID_SENDMESSAGEEX .text:77D7AEBA push 0 .text:77D7AEBC push 0 .text:77D7AEBE push [ebp+hMem] .text:77D7AEC1 push 128h .text:77D7AEC6 .text:77D7AEC6 loc_77D7AEC6: ; CODE XREF: RealDefWindowProcWorker(x,x,x,x,x)-81CAj .text:77D7AEC6 ; RealDefWindowProcWorker(x,x,x,x,x)+3029Fj .text:77D7AEC6 push ebx .text:77D7AEC7 jmp loc_77D4C756 .text:77D4C756 loc_77D4C756: ; CODE XREF: RealDefWindowProcWorker(x,x,x,x,x)+2FE07j .text:77D4C756 call ds:_gapfnScSendMessage ; NtUserMessageCall(x,x,x,x,x,x,x) |
xpfnProc 에 0x2B0h 값
.text:77D4B2A5 loc_77D4B2A5: ; CODE XREF: RealDefWindowProcWorker(x,x,x,x,x)+38j .text:77D4B2A5 cmp edi, 400h .text:77D4B2AB push [ebp+lpMultiByteStr] ; int .text:77D4B2AE push 29Eh // FNID_DEFWINDOWPROC .text:77D4B2B3 push 0 ; int .text:77D4B2B5 push [ebp+hMem] ; hMem .text:77D4B2B8 push dword ptr [ebp+WideCharStr] ; int .text:77D4B2BB push edi ; int .text:77D4B2BC push eax ; int .text:77D4B2BD jnb loc_77D7AB10 .text:77D4B2C3 xor ecx, ecx .text:77D4B2C5 mov cl, ds:_MessageTable[edi] .text:77D4B2CB and ecx, 3Fh ; int .text:77D4B2CE call ds:_gapfnScSendMessage[ecx*4] ; NtUserMessageCall(x,x,x,x,x,x,x) |
xpfnProc 에 0x29Eh 값
위의 두 부분에서 NtUserMessageCall 을 호출하고 있으며,
이때, NtUserMessageCall 에서는 이를 다음과 같이 처리합니다.
bf834b50 8b4d1c mov ecx,dword ptr [ebp+1Ch] // xpfnProc bf834b53 83c106 add ecx,6 bf834b56 83e11f and ecx,1Fh bf834b59 ff7518 push dword ptr [ebp+18h] bf834b5c 50 push eax bf834b5d ff7510 push dword ptr [ebp+10h] bf834b60 ff750c push dword ptr [ebp+0Ch] bf834b63 ff7508 push dword ptr [ebp+8] bf834b66 a158859abf mov eax,dword ptr [win32k!gpsi (bf9a8558)] bf834b6b ff54880c call dword ptr [eax+ecx*4+0Ch] |
위의 어셈 코드에서, 호출되는 procedure 의 주소를 보면,
bc5d0650 00200031 bc5d0654 00000000 bc5d0658 00000155 bc5d065c bf90ade2 win32k!xxxWrapSBWnd16Proc bc5d0660 bf80f420 win32k!xxxWrapRealDefWindowProc bc5d0664 bf86a712 win32k!xxxWrapMenuWindowProc bc5d0668 bf915448 win32k!xxxWrapDesktopWndProc bc5d066c bf80f420 win32k!xxxWrapRealDefWindowProc >> (29E+6) & 1F bc5d0670 bf80f420 win32k!xxxWrapRealDefWindowProc bc5d0674 bf8cb6f2 win32k!xxxWrapSwitchWndProc bc5d0678 bf942a7c win32k!xxxUnusedFunctionId bc5d067c bf942a7c win32k!xxxUnusedFunctionId bc5d0680 bf942a7c win32k!xxxUnusedFunctionId bc5d0684 bf942a7c win32k!xxxUnusedFunctionId bc5d0688 bf942a7c win32k!xxxUnusedFunctionId bc5d068c bf942a7c win32k!xxxUnusedFunctionId bc5d0690 bf942a7c win32k!xxxUnusedFunctionId bc5d0694 bf942a7c win32k!xxxUnusedFunctionId bc5d0698 bf942a7c win32k!xxxUnusedFunctionId bc5d069c bf90b699 win32k!fnHkINLPCWPEXSTRUCT bc5d06a0 bf92f155 win32k!fnHkINLPCWPRETEXSTRUCT bc5d06a4 bf942a7c win32k!xxxUnusedFunctionId bc5d06a8 bf942a7c win32k!xxxUnusedFunctionId bc5d06ac bf942a7c win32k!xxxUnusedFunctionId bc5d06b0 bf942a7c win32k!xxxUnusedFunctionId bc5d06b4 bf831785 win32k!xxxWrapSendMessage >> (2B0+6) & 1F bc5d06b8 bf8a003f win32k!xxxSendMessageFF bc5d06bc bf82eedc win32k!xxxSendMessageEx bc5d06c0 bf89ef23 win32k!xxxWrapCallWindowProc bc5d06c4 bf8622d9 win32k!xxxWrapSendMessageBSM bc5d06c8 bf942a7c win32k!xxxUnusedFunctionId bc5d06cc bf942a7c win32k!xxxUnusedFunctionId bc5d06d0 bf82f3dd win32k!xxxWrapSendNotifyMessage bc5d06d4 bf82f461 win32k!xxxWrapSendMessageCallback bc5d06d8 bf942a7c win32k!xxxUnusedFunctionId bc5d06dc bf90a41b win32k!xxxSBWndProc bc5d06e0 bf80d027 win32k!xxxDefWindowProc bc5d06e4 bf865f56 win32k!xxxMenuWindowProc bc5d06e8 bf87fac4 win32k!xxxDesktopWndProc bc5d06ec bf80d027 win32k!xxxDefWindowProc bc5d06f0 bf80d027 win32k!xxxDefWindowProc |
위와 같이 메시지를 처리하는 실제 procedure 들의 주소가 담긴 테이블을 확인할 수 있으며,
RealDefWindowProcWorker 가 호출하는 0x2B0, 0x29E 인자에 대응하는 실제 procedure 를 찾을 수 있습니다.
다음은 xpfnProc에 대응하는 FNID 값입니다.
#define FNID_START 0x0000029A #define FNID_WNDPROCSTART 0x0000029A #define FNID_SCROLLBAR 0x0000029A // xxxSBWndProc; #define FNID_ICONTITLE 0x0000029B // xxxDefWindowProc; #define FNID_MENU 0x0000029C // xxxMenuWindowProc; #define FNID_DESKTOP 0x0000029D // xxxDesktopWndProc; #define FNID_DEFWINDOWPROC 0x0000029E // xxxDefWindowProc; #define FNID_WNDPROCEND 0x0000029E // see PatchThreadWindows #define FNID_CONTROLSTART 0x0000029F #define FNID_BUTTON 0x0000029F // No server side proc #define FNID_COMBOBOX 0x000002A0 // No server side proc #define FNID_COMBOLISTBOX 0x000002A1 // No server side proc #define FNID_DIALOG 0x000002A2 // No server side proc #define FNID_EDIT 0x000002A3 // No server side proc #define FNID_LISTBOX 0x000002A4 // No server side proc #define FNID_MDICLIENT 0x000002A5 // No server side proc #define FNID_STATIC 0x000002A6 // No server side proc #define FNID_IME 0x000002A7 // No server side proc #define FNID_CONTROLEND 0x000002A7 #define FNID_HKINLPCWPEXSTRUCT 0x000002A8 #define FNID_HKINLPCWPRETEXSTRUCT 0x000002A9 #define FNID_DEFFRAMEPROC 0x000002AA // No server side proc #define FNID_DEFMDICHILDPROC 0x000002AB // No server side proc #define FNID_MB_DLGPROC 0x000002AC // No server side proc #define FNID_MDIACTIVATEDLGPROC 0x000002AD // No server side proc #define FNID_SENDMESSAGE 0x000002AE #define FNID_SENDMESSAGEFF 0x000002AF #define FNID_SENDMESSAGEEX 0x000002B0 #define FNID_CALLWINDOWPROC 0x000002B1 #define FNID_SENDMESSAGEBSM 0x000002B2 #define FNID_SWITCH 0x000002B3 // Just used by GetTopMostInserAfter #define FNID_TOOLTIP 0x000002B4 #define FNID_END 0x000002B4 |
WinDBG // Service Descriptor Table 확인하기
KD> !osrexts.sst

IRP Major Function Codes
Windows Driver Kit: Kernel-Mode Driver Architecture
IRP Major Function Codes
Each driver-specific I/O stack location (IO_STACK_LOCATION) for every IRP contains a major function code (IRP_MJ_XXX), which tells the driver what operation it or the underlying device driver should carry out to satisfy the I/O request. Each kernel-mode driver must provide dispatch routines for the major function codes that it must support.
The specific operations a driver carries out for a given IRP_MJ_XXX code depend somewhat on the underlying device, particularly for IRP_MJ_DEVICE_CONTROL and IRP_MJ_INTERNAL_DEVICE_CONTROL requests. For example, the requests sent to a keyboard driver are necessarily somewhat different from those sent to a disk driver. However, the I/O manager defines the parameters and I/O stack location contents for each system-defined major function code.
Every higher-level driver must set up the appropriate I/O stack location in IRPs for the next-lower-level driver and call IoCallDriver, either with each input IRP, or with a driver-created IRP (if the higher-level driver holds on to the input IRP). Consequently, every intermediate driver must supply a dispatch routine for each major function code that the underlying device driver handles. Otherwise, a new intermediate driver will "break the chain" whenever an application or still higher-level driver attempts to send an I/O request down to the underlying device driver.
File system drivers also handle a required subset of system-defined IRP_MJ_XXX function codes, some with subordinate IRP_MN_XXX function codes.
Drivers handle IRPs set with some or all of the following major function codes:
IRP_MJ_INTERNAL_DEVICE_CONTROL
The input and output parameters described in this section are the function-specific parameters in the IRP.
IRP_MJ_CREATE
Every kernel-mode driver must handle IRP_MJ_CREATE requests in a DispatchCreate or DispatchCreateClose routine.
When Sent
The operating system sends an IRP_MJ_CREATE request to open a handle to a file object or device object. For example, when a driver calls ZwCreateFile, the operating system sends an IRP_MJ_CREATE request to perform the actual open operation.
Input Parameters
The Parameters.Create.SecurityContext member points to an IO_SECURITY_CONTEXT structure that describes the security context for the request.
The Parameters.Create.Options member is a ULONG value that describes the options that are used when opening the handle. The high 8 bits correspond to the value of the CreateDisposition parameter of ZwCreateFile, and the low 24 bits correspond to the value of the CreateOptions parameter of ZwCreateFile.
The Parameters.Create.ShareAccess member is a USHORT value that describes the type of share access. This value corresponds to the value of the ShareAccess parameter of ZwCreateFile.
The Parameters.Create.FileAttributes and Parameters.Create.EaLength members are reserved for use by file systems and file system filter drivers. For more information, see the IRP_MJ_CREATE topic in the Installable File System (IFS) documentation.
Output Parameters
None
Operation
Most device and intermediate drivers set STATUS_SUCESS in the I/O status block of the IRP and complete the create request, but drivers can optionally use their DispatchCreate routine to reserve resources for any subsequent I/O requests for that handle. For example, the system serial driver maps its paged-out code and allocates any resources that are necessary to handle subsequent I/O requests for the user-mode thread that is attempting to open the device for input and output.
IRP_MJ_PNP
All drivers must be prepared to service IRP_MJ_PNP requests in a DispatchPnP routine.
When Sent
The PnP manager sends IRP_MJ_PNP requests during enumeration, resource rebalancing, and any other time Plug and Play activity occurs on the system. Drivers can also send certain IRP_MJ_PNP requests, depending on the minor function code.
Input Parameters
Depends on the value at MinorFunction in the current I/O stack location of the IRP. Every IRP_MJ_PNP request specifies a minor function code that identifies the requested PnP action.
Output Parameters
Depends on the value at MinorFunction in the current I/O stack location of the IRP.
Operation
See Plug and Play Minor IRPs for detailed information about IRP_MJ_PNP requests.
IRP_MJ_POWER
All drivers must be prepared to service IRP_MJ_POWER requests in a DispatchPower routine.
When Sent
The power manager or a driver can send IRP_MJ_POWER requests at any time the operating system is running.
Input Parameters
Depends on the value at MinorFunction in the current I/O stack location of the IRP. Every IRP_MJ_POWER request specifies a minor function code that identifies the requested power action.
Output Parameters
Depends on the value at MinorFunction in the current I/O stack location of the IRP.
Operation
See Power Management Minor IRPs for detailed information about IRP_MJ_POWER requests.
IRP_MJ_READ
Every device driver that transfers data from its device to the system must handle read requests in a DispatchRead or DispatchReadWrite routine, as must any higher-level driver layered over such a device driver.
When Sent
Any time following the successful completion of a create request.
Possibly, a user-mode application or Win32 component with a handle for the file object representing the target device object has requested a data transfer from the device. Possibly, a higher-level driver has created and set up the read IRP.
Input Parameters
The driver's I/O stack location in the IRP indicates how many bytes to transfer at Parameters.Read.Length.
Some drivers use the value at Parameters.Read.Key to sort incoming read requests into a driver-determined order in the device queue or in a driver-managed internal queue of IRPs. Certain types of drivers also use the value at Parameters.Read.ByteOffset, which indicates the starting offset for the transfer operation.
Output Parameters
Depending on whether the underlying device driver sets up the target device object's Flags with DO_BUFFERED_IO or with DO_DIRECT_IO, data is transferred into one of the following:
- The buffer at Irp->AssociatedIrp.SystemBuffer if the driver uses buffered I/O
- The buffer described by the MDL at Irp->MdlAddress if the underlying device driver uses direct I/O (DMA or PIO)
Operation
On receipt of a read request, a higher-level driver sets up the I/O stack location in the IRP for the next-lower driver, or it creates and sets up additional IRPs for one or more lower drivers. It can set up its IoCompletion routine, which is optional for the input IRP but required for driver-created IRPs, by calling IoSetCompletionRoutine. Then, the driver passes the request on to the next-lower driver with IoCallDriver.
On receipt of a read request, a device driver transfers data from its device to system memory. The device driver sets the Information field of the I/O status block to the number of bytes transferred when it completes the IRP.
IRP_MJ_WRITE
Every device driver that transfers data from the system to its device must handle write requests in a DispatchWrite or DispatchReadWrite routine, as must any higher-level driver layered over such a device driver.
When Sent
Any time following the successful completion of a create request.
Possibly, a user-mode application or Win32 component with a handle for the file object representing the target device object has requested a data transfer to the device. Possibly, a higher-level driver has created and set up the write IRP.
Input Parameters
The driver's I/O stack location in the IRP indicates how many bytes to transfer at Parameters.Write.Length.
Some drivers use the value at Parameters.Write.Key to sort incoming write requests into a driver-determined order in the device queue or in a driver-managed internal queue of IRPs. Certain types of drivers also use the value at Parameters.Write.ByteOffset, which indicates the starting offset for the transfer operation.
Depending on whether the underlying device driver sets up the target device object's Flags with DO_BUFFERED_IO or with DO_DIRECT_IO, data is transferred from one of the following:
- The buffer at Irp->AssociatedIrp.SystemBuffer, if the driver uses buffered I/O
- The buffer described by the MDL at Irp->MdlAddress, if the underlying device driver uses direct I/O (DMA or PIO)
Output Parameters
None
Operation
On receipt of a write request, a higher-level driver sets up the I/O stack location in the IRP for the next-lower driver, or it creates and sets up additional IRPs for one or more lower drivers. It can set up its IoCompletion routine, which is optional for the input IRP but required for driver-created IRPs, by calling IoSetCompletionRoutine. Then, the driver passes the request on to the next-lower driver with IoCallDriver.
On receipt of a write request, a device driver transfers data from system memory to its device. The device driver sets the Information field of the I/O status block to the number of bytes transferred when it completes the IRP.
IRP_MJ_FLUSH_BUFFERS
Drivers of devices with internal caches for data and drivers that maintain internal buffers for data must handle this request in a DispatchFlushBuffers routine.
When Sent
Receipt of a flush request indicates that the driver should flush the device's cache or its internal buffer, or, possibly, should discard the data in its internal buffer.
Input Parameters
None
Output Parameters
None
Operation
The driver transfers any data currently cached in the device or held in the driver's internal buffers before completing the flush request. The driver of an input-only device that buffers data internally might simply discard the currently buffered device data before completing the flush IRP, depending on the nature of its device.
IRP_MJ_QUERY_INFORMATION
Drivers can optionally handle an IRP_MJ_QUERY_INFORMATION request.
When Sent
The operating system sends an IRP_MJ_QUERY_INFORMATION request to obtain metadata about a file or file handle. For example, when a driver calls ZwQueryInformationFile, the operating system sends an IRP_MJ_QUERY_INFORMATION request.
Input Parameters
The Parameters.QueryFile.FileInformationClass member is a FILE_INFORMATION_CLASS constant that specifies the type of metadata to provide. For more information about the types of metadata, see the FileInformationClass parameter of the ZwQueryInformationFile routine.
The Parameters.QueryFile.Length member specifies the length of the buffer that the AssociatedIrp.SystemBuffer member points to.
Output Parameters
The AssociatedIrp.SystemBuffer member points to the buffer where the driver supplies the requested information. The value of Parameters.QueryFile.FileInformationClass determines the format of the metadata (a FILE_XXX_INFORMATION structure) to return. For more information about the formats of metadata, see the FileInformation parameter of ZwQueryInformationFile.
Operation
Drivers are not required to handle this request, and drivers that do are not required to handle every possible value of Parameters.QueryFile.FileInformationClass. The driver's dispatch routine should return an error code such as STATUS_INVALID_DEVICE_REQUEST for any values that it does not handle.
Not all of the possible values of FILE_INFORMATION_CLASS can occur. For a complete list of the possible values, see the IRP_MJ_QUERY_INFORMATION topic in the Installable File System (IFS) documentation.
IRP_MJ_SET_INFORMATION
Device drivers can optionally handle an IRP_MJ_SET_INFORMATION request.
When Sent
The operating system sends an IRP_MJ_SET_INFORMATION request to set metadata about a file or file handle. For example, when a driver calls ZwSetInformationFile, the operating system sends an IRP_MJ_SET_INFORMATION request.
Input Parameters
The Parameters.SetFile.FileInformationClass member is a FILE_INFORMATION_CLASS constant that specifies the type of metadata to set. For more information about the types of metadata, see the FileInformationClass parameter of ZwSetInformationFile.
The Parameters.SetFile.Length member specifies the length of the buffer that the AssociatedIrp.SystemBuffer member points to.
AssociatedIrp.SystemBuffer points to the buffer that contains the new information setting. The value of Parameters.SetFile.FileInformationClass determines the format of the data (a FILE_XXX_INFORMATION structure) to return. For more information about the formats of metadata, see the FileInformation parameter of ZwSetInformationFile.
Output Parameters
None
Operation
Drivers are not required to handle this request, and drivers that do are not required to handle every possible value of Parameters.SetFile.FileInformationClass. The driver's dispatch routine should return an error code such as STATUS_INVALID_DEVICE_REQUEST for any values that it does not handle.
Not all of the possible values of FILE_INFORMATION_CLASS can occur. For a complete list of the possible values, see the IRP_MJ_SET_INFORMATION topic in the Installable File System (IFS) documentation.
IRP_MJ_DEVICE_CONTROL
Every driver whose device objects belong to a particular device type (see Specifying Device Types) is required to support this request in a DispatchDeviceControl routine, if a set of system-defined I/O control codes (IOCTLs) exists for the type.
Higher-level drivers usually pass these requests on to an underlying device driver. Each device driver in a driver stack is assumed to support this request, along with a set of device type-specific, public or private IOCTLs. For more information about IOCTLs for specific device types, see device type-specific documentation in the Microsoft Windows Driver Kit (WDK).
When Sent
Any time following the successful completion of a create request.
Input Parameters
The I/O control code is contained at Parameters.DeviceIoControl.IoControlCode in the driver's I/O stack location of the IRP.
Other input parameters depend on the I/O control code's value. For more information, see Buffer Descriptions for I/O Control Codes.
Output Parameters
Output parameters depend on the I/O control code's value. For more information, see Buffer Descriptions for I/O Control Codes.
Operation
A driver receives this I/O control code because user-mode thread has called the Microsoft Win32 DeviceIoControl function, or a higher-level kernel-mode driver has set up the request. Possibly, a user-mode driver has called DeviceIoControl, passing in a driver-defined (also called private) I/O control code, to request device- or driver-specific support from a closely coupled, kernel-mode device driver.
On receipt of a device I/O control request, a higher-level driver usually passes the IRP on to the next-lower driver. However, there are some exceptions to this practice. For example, a class driver that has stored configuration information obtained from the underlying port driver might complete certain IOCTL_XXX requests without passing the IRP down to the corresponding port driver.
On receipt of a device I/O control request, a device driver examines the I/O control code to determine how to satisfy the request. For most public I/O control codes, device drivers transfer a small amount of data to or from the buffer at Irp->AssociatedIrp.SystemBuffer.
For general information about I/O control codes for IRP_MJ_DEVICE_CONTROL or IRP_MJ_INTERNAL_DEVICE_CONTROL requests, see Using I/O Control Codes. See also Device Type-specific I/O Requests.
IRP_MJ_INTERNAL_DEVICE_CONTROL
In general, any replacement for an existing driver that supports internal device control requests should handle this request in a DispatchInternalDeviceControl routine. Such a driver must support at least the same set of internal I/O control codes as the driver it replaces. Otherwise, existing higher-level drivers might not work with the new driver.
Drivers that replace certain lower-level system drivers are required to handle this request. For example, a replacement for the system parallel port driver must continue to support existing parallel class drivers. Note that certain system drivers that handle this request cannot be replaced, in particular, the system-supplied SCSI and video port drivers.
When Sent
Any time after the successful completion of a create request.
Input Parameters
The I/O control code is contained at Parameters.DeviceIoControl.IoControlCode in the I/O stack location of the IRP.
Other input parameters depend on the I/O control code's value. For more information, see Buffer Descriptions for I/O Control Codes.
Output Parameters
Output parameters depend on the I/O control code's value. For more information, see Buffer Descriptions for I/O Control Codes.
Operation
Drivers receive IRP_MJ_INTERNAL_DEVICE_CONTROL requests when another driver calls either IoBuildDeviceIoControlRequest or IoAllocateIrp to create a request.
This I/O control code has been defined for communication between paired and layered kernel-mode drivers, such as one or more class drivers layered over a port driver. The higher-level driver sets up IRPs with device- or driver-specific I/O control codes, requesting support from the next-lower driver.
The requested operation is device- or driver-specific.
For general information about I/O control codes for IRP_MJ_DEVICE_CONTROL or IRP_MJ_INTERNAL_DEVICE_CONTROL requests, see Using I/O Control Codes. See also Device Type-specific I/O Requests.
IRP_MJ_SYSTEM_CONTROL
All drivers must provide a DispatchSystemControl routine that handles IRP_MJ_SYSTEM_CONTROL requests, which are sent by the kernel-mode component of Windows Management Instrumentation (WMI).
When Sent
The WMI kernel-mode component can send an IRP_MJ_SYSTEM_CONTROL request any time following a driver's successful registration as a supplier of WMI data. WMI IRPs typically are sent when a user-mode data consumer has requested WMI data.
Input Parameters
Depends on the value at MinorFunction in the current I/O stack location of the IRP. Every IRP_MJ_SYSTEM_CONTROL request specifies a minor function code that identifies the requested WMI action.
Output Parameters
Depends on the value at MinorFunction in the current I/O stack location of the IRP.
Operation
All drivers must support IRP_MJ_SYSTEM_CONTROL requests by supplying a DispatchSystemControl routine.
Drivers that support Windows Management Instrumentation (WMI) must handle IRP_MJ_SYSTEM_CONTROL requests by processing the minor function codes associated with this major function code. For information about the WMI minor function codes, see WMI Minor IRPs.
Drivers that do not support WMI by registering as a WMI data provider must pass IRP_MJ_SYSTEM_CONTROL requests to the next lower driver.
IRP_MJ_CLEANUP
Drivers that maintain process-specific context information must handle cleanup requests in DispatchCleanup routines.
When Sent
Receipt of this request indicates that the last handle for a file object that is associated with the target device object has been closed (but, due to outstanding I/O requests, might not have been released).
Input Parameters
None
Output Parameters
None
Operation
This IRP is sent in the context of the process that closed the file object handle. Therefore, the driver should release process-specific resources, such as user memory, that the driver previously locked or mapped.
If the driver's device objects were set up as exclusive, so that only a single thread can use the device at a time, the driver must complete every IRP that is currently queued to the target device object and set STATUS_CANCELLED in each IRP's I/O status block.
Otherwise, the driver must cancel and complete only the currently queued IRPs that are associated with the file object handle that is being released. (A pointer to the file object is located in the FileObject member of the driver's IO_STACK_LOCATION of the IRP.) After canceling these queued IRPs, the driver completes the cleanup IRP and sets STATUS_SUCCESS in its I/O status block.
For more information about handling this request, see DispatchCleanup Routines.
IRP_MJ_CLOSE
Every driver must handle close requests in a DispatchClose routine, with the possible exception of a driver whose device cannot be disabled or removed from the machine without bringing down the system. A disk driver whose device holds the system page file is an example of such a driver. Note that the driver of such a device also cannot be unloaded dynamically.
When Sent
Receipt of this request indicates that the last handle of the file object that is associated with the target device object has been closed and released. All outstanding I/O requests have been completed or canceled.
Input Parameters
None
Output Parameters
None
Operation
Many device and intermediate drivers merely set STATUS_SUCCESS in the I/O status block of the IRP and complete the close request. However, what a given driver does on receipt of a close request depends on the driver's design. In general, a driver should undo whatever actions it takes on receipt of the IRP_MJ_CREATE request. Device drivers whose device objects are exclusive, such as a serial driver, also can reset the hardware on receipt of a close request.
The IRP_MJ_CLOSE request is not necessarily sent in the context of the process that closed the file object handle. If the driver must release process-specific resources, such as user memory, that the driver previously locked or mapped, it must do so in response to an IRP_MJ_CLEANUP request.
The IRP_MJ_CLOSE request will always be sent at PASSIVE_LEVEL.
IRP_MJ_SHUTDOWN
Drivers of mass-storage devices that have internal caches for data must handle this request in a DispatchShutdown routine. Drivers of mass-storage devices and intermediate drivers layered over them also must handle this request if an underlying driver maintains internal buffers for data.
When Sent
Receipt of a shutdown request indicates that a file system driver is sending notice that the system is being shut down.
One or more file system drivers can send such a lower-level driver more than one shutdown request when a user logs off or when the system is being shut down for some other reason.
Input Parameters
None
Output Parameters
None
Operation
The driver must complete the transfer of any data currently cached in the device or held in the driver's internal buffers before completing the shutdown request.
A driver does not receive an IRP_MJ_SHUTDOWN request for a device object unless it registers to do so with either IoRegisterShutdownNotification or IoRegisterLastChanceShutdownNotification.