I/O Request Packet

 5  I/O Request Packet

5.1     
    I/O    ,          :IRP(I/O request packet)  IO_STACK_LOCATION

5.1.1 IRP    
     windbg      IRP   :

nt!_IRP
   +0x000 Type             : Int2B
   +0x002 Size             : Uint2B
   +0x004 MdlAddress       : Ptr32 _MDL
   +0x008 Flags            : Uint4B
   +0x00c AssociatedIrp    : 
   +0x010 ThreadListEntry  : _LIST_ENTRY
   +0x018 IoStatus         : _IO_STATUS_BLOCK
   +0x020 RequestorMode    : Char
   +0x021 PendingReturned  : UChar
   +0x022 StackCount       : Char
   +0x023 CurrentLocation  : Char
   +0x024 Cancel           : UChar
   +0x025 CancelIrql       : UChar
   +0x026 ApcEnvironment   : Char
   +0x027 AllocationFlags  : UChar
   +0x028 UserIosb         : Ptr32 _IO_STATUS_BLOCK
   +0x02c UserEvent        : Ptr32 _KEVENT
   +0x030 Overlay          : 
   +0x038 CancelRoutine    : Ptr32     void 
   +0x03c UserBuffer       : Ptr32 Void
   +0x040 Tail             : 

MdlAddress      user-mode buffer   MDL(memory descriptor list),      “direct I/O”。
       device object   flags       DO_DIRECT_IO  :
(1) I/O    IRP_MJ_READ   IRP_MJ_WRITE     MDL。
(2) I/O    IRP_MJ_DEVICE_CONTROL     control     METHOD_IN_DIRECT   METHOD_OUT_DIRECT,   MDL。
MDL    user-mode virtual buffer        physical address,driver           user-mode buffer。
 
AssociatedIrq     union   ,      :
union {
        struct _IRP *MasterIrp;                                 //   IRP   associate IRP,    master IRP
        LONG IrpCount;                                          //   IRP   master IRP,    associate IRP    
        PVOID SystemBuffer;                                     //   IRP   master IRP,    system buffer
} AssociatedIrp;                                                //     user-mode buffer       。

AssociatedIrq.SystemBuffer    kernel-mode nonpaged   data buffer   ,        :
(1)   IRP_MJ_READ   IRP_MJ_WRITE    ,       device object   flags     DO_BUFFERED_IO
(2)   IRP_MJ_DEVICE_CONTROL    ,   I/O control code      buffer。   WriteFile()    DeviceIoControl()      data
I/O manager    user-mode data buffer   kernel-mode data buffer  。
(3)      ,I/O manager    kernel-mode data buffer   user-mode data buffer  。
IoStatus       ,      :Status   Information。IoStatus.Status    NTSTATUS  ,  IoStatus.Information   ULONG   ,
            IRP          。        :Information          bytes  (    IRP_MJ_READ    )。
        :
typedef struct _IO_STATUS_BLOCK
{
        union {
                ULONG Status;
                PVOID Pointer;
        };
        ULONG Information;
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;

RequestorMode   UserMode    KernelMode      。
CancelRoutine   driver   IRP cancel routine    ,     IoSetCancelRoutine()   ,          。
UserBuffer     user-mode   data buffer,  kernel-mode data buffer       。
    Tail   ,     union   ,   Tail     ,      :

union
{
	struct
	{
		union
		{	
			KDEVICE_QUEUE_ENTRY DeviceQueueEntry;
			struct
			{
				PVOID DriverContext[4];
			};
		};
	
		PETHREAD thread;
		PCHAR AuxiliaryBuffer;

		struct
		{
			LIST_ENTRY ListEntry;
			union
			{
				struct _IO_STACK_LOCATION *CurrentStackLocation;
				ULONG PacketType;
			};
		};

		PFILE_OBJECT OriginalFileObject;
	} Overlay;
	
	KAPC Apc;
	PVOID CompletionKey;

} Tail;

Tail union       :Overlay,Apc    CompletionKey。

5.1.2 I/O stack
  kernel-mode        IRP  ,          IO_STACK_LOCATION      ,        stack location。
   stack location     IRP   type   parameter   ,     completion routine   ,      :

nt!_IO_STACK_LOCATION
   +0x000 MajorFunction    : UChar
   +0x001 MinorFunction    : UChar
   +0x002 Flags            : UChar
   +0x003 Control          : UChar
   +0x004 Parameters       : 
   +0x014 DeviceObject     : Ptr32 _DEVICE_OBJECT
   +0x018 FileObject       : Ptr32 _FILE_OBJECT
   +0x01c CompletionRoutine : Ptr32     long 
   +0x020 Context          : Ptr32 Void

  ,Parameters            union   ,  :

union
{
	//
	// NtCreateFIle   
	//
	struct 
	{
		PIO_SECURITY_CONTEXT SecurityContext;
		ULONG Options;
		USHORT POINTER_ALIGNMENT FileAttributes;
		USHORT ShareAccess;
		ULONG POINTER_ALIGNMENT EaLength;
	} Create;

	//
	// NtCreateNamedPipeFile   
	//
	struct
	{
		PIO_SECURITY_CONTEXT SecurityContext;
		ULONG Options;
		USHORT POINTER_ALIGNMENT Reserved;
		USHORT SharedAccess;
		PNAMED_PIPE_CREATE_PARAMETERS Parameters;
	} CreatePipe;

	//
	// NtCreateMailsotFIle    
	//
	struct
	{
		PIO_SECURITY_CONTEXT SecurityContext;
		ULONG Options;
		USHORT POINTER_ALIGNMENT Reserved;
		USHORT SharedAccess;
		PMAILSLOT_CREATE_PARAMETERS Parameters;
	} CreateMailslot;

	
	//
	// NtReadFile   
	//
	struct
	{
		ULONG Length;
		ULONG PINTER_ALIGNMENT Key;
		LARGE_INTEGER ByteOffset;
	} Read;

	//
	// NtWriteFile   
	//
	struct
	{
		ULONG Length;
		ULONG POINTER_ALIGNMENT Key;
		LARGE_INTEGER ByteOffset;
	} Write;

	//
	// NtQueryDirectoryFile   
	//
	struct
	{
		ULONG Length;
		PSTRING FileName;
		FILE_INFORMATION_CLASS FileInformationClass;
		ULONG POINTER_ALIGNMENT FileIndex;
	} QueryDirectory;

	//
	// NtNotifyChangeDirectoryFile   
	//
	struct
	{
		ULONG Length;
		ULONG POINTER_ALIGNMENT CompletionFilter;
	} NotifyDirectory;

	
	//
	// NtQueryInformationFile   
	//
	struct
	{
		ULONG Length;
		FILE_INFORMATION_CLASS POINTER_ALIGNMENT FileInformationClass;
	} QueryFile;

	//
	// NtSetInformationFile   
 	//
	struct
	{
		ULONG Length;
		FILE_INFORMATION_CLASS POINTER_ALIGNMENT FileInformationClass;
		PFILE_OBJECT FileObject;
		union
		{
			struct
			{
				BOOLEAN ReplaceIfExists;
				BOOLEAN AdvanceOnly;
			};
			ULONG ClusterCount;
			HANDLE DeleteHandle;
		};
	} SetFile;


	//
	// NtQueryEaFile   
	//
	struct
	{
		ULONG Length;
		PVOID EaList;
		ULONG EaListLength;
		ULONG POINTER_ALIGNMENT EaIndex;
	} QueryEa;
	
	//
	// NtSetEaFIle   
	//
	struct
	{
		ULONG Length;
	} SetEa;

	//
	// NtQueryVolumeInformationFile   
	//
	struct
	{
		ULONG Length;
		FS_INORTMATION_CLASS POINTER_ALIGNMENT FsInformationClass;
	} QueryVoume;


	// 
	// NtSetVolumeInformationFile    
	//
	struct 
	{
		ULONG Length;
		FS_INFORMATION_CLASS POINTER_ALIGNMENT FsInformationClass;
	} setValue;


	//
	// NtFsControlFile    
	//
	struct
	{
		ULONG OutputBufferLength;
		ULONG POINTER_ALIGNMENT InputBufferLength;
		ULONG POINTER_ALIGNMENT  FsControlCode;
		PVOID Type3InputBuffer;
	} FileSystemControl;


	//
	// NtLockFile/NtUnlockFile   
	//
	struct
	{
		PLARGE_INTEGER Length;
		ULONG POINTER_ALIGNMENT Key;
		LARGE_INTEGER ByteOffset;
	} LockControl;


	//
	// NtDeviceIoControlFile   
	//
	struct
	{
		ULONG OutputBufferLength;
		ULONG POINTER_ALIGNMENT InputBufferLength;
		ULONG POINTER_ALIGNMENT IoControlCode;
		PVOID Type3InputBuffer;
	} DeviceIoControl;


	//
	// NtQuerySecurityObject   
	//
	struct
	{
		SECURITY_INFORMATION SecurityInformation;
		ULONG POINTER_ALIGNMENT Length;
	} QuerySecurity;


	//
	// NtSetScurityObject   
	//
	struct
	{
		SECURITY_INFORMATION SecurityInformation;
		PSECURITY_DESCRIPTOR SecurityDescriptor;
	} SetSecurity;


	//
	// MountVoluem    
	//
	struct
	{
		PVPB Vpb;
		PDEVICE_OBJECT DeviceObject;
	} MountVolume;


	//
	// VerifyVolume   
	//
	struct
	{
		PVPB Vpb;
		PDEVICE_OBJECT DeviceObject;
	} VerityVolume;

	
	//
	// Scsi    device control
	//
	struct
	{
		struct _SCSI_REQUEST_BLOCK *Srb;
	} Scsi;

	
	//
	// NtQueryQuotaInformationFile    
	//
	struct
	{
		ULONG Length;
		PSID StartSid;
		PFILE_GET_QUOTA_INFORMATION SidList;
		ULONG SidListLength;
	} QueryQuota;


	//
	// NtSetQuotaInformationFile    
	//
	struct
	{
		ULONG Length;
	} SetQuota;


	//
	// IRP_MN_QUERY_DEVICE_RELATIONS   
	//
	struct
	{
		DEVICE_RELATION_TYPE Type;
	} QueryDevceRelations;


	//
	// IRP_MN_QUERY_INTERFACE   
	//
	struct
	{
		CONST GUID *InterfaceType;
		USHORT Size;
		USHORT Version;
		PINTERFACE Interface;
		PVOID InterfacespecificData;
	} QueryInterface;

	//
	// IRP_MN_QUERY_CAPABILITIES   
	//
	struct
	{
		PDEVICE_CAPABILITIES Capabilities;
	} DeviceCapabilities;


	//
	// IRP_MN_FILTER_RESOURCE_REQUIREMENTS   
	//
	struct
	{
		PIO_RESOURCE_REQUIREMENTS_LIST IoResourceRequirementList;
	} FilterResourceRequirements;
		

	//
	// IRP_MN_READ_CONFIG   IRP_MN_WRITE_CONFIG   
	//
	struct
	{
		ULONG WhichSpace;
		PVOID Buffer;
		ULONG Offset;
		ULONG POINTER_ALIGNMENT Length;
	} ReadWriteConfig;


	//
	// IRP_MN_SET_LOCK   
	//
	struct
	{
		BOOLEAN Lock;
	} SetLock;

	//
	// IRP_MN_QUERY_ID   
	//
	struct
	{
		BUS_QUERY_ID_TYPE IdType;	
	} QueryId;


	//
	// IRP_MN_QUERY_DEVICE_TEXT   
	//
	struct
	{
		DEVICE_TEXT_TYPE DeviceTextType;
		LCID POINTER_ALIGNMENT LocaleId;
	}  QueryDeviceText;


	//
	// IRP_MN_DEVICE_USAGE_NOTIFICATION   
	//
	struct
	{
		BOOLEAN InPath;
		BOOLEAN Reserved[3];
		DEVICE_USAGE_NOTIFICATION_TYPE POINTER_ALIGNMENT Type;
	} UsageNotification;


	//
	// IRP_MN_WAIT_WAKE   
	//
	struct
	{
		SYSTEM_POWER_STATE PowerState;
	} WaitWake;


	//
	// IRP_MN_POWER_SEQUENCE   
	//
	struct
	{
		PPOWER_SEQUENCE PowerSequence;
	} PowerSquence;


	//
	// IRP_MN_SET_POWER   IRP_MN_QUERY_POWER   
	//
	struct
	{
		ULONG SystemCotext;
		POWER_STATE_TYPE POINTER_ALIGNMENT Type;	
		POWER_STATE POINTER_ALIGNMENT State;
		POWER_ACTION POINTER_ALIGNMENT ShutdownType;
	} Power;


	//
	// StartDevice    
	//
	struct
	{
		PCM_RESOURCE_LIST AllocatedResources;
		PCM_RESOURCE_LIST AllocatedResourcesTranslated;
	} StartDevice;


	//
	// WMI Irps   
	//
	struct
	{
		ULONG_PTR ProviderId;
		PVOID DataPath;
		ULONG BufferSize;
		PVOID Buffer;
	} WMI;


	//
	//    device      
	//
	struct
	{
		PVOID Argument1
		PVOID Argument2;
		PVOID Argument3;
		PVOID Argument4;
	} Others;

} Parameters;

Parameters        request     ,  :Create(IRP_MJ_CREATE   ),Read(IRP_MJ_READ   ),StartDevice(IRP_MJ_PNP     IRP_MN_START_DEVICE)
MajorFunction   MinorFunction     IRP           。DeviceObject   stack entry     device object,IoCallDriver()      。
FileObject    kernel file object。driver        FileObject       IRP     request    。
CompletionRoutine       I/O completion routine,         ,     IoSetCompletionRoutine()    。
Context      ,    completion routine     。         ,     IoSetCompletionRoutine()    。

5.2 IRP        
      :
I/O manager ---> Dispatch routine ---> StartIo routine ---> ISR ---> DPC routine ---> I/O manager

5.2.1      IRP
IRP         I/O manager function    IRP   ,        4   function         IRP:
(1) IoBuildAsynchronousFsdRequest():      IRP      。             IRP
(2) IoBuildSynchronousFsdRequest():      IRP       。
(3) IoBuildDeviceIoControlRequest():         IRP_MJ_DEVICE_CONTROL    IRP_MJ_INTERNAL_DEVICE_CONTROL
(4) IoAllcateIrp():      asynchronous   IRP

>>>    synchronous IRP
   IoBuildSynchronousFsdRequest()   IoBuildDeviceIoControlRequest()        IRP,   IRP         。
       ,           :
(1)         ,I/O manager              IRP   pending
(2)              IRP    ,         context       IRP,             I/O manager    IRP。
(3)    IoCompleteRequest(),I/O manager       IRP,          event   signaled   。
(4)   I/O manager   event object signaled    ,event object              event object。
    PASSIVE_LEVEL         ,       APC_LEVEL    。  :    fast mutex      APC_LEVEL,   I/O manager
     special APC routine       complete   。

PIRP Irp = IoBuildSycnhronousFsdRequest(...);
ExAcqurireFastMutex(...);
NTSTATUS status = IoCallDriver(...);
if (status == STATUS_PENDING)
{
        KeWaitForSingleObject(...);             //   :     
}
ExReleaseFastMutex(...);

       ,   KeWaitForSingleObject()        :      IoCompleteRequest(),   APC routine       event,
      APC_LEVEL    ,APC routine         event signled。
          synchronous IRP     driver,       :
(1)       kernel mutex     fast mutex,kernel mutex      PASSIVE_LEVEL    ,      special APC   。
(2)    KeEnterCriticalRegion()         special APC  ,     ExAcquireFastMutexUnsafe()     mutex。
(3)    asynchronous IRP(   synchronous IRP),    signaled event。

          IRP      :
support function                                IRP   
------------------------------------------------------------------------------------
IoBuildSynchronousFsdRequest()                  IRP_MJ_READ
                                                IRP_MJ_WRITE
                                                IRP_MJ_FLUSH_BUFFERS
                                                IRP_MJ_SHUTDOWN
                                                IRP_MJ_PNP
                                                IRP_MJ_POWER(    IRP_MN_POWER_SEQUENCE)
-------------------------------------------------------------------------------------
IoBuildDeviceControlRequest()                   IRP_MJ_DEVICE_CONTROL
                                                IRP_MJ_INTERNAL_DEVICE_CONTROL

>>>      IRP
IoBuildAsynchronousFsdRequest()   IoAllocateIrp()            IRP,       IRP      :

support function                                IRP   
--------------------------------------------------------------------------------------
IoBuildAsynchronousFsdRequest()                 IRP_MJ_READ
                                                IRP_MJ_WRITE
                                                IRP_MJ_FLUSH_BUFFERS
                                                IRP_MJ_SHUTDOWN
                                                IRP_MJ_PNP
                                                IRP_MJ_POWER(    IRP_MN_POWER_SEQUENCE)
---------------------------------------------------------------------------------------
IoAllocateIrp()                                   (       Marjor function  )

   IRP         ,  IRP    ,I/O manager     APC       IRP。       :
(1)       ,I/O manager          IRP   pending
(2)         context    
(3)    IRP     I/O manager     IRP,       complete routine     buffer      IoFreeIrp()    IRP       。
(4)           ,          cancel routine。
(5)           IRP    ,      IRP   IRQL <= DISPATCH_LEVEL    ,    fast mutex      IRP     。

5.2.2 dispatch routine
      IRP  ,     IoGetNextIrpStackLocation()     first stack location,      stack location      。
      IoAllcateIrp()            MajorFunction  。

PEDEVICE_OBJECT DeviceObject;
PIO_STACK_LOCATION stack = IoGetNextIrpStackLoction(Irp);
stack->MajorFunction = IRP_MJ_Xxx;
// ... stack      
NTSTATUS status = IoCallDriver(DeviceObject, Irp);

IoGetNextIrpStackLocation()             stack location,      :
#define IoGetNextIrpStackLocation(Irp)          ((Irp)->Tail.Overlay.CurrentStackLocation - 1)


>>> What IoCallDriver Does
IoCallDriver()       :

NTSTATUS IoCallDriver(PDEVICE_OBJECT DeviceObject,
                PIRP Irp)
{
        IoSetNextIrpStackLocation(Irp);
        PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
        Stack->DeviceObject = DeviceObject;
        ULONG fcn = Stack->MajorFunction;
        PDRVIER_OBJECT Driver = DeviceObject->DriverObject;
        return (*Driver->MajorFunction[fcn]))(DeviceObject, Irp);
}

IoCallDriver()       stack       driver   dispatch routine。

>>> location device objects
     IoAttachDeviceToDeviceStack()  ,           :IoGetDeviceObjectPointer()   IoGetAttachedDeviceReference()
NTSTATUS 
IoGetDeviceObjectPointer(
    IN PUNICODE_STRING  ObjectName,
    IN ACCESS_MASK  DesiredAccess,
    OUT PFILE_OBJECT  *FileObject,
    OUT PDEVICE_OBJECT  *DeviceObject
    );
      device object    ,            IoGetDeviceObjectPointer()    device object,      :
PUNICODE_STRING devname;
ASSESS_MASK access;
PDEVICE_OBJECT DeviceObject;
PFILE_OBJECT FileObject;
NTSTATUS status;

ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
status = IoGetDeviceObjectPointer(devname, access, &FileObject, &DeviceObject);

          :     FILE_OBJECT,      DEVICE_OBJECT。

PIRP Irp = IoXxx(...);
PIO_STACK_LOCATION Stack = IoGetNextIrpStackLocation(Irp);
ObReferenceObject(FileObject);
Stack->FileObject = FileObject;
IoCallDriver(DeviceObject, Irp);
ObDereferenceObject(FileObject);
------------------------------------
IoGetDeviceObjectPointer()                 :
(1)    ZwOpenFile()         device object,     object manager      file object     IRP_MJ_CREATE      ,ZwOpenFile()    file handle
(2)    ObReferenceObjectByHandle()      file handle   FILE_OBJECT     ,      FileObject   。
(3)    IoGetRelatedDeviceObject()     FileObject     DEVICE_OBJECT     ,      DeviceObject   。
(4)    ZwClose()    Handle
 

5.2.3 Dispatch routine   
   Dispatch routine    ,      :
NTSTATUS DispatchXxx(PDEVICE_OBJECT fdo, PRIP Irp)
{
        PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
        PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)fdo->DeviceExtension;
        
        ...
        return STATUS_Xxx;
}
1.          stack location           minor    
2.             device extension   (  AddDevice()       )。
3.       IoCallDriver()    。     NTSTATUS  。

>>> IRP    
     IRP      IRP   IoStatus     Status   Information  ,     IoCompleteRequest()   。
   Status     NTSTATUS.h        status code   。  Information      IRP      ,      IRP     Information     0
  IRP          ,     Information         。










좋은 웹페이지 즐겨찾기