1 /*
2 * COPYRIGHT: See COPYRIGHT.TXT
3 * PROJECT: Ext2 File System Driver for WinNT/2K/XP
4 * FILE: dispatch.c
5 * PROGRAMMER: Matt Wu <mattwu@163.com>
6 * HOMEPAGE: http://www.ext2fsd.com
7 * UPDATE HISTORY:
8 */
9
10 /* INCLUDES *****************************************************************/
11
12 #include "ext2fs.h"
13
14 /* GLOBALS ***************************************************************/
15
16 extern PEXT2_GLOBAL Ext2Global;
17
18 /* DEFINITIONS *************************************************************/
19
20 #ifdef ALLOC_PRAGMA
21 #pragma alloc_text(PAGE, Ext2QueueRequest)
22 #pragma alloc_text(PAGE, Ext2DeQueueRequest)
23 #endif
24
25 /*
26 * Ext2OplockComplete
27 *
28 * callback routine of FsRtlCheckOplock when an oplock break has
29 * completed, allowing an Irp to resume execution.
30 *
31 * Arguments:
32 *
33 * Context: the IrpContext to be queued
34 * Irp: the I/O request packet
35 *
36 * Return Value:
37 * N/A
38 */
39
40 #ifdef __REACTOS__
41 VOID NTAPI
42 #else
43 VOID
44 #endif
Ext2OplockComplete(IN PVOID Context,IN PIRP Irp)45 Ext2OplockComplete (
46 IN PVOID Context,
47 IN PIRP Irp
48 )
49 {
50 //
51 // Check on the return value in the Irp.
52 //
53
54 if (Irp->IoStatus.Status == STATUS_SUCCESS) {
55
56 //
57 // queue the Irp context in the workqueue.
58 //
59
60 Ext2QueueRequest((PEXT2_IRP_CONTEXT)Context);
61
62 } else {
63
64 //
65 // complete the request in case of failure
66 //
67
68 Ext2CompleteIrpContext( (PEXT2_IRP_CONTEXT) Context,
69 Irp->IoStatus.Status );
70 }
71
72 return;
73 }
74
75
76 /*
77 * Ext2LockIrp
78 *
79 * performs buffer locking if we need pend the process of the Irp
80 *
81 * Arguments:
82 * Context: the irp context
83 * Irp: the I/O request packet.
84 *
85 * Return Value:
86 * N/A
87 */
88
89 #ifdef __REACTOS__
90 VOID NTAPI
91 #else
92 VOID
93 #endif
Ext2LockIrp(IN PVOID Context,IN PIRP Irp)94 Ext2LockIrp (
95 IN PVOID Context,
96 IN PIRP Irp
97 )
98 {
99 PIO_STACK_LOCATION IrpSp;
100 PEXT2_IRP_CONTEXT IrpContext;
101
102 if (Irp == NULL) {
103 return;
104 }
105
106 IrpSp = IoGetCurrentIrpStackLocation(Irp);
107
108 IrpContext = (PEXT2_IRP_CONTEXT) Context;
109
110 if ( IrpContext->MajorFunction == IRP_MJ_READ ||
111 IrpContext->MajorFunction == IRP_MJ_WRITE ) {
112
113 //
114 // lock the user's buffer to MDL, if the I/O is bufferred
115 //
116
117 if (!IsFlagOn(IrpContext->MinorFunction, IRP_MN_MDL)) {
118
119 Ext2LockUserBuffer( Irp, IrpSp->Parameters.Write.Length,
120 (IrpContext->MajorFunction == IRP_MJ_READ) ?
121 IoWriteAccess : IoReadAccess );
122 }
123
124 } else if (IrpContext->MajorFunction == IRP_MJ_DIRECTORY_CONTROL
125 && IrpContext->MinorFunction == IRP_MN_QUERY_DIRECTORY) {
126
127 ULONG Length = ((PEXTENDED_IO_STACK_LOCATION) IrpSp)->Parameters.QueryDirectory.Length;
128 Ext2LockUserBuffer(Irp, Length, IoWriteAccess);
129
130 } else if (IrpContext->MajorFunction == IRP_MJ_QUERY_EA) {
131
132 ULONG Length = ((PEXTENDED_IO_STACK_LOCATION) IrpSp)->Parameters.QueryEa.Length;
133 Ext2LockUserBuffer(Irp, Length, IoWriteAccess);
134
135 } else if (IrpContext->MajorFunction == IRP_MJ_SET_EA) {
136 ULONG Length = ((PEXTENDED_IO_STACK_LOCATION) IrpSp)->Parameters.SetEa.Length;
137 Ext2LockUserBuffer(Irp, Length, IoReadAccess);
138
139 } else if ( (IrpContext->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL) &&
140 (IrpContext->MinorFunction == IRP_MN_USER_FS_REQUEST) ) {
141 PEXTENDED_IO_STACK_LOCATION EIrpSp = (PEXTENDED_IO_STACK_LOCATION)IrpSp;
142 if ( (EIrpSp->Parameters.FileSystemControl.FsControlCode == FSCTL_GET_VOLUME_BITMAP) ||
143 (EIrpSp->Parameters.FileSystemControl.FsControlCode == FSCTL_GET_RETRIEVAL_POINTERS) ||
144 (EIrpSp->Parameters.FileSystemControl.FsControlCode == FSCTL_GET_RETRIEVAL_POINTER_BASE) ) {
145 ULONG Length = EIrpSp->Parameters.FileSystemControl.OutputBufferLength;
146 Ext2LockUserBuffer(Irp, Length, IoWriteAccess);
147 }
148 }
149
150 // Mark the request as pending status
151
152 IoMarkIrpPending( Irp );
153
154 return;
155 }
156
157 NTSTATUS
Ext2QueueRequest(IN PEXT2_IRP_CONTEXT IrpContext)158 Ext2QueueRequest (IN PEXT2_IRP_CONTEXT IrpContext)
159 {
160 ASSERT(IrpContext);
161
162 ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
163 (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
164
165 /* set the flags of "can wait" and "queued" */
166 SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
167 SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED);
168
169 /* make sure the buffer is kept valid in system context */
170 Ext2LockIrp(IrpContext, IrpContext->Irp);
171
172 /* initialize workite*/
173 ExInitializeWorkItem(
174 &IrpContext->WorkQueueItem,
175 Ext2DeQueueRequest,
176 IrpContext );
177
178 /* dispatch it */
179 ExQueueWorkItem(&IrpContext->WorkQueueItem, CriticalWorkQueue);
180
181 return STATUS_PENDING;
182 }
183
184
185 #ifdef __REACTOS__
186 VOID NTAPI
187 #else
188 VOID
189 #endif
Ext2DeQueueRequest(IN PVOID Context)190 Ext2DeQueueRequest (IN PVOID Context)
191 {
192 PEXT2_IRP_CONTEXT IrpContext;
193
194 IrpContext = (PEXT2_IRP_CONTEXT) Context;
195
196 ASSERT(IrpContext);
197
198 ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
199 (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
200
201 _SEH2_TRY {
202
203 _SEH2_TRY {
204
205 FsRtlEnterFileSystem();
206
207 if (!IrpContext->IsTopLevel) {
208 IoSetTopLevelIrp((PIRP) FSRTL_FSP_TOP_LEVEL_IRP);
209 }
210
211 Ext2DispatchRequest(IrpContext);
212
213 } _SEH2_EXCEPT (Ext2ExceptionFilter(IrpContext, _SEH2_GetExceptionInformation())) {
214
215 Ext2ExceptionHandler(IrpContext);
216 } _SEH2_END;
217
218 } _SEH2_FINALLY {
219
220 IoSetTopLevelIrp(NULL);
221
222 FsRtlExitFileSystem();
223 } _SEH2_END;
224 }
225
226
227 NTSTATUS
Ext2DispatchRequest(IN PEXT2_IRP_CONTEXT IrpContext)228 Ext2DispatchRequest (IN PEXT2_IRP_CONTEXT IrpContext)
229 {
230 ASSERT(IrpContext);
231
232 ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
233 (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
234
235 switch (IrpContext->MajorFunction) {
236
237 case IRP_MJ_CREATE:
238 return Ext2Create(IrpContext);
239
240 case IRP_MJ_CLOSE:
241 return Ext2Close(IrpContext);
242
243 case IRP_MJ_READ:
244 return Ext2Read(IrpContext);
245
246 case IRP_MJ_WRITE:
247 return Ext2Write(IrpContext);
248
249 case IRP_MJ_FLUSH_BUFFERS:
250 return Ext2Flush(IrpContext);
251
252 case IRP_MJ_QUERY_INFORMATION:
253 return Ext2QueryFileInformation(IrpContext);
254
255 case IRP_MJ_SET_INFORMATION:
256 return Ext2SetFileInformation(IrpContext);
257
258 case IRP_MJ_QUERY_VOLUME_INFORMATION:
259 return Ext2QueryVolumeInformation(IrpContext);
260
261 case IRP_MJ_SET_VOLUME_INFORMATION:
262 return Ext2SetVolumeInformation(IrpContext);
263
264 case IRP_MJ_DIRECTORY_CONTROL:
265 return Ext2DirectoryControl(IrpContext);
266
267 case IRP_MJ_FILE_SYSTEM_CONTROL:
268 return Ext2FileSystemControl(IrpContext);
269
270 case IRP_MJ_DEVICE_CONTROL:
271 return Ext2DeviceControl(IrpContext);
272
273 case IRP_MJ_LOCK_CONTROL:
274 return Ext2LockControl(IrpContext);
275
276 case IRP_MJ_CLEANUP:
277 return Ext2Cleanup(IrpContext);
278
279 case IRP_MJ_SHUTDOWN:
280 return Ext2ShutDown(IrpContext);
281
282 case IRP_MJ_QUERY_EA:
283 return Ext2QueryEa(IrpContext);
284
285 case IRP_MJ_SET_EA:
286 return Ext2SetEa(IrpContext);
287
288 #if (_WIN32_WINNT >= 0x0500)
289 case IRP_MJ_PNP:
290 return Ext2Pnp(IrpContext);
291 #endif //(_WIN32_WINNT >= 0x0500)
292 default:
293 DEBUG(DL_ERR, ( "Ext2DispatchRequest: Unexpected major function: %xh\n",
294 IrpContext->MajorFunction));
295
296 Ext2CompleteIrpContext(IrpContext, STATUS_DRIVER_INTERNAL_ERROR);
297
298 return STATUS_DRIVER_INTERNAL_ERROR;
299 }
300 }
301
302
303 #ifdef __REACTOS__
304 NTSTATUS NTAPI
305 #else
306 NTSTATUS
307 #endif
Ext2BuildRequest(PDEVICE_OBJECT DeviceObject,PIRP Irp)308 Ext2BuildRequest (PDEVICE_OBJECT DeviceObject, PIRP Irp)
309 {
310 BOOLEAN AtIrqlPassiveLevel = FALSE;
311 BOOLEAN IsTopLevelIrp = FALSE;
312 PEXT2_IRP_CONTEXT IrpContext = NULL;
313 NTSTATUS Status = STATUS_UNSUCCESSFUL;
314
315 _SEH2_TRY {
316
317 _SEH2_TRY {
318
319 #if EXT2_DEBUG
320 Ext2DbgPrintCall(DeviceObject, Irp);
321 #endif
322
323 AtIrqlPassiveLevel = (KeGetCurrentIrql() == PASSIVE_LEVEL);
324
325 if (AtIrqlPassiveLevel) {
326 FsRtlEnterFileSystem();
327 }
328
329 if (!IoGetTopLevelIrp()) {
330 IsTopLevelIrp = TRUE;
331 IoSetTopLevelIrp(Irp);
332 }
333
334 IrpContext = Ext2AllocateIrpContext(DeviceObject, Irp);
335
336 if (!IrpContext) {
337
338 Status = STATUS_INSUFFICIENT_RESOURCES;
339 Irp->IoStatus.Status = Status;
340
341 Ext2CompleteRequest(Irp, TRUE, IO_NO_INCREMENT);
342
343 } else {
344
345 if ((IrpContext->MajorFunction == IRP_MJ_CREATE) &&
346 !AtIrqlPassiveLevel) {
347
348 DbgBreak();
349 }
350
351 Status = Ext2DispatchRequest(IrpContext);
352 }
353 } _SEH2_EXCEPT (Ext2ExceptionFilter(IrpContext, _SEH2_GetExceptionInformation())) {
354
355 Status = Ext2ExceptionHandler(IrpContext);
356 } _SEH2_END;
357
358 } _SEH2_FINALLY {
359
360 if (IsTopLevelIrp) {
361 IoSetTopLevelIrp(NULL);
362 }
363
364 if (AtIrqlPassiveLevel) {
365 FsRtlExitFileSystem();
366 }
367 } _SEH2_END;
368
369 return Status;
370 }
371