2 * COPYRIGHT: See COPYRIGHT.TXT
3 * PROJECT: Ext2 File System Driver for WinNT/2K/XP
5 * PROGRAMMER: Matt Wu <mattwu@163.com>
6 * HOMEPAGE: http://www.ext2fsd.com
10 /* INCLUDES *****************************************************************/
14 /* GLOBALS ***************************************************************/
16 extern PEXT2_GLOBAL Ext2Global
;
18 /* DEFINITIONS *************************************************************/
21 #pragma alloc_text(PAGE, Ext2QueueRequest)
22 #pragma alloc_text(PAGE, Ext2DeQueueRequest)
28 * callback routine of FsRtlCheckOplock when an oplock break has
29 * completed, allowing an Irp to resume execution.
33 * Context: the IrpContext to be queued
34 * Irp: the I/O request packet
47 // Check on the return value in the Irp.
50 if (Irp
->IoStatus
.Status
== STATUS_SUCCESS
) {
53 // queue the Irp context in the workqueue.
56 Ext2QueueRequest((PEXT2_IRP_CONTEXT
)Context
);
61 // complete the request in case of failure
64 Ext2CompleteIrpContext( (PEXT2_IRP_CONTEXT
) Context
,
65 Irp
->IoStatus
.Status
);
75 * performs buffer locking if we need pend the process of the Irp
78 * Context: the irp context
79 * Irp: the I/O request packet.
91 PIO_STACK_LOCATION IrpSp
;
92 PEXT2_IRP_CONTEXT IrpContext
;
98 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
100 IrpContext
= (PEXT2_IRP_CONTEXT
) Context
;
102 if ( IrpContext
->MajorFunction
== IRP_MJ_READ
||
103 IrpContext
->MajorFunction
== IRP_MJ_WRITE
) {
106 // lock the user's buffer to MDL, if the I/O is bufferred
109 if (!IsFlagOn(IrpContext
->MinorFunction
, IRP_MN_MDL
)) {
111 Ext2LockUserBuffer( Irp
, IrpSp
->Parameters
.Write
.Length
,
112 (IrpContext
->MajorFunction
== IRP_MJ_READ
) ?
113 IoWriteAccess
: IoReadAccess
);
116 } else if (IrpContext
->MajorFunction
== IRP_MJ_DIRECTORY_CONTROL
117 && IrpContext
->MinorFunction
== IRP_MN_QUERY_DIRECTORY
) {
119 ULONG Length
= ((PEXTENDED_IO_STACK_LOCATION
) IrpSp
)->Parameters
.QueryDirectory
.Length
;
120 Ext2LockUserBuffer(Irp
, Length
, IoWriteAccess
);
122 } else if (IrpContext
->MajorFunction
== IRP_MJ_QUERY_EA
) {
124 ULONG Length
= ((PEXTENDED_IO_STACK_LOCATION
) IrpSp
)->Parameters
.QueryEa
.Length
;
125 Ext2LockUserBuffer(Irp
, Length
, IoWriteAccess
);
127 } else if (IrpContext
->MajorFunction
== IRP_MJ_SET_EA
) {
128 ULONG Length
= ((PEXTENDED_IO_STACK_LOCATION
) IrpSp
)->Parameters
.SetEa
.Length
;
129 Ext2LockUserBuffer(Irp
, Length
, IoReadAccess
);
131 } else if ( (IrpContext
->MajorFunction
== IRP_MJ_FILE_SYSTEM_CONTROL
) &&
132 (IrpContext
->MinorFunction
== IRP_MN_USER_FS_REQUEST
) ) {
133 PEXTENDED_IO_STACK_LOCATION EIrpSp
= (PEXTENDED_IO_STACK_LOCATION
)IrpSp
;
134 if ( (EIrpSp
->Parameters
.FileSystemControl
.FsControlCode
== FSCTL_GET_VOLUME_BITMAP
) ||
135 (EIrpSp
->Parameters
.FileSystemControl
.FsControlCode
== FSCTL_GET_RETRIEVAL_POINTERS
) ||
136 (EIrpSp
->Parameters
.FileSystemControl
.FsControlCode
== FSCTL_GET_RETRIEVAL_POINTER_BASE
) ) {
137 ULONG Length
= EIrpSp
->Parameters
.FileSystemControl
.OutputBufferLength
;
138 Ext2LockUserBuffer(Irp
, Length
, IoWriteAccess
);
142 // Mark the request as pending status
144 IoMarkIrpPending( Irp
);
150 Ext2QueueRequest (IN PEXT2_IRP_CONTEXT IrpContext
)
154 ASSERT((IrpContext
->Identifier
.Type
== EXT2ICX
) &&
155 (IrpContext
->Identifier
.Size
== sizeof(EXT2_IRP_CONTEXT
)));
157 /* set the flags of "can wait" and "queued" */
158 SetFlag(IrpContext
->Flags
, IRP_CONTEXT_FLAG_WAIT
);
159 SetFlag(IrpContext
->Flags
, IRP_CONTEXT_FLAG_REQUEUED
);
161 /* make sure the buffer is kept valid in system context */
162 Ext2LockIrp(IrpContext
, IrpContext
->Irp
);
164 /* initialize workite*/
165 ExInitializeWorkItem(
166 &IrpContext
->WorkQueueItem
,
171 ExQueueWorkItem(&IrpContext
->WorkQueueItem
, CriticalWorkQueue
);
173 return STATUS_PENDING
;
178 Ext2DeQueueRequest (IN PVOID Context
)
180 PEXT2_IRP_CONTEXT IrpContext
;
182 IrpContext
= (PEXT2_IRP_CONTEXT
) Context
;
186 ASSERT((IrpContext
->Identifier
.Type
== EXT2ICX
) &&
187 (IrpContext
->Identifier
.Size
== sizeof(EXT2_IRP_CONTEXT
)));
193 FsRtlEnterFileSystem();
195 if (!IrpContext
->IsTopLevel
) {
196 IoSetTopLevelIrp((PIRP
) FSRTL_FSP_TOP_LEVEL_IRP
);
199 Ext2DispatchRequest(IrpContext
);
201 } _SEH2_EXCEPT (Ext2ExceptionFilter(IrpContext
, _SEH2_GetExceptionInformation())) {
203 Ext2ExceptionHandler(IrpContext
);
208 IoSetTopLevelIrp(NULL
);
210 FsRtlExitFileSystem();
216 Ext2DispatchRequest (IN PEXT2_IRP_CONTEXT IrpContext
)
220 ASSERT((IrpContext
->Identifier
.Type
== EXT2ICX
) &&
221 (IrpContext
->Identifier
.Size
== sizeof(EXT2_IRP_CONTEXT
)));
223 switch (IrpContext
->MajorFunction
) {
226 return Ext2Create(IrpContext
);
229 return Ext2Close(IrpContext
);
232 return Ext2Read(IrpContext
);
235 return Ext2Write(IrpContext
);
237 case IRP_MJ_FLUSH_BUFFERS
:
238 return Ext2Flush(IrpContext
);
240 case IRP_MJ_QUERY_INFORMATION
:
241 return Ext2QueryFileInformation(IrpContext
);
243 case IRP_MJ_SET_INFORMATION
:
244 return Ext2SetFileInformation(IrpContext
);
246 case IRP_MJ_QUERY_VOLUME_INFORMATION
:
247 return Ext2QueryVolumeInformation(IrpContext
);
249 case IRP_MJ_SET_VOLUME_INFORMATION
:
250 return Ext2SetVolumeInformation(IrpContext
);
252 case IRP_MJ_DIRECTORY_CONTROL
:
253 return Ext2DirectoryControl(IrpContext
);
255 case IRP_MJ_FILE_SYSTEM_CONTROL
:
256 return Ext2FileSystemControl(IrpContext
);
258 case IRP_MJ_DEVICE_CONTROL
:
259 return Ext2DeviceControl(IrpContext
);
261 case IRP_MJ_LOCK_CONTROL
:
262 return Ext2LockControl(IrpContext
);
265 return Ext2Cleanup(IrpContext
);
267 case IRP_MJ_SHUTDOWN
:
268 return Ext2ShutDown(IrpContext
);
270 #if (_WIN32_WINNT >= 0x0500)
272 return Ext2Pnp(IrpContext
);
273 #endif //(_WIN32_WINNT >= 0x0500)
275 DEBUG(DL_ERR
, ( "Ext2DispatchRequest: Unexpected major function: %xh\n",
276 IrpContext
->MajorFunction
));
278 Ext2CompleteIrpContext(IrpContext
, STATUS_DRIVER_INTERNAL_ERROR
);
280 return STATUS_DRIVER_INTERNAL_ERROR
;
286 Ext2BuildRequest (PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
288 BOOLEAN AtIrqlPassiveLevel
= FALSE
;
289 BOOLEAN IsTopLevelIrp
= FALSE
;
290 PEXT2_IRP_CONTEXT IrpContext
= NULL
;
291 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
298 Ext2DbgPrintCall(DeviceObject
, Irp
);
301 AtIrqlPassiveLevel
= (KeGetCurrentIrql() == PASSIVE_LEVEL
);
303 if (AtIrqlPassiveLevel
) {
304 FsRtlEnterFileSystem();
307 if (!IoGetTopLevelIrp()) {
308 IsTopLevelIrp
= TRUE
;
309 IoSetTopLevelIrp(Irp
);
312 IrpContext
= Ext2AllocateIrpContext(DeviceObject
, Irp
);
316 Status
= STATUS_INSUFFICIENT_RESOURCES
;
317 Irp
->IoStatus
.Status
= Status
;
319 Ext2CompleteRequest(Irp
, TRUE
, IO_NO_INCREMENT
);
323 if ((IrpContext
->MajorFunction
== IRP_MJ_CREATE
) &&
324 !AtIrqlPassiveLevel
) {
329 Status
= Ext2DispatchRequest(IrpContext
);
331 } _SEH2_EXCEPT (Ext2ExceptionFilter(IrpContext
, _SEH2_GetExceptionInformation())) {
333 Status
= Ext2ExceptionHandler(IrpContext
);
339 IoSetTopLevelIrp(NULL
);
342 if (AtIrqlPassiveLevel
) {
343 FsRtlExitFileSystem();