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