xref: /reactos/drivers/filesystems/ext2/src/fastio.c (revision 8f9ef68e)
1 /*
2  * COPYRIGHT:        See COPYRIGHT.TXT
3  * PROJECT:          Ext2 File System Driver for WinNT/2K/XP
4  * FILE:             fastio.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 #define FASTIO_DEBUG_LEVEL DL_NVR
21 
22 
23 #ifdef ALLOC_PRAGMA
24 
25 #pragma alloc_text(PAGE, Ext2FastIoRead)
26 #pragma alloc_text(PAGE, Ext2FastIoWrite)
27 #pragma alloc_text(PAGE, Ext2FastIoCheckIfPossible)
28 #pragma alloc_text(PAGE, Ext2FastIoQueryBasicInfo)
29 #pragma alloc_text(PAGE, Ext2FastIoQueryStandardInfo)
30 #pragma alloc_text(PAGE, Ext2FastIoQueryNetworkOpenInfo)
31 #pragma alloc_text(PAGE, Ext2FastIoLock)
32 #pragma alloc_text(PAGE, Ext2FastIoUnlockSingle)
33 #pragma alloc_text(PAGE, Ext2FastIoUnlockAll)
34 #pragma alloc_text(PAGE, Ext2FastIoUnlockAll)
35 #endif
36 
37 FAST_IO_POSSIBLE
38 Ext2IsFastIoPossible(
39     IN PEXT2_FCB Fcb
40 )
41 {
42     FAST_IO_POSSIBLE IsPossible = FastIoIsNotPossible;
43 
44     if (!Fcb || !FsRtlOplockIsFastIoPossible(&Fcb->Oplock))
45         return IsPossible;
46 
47     IsPossible = FastIoIsQuestionable;
48 
49     if (!FsRtlAreThereCurrentFileLocks(&Fcb->FileLockAnchor)) {
50         if (!IsVcbReadOnly(Fcb->Vcb) && !FlagOn(Fcb->Vcb->Flags, VCB_VOLUME_LOCKED)) {
51             IsPossible = FastIoIsPossible;
52         }
53     }
54 
55     return IsPossible;
56 }
57 
58 
59 #ifdef __REACTOS__
60 BOOLEAN NTAPI
61 #else
62 BOOLEAN
63 #endif
64 Ext2FastIoCheckIfPossible (
65     IN PFILE_OBJECT         FileObject,
66     IN PLARGE_INTEGER       FileOffset,
67     IN ULONG                Length,
68     IN BOOLEAN              Wait,
69     IN ULONG                LockKey,
70     IN BOOLEAN              CheckForReadOperation,
71     OUT PIO_STATUS_BLOCK    IoStatus,
72     IN PDEVICE_OBJECT       DeviceObject
73 )
74 {
75     BOOLEAN          bPossible = FastIoIsNotPossible;
76     PEXT2_FCB        Fcb;
77     PEXT2_CCB        Ccb;
78     LARGE_INTEGER    lLength;
79 
80     lLength.QuadPart = Length;
81 
82     _SEH2_TRY {
83 
84         FsRtlEnterFileSystem();
85 
86         _SEH2_TRY {
87 
88             if (IsExt2FsDevice(DeviceObject)) {
89                 _SEH2_LEAVE;
90             }
91 
92             Fcb = (PEXT2_FCB) FileObject->FsContext;
93             if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB) {
94                 _SEH2_LEAVE;
95             }
96 
97             ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
98                    (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
99 
100             /* do nothing if target fie was deleted */
101             if (FlagOn(Fcb->Flags, FCB_DELETE_PENDING)) {
102                 _SEH2_LEAVE;
103             }
104 
105             if (IsDirectory(Fcb)) {
106                 _SEH2_LEAVE;
107             }
108 
109             Ccb = (PEXT2_CCB) FileObject->FsContext2;
110             if (Ccb == NULL) {
111                 _SEH2_LEAVE;
112             }
113 
114             if (CheckForReadOperation) {
115 
116                 bPossible = FsRtlFastCheckLockForRead(
117                                 &Fcb->FileLockAnchor,
118                                 FileOffset,
119                                 &lLength,
120                                 LockKey,
121                                 FileObject,
122                                 PsGetCurrentProcess());
123 
124             } else {
125 
126                 if (!IsVcbReadOnly(Fcb->Vcb)) {
127                     bPossible = FsRtlFastCheckLockForWrite(
128                                     &Fcb->FileLockAnchor,
129                                     FileOffset,
130                                     &lLength,
131                                     LockKey,
132                                     FileObject,
133                                     PsGetCurrentProcess());
134                 }
135             }
136 
137 #if EXT2_DEBUG
138             DEBUG(DL_INF, ("Ext2FastIIOCheckPossible: %s %s %wZ\n",
139                            Ext2GetCurrentProcessName(),
140                            "FASTIO_CHECK_IF_POSSIBLE",
141                            &Fcb->Mcb->FullName
142                           ));
143 
144             DEBUG(DL_INF, (
145                       "Ext2FastIIOCheckPossible: Offset: %I64xg Length: %xh Key: %u %s %s\n",
146                       FileOffset->QuadPart,
147                       Length,
148                       LockKey,
149                       (CheckForReadOperation ? "CheckForReadOperation:" :
150                        "CheckForWriteOperation:"),
151                       (bPossible ? "Succeeded" : "Failed")));
152 #endif
153 
154         } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
155             bPossible = FastIoIsNotPossible;
156         } _SEH2_END;
157 
158     } _SEH2_FINALLY {
159 
160         FsRtlExitFileSystem();
161     } _SEH2_END;
162 
163     return bPossible;
164 }
165 
166 
167 #ifdef __REACTOS__
168 BOOLEAN NTAPI
169 #else
170 BOOLEAN
171 #endif
172 Ext2FastIoRead (IN PFILE_OBJECT         FileObject,
173                 IN PLARGE_INTEGER       FileOffset,
174                 IN ULONG                Length,
175                 IN BOOLEAN              Wait,
176                 IN ULONG                LockKey,
177                 OUT PVOID               Buffer,
178                 OUT PIO_STATUS_BLOCK    IoStatus,
179                 IN PDEVICE_OBJECT       DeviceObject)
180 {
181     PEXT2_FCB    Fcb;
182     BOOLEAN      Status = FALSE;
183 
184     Fcb = (PEXT2_FCB) FileObject->FsContext;
185     if (Fcb == NULL) {
186         return FALSE;
187     }
188 
189     ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
190            (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
191 
192     Status = FsRtlCopyRead (
193                  FileObject, FileOffset, Length, Wait,
194                  LockKey, Buffer, IoStatus, DeviceObject);
195 
196     DEBUG(DL_IO, ("Ext2FastIoRead: %wZ Offset: %I64xh Length: %xh Key: %u Status: %d\n",
197                   &Fcb->Mcb->ShortName, FileOffset->QuadPart, Length, LockKey, Status));
198 
199     return Status;
200 }
201 
202 #ifdef __REACTOS__
203 BOOLEAN NTAPI
204 #else
205 BOOLEAN
206 #endif
207 Ext2FastIoWrite (
208     IN PFILE_OBJECT         FileObject,
209     IN PLARGE_INTEGER       FileOffset,
210     IN ULONG                Length,
211     IN BOOLEAN              Wait,
212     IN ULONG                LockKey,
213     OUT PVOID               Buffer,
214     OUT PIO_STATUS_BLOCK    IoStatus,
215     IN PDEVICE_OBJECT       DeviceObject)
216 {
217     PEXT2_FCB   Fcb = NULL;
218     BOOLEAN     Status = FALSE;
219     BOOLEAN     Locked = FALSE;
220 
221     Fcb = (PEXT2_FCB) FileObject->FsContext;
222     if (Fcb == NULL)
223         return FALSE;
224 
225     _SEH2_TRY {
226 
227         FsRtlEnterFileSystem();
228 
229         ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
230                (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
231 
232         if (IsVcbReadOnly(Fcb->Vcb)) {
233             _SEH2_LEAVE;
234         }
235 
236         if (!ExAcquireResourceSharedLite(Fcb->Header.Resource, Wait)) {
237             _SEH2_LEAVE;
238         }
239         Locked = TRUE;
240 
241         if (IsWritingToEof(*FileOffset) ||
242             Fcb->Header.ValidDataLength.QuadPart < FileOffset->QuadPart + Length ||
243             Fcb->Header.FileSize.QuadPart < FileOffset->QuadPart + Length ) {
244             Status = FALSE;
245             _SEH2_LEAVE;
246         }
247 
248         if (Locked) {
249             ExReleaseResourceLite(Fcb->Header.Resource);
250             Locked = FALSE;
251         }
252 
253         Status = FsRtlCopyWrite(FileObject, FileOffset, Length, Wait,
254                                 LockKey, Buffer, IoStatus, DeviceObject);
255         if (Status) {
256             if (IoStatus)
257                 Length = (ULONG)IoStatus->Information;
258         }
259 
260     } _SEH2_FINALLY {
261 
262         if (Locked) {
263             ExReleaseResourceLite(Fcb->Header.Resource);
264         }
265 
266         FsRtlExitFileSystem();
267     } _SEH2_END;
268 
269     DEBUG(DL_IO, ("Ext2FastIoWrite: %wZ Offset: %I64xh Length: %xh Key: %xh Status=%d\n",
270                   &Fcb->Mcb->ShortName,  FileOffset->QuadPart, Length, LockKey, Status));
271 
272     return Status;
273 }
274 
275 #ifdef __REACTOS__
276 BOOLEAN NTAPI
277 #else
278 BOOLEAN
279 #endif
280 Ext2FastIoQueryBasicInfo (
281     IN PFILE_OBJECT             FileObject,
282     IN BOOLEAN                  Wait,
283     OUT PFILE_BASIC_INFORMATION Buffer,
284     OUT PIO_STATUS_BLOCK        IoStatus,
285     IN PDEVICE_OBJECT           DeviceObject)
286 {
287     PEXT2_FCB   Fcb = NULL;
288     PEXT2_CCB   Ccb = NULL;
289     PEXT2_MCB   Mcb = NULL;
290     BOOLEAN     Status = FALSE;
291     BOOLEAN     FcbMainResourceAcquired = FALSE;
292 
293     _SEH2_TRY {
294 
295         FsRtlEnterFileSystem();
296 
297         _SEH2_TRY {
298 
299             if (IsExt2FsDevice(DeviceObject)) {
300                 IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;
301                 _SEH2_LEAVE;
302             }
303 
304             Fcb = (PEXT2_FCB) FileObject->FsContext;
305             if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB) {
306                 IoStatus->Status = STATUS_INVALID_PARAMETER;
307                 _SEH2_LEAVE;
308             }
309             Ccb = (PEXT2_CCB) FileObject->FsContext2;
310             Mcb = Fcb->Mcb;
311             ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
312                    (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
313 #if EXT2_DEBUG
314             DEBUG(DL_INF, (
315                       "Ext2FastIoQueryBasicInfo: %s %s %wZ\n",
316                       Ext2GetCurrentProcessName(),
317                       "FASTIO_QUERY_BASIC_INFO",
318                       &Fcb->Mcb->FullName
319                   ));
320 #endif
321             if (!IsFlagOn(Fcb->Flags, FCB_PAGE_FILE)) {
322                 if (!ExAcquireResourceSharedLite(
323                             &Fcb->MainResource,
324                             Wait)) {
325                     _SEH2_LEAVE;
326                 }
327                 FcbMainResourceAcquired = TRUE;
328             }
329 
330             RtlZeroMemory(Buffer, sizeof(FILE_BASIC_INFORMATION));
331 
332             /*
333             typedef struct _FILE_BASIC_INFORMATION {
334             LARGE_INTEGER   CreationTime;
335             LARGE_INTEGER   LastAccessTime;
336             LARGE_INTEGER   LastWriteTime;
337             LARGE_INTEGER   ChangeTime;
338             ULONG           FileAttributes;
339             } FILE_BASIC_INFORMATION, *PFILE_BASIC_INFORMATION;
340             */
341 
342             Buffer->CreationTime = Mcb->CreationTime;
343             Buffer->LastAccessTime = Mcb->LastAccessTime;
344             Buffer->LastWriteTime = Mcb->LastWriteTime;
345             Buffer->ChangeTime = Mcb->ChangeTime;
346             Buffer->FileAttributes = Mcb->FileAttr;
347             if (Buffer->FileAttributes == 0) {
348                 Buffer->FileAttributes = FILE_ATTRIBUTE_NORMAL;
349             }
350 
351             IoStatus->Information = sizeof(FILE_BASIC_INFORMATION);
352             IoStatus->Status = STATUS_SUCCESS;
353 
354             Status =  TRUE;
355 
356         } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
357             IoStatus->Status = _SEH2_GetExceptionCode();
358         } _SEH2_END;
359 
360     } _SEH2_FINALLY {
361 
362         if (FcbMainResourceAcquired) {
363             ExReleaseResourceLite(&Fcb->MainResource);
364         }
365 
366         FsRtlExitFileSystem();
367     } _SEH2_END;
368 
369 #if EXT2_DEBUG
370 
371     if (Status == FALSE) {
372 
373         DEBUG(DL_ERR, ("Ext2FastIoQueryBasicInfo: %s %s Status: FALSE ***\n",
374                        Ext2GetCurrentProcessName(),
375                        "FASTIO_QUERY_BASIC_INFO"));
376 
377     } else if (IoStatus->Status != STATUS_SUCCESS) {
378 
379         DEBUG(DL_ERR, (
380                   "Ext2FastIoQueryBasicInfo: %s %s Status: %#x ***\n",
381                   Ext2FastIoQueryBasicInfo,
382                   "FASTIO_QUERY_BASIC_INFO",
383                   IoStatus->Status
384               ));
385     }
386 #endif
387 
388     return Status;
389 }
390 
391 #ifdef __REACTOS__
392 BOOLEAN NTAPI
393 #else
394 BOOLEAN
395 #endif
396 Ext2FastIoQueryStandardInfo (
397     IN PFILE_OBJECT                 FileObject,
398     IN BOOLEAN                      Wait,
399     OUT PFILE_STANDARD_INFORMATION  Buffer,
400     OUT PIO_STATUS_BLOCK            IoStatus,
401     IN PDEVICE_OBJECT               DeviceObject
402 )
403 {
404 
405     BOOLEAN     Status = FALSE;
406     PEXT2_VCB   Vcb = NULL;
407     PEXT2_FCB   Fcb = NULL;
408     BOOLEAN     FcbMainResourceAcquired = FALSE;
409 
410     _SEH2_TRY {
411 
412         FsRtlEnterFileSystem();
413 
414         _SEH2_TRY {
415 
416             if (IsExt2FsDevice(DeviceObject)) {
417                 IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;
418                 _SEH2_LEAVE;
419             }
420 
421             Fcb = (PEXT2_FCB) FileObject->FsContext;
422             if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB)  {
423                 IoStatus->Status = STATUS_INVALID_PARAMETER;
424                 _SEH2_LEAVE;
425             }
426 
427             ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
428                    (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
429 
430 #if EXT2_DEBUG
431             DEBUG(DL_INF, (
432                       "Ext2FastIoQueryStandardInfo: %s %s %wZ\n",
433                       Ext2GetCurrentProcessName(),
434                       "FASTIO_QUERY_STANDARD_INFO",
435                       &Fcb->Mcb->FullName ));
436 #endif
437             Vcb = Fcb->Vcb;
438 
439             if (!IsFlagOn(Fcb->Flags, FCB_PAGE_FILE)) {
440                 if (!ExAcquireResourceSharedLite(
441                             &Fcb->MainResource,
442                             Wait        )) {
443                     _SEH2_LEAVE;
444                 }
445                 FcbMainResourceAcquired = TRUE;
446             }
447 
448             RtlZeroMemory(Buffer, sizeof(FILE_STANDARD_INFORMATION));
449 
450             /*
451             typedef struct _FILE_STANDARD_INFORMATION {
452             LARGE_INTEGER   AllocationSize;
453             LARGE_INTEGER   EndOfFile;
454             ULONG           NumberOfLinks;
455             BOOLEAN         DeletePending;
456             BOOLEAN         Directory;
457             } FILE_STANDARD_INFORMATION, *PFILE_STANDARD_INFORMATION;
458             */
459 
460             Buffer->NumberOfLinks = Fcb->Inode->i_nlink;
461             Buffer->DeletePending = IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING);
462 
463             if (IsDirectory(Fcb)) {
464                 Buffer->Directory = IsDirectory(Fcb);
465                 Buffer->AllocationSize.QuadPart = 0;
466                 Buffer->EndOfFile.QuadPart = 0;
467             } else {
468                 Buffer->Directory = FALSE;
469                 Buffer->AllocationSize = Fcb->Header.AllocationSize;
470                 Buffer->EndOfFile = Fcb->Header.FileSize;
471             }
472 
473             IoStatus->Information = sizeof(FILE_STANDARD_INFORMATION);
474             IoStatus->Status = STATUS_SUCCESS;
475 #if EXT2_DEBUG
476             DEBUG(DL_INF, ( "Ext2FastIoQueryStandInfo: AllocatieonSize = %I64xh FileSize = %I64xh\n",
477                             Buffer->AllocationSize.QuadPart, Buffer->EndOfFile.QuadPart));
478 #endif
479             Status =  TRUE;
480 
481         } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
482             IoStatus->Status = _SEH2_GetExceptionCode();
483         } _SEH2_END;
484 
485     } _SEH2_FINALLY {
486 
487         if (FcbMainResourceAcquired) {
488             ExReleaseResourceLite(&Fcb->MainResource);
489         }
490 
491         FsRtlExitFileSystem();
492     } _SEH2_END;
493 
494 #if EXT2_DEBUG
495     if (Status == FALSE) {
496         DEBUG(DL_INF, (
497                   "Ext2FastIoQueryStandardInfo: %s %s Status: FALSE ***\n",
498                   Ext2GetCurrentProcessName(),
499                   "FASTIO_QUERY_STANDARD_INFO"            ));
500     } else if (IoStatus->Status != STATUS_SUCCESS) {
501         DEBUG(DL_INF, (
502                   "Ext2FastIoQueryStandardInfo: %s %s Status: %#x ***\n",
503                   Ext2GetCurrentProcessName(),
504                   "FASTIO_QUERY_STANDARD_INFO",
505                   IoStatus->Status            ));
506     }
507 #endif
508 
509     return Status;
510 }
511 
512 #ifdef __REACTOS__
513 BOOLEAN NTAPI
514 #else
515 BOOLEAN
516 #endif
517 Ext2FastIoLock (
518     IN PFILE_OBJECT         FileObject,
519     IN PLARGE_INTEGER       FileOffset,
520     IN PLARGE_INTEGER       Length,
521     IN PEPROCESS            Process,
522     IN ULONG                Key,
523     IN BOOLEAN              FailImmediately,
524     IN BOOLEAN              ExclusiveLock,
525     OUT PIO_STATUS_BLOCK    IoStatus,
526     IN PDEVICE_OBJECT       DeviceObject
527 )
528 {
529     BOOLEAN     Status = FALSE;
530     PEXT2_FCB   Fcb;
531 
532     _SEH2_TRY {
533 
534         FsRtlEnterFileSystem();
535 
536         _SEH2_TRY {
537 
538             if (IsExt2FsDevice(DeviceObject)) {
539                 IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;
540                 _SEH2_LEAVE;
541             }
542 
543             Fcb = (PEXT2_FCB) FileObject->FsContext;
544             if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB) {
545                 IoStatus->Status = STATUS_INVALID_PARAMETER;
546                 _SEH2_LEAVE;
547             }
548 
549             ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
550                    (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
551 
552             if (IsDirectory(Fcb)) {
553                 DbgBreak();
554                 IoStatus->Status = STATUS_INVALID_PARAMETER;
555                 _SEH2_LEAVE;
556             }
557 #if EXT2_DEBUG
558             DEBUG(DL_INF, (
559                       "Ext2FastIoLock: %s %s %wZ\n",
560                       Ext2GetCurrentProcessName(),
561                       "FASTIO_LOCK",
562                       &Fcb->Mcb->FullName        ));
563 
564             DEBUG(DL_INF, (
565                       "Ext2FastIoLock: Offset: %I64xh Length: %I64xh Key: %u %s%s\n",
566                       FileOffset->QuadPart,
567                       Length->QuadPart,
568                       Key,
569                       (FailImmediately ? "FailImmediately " : ""),
570                       (ExclusiveLock ? "ExclusiveLock " : "") ));
571 #endif
572 
573             if (!FsRtlOplockIsFastIoPossible(&Fcb->Oplock)) {
574                 _SEH2_LEAVE;
575             }
576 
577             Status = FsRtlFastLock(
578                          &Fcb->FileLockAnchor,
579                          FileObject,
580                          FileOffset,
581                          Length,
582                          Process,
583                          Key,
584                          FailImmediately,
585                          ExclusiveLock,
586                          IoStatus,
587                          NULL,
588                          FALSE);
589 
590             if (Status) {
591                 Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb);
592             }
593 
594         } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
595             IoStatus->Status = _SEH2_GetExceptionCode();
596         } _SEH2_END;
597 
598     } _SEH2_FINALLY {
599 
600         FsRtlExitFileSystem();
601     } _SEH2_END;
602 
603 #if EXT2_DEBUG
604     if (Status == FALSE) {
605         DEBUG(DL_ERR, (
606                   "Ext2FastIoLock: %s %s *** Status: FALSE ***\n",
607                   (PUCHAR) Process + ProcessNameOffset,
608                   "FASTIO_LOCK"
609               ));
610     } else if (IoStatus->Status != STATUS_SUCCESS) {
611         DEBUG(DL_ERR, (
612                   "Ext2FastIoLock: %s %s *** Status: %s (%#x) ***\n",
613                   (PUCHAR) Process + ProcessNameOffset,
614                   "FASTIO_LOCK",
615                   Ext2NtStatusToString(IoStatus->Status),
616                   IoStatus->Status
617               ));
618     }
619 #endif
620 
621     return Status;
622 }
623 
624 #ifdef __REACTOS__
625 BOOLEAN NTAPI
626 #else
627 BOOLEAN
628 #endif
629 Ext2FastIoUnlockSingle (
630     IN PFILE_OBJECT         FileObject,
631     IN PLARGE_INTEGER       FileOffset,
632     IN PLARGE_INTEGER       Length,
633     IN PEPROCESS            Process,
634     IN ULONG                Key,
635     OUT PIO_STATUS_BLOCK    IoStatus,
636     IN PDEVICE_OBJECT       DeviceObject
637 )
638 {
639     BOOLEAN     Status = FALSE;
640     PEXT2_FCB   Fcb;
641 
642     _SEH2_TRY {
643 
644         FsRtlEnterFileSystem();
645 
646         _SEH2_TRY {
647 
648             if (IsExt2FsDevice(DeviceObject)) {
649                 IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;
650                 _SEH2_LEAVE;
651             }
652 
653             Fcb = (PEXT2_FCB) FileObject->FsContext;
654             if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB) {
655                 DbgBreak();
656                 IoStatus->Status = STATUS_INVALID_PARAMETER;
657                 _SEH2_LEAVE;
658             }
659 
660             ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
661                    (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
662 
663             if (IsDirectory(Fcb)) {
664                 DbgBreak();
665                 IoStatus->Status = STATUS_INVALID_PARAMETER;
666                 _SEH2_LEAVE;
667             }
668 
669 #if EXT2_DEBUG
670             DEBUG(DL_INF, (
671                       "Ext2FastIoUnlockSingle: %s %s %wZ\n",
672                       (PUCHAR) Process + ProcessNameOffset,
673                       "FASTIO_UNLOCK_SINGLE",
674                       &Fcb->Mcb->FullName        ));
675 
676             DEBUG(DL_INF, (
677                       "Ext2FastIoUnlockSingle: Offset: %I64xh Length: %I64xh Key: %u\n",
678                       FileOffset->QuadPart,
679                       Length->QuadPart,
680                       Key     ));
681 #endif
682 
683             if (!FsRtlOplockIsFastIoPossible(&Fcb->Oplock)) {
684                 _SEH2_LEAVE;
685             }
686 
687             IoStatus->Status = FsRtlFastUnlockSingle(
688                                    &Fcb->FileLockAnchor,
689                                    FileObject,
690                                    FileOffset,
691                                    Length,
692                                    Process,
693                                    Key,
694                                    NULL,
695                                    FALSE);
696 
697             IoStatus->Information = 0;
698             Status =  TRUE;
699 
700             Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb);
701 
702         } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
703             IoStatus->Status = _SEH2_GetExceptionCode();
704         } _SEH2_END;
705 
706     } _SEH2_FINALLY {
707 
708         FsRtlExitFileSystem();
709     } _SEH2_END;
710 
711 #if EXT2_DEBUG
712     if (Status == FALSE) {
713 
714         DEBUG(DL_ERR, (
715                   "Ext2FastIoUnlockSingle: %s %s *** Status: FALSE ***\n",
716                   (PUCHAR) Process + ProcessNameOffset,
717                   "FASTIO_UNLOCK_SINGLE"          ));
718     } else if (IoStatus->Status != STATUS_SUCCESS) {
719         DEBUG(DL_ERR, (
720                   "Ext2FastIoUnlockSingle: %s %s *** Status: %s (%#x) ***\n",
721                   (PUCHAR) Process + ProcessNameOffset,
722                   "FASTIO_UNLOCK_SINGLE",
723                   Ext2NtStatusToString(IoStatus->Status),
724                   IoStatus->Status            ));
725     }
726 #endif
727 
728     return Status;
729 }
730 
731 #ifdef __REACTOS__
732 BOOLEAN NTAPI
733 #else
734 BOOLEAN
735 #endif
736 Ext2FastIoUnlockAll (
737     IN PFILE_OBJECT         FileObject,
738     IN PEPROCESS            Process,
739     OUT PIO_STATUS_BLOCK    IoStatus,
740     IN PDEVICE_OBJECT       DeviceObject)
741 {
742     BOOLEAN     Status = FALSE;
743     PEXT2_FCB   Fcb;
744 
745     _SEH2_TRY {
746 
747         FsRtlEnterFileSystem();
748 
749         _SEH2_TRY {
750 
751             if (IsExt2FsDevice(DeviceObject)) {
752                 IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;
753                 _SEH2_LEAVE;
754             }
755 
756             Fcb = (PEXT2_FCB) FileObject->FsContext;
757             if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB) {
758                 DbgBreak();
759                 IoStatus->Status = STATUS_INVALID_PARAMETER;
760                 _SEH2_LEAVE;
761             }
762 
763             ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
764                    (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
765 
766             if (IsDirectory(Fcb)) {
767                 DbgBreak();
768                 IoStatus->Status = STATUS_INVALID_PARAMETER;
769                 _SEH2_LEAVE;
770             }
771 #if EXT2_DEBUG
772             DEBUG(DL_INF, (
773                       "Ext2FastIoUnlockSingle: %s %s %wZ\n",
774                       (PUCHAR) Process + ProcessNameOffset,
775                       "FASTIO_UNLOCK_ALL",
776                       &Fcb->Mcb->FullName
777                   ));
778 #endif
779 
780             if (!FsRtlOplockIsFastIoPossible(&Fcb->Oplock)) {
781                 _SEH2_LEAVE;
782             }
783 
784             IoStatus->Status = FsRtlFastUnlockAll(
785                                    &Fcb->FileLockAnchor,
786                                    FileObject,
787                                    Process,
788                                    NULL        );
789 
790             IoStatus->Information = 0;
791             Status =  TRUE;
792 
793             Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb);
794 
795         } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
796             IoStatus->Status = _SEH2_GetExceptionCode();
797         } _SEH2_END;
798 
799     } _SEH2_FINALLY {
800 
801         FsRtlExitFileSystem();
802     } _SEH2_END;
803 
804 #if EXT2_DEBUG
805     if (Status == FALSE) {
806 
807         DEBUG(DL_ERR, (
808                   "Ext2FastIoUnlockSingle: %s %s *** Status: FALSE ***\n",
809                   (PUCHAR) Process + ProcessNameOffset,
810                   "FASTIO_UNLOCK_ALL"
811               ));
812     } else if (IoStatus->Status != STATUS_SUCCESS) {
813         DEBUG(DL_ERR, (
814                   "Ext2FastIoUnlockSingle: %s %s *** Status: %s (%#x) ***\n",
815                   (PUCHAR) Process + ProcessNameOffset,
816                   "FASTIO_UNLOCK_ALL",
817                   Ext2NtStatusToString(IoStatus->Status),
818                   IoStatus->Status
819               ));
820     }
821 #endif
822 
823     return Status;
824 }
825 
826 #ifdef __REACTOS__
827 BOOLEAN NTAPI
828 #else
829 BOOLEAN
830 #endif
831 Ext2FastIoUnlockAllByKey (
832     IN PFILE_OBJECT         FileObject,
833 #ifdef __REACTOS__
834     IN PVOID                Process,
835 #else
836     IN PEPROCESS            Process,
837 #endif
838     IN ULONG                Key,
839     OUT PIO_STATUS_BLOCK    IoStatus,
840     IN PDEVICE_OBJECT       DeviceObject
841 )
842 {
843     BOOLEAN     Status = FALSE;
844     PEXT2_FCB   Fcb;
845 
846     _SEH2_TRY {
847 
848         FsRtlEnterFileSystem();
849 
850         _SEH2_TRY {
851 
852             if (IsExt2FsDevice(DeviceObject)) {
853                 IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;
854                 _SEH2_LEAVE;
855             }
856 
857             Fcb = (PEXT2_FCB) FileObject->FsContext;
858             if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB) {
859                 DbgBreak();
860                 IoStatus->Status = STATUS_INVALID_PARAMETER;
861                 _SEH2_LEAVE;
862             }
863 
864             ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
865                    (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
866 
867             if (IsDirectory(Fcb)) {
868                 DbgBreak();
869                 IoStatus->Status = STATUS_INVALID_PARAMETER;
870                 _SEH2_LEAVE;
871             }
872 
873 #if EXT2_DEBUG
874             DEBUG(DL_INF, (
875                       "Ext2FastIoUnlockAllByKey: %s %s %wZ\n",
876                       (PUCHAR) Process + ProcessNameOffset,
877                       "FASTIO_UNLOCK_ALL_BY_KEY",
878                       &Fcb->Mcb->FullName
879                   ));
880 
881             DEBUG(DL_INF, (
882                       "Ext2FastIoUnlockAllByKey: Key: %u\n",
883                       Key
884                   ));
885 #endif
886 
887             if (!FsRtlOplockIsFastIoPossible(&Fcb->Oplock)) {
888                 _SEH2_LEAVE;
889             }
890 
891             IoStatus->Status = FsRtlFastUnlockAllByKey(
892                                    &Fcb->FileLockAnchor,
893                                    FileObject,
894                                    Process,
895                                    Key,
896                                    NULL
897                                );
898 
899             IoStatus->Information = 0;
900             Status =  TRUE;
901 
902             Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb);
903 
904         } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
905             IoStatus->Status = _SEH2_GetExceptionCode();
906         } _SEH2_END;
907 
908     } _SEH2_FINALLY {
909 
910         FsRtlExitFileSystem();
911     } _SEH2_END;
912 
913 #if EXT2_DEBUG
914     if (Status == FALSE) {
915 
916         DEBUG(DL_ERR, (
917                   "Ext2FastIoUnlockAllByKey: %s %s *** Status: FALSE ***\n",
918                   (PUCHAR) Process + ProcessNameOffset,
919                   "FASTIO_UNLOCK_ALL_BY_KEY"
920               ));
921     } else if (IoStatus->Status != STATUS_SUCCESS) {
922 
923         DEBUG(DL_ERR, (
924                   "Ext2FastIoUnlockAllByKey: %s %s *** Status: %s (%#x) ***\n",
925                   (PUCHAR) Process + ProcessNameOffset,
926                   "FASTIO_UNLOCK_ALL_BY_KEY",
927                   Ext2NtStatusToString(IoStatus->Status),
928                   IoStatus->Status
929               ));
930     }
931 #endif
932 
933     return Status;
934 }
935 
936 
937 #ifdef __REACTOS__
938 BOOLEAN NTAPI
939 #else
940 BOOLEAN
941 #endif
942 Ext2FastIoQueryNetworkOpenInfo (
943     IN PFILE_OBJECT         FileObject,
944     IN BOOLEAN              Wait,
945     IN OUT PFILE_NETWORK_OPEN_INFORMATION PFNOI,
946     OUT PIO_STATUS_BLOCK    IoStatus,
947     IN PDEVICE_OBJECT       DeviceObject
948 )
949 {
950     PEXT2_FCB   Fcb = NULL;
951     PEXT2_CCB   Ccb = NULL;
952     PEXT2_MCB   Mcb = NULL;
953 
954     BOOLEAN     bResult = FALSE;
955     BOOLEAN FcbResourceAcquired = FALSE;
956 
957     _SEH2_TRY {
958 
959         FsRtlEnterFileSystem();
960 
961         if (IsExt2FsDevice(DeviceObject)) {
962             IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;
963             _SEH2_LEAVE;
964         }
965 
966         Fcb = (PEXT2_FCB) FileObject->FsContext;
967         if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB) {
968             DbgBreak();
969             IoStatus->Status = STATUS_INVALID_PARAMETER;
970             _SEH2_LEAVE;
971         }
972 
973         ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
974                (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
975         Ccb = (PEXT2_CCB) FileObject->FsContext2;
976         Mcb = Fcb->Mcb;
977 
978 #if EXT2_DEBUG
979         DEBUG(DL_INF, (
980                   "%-31s %wZ\n",
981                   "FASTIO_QUERY_NETWORK_OPEN_INFO",
982                   &Fcb->Mcb->FullName
983               ));
984 #endif
985 
986         if (!Ccb) {
987             _SEH2_LEAVE;
988         }
989 
990         if (!IsFlagOn(Fcb->Flags, FCB_PAGE_FILE)) {
991 
992             if (!ExAcquireResourceSharedLite(
993                         &Fcb->MainResource,
994                         Wait
995                     )) {
996                 _SEH2_LEAVE;
997             }
998 
999             FcbResourceAcquired = TRUE;
1000         }
1001 
1002         if (IsDirectory(Fcb)) {
1003             PFNOI->AllocationSize.QuadPart = 0;
1004             PFNOI->EndOfFile.QuadPart = 0;
1005         } else {
1006             PFNOI->AllocationSize = Fcb->Header.AllocationSize;
1007             PFNOI->EndOfFile      = Fcb->Header.FileSize;
1008         }
1009 
1010         PFNOI->FileAttributes = Mcb->FileAttr;
1011         if (PFNOI->FileAttributes == 0) {
1012             PFNOI->FileAttributes = FILE_ATTRIBUTE_NORMAL;
1013         }
1014 
1015         PFNOI->CreationTime   = Mcb->CreationTime;
1016         PFNOI->LastAccessTime = Mcb->LastAccessTime;
1017         PFNOI->LastWriteTime  = Mcb->LastWriteTime;
1018         PFNOI->ChangeTime     = Mcb->ChangeTime;
1019 
1020         bResult = TRUE;
1021 
1022         IoStatus->Status = STATUS_SUCCESS;
1023         IoStatus->Information = sizeof(FILE_NETWORK_OPEN_INFORMATION);
1024 
1025     } _SEH2_FINALLY {
1026 
1027         if (FcbResourceAcquired) {
1028             ExReleaseResourceLite(&Fcb->MainResource);
1029         }
1030 
1031         FsRtlExitFileSystem();
1032     } _SEH2_END;
1033 
1034     return bResult;
1035 }
1036 
1037 
1038 #ifdef __REACTOS__
1039 VOID NTAPI
1040 #else
1041 VOID
1042 #endif
1043 Ext2AcquireForCreateSection (
1044     IN PFILE_OBJECT FileObject
1045 )
1046 
1047 {
1048     PEXT2_FCB Fcb = FileObject->FsContext;
1049 
1050     if (Fcb->Header.Resource != NULL) {
1051         ExAcquireResourceExclusiveLite(Fcb->Header.Resource, TRUE);
1052     }
1053 
1054     DEBUG(FASTIO_DEBUG_LEVEL, ("Ext2AcquireForCreateSection:  Fcb=%p\n", Fcb));
1055 }
1056 
1057 #ifdef __REACTOS__
1058 VOID NTAPI
1059 #else
1060 VOID
1061 #endif
1062 Ext2ReleaseForCreateSection (
1063     IN PFILE_OBJECT FileObject
1064 )
1065 {
1066     PEXT2_FCB Fcb = FileObject->FsContext;
1067 
1068     DEBUG(FASTIO_DEBUG_LEVEL, ("Ext2ReleaseForCreateSection:  Fcb=%p\n", Fcb));
1069 
1070     if (Fcb->Header.Resource != NULL) {
1071         ExReleaseResourceLite(Fcb->Header.Resource);
1072     }
1073 }
1074 
1075 
1076 #ifdef __REACTOS__
1077 NTSTATUS NTAPI
1078 #else
1079 NTSTATUS
1080 #endif
1081 Ext2AcquireFileForModWrite (
1082     IN PFILE_OBJECT FileObject,
1083     IN PLARGE_INTEGER EndingOffset,
1084     OUT PERESOURCE *ResourceToRelease,
1085     IN PDEVICE_OBJECT DeviceObject
1086 )
1087 
1088 {
1089     BOOLEAN ResourceAcquired = FALSE;
1090 
1091     PEXT2_FCB Fcb = FileObject->FsContext;
1092 
1093     *ResourceToRelease = Fcb->Header.Resource;
1094     ResourceAcquired = ExAcquireResourceExclusiveLite(*ResourceToRelease, FALSE);
1095     if (!ResourceAcquired) {
1096         *ResourceToRelease = NULL;
1097     }
1098 
1099     DEBUG(FASTIO_DEBUG_LEVEL, ("Ext2AcquireFileForModWrite:  Fcb=%p Acquired=%d\n",
1100                              Fcb, ResourceAcquired));
1101 
1102     return (ResourceAcquired ? STATUS_SUCCESS : STATUS_CANT_WAIT);
1103 }
1104 
1105 #ifdef __REACTOS__
1106 NTSTATUS NTAPI
1107 #else
1108 NTSTATUS
1109 #endif
1110 Ext2ReleaseFileForModWrite (
1111     IN PFILE_OBJECT FileObject,
1112     IN PERESOURCE ResourceToRelease,
1113     IN PDEVICE_OBJECT DeviceObject
1114 )
1115 {
1116     PEXT2_FCB Fcb = FileObject->FsContext;
1117 
1118     DEBUG(FASTIO_DEBUG_LEVEL, ("Ext2ReleaseFileForModWrite: Fcb=%p\n", Fcb));
1119 
1120     if (ResourceToRelease != NULL) {
1121         ASSERT(ResourceToRelease == Fcb->Header.Resource);
1122         ExReleaseResourceLite(ResourceToRelease);
1123     } else {
1124         DbgBreak();
1125     }
1126 
1127     return STATUS_SUCCESS;
1128 }
1129 
1130 #ifdef __REACTOS__
1131 NTSTATUS NTAPI
1132 #else
1133 NTSTATUS
1134 #endif
1135 Ext2AcquireFileForCcFlush (
1136     IN PFILE_OBJECT FileObject,
1137     IN PDEVICE_OBJECT DeviceObject
1138 )
1139 {
1140     PEXT2_FCB Fcb = FileObject->FsContext;
1141 
1142     if (Fcb->Header.Resource != NULL) {
1143         ExAcquireResourceExclusiveLite(Fcb->Header.Resource, TRUE);
1144     }
1145 
1146     DEBUG(FASTIO_DEBUG_LEVEL, ("Ext2AcquireFileForCcFlush: Fcb=%p\n", Fcb));
1147 
1148     return STATUS_SUCCESS;
1149 }
1150 
1151 #ifdef __REACTOS__
1152 NTSTATUS NTAPI
1153 #else
1154 NTSTATUS
1155 #endif
1156 Ext2ReleaseFileForCcFlush (
1157     IN PFILE_OBJECT FileObject,
1158     IN PDEVICE_OBJECT DeviceObject
1159 )
1160 {
1161     PEXT2_FCB Fcb = FileObject->FsContext;
1162 
1163     DEBUG(FASTIO_DEBUG_LEVEL, ("Ext2ReleaseFileForCcFlush: Fcb=%p\n", Fcb));
1164 
1165     if (Fcb->Header.Resource != NULL) {
1166         ExReleaseResourceLite(Fcb->Header.Resource);
1167     }
1168 
1169     return STATUS_SUCCESS;
1170 }
1171 
1172 
1173 #ifdef __REACTOS__
1174 NTSTATUS NTAPI
1175 #else
1176 NTSTATUS
1177 #endif
1178 Ext2PreAcquireForCreateSection(
1179     IN PFS_FILTER_CALLBACK_DATA cd,
1180     OUT PVOID *cc
1181     )
1182 {
1183     PEXT2_FCB Fcb = (PEXT2_FCB)cd->FileObject->FsContext;
1184     NTSTATUS        status;
1185 
1186     ASSERT(cd->Operation == FS_FILTER_ACQUIRE_FOR_SECTION_SYNCHRONIZATION);
1187     ExAcquireResourceExclusiveLite(Fcb->Header.Resource, TRUE);
1188     if (cd->Parameters.AcquireForSectionSynchronization.SyncType != SyncTypeCreateSection) {
1189         status = STATUS_FSFILTER_OP_COMPLETED_SUCCESSFULLY;
1190     } else if (Fcb->ShareAccess.Writers == 0) {
1191         status = STATUS_FILE_LOCKED_WITH_ONLY_READERS;
1192     } else {
1193         status = STATUS_FILE_LOCKED_WITH_WRITERS;
1194     }
1195 
1196     return status;
1197 }
1198