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