1 /*++ 2 3 Copyright (c) 1989-2000 Microsoft Corporation 4 5 Module Name: 6 7 FatProcs.h 8 9 Abstract: 10 11 This module defines all of the globally used procedures in the FAT 12 file system. 13 14 15 --*/ 16 17 #ifndef _FATPROCS_ 18 #define _FATPROCS_ 19 20 #ifdef _MSC_VER 21 #pragma warning( disable: 4127 ) // conditional expression is constant 22 23 #pragma warning( push ) 24 #pragma warning( disable: 4201 ) // nonstandard extension used : nameless struct/union 25 #pragma warning( disable: 4214 ) // nonstandard extension used : bit field types 26 #endif 27 28 #include <ntifs.h> 29 30 31 #include <ntddscsi.h> 32 #include <scsi.h> 33 #include <ntddcdrm.h> 34 #include <ntdddisk.h> 35 #include <ntddstor.h> 36 #include <ntintsafe.h> 37 #ifdef __REACTOS__ 38 #include <pseh/pseh2.h> 39 #endif 40 41 42 #ifdef __REACTOS__ 43 // Downgrade unsupported NT6.2+ features. 44 #undef MdlMappingNoExecute 45 #define MdlMappingNoExecute 0 46 #define NonPagedPoolNx NonPagedPool 47 #define NonPagedPoolNxCacheAligned NonPagedPoolCacheAligned 48 #undef POOL_NX_ALLOCATION 49 #define POOL_NX_ALLOCATION 0 50 51 // Moved up: needed in 'fatstruc.h'. 52 typedef enum _TYPE_OF_OPEN { 53 54 UnopenedFileObject = 1, 55 UserFileOpen, 56 UserDirectoryOpen, 57 UserVolumeOpen, 58 VirtualVolumeFile, 59 DirectoryFile, 60 EaFile, 61 } TYPE_OF_OPEN; 62 #endif 63 64 #include "nodetype.h" 65 #include "fat.h" 66 #include "lfn.h" 67 #include "fatstruc.h" 68 #include "fatdata.h" 69 70 71 72 #ifdef _MSC_VER 73 #pragma warning( pop ) 74 #endif 75 76 #ifndef INLINE 77 #define INLINE __inline 78 #endif 79 80 #define Add2Ptr(P,I) ((PVOID)((PUCHAR)(P) + (I))) 81 82 #ifndef MAX_ULONG 83 #define MAX_ULONG ((ULONG)-1) 84 #endif 85 86 #ifndef MAX_USHORT 87 #define MAX_USHORT ((USHORT)-1) 88 #endif 89 90 // 91 // We must explicitly tag our allocations. 92 // 93 94 #undef FsRtlAllocatePool 95 #undef FsRtlAllocatePoolWithQuota 96 97 // 98 // A function that returns finished denotes if it was able to complete the 99 // operation (TRUE) or could not complete the operation (FALSE) because the 100 // wait value stored in the irp context was false and we would have had 101 // to block for a resource or I/O 102 // 103 104 typedef BOOLEAN FINISHED; 105 106 // 107 // Size (characters) of stack allocated name component buffers in 108 // the create/rename paths. 109 // 110 111 #define FAT_CREATE_INITIAL_NAME_BUF_SIZE 32 112 113 114 // 115 // Some string buffer handling functions, implemented in strucsup.c 116 // 117 118 VOID 119 FatFreeStringBuffer ( 120 _Inout_ PVOID String 121 ); 122 123 VOID 124 FatExtendString( 125 _Inout_ PVOID String, 126 _In_ USHORT DesiredBufferSize, 127 _In_ BOOLEAN FreeOldBuffer, 128 __out_opt PBOOLEAN NeedsFree 129 ); 130 131 VOID 132 FatEnsureStringBufferEnough ( 133 _Inout_ PVOID String, 134 _In_ USHORT DesiredBufferSize 135 ); 136 137 BOOLEAN 138 FatAddMcbEntry ( 139 IN PVCB Vcb, 140 IN PLARGE_MCB Mcb, 141 IN VBO Vbo, 142 IN LBO Lbo, 143 IN ULONG SectorCount 144 ); 145 146 BOOLEAN 147 FatLookupMcbEntry ( 148 IN PVCB Vcb, 149 IN PLARGE_MCB Mcb, 150 IN VBO Vbo, 151 OUT PLBO Lbo, 152 OUT PULONG ByteCount OPTIONAL, 153 OUT PULONG Index OPTIONAL 154 ); 155 156 BOOLEAN 157 FatLookupLastMcbEntry ( 158 IN PVCB Vcb, 159 IN PLARGE_MCB Mcb, 160 OUT PVBO Vbo, 161 OUT PLBO Lbo, 162 OUT PULONG Index OPTIONAL 163 ); 164 165 BOOLEAN 166 FatGetNextMcbEntry ( 167 IN PVCB Vcb, 168 IN PLARGE_MCB Mcb, 169 IN ULONG RunIndex, 170 OUT PVBO Vbo, 171 OUT PLBO Lbo, 172 OUT PULONG ByteCount 173 ); 174 175 VOID 176 FatRemoveMcbEntry ( 177 IN PVCB Vcb, 178 IN PLARGE_MCB Mcb, 179 IN VBO Vbo, 180 IN ULONG SectorCount 181 ); 182 183 184 // 185 // File access check routine, implemented in AcChkSup.c 186 // 187 188 BOOLEAN 189 FatCheckFileAccess ( 190 PIRP_CONTEXT IrpContext, 191 IN UCHAR DirentAttributes, 192 IN PACCESS_MASK DesiredAccess 193 ); 194 195 BOOLEAN 196 FatCheckManageVolumeAccess ( 197 _In_ PIRP_CONTEXT IrpContext, 198 _In_ PACCESS_STATE AccessState, 199 _In_ KPROCESSOR_MODE ProcessorMode 200 ); 201 202 NTSTATUS 203 FatExplicitDeviceAccessGranted ( 204 IN PIRP_CONTEXT IrpContext, 205 IN PDEVICE_OBJECT DeviceObject, 206 IN PACCESS_STATE AccessState, 207 IN KPROCESSOR_MODE ProcessorMode 208 ); 209 210 211 // 212 // Allocation support routines, implemented in AllocSup.c 213 // 214 215 static 216 INLINE 217 BOOLEAN 218 FatIsIoRangeValid ( 219 IN PVCB Vcb, 220 IN LARGE_INTEGER Start, 221 IN ULONG Length 222 ) 223 224 /*++ 225 226 Routine Description: 227 228 This routine enforces the restriction that object space must be 229 representable in 32 bits. 230 231 Arguments: 232 233 Vcb - the volume the range is on 234 235 Start - starting byte (zero based) of the range 236 237 Length - size of the range 238 239 HeaderSize - if the file has a header 240 241 Return Value: 242 243 BOOLEAN - if, considering the cluster size, the neccesary size of 244 the object to contain the range can be represented in 32 bits. 245 246 --*/ 247 248 { 249 250 UNREFERENCED_PARAMETER( Vcb ); 251 252 // 253 // The only restriction on a FAT object is that the filesize must 254 // fit in 32bits, i.e. <= 0xffffffff. This then implies that the 255 // range of valid byte offsets is [0, fffffffe]. 256 // 257 // Two phases which check for illegality 258 // 259 // - if the high 32bits are nonzero 260 // - if the length would cause a 32bit overflow 261 // 262 263 return !(Start.HighPart || 264 Start.LowPart + Length < Start.LowPart); 265 } 266 267 268 // 269 // This strucure is used by FatLookupFatEntry to remember a pinned page 270 // of fat. 271 // 272 273 typedef struct _FAT_ENUMERATION_CONTEXT { 274 275 VBO VboOfPinnedPage; 276 PBCB Bcb; 277 PVOID PinnedPage; 278 279 } FAT_ENUMERATION_CONTEXT, *PFAT_ENUMERATION_CONTEXT; 280 281 VOID 282 FatLookupFatEntry ( 283 IN PIRP_CONTEXT IrpContext, 284 IN PVCB Vcb, 285 IN ULONG FatIndex, 286 IN OUT PULONG FatEntry, 287 IN OUT PFAT_ENUMERATION_CONTEXT Context 288 ); 289 290 VOID 291 FatSetupAllocationSupport ( 292 IN PIRP_CONTEXT IrpContext, 293 IN PVCB Vcb 294 ); 295 296 VOID 297 FatTearDownAllocationSupport ( 298 IN PIRP_CONTEXT IrpContext, 299 IN PVCB Vcb 300 ); 301 302 _Requires_lock_held_(_Global_critical_region_) 303 VOID 304 FatLookupFileAllocation ( 305 IN PIRP_CONTEXT IrpContext, 306 IN PFCB FcbOrDcb, 307 IN VBO Vbo, 308 OUT PLBO Lbo, 309 OUT PULONG ByteCount, 310 OUT PBOOLEAN Allocated, 311 OUT PBOOLEAN EndOnMax, 312 OUT PULONG Index OPTIONAL 313 ); 314 315 _Requires_lock_held_(_Global_critical_region_) 316 VOID 317 FatAddFileAllocation ( 318 IN PIRP_CONTEXT IrpContext, 319 IN PFCB FcbOrDcb, 320 IN PFILE_OBJECT FileObject OPTIONAL, 321 IN ULONG AllocationSize 322 ); 323 324 _Requires_lock_held_(_Global_critical_region_) 325 VOID 326 FatTruncateFileAllocation ( 327 IN PIRP_CONTEXT IrpContext, 328 IN PFCB FcbOrDcb, 329 IN ULONG AllocationSize 330 ); 331 332 _Requires_lock_held_(_Global_critical_region_) 333 VOID 334 FatLookupFileAllocationSize ( 335 IN PIRP_CONTEXT IrpContext, 336 IN PFCB FcbOrDcb 337 ); 338 339 _Requires_lock_held_(_Global_critical_region_) 340 VOID 341 FatAllocateDiskSpace ( 342 IN PIRP_CONTEXT IrpContext, 343 IN PVCB Vcb, 344 IN ULONG AbsoluteClusterHint, 345 IN OUT PULONG ByteCount, 346 IN BOOLEAN ExactMatchRequired, 347 OUT PLARGE_MCB Mcb 348 ); 349 350 _Requires_lock_held_(_Global_critical_region_) 351 VOID 352 FatDeallocateDiskSpace ( 353 IN PIRP_CONTEXT IrpContext, 354 IN PVCB Vcb, 355 IN PLARGE_MCB Mcb, 356 IN BOOLEAN ZeroOnDeallocate 357 ); 358 359 _Requires_lock_held_(_Global_critical_region_) 360 VOID 361 FatSplitAllocation ( 362 IN PIRP_CONTEXT IrpContext, 363 IN PVCB Vcb, 364 IN OUT PLARGE_MCB Mcb, 365 IN VBO SplitAtVbo, 366 OUT PLARGE_MCB RemainingMcb 367 ); 368 369 _Requires_lock_held_(_Global_critical_region_) 370 VOID 371 FatMergeAllocation ( 372 IN PIRP_CONTEXT IrpContext, 373 IN PVCB Vcb, 374 IN OUT PLARGE_MCB Mcb, 375 IN PLARGE_MCB SecondMcb 376 ); 377 378 _Requires_lock_held_(_Global_critical_region_) 379 VOID 380 FatSetFatEntry ( 381 IN PIRP_CONTEXT IrpContext, 382 IN PVCB Vcb, 383 IN ULONG FatIndex, 384 IN FAT_ENTRY FatEntry 385 ); 386 387 UCHAR 388 FatLogOf( 389 IN ULONG Value 390 ); 391 392 393 // 394 // Buffer control routines for data caching, implemented in CacheSup.c 395 // 396 397 VOID 398 FatReadVolumeFile ( 399 IN PIRP_CONTEXT IrpContext, 400 IN PVCB Vcb, 401 IN VBO StartingVbo, 402 IN ULONG ByteCount, 403 OUT PBCB *Bcb, 404 OUT PVOID *Buffer 405 ); 406 407 _Requires_lock_held_(_Global_critical_region_) 408 VOID 409 FatPrepareWriteVolumeFile ( 410 IN PIRP_CONTEXT IrpContext, 411 IN PVCB Vcb, 412 IN VBO StartingVbo, 413 IN ULONG ByteCount, 414 OUT PBCB *Bcb, 415 OUT PVOID *Buffer, 416 IN BOOLEAN Reversible, 417 IN BOOLEAN Zero 418 ); 419 420 _Requires_lock_held_(_Global_critical_region_) 421 VOID 422 FatReadDirectoryFile ( 423 IN PIRP_CONTEXT IrpContext, 424 IN PDCB Dcb, 425 IN VBO StartingVbo, 426 IN ULONG ByteCount, 427 IN BOOLEAN Pin, 428 OUT PBCB *Bcb, 429 OUT PVOID *Buffer, 430 OUT PNTSTATUS Status 431 ); 432 433 _Requires_lock_held_(_Global_critical_region_) 434 VOID 435 FatPrepareWriteDirectoryFile ( 436 IN PIRP_CONTEXT IrpContext, 437 IN PDCB Dcb, 438 IN VBO StartingVbo, 439 IN ULONG ByteCount, 440 OUT PBCB *Bcb, 441 OUT PVOID *Buffer, 442 IN BOOLEAN Zero, 443 IN BOOLEAN Reversible, 444 OUT PNTSTATUS Status 445 ); 446 447 _Requires_lock_held_(_Global_critical_region_) 448 VOID 449 FatOpenDirectoryFile ( 450 IN PIRP_CONTEXT IrpContext, 451 IN PDCB Dcb 452 ); 453 454 PFILE_OBJECT 455 FatOpenEaFile ( 456 IN PIRP_CONTEXT IrpContext, 457 IN PFCB EaFcb 458 ); 459 460 VOID 461 FatCloseEaFile ( 462 IN PIRP_CONTEXT IrpContext, 463 IN PVCB Vcb, 464 IN BOOLEAN FlushFirst 465 ); 466 467 468 _Requires_lock_held_(_Global_critical_region_) 469 VOID 470 FatSetDirtyBcb ( 471 IN PIRP_CONTEXT IrpContext, 472 IN PBCB Bcb, 473 IN PVCB Vcb OPTIONAL, 474 IN BOOLEAN Reversible 475 ); 476 477 VOID 478 FatRepinBcb ( 479 IN PIRP_CONTEXT IrpContext, 480 IN PBCB Bcb 481 ); 482 483 VOID 484 FatUnpinRepinnedBcbs ( 485 IN PIRP_CONTEXT IrpContext 486 ); 487 488 FINISHED 489 FatZeroData ( 490 IN PIRP_CONTEXT IrpContext, 491 IN PVCB Vcb, 492 IN PFILE_OBJECT FileObject, 493 IN ULONG StartingZero, 494 IN ULONG ByteCount 495 ); 496 497 NTSTATUS 498 FatCompleteMdl ( 499 IN PIRP_CONTEXT IrpContext, 500 IN PIRP Irp 501 ); 502 503 VOID 504 FatPinMappedData ( 505 IN PIRP_CONTEXT IrpContext, 506 IN PDCB Dcb, 507 IN VBO StartingVbo, 508 IN ULONG ByteCount, 509 OUT PBCB *Bcb 510 ); 511 512 NTSTATUS 513 FatPrefetchPages ( 514 IN PIRP_CONTEXT IrpContext, 515 IN PFILE_OBJECT FileObject, 516 IN ULONG StartingPage, 517 IN ULONG PageCount 518 ); 519 520 // 521 // VOID 522 // FatUnpinBcb ( 523 // IN PIRP_CONTEXT IrpContext, 524 // IN OUT PBCB Bcb, 525 // ); 526 // 527 528 // 529 // This macro unpins a Bcb, in the checked build make sure all 530 // requests unpin all Bcbs before leaving. 531 // 532 533 #if DBG 534 535 #define FatUnpinBcb(IRPCONTEXT,BCB) { \ 536 if ((BCB) != NULL) { \ 537 CcUnpinData((BCB)); \ 538 NT_ASSERT( (IRPCONTEXT)->PinCount );\ 539 (IRPCONTEXT)->PinCount -= 1; \ 540 (BCB) = NULL; \ 541 } \ 542 } 543 544 #else 545 546 #define FatUnpinBcb(IRPCONTEXT,BCB) { \ 547 if ((BCB) != NULL) { \ 548 CcUnpinData((BCB)); \ 549 (BCB) = NULL; \ 550 } \ 551 } 552 553 #endif // DBG 554 555 VOID 556 FatInitializeCacheMap ( 557 _In_ PFILE_OBJECT FileObject, 558 _In_ PCC_FILE_SIZES FileSizes, 559 _In_ BOOLEAN PinAccess, 560 _In_ PCACHE_MANAGER_CALLBACKS Callbacks, 561 _In_ PVOID LazyWriteContext 562 ); 563 564 VOID 565 FatSyncUninitializeCacheMap ( 566 IN PIRP_CONTEXT IrpContext, 567 IN PFILE_OBJECT FileObject 568 ); 569 570 571 // 572 // Device I/O routines, implemented in DevIoSup.c 573 // 574 // These routines perform the actual device read and writes. They only affect 575 // the on disk structure and do not alter any other data structures. 576 // 577 578 VOID 579 FatPagingFileIo ( 580 IN PIRP Irp, 581 IN PFCB Fcb 582 ); 583 584 585 _Requires_lock_held_(_Global_critical_region_) 586 NTSTATUS 587 FatNonCachedIo ( 588 IN PIRP_CONTEXT IrpContext, 589 IN PIRP Irp, 590 IN PFCB FcbOrDcb, 591 IN ULONG StartingVbo, 592 IN ULONG ByteCount, 593 IN ULONG UserByteCount, 594 IN ULONG StreamFlags 595 ); 596 597 _Requires_lock_held_(_Global_critical_region_) 598 VOID 599 FatNonCachedNonAlignedRead ( 600 IN PIRP_CONTEXT IrpContext, 601 IN PIRP Irp, 602 IN PFCB FcbOrDcb, 603 IN ULONG StartingVbo, 604 IN ULONG ByteCount 605 ); 606 607 VOID 608 FatMultipleAsync ( 609 IN PIRP_CONTEXT IrpContext, 610 IN PVCB Vcb, 611 IN PIRP Irp, 612 IN ULONG MultipleIrpCount, 613 IN PIO_RUN IoRuns 614 ); 615 616 VOID 617 FatSingleAsync ( 618 IN PIRP_CONTEXT IrpContext, 619 IN PVCB Vcb, 620 IN LBO Lbo, 621 IN ULONG ByteCount, 622 IN PIRP Irp 623 ); 624 625 VOID 626 FatWaitSync ( 627 IN PIRP_CONTEXT IrpContext 628 ); 629 630 VOID 631 FatLockUserBuffer ( 632 IN PIRP_CONTEXT IrpContext, 633 IN OUT PIRP Irp, 634 IN LOCK_OPERATION Operation, 635 IN ULONG BufferLength 636 ); 637 638 PVOID 639 FatBufferUserBuffer ( 640 IN PIRP_CONTEXT IrpContext, 641 IN OUT PIRP Irp, 642 IN ULONG BufferLength 643 ); 644 645 PVOID 646 FatMapUserBuffer ( 647 IN PIRP_CONTEXT IrpContext, 648 IN OUT PIRP Irp 649 ); 650 651 NTSTATUS 652 FatToggleMediaEjectDisable ( 653 IN PIRP_CONTEXT IrpContext, 654 IN PVCB Vcb, 655 IN BOOLEAN PreventRemoval 656 ); 657 658 NTSTATUS 659 FatPerformDevIoCtrl ( 660 IN PIRP_CONTEXT IrpContext, 661 IN ULONG IoControlCode, 662 IN PDEVICE_OBJECT Device, 663 IN PVOID InputBuffer OPTIONAL, 664 IN ULONG InputBufferLength, 665 OUT PVOID OutputBuffer OPTIONAL, 666 IN ULONG OutputBufferLength, 667 IN BOOLEAN InternalDeviceIoControl, 668 IN BOOLEAN OverrideVerify, 669 OUT PIO_STATUS_BLOCK Iosb OPTIONAL 670 ); 671 672 PMDL 673 FatBuildZeroMdl ( 674 __in PIRP_CONTEXT IrpContext, 675 __in ULONG Length 676 ); 677 678 679 // 680 // Dirent support routines, implemented in DirSup.c 681 // 682 683 // 684 // Tunneling is a deletion precursor (all tunneling cases do 685 // not involve deleting dirents, however) 686 // 687 688 VOID 689 FatTunnelFcbOrDcb ( 690 IN PFCB FcbOrDcb, 691 IN PCCB Ccb OPTIONAL 692 ); 693 694 _Requires_lock_held_(_Global_critical_region_) 695 ULONG 696 FatCreateNewDirent ( 697 IN PIRP_CONTEXT IrpContext, 698 IN PDCB ParentDirectory, 699 IN ULONG DirentsNeeded, 700 IN BOOLEAN RescanDir 701 ); 702 703 _Requires_lock_held_(_Global_critical_region_) 704 VOID 705 FatInitializeDirectoryDirent ( 706 IN PIRP_CONTEXT IrpContext, 707 IN PDCB Dcb, 708 IN PDIRENT ParentDirent 709 ); 710 711 _Requires_lock_held_(_Global_critical_region_) 712 VOID 713 FatDeleteDirent ( 714 IN PIRP_CONTEXT IrpContext, 715 IN PFCB FcbOrDcb, 716 IN PDELETE_CONTEXT DeleteContext OPTIONAL, 717 IN BOOLEAN DeleteEa 718 ); 719 720 721 _Requires_lock_held_(_Global_critical_region_) 722 VOID 723 FatLocateDirent ( 724 IN PIRP_CONTEXT IrpContext, 725 IN PDCB ParentDirectory, 726 IN PCCB Ccb, 727 IN VBO OffsetToStartSearchFrom, 728 IN OUT PULONG Flags, 729 OUT PDIRENT *Dirent, 730 OUT PBCB *Bcb, 731 OUT PVBO ByteOffset, 732 OUT PBOOLEAN FileNameDos OPTIONAL, 733 IN OUT PUNICODE_STRING Lfn OPTIONAL, 734 IN OUT PUNICODE_STRING OrigLfn OPTIONAL 735 ); 736 737 _Requires_lock_held_(_Global_critical_region_) 738 VOID 739 FatLocateSimpleOemDirent ( 740 IN PIRP_CONTEXT IrpContext, 741 IN PDCB ParentDirectory, 742 IN POEM_STRING FileName, 743 OUT PDIRENT *Dirent, 744 OUT PBCB *Bcb, 745 OUT PVBO ByteOffset 746 ); 747 748 _Requires_lock_held_(_Global_critical_region_) 749 BOOLEAN 750 FatLfnDirentExists ( 751 IN PIRP_CONTEXT IrpContext, 752 IN PDCB Dcb, 753 IN PUNICODE_STRING Lfn, 754 IN PUNICODE_STRING LfnTmp 755 ); 756 757 _Requires_lock_held_(_Global_critical_region_) 758 VOID 759 FatLocateVolumeLabel ( 760 IN PIRP_CONTEXT IrpContext, 761 IN PVCB Vcb, 762 OUT PDIRENT *Dirent, 763 OUT PBCB *Bcb, 764 OUT PVBO ByteOffset 765 ); 766 767 _Requires_lock_held_(_Global_critical_region_) 768 VOID 769 FatGetDirentFromFcbOrDcb ( 770 IN PIRP_CONTEXT IrpContext, 771 IN PFCB FcbOrDcb, 772 IN BOOLEAN ReturnOnFailure, 773 OUT PDIRENT *Dirent, 774 OUT PBCB *Bcb 775 ); 776 777 _Requires_lock_held_(_Global_critical_region_) 778 BOOLEAN 779 FatIsDirectoryEmpty ( 780 IN PIRP_CONTEXT IrpContext, 781 IN PDCB Dcb 782 ); 783 784 _Requires_lock_held_(_Global_critical_region_) 785 VOID 786 FatDeleteFile ( 787 IN PIRP_CONTEXT IrpContext, 788 IN PDCB TargetDcb, 789 IN ULONG LfnOffset, 790 IN ULONG DirentOffset, 791 IN PDIRENT Dirent, 792 IN PUNICODE_STRING Lfn 793 ); 794 795 796 VOID 797 FatConstructDirent ( 798 IN PIRP_CONTEXT IrpContext, 799 IN OUT PDIRENT Dirent, 800 IN POEM_STRING FileName, 801 IN BOOLEAN ComponentReallyLowercase, 802 IN BOOLEAN ExtensionReallyLowercase, 803 IN PUNICODE_STRING Lfn OPTIONAL, 804 IN USHORT Attributes, 805 IN BOOLEAN ZeroAndSetTimeFields, 806 IN PLARGE_INTEGER SetCreationTime OPTIONAL 807 ); 808 809 VOID 810 FatConstructLabelDirent ( 811 IN PIRP_CONTEXT IrpContext, 812 IN OUT PDIRENT Dirent, 813 IN POEM_STRING Label 814 ); 815 816 _Requires_lock_held_(_Global_critical_region_) 817 VOID 818 FatSetFileSizeInDirent ( 819 IN PIRP_CONTEXT IrpContext, 820 IN PFCB Fcb, 821 IN PULONG AlternativeFileSize OPTIONAL 822 ); 823 824 _Requires_lock_held_(_Global_critical_region_) 825 VOID 826 FatSetFileSizeInDirentNoRaise ( 827 IN PIRP_CONTEXT IrpContext, 828 IN PFCB Fcb, 829 IN PULONG AlternativeFileSize OPTIONAL 830 ); 831 832 833 _Requires_lock_held_(_Global_critical_region_) 834 VOID 835 FatUpdateDirentFromFcb ( 836 IN PIRP_CONTEXT IrpContext, 837 IN PFILE_OBJECT FileObject, 838 IN PFCB FcbOrDcb, 839 IN PCCB Ccb 840 ); 841 842 843 // 844 // Generate a relatively unique static 64bit ID from a FAT Fcb/Dcb 845 // 846 // ULONGLONG 847 // FatDirectoryKey (FcbOrDcb); 848 // 849 850 #define FatDirectoryKey(FcbOrDcb) ((ULONGLONG)((FcbOrDcb)->CreationTime.QuadPart ^ (FcbOrDcb)->FirstClusterOfFile)) 851 852 853 // 854 // The following routines are used to access and manipulate the 855 // clusters containing EA data in the ea data file. They are 856 // implemented in EaSup.c 857 // 858 859 // 860 // VOID 861 // FatUpcaseEaName ( 862 // IN PIRP_CONTEXT IrpContext, 863 // IN POEM_STRING EaName, 864 // OUT POEM_STRING UpcasedEaName 865 // ); 866 // 867 868 #define FatUpcaseEaName( IRPCONTEXT, NAME, UPCASEDNAME ) \ 869 RtlUpperString( UPCASEDNAME, NAME ) 870 871 _Requires_lock_held_(_Global_critical_region_) 872 VOID 873 FatGetEaLength ( 874 IN PIRP_CONTEXT IrpContext, 875 IN PVCB Vcb, 876 IN PDIRENT Dirent, 877 OUT PULONG EaLength 878 ); 879 880 _Requires_lock_held_(_Global_critical_region_) 881 VOID 882 FatGetNeedEaCount ( 883 IN PIRP_CONTEXT IrpContext, 884 IN PVCB Vcb, 885 IN PDIRENT Dirent, 886 OUT PULONG NeedEaCount 887 ); 888 889 _Requires_lock_held_(_Global_critical_region_) 890 VOID 891 FatCreateEa ( 892 IN PIRP_CONTEXT IrpContext, 893 IN PVCB Vcb, 894 IN PUCHAR Buffer, 895 IN ULONG Length, 896 IN POEM_STRING FileName, 897 OUT PUSHORT EaHandle 898 ); 899 900 _Requires_lock_held_(_Global_critical_region_) 901 VOID 902 FatDeleteEa ( 903 IN PIRP_CONTEXT IrpContext, 904 IN PVCB Vcb, 905 IN USHORT EaHandle, 906 IN POEM_STRING FileName 907 ); 908 909 _Requires_lock_held_(_Global_critical_region_) 910 VOID 911 FatGetEaFile ( 912 IN PIRP_CONTEXT IrpContext, 913 IN OUT PVCB Vcb, 914 OUT PDIRENT *EaDirent, 915 OUT PBCB *EaBcb, 916 IN BOOLEAN CreateFile, 917 IN BOOLEAN ExclusiveFcb 918 ); 919 920 VOID 921 FatReadEaSet ( 922 IN PIRP_CONTEXT IrpContext, 923 IN PVCB Vcb, 924 IN USHORT EaHandle, 925 IN POEM_STRING FileName, 926 IN BOOLEAN ReturnEntireSet, 927 OUT PEA_RANGE EaSetRange 928 ); 929 930 _Requires_lock_held_(_Global_critical_region_) 931 VOID 932 FatDeleteEaSet ( 933 IN PIRP_CONTEXT IrpContext, 934 IN PVCB Vcb, 935 IN PBCB EaBcb, 936 OUT PDIRENT EaDirent, 937 IN USHORT EaHandle, 938 IN POEM_STRING Filename 939 ); 940 941 _Requires_lock_held_(_Global_critical_region_) 942 VOID 943 FatAddEaSet ( 944 IN PIRP_CONTEXT IrpContext, 945 IN PVCB Vcb, 946 IN ULONG EaSetLength, 947 IN PBCB EaBcb, 948 OUT PDIRENT EaDirent, 949 OUT PUSHORT EaHandle, 950 OUT PEA_RANGE EaSetRange 951 ); 952 953 VOID 954 FatDeletePackedEa ( 955 IN PIRP_CONTEXT IrpContext, 956 IN OUT PEA_SET_HEADER EaSetHeader, 957 IN OUT PULONG PackedEasLength, 958 IN ULONG Offset 959 ); 960 961 VOID 962 FatAppendPackedEa ( 963 IN PIRP_CONTEXT IrpContext, 964 IN OUT PEA_SET_HEADER *EaSetHeader, 965 IN OUT PULONG PackedEasLength, 966 IN OUT PULONG AllocationLength, 967 IN PFILE_FULL_EA_INFORMATION FullEa, 968 IN ULONG BytesPerCluster 969 ); 970 971 ULONG 972 FatLocateNextEa ( 973 IN PIRP_CONTEXT IrpContext, 974 IN PPACKED_EA FirstPackedEa, 975 IN ULONG PackedEasLength, 976 IN ULONG PreviousOffset 977 ); 978 979 BOOLEAN 980 FatLocateEaByName ( 981 IN PIRP_CONTEXT IrpContext, 982 IN PPACKED_EA FirstPackedEa, 983 IN ULONG PackedEasLength, 984 IN POEM_STRING EaName, 985 OUT PULONG Offset 986 ); 987 988 BOOLEAN 989 FatIsEaNameValid ( 990 IN PIRP_CONTEXT IrpContext, 991 IN OEM_STRING Name 992 ); 993 994 VOID 995 FatPinEaRange ( 996 IN PIRP_CONTEXT IrpContext, 997 IN PFILE_OBJECT VirtualEaFile, 998 IN PFCB EaFcb, 999 IN OUT PEA_RANGE EaRange, 1000 IN ULONG StartingVbo, 1001 IN ULONG Length, 1002 IN NTSTATUS ErrorStatus 1003 ); 1004 1005 VOID 1006 FatMarkEaRangeDirty ( 1007 IN PIRP_CONTEXT IrpContext, 1008 IN PFILE_OBJECT EaFileObject, 1009 IN OUT PEA_RANGE EaRange 1010 ); 1011 1012 VOID 1013 FatUnpinEaRange ( 1014 IN PIRP_CONTEXT IrpContext, 1015 IN OUT PEA_RANGE EaRange 1016 ); 1017 1018 // 1019 // The following macro computes the size of a full ea (not including 1020 // padding to bring it to a longword. A full ea has a 4 byte offset, 1021 // folowed by 1 byte flag, 1 byte name length, 2 bytes value length, 1022 // the name, 1 null byte, and the value. 1023 // 1024 // ULONG 1025 // SizeOfFullEa ( 1026 // IN PFILE_FULL_EA_INFORMATION FullEa 1027 // ); 1028 // 1029 1030 #define SizeOfFullEa(EA) (4+1+1+2+(EA)->EaNameLength+1+(EA)->EaValueLength) 1031 1032 1033 // 1034 // The following routines are used to manipulate the fscontext fields 1035 // of the file object, implemented in FilObSup.c 1036 // 1037 1038 #ifndef __REACTOS__ 1039 typedef enum _TYPE_OF_OPEN { 1040 1041 UnopenedFileObject = 1, 1042 UserFileOpen, 1043 UserDirectoryOpen, 1044 UserVolumeOpen, 1045 VirtualVolumeFile, 1046 DirectoryFile, 1047 EaFile, 1048 } TYPE_OF_OPEN; 1049 #endif 1050 1051 typedef enum _FAT_FLUSH_TYPE { 1052 1053 NoFlush = 0, 1054 Flush, 1055 FlushAndInvalidate, 1056 FlushWithoutPurge 1057 1058 } FAT_FLUSH_TYPE; 1059 1060 VOID 1061 FatSetFileObject ( 1062 IN PFILE_OBJECT FileObject OPTIONAL, 1063 IN TYPE_OF_OPEN TypeOfOpen, 1064 IN PVOID VcbOrFcbOrDcb, 1065 IN PCCB Ccb OPTIONAL 1066 ); 1067 1068 TYPE_OF_OPEN 1069 FatDecodeFileObject ( 1070 _In_ PFILE_OBJECT FileObject, 1071 _Outptr_ PVCB *Vcb, 1072 _Outptr_ PFCB *FcbOrDcb, 1073 _Outptr_ PCCB *Ccb 1074 ); 1075 1076 _Requires_lock_held_(_Global_critical_region_) 1077 VOID 1078 FatPurgeReferencedFileObjects ( 1079 IN PIRP_CONTEXT IrpContext, 1080 IN PFCB FcbOrDcb, 1081 IN FAT_FLUSH_TYPE FlushType 1082 ); 1083 1084 _Requires_lock_held_(_Global_critical_region_) 1085 VOID 1086 FatForceCacheMiss ( 1087 IN PIRP_CONTEXT IrpContext, 1088 IN PFCB Fcb, 1089 IN FAT_FLUSH_TYPE FlushType 1090 ); 1091 1092 1093 // 1094 // File system control routines, implemented in FsCtrl.c 1095 // 1096 1097 _Requires_lock_held_(_Global_critical_region_) 1098 VOID 1099 FatFlushAndCleanVolume( 1100 IN PIRP_CONTEXT IrpContext, 1101 IN PIRP Irp, 1102 IN PVCB Vcb, 1103 IN FAT_FLUSH_TYPE FlushType 1104 ); 1105 1106 BOOLEAN 1107 FatIsBootSectorFat ( 1108 IN PPACKED_BOOT_SECTOR BootSector 1109 ); 1110 1111 _Requires_lock_held_(_Global_critical_region_) 1112 NTSTATUS 1113 FatLockVolumeInternal ( 1114 IN PIRP_CONTEXT IrpContext, 1115 IN PVCB Vcb, 1116 IN PFILE_OBJECT FileObject OPTIONAL 1117 ); 1118 1119 NTSTATUS 1120 FatUnlockVolumeInternal ( 1121 IN PIRP_CONTEXT IrpContext, 1122 IN PVCB Vcb, 1123 IN PFILE_OBJECT FileObject OPTIONAL 1124 ); 1125 1126 1127 // 1128 // Name support routines, implemented in NameSup.c 1129 // 1130 1131 // 1132 // BOOLEAN 1133 // FatAreNamesEqual ( 1134 // IN PIRP_CONTEXT IrpContext, 1135 // IN OEM_STRING ConstantNameA, 1136 // IN OEM_STRING ConstantNameB 1137 // ) 1138 // 1139 // /*++ 1140 // 1141 // Routine Description: 1142 // 1143 // This routine simple returns whether the two names are exactly equal. 1144 // If the two names are known to be constant, this routine is much 1145 // faster than FatIsDbcsInExpression. 1146 // 1147 // Arguments: 1148 // 1149 // ConstantNameA - Constant name. 1150 // 1151 // ConstantNameB - Constant name. 1152 // 1153 // Return Value: 1154 // 1155 // BOOLEAN - TRUE if the two names are lexically equal. 1156 // 1157 1158 #define FatAreNamesEqual(IRPCONTEXT,NAMEA,NAMEB) ( \ 1159 ((ULONG)(NAMEA).Length == (ULONG)(NAMEB).Length) && \ 1160 (RtlEqualMemory( &(NAMEA).Buffer[0], \ 1161 &(NAMEB).Buffer[0], \ 1162 (NAMEA).Length )) \ 1163 ) 1164 1165 // 1166 // BOOLEAN 1167 // FatIsNameShortOemValid ( 1168 // IN PIRP_CONTEXT IrpContext, 1169 // IN OEM_STRING Name, 1170 // IN BOOLEAN CanContainWildCards, 1171 // IN BOOLEAN PathNamePermissible, 1172 // IN BOOLEAN LeadingBackslashPermissible 1173 // ) 1174 // 1175 // /*++ 1176 // 1177 // Routine Description: 1178 // 1179 // This routine scans the input name and verifies that if only 1180 // contains valid characters 1181 // 1182 // Arguments: 1183 // 1184 // Name - Supplies the input name to check. 1185 // 1186 // CanContainWildCards - Indicates if the name can contain wild cards 1187 // (i.e., * and ?). 1188 // 1189 // Return Value: 1190 // 1191 // BOOLEAN - Returns TRUE if the name is valid and FALSE otherwise. 1192 // 1193 // --*/ 1194 // 1195 // The FatIsNameLongOemValid and FatIsNameLongUnicodeValid are similar. 1196 // 1197 1198 #define FatIsNameShortOemValid(IRPCONTEXT,NAME,CAN_CONTAIN_WILD_CARDS,PATH_NAME_OK,LEADING_BACKSLASH_OK) ( \ 1199 FsRtlIsFatDbcsLegal((NAME), \ 1200 (CAN_CONTAIN_WILD_CARDS), \ 1201 (PATH_NAME_OK), \ 1202 (LEADING_BACKSLASH_OK)) \ 1203 ) 1204 1205 #define FatIsNameLongOemValid(IRPCONTEXT,NAME,CAN_CONTAIN_WILD_CARDS,PATH_NAME_OK,LEADING_BACKSLASH_OK) ( \ 1206 FsRtlIsHpfsDbcsLegal((NAME), \ 1207 (CAN_CONTAIN_WILD_CARDS), \ 1208 (PATH_NAME_OK), \ 1209 (LEADING_BACKSLASH_OK)) \ 1210 ) 1211 1212 static 1213 INLINE 1214 BOOLEAN 1215 FatIsNameLongUnicodeValid ( 1216 PIRP_CONTEXT IrpContext, 1217 PUNICODE_STRING Name, 1218 BOOLEAN CanContainWildcards, 1219 BOOLEAN PathNameOk, 1220 BOOLEAN LeadingBackslashOk 1221 ) 1222 { 1223 ULONG i; 1224 1225 UNREFERENCED_PARAMETER( IrpContext ); 1226 UNREFERENCED_PARAMETER( LeadingBackslashOk ); 1227 UNREFERENCED_PARAMETER( PathNameOk ); 1228 1229 // 1230 // I'm not bothering to do the whole thing, just enough to make this call look 1231 // the same as the others. 1232 // 1233 1234 NT_ASSERT( !PathNameOk && !LeadingBackslashOk ); 1235 1236 for (i=0; i < Name->Length/sizeof(WCHAR); i++) { 1237 1238 if ((Name->Buffer[i] < 0x80) && 1239 !(FsRtlIsAnsiCharacterLegalHpfs(Name->Buffer[i], CanContainWildcards))) { 1240 1241 return FALSE; 1242 } 1243 } 1244 1245 return TRUE; 1246 } 1247 1248 BOOLEAN 1249 FatIsNameInExpression ( 1250 IN PIRP_CONTEXT IrpContext, 1251 IN OEM_STRING Expression, 1252 IN OEM_STRING Name 1253 ); 1254 1255 VOID 1256 FatStringTo8dot3 ( 1257 _In_ PIRP_CONTEXT IrpContext, 1258 _In_ OEM_STRING InputString, 1259 _Out_writes_bytes_(11) PFAT8DOT3 Output8dot3 1260 ); 1261 1262 VOID 1263 Fat8dot3ToString ( 1264 _In_ PIRP_CONTEXT IrpContext, 1265 _In_ PDIRENT Dirent, 1266 _In_ BOOLEAN RestoreCase, 1267 _Out_ POEM_STRING OutputString 1268 ); 1269 1270 _Requires_lock_held_(_Global_critical_region_) 1271 VOID 1272 FatGetUnicodeNameFromFcb ( 1273 IN PIRP_CONTEXT IrpContext, 1274 IN PFCB Fcb, 1275 IN OUT PUNICODE_STRING Lfn 1276 ); 1277 1278 _Requires_lock_held_(_Global_critical_region_) 1279 VOID 1280 FatSetFullFileNameInFcb ( 1281 IN PIRP_CONTEXT IrpContext, 1282 IN PFCB Fcb 1283 ); 1284 1285 VOID 1286 FatSetFullNameInFcb ( 1287 _In_ PIRP_CONTEXT IrpContext, 1288 _Inout_ PFCB Fcb, 1289 _In_ PUNICODE_STRING FinalName 1290 ); 1291 1292 VOID 1293 FatUnicodeToUpcaseOem ( 1294 IN PIRP_CONTEXT IrpContext, 1295 IN POEM_STRING OemString, 1296 IN PUNICODE_STRING UnicodeString 1297 ); 1298 1299 _Requires_lock_held_(_Global_critical_region_) 1300 VOID 1301 FatSelectNames ( 1302 IN PIRP_CONTEXT IrpContext, 1303 IN PDCB Parent, 1304 IN POEM_STRING OemName, 1305 IN PUNICODE_STRING UnicodeName, 1306 IN OUT POEM_STRING ShortName, 1307 IN PUNICODE_STRING SuggestedShortName OPTIONAL, 1308 IN OUT BOOLEAN *AllLowerComponent, 1309 IN OUT BOOLEAN *AllLowerExtension, 1310 IN OUT BOOLEAN *CreateLfn 1311 ); 1312 1313 VOID 1314 FatEvaluateNameCase ( 1315 IN PIRP_CONTEXT IrpContext, 1316 IN PUNICODE_STRING Name, 1317 IN OUT BOOLEAN *AllLowerComponent, 1318 IN OUT BOOLEAN *AllLowerExtension, 1319 IN OUT BOOLEAN *CreateLfn 1320 ); 1321 1322 BOOLEAN 1323 FatSpaceInName ( 1324 IN PIRP_CONTEXT IrpContext, 1325 IN PUNICODE_STRING UnicodeName 1326 ); 1327 1328 VOID 1329 FatUnicodeRestoreShortNameCase( 1330 IN PUNICODE_STRING ShortNameWithCase, 1331 IN BOOLEAN LowerCase8, 1332 IN BOOLEAN LowerCase3 1333 ); 1334 1335 1336 // 1337 // Resources support routines/macros, implemented in ResrcSup.c 1338 // 1339 // The following routines/macros are used for gaining shared and exclusive 1340 // access to the global/vcb data structures. The routines are implemented 1341 // in ResrcSup.c. There is a global resources that everyone tries to take 1342 // out shared to do their work, with the exception of mount/dismount which 1343 // take out the global resource exclusive. All other resources only work 1344 // on their individual item. For example, an Fcb resource does not take out 1345 // a Vcb resource. But the way the file system is structured we know 1346 // that when we are processing an Fcb other threads cannot be trying to remove 1347 // or alter the Fcb, so we do not need to acquire the Vcb. 1348 // 1349 // The procedures/macros are: 1350 // 1351 // Macro FatData Vcb Fcb Subsequent macros 1352 // 1353 // AcquireExclusiveGlobal Read/Write None None ReleaseGlobal 1354 // 1355 // AcquireSharedGlobal Read None None ReleaseGlobal 1356 // 1357 // AcquireExclusiveVcb Read Read/Write None ReleaseVcb 1358 // 1359 // AcquireSharedVcb Read Read None ReleaseVcb 1360 // 1361 // AcquireExclusiveFcb Read None Read/Write ConvertToSharFcb 1362 // ReleaseFcb 1363 // 1364 // AcquireSharedFcb Read None Read ReleaseFcb 1365 // 1366 // ConvertToSharedFcb Read None Read ReleaseFcb 1367 // 1368 // ReleaseGlobal 1369 // 1370 // ReleaseVcb 1371 // 1372 // ReleaseFcb 1373 // 1374 1375 // 1376 // FINISHED 1377 // FatAcquireExclusiveGlobal ( 1378 // IN PIRP_CONTEXT IrpContext 1379 // ); 1380 // 1381 // FINISHED 1382 // FatAcquireSharedGlobal ( 1383 // IN PIRP_CONTEXT IrpContext 1384 // ); 1385 // 1386 1387 #define FatAcquireExclusiveGlobal(IRPCONTEXT) ( \ 1388 ExAcquireResourceExclusiveLite( &FatData.Resource, BooleanFlagOn((IRPCONTEXT)->Flags, IRP_CONTEXT_FLAG_WAIT) ) \ 1389 ) 1390 1391 #define FatAcquireSharedGlobal(IRPCONTEXT) ( \ 1392 ExAcquireResourceSharedLite( &FatData.Resource, BooleanFlagOn((IRPCONTEXT)->Flags, IRP_CONTEXT_FLAG_WAIT) ) \ 1393 ) 1394 1395 // 1396 // The following macro must only be called when Wait is TRUE! 1397 // 1398 // FatAcquireExclusiveVolume ( 1399 // IN PIRP_CONTEXT IrpContext, 1400 // IN PVCB Vcb 1401 // ); 1402 // 1403 // FatReleaseVolume ( 1404 // IN PIRP_CONTEXT IrpContext, 1405 // IN PVCB Vcb 1406 // ); 1407 // 1408 1409 #define FatAcquireExclusiveVolume(IRPCONTEXT,VCB) { \ 1410 PFCB __FFFFFcb = NULL; \ 1411 NT_ASSERT(FlagOn((IRPCONTEXT)->Flags, IRP_CONTEXT_FLAG_WAIT)); \ 1412 (VOID)FatAcquireExclusiveVcb( (IRPCONTEXT), (VCB) ); \ 1413 while ( (__FFFFFcb = FatGetNextFcbBottomUp((IRPCONTEXT), __FFFFFcb, (VCB)->RootDcb)) != NULL) { \ 1414 (VOID)FatAcquireExclusiveFcb((IRPCONTEXT), __FFFFFcb ); \ 1415 } \ 1416 } 1417 1418 #define FatReleaseVolume(IRPCONTEXT,VCB) { \ 1419 PFCB __FFFFFcb = NULL; \ 1420 NT_ASSERT(FlagOn((IRPCONTEXT)->Flags, IRP_CONTEXT_FLAG_WAIT)); \ 1421 while ( (__FFFFFcb = FatGetNextFcbBottomUp((IRPCONTEXT), __FFFFFcb, (VCB)->RootDcb)) != NULL) { \ 1422 (VOID)ExReleaseResourceLite( __FFFFFcb->Header.Resource ); \ 1423 } \ 1424 FatReleaseVcb((IRPCONTEXT), (VCB)); \ 1425 } 1426 1427 // 1428 // Macro to enable easy tracking of Vcb state transitions. 1429 // 1430 1431 #ifdef FASTFATDBG 1432 #define FatSetVcbCondition( V, X) { \ 1433 DebugTrace(0,DEBUG_TRACE_VERFYSUP,"%d -> ",(V)->VcbCondition); \ 1434 DebugTrace(0,DEBUG_TRACE_VERFYSUP,"%x\n",(X)); \ 1435 (V)->VcbCondition = (X); \ 1436 } 1437 #else 1438 #define FatSetVcbCondition( V, X) (V)->VcbCondition = (X) 1439 #endif 1440 1441 // 1442 // These macros can be used to determine what kind of FAT we have for an 1443 // initialized Vcb. It is somewhat more elegant to use these (visually). 1444 // 1445 1446 #define FatIsFat32(VCB) ((BOOLEAN)((VCB)->AllocationSupport.FatIndexBitSize == 32)) 1447 #define FatIsFat16(VCB) ((BOOLEAN)((VCB)->AllocationSupport.FatIndexBitSize == 16)) 1448 #define FatIsFat12(VCB) ((BOOLEAN)((VCB)->AllocationSupport.FatIndexBitSize == 12)) 1449 1450 1451 _Requires_lock_held_(_Global_critical_region_) 1452 _When_(return != FALSE && NoOpCheck != FALSE, _Acquires_exclusive_lock_(Vcb->Resource)) 1453 FINISHED 1454 FatAcquireExclusiveVcb_Real ( 1455 IN PIRP_CONTEXT IrpContext, 1456 IN PVCB Vcb, 1457 IN BOOLEAN NoOpCheck 1458 ); 1459 1460 #define FatAcquireExclusiveVcb( IC, V) FatAcquireExclusiveVcb_Real( IC, V, FALSE) 1461 #define FatAcquireExclusiveVcbNoOpCheck( IC, V) FatAcquireExclusiveVcb_Real( IC, V, TRUE) 1462 1463 _Requires_lock_held_(_Global_critical_region_) 1464 _When_(return != 0, _Acquires_shared_lock_(Vcb->Resource)) 1465 FINISHED 1466 FatAcquireSharedVcb ( 1467 IN PIRP_CONTEXT IrpContext, 1468 IN PVCB Vcb 1469 ); 1470 1471 _Requires_lock_held_(_Global_critical_region_) 1472 _Acquires_exclusive_lock_(*Fcb->Header.Resource) 1473 FINISHED 1474 FatAcquireExclusiveFcb ( 1475 IN PIRP_CONTEXT IrpContext, 1476 IN PFCB Fcb 1477 ); 1478 1479 _Requires_lock_held_(_Global_critical_region_) 1480 _Acquires_shared_lock_(*Fcb->Header.Resource) 1481 FINISHED 1482 FatAcquireSharedFcb ( 1483 IN PIRP_CONTEXT IrpContext, 1484 IN PFCB Fcb 1485 ); 1486 1487 _Requires_lock_held_(_Global_critical_region_) 1488 _When_(return != 0, _Acquires_shared_lock_(*Fcb->Header.Resource)) 1489 FINISHED 1490 FatAcquireSharedFcbWaitForEx ( 1491 IN PIRP_CONTEXT IrpContext, 1492 IN PFCB Fcb 1493 ); 1494 1495 #define FatVcbAcquiredExclusive(IRPCONTEXT,VCB) ( \ 1496 ExIsResourceAcquiredExclusiveLite(&(VCB)->Resource) || \ 1497 ExIsResourceAcquiredExclusiveLite(&FatData.Resource) \ 1498 ) 1499 1500 #define FatFcbAcquiredShared(IRPCONTEXT,FCB) ( \ 1501 ExIsResourceAcquiredSharedLite((FCB)->Header.Resource) \ 1502 ) 1503 1504 #define FatFcbAcquiredExclusive(IRPCONTEXT,FCB) ( \ 1505 ExIsResourceAcquiredExclusiveLite((FCB)->Header.Resource) \ 1506 ) 1507 1508 #define FatAcquireDirectoryFileMutex(VCB) { \ 1509 NT_ASSERT(KeAreApcsDisabled()); \ 1510 ExAcquireFastMutexUnsafe(&(VCB)->DirectoryFileCreationMutex); \ 1511 } 1512 1513 #define FatReleaseDirectoryFileMutex(VCB) { \ 1514 NT_ASSERT(KeAreApcsDisabled()); \ 1515 ExReleaseFastMutexUnsafe(&(VCB)->DirectoryFileCreationMutex); \ 1516 } 1517 1518 // 1519 // The following are cache manager call backs 1520 1521 BOOLEAN 1522 FatAcquireVolumeForClose ( 1523 IN PVOID Vcb, 1524 IN BOOLEAN Wait 1525 ); 1526 1527 VOID 1528 FatReleaseVolumeFromClose ( 1529 IN PVOID Vcb 1530 ); 1531 1532 _Requires_lock_held_(_Global_critical_region_) 1533 BOOLEAN 1534 NTAPI 1535 FatAcquireFcbForLazyWrite ( 1536 IN PVOID Null, 1537 IN BOOLEAN Wait 1538 ); 1539 1540 _Requires_lock_held_(_Global_critical_region_) 1541 VOID 1542 NTAPI 1543 FatReleaseFcbFromLazyWrite ( 1544 IN PVOID Null 1545 ); 1546 1547 _Requires_lock_held_(_Global_critical_region_) 1548 BOOLEAN 1549 NTAPI 1550 FatAcquireFcbForReadAhead ( 1551 IN PVOID Null, 1552 IN BOOLEAN Wait 1553 ); 1554 1555 _Requires_lock_held_(_Global_critical_region_) 1556 VOID 1557 NTAPI 1558 FatReleaseFcbFromReadAhead ( 1559 IN PVOID Null 1560 ); 1561 1562 _Function_class_(FAST_IO_ACQUIRE_FOR_CCFLUSH) 1563 _Requires_lock_held_(_Global_critical_region_) 1564 NTSTATUS 1565 NTAPI 1566 FatAcquireForCcFlush ( 1567 IN PFILE_OBJECT FileObject, 1568 IN PDEVICE_OBJECT DeviceObject 1569 ); 1570 1571 _Function_class_(FAST_IO_RELEASE_FOR_CCFLUSH) 1572 _Requires_lock_held_(_Global_critical_region_) 1573 NTSTATUS 1574 NTAPI 1575 FatReleaseForCcFlush ( 1576 IN PFILE_OBJECT FileObject, 1577 IN PDEVICE_OBJECT DeviceObject 1578 ); 1579 1580 BOOLEAN 1581 NTAPI 1582 FatNoOpAcquire ( 1583 IN PVOID Fcb, 1584 IN BOOLEAN Wait 1585 ); 1586 1587 VOID 1588 NTAPI 1589 FatNoOpRelease ( 1590 IN PVOID Fcb 1591 ); 1592 1593 _Requires_lock_held_(_Global_critical_region_) 1594 NTSTATUS 1595 NTAPI 1596 FatFilterCallbackAcquireForCreateSection ( 1597 IN PFS_FILTER_CALLBACK_DATA CallbackData, 1598 OUT PVOID *CompletionContext 1599 ); 1600 1601 // 1602 // VOID 1603 // FatConvertToSharedFcb ( 1604 // IN PIRP_CONTEXT IrpContext, 1605 // IN PFCB Fcb 1606 // ); 1607 // 1608 1609 #define FatConvertToSharedFcb(IRPCONTEXT,Fcb) { \ 1610 ExConvertExclusiveToSharedLite( (Fcb)->Header.Resource ); \ 1611 } 1612 1613 // 1614 // VOID 1615 // FatReleaseGlobal ( 1616 // IN PIRP_CONTEXT IrpContext 1617 // ); 1618 // 1619 // VOID 1620 // FatReleaseVcb ( 1621 // IN PIRP_CONTEXT IrpContext, 1622 // IN PVCB Vcb 1623 // ); 1624 // 1625 // VOID 1626 // FatReleaseFcb ( 1627 // IN PIRP_CONTEXT IrpContext, 1628 // IN PVCB Vcb 1629 // ); 1630 // 1631 1632 #define FatDeleteResource(RESRC) { \ 1633 ExDeleteResourceLite( (RESRC) ); \ 1634 } 1635 1636 #define FatReleaseGlobal(IRPCONTEXT) { \ 1637 ExReleaseResourceLite( &(FatData.Resource) ); \ 1638 } 1639 1640 #define FatReleaseVcb(IRPCONTEXT,Vcb) { \ 1641 ExReleaseResourceLite( &((Vcb)->Resource) ); \ 1642 } 1643 1644 #define FatReleaseFcb(IRPCONTEXT,Fcb) { \ 1645 ExReleaseResourceLite( (Fcb)->Header.Resource ); \ 1646 } 1647 1648 // 1649 // The following macro is used to retrieve the oplock structure within 1650 // the Fcb. This structure was moved to the advanced Fcb header 1651 // in Win8. 1652 // 1653 1654 #if (NTDDI_VERSION >= NTDDI_WIN8) 1655 1656 #define FatGetFcbOplock(F) &(F)->Header.Oplock 1657 1658 #else 1659 1660 #define FatGetFcbOplock(F) &(F)->Specific.Fcb.Oplock 1661 1662 #endif 1663 1664 1665 // 1666 // In-memory structure support routine, implemented in StrucSup.c 1667 // 1668 1669 _Requires_lock_held_(_Global_critical_region_) 1670 VOID 1671 FatInitializeVcb ( 1672 IN PIRP_CONTEXT IrpContext, 1673 IN OUT PVCB Vcb, 1674 IN PDEVICE_OBJECT TargetDeviceObject, 1675 IN PVPB Vpb, 1676 IN PDEVICE_OBJECT FsDeviceObject 1677 ); 1678 1679 VOID 1680 FatTearDownVcb ( 1681 IN PIRP_CONTEXT IrpContext, 1682 IN PVCB Vcb 1683 ); 1684 1685 VOID 1686 FatDeleteVcb ( 1687 IN PIRP_CONTEXT IrpContext, 1688 IN PVCB Vcb 1689 ); 1690 1691 _Requires_lock_held_(_Global_critical_region_) 1692 VOID 1693 FatCreateRootDcb ( 1694 IN PIRP_CONTEXT IrpContext, 1695 IN PVCB Vcb 1696 ); 1697 1698 PFCB 1699 FatCreateFcb ( 1700 IN PIRP_CONTEXT IrpContext, 1701 IN PVCB Vcb, 1702 IN PDCB ParentDcb, 1703 IN ULONG LfnOffsetWithinDirectory, 1704 IN ULONG DirentOffsetWithinDirectory, 1705 IN PDIRENT Dirent, 1706 IN PUNICODE_STRING Lfn OPTIONAL, 1707 IN PUNICODE_STRING OrigLfn OPTIONAL, 1708 IN BOOLEAN IsPagingFile, 1709 IN BOOLEAN SingleResource 1710 ); 1711 1712 PDCB 1713 FatCreateDcb ( 1714 IN PIRP_CONTEXT IrpContext, 1715 IN PVCB Vcb, 1716 IN PDCB ParentDcb, 1717 IN ULONG LfnOffsetWithinDirectory, 1718 IN ULONG DirentOffsetWithinDirectory, 1719 IN PDIRENT Dirent, 1720 IN PUNICODE_STRING Lfn OPTIONAL 1721 ); 1722 1723 VOID 1724 FatDeleteFcb ( 1725 IN PIRP_CONTEXT IrpContext, 1726 IN PFCB *Fcb 1727 ); 1728 1729 PCCB 1730 FatCreateCcb ( 1731 IN PIRP_CONTEXT IrpContext 1732 ); 1733 1734 VOID 1735 FatDeallocateCcbStrings( 1736 IN PCCB Ccb 1737 ); 1738 1739 VOID 1740 FatDeleteCcb ( 1741 IN PIRP_CONTEXT IrpContext, 1742 IN PCCB *Ccb 1743 ); 1744 1745 PIRP_CONTEXT 1746 FatCreateIrpContext ( 1747 IN PIRP Irp, 1748 IN BOOLEAN Wait 1749 ); 1750 1751 VOID 1752 FatDeleteIrpContext_Real ( 1753 IN PIRP_CONTEXT IrpContext 1754 ); 1755 1756 #ifdef FASTFATDBG 1757 #define FatDeleteIrpContext(IRPCONTEXT) { \ 1758 FatDeleteIrpContext_Real((IRPCONTEXT)); \ 1759 (IRPCONTEXT) = NULL; \ 1760 } 1761 #else 1762 #define FatDeleteIrpContext(IRPCONTEXT) { \ 1763 FatDeleteIrpContext_Real((IRPCONTEXT)); \ 1764 } 1765 #endif // FASTFAT_DBG 1766 1767 PFCB 1768 FatGetNextFcbTopDown ( 1769 IN PIRP_CONTEXT IrpContext, 1770 IN PFCB Fcb, 1771 IN PFCB TerminationFcb 1772 ); 1773 1774 PFCB 1775 FatGetNextFcbBottomUp ( 1776 IN PIRP_CONTEXT IrpContext, 1777 IN PFCB Fcb, 1778 IN PFCB TerminationFcb 1779 ); 1780 1781 // 1782 // These two macros just make the code a bit cleaner. 1783 // 1784 1785 #define FatGetFirstChild(DIR) ((PFCB)( \ 1786 IsListEmpty(&(DIR)->Specific.Dcb.ParentDcbQueue) ? NULL : \ 1787 CONTAINING_RECORD((DIR)->Specific.Dcb.ParentDcbQueue.Flink, \ 1788 DCB, \ 1789 ParentDcbLinks.Flink))) 1790 1791 #define FatGetNextSibling(FILE) ((PFCB)( \ 1792 &(FILE)->ParentDcb->Specific.Dcb.ParentDcbQueue.Flink == \ 1793 (PVOID)(FILE)->ParentDcbLinks.Flink ? NULL : \ 1794 CONTAINING_RECORD((FILE)->ParentDcbLinks.Flink, \ 1795 FCB, \ 1796 ParentDcbLinks.Flink))) 1797 1798 _Requires_lock_held_(_Global_critical_region_) 1799 BOOLEAN 1800 FatCheckForDismount ( 1801 IN PIRP_CONTEXT IrpContext, 1802 PVCB Vcb, 1803 IN BOOLEAN Force 1804 ); 1805 1806 VOID 1807 FatConstructNamesInFcb ( 1808 IN PIRP_CONTEXT IrpContext, 1809 PFCB Fcb, 1810 PDIRENT Dirent, 1811 PUNICODE_STRING Lfn OPTIONAL 1812 ); 1813 1814 _Requires_lock_held_(_Global_critical_region_) 1815 VOID 1816 FatCheckFreeDirentBitmap ( 1817 IN PIRP_CONTEXT IrpContext, 1818 IN PDCB Dcb 1819 ); 1820 1821 ULONG 1822 FatVolumeUncleanCount ( 1823 IN PIRP_CONTEXT IrpContext, 1824 IN PVCB Vcb 1825 ); 1826 1827 VOID 1828 FatPreallocateCloseContext ( 1829 IN PVCB Vcb 1830 ); 1831 1832 PCLOSE_CONTEXT 1833 FatAllocateCloseContext( 1834 IN PVCB Vcb 1835 ); 1836 1837 // 1838 // BOOLEAN 1839 // FatIsRawDevice ( 1840 // IN PIRP_CONTEXT IrpContext, 1841 // IN NTSTATUS Status 1842 // ); 1843 // 1844 1845 #define FatIsRawDevice(IC,S) ( \ 1846 ((S) == STATUS_DEVICE_NOT_READY) || \ 1847 ((S) == STATUS_NO_MEDIA_IN_DEVICE) \ 1848 ) 1849 1850 1851 // 1852 // Routines to support managing file names Fcbs and Dcbs. 1853 // Implemented in SplaySup.c 1854 // 1855 1856 VOID 1857 FatInsertName ( 1858 IN PIRP_CONTEXT IrpContext, 1859 IN PRTL_SPLAY_LINKS *RootNode, 1860 IN PFILE_NAME_NODE Name 1861 ); 1862 1863 VOID 1864 FatRemoveNames ( 1865 IN PIRP_CONTEXT IrpContext, 1866 IN PFCB Fcb 1867 ); 1868 1869 PFCB 1870 FatFindFcb ( 1871 IN PIRP_CONTEXT IrpContext, 1872 IN OUT PRTL_SPLAY_LINKS *RootNode, 1873 IN PSTRING Name, 1874 OUT PBOOLEAN FileNameDos OPTIONAL 1875 ); 1876 1877 BOOLEAN 1878 FatIsHandleCountZero ( 1879 IN PIRP_CONTEXT IrpContext, 1880 IN PVCB Vcb 1881 ); 1882 1883 typedef enum _COMPARISON { 1884 IsLessThan, 1885 IsGreaterThan, 1886 IsEqual 1887 } COMPARISON; 1888 1889 COMPARISON 1890 FatCompareNames ( 1891 IN PSTRING NameA, 1892 IN PSTRING NameB 1893 ); 1894 1895 // 1896 // Do a macro here to check for a common case. 1897 // 1898 1899 #define CompareNames(NAMEA,NAMEB) ( \ 1900 *(PUCHAR)(NAMEA)->Buffer != *(PUCHAR)(NAMEB)->Buffer ? \ 1901 *(PUCHAR)(NAMEA)->Buffer < *(PUCHAR)(NAMEB)->Buffer ? \ 1902 IsLessThan : IsGreaterThan : \ 1903 FatCompareNames((PSTRING)(NAMEA), (PSTRING)(NAMEB)) \ 1904 ) 1905 1906 // 1907 // Time conversion support routines, implemented in TimeSup.c 1908 // 1909 1910 _Success_(return != FALSE) 1911 BOOLEAN 1912 FatNtTimeToFatTime ( 1913 _In_ PIRP_CONTEXT IrpContext, 1914 _In_ PLARGE_INTEGER NtTime, 1915 _In_ BOOLEAN Rounding, 1916 _Out_ PFAT_TIME_STAMP FatTime, 1917 _Out_opt_ PUCHAR TenMsecs 1918 ); 1919 1920 LARGE_INTEGER 1921 FatFatTimeToNtTime ( 1922 _In_ PIRP_CONTEXT IrpContext, 1923 _In_ FAT_TIME_STAMP FatTime, 1924 _In_ UCHAR TenMilliSeconds 1925 ); 1926 1927 LARGE_INTEGER 1928 FatFatDateToNtTime ( 1929 _In_ PIRP_CONTEXT IrpContext, 1930 _In_ FAT_DATE FatDate 1931 ); 1932 1933 FAT_TIME_STAMP 1934 FatGetCurrentFatTime ( 1935 _In_ PIRP_CONTEXT IrpContext 1936 ); 1937 1938 1939 // 1940 // Low level verification routines, implemented in VerfySup.c 1941 // 1942 // The first routine is called to help process a verify IRP. Its job is 1943 // to walk every Fcb/Dcb and mark them as need to be verified. 1944 // 1945 // The other routines are used by every dispatch routine to verify that 1946 // an Vcb/Fcb/Dcb is still good. The routine walks as much of the opened 1947 // file/directory tree as necessary to make sure that the path is still valid. 1948 // The function result indicates if the procedure needed to block for I/O. 1949 // If the structure is bad the procedure raise the error condition 1950 // STATUS_FILE_INVALID, otherwise they simply return to their caller 1951 // 1952 1953 typedef enum _FAT_VOLUME_STATE { 1954 VolumeClean, 1955 VolumeDirty, 1956 VolumeDirtyWithSurfaceTest 1957 } FAT_VOLUME_STATE, *PFAT_VOLUME_STATE; 1958 1959 VOID 1960 FatMarkFcbCondition ( 1961 IN PIRP_CONTEXT IrpContext, 1962 IN PFCB Fcb, 1963 IN FCB_CONDITION FcbCondition, 1964 IN BOOLEAN Recursive 1965 ); 1966 1967 VOID 1968 FatVerifyVcb ( 1969 IN PIRP_CONTEXT IrpContext, 1970 IN PVCB Vcb 1971 ); 1972 1973 _Requires_lock_held_(_Global_critical_region_) 1974 VOID 1975 FatVerifyFcb ( 1976 IN PIRP_CONTEXT IrpContext, 1977 IN PFCB Fcb 1978 ); 1979 1980 1981 KDEFERRED_ROUTINE FatCleanVolumeDpc; 1982 1983 VOID 1984 NTAPI 1985 FatCleanVolumeDpc ( 1986 _In_ PKDPC Dpc, 1987 _In_opt_ PVOID DeferredContext, 1988 _In_opt_ PVOID SystemArgument1, 1989 _In_opt_ PVOID SystemArgument2 1990 ); 1991 1992 _Requires_lock_held_(_Global_critical_region_) 1993 VOID 1994 FatMarkVolume ( 1995 IN PIRP_CONTEXT IrpContext, 1996 IN PVCB Vcb, 1997 IN FAT_VOLUME_STATE VolumeState 1998 ); 1999 2000 WORKER_THREAD_ROUTINE FatFspMarkVolumeDirtyWithRecover; 2001 2002 VOID 2003 NTAPI 2004 FatFspMarkVolumeDirtyWithRecover ( 2005 PVOID Parameter 2006 ); 2007 2008 VOID 2009 FatCheckDirtyBit ( 2010 IN PIRP_CONTEXT IrpContext, 2011 IN PVCB Vcb 2012 ); 2013 2014 VOID 2015 FatQuickVerifyVcb ( 2016 IN PIRP_CONTEXT IrpContext, 2017 IN PVCB Vcb 2018 ); 2019 2020 VOID 2021 FatVerifyOperationIsLegal ( 2022 IN PIRP_CONTEXT IrpContext 2023 ); 2024 2025 _Requires_lock_held_(_Global_critical_region_) 2026 NTSTATUS 2027 FatPerformVerify ( 2028 _In_ PIRP_CONTEXT IrpContext, 2029 _In_ PIRP Irp, 2030 _In_ PDEVICE_OBJECT Device 2031 ); 2032 2033 2034 // 2035 // Work queue routines for posting and retrieving an Irp, implemented in 2036 // workque.c 2037 // 2038 2039 VOID 2040 NTAPI 2041 FatOplockComplete ( 2042 IN PVOID Context, 2043 IN PIRP Irp 2044 ); 2045 2046 VOID 2047 NTAPI 2048 FatPrePostIrp ( 2049 IN PVOID Context, 2050 IN PIRP Irp 2051 ); 2052 2053 VOID 2054 #ifdef __REACTOS__ 2055 NTAPI 2056 #endif 2057 FatAddToWorkque ( 2058 IN PIRP_CONTEXT IrpContext, 2059 IN PIRP Irp 2060 ); 2061 2062 NTSTATUS 2063 FatFsdPostRequest ( 2064 IN PIRP_CONTEXT IrpContext, 2065 IN PIRP Irp 2066 ); 2067 2068 // 2069 // Miscellaneous support routines 2070 // 2071 2072 // 2073 // ULONG 2074 // PtrOffset ( 2075 // IN PVOID BasePtr, 2076 // IN PVOID OffsetPtr 2077 // ); 2078 // 2079 2080 #define PtrOffset(BASE,OFFSET) ((ULONG)((ULONG_PTR)(OFFSET) - (ULONG_PTR)(BASE))) 2081 2082 // 2083 // This macro takes a pointer (or ulong) and returns its rounded up word 2084 // value 2085 // 2086 2087 #define WordAlign(Ptr) ( \ 2088 ((((ULONG)(Ptr)) + 1) & 0xfffffffe) \ 2089 ) 2090 2091 // 2092 // This macro takes a pointer (or ulong) and returns its rounded up longword 2093 // value 2094 // 2095 2096 #define LongAlign(Ptr) ( \ 2097 ((((ULONG)(Ptr)) + 3) & 0xfffffffc) \ 2098 ) 2099 2100 // 2101 // This macro takes a pointer (or ulong) and returns its rounded up quadword 2102 // value 2103 // 2104 2105 #define QuadAlign(Ptr) ( \ 2106 ((((ULONG)(Ptr)) + 7) & 0xfffffff8) \ 2107 ) 2108 2109 // 2110 // The following types and macros are used to help unpack the packed and 2111 // misaligned fields found in the Bios parameter block 2112 // 2113 2114 typedef union _UCHAR1 { 2115 UCHAR Uchar[1]; 2116 UCHAR ForceAlignment; 2117 } UCHAR1, *PUCHAR1; 2118 2119 typedef union _UCHAR2 { 2120 UCHAR Uchar[2]; 2121 USHORT ForceAlignment; 2122 } UCHAR2, *PUCHAR2; 2123 2124 typedef union _UCHAR4 { 2125 UCHAR Uchar[4]; 2126 ULONG ForceAlignment; 2127 } UCHAR4, *PUCHAR4; 2128 2129 // 2130 // This macro copies an unaligned src byte to an aligned dst byte 2131 // 2132 2133 #define CopyUchar1(Dst,Src) { \ 2134 *((UCHAR1 *)(Dst)) = *((UNALIGNED UCHAR1 *)(Src)); \ 2135 } 2136 2137 // 2138 // This macro copies an unaligned src word to an aligned dst word 2139 // 2140 2141 #define CopyUchar2(Dst,Src) { \ 2142 *((UCHAR2 *)(Dst)) = *((UNALIGNED UCHAR2 *)(Src)); \ 2143 } 2144 2145 // 2146 // This macro copies an unaligned src longword to an aligned dsr longword 2147 // 2148 2149 #define CopyUchar4(Dst,Src) { \ 2150 *((UCHAR4 *)(Dst)) = *((UNALIGNED UCHAR4 *)(Src)); \ 2151 } 2152 2153 #define CopyU4char(Dst,Src) { \ 2154 *((UNALIGNED UCHAR4 *)(Dst)) = *((UCHAR4 *)(Src)); \ 2155 } 2156 2157 // 2158 // VOID 2159 // FatNotifyReportChange ( 2160 // IN PIRP_CONTEXT IrpContext, 2161 // IN PVCB Vcb, 2162 // IN PFCB Fcb, 2163 // IN ULONG Filter, 2164 // IN ULONG Action 2165 // ); 2166 // 2167 2168 #define FatNotifyReportChange(I,V,F,FL,A) { \ 2169 if ((F)->FullFileName.Buffer == NULL) { \ 2170 FatSetFullFileNameInFcb((I),(F)); \ 2171 } \ 2172 NT_ASSERT( (F)->FullFileName.Length != 0 ); \ 2173 NT_ASSERT( (F)->FinalNameLength != 0 ); \ 2174 NT_ASSERT( (F)->FullFileName.Length > (F)->FinalNameLength ); \ 2175 NT_ASSERT( (F)->FullFileName.Buffer[((F)->FullFileName.Length - (F)->FinalNameLength)/sizeof(WCHAR) - 1] == L'\\' ); \ 2176 FsRtlNotifyFullReportChange( (V)->NotifySync, \ 2177 &(V)->DirNotifyList, \ 2178 (PSTRING)&(F)->FullFileName, \ 2179 (USHORT) ((F)->FullFileName.Length - \ 2180 (F)->FinalNameLength), \ 2181 (PSTRING)NULL, \ 2182 (PSTRING)NULL, \ 2183 (ULONG)FL, \ 2184 (ULONG)A, \ 2185 (PVOID)NULL ); \ 2186 } 2187 2188 2189 // 2190 // The FSD Level dispatch routines. These routines are called by the 2191 // I/O system via the dispatch table in the Driver Object. 2192 // 2193 // They each accept as input a pointer to a device object (actually most 2194 // expect a volume device object, with the exception of the file system 2195 // control function which can also take a file system device object), and 2196 // a pointer to the IRP. They either perform the function at the FSD level 2197 // or post the request to the FSP work queue for FSP level processing. 2198 // 2199 2200 _Function_class_(IRP_MJ_CLEANUP) 2201 _Function_class_(DRIVER_DISPATCH) 2202 NTSTATUS 2203 NTAPI 2204 FatFsdCleanup ( // implemented in Cleanup.c 2205 _In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject, 2206 _Inout_ PIRP Irp 2207 ); 2208 2209 _Function_class_(IRP_MJ_CLOSE) 2210 _Function_class_(DRIVER_DISPATCH) 2211 NTSTATUS 2212 NTAPI 2213 FatFsdClose ( // implemented in Close.c 2214 _In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject, 2215 _Inout_ PIRP Irp 2216 ); 2217 2218 _Function_class_(IRP_MJ_CREATE) 2219 _Function_class_(DRIVER_DISPATCH) 2220 NTSTATUS 2221 NTAPI 2222 FatFsdCreate ( // implemented in Create.c 2223 _In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject, 2224 _Inout_ PIRP Irp 2225 ); 2226 2227 2228 _Function_class_(IRP_MJ_DEVICE_CONTROL) 2229 _Function_class_(DRIVER_DISPATCH) 2230 NTSTATUS 2231 NTAPI 2232 FatFsdDeviceControl ( // implemented in DevCtrl.c 2233 _In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject, 2234 _Inout_ PIRP Irp 2235 ); 2236 2237 _Function_class_(IRP_MJ_DIRECTORY_CONTROL) 2238 _Function_class_(DRIVER_DISPATCH) 2239 NTSTATUS 2240 NTAPI 2241 FatFsdDirectoryControl ( // implemented in DirCtrl.c 2242 _In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject, 2243 _Inout_ PIRP Irp 2244 ); 2245 2246 _Function_class_(IRP_MJ_QUERY_EA) 2247 _Function_class_(DRIVER_DISPATCH) 2248 NTSTATUS 2249 NTAPI 2250 FatFsdQueryEa ( // implemented in Ea.c 2251 _In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject, 2252 _Inout_ PIRP Irp 2253 ); 2254 2255 _Function_class_(IRP_MJ_SET_EA) 2256 _Function_class_(DRIVER_DISPATCH) 2257 NTSTATUS 2258 NTAPI 2259 FatFsdSetEa ( // implemented in Ea.c 2260 _In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject, 2261 _Inout_ PIRP Irp 2262 ); 2263 2264 _Function_class_(IRP_MJ_QUERY_INFORMATION) 2265 _Function_class_(DRIVER_DISPATCH) 2266 NTSTATUS 2267 NTAPI 2268 FatFsdQueryInformation ( // implemented in FileInfo.c 2269 _In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject, 2270 _Inout_ PIRP Irp 2271 ); 2272 2273 _Function_class_(IRP_MJ_SET_INFORMATION) 2274 _Function_class_(DRIVER_DISPATCH) 2275 NTSTATUS 2276 NTAPI 2277 FatFsdSetInformation ( // implemented in FileInfo.c 2278 _In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject, 2279 _Inout_ PIRP Irp 2280 ); 2281 2282 _Function_class_(IRP_MJ_FLUSH_BUFFERS) 2283 _Function_class_(DRIVER_DISPATCH) 2284 NTSTATUS 2285 NTAPI 2286 FatFsdFlushBuffers ( // implemented in Flush.c 2287 _In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject, 2288 _Inout_ PIRP Irp 2289 ); 2290 2291 _Function_class_(IRP_MJ_FILE_SYSTEM_CONTROL) 2292 _Function_class_(DRIVER_DISPATCH) 2293 NTSTATUS 2294 NTAPI 2295 FatFsdFileSystemControl ( // implemented in FsCtrl.c 2296 _In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject, 2297 _Inout_ PIRP Irp 2298 ); 2299 2300 _Function_class_(IRP_MJ_LOCK_CONTROL) 2301 _Function_class_(DRIVER_DISPATCH) 2302 NTSTATUS 2303 NTAPI 2304 FatFsdLockControl ( // implemented in LockCtrl.c 2305 _In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject, 2306 _Inout_ PIRP Irp 2307 ); 2308 2309 _Function_class_(IRP_MJ_PNP) 2310 _Function_class_(DRIVER_DISPATCH) 2311 NTSTATUS 2312 NTAPI 2313 FatFsdPnp ( // implemented in Pnp.c 2314 _In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject, 2315 _Inout_ PIRP Irp 2316 ); 2317 2318 _Function_class_(IRP_MJ_READ) 2319 _Function_class_(DRIVER_DISPATCH) 2320 NTSTATUS 2321 NTAPI 2322 FatFsdRead ( // implemented in Read.c 2323 _In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject, 2324 _Inout_ PIRP Irp 2325 ); 2326 2327 _Function_class_(IRP_MJ_SHUTDOWN) 2328 _Function_class_(DRIVER_DISPATCH) 2329 NTSTATUS 2330 NTAPI 2331 FatFsdShutdown ( // implemented in Shutdown.c 2332 _In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject, 2333 _Inout_ PIRP Irp 2334 ); 2335 2336 _Function_class_(IRP_MJ_QUERY_VOLUME_INFORMATION) 2337 _Function_class_(DRIVER_DISPATCH) 2338 NTSTATUS 2339 NTAPI 2340 FatFsdQueryVolumeInformation ( // implemented in VolInfo.c 2341 _In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject, 2342 _Inout_ PIRP Irp 2343 ); 2344 2345 _Function_class_(IRP_MJ_SET_VOLUME_INFORMATION) 2346 _Function_class_(DRIVER_DISPATCH) 2347 NTSTATUS 2348 NTAPI 2349 FatFsdSetVolumeInformation ( // implemented in VolInfo.c 2350 _In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject, 2351 _Inout_ PIRP Irp 2352 ); 2353 2354 _Function_class_(IRP_MJ_WRITE) 2355 _Function_class_(DRIVER_DISPATCH) 2356 NTSTATUS 2357 NTAPI 2358 FatFsdWrite ( // implemented in Write.c 2359 _In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject, 2360 _Inout_ PIRP Irp 2361 ); 2362 2363 // 2364 // The following macro is used to determine if an FSD thread can block 2365 // for I/O or wait for a resource. It returns TRUE if the thread can 2366 // block and FALSE otherwise. This attribute can then be used to call 2367 // the FSD & FSP common work routine with the proper wait value. 2368 // 2369 2370 #define CanFsdWait(IRP) IoIsOperationSynchronous(Irp) 2371 2372 2373 // 2374 // The FSP level dispatch/main routine. This is the routine that takes 2375 // IRP's off of the work queue and calls the appropriate FSP level 2376 // work routine. 2377 // 2378 2379 2380 WORKER_THREAD_ROUTINE FatFspDispatch; 2381 2382 VOID 2383 NTAPI 2384 FatFspDispatch ( // implemented in FspDisp.c 2385 _In_ PVOID Context 2386 ); 2387 2388 // 2389 // The following routines are the FSP work routines that are called 2390 // by the preceding FatFspDispath routine. Each takes as input a pointer 2391 // to the IRP, perform the function, and return a pointer to the volume 2392 // device object that they just finished servicing (if any). The return 2393 // pointer is then used by the main Fsp dispatch routine to check for 2394 // additional IRPs in the volume's overflow queue. 2395 // 2396 // Each of the following routines is also responsible for completing the IRP. 2397 // We moved this responsibility from the main loop to the individual routines 2398 // to allow them the ability to complete the IRP and continue post processing 2399 // actions. 2400 // 2401 2402 _Requires_lock_held_(_Global_critical_region_) 2403 NTSTATUS 2404 FatCommonCleanup ( // implemented in Cleanup.c 2405 IN PIRP_CONTEXT IrpContext, 2406 IN PIRP Irp 2407 ); 2408 2409 _Requires_lock_held_(_Global_critical_region_) 2410 NTSTATUS 2411 FatCommonClose ( // implemented in Close.c 2412 IN PVCB Vcb, 2413 IN PFCB Fcb, 2414 IN PCCB Ccb, 2415 IN TYPE_OF_OPEN TypeOfOpen, 2416 IN BOOLEAN Wait, 2417 IN BOOLEAN TopLevel, 2418 OUT PBOOLEAN VcbDeleted OPTIONAL 2419 ); 2420 2421 _Requires_lock_held_(_Global_critical_region_) 2422 VOID 2423 FatFspClose ( // implemented in Close.c 2424 IN PVCB Vcb OPTIONAL 2425 ); 2426 2427 _Requires_lock_held_(_Global_critical_region_) 2428 NTSTATUS 2429 FatCommonCreate ( // implemented in Create.c 2430 _Inout_ PIRP_CONTEXT IrpContext, 2431 _Inout_ PIRP Irp 2432 ); 2433 2434 #if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD) 2435 2436 _Requires_lock_held_(_Global_critical_region_) 2437 NTSTATUS 2438 FatCommonCreateOnNewStack ( // implemented in Create.c 2439 _Inout_ PIRP_CONTEXT IrpContext, 2440 _Inout_ PIRP Irp 2441 ); 2442 2443 _Requires_lock_held_(_Global_critical_region_) 2444 VOID 2445 FatCommonCreateCallout ( // implemented in Create.c 2446 _In_ PFAT_CALLOUT_PARAMETERS CalloutParameters 2447 ); 2448 2449 #endif 2450 2451 _Requires_lock_held_(_Global_critical_region_) 2452 NTSTATUS 2453 FatCommonDirectoryControl ( // implemented in DirCtrl.c 2454 IN PIRP_CONTEXT IrpContext, 2455 IN PIRP Irp 2456 ); 2457 2458 _Requires_lock_held_(_Global_critical_region_) 2459 NTSTATUS 2460 FatCommonDeviceControl ( // implemented in DevCtrl.c 2461 IN PIRP_CONTEXT IrpContext, 2462 IN PIRP Irp 2463 ); 2464 2465 NTSTATUS 2466 FatCommonQueryEa ( // implemented in Ea.c 2467 IN PIRP_CONTEXT IrpContext, 2468 IN PIRP Irp 2469 ); 2470 2471 NTSTATUS 2472 FatCommonSetEa ( // implemented in Ea.c 2473 IN PIRP_CONTEXT IrpContext, 2474 IN PIRP Irp 2475 ); 2476 2477 _Requires_lock_held_(_Global_critical_region_) 2478 NTSTATUS 2479 FatCommonQueryInformation ( // implemented in FileInfo.c 2480 IN PIRP_CONTEXT IrpContext, 2481 IN PIRP Irp 2482 ); 2483 2484 _Requires_lock_held_(_Global_critical_region_) 2485 NTSTATUS 2486 FatCommonSetInformation ( // implemented in FileInfo.c 2487 IN PIRP_CONTEXT IrpContext, 2488 IN PIRP Irp 2489 ); 2490 2491 _Requires_lock_held_(_Global_critical_region_) 2492 NTSTATUS 2493 FatCommonFlushBuffers ( // implemented in Flush.c 2494 IN PIRP_CONTEXT IrpContext, 2495 IN PIRP Irp 2496 ); 2497 2498 _Requires_lock_held_(_Global_critical_region_) 2499 NTSTATUS 2500 FatCommonFileSystemControl ( // implemented in FsCtrl.c 2501 IN PIRP_CONTEXT IrpContext, 2502 IN PIRP Irp 2503 ); 2504 2505 _Requires_lock_held_(_Global_critical_region_) 2506 NTSTATUS 2507 FatCommonLockControl ( // implemented in LockCtrl.c 2508 IN PIRP_CONTEXT IrpContext, 2509 IN PIRP Irp 2510 ); 2511 2512 _Requires_lock_held_(_Global_critical_region_) 2513 NTSTATUS 2514 FatCommonPnp ( // implemented in Pnp.c 2515 IN PIRP_CONTEXT IrpContext, 2516 IN PIRP Irp 2517 ); 2518 2519 _Requires_lock_held_(_Global_critical_region_) 2520 NTSTATUS 2521 FatCommonRead ( // implemented in Read.c 2522 IN PIRP_CONTEXT IrpContext, 2523 IN PIRP Irp 2524 ); 2525 2526 _Requires_lock_held_(_Global_critical_region_) 2527 NTSTATUS 2528 FatCommonShutdown ( // implemented in Shutdown.c 2529 IN PIRP_CONTEXT IrpContext, 2530 IN PIRP Irp 2531 ); 2532 2533 _Requires_lock_held_(_Global_critical_region_) 2534 NTSTATUS 2535 FatCommonQueryVolumeInfo ( // implemented in VolInfo.c 2536 IN PIRP_CONTEXT IrpContext, 2537 IN PIRP Irp 2538 ); 2539 2540 _Requires_lock_held_(_Global_critical_region_) 2541 NTSTATUS 2542 FatCommonSetVolumeInfo ( // implemented in VolInfo.c 2543 IN PIRP_CONTEXT IrpContext, 2544 IN PIRP Irp 2545 ); 2546 2547 _Requires_lock_held_(_Global_critical_region_) 2548 NTSTATUS 2549 FatCommonWrite ( // implemented in Write.c 2550 IN PIRP_CONTEXT IrpContext, 2551 IN PIRP Irp 2552 ); 2553 2554 // 2555 // The following is implemented in Flush.c, and does what is says. 2556 // 2557 2558 _Requires_lock_held_(_Global_critical_region_) 2559 NTSTATUS 2560 FatFlushFile ( 2561 IN PIRP_CONTEXT IrpContext, 2562 IN PFCB Fcb, 2563 IN FAT_FLUSH_TYPE FlushType 2564 ); 2565 2566 _Requires_lock_held_(_Global_critical_region_) 2567 NTSTATUS 2568 FatFlushDirectory ( 2569 IN PIRP_CONTEXT IrpContext, 2570 IN PDCB Dcb, 2571 IN FAT_FLUSH_TYPE FlushType 2572 ); 2573 2574 NTSTATUS 2575 FatFlushFat ( 2576 IN PIRP_CONTEXT IrpContext, 2577 IN PVCB Vcb 2578 ); 2579 2580 _Requires_lock_held_(_Global_critical_region_) 2581 NTSTATUS 2582 FatFlushVolume ( 2583 IN PIRP_CONTEXT IrpContext, 2584 IN PVCB Vcb, 2585 IN FAT_FLUSH_TYPE FlushType 2586 ); 2587 2588 NTSTATUS 2589 FatHijackIrpAndFlushDevice ( 2590 IN PIRP_CONTEXT IrpContext, 2591 IN PIRP Irp, 2592 IN PDEVICE_OBJECT TargetDeviceObject 2593 ); 2594 2595 VOID 2596 FatFlushFatEntries ( 2597 IN PIRP_CONTEXT IrpContext, 2598 IN PVCB Vcb, 2599 IN ULONG Cluster, 2600 IN ULONG Count 2601 ); 2602 2603 VOID 2604 FatFlushDirentForFile ( 2605 IN PIRP_CONTEXT IrpContext, 2606 IN PFCB Fcb 2607 ); 2608 2609 2610 2611 // 2612 // The following procedure is used by the FSP and FSD routines to complete 2613 // an IRP. 2614 // 2615 // Note that this macro allows either the Irp or the IrpContext to be 2616 // null, however the only legal order to do this in is: 2617 // 2618 // FatCompleteRequest( NULL, Irp, Status ); // completes Irp & preserves context 2619 // ... 2620 // FatCompleteRequest( IrpContext, NULL, DontCare ); // deallocates context 2621 // 2622 // This would typically be done in order to pass a "naked" IrpContext off to 2623 // the Fsp for post processing, such as read ahead. 2624 // 2625 2626 VOID 2627 FatCompleteRequest_Real ( 2628 IN PIRP_CONTEXT IrpContext, 2629 IN PIRP Irp, 2630 IN NTSTATUS Status 2631 ); 2632 2633 #define FatCompleteRequest(IRPCONTEXT,IRP,STATUS) { \ 2634 FatCompleteRequest_Real(IRPCONTEXT,IRP,STATUS); \ 2635 } 2636 2637 BOOLEAN 2638 FatIsIrpTopLevel ( 2639 IN PIRP Irp 2640 ); 2641 2642 // 2643 // The Following routine makes a popup 2644 // 2645 2646 _Requires_lock_held_(_Global_critical_region_) 2647 VOID 2648 FatPopUpFileCorrupt ( 2649 IN PIRP_CONTEXT IrpContext, 2650 IN PFCB Fcb 2651 ); 2652 2653 // 2654 // Here are the callbacks used by the I/O system for checking for fast I/O or 2655 // doing a fast query info call, or doing fast lock calls. 2656 // 2657 _Function_class_(FAST_IO_CHECK_IF_POSSIBLE) 2658 BOOLEAN 2659 NTAPI 2660 FatFastIoCheckIfPossible ( 2661 IN PFILE_OBJECT FileObject, 2662 IN PLARGE_INTEGER FileOffset, 2663 IN ULONG Length, 2664 IN BOOLEAN Wait, 2665 IN ULONG LockKey, 2666 IN BOOLEAN CheckForReadOperation, 2667 OUT PIO_STATUS_BLOCK IoStatus, 2668 IN PDEVICE_OBJECT DeviceObject 2669 ); 2670 2671 _Function_class_(FAST_IO_QUERY_BASIC_INFO) 2672 BOOLEAN 2673 NTAPI 2674 FatFastQueryBasicInfo ( 2675 IN PFILE_OBJECT FileObject, 2676 IN BOOLEAN Wait, 2677 IN OUT PFILE_BASIC_INFORMATION Buffer, 2678 OUT PIO_STATUS_BLOCK IoStatus, 2679 IN PDEVICE_OBJECT DeviceObject 2680 ); 2681 2682 _Function_class_(FAST_IO_QUERY_STANDARD_INFO) 2683 BOOLEAN 2684 NTAPI 2685 FatFastQueryStdInfo ( 2686 IN PFILE_OBJECT FileObject, 2687 IN BOOLEAN Wait, 2688 IN OUT PFILE_STANDARD_INFORMATION Buffer, 2689 OUT PIO_STATUS_BLOCK IoStatus, 2690 IN PDEVICE_OBJECT DeviceObject 2691 ); 2692 2693 _Function_class_(FAST_IO_QUERY_NETWORK_OPEN_INFO) 2694 BOOLEAN 2695 NTAPI 2696 FatFastQueryNetworkOpenInfo ( 2697 IN PFILE_OBJECT FileObject, 2698 IN BOOLEAN Wait, 2699 IN OUT PFILE_NETWORK_OPEN_INFORMATION Buffer, 2700 OUT PIO_STATUS_BLOCK IoStatus, 2701 IN PDEVICE_OBJECT DeviceObject 2702 ); 2703 2704 _Function_class_(FAST_IO_LOCK) 2705 BOOLEAN 2706 NTAPI 2707 FatFastLock ( 2708 IN PFILE_OBJECT FileObject, 2709 IN PLARGE_INTEGER FileOffset, 2710 IN PLARGE_INTEGER Length, 2711 PEPROCESS ProcessId, 2712 ULONG Key, 2713 BOOLEAN FailImmediately, 2714 BOOLEAN ExclusiveLock, 2715 OUT PIO_STATUS_BLOCK IoStatus, 2716 IN PDEVICE_OBJECT DeviceObject 2717 ); 2718 2719 _Function_class_(FAST_IO_UNLOCK_SINGLE) 2720 BOOLEAN 2721 NTAPI 2722 FatFastUnlockSingle ( 2723 IN PFILE_OBJECT FileObject, 2724 IN PLARGE_INTEGER FileOffset, 2725 IN PLARGE_INTEGER Length, 2726 PEPROCESS ProcessId, 2727 ULONG Key, 2728 OUT PIO_STATUS_BLOCK IoStatus, 2729 IN PDEVICE_OBJECT DeviceObject 2730 ); 2731 2732 _Function_class_(FAST_IO_UNLOCK_ALL) 2733 BOOLEAN 2734 NTAPI 2735 FatFastUnlockAll ( 2736 IN PFILE_OBJECT FileObject, 2737 PEPROCESS ProcessId, 2738 OUT PIO_STATUS_BLOCK IoStatus, 2739 IN PDEVICE_OBJECT DeviceObject 2740 ); 2741 2742 _Function_class_(FAST_IO_UNLOCK_ALL_BY_KEY) 2743 BOOLEAN 2744 NTAPI 2745 FatFastUnlockAllByKey ( 2746 IN PFILE_OBJECT FileObject, 2747 PVOID ProcessId, 2748 ULONG Key, 2749 OUT PIO_STATUS_BLOCK IoStatus, 2750 IN PDEVICE_OBJECT DeviceObject 2751 ); 2752 2753 2754 VOID 2755 FatExamineFatEntries( 2756 IN PIRP_CONTEXT IrpContext, 2757 IN PVCB Vcb, 2758 IN ULONG StartIndex OPTIONAL, 2759 IN ULONG EndIndex OPTIONAL, 2760 IN BOOLEAN SetupWindows, 2761 IN PFAT_WINDOW SwitchToWindow OPTIONAL, 2762 IN PULONG BitMapBuffer OPTIONAL 2763 ); 2764 2765 BOOLEAN 2766 FatScanForDataTrack( 2767 IN PIRP_CONTEXT IrpContext, 2768 IN PDEVICE_OBJECT TargetDeviceObject 2769 ); 2770 2771 // 2772 // The following macro is used to determine is a file has been deleted. 2773 // 2774 // BOOLEAN 2775 // IsFileDeleted ( 2776 // IN PIRP_CONTEXT IrpContext, 2777 // IN PFCB Fcb 2778 // ); 2779 // 2780 2781 #define IsFileDeleted(IRPCONTEXT,FCB) \ 2782 (FlagOn((FCB)->FcbState, FCB_STATE_DELETE_ON_CLOSE) && \ 2783 ((FCB)->UncleanCount == 0)) 2784 2785 // 2786 // The following macro is used by the dispatch routines to determine if 2787 // an operation is to be done with or without Write Through. 2788 // 2789 // BOOLEAN 2790 // IsFileWriteThrough ( 2791 // IN PFILE_OBJECT FileObject, 2792 // IN PVCB Vcb 2793 // ); 2794 // 2795 2796 #define IsFileWriteThrough(FO,VCB) ( \ 2797 BooleanFlagOn((FO)->Flags, FO_WRITE_THROUGH) \ 2798 ) 2799 2800 // 2801 // The following macro is used to set the is fast i/o possible field in 2802 // the common part of the nonpaged fcb. It checks that this is actually 2803 // an FCB (as opposed to a DCB) so that directory oplock code works properly. 2804 // 2805 // 2806 // BOOLEAN 2807 // FatIsFastIoPossible ( 2808 // IN PFCB Fcb 2809 // ); 2810 // 2811 2812 2813 #define FatIsFastIoPossible(FCB) ((BOOLEAN) \ 2814 ((((FCB)->FcbCondition != FcbGood) || \ 2815 (NodeType( (FCB) ) != FAT_NTC_FCB) || \ 2816 !FsRtlOplockIsFastIoPossible( FatGetFcbOplock(FCB) )) ? \ 2817 FastIoIsNotPossible \ 2818 : \ 2819 (!FsRtlAreThereCurrentFileLocks( &(FCB)->Specific.Fcb.FileLock ) && \ 2820 ((FCB)->NonPaged->OutstandingAsyncWrites == 0) && \ 2821 !FlagOn( (FCB)->Vcb->VcbState, VCB_STATE_FLAG_WRITE_PROTECTED ) ? \ 2822 FastIoIsPossible \ 2823 : \ 2824 FastIoIsQuestionable \ 2825 ) \ 2826 ) \ 2827 ) 2828 2829 2830 #if (NTDDI_VERSION >= NTDDI_WIN8) 2831 2832 // 2833 // Detect whether this file can have an oplock on it. As of Windows 8 file and 2834 // directories can have oplocks. 2835 // 2836 2837 #define FatIsNodeTypeOplockable(N) ( \ 2838 ((N) == FAT_NTC_FCB) || \ 2839 ((N) == FAT_NTC_ROOT_DCB) || \ 2840 ((N) == FAT_NTC_DCB) \ 2841 ) 2842 2843 #else 2844 2845 #define FatIsNodeTypeOplockable(N) ( \ 2846 ((N) == FAT_NTC_FCB) \ 2847 ) 2848 2849 #endif 2850 2851 #define FatIsFileOplockable(F) ( \ 2852 FatIsNodeTypeOplockable( NodeType( (F) )) \ 2853 ) 2854 2855 // 2856 // The following macro is used to detemine if the file object is opened 2857 // for read only access (i.e., it is not also opened for write access or 2858 // delete access). 2859 // 2860 // BOOLEAN 2861 // IsFileObjectReadOnly ( 2862 // IN PFILE_OBJECT FileObject 2863 // ); 2864 // 2865 2866 #define IsFileObjectReadOnly(FO) (!((FO)->WriteAccess | (FO)->DeleteAccess)) 2867 2868 2869 // 2870 // The following two macro are used by the Fsd/Fsp exception handlers to 2871 // process an exception. The first macro is the exception filter used in the 2872 // Fsd/Fsp to decide if an exception should be handled at this level. 2873 // The second macro decides if the exception is to be finished off by 2874 // completing the IRP, and cleaning up the Irp Context, or if we should 2875 // bugcheck. Exception values such as STATUS_FILE_INVALID (raised by 2876 // VerfySup.c) cause us to complete the Irp and cleanup, while exceptions 2877 // such as accvio cause us to bugcheck. 2878 // 2879 // The basic structure for fsd/fsp exception handling is as follows: 2880 // 2881 // FatFsdXxx(...) 2882 // { 2883 // try { 2884 // 2885 // ... 2886 // 2887 // } except(FatExceptionFilter( IrpContext, GetExceptionCode() )) { 2888 // 2889 // Status = FatProcessException( IrpContext, Irp, GetExceptionCode() ); 2890 // } 2891 // 2892 // Return Status; 2893 // } 2894 // 2895 // To explicitly raise an exception that we expect, such as 2896 // STATUS_FILE_INVALID, use the below macro FatRaiseStatus(). To raise a 2897 // status from an unknown origin (such as CcFlushCache()), use the macro 2898 // FatNormalizeAndRaiseStatus. This will raise the status if it is expected, 2899 // or raise STATUS_UNEXPECTED_IO_ERROR if it is not. 2900 // 2901 // If we are vicariously handling exceptions without using FatProcessException(), 2902 // if there is the possibility that we raised that exception, one *must* 2903 // reset the IrpContext so a subsequent raise in the course of handling this 2904 // request that is *not* explicit, i.e. like a pagein error, does not get 2905 // spoofed into believing that the first raise status is the reason the second 2906 // occured. This could have really serious consequences. 2907 // 2908 // It is an excellent idea to always FatResetExceptionState in these cases. 2909 // 2910 // Note that when using these two macros, the original status is placed in 2911 // IrpContext->ExceptionStatus, signaling FatExceptionFilter and 2912 // FatProcessException that the status we actually raise is by definition 2913 // expected. 2914 // 2915 2916 ULONG 2917 FatExceptionFilter ( 2918 IN PIRP_CONTEXT IrpContext, 2919 IN PEXCEPTION_POINTERS ExceptionPointer 2920 ); 2921 2922 #if DBG 2923 ULONG 2924 FatBugCheckExceptionFilter ( 2925 IN PEXCEPTION_POINTERS ExceptionPointer 2926 ); 2927 #endif 2928 2929 _Requires_lock_held_(_Global_critical_region_) 2930 NTSTATUS 2931 FatProcessException ( 2932 IN PIRP_CONTEXT IrpContext, 2933 IN PIRP Irp, 2934 IN NTSTATUS ExceptionCode 2935 ); 2936 2937 // 2938 // VOID 2939 // FatRaiseStatus ( 2940 // IN PRIP_CONTEXT IrpContext, 2941 // IN NT_STATUS Status 2942 // ); 2943 // 2944 // 2945 2946 #if DBG 2947 #ifdef _MSC_VER 2948 #define DebugBreakOnStatus(S) { \ 2949 __pragma(warning(push)) \ 2950 __pragma(warning(disable:4127)) \ 2951 if (FatTestRaisedStatus) { \ 2952 if ((S) == STATUS_DISK_CORRUPT_ERROR || (S) == STATUS_FILE_CORRUPT_ERROR) { \ 2953 __pragma(warning(pop)) \ 2954 DbgPrint( "FAT: Breaking on interesting raised status (0x%08x)\n", (S) );\ 2955 DbgPrint( "FAT: Set FatTestRaisedStatus @ 0x%p to 0 to disable\n", \ 2956 &FatTestRaisedStatus ); \ 2957 NT_ASSERT(FALSE); \ 2958 } \ 2959 } \ 2960 } 2961 #else 2962 #define DebugBreakOnStatus(S) { \ 2963 if (FatTestRaisedStatus) { \ 2964 if ((S) == STATUS_DISK_CORRUPT_ERROR || (S) == STATUS_FILE_CORRUPT_ERROR) { \ 2965 DbgPrint( "FAT: Breaking on interesting raised status (0x%08x)\n", (S) );\ 2966 DbgPrint( "FAT: Set FatTestRaisedStatus @ 0x%p to 0 to disable\n", \ 2967 &FatTestRaisedStatus ); \ 2968 NT_ASSERT(FALSE); \ 2969 } \ 2970 } \ 2971 } 2972 #endif 2973 #else 2974 #define DebugBreakOnStatus(S) 2975 #endif 2976 2977 #define FatRaiseStatus(IRPCONTEXT,STATUS) { \ 2978 (IRPCONTEXT)->ExceptionStatus = (STATUS); \ 2979 DebugBreakOnStatus( (STATUS) ) \ 2980 ExRaiseStatus( (STATUS) ); \ 2981 } 2982 2983 #define FatResetExceptionState( IRPCONTEXT ) { \ 2984 (IRPCONTEXT)->ExceptionStatus = STATUS_SUCCESS; \ 2985 } 2986 2987 // 2988 // VOID 2989 // FatNormalAndRaiseStatus ( 2990 // IN PRIP_CONTEXT IrpContext, 2991 // IN NT_STATUS Status 2992 // ); 2993 // 2994 2995 #define FatNormalizeAndRaiseStatus(IRPCONTEXT,STATUS) { \ 2996 (IRPCONTEXT)->ExceptionStatus = (STATUS); \ 2997 ExRaiseStatus(FsRtlNormalizeNtstatus((STATUS),STATUS_UNEXPECTED_IO_ERROR)); \ 2998 } 2999 3000 3001 // 3002 // The following macros are used to establish the semantics needed 3003 // to do a return from within a try-finally clause. As a rule every 3004 // try clause must end with a label call try_exit. For example, 3005 // 3006 // try { 3007 // : 3008 // : 3009 // 3010 // try_exit: NOTHING; 3011 // } finally { 3012 // 3013 // : 3014 // : 3015 // } 3016 // 3017 // Every return statement executed inside of a try clause should use the 3018 // try_return macro. If the compiler fully supports the try-finally construct 3019 // then the macro should be 3020 // 3021 // #define try_return(S) { return(S); } 3022 // 3023 // If the compiler does not support the try-finally construct then the macro 3024 // should be 3025 // 3026 // #define try_return(S) { S; goto try_exit; } 3027 // 3028 3029 #define try_return(S) { S; goto try_exit; } 3030 #define try_leave(S) { S; _SEH2_LEAVE; } 3031 3032 3033 CLUSTER_TYPE 3034 FatInterpretClusterType ( 3035 IN PVCB Vcb, 3036 IN FAT_ENTRY Entry 3037 ); 3038 3039 3040 // 3041 // These routines define the FileId for FAT. Lacking a fixed/uniquifiable 3042 // notion, we simply come up with one which is unique in a given snapshot 3043 // of the volume. As long as the parent directory is not moved or compacted, 3044 // it may even be permanent. 3045 // 3046 3047 // 3048 // The internal information used to identify the fcb/dcb on the 3049 // volume is the byte offset of the dirent of the file on disc. 3050 // Our root always has fileid 0. FAT32 roots are chains and can 3051 // use the LBO of the cluster, 12/16 roots use the lbo in the Vcb. 3052 // 3053 3054 #define FatGenerateFileIdFromDirentOffset(ParentDcb,DirentOffset) \ 3055 ((ParentDcb) ? ((NodeType(ParentDcb) != FAT_NTC_ROOT_DCB || FatIsFat32((ParentDcb)->Vcb)) ? \ 3056 FatGetLboFromIndex( (ParentDcb)->Vcb, \ 3057 (ParentDcb)->FirstClusterOfFile ) : \ 3058 (ParentDcb)->Vcb->AllocationSupport.RootDirectoryLbo) + \ 3059 (DirentOffset) \ 3060 : \ 3061 0) 3062 3063 // 3064 // 3065 3066 #define FatGenerateFileIdFromFcb(Fcb) \ 3067 FatGenerateFileIdFromDirentOffset( (Fcb)->ParentDcb, (Fcb)->DirentOffsetWithinDirectory ) 3068 3069 // 3070 // Wrap to handle the ./.. cases appropriately. Note that we commute NULL parent to 0. This would 3071 // only occur in an illegal root ".." entry. 3072 // 3073 3074 #define FATDOT ((ULONG)0x2020202E) 3075 #define FATDOTDOT ((ULONG)0x20202E2E) 3076 3077 #define FatGenerateFileIdFromDirentAndOffset(Dcb,Dirent,DirentOffset) \ 3078 ((*((PULONG)(Dirent)->FileName)) == FATDOT ? FatGenerateFileIdFromFcb(Dcb) : \ 3079 ((*((PULONG)(Dirent)->FileName)) == FATDOTDOT ? ((Dcb)->ParentDcb ? \ 3080 FatGenerateFileIdFromFcb((Dcb)->ParentDcb) : \ 3081 0) : \ 3082 FatGenerateFileIdFromDirentOffset(Dcb,DirentOffset))) 3083 3084 3085 // 3086 // BOOLEAN 3087 // FatDeviceIsFatFsdo( 3088 // IN PDEVICE_OBJECT D 3089 // ); 3090 // 3091 // Evaluates to TRUE if the supplied device object is one of the file system devices 3092 // we created at initialisation. 3093 // 3094 3095 #define FatDeviceIsFatFsdo( D) (((D) == FatData.DiskFileSystemDeviceObject) || ((D) == FatData.CdromFileSystemDeviceObject)) 3096 3097 3098 // 3099 // BlockAlign(): Aligns P on the next V boundary. 3100 // BlockAlignTruncate(): Aligns P on the prev V boundary. 3101 // 3102 3103 #define BlockAlign(P,V) ((ASSERT( V != 0)), (((P)) + (V-1) & (0-(V)))) 3104 #define BlockAlignTruncate(P,V) ((P) & (0-(V))) 3105 3106 #define IsDirectory(FcbOrDcb) ((NodeType((FcbOrDcb)) == FAT_NTC_DCB) || (NodeType((FcbOrDcb)) == FAT_NTC_ROOT_DCB)) 3107 3108 #endif // _FATPROCS_ 3109 3110 3111