I/O Request Packet(IRP)

IRP概述:

IRP是由I/O管理器发出的,I/O管理器是用户态与内核态之间的桥梁,当用户态进程发出I/O请求时,I/O管理器就捕获这些请求,将其转换为IRP请求,发送给驱动程序。

I/O管理器无疑是非常重要的,具有核心地位。它负责所有I/O请求的调度和管理工作,根据请求的不同内容,选择相应的驱动程序对象,设备对象,并生成、发送、释放各种不同的IRP。

整个I/O处理流程是在它的指挥下完成的。

一个IRP是从非分页内存中分配的可变大小的结构,它包括两部分:IRP首部和I/O堆栈。

IRP首部中包含了指向IRP输入输出缓冲区指针、当前拥有IRP的驱动指针等。

紧接着首部的IO_STACK_LOCATION结构的数组。它的大小由设备栈中的设备数确定。IO_STACK_LOCATION结构中保存了一个I/O请求的参数及代码、请求当前对应的设备指针、完成函数指针(IoCompletion)等。

IRP结构介绍:

我们先看看WRK中对IRP的定义

  1 typedef struct DECLSPEC_ALIGN(MEMORY_ALLOCATION_ALIGNMENT) _IRP {
2 CSHORT Type;
3 USHORT Size;
4
5 //
6 // Define the common fields used to control the IRP.
7 //
8
9 //
10 // Define a pointer to the Memory Descriptor List (MDL) for this I/O
11 // request. This field is only used if the I/O is "direct I/O".
12 //
13
14 PMDL MdlAddress;
15
16 //
17 // Flags word - used to remember various flags.
18 //
19
20 ULONG Flags;
21
22 //
23 // The following union is used for one of three purposes:
24 //
25 // 1. This IRP is an associated IRP. The field is a pointer to a master
26 // IRP.
27 //
28 // 2. This is the master IRP. The field is the count of the number of
29 // IRPs which must complete (associated IRPs) before the master can
30 // complete.
31 //
32 // 3. This operation is being buffered and the field is the address of
33 // the system space buffer.
34 //
35
36 union {
37 struct _IRP *MasterIrp;
38 __volatile LONG IrpCount;
39 PVOID SystemBuffer;
40 } AssociatedIrp;
41
42 //
43 // Thread list entry - allows queueing the IRP to the thread pending I/O
44 // request packet list.
45 //
46
47 LIST_ENTRY ThreadListEntry;
48
49 //
50 // I/O status - final status of operation.
51 //
52
53 IO_STATUS_BLOCK IoStatus;
54
55 //
56 // Requestor mode - mode of the original requestor of this operation.
57 //
58
59 KPROCESSOR_MODE RequestorMode;
60
61 //
62 // Pending returned - TRUE if pending was initially returned as the
63 // status for this packet.
64 //
65
66 BOOLEAN PendingReturned;
67
68 //
69 // Stack state information.
70 //
71
72 CHAR StackCount;
73 CHAR CurrentLocation;
74
75 //
76 // Cancel - packet has been canceled.
77 //
78
79 BOOLEAN Cancel;
80
81 //
82 // Cancel Irql - Irql at which the cancel spinlock was acquired.
83 //
84
85 KIRQL CancelIrql;
86
87 //
88 // ApcEnvironment - Used to save the APC environment at the time that the
89 // packet was initialized.
90 //
91
92 CCHAR ApcEnvironment;
93
94 //
95 // Allocation control flags.
96 //
97
98 UCHAR AllocationFlags;
99
100 //
101 // User parameters.
102 //
103
104 PIO_STATUS_BLOCK UserIosb;
105 PKEVENT UserEvent;
106 union {
107 struct {
108 union {
109 PIO_APC_ROUTINE UserApcRoutine;
110 PVOID IssuingProcess;
111 };
112 PVOID UserApcContext;
113 } AsynchronousParameters;
114 LARGE_INTEGER AllocationSize;
115 } Overlay;
116
117 //
118 // CancelRoutine - Used to contain the address of a cancel routine supplied
119 // by a device driver when the IRP is in a cancelable state.
120 //
121
122 __volatile PDRIVER_CANCEL CancelRoutine;
123
124 //
125 // Note that the UserBuffer parameter is outside of the stack so that I/O
126 // completion can copy data back into the user's address space without
127 // having to know exactly which service was being invoked. The length
128 // of the copy is stored in the second half of the I/O status block. If
129 // the UserBuffer field is NULL, then no copy is performed.
130 //
131
132 PVOID UserBuffer;
133
134 //
135 // Kernel structures
136 //
137 // The following section contains kernel structures which the IRP needs
138 // in order to place various work information in kernel controller system
139 // queues. Because the size and alignment cannot be controlled, they are
140 // placed here at the end so they just hang off and do not affect the
141 // alignment of other fields in the IRP.
142 //
143
144 union {
145
146 struct {
147
148 union {
149
150 //
151 // DeviceQueueEntry - The device queue entry field is used to
152 // queue the IRP to the device driver device queue.
153 //
154
155 KDEVICE_QUEUE_ENTRY DeviceQueueEntry;
156
157 struct {
158
159 //
160 // The following are available to the driver to use in
161 // whatever manner is desired, while the driver owns the
162 // packet.
163 //
164
165 PVOID DriverContext[4];
166
167 } ;
168
169 } ;
170
171 //
172 // Thread - pointer to caller's Thread Control Block.
173 //
174
175 PETHREAD Thread;
176
177 //
178 // Auxiliary buffer - pointer to any auxiliary buffer that is
179 // required to pass information to a driver that is not contained
180 // in a normal buffer.
181 //
182
183 PCHAR AuxiliaryBuffer;
184
185 //
186 // The following unnamed structure must be exactly identical
187 // to the unnamed structure used in the minipacket header used
188 // for completion queue entries.
189 //
190
191 struct {
192
193 //
194 // List entry - used to queue the packet to completion queue, among
195 // others.
196 //
197
198 LIST_ENTRY ListEntry;
199
200 union {
201
202 //
203 // Current stack location - contains a pointer to the current
204 // IO_STACK_LOCATION structure in the IRP stack. This field
205 // should never be directly accessed by drivers. They should
206 // use the standard functions.
207 //
208
209 struct _IO_STACK_LOCATION *CurrentStackLocation;
210
211 //
212 // Minipacket type.
213 //
214
215 ULONG PacketType;
216 };
217 };
218
219 //
220 // Original file object - pointer to the original file object
221 // that was used to open the file. This field is owned by the
222 // I/O system and should not be used by any other drivers.
223 //
224
225 PFILE_OBJECT OriginalFileObject;
226
227 } Overlay;
228
229 //
230 // APC - This APC control block is used for the special kernel APC as
231 // well as for the caller's APC, if one was specified in the original
232 // argument list. If so, then the APC is reused for the normal APC for
233 // whatever mode the caller was in and the "special" routine that is
234 // invoked before the APC gets control simply deallocates the IRP.
235 //
236
237 KAPC Apc;
238
239 //
240 // CompletionKey - This is the key that is used to distinguish
241 // individual I/O operations initiated on a single file handle.
242 //
243
244 PVOID CompletionKey;
245
246 } Tail;
247
248 } IRP;

结构图如下,其中灰色部分为不可见区域,这里主要讲解一下可见区域。

1.1 PMDL  MdlAddress : 设备执行直接I/O时,指向用户空间的内存描述表

1.2 ULONG Flags: 包含一些对驱动程序只读的标志。但这些标志与WDM驱动程序无关

1.3 AssociatedIrp.SystemBuffer : SystemBuffer指针指向一个数据缓冲区,该缓冲区位于内核模式的非分页内存中I/O管理器把用户模式程序发送给驱动程序的数据复制到这个缓冲区,这也是创建IRP过程的一部分。对于读请求,设备驱动程序把读出的数据填到这个缓冲区,然后I/O管理器再把缓冲区的内容复制到用户模式缓冲区。

1.4 IoStatus : 是一个结构体IO_STATUS_BLOCK, 这个结构体仅包含两个域,驱动程序在最终完成请求时设置这个结构。
       IoStatus.Status : 将收到一个NTSTATUS代码。
       IoStatus.Information 的类型为ULONG_PTR,它将收到一个信息值,该信息值的确切含义要取决于具体的IRP类型和请求完成的状态。Information域的一个公认用法是用于保存数据传输操作。某些PnP请求把这个域作为指向另外一个结构的指针,这个结构通常包含查询请求的结果。

1.5 RequestorMode将等于一个枚举常量UserModeKernelMode,指定原始I/O请求的来源。驱动程序有时需要查看这个值来决定是否要信任某些参数。

1.6 PendingReturned(BOOLEAN)如果为TRUE,则表明处理该IRP的最低级派遣例程返回了STATUS_PENDING。完成例程通过参考该域来避免自己与派遣例程间的潜在竞争。

1.7 Cancel(BOOLEAN)如果为TRUE,则表明IoCancelIrp已被调用,该函数用于取消这个请求。如果为FALSE,则表明没有调用IoCancelIrp函数。取消IRP是一个相对复杂的主题,我将在本章的最后详细描述它。

1.8 CancelIrql(KIRQL)是一个IRQL值,表明那个专用的取消自旋锁是在这个IRQL上获取的。当你在取消例程中释放自旋锁时应参考这个域。

1.9 CancelRoutine(PDRIVER_CANCEL)是驱动程序取消例程的地址。你应该使用IoSetCancelRoutine函数设置这个域而不是直接修改该域。

2.0 UserBuffer(PVOID) 对于METHOD_NEITHER方式的IRP_MJ_DEVICE_CONTROL请求,该域包含输出缓冲区的用户模式虚拟地址。该域还用于保存读写请求缓冲区的用户模式虚拟地址,但指定了DO_BUFFERED_IO或DO_DIRECT_IO标志的驱动程序,其读写例程通常不需要访问这个域。当处理一个METHOD_NEITHER控制操作时,驱动程序能用这个地址创建自己的MDL。

PIO_STACK_LOCATION结构介绍:

我们再来看看WRK中对PIO_STACK_LOCATION结构的定义

typedef struct _IO_STACK_LOCATION {
UCHAR MajorFunction;
UCHAR MinorFunction;
UCHAR Flags;
UCHAR Control; //
// The following user parameters are based on the service that is being
// invoked. Drivers and file systems can determine which set to use based
// on the above major and minor function codes.
// union { //
// System service parameters for: NtCreateFile
// struct {
PIO_SECURITY_CONTEXT SecurityContext;
ULONG Options;
USHORT POINTER_ALIGNMENT FileAttributes;
USHORT ShareAccess;
ULONG POINTER_ALIGNMENT EaLength;
} Create; //
// System service parameters for: NtReadFile
// struct {
ULONG Length;
ULONG POINTER_ALIGNMENT Key;
LARGE_INTEGER ByteOffset;
} Read; //
// System service parameters for: NtWriteFile
// struct {
ULONG Length;
ULONG POINTER_ALIGNMENT Key;
LARGE_INTEGER ByteOffset;
} Write; //
// System service parameters for: NtQueryDirectoryFile
// struct {
ULONG Length;
PUNICODE_STRING FileName;
FILE_INFORMATION_CLASS FileInformationClass;
ULONG POINTER_ALIGNMENT FileIndex;
} QueryDirectory; //
// System service parameters for: NtNotifyChangeDirectoryFile
// struct {
ULONG Length;
ULONG POINTER_ALIGNMENT CompletionFilter;
} NotifyDirectory; //
// System service parameters for: NtQueryInformationFile
// struct {
ULONG Length;
FILE_INFORMATION_CLASS POINTER_ALIGNMENT FileInformationClass;
} QueryFile; //
// System service parameters for: NtSetInformationFile
// struct {
ULONG Length;
FILE_INFORMATION_CLASS POINTER_ALIGNMENT FileInformationClass;
PFILE_OBJECT FileObject;
union {
struct {
BOOLEAN ReplaceIfExists;
BOOLEAN AdvanceOnly;
};
ULONG ClusterCount;
HANDLE DeleteHandle;
};
} SetFile; //
// System service parameters for: NtQueryEaFile
// struct {
ULONG Length;
PVOID EaList;
ULONG EaListLength;
ULONG POINTER_ALIGNMENT EaIndex;
} QueryEa; //
// System service parameters for: NtSetEaFile
// struct {
ULONG Length;
} SetEa; //
// System service parameters for: NtQueryVolumeInformationFile
// struct {
ULONG Length;
FS_INFORMATION_CLASS POINTER_ALIGNMENT FsInformationClass;
} QueryVolume; //
// System service parameters for: NtSetVolumeInformationFile
// struct {
ULONG Length;
FS_INFORMATION_CLASS POINTER_ALIGNMENT FsInformationClass;
} SetVolume; //
// System service parameters for: NtFsControlFile
//
// Note that the user's output buffer is stored in the UserBuffer field
// and the user's input buffer is stored in the SystemBuffer field.
// struct {
ULONG OutputBufferLength;
ULONG POINTER_ALIGNMENT InputBufferLength;
ULONG POINTER_ALIGNMENT FsControlCode;
PVOID Type3InputBuffer;
} FileSystemControl;
//
// System service parameters for: NtLockFile/NtUnlockFile
// struct {
PLARGE_INTEGER Length;
ULONG POINTER_ALIGNMENT Key;
LARGE_INTEGER ByteOffset;
} LockControl; //
// System service parameters for: NtFlushBuffersFile
//
// No extra user-supplied parameters.
// //
// System service parameters for: NtCancelIoFile
//
// No extra user-supplied parameters.
// //
// System service parameters for: NtDeviceIoControlFile
//
// Note that the user's output buffer is stored in the UserBuffer field
// and the user's input buffer is stored in the SystemBuffer field.
// struct {
ULONG OutputBufferLength;
ULONG POINTER_ALIGNMENT InputBufferLength;
ULONG POINTER_ALIGNMENT IoControlCode;
PVOID Type3InputBuffer;
} DeviceIoControl; //
// System service parameters for: NtQuerySecurityObject
// struct {
SECURITY_INFORMATION SecurityInformation;
ULONG POINTER_ALIGNMENT Length;
} QuerySecurity; //
// System service parameters for: NtSetSecurityObject
// struct {
SECURITY_INFORMATION SecurityInformation;
PSECURITY_DESCRIPTOR SecurityDescriptor;
} SetSecurity; //
// Non-system service parameters.
//
// Parameters for MountVolume
// struct {
PVPB Vpb;
PDEVICE_OBJECT DeviceObject;
} MountVolume; //
// Parameters for VerifyVolume
// struct {
PVPB Vpb;
PDEVICE_OBJECT DeviceObject;
} VerifyVolume; //
// Parameters for Scsi with internal device contorl.
// struct {
struct _SCSI_REQUEST_BLOCK *Srb;
} Scsi; //
// System service parameters for: NtQueryQuotaInformationFile
// struct {
ULONG Length;
PSID StartSid;
PFILE_GET_QUOTA_INFORMATION SidList;
ULONG SidListLength;
} QueryQuota; //
// System service parameters for: NtSetQuotaInformationFile
// struct {
ULONG Length;
} SetQuota; //
// Parameters for IRP_MN_QUERY_DEVICE_RELATIONS
// struct {
DEVICE_RELATION_TYPE Type;
} QueryDeviceRelations; //
// Parameters for IRP_MN_QUERY_INTERFACE
// struct {
CONST GUID *InterfaceType;
USHORT Size;
USHORT Version;
PINTERFACE Interface;
PVOID InterfaceSpecificData;
} QueryInterface; //
// Parameters for IRP_MN_QUERY_CAPABILITIES
// struct {
PDEVICE_CAPABILITIES Capabilities;
} DeviceCapabilities; //
// Parameters for IRP_MN_FILTER_RESOURCE_REQUIREMENTS
// struct {
PIO_RESOURCE_REQUIREMENTS_LIST IoResourceRequirementList;
} FilterResourceRequirements; //
// Parameters for IRP_MN_READ_CONFIG and IRP_MN_WRITE_CONFIG
// struct {
ULONG WhichSpace;
PVOID Buffer;
ULONG Offset;
ULONG POINTER_ALIGNMENT Length;
} ReadWriteConfig; //
// Parameters for IRP_MN_SET_LOCK
// struct {
BOOLEAN Lock;
} SetLock; //
// Parameters for IRP_MN_QUERY_ID
// struct {
BUS_QUERY_ID_TYPE IdType;
} QueryId; //
// Parameters for IRP_MN_QUERY_DEVICE_TEXT
// struct {
DEVICE_TEXT_TYPE DeviceTextType;
LCID POINTER_ALIGNMENT LocaleId;
} QueryDeviceText; //
// Parameters for IRP_MN_DEVICE_USAGE_NOTIFICATION
// struct {
BOOLEAN InPath;
BOOLEAN Reserved[3];
DEVICE_USAGE_NOTIFICATION_TYPE POINTER_ALIGNMENT Type;
} UsageNotification; //
// Parameters for IRP_MN_WAIT_WAKE
// struct {
SYSTEM_POWER_STATE PowerState;
} WaitWake; //
// Parameter for IRP_MN_POWER_SEQUENCE
// struct {
PPOWER_SEQUENCE PowerSequence;
} PowerSequence; //
// Parameters for IRP_MN_SET_POWER and IRP_MN_QUERY_POWER
// #if (NTDDI_VERSION >= NTDDI_VISTA)
struct {
union {
ULONG SystemContext;
SYSTEM_POWER_STATE_CONTEXT SystemPowerStateContext;
};
POWER_STATE_TYPE POINTER_ALIGNMENT Type;
POWER_STATE POINTER_ALIGNMENT State;
POWER_ACTION POINTER_ALIGNMENT ShutdownType;
} Power;
#else
struct {
ULONG SystemContext;
POWER_STATE_TYPE POINTER_ALIGNMENT Type;
POWER_STATE POINTER_ALIGNMENT State;
POWER_ACTION POINTER_ALIGNMENT ShutdownType;
} Power;
#endif // (NTDDI_VERSION >= NTDDI_VISTA) //
// Parameters for StartDevice
// struct {
PCM_RESOURCE_LIST AllocatedResources;
PCM_RESOURCE_LIST AllocatedResourcesTranslated;
} StartDevice; //
// Parameters for Cleanup
//
// No extra parameters supplied
// //
// WMI Irps
// struct {
ULONG_PTR ProviderId;
PVOID DataPath;
ULONG BufferSize;
PVOID Buffer;
} WMI; //
// Others - driver-specific
// struct {
PVOID Argument1;
PVOID Argument2;
PVOID Argument3;
PVOID Argument4;
} Others; } Parameters; //
// Save a pointer to this device driver's device object for this request
// so it can be passed to the completion routine if needed.
// PDEVICE_OBJECT DeviceObject; //
// The following location contains a pointer to the file object for this
// request.
// PFILE_OBJECT FileObject; //
// The following routine is invoked depending on the flags in the above
// flags field.
// PIO_COMPLETION_ROUTINE CompletionRoutine; //
// The following is used to store the address of the context parameter
// that should be passed to the CompletionRoutine.
// PVOID Context; } IO_STACK_LOCATION, *PIO_STACK_LOCATION;

结构图如下

MajorFunction(UCHAR)是该IRP的主功能码

MinorFunction(UCHAR)是该IRP的副功能码

Parameters(union)是几个子结构的联合,每个请求类型都有自己专用的参数,而每个子结构就是一种参数。这些子结构包括Create(IRP_MJ_CREATE请求)、Read(IRP_MJ_READ请求)、StartDevice(IRP_MJ_PNP的IRP_MN_START_DEVICE子类型),等等。

DeviceObject(PDEVICE_OBJECT)是与该堆栈单元对应的设备对象的地址。该域由IoCallDriver函数负责填写。

FileObject(PFILE_OBJECT)是内核文件对象的地址,IRP的目标就是这个文件对象。驱动程序通常在处理清除请求(IRP_MJ_CLEANUP)时使用FileObject指针,以区分队列中与该文件对象无关的IRP。

CompletionRoutine(PIO_COMPLETION_ROUTINE)是一个I/O完成例程的地址,该地址是由与这个堆栈单元对应的驱动程序的更上一层驱动程序设置的。你绝对不要直接设置这个域,应该调用IoSetCompletionRoutine函数,该函数知道如何参考下一层驱动程序的堆栈单元。设备堆栈的最低一级驱动程序并不需要完成例程,因为它们必须直接完成请求。然而,请求的发起者有时确实需要一个完成例程,但通常没有自己的堆栈单元。这就是为什么每一级驱动程序都使用下一级驱动程序的堆栈单元保存自己完成例程指针的原因。

IRP、PIO_STACK_LOCATIONDEVICE:

1)I/O堆栈位置的主要目的是,保存一个I/O请求的函数代码和参数。
2)I/O堆栈数量实际上就是参与I/O请求的I/O层的数量。
3)在一个IRP中,上层驱动负责为下层驱动设置堆栈位置指针。
  i)驱动程序可以为每个IRP调用IoGetCurrentStackLocation来获得指向其自身堆栈位置的指针,
  ii)上层驱动程序必须调用IoGetNextIrpStackLocation来获得指向下层驱动程序堆栈位置的指针。
因此,上层驱动可以在传送IRP给下层驱动之前设置堆栈位置的内容。
4)上层驱动调用IoCallDriver,将DeviceObject成员设置成下层驱动目标设备对象。当上层驱动完成IRP时,IoCompletion 函数被调用,I/O管理器传送给IoCompletion函数一个指向上层驱动的设备对象的指针。

示例:

下面我们通过构造IPR去删除一个文件来加深对IPR的认识

  1 #include "DeleteFile.h"
2
3 NTSTATUS
4 DriverEntry(PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegisterPath)
5 {
6
7 HANDLE hFile = GetFileHandle(L"\\??\\D:\\1.exe");
8 DriverObject->DriverUnload = UnloadDriver;
9
10 if (hFile!=NULL)
11 {
12
13 DbgPrint("Get File Success\r\n");
14 DestroyFile(hFile);
15
16 ZwClose(hFile);
17 }
18
19 return STATUS_SUCCESS;
20 }
21
22
23 VOID
24 UnloadDriver(PDRIVER_OBJECT DriverObject)
25 {
26
27 }
28
29
30 HANDLE
31 GetFileHandle(PCWSTR FileName)
32 {
33
34 NTSTATUS Status;
35 UNICODE_STRING uniFileName;
36 OBJECT_ATTRIBUTES oa;
37 HANDLE hFile;
38 IO_STATUS_BLOCK Iosb;
39
40 RtlInitUnicodeString(&uniFileName,FileName);
41
42 InitializeObjectAttributes(&oa,&uniFileName,
43 OBJ_KERNEL_HANDLE|OBJ_CASE_INSENSITIVE,NULL,NULL);
44
45 //通过文件名得文件句柄
46 Status = IoCreateFile(&hFile,FILE_READ_ATTRIBUTES,
47 &oa,&Iosb,0,FILE_ATTRIBUTE_NORMAL,FILE_SHARE_DELETE,FILE_OPEN,0,NULL,0,0,NULL,
48 IO_NO_PARAMETER_CHECKING);
49
50
51 if (!NT_SUCCESS(Status))
52 {
53 return NULL;
54 }
55
56 return hFile;
57
58 }
59
60
61 VOID
62 DestroyFile(HANDLE hFile)
63 {
64
65 IO_STATUS_BLOCK Iosb;
66 PIO_STACK_LOCATION IrpSp;
67 NTSTATUS Status;
68 PFILE_OBJECT FileObject;
69 PIRP Irp;
70 PDEVICE_OBJECT DeviceObject;
71 KEVENT hEvent;
72 FILE_DISPOSITION_INFORMATION FileInfor;//微软官方结构体
73
74
75 static PVOID ImageSectionObject = NULL;
76 static PVOID DataSectionObject = NULL;
77 static PVOID SharedCacheMap = NULL;
78
79 //通过文件句柄得文件对象
80 Status = ObReferenceObjectByHandle(hFile,DELETE,*IoFileObjectType,KernelMode,
81 &FileObject,NULL);
82
83
84 DeviceObject = IoGetRelatedDeviceObject(FileObject); //文件系统栈最上层的设备对象 //也可以获得卷设备直接发送
85
86
87
88 //去除文件的只读属性
89 if (SKillStripFileAttributes(hFile)==FALSE)
90 {
91 return;
92 }
93 //构建一个IRP
94
95 Irp = IoAllocateIrp(DeviceObject->StackSize,TRUE);
96 if (Irp==NULL)
97 {
98 ObDereferenceObject(FileObject);
99
100 return;
101 }
102
103
104 KeInitializeEvent(&hEvent,SynchronizationEvent,FALSE);
105
106
107 FileInfor.DeleteFile = TRUE;
108
109
110 Irp->AssociatedIrp.SystemBuffer = &FileInfor;
111 Irp->UserEvent = &hEvent;
112 Irp->UserIosb = &Iosb;
113 Irp->Tail.Overlay.OriginalFileObject = FileObject;
114 Irp->Tail.Overlay.Thread = KeGetCurrentThread();
115 Irp->RequestorMode = KernelMode;
116
117
118 IrpSp = IoGetNextIrpStackLocation(Irp);
119
120 IrpSp->MajorFunction = IRP_MJ_SET_INFORMATION;
121
122 IrpSp->DeviceObject = DeviceObject;// Irp栈中保存的设备对象是文件系统设备对象
123 IrpSp->FileObject = FileObject; //
124
125 IrpSp->Parameters.SetFile.FileObject = FileObject;
126 IrpSp->Parameters.SetFile.Length = sizeof(FILE_DISPOSITION_INFORMATION);
127 IrpSp->Parameters.SetFile.FileObject = FileObject;
128
129 IrpSp->Parameters.SetFile.FileInformationClass = FileDispositionInformation;
130
131
132 //将文件的物理页面的属性先保存起来
133 //文件对象指向的物理页(IRP会对他进行检测,如果不为空不删除文件)
134 if (MmIsAddressValid(FileObject->SectionObjectPointer))
135 {
136 ImageSectionObject = FileObject->SectionObjectPointer->ImageSectionObject;
137 DataSectionObject = FileObject->SectionObjectPointer->DataSectionObject;
138 SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
139
140 FileObject->SectionObjectPointer->ImageSectionObject = NULL;
141 FileObject->SectionObjectPointer->DataSectionObject = NULL;
142 FileObject->SectionObjectPointer->SharedCacheMap = NULL;
143 }
144
145
146
147
148 IoSetCompletionRoutine(Irp,IrpCompleteRoutine,&hEvent,TRUE,TRUE,TRUE);
149
150
151 IoCallDriver(DeviceObject,Irp);
152
153 KeWaitForSingleObject(&hEvent,Executive,KernelMode,TRUE,NULL);
154
155
156
157
158 //恢复环境
159 if (MmIsAddressValid(FileObject->SectionObjectPointer))
160 {
161 FileObject->SectionObjectPointer->ImageSectionObject = ImageSectionObject;
162 FileObject->SectionObjectPointer->DataSectionObject = DataSectionObject;
163 FileObject->SectionObjectPointer->SharedCacheMap = SharedCacheMap;
164 }
165
166
167
168 ObDereferenceObject(FileObject);
169 }
170
171
172
173 BOOLEAN
174 SKillStripFileAttributes(HANDLE hFile)
175 {
176 NTSTATUS Status = STATUS_SUCCESS;
177 PFILE_OBJECT FileObject;
178 PDEVICE_OBJECT DeviceObject;
179 PIRP Irp;
180 KEVENT kEvent;
181 FILE_BASIC_INFORMATION FileBaseInfor;
182 IO_STATUS_BLOCK Iosb;
183 PIO_STACK_LOCATION IrpSp;
184
185 BOOLEAN bInit = FALSE;
186
187
188
189 Status = ObReferenceObjectByHandle(hFile,
190 DELETE,
191 *IoFileObjectType,
192 KernelMode,
193 &FileObject,
194 NULL);
195
196 if (!NT_SUCCESS(Status))
197 {
198 return FALSE;
199 }
200
201 DeviceObject = IoGetRelatedDeviceObject(FileObject); //VPB->DeviceObject
202 Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE);
203
204 if (Irp == NULL)
205 {
206 ObDereferenceObject(FileObject);
207 return FALSE;
208 }
209
210 KeInitializeEvent(&kEvent, SynchronizationEvent, FALSE);
211
212 memset(&FileBaseInfor,0,sizeof(FILE_BASIC_INFORMATION));
213
214 FileBaseInfor.FileAttributes = FILE_ATTRIBUTE_NORMAL;
215 Irp->AssociatedIrp.SystemBuffer = &FileBaseInfor;
216 Irp->UserEvent = &kEvent;
217 Irp->UserIosb = &Iosb;
218 Irp->Tail.Overlay.OriginalFileObject = FileObject;
219 Irp->Tail.Overlay.Thread = (PETHREAD)KeGetCurrentThread();
220 Irp->RequestorMode = KernelMode;
221
222 IrpSp = IoGetNextIrpStackLocation(Irp);
223 IrpSp->MajorFunction = IRP_MJ_SET_INFORMATION;
224 IrpSp->DeviceObject = DeviceObject;
225 IrpSp->FileObject = FileObject;
226 IrpSp->Parameters.SetFile.Length = sizeof(FILE_BASIC_INFORMATION);
227 IrpSp->Parameters.SetFile.FileInformationClass = FileBasicInformation;
228
229
230 IoSetCompletionRoutine(
231 Irp,
232 IrpCompleteRoutine,
233 &kEvent,
234 TRUE,
235 TRUE,
236 TRUE);
237
238 IoCallDriver(DeviceObject,Irp);
239 KeWaitForSingleObject(&kEvent, Executive, KernelMode, TRUE, NULL);
240 ObDereferenceObject(FileObject);
241
242 return TRUE;
243 }
244
245
246
247 NTSTATUS
248 IrpCompleteRoutine(PDEVICE_OBJECT DeviceObject,PIRP Irp,PVOID Context)
249 {
250 KeSetEvent(Irp->UserEvent,IO_NO_INCREMENT,FALSE);
251
252 IoFreeIrp(Irp);
253
254 return STATUS_MORE_PROCESSING_REQUIRED;
255
256 }

漫谈IRP的更多相关文章

  1. 【道德经】漫谈实体、对象、DTO及AutoMapper的使用

    写在前面 实体和值对象 实体和对象 故常无欲以观其妙,常有欲以观其徼 初始实体和演化实体 代码中的DTO AutoMapper实体转换 后记 实体(Entity).对象(Object).DTO(Dat ...

  2. CSS实现水平|垂直居中漫谈

    利用CSS进行元素的水平居中,比较简单,手到擒来:行级元素设置其父元素的text-align center,块级元素设置其本身的left 和 right margins为auto即可.而撸起垂直居中, ...

  3. 【转】漫谈iOS程序的证书和签名机制

    转自:漫谈iOS程序的证书和签名机制 接触iOS开发半年,曾经也被这个主题坑的摸不着头脑,也在淘宝上买过企业证书签名这些服务,有大神都做了一个全自动的发布打包(不过此大神现在不卖企业证书了),甚是羡慕 ...

  4. UP board 漫谈(1)——从Atom到UP Board

    title: UP board 漫谈(1)--从Atom到UP Board date: 2016-12-26 12:33:03 tags: UP board categories: 开发板 perma ...

  5. IRP完成例程返回值理解

    第一,完成例程里面直接返回STATUS_SUCCESS,这时候IRP已经继续向上回卷,失去了对IRP的控制. 第二,完成例程里面返回STATUS_MORE_PROCESSING_REQUIRED,仍具 ...

  6. 漫谈C++11 Thread库之原子操作

    我在之前一篇博文<漫谈C++11 Thread库之使写多线程程序>中,着重介绍了<thread>头文件中的std::thread类以及其上的一些基本操作,至此我们动手写多线程程 ...

  7. 漫谈可视化Prefuse(六)---改动源码定制边粗细

    可视化一路走来,体会很多:博客一路写来,收获颇丰:代码一路码来,思路越来越清晰.终究还是明白了一句古话:纸上得来终觉浅,绝知此事要躬行. 跌跌撞撞整合了个可视化小tool,零零碎碎结交了众多的志同道合 ...

  8. 漫谈可视化Prefuse(五)---一款属于我自己的可视化工具

    伴随着前期的基础积累,翻过API,读过一些Demo,总觉得自己已经摸透了Prefuse,小打小闹似乎已经无法满足内心膨胀的自己.还记得儿时看的<武状元苏乞儿>中降龙十八掌最后一张居然是空白 ...

  9. 漫谈可视化Prefuse(四)---被玩坏的Prefuse API

    这个双12,别人都在抢红包.逛淘宝.上京东,我选择再续我的“漫谈可视化”系列(好了,不装了,其实是郎中羞涩...) 上篇<漫谈可视化Prefuse(三)---Prefuse API数据结构阅读有 ...

随机推荐

  1. [cf1217F]Forced Online Queries Problem

    可以用并查集维护连通性,删除可以用按置合并并查集,但删掉一条边后无法再维护两点的联通性了(因为产生环的边是不加入的)暴力思路是, 考虑前i个操作后边的集合,暴力加入即可,但复杂度是$o(n^2)$的用 ...

  2. [bzoj3170]松鼠聚会

    这个距离就是切比雪夫距离,有一个神奇的东西是说将(x,y)变成(x+y,x-y),然后就是曼哈顿距离,因此转化后对x坐标和y坐标分别统计排序和求和(求前缀和预处理+二分) 1 #include< ...

  3. 推荐几款谷歌浏览器(chrome)超实用的插件

    1.github加速器 在谷歌应用商店搜索"Github加速器",安装即可. 说明:在国内访问github有时候非常慢,是让人非常头疼的一件事,安装这个插件后 大大加快github ...

  4. [ARC098B] Xor Sum 2

    关于异或运算和代数和运算有很不错的性质: \(xor_{i = 1} ^ {n}a_i \leq \sum_{i = 1} ^ n a_i\) 所以我们考虑一段区间按题目来说是合法的,即 \(xor_ ...

  5. JOI 2020 Final 题解

    T1. 只不过是长的领带 大水题,把 \(a_i,b_i\) 从小到大排序. 发现最优方案只可能是大的 \(a_i\) 跟大的 \(b_i\) 匹配,小的 \(a_i\) 与小的 \(b_i\) 匹配 ...

  6. python20判断变量是否存在

    python中检测某个变量是否有定义 第一种方法使用内置函数locals(): locals():获取已定义对象字典 'testvar' in locals().keys() 第二种方法使用内置函数d ...

  7. 64-Unique Binary Search Trees

    96. Unique Binary Search Trees My Submissions Question Editorial Solution Total Accepted: 82788 Tota ...

  8. 使用Postman轻松实现接口数据关联

    Postman Postman是一款非常流行的HTTP(s)接口测试工具,入门简单,界面美观,功能强大.作为一个测试/开发工程师,这是一款必须要会用的工具.今天以一个实际的案例,来介绍下Postman ...

  9. 日常Java 2021/9/28

    字符串反转 package m; public class m { public static void main(String[] args) { //定义一个字符串 String str = &q ...

  10. HashMap有几种遍历方法?推荐使用哪种?

    本文已收录<面试精选>系列,Gitee 开源地址:https://gitee.com/mydb/interview HashMap 的遍历方法有很多种,不同的 JDK 版本有不同的写法,其 ...