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