xref: /reactos/drivers/filesystems/udfs/fastio.cpp (revision 7eead935)
1 ////////////////////////////////////////////////////////////////////
2 // Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine
3 // All rights reserved
4 // This file was released under the GPLv2 on June 2015.
5 ////////////////////////////////////////////////////////////////////
6 /*************************************************************************
7 *
8 * File: Fastio.cpp
9 *
10 * Module: UDF File System Driver (Kernel mode execution only)
11 *
12 * Description:
13 *   Contains code to handle the various "fast-io" calls.
14 *
15 *************************************************************************/
16 
17 #include            "udffs.h"
18 
19 // define the file specific bug-check id
20 #define         UDF_BUG_CHECK_ID                UDF_FILE_FAST_IO
21 
22 
23 
24 /*************************************************************************
25 *
26 * Function: UDFFastIoCheckIfPossible()
27 *
28 * Description:
29 *   To fast-io or not to fast-io, that is the question ...
30 *   This routine helps the I/O Manager determine whether the FSD wishes
31 *   to permit fast-io on a specific file stream.
32 *
33 * Expected Interrupt Level (for execution) :
34 *
35 *  IRQL_PASSIVE_LEVEL
36 *
37 * Return Value: TRUE/FALSE
38 *
39 *************************************************************************/
40 BOOLEAN
41 NTAPI
42 UDFFastIoCheckIfPossible(
43     IN PFILE_OBJECT             FileObject,
44     IN PLARGE_INTEGER           FileOffset,
45     IN ULONG                    Length,
46     IN BOOLEAN                  Wait,
47     IN ULONG                    LockKey,
48     IN BOOLEAN                  CheckForReadOperation,
49     OUT PIO_STATUS_BLOCK        IoStatus,
50     IN PDEVICE_OBJECT           DeviceObject
51     )
52 {
53     BOOLEAN             ReturnedStatus = FALSE;
54     PtrUDFFCB           Fcb = NULL;
55     PtrUDFCCB           Ccb = NULL;
56     LARGE_INTEGER       IoLength;
57 
58     // Obtain a pointer to the FCB and CCB for the file stream.
59     Ccb = (PtrUDFCCB)(FileObject->FsContext2);
60     ASSERT(Ccb);
61     Fcb = Ccb->Fcb;
62     ASSERT(Fcb);
63 
64     // Validate that this is a fast-IO request to a regular file.
65     // The UDF FSD for example, will not allow fast-IO requests
66     // to volume objects, or to directories.
67     if ((Fcb->NodeIdentifier.NodeType == UDF_NODE_TYPE_VCB) ||
68          (Fcb->FCBFlags & UDF_FCB_DIRECTORY)) {
69         // This is not allowed.
70         IoStatus->Status = STATUS_INVALID_PARAMETER;
71         MmPrint(("    UDFFastIoCheckIfPossible() TRUE, Failed\n"));
72         return FALSE;
73     }
74 /*
75     // back pressure for very smart and fast system cache ;)
76     if(Fcb->Vcb->VerifyCtx.ItemCount >= UDF_MAX_VERIFY_CACHE) {
77         AdPrint(("    Verify queue overflow -> UDFFastIoCheckIfPossible() = FALSE\n"));
78         return FALSE;
79     }
80 */
81     IoLength.QuadPart = Length;
82 
83     // The FSD can determine the checks that it needs to perform.
84     // Typically, a FSD will check whether there exist any byte-range
85     // locks that would prevent a fast-IO operation from proceeding.
86 
87     // ... (FSD specific checks go here).
88 
89     if (CheckForReadOperation) {
90         // The following routine is exported by the FSRTL
91         // package and it returns TRUE if the read operation should be
92         // allowed to proceed based on the status of the current byte-range
93         // locks on the file stream. If we do not use the FSRTL package
94         // for byte-range locking support, then we must substitute our
95         // own checks over here.
96         ReturnedStatus = FsRtlFastCheckLockForRead(&(Fcb->NTRequiredFCB->FileLock),
97                               FileOffset, &IoLength, LockKey, FileObject,
98                               PsGetCurrentProcess());
99     } else {
100 //        if(Fcb->Vcb->VCBFlags );
101         // This is a write request. Invoke the FSRTL byte-range lock package
102         // to see whether the write should be allowed to proceed.
103         ReturnedStatus = FsRtlFastCheckLockForWrite(&(Fcb->NTRequiredFCB->FileLock),
104                               FileOffset, &IoLength, LockKey, FileObject,
105                               PsGetCurrentProcess());
106     }
107 
108     MmPrint(("    UDFFastIoCheckIfPossible() %s\n", ReturnedStatus ? "TRUE" : "FALSE"));
109     return(ReturnedStatus);
110 //    return FALSE;
111 
112 } // end UDFFastIoCheckIfPossible()
113 
114 /*
115  */
116 FAST_IO_POSSIBLE
117 NTAPI
118 UDFIsFastIoPossible(
119     IN PtrUDFFCB Fcb
120     )
121 {
122     if( !(Fcb->Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_MOUNTED) /*||
123         !FsRtlOplockIsFastIoPossible(&(Fcb->Oplock))*/ ) {
124         UDFPrint(("    FastIoIsNotPossible\n"));
125         return FastIoIsNotPossible;
126     }
127 /*
128     // back pressure for very smart and fast system cache ;)
129     if(Fcb->Vcb->VerifyCtx.ItemCount >= UDF_MAX_VERIFY_CACHE) {
130         AdPrint(("    Verify queue overflow -> UDFIsFastIoPossible() = FastIoIsNotPossible\n"));
131         return FastIoIsNotPossible;
132     }
133 */
134     if(FsRtlAreThereCurrentFileLocks(&(Fcb->NTRequiredFCB->FileLock)) ) {
135         UDFPrint(("    FastIoIsQuestionable\n"));
136         return FastIoIsQuestionable;
137     }
138     UDFPrint(("    FastIoIsPossible\n"));
139     return FastIoIsPossible;
140 } // end UDFIsFastIoPossible()
141 
142 /*************************************************************************
143 *
144 * Function: UDFFastIoQueryBasicInfo()
145 *
146 * Description:
147 *   Bypass the traditional IRP method to perform a query basic
148 *   information operation.
149 *
150 * Expected Interrupt Level (for execution) :
151 *
152 *  IRQL_PASSIVE_LEVEL
153 *
154 * Return Value: TRUE/FALSE
155 *
156 *************************************************************************/
157 BOOLEAN
158 NTAPI
159 UDFFastIoQueryBasicInfo(
160     IN PFILE_OBJECT             FileObject,
161     IN BOOLEAN                  Wait,
162     OUT PFILE_BASIC_INFORMATION Buffer,
163     OUT PIO_STATUS_BLOCK        IoStatus,
164     IN PDEVICE_OBJECT           DeviceObject
165     )
166 {
167     BOOLEAN          ReturnedStatus = FALSE;     // fast i/o failed/not allowed
168     NTSTATUS         RC = STATUS_SUCCESS;
169     PtrUDFIrpContext PtrIrpContext = NULL;
170     LONG             Length = sizeof(FILE_BASIC_INFORMATION);
171     PtrUDFFCB        Fcb;
172     PtrUDFCCB        Ccb;
173     PtrUDFNTRequiredFCB NtReqFcb = NULL;
174     BOOLEAN          MainResourceAcquired = FALSE;
175 
176     FsRtlEnterFileSystem();
177 
178     UDFPrint(("UDFFastIo  \n"));
179     // if the file is already opended we can satisfy this request
180     // immediately 'cause all the data we need must be cached
181     _SEH2_TRY {
182 
183         _SEH2_TRY {
184 
185             // Get the FCB and CCB pointers.
186             Ccb = (PtrUDFCCB)(FileObject->FsContext2);
187             ASSERT(Ccb);
188             Fcb = Ccb->Fcb;
189             ASSERT(Fcb);
190             NtReqFcb = Fcb->NTRequiredFCB;
191             //Fcb->Vcb->VCBFlags |= UDF_VCB_SKIP_EJECT_CHECK;
192 
193             if (!(Fcb->FCBFlags & UDF_FCB_PAGE_FILE)) {
194                 // Acquire the MainResource shared.
195                 UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb);
196                 if (!UDFAcquireResourceShared(&(NtReqFcb->MainResource), Wait)) {
197                     try_return(RC = STATUS_CANT_WAIT);
198                 }
199                 MainResourceAcquired = TRUE;
200             }
201 
202             ReturnedStatus =
203                 ((RC = UDFGetBasicInformation(FileObject, Fcb, Buffer, &Length)) == STATUS_SUCCESS);
204 
205         } _SEH2_EXCEPT(UDFExceptionFilter(PtrIrpContext, _SEH2_GetExceptionInformation())) {
206 
207             RC = UDFExceptionHandler(PtrIrpContext, NULL);
208 
209             UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC);
210 
211         } _SEH2_END;
212 try_exit: NOTHING;
213     } _SEH2_FINALLY {
214         if (MainResourceAcquired) {
215             UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb);
216             UDFReleaseResource(&(NtReqFcb->MainResource));
217             MainResourceAcquired = FALSE;
218         }
219         IoStatus->Status = RC;
220         if(ReturnedStatus) {
221             IoStatus->Information = sizeof(FILE_BASIC_INFORMATION);
222         } else {
223             IoStatus->Information = 0;
224         }
225     } _SEH2_END;
226 
227     FsRtlExitFileSystem();
228 
229     return(ReturnedStatus);
230 } // end UDFFastIoQueryBasicInfo()
231 
232 
233 /*************************************************************************
234 *
235 * Function: UDFFastIoQueryStdInfo()
236 *
237 * Description:
238 *   Bypass the traditional IRP method to perform a query standard
239 *   information operation.
240 *
241 * Expected Interrupt Level (for execution) :
242 *
243 *  IRQL_PASSIVE_LEVEL
244 *
245 * Return Value: TRUE/FALSE
246 *
247 *************************************************************************/
248 BOOLEAN
249 NTAPI
250 UDFFastIoQueryStdInfo(
251     IN PFILE_OBJECT                 FileObject,
252     IN BOOLEAN                      Wait,
253     OUT PFILE_STANDARD_INFORMATION  Buffer,
254     OUT PIO_STATUS_BLOCK            IoStatus,
255     IN PDEVICE_OBJECT               DeviceObject)
256 {
257     BOOLEAN          ReturnedStatus = FALSE;     // fast i/o failed/not allowed
258     NTSTATUS         RC = STATUS_SUCCESS;
259     PtrUDFIrpContext PtrIrpContext = NULL;
260     LONG             Length = sizeof(FILE_STANDARD_INFORMATION);
261     PtrUDFFCB        Fcb;
262     PtrUDFCCB        Ccb;
263 //    PtrUDFNTRequiredFCB NtReqFcb = NULL;
264 //    BOOLEAN          MainResourceAcquired = FALSE;
265 
266     FsRtlEnterFileSystem();
267 
268     UDFPrint(("UDFFastIo  \n"));
269     // if the file is already opended we can satisfy this request
270     // immediately 'cause all the data we need must be cached
271     _SEH2_TRY {
272 
273         _SEH2_TRY {
274 
275             // Get the FCB and CCB pointers.
276             Ccb = (PtrUDFCCB)(FileObject->FsContext2);
277             ASSERT(Ccb);
278             Fcb = Ccb->Fcb;
279             ASSERT(Fcb);
280 //            NtReqFcb = Fcb->NTRequiredFCB;
281             //Fcb->Vcb->VCBFlags |= UDF_VCB_SKIP_EJECT_CHECK;
282 
283 /*
284             if (!(Fcb->FCBFlags & UDF_FCB_PAGE_FILE)) {
285                 // Acquire the MainResource shared.
286                 UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb);
287                 if (!UDFAcquireResourceShared(&(NtReqFcb->MainResource), Wait)) {
288                     try_return(RC = STATUS_CANT_WAIT);
289                 }
290                 MainResourceAcquired = TRUE;
291             }
292 */
293             ReturnedStatus =
294                 ((RC = UDFGetStandardInformation(Fcb, Buffer, &Length)) == STATUS_SUCCESS);
295 
296         } _SEH2_EXCEPT(UDFExceptionFilter(PtrIrpContext, _SEH2_GetExceptionInformation())) {
297 
298             RC = UDFExceptionHandler(PtrIrpContext, NULL);
299 
300             UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC);
301 
302         } _SEH2_END;
303 //try_exit: NOTHING;
304     } _SEH2_FINALLY {
305 /*
306         if (MainResourceAcquired) {
307             UDFReleaseResource(&(NtReqFcb->MainResource));
308             MainResourceAcquired = FALSE;
309         }
310 */
311         IoStatus->Status = RC;
312         if(ReturnedStatus) {
313             IoStatus->Information = sizeof(FILE_STANDARD_INFORMATION);
314         } else {
315             IoStatus->Information = 0;
316         }
317     } _SEH2_END;
318 
319     FsRtlExitFileSystem();
320 
321     return(ReturnedStatus);
322 } // end UDFFastIoQueryStdInfo()
323 
324 
325 /*************************************************************************
326 *
327 * Function: UDFFastIoAcqCreateSec()
328 *
329 * Description:
330 *   Not really a fast-io operation. Used by the VMM to acquire FSD resources
331 *   before processing a file map (create section object) request.
332 *
333 * Expected Interrupt Level (for execution) :
334 *
335 *  IRQL_PASSIVE_LEVEL
336 *
337 * Return Value: None (we must be prepared to handle VMM initiated calls)
338 *
339 *************************************************************************/
340 VOID
341 NTAPI
342 UDFFastIoAcqCreateSec(
343     IN PFILE_OBJECT FileObject
344     )
345 {
346     PtrUDFNTRequiredFCB NtReqFcb = (PtrUDFNTRequiredFCB)(FileObject->FsContext);
347 
348     MmPrint(("  AcqForCreateSection()\n"));
349     // Acquire the MainResource exclusively for the file stream
350     if(!ExIsResourceAcquiredExclusiveLite(&(NtReqFcb->MainResource)) ||
351        !ExIsResourceAcquiredExclusiveLite(&(NtReqFcb->PagingIoResource)) ) {
352         UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb);
353     } else {
354         MmPrint(("    already acquired\n"));
355     }
356     UDFAcquireResourceExclusive(&(NtReqFcb->MainResource), TRUE);
357 
358     // Although this is typically not required, the UDF FSD will
359     // also acquire the PagingIoResource exclusively at this time
360     // to conform with the resource acquisition described in the set
361     // file information routine. Once again though, we will probably
362     // not need to do this.
363     UDFAcquireResourceExclusive(&(NtReqFcb->PagingIoResource), TRUE);
364     NtReqFcb->AcqSectionCount++;
365 
366     return;
367 } // end UDFFastIoAcqCreateSec()
368 
369 
370 /*************************************************************************
371 *
372 * Function: UDFFastIoRelCreateSec()
373 *
374 * Description:
375 *   Not really a fast-io operation. Used by the VMM to release FSD resources
376 *   after processing a file map (create section object) request.
377 *
378 * Expected Interrupt Level (for execution) :
379 *
380 *  IRQL_PASSIVE_LEVEL
381 *
382 * Return Value: None
383 *
384 *************************************************************************/
385 VOID
386 NTAPI
387 UDFFastIoRelCreateSec(
388     IN PFILE_OBJECT FileObject)
389 {
390     PtrUDFNTRequiredFCB NtReqFcb = (PtrUDFNTRequiredFCB)(FileObject->FsContext);
391 
392     MmPrint(("  RelFromCreateSection()\n"));
393 
394     NtReqFcb->AcqSectionCount--;
395     // Release the PagingIoResource for the file stream
396     UDFReleaseResource(&(NtReqFcb->PagingIoResource));
397 
398     // Release the MainResource for the file stream
399     UDFReleaseResource(&(NtReqFcb->MainResource));
400 
401     return;
402 } // end UDFFastIoRelCreateSec()
403 
404 
405 /*************************************************************************
406 *
407 * Function: UDFAcqLazyWrite()
408 *
409 * Description:
410 *   Not really a fast-io operation. Used by the NT Cache Mgr to acquire FSD
411 *   resources before performing a delayed write (write behind/lazy write)
412 *   operation.
413 *   NOTE: this function really must succeed since the Cache Manager will
414 *           typically ignore failure and continue on ...
415 *
416 * Expected Interrupt Level (for execution) :
417 *
418 *  IRQL_PASSIVE_LEVEL
419 *
420 * Return Value: TRUE/FALSE (Cache Manager does not tolerate FALSE well)
421 *
422 *************************************************************************/
423 BOOLEAN NTAPI UDFAcqLazyWrite(
424     IN PVOID   Context,
425     IN BOOLEAN Wait)
426 {
427     // The context is whatever we passed to the Cache Manager when invoking
428     // the CcInitializeCacheMaps() function. In the case of the UDF FSD
429     // implementation, this context is a pointer to the NT_REQ_FCB structure.
430     PtrUDFNTRequiredFCB NtReqFcb = (PtrUDFNTRequiredFCB)Context;
431 
432     MmPrint(("  UDFAcqLazyWrite()\n"));
433 
434     // Acquire the PagingIoResource in the NT_REQ_FCB exclusively. Then, set the
435     // lazy-writer thread id in the NT_REQ_FCB structure for identification
436     // when an actual write request is received by the FSD.
437     // Note: The lazy-writer typically always supplies WAIT set to TRUE.
438     if (!UDFAcquireResourceExclusive(&(NtReqFcb->PagingIoResource), Wait))
439         return FALSE;
440 
441     // Now, set the lazy-writer thread id.
442     ASSERT(!(NtReqFcb->LazyWriterThreadID));
443     NtReqFcb->LazyWriterThreadID = HandleToUlong(PsGetCurrentThreadId());
444 
445     ASSERT(IoGetTopLevelIrp() == NULL);
446     IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
447 
448     // If our FSD needs to perform some special preparations in anticipation
449     // of receving a lazy-writer request, do so now.
450     return TRUE;
451 } // end UDFAcqLazyWrite()
452 
453 
454 /*************************************************************************
455 *
456 * Function: UDFRelLazyWrite()
457 *
458 * Description:
459 *   Not really a fast-io operation. Used by the NT Cache Mgr to release FSD
460 *   resources after performing a delayed write (write behind/lazy write)
461 *   operation.
462 *
463 * Expected Interrupt Level (for execution) :
464 *
465 *  IRQL_PASSIVE_LEVEL
466 *
467 * Return Value: None
468 *
469 *************************************************************************/
470 VOID
471 NTAPI
472 UDFRelLazyWrite(
473     IN PVOID   Context)
474 {
475     // The context is whatever we passed to the Cache Manager when invoking
476     // the CcInitializeCacheMaps() function. In the case of the UDF FSD
477     // implementation, this context is a pointer to the NT_REQ_FCB structure.
478     PtrUDFNTRequiredFCB NtReqFcb = (PtrUDFNTRequiredFCB)Context;
479 
480     MmPrint(("  UDFRelLazyWrite()\n"));
481 
482     // Remove the current thread-id from the NT_REQ_FCB
483     // and release the MainResource.
484     ASSERT((NtReqFcb->LazyWriterThreadID) == HandleToUlong(PsGetCurrentThreadId()));
485     NtReqFcb->LazyWriterThreadID = 0;
486 
487     // Release the acquired resource.
488     UDFReleaseResource(&(NtReqFcb->PagingIoResource));
489 
490     IoSetTopLevelIrp( NULL );
491     return;
492 } // end UDFRelLazyWrite()
493 
494 
495 /*************************************************************************
496 *
497 * Function: UDFAcqReadAhead()
498 *
499 * Description:
500 *   Not really a fast-io operation. Used by the NT Cache Mgr to acquire FSD
501 *   resources before performing a read-ahead operation.
502 *   NOTE: this function really must succeed since the Cache Manager will
503 *           typically ignore failure and continue on ...
504 *
505 * Expected Interrupt Level (for execution) :
506 *
507 *  IRQL_PASSIVE_LEVEL
508 *
509 * Return Value: TRUE/FALSE (Cache Manager does not tolerate FALSE well)
510 *
511 *************************************************************************/
512 BOOLEAN
513 NTAPI
514 UDFAcqReadAhead(
515     IN PVOID   Context,
516     IN BOOLEAN Wait
517     )
518 {
519     // The context is whatever we passed to the Cache Manager when invoking
520     // the CcInitializeCacheMaps() function. In the case of the UDF FSD
521     // implementation, this context is a pointer to the NT_REQ_FCB structure.
522 #define NtReqFcb ((PtrUDFNTRequiredFCB)Context)
523 
524     MmPrint(("  AcqForReadAhead()\n"));
525 
526     // Acquire the MainResource in the NT_REQ_FCB shared.
527     // Note: The read-ahead thread typically always supplies WAIT set to TRUE.
528     UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb);
529     if (!UDFAcquireResourceShared(&(NtReqFcb->MainResource), Wait))
530         return FALSE;
531 
532     ASSERT(IoGetTopLevelIrp() == NULL);
533     IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
534 
535     return TRUE;
536 #undef NtReqFcb
537 
538 } // end UDFAcqReadAhead()
539 
540 
541 /*************************************************************************
542 *
543 * Function: UDFRelReadAhead()
544 *
545 * Description:
546 *   Not really a fast-io operation. Used by the NT Cache Mgr to release FSD
547 *   resources after performing a read-ahead operation.
548 *
549 * Expected Interrupt Level (for execution) :
550 *
551 *  IRQL_PASSIVE_LEVEL
552 *
553 * Return Value: None
554 *
555 *************************************************************************/
556 VOID
557 NTAPI
558 UDFRelReadAhead(
559     IN PVOID  Context)
560 {
561     // The context is whatever we passed to the Cache Manager when invoking
562     // the CcInitializeCacheMaps() function. In the case of the UDF FSD
563     // implementation, this context is a pointer to the NT_REQ_FCB structure.
564 #define NtReqFcb ((PtrUDFNTRequiredFCB)Context)
565 
566     MmPrint(("  RelFromReadAhead()\n"));
567 
568     // Release the acquired resource.
569     UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb);
570     UDFReleaseResource(&(NtReqFcb->MainResource));
571 
572     // Of course, the FSD should undo whatever else seems appropriate at this
573     // time.
574     IoSetTopLevelIrp( NULL );
575 
576     return;
577 #undef NtReqFcb
578 } // end UDFRelReadAhead()
579 
580 /* the remaining are only valid under NT Version 4.0 and later */
581 #if(_WIN32_WINNT >= 0x0400)
582 
583 
584 /*************************************************************************
585 *
586 * Function: UDFFastIoQueryNetInfo()
587 *
588 * Description:
589 *   Get information requested by a redirector across the network. This call
590 *   will originate from the LAN Manager server.
591 *
592 * Expected Interrupt Level (for execution) :
593 *
594 *  IRQL_PASSIVE_LEVEL
595 *
596 * Return Value: TRUE/FALSE
597 *
598 *************************************************************************/
599 BOOLEAN
600 NTAPI
601 UDFFastIoQueryNetInfo(
602     IN PFILE_OBJECT                                 FileObject,
603     IN BOOLEAN                                      Wait,
604     OUT PFILE_NETWORK_OPEN_INFORMATION              Buffer,
605     OUT PIO_STATUS_BLOCK                            IoStatus,
606     IN PDEVICE_OBJECT                               DeviceObject)
607 {
608     BOOLEAN          ReturnedStatus = FALSE;     // fast i/o failed/not allowed
609     NTSTATUS         RC = STATUS_SUCCESS;
610     PtrUDFIrpContext PtrIrpContext = NULL;
611     LONG             Length = sizeof(FILE_NETWORK_OPEN_INFORMATION);
612     PtrUDFFCB        Fcb;
613     PtrUDFCCB        Ccb;
614     PtrUDFNTRequiredFCB NtReqFcb = NULL;
615     BOOLEAN          MainResourceAcquired = FALSE;
616 
617     FsRtlEnterFileSystem();
618 
619     UDFPrint(("UDFFastIo  \n"));
620     // if the file is already opended we can satisfy this request
621     // immediately 'cause all the data we need must be cached
622     _SEH2_TRY {
623 
624         _SEH2_TRY {
625 
626             // Get the FCB and CCB pointers.
627             Ccb = (PtrUDFCCB)(FileObject->FsContext2);
628             ASSERT(Ccb);
629             Fcb = Ccb->Fcb;
630             ASSERT(Fcb);
631             NtReqFcb = Fcb->NTRequiredFCB;
632             //Fcb->Vcb->VCBFlags |= UDF_VCB_SKIP_EJECT_CHECK;
633 
634             if (!(Fcb->FCBFlags & UDF_FCB_PAGE_FILE)) {
635                 // Acquire the MainResource shared.
636                 UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb);
637                 if (!UDFAcquireResourceShared(&(NtReqFcb->MainResource), Wait)) {
638                     try_return(RC = STATUS_CANT_WAIT);
639                 }
640                 MainResourceAcquired = TRUE;
641             }
642 
643             ReturnedStatus =
644                 ((RC = UDFGetNetworkInformation(Fcb, Buffer, &Length)) == STATUS_SUCCESS);
645 
646         } _SEH2_EXCEPT(UDFExceptionFilter(PtrIrpContext, _SEH2_GetExceptionInformation())) {
647 
648             RC = UDFExceptionHandler(PtrIrpContext, NULL);
649 
650             UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC);
651 
652         } _SEH2_END;
653 try_exit: NOTHING;
654     } _SEH2_FINALLY {
655         if (MainResourceAcquired) {
656             UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb);
657             UDFReleaseResource(&(NtReqFcb->MainResource));
658             MainResourceAcquired = FALSE;
659         }
660         IoStatus->Status = RC;
661         if(ReturnedStatus) {
662             IoStatus->Information = sizeof(FILE_NETWORK_OPEN_INFORMATION);
663         } else {
664             IoStatus->Information = 0;
665         }
666     } _SEH2_END;
667 
668     FsRtlExitFileSystem();
669 
670     return(ReturnedStatus);
671 
672 } // end UDFFastIoQueryNetInfo()
673 
674 
675 /*************************************************************************
676 *
677 * Function: UDFFastIoMdlRead()
678 *
679 * Description:
680 *   Bypass the traditional IRP method to perform a MDL read operation.
681 *
682 * Expected Interrupt Level (for execution) :
683 *
684 *  IRQL_PASSIVE_LEVEL
685 *
686 * Return Value: TRUE/FALSE
687 *
688 *************************************************************************/
689 /*BOOLEAN UDFFastIoMdlRead(
690 IN PFILE_OBJECT             FileObject,
691 IN PLARGE_INTEGER           FileOffset,
692 IN ULONG                    Length,
693 IN ULONG                    LockKey,
694 OUT PMDL*                   MdlChain,
695 OUT PIO_STATUS_BLOCK        IoStatus,
696 IN PDEVICE_OBJECT           DeviceObject)
697 {
698     BOOLEAN ReturnedStatus = FALSE;     // fast i/o failed/not allowed
699     NTSTATUS RC = STATUS_SUCCESS;
700     PtrUDFIrpContext PtrIrpContext = NULL;
701 
702     FsRtlEnterFileSystem();
703 
704     _SEH2_TRY {
705 
706         _SEH2_TRY {
707 
708             // See description in UDFFastIoRead() before filling-in the
709             // stub here.
710             NOTHING;
711 
712 
713         } __except (UDFExceptionFilter(PtrIrpContext, GetExceptionInformation())) {
714 
715             RC = UDFExceptionHandler(PtrIrpContext, NULL);
716 
717             UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC);
718 
719         }
720 
721         //try_exit: NOTHING;
722 
723     } _SEH2_FINALLY {
724 
725     }
726 
727     FsRtlExitFileSystem();
728 
729     return(ReturnedStatus);
730 }*/
731 
732 
733 /*************************************************************************
734 *
735 * Function: UDFFastIoMdlReadComplete()
736 *
737 * Description:
738 *   Bypass the traditional IRP method to inform the NT Cache Manager and the
739 *   FSD that the caller no longer requires the data locked in the system cache
740 *   or the MDL to stay around anymore ..
741 *
742 * Expected Interrupt Level (for execution) :
743 *
744 *  IRQL_PASSIVE_LEVEL
745 *
746 * Return Value: TRUE/FALSE
747 *
748 *************************************************************************/
749 /*BOOLEAN UDFFastIoMdlReadComplete(
750 IN PFILE_OBJECT             FileObject,
751 OUT PMDL                            MdlChain,
752 IN PDEVICE_OBJECT               DeviceObject)
753 {
754     BOOLEAN             ReturnedStatus = FALSE;     // fast i/o failed/not allowed
755     NTSTATUS                RC = STATUS_SUCCESS;
756    PtrUDFIrpContext PtrIrpContext = NULL;
757 
758     FsRtlEnterFileSystem();
759 
760     _SEH2_TRY {
761 
762         _SEH2_TRY {
763 
764             // See description in UDFFastIoRead() before filling-in the
765             // stub here.
766             NOTHING;
767 
768         } __except (UDFExceptionFilter(PtrIrpContext, GetExceptionInformation())) {
769 
770             RC = UDFExceptionHandler(PtrIrpContext, NULL);
771 
772             UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC);
773 
774         }
775 
776         //try_exit: NOTHING;
777 
778     } _SEH2_FINALLY {
779 
780     }
781 
782     FsRtlExitFileSystem();
783 
784     return(ReturnedStatus);
785 }*/
786 
787 
788 /*************************************************************************
789 *
790 * Function: UDFFastIoPrepareMdlWrite()
791 *
792 * Description:
793 *   Bypass the traditional IRP method to prepare for a MDL write operation.
794 *
795 * Expected Interrupt Level (for execution) :
796 *
797 *  IRQL_PASSIVE_LEVEL
798 *
799 * Return Value: TRUE/FALSE
800 *
801 *************************************************************************/
802 /*BOOLEAN
803 UDFFastIoPrepareMdlWrite(
804     IN PFILE_OBJECT      FileObject,
805     IN PLARGE_INTEGER    FileOffset,
806     IN ULONG             Length,
807     IN ULONG             LockKey,
808     OUT PMDL             *MdlChain,
809     OUT PIO_STATUS_BLOCK IoStatus,
810     IN PDEVICE_OBJECT    DeviceObject
811     )
812 {
813     BOOLEAN              ReturnedStatus = FALSE; // fast i/o failed/not allowed
814     NTSTATUS             RC = STATUS_SUCCESS;
815    PtrUDFIrpContext PtrIrpContext = NULL;
816 
817     FsRtlEnterFileSystem();
818 
819     _SEH2_TRY {
820 
821         _SEH2_TRY {
822 
823             // See description in UDFFastIoRead() before filling-in the
824             // stub here.
825             NOTHING;
826 
827         } __except (UDFExceptionFilter(PtrIrpContext, GetExceptionInformation())) {
828 
829             RC = UDFExceptionHandler(PtrIrpContext, NULL);
830 
831             UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC);
832 
833         }
834 
835         //try_exit: NOTHING;
836 
837     } _SEH2_FINALLY {
838 
839     }
840 
841     FsRtlExitFileSystem();
842 
843     return(ReturnedStatus);
844 }*/
845 
846 
847 /*************************************************************************
848 *
849 * Function: UDFFastIoMdlWriteComplete()
850 *
851 * Description:
852 *   Bypass the traditional IRP method to inform the NT Cache Manager and the
853 *   FSD that the caller has updated the contents of the MDL. This data can
854 *   now be asynchronously written out to secondary storage by the Cache Mgr.
855 *
856 * Expected Interrupt Level (for execution) :
857 *
858 *  IRQL_PASSIVE_LEVEL
859 *
860 * Return Value: TRUE/FALSE
861 *
862 *************************************************************************/
863 /*BOOLEAN UDFFastIoMdlWriteComplete(
864 IN PFILE_OBJECT             FileObject,
865 IN PLARGE_INTEGER               FileOffset,
866 OUT PMDL                            MdlChain,
867 IN PDEVICE_OBJECT               DeviceObject)
868 {
869     BOOLEAN             ReturnedStatus = FALSE;     // fast i/o failed/not allowed
870     NTSTATUS                RC = STATUS_SUCCESS;
871    PtrUDFIrpContext PtrIrpContext = NULL;
872 
873     FsRtlEnterFileSystem();
874 
875     _SEH2_TRY {
876 
877         _SEH2_TRY {
878 
879             // See description in UDFFastIoRead() before filling-in the
880             // stub here.
881             NOTHING;
882 
883         } __except (UDFExceptionFilter(PtrIrpContext, GetExceptionInformation())) {
884 
885             RC = UDFExceptionHandler(PtrIrpContext, NULL);
886 
887             UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC);
888 
889         }
890 
891         //try_exit: NOTHING;
892 
893     } _SEH2_FINALLY {
894 
895     }
896 
897     FsRtlExitFileSystem();
898 
899     return(ReturnedStatus);
900 }*/
901 
902 
903 /*************************************************************************
904 *
905 * Function: UDFFastIoAcqModWrite()
906 *
907 * Description:
908 *   Not really a fast-io operation. Used by the VMM to acquire FSD resources
909 *   before initiating a write operation via the Modified Page/Block Writer.
910 *
911 * Expected Interrupt Level (for execution) :
912 *
913 *  IRQL_PASSIVE_LEVEL
914 *
915 * Return Value: STATUS_SUCCESS/Error (__try not to return an error, will 'ya ? :-)
916 *
917 *************************************************************************/
918 NTSTATUS
919 NTAPI
920 UDFFastIoAcqModWrite(
921     IN PFILE_OBJECT   FileObject,
922     IN PLARGE_INTEGER EndingOffset,
923     OUT PERESOURCE    *ResourceToRelease,
924     IN PDEVICE_OBJECT DeviceObject)
925 {
926     NTSTATUS RC = STATUS_SUCCESS;
927 
928     FsRtlEnterFileSystem();
929 
930     MmPrint(("  AcqModW %I64x\n", EndingOffset->QuadPart));
931 
932 #define NtReqFcb ((PtrUDFNTRequiredFCB)(FileObject->FsContext))
933 
934     // We must determine which resource(s) we would like to
935     // acquire at this time. We know that a write is imminent;
936     // we will probably therefore acquire appropriate resources
937     // exclusively.
938 
939     // We must first get the FCB and CCB pointers from the file object
940     // that is passed in to this function (as an argument). Note that
941     // the ending offset (when examined in conjunction with current valid data
942     // length) may help us in determining the appropriate resource(s) to acquire.
943 
944     // For example, if the ending offset is beyond current valid data length,
945     // We may decide to acquire *both* the MainResource and the PagingIoResource
946     // exclusively; otherwise, we may decide simply to acquire the PagingIoResource.
947 
948     // Consult the text for more information on synchronization in FSDs.
949 
950     // One final note; the VMM expects that we will return a pointer to
951     // the resource that we acquired (single return value). This pointer
952     // will be returned back to we in the release call (below).
953 
954     if(UDFAcquireResourceShared(&(NtReqFcb->PagingIoResource), FALSE)) {
955         if(EndingOffset->QuadPart <= NtReqFcb->CommonFCBHeader.ValidDataLength.QuadPart) {
956             UDFReleaseResource(&(NtReqFcb->PagingIoResource));
957             RC = STATUS_CANT_WAIT;
958         } else {
959             NtReqFcb->AcqFlushCount++;
960             (*ResourceToRelease) = &(NtReqFcb->PagingIoResource);
961             MmPrint(("    AcqModW OK\n"));
962         }
963     } else {
964         RC = STATUS_CANT_WAIT;
965     }
966 
967 #undef NtReqFcb
968 
969     FsRtlExitFileSystem();
970 
971     return RC;
972 } // end UDFFastIoAcqModWrite()
973 
974 
975 /*************************************************************************
976 *
977 * Function: UDFFastIoRelModWrite()
978 *
979 * Description:
980 *   Not really a fast-io operation. Used by the VMM to release FSD resources
981 *   after processing a modified page/block write operation.
982 *
983 * Expected Interrupt Level (for execution) :
984 *
985 *  IRQL_PASSIVE_LEVEL
986 *
987 * Return Value: STATUS_SUCCESS/Error (an error returned here is really not expected!)
988 *
989 *************************************************************************/
990 NTSTATUS
991 NTAPI
992 UDFFastIoRelModWrite(
993     IN PFILE_OBJECT   FileObject,
994     IN PERESOURCE     ResourceToRelease,
995     IN PDEVICE_OBJECT DeviceObject)
996 {
997     FsRtlEnterFileSystem();
998 
999     MmPrint(("  RelModW\n"));
1000 
1001 #define NtReqFcb ((PtrUDFNTRequiredFCB)(FileObject->FsContext))
1002 
1003     // The MPW has complete the write for modified pages and therefore
1004     // wants us to release pre-acquired resource(s).
1005 
1006     // We must undo here whatever it is that we did in the
1007     // UDFFastIoAcqModWrite() call above.
1008 
1009     NtReqFcb->AcqFlushCount--;
1010     ASSERT(ResourceToRelease == &(NtReqFcb->PagingIoResource));
1011     UDFReleaseResource(ResourceToRelease);
1012 
1013 #undef NtReqFcb
1014 
1015     FsRtlExitFileSystem();
1016 
1017     return(STATUS_SUCCESS);
1018 } // end UDFFastIoRelModWrite()
1019 
1020 
1021 /*************************************************************************
1022 *
1023 * Function: UDFFastIoAcqCcFlush()
1024 *
1025 * Description:
1026 *   Not really a fast-io operation. Used by the NT Cache Mgr to acquire FSD
1027 *   resources before performing a CcFlush() operation on a specific file
1028 *   stream.
1029 *
1030 * Expected Interrupt Level (for execution) :
1031 *
1032 *  IRQL_PASSIVE_LEVEL
1033 *
1034 * Return Value: STATUS_SUCCESS/Error
1035 *
1036 *************************************************************************/
1037 NTSTATUS
1038 NTAPI
1039 UDFFastIoAcqCcFlush(
1040     IN PFILE_OBJECT         FileObject,
1041     IN PDEVICE_OBJECT       DeviceObject)
1042 {
1043 //    NTSTATUS                RC = STATUS_SUCCESS;
1044 
1045     FsRtlEnterFileSystem();
1046 
1047     MmPrint(("  AcqCcFlush\n"));
1048 
1049     // Acquire appropriate resources that will allow correct synchronization
1050     // with a flush call (and avoid deadlock).
1051 
1052 #define NtReqFcb ((PtrUDFNTRequiredFCB)(FileObject->FsContext))
1053 
1054 //    UDFAcquireResourceExclusive(&(NtReqFcb->MainResource), TRUE);
1055     UDFAcquireResourceExclusive(&(NtReqFcb->PagingIoResource), TRUE);
1056 //    ASSERT(!(NtReqFcb->AcqFlushCount));
1057     NtReqFcb->AcqFlushCount++;
1058 
1059 #undef NtReqFcb
1060 
1061     FsRtlExitFileSystem();
1062 
1063     return(STATUS_SUCCESS);
1064 
1065 } // end UDFFastIoAcqCcFlush()
1066 
1067 /*************************************************************************
1068 *
1069 * Function: UDFFastIoRelCcFlush()
1070 *
1071 * Description:
1072 *   Not really a fast-io operation. Used by the NT Cache Mgr to acquire FSD
1073 *   resources before performing a CcFlush() operation on a specific file
1074 *   stream.
1075 *
1076 * Expected Interrupt Level (for execution) :
1077 *
1078 *  IRQL_PASSIVE_LEVEL
1079 *
1080 * Return Value: STATUS_SUCCESS/Error
1081 *
1082 *************************************************************************/
1083 NTSTATUS
1084 NTAPI
1085 UDFFastIoRelCcFlush(
1086     IN PFILE_OBJECT         FileObject,
1087     IN PDEVICE_OBJECT       DeviceObject
1088     )
1089 {
1090 //    NTSTATUS                RC = STATUS_SUCCESS;
1091 
1092     FsRtlEnterFileSystem();
1093 
1094     MmPrint(("  RelCcFlush\n"));
1095 
1096 #define NtReqFcb ((PtrUDFNTRequiredFCB)(FileObject->FsContext))
1097 
1098     // Release resources acquired in UDFFastIoAcqCcFlush() above.
1099 
1100     NtReqFcb->AcqFlushCount--;
1101     UDFReleaseResource(&(NtReqFcb->PagingIoResource));
1102 //    UDFReleaseResource(&(NtReqFcb->MainResource));
1103 
1104 #undef NtReqFcb
1105 
1106     FsRtlExitFileSystem();
1107 
1108     return(STATUS_SUCCESS);
1109 
1110 } // end UDFFastIoRelCcFlush()
1111 
1112 
1113 /*BOOLEAN
1114 UDFFastIoDeviceControl (
1115     IN PFILE_OBJECT FileObject,
1116     IN BOOLEAN Wait,
1117     IN PVOID InputBuffer OPTIONAL,
1118     IN ULONG InputBufferLength,
1119     OUT PVOID OutputBuffer OPTIONAL,
1120     IN ULONG OutputBufferLength,
1121     IN ULONG IoControlCode,
1122     OUT PIO_STATUS_BLOCK IoStatus,
1123     IN PDEVICE_OBJECT DeviceObject
1124     )
1125 {
1126     switch(IoControlCode) {
1127     case FSCTL_ALLOW_EXTENDED_DASD_IO: {
1128         IoStatus->Information = 0;
1129         IoStatus->Status = STATUS_SUCCESS;
1130         break;
1131     }
1132     case FSCTL_IS_VOLUME_MOUNTED: {
1133         PtrUDFFCB Fcb;
1134         PtrUDFCCB Ccb;
1135 
1136         Ccb = (PtrUDFCCB)(FileObject->FsContext2);
1137         Fcb = Ccb->Fcb;
1138 
1139         if(Fcb &&
1140            !(Fcb->Vcb->VCBFlags & UDF_VCB_FLAGS_RAW_DISK) &&
1141            !(Fcb->Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_LOCKED) ) {
1142             return FALSE;
1143         }
1144 
1145         IoStatus->Information = 0;
1146         IoStatus->Status = STATUS_SUCCESS;
1147 
1148         break;
1149     }
1150     default:
1151         return FALSE;
1152     }
1153     return TRUE;
1154 }*/
1155 
1156 #endif  //_WIN32_WINNT >= 0x0400
1157 
1158 BOOLEAN
1159 NTAPI
1160 UDFFastIoCopyWrite (
1161     IN PFILE_OBJECT FileObject,
1162     IN PLARGE_INTEGER FileOffset,
1163     IN ULONG Length,
1164     IN BOOLEAN Wait,
1165     IN ULONG LockKey,
1166     IN PVOID Buffer,
1167     OUT PIO_STATUS_BLOCK IoStatus,
1168     IN PDEVICE_OBJECT DeviceObject
1169     )
1170 {
1171     PtrUDFFCB           Fcb = NULL;
1172     PtrUDFCCB           Ccb = NULL;
1173 
1174     // Obtain a pointer to the FCB and CCB for the file stream.
1175     Ccb = (PtrUDFCCB)(FileObject->FsContext2);
1176     ASSERT(Ccb);
1177     Fcb = Ccb->Fcb;
1178     ASSERT(Fcb);
1179 
1180     // back pressure for very smart and fast system cache ;)
1181     if(Fcb->Vcb->VerifyCtx.QueuedCount ||
1182        Fcb->Vcb->VerifyCtx.ItemCount >= UDF_MAX_VERIFY_CACHE) {
1183         AdPrint(("    Verify queue overflow -> UDFFastIoCopyWrite() = FALSE\n"));
1184         return FALSE;
1185     }
1186     if(Fcb->NTRequiredFCB->SectionObject.DataSectionObject &&
1187        Length >= 0x10000 &&
1188        FileOffset->LowPart &&
1189        !(FileOffset->LowPart & 0x00ffffff)) {
1190 
1191         MmPrint(("    no FastIo 16Mb\n"));
1192         return FALSE;
1193     }
1194     return FsRtlCopyWrite(FileObject, FileOffset, Length, Wait, LockKey, Buffer, IoStatus, DeviceObject);
1195 
1196 } // end UDFFastIoCopyWrite()
1197