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