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