[PSDK]
[reactos.git] / reactos / drivers / filesystems / ext2_new / src / dispatch.c
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 VOID NTAPI
41 Ext2OplockComplete (
42 IN PVOID Context,
43 IN PIRP Irp
44 )
45 {
46 //
47 // Check on the return value in the Irp.
48 //
49
50 if (Irp->IoStatus.Status == STATUS_SUCCESS) {
51
52 //
53 // queue the Irp context in the workqueue.
54 //
55
56 Ext2QueueRequest((PEXT2_IRP_CONTEXT)Context);
57
58 } else {
59
60 //
61 // complete the request in case of failure
62 //
63
64 Ext2CompleteIrpContext( (PEXT2_IRP_CONTEXT) Context,
65 Irp->IoStatus.Status );
66 }
67
68 return;
69 }
70
71
72 /*
73 * Ext2LockIrp
74 *
75 * performs buffer locking if we need pend the process of the Irp
76 *
77 * Arguments:
78 * Context: the irp context
79 * Irp: the I/O request packet.
80 *
81 * Return Value:
82 * N/A
83 */
84
85 VOID NTAPI
86 Ext2LockIrp (
87 IN PVOID Context,
88 IN PIRP Irp
89 )
90 {
91 PIO_STACK_LOCATION IrpSp;
92 PEXT2_IRP_CONTEXT IrpContext;
93
94 if (Irp == NULL) {
95 return;
96 }
97
98 IrpSp = IoGetCurrentIrpStackLocation(Irp);
99
100 IrpContext = (PEXT2_IRP_CONTEXT) Context;
101
102 if ( IrpContext->MajorFunction == IRP_MJ_READ ||
103 IrpContext->MajorFunction == IRP_MJ_WRITE ) {
104
105 //
106 // lock the user's buffer to MDL, if the I/O is bufferred
107 //
108
109 if (!IsFlagOn(IrpContext->MinorFunction, IRP_MN_MDL)) {
110
111 Ext2LockUserBuffer( Irp, IrpSp->Parameters.Write.Length,
112 (IrpContext->MajorFunction == IRP_MJ_READ) ?
113 IoWriteAccess : IoReadAccess );
114 }
115
116 } else if (IrpContext->MajorFunction == IRP_MJ_DIRECTORY_CONTROL
117 && IrpContext->MinorFunction == IRP_MN_QUERY_DIRECTORY) {
118
119 ULONG Length = ((PEXTENDED_IO_STACK_LOCATION) IrpSp)->Parameters.QueryDirectory.Length;
120 Ext2LockUserBuffer(Irp, Length, IoWriteAccess);
121
122 } else if (IrpContext->MajorFunction == IRP_MJ_QUERY_EA) {
123
124 ULONG Length = ((PEXTENDED_IO_STACK_LOCATION) IrpSp)->Parameters.QueryEa.Length;
125 Ext2LockUserBuffer(Irp, Length, IoWriteAccess);
126
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);
130
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);
139 }
140 }
141
142 // Mark the request as pending status
143
144 IoMarkIrpPending( Irp );
145
146 return;
147 }
148
149 NTSTATUS
150 Ext2QueueRequest (IN PEXT2_IRP_CONTEXT IrpContext)
151 {
152 ASSERT(IrpContext);
153
154 ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
155 (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
156
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);
160
161 /* make sure the buffer is kept valid in system context */
162 Ext2LockIrp(IrpContext, IrpContext->Irp);
163
164 /* initialize workite*/
165 ExInitializeWorkItem(
166 &IrpContext->WorkQueueItem,
167 Ext2DeQueueRequest,
168 IrpContext );
169
170 /* dispatch it */
171 ExQueueWorkItem(&IrpContext->WorkQueueItem, CriticalWorkQueue);
172
173 return STATUS_PENDING;
174 }
175
176
177 VOID NTAPI
178 Ext2DeQueueRequest (IN PVOID Context)
179 {
180 PEXT2_IRP_CONTEXT IrpContext;
181
182 IrpContext = (PEXT2_IRP_CONTEXT) Context;
183
184 ASSERT(IrpContext);
185
186 ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
187 (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
188
189 _SEH2_TRY {
190
191 _SEH2_TRY {
192
193 FsRtlEnterFileSystem();
194
195 if (!IrpContext->IsTopLevel) {
196 IoSetTopLevelIrp((PIRP) FSRTL_FSP_TOP_LEVEL_IRP);
197 }
198
199 Ext2DispatchRequest(IrpContext);
200
201 } _SEH2_EXCEPT (Ext2ExceptionFilter(IrpContext, _SEH2_GetExceptionInformation())) {
202
203 Ext2ExceptionHandler(IrpContext);
204 } _SEH2_END;
205
206 } _SEH2_FINALLY {
207
208 IoSetTopLevelIrp(NULL);
209
210 FsRtlExitFileSystem();
211 } _SEH2_END;
212 }
213
214
215 NTSTATUS
216 Ext2DispatchRequest (IN PEXT2_IRP_CONTEXT IrpContext)
217 {
218 ASSERT(IrpContext);
219
220 ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
221 (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
222
223 switch (IrpContext->MajorFunction) {
224
225 case IRP_MJ_CREATE:
226 return Ext2Create(IrpContext);
227
228 case IRP_MJ_CLOSE:
229 return Ext2Close(IrpContext);
230
231 case IRP_MJ_READ:
232 return Ext2Read(IrpContext);
233
234 case IRP_MJ_WRITE:
235 return Ext2Write(IrpContext);
236
237 case IRP_MJ_FLUSH_BUFFERS:
238 return Ext2Flush(IrpContext);
239
240 case IRP_MJ_QUERY_INFORMATION:
241 return Ext2QueryFileInformation(IrpContext);
242
243 case IRP_MJ_SET_INFORMATION:
244 return Ext2SetFileInformation(IrpContext);
245
246 case IRP_MJ_QUERY_VOLUME_INFORMATION:
247 return Ext2QueryVolumeInformation(IrpContext);
248
249 case IRP_MJ_SET_VOLUME_INFORMATION:
250 return Ext2SetVolumeInformation(IrpContext);
251
252 case IRP_MJ_DIRECTORY_CONTROL:
253 return Ext2DirectoryControl(IrpContext);
254
255 case IRP_MJ_FILE_SYSTEM_CONTROL:
256 return Ext2FileSystemControl(IrpContext);
257
258 case IRP_MJ_DEVICE_CONTROL:
259 return Ext2DeviceControl(IrpContext);
260
261 case IRP_MJ_LOCK_CONTROL:
262 return Ext2LockControl(IrpContext);
263
264 case IRP_MJ_CLEANUP:
265 return Ext2Cleanup(IrpContext);
266
267 case IRP_MJ_SHUTDOWN:
268 return Ext2ShutDown(IrpContext);
269
270 #if (_WIN32_WINNT >= 0x0500)
271 case IRP_MJ_PNP:
272 return Ext2Pnp(IrpContext);
273 #endif //(_WIN32_WINNT >= 0x0500)
274 default:
275 DEBUG(DL_ERR, ( "Ext2DispatchRequest: Unexpected major function: %xh\n",
276 IrpContext->MajorFunction));
277
278 Ext2CompleteIrpContext(IrpContext, STATUS_DRIVER_INTERNAL_ERROR);
279
280 return STATUS_DRIVER_INTERNAL_ERROR;
281 }
282 }
283
284
285 NTSTATUS NTAPI
286 Ext2BuildRequest (PDEVICE_OBJECT DeviceObject, PIRP Irp)
287 {
288 BOOLEAN AtIrqlPassiveLevel = FALSE;
289 BOOLEAN IsTopLevelIrp = FALSE;
290 PEXT2_IRP_CONTEXT IrpContext = NULL;
291 NTSTATUS Status = STATUS_UNSUCCESSFUL;
292
293 _SEH2_TRY {
294
295 _SEH2_TRY {
296
297 #if EXT2_DEBUG
298 Ext2DbgPrintCall(DeviceObject, Irp);
299 #endif
300
301 AtIrqlPassiveLevel = (KeGetCurrentIrql() == PASSIVE_LEVEL);
302
303 if (AtIrqlPassiveLevel) {
304 FsRtlEnterFileSystem();
305 }
306
307 if (!IoGetTopLevelIrp()) {
308 IsTopLevelIrp = TRUE;
309 IoSetTopLevelIrp(Irp);
310 }
311
312 IrpContext = Ext2AllocateIrpContext(DeviceObject, Irp);
313
314 if (!IrpContext) {
315
316 Status = STATUS_INSUFFICIENT_RESOURCES;
317 Irp->IoStatus.Status = Status;
318
319 Ext2CompleteRequest(Irp, TRUE, IO_NO_INCREMENT);
320
321 } else {
322
323 if ((IrpContext->MajorFunction == IRP_MJ_CREATE) &&
324 !AtIrqlPassiveLevel) {
325
326 DbgBreak();
327 }
328
329 Status = Ext2DispatchRequest(IrpContext);
330 }
331 } _SEH2_EXCEPT (Ext2ExceptionFilter(IrpContext, _SEH2_GetExceptionInformation())) {
332
333 Status = Ext2ExceptionHandler(IrpContext);
334 } _SEH2_END;
335
336 } _SEH2_FINALLY {
337
338 if (IsTopLevelIrp) {
339 IoSetTopLevelIrp(NULL);
340 }
341
342 if (AtIrqlPassiveLevel) {
343 FsRtlExitFileSystem();
344 }
345 } _SEH2_END;
346
347 return Status;
348 }