[FASTFAT] Implement delayed close
[reactos.git] / 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 // 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 = (unsigned int)(PsGetCurrentThread());
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) == (unsigned int)PsGetCurrentThread());
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()