From b9d68f3ef310c77b93fe574e9de56f9350cf143b Mon Sep 17 00:00:00 2001 From: Gleb Lamm Date: Sat, 1 Nov 2025 09:48:48 +0400 Subject: [PATCH 1/9] refactoring --- drivers/filesystems/udfs/CMakeLists.txt | 1 + .../filesystems/udfs/Include/Sys_spec_lib.cpp | 8 +- .../filesystems/udfs/Include/Sys_spec_lib.h | 17 +- drivers/filesystems/udfs/Include/phys_lib.cpp | 275 ++------ drivers/filesystems/udfs/Include/phys_lib.h | 8 +- drivers/filesystems/udfs/Include/udf_reg.h | 6 - drivers/filesystems/udfs/cleanup.cpp | 72 +- drivers/filesystems/udfs/close.cpp | 75 +- drivers/filesystems/udfs/create.cpp | 133 +--- drivers/filesystems/udfs/devcntrl.cpp | 68 +- drivers/filesystems/udfs/dircntrl.cpp | 147 +--- drivers/filesystems/udfs/env_spec.cpp | 80 +-- drivers/filesystems/udfs/fastio.cpp | 30 +- drivers/filesystems/udfs/fileinfo.cpp | 426 ++++-------- drivers/filesystems/udfs/flush.cpp | 69 +- drivers/filesystems/udfs/fscntrl.cpp | 121 +--- drivers/filesystems/udfs/lockctrl.cpp | 140 +--- drivers/filesystems/udfs/misc.cpp | 657 ++++++++++-------- drivers/filesystems/udfs/pnp.cpp | 70 -- drivers/filesystems/udfs/protos.h | 351 ++++------ drivers/filesystems/udfs/read.cpp | 217 ++---- drivers/filesystems/udfs/shutdown.cpp | 96 +-- drivers/filesystems/udfs/strucsup.cpp | 300 +++----- drivers/filesystems/udfs/struct.h | 57 +- drivers/filesystems/udfs/udf_dbg.cpp | 278 +------- drivers/filesystems/udfs/udf_dbg.h | 73 +- drivers/filesystems/udfs/udf_info/alloc.cpp | 44 +- drivers/filesystems/udfs/udf_info/dirtree.cpp | 6 +- drivers/filesystems/udfs/udf_info/extent.cpp | 110 +-- drivers/filesystems/udfs/udf_info/mount.cpp | 527 +++++++------- .../filesystems/udfs/udf_info/phys_eject.cpp | 3 - drivers/filesystems/udfs/udf_info/remap.cpp | 41 +- .../filesystems/udfs/udf_info/udf_info.cpp | 128 ++-- drivers/filesystems/udfs/udf_info/udf_info.h | 35 +- drivers/filesystems/udfs/udf_info/udf_rel.h | 6 - drivers/filesystems/udfs/udfdata.cpp | 280 ++++++++ drivers/filesystems/udfs/udffs.h | 66 +- drivers/filesystems/udfs/udfinit.cpp | 82 +-- drivers/filesystems/udfs/verfysup.cpp | 107 +-- drivers/filesystems/udfs/volinfo.cpp | 146 +--- drivers/filesystems/udfs/write.cpp | 129 +--- 41 files changed, 1886 insertions(+), 3599 deletions(-) create mode 100644 drivers/filesystems/udfs/udfdata.cpp diff --git a/drivers/filesystems/udfs/CMakeLists.txt b/drivers/filesystems/udfs/CMakeLists.txt index e12d4d4dca000..d15da5fdf6c01 100644 --- a/drivers/filesystems/udfs/CMakeLists.txt +++ b/drivers/filesystems/udfs/CMakeLists.txt @@ -38,6 +38,7 @@ list(APPEND SOURCE write.cpp strucsup.cpp filobsup.cpp + udfdata.cpp udffs.h) add_library(udfs MODULE ${SOURCE} udffs.rc) diff --git a/drivers/filesystems/udfs/Include/Sys_spec_lib.cpp b/drivers/filesystems/udfs/Include/Sys_spec_lib.cpp index ff0e83ba441ac..272d2342ce18c 100644 --- a/drivers/filesystems/udfs/Include/Sys_spec_lib.cpp +++ b/drivers/filesystems/udfs/Include/Sys_spec_lib.cpp @@ -298,10 +298,10 @@ UDFFileDirInfoToNT( LONG_AD feloc; UDFPrint((" !SYS_ATTR\n")); - FileEntry = (PFILE_ENTRY)MyAllocatePool__(NonPagedPool, Vcb->LBlockSize); + FileEntry = (PFILE_ENTRY)MyAllocatePool__(NonPagedPool, Vcb->SectorSize); if (!FileEntry) return STATUS_INSUFFICIENT_RESOURCES; - feloc.extLength = Vcb->LBlockSize; + feloc.extLength = Vcb->SectorSize; feloc.extLocation = FileDirNdx->FileEntryLoc; if (!NT_SUCCESS(status = UDFReadFileEntry(IrpContext, Vcb, &feloc, FileEntry, &Ident))) { @@ -346,7 +346,7 @@ UDFFileDirInfoToNT( // AllocSize FileDirNdx->AllocationSize = NTFileInfo->AllocationSize.QuadPart = - (FileEntry->informationLength + Vcb->LBlockSize - 1) & ~((LONGLONG)(Vcb->LBlockSize) - 1); + (FileEntry->informationLength + Vcb->SectorSize - 1) & ~((LONGLONG)(Vcb->SectorSize) - 1); } // NTFileInfo->EaSize = 0;//FileEntry->lengthExtendedAttr; } else if (FileEntry->descTag.tagIdent == TID_EXTENDED_FILE_ENTRY) { @@ -370,7 +370,7 @@ UDFFileDirInfoToNT( // AllocSize FileDirNdx->AllocationSize = NTFileInfo->AllocationSize.QuadPart = - (ExFileEntry->informationLength + Vcb->LBlockSize - 1) & ~((LONGLONG)(Vcb->LBlockSize) - 1); + (ExFileEntry->informationLength + Vcb->SectorSize - 1) & ~((LONGLONG)(Vcb->SectorSize) - 1); } // NTFileInfo->EaSize = 0;//ExFileEntry->lengthExtendedAttr; } else { diff --git a/drivers/filesystems/udfs/Include/Sys_spec_lib.h b/drivers/filesystems/udfs/Include/Sys_spec_lib.h index 20061dbfcb25d..858c8bbbbb5c5 100644 --- a/drivers/filesystems/udfs/Include/Sys_spec_lib.h +++ b/drivers/filesystems/udfs/Include/Sys_spec_lib.h @@ -24,8 +24,6 @@ typedef struct _UDF_PH_CALL_CONTEXT { IO_STATUS_BLOCK IosbToUse; } UDF_PH_CALL_CONTEXT, *PUDF_PH_CALL_CONTEXT; -#ifdef _BROWSE_UDF_ - // convert UDF timestamp to NT time LONGLONG UDFTimeToNT(IN PUDF_TIME_STAMP UdfTime); // translate UDF file attributes to NT ones @@ -159,7 +157,7 @@ __inline LARGE_INTEGER UDFMakeLargeInteger(LONGLONG value) { #define UnicodeIsPrint(a) RtlIsValidOemCharacter(&(a)) -#define UDFSysGetAllocSize(Vcb, Size) ((Size + Vcb->LBlockSize - 1) & ~((LONGLONG)(Vcb->LBlockSize - 1))) +#define UDFSysGetAllocSize(Vcb, Size) ((Size + Vcb->SectorSize - 1) & ~((LONGLONG)(Vcb->SectorSize - 1))) NTSTATUS UDFDoesOSAllowFileToBeTargetForRename__(IN PUDF_FILE_INFO FileInfo); #define UDFDoesOSAllowFileToBeTargetForHLink__ UDFDoesOSAllowFileToBeTargetForRename__ @@ -168,17 +166,4 @@ NTSTATUS UDFDoesOSAllowFileToBeUnlinked__(IN PUDF_FILE_INFO FileInfo); NTSTATUS UDFDoesOSAllowFilePretendDeleted__(IN PUDF_FILE_INFO FileInfo); BOOLEAN UDFRemoveOSReferences__(IN PUDF_FILE_INFO FileInfo); -/* -extern ULONG MajorVersion; -extern ULONG MinorVersion; -extern ULONG BuildNumber; - -#define WinVer_Is351 (MajorVersion==0x03 && MinorVersion==51) -#define WinVer_IsNT (MajorVersion==0x04) -#define WinVer_Is2k (MajorVersion==0x05 && MinorVersion==0x00) -#define WinVer_IsXP (MajorVersion==0x05 && MinorVersion==0x01) -#define WinVer_IsdNET (MajorVersion==0x05 && MinorVersion==0x02) -*/ -#endif //_BROWSE_UDF_ - #endif // _UDF_SYS_SPEC_LIB__H_ diff --git a/drivers/filesystems/udfs/Include/phys_lib.cpp b/drivers/filesystems/udfs/Include/phys_lib.cpp index ea71a5a56d2a9..ee76d63404c16 100644 --- a/drivers/filesystems/udfs/Include/phys_lib.cpp +++ b/drivers/filesystems/udfs/Include/phys_lib.cpp @@ -75,23 +75,18 @@ UDFRecoverFromError( IN uint32 BCount, IN OUT uint32* retry); -#ifdef _BROWSE_UDF_ - uint32 UDFFixFPAddress( IN PVCB Vcb, // Volume control block from this DevObj IN uint32 Lba ); -#endif //_BROWSE_UDF_ - NTSTATUS UDFReallocTrackMap( IN PVCB Vcb, IN uint32 TrackNum ) { -#ifdef _BROWSE_UDF_ if (Vcb->TrackMap) { MyFreePool__(Vcb->TrackMap); Vcb->TrackMap = NULL; @@ -101,14 +96,11 @@ UDFReallocTrackMap( if (!Vcb->TrackMap) { return STATUS_INSUFFICIENT_RESOURCES; } -#endif //_BROWSE_UDF_ + RtlZeroMemory(Vcb->TrackMap,TrackNum*sizeof(UDFTrackMap)); return STATUS_SUCCESS; } // end UDFReallocTrackMap() -#ifdef _BROWSE_UDF_ - - NTSTATUS __fastcall UDFTIOVerify( @@ -200,13 +192,13 @@ UDFTIOVerify( // perform recovery mask = Vcb->SparingBlockSize-1; lba0 = LBA & ~mask; - len = ((LBA+(Length>>Vcb->BlockSizeBits)+mask) & ~mask) - lba0; + len = ((LBA+(Length>>Vcb->SectorShift)+mask) & ~mask) - lba0; j=0; - if ((lba0 == LBA) && (len == mask+1) && (len == (Length>>Vcb->BlockSizeBits))) { + if ((lba0 == LBA) && (len == mask+1) && (len == (Length>>Vcb->SectorShift))) { single_packet = TRUE; tmp_buff = NULL; } else { - tmp_buff = (PUCHAR)DbgAllocatePoolWithTag(NonPagedPool, Vcb->SparingBlockSize << Vcb->BlockSizeBits, 'bNWD'); + tmp_buff = (PUCHAR)DbgAllocatePoolWithTag(NonPagedPool, Vcb->SparingBlockSize << Vcb->SectorShift, 'bNWD'); if (!tmp_buff) { UDFPrint((" can't alloc tmp\n")); UDFReleaseResource(&(Vcb->IoResource)); @@ -238,10 +230,10 @@ UDFTIOVerify( } } } - p = tmp_buff+(j<BlockSizeBits); + p = tmp_buff+(j<SectorShift); // not cached, try to read // prepare for error, if block cannot be read, assume it is zero-filled - RtlZeroMemory(p, Vcb->BlockSize); + RtlZeroMemory(p, Vcb->SectorSize); // check if block valid if (Vcb->BSBM_Bitmap) { @@ -257,12 +249,7 @@ UDFTIOVerify( zero = TRUE; } } - if (!zero && Vcb->ZSBM_Bitmap) { - if (UDFGetZeroBit((uint32*)(Vcb->ZSBM_Bitmap), lba0+i)) { - UDFPrint((" unused @ %x (Z)\n", lba0+i)); - zero = TRUE; - } - } + non_zero |= !zero; if (!j) { @@ -270,7 +257,7 @@ UDFTIOVerify( if (!single_packet) { // try to read entire packet, this returs error more often then sequential reading of all blocks one by one tmp_wb = (SIZE_T)_Vcb; - RC = UDFTRead(IrpContext, _Vcb, p, Vcb->SparingBlockSize << Vcb->BlockSizeBits, lba0+i, &tmp_wb, + RC = UDFTRead(IrpContext, _Vcb, p, Vcb->SparingBlockSize << Vcb->SectorShift, lba0+i, &tmp_wb, Flags | PH_READ_VERIFY_CACHE | PH_TMP_BUFFER | PH_VCB_IN_RETLEN); } else { // Note: we get here ONLY if original request failed @@ -293,7 +280,7 @@ UDFTIOVerify( if (!packet_ok && !UDFVIsStored(Vcb, lba0+i)) { tmp_wb = (SIZE_T)_Vcb; - RC = UDFTRead(IrpContext, _Vcb, p, Vcb->BlockSize, lba0+i, &tmp_wb, + RC = UDFTRead(IrpContext, _Vcb, p, Vcb->SectorSize, lba0+i, &tmp_wb, Flags | PH_FORGET_VERIFIED | PH_READ_VERIFY_CACHE | PH_TMP_BUFFER | PH_VCB_IN_RETLEN); if (!NT_SUCCESS(RC)) { UDFPrint((" Found BB @ %x\n", lba0+i)); @@ -313,13 +300,13 @@ UDFTIOVerify( // cached or successfully read if (cached_block) { // we can get from cache the most fresh data - RtlCopyMemory(p, cached_block, Vcb->BlockSize); + RtlCopyMemory(p, cached_block, Vcb->SectorSize); } } else { if (!UDFVIsStored(Vcb, lba0+i)) { tmp_wb = (SIZE_T)_Vcb; - RC = UDFTRead(IrpContext, _Vcb, p, Vcb->BlockSize, lba0+i, &tmp_wb, + RC = UDFTRead(IrpContext, _Vcb, p, Vcb->SectorSize, lba0+i, &tmp_wb, Flags | PH_FORGET_VERIFIED | PH_READ_VERIFY_CACHE | PH_TMP_BUFFER | PH_VCB_IN_RETLEN); } else { // get it from verify-cache @@ -339,7 +326,7 @@ UDFTIOVerify( } } } else { - RtlZeroMemory(p, Vcb->BlockSize); + RtlZeroMemory(p, Vcb->SectorSize); } if (!packet_ok) { UDFPrint((" try del from verify cache @ %x\n", lba0+i)); @@ -385,7 +372,7 @@ UDFTIOVerify( if (NT_SUCCESS(RC)) { // write to remapped area tmp_wb = (SIZE_T)_Vcb; - RC = UDFTWrite(IrpContext, _Vcb, tmp_buff, Vcb->SparingBlockSize << Vcb->BlockSizeBits, lba1, &tmp_wb, + RC = UDFTWrite(IrpContext, _Vcb, tmp_buff, Vcb->SparingBlockSize << Vcb->SectorShift, lba1, &tmp_wb, Flags | PH_FORGET_VERIFIED | PH_READ_VERIFY_CACHE | PH_TMP_BUFFER | PH_VCB_IN_RETLEN); UDFPrint((" write status %x\n", RC)); if (RC != STATUS_SUCCESS) { @@ -464,7 +451,6 @@ UDFTReadVerify( { return UDFTIOVerify(IrpContext, _Vcb, Buffer, Length, LBA, ReadBytes, Flags | PH_VCB_IN_RETLEN | PH_KEEP_VERIFY_CACHE); } // end UDFTReadVerify() -#endif //_BROWSE_UDF_ /* This routine performs low-level write @@ -485,10 +471,8 @@ UDFTWrite( { #define Vcb ((PVCB)_Vcb) -#ifdef _BROWSE_UDF_ PEXTENT_MAP RelocExtent; PEXTENT_MAP RelocExtent_saved = NULL; -#endif //_BROWSE_UDF_ uint32 retry; BOOLEAN res_acq = FALSE; @@ -502,10 +486,10 @@ UDFTWrite( #endif //DBG (*WrittenBytes) = 0; - BCount = Length>>Vcb->BlockSizeBits; + BCount = Length>>Vcb->SectorShift; UDFPrint(("TWrite %x (%x)\n", LBA, BCount)); -#ifdef _BROWSE_UDF_ + if (Vcb->VcbState & UDF_VCB_FLAGS_DEAD) { UDFPrint(("DEAD\n")); return STATUS_NO_SUCH_DEVICE; @@ -523,16 +507,12 @@ UDFTWrite( RelocExtent = UDF_NO_EXTENT_MAP; rLba = Vcb->NWA; } -#else //_BROWSE_UDF_ - rLba = LBA; -#endif //_BROWSE_UDF_ #ifdef DBG //ASSERT(!(rLba & (32-1))); #endif //DBG _SEH2_TRY { -#ifdef _BROWSE_UDF_ if (!(Flags & PH_IO_LOCKED)) { UDFAcquireResourceExclusive(&(Vcb->IoResource), TRUE); @@ -540,7 +520,7 @@ UDFTWrite( } if (RelocExtent == UDF_NO_EXTENT_MAP) { -#endif //_BROWSE_UDF_ + retry = UDF_WRITE_MAX_RETRY; retry_1: RC = UDFPrepareForWriteOperation(Vcb, rLba, BCount); @@ -552,22 +532,21 @@ UDFTWrite( (*WrittenBytes) = (ULONG_PTR)Vcb; } RC = UDFPhWriteSynchronous(Vcb->TargetDeviceObject, Buffer, Length, - ((uint64)rLba) << Vcb->BlockSizeBits, WrittenBytes, Flags); -#ifdef _BROWSE_UDF_ + ((uint64)rLba) << Vcb->SectorShift, WrittenBytes, Flags); + Vcb->VcbState |= UDF_VCB_SKIP_EJECT_CHECK; -#endif //_BROWSE_UDF_ + if (!NT_SUCCESS(RC) && NT_SUCCESS(RC = UDFRecoverFromError(Vcb, TRUE, RC, rLba, BCount, &retry)) ) goto retry_1; try_return(RC); -#ifdef _BROWSE_UDF_ } // write according to relocation table RelocExtent_saved = RelocExtent; for(i=0; RelocExtent->extLength; i++, RelocExtent++) { SIZE_T _WrittenBytes; rLba = RelocExtent->extLocation; - BCount = RelocExtent->extLength>>Vcb->BlockSizeBits; + BCount = RelocExtent->extLength>>Vcb->SectorShift; retry = UDF_WRITE_MAX_RETRY; retry_2: RC = UDFPrepareForWriteOperation(Vcb, rLba, BCount); @@ -579,7 +558,7 @@ UDFTWrite( _WrittenBytes = (ULONG_PTR)Vcb; } RC = UDFPhWriteSynchronous(Vcb->TargetDeviceObject, Buffer, RelocExtent->extLength, - ((uint64)rLba) << Vcb->BlockSizeBits, &_WrittenBytes, Flags); + ((uint64)rLba) << Vcb->SectorShift, &_WrittenBytes, Flags); Vcb->VcbState |= UDF_VCB_SKIP_EJECT_CHECK; if (!NT_SUCCESS(RC) && NT_SUCCESS(RC = UDFRecoverFromError(Vcb, TRUE, RC, rLba, BCount, &retry)) ) @@ -589,17 +568,14 @@ UDFTWrite( if (!NT_SUCCESS(RC)) break; *((uint32*)&Buffer) += RelocExtent->extLength; } -#endif //_BROWSE_UDF_ try_exit: NOTHING; } _SEH2_FINALLY { if (res_acq) { UDFReleaseResource(&(Vcb->IoResource)); } -#ifdef _BROWSE_UDF_ if (RelocExtent_saved) { MyFreePool__(RelocExtent_saved); } -#endif //_BROWSE_UDF_ } _SEH2_END; UDFPrint(("TWrite: %x\n", RC)); return RC; @@ -625,9 +601,8 @@ UDFTRead( NTSTATUS RC = STATUS_SUCCESS; uint32 retry; PVCB Vcb = (PVCB)_Vcb; - uint32 BCount = Length >> Vcb->BlockSizeBits; + uint32 BCount = Length >> Vcb->SectorShift; uint32 i; -#ifdef _BROWSE_UDF_ PEXTENT_MAP RelocExtent; PEXTENT_MAP RelocExtent_saved = NULL; BOOLEAN res_acq = FALSE; @@ -659,25 +634,17 @@ UDFTRead( } retry = UDF_WRITE_MAX_RETRY; retry_1: - RC = UDFPrepareForReadOperation(IrpContext, Vcb, rLba, Length >> Vcb->BlockSizeBits); + RC = UDFPrepareForReadOperation(IrpContext, Vcb, rLba, Length >> Vcb->SectorShift); if (!NT_SUCCESS(RC)) try_return(RC); rLba = UDFFixFPAddress(Vcb, rLba); -#else - rLba = LBA; - retry = UDF_WRITE_MAX_RETRY; -retry_1: - RC = UDFPrepareForReadOperation(Vcb, rLba, Length >> Vcb->BlockSizeBits); - if (!NT_SUCCESS(RC)) return RC; // this is for !_BROWSE_UDF only -#endif //_BROWSE_UDF_ + if (Flags & PH_VCB_IN_RETLEN) { (*ReadBytes) = (SIZE_T)Vcb; } RC = UDFPhReadSynchronous(IrpContext, Vcb->TargetDeviceObject, Buffer, Length, - ((uint64)rLba) << Vcb->BlockSizeBits, ReadBytes, Flags); + ((uint64)rLba) << Vcb->SectorShift, ReadBytes, Flags); Vcb->VcbState &= ~UDF_VCB_LAST_WRITE; -#ifdef _BROWSE_UDF_ Vcb->VcbState |= UDF_VCB_SKIP_EJECT_CHECK; -#endif //_BROWSE_UDF_ if (!NT_SUCCESS(RC) && NT_SUCCESS(RC = UDFRecoverFromError(Vcb, FALSE, RC, rLba, BCount, &retry)) ) { if (RC != STATUS_BUFFER_ALL_ZEROS) { @@ -687,7 +654,7 @@ UDFTRead( (*ReadBytes) = Length; RC = STATUS_SUCCESS; } -#ifdef _BROWSE_UDF_ + try_return(RC); } // read according to relocation table @@ -700,17 +667,17 @@ UDFTRead( RC = STATUS_SUCCESS; goto TR_continue; } - BCount = RelocExtent->extLength>>Vcb->BlockSizeBits; + BCount = RelocExtent->extLength>>Vcb->SectorShift; retry = UDF_WRITE_MAX_RETRY; retry_2: - RC = UDFPrepareForReadOperation(IrpContext, Vcb, rLba, RelocExtent->extLength >> Vcb->BlockSizeBits); + RC = UDFPrepareForReadOperation(IrpContext, Vcb, rLba, RelocExtent->extLength >> Vcb->SectorShift); if (!NT_SUCCESS(RC)) break; rLba = UDFFixFPAddress(Vcb, rLba); if (Flags & PH_VCB_IN_RETLEN) { _ReadBytes = (SIZE_T)Vcb; } RC = UDFPhReadSynchronous(IrpContext, Vcb->TargetDeviceObject, Buffer, RelocExtent->extLength, - ((uint64)rLba) << Vcb->BlockSizeBits, &_ReadBytes, Flags); + ((uint64)rLba) << Vcb->SectorShift, &_ReadBytes, Flags); Vcb->VcbState &= ~UDF_VCB_LAST_WRITE; Vcb->VcbState |= UDF_VCB_SKIP_EJECT_CHECK; if (!NT_SUCCESS(RC) && @@ -736,7 +703,7 @@ try_exit: NOTHING; MyFreePool__(RelocExtent_saved); } } _SEH2_END; -#endif //_BROWSE_UDF_ + return RC; } // end UDFTRead() @@ -861,7 +828,6 @@ UDFPrepareForWriteOperation( return STATUS_SUCCESS; } // end UDFPrepareForWriteOperation() -//#ifdef _BROWSE_UDF_ /* This routine tries to recover from hardware error Return: STATUS_SUCCESS - retry requst @@ -881,16 +847,16 @@ UDFRecoverFromError( } // end UDFRecoverFromError() -//#endif //_BROWSE_UDF_ - /* use standard way to determine disk layout (ReadTOC cmd) */ NTSTATUS -UDFUseStandard( +UDFDetermineVolumeLayout( PIRP_CONTEXT IrpContext, - PDEVICE_OBJECT DeviceObject, // the target device object - PVCB Vcb // Volume control block from this DevObj + PDEVICE_OBJECT DeviceObject, + PVCB Vcb, + PULONG SessionStart, + PULONG SessionEnd ) { NTSTATUS RC = STATUS_SUCCESS; @@ -899,11 +865,9 @@ UDFUseStandard( uint32 LocalTrackCount; uint32 TocEntry; void* TempBuffer = NULL; -#ifdef _BROWSE_UDF_ uint32 OldTrkNum; uint32 TrkNum; SIZE_T ReadBytes, i, len; -#endif //_BROWSE_UDF_ UDFPrint(("UDFUseStandard\n")); @@ -912,6 +876,7 @@ UDFUseStandard( if (!toc || !LastSes) { try_return (RC = STATUS_INSUFFICIENT_RESOURCES); } + RtlZeroMemory(toc, sizeof(CDROM_TOC_LARGE)); CDROM_READ_TOC_EX Command; @@ -958,11 +923,10 @@ UDFUseStandard( Vcb->TrackMap[1].LastLba = Vcb->LastLBA; Vcb->TrackMap[1].PacketSize = PACKETSIZE_UDF; -#ifdef _BROWSE_UDF_ - if (UDFGetDevType(DeviceObject) == FILE_DEVICE_DISK) { - try_return(RC = STATUS_SUCCESS); - } -#endif //_BROWSE_UDF_ + + if (UDFGetDevType(DeviceObject) == FILE_DEVICE_DISK) { + try_return(RC = STATUS_SUCCESS); + } Vcb->LastPossibleLBA = max(Vcb->LastLBA, DEFAULT_LAST_LBA_FP_CD); Vcb->TrackMap[1].DataParam = TrkInfo_Dat_XA | TrkInfo_FP | TrkInfo_Packet; @@ -979,7 +943,6 @@ UDFUseStandard( try_return(RC = STATUS_DISK_CORRUPT_ERROR); } -#ifdef _BROWSE_UDF_ Vcb->LastTrackNum = toc->LastTrack; Vcb->FirstTrackNum = toc->FirstTrack; // some devices report LastTrackNum=0 for full disks @@ -1099,15 +1062,15 @@ UDFUseStandard( // be unreadable. We should forget about them, because UDF needs // last _readable_ sector. - TempBuffer = MyAllocatePool__(NonPagedPool, Vcb->BlockSize); + TempBuffer = MyAllocatePool__(NonPagedPool, Vcb->SectorSize); if (!TempBuffer) { return STATUS_INSUFFICIENT_RESOURCES; } while(!NT_SUCCESS(RC) && (i<8)) { - RC = UDFPhReadSynchronous(IrpContext, Vcb->TargetDeviceObject, TempBuffer, Vcb->BlockSize, - ((uint64)(Vcb->TrackMap[TrkNum].LastLba-i)) << Vcb->BlockSizeBits, &ReadBytes, PH_TMP_BUFFER); + RC = UDFPhReadSynchronous(IrpContext, Vcb->TargetDeviceObject, TempBuffer, Vcb->SectorSize, + ((uint64)(Vcb->TrackMap[TrkNum].LastLba-i)) << Vcb->SectorShift, &ReadBytes, PH_TMP_BUFFER); i++; } if (NT_SUCCESS(RC)) { @@ -1127,8 +1090,8 @@ UDFUseStandard( len = (uint32)(((int64)len*PACKETSIZE_UDF) / (PACKETSIZE_UDF+7)); while(!NT_SUCCESS(RC) && (i<9)) { - RC = UDFPhReadSynchronous(IrpContext, Vcb->TargetDeviceObject, TempBuffer, Vcb->BlockSize, - ((uint64)(Vcb->TrackMap[TrkNum].FirstLba-i+len)) << Vcb->BlockSizeBits, &ReadBytes, PH_TMP_BUFFER); + RC = UDFPhReadSynchronous(IrpContext, Vcb->TargetDeviceObject, TempBuffer, Vcb->SectorSize, + ((uint64)(Vcb->TrackMap[TrkNum].FirstLba-i+len)) << Vcb->SectorShift, &ReadBytes, PH_TMP_BUFFER); i++; } if (NT_SUCCESS(RC)) { @@ -1151,29 +1114,6 @@ UDFUseStandard( Vcb->NWA = Vcb->LastLBA+7+1; #endif //UDF_CDRW_EMULATION_ON_ROM -#else //_BROWSE_UDF_ - - Vcb->FirstTrackNum=toc->Tracks.Last_TrackSes; - Vcb->LastTrackNum=toc->Tracks.First_TrackSes; - - // Scan toc for first & last LBA - for(TocEntry=0;TocEntryTrackData[TocEntry].LBA - if (Vcb->FirstTrackNum == toc->TrackData[TocEntry].TrackNum) { - Vcb->FirstLBA = MSF_TO_LBA(TempMSF[1],TempMSF[2],TempMSF[3]); - if (Vcb->FirstLBA & 0x80000000) { - Vcb->FirstLBA = 0; - } - } - if (TOC_LastTrack_ID == toc->TrackData[TocEntry].TrackNum) { - Vcb->LastLBA = MSF_TO_LBA(TempMSF[1],TempMSF[2],TempMSF[3])-1; - } -#undef TempMSF - } - -// Vcb->LastLBA=PacketVariable2Fixed(Vcb->LastLBA)-2; - Vcb->LastPossibleLBA = DEFAULT_LAST_LBA_FP_CD; -#endif //_BROWSE_UDF_ try_exit: NOTHING; } _SEH2_FINALLY { if (toc) MyFreePool__(toc); @@ -1197,14 +1137,13 @@ UDFGetBlockSize( DISK_GEOMETRY_EX DiskGeometryEx; PARTITION_INFORMATION PartitionInfo; -#ifdef _BROWSE_UDF_ if (UDFGetDevType(DeviceObject) == FILE_DEVICE_DISK) { UDFPrint(("UDFGetBlockSize: HDD\n")); RC = UDFPhSendIOCTL(IOCTL_DISK_GET_DRIVE_GEOMETRY_EX,DeviceObject, 0,NULL, &DiskGeometryEx,sizeof(DISK_GEOMETRY_EX), TRUE,NULL ); - Vcb->BlockSize = (NT_SUCCESS(RC)) ? DiskGeometryEx.Geometry.BytesPerSector : 512; + Vcb->SectorSize = (NT_SUCCESS(RC)) ? DiskGeometryEx.Geometry.BytesPerSector : 512; if (!NT_SUCCESS(RC)) try_return(RC); RC = UDFPhSendIOCTL(IOCTL_DISK_GET_PARTITION_INFO,DeviceObject, @@ -1233,33 +1172,15 @@ UDFGetBlockSize( try_return(RC); } - Vcb->BlockSize = (NT_SUCCESS(RC)) ? DiskGeometryEx.Geometry.BytesPerSector : 2048; - } - -#endif //_BROWSE_UDF_ - - // Block size must be an even multiple of 512 - switch (Vcb->BlockSize) { - case 2048: Vcb->BlockSizeBits = 11; break; - case 512: Vcb->BlockSizeBits = 9; break; - case 1024: Vcb->BlockSizeBits = 10; break; - case 4096: Vcb->BlockSizeBits = 12; break; - case 8192: Vcb->BlockSizeBits = 13; break; - default: - { - UserPrint(("UDF: Bad block size (%ld)\n", Vcb->BlockSize)); - try_return(RC = STATUS_UNSUCCESSFUL); - } + Vcb->SectorSize = (NT_SUCCESS(RC)) ? DiskGeometryEx.Geometry.BytesPerSector : 2048; } if ( -#ifdef _BROWSE_UDF_ UDFGetDevType(DeviceObject) == FILE_DEVICE_DISK || -#endif //_BROWSE_UDF_ FALSE) { Vcb->FirstLBA=0;//(ULONG)(PartitionInfo->StartingOffset.QuadPart >> Vcb->BlockSizeBits); Vcb->LastPossibleLBA = - Vcb->LastLBA = (uint32)(DiskGeometryEx.DiskSize.QuadPart >> Vcb->BlockSizeBits)/* + Vcb->FirstLBA*/ - 1; + Vcb->LastLBA = (uint32)(DiskGeometryEx.DiskSize.QuadPart >> Vcb->SectorShift)/* + Vcb->FirstLBA*/ - 1; } else { Vcb->FirstLBA=0; if (NT_SUCCESS(RC)) { @@ -1275,33 +1196,23 @@ UDFGetBlockSize( Vcb->LastPossibleLBA = Vcb->LastLBA; } -#ifdef _BROWSE_UDF_ // if (UDFGetDevType(DeviceObject) == FILE_DEVICE_DISK) { - Vcb->WriteBlockSize = PACKETSIZE_UDF*Vcb->BlockSize; + Vcb->WriteBlockSize = PACKETSIZE_UDF*Vcb->SectorSize; // } else { // Vcb->WriteBlockSize = PACKETSIZE_UDF*Vcb->BlockSize; // } -#else //_BROWSE_UDF_ - if (fms->opt_media == MT_HD) { - Vcb->WriteBlockSize = Vcb->BlockSize; - } else { - Vcb->WriteBlockSize = PACKETSIZE_UDF*Vcb->BlockSize; - } -#endif //_BROWSE_UDF_ RC = STATUS_SUCCESS; try_exit: NOTHING; UDFPrint(("UDFGetBlockSize:\nBlock size is %x, Block size bits %x, Last LBA is %x\n", - Vcb->BlockSize, Vcb->BlockSizeBits, Vcb->LastLBA)); + Vcb->SectorSize, Vcb->SectorShift, Vcb->LastLBA)); return RC; } // end UDFGetBlockSize() -#ifdef _BROWSE_UDF_ - uint32 UDFFixFPAddress( IN PVCB Vcb, // Volume control block from this DevObj @@ -1312,14 +1223,7 @@ UDFFixFPAddress( uint32 pk; uint32 rel; -// if (Vcb->CompatFlags & UDF_VCB_IC_MRW_ADDR_PROBLEM) { - if (Vcb->TrackMap[i].Flags & TrackMap_FixMRWAddressing) { - pk = Lba / MRW_DA_SIZE; - rel = Lba % MRW_DA_SIZE; - Lba = pk*MRW_DMA_SEGMENT_SIZE + rel; - Lba += MRW_DMA_OFFSET; - } - if (Vcb->TrackMap[i].Flags & TrackMap_FixFPAddressing) { + if(FlagOn(Vcb->VcbState, VCB_STATE_PACKET_RUNOUT_FIXUP)) { if (Lba < 0x20) return Lba; pk = Lba / Vcb->TrackMap[i].PacketSize; @@ -1330,8 +1234,6 @@ UDFFixFPAddress( return Lba; } // end UDFFixFPAddress() -#endif //_BROWSE_UDF_ - /* detect device driver & try to read disk layout (use all methods) */ @@ -1354,7 +1256,10 @@ UDFGetDiskInfo( try_return(RC); } - RC = UDFUseStandard(IrpContext, DeviceObject, Vcb); + ULONG SessionStart; + ULONG SessionEnd; + + RC = UDFDetermineVolumeLayout(IrpContext, DeviceObject, Vcb, &SessionStart, &SessionEnd); if (!NT_SUCCESS(RC)) { try_return(RC); @@ -1369,9 +1274,8 @@ try_exit: NOTHING; Vcb->LastPossibleLBA = Vcb->LastLBA; } if (!Vcb->WriteBlockSize) - Vcb->WriteBlockSize = PACKETSIZE_UDF*Vcb->BlockSize; + Vcb->WriteBlockSize = PACKETSIZE_UDF*Vcb->SectorSize; -#ifdef _BROWSE_UDF_ if (Vcb->TrackMap) { if (Vcb->TrackMap[Vcb->LastTrackNum].LastLba > Vcb->NWA) { if (Vcb->NWA) { @@ -1398,8 +1302,6 @@ try_exit: NOTHING; Vcb->WCacheBlocksPerFrameSh = min(Vcb->WCacheBlocksPerFrameSh, 16); } -#endif //_BROWSE_UDF_ - if (Vcb->VcbState & VCB_STATE_VOLUME_READ_ONLY) { if (!Vcb->BlankCD && Vcb->MediaType != MediaType_UnknownSize_CDRW) { UDFPrint(("UDFGetDiskInfo: R/O+!Blank+!RW -> !RAW\n")); @@ -1434,8 +1336,6 @@ try_exit: NOTHING; } // end UDFGetDiskInfo() -//#ifdef _BROWSE_UDF_ - NTSTATUS UDFPrepareForReadOperation( IN PIRP_CONTEXT IrpContext, @@ -1449,11 +1349,9 @@ UDFPrepareForReadOperation( return STATUS_SUCCESS; } uint32 i = Vcb->LastReadTrack; -#ifdef _BROWSE_UDF_ PUCHAR tmp; NTSTATUS RC; SIZE_T ReadBytes; -#endif //_BROWSE_UDF_ #ifdef _UDF_STRUCTURES_H_ if (Vcb->BSBM_Bitmap) { @@ -1469,8 +1367,6 @@ UDFPrepareForReadOperation( } #endif //_UDF_STRUCTURES_H_ -#ifdef _BROWSE_UDF_ - if (UDFIsDvdMedia(Vcb)) return STATUS_SUCCESS; @@ -1505,24 +1401,21 @@ UDFPrepareForReadOperation( UDFPrint((" UDFPrepareForReadOperation: seek workaround...\n")); Vcb->IncrementalSeekState = INCREMENTAL_SEEK_DONE; - tmp = (PUCHAR)DbgAllocatePoolWithTag(NonPagedPool, Vcb->BlockSize, 'bNWD'); + tmp = (PUCHAR)DbgAllocatePoolWithTag(NonPagedPool, Vcb->SectorSize, 'bNWD'); if (!tmp) { Vcb->IncrementalSeekState = INCREMENTAL_SEEK_NONE; return STATUS_INSUFFICIENT_RESOURCES; } for(i=0x1000; i<=Lba; i+=0x1000) { - RC = UDFPhReadSynchronous(IrpContext, Vcb->TargetDeviceObject, tmp, Vcb->BlockSize, - ((uint64)UDFFixFPAddress(Vcb,i)) << Vcb->BlockSizeBits, &ReadBytes, 0); + RC = UDFPhReadSynchronous(IrpContext, Vcb->TargetDeviceObject, tmp, Vcb->SectorSize, + ((uint64)UDFFixFPAddress(Vcb,i)) << Vcb->SectorShift, &ReadBytes, 0); UDFPrint((" seek workaround, LBA %x, status %x\n", i, RC)); } DbgFreePool(tmp); -#endif //_BROWSE_UDF_ return STATUS_SUCCESS; } // end UDFPrepareForReadOperation() -//#endif //_BROWSE_UDF_ - /* This routine reads physical sectors */ @@ -1541,11 +1434,9 @@ UDFReadSectors( if (Vcb->FastCache.ReadProc && (KeGetCurrentIrql() < DISPATCH_LEVEL)) { return WCacheReadBlocks__(IrpContext, &Vcb->FastCache, Vcb, Buffer, Lba, BCount, ReadBytes, Direct); } - return UDFTRead(IrpContext, Vcb, Buffer, BCount*Vcb->BlockSize, Lba, ReadBytes); + return UDFTRead(IrpContext, Vcb, Buffer, BCount*Vcb->SectorSize, Lba, ReadBytes); } // end UDFReadSectors() -#ifdef _BROWSE_UDF_ - /* This routine reads physical sectors */ @@ -1578,7 +1469,7 @@ UDFReadInSector( if (Direct) { return STATUS_INVALID_PARAMETER; } - tmp_buff = (int8*)MyAllocatePool__(NonPagedPool, Vcb->BlockSize); + tmp_buff = (int8*)MyAllocatePool__(NonPagedPool, Vcb->SectorSize); if (!tmp_buff) return STATUS_INSUFFICIENT_RESOURCES; status = UDFReadSectors(IrpContext, Vcb, Translate, Lba, 1, FALSE, tmp_buff, &_ReadBytes); if (NT_SUCCESS(status)) { @@ -1605,8 +1496,8 @@ UDFReadData( OUT PSIZE_T ReadBytes ) { - uint32 i, l, Lba, BS=Vcb->BlockSize; - uint32 BSh=Vcb->BlockSizeBits; + uint32 i, l, Lba, BS=Vcb->SectorSize; + uint32 BSh=Vcb->SectorShift; NTSTATUS status; SIZE_T _ReadBytes = 0; Vcb->VcbState |= UDF_VCB_SKIP_EJECT_CHECK; @@ -1650,8 +1541,6 @@ UDFReadData( return status; } // end UDFReadData() -#endif //_BROWSE_UDF_ - /* This routine writes physical sectors. This routine supposes Lba & Length alignment on WriteBlock (packet) size. @@ -1670,7 +1559,6 @@ UDFWriteSectors( { NTSTATUS status; -#ifdef _BROWSE_UDF_ if (!Vcb->Modified || (Vcb->IntegrityType == INTEGRITY_TYPE_CLOSE)) { UDFSetModified(Vcb); if (Vcb->LVid && !Direct) { @@ -1682,22 +1570,17 @@ UDFWriteSectors( if (Vcb->LastLBA < Lba+BCount-1) Vcb->LastLBA = Lba+BCount-1; } -#endif //_BROWSE_UDF_ if (Vcb->FastCache.WriteProc && (KeGetCurrentIrql() < DISPATCH_LEVEL)) { status = WCacheWriteBlocks__(IrpContext, &Vcb->FastCache, Vcb, Buffer, Lba, BCount, WrittenBytes, Direct); ASSERT(NT_SUCCESS(status)); -#ifdef _BROWSE_UDF_ - UDFClrZeroBits(Vcb->ZSBM_Bitmap, Lba, BCount); -#endif //_BROWSE_UDF_ + return status; } - status = UDFTWrite(IrpContext, Vcb, Buffer, BCount<BlockSizeBits, Lba, WrittenBytes); + status = UDFTWrite(IrpContext, Vcb, Buffer, BCount<SectorShift, Lba, WrittenBytes); ASSERT(NT_SUCCESS(status)); -#ifdef _BROWSE_UDF_ - UDFClrZeroBits(Vcb->ZSBM_Bitmap, Lba, BCount); -#endif //_BROWSE_UDF_ + return status; } // end UDFWriteSectors() @@ -1716,7 +1599,6 @@ UDFWriteInSector( { int8* tmp_buff; NTSTATUS status; -#ifdef _BROWSE_UDF_ SIZE_T _WrittenBytes; SIZE_T ReadBytes; @@ -1730,29 +1612,25 @@ UDFWriteInSector( if (Vcb->LastLBA < Lba) Vcb->LastLBA = Lba; } -#endif //_BROWSE_UDF_ (*WrittenBytes) = 0; -#ifdef _BROWSE_UDF_ + if (Vcb->FastCache.WriteProc && (KeGetCurrentIrql() < DISPATCH_LEVEL)) { -#endif //_BROWSE_UDF_ + status = WCacheDirect__(IrpContext, &Vcb->FastCache, Vcb, Lba, TRUE, &tmp_buff, Direct); if (NT_SUCCESS(status)) { -#ifdef _BROWSE_UDF_ - UDFClrZeroBit(Vcb->ZSBM_Bitmap, Lba); -#endif //_BROWSE_UDF_ + (*WrittenBytes) += l; RtlCopyMemory(tmp_buff+i, Buffer, l); } if (!Direct) WCacheEODirect__(&(Vcb->FastCache), Vcb); -#ifdef _BROWSE_UDF_ } else { // If Direct = TRUE we should never get here, but... if (Direct) { BrutePoint(); return STATUS_INVALID_PARAMETER; } - tmp_buff = (int8*)MyAllocatePool__(NonPagedPool, Vcb->BlockSize); + tmp_buff = (int8*)MyAllocatePool__(NonPagedPool, Vcb->SectorSize); if (!tmp_buff) { BrutePoint(); return STATUS_INSUFFICIENT_RESOURCES; @@ -1773,7 +1651,7 @@ UDFWriteInSector( if (!NT_SUCCESS(status)) { UDFPrint(("UDFWriteInSector() for LBA %x failed\n", Lba)); } -#endif //_BROWSE_UDF_ + return status; } // end UDFWriteInSector() @@ -1793,8 +1671,8 @@ UDFWriteData( OUT PSIZE_T WrittenBytes ) { - uint32 i, l, Lba, BS=Vcb->BlockSize; - uint32 BSh=Vcb->BlockSizeBits; + uint32 i, l, Lba, BS=Vcb->SectorSize; + uint32 BSh=Vcb->SectorShift; NTSTATUS status; SIZE_T _WrittenBytes; Vcb->VcbState |= UDF_VCB_SKIP_EJECT_CHECK; @@ -1821,18 +1699,13 @@ UDFWriteData( (*WrittenBytes) += _WrittenBytes; if (!NT_SUCCESS(status)) return status; l = i<ZSBM_Bitmap, Lba, i); -#endif //_BROWSE_UDF_ + if (!(Length = Length - l)) return STATUS_SUCCESS; Lba += i; Buffer += l; } status = UDFWriteInSector(IrpContext, Vcb, Translate, Lba, 0, Length, Direct, Buffer, &_WrittenBytes); (*WrittenBytes) += _WrittenBytes; -#ifdef _BROWSE_UDF_ - UDFClrZeroBit(Vcb->ZSBM_Bitmap, Lba); -#endif //_BROWSE_UDF_ return status; } // end UDFWriteData() diff --git a/drivers/filesystems/udfs/Include/phys_lib.h b/drivers/filesystems/udfs/Include/phys_lib.h index 975877f598cc4..ce71d63482975 100644 --- a/drivers/filesystems/udfs/Include/phys_lib.h +++ b/drivers/filesystems/udfs/Include/phys_lib.h @@ -82,10 +82,12 @@ extern NTSTATUS UDFPrepareForWriteOperation( IN ULONG BCount); NTSTATUS -UDFUseStandard( +UDFDetermineVolumeLayout( PIRP_CONTEXT IrpContext, - PDEVICE_OBJECT DeviceObject, // the target device object - PVCB Vcb // Volume control block fro this DevObj + PDEVICE_OBJECT DeviceObject, + PVCB Vcb, + PULONG SessionStart, + PULONG SessionEnd ); extern NTSTATUS UDFGetBlockSize(PDEVICE_OBJECT DeviceObject, // the target device object diff --git a/drivers/filesystems/udfs/Include/udf_reg.h b/drivers/filesystems/udfs/Include/udf_reg.h index f0a3252b01bb4..88f6cbffc0472 100644 --- a/drivers/filesystems/udfs/Include/udf_reg.h +++ b/drivers/filesystems/udfs/Include/udf_reg.h @@ -12,7 +12,6 @@ #define UDF_FS_TITLE_BLANK L"Blank media" #define UDF_BLANK_VOLUME_LABEL L"Blank CD" -#define REG_USEEXTENDEDFE_NAME L"UseExtendedFE" #define REG_DEFALLOCMODE_NAME L"DefaultAllocMode" #define UDF_DIR_PACK_THRESHOLD_NAME L"PackDirThreshold" #define UDF_FE_CHARGE_NAME L"FECharge" @@ -35,14 +34,9 @@ #define UDF_INSTANT_COMPAT_ALLOC_DESCS L"AllocDescCompatInstantBurner" #define UDF_HANDLE_HW_RO L"HandleHWReadOnly" #define UDF_HANDLE_SOFT_RO L"HandleSoftReadOnly" -#define UDF_COMPARE_BEFORE_WRITE L"CompareBeforeWrite" #define UDF_CACHE_SIZE_MULTIPLIER L"WCacheSizeMultiplier" -#define UDF_CHAINED_IO L"CacheChainedIo" -#define UDF_FORCE_HW_RO L"ForceHWReadOnly" #define UDF_IGNORE_SEQUENTIAL_IO L"IgnoreSequantialIo" -#define UDF_PART_DAMAGED_BEHAVIOR L"PartitialDamagedVolumeAction" #define UDF_NO_SPARE_BEHAVIOR L"NoFreeRelocationSpaceVolumeAction" #define UDF_DIRTY_VOLUME_BEHAVIOR L"DirtyVolumeVolumeAction" -#define UDF_SHOW_BLANK_CD L"ShowBlankCd" #endif //__DWUDF_REGISTRY__H__ diff --git a/drivers/filesystems/udfs/cleanup.cpp b/drivers/filesystems/udfs/cleanup.cpp index 029e264d8401c..22788214d386c 100644 --- a/drivers/filesystems/udfs/cleanup.cpp +++ b/drivers/filesystems/udfs/cleanup.cpp @@ -26,70 +26,6 @@ UDFAutoUnlock ( IN PVCB Vcb ); -/************************************************************************* -* -* Function: UDFCleanup() -* -* Description: -* The I/O Manager will invoke this routine to handle a cleanup -* request -* -* Expected Interrupt Level (for execution) : -* -* IRQL_PASSIVE_LEVEL (invocation at higher IRQL will cause execution -* to be deferred to a worker thread context) -* -* Return Value: STATUS_SUCCESS -* -*************************************************************************/ -NTSTATUS -NTAPI -UDFCleanup( - PDEVICE_OBJECT DeviceObject, // the logical volume device object - PIRP Irp // I/O Request Packet - ) -{ - NTSTATUS RC = STATUS_SUCCESS; - PIRP_CONTEXT IrpContext = NULL; - BOOLEAN AreWeTopLevel = FALSE; - - TmPrint(("UDFCleanup\n")); - - FsRtlEnterFileSystem(); - ASSERT(DeviceObject); - ASSERT(Irp); - - // set the top level context - AreWeTopLevel = UDFIsIrpTopLevel(Irp); - - _SEH2_TRY { - - // get an IRP context structure and issue the request - IrpContext = UDFCreateIrpContext(Irp, DeviceObject); - if (IrpContext) { - RC = UDFCommonCleanup(IrpContext, Irp); - } else { - - UDFCompleteRequest(IrpContext, Irp, STATUS_INSUFFICIENT_RESOURCES); - RC = STATUS_INSUFFICIENT_RESOURCES; - } - - } _SEH2_EXCEPT(UDFExceptionFilter(IrpContext, _SEH2_GetExceptionInformation())) { - - RC = UDFProcessException(IrpContext, Irp); - - UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC); - } _SEH2_END; - - if (AreWeTopLevel) { - IoSetTopLevelIrp(NULL); - } - - FsRtlExitFileSystem(); - - return(RC); -} // end UDFCleanup() - /************************************************************************* * * Function: UDFCommonCleanup() @@ -217,7 +153,7 @@ UDFCommonCleanup( if (FileObject->Flags & FO_CACHE_SUPPORTED) { // we've cached close - UDFInterlockedDecrement((PLONG)&(Fcb->CachedOpenHandleCount)); + InterlockedDecrement((PLONG)&Fcb->CachedOpenHandleCount); } ASSERT(Fcb->FcbCleanup <= (Fcb->FcbReference-1)); @@ -259,7 +195,7 @@ UDFCommonCleanup( if (FileObject->Flags & FO_CACHE_SUPPORTED) { // we've cached close - UDFInterlockedDecrement((PLONG)&Fcb->CachedOpenHandleCount); + InterlockedDecrement((PLONG)&Fcb->CachedOpenHandleCount); } ASSERT(Fcb->FcbCleanup <= (Fcb->FcbReference-1)); @@ -272,7 +208,7 @@ UDFCommonCleanup( FileObject->DeletePending = TRUE; // Report this to the dir notify package for a directory. if (Fcb->FcbState & UDF_FCB_DIRECTORY) { - FsRtlNotifyFullChangeDirectory( Vcb->NotifyIRPMutex, &(Vcb->NextNotifyIRP), + FsRtlNotifyFullChangeDirectory( Vcb->NotifySync, &(Vcb->NextNotifyIRP), (PVOID)Ccb, NULL, FALSE, FALSE, 0, NULL, NULL, NULL ); } @@ -471,7 +407,7 @@ UDFCommonCleanup( if (Fcb->FcbState & UDF_FCB_DIRECTORY) { // Report to the dir notify package for a directory. - FsRtlNotifyCleanup( Vcb->NotifyIRPMutex, &(Vcb->NextNotifyIRP), (PVOID)Ccb ); + FsRtlNotifyCleanup( Vcb->NotifySync, &(Vcb->NextNotifyIRP), (PVOID)Ccb ); } // we can't purge Cache when more than one link exists diff --git a/drivers/filesystems/udfs/close.cpp b/drivers/filesystems/udfs/close.cpp index 193a7ca3c8ac1..664f54f599dbf 100644 --- a/drivers/filesystems/udfs/close.cpp +++ b/drivers/filesystems/udfs/close.cpp @@ -49,69 +49,6 @@ UDFQueueClose( UDFFreePool(&Pool); \ } -/************************************************************************* -* -* Function: UDFClose() -* -* Description: -* The I/O Manager will invoke this routine to handle a close -* request -* -* Expected Interrupt Level (for execution) : -* -* IRQL_PASSIVE_LEVEL (invocation at higher IRQL will cause execution -* to be deferred to a worker thread context) -* -* Return Value: STATUS_SUCCESS -* -*************************************************************************/ -NTSTATUS -NTAPI -UDFClose( - PDEVICE_OBJECT DeviceObject, // the logical volume device object - PIRP Irp // I/O Request Packet - ) -{ - NTSTATUS RC = STATUS_SUCCESS; - PIRP_CONTEXT IrpContext = NULL; - BOOLEAN AreWeTopLevel = FALSE; - - AdPrint(("UDFClose: \n")); - - FsRtlEnterFileSystem(); - ASSERT(DeviceObject); - ASSERT(Irp); - - // set the top level context - AreWeTopLevel = UDFIsIrpTopLevel(Irp); - - _SEH2_TRY { - - // get an IRP context structure and issue the request - IrpContext = UDFCreateIrpContext(Irp, DeviceObject); - ASSERT(IrpContext); - - RC = UDFCommonClose(IrpContext, Irp); - - } _SEH2_EXCEPT(UDFExceptionFilter(IrpContext, _SEH2_GetExceptionInformation())) { - - RC = UDFProcessException(IrpContext, Irp); - - UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC); - } _SEH2_END; - - if (AreWeTopLevel) { - IoSetTopLevelIrp(NULL); - } - - FsRtlExitFileSystem(); - - return(RC); -} - - - - /************************************************************************* * * Function: UDFCommonClose() @@ -218,9 +155,9 @@ UDFCommonClose( // Close request is near completion, Vcb is acquired. // Now we can safely decrease CcbCount, because no Rename // operation can run until Vcb release. - InterlockedDecrement((PLONG)&(Fcb->CcbCount)); + InterlockedDecrement((PLONG)&Fcb->CcbCount); - UDFInterlockedDecrement((PLONG)&(Vcb->VcbReference)); + InterlockedDecrement((PLONG)&Vcb->VcbReference); if (!i || (Fcb == Fcb->Vcb->VolumeDasdFcb)) { @@ -229,14 +166,14 @@ UDFCommonClose( if (Vcb->VcbCleanup > 0) { ASSERT(Fcb == Fcb->Vcb->VolumeDasdFcb); - UDFInterlockedDecrement((PLONG)&Fcb->FcbReference); + InterlockedDecrement((PLONG)&Fcb->FcbReference); ASSERT(Fcb); try_return(RC = STATUS_SUCCESS); } ASSERT(Fcb == Fcb->Vcb->VolumeDasdFcb); - UDFInterlockedDecrement((PLONG)&Fcb->FcbReference); + InterlockedDecrement((PLONG)&Fcb->FcbReference); ASSERT(Fcb); if ((Vcb->VcbCleanup == 0) && @@ -374,7 +311,7 @@ UDFTeardownStructures( if (CurrentFcb) { if (TreeLength) { ASSERT(CurrentFcb->FcbReference); - RefCount = UDFInterlockedDecrement((PLONG)&CurrentFcb->FcbReference); + RefCount = InterlockedDecrement((PLONG)&CurrentFcb->FcbReference); } } else { BrutePoint(); @@ -384,7 +321,7 @@ UDFTeardownStructures( ASSERT(CurrentFcb->FcbCleanup <= CurrentFcb->FcbReference); #else if (TreeLength) { - RefCount = UDFInterlockedDecrement((PLONG)&CurrentFcb->FcbReference); + RefCount = InterlockedDecrement((PLONG)&CurrentFcb->FcbReference); TreeLength--; } #endif diff --git a/drivers/filesystems/udfs/create.cpp b/drivers/filesystems/udfs/create.cpp index c12eea6c27a72..a72893b61512f 100644 --- a/drivers/filesystems/udfs/create.cpp +++ b/drivers/filesystems/udfs/create.cpp @@ -41,72 +41,6 @@ UDFNormalizeFileNames( _Inout_ PUNICODE_STRING RemainingName ); -/************************************************************************* -* -* Function: UDFCreate() -* -* Description: -* The I/O Manager will invoke this routine to handle a create/open -* request -* -* Expected Interrupt Level (for execution) : -* -* IRQL_PASSIVE_LEVEL (invocation at higher IRQL will cause execution -* to be deferred to a worker thread context) -* -* Return Value: STATUS_SUCCESS/Error -* -*************************************************************************/ -NTSTATUS -NTAPI -UDFCreate( - PDEVICE_OBJECT DeviceObject, // the logical volume device object - PIRP Irp) // I/O Request Packet -{ - NTSTATUS RC = STATUS_SUCCESS; - PIRP_CONTEXT IrpContext = NULL; - BOOLEAN AreWeTopLevel = FALSE; - - TmPrint(("UDFCreate:\n")); - - FsRtlEnterFileSystem(); - ASSERT(DeviceObject); - ASSERT(Irp); - - // set the top level context - AreWeTopLevel = UDFIsIrpTopLevel(Irp); - - _SEH2_TRY { - - // get an IRP context structure and issue the request - IrpContext = UDFCreateIrpContext(Irp, DeviceObject); - if (IrpContext) { - RC = UDFCommonCreate(IrpContext, Irp); - } else { - - UDFCompleteRequest(IrpContext, Irp, STATUS_INSUFFICIENT_RESOURCES); - RC = STATUS_INSUFFICIENT_RESOURCES; - } - - } _SEH2_EXCEPT(UDFExceptionFilter(IrpContext, _SEH2_GetExceptionInformation())) { - - RC = UDFProcessException(IrpContext, Irp); - - UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC); - } _SEH2_END; - - if (AreWeTopLevel) { - IoSetTopLevelIrp(NULL); - } - - AdPrint(("UDFCreate: %x\n", RC)); - - FsRtlExitFileSystem(); - - return(RC); - -} // end UDFCreate() - /* */ VOID @@ -151,7 +85,7 @@ UDFAcquireParent( UDF_CHECK_PAGING_IO_RESOURCE(RelatedFileInfo->Fcb); UDFAcquireResourceExclusive((*Res1) = &RelatedFileInfo->Fcb->FcbNonpaged->FcbResource, TRUE); - UDFInterlockedIncrement((PLONG)&RelatedFileInfo->Fcb->FcbReference); + InterlockedIncrement((PLONG)&RelatedFileInfo->Fcb->FcbReference); UDFReferenceFile__(RelatedFileInfo); ASSERT(RelatedFileInfo->Fcb->FcbReference >= RelatedFileInfo->RefCount); } // end UDFAcquireParent() @@ -435,7 +369,7 @@ UDFCommonCreate( // We must defer processing of this request since we could // block anytime while performing the create/open ... ASSERT(FALSE); - RC = UDFPostRequest(IrpContext, Irp); + RC = UDFFsdPostRequest(IrpContext, Irp); try_return(RC); } @@ -473,27 +407,6 @@ UDFCommonCreate( ASSERT(Vcb->VcbCondition == VcbMounted); - // We fail in the following cases for Read-Only volumes - // - Open a target directory. - // - Create a file. - if ( - ( - ((Vcb->origIntegrityType == INTEGRITY_TYPE_OPEN) && - (Vcb->CompatFlags & UDF_VCB_IC_DIRTY_RO)) || - (Vcb->VcbState & VCB_STATE_VOLUME_READ_ONLY) - ) && - (DeleteOnClose || - OpenTargetDirectory || - (CreateDisposition == FILE_CREATE) || - (CreateDisposition == FILE_OVERWRITE) || - (CreateDisposition == FILE_OVERWRITE_IF) || - (CreateDisposition == FILE_SUPERSEDE) || - AllocationSize) ) { - ReturnedInformation = 0; - AdPrint((" Write protected or dirty\n")); - try_return(RC = STATUS_MEDIA_WRITE_PROTECTED); - } - // If we are opening this volume Dasd then process this immediately // and exit. @@ -573,7 +486,7 @@ UDFCommonCreate( IrpContext->Flags |= UDF_IRP_CONTEXT_FLUSH2_REQUIRED; /* - UDFInterlockedIncrement((PLONG)&(Vcb->VcbReference)); + InterlockedIncrement((PLONG)&Vcb->VcbReference); UDFReleaseResource(&(Vcb->VcbResource)); AcquiredVcb = FALSE; @@ -585,7 +498,7 @@ UDFCommonCreate( UDFAcquireResourceExclusive(&(Vcb->VcbResource), TRUE); AcquiredVcb = TRUE; - UDFInterlockedDecrement((PLONG)&(Vcb->VcbReference)); + InterlockedDecrement((PLONG)&Vcb->VcbReference); */ } } @@ -605,11 +518,11 @@ UDFCommonCreate( UDFPrint((" perform flush\n")); IrpContext->Flags &= ~UDF_IRP_CONTEXT_FLUSH2_REQUIRED; - UDFInterlockedIncrement((PLONG)&(Vcb->VcbReference)); + InterlockedIncrement((PLONG)&Vcb->VcbReference); UDFFspClose(Vcb); - UDFInterlockedDecrement((PLONG)&(Vcb->VcbReference)); + InterlockedDecrement((PLONG)&Vcb->VcbReference); UDFFlushVolume(IrpContext, Vcb); } @@ -731,7 +644,7 @@ UDFCommonCreate( // during I/O operations), this field is meaningless from // the FSD's perspective. if (!(NextFcb->FcbState & UDF_FCB_DIRECTORY)) { - if (UDFStreamsSupported(Vcb) && FileName->Length && (FileName->Buffer[0] == L':')) { + if (UDFIsStreamsSupported(Vcb) && FileName->Length && (FileName->Buffer[0] == L':')) { StreamTargetOpen = TRUE; } else { @@ -964,7 +877,7 @@ UDFCommonCreate( AdPrint((" Absolute path is not valid\n")); try_return(RC = STATUS_OBJECT_NAME_INVALID); } - if (StreamOpen && !UDFStreamsSupported(Vcb)) { + if (StreamOpen && !UDFIsStreamsSupported(Vcb)) { ReturnedInformation = FILE_DOES_NOT_EXIST; try_return(RC = STATUS_OBJECT_NAME_INVALID); } @@ -1206,7 +1119,7 @@ UDFCommonCreate( UDF_CHECK_PAGING_IO_RESOURCE(NewFileInfo->Fcb); UDFAcquireResourceExclusive(Res1 = &NewFileInfo->Fcb->FcbNonpaged->FcbResource, TRUE); // ...and reference it - UDFInterlockedIncrement((PLONG)&PtrNewFcb->FcbReference); + InterlockedIncrement((PLONG)&PtrNewFcb->FcbReference); ASSERT(PtrNewFcb->FcbReference >= NewFileInfo->RefCount); // update unwind information @@ -1315,7 +1228,7 @@ UDFCommonCreate( try_return(RC); } // discard changes for last successfully opened file - UDFInterlockedDecrement((PLONG)&PtrNewFcb->FcbReference); + InterlockedDecrement((PLONG)&PtrNewFcb->FcbReference); RC = STATUS_SUCCESS; ASSERT(!OpenTargetDirectory); // break open loop and continue with Open @@ -1379,7 +1292,7 @@ UDFCommonCreate( // to reflect the fact that the parent directory of the // target has been opened PtrNewFcb = NewFileInfo->Fcb; - UDFInterlockedDecrement((PLONG)&PtrNewFcb->FcbReference); + InterlockedDecrement((PLONG)&PtrNewFcb->FcbReference); RC = UDFCompleteFcbOpen(IrpContext, IrpSp, Vcb, &PtrNewFcb, UserDirectoryOpen, 0, CreateDisposition); @@ -1468,8 +1381,8 @@ UDFCommonCreate( RelatedFileInfo = OldRelatedFileInfo; RC = UDFCreateFile__(IrpContext, Vcb, IgnoreCase, &LastGoodTail, 0, 0, - Vcb->UseExtendedFE || (StreamOpen && !StreamExists), - (CreateDisposition == FILE_CREATE), RelatedFileInfo, &NewFileInfo); + UdfIsExtendedFESupported(Vcb), + (CreateDisposition == FILE_CREATE), RelatedFileInfo, &NewFileInfo); if (!NT_SUCCESS(RC)) { AdPrint((" Creation error\n")); Creation_Err_1: @@ -1566,7 +1479,7 @@ UDFCommonCreate( RC = MyAppendUnicodeStringToStringTag(&LocalPath, &LastGoodTail, MEM_USLOC_TAG); if (!NT_SUCCESS(RC)) goto Creation_Err_1; - UDFInterlockedIncrement((PLONG)&PtrNewFcb->FcbReference); + InterlockedIncrement((PLONG)&PtrNewFcb->FcbReference); ASSERT(PtrNewFcb->FcbReference >= NewFileInfo->RefCount); PtrNewFcb->NtReqFCBFlags |= UDF_NTREQ_FCB_VALID; PtrNewFcb->FcbState |= UDF_FCB_VALID; @@ -1619,7 +1532,7 @@ UDFCommonCreate( BrutePoint(); goto Creation_Err_1; } - UDFInterlockedIncrement((PLONG)&PtrNewFcb->FcbReference); + InterlockedIncrement((PLONG)&PtrNewFcb->FcbReference); ASSERT(PtrNewFcb->FcbReference >= NewFileInfo->RefCount); PtrNewFcb->NtReqFCBFlags |= UDF_NTREQ_FCB_VALID; PtrNewFcb->FcbState |= UDF_FCB_VALID; @@ -1629,7 +1542,7 @@ UDFCommonCreate( // create stream RelatedFileInfo = NewFileInfo; RC = UDFCreateFile__(IrpContext, Vcb, IgnoreCase, &StreamName, 0, 0, - Vcb->UseExtendedFE, (CreateDisposition == FILE_CREATE), + UdfIsExtendedFESupported(Vcb), (CreateDisposition == FILE_CREATE), RelatedFileInfo, &NewFileInfo); if (!NT_SUCCESS(RC)) { AdPrint((" Can't create Stream\n")); @@ -2049,13 +1962,13 @@ try_exit: NOTHING; UDFIncrementReferenceCounts(IrpContext, PtrNewFcb, 1, 1); if (FileObject->Flags & FO_CACHE_SUPPORTED) - UDFInterlockedIncrement((PLONG) & (PtrNewFcb->CachedOpenHandleCount)); + InterlockedIncrement((PLONG)&PtrNewFcb->CachedOpenHandleCount); UDFUnlockVcb(IrpContext, Vcb); if (FileObject->Flags & FO_CACHE_SUPPORTED) - UDFInterlockedIncrement((PLONG)&(PtrNewFcb->CachedOpenHandleCount)); + InterlockedIncrement((PLONG)&PtrNewFcb->CachedOpenHandleCount); // Store some flags in CCB if (PtrNewCcb) { PtrNewCcb->TreeLength = TreeLength; @@ -2080,7 +1993,7 @@ try_exit: NOTHING; // PtrNewCcb->CCBFlags |= UDF_CCB_VALID; // increment the number of outstanding open operations on this // logical volume (i.e. volume cannot be dismounted) - UDFInterlockedIncrement((PLONG)&(Vcb->VcbReference)); + InterlockedIncrement((PLONG)&Vcb->VcbReference); PtrNewFcb->NtReqFCBFlags |= UDF_NTREQ_FCB_VALID; PtrNewFcb->FcbState |= UDF_FCB_VALID; #ifdef UDF_DBG @@ -2497,7 +2410,7 @@ UDFCompleteFcbOpen( AdPrint(("Can't allocate CCB\n")); IrpSp->FileObject->FsContext2 = NULL; // - UDFInterlockedIncrement((PLONG)&Fcb->FcbReference); + InterlockedIncrement((PLONG)&Fcb->FcbReference); Status = STATUS_INSUFFICIENT_RESOURCES; try_return(Status); } @@ -2550,12 +2463,12 @@ UDFCompleteFcbOpen( Fcb->FcbState &= ~UDF_FCB_DELAY_CLOSE; #endif //UDF_DELAYED_CLOSE - UDFAcquireResourceExclusive(&Fcb->CcbListResource, TRUE); + UDFAcquireResourceExclusive(&Fcb->FcbNonpaged->CcbListResource, TRUE); // insert CCB into linked list of open file object to Fcb or // to Vcb and do other intialization InsertTailList(&Fcb->NextCCB, &Ccb->NextCCB); - UDFInterlockedIncrement((PLONG)&Fcb->FcbReference); - UDFReleaseResource(&Fcb->CcbListResource); + InterlockedIncrement((PLONG)&Fcb->FcbReference); + UDFReleaseResource(&Fcb->FcbNonpaged->CcbListResource); Ccb = NULL; diff --git a/drivers/filesystems/udfs/devcntrl.cpp b/drivers/filesystems/udfs/devcntrl.cpp index 9a684be54320f..de06c22933c77 100644 --- a/drivers/filesystems/udfs/devcntrl.cpp +++ b/drivers/filesystems/udfs/devcntrl.cpp @@ -36,72 +36,6 @@ UDFDevCtrlCompletionRoutine ( IN PVOID Contxt ); -/************************************************************************* -* -* Function: UDFDeviceControl() -* -* Description: -* The I/O Manager will invoke this routine to handle a Device IOCTL -* request -* -* Expected Interrupt Level (for execution) : -* -* IRQL_PASSIVE_LEVEL (invocation at higher IRQL will cause execution -* to be deferred to a worker thread context) -* -* Return Value: STATUS_SUCCESS/Error -* -*************************************************************************/ -NTSTATUS -NTAPI -UDFDeviceControl( - PDEVICE_OBJECT DeviceObject, // the logical volume device object - PIRP Irp) // I/O Request Packet -{ - NTSTATUS RC = STATUS_SUCCESS; - PIRP_CONTEXT IrpContext = NULL; - BOOLEAN AreWeTopLevel = FALSE; - - TmPrint(("UDFDeviceControl: \n")); - - FsRtlEnterFileSystem(); - ASSERT(DeviceObject); - ASSERT(Irp); - - // set the top level context - AreWeTopLevel = UDFIsIrpTopLevel(Irp); - //ASSERT(!UDFIsFSDevObj(DeviceObject)); - - _SEH2_TRY { - - // get an IRP context structure and issue the request - IrpContext = UDFCreateIrpContext(Irp, DeviceObject); - if (IrpContext) { - RC = UDFCommonDeviceControl(IrpContext, Irp); - } else { - - UDFCompleteRequest(IrpContext, Irp, STATUS_INSUFFICIENT_RESOURCES); - RC = STATUS_INSUFFICIENT_RESOURCES; - } - - } _SEH2_EXCEPT(UDFExceptionFilter(IrpContext, _SEH2_GetExceptionInformation())) { - - RC = UDFProcessException(IrpContext, Irp); - - UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC); - } _SEH2_END; - - if (AreWeTopLevel) { - IoSetTopLevelIrp(NULL); - } - - FsRtlExitFileSystem(); - - return(RC); -} // end UDFDeviceControl() - - - NTSTATUS UDFDvdTransferKey ( IN PIRP_CONTEXT IrpContext, @@ -160,7 +94,7 @@ UdfIsVolumeModifyingScsiOp( } NTSTATUS -UDFCommonDeviceControl(PIRP_CONTEXT IrpContext, PIRP Irp) +UDFCommonDevControl(PIRP_CONTEXT IrpContext, PIRP Irp) { BOOLEAN FcbAcquired = FALSE; BOOLEAN DeviceAcquired = FALSE; diff --git a/drivers/filesystems/udfs/dircntrl.cpp b/drivers/filesystems/udfs/dircntrl.cpp index 904ec34f9d234..772b7a53a4446 100644 --- a/drivers/filesystems/udfs/dircntrl.cpp +++ b/drivers/filesystems/udfs/dircntrl.cpp @@ -37,72 +37,6 @@ UDFFindNextMatch( IN PHASH_ENTRY hashes, OUT PDIR_INDEX_ITEM* _DirNdx); -/************************************************************************* -* -* Function: UDFDirControl() -* -* Description: -* The I/O Manager will invoke this routine to handle a directory control -* request -* -* Expected Interrupt Level (for execution) : -* -* IRQL_PASSIVE_LEVEL (invocation at higher IRQL will cause execution -* to be deferred to a worker thread context) -* -* Return Value: STATUS_SUCCESS/Error -* -*************************************************************************/ -NTSTATUS -NTAPI -UDFDirControl( - PDEVICE_OBJECT DeviceObject, // the logical volume device object - PIRP Irp // I/O Request Packet - ) -{ - NTSTATUS RC = STATUS_SUCCESS; - PIRP_CONTEXT IrpContext = NULL; - BOOLEAN AreWeTopLevel = FALSE; - - TmPrint(("UDFDirControl: \n")); - - FsRtlEnterFileSystem(); - ASSERT(DeviceObject); - ASSERT(Irp); - - // set the top level context - AreWeTopLevel = UDFIsIrpTopLevel(Irp); - - _SEH2_TRY { - - // get an IRP context structure and issue the request - IrpContext = UDFCreateIrpContext(Irp, DeviceObject); - if (IrpContext) { - RC = UDFCommonDirControl(IrpContext, Irp); - } else { - - UDFCompleteRequest(IrpContext, Irp, RC); - RC = STATUS_INSUFFICIENT_RESOURCES; - } - - } _SEH2_EXCEPT(UDFExceptionFilter(IrpContext, _SEH2_GetExceptionInformation())) { - - RC = UDFProcessException(IrpContext, Irp); - - UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC); - } _SEH2_END; - - if (AreWeTopLevel) { - IoSetTopLevelIrp(NULL); - } - - FsRtlExitFileSystem(); - - return(RC); -} // end UDFDirControl() - - - /************************************************************************* * * Function: UDFCommonDirControl() @@ -212,10 +146,7 @@ UDFQueryDirectory( ) { NTSTATUS RC = STATUS_SUCCESS; - BOOLEAN PostRequest = FALSE; - BOOLEAN CanWait = FALSE; - _SEH2_VOLATILE PVCB Vcb = NULL; - _SEH2_VOLATILE BOOLEAN AcquiredFCB = FALSE; + PVCB Vcb = NULL; unsigned long BufferLength = 0; UNICODE_STRING SearchPattern; PUNICODE_STRING PtrSearchPattern; @@ -231,7 +162,6 @@ UDFQueryDirectory( ULONG Information = 0; ULONG LastOffset = 0; BOOLEAN AtLeastOneFound = FALSE; - PEXTENDED_IO_STACK_LOCATION pStackLocation = (PEXTENDED_IO_STACK_LOCATION) IrpSp; PUDF_FILE_INFO DirFileInfo = NULL; PDIR_INDEX_HDR hDirIndex = NULL; PFILE_BOTH_DIR_INFORMATION DirInformation = NULL; // Returned from udf_info module @@ -250,7 +180,10 @@ UDFQueryDirectory( #define IgnoreCase (FNM_Flags & UDF_FNM_FLAG_IGNORE_CASE) #define ContainsWC (FNM_Flags & UDF_FNM_FLAG_CONTAINS_WC) - FileInformationClass = pStackLocation->Parameters.QueryDirectory.FileInformationClass; + Vcb = Fcb->Vcb; + ASSERT_VCB(Vcb); + + FileInformationClass = IrpSp->Parameters.QueryDirectory.FileInformationClass; // Check if we support this search mode. Also remember the size of the base part of // each of these structures. @@ -278,38 +211,27 @@ UDFQueryDirectory( return STATUS_INVALID_INFO_CLASS; } + // Acquire the directory. + + UDFAcquireFcbShared(IrpContext, Fcb, FALSE); + _SEH2_TRY { - // Obtain the callers parameters - CanWait = (IrpContext->Flags & IRP_CONTEXT_FLAG_WAIT) ? TRUE : FALSE; - Vcb = Fcb->Vcb; - DirFileInfo = Fcb->FileInfo; - BufferLength = pStackLocation->Parameters.QueryDirectory.Length; - - // If the caller does not want to block, it would be easier to - // simply post the request now. - if (!CanWait) { - PostRequest = TRUE; - try_return(RC = STATUS_PENDING); - } + BufferLength = IrpSp->Parameters.QueryDirectory.Length; // Continue obtaining the callers parameters... - if (FlagOn(Ccb->Flags, CCB_FLAG_IGNORE_CASE) && pStackLocation->Parameters.QueryDirectory.FileName) { + if (FlagOn(Ccb->Flags, CCB_FLAG_IGNORE_CASE) && IrpSp->Parameters.QueryDirectory.FileName) { PtrSearchPattern = &SearchPattern; - if (!NT_SUCCESS(RC = RtlUpcaseUnicodeString(PtrSearchPattern, (PUNICODE_STRING)(pStackLocation->Parameters.QueryDirectory.FileName), TRUE))) + if (!NT_SUCCESS(RC = RtlUpcaseUnicodeString(PtrSearchPattern, (PUNICODE_STRING)(IrpSp->Parameters.QueryDirectory.FileName), TRUE))) try_return(RC); } else { - PtrSearchPattern = (PUNICODE_STRING)(pStackLocation->Parameters.QueryDirectory.FileName); + PtrSearchPattern = (PUNICODE_STRING)(IrpSp->Parameters.QueryDirectory.FileName); } // Some additional arguments that affect the FSD behavior ReturnSingleEntry = (IrpSp->Flags & SL_RETURN_SINGLE_ENTRY) ? TRUE : FALSE; - UDF_CHECK_PAGING_IO_RESOURCE(Fcb); - UDFAcquireResourceShared(&Fcb->FcbNonpaged->FcbResource, TRUE); - AcquiredFCB = TRUE; - // We must determine the buffer pointer to be used. Since this // routine could either be invoked directly in the context of the // calling thread, or in the context of a worker thread, here is @@ -418,7 +340,7 @@ UDFQueryDirectory( // Caller has told us wherefrom to begin. // We may need to round this to an appropriate directory entry // entry alignment value. - NextMatch = pStackLocation->Parameters.QueryDirectory.FileIndex; + NextMatch = IrpSp->Parameters.QueryDirectory.FileIndex; } else if (IrpSp->Flags & SL_RESTART_SCAN) { NextMatch = 0; } else { @@ -448,7 +370,7 @@ UDFQueryDirectory( try_return(RC = STATUS_INSUFFICIENT_RESOURCES); } CurrentOffset=0; - BytesRemainingInBuffer = pStackLocation->Parameters.QueryDirectory.Length; + BytesRemainingInBuffer = IrpSp->Parameters.QueryDirectory.Length; RtlZeroMemory(Buffer,BytesRemainingInBuffer); if ((!FirstTimeQuery) && !UDFDirIndex(hDirIndex, (uint_di)NextMatch) ) { @@ -566,42 +488,29 @@ try_exit: NOTHING; } _SEH2_FINALLY { - if (PostRequest) { - - if (AcquiredFCB) { - UDF_CHECK_PAGING_IO_RESOURCE(Fcb); - UDFReleaseResource(&Fcb->FcbNonpaged->FcbResource); - } - // Map the users buffer and then post the request. - RC = UDFLockUserBuffer(IrpContext, BufferLength, IoWriteAccess); - ASSERT(NT_SUCCESS(RC)); - - RC = UDFPostRequest(IrpContext, Irp); - } else { #ifdef UDF_DBG - if (!NT_SUCCESS(RC)) { - UDFPrint((" Not found\n")); - } + if (!NT_SUCCESS(RC)) { + UDFPrint((" Not found\n")); + } #endif // UDF_DBG - // Remember to update the CurrentByteOffset field in the CCB if required. - if (Ccb) Ccb->CurrentIndex = NextMatch; - if (AcquiredFCB) { - UDF_CHECK_PAGING_IO_RESOURCE(Fcb); - UDFReleaseResource(&Fcb->FcbNonpaged->FcbResource); - } - if (!_SEH2_AbnormalTermination()) { + UDFReleaseFcb(IrpContext, Fcb); - Irp->IoStatus.Information = Information; - UDFCompleteRequest(IrpContext, Irp, RC); - } + if (!_SEH2_AbnormalTermination() && !NT_ERROR(RC)) { + + // Remember to update the CurrentByteOffset field in the CCB if required. + Ccb->CurrentIndex = NextMatch; } if (SearchPattern.Buffer) RtlFreeUnicodeString(&SearchPattern); if (DirInformation) MyFreePool__(DirInformation); } _SEH2_END; + Irp->IoStatus.Information = Information; + + UDFCompleteRequest(IrpContext, Irp, RC); + return(RC); } // end UDFQueryDirectory() @@ -706,7 +615,7 @@ UDFNotifyChangeDirectory( UDFVerifyVcb(IrpContext, Vcb); FsRtlNotifyFullChangeDirectory( - Vcb->NotifyIRPMutex, + Vcb->NotifySync, &Vcb->NextNotifyIRP, (PVOID)Ccb, (Fcb->FileInfo->ParentFile) ? (PSTRING)&(Fcb->FCBName->ObjectName) : (PSTRING)&(UdfData.UnicodeStrRoot), diff --git a/drivers/filesystems/udfs/env_spec.cpp b/drivers/filesystems/udfs/env_spec.cpp index 25813e18d5f68..22ee33064feef 100644 --- a/drivers/filesystems/udfs/env_spec.cpp +++ b/drivers/filesystems/udfs/env_spec.cpp @@ -19,15 +19,6 @@ // define the file specific bug-check id #define UDF_BUG_CHECK_ID UDF_FILE_ENV_SPEC -#define MEASURE_IO_PERFORMANCE - -#ifdef MEASURE_IO_PERFORMANCE -LONGLONG IoReadTime=0; -LONGLONG IoWriteTime=0; -LONGLONG WrittenData=0; -LONGLONG IoRelWriteTime=0; -#endif //MEASURE_IO_PERFORMANCE - #ifdef DBG ULONG UDF_SIMULATE_WRITES=0; #endif //DBG @@ -143,23 +134,11 @@ UDFPhReadSynchronous( PIO_STACK_LOCATION IrpSp; KIRQL CurIrql = KeGetCurrentIrql(); PVOID IoBuf = NULL; -// ULONG i; -#ifdef MEASURE_IO_PERFORMANCE - LONGLONG IoEnterTime; - LONGLONG IoExitTime; - ULONG dt; - ULONG dtm; -#endif //MEASURE_IO_PERFORMANCE -#ifdef _BROWSE_UDF_ PVCB Vcb = NULL; + if (Flags & PH_VCB_IN_RETLEN) { Vcb = (PVCB)(*ReadBytes); } -#endif //_BROWSE_UDF_ - -#ifdef MEASURE_IO_PERFORMANCE - KeQuerySystemTime((PLARGE_INTEGER)&IoEnterTime); -#endif //MEASURE_IO_PERFORMANCE ROffset.QuadPart = Offset; (*ReadBytes) = 0; @@ -243,11 +222,9 @@ UDFPhReadSynchronous( UDFPrint(("IOCRC %8.8x R %x\n", crc32((PUCHAR)Buffer+i, 2048), (ULONG)((Offset+i)/2048) )); } */ -#ifdef _BROWSE_UDF_ if (Vcb) { - RC = UDFVRead(Vcb, IoBuf, ByteCount >> Vcb->BlockSizeBits, (ULONG)(Offset >> Vcb->BlockSizeBits), Flags); + RC = UDFVRead(Vcb, IoBuf, ByteCount >> Vcb->SectorShift, (ULONG)(Offset >> Vcb->SectorShift), Flags); } -#endif //_BROWSE_UDF_ } try_exit: NOTHING; @@ -255,16 +232,6 @@ try_exit: NOTHING; if (Context) MyFreePool__(Context); if (IoBuf && !(Flags & PH_TMP_BUFFER)) DbgFreePool(IoBuf); -#ifdef MEASURE_IO_PERFORMANCE - KeQuerySystemTime((PLARGE_INTEGER)&IoExitTime); - IoReadTime += (IoExitTime-IoEnterTime); - dt = (ULONG)((IoExitTime-IoEnterTime)/10/1000); - dtm = (ULONG)(((IoExitTime-IoEnterTime)/10)%1000); - PerfPrint(("\nUDFPhReadSynchronous() exit: %08X, after %d.%4.4d msec.\n", RC, dt, dtm)); -#else - UDFPrint(("UDFPhReadSynchronous() exit: %08X\n", RC)); -#endif //MEASURE_IO_PERFORMANCE - return(RC); } // end UDFPhReadSynchronous() @@ -297,33 +264,14 @@ UDFPhWriteSynchronous( LARGE_INTEGER ROffset; PUDF_PH_CALL_CONTEXT Context = NULL; PIRP irp; -// LARGE_INTEGER timeout; KIRQL CurIrql = KeGetCurrentIrql(); PVOID IoBuf = NULL; -// ULONG i; -#ifdef MEASURE_IO_PERFORMANCE - LONGLONG IoEnterTime; - LONGLONG IoExitTime; - ULONG dt; - ULONG dtm; -#endif //MEASURE_IO_PERFORMANCE -#ifdef _BROWSE_UDF_ + PVCB Vcb = NULL; if (Flags & PH_VCB_IN_RETLEN) { Vcb = (PVCB)(*WrittenBytes); } -#endif //_BROWSE_UDF_ - -#ifdef MEASURE_IO_PERFORMANCE - KeQuerySystemTime((PLARGE_INTEGER)&IoEnterTime); -#endif //MEASURE_IO_PERFORMANCE -#ifdef USE_PERF_PRINT - ULONG Lba = (ULONG)(Offset>>0xb); -// ASSERT(!(Lba & (32-1))); - PerfPrint(("UDFPhWrite: Length: %x Lba: %lx\n",Length>>0xb,Lba)); -// UDFPrint(("UDFPhWrite: Length: %x Lba: %lx\n",Length>>0x9,Offset>>0x9)); -#endif //DBG #ifdef DBG if (UDF_SIMULATE_WRITES) { @@ -379,11 +327,9 @@ UDFPhWriteSynchronous( UDFPrint(("IOCRC %8.8x W %x\n", crc32((PUCHAR)Buffer+i, 2048), (ULONG)((Offset+i)/2048) )); } */ -#ifdef _BROWSE_UDF_ if (Vcb) { - UDFVWrite(Vcb, IoBuf, ByteCount >> Vcb->BlockSizeBits, (ULONG)(Offset >> Vcb->BlockSizeBits), Flags); + UDFVWrite(Vcb, IoBuf, ByteCount >> Vcb->SectorShift, (ULONG)(Offset >> Vcb->SectorShift), Flags); } -#endif //_BROWSE_UDF_ if (RC == STATUS_PENDING) { DbgWaitForSingleObject(&(Context->event), NULL); @@ -406,22 +352,6 @@ try_exit: NOTHING; UDFPrint(("WriteError\n")); } -#ifdef MEASURE_IO_PERFORMANCE - KeQuerySystemTime((PLARGE_INTEGER)&IoExitTime); - IoWriteTime += (IoExitTime-IoEnterTime); - if (WrittenData > 1024*1024*8) { - PerfPrint(("\nUDFPhWriteSynchronous() Relative size=%I64d, time=%I64d.\n", WrittenData, IoRelWriteTime)); - WrittenData = IoRelWriteTime = 0; - } - WrittenData += ByteCount; - IoRelWriteTime += (IoExitTime-IoEnterTime); - dt = (ULONG)((IoExitTime-IoEnterTime)/10/1000); - dtm = (ULONG)(((IoExitTime-IoEnterTime)/10)%1000); - PerfPrint(("\nUDFPhWriteSynchronous() exit: %08X, after %d.%4.4d msec.\n", RC, dt, dtm)); -#else - UDFPrint(("nUDFPhWriteSynchronous() exit: %08X\n", RC)); -#endif //MEASURE_IO_PERFORMANCE - return(RC); } // end UDFPhWriteSynchronous() @@ -585,7 +515,7 @@ UDFNotifyFullReportChange( } } - FsRtlNotifyFullReportChange(Vcb->NotifyIRPMutex, + FsRtlNotifyFullReportChange(Vcb->NotifySync, &Vcb->NextNotifyIRP, (PSTRING)&Fcb->FCBName->ObjectName, TargetNameOffset, diff --git a/drivers/filesystems/udfs/fastio.cpp b/drivers/filesystems/udfs/fastio.cpp index 8044a93472499..3709db14a7745 100644 --- a/drivers/filesystems/udfs/fastio.cpp +++ b/drivers/filesystems/udfs/fastio.cpp @@ -166,9 +166,6 @@ UDFFastIoQueryBasicInfo( TypeOfOpen = UDFDecodeFileObject(FileObject, &Fcb, &Ccb); - ASSERT_FCB(Fcb); - ASSERT_CCB(Ccb); - // We only support this request on user file or directory objects. if ((TypeOfOpen != UserFileOpen) && @@ -177,6 +174,9 @@ UDFFastIoQueryBasicInfo( return FALSE; } + ASSERT_FCB(Fcb); + ASSERT_CCB(Ccb); + FsRtlEnterFileSystem(); // if the file is already opended we can satisfy this request @@ -254,9 +254,6 @@ UDFFastIoQueryStdInfo( TypeOfOpen = UDFDecodeFileObject(FileObject, &Fcb, &Ccb); - ASSERT_FCB(Fcb); - ASSERT_CCB(Ccb); - // We only support this request on user file or directory objects. if ((TypeOfOpen != UserFileOpen) && @@ -265,6 +262,9 @@ UDFFastIoQueryStdInfo( return FALSE; } + ASSERT_FCB(Fcb); + ASSERT_CCB(Ccb); + FsRtlEnterFileSystem(); _SEH2_TRY{ @@ -580,9 +580,6 @@ UDFFastIoQueryNetInfo( TypeOfOpen = UDFDecodeFileObject(FileObject, &Fcb, &Ccb); - ASSERT_FCB(Fcb); - ASSERT_CCB(Ccb); - // We only support this request on user file or directory objects. if ((TypeOfOpen != UserFileOpen) && @@ -591,6 +588,9 @@ UDFFastIoQueryNetInfo( return FALSE; } + ASSERT_FCB(Fcb); + ASSERT_CCB(Ccb); + FsRtlEnterFileSystem(); _SEH2_TRY{ @@ -671,9 +671,6 @@ IN PDEVICE_OBJECT DeviceObject) } __except (UDFExceptionFilter(IrpContext, GetExceptionInformation())) { RC = UDFExceptionHandler(IrpContext, NULL); - - UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC); - } //try_exit: NOTHING; @@ -726,9 +723,6 @@ IN PDEVICE_OBJECT DeviceObject) } __except (UDFExceptionFilter(IrpContext, GetExceptionInformation())) { RC = UDFExceptionHandler(IrpContext, NULL); - - UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC); - } //try_exit: NOTHING; @@ -785,9 +779,6 @@ UDFFastIoPrepareMdlWrite( } __except (UDFExceptionFilter(IrpContext, GetExceptionInformation())) { RC = UDFExceptionHandler(IrpContext, NULL); - - UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC); - } //try_exit: NOTHING; @@ -841,9 +832,6 @@ IN PDEVICE_OBJECT DeviceObject) } __except (UDFExceptionFilter(IrpContext, GetExceptionInformation())) { RC = UDFExceptionHandler(IrpContext, NULL); - - UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC); - } //try_exit: NOTHING; diff --git a/drivers/filesystems/udfs/fileinfo.cpp b/drivers/filesystems/udfs/fileinfo.cpp index 2378784a165d1..d527a8902ac7c 100644 --- a/drivers/filesystems/udfs/fileinfo.cpp +++ b/drivers/filesystems/udfs/fileinfo.cpp @@ -25,134 +25,6 @@ #define MEM_USFIDC_TAG "US_FIDC" #define MEM_USHL_TAG "US_HL" -/************************************************************************* -* -* Function: UDFQueryInfo() -* -* Description: -* The I/O Manager will invoke this routine to handle a query file -* information request -* -* Expected Interrupt Level (for execution) : -* -* IRQL_PASSIVE_LEVEL (invocation at higher IRQL will cause execution -* to be deferred to a worker thread context) -* -* Return Value: STATUS_SUCCESS/Error -* -*************************************************************************/ -NTSTATUS -NTAPI -UDFQueryInfo( - PDEVICE_OBJECT DeviceObject, // the logical volume device object - PIRP Irp // I/O Request Packet - ) -{ - NTSTATUS RC = STATUS_SUCCESS; - PIRP_CONTEXT IrpContext = NULL; - BOOLEAN AreWeTopLevel = FALSE; - - TmPrint(("UDFQueryInfo: \n")); - - FsRtlEnterFileSystem(); - ASSERT(DeviceObject); - ASSERT(Irp); - - // set the top level context - AreWeTopLevel = UDFIsIrpTopLevel(Irp); - - _SEH2_TRY { - - // get an IRP context structure and issue the request - IrpContext = UDFCreateIrpContext(Irp, DeviceObject); - if (IrpContext) { - RC = UDFCommonQueryInfo(IrpContext, Irp); - } else { - - UDFCompleteRequest(IrpContext, Irp, STATUS_INSUFFICIENT_RESOURCES); - RC = STATUS_INSUFFICIENT_RESOURCES; - } - - } _SEH2_EXCEPT(UDFExceptionFilter(IrpContext, _SEH2_GetExceptionInformation())) { - - RC = UDFProcessException(IrpContext, Irp); - - UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC); - } _SEH2_END; - - if (AreWeTopLevel) { - IoSetTopLevelIrp(NULL); - } - - FsRtlExitFileSystem(); - - return(RC); -} // end UDFQueryInfo() - -/************************************************************************* -* -* Function: UDFSetInfo() -* -* Description: -* The I/O Manager will invoke this routine to handle a set file -* information request -* -* Expected Interrupt Level (for execution) : -* -* IRQL_PASSIVE_LEVEL (invocation at higher IRQL will cause execution -* to be deferred to a worker thread context) -* -* Return Value: STATUS_SUCCESS/Error -* -*************************************************************************/ -NTSTATUS -NTAPI -UDFSetInfo( - PDEVICE_OBJECT DeviceObject, // the logical volume device object - PIRP Irp // I/O Request Packet - ) -{ - NTSTATUS RC = STATUS_SUCCESS; - PIRP_CONTEXT IrpContext = NULL; - BOOLEAN AreWeTopLevel = FALSE; - - TmPrint(("UDFSetInfo: \n")); - - FsRtlEnterFileSystem(); - ASSERT(DeviceObject); - ASSERT(Irp); - - // set the top level context - AreWeTopLevel = UDFIsIrpTopLevel(Irp); - - _SEH2_TRY { - - // get an IRP context structure and issue the request - IrpContext = UDFCreateIrpContext(Irp, DeviceObject); - if (IrpContext) { - RC = UDFCommonSetInfo(IrpContext, Irp); - } else { - - UDFCompleteRequest(IrpContext, Irp, STATUS_INSUFFICIENT_RESOURCES); - RC = STATUS_INSUFFICIENT_RESOURCES; - } - - } _SEH2_EXCEPT(UDFExceptionFilter(IrpContext, _SEH2_GetExceptionInformation())) { - - RC = UDFProcessException(IrpContext, Irp); - - UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC); - } _SEH2_END; - - if (AreWeTopLevel) { - IoSetTopLevelIrp(NULL); - } - - FsRtlExitFileSystem(); - - return(RC); -} // end UDFSetInfo() - /************************************************************************* * * Function: UDFCommonQueryInfo() @@ -176,190 +48,154 @@ UDFCommonQueryInfo( PIRP Irp ) { - NTSTATUS RC = STATUS_SUCCESS; - PIO_STACK_LOCATION IrpSp = NULL; - PFILE_OBJECT FileObject = NULL; + NTSTATUS Status = STATUS_SUCCESS; + PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); + + LONG Length; + FILE_INFORMATION_CLASS FileInformationClass; + PVOID Buffer; TYPE_OF_OPEN TypeOfOpen; - PFCB Fcb = NULL; - PCCB Ccb = NULL; - PVCB Vcb = NULL; - BOOLEAN MainResourceAcquired = FALSE; - BOOLEAN ParentResourceAcquired = FALSE; - BOOLEAN PagingIoResourceAcquired = FALSE; - PVOID PtrSystemBuffer = NULL; - LONG BufferLength = 0; - FILE_INFORMATION_CLASS FunctionalityRequested; - BOOLEAN CanWait = FALSE; - BOOLEAN PostRequest = FALSE; - BOOLEAN AcquiredVcb = FALSE; + PFCB Fcb; + PCCB Ccb; + BOOLEAN ReleaseFcb = FALSE; - TmPrint(("UDFCommonQueryInfo: irp %x\n", Irp)); + PAGED_CODE(); - // Decode the file object + // Reference our input parameters to make things easier - IrpSp = IoGetCurrentIrpStackLocation(Irp); + Length = IrpSp->Parameters.QueryFile.Length; + FileInformationClass = IrpSp->Parameters.QueryFile.FileInformationClass; + Buffer = Irp->AssociatedIrp.SystemBuffer; - FileObject = IrpSp->FileObject; + // Decode the file object - TypeOfOpen = UDFDecodeFileObject(FileObject, &Fcb, &Ccb); + TypeOfOpen = UDFDecodeFileObject(IrpSp->FileObject, &Fcb, &Ccb); ASSERT_CCB(Ccb); ASSERT_FCB(Fcb); _SEH2_TRY { - CanWait = (IrpContext->Flags & IRP_CONTEXT_FLAG_WAIT) ? TRUE : FALSE; + // We only support query on file and directory handles. - // If the caller has opened a logical volume and is attempting to - // query information for it as a file stream, return an error. - if (Fcb == Fcb->Vcb->VolumeDasdFcb) { - // This is not allowed. Caller must use get/set volume information instead. - RC = STATUS_INVALID_PARAMETER; - try_return(RC); - } + switch (TypeOfOpen) { - Vcb = Fcb->Vcb; - ASSERT_VCB(Vcb); - //Vcb->VcbState |= UDF_VCB_SKIP_EJECT_CHECK; + case UserDirectoryOpen: + case UserFileOpen: - // The NT I/O Manager always allocates and supplies a system - // buffer for query and set file information calls. - // Copying information to/from the user buffer and the system - // buffer is performed by the I/O Manager and the FSD need not worry about it. - PtrSystemBuffer = Irp->AssociatedIrp.SystemBuffer; + UDFAcquireFcbShared(IrpContext, Fcb, FALSE); + ReleaseFcb = TRUE; - UDFFlushTryBreak(Vcb); + // Make sure the Fcb is in a usable condition. This will raise + // an error condition if the volume is unusable - // Now, obtain some parameters. - BufferLength = IrpSp->Parameters.QueryFile.Length; - FunctionalityRequested = IrpSp->Parameters.QueryFile.FileInformationClass; + UDFVerifyFcbOperation(IrpContext, Fcb, Ccb); - if (!UDFAcquireResourceShared(&Vcb->VcbResource, CanWait)) { - PostRequest = TRUE; - try_return(RC = STATUS_PENDING); - } - AcquiredVcb = TRUE; + // Do whatever the caller asked us to do + switch (FileInformationClass) { + case FileBasicInformation: + Status = UDFGetBasicInformation(IrpSp->FileObject, Fcb, (PFILE_BASIC_INFORMATION)Buffer, &Length); + break; + case FileStandardInformation: + Status = UDFGetStandardInformation(Fcb, (PFILE_STANDARD_INFORMATION)Buffer, &Length); + break; + case FileNetworkOpenInformation: + Status = UDFGetNetworkInformation(Fcb, (PFILE_NETWORK_OPEN_INFORMATION)Buffer, &Length); + break; + case FileInternalInformation: + Status = UDFGetInternalInformation(IrpContext, Fcb, (PFILE_INTERNAL_INFORMATION)Buffer, &Length); + break; + case FileEaInformation: + Status = UDFGetEaInformation(IrpContext, Fcb, (PFILE_EA_INFORMATION)Buffer, &Length); + break; + case FileNameInformation: - // Acquire the MainResource shared (NOTE: for paging-IO on a - // page file, we should avoid acquiring any resources and simply - // trust the VMM to do the right thing, else we could possibly - // run into deadlocks). + // We don't allow this operation on a file opened by file Id. - // Acquire the MainResource shared. - UDF_CHECK_PAGING_IO_RESOURCE(Fcb); - UDFAcquireResourceShared(&Fcb->FcbNonpaged->FcbResource, TRUE); - MainResourceAcquired = TRUE; + if (FlagOn(Ccb->Flags, CCB_FLAG_OPEN_BY_ID)) { - // Do whatever the caller asked us to do - switch (FunctionalityRequested) { - case FileBasicInformation: - RC = UDFGetBasicInformation(FileObject, Fcb, (PFILE_BASIC_INFORMATION)PtrSystemBuffer, &BufferLength); - break; - case FileStandardInformation: - RC = UDFGetStandardInformation(Fcb, (PFILE_STANDARD_INFORMATION) PtrSystemBuffer, &BufferLength); - break; - case FileNetworkOpenInformation: - RC = UDFGetNetworkInformation(Fcb, (PFILE_NETWORK_OPEN_INFORMATION)PtrSystemBuffer, &BufferLength); - break; - case FileInternalInformation: - RC = UDFGetInternalInformation(IrpContext, Fcb, (PFILE_INTERNAL_INFORMATION)PtrSystemBuffer, &BufferLength); - break; - case FileEaInformation: - RC = UDFGetEaInformation(IrpContext, Fcb, (PFILE_EA_INFORMATION) PtrSystemBuffer, &BufferLength); - break; - case FileNameInformation: - RC = UDFGetFullNameInformation(FileObject, (PFILE_NAME_INFORMATION) PtrSystemBuffer, &BufferLength); - break; - case FileAlternateNameInformation: - RC = UDFGetAltNameInformation(Fcb, (PFILE_NAME_INFORMATION) PtrSystemBuffer, &BufferLength); - break; - //TODO: impl -// case FileCompressionInformation: -// // RC = UDFGetCompressionInformation(...); -// break; - case FilePositionInformation: - RC = UDFGetPositionInformation(FileObject, (PFILE_POSITION_INFORMATION)PtrSystemBuffer, &BufferLength); - break; - case FileStreamInformation: - RC = UDFGetFileStreamInformation(IrpContext, Fcb, (PFILE_STREAM_INFORMATION)PtrSystemBuffer, (PULONG)&BufferLength); - break; - case FileAllInformation: - // The I/O Manager supplies the Mode, Access, and Alignment - // information. The rest is up to us to provide. - // Therefore, decrement the BufferLength appropriately (assuming - // that the above 3 types on information are already in the - // buffer) - { - PFILE_ALL_INFORMATION PtrAllInfo = (PFILE_ALL_INFORMATION)PtrSystemBuffer; - - BufferLength -= (sizeof(FILE_MODE_INFORMATION) + - sizeof(FILE_ACCESS_INFORMATION) + - sizeof(FILE_ALIGNMENT_INFORMATION)); - - // Get the remaining stuff. - if (!NT_SUCCESS(RC = UDFGetBasicInformation(FileObject, Fcb, &(PtrAllInfo->BasicInformation), &BufferLength)) || - !NT_SUCCESS(RC = UDFGetStandardInformation(Fcb, &(PtrAllInfo->StandardInformation), &BufferLength)) || - !NT_SUCCESS(RC = UDFGetInternalInformation(IrpContext, Fcb, &(PtrAllInfo->InternalInformation), &BufferLength)) || - !NT_SUCCESS(RC = UDFGetEaInformation(IrpContext, Fcb, &(PtrAllInfo->EaInformation), &BufferLength)) || - !NT_SUCCESS(RC = UDFGetPositionInformation(FileObject, &(PtrAllInfo->PositionInformation), &BufferLength)) || - !NT_SUCCESS(RC = UDFGetFullNameInformation(FileObject, &(PtrAllInfo->NameInformation), &BufferLength)) - ) - try_return(RC); - } - break; - default: - RC = STATUS_INVALID_PARAMETER; - try_return(RC); - } + Status = STATUS_INVALID_PARAMETER; + break; + } -try_exit: NOTHING; + Status = UDFGetFullNameInformation(IrpSp->FileObject, (PFILE_NAME_INFORMATION)Buffer, &Length); + break; + case FileAlternateNameInformation: + Status = UDFGetAltNameInformation(Fcb, (PFILE_NAME_INFORMATION)Buffer, &Length); + break; + //TODO: impl + // case FileCompressionInformation: + // // Status = UDFGetCompressionInformation(...); + // break; + case FilePositionInformation: + Status = UDFGetPositionInformation(IrpSp->FileObject, (PFILE_POSITION_INFORMATION)Buffer, &Length); + break; + case FileStreamInformation: + Status = UDFGetFileStreamInformation(IrpContext, Fcb, (PFILE_STREAM_INFORMATION)Buffer, (PULONG)&Length); + break; + case FileAllInformation: + { + // We don't allow this operation on a file opened by file Id. - } _SEH2_FINALLY { + if (FlagOn(Ccb->Flags, CCB_FLAG_OPEN_BY_ID)) { - if (PagingIoResourceAcquired) { - UDFReleaseResource(&Fcb->FcbNonpaged->FcbPagingIoResource); - PagingIoResourceAcquired = FALSE; - } + Status = STATUS_INVALID_PARAMETER; + break; + } - if (MainResourceAcquired) { - UDFReleaseResource(&Fcb->FcbNonpaged->FcbResource); - MainResourceAcquired = FALSE; - } + PFILE_ALL_INFORMATION PtrAllInfo = (PFILE_ALL_INFORMATION)Buffer; + + Length -= (sizeof(FILE_MODE_INFORMATION) + + sizeof(FILE_ACCESS_INFORMATION) + + sizeof(FILE_ALIGNMENT_INFORMATION)); + + // Get the remaining stuff. + if (!NT_SUCCESS(Status = UDFGetBasicInformation(IrpSp->FileObject, Fcb, &(PtrAllInfo->BasicInformation), &Length)) || + !NT_SUCCESS(Status = UDFGetStandardInformation(Fcb, &(PtrAllInfo->StandardInformation), &Length)) || + !NT_SUCCESS(Status = UDFGetInternalInformation(IrpContext, Fcb, &(PtrAllInfo->InternalInformation), &Length)) || + !NT_SUCCESS(Status = UDFGetEaInformation(IrpContext, Fcb, &(PtrAllInfo->EaInformation), &Length)) || + !NT_SUCCESS(Status = UDFGetPositionInformation(IrpSp->FileObject, &(PtrAllInfo->PositionInformation), &Length)) || + !NT_SUCCESS(Status = UDFGetFullNameInformation(IrpSp->FileObject, &(PtrAllInfo->NameInformation), &Length)) + ) + break; + } - if (ParentResourceAcquired) { - UDF_CHECK_PAGING_IO_RESOURCE(Fcb->ParentFcb); - UDFReleaseResource(&Fcb->ParentFcb->FcbNonpaged->FcbResource); - ParentResourceAcquired = FALSE; - } + break; - if (AcquiredVcb) { - AcquiredVcb = FALSE; - UDFReleaseResource(&(Vcb->VcbResource)); - } + default: - // Post IRP if required - if (PostRequest) { + Status = STATUS_INVALID_PARAMETER; + try_return(Status); + } - // Since, the I/O Manager gave us a system buffer, we do not - // need to "lock" anything. + break; - // Perform the post operation which will mark the IRP pending - // and will return STATUS_PENDING back to us - RC = UDFPostRequest(IrpContext, Irp); + default: - } else { + Status = STATUS_INVALID_PARAMETER; + } - if (!_SEH2_AbnormalTermination()) { + // Set the information field to the number of bytes actually filled in + // and then complete the request - Irp->IoStatus.Information = IrpSp->Parameters.QueryFile.Length - BufferLength; + Irp->IoStatus.Information = IrpSp->Parameters.QueryFile.Length - Length; - UDFCompleteRequest(IrpContext, Irp, RC); - } +try_exit: NOTHING; + + } _SEH2_FINALLY { + + if (ReleaseFcb) { + UDFReleaseFcb(IrpContext, Fcb); } + } _SEH2_END;// end of "__finally" processing - return(RC); + // Complete the request if we didn't raise. + + UDFCompleteRequest(IrpContext, Irp, Status); + + return Status; } // end UDFCommonQueryInfo() /************************************************************************* @@ -620,7 +456,7 @@ try_exit: NOTHING; // Perform the post operation which will mark the IRP pending // and will return STATUS_PENDING back to us - Status = UDFPostRequest(IrpContext, Irp); + Status = UDFFsdPostRequest(IrpContext, Irp); } else { @@ -1630,7 +1466,7 @@ UDFSetDispositionInfo( FileObject->DeletePending = TRUE; if ((Fcb->FcbState & UDF_FCB_DIRECTORY) && Ccb) { - FsRtlNotifyFullChangeDirectory( Vcb->NotifyIRPMutex, &(Vcb->NextNotifyIRP), + FsRtlNotifyFullChangeDirectory( Vcb->NotifySync, &(Vcb->NextNotifyIRP), (PVOID)Ccb, NULL, FALSE, FALSE, 0, NULL, NULL, NULL ); } @@ -1705,7 +1541,7 @@ UDFSetAllocationInfo( // Yes. Do the FSD specific stuff i.e. increase reserved // space on disk. - if (((LONGLONG)UDFGetFreeSpace(Vcb) << Vcb->LBlockSizeBits) < Buffer->AllocationSize.QuadPart) { + if (((LONGLONG)UDFGetFreeSpace(Vcb) << Vcb->SectorShift) < Buffer->AllocationSize.QuadPart) { try_return(RC = STATUS_DISK_FULL); } // RC = STATUS_SUCCESS; @@ -1918,12 +1754,12 @@ UDFSetEndOfFileInfo( // reference file to pretend that it is opened UDFReferenceFile__(Fcb->FileInfo); - UDFInterlockedIncrement((PLONG)&Fcb->FcbReference); + InterlockedIncrement((PLONG)&Fcb->FcbReference); // perform resize operation RC = UDFResizeFile__(IrpContext, Vcb, Fcb->FileInfo, PtrBuffer->EndOfFile.QuadPart); // dereference file UDFCloseFile__(IrpContext, Vcb, Fcb->FileInfo); - UDFInterlockedDecrement((PLONG)&Fcb->FcbReference); + InterlockedDecrement((PLONG)&Fcb->FcbReference); // update values in NtReqFcb Fcb->Header.FileSize.QuadPart = // NtReqFcb->CommonFCBHeader.ValidDataLength.QuadPart = @@ -1948,12 +1784,12 @@ UDFSetEndOfFileInfo( // Perform directory entry modifications. Release any on-disk // space we may need to in the process. UDFReferenceFile__(Fcb->FileInfo); - UDFInterlockedIncrement((PLONG)&Fcb->FcbReference); + InterlockedIncrement((PLONG)&Fcb->FcbReference); // perform resize operation RC = UDFResizeFile__(IrpContext, Vcb, Fcb->FileInfo, PtrBuffer->EndOfFile.QuadPart); // dereference file UDFCloseFile__(IrpContext, Vcb, Fcb->FileInfo); - UDFInterlockedDecrement((PLONG)&Fcb->FcbReference); + InterlockedDecrement((PLONG)&Fcb->FcbReference); ModifiedAllocSize = TRUE; TruncatedFile = TRUE; @@ -2073,16 +1909,16 @@ UDFPrepareForRenameMoveLink( // one of them is a parent of another. Sequential resource // acquisition may lead to deadlock due to concurrent // CleanUpFcbChain() or UDFCloseFileInfoChain() - UDFInterlockedIncrement((PLONG)&(Vcb->VcbReference)); + InterlockedIncrement((PLONG)&Vcb->VcbReference); (*SingleDir) = ((Dir1 == Dir2) && (Dir1->Fcb)); if (!(*SingleDir) || (UDFGetFileLinkCount(File1) != 1)) { - UDFInterlockedDecrement((PLONG)&(Vcb->VcbReference)); + InterlockedDecrement((PLONG)&Vcb->VcbReference); } else { - UDFInterlockedDecrement((PLONG)&(Vcb->VcbReference)); + InterlockedDecrement((PLONG)&Vcb->VcbReference); UDF_CHECK_PAGING_IO_RESOURCE(Dir1->Fcb); UDFAcquireResourceExclusive(&Dir1->Fcb->FcbNonpaged->FcbResource, TRUE); @@ -2317,7 +2153,7 @@ UDFSetRenameInfo( /* UDFNotifyFullReportChange( Vcb, File2, UDFIsADirectory(File2) ? FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME, FILE_ACTION_RENAMED_NEW_NAME );*/ - FsRtlNotifyFullReportChange( Vcb->NotifyIRPMutex, &(Vcb->NextNotifyIRP), + FsRtlNotifyFullReportChange( Vcb->NotifySync, &(Vcb->NextNotifyIRP), (PSTRING)&LocalPath, ((TargetDirInfo->Fcb->FcbState & UDF_FCB_ROOT_DIRECTORY) ? 0 : TargetDirInfo->Fcb->FCBName->ObjectName.Length) + sizeof(WCHAR), NULL,NULL, @@ -2337,7 +2173,7 @@ UDFSetRenameInfo( FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_EA, FILE_ACTION_MODIFIED );*/ - FsRtlNotifyFullReportChange( Vcb->NotifyIRPMutex, &(Vcb->NextNotifyIRP), + FsRtlNotifyFullReportChange( Vcb->NotifySync, &(Vcb->NextNotifyIRP), (PSTRING)&LocalPath, ((TargetDirInfo->Fcb->FcbState & UDF_FCB_ROOT_DIRECTORY) ? 0 : TargetDirInfo->Fcb->FCBName->ObjectName.Length) + sizeof(WCHAR), @@ -2354,7 +2190,7 @@ UDFSetRenameInfo( /* UDFNotifyFullReportChange( Vcb, File2, UDFIsADirectory(File2) ? FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME, FILE_ACTION_ADDED );*/ - FsRtlNotifyFullReportChange( Vcb->NotifyIRPMutex, &(Vcb->NextNotifyIRP), + FsRtlNotifyFullReportChange( Vcb->NotifySync, &(Vcb->NextNotifyIRP), (PSTRING)&LocalPath, ((TargetDirInfo->Fcb->FcbState & UDF_FCB_ROOT_DIRECTORY) ? 0 : TargetDirInfo->Fcb->FCBName->ObjectName.Length) + sizeof(WCHAR), @@ -2369,13 +2205,13 @@ UDFSetRenameInfo( // this will prevent structutre release before call to // UDFCleanUpFcbChain() - UDFInterlockedIncrement((PLONG)&DirInfo->Fcb->FcbReference); + InterlockedIncrement((PLONG)&DirInfo->Fcb->FcbReference); ASSERT(DirInfo->Fcb->FcbReference >= DirInfo->RefCount); // Look through Ccb list & decrement OpenHandleCounter(s) // acquire CcbList if (!SingleDir) { - UDFAcquireResourceExclusive(&Fcb->CcbListResource, TRUE); + UDFAcquireResourceExclusive(&Fcb->FcbNonpaged->CcbListResource, TRUE); Link = Fcb->NextCCB.Flink; DirRefCount = 0; FileInfoRefCount = 0; @@ -2401,7 +2237,7 @@ UDFSetRenameInfo( } ASSERT(NextFileInfo->Fcb->FcbReference > NextFileInfo->RefCount); ASSERT(NextFileInfo->Fcb->FcbReference); - UDFInterlockedDecrement((PLONG)&NextFileInfo->Fcb->FcbReference); + InterlockedDecrement((PLONG)&NextFileInfo->Fcb->FcbReference); ASSERT(NextFileInfo->Fcb->FcbReference >= NextFileInfo->RefCount); NextFileInfo = fi; } @@ -2417,15 +2253,15 @@ UDFSetRenameInfo( #endif // UDF_DBG } } - UDFReleaseResource(&Fcb->CcbListResource); + UDFReleaseResource(&Fcb->FcbNonpaged->CcbListResource); ASSERT(DirRefCount >= FileInfoRefCount); // update counters & pointers Fcb->ParentFcb = TargetDirInfo->Fcb; // move references to TargetDir - UDFInterlockedExchangeAdd((PLONG)&TargetDirInfo->Fcb->FcbReference, DirRefCount); + InterlockedExchangeAdd((PLONG)&TargetDirInfo->Fcb->FcbReference, DirRefCount); ASSERT(TargetDirInfo->Fcb->FcbReference > TargetDirInfo->RefCount); - UDFReferenceFileEx__(TargetDirInfo,FileInfoRefCount); + UDFReferenceFileEx__(TargetDirInfo, FileInfoRefCount); ASSERT(TargetDirInfo->Fcb->FcbReference >= TargetDirInfo->RefCount); } ASSERT(TargetDirInfo->Fcb->FcbReference >= TargetDirInfo->RefCount); @@ -2769,7 +2605,7 @@ UDFHardLink( /* UDFNotifyFullReportChange( Vcb, File2, UDFIsADirectory(File1) ? FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME, FILE_ACTION_ADDED );*/ - FsRtlNotifyFullReportChange( Vcb->NotifyIRPMutex, &(Vcb->NextNotifyIRP), + FsRtlNotifyFullReportChange( Vcb->NotifySync, &(Vcb->NextNotifyIRP), (PSTRING)&LocalPath, ((Dir2->Fcb->FcbState & UDF_FCB_ROOT_DIRECTORY) ? 0 : Dir2->Fcb->FCBName->ObjectName.Length) + sizeof(WCHAR), NULL,NULL, @@ -2785,7 +2621,7 @@ UDFHardLink( FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_EA, FILE_ACTION_MODIFIED );*/ - FsRtlNotifyFullReportChange( Vcb->NotifyIRPMutex, &(Vcb->NextNotifyIRP), + FsRtlNotifyFullReportChange( Vcb->NotifySync, &(Vcb->NextNotifyIRP), (PSTRING)&LocalPath, ((Dir2->Fcb->FcbState & UDF_FCB_ROOT_DIRECTORY) ? 0 : Dir2->Fcb->FCBName->ObjectName.Length) + sizeof(WCHAR), NULL,NULL, diff --git a/drivers/filesystems/udfs/flush.cpp b/drivers/filesystems/udfs/flush.cpp index 61cc276b5e4a1..797f98341d0e5 100644 --- a/drivers/filesystems/udfs/flush.cpp +++ b/drivers/filesystems/udfs/flush.cpp @@ -19,73 +19,6 @@ // define the file specific bug-check id #define UDF_BUG_CHECK_ID UDF_FILE_FLUSH - - -/************************************************************************* -* -* Function: UDFFlushBuffers() -* -* Description: -* The I/O Manager will invoke this routine to handle a flush buffers -* request -* -* Expected Interrupt Level (for execution) : -* -* IRQL_PASSIVE_LEVEL (invocation at higher IRQL will cause execution -* to be deferred to a worker thread context) -* -* Return Value: STATUS_SUCCESS/Error -* -*************************************************************************/ -NTSTATUS -NTAPI -UDFFlushBuffers( - PDEVICE_OBJECT DeviceObject, // the logical volume device object - PIRP Irp) // I/O Request Packet -{ - NTSTATUS RC = STATUS_SUCCESS; - PIRP_CONTEXT IrpContext = NULL; - BOOLEAN AreWeTopLevel = FALSE; - - UDFPrint(("UDFFlush: \n")); - - FsRtlEnterFileSystem(); - ASSERT(DeviceObject); - ASSERT(Irp); - - // set the top level context - AreWeTopLevel = UDFIsIrpTopLevel(Irp); - - _SEH2_TRY { - - // get an IRP context structure and issue the request - IrpContext = UDFCreateIrpContext(Irp, DeviceObject); - if (IrpContext) { - RC = UDFCommonFlush(IrpContext, Irp); - } else { - - UDFCompleteRequest(IrpContext, Irp, STATUS_INSUFFICIENT_RESOURCES); - RC = STATUS_INSUFFICIENT_RESOURCES; - } - - } _SEH2_EXCEPT(UDFExceptionFilter(IrpContext, _SEH2_GetExceptionInformation())) { - - RC = UDFProcessException(IrpContext, Irp); - - UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC); - } _SEH2_END; - - if (AreWeTopLevel) { - IoSetTopLevelIrp(NULL); - } - - FsRtlExitFileSystem(); - - return(RC); -} // end UDFFlushBuffers() - - - /************************************************************************* * * Function: UDFCommonFlush() @@ -166,7 +99,7 @@ UDFCommonFlush( if (!FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)) { - Status = UDFPostRequest(IrpContext, Irp); + Status = UDFFsdPostRequest(IrpContext, Irp); return Status; } diff --git a/drivers/filesystems/udfs/fscntrl.cpp b/drivers/filesystems/udfs/fscntrl.cpp index a8cd4b5d0785d..b5674a0a4d7c3 100644 --- a/drivers/filesystems/udfs/fscntrl.cpp +++ b/drivers/filesystems/udfs/fscntrl.cpp @@ -25,64 +25,7 @@ PDIR_INDEX_HDR UDFDirIndexAlloc(IN uint_di i); /* - Function: UDFFSControl() - - Description: - The I/O Manager will invoke this routine to handle a File System - Control request (this is IRP_MJ_FILE_SYSTEM_CONTROL dispatch point) - -*/ -NTSTATUS -NTAPI -UDFFSControl( - PDEVICE_OBJECT DeviceObject, // the logical volume device object - PIRP Irp // I/O Request Packet - ) -{ - NTSTATUS RC = STATUS_SUCCESS; - PIRP_CONTEXT IrpContext = NULL; - BOOLEAN AreWeTopLevel = FALSE; - - UDFPrint(("\nUDFFSControl: \n\n")); - - FsRtlEnterFileSystem(); - ASSERT(DeviceObject); - ASSERT(Irp); - - // set the top level context - AreWeTopLevel = UDFIsIrpTopLevel(Irp); - - _SEH2_TRY { - - // get an IRP context structure and issue the request - IrpContext = UDFCreateIrpContext(Irp, DeviceObject); - if (IrpContext) { - RC = UDFCommonFSControl(IrpContext, Irp); - } else { - - UDFCompleteRequest(IrpContext, Irp, STATUS_INSUFFICIENT_RESOURCES); - RC = STATUS_INSUFFICIENT_RESOURCES; - } - - } _SEH2_EXCEPT(UDFExceptionFilter(IrpContext, _SEH2_GetExceptionInformation())) { - - UDFPrintErr(("UDFFSControl: exception ***")); - RC = UDFProcessException(IrpContext, Irp); - - UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC); - } _SEH2_END; - - if (AreWeTopLevel) { - IoSetTopLevelIrp(NULL); - } - - FsRtlExitFileSystem(); - - return(RC); -} // end UDFFSControl() - -/* - Function: UDFCommonFSControl() + Function: UDFCommonFsControl() Description: The actual work is performed here. @@ -95,7 +38,7 @@ UDFFSControl( */ NTSTATUS -UDFCommonFSControl( +UDFCommonFsControl( PIRP_CONTEXT IrpContext, PIRP Irp ) @@ -161,10 +104,10 @@ UDFUserFsCtrlRequest( ) { NTSTATUS RC; - PEXTENDED_IO_STACK_LOCATION IrpSp = (PEXTENDED_IO_STACK_LOCATION) IoGetCurrentIrpStackLocation( Irp ); + PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); // Case on the control code. - switch ( IrpSp->Parameters.FileSystemControl.FsControlCode ) { + switch (IrpSp->Parameters.FileSystemControl.FsControlCode) { case FSCTL_REQUEST_OPLOCK_LEVEL_1 : case FSCTL_REQUEST_OPLOCK_LEVEL_2 : @@ -470,11 +413,8 @@ UDFMountVolume( // Initialize the Vcb. This routine will raise on an allocation // failure. - RC = UDFInitializeVCB(IrpContext, &VolDo->Vcb, DeviceObjectWeTalkTo, Vpb); - if (!NT_SUCCESS(RC)) { - Vcb = NULL; - try_return(RC); - } + + UDFInitializeVCB(IrpContext, &VolDo->Vcb, DeviceObjectWeTalkTo, Vpb, &DiskGeometry, MediaChangeCount); // Show that we initialized the Vcb and can cleanup with the Vcb. @@ -519,8 +459,8 @@ UDFMountVolume( Vcb->WCacheBlocksPerFrameSh, 0/*Vcb->FirstLBA*/, Vcb->LastPossibleLBA, Mode, 0/*WCACHE_CACHE_WHOLE_PACKET*/ | - (Vcb->DoNotCompareBeforeWrite ? WCACHE_DO_NOT_COMPARE : 0) | - (Vcb->CacheChainedIo ? WCACHE_CHAINED_IO : 0) | + WCACHE_DO_NOT_COMPARE | + WCACHE_CHAINED_IO | WCACHE_MARK_BAD_BLOCKS | WCACHE_RO_BAD_BLOCKS, // this will be cleared after mount Vcb->WCacheFramesToKeepFree, // UDFTWrite, UDFTRead, @@ -570,11 +510,6 @@ UDFMountVolume( UDFPrint(("UDFMountVolume: R mode\n")); Mode = WCACHE_MODE_R; } - // we can't record ACL on old format disks - if (!UDFNtAclSupported(Vcb)) { - UDFPrint(("UDFMountVolume: NO ACL and ExtFE support\n")); - Vcb->UseExtendedFE = FALSE; - } } #ifdef UDF_USE_WCACHE WCacheSetMode__(&(Vcb->FastCache), Mode); @@ -591,7 +526,7 @@ UDFMountVolume( // but simply cleanup and return error, Vcb->VcbReference // will be decremented during cleanup. Thus anyway it must // stay 1 unchanged here - //UDFInterlockedDecrement((PLONG)&(Vcb->VcbReference)); + //InterlockedDecrement((PLONG)&Vcb->VcbReference); UDFCloseResidual(IrpContext, Vcb); Vcb->VcbReference = 1; @@ -651,7 +586,7 @@ try_exit: NOTHING; } // Make sure there is no Vcb since it could go away if (Vcb->VcbReference) - UDFInterlockedDecrement((PLONG)&(Vcb->VcbReference)); + InterlockedDecrement((PLONG)&Vcb->VcbReference); // This procedure will also delete the volume device object if (UDFDismountVcb(IrpContext, Vcb, FALSE)) { UDFReleaseResource( &(Vcb->VcbResource) ); @@ -701,7 +636,7 @@ UDFCloseResidual( { // Deinitialize Non-alloc file if (Vcb->VcbReference) - UDFInterlockedDecrement((PLONG)&(Vcb->VcbReference)); + InterlockedDecrement((PLONG)&Vcb->VcbReference); UDFPrint(("UDFCloseResidual: NonAllocFileInfo %x\n", Vcb->NonAllocFileInfo)); if (Vcb->NonAllocFileInfo) { UDFCloseFile__(IrpContext, Vcb, Vcb->NonAllocFileInfo); @@ -768,7 +703,7 @@ UDFCloseResidual( UDFTeardownStructures(IrpContext, Vcb->RootIndexFcb, 1, NULL); // Remove root FCB reference in vcb if (Vcb->VcbReference) - UDFInterlockedDecrement((PLONG)&(Vcb->VcbReference)); + InterlockedDecrement((PLONG)&Vcb->VcbReference); Vcb->RootIndexFcb = NULL; } } // end UDFCloseResidual() @@ -794,10 +729,7 @@ UDFCleanupVCB( DbgFreePool(Vcb->FSBM_Bitmap); Vcb->FSBM_Bitmap = NULL; } - if (Vcb->ZSBM_Bitmap) { - DbgFreePool(Vcb->ZSBM_Bitmap); - Vcb->ZSBM_Bitmap = NULL; - } + if (Vcb->BSBM_Bitmap) { DbgFreePool(Vcb->BSBM_Bitmap); Vcb->BSBM_Bitmap = NULL; @@ -1378,8 +1310,7 @@ UDFGetVolumeBitmap( { // NTSTATUS RC; - PEXTENDED_IO_STACK_LOCATION IrpSp = - (PEXTENDED_IO_STACK_LOCATION)IoGetCurrentIrpStackLocation( Irp ); + PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); UDFPrint(("UDFGetVolumeBitmap\n")); @@ -1398,7 +1329,6 @@ UDFGetVolumeBitmap( ULONG i, lim; PULONG FSBM; // PULONG Dest; - ULONG LSh; // Decode the file object, the only type of opens we accept are // user volume opens. @@ -1480,11 +1410,11 @@ UDFGetVolumeBitmap( RtlZeroMemory( &OutputBuffer->Buffer[0], BytesToCopy ); lim = BytesToCopy * 8; FSBM = (PULONG)(Vcb->FSBM_Bitmap); - LSh = Vcb->LB2B_Bits; + // Dest = (PULONG)(&OutputBuffer->Buffer[0]); for(i=StartingCluster & ~7; iSectorShift)) UDFSetFreeBit(FSBM, i); } @@ -1526,8 +1456,7 @@ UDFGetRetrievalPointers( { NTSTATUS RC; - PEXTENDED_IO_STACK_LOCATION IrpSp = - (PEXTENDED_IO_STACK_LOCATION)IoGetCurrentIrpStackLocation( Irp ); + PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); PUDF_FILE_INFO FileInfo; ULONG InputBufferLength; @@ -1548,7 +1477,6 @@ UDFGetRetrievalPointers( ULONG i; ULONG LBS; ULONG LBSh; - ULONG L2BSh; UDFPrint(("UDFGetRetrievalPointers\n")); @@ -1628,9 +1556,8 @@ UDFGetRetrievalPointers( AllocationSize = UDFGetFileAllocationSize(Vcb, FileInfo); - LBS = Vcb->LBlockSize; - LBSh = Vcb->LBlockSizeBits; - L2BSh = Vcb->LB2B_Bits; + LBS = Vcb->SectorSize; + LBSh = Vcb->SectorShift; if (StartingVcn.HighPart || StartingVcn.LowPart >= (ULONG)(AllocationSize >> LBSh)) { @@ -1656,10 +1583,10 @@ UDFGetRetrievalPointers( OutputBuffer->Extents[i].Lcn.QuadPart = (int64)(-1); } else if (SubMapping[i].extLocation & 0x80000000) { - OutputBuffer->Extents[i].Lcn.LowPart = (SubMapping[i].extLocation & 0x7fffffff) >> L2BSh; + OutputBuffer->Extents[i].Lcn.LowPart = (SubMapping[i].extLocation & 0x7fffffff) >> Vcb->SectorShift; OutputBuffer->Extents[i].Lcn.HighPart = 0x80000000; } else { - OutputBuffer->Extents[i].Lcn.LowPart = SubMapping[i].extLocation >> L2BSh; + OutputBuffer->Extents[i].Lcn.LowPart = SubMapping[i].extLocation >> Vcb->SectorShift; OutputBuffer->Extents[i].Lcn.HighPart = 0; } // alignment for last sector @@ -1867,6 +1794,8 @@ UDFInvalidateVolumes( // off immediately. IoAcquireVpbSpinLock(&SavedIrql); +#pragma prefast(push) +#pragma prefast(disable: 28175, "this is a filesystem driver, touching the vpb is allowed") if (DeviceToMarkBad->Vpb == Vcb->Vpb) { PVPB NewVpb = Vcb->SwapVpb; @@ -1880,11 +1809,13 @@ UDFInvalidateVolumes( NewVpb->Size = sizeof(VPB); NewVpb->RealDevice = DeviceToMarkBad; NewVpb->Flags = FlagOn(DeviceToMarkBad->Vpb->Flags, VPB_REMOVE_PENDING); - DeviceToMarkBad->Vpb = NewVpb; + Vcb->SwapVpb = NULL; } +#pragma prefast(pop) + IoReleaseVpbSpinLock(SavedIrql); if (Vcb->VcbCondition != VcbDismountInProgress) { diff --git a/drivers/filesystems/udfs/lockctrl.cpp b/drivers/filesystems/udfs/lockctrl.cpp index ff9f0f8894433..60f52a880cf62 100644 --- a/drivers/filesystems/udfs/lockctrl.cpp +++ b/drivers/filesystems/udfs/lockctrl.cpp @@ -19,70 +19,6 @@ // define the file specific bug-check id #define UDF_BUG_CHECK_ID UDF_FILE_SHUTDOWN - -/************************************************************************* -* -* Function: UDFLockControl() -* -* Description: -* -* Expected Interrupt Level (for execution) : -* -* IRQL_PASSIVE_LEVEL -* -* Return Value: Irrelevant. -* -*************************************************************************/ -NTSTATUS -NTAPI -UDFLockControl( - IN PDEVICE_OBJECT DeviceObject, // the logical volume device object - IN PIRP Irp) // I/O Request Packet -{ - NTSTATUS RC = STATUS_SUCCESS; - PIRP_CONTEXT IrpContext = NULL; - BOOLEAN AreWeTopLevel = FALSE; - - UDFPrint(("UDFLockControl\n")); -// BrutePoint(); - - FsRtlEnterFileSystem(); - ASSERT(DeviceObject); - ASSERT(Irp); - - // set the top level context - AreWeTopLevel = UDFIsIrpTopLevel(Irp); - // Call the common Lock Control routine, with blocking allowed if - // synchronous - _SEH2_TRY { - - // get an IRP context structure and issue the request - IrpContext = UDFCreateIrpContext(Irp, DeviceObject); - if (IrpContext) { - RC = UDFCommonLockControl(IrpContext, Irp); - } else { - - UDFCompleteRequest(IrpContext, Irp, STATUS_INSUFFICIENT_RESOURCES); - RC = STATUS_INSUFFICIENT_RESOURCES; - } - - } _SEH2_EXCEPT(UDFExceptionFilter(IrpContext, _SEH2_GetExceptionInformation())) { - - RC = UDFProcessException(IrpContext, Irp); - - UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC); - } _SEH2_END; - - if (AreWeTopLevel) { - IoSetTopLevelIrp(NULL); - } - - FsRtlExitFileSystem(); - - return(RC); -} // end UDFLockControl() - - /************************************************************************* * * Function: UDFCommonLockControl() @@ -104,16 +40,11 @@ UDFCommonLockControl( IN PIRP_CONTEXT IrpContext, IN PIRP Irp) { - NTSTATUS RC = STATUS_SUCCESS; + NTSTATUS Status = STATUS_SUCCESS; PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); - //IO_STATUS_BLOCK LocalIoStatus; -// BOOLEAN CompleteRequest = FALSE; - BOOLEAN PostRequest = FALSE; - BOOLEAN CanWait = FALSE; - BOOLEAN AcquiredFCB = FALSE; TYPE_OF_OPEN TypeOfOpen; - PFCB Fcb = NULL; - PCCB Ccb = NULL; + PFCB Fcb = NULL; + PCCB Ccb = NULL; UDFPrint(("UDFCommonLockControl\n")); @@ -124,60 +55,55 @@ UDFCommonLockControl( ASSERT_CCB(Ccb); ASSERT_FCB(Fcb); - _SEH2_TRY { + // If the file is not a user file open then we reject the request + // as an invalid parameter - // Validate the sent-in FCB - if ( (Fcb == Fcb->Vcb->VolumeDasdFcb) || - (Fcb->FcbState & UDF_FCB_DIRECTORY)) { + if (TypeOfOpen != UserFileOpen) { -// CompleteRequest = TRUE; - try_return(RC = STATUS_INVALID_PARAMETER); - } + UDFCompleteRequest(IrpContext, Irp, STATUS_INVALID_PARAMETER); + return STATUS_INVALID_PARAMETER; + } - CanWait = ((IrpContext->Flags & IRP_CONTEXT_FLAG_WAIT) ? TRUE : FALSE); + UDFAcquireFcbShared(IrpContext, Fcb, FALSE); - // Acquire the FCB resource shared - UDF_CHECK_PAGING_IO_RESOURCE(Fcb); - if (!UDFAcquireResourceExclusive(&Fcb->FcbNonpaged->FcbResource, CanWait)) { - PostRequest = TRUE; - try_return(RC = STATUS_PENDING); - } - AcquiredFCB = TRUE; + _SEH2_TRY { + + UDFVerifyFcbOperation(IrpContext, Fcb, Ccb); // If we don't have a file lock, then get one now. - if ((Fcb->FileLock == NULL) && !UDFCreateFileLock(NULL, Fcb, FALSE)) { + if (Fcb->FileLock == NULL) { if (!UDFCreateFileLock(NULL, Fcb, FALSE)) { - try_return(RC = STATUS_INSUFFICIENT_RESOURCES); + try_return(Status = STATUS_INSUFFICIENT_RESOURCES); } } - RC = FsRtlProcessFileLock(Fcb->FileLock, Irp, NULL); -// CompleteRequest = TRUE; + // Now call the FsRtl routine to do the actual processing of the + // Lock request + + Status = FsRtlProcessFileLock(Fcb->FileLock, Irp, NULL); + + // Set the flag indicating if Fast I/O is possible + + //TODO: impl + //UDFLockFcb(IrpContext, Fcb); + Fcb->Header.IsFastIoPossible = UDFIsFastIoPossible(Fcb); + //UDFUnlockFcb(IrpContext, Fcb); try_exit: NOTHING; } _SEH2_FINALLY { - // Release the FCB resources if acquired. - if (AcquiredFCB) { - UDF_CHECK_PAGING_IO_RESOURCE(Fcb); - UDFReleaseResource(&Fcb->FcbNonpaged->FcbResource); - AcquiredFCB = FALSE; - } - if (PostRequest) { - // Perform appropriate post related processing here - RC = UDFPostRequest(IrpContext, Irp); - } else - if (!_SEH2_AbnormalTermination()) { - // Simply free up the IrpContext since the IRP has been queued or - // Completed by FsRtlProcessFileLock - UDFCleanupIrpContext(IrpContext); - } + UDFReleaseFcb(IrpContext, Fcb); + } _SEH2_END; // end of "__finally" processing - return(RC); + // Complete the request. + + UDFCompleteRequest(IrpContext, NULL, Status); + + return Status; } // end UDFCommonLockControl() diff --git a/drivers/filesystems/udfs/misc.cpp b/drivers/filesystems/udfs/misc.cpp index 39a2e0dfb8b8e..1c3d198845ed7 100644 --- a/drivers/filesystems/udfs/misc.cpp +++ b/drivers/filesystems/udfs/misc.cpp @@ -23,6 +23,13 @@ #define FSP_PER_DEVICE_THRESHOLD (2) +#define UDFAllocateIoContext() \ + FsRtlAllocatePoolWithTag(NonPagedPool, \ + sizeof(UDF_IO_CONTEXT), \ + TAG_IO_CONTEXT) + +#define UDFFreeIoContext(IO) ExFreePool( &(IO) ) + /* Function: UDFInitializeZones() @@ -172,41 +179,6 @@ VOID UDFDestroyZones(VOID) ExDeletePagedLookasideList(&UdfData.CcbLookasideList); } - -/************************************************************************* -* -* Function: UDFIsIrpTopLevel() -* -* Description: -* Helps the FSD determine who the "top level" caller is for this -* request. A request can originate directly from a user process -* (in which case, the "top level" will be NULL when this routine -* is invoked), OR the user may have originated either from the NT -* Cache Manager/VMM ("top level" may be set), or this could be a -* recursion into our code in which we would have set the "top level" -* field the last time around. -* -* Expected Interrupt Level (for execution) : -* -* whatever level a particular dispatch routine is invoked at. -* -* Return Value: TRUE/FALSE (TRUE if top level was NULL when routine invoked) -* -*************************************************************************/ -BOOLEAN -__fastcall -UDFIsIrpTopLevel( - PIRP Irp) // the IRP sent to our dispatch routine -{ - if (!IoGetTopLevelIrp()) { - // OK, so we can set ourselves to become the "top level" component - IoSetTopLevelIrp(Irp); - return TRUE; - } - return FALSE; -} - - /************************************************************************* * * Function: UDFExceptionFilter() @@ -231,52 +203,26 @@ UDFIsIrpTopLevel( * Return Value: EXCEPTION_EXECUTE_HANDLER/EXECEPTION_CONTINUE_SEARCH * *************************************************************************/ -long +LONG UDFExceptionFilter( PIRP_CONTEXT IrpContext, PEXCEPTION_POINTERS ExceptionPointer ) { - long ReturnCode = EXCEPTION_EXECUTE_HANDLER; - NTSTATUS ExceptionCode = STATUS_SUCCESS; -#if defined UDF_DBG || defined PRINT_ALWAYS - ULONG i; - - UDFPrint(("UDFExceptionFilter\n")); - UDFPrint((" Ex. Code: %x\n",ExceptionPointer->ExceptionRecord->ExceptionCode)); - UDFPrint((" Ex. Addr: %x\n",ExceptionPointer->ExceptionRecord->ExceptionAddress)); - UDFPrint((" Ex. Flag: %x\n",ExceptionPointer->ExceptionRecord->ExceptionFlags)); - UDFPrint((" Ex. Pnum: %x\n",ExceptionPointer->ExceptionRecord->NumberParameters)); - for(i=0;iExceptionRecord->NumberParameters;i++) { - UDFPrint((" %x\n",ExceptionPointer->ExceptionRecord->ExceptionInformation[i])); - } -#ifdef _X86_ - UDFPrint(("Exception context:\n")); - if (ExceptionPointer->ContextRecord->ContextFlags & CONTEXT_INTEGER) { - UDFPrint(("EAX=%8.8x ",ExceptionPointer->ContextRecord->Eax)); - UDFPrint(("EBX=%8.8x ",ExceptionPointer->ContextRecord->Ebx)); - UDFPrint(("ECX=%8.8x ",ExceptionPointer->ContextRecord->Ecx)); - UDFPrint(("EDX=%8.8x\n",ExceptionPointer->ContextRecord->Edx)); - - UDFPrint(("ESI=%8.8x ",ExceptionPointer->ContextRecord->Esi)); - UDFPrint(("EDI=%8.8x ",ExceptionPointer->ContextRecord->Edi)); - } - if (ExceptionPointer->ContextRecord->ContextFlags & CONTEXT_CONTROL) { - UDFPrint(("EBP=%8.8x ",ExceptionPointer->ContextRecord->Esp)); - UDFPrint(("ESP=%8.8x\n",ExceptionPointer->ContextRecord->Ebp)); - - UDFPrint(("EIP=%8.8x\n",ExceptionPointer->ContextRecord->Eip)); - } -// UDFPrint(("Flags: %s %s ",ExceptionPointer->ContextRecord->Eip)); -#endif //_X86_ + NTSTATUS ExceptionCode; -#endif // UDF_DBG + ASSERT_OPTIONAL_IRP_CONTEXT(IrpContext); - // figure out the exception code ExceptionCode = ExceptionPointer->ExceptionRecord->ExceptionCode; - if ((ExceptionCode == STATUS_IN_PAGE_ERROR) && (ExceptionPointer->ExceptionRecord->NumberParameters >= 3)) { - ExceptionCode = (NTSTATUS)ExceptionPointer->ExceptionRecord->ExceptionInformation[2]; + // If the exception is STATUS_IN_PAGE_ERROR, get the I/O error code + // from the exception record. + + if ((ExceptionCode == STATUS_IN_PAGE_ERROR) && + (ExceptionPointer->ExceptionRecord->NumberParameters >= 3)) { + + ExceptionCode = + (NTSTATUS)ExceptionPointer->ExceptionRecord->ExceptionInformation[2]; } if (IrpContext) { @@ -293,13 +239,12 @@ UDFExceptionFilter( } else { // we are not ok, propagate this exception. // NOTE: we will bring down the machine ... - ReturnCode = EXCEPTION_CONTINUE_SEARCH; + //ReturnCode = EXCEPTION_CONTINUE_SEARCH; + BrutePoint(); } } - - // return the appropriate code - return(ReturnCode); + return EXCEPTION_EXECUTE_HANDLER; } // end UDFExceptionFilter() @@ -323,85 +268,111 @@ UDFExceptionFilter( * Return Value: Error code * *************************************************************************/ +_Requires_lock_held_(_Global_critical_region_) NTSTATUS UDFProcessException( - PIRP_CONTEXT IrpContext, - PIRP Irp + _In_opt_ PIRP_CONTEXT IrpContext, + _Inout_ PIRP Irp, + _In_ NTSTATUS ExceptionCode ) { -// NTSTATUS RC; - NTSTATUS ExceptionCode = STATUS_INSUFFICIENT_RESOURCES; - PDEVICE_OBJECT Device; + PDEVICE_OBJECT Device; PVPB Vpb; PETHREAD Thread; - UDFPrint(("UDFExceptionHandler \n")); + ASSERT_OPTIONAL_IRP_CONTEXT(IrpContext); + ASSERT_IRP(Irp); -// ASSERT(Irp); + // If there is not an irp context, then complete the request with the + // current status code. - if (!Irp) { - UDFPrint((" !Irp, return\n")); - ASSERT(!IrpContext); + if (!ARGUMENT_PRESENT(IrpContext)) { + + UDFCompleteRequest(NULL, Irp, ExceptionCode); return ExceptionCode; } - // If it was a queued close (or something like this) then we need not - // completing it because of MUST_SUCCEED requirement. - if (IrpContext) { - ExceptionCode = IrpContext->ExceptionStatus; - // Free irp context here -// UDFReleaseIrpContext(IrpContext); - } else { - UDFPrint((" complete Irp and return\n")); - // must be insufficient resources ...? - ExceptionCode = STATUS_INSUFFICIENT_RESOURCES; - Irp->IoStatus.Status = ExceptionCode; - Irp->IoStatus.Information = 0; - // complete the IRP - IoCompleteRequest(Irp, IO_NO_INCREMENT); + // Get the real exception status from the IrpContext. - return ExceptionCode; + ExceptionCode = IrpContext->ExceptionStatus; + + // If this is an Mdl write request, then take care of the Mdl + // here so that things get cleaned up properly. Cc now leaves + // the MDL in place so a filesystem can retry after clearing an + // internal condition (FAT does not). + + if ((IrpContext->MajorFunction == IRP_MJ_WRITE) && + (FlagOn(IrpContext->MinorFunction, IRP_MN_COMPLETE_MDL) == IRP_MN_COMPLETE_MDL) && + (Irp->MdlAddress != NULL)) { + + PIO_STACK_LOCATION LocalIrpSp = IoGetCurrentIrpStackLocation(Irp); + + CcMdlWriteAbort(LocalIrpSp->FileObject, Irp->MdlAddress); + Irp->MdlAddress = NULL; } - // Check if we are posting this request. One of the following must be true - // if we are to post a request. + // Check if we are posting this request. One of the following must be true + // if we are to post a request. // - // - Status code is STATUS_CANT_WAIT and the request is asynchronous - // or we are forcing this to be posted. + // - Status code is STATUS_CANT_WAIT and the request is asynchronous + // or we are forcing this to be posted. // - // - Status code is STATUS_VERIFY_REQUIRED and we are at APC level - // or higher. Can't wait for IO in the verify path in this case. + // - Status code is STATUS_VERIFY_REQUIRED and we are at APC level + // or higher, or within a guarded region. Can't wait for IO in + // the verify path in this case. // - // Set the MORE_PROCESSING flag in the IrpContext to keep if from being - // deleted if this is a retryable condition. + // Set the MORE_PROCESSING flag in the IrpContext to keep if from being + // deleted if this is a retryable condition. + + // Note that (children of) UDFFsdPostRequest can raise (Mdl allocation). - if (ExceptionCode == STATUS_VERIFY_REQUIRED) { - if (KeGetCurrentIrql() >= APC_LEVEL) { - UDFPrint((" use UDFPostRequest()\n")); - ExceptionCode = UDFPostRequest(IrpContext, Irp); + _SEH2_TRY { + + if (ExceptionCode == STATUS_CANT_WAIT) { + + if (FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_FORCE_POST)) { + + ExceptionCode = UDFFsdPostRequest(IrpContext, Irp); + } + } + else if ((ExceptionCode == STATUS_VERIFY_REQUIRED) && + FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_TOP_LEVEL) && + KeAreAllApcsDisabled()) { + + ExceptionCode = UDFFsdPostRequest(IrpContext, Irp); } - } - // If we posted the request or our caller will retry then just return here. + } _SEH2_EXCEPT(UDFExceptionFilter(IrpContext, _SEH2_GetExceptionInformation())) { + + ExceptionCode = GetExceptionCode(); + } _SEH2_END; + + // If we posted the request or our caller will retry then just return here. + if ((ExceptionCode == STATUS_PENDING) || (ExceptionCode == STATUS_CANT_WAIT)) { - UDFPrint((" STATUS_PENDING/STATUS_CANT_WAIT, return\n")); return ExceptionCode; } - // Store this error into the Irp for posting back to the Io system. + ClearFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_MORE_PROCESSING); + + // Store this error into the Irp for posting back to the Io system. + Irp->IoStatus.Status = ExceptionCode; - if (IoIsErrorUserInduced( ExceptionCode )) { - // Check for the various error conditions that can be caused by, - // and possibly resolved my the user. + if (IoIsErrorUserInduced(ExceptionCode)) { + + // Check for the various error conditions that can be caused by, + // and possibly resolved my the user. + if (ExceptionCode == STATUS_VERIFY_REQUIRED) { - // Now we are at the top level file system entry point. + // Now we are at the top level file system entry point. // - // If we have already posted this request then the device to - // verify is in the original thread. Find this via the Irp. + // If we have already posted this request then the device to + // verify is in the original thread. Find this via the Irp. + Device = IoGetDeviceToVerify( Irp->Tail.Overlay.Thread ); IoSetDeviceToVerify( Irp->Tail.Overlay.Thread, NULL ); @@ -417,14 +388,9 @@ UDFProcessException( // Let's not BugCheck just because the driver screwed up. if (Device == NULL) { - UDFPrint((" Device == NULL, return\n")); ExceptionCode = STATUS_DRIVER_INTERNAL_ERROR; - Irp->IoStatus.Status = ExceptionCode; - Irp->IoStatus.Information = 0; - // complete the IRP - IoCompleteRequest(Irp, IO_NO_INCREMENT); - UDFCleanupIrpContext(IrpContext); + UDFCompleteRequest(IrpContext, Irp, ExceptionCode); return ExceptionCode; } @@ -437,10 +403,8 @@ UDFProcessException( return UDFPerformVerify( IrpContext, Irp, Device ); } - // - // The other user induced conditions generate an error unless - // they have been disabled for this request. - // + // The other user induced conditions generate an error unless + // they have been disabled for this request. if (FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DISABLE_POPUPS)) { @@ -472,13 +436,8 @@ UDFProcessException( // Let's not BugCheck just because the driver screwed up. if (Device == NULL) { - UDFPrint((" Device == NULL, return(2)\n")); - Irp->IoStatus.Status = ExceptionCode; - Irp->IoStatus.Information = 0; - // complete the IRP - IoCompleteRequest(Irp, IO_NO_INCREMENT); - UDFCleanupIrpContext(IrpContext); + UDFCompleteRequest(IrpContext, Irp, ExceptionCode); return ExceptionCode; } @@ -488,76 +447,31 @@ UDFProcessException( // does this by queuing an APC to the callers thread, // but in some cases it will complete the request immediately, // so it is very important to IoMarkIrpPending() first. - IoMarkIrpPending( Irp ); - IoRaiseHardError( Irp, Vpb, Device ); - // We will be handing control back to the caller here, so - // reset the saved device object. + IoMarkIrpPending(Irp); + IoRaiseHardError(Irp, Vpb, Device); - UDFPrint((" use IoSetDeviceToVerify()\n")); - IoSetDeviceToVerify( Thread, NULL ); - // The Irp will be completed by Io or resubmitted. In either - // case we must clean up the IrpContext here. + // We will be handing control back to the caller here, so + // reset the saved device object. - UDFCleanupIrpContext(IrpContext); + IoSetDeviceToVerify(Thread, NULL); + + // The Irp will be completed by Io or resubmitted. In either + // case we must clean up the IrpContext here. + + UDFCompleteRequest(IrpContext, NULL, STATUS_SUCCESS); return STATUS_PENDING; } } // If it was a normal request from IOManager then complete it - if (Irp) { - UDFPrint((" complete Irp\n")); - // set the error code in the IRP - Irp->IoStatus.Status = ExceptionCode; - Irp->IoStatus.Information = 0; - // complete the IRP - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - UDFCleanupIrpContext(IrpContext); - } + UDFCompleteRequest(IrpContext, Irp, ExceptionCode); UDFPrint((" return from exception handler with code %x\n", ExceptionCode)); return(ExceptionCode); } // end UDFExceptionHandler() -/************************************************************************* -* -* Function: UDFLogEvent() -* -* Description: -* Log a message in the NT Event Log. This is a rather simplistic log -* methodology since we can potentially utilize the event log to -* provide a lot of information to the user (and you should too!) -* -* Expected Interrupt Level (for execution) : -* -* IRQL_PASSIVE_LEVEL -* -* Return Value: None -* -*************************************************************************/ -VOID -UDFLogEvent( - NTSTATUS UDFEventLogId, // the UDF private message id - NTSTATUS RC) // any NT error code we wish to log ... -{ - _SEH2_TRY { - - // Implement a call to IoAllocateErrorLogEntry() followed by a call - // to IoWriteErrorLogEntry(). You should note that the call to IoWriteErrorLogEntry() - // will free memory for the entry once the write completes (which in actuality - // is an asynchronous operation). - - } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { - // nothing really we can do here, just do not wish to crash ... - NOTHING; - } _SEH2_END; - - return; -} // end UDFLogEvent() - - /************************************************************************* * * Function: UDFAllocateObjectName() @@ -707,10 +621,9 @@ UDFDeleteCcb( _SEH2_TRY { if (Ccb->Fcb) { - UDFTouch(&(Ccb->Fcb->CcbListResource)); - UDFAcquireResourceExclusive(&(Ccb->Fcb->CcbListResource),TRUE); + UDFAcquireResourceExclusive(&Ccb->Fcb->FcbNonpaged->CcbListResource, TRUE); RemoveEntryList(&(Ccb->NextCCB)); - UDFReleaseResource(&(Ccb->Fcb->CcbListResource)); + UDFReleaseResource(&Ccb->Fcb->FcbNonpaged->CcbListResource); } else { BrutePoint(); } @@ -748,10 +661,10 @@ UDFDeleteCcb( * Return Value: A pointer to the IrpContext structure OR NULL. * *************************************************************************/ -PIRP_CONTEXT +_Ret_valid_ PIRP_CONTEXT UDFCreateIrpContext( - PIRP Irp, - PDEVICE_OBJECT PtrTargetDeviceObject + _In_ PIRP Irp, + _In_ BOOLEAN Wait ) { ASSERT(Irp); @@ -801,14 +714,19 @@ UDFCreateIrpContext( // Set the originating Irp field NewIrpContext->Irp = Irp; - NewIrpContext->RealDevice = PtrTargetDeviceObject; + // Copy RealDevice for workque algorithms. We will update this in the Mount or + // Verify since they have no file objects to use here. + + if (IrpSp->FileObject != NULL) { + + NewIrpContext->RealDevice = IrpSp->FileObject->DeviceObject; + } // TODO: fix if (false && IrpSp->FileObject != NULL) { PFILE_OBJECT FileObject = IrpSp->FileObject; - ASSERT(FileObject->DeviceObject == PtrTargetDeviceObject); NewIrpContext->RealDevice = FileObject->DeviceObject; // @@ -838,18 +756,15 @@ UDFCreateIrpContext( NewIrpContext->MajorFunction = IrpSp->MajorFunction; NewIrpContext->MinorFunction = IrpSp->MinorFunction; - // Often, a FSD cannot honor a request for asynchronous processing - // of certain critical requests. For example, a "close" request on - // a file object can typically never be deferred. Therefore, do not - // be surprised if sometimes our FSD (just like all other FSD - // implementations on the Windows NT system) has to override the flag - // below. - if (IrpSp->FileObject == NULL) { - NewIrpContext->Flags |= IRP_CONTEXT_FLAG_WAIT; + // Set the wait parameter + + if (Wait) { + + SetFlag(NewIrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); + } else { - if (IoIsOperationSynchronous(Irp)) { - NewIrpContext->Flags |= IRP_CONTEXT_FLAG_WAIT; - } + + SetFlag(NewIrpContext->Flags, IRP_CONTEXT_FLAG_FORCE_POST); } // Are we top-level ? This information is used by the dispatching code @@ -862,34 +777,81 @@ UDFCreateIrpContext( return NewIrpContext; } // end UDFCreateIrpContext() - -/************************************************************************* -* -* Function: UDFCleanupIrpContext() -* -* Description: -* Deallocate a previously allocated structure. -* -* Expected Interrupt Level (for execution) : -* -* IRQL_PASSIVE_LEVEL -* -* Return Value: None -* -*************************************************************************/ VOID UDFCleanupIrpContext( _In_ PIRP_CONTEXT IrpContext, _In_ BOOLEAN Post ) + +/*++ + +Routine Description: + + This routine is called to cleanup and possibly deallocate the Irp Context. + If the request is being posted or this Irp Context is possibly on the + stack then we only cleanup any auxilary structures. + +Arguments: + + Post - TRUE if we are posting this request, FALSE if we are deleting + or retrying this in the current thread. + +Return Value: + + None. + +--*/ + { - ASSERT(IrpContext); + PAGED_CODE(); - if (!FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_ON_STACK)) { + // If we aren't doing more processing then deallocate this as appropriate. - ExFreeToNPagedLookasideList(&UdfData.IrpContextLookasideList, IrpContext); + if (!FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_MORE_PROCESSING)) { + + // If this context is the top level UDFS context then we need to + // restore the top level thread context. + + if (IrpContext->ThreadContext != NULL) { + + UDFRestoreThreadContext(IrpContext); + } + + // Deallocate the Io context if allocated. + + if (FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_ALLOC_IO)) { + + UDFFreeIoContext(IrpContext->IoContext); + } + + // Deallocate the IrpContext if not from the stack. + + if (!FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_ON_STACK )) { + + ExFreeToNPagedLookasideList(&UdfData.IrpContextLookasideList, IrpContext); + } + + // Clear the appropriate flags. + + } else if (Post) { + + // If this context is the top level CDFS context then we need to + // restore the top level thread context. + + if (IrpContext->ThreadContext != NULL) { + + UDFRestoreThreadContext(IrpContext); + } + + ClearFlag(IrpContext->Flags, IRP_CONTEXT_FLAGS_CLEAR_ON_POST); + + } else { + + ClearFlag(IrpContext->Flags, IRP_CONTEXT_FLAGS_CLEAR_ON_RETRY); } -} // end UDFCleanupIrpContext() + + return; +} _When_(RaiseOnError || return, _At_(Fcb->FileLock, _Post_notnull_)) _When_(RaiseOnError, _At_(IrpContext, _Pre_notnull_)) @@ -964,9 +926,123 @@ Return Value: return Result; } +_Requires_lock_held_(_Global_critical_region_) +VOID +UDFPrePostIrp( + _Inout_ PIRP_CONTEXT IrpContext, + _Inout_ PIRP Irp + ) + +/*++ + +Routine Description: + + This routine performs any neccessary work before STATUS_PENDING is + returned with the Fsd thread. This routine is called within the + filesystem and by the oplock package. + +Arguments: + + Context - Pointer to the IrpContext to be queued to the Fsp + + Irp - I/O Request Packet. + +Return Value: + + None. + +--*/ + +{ + PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); + BOOLEAN RemovedFcb; + + PAGED_CODE(); + + ASSERT_IRP_CONTEXT(IrpContext); + ASSERT_IRP(Irp); + + // Case on the type of the operation. + + switch (IrpContext->MajorFunction) { + + case IRP_MJ_CREATE : + + // If called from the oplock package then there is an + // Fcb to possibly teardown. We will call the teardown + // routine and release the Fcb if still present. The cleanup + // code in create will know not to release this Fcb because + // we will clear the pointer. + + if ((IrpContext->TeardownFcb != NULL) && + *(IrpContext->TeardownFcb) != NULL) { + + //TODO: Impl + ASSERT(FALSE); + RemovedFcb = FALSE; //TODO: temp init + + //UDFTeardownStructures( IrpContext, *(IrpContext->TeardownFcb), &RemovedFcb ); + + if (!RemovedFcb) { + + _Analysis_assume_lock_held_((*IrpContext->TeardownFcb)->FcbNonpaged->FcbResource); + UDFReleaseFcb(IrpContext, *(IrpContext->TeardownFcb)); + } + + *(IrpContext->TeardownFcb) = NULL; + IrpContext->TeardownFcb = NULL; + } + + break; + + // We need to lock the user's buffer, unless this is an MDL read/write, + // in which case there is no user buffer. + + case IRP_MJ_READ : + + if (!FlagOn( IrpContext->MinorFunction, IRP_MN_MDL)) { + + UDFLockUserBuffer(IrpContext, IrpSp->Parameters.Read.Length, IoWriteAccess); + } + + break; + + case IRP_MJ_WRITE : + + if (!FlagOn(IrpContext->MinorFunction, IRP_MN_MDL)) { + + UDFLockUserBuffer(IrpContext, IrpSp->Parameters.Read.Length, IoReadAccess); + } + + break; + + // We also need to check whether this is a query file operation. + + case IRP_MJ_DIRECTORY_CONTROL : + + if (IrpContext->MinorFunction == IRP_MN_QUERY_DIRECTORY) { + + UDFLockUserBuffer(IrpContext, IrpSp->Parameters.QueryDirectory.Length, IoWriteAccess); + } + + break; + } + + // Cleanup the IrpContext for the post. + + SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_MORE_PROCESSING); + UDFCleanupIrpContext(IrpContext, TRUE); + + // Mark the Irp to show that we've already returned pending to the user. + + IoMarkIrpPending(Irp); + + return; +} + /************************************************************************* * -* Function: UDFPostRequest() +* Function: UDFAddToWorkque() * * Description: * Queue up a request for deferred processing (in the context of a system @@ -976,11 +1052,11 @@ Return Value: * * IRQL_PASSIVE_LEVEL * -* Return Value: STATUS_PENDING +* Return Value: None * *************************************************************************/ -NTSTATUS -UDFPostRequest( +VOID +UDFAddToWorkque( IN PIRP_CONTEXT IrpContext, IN PIRP Irp ) @@ -989,10 +1065,6 @@ UDFPostRequest( KIRQL SavedIrql; PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); - // mark the IRP pending if this is not double post - if (Irp) - IoMarkIrpPending(Irp); - // Check if this request has an associated file object, and thus volume // device object. @@ -1019,7 +1091,7 @@ UDFPostRequest( KeReleaseSpinLock(&Vdo->OverflowQueueSpinLock, SavedIrql); - return STATUS_PENDING; + return; } else { @@ -1043,9 +1115,54 @@ UDFPostRequest( #pragma prefast(suppress: 28159, "prefast believes this routine is obsolete, but it is ok for CDFS to continue using it") ExQueueWorkItem(&IrpContext->WorkQueueItem, CriticalWorkQueue); - return STATUS_PENDING; -} // end UDFPostRequest() + return; +} // end UDFAddToWorkque() + +_Requires_lock_held_(_Global_critical_region_) +NTSTATUS +UDFFsdPostRequest( + _Inout_ PIRP_CONTEXT IrpContext, + _Inout_ PIRP Irp + ) + +/*++ +Routine Description: + + This routine enqueues the request packet specified by IrpContext to the + work queue associated with the FileSystemDeviceObject. This is a FSD + routine. + +Arguments: + + IrpContext - Pointer to the IrpContext to be queued to the Fsp. + + Irp - I/O Request Packet. + +Return Value: + + STATUS_PENDING + +--*/ + +{ + PAGED_CODE(); + + ASSERT_IRP_CONTEXT(IrpContext); + ASSERT_IRP(Irp); + + // Posting is a three step operation. First lock down any buffers + // in the Irp. Next cleanup the IrpContext for the post and finally + // add this to a workque. + + UDFPrePostIrp(IrpContext, Irp); + + UDFAddToWorkque(IrpContext, Irp); + + // And return to our caller + + return STATUS_PENDING; +} /************************************************************************* * @@ -1135,7 +1252,7 @@ UDFFspDispatch( case IRP_MJ_DEVICE_CONTROL: - Status = UDFCommonDeviceControl(IrpContext, Irp); + Status = UDFCommonDevControl(IrpContext, Irp); break; case IRP_MJ_READ: @@ -1165,7 +1282,7 @@ UDFFspDispatch( case IRP_MJ_FILE_SYSTEM_CONTROL: - Status = UDFCommonFSControl(IrpContext, Irp); + Status = UDFCommonFsControl(IrpContext, Irp); break; case IRP_MJ_LOCK_CONTROL: @@ -1207,7 +1324,7 @@ UDFFspDispatch( } _SEH2_EXCEPT(UDFExceptionFilter(IrpContext, _SEH2_GetExceptionInformation())) { - Status = UDFProcessException(IrpContext, Irp); + Status = UDFProcessException(IrpContext, Irp, _SEH2_GetExceptionCode()); } _SEH2_END; // Break out of the loop if we didn't get CANT_WAIT. @@ -1328,9 +1445,6 @@ UDFReadRegKeys( Vcb->DefaultRegName = REG_DEFAULT_UNKNOWN; - // Should we use Extended FE by default ? - Vcb->UseExtendedFE = (UCHAR)UDFGetParameter(Vcb, REG_USEEXTENDEDFE_NAME, - Update ? Vcb->UseExtendedFE : FALSE); // What type of AllocDescs should we use Vcb->DefaultAllocMode = (USHORT)UDFGetParameter(Vcb, REG_DEFALLOCMODE_NAME, Update ? Vcb->DefaultAllocMode : ICB_FLAG_AD_SHORT); @@ -1408,45 +1522,12 @@ UDFReadRegKeys( // Should we make a copy of VolumeLabel in LVD // usually only PVD is updated UDFUpdateCompatOption(Vcb, Update, UseCfg, UDF_W2K_COMPAT_VLABEL, UDF_VCB_IC_W2K_COMPAT_VLABEL, TRUE); - // Should we handle or ignore HW_RO flag - UDFUpdateCompatOption(Vcb, Update, UseCfg, UDF_HANDLE_HW_RO, UDF_VCB_IC_HW_RO, FALSE); - // Should we handle or ignore SOFT_RO flag - UDFUpdateCompatOption(Vcb, Update, UseCfg, UDF_HANDLE_SOFT_RO, UDF_VCB_IC_SOFT_RO, TRUE); // Should we ignore FO_SEQUENTIAL_ONLY UDFUpdateCompatOption(Vcb, Update, UseCfg, UDF_IGNORE_SEQUENTIAL_IO, UDF_VCB_IC_IGNORE_SEQUENTIAL_IO, FALSE); -// Force Read-only mounts - UDFUpdateCompatOption(Vcb, Update, UseCfg, UDF_FORCE_HW_RO, UDF_VCB_IC_FORCE_HW_RO, FALSE); - // compare data from packet with data to be writen there - // before physical writing - if (!UDFGetParameter(Vcb, UDF_COMPARE_BEFORE_WRITE, Update ? Vcb->DoNotCompareBeforeWrite : FALSE)) { - Vcb->DoNotCompareBeforeWrite = TRUE; - } else { - Vcb->DoNotCompareBeforeWrite = FALSE; - } if (!Update) { - if (UDFGetParameter(Vcb, UDF_CHAINED_IO, TRUE)) { - Vcb->CacheChainedIo = TRUE; - } - - // Should we show Blank.Cd file on damaged/unformatted, - // but UDF-compatible disks - Vcb->ShowBlankCd = (UCHAR)UDFGetParameter(Vcb, UDF_SHOW_BLANK_CD, FALSE); - if (Vcb->ShowBlankCd) { - Vcb->CompatFlags |= UDF_VCB_IC_SHOW_BLANK_CD; - if (Vcb->ShowBlankCd > 2) { - Vcb->ShowBlankCd = 2; - } - } - // Set partitially damaged volume mount mode - Vcb->PartitialDamagedVolumeAction = (UCHAR)UDFGetParameter(Vcb, UDF_PART_DAMAGED_BEHAVIOR, UDF_PART_DAMAGED_RW); - if (Vcb->PartitialDamagedVolumeAction > 2) { - Vcb->PartitialDamagedVolumeAction = UDF_PART_DAMAGED_RW; - } - - // Set partitially damaged volume mount mode Vcb->NoFreeRelocationSpaceVolumeAction = (UCHAR)UDFGetParameter(Vcb, UDF_NO_SPARE_BEHAVIOR, UDF_PART_DAMAGED_RW); if (Vcb->NoFreeRelocationSpaceVolumeAction > 1) { Vcb->NoFreeRelocationSpaceVolumeAction = UDF_PART_DAMAGED_RW; @@ -1494,7 +1575,7 @@ UDFDeleteVCB( delay.QuadPart = -500000; // 0.05 sec while(Vdo->PostedRequestCount) { - UDFPrint(("UDFDeleteVCB: PostedRequestCount = %d\n", Vcb->PostedRequestCount)); + UDFPrint(("UDFDeleteVCB: PostedRequestCount = %d\n", Vdo->PostedRequestCount)); // spin until all queues IRPs are processed KeDelayExecutionThread(KernelMode, FALSE, &delay); delay.QuadPart -= 500000; // grow delay 0.05 sec @@ -1545,7 +1626,7 @@ UDFDeleteVCB( _SEH2_TRY { UDFPrint(("UDF: Cleanup VCB\n")); ASSERT(IsListEmpty(&(Vcb->NextNotifyIRP))); - FsRtlNotifyUninitializeSync(&(Vcb->NotifyIRPMutex)); + FsRtlNotifyUninitializeSync(&Vcb->NotifySync); UDFCleanupVCB(Vcb); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { BrutePoint(); @@ -1871,7 +1952,7 @@ UDFSetModified( IN PVCB Vcb ) { - if (UDFInterlockedIncrement((PLONG) & (Vcb->Modified)) & 0x80000000) + if (InterlockedIncrement((PLONG) & (Vcb->Modified)) & 0x80000000) Vcb->Modified = 2; } // end UDFSetModified() @@ -1889,7 +1970,7 @@ UDFClrModified( ) { UDFPrint(("ClrModified\n")); - UDFInterlockedDecrement((PLONG) & (Vcb->Modified)); + InterlockedDecrement((PLONG)&Vcb->Modified); } // end UDFClrModified() NTSTATUS @@ -2073,9 +2154,7 @@ Return Value: SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_TOP_LEVEL_UDFS); - // // Otherwise use the IrpContext in the thread context. - // } else { diff --git a/drivers/filesystems/udfs/pnp.cpp b/drivers/filesystems/udfs/pnp.cpp index 968f6097e22a6..d28366fc4048b 100644 --- a/drivers/filesystems/udfs/pnp.cpp +++ b/drivers/filesystems/udfs/pnp.cpp @@ -57,76 +57,6 @@ UDFPnpCompletionRoutine ( IN PVOID Contxt ); -NTSTATUS -UDFCommonPnp ( - PIRP_CONTEXT IrpContext, - IN PIRP Irp - ); - -/* - This routine implements the FSD part of PnP operations - -Arguments: - - VolumeDeviceObject - Supplies the volume device object where the - file exists - Irp - Supplies the Irp being processed - -Return Value: - - NTSTATUS - The FSD status for the IRP - - */ -NTSTATUS -NTAPI -UDFPnp ( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ) -{ - NTSTATUS RC; - PIRP_CONTEXT IrpContext = NULL; - BOOLEAN AreWeTopLevel; - - UDFPrint(("UDFPnp\n")); - - FsRtlEnterFileSystem(); - ASSERT(DeviceObject); - ASSERT(Irp); - - // set the top level context - AreWeTopLevel = UDFIsIrpTopLevel(Irp); - - _SEH2_TRY { - // We expect there to never be a fileobject, in which case we will always - // wait. Since at the moment we don't have any concept of pending Pnp - // operations, this is a bit nitpicky. - - // get an IRP context structure and issue the request - IrpContext = UDFCreateIrpContext(Irp, DeviceObject); - if (IrpContext) { - RC = UDFCommonPnp(IrpContext, Irp); - } else { - - UDFCompleteRequest(IrpContext, Irp, STATUS_INSUFFICIENT_RESOURCES); - RC = STATUS_INSUFFICIENT_RESOURCES; - } - - } _SEH2_EXCEPT(UDFExceptionFilter( IrpContext, _SEH2_GetExceptionInformation() )) { - - RC = UDFProcessException(IrpContext, Irp); - UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC); - } _SEH2_END; - - if (AreWeTopLevel) { - IoSetTopLevelIrp(NULL); - } - - FsRtlExitFileSystem(); - - return RC; -} - /* This is the common routine for doing PnP operations called by both the fsd and fsp threads diff --git a/drivers/filesystems/udfs/protos.h b/drivers/filesystems/udfs/protos.h index 070bee1d10b52..ebed36f05d1c0 100644 --- a/drivers/filesystems/udfs/protos.h +++ b/drivers/filesystems/udfs/protos.h @@ -32,6 +32,13 @@ typedef enum _TYPE_OF_OPEN { } TYPE_OF_OPEN; +// The following macro is used to determine if an FSD thread can block +// for I/O or wait for a resource. It returns TRUE if the thread can +// block and FALSE otherwise. This attribute can then be used to call +// the FSD & FSP common work routine with the proper wait value. + +#define CanFsdWait(I) IoIsOperationSynchronous(I) + _When_(TypeOfOpen == UnopenedFileObject, _At_(Fcb, _In_opt_)) _When_(TypeOfOpen != UnopenedFileObject, _At_(Fcb, _In_)) VOID @@ -203,7 +210,7 @@ PDEVICE_OBJECT DeviceObject, // the logical volume device obj PIRP Irp); // I/O Request Packet NTSTATUS -UDFCommonDeviceControl( +UDFCommonDevControl( PIRP_CONTEXT IrpContext, PIRP Irp ); @@ -229,8 +236,11 @@ IN BOOLEAN CheckForReadOperation, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject); -extern FAST_IO_POSSIBLE NTAPI UDFIsFastIoPossible( -IN PFCB Fcb); +FAST_IO_POSSIBLE +NTAPI +UDFIsFastIoPossible( + IN PFCB Fcb + ); extern BOOLEAN NTAPI UDFFastIoQueryBasicInfo( IN PFILE_OBJECT FileObject, @@ -350,13 +360,6 @@ UDFFastIoCopyWrite( /************************************************************************* * Prototypes for the file fileinfo.cpp *************************************************************************/ -extern NTSTATUS NTAPI UDFQueryInfo( -PDEVICE_OBJECT DeviceObject, // the logical volume device object -PIRP Irp); // I/O Request Packet - -extern NTSTATUS NTAPI UDFSetInfo( -PDEVICE_OBJECT DeviceObject, // the logical volume device object -PIRP Irp); // I/O Request Packet extern NTSTATUS UDFCommonQueryInfo( PIRP_CONTEXT IrpContext, @@ -566,7 +569,7 @@ PDEVICE_OBJECT DeviceObject, PIRP Irp); NTSTATUS -UDFCommonFSControl( +UDFCommonFsControl( PIRP_CONTEXT IrpContext, PIRP Irp ); @@ -710,8 +713,28 @@ VOID); extern VOID UDFDestroyZones( VOID); -extern BOOLEAN __fastcall UDFIsIrpTopLevel( -PIRP Irp); // the IRP sent to our dispatch routine +_IRQL_requires_max_(APC_LEVEL) +__drv_dispatchType(DRIVER_DISPATCH) +__drv_dispatchType(IRP_MJ_CREATE) +__drv_dispatchType(IRP_MJ_CLOSE) +__drv_dispatchType(IRP_MJ_READ) +__drv_dispatchType(IRP_MJ_WRITE) +__drv_dispatchType(IRP_MJ_QUERY_INFORMATION) +__drv_dispatchType(IRP_MJ_SET_INFORMATION) +__drv_dispatchType(IRP_MJ_QUERY_VOLUME_INFORMATION) +__drv_dispatchType(IRP_MJ_DIRECTORY_CONTROL) +__drv_dispatchType(IRP_MJ_FILE_SYSTEM_CONTROL) +__drv_dispatchType(IRP_MJ_DEVICE_CONTROL) +__drv_dispatchType(IRP_MJ_LOCK_CONTROL) +__drv_dispatchType(IRP_MJ_CLEANUP) +__drv_dispatchType(IRP_MJ_PNP) +__drv_dispatchType(IRP_MJ_SHUTDOWN) +NTSTATUS +NTAPI +UDFFsdDispatch( + _In_ PDEVICE_OBJECT DeviceObject, + _Inout_ PIRP Irp + ); LONG UDFExceptionFilter( @@ -719,13 +742,13 @@ UDFExceptionFilter( PEXCEPTION_POINTERS ExceptionPointer ); -extern NTSTATUS UDFProcessException( -PIRP_CONTEXT IrpContext, -PIRP Irp); - -extern VOID UDFLogEvent( -NTSTATUS UDFEventLogId, // the UDF private message id -NTSTATUS RC); // any NT error code we wish to log ... +_Requires_lock_held_(_Global_critical_region_) +NTSTATUS +UDFProcessException( + _In_opt_ PIRP_CONTEXT IrpContext, + _Inout_ PIRP Irp, + _In_ NTSTATUS ExceptionCode + ); extern PtrUDFObjectName UDFAllocateObjectName( VOID); @@ -760,14 +783,16 @@ UDFDeleteFcb( VOID UDFCleanUpFCB(PFCB Fcb); -extern PIRP_CONTEXT UDFCreateIrpContext( -PIRP Irp, -PDEVICE_OBJECT PtrTargetDeviceObject); +_Ret_valid_ PIRP_CONTEXT +UDFCreateIrpContext( + _In_ PIRP Irp, + _In_ BOOLEAN Wait + ); VOID UDFCleanupIrpContext( _In_ PIRP_CONTEXT IrpContext, - _In_ BOOLEAN Post = FALSE + _In_ BOOLEAN Post ); VOID @@ -777,9 +802,18 @@ UDFCompleteRequest( _In_ NTSTATUS Status ); -extern NTSTATUS UDFPostRequest( -PIRP_CONTEXT IrpContext, -PIRP Irp); +VOID +UDFAddToWorkque( + PIRP_CONTEXT IrpContext, + PIRP Irp + ); + +_Requires_lock_held_(_Global_critical_region_) +NTSTATUS +UDFFsdPostRequest( + _Inout_ PIRP_CONTEXT IrpContext, + _Inout_ PIRP Irp +); VOID NTAPI @@ -787,12 +821,14 @@ UDFFspDispatch( PVOID Context ); -NTSTATUS +VOID UDFInitializeVCB( _In_ PIRP_CONTEXT IrpContext, _Inout_ PVCB Vcb, _In_ PDEVICE_OBJECT TargetDeviceObject, - _In_ PVPB Vpb + _In_ PVPB Vpb, + _In_ PDISK_GEOMETRY DiskGeometry, + _In_ ULONG MediaChangeCount ); VOID @@ -861,109 +897,6 @@ UDFCreateFileLock( #include "namesup.h" -/************************************************************************* -* Prototypes for the file Udf_info\physical.cpp -*************************************************************************/ -#if 0 - -extern NTSTATUS UDFTRead(PVOID _Vcb, - PVOID Buffer, // Target buffer - ULONG Length, - ULONG LBA, - PULONG ReadBytes, - ULONG Flags = 0); - -extern NTSTATUS UDFTWrite(IN PVOID _Vcb, - IN PVOID Buffer, // Target buffer - IN ULONG Length, - IN ULONG LBA, - OUT PULONG WrittenBytes, - IN ULONG Flags = 0); - -extern NTSTATUS UDFPrepareForWriteOperation( - IN PVCB Vcb, - IN ULONG Lba, - IN ULONG BCount); - -extern NTSTATUS UDFReadDiscTrackInfo(PDEVICE_OBJECT DeviceObject, // the target device object - PVCB Vcb); // Volume Control Block for ^ DevObj - -extern NTSTATUS UDFUseStandard(PDEVICE_OBJECT DeviceObject, // the target device object - PVCB Vcb); // Volume control block fro this DevObj - -extern NTSTATUS UDFGetBlockSize(PDEVICE_OBJECT DeviceObject, // the target device object - PVCB Vcb); // Volume control block fro this DevObj - -extern NTSTATUS UDFGetDiskInfo(IN PDEVICE_OBJECT DeviceObject, // the target device object - IN PVCB Vcb); // Volume control block from this DevObj - -extern VOID UDFUpdateNWA(PVCB Vcb, - ULONG LBA, - ULONG BCount, - NTSTATUS RC); - -extern NTSTATUS UDFDoDismountSequence(IN PVCB Vcb, - IN BOOLEAN Eject); - -// read physical sectors -NTSTATUS UDFReadSectors(IN PVCB Vcb, - IN BOOLEAN Translate,// Translate Logical to Physical - IN ULONG Lba, - IN ULONG BCount, - IN BOOLEAN Direct, - OUT PCHAR Buffer, - OUT PSIZE_T ReadBytes); - -// read data inside physical sector -extern NTSTATUS UDFReadInSector(IN PVCB Vcb, - IN BOOLEAN Translate, // Translate Logical to Physical - IN ULONG Lba, - IN ULONG i, // offset in sector - IN ULONG l, // transfer length - IN BOOLEAN Direct, - OUT PCHAR Buffer, - OUT PULONG ReadBytes); -// read unaligned data -extern NTSTATUS UDFReadData(IN PVCB Vcb, - IN BOOLEAN Translate, // Translate Logical to Physical - IN LONGLONG Offset, - IN ULONG Length, - IN BOOLEAN Direct, - OUT PCHAR Buffer, - OUT PULONG ReadBytes); - -// write physical sectors -NTSTATUS UDFWriteSectors(IN PVCB Vcb, - IN BOOLEAN Translate, // Translate Logical to Physical - IN ULONG Lba, - IN ULONG WBCount, - IN BOOLEAN Direct, // setting this flag delays flushing of given - // data to indefinite term - IN PCHAR Buffer, - OUT PULONG WrittenBytes); -// write directly to cached sector -NTSTATUS UDFWriteInSector(IN PVCB Vcb, - IN BOOLEAN Translate, // Translate Logical to Physical - IN ULONG Lba, - IN ULONG i, // offset in sector - IN ULONG l, // transfer length - IN BOOLEAN Direct, - OUT PCHAR Buffer, - OUT PULONG WrittenBytes); -// write data at unaligned offset & length -NTSTATUS UDFWriteData(IN PVCB Vcb, - IN BOOLEAN Translate, // Translate Logical to Physical - IN LONGLONG Offset, - IN ULONG Length, - IN BOOLEAN Direct, // setting this flag delays flushing of given - // data to indefinite term - IN PCHAR Buffer, - OUT PULONG WrittenBytes); - -NTSTATUS UDFResetDeviceDriver(IN PVCB Vcb. - IN PDEVICE_OBJECT TargetDeviceObject, - IN BOOLEAN Unlock); -#endif /************************************************************************* * Prototypes for the file Pnp.cpp *************************************************************************/ @@ -1036,9 +969,6 @@ UDFSetAccessRights( /************************************************************************* * Prototypes for the file Shutdown.cpp *************************************************************************/ -extern NTSTATUS NTAPI UDFShutdown( -PDEVICE_OBJECT DeviceObject, // the logical volume device object -PIRP Irp); // I/O Request Packet NTSTATUS UDFCommonShutdown( @@ -1046,84 +976,6 @@ UDFCommonShutdown( _Inout_ PIRP Irp ); -/************************************************************************* -* Prototypes for the file Udf_dbg.cpp -*************************************************************************/ -extern BOOLEAN -UDFDebugAcquireResourceSharedLite( - IN PERESOURCE Resource, - IN BOOLEAN Wait, - ULONG BugCheckId, - ULONG Line); - -extern BOOLEAN -UDFDebugAcquireSharedStarveExclusive( - IN PERESOURCE Resource, - IN BOOLEAN Wait, - ULONG BugCheckId, - ULONG Line); - -extern BOOLEAN -UDFDebugAcquireResourceExclusiveLite( - IN PERESOURCE Resource, - IN BOOLEAN Wait, - ULONG BugCheckId, - ULONG Line); - -extern VOID -UDFDebugReleaseResourceForThreadLite( - IN PERESOURCE Resource, - IN ERESOURCE_THREAD ResourceThreadId, - ULONG BugCheckId, - ULONG Line); - -extern VOID -UDFDebugDeleteResource( - IN PERESOURCE Resource, - IN ERESOURCE_THREAD ResourceThreadId, - ULONG BugCheckId, - ULONG Line); - -extern NTSTATUS -UDFDebugInitializeResourceLite( - IN PERESOURCE Resource, - IN ERESOURCE_THREAD ResourceThreadId, - ULONG BugCheckId, - ULONG Line); - -extern VOID -UDFDebugConvertExclusiveToSharedLite( - IN PERESOURCE Resource, - IN ERESOURCE_THREAD ResourceThreadId, - ULONG BugCheckId, - ULONG Line); - -extern BOOLEAN -UDFDebugAcquireSharedWaitForExclusive( - IN PERESOURCE Resource, - IN BOOLEAN Wait, - ULONG BugCheckId, - ULONG Line); - -extern LONG -UDFDebugInterlockedIncrement( - IN PLONG addr, - ULONG BugCheckId, - ULONG Line); - -extern LONG -UDFDebugInterlockedDecrement( - IN PLONG addr, - ULONG BugCheckId, - ULONG Line); - -extern LONG -UDFDebugInterlockedExchangeAdd( - IN PLONG addr, - IN LONG i, - ULONG BugCheckId, - ULONG Line); - /************************************************************************* * Prototypes for the file UDFinit.cpp *************************************************************************/ @@ -1134,23 +986,6 @@ PUNICODE_STRING RegistryPath); // path to the registry key extern VOID NTAPI UDFInitializeFunctionPointers( PDRIVER_OBJECT DriverObject); // created by the I/O sub-system -extern VOID NTAPI -UDFFsNotification(IN PDEVICE_OBJECT DeviceObject, - IN BOOLEAN FsActive); - -#ifndef WIN64 -//extern ptrFsRtlNotifyVolumeEvent FsRtlNotifyVolumeEvent; -#endif //WIN64 - -extern BOOLEAN -UDFGetInstallVersion(PULONG iVer); - -extern BOOLEAN -UDFGetInstallTime(PULONG iTime); - -extern BOOLEAN -UDFGetTrialEnd(PULONG iTrial); - /************************************************************************* * Prototypes for the file verify.cpp *************************************************************************/ @@ -1448,10 +1283,66 @@ UDFAcquireResource( #define UDFReleasePagingIo(IC,F) \ ExReleaseResourceLite((F)->Header.PagingIoResource) +inline +ULONG +UDFHighBit( + ULONG Word + ) +{ + ULONG Index; + + if (_BitScanReverse(&Index, Word)) { + return Index; + } + return 0; +} + +#define LlBytesFromSectors(V, L) ( \ + Int64ShllMod32( (ULONGLONG)(L), ((V)->SectorShift) ) \ +) + +#define LlSectorsFromBytes(V, L) ( \ + Int64ShrlMod32( (ULONGLONG)(L), ((V)->SectorShift) ) \ +) + +#define SectorSize(V) ((V)->SectorSize) + +inline +ULONG +SectorAlign( + PVCB Vcb, + ULONG Length +) { + + return (Length + (Vcb->SectorSize - 1)) & ~(Vcb->SectorSize - 1); +} + VOID UDFSetThreadContext( _Inout_ PIRP_CONTEXT IrpContext, _In_ PTHREAD_CONTEXT ThreadContext ); +#define UDFRestoreThreadContext(IC) \ + (IC)->ThreadContext->Udfs = 0; \ + IoSetTopLevelIrp( (IC)->ThreadContext->SavedTopLevelIrp ); \ + (IC)->ThreadContext = NULL + + +inline +BOOLEAN UdfIsExtendedFESupported( + _In_ PVCB Vcb +) +{ + return Vcb->NSRDesc == VRS_NSR03_FOUND; +} + +inline +BOOLEAN UDFIsStreamsSupported( + _In_ PVCB Vcb +) +{ + return Vcb->UdfRevision >= 0x0200; +} + #endif // _UDF_PROTOS_H_ diff --git a/drivers/filesystems/udfs/read.cpp b/drivers/filesystems/udfs/read.cpp index 9bb2280dcb814..7d274994cd361 100644 --- a/drivers/filesystems/udfs/read.cpp +++ b/drivers/filesystems/udfs/read.cpp @@ -39,79 +39,6 @@ } _SEH2_END; \ } -/************************************************************************* -* -* Function: UDFRead() -* -* Description: -* The I/O Manager will invoke this routine to handle a read -* request -* -* Expected Interrupt Level (for execution) : -* -* IRQL_PASSIVE_LEVEL (invocation at higher IRQL will cause execution -* to be deferred to a worker thread context) -* -* Return Value: STATUS_SUCCESS/Error -* -*************************************************************************/ -NTSTATUS -NTAPI -UDFRead( - PDEVICE_OBJECT DeviceObject, // the logical volume device object - PIRP Irp) // I/O Request Packet -{ - NTSTATUS RC = STATUS_SUCCESS; - PIRP_CONTEXT IrpContext = NULL; - BOOLEAN AreWeTopLevel = FALSE; - - TmPrint(("UDFRead: \n")); - - FsRtlEnterFileSystem(); - ASSERT(DeviceObject); - ASSERT(Irp); - - // set the top level context - AreWeTopLevel = UDFIsIrpTopLevel(Irp); - - _SEH2_TRY { - - // get an IRP context structure and issue the request - IrpContext = UDFCreateIrpContext(Irp, DeviceObject); - if (IrpContext) { - - if (FlagOn(IrpContext->MinorFunction, IRP_MN_COMPLETE)) { - - RC = UDFCompleteMdl(IrpContext, Irp); - - } else { - - RC = UDFCommonRead(IrpContext, Irp); - } - - } else { - - UDFCompleteRequest(IrpContext, Irp, STATUS_INSUFFICIENT_RESOURCES); - RC = STATUS_INSUFFICIENT_RESOURCES; - } - - } _SEH2_EXCEPT(UDFExceptionFilter(IrpContext, _SEH2_GetExceptionInformation())) { - - RC = UDFProcessException(IrpContext, Irp); - - UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC); - } _SEH2_END; - - if (AreWeTopLevel) { - IoSetTopLevelIrp(NULL); - } - - FsRtlExitFileSystem(); - - return(RC); -} // end UDFRead() - - /************************************************************************* * * Function: UDFPostStackOverflowRead() @@ -211,8 +138,8 @@ UDFStackOverflowRead( _SEH2_TRY { UDFCommonRead(IrpContext, IrpContext->Irp); } _SEH2_EXCEPT(UDFExceptionFilter(IrpContext, _SEH2_GetExceptionInformation())) { - RC = UDFProcessException(IrpContext, IrpContext->Irp); - UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC); + + RC = UDFProcessException(IrpContext, IrpContext->Irp, _SEH2_GetExceptionCode()); } _SEH2_END; // Set the stack overflow item's event to tell the original @@ -258,7 +185,6 @@ UDFCommonRead( BOOLEAN MainResourceAcquired = FALSE; BOOLEAN PagingIoResourceAcquired = FALSE; PVOID SystemBuffer = NULL; - PIRP TopIrp; BOOLEAN CacheLocked = FALSE; @@ -267,64 +193,38 @@ UDFCommonRead( BOOLEAN NonCachedIo = FALSE; BOOLEAN SynchronousIo = FALSE; - TmPrint(("UDFCommonRead: irp %x\n", Irp)); + PAGED_CODE(); - _SEH2_TRY { + // Decode the file object and verify we support read on this. It + // must be a user file, stream file or volume file (for a data disk). - TopIrp = IoGetTopLevelIrp(); - switch((ULONG_PTR)TopIrp) { - case FSRTL_FSP_TOP_LEVEL_IRP: - UDFPrint((" FSRTL_FSP_TOP_LEVEL_IRP\n")); - break; - case FSRTL_CACHE_TOP_LEVEL_IRP: - UDFPrint((" FSRTL_CACHE_TOP_LEVEL_IRP\n")); - break; - case FSRTL_MOD_WRITE_TOP_LEVEL_IRP: - UDFPrint((" FSRTL_MOD_WRITE_TOP_LEVEL_IRP\n")); -// BrutePoint() - break; - case FSRTL_FAST_IO_TOP_LEVEL_IRP: - UDFPrint((" FSRTL_FAST_IO_TOP_LEVEL_IRP\n")); -// BrutePoint() - break; - case NULL: - UDFPrint((" NULL TOP_LEVEL_IRP\n")); - break; - default: - if (TopIrp == Irp) { - UDFPrint((" TOP_LEVEL_IRP\n")); - } else { - UDFPrint((" RECURSIVE_IRP, TOP = %x\n", TopIrp)); - } - break; - } + TypeOfOpen = UDFDecodeFileObject(IrpSp->FileObject, &Fcb, &Ccb); - MmPrint((" Enter Irp, MDL=%x\n", Irp->MdlAddress)); - if (Irp->MdlAddress) { - UDFTouch(Irp->MdlAddress); - } + if ((TypeOfOpen == UnopenedFileObject) || + (TypeOfOpen == UserDirectoryOpen)) { - // If this is a request at IRQL DISPATCH_LEVEL, then post - // the request (your FSD may choose to process it synchronously - // if you implement the support correctly; obviously you will be - // quite constrained in what you can do at such IRQL). - if (IrpSp->MinorFunction & IRP_MN_DPC) { - try_return(RC = STATUS_PENDING); - } + UDFCompleteRequest(IrpContext, Irp, STATUS_INVALID_DEVICE_REQUEST); + return STATUS_INVALID_DEVICE_REQUEST; + } - FileObject = IrpSp->FileObject; - ASSERT(FileObject); + Vcb = Fcb->Vcb; - // Decode the file object and verify we support read on this. It - // must be a user file, stream file or volume file (for a data disk). + ASSERT_CCB(Ccb); + ASSERT_FCB(Fcb); + ASSERT_VCB(Vcb); - TypeOfOpen = UDFDecodeFileObject(IrpSp->FileObject, &Fcb, &Ccb); + // If this is a zero length read then return SUCCESS immediately. - Vcb = Fcb->Vcb; + if (IrpSp->Parameters.Read.Length == 0) { - ASSERT_CCB(Ccb); - ASSERT_FCB(Fcb); - ASSERT_VCB(Vcb); + UDFCompleteRequest(IrpContext, Irp, STATUS_SUCCESS); + return STATUS_SUCCESS; + } + + _SEH2_TRY { + + FileObject = IrpSp->FileObject; + ASSERT(FileObject); if (Fcb->FcbState & UDF_FCB_DELETED) { ASSERT(FALSE); @@ -431,7 +331,7 @@ UDFCommonRead( &NumberBytesRead); } else { RC = UDFTRead(IrpContext, Vcb, SystemBuffer, ReadLength, - (ULONG)(ByteOffset.QuadPart >> Vcb->BlockSizeBits), + (ULONG)(ByteOffset.QuadPart >> Vcb->SectorShift), &NumberBytesRead); } UDFUnlockCallersBuffer(IrpContext, Irp, SystemBuffer); @@ -667,7 +567,7 @@ UDFCommonRead( if (ByteOffset.QuadPart < ValidDataLength.QuadPart) { - ULONG LBS = Vcb->LBlockSize; + ULONG LBS = Vcb->SectorSize; ULONG ZeroingOffset = ((ValidDataLength.QuadPart - ByteOffset.QuadPart) + (LBS - 1)) & ~(LBS - 1); // If the offset is at or above the byte count, no harm: just means @@ -740,49 +640,35 @@ try_exit: NOTHING; if (VcbAcquired) { UDFReleaseResource(&Vcb->VcbResource); } + } _SEH2_END; // end of "__finally" processing - // Post IRP if required - if (RC == STATUS_PENDING) { + // Post the request if we got CANT_WAIT. - // Lock the callers buffer here. Then invoke a common routine to - // perform the post operation. - if (!(IrpSp->MinorFunction & IRP_MN_MDL)) { - RC = UDFLockUserBuffer(IrpContext, ReadLength, IoWriteAccess); - ASSERT(NT_SUCCESS(RC)); - } + if (RC == STATUS_PENDING) { - // Perform the post operation which will mark the IRP pending - // and will return STATUS_PENDING back to us - RC = UDFPostRequest(IrpContext, Irp); + RC = UDFFsdPostRequest(IrpContext, Irp); - } else { - // For synchronous I/O, the FSD must maintain the current byte offset - // Do not do this however, if I/O is marked as paging-io - if (SynchronousIo && !PagingIo && NT_SUCCESS(RC)) { - FileObject->CurrentByteOffset.QuadPart = ByteOffset.QuadPart + NumberBytesRead; - } - // If the read completed successfully and this was not a paging-io - // operation, set a flag in the CCB that indicates that a read was - // performed and that the file time should be updated at cleanup - if (NT_SUCCESS(RC) && !PagingIo) { - FileObject->Flags |= FO_FILE_FAST_IO_READ; - } + } else { - if (!_SEH2_AbnormalTermination()) { - Irp->IoStatus.Status = RC; - Irp->IoStatus.Information = NumberBytesRead; - UDFPrint((" NumberBytesRead = %x\n", NumberBytesRead)); - // Free up the Irp Context - UDFCleanupIrpContext(IrpContext); - // complete the IRP - MmPrint((" Complete Irp, MDL=%x\n", Irp->MdlAddress)); - if (Irp->MdlAddress) { - UDFTouch(Irp->MdlAddress); - } - IoCompleteRequest(Irp, IO_DISK_INCREMENT); - } - } // can we complete the IRP ? - } _SEH2_END; // end of "__finally" processing + // For synchronous I/O, the FSD must maintain the current byte offset + // Do not do this however, if I/O is marked as paging-io + + if (SynchronousIo && !PagingIo && NT_SUCCESS(RC)) { + + FileObject->CurrentByteOffset.QuadPart = ByteOffset.QuadPart + NumberBytesRead; + } + + // If the read completed successfully and this was not a paging-io + // operation, set a flag in the CCB that indicates that a read was + // performed and that the file time should be updated at cleanup + if (NT_SUCCESS(RC) && !PagingIo) { + FileObject->Flags |= FO_FILE_FAST_IO_READ; + } + + Irp->IoStatus.Information = NumberBytesRead; + + UDFCompleteRequest(IrpContext, Irp, RC); + } return(RC); } // end UDFCommonRead() @@ -957,7 +843,6 @@ UDFCompleteMdl( FileObject = IrpSp->FileObject; ASSERT(FileObject); - UDFTouch(Irp->MdlAddress); // Not much to do here. if (IrpContext->MajorFunction == IRP_MJ_READ) { diff --git a/drivers/filesystems/udfs/shutdown.cpp b/drivers/filesystems/udfs/shutdown.cpp index 779d510f8485d..bb2afb2d128c8 100644 --- a/drivers/filesystems/udfs/shutdown.cpp +++ b/drivers/filesystems/udfs/shutdown.cpp @@ -19,80 +19,6 @@ // define the file specific bug-check id #define UDF_BUG_CHECK_ID UDF_FILE_SHUTDOWN - - -/************************************************************************* -* -* Function: UDFShutdown() -* -* Description: -* All disk-based FSDs can expect to receive this shutdown notification -* request whenever the system is about to be halted gracefully. If you -* design and implement a network redirector, you must register explicitly -* for shutdown notification by invoking the IoRegisterShutdownNotification() -* routine from your driver entry. -* -* Note that drivers that register to receive shutdown notification get -* invoked BEFORE disk-based FSDs are told about the shutdown notification. -* -* Expected Interrupt Level (for execution) : -* -* IRQL_PASSIVE_LEVEL -* -* Return Value: Irrelevant. -* -*************************************************************************/ -NTSTATUS -NTAPI -UDFShutdown( - PDEVICE_OBJECT DeviceObject, // the logical volume device object - PIRP Irp // I/O Request Packet - ) -{ - NTSTATUS RC = STATUS_SUCCESS; - PIRP_CONTEXT IrpContext = NULL; - BOOLEAN AreWeTopLevel = FALSE; - - UDFPrint(("UDFShutDown\n")); -// BrutePoint(); - - FsRtlEnterFileSystem(); - ASSERT(DeviceObject); - ASSERT(Irp); - - // set the top level context - AreWeTopLevel = UDFIsIrpTopLevel(Irp); - //ASSERT(!UDFIsFSDevObj(DeviceObject)); - - _SEH2_TRY { - - // get an IRP context structure and issue the request - IrpContext = UDFCreateIrpContext(Irp, DeviceObject); - if (IrpContext) { - RC = UDFCommonShutdown(IrpContext, Irp); - } else { - - UDFCompleteRequest(IrpContext, Irp, STATUS_INSUFFICIENT_RESOURCES); - RC = STATUS_INSUFFICIENT_RESOURCES; - } - - } _SEH2_EXCEPT(UDFExceptionFilter(IrpContext, _SEH2_GetExceptionInformation())) { - - RC = UDFProcessException(IrpContext, Irp); - - UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC); - } _SEH2_END; - - if (AreWeTopLevel) { - IoSetTopLevelIrp(NULL); - } - - FsRtlExitFileSystem(); - - return(RC); -} // end UDFShutdown() - - /************************************************************************* * * Function: UDFCommonShutdown() @@ -116,7 +42,6 @@ UDFCommonShutdown( ) { KEVENT Event; - NTSTATUS Status; PVCB Vcb; PLIST_ENTRY Link; BOOLEAN VcbPresent = TRUE; @@ -125,7 +50,7 @@ UDFCommonShutdown( // Make sure we don't get any pop-ups. - SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_DISABLE_POPUPS ); + SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DISABLE_POPUPS); // Initialize an event for doing calls down to // our target device objects. @@ -238,10 +163,12 @@ UDFCommonShutdown( } } - // Once we have processed all the mounted logical volumes, we can release - // all acquired global resources and leave (in peace :-) + } _SEH2_FINALLY { + UDFReleaseUdfData(IrpContext); + ExDeleteResourceLite(&UdfData.GlobalDataResource); + // Now, delete any device objects, etc. we may have created IoUnregisterFileSystem(UdfData.UDFDeviceObject_CD); if (UdfData.UDFDeviceObject_CD) { @@ -260,18 +187,7 @@ UDFCommonShutdown( UDFDestroyZones(); } - // delete the resource we may have initialized - if (UdfData.Flags & UDF_DATA_FLAGS_RESOURCE_INITIALIZED) { - // un-initialize this resource - UDFDeleteResource(&UdfData.GlobalDataResource); - ClearFlag(UdfData.Flags, UDF_DATA_FLAGS_RESOURCE_INITIALIZED); - } - - Status = STATUS_SUCCESS; - - } _SEH2_FINALLY { - - UDFReleaseUdfData(IrpContext); + UDFCompleteRequest(IrpContext, Irp, STATUS_SUCCESS); } _SEH2_END; // end of "__finally" processing diff --git a/drivers/filesystems/udfs/strucsup.cpp b/drivers/filesystems/udfs/strucsup.cpp index acbda751e0334..9add5f14e35ed 100644 --- a/drivers/filesystems/udfs/strucsup.cpp +++ b/drivers/filesystems/udfs/strucsup.cpp @@ -130,6 +130,8 @@ Return Value: ExInitializeFastMutex(&FcbNonpaged->FcbMutex); ExInitializeFastMutex(&FcbNonpaged->AdvancedFcbHeaderMutex); + ExInitializeResourceLite(&FcbNonpaged->CcbListResource); + return FcbNonpaged; } @@ -161,6 +163,8 @@ Return Value: UNREFERENCED_PARAMETER(IrpContext); ExDeleteResourceLite(&FcbNonpaged->FcbResource); + ExDeleteResourceLite(&FcbNonpaged->FcbPagingIoResource); + ExDeleteResourceLite(&FcbNonpaged->CcbListResource); UDFDeallocateFcbNonpaged(FcbNonpaged); @@ -543,9 +547,6 @@ UDFInitializeFCB( { ASSERT_LOCKED_VCB(Vcb); - AdPrint(("UDFInitializeFCB\n")); - NTSTATUS status; - // Fill NT required Fcb part ASSERT(!Fcb->Header.Resource); @@ -554,24 +555,6 @@ UDFInitializeFCB( FsRtlSetupAdvancedHeader(&Fcb->Header, &Fcb->FcbNonpaged->AdvancedFcbHeaderMutex); Fcb->FileLock = NULL; - if (!NT_SUCCESS(status = UDFInitializeResourceLite(&Fcb->CcbListResource))) { - - AdPrint((" Can't init resource (3)\n")); - BrutePoint(); - - UDFDeleteResource(&Fcb->FcbNonpaged->FcbPagingIoResource); - UDFDeleteResource(&Fcb->FcbNonpaged->FcbResource); - Fcb->Header.Resource = NULL; - Fcb->Header.PagingIoResource = NULL; - - if (Fcb->FileLock != NULL) { - - FsRtlFreeFileLock(Fcb->FileLock); - } - - return status; - } - Fcb->FcbState = Flags; UDFInsertFcbTable(IrpContext, Fcb); @@ -583,8 +566,6 @@ UDFInitializeFCB( Fcb->FcbReference = 0; Fcb->FcbCleanup = 0; - SetFlag(Fcb->FcbState, UDF_FCB_INITIALIZED_CCB_LIST_RESOURCE); - Fcb->FCBName = PtrObjectName; Fcb->Vcb = Vcb; @@ -724,198 +705,140 @@ Return Value: * Return Value: status * *************************************************************************/ -NTSTATUS +VOID UDFInitializeVCB( _In_ PIRP_CONTEXT IrpContext, _Inout_ PVCB Vcb, _In_ PDEVICE_OBJECT TargetDeviceObject, - _In_ PVPB Vpb + _In_ PVPB Vpb, + _In_ PDISK_GEOMETRY DiskGeometry, + _In_ ULONG MediaChangeCount ) { - NTSTATUS RC = STATUS_SUCCESS; + PAGED_CODE(); + + UNREFERENCED_PARAMETER(IrpContext); - BOOLEAN VCBResourceInit = FALSE; - BOOLEAN BitMapResource1Init = FALSE; - BOOLEAN FileIdResourceInit = FALSE; - BOOLEAN DlocResourceInit = FALSE; - BOOLEAN DlocResource2Init = FALSE; - BOOLEAN FlushResourceInit = FALSE; - BOOLEAN PreallocResourceInit= FALSE; - BOOLEAN IoResourceInit = FALSE; + // We start by first zeroing out all of the VCB, this will guarantee + // that any stale data is wiped clean. - _SEH2_TRY { - // Zero it out (typically this has already been done by the I/O - // Manager but it does not hurt to do it again)! RtlZeroMemory(Vcb, sizeof(VCB)); - // Initialize the signature fields + // Set the proper node type code and node byte size. + Vcb->NodeIdentifier.NodeTypeCode = UDF_NODE_TYPE_VCB; Vcb->NodeIdentifier.NodeByteSize = sizeof(VCB); - // Initialize the ERESOURCE object. - RC = UDFInitializeResourceLite(&(Vcb->VcbResource)); - if (!NT_SUCCESS(RC)) - try_return(RC); - VCBResourceInit = TRUE; - - RC = UDFInitializeResourceLite(&(Vcb->BitMapResource1)); - if (!NT_SUCCESS(RC)) - try_return(RC); - BitMapResource1Init = TRUE; - - RC = UDFInitializeResourceLite(&(Vcb->FileIdResource)); - if (!NT_SUCCESS(RC)) - try_return(RC); - FileIdResourceInit = TRUE; - - RC = UDFInitializeResourceLite(&(Vcb->DlocResource)); - if (!NT_SUCCESS(RC)) - try_return(RC); - DlocResourceInit = TRUE; - - RC = UDFInitializeResourceLite(&(Vcb->DlocResource2)); - if (!NT_SUCCESS(RC)) - try_return(RC); - DlocResource2Init = TRUE; - - RC = UDFInitializeResourceLite(&(Vcb->FlushResource)); - if (!NT_SUCCESS(RC)) - try_return(RC); - FlushResourceInit = TRUE; - - RC = UDFInitializeResourceLite(&(Vcb->PreallocResource)); - if (!NT_SUCCESS(RC)) - try_return(RC); - PreallocResourceInit = TRUE; - - RC = UDFInitializeResourceLite(&(Vcb->IoResource)); - if (!NT_SUCCESS(RC)) - try_return(RC); - IoResourceInit = TRUE; - -// RC = UDFInitializeResourceLite(&(Vcb->DelayedCloseResource)); -// ASSERT(NT_SUCCESS(RC)); - - ExInitializeFastMutex(&Vcb->VcbMutex); - - // Initialize the generic Fcb Table. - - RtlInitializeGenericTable(&Vcb->FcbTable, - (PRTL_GENERIC_COMPARE_ROUTINE)UDFFcbTableCompare, - (PRTL_GENERIC_ALLOCATE_ROUTINE)UDFAllocateFcbTable, - (PRTL_GENERIC_FREE_ROUTINE)UDFDeallocateFcbTable, - NULL); - - // Pick up a VPB right now so we know we can pull this filesystem stack off - // of the storage stack on demand. - Vcb->SwapVpb = (PVPB)FsRtlAllocatePoolWithTag(NonPagedPoolNx, sizeof(VPB), TAG_VPB); - - if (!Vcb->SwapVpb) { - try_return(RC = STATUS_INSUFFICIENT_RESOURCES); - } - - RtlZeroMemory(Vcb->SwapVpb, sizeof(VPB)); - - // We know the target device object. - // Note that this is not neccessarily a pointer to the actual - // physical/virtual device on which the logical volume should - // be mounted. This is actually a pointer to either the actual - // (real) device or to any device object that may have been - // attached to it. Any IRPs that we send down should be sent to this - // device object. However, the "real" physical/virtual device object - // on which we perform our mount operation can be determined from the - // RealDevice field in the VPB sent to us. - Vcb->TargetDeviceObject = TargetDeviceObject; - - // We also have the VPB pointer. This was obtained from the - // Parameters.MountVolume.Vpb field in the current I/O stack location - // for the mount IRP. - Vcb->Vpb = Vpb; - - // Set the removable media flag based on the real device's - // characteristics - if (Vpb->RealDevice->Characteristics & FILE_REMOVABLE_MEDIA) { - - Vcb->VcbState |= VCB_STATE_REMOVABLE_MEDIA; - } + // Initialize the notify sync mutex. FsRtlNotifyInitializeSync can raise. - // Initialize the list anchor (head) for some lists in this VCB. - InitializeListHead(&Vcb->NextNotifyIRP); + FsRtlNotifyInitializeSync(&Vcb->NotifySync); - // Initialize the notify IRP list mutex - FsRtlNotifyInitializeSync(&(Vcb->NotifyIRPMutex)); + _SEH2_TRY { - // Intilize FCB for this VCB + ExInitializeResourceLite(&Vcb->VcbResource); + ExInitializeResourceLite(&Vcb->BitMapResource1); + ExInitializeResourceLite(&Vcb->FileIdResource); + ExInitializeResourceLite(&Vcb->DlocResource); + ExInitializeResourceLite(&Vcb->DlocResource2); + ExInitializeResourceLite(&Vcb->FlushResource); + ExInitializeResourceLite(&Vcb->PreallocResource); + ExInitializeResourceLite(&Vcb->IoResource); + + ExInitializeFastMutex(&Vcb->VcbMutex); + + // Initialize the generic Fcb Table. + + RtlInitializeGenericTable(&Vcb->FcbTable, + (PRTL_GENERIC_COMPARE_ROUTINE)UDFFcbTableCompare, + (PRTL_GENERIC_ALLOCATE_ROUTINE)UDFAllocateFcbTable, + (PRTL_GENERIC_FREE_ROUTINE)UDFDeallocateFcbTable, + NULL); + + // Pick up a VPB right now so we know we can pull this filesystem stack + // off of the storage stack on demand. This can raise - if it does, + // uninitialize the notify structures before returning. + + Vcb->SwapVpb = (PVPB)FsRtlAllocatePoolWithTag(NonPagedPoolNx, sizeof(VPB), TAG_VPB); + + RtlZeroMemory(Vcb->SwapVpb, sizeof(VPB)); + + // We know the target device object. + // Note that this is not neccessarily a pointer to the actual + // physical/virtual device on which the logical volume should + // be mounted. This is actually a pointer to either the actual + // (real) device or to any device object that may have been + // attached to it. Any IRPs that we send down should be sent to this + // device object. However, the "real" physical/virtual device object + // on which we perform our mount operation can be determined from the + // RealDevice field in the VPB sent to us. + Vcb->TargetDeviceObject = TargetDeviceObject; + + // We also have the VPB pointer. This was obtained from the + // Parameters.MountVolume.Vpb field in the current I/O stack location + // for the mount IRP. + Vcb->Vpb = Vpb; + + // Set the removable media flag based on the real device's + // characteristics + if (Vpb->RealDevice->Characteristics & FILE_REMOVABLE_MEDIA) { + + Vcb->VcbState |= VCB_STATE_REMOVABLE_MEDIA; + } - // Refererence the Vcb for two reasons. The first is a reference - // that prevents the Vcb from going away on the last close unless - // dismount has already occurred. The second is to make sure - // we don't go into the dismount path on any error during mount - // until we get to the Mount cleanup. + // Initialize the list anchor (head) for some lists in this VCB. + InitializeListHead(&Vcb->NextNotifyIRP); - Vcb->VcbResidualReference = UDFS_BASE_RESIDUAL_REFERENCE; - Vcb->VcbResidualUserReference = UDFS_BASE_RESIDUAL_USER_REFERENCE; + // Intilize FCB for this VCB - Vcb->VcbReference = 1 + Vcb->VcbResidualReference; + // Refererence the Vcb for two reasons. The first is a reference + // that prevents the Vcb from going away on the last close unless + // dismount has already occurred. The second is to make sure + // we don't go into the dismount path on any error during mount + // until we get to the Mount cleanup. - Vcb->WCacheMaxBlocks = UdfData.WCacheMaxBlocks; - Vcb->WCacheMaxFrames = UdfData.WCacheMaxFrames; - Vcb->WCacheBlocksPerFrameSh = UdfData.WCacheBlocksPerFrameSh; - Vcb->WCacheFramesToKeepFree = UdfData.WCacheFramesToKeepFree; + Vcb->VcbResidualReference = UDFS_BASE_RESIDUAL_REFERENCE; + Vcb->VcbResidualUserReference = UDFS_BASE_RESIDUAL_USER_REFERENCE; - // Create a stream file object for this volume. - //Vcb->PtrStreamFileObject = IoCreateStreamFileObject(NULL, - // Vcb->Vpb->RealDevice); - //ASSERT(Vcb->PtrStreamFileObject); + Vcb->VcbReference = 1 + Vcb->VcbResidualReference; - // Initialize some important fields in the newly created file object. - //Vcb->PtrStreamFileObject->FsContext = (PVOID)Vcb; - //Vcb->PtrStreamFileObject->FsContext2 = NULL; - //Vcb->PtrStreamFileObject->SectionObjectPointer = &(Vcb->SectionObject); + Vcb->WCacheMaxBlocks = UdfData.WCacheMaxBlocks; + Vcb->WCacheMaxFrames = UdfData.WCacheMaxFrames; + Vcb->WCacheBlocksPerFrameSh = UdfData.WCacheBlocksPerFrameSh; + Vcb->WCacheFramesToKeepFree = UdfData.WCacheFramesToKeepFree; - //Vcb->PtrStreamFileObject->Vpb = PtrVPB; + // Create a stream file object for this volume. + //Vcb->PtrStreamFileObject = IoCreateStreamFileObject(NULL, + // Vcb->Vpb->RealDevice); + //ASSERT(Vcb->PtrStreamFileObject); - // Insert this Vcb record on the CdData.VcbQueue. + // Initialize some important fields in the newly created file object. + //Vcb->PtrStreamFileObject->FsContext = (PVOID)Vcb; + //Vcb->PtrStreamFileObject->FsContext2 = NULL; + //Vcb->PtrStreamFileObject->SectionObjectPointer = &(Vcb->SectionObject); - ASSERT_EXCLUSIVE_CDDATA; - InsertTailList(&(UdfData.VcbQueue), &(Vcb->NextVCB)); + //Vcb->PtrStreamFileObject->Vpb = PtrVPB; - // Initialize caching for the stream file object. - //CcInitializeCacheMap(Vcb->PtrStreamFileObject, (PCC_FILE_SIZES)(&(Vcb->AllocationSize)), - // TRUE, // We will use pinned access. - // &(UDFGlobalData.CacheMgrCallBacks), Vcb); + // Insert this Vcb record on the CdData.VcbQueue. - // Mark the fact that this VCB structure is initialized. - Vcb->VcbState |= UDF_VCB_FLAGS_VCB_INITIALIZED; + ASSERT_EXCLUSIVE_CDDATA; + InsertTailList(&(UdfData.VcbQueue), &(Vcb->NextVCB)); - RC = STATUS_SUCCESS; + // Initialize caching for the stream file object. + //CcInitializeCacheMap(Vcb->PtrStreamFileObject, (PCC_FILE_SIZES)(&(Vcb->AllocationSize)), + // TRUE, // We will use pinned access. + // &(UDFGlobalData.CacheMgrCallBacks), Vcb); -try_exit: NOTHING; + Vcb->SectorSize = DiskGeometry->BytesPerSector; + Vcb->SectorShift = UDFHighBit(DiskGeometry->BytesPerSector); + Vcb->MediaChangeCount = MediaChangeCount; } _SEH2_FINALLY { - if (!NT_SUCCESS(RC)) { - - if (VCBResourceInit) - UDFDeleteResource(&(Vcb->VcbResource)); - if (BitMapResource1Init) - UDFDeleteResource(&(Vcb->BitMapResource1)); - if (FileIdResourceInit) - UDFDeleteResource(&(Vcb->FileIdResource)); - if (DlocResourceInit) - UDFDeleteResource(&(Vcb->DlocResource)); - if (DlocResource2Init) - UDFDeleteResource(&(Vcb->DlocResource2)); - if (FlushResourceInit) - UDFDeleteResource(&(Vcb->FlushResource)); - if (PreallocResourceInit) - UDFDeleteResource(&(Vcb->PreallocResource)); - if (IoResourceInit) - UDFDeleteResource(&(Vcb->IoResource)); + if (_SEH2_AbnormalTermination()) { + + FsRtlNotifyUninitializeSync(&Vcb->NotifySync); } } _SEH2_END; - - return RC; } // end UDFInitializeVCB() VOID @@ -970,9 +893,6 @@ UDFCleanUpFCB( // } end transaction - if (Fcb->FcbState & UDF_FCB_INITIALIZED_CCB_LIST_RESOURCE) - UDFDeleteResource(&(Fcb->CcbListResource)); - // Free memory UDFDeleteFcb(0, Fcb); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { @@ -1001,14 +921,14 @@ UDFCompleteMount( _SEH2_TRY { - Vcb->ZBuffer = (PCHAR)DbgAllocatePoolWithTag(NonPagedPool, max(Vcb->LBlockSize, PAGE_SIZE), 'zNWD'); + Vcb->ZBuffer = (PCHAR)DbgAllocatePoolWithTag(NonPagedPool, max(Vcb->SectorSize, PAGE_SIZE), 'zNWD'); if (!Vcb->ZBuffer) { try_return(Status = STATUS_INSUFFICIENT_RESOURCES); } - RtlZeroMemory(Vcb->ZBuffer, Vcb->LBlockSize); + RtlZeroMemory(Vcb->ZBuffer, Vcb->SectorSize); // Create the root index and reference it in the Vcb. @@ -1086,7 +1006,7 @@ UDFCompleteMount( } // this is a part of UDF_RESIDUAL_REFERENCE - UDFInterlockedIncrement((PLONG)&(Vcb->VcbReference)); + InterlockedIncrement((PLONG)&Vcb->VcbReference); Vcb->RootIndexFcb->FcbCleanup = 1; Vcb->RootIndexFcb->FcbReference = 1; @@ -1129,7 +1049,7 @@ UDFCompleteMount( UDFCleanUpFile__(Vcb, Vcb->NonAllocFileInfo); Vcb->NonAllocFileInfo = NULL; // this was a part of UDF_RESIDUAL_REFERENCE - UDFInterlockedDecrement((PLONG)&(Vcb->VcbReference)); + InterlockedDecrement((PLONG)&Vcb->VcbReference); unwind_1: // UDFCloseResidual() will clean up everything @@ -1208,7 +1128,7 @@ UDFCompleteMount( UDFPreClrModified(Vcb); UDFClrModified(Vcb); // this is a part of UDF_RESIDUAL_REFERENCE - UDFInterlockedIncrement((PLONG)&Vcb->VcbReference); + InterlockedIncrement((PLONG)&Vcb->VcbReference); // Start initializing the fields contained in the Header. @@ -1267,7 +1187,7 @@ UDFCompleteMount( } } - Vcb->VolumeDasdFcb->Header.FileSize.QuadPart = Int64ShllMod32(Vcb->LB2B_Bits, LastSector); + Vcb->VolumeDasdFcb->Header.FileSize.QuadPart = LlBytesFromSectors(Vcb, LastSector); Vcb->VolumeDasdFcb->Header.AllocationSize.QuadPart = Vcb->VolumeDasdFcb->Header.ValidDataLength.QuadPart = Vcb->VolumeDasdFcb->Header.FileSize.QuadPart; diff --git a/drivers/filesystems/udfs/struct.h b/drivers/filesystems/udfs/struct.h index 15030ef14567a..a1fbba1b12c91 100644 --- a/drivers/filesystems/udfs/struct.h +++ b/drivers/filesystems/udfs/struct.h @@ -139,6 +139,8 @@ struct FCB_NONPAGED { ERESOURCE FcbPagingIoResource; + ERESOURCE CcbListResource; + // This is the FastMutex for this Fcb. FAST_MUTEX FcbMutex; @@ -244,8 +246,7 @@ struct FCB { // for the UDF fsd, there exists a 1-1 correspondence between a // full object pathname and a FCB - PtrUDFObjectName FCBName; - ERESOURCE CcbListResource; + PtrUDFObjectName FCBName; // Pointer to the Fcb non-paged structures. @@ -297,17 +298,12 @@ using PFCB = FCB*; #define UDF_FCB_VALID (0x00000002) #define UDF_FCB_DIRECTORY (0x00000008) #define UDF_FCB_ROOT_DIRECTORY (0x00000010) -#define UDF_FCB_MAPPED (0x00000040) -#define UDF_FCB_FAST_IO_READ_IN_PROGESS (0x00000080) -#define UDF_FCB_FAST_IO_WRITE_IN_PROGESS (0x00000100) #define UDF_FCB_DELETE_ON_CLOSE (0x00000200) #define UDF_FCB_MODIFIED (0x00000400) #define UDF_FCB_ACCESSED (0x00000800) #define UDF_FCB_READ_ONLY (0x00001000) #define UDF_FCB_DELAY_CLOSE (0x00002000) #define UDF_FCB_DELETED (0x00004000) - -#define UDF_FCB_INITIALIZED_CCB_LIST_RESOURCE (0x00008000) #define UDF_FCB_POSTED_RENAME (0x00010000) #define FCB_STATE_INITIALIZED (0x00020000) @@ -324,8 +320,6 @@ using PFCB = FCB*; **************************************************************************/ -#define _BROWSE_UDF_ - enum UDFFSD_MEDIA_TYPE { MediaUnknown = 0, MediaHdd, @@ -368,7 +362,7 @@ struct VCB { // because of a directory notify request. LIST_ENTRY NextNotifyIRP; // the above list is protected only by the mutex declared below - PNOTIFY_SYNC NotifyIRPMutex; + PNOTIFY_SYNC NotifySync; // We also retain a pointer to the physical device object on which we // have mounted ourselves. The I/O Manager passes us a pointer to this // device object when requesting a mount operation. @@ -434,12 +428,10 @@ struct VCB { // Physical media parameters //--------------- - ULONG BlockSize; - ULONG BlockSizeBits; + ULONG SectorSize; + ULONG SectorShift; ULONG WriteBlockSize; - ULONG LBlockSize; - ULONG LBlockSizeBits; - ULONG LB2B_Bits; + // Number of last session ULONG LastSession; ULONG FirstTrackNum; @@ -457,23 +449,13 @@ struct VCB { struct _UDFTrackMap* TrackMap; ULONG LastModifiedTrack; ULONG LastReadTrack; - ULONG CdrwBufferSize; - ULONG CdrwBufferSizeCounter; uint32 SavedFeatures; - // OPC info -// PCHAR OPC_buffer; - UCHAR OPCNum; - BOOLEAN OPCDone; + UCHAR MediaType; UCHAR MediaClassEx; - UCHAR PhErasable; - UCHAR PhDiskType; - UCHAR PhMediaCapFlags; - UCHAR MRWStatus; BOOLEAN BlankCD; - UCHAR Reserved; ULONG PhSerialNumber; @@ -506,11 +488,7 @@ struct VCB { #define INCREMENTAL_SEEK_DONE 2 UCHAR IncrementalSeekState; - BOOLEAN VerifyOnWrite; - BOOLEAN DoNotCompareBeforeWrite; - BOOLEAN CacheChainedIo; - ULONG MountPhErrorCount; // a set of flags that might mean something useful @@ -580,9 +558,6 @@ struct VCB { PCHAR FSBM_OldBitmap; // 0 - free, 1 - used ULONG BitmapModified; - - PCHAR ZSBM_Bitmap; // 0 - data, 1 - zero-filleld - PCHAR BSBM_Bitmap; // 0 - normal, 1 - bad-block // pointers to Volume Descriptor Sequences @@ -611,13 +586,10 @@ struct VCB { ULONG DlocCount; // FS compatibility USHORT DefaultAllocMode; // Default alloc mode (from registry) - BOOLEAN UseExtendedFE; BOOLEAN LowFreeSpace; UDFFSD_MEDIA_TYPE MediaTypeEx; ULONG DefaultAttr; // Default file attributes (NT-style) - - UCHAR PartitialDamagedVolumeAction; BOOLEAN NoFreeRelocationSpaceVolumeAction; BOOLEAN ForgetVolume; UCHAR Reserved5[3]; @@ -637,7 +609,6 @@ struct VCB { UDF_VERIFY_CTX VerifyCtx; uint32 CompatFlags; - UCHAR ShowBlankCd; // Fcb table. Synchronized with the Vcb fast mutex. @@ -935,7 +906,7 @@ typedef struct _UDFData { #define VCB_STATE_MOUNTED_DIRTY (0x00000004) #define VCB_STATE_SHUTDOWN (0x00000008) #define VCB_STATE_VOLUME_READ_ONLY (0x00000010) -#define UDF_VCB_FLAGS_VCB_INITIALIZED (0x00000020) +#define VCB_STATE_PACKET_RUNOUT_FIXUP (0x00000020) #define VCB_STATE_VPB_NOT_ON_DEVICE (0x00000040) #define VCB_STATE_MEDIA_WRITE_PROTECT (0x00000080) #define VCB_STATE_REMOVABLE_MEDIA (0x00000100) @@ -952,8 +923,6 @@ typedef struct _UDFData { #define UDF_VCB_FLAGS_FLUSH_BREAK_REQ (0x01000000) #define UDF_VCB_FLAGS_EJECT_REQ (0x02000000) #define UDF_VCB_FLAGS_FORCE_SYNC_CACHE (0x04000000) - -#define UDF_VCB_FLAGS_UNSAFE_IOCTL (0x10000000) #define UDF_VCB_FLAGS_DEAD (0x20000000) // device unexpectedly disappeared @@ -967,25 +936,18 @@ typedef struct _UDFData { #define UDF_VCB_IC_WRITE_IN_RO_DIR (0x00000040) #define UDF_VCB_IC_UPDATE_UCHG_DIR_ACCESS_TIME (0x00000080) #define UDF_VCB_IC_W2K_COMPAT_ALLOC_DESCS (0x00000100) -#define UDF_VCB_IC_HW_RO (0x00000200) -#define UDF_VCB_IC_FORCE_HW_RO (0x00001000) #define UDF_VCB_IC_IGNORE_SEQUENTIAL_IO (0x00002000) #define UDF_VCB_IC_NO_SYNCCACHE_AFTER_WRITE (0x00004000) #define UDF_VCB_IC_BAD_RW_SEEK (0x00008000) -#define UDF_VCB_IC_FP_ADDR_PROBLEM (0x00010000) -#define UDF_VCB_IC_MRW_ADDR_PROBLEM (0x00020000) #define UDF_VCB_IC_BAD_DVD_LAST_LBA (0x00040000) #define UDF_VCB_IC_SYNCCACHE_BEFORE_READ (0x00080000) #define UDF_VCB_IC_INSTANT_COMPAT_ALLOC_DESCS (0x00100000) -#define UDF_VCB_IC_SOFT_RO (0x00200000) #define UDF_VCB_IC_DIRTY_RO (0x04000000) #define UDF_VCB_IC_W2K_COMPAT_VLABEL (0x08000000) -#define UDF_VCB_IC_SHOW_BLANK_CD (0x40000000) #define UDF_VCB_IC_ADAPTEC_NONALLOC_COMPAT (0x80000000) // valid flag values for the global data structure -#define UDF_DATA_FLAGS_RESOURCE_INITIALIZED (0x00000001) #define UDF_DATA_FLAGS_ZONES_INITIALIZED (0x00000002) #define UDF_DATA_FLAGS_SHUTDOWN (0x00000004) @@ -994,7 +956,6 @@ typedef struct _UDFData { // Some defines #define UDFIsDvdMedia(Vcb) (Vcb->DVD_Mode) -#define UDFIsWriteParamsReq(Vcb) (Vcb->WriteParamsReq && !Vcb->DVD_Mode) typedef struct _UDFFileIDCacheItem { FILE_ID Id; diff --git a/drivers/filesystems/udfs/udf_dbg.cpp b/drivers/filesystems/udfs/udf_dbg.cpp index 1e26e7b0929be..0d16f8280a41e 100644 --- a/drivers/filesystems/udfs/udf_dbg.cpp +++ b/drivers/filesystems/udfs/udf_dbg.cpp @@ -4,288 +4,12 @@ // This file was released under the GPLv2 on June 2015. //////////////////////////////////////////////////////////////////// #include "udffs.h" -#if defined(UDF_DBG) || defined(PRINT_ALWAYS) +#if defined(UDF_DBG) -//#define TRACK_RESOURCES //#define TRACK_REF_COUNTERS -ULONG ResCounter = 0; -ULONG AcqCounter = 0; ULONG UdfTimeStamp = -1; -BOOLEAN -UDFDebugAcquireResourceSharedLite( - IN PERESOURCE Resource, - IN BOOLEAN Wait, - ULONG BugCheckId, - ULONG Line -) { - ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL); -#ifdef TRACK_RESOURCES - UDFPrint(("Res:Sha:Try:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, - BugCheckId,Line,PsGetCurrentThread())); -#endif - - BOOLEAN Success = ExAcquireResourceSharedLite(Resource,Wait); - - if (Success) { -#ifdef TRACK_RESOURCES - UDFPrint(("Res:Sha:Ok:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, - BugCheckId,Line,PsGetCurrentThread())); -#endif - AcqCounter++; - return Success; - } -#ifdef TRACK_RESOURCES - UDFPrint(("Res:Sha:Fail:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, - BugCheckId,Line,PsGetCurrentThread())); -#endif - return FALSE; -} - -BOOLEAN -UDFDebugAcquireSharedStarveExclusive( - IN PERESOURCE Resource, - IN BOOLEAN Wait, - ULONG BugCheckId, - ULONG Line -) { - ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL); -#ifdef TRACK_RESOURCES - UDFPrint(("Res:Sha*:Try:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, - BugCheckId,Line,PsGetCurrentThread())); -#endif - - BOOLEAN Success = ExAcquireResourceSharedLite(Resource,Wait); - - if (Success) { -#ifdef TRACK_RESOURCES - UDFPrint(("Res:Sha*:Ok:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, - BugCheckId,Line,PsGetCurrentThread())); -#endif - AcqCounter++; - return Success; - } -#ifdef TRACK_RESOURCES - UDFPrint(("Res:Sha*:Fail:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, - BugCheckId,Line,PsGetCurrentThread())); -#endif - return FALSE; -} - -BOOLEAN -UDFDebugAcquireResourceExclusiveLite( - IN PERESOURCE Resource, - IN BOOLEAN Wait, - ULONG BugCheckId, - ULONG Line -) { - ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL); -#ifdef TRACK_RESOURCES - UDFPrint(("Res:Exc:Try:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, - BugCheckId,Line,PsGetCurrentThread())); -#endif - - - BOOLEAN Success = ExAcquireResourceExclusiveLite(Resource,Wait); - - if (Success) { -#ifdef TRACK_RESOURCES - UDFPrint(("Res:Exc:OK:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, - BugCheckId,Line,PsGetCurrentThread())); -#endif - AcqCounter++; - return Success; - } -#ifdef TRACK_RESOURCES - UDFPrint(("Res:Exc:Fail:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, - BugCheckId,Line,PsGetCurrentThread())); -#endif -// BrutePoint(); - return FALSE; - -} - -VOID -UDFDebugReleaseResourceForThreadLite( - IN PERESOURCE Resource, - IN ERESOURCE_THREAD ResourceThreadId, - ULONG BugCheckId, - ULONG Line - ) -{ - ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL); -#ifdef TRACK_RESOURCES - UDFPrint(("Res:Free:Try:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, - BugCheckId,Line,PsGetCurrentThread())); -#endif - ExReleaseResourceForThreadLite(Resource, ResourceThreadId); -#ifdef TRACK_RESOURCES - UDFPrint(("Res:Free:Ok:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, - BugCheckId,Line,ResourceThreadId)); -#endif - AcqCounter--; -} - -VOID -UDFDebugDeleteResource( - IN PERESOURCE Resource, - IN ERESOURCE_THREAD ResourceThreadId, - ULONG BugCheckId, - ULONG Line - ) -{ - ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL); -#ifdef TRACK_RESOURCES - UDFPrint(("Res:Del:Try:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, - BugCheckId,Line,ResourceThreadId)); -#endif - _SEH2_TRY { - ASSERT((*((PULONG)Resource))); - ASSERT((*(((PULONG)Resource)+1))); - ExDeleteResourceLite(Resource); - RtlZeroMemory(Resource, sizeof(ERESOURCE)); - } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) { - BrutePoint(); - } _SEH2_END; -#ifdef TRACK_RESOURCES - UDFPrint(("Res:Del:Ok:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, - BugCheckId,Line,ResourceThreadId)); -#endif - ResCounter--; -} - -NTSTATUS -UDFDebugInitializeResourceLite( - IN PERESOURCE Resource, - IN ERESOURCE_THREAD ResourceThreadId, - ULONG BugCheckId, - ULONG Line - ) -{ - ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL); - NTSTATUS RC; -#ifdef TRACK_RESOURCES - UDFPrint(("Res:Ini:Try:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, - BugCheckId,Line,ResourceThreadId)); -#endif - ASSERT(!(*((PULONG)Resource))); - ASSERT(!(*(((PULONG)Resource)+1))); - RC = ExInitializeResourceLite(Resource); -#ifdef TRACK_RESOURCES - UDFPrint(("Res:Ini:Ok:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, - BugCheckId,Line,ResourceThreadId)); -#endif - if (NT_SUCCESS(RC)) { - ResCounter++; - } - return RC; -} - -VOID -UDFDebugConvertExclusiveToSharedLite( - IN PERESOURCE Resource, - IN ERESOURCE_THREAD ResourceThreadId, - ULONG BugCheckId, - ULONG Line - ) -{ - ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL); -#ifdef TRACK_RESOURCES - UDFPrint(("Res:2Sha:Try:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, - BugCheckId,Line,ResourceThreadId)); -#endif - ExConvertExclusiveToSharedLite(Resource); -#ifdef TRACK_RESOURCES - UDFPrint(("Res:2Sha:Ok:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, - BugCheckId,Line,ResourceThreadId)); -#endif -} - -BOOLEAN -UDFDebugAcquireSharedWaitForExclusive( - IN PERESOURCE Resource, - IN BOOLEAN Wait, - ULONG BugCheckId, - ULONG Line -) { - ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL); -#ifdef TRACK_RESOURCES - UDFPrint(("Res:Sha*:Try:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, - BugCheckId,Line,PsGetCurrentThread())); -#endif - - BOOLEAN Success = ExAcquireSharedWaitForExclusive(Resource,Wait); - - if (Success) { -#ifdef TRACK_RESOURCES - UDFPrint(("Res:Sha*:OK:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, - BugCheckId,Line,PsGetCurrentThread())); -#endif - return Success; - } -#ifdef TRACK_RESOURCES - UDFPrint(("Res:Sha*:Fail:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, - BugCheckId,Line,PsGetCurrentThread())); -#endif -// BrutePoint(); - return FALSE; - -} - - -LONG -UDFDebugInterlockedIncrement( - IN PLONG addr, - ULONG BugCheckId, - ULONG Line) -{ -#ifdef TRACK_REF_COUNTERS - LONG a; - a = InterlockedIncrement(addr); - UDFPrint(("ThId:%x:Ilck:Inc:FileId:%x:Line:%d:Ref:%x:Val:%x:%x\n", - PsGetCurrentThread(),BugCheckId,Line,addr,a-1,a)); - return a; -#else - return InterlockedIncrement(addr); -#endif -} - -LONG -UDFDebugInterlockedDecrement( - IN PLONG addr, - ULONG BugCheckId, - ULONG Line) -{ -#ifdef TRACK_REF_COUNTERS - LONG a; - a = InterlockedDecrement(addr); - UDFPrint(("ThId:%x:Ilck:Dec:FileId:%x:Line:%d:Ref:%x:Val:%x:%x\n", - PsGetCurrentThread(),BugCheckId,Line,addr,a+1,a)); - return a; -#else - return InterlockedDecrement(addr); -#endif -} - -LONG -UDFDebugInterlockedExchangeAdd( - IN PLONG addr, - IN LONG i, - ULONG BugCheckId, - ULONG Line) -{ -#ifdef TRACK_REF_COUNTERS - LONG a; - a = InterlockedExchangeAdd(addr,i); - UDFPrint(("ThId:%x:Ilck:Add:FileId:%x:Line:%d:Ref:%x:Val:%x:%x\n", - PsGetCurrentThread(),BugCheckId,Line,addr,a,a+i)); - return a; -#else - return InterlockedExchangeAdd(addr,i); -#endif -} - #define MAX_MEM_DEBUG_DESCRIPTORS 8192 typedef struct _MEM_DESC { diff --git a/drivers/filesystems/udfs/udf_dbg.h b/drivers/filesystems/udfs/udf_dbg.h index 5de2d0a61f8b3..a0bbe56e39d10 100644 --- a/drivers/filesystems/udfs/udf_dbg.h +++ b/drivers/filesystems/udfs/udf_dbg.h @@ -21,7 +21,6 @@ //====================================== //#define ALWAYS_CHECK_WAIT_TIMEOUT -//#define PRINT_ALWAYS #ifdef UDF_DBG @@ -36,8 +35,6 @@ //#define UDF_SIMULATE_WRITES -//#define USE_PERF_PRINT - #define USE_KD_PRINT #define USE_MM_PRINT #define USE_AD_PRINT @@ -47,7 +44,7 @@ //====================================== -#if defined UDF_DBG || defined PRINT_ALWAYS +#if defined UDF_DBG ULONG _cdecl @@ -80,12 +77,6 @@ #define TmPrint KdPrint #endif //USE_MM_PRINT - #ifdef USE_PERF_PRINT - #define PerfPrint(_x_) DbgPrint _x_ - #else - #define PerfPrint(_x_) {NOTHING;} - #endif //USE_MM_PRINT - #ifdef USE_AD_PRINT #define AdPrint(_x_) {DbgPrint("Thrd:%x:",PsGetCurrentThread());DbgPrint _x_;} #else @@ -129,11 +120,25 @@ DbgWaitForSingleObject_( #ifdef UDF_DBG -#ifdef UDF_DBG - #define BrutePoint() DbgBreakPoint() +#ifdef _X86_ +// This is an illegal use of INT3 +#define UDFBreakPoint() { __asm int 3 } +#else // _X86_ + +#define UDFBreakPoint() DbgBreakPoint() +#endif // _X86_ + +#ifdef BRUTE +#define BrutePoint() UDFBreakPoint() #else - #define BrutePoint() {} -#endif // UDF_DBG +#define BrutePoint() {} +#endif // BRUTE + +#ifdef CHECK_REF_COUNTS +#define ASSERT_REF(_a_) ASSERT(_a_) +#else +#define ASSERT_REF(_a_) {NOTHING;} +#endif //CHECK_REF_COUNTS #ifdef TRACK_SYS_ALLOCS @@ -161,52 +166,20 @@ VOID DebugFreePool(PVOID addr); #endif //TRACK_SYS_ALLOCS - -#ifdef PROTECTED_MEM_RTL - -#define DbgMoveMemory(d, s, l) \ -_SEH2_TRY { \ - RtlMoveMemory(d, s, l); \ -} _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) { \ - BrutePoint(); \ -} _SEH2_END; - -#define DbgCopyMemory(d, s, l) \ -_SEH2_TRY { \ - RtlCopyMemory(d, s, l); \ -} _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) { \ - BrutePoint(); \ -} _SEH2_END; - -__inline -SIZE_T -DbgCompareMemory(PVOID d, PVOID s, SIZE_T l) { - _SEH2_TRY { - return RtlCompareMemory(d, s, l); - } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) { - BrutePoint(); - } _SEH2_END; - return (SIZE_T)-1; -} - -#else //PROTECTED_MEM_RTL - #define DbgMoveMemory(d, s, l) RtlMoveMemory(d, s, l) #define DbgCopyMemory(d, s, l) RtlCopyMemory(d, s, l) #define DbgCompareMemory(d, s, l) RtlCompareMemory(d, s, l) -#endif //PROTECTED_MEM_RTL - //#define KdPrint(_x_) #ifdef VALIDATE_STRUCTURES #define ValidateFileInfo(fi) \ { /* validate FileInfo */ \ - if (!fi || (fi)->IntegrityTag) { \ + if(!fi || (fi)->IntegrityTag) { \ KdPrint(("UDF: ERROR! Using deallocated structure !!!\n"));\ BrutePoint(); \ } \ - if (fi && !fi->Dloc) { \ + if(fi && !fi->Dloc) { \ KdPrint(("UDF: ERROR! FI without Dloc !!!\n"));\ BrutePoint(); \ } \ @@ -246,6 +219,8 @@ __inline VOID UDFTouch(IN PVOID addr) #define DbgCopyMemory(d, s, l) RtlCopyMemory(d, s, l) #define DbgCompareMemory(d, s, l) RtlCompareMemory(d, s, l) +#define ASSERT_REF(_a_) {NOTHING;} + #define UDFBreakPoint() {} #define BrutePoint() {} #define ValidateFileInfo(fi) {} @@ -257,7 +232,7 @@ __inline VOID UDFTouch(IN PVOID addr) #if defined UDF_DBG || defined PRINT_ALWAYS #define KdDump(a,b) \ -if ((a)!=NULL) { \ +if ((a)!=NULL) { \ ULONG i; \ for(i=0; i<(b); i++) { \ ULONG c; \ diff --git a/drivers/filesystems/udfs/udf_info/alloc.cpp b/drivers/filesystems/udfs/udf_info/alloc.cpp index 0f76b02a10818..ab008b415cf4d 100644 --- a/drivers/filesystems/udfs/udf_info/alloc.cpp +++ b/drivers/filesystems/udfs/udf_info/alloc.cpp @@ -56,7 +56,7 @@ UDFPhysLbaToPart( for(i=RefPartNum; iPartitionMaps; i++, pm++) { if (pm->PartitionNum == UDFGetPartNumByPartRef(Vcb, RefPartNum)) // wow! return relative address - retval = (Addr - pm->PartitionRoot) >> Vcb->LB2B_Bits; + retval = (Addr - pm->PartitionRoot); } #ifdef UDF_DBG @@ -99,8 +99,7 @@ UDFPartLbaToPhys( // to physical for(i=Addr->partitionReferenceNum; iPartitionMaps; i++) { if (Vcb->Partitions[i].PartitionNum == Addr->partitionReferenceNum) { - a = Vcb->Partitions[i].PartitionRoot + - (Addr->logicalBlockNum << Vcb->LB2B_Bits); + a = Vcb->Partitions[i].PartitionRoot + Addr->logicalBlockNum; if (a > Vcb->LastPossibleLBA) { AdPrint(("UDFPartLbaToPhys: root %x, lbn %x, lba %x (err1)\n", Vcb->Partitions[i].PartitionRoot, Addr->logicalBlockNum, a)); @@ -110,8 +109,8 @@ UDFPartLbaToPhys( return a; } } - a = Vcb->Partitions[i-1].PartitionRoot + - (Addr->logicalBlockNum << Vcb->LB2B_Bits); + a = Vcb->Partitions[i-1].PartitionRoot + Addr->logicalBlockNum; + if (a > Vcb->LastPossibleLBA) { AdPrint(("UDFPartLbaToPhys: i %x, root %x, lbn %x, lba %x (err2)\n", i, Vcb->Partitions[i-1].PartitionRoot, Addr->logicalBlockNum, a)); @@ -142,16 +141,14 @@ UDFPartLbaToPhysCompat( // to physical for(i=Addr->partitionReferenceNum; iPartitionMaps; i++) { if (Vcb->Partitions[i].PartitionNum == Addr->partitionReferenceNum) { - a = Vcb->Partitions[i].PartitionRoot + - (Addr->logicalBlockNum << Vcb->LB2B_Bits); + a = Vcb->Partitions[i].PartitionRoot + Addr->logicalBlockNum; if (a > Vcb->LastPossibleLBA) { BrutePoint(); } return a; } } - a = Vcb->Partitions[i-1].PartitionRoot + - (Addr->logicalBlockNum << Vcb->LB2B_Bits); + a = Vcb->Partitions[i-1].PartitionRoot + Addr->logicalBlockNum; if (a > Vcb->LastPossibleLBA) { BrutePoint(); } @@ -324,7 +321,7 @@ UDFFindMinSuitableExtent( SIZE_T max_lba=0; SIZE_T max_len=0; BOOLEAN align = FALSE; - SIZE_T PS = Vcb->WriteBlockSize >> Vcb->BlockSizeBits; + SIZE_T PS = Vcb->WriteBlockSize >> Vcb->SectorShift; UDF_CHECK_BITMAP_RESOURCE(Vcb); @@ -333,11 +330,9 @@ UDFFindMinSuitableExtent( align = TRUE; if (AllocFlags & EXTENT_FLAG_ALLOC_SEQUENTIAL) align = TRUE; - if (Length > (uint32)(UDF_EXTENT_LENGTH_MASK >> Vcb->BlockSizeBits)) - Length = (UDF_EXTENT_LENGTH_MASK >> Vcb->BlockSizeBits); - // align Length according to _Logical_ block size & convert it to BCount - i = (1<LB2B_Bits)-1; - Length = (Length+i) & ~i; + if (Length > (uint32)(UDF_EXTENT_LENGTH_MASK >> Vcb->SectorShift)) + Length = (UDF_EXTENT_LENGTH_MASK >> Vcb->SectorShift); + cur = (uint32*)(Vcb->FSBM_Bitmap); retry_no_align: @@ -558,8 +553,8 @@ UDFMarkSpaceAsXXXNoProtect_( if (!Map) return; - BS = Vcb->BlockSize; - BSh = Vcb->BlockSizeBits; + BS = Vcb->SectorSize; + BSh = Vcb->SectorShift; Vcb->BitmapModified = TRUE; UDFSetModified(Vcb); // walk through all frags in data area specified @@ -650,7 +645,6 @@ UDFMarkSpaceAsXXXNoProtect_( if (asXXX & AS_DISCARDED) { UDFUnmapRange(Vcb, lba, len); WCacheDiscardBlocks__(&(Vcb->FastCache), Vcb, lba, len); - UDFSetZeroBits(Vcb->ZSBM_Bitmap, lba, len); } if (Vcb->Vat) { // mark logical blocks in VAT as free @@ -733,8 +727,8 @@ UDFAllocFreeExtent_( PEXTENT_MAP Map = NULL; uint32 len, LBS, BSh, blen; - LBS = Vcb->LBlockSize; - BSh = Vcb->BlockSizeBits; + LBS = Vcb->SectorSize; + BSh = Vcb->SectorShift; uint32 MaxExtentLength = ALIGN_DOWN_BY(UDF_EXTENT_LENGTH_MASK, LBS); blen = (uint32)(((Length+LBS-1) & ~((int64)LBS-1)) >> BSh); ExtInfo->Mapping = NULL; @@ -779,9 +773,6 @@ UDFAllocFreeExtent_( ASSERT(!(Ext.extLength >> 30)); ASSERT(Ext.extLocation); - // mark newly allocated blocks as zero-filled - UDFSetZeroBits(Vcb->ZSBM_Bitmap, Ext.extLocation, (Ext.extLength & UDF_EXTENT_LENGTH_MASK) >> BSh); - if (AllocFlags & EXTENT_FLAG_VERIFY) { if (!UDFCheckArea(IrpContext, Vcb, Ext.extLocation, Ext.extLength >> BSh)) { AdPrint(("newly allocated extent contains BB\n")); @@ -881,7 +872,7 @@ UDFGetFreeSpace( s = Vcb->LastPossibleLBA - max(Vcb->NWA, Vcb->LastLBA); //if (s & ((int64)1 << 64)) s=0; } - return s >> Vcb->LB2B_Bits; + return s; } // end UDFGetFreeSpace() /* @@ -903,7 +894,7 @@ UDFGetTotalSpace( if (s & ((int64)1 << 63)) s=0; /* FIXME ReactOS this shift value was 64, which is undefiened behavior. */ s= Vcb->LastPossibleLBA - Vcb->Partitions[0].PartitionRoot; } - return s >> Vcb->LB2B_Bits; + return s; } // end UDFGetTotalSpace() /* @@ -924,9 +915,6 @@ UDFIsBlockAllocated( // check used if ((bm = (uint32*)(((PVCB)_Vcb)->FSBM_Bitmap))) ret_val = (UDFGetUsedBit(bm, Lba) ? WCACHE_BLOCK_USED : 0); - // check zero-filled - if ((bm = (uint32*)(((PVCB)_Vcb)->ZSBM_Bitmap))) - ret_val |= (UDFGetZeroBit(bm, Lba) ? WCACHE_BLOCK_ZERO : 0); } else { ret_val = WCACHE_BLOCK_USED; } diff --git a/drivers/filesystems/udfs/udf_info/dirtree.cpp b/drivers/filesystems/udfs/udf_info/dirtree.cpp index d2491bc35dfe7..16c4cde304419 100644 --- a/drivers/filesystems/udfs/udf_info/dirtree.cpp +++ b/drivers/filesystems/udfs/udf_info/dirtree.cpp @@ -517,7 +517,7 @@ UDFIndexDirectory( FileId = (PFILE_IDENT_DESC)((buff)+Offset); } } - if (((ULONG)Offset & (Vcb->LBlockSize-1)) > (Vcb->LBlockSize-sizeof(FILE_IDENT_DESC))) { + if (((ULONG)Offset & (Vcb->SectorSize-1)) > (Vcb->SectorSize-sizeof(FILE_IDENT_DESC))) { DirPrint((" badly aligned\n", Offset)); if (Vcb->Modified) { DirPrint((" queue repack request\n")); @@ -727,7 +727,7 @@ UDFPackDirectory__( if (!Vcb->Modified) return STATUS_SUCCESS; // start packing - LBS = Vcb->LBlockSize; + LBS = Vcb->SectorSize; Buf = (int8*)DbgAllocatePool(PagedPool, LBS*2); if (!Buf) return STATUS_INSUFFICIENT_RESOURCES; // we shall never touch 1st entry 'cause it can't be deleted @@ -883,7 +883,7 @@ UDFReTagDirectory( } // start packing - Buf = (int8*)DbgAllocatePool(PagedPool, Vcb->LBlockSize*2); + Buf = (int8*)DbgAllocatePool(PagedPool, Vcb->SectorSize*2); if (!Buf) return STATUS_INSUFFICIENT_RESOURCES; Offset = UDFDirIndex(hDirNdx,1)->Offset; diff --git a/drivers/filesystems/udfs/udf_info/extent.cpp b/drivers/filesystems/udfs/udf_info/extent.cpp index f86b0b4d0e8f1..05793bd06c12e 100644 --- a/drivers/filesystems/udfs/udf_info/extent.cpp +++ b/drivers/filesystems/udfs/udf_info/extent.cpp @@ -35,7 +35,7 @@ UDFExtentOffsetToLba( OUT uint32* Index ) { - uint32 j=0, l, d, BSh = Vcb->BlockSizeBits; + uint32 j=0, l, d, BSh = Vcb->SectorShift; uint32 Offs; uint32 i=0, BOffset; // block nums @@ -62,7 +62,7 @@ UDFExtentOffsetToLba( Offs = (*((uint32*)&Offset)) - (i << BSh); // offset in frag if (SectorOffset) - (*SectorOffset) = Offs & (Vcb->BlockSize-1);// offset in 1st Lba + (*SectorOffset) = Offs & (Vcb->SectorSize-1);// offset in 1st Lba if (AvailLength) (*AvailLength) = l - Offs;// bytes to EO frag if (Flags) @@ -119,7 +119,7 @@ UDFLocateLbaInExtent( IN lba_t lba ) { - uint32 l, BSh = Vcb->BlockSizeBits; + uint32 l, BSh = Vcb->SectorShift; uint32 i=0; while((l = ((Extent->extLength & UDF_EXTENT_LENGTH_MASK) >> BSh))) { @@ -398,10 +398,10 @@ UDFShortAllocDescToMapping( #ifdef UDF_CHECK_EXTENT_SIZE_ALIGNMENT ASSERT(!(len & (Vcb->LBlockSize-1) )); #endif //UDF_CHECK_EXTENT_SIZE_ALIGNMENT - if (len & (Vcb->LBlockSize-1)) { + if (len & (Vcb->SectorSize-1)) { w2k_compat = TRUE; } - ExtentNext[AllocDescsIndex].extLength = (len+Vcb->LBlockSize-1) & ~(Vcb->LBlockSize-1); + ExtentNext[AllocDescsIndex].extLength = (len+Vcb->SectorSize-1) & ~(Vcb->SectorSize-1); locAddr.logicalBlockNum = AllocDesc->extPosition; // Note: for compatibility Adaptec DirectCD we check 'len' here // That strange implementation records bogus extLocation in terminal entries @@ -555,9 +555,9 @@ UDFLongAllocDescToMapping( // Extent[i].extLength = len; #ifdef UDF_CHECK_EXTENT_SIZE_ALIGNMENT - ASSERT(!(len & (Vcb->LBlockSize-1) )); + ASSERT(!(len & (Vcb->SectorSize-1) )); #endif //UDF_CHECK_EXTENT_SIZE_ALIGNMENT - Extent[i].extLength = (len+Vcb->LBlockSize-1) & ~(Vcb->LBlockSize-1); + Extent[i].extLength = (len+Vcb->SectorSize-1) & ~(Vcb->SectorSize-1); // Note: for compatibility Adaptec DirectCD we check 'len' here // That strange implementation records bogus extLocation in terminal entries if (type != EXTENT_NOT_RECORDED_NOT_ALLOCATED && len) { @@ -842,8 +842,8 @@ UDFBuildShortAllocDescs( // but we need its lower part only #ifdef UDF_ALLOW_FRAG_AD uint32 ts, ac, len2; - uint32 LBS = Vcb->LBlockSize; - uint32 LBSh = Vcb->BlockSizeBits; + uint32 LBS = Vcb->SectorSize; + uint32 LBSh = Vcb->SectorShift; uint32 TagLen = 0; tag* Tag = NULL; PSHORT_AD saved_Alloc; @@ -872,7 +872,7 @@ UDFBuildShortAllocDescs( } if ((Vcb->CompatFlags & UDF_VCB_IC_W2K_COMPAT_ALLOC_DESCS) && i) { Alloc[i-1].extLength -= (ph_len - (ULONG)(FileInfo->Dloc->DataLoc.Length)) & - (Vcb->LBlockSize-1); + (Vcb->SectorSize-1); ExtPrint(("bShExt: cut tail -> %x\n", Alloc[i-1].extLength & UDF_EXTENT_LENGTH_MASK)); } @@ -1031,8 +1031,8 @@ UDFBuildLongAllocDescs( #ifdef UDF_ALLOW_FRAG_AD uint32 ac, len2, ts; uint32 TagLoc, prevTagLoc; - uint32 LBS = Vcb->LBlockSize; - uint32 LBSh = Vcb->BlockSizeBits; + uint32 LBS = Vcb->SectorSize; + uint32 LBSh = Vcb->SectorShift; uint32 BufOffs; uint32 ExtOffs = AllocExtent->Offset; PLONG_AD saved_Alloc; @@ -1059,7 +1059,7 @@ UDFBuildLongAllocDescs( } if ((Vcb->CompatFlags & UDF_VCB_IC_W2K_COMPAT_ALLOC_DESCS) && i) { Alloc[i-1].extLength -= (ph_len - (ULONG)(FileInfo->Dloc->DataLoc.Length)) & - (Vcb->LBlockSize-1); + (Vcb->SectorSize-1); ExtPrint(("bLnExt: cut tail -> %x\n", Alloc[i-1].extLength & UDF_EXTENT_LENGTH_MASK)); } @@ -1344,7 +1344,7 @@ UDFDiscardFESpace( // we should not discard allocated FEs if ( (Mapping->extLength >> 30) == EXTENT_RECORDED_ALLOCATED) { UDFPrint((" used @ %x\n", Mapping->extLocation)); - Mapping->extLength = Vcb->LBlockSize | (EXTENT_NOT_RECORDED_NOT_ALLOCATED << 30); + Mapping->extLength = Vcb->SectorSize | (EXTENT_NOT_RECORDED_NOT_ALLOCATED << 30); Mapping->extLocation = 0; } else { UDFPrint((" free @ %x\n", Mapping->extLocation)); @@ -1622,7 +1622,7 @@ UDFAllocateFESpace( // do nothing, even do not unpack } else if (Vcb->LowFreeSpace) { - status = UDFAllocFreeExtent(IrpContext, Vcb, Len << Vcb->LBlockSizeBits,p_start, p_end, FEExtInfo, EXTENT_FLAG_VERIFY); + status = UDFAllocFreeExtent(IrpContext, Vcb, Len << Vcb->SectorShift,p_start, p_end, FEExtInfo, EXTENT_FLAG_VERIFY); if (NT_SUCCESS(status)) { UDFPrint(("FE @ %x (1)\n", FEExtInfo->Mapping[0].extLocation )); } @@ -1638,17 +1638,17 @@ UDFAllocateFESpace( } else { l2 = p_end; } - status = UDFAllocFreeExtent(IrpContext, Vcb, lim << Vcb->LBlockSizeBits, l1, l2, Ext, EXTENT_FLAG_VERIFY); + status = UDFAllocFreeExtent(IrpContext, Vcb, lim << Vcb->SectorShift, l1, l2, Ext, EXTENT_FLAG_VERIFY); if (!NT_SUCCESS(status)) { - status = UDFAllocFreeExtent(IrpContext, Vcb, lim << Vcb->LBlockSizeBits, (p_start+fe_loc)/2, (fe_loc+p_end)/2, Ext, EXTENT_FLAG_VERIFY); + status = UDFAllocFreeExtent(IrpContext, Vcb, lim << Vcb->SectorShift, (p_start+fe_loc)/2, (fe_loc+p_end)/2, Ext, EXTENT_FLAG_VERIFY); } if (!NT_SUCCESS(status)) { - status = UDFAllocFreeExtent(IrpContext, Vcb, lim << Vcb->LBlockSizeBits, p_start, p_end, Ext, EXTENT_FLAG_VERIFY); + status = UDFAllocFreeExtent(IrpContext, Vcb, lim << Vcb->SectorShift, p_start, p_end, Ext, EXTENT_FLAG_VERIFY); } if (!NT_SUCCESS(status)) { - status = UDFAllocFreeExtent(IrpContext, Vcb, lim << Vcb->LBlockSizeBits, p_start+1024, p_end-1024, Ext, EXTENT_FLAG_VERIFY); + status = UDFAllocFreeExtent(IrpContext, Vcb, lim << Vcb->SectorShift, p_start+1024, p_end-1024, Ext, EXTENT_FLAG_VERIFY); } - if (!NT_SUCCESS(status = UDFAllocFreeExtent(IrpContext, Vcb, lim << Vcb->LBlockSizeBits, p_start, p_end, Ext, EXTENT_FLAG_VERIFY) )) { + if (!NT_SUCCESS(status = UDFAllocFreeExtent(IrpContext, Vcb, lim << Vcb->SectorShift, p_start, p_end, Ext, EXTENT_FLAG_VERIFY) )) { // can't pre-allocate space for multiple FEs. Try single FE UDFPrint(("allocate single FE entry\n")); status = UDFAllocFreeExtent(IrpContext, Vcb, Len, @@ -1671,7 +1671,7 @@ UDFAllocateFESpace( if ( (Ext->Mapping[i].extLength >> 30) == EXTENT_NOT_RECORDED_ALLOCATED ) { Ext->Mapping[i].extLength &= UDF_EXTENT_LENGTH_MASK; // EXTENT_RECORDED_ALLOCATED - Extent.extLength = Vcb->LBlockSize | (EXTENT_NOT_RECORDED_ALLOCATED << 30); + Extent.extLength = Vcb->SectorSize | (EXTENT_NOT_RECORDED_ALLOCATED << 30); Extent.extLocation = Ext->Mapping[i].extLocation; if (Vcb->BSBM_Bitmap) { @@ -1758,7 +1758,7 @@ UDFFreeFESpace( if (j != (ULONG)-1) { i = j; Ext->Mapping[i].extLocation = Lba; - Ext->Mapping[i].extLength = Vcb->LBlockSize | (EXTENT_NOT_RECORDED_ALLOCATED << 30); + Ext->Mapping[i].extLength = Vcb->SectorSize | (EXTENT_NOT_RECORDED_ALLOCATED << 30); goto clean_caller; } } @@ -1822,9 +1822,9 @@ UDFMarkAllocatedAsRecorded( uint32 i, len, lba, sLen; PEXTENT_MAP Extent = ExtInfo->Mapping; // Extent array PEXTENT_MAP NewExtent; - uint32 BS = Vcb->BlockSize; - uint32 LBS = Vcb->LBlockSize; - uint32 BSh = Vcb->BlockSizeBits; + uint32 BS = Vcb->SectorSize; + uint32 LBS = Vcb->SectorSize; + uint32 BSh = Vcb->SectorShift; uint32 MaxExtentLength = ALIGN_DOWN_BY(UDF_EXTENT_LENGTH_MASK, LBS); BOOLEAN TryPack = TRUE; #ifdef UDF_DBG @@ -1959,11 +1959,11 @@ UDFMarkNotAllocatedAsAllocated( PEXTENT_MAP Extent = ExtInfo->Mapping; // Extent array PEXTENT_MAP NewExtent; // uint32 BS = Vcb->BlockSize; - uint32 BSh = Vcb->BlockSizeBits; + uint32 BSh = Vcb->SectorShift; NTSTATUS status; EXTENT_INFO TmpExtInf; SIZE_T aLen, sLen; - SIZE_T LBS = Vcb->LBlockSize; + SIZE_T LBS = Vcb->SectorSize; // I don't know what else comment can be added here. // Just belive that it works /*lba = */ @@ -2107,7 +2107,7 @@ UDFMarkAllocatedAsNotXXX( PEXTENT_MAP NewExtent; // EXTENT_MAP TmpExtent; // uint32 BS = Vcb->BlockSize; - uint32 BSh = Vcb->BlockSizeBits; + uint32 BSh = Vcb->SectorShift; // NTSTATUS status; EXTENT_INFO TmpExtInf; uint32 aLen, sLen; @@ -2115,7 +2115,7 @@ UDFMarkAllocatedAsNotXXX( uint32 target_flags = Deallocate ? EXTENT_NOT_RECORDED_NOT_ALLOCATED : EXTENT_NOT_RECORDED_ALLOCATED; - SIZE_T LBS = Vcb->LBlockSize; + SIZE_T LBS = Vcb->SectorSize; EXTENT_MAP DeadMapping[2]; // I don't know what else comment can be added here. // Just belive that it works @@ -2252,9 +2252,9 @@ UDFResizeExtent( EXTENT_MAP TmpMapping[2]; uint32 s, pe, BSh, PS; SIZE_T req_s; - SIZE_T LBS = Vcb->LBlockSize; - BSh = Vcb->BlockSizeBits; - PS = Vcb->WriteBlockSize >> Vcb->BlockSizeBits; + SIZE_T LBS = Vcb->SectorSize; + BSh = Vcb->SectorShift; + PS = Vcb->WriteBlockSize >> Vcb->SectorShift; uint32 MaxGrow = ALIGN_DOWN_BY(UDF_EXTENT_LENGTH_MASK, LBS); BOOLEAN Sequential = FALSE; @@ -2649,7 +2649,7 @@ UDFBuildAllocDescs( ValidateFileInfo(FileInfo); AdPrint(("BuildAllocDesc\n")); // get space available in the 1st LBlock after FE - InitSz = Vcb->LBlockSize - FileInfo->Dloc->FileEntryLen; + InitSz = Vcb->SectorSize - FileInfo->Dloc->FileEntryLen; Allocs = (int8*)MyAllocatePool__(NonPagedPool, InitSz); if (!Allocs) { *AllocData = NULL; @@ -2759,7 +2759,7 @@ UDFPackMapping( uint32 i, j, l; uint32 LastLba, LastType, OldLen; uint32 OldSize, NewSize; - uint32 LBS = Vcb->LBlockSize; + uint32 LBS = Vcb->SectorSize; uint32 MaxExtentLength = ALIGN_DOWN_BY(UDF_EXTENT_LENGTH_MASK, LBS); #ifdef UDF_DBG @@ -2771,13 +2771,13 @@ UDFPackMapping( OldMap = ExtInfo->Mapping; LastLba = OldMap[0].extLocation; - OldLen = (OldMap[0].extLength & UDF_EXTENT_LENGTH_MASK) >> Vcb->BlockSizeBits; + OldLen = (OldMap[0].extLength & UDF_EXTENT_LENGTH_MASK) >> Vcb->SectorShift; LastType = OldMap[0].extLength >> 30; OldSize = NewSize = UDFGetMappingLength(OldMap); #ifdef UDF_DBG check_size = UDFGetExtentLength(ExtInfo->Mapping); - ASSERT(!(check_size & (Vcb->LBlockSize-1))); + ASSERT(!(check_size & (Vcb->SectorSize-1))); #endif //UDF_DBG l=OldMap[0].extLength & UDF_EXTENT_LENGTH_MASK; @@ -2797,7 +2797,7 @@ UDFPackMapping( } LastLba = OldMap[i].extLocation; LastType = OldMap[i].extLength >> 30; - OldLen = (OldMap[i].extLength & UDF_EXTENT_LENGTH_MASK) >> Vcb->BlockSizeBits; + OldLen = (OldMap[i].extLength & UDF_EXTENT_LENGTH_MASK) >> Vcb->SectorShift; } // no changes ? if (OldSize <= (NewSize + PACK_MAPPING_THRESHOLD)) { @@ -2815,7 +2815,7 @@ UDFPackMapping( j=0; NewMap[0] = OldMap[0]; LastLba = OldMap[0].extLocation; - OldLen = (OldMap[0].extLength & UDF_EXTENT_LENGTH_MASK) >> Vcb->BlockSizeBits; + OldLen = (OldMap[0].extLength & UDF_EXTENT_LENGTH_MASK) >> Vcb->SectorShift; LastType = OldMap[0].extLength >> 30; for(i=1; OldMap[i].extLength; i++) { @@ -2839,7 +2839,7 @@ UDFPackMapping( LastLba = OldMap[i].extLocation; LastType = OldMap[i].extLength >> 30; - OldLen = (OldMap[i].extLength & UDF_EXTENT_LENGTH_MASK) >> Vcb->BlockSizeBits; + OldLen = (OldMap[i].extLength & UDF_EXTENT_LENGTH_MASK) >> Vcb->SectorShift; } // write terminator j++; @@ -2873,8 +2873,8 @@ UDFUnPackMapping( { PEXTENT_MAP NewMapping; PEXTENT_MAP Mapping = ExtInfo->Mapping; - uint32 LBS = Vcb->LBlockSize; - uint32 len = (uint32)(UDFGetExtentLength(Mapping) >> Vcb->LBlockSizeBits); + uint32 LBS = Vcb->SectorSize; + uint32 len = (uint32)(UDFGetExtentLength(Mapping) >> Vcb->SectorShift); uint32 i,j, type, base, d; LONG l; @@ -2883,7 +2883,7 @@ UDFUnPackMapping( if (!NewMapping) return STATUS_INSUFFICIENT_RESOURCES; j=0; - d = LBS >> Vcb->BlockSizeBits; + d = LBS >> Vcb->SectorShift; for(i=0; (l = (Mapping[i].extLength & UDF_EXTENT_LENGTH_MASK)); i++) { base = Mapping[i].extLocation; type = Mapping[i].extLength & UDF_EXTENT_FLAG_MASK; @@ -2957,7 +2957,7 @@ UDFIsExtentCached( // check for reading tail to_read = min(to_read, Length); if (flags == EXTENT_RECORDED_ALLOCATED) { - retstat = UDFIsDataCached(Vcb, Lba, (to_read+sect_offs+Vcb->BlockSize-1)>>Vcb->BlockSizeBits); + retstat = UDFIsDataCached(Vcb, Lba, (to_read+sect_offs+Vcb->SectorSize-1)>>Vcb->SectorShift); if (!retstat) goto EO_IsCached; } else if (ForWrite) { goto EO_IsCached; @@ -3063,7 +3063,7 @@ UDFReadExtent( // check for reading tail to_read = min(to_read, Length); if (flags == EXTENT_RECORDED_ALLOCATED) { - status = UDFReadData(IrpContext, Vcb, TRUE, ( ((uint64)Lba) << Vcb->BlockSizeBits) + sect_offs, to_read, Direct, Buffer, &_ReadBytes); + status = UDFReadData(IrpContext, Vcb, TRUE, ( ((uint64)Lba) << Vcb->SectorShift) + sect_offs, to_read, Direct, Buffer, &_ReadBytes); (*ReadBytes) += _ReadBytes; if (!NT_SUCCESS(status)) return status; } else { @@ -3299,21 +3299,21 @@ UDFWriteExtent( // if (!prepare) { // pad 1st logical block - if ((sect_offs || (sect_offs + to_write < Vcb->LBlockSize) ) + if ((sect_offs || (sect_offs + to_write < Vcb->SectorSize) ) && !Vcb->CDR_Mode) { status = UDFWriteData(IrpContext, Vcb, TRUE, - ( ((uint64)Lba) << Vcb->BlockSizeBits), - Vcb->LBlockSize, Direct, Vcb->ZBuffer, &_WrittenBytes); + ( ((uint64)Lba) << Vcb->SectorShift), + Vcb->SectorSize, Direct, Vcb->ZBuffer, &_WrittenBytes); if (!NT_SUCCESS(status)) return status; } // pad last logical block - if ((sect_offs + to_write > Vcb->LBlockSize) && - (sect_offs + to_write) & (Vcb->LBlockSize - 1)) { + if ((sect_offs + to_write > Vcb->SectorSize) && + (sect_offs + to_write) & (Vcb->SectorSize - 1)) { status = UDFWriteData(IrpContext, Vcb, TRUE, - (( ((uint64)Lba) << Vcb->BlockSizeBits) + sect_offs + to_write) & ~((int64)(Vcb->LBlockSize)-1), - Vcb->LBlockSize, Direct, Vcb->ZBuffer, &_WrittenBytes); + (( ((uint64)Lba) << Vcb->SectorShift) + sect_offs + to_write) & ~((int64)(Vcb->SectorSize)-1), + Vcb->SectorSize, Direct, Vcb->ZBuffer, &_WrittenBytes); } if (!NT_SUCCESS(status)) return status; @@ -3323,7 +3323,7 @@ UDFWriteExtent( } ASSERT(to_write); // if (!prepare) { - status = UDFWriteData(IrpContext, Vcb, TRUE, ( ((uint64)Lba) << Vcb->BlockSizeBits) + sect_offs, to_write, Direct, Buffer, &_WrittenBytes); + status = UDFWriteData(IrpContext, Vcb, TRUE, ( ((uint64)Lba) << Vcb->SectorShift) + sect_offs, to_write, Direct, Buffer, &_WrittenBytes); *WrittenBytes += _WrittenBytes; if (!NT_SUCCESS(status)) return status; /* } else { @@ -3363,7 +3363,7 @@ UDFZeroExtent( uint32 Lba, sect_offs, flags; NTSTATUS status; SIZE_T to_write, _WrittenBytes; - SIZE_T LBS = Vcb->LBlockSize; + SIZE_T LBS = Vcb->SectorSize; AdPrint(("Zero ExtInfo %x, Mapping %x\n", ExtInfo, ExtInfo->Mapping)); @@ -3393,7 +3393,7 @@ UDFZeroExtent( } else { // fill tail of the 1st Block with ZEROs if (sect_offs) { - status = UDFWriteData(IrpContext, Vcb, TRUE, ( ((uint64)Lba) << Vcb->BlockSizeBits) + sect_offs, + status = UDFWriteData(IrpContext, Vcb, TRUE, ( ((uint64)Lba) << Vcb->SectorShift) + sect_offs, min(to_write, LBS-sect_offs), Direct, Vcb->ZBuffer, &_WrittenBytes); *WrittenBytes += _WrittenBytes; @@ -3431,7 +3431,7 @@ UDFZeroExtent( } // fill beginning of the last Block with ZEROs if (to_write) { - status = UDFWriteData(IrpContext, Vcb, TRUE, ( ((uint64)Lba) << Vcb->BlockSizeBits), to_write, Direct, Vcb->ZBuffer, &_WrittenBytes); + status = UDFWriteData(IrpContext, Vcb, TRUE, ( ((uint64)Lba) << Vcb->SectorShift), to_write, Direct, Vcb->ZBuffer, &_WrittenBytes); *WrittenBytes += _WrittenBytes; if (!NT_SUCCESS(status)) return status; diff --git a/drivers/filesystems/udfs/udf_info/mount.cpp b/drivers/filesystems/udfs/udf_info/mount.cpp index 2d34351eb08d0..8c6281fd7e487 100644 --- a/drivers/filesystems/udfs/udf_info/mount.cpp +++ b/drivers/filesystems/udfs/udf_info/mount.cpp @@ -34,7 +34,6 @@ } #define UDF_BUG_CHECK_ID UDF_FILE_UDF_INFO_MOUNT -#define MRW_DMA_OFFSET 0x500 NTSTATUS __fastcall @@ -78,8 +77,8 @@ UDFPrepareXSpaceBitmap( locAddr.partitionReferenceNum = (uint16)RefPartNum; plen = UDFPartStart(Vcb, RefPartNum) + UDFPartLen(Vcb, RefPartNum); - BS = Vcb->BlockSize; - LBS = Vcb->LBlockSize; + BS = Vcb->SectorSize; + LBS = Vcb->SectorSize; *XSl = sizeof(SPACE_BITMAP_DESC) + ((plen+7)>>3); _XSBM = (int8*)DbgAllocatePool(NonPagedPool, (*XSl + BS - 1) & ~(BS-1) ); @@ -251,7 +250,7 @@ UDFUpdateXSpaceBitmaps( if (FSBM) fpart_bm = FSBM + sizeof(SPACE_BITMAP_DESC); pend = min(pstart + plen, Vcb->FSBM_BitCount); - d=1<LB2B_Bits; + d=1; // if we have some bad bits, mark corresponding area as BAD if (bad_bm) { for(i=pstart; iLVid_loc.extLocation, Vcb->LVid_loc.extLength)); - len = max(Vcb->LVid_loc.extLength, Vcb->BlockSize); + len = max(Vcb->LVid_loc.extLength, Vcb->SectorSize); lvid = Vcb->LVid; if (lvid->descTag.tagSerialNum > UDF_LVID_TTL) { // TODO: allocate space for new LVID @@ -425,7 +424,7 @@ UDFUpdateLogicalVolInt( // update Free Space Table partFreeSpace = (uint32*)(lvid+1); for(i=0; inumOfPartitions; i++) { - pSize = UDFGetPartFreeSpace(Vcb, i) >> Vcb->LB2B_Bits; + pSize = UDFGetPartFreeSpace(Vcb, i); equal = equal && (partFreeSpace[i] == pSize); partFreeSpace[i] = pSize; } @@ -450,8 +449,8 @@ UDFUpdateLogicalVolInt( PTag->tagLocation, 0); Vcb->IntegrityType = INTEGRITY_TYPE_OPEN; // make happy auto-dirty - RC = UDFWriteSectors(IrpContext, Vcb, TRUE, PTag->tagLocation, len >> Vcb->BlockSizeBits, FALSE, (int8*)(lvid), &WrittenBytes); - WCacheFlushBlocks__(IrpContext, &Vcb->FastCache, Vcb, PTag->tagLocation, len >> Vcb->BlockSizeBits); + RC = UDFWriteSectors(IrpContext, Vcb, TRUE, PTag->tagLocation, len >> Vcb->SectorShift, FALSE, (int8*)(lvid), &WrittenBytes); + WCacheFlushBlocks__(IrpContext, &Vcb->FastCache, Vcb, PTag->tagLocation, len >> Vcb->SectorShift); // update it here to prevent recursion Vcb->IntegrityType = lvid->integrityType; @@ -483,8 +482,8 @@ UDFUpdateSparingTable( if (!Vcb->SparingTableModified) return STATUS_SUCCESS; if (!Vcb->SparingTable) return STATUS_SUCCESS; - BC = (Vcb->SparingTableLength >> Vcb->BlockSizeBits) + 1; - SparTable = (PSPARING_TABLE)MyAllocatePool__(NonPagedPool, BC*Vcb->BlockSize); + BC = (Vcb->SparingTableLength >> Vcb->SectorShift) + 1; + SparTable = (PSPARING_TABLE)MyAllocatePool__(NonPagedPool, BC*Vcb->SectorSize); if (!SparTable) return STATUS_INSUFFICIENT_RESOURCES; // if a part of Sparing Table is already loaded, // update it with data from another one @@ -531,8 +530,8 @@ UDFUpdateSparingTable( BC2 = ((sizeof(SPARING_TABLE) + SparTable->reallocationTableLen*sizeof(SparingEntry) + - Vcb->BlockSize-1) - >> Vcb->BlockSizeBits); + Vcb->SectorSize-1) + >> Vcb->SectorShift); if (BC2 > BC) { UDFPrint((" sizeSparingTable @%x too long: %x > %x\n", Vcb->SparingTableLoc[i], BC2, BC @@ -551,8 +550,8 @@ UDFUpdateSparingTable( BC2 = ((sizeof(SPARING_TABLE) + Vcb->SparingCount*sizeof(SparingEntry) + - Vcb->BlockSize-1) - >> Vcb->BlockSizeBits); + Vcb->SectorSize-1) + >> Vcb->SectorShift); if (BC2 > BC) { UDFPrint((" new sizeSparingTable @%x too long: %x > %x\n", Vcb->SparingTableLoc[i], BC2, BC @@ -580,7 +579,8 @@ UDFUpdateSparingTable( */ // if (merged) { UDFPrint(("UDF: record updated\n")); - status = UDFWriteSectors(IrpContext, Vcb, FALSE, Vcb->SparingTableLoc[i], BC2, FALSE, (int8*)SparTable, &ReadBytes); + SIZE_T WrittenBytes; + status = UDFWriteSectors(IrpContext, Vcb, FALSE, Vcb->SparingTableLoc[i], BC2, FALSE, (int8*)SparTable, &WrittenBytes); if (!NT_SUCCESS(status)) { if (!NT_SUCCESS(status2)) { status2 = status; @@ -621,14 +621,14 @@ UDFUpdateLogicalVol( goto Err_SetVI; } - lvd = (LogicalVolDesc*)MyAllocatePool__(NonPagedPool, max(Vcb->BlockSize, sizeof(LogicalVolDesc)) ); + lvd = (LogicalVolDesc*)MyAllocatePool__(NonPagedPool, max(Vcb->SectorSize, sizeof(LogicalVolDesc)) ); if (!lvd) { status = STATUS_INSUFFICIENT_RESOURCES; goto Err_SetVI; } - UDFPrint(("UDF: Updating LVD @%x (%x)\n", Lba.block, Vcb->BlockSize)); + UDFPrint(("UDF: Updating LVD @%x (%x)\n", Lba.block, Vcb->SectorSize)); status = UDFSetDstring(&(Vcb->VolIdent), (dstring*)&CS0, CUR_IDENT_SZ); if (!NT_SUCCESS(status)) { @@ -685,7 +685,7 @@ UDFUpdateVDS( ) { NTSTATUS status; - int8* Buf = (int8*)DbgAllocatePool(NonPagedPool,Vcb->LBlockSize); + int8* Buf = (int8*)DbgAllocatePool(NonPagedPool,Vcb->SectorSize); UDF_VDS_RECORD vds[VDS_POS_LENGTH]; uint32 i,j; uint16 ident; @@ -731,7 +731,7 @@ UDFUpdateVDS( if (!(flags & 1)) continue; // update partition descriptor(s) - int8* Buf2 = (int8*)DbgAllocatePool(NonPagedPool,Vcb->BlockSize); + int8* Buf2 = (int8*)DbgAllocatePool(NonPagedPool,Vcb->SectorSize); if (!Buf2) { DbgFreePool(Buf); return STATUS_INSUFFICIENT_RESOURCES; @@ -817,7 +817,7 @@ UDFUpdateVolIdent( ) { #define CUR_IDENT_SZ (sizeof(pvoldesc->volIdent)) - PrimaryVolDesc* pvoldesc = (PrimaryVolDesc*)MyAllocatePool__(NonPagedPool, max(Vcb->BlockSize, sizeof(PrimaryVolDesc)) ); + PrimaryVolDesc* pvoldesc = (PrimaryVolDesc*)MyAllocatePool__(NonPagedPool, max(Vcb->SectorSize, sizeof(PrimaryVolDesc)) ); NTSTATUS status; dstring CS0[CUR_IDENT_SZ]; uint16 ident; @@ -825,7 +825,7 @@ UDFUpdateVolIdent( if (!pvoldesc) return STATUS_INSUFFICIENT_RESOURCES; - UDFPrint(("UDF: Updating PVD @%x (%x)\n", Lba.block, Vcb->BlockSize)); + UDFPrint(("UDF: Updating PVD @%x (%x)\n", Lba.block, Vcb->SectorSize)); status = UDFSetDstring(&(Vcb->VolIdent), (dstring*)&CS0, CUR_IDENT_SZ); if (!NT_SUCCESS(status)) { @@ -909,9 +909,8 @@ UDFUpdateNonAllocated( } UDFPrint(("add lba %#x to NonAllocFileInfo\n", i)); DataLoc->Modified = TRUE; - Ext.extLength = Vcb->LBlockSize; - // align lba on LogicalBlock boundary - Ext.extLocation = i & ~((1<LB2B_Bits) - 1); + Ext.extLength = Vcb->SectorSize; + Ext.extLocation = i; Map = UDFExtentToMapping(&Ext); DataLoc->Mapping = UDFMergeMappings(DataLoc->Mapping, Map); } @@ -944,7 +943,7 @@ UDFUmount__( Vcb->VcbState |= UDF_VCB_ASSUME_ALL_USED; if (Vcb->CDR_Mode) { // flush internal cache - if (WCacheGetWriteBlockCount__(&(Vcb->FastCache)) >= (Vcb->WriteBlockSize >> Vcb->BlockSizeBits) ) + if (WCacheGetWriteBlockCount__(&(Vcb->FastCache)) >= (Vcb->WriteBlockSize >> Vcb->SectorShift) ) WCacheFlushAll__(IrpContext, &Vcb->FastCache, Vcb); // record VAT return UDFRecordVAT(IrpContext, Vcb); @@ -1019,9 +1018,9 @@ UDFUmount__( Anchor Volume Descriptors on the target device */ lba_t -UDFFindAnchor( +UDFFindAnchorVolumeDescriptor( IN PIRP_CONTEXT IrpContext, - PVCB Vcb // Volume control block + PVCB Vcb ) { // NTSTATUS RC = STATUS_SUCCESS; @@ -1030,9 +1029,9 @@ UDFFindAnchor( uint32 i; uint32 LastBlock; NTSTATUS status; - int8* Buf = (int8*)MyAllocatePool__(NonPagedPool,Vcb->BlockSize); - BOOLEAN MRW_candidate; - BOOLEAN IsMRW = (Vcb->MRWStatus != 0); + + int8* Buf = (int8*)MyAllocatePool__(NonPagedPool, ROUND_TO_PAGES(SectorAlign(Vcb, sizeof(AnchorVolDescPtr)))); + if (!Buf) return 0; @@ -1059,31 +1058,19 @@ UDFFindAnchor( for (i=0; iAnchor)/sizeof(int); i++) { if (Vcb->Anchor[i] > Vcb->LastLBA) Vcb->Anchor[i] = 0; - MRW_candidate = FALSE; + if (Vcb->Anchor[i]) { UDFPrint(("check Anchor %x\n", Vcb->Anchor[i])); if (!NT_SUCCESS(status = UDFReadTagged(IrpContext, Vcb, Buf, Vcb->Anchor[i], Vcb->Anchor[i], &ident))) { - // Fucking MRW... - if (!IsMRW && (i<2) && - (Vcb->CompatFlags & UDF_VCB_IC_MRW_ADDR_PROBLEM)) { - if (NT_SUCCESS(status = UDFReadTagged(IrpContext, Vcb, Buf, - Vcb->Anchor[i]+MRW_DMA_OFFSET, Vcb->Anchor[i], &ident))) { - // do MRW workaround..... - UDFPrint(("UDF: looks like we have MRW....\n")); - MRW_candidate = TRUE; - goto MRW_workaround; - } - } - Vcb->Anchor[i] = 0; if (status == STATUS_NONEXISTENT_SECTOR) { UDFPrint(("UDF: disk seems to be incomplete\n")); break; } } else { -MRW_workaround: + if ((ident != TID_ANCHOR_VOL_DESC_PTR) && ((i<6) || (ident != TID_FILE_ENTRY && ident != TID_EXTENDED_FILE_ENTRY))) { Vcb->Anchor[i] = 0; @@ -1091,15 +1078,6 @@ UDFFindAnchor( UDFPrint(("UDF: Found AVD at %x (point %d)\n",Vcb->Anchor[i], i)); if (!LastBlock) LastBlock = Vcb->LastLBA; - if (MRW_candidate) { - UDFPrint(("UDF: looks like we _*really*_ have MRW....\n")); - IsMRW = TRUE; - ASSERT(Vcb->LastReadTrack == 1); - Vcb->TrackMap[Vcb->LastReadTrack].Flags |= TrackMap_FixMRWAddressing; - WCachePurgeAll__(IrpContext, &Vcb->FastCache, Vcb); - UDFPrint(("UDF: MRW on non-MRW drive => ReadOnly")); - Vcb->VcbState |= VCB_STATE_VOLUME_READ_ONLY; - } } } } @@ -1124,7 +1102,7 @@ UDFFindVRS( uint32 retStat = 0; uint32 BeginOffset = Vcb->FirstLBA; NTSTATUS RC; - int8* buffer = (int8*)MyAllocatePool__(NonPagedPool,Vcb->BlockSize); + int8* buffer = (int8*)MyAllocatePool__(NonPagedPool,Vcb->SectorSize); SIZE_T ReadBytes; if (!buffer) return 0; @@ -1254,90 +1232,159 @@ UDFLoadLogicalVolInt( ) { NTSTATUS RC = STATUS_SUCCESS; - uint32 len; - SIZE_T _ReadBytes; + uint32 Len; + uint32 Lbn; + uint32 SectorSize; int8* Buf = NULL; + int8* TempBuf = NULL; uint16 ident; LogicalVolIntegrityDescImpUse* LVID_iUse; LogicalVolHeaderDesc* LVID_hd; - extent_ad last_loc; - BOOLEAN read_last = FALSE; - uint32 lvid_count = 0; + uint32 MaxIterations = UDF_MAX_LVID_CHAIN_LENGTH; ASSERT(!Vcb->LVid); if (Vcb->LVid) { MyFreePool__(Vcb->LVid); Vcb->LVid = NULL; } - // walk through all sectors inside LogicalVolumeIntegrityDesc - while(loc.extLength) { - UDFPrint(("UDF: Reading LVID @%x (%x)\n", loc.extLocation, loc.extLength)); - len = max(loc.extLength, Vcb->BlockSize); - Buf = (int8*)MyAllocatePool__(NonPagedPool,len); - if (!Buf) - return STATUS_INSUFFICIENT_RESOURCES; - RC = UDFReadTagged(IrpContext, Vcb, Buf, loc.extLocation, loc.extLocation, &ident); - if (!NT_SUCCESS(RC)) { -exit_with_err: - UDFPrint(("UDF: Reading LVID @%x (%x) failed.\n", loc.extLocation, loc.extLength)); - switch(Vcb->PartitialDamagedVolumeAction) { - case UDF_PART_DAMAGED_RO: - UDFPrint(("UDF: Switch to r/o mode.\n")); + + + // Get extent length and starting LBN + + Len = loc.extLength; + Lbn = loc.extLocation; + SectorSize = Vcb->SectorSize; + + + // Validate: length must be non-zero and sector-aligned + + if (Len == 0 || ((Len & (SectorSize - 1)) != 0)) { + return STATUS_DISK_CORRUPT_ERROR; + } + + + // Allocate sector buffer + + Buf = (int8*)MyAllocatePool__(NonPagedPool, SectorSize); + if (!Buf) { + return STATUS_INSUFFICIENT_RESOURCES; + } + + _SEH2_TRY { + + // Process integrity descriptors - one sector at a time + + while (Len != 0) { + + UDFPrint(("UDF: Reading LVID @%x (%x)\n", Lbn, Len)); + + // + // Read one sector and verify tag + // + RC = UDFReadTagged(IrpContext, Vcb, Buf, Lbn, Lbn, &ident); + if (!NT_SUCCESS(RC)) { + UDFPrint(("UDF: Reading LVID @%x failed.\n", Lbn)); Vcb->VcbState |= VCB_STATE_VOLUME_READ_ONLY; - RC = STATUS_SUCCESS; - break; - case UDF_PART_DAMAGED_NO: - UDFPrint(("UDF: Switch to raw mount mode, return UNRECOGNIZED_VOLUME.\n")); - Vcb->VcbState |= UDF_VCB_FLAGS_RAW_DISK; - //RC = STATUS_WRONG_VOLUME; + try_return(RC = STATUS_SUCCESS); + } + + // Check for unrecorded sector (tag ident == 0) + + if (ident == 0) { break; - case UDF_PART_DAMAGED_RW: - default: - UDFPrint(("UDF: Keep r/w mode for your own risk.\n")); - RC = STATUS_SUCCESS; - // asume we have INTEGRITY_TYPE_CLOSE - Vcb->IntegrityType = INTEGRITY_TYPE_CLOSE; + } + + // Must be LVID or Terminating Descriptor + + if (ident == TID_TERMINATING_DESC) { + // Terminating descriptor - done with this extent break; } - MyFreePool__(Buf); - return RC; - } + if (ident != TID_LOGICAL_VOL_INTEGRITY_DESC) { + try_return(RC = STATUS_DISK_CORRUPT_ERROR); + } - // handle Terminal Entry - if (ident == TID_TERMINAL_ENTRY) { - read_last = TRUE; - MyFreePool__(Buf); - Vcb->LVid = NULL; - loc = last_loc; - continue; - } else - if (ident != TID_LOGICAL_VOL_INTEGRITY_DESC) { - RC = STATUS_DISK_CORRUPT_ERROR; - goto exit_with_err; - } + // Valid LVID found - check integrity type - Vcb->LVid = (LogicalVolIntegrityDesc *)Buf; - RC = UDFReadData(IrpContext, Vcb, TRUE, ((uint64)(loc.extLocation)) << Vcb->BlockSizeBits, len, FALSE, Buf, &_ReadBytes); - // update info - if ( !read_last && - Vcb->LVid->nextIntegrityExt.extLength) { - // go to next LVID - last_loc = loc; - loc = Vcb->LVid->nextIntegrityExt; - Vcb->LVid = NULL; - lvid_count++; - if (lvid_count > UDF_MAX_LVID_CHAIN_LENGTH) { - RC = STATUS_DISK_CORRUPT_ERROR; - goto exit_with_err; + LogicalVolIntegrityDesc* lvid = (LogicalVolIntegrityDesc*)Buf; + + if (lvid->integrityType != INTEGRITY_TYPE_OPEN && + lvid->integrityType != INTEGRITY_TYPE_CLOSE) { + try_return(RC = STATUS_DISK_CORRUPT_ERROR); } - MyFreePool__(Buf); - continue; + + + // Check for continuation extent (nextIntegrityExt) + + if (lvid->nextIntegrityExt.extLength != 0) { + uint32 NextLen = lvid->nextIntegrityExt.extLength; + + // + // Decrement max iterations to prevent infinite loops + // + MaxIterations--; + if (MaxIterations == 0) { + UDFPrint(("UDF: LVID chain too long, aborting.\n")); + try_return(RC = STATUS_DISK_CORRUPT_ERROR); + } + + // + // Validate next extent alignment + // + if ((NextLen & (SectorSize - 1)) != 0) { + try_return(RC = STATUS_DISK_CORRUPT_ERROR); + } + + + // Prepare jump to continuation extent: + // After "Len -= SectorSize; Lbn++;" below, we'll have + // Len = NextLen and Lbn = nextIntegrityExt.extLocation + + Len = NextLen + SectorSize; + Lbn = lvid->nextIntegrityExt.extLocation - 1; + } + + + // Swap buffers - save current descriptor as result + + TempBuf = (int8*)Vcb->LVid; + Vcb->LVid = (LogicalVolIntegrityDesc*)Buf; + Buf = TempBuf; + TempBuf = NULL; + + // + // Allocate new buffer for next iteration if needed + // + if (Buf == NULL && Len > SectorSize) { + Buf = (int8*)MyAllocatePool__(NonPagedPool, SectorSize); + if (!Buf) { + try_return(RC = STATUS_INSUFFICIENT_RESOURCES); + } + } + + // Advance to next sector + + Len -= SectorSize; + Lbn++; + } + + + // Check if we found a valid LVID + + if (Vcb->LVid == NULL) { + UDFPrint(("UDF: No valid LVID found.\n")); + Vcb->VcbState |= VCB_STATE_VOLUME_READ_ONLY; + try_return(RC = STATUS_SUCCESS); } - // process last LVID + + + // Process the last (most recent) LVID + Vcb->origIntegrityType = Vcb->IntegrityType = Vcb->LVid->integrityType; - Vcb->LVid_loc = loc; + Vcb->LVid_loc.extLength = SectorSize; + Vcb->LVid_loc.extLocation = Lbn - 1; // Last read sector LVID_iUse = UDFGetLVIDiUse(Vcb); @@ -1357,8 +1404,9 @@ UDFLoadLogicalVolInt( UDFPrint((" nDirs: %x\n",Vcb->numDirs )); // Check if we can understand this format - if (Vcb->minUDFReadRev > UDF_MAX_READ_REVISION) + if (Vcb->minUDFReadRev > UDF_MAX_READ_REVISION) { RC = STATUS_UNRECOGNIZED_VOLUME; + } // Check if we know how to write here if (Vcb->minUDFWriteRev > UDF_MAX_WRITE_REVISION) { UDFPrint((" Target FS requires: %x Revision => ReadOnly\n",Vcb->minUDFWriteRev)); @@ -1369,7 +1417,27 @@ UDFLoadLogicalVolInt( Vcb->NextUniqueId = LVID_hd->uniqueID; UDFPrint((" Next FID: %x\n",Vcb->NextUniqueId)); - break; +try_exit: NOTHING; + + } _SEH2_FINALLY { + + // + // Free temporary buffer + // + if (Buf != NULL) { + MyFreePool__(Buf); + } + + } _SEH2_END; + + // + // If failed, free any allocated LVID + // + if (!NT_SUCCESS(RC)) { + if (Vcb->LVid != NULL) { + MyFreePool__(Vcb->LVid); + Vcb->LVid = NULL; + } } return RC; @@ -1404,29 +1472,19 @@ UDFLoadLogicalVol( return STATUS_DISK_CORRUPT_ERROR; } UDFPrint(("UDF: volDescSeqNum = %x\n", lvd->volDescSeqNum)); - // Get logical block size (may be different from physical) - Vcb->LBlockSize = lvd->logicalBlockSize; + + // Since UDF requires that all Volumes within a Volume Set have the same logical sector size, + // the Logical Block Size will be the same as the logical sector size of the Volume. + + if (lvd->logicalBlockSize != Vcb->SectorSize) { + + return STATUS_UNRECOGNIZED_VOLUME; + } + // Get current UDF revision // Get Read-Only flags UDFReadEntityID_Domain(Vcb, &(lvd->domainIdent)); - if (Vcb->LBlockSize < Vcb->BlockSize) - return STATUS_DISK_CORRUPT_ERROR; - switch(Vcb->LBlockSize) { - case 512: Vcb->LBlockSizeBits = 9; break; - case 1024: Vcb->LBlockSizeBits = 10; break; - case 2048: Vcb->LBlockSizeBits = 11; break; - case 4096: Vcb->LBlockSizeBits = 12; break; - case 8192: Vcb->LBlockSizeBits = 13; break; - case 16384: Vcb->LBlockSizeBits = 14; break; - case 32768: Vcb->LBlockSizeBits = 15; break; - case 65536: Vcb->LBlockSizeBits = 16; break; - default: - UDFPrint(("UDF: Bad block size (%ld)\n", Vcb->LBlockSize)); - return STATUS_DISK_CORRUPT_ERROR; - } - UDFPrint(("UDF: logical block size (%ld)\n", Vcb->LBlockSize)); - Vcb->LB2B_Bits = Vcb->LBlockSizeBits - Vcb->BlockSizeBits; UDFPrint(("UDF: mapTableLength = %x\n", lvd->mapTableLength)); UDFPrint(("UDF: numPartitionMaps = %x\n", lvd->numPartitionMaps)); // walk through all available part maps @@ -1529,17 +1587,11 @@ UDFLoadBogusLogicalVol( return STATUS_DISK_CORRUPT_ERROR; } UDFPrint(("UDF: volDescSeqNum = %x\n", 0)); - // Get logical block size (may be different from physical) - Vcb->LBlockSize = 2048; + // Get current UDF revision // Get Read-Only flags // UDFReadEntityID_Domain(Vcb, &(lvd->domainIdent)); - if (Vcb->LBlockSize < Vcb->BlockSize) - return STATUS_DISK_CORRUPT_ERROR; - Vcb->LBlockSizeBits = 11; - UDFPrint(("UDF: logical block size (%ld)\n", Vcb->LBlockSize)); - Vcb->LB2B_Bits = Vcb->LBlockSizeBits - Vcb->BlockSizeBits; UDFPrint(("UDF: mapTableLength = %x\n", 0)); UDFPrint(("UDF: numPartitionMaps = %x\n", 0)); @@ -1580,8 +1632,7 @@ UDFAddXSpaceBitmap( IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN uint32 RefPartNum, - IN PSHORT_AD bm, - IN ULONG bm_type + IN PSHORT_AD bm ) { int8* tmp; @@ -1604,7 +1655,7 @@ UDFAddXSpaceBitmap( i=UDFPartStart(Vcb, RefPartNum); flags = bm->extLength >> 30; if (!flags /*|| flags == EXTENT_NOT_RECORDED_ALLOCATED*/) { - tmp = (int8*)DbgAllocatePool(NonPagedPool, max(Length, Vcb->BlockSize)); + tmp = (int8*)DbgAllocatePool(NonPagedPool, max(Length, Vcb->SectorSize)); if (!tmp) return STATUS_INSUFFICIENT_RESOURCES; locAddr.partitionReferenceNum = (uint16)RefPartNum; locAddr.logicalBlockNum = bm->extPosition; @@ -1621,42 +1672,24 @@ UDFAddXSpaceBitmap( } // read the whole Bitmap - if (!NT_SUCCESS(status = UDFReadData(IrpContext, Vcb, FALSE, ((uint64)lba)<BlockSizeBits, Length, FALSE, tmp, &ReadBytes))) + if (!NT_SUCCESS(status = UDFReadData(IrpContext, Vcb, FALSE, ((uint64)lba)<SectorShift, Length, FALSE, tmp, &ReadBytes))) goto err_addxsbm_1; - lim = min(i + ((lim2 = ((PSPACE_BITMAP_DESC)tmp)->numOfBits) << Vcb->LB2B_Bits), Vcb->FSBM_BitCount); + lim = min(i + (lim2 = ((PSPACE_BITMAP_DESC)tmp)->numOfBits), Vcb->FSBM_BitCount); tmp_bm = tmp + sizeof(SPACE_BITMAP_DESC); j = 0; for(;(l = UDFGetBitmapLen((uint32*)tmp_bm, j, lim2)) && (iLB2B_Bits; + l2 = l; // ...and mark them - if (bm_type == UDF_FSPACE_BM) { - bit_set = UDFGetFreeBit(tmp_bm, j); - for(k=0;(kFSBM_Bitmap, i); - UDFSetFreeBitOwner(Vcb, i); - UDFSetZeroBit(Vcb->ZSBM_Bitmap, i); - } else { - // USED block - UDFClrZeroBit(Vcb->ZSBM_Bitmap, i); - } - i++; - } - } else { - bit_set = UDFGetZeroBit(tmp_bm, j); - for(k=0;(kZSBM_Bitmap, i); - } else { - // DATA block - UDFClrZeroBit(Vcb->ZSBM_Bitmap, i); - } - i++; + bit_set = UDFGetFreeBit(tmp_bm, j); + for(k=0;(kFSBM_Bitmap, i); + UDFSetFreeBitOwner(Vcb, i); } + i++; } j += l; } @@ -1679,8 +1712,7 @@ UDFVerifyXSpaceBitmap( IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN uint32 RefPartNum, - IN PSHORT_AD bm, - IN ULONG bm_type + IN PSHORT_AD bm ) { int8* tmp; @@ -1703,7 +1735,7 @@ UDFVerifyXSpaceBitmap( // i=UDFPartStart(Vcb, RefPartNum); flags = bm->extLength >> 30; if (!flags /*|| flags == EXTENT_NOT_RECORDED_ALLOCATED*/) { - tmp = (int8*)DbgAllocatePool(NonPagedPool, max(Length, Vcb->BlockSize)); + tmp = (int8*)DbgAllocatePool(NonPagedPool, max(Length, Vcb->SectorSize)); if (!tmp) return STATUS_INSUFFICIENT_RESOURCES; locAddr.partitionReferenceNum = (uint16)RefPartNum; locAddr.logicalBlockNum = bm->extPosition; @@ -1720,7 +1752,7 @@ UDFVerifyXSpaceBitmap( goto err_vfyxsbm_1; } // read the whole Bitmap - if (!NT_SUCCESS(status = UDFReadData(IrpContext, Vcb, FALSE, ((uint64)lba)<BlockSizeBits, Length, FALSE, tmp, &ReadBytes))) + if (!NT_SUCCESS(status = UDFReadData(IrpContext, Vcb, FALSE, ((uint64)lba)<SectorShift, Length, FALSE, tmp, &ReadBytes))) goto err_vfyxsbm_1; // lim = min(i + ((lim2 = ((PSPACE_BITMAP_DESC)tmp)->numOfBits) << Vcb->LB2B_Bits), Vcb->FSBM_BitCount); @@ -1849,18 +1881,22 @@ UDFVerifyFreeSpaceBitmap( // read info for partition header (if any) if (phd) { // read unallocated Bitmap - if (!NT_SUCCESS(status = UDFVerifyXSpaceBitmap(IrpContext, Vcb, RefPartNum, &(phd->unallocatedSpaceBitmap), UDF_FSPACE_BM))) - return status; - // read freed Bitmap - if (!NT_SUCCESS(status = UDFVerifyXSpaceBitmap(IrpContext, Vcb, RefPartNum, &(phd->freedSpaceBitmap), UDF_ZSPACE_BM))) + if (!NT_SUCCESS(status = UDFVerifyXSpaceBitmap(IrpContext, Vcb, RefPartNum, &(phd->unallocatedSpaceBitmap)))) return status; + + if (phd->unallocatedSpaceTable.extPosition || + phd->freedSpaceTable.extPosition || + phd->freedSpaceBitmap.extPosition ) { + + Vcb->VcbState |= VCB_STATE_VOLUME_READ_ONLY; + } } // read UnallocatedSpaceDesc & convert to Bitmap if (Lba) { UDFPrint((" Lba @%x\n", Lba)); - if (!(AllocDesc = (int8*)MyAllocatePool__(NonPagedPool, Vcb->LBlockSize + sizeof(EXTENT_AD) ))) + if (!(AllocDesc = (int8*)MyAllocatePool__(NonPagedPool, Vcb->SectorSize + sizeof(EXTENT_AD) ))) return STATUS_INSUFFICIENT_RESOURCES; - RtlZeroMemory(((int8*)AllocDesc) + Vcb->LBlockSize, sizeof(EXTENT_AD)); + RtlZeroMemory(((int8*)AllocDesc) + Vcb->SectorSize, sizeof(EXTENT_AD)); if (!NT_SUCCESS(status = UDFReadTagged(IrpContext, Vcb, AllocDesc, Lba, Lba, &Ident)) || !(Extent = (PEXTENT_MAP)MyAllocatePool__(NonPagedPool, l = (((PUNALLOC_SPACE_DESC)AllocDesc)->numAllocDescs+1) * sizeof(EXTENT_AD) ))) { MyFreePool__(AllocDesc); @@ -1943,18 +1979,8 @@ UDFBuildFreeSpaceBitmap( Vcb->FSBM_Bitmap = (int8*)DbgAllocatePool(NonPagedPool, (i = (Vcb->LastPossibleLBA+1+7)>>3) ); if (!(Vcb->FSBM_Bitmap)) return STATUS_INSUFFICIENT_RESOURCES; - Vcb->ZSBM_Bitmap = (int8*)DbgAllocatePool(NonPagedPool, (i = (Vcb->LastPossibleLBA+1+7)>>3) ); - if (!(Vcb->ZSBM_Bitmap)) { -#ifdef UDF_TRACK_ONDISK_ALLOCATION_OWNERS -free_fsbm: -#endif //UDF_TRACK_ONDISK_ALLOCATION_OWNERS - MyFreePool__(Vcb->FSBM_Bitmap); - Vcb->FSBM_Bitmap = NULL; - return STATUS_INSUFFICIENT_RESOURCES; - } - RtlZeroMemory(Vcb->FSBM_Bitmap, i); - RtlZeroMemory(Vcb->ZSBM_Bitmap, i); + #ifdef UDF_TRACK_ONDISK_ALLOCATION_OWNERS Vcb->FSBM_Bitmap_owners = (uint32*)DbgAllocatePool(NonPagedPool, (Vcb->LastPossibleLBA+1)*sizeof(uint32)); if (!(Vcb->FSBM_Bitmap_owners)) { @@ -1970,17 +1996,21 @@ UDFBuildFreeSpaceBitmap( // read info for partition header (if any) if (phd) { // read unallocated Bitmap - if (!NT_SUCCESS(status = UDFAddXSpaceBitmap(IrpContext, Vcb, RefPartNum, &phd->unallocatedSpaceBitmap, UDF_FSPACE_BM))) - return status; - // read freed Bitmap - if (!NT_SUCCESS(status = UDFAddXSpaceBitmap(IrpContext, Vcb, RefPartNum, &phd->freedSpaceBitmap, UDF_ZSPACE_BM))) + if (!NT_SUCCESS(status = UDFAddXSpaceBitmap(IrpContext, Vcb, RefPartNum, &phd->unallocatedSpaceBitmap))) return status; + + if (phd->unallocatedSpaceTable.extPosition || + phd->freedSpaceTable.extPosition || + phd->freedSpaceBitmap.extPosition ) { + + Vcb->VcbState |= VCB_STATE_VOLUME_READ_ONLY; + } } // read UnallocatedSpaceDesc & convert to Bitmap if (Lba) { - if (!(AllocDesc = (int8*)MyAllocatePool__(NonPagedPool, Vcb->LBlockSize + sizeof(EXTENT_AD) ))) + if (!(AllocDesc = (int8*)MyAllocatePool__(NonPagedPool, Vcb->SectorSize + sizeof(EXTENT_AD) ))) return STATUS_INSUFFICIENT_RESOURCES; - RtlZeroMemory(((int8*)AllocDesc) + Vcb->LBlockSize, sizeof(EXTENT_AD)); + RtlZeroMemory(((int8*)AllocDesc) + Vcb->SectorSize, sizeof(EXTENT_AD)); if (!NT_SUCCESS(status = UDFReadTagged(IrpContext, Vcb, AllocDesc, Lba, Lba, &Ident)) || !(Extent = (PEXTENT_MAP)MyAllocatePool__(NonPagedPool, l = (((PUNALLOC_SPACE_DESC)AllocDesc)->numAllocDescs+1) * sizeof(EXTENT_AD) ))) { MyFreePool__(AllocDesc); @@ -2314,7 +2344,7 @@ UDFReadVDS( pVDP = (struct VolDescPtr*)Buf; UDFPrint(("multipart VDS...\n")); return UDFReadVDS(IrpContext, Vcb, pVDP->nextVolDescSeqExt.extLocation, - pVDP->nextVolDescSeqExt.extLocation + (pVDP->nextVolDescSeqExt.extLocation >> Vcb->BlockSizeBits), + pVDP->nextVolDescSeqExt.extLocation + (pVDP->nextVolDescSeqExt.extLocation >> Vcb->SectorShift), vds, Buf); } break; @@ -2396,7 +2426,7 @@ UDFProcessSequence( ) { NTSTATUS RC = STATUS_SUCCESS; - int8* Buf = (int8*)MyAllocatePool__(NonPagedPool,Vcb->BlockSize); + int8* Buf = (int8*)MyAllocatePool__(NonPagedPool,Vcb->SectorSize); UDF_VDS_RECORD vds[VDS_POS_LENGTH]; // GenericDesc *gd; uint32 i,j; @@ -2436,7 +2466,7 @@ UDFProcessSequence( if (i == VDS_POS_PARTITION_DESC) { - Buf2 = (int8*)MyAllocatePool__(NonPagedPool,Vcb->BlockSize); + Buf2 = (int8*)MyAllocatePool__(NonPagedPool,Vcb->SectorSize); if (!Buf2) try_return(RC = STATUS_INSUFFICIENT_RESOURCES); RC = UDFLoadPartDesc(IrpContext, Vcb, Buf); if (!NT_SUCCESS(RC)) try_return(RC); @@ -2463,6 +2493,7 @@ UDFProcessSequence( } } else { if (i == VDS_POS_LOGICAL_VOL_DESC) { + RC = UDFLoadBogusLogicalVol(DeviceObject,Vcb, Buf, fileset); if (!NT_SUCCESS(RC)) try_return(RC); } @@ -2494,7 +2525,7 @@ UDFVerifySequence( ) { NTSTATUS RC = STATUS_SUCCESS; - int8* Buf = (int8*)MyAllocatePool__(NonPagedPool,Vcb->BlockSize); + int8* Buf = (int8*)MyAllocatePool__(NonPagedPool,Vcb->SectorSize); UDF_VDS_RECORD vds[VDS_POS_LENGTH]; // GenericDesc *gd; uint32 i,j; @@ -2522,7 +2553,7 @@ UDFVerifySequence( } else if (i == VDS_POS_PARTITION_DESC) { - Buf2 = (int8*)MyAllocatePool__(NonPagedPool,Vcb->BlockSize); + Buf2 = (int8*)MyAllocatePool__(NonPagedPool,Vcb->SectorSize); if (!Buf2) try_return(RC = STATUS_INSUFFICIENT_RESOURCES); RC = UDFVerifyPartDesc(IrpContext, Vcb, Buf); if (!NT_SUCCESS(RC)) try_return(RC); @@ -2640,7 +2671,7 @@ UDFLoadPartition( NTSTATUS RC2 = STATUS_UNRECOGNIZED_VOLUME; AnchorVolDescPtr *anchor; uint16 ident; - int8* Buf = (int8*)MyAllocatePool__(NonPagedPool,Vcb->BlockSize); + int8* Buf = (int8*)MyAllocatePool__(NonPagedPool,Vcb->SectorSize); uint32 main_s, main_e; uint32 reserve_s, reserve_e; UDF_VDS_RECORD mainVolDesc; @@ -2659,13 +2690,13 @@ UDFLoadPartition( // Locate the main sequence main_s = ( anchor->mainVolDescSeqExt.extLocation ); main_e = ( anchor->mainVolDescSeqExt.extLength ); - main_e = main_e >> Vcb->BlockSizeBits; + main_e = main_e >> Vcb->SectorShift; main_e += main_s; // Locate the reserve sequence reserve_s = (anchor->reserveVolDescSeqExt.extLocation); reserve_e = (anchor->reserveVolDescSeqExt.extLength); - reserve_e = reserve_e >> Vcb->BlockSizeBits; + reserve_e = reserve_e >> Vcb->SectorShift; reserve_e += reserve_s; // Check if it is known bad sequence @@ -2723,21 +2754,6 @@ UDFLoadPartition( break; } else { UDFPrint(("UDF: Reserve sequence verification failed.\n")); - switch(Vcb->PartitialDamagedVolumeAction) { - case UDF_PART_DAMAGED_RO: - UDFPrint(("UDF: Switch to r/o mode.\n")); - Vcb->VcbState |= VCB_STATE_VOLUME_READ_ONLY; - break; - case UDF_PART_DAMAGED_NO: - UDFPrint(("UDF: Switch to raw mount mode, return UNRECOGNIZED_VOLUME.\n")); - Vcb->VcbState |= UDF_VCB_FLAGS_RAW_DISK; - RC = STATUS_WRONG_VOLUME; - break; - case UDF_PART_DAMAGED_RW: - default: - UDFPrint(("UDF: Keep r/w mode for your own risk.\n")); - break; - } } break; } @@ -2831,7 +2847,7 @@ UDFLoadSparingTable( UDFPrint(("UDF: Sparable Part Map:\n")); Vcb->SparingTableLength = PartMap->sizeSparingTable; - BC = (PartMap->sizeSparingTable >> Vcb->BlockSizeBits) + 1; + BC = (PartMap->sizeSparingTable >> Vcb->SectorShift) + 1; UDFPrint((" partitionMapType = %x\n", PartMap->partitionMapType)); UDFPrint((" partitionMapLength = %x\n", PartMap->partitionMapLength)); UDFPrint((" volSeqNum = %x\n", PartMap->volSeqNum)); @@ -2839,7 +2855,7 @@ UDFLoadSparingTable( UDFPrint((" packetLength = %x\n", PartMap->packetLength)); UDFPrint((" numSparingTables = %x\n", PartMap->numSparingTables)); UDFPrint((" sizeSparingTable = %x\n", PartMap->sizeSparingTable)); - SparTable = (PSPARING_TABLE)MyAllocatePool__(NonPagedPool, BC*Vcb->BlockSize); + SparTable = (PSPARING_TABLE)MyAllocatePool__(NonPagedPool, BC*Vcb->SectorSize); if (!SparTable) return STATUS_INSUFFICIENT_RESOURCES; if (Vcb->SparingTable) { // if a part of Sparing Table is already loaded, @@ -2874,8 +2890,8 @@ UDFLoadSparingTable( BC2 = ((sizeof(SPARING_TABLE) + SparTable->reallocationTableLen*sizeof(SparingEntry) + - Vcb->BlockSize-1) - >> Vcb->BlockSizeBits); + Vcb->SectorSize-1) + >> Vcb->SectorShift); if (BC2 > BC) { UDFPrint((" sizeSparingTable @%x too long: %x > %x\n", SparTableLoc, BC2, BC @@ -2983,61 +2999,25 @@ UDFGetDiskInfoAndVerify( lb_addr fileset; PFILE_SET_DESC FileSetDesc = NULL; - int8* Buf = NULL; - SIZE_T ReadBytes; - UDFPrint(("UDFGetDiskInfoAndVerify\n")); _SEH2_TRY { - if (!UDFFindAnchor(IrpContext, Vcb)) { - if (Vcb->FsDeviceType == FILE_DEVICE_CD_ROM_FILE_SYSTEM) { - // check if this disc is mountable for CDFS - UDFPrint((" FILE_DEVICE_CD_ROM_FILE_SYSTEM\n")); -check_NSR: - NSRDesc = UDFFindVRS(IrpContext, Vcb); - if (!(NSRDesc & VRS_ISO9660_FOUND)) { - // no CDFS VRS found - UDFPrint(("UDFGetDiskInfoAndVerify: no CDFS VRS found\n")); - if (!Vcb->TrackMap[Vcb->LastTrackNum].LastLba && - !Vcb->TrackMap[Vcb->FirstTrackNum].LastLba) { - // such a stupid method of Audio-CD detection... - UDFPrint(("UDFGetDiskInfoAndVerify: set UDF_VCB_FLAGS_RAW_DISK\n")); - Vcb->VcbState |= UDF_VCB_FLAGS_RAW_DISK; - } - } - Vcb->NSRDesc = NSRDesc; + if (!UDFFindAnchorVolumeDescriptor(IrpContext, Vcb)) { - Buf = (int8*)MyAllocatePool__(NonPagedPool, 0x10000); - if (!Buf) try_return(RC = STATUS_INSUFFICIENT_RESOURCES); - RC = UDFReadData(IrpContext, Vcb, FALSE, 0, 0x10000, FALSE, Buf, &ReadBytes); - if (!NT_SUCCESS(RC)) - try_return(RC = STATUS_UNRECOGNIZED_VOLUME); - RC = STATUS_UNRECOGNIZED_VOLUME; - if (!UDFCheckZeroBuf(Buf,0x10000)) { - UDFPrint(("UDFGetDiskInfoAndVerify: possible FS detected, remove UDF_VCB_FLAGS_RAW_DISK\n")); - Vcb->VcbState &= ~UDF_VCB_FLAGS_RAW_DISK; - } - MyFreePool__(Buf); - Buf = NULL; - } try_return(RC = STATUS_UNRECOGNIZED_VOLUME); } - else - { - NSRDesc = VRS_NSR03_FOUND | VRS_NSR02_FOUND; - Vcb->NSRDesc = NSRDesc; - } + + NSRDesc = VRS_NSR03_FOUND | VRS_NSR02_FOUND; + Vcb->NSRDesc = NSRDesc; RC = UDFLoadPartition(IrpContext, DeviceObject, Vcb, &fileset); + if (!NT_SUCCESS(RC)) { - if (RC == STATUS_UNRECOGNIZED_VOLUME) { - UDFPrint(("UDFGetDiskInfoAndVerify: check NSR presence\n")); - goto check_NSR; - } + try_return(RC); } - FileSetDesc = (PFILE_SET_DESC)MyAllocatePool__(NonPagedPool,Vcb->BlockSize); + FileSetDesc = (PFILE_SET_DESC)MyAllocatePool__(NonPagedPool,Vcb->SectorSize); if (!FileSetDesc) try_return(RC = STATUS_INSUFFICIENT_RESOURCES); RC = UDFFindLastFileSet(IrpContext, Vcb, &fileset, FileSetDesc); @@ -3052,7 +3032,6 @@ UDFGetDiskInfoAndVerify( try_exit: NOTHING; } _SEH2_FINALLY { if (FileSetDesc) MyFreePool__(FileSetDesc); - if (Buf) MyFreePool__(Buf); } _SEH2_END; return(RC); diff --git a/drivers/filesystems/udfs/udf_info/phys_eject.cpp b/drivers/filesystems/udfs/udf_info/phys_eject.cpp index 2497316571137..f24e3012140a0 100644 --- a/drivers/filesystems/udfs/udf_info/phys_eject.cpp +++ b/drivers/filesystems/udfs/udf_info/phys_eject.cpp @@ -68,9 +68,6 @@ UDFDoDismountSequence( // ... and make it Read-Only... :-\~ Vcb->VcbState &= ~UDF_VCB_FLAGS_MEDIA_LOCKED; - UDFPrint((" set UnsafeIoctl\n")); - Vcb->VcbState |= UDF_VCB_FLAGS_UNSAFE_IOCTL; - return STATUS_SUCCESS; } // end UDFDoDismountSequence() diff --git a/drivers/filesystems/udfs/udf_info/remap.cpp b/drivers/filesystems/udfs/udf_info/remap.cpp index 4ff842dab68df..b1e2e09587377 100644 --- a/drivers/filesystems/udfs/udf_info/remap.cpp +++ b/drivers/filesystems/udfs/udf_info/remap.cpp @@ -73,9 +73,9 @@ UDFVInit( UDFPrint(("Verify is not intended for CD/DVD-R\n")); return STATUS_SUCCESS; } - if (!NT_SUCCESS(status = ExInitializeResourceLite(&(VerifyCtx->VerifyLock)))) { - try_return(status); - } + + ExInitializeResourceLite(&VerifyCtx->VerifyLock); + res_inited = TRUE; VerifyCtx->ItemCount = 0; VerifyCtx->StoredBitMap = (uint8*)DbgAllocatePoolWithTag(PagedPool, (i = (Vcb->LastPossibleLBA+1+7)>>3), 'mNWD' ); @@ -177,12 +177,12 @@ UDFVStoreBlock( UDFPrint(("v-add %x\n", LBA)); - vItem = (PUDF_VERIFY_ITEM)DbgAllocatePoolWithTag(PagedPool, sizeof(UDF_VERIFY_ITEM)+Vcb->BlockSize, 'bvWD'); + vItem = (PUDF_VERIFY_ITEM)DbgAllocatePoolWithTag(PagedPool, sizeof(UDF_VERIFY_ITEM)+Vcb->SectorSize, 'bvWD'); if (!vItem) return NULL; - RtlCopyMemory(vItem+1, Buffer, Vcb->BlockSize); + RtlCopyMemory(vItem+1, Buffer, Vcb->SectorSize); vItem->lba = LBA; - vItem->crc = crc32((PUCHAR)Buffer, Vcb->BlockSize); + vItem->crc = crc32((PUCHAR)Buffer, Vcb->SectorSize); vItem->Buffer = (PUCHAR)(vItem+1); vItem->queued = FALSE; InitializeListHead(&(vItem->vrfList)); @@ -200,8 +200,8 @@ UDFVUpdateBlock( ) { UDFPrint(("v-upd %x\n", vItem->lba)); - RtlCopyMemory(vItem+1, Buffer, Vcb->BlockSize); - vItem->crc = crc32((PUCHAR)Buffer, Vcb->BlockSize); + RtlCopyMemory(vItem+1, Buffer, Vcb->SectorSize); + vItem->crc = crc32((PUCHAR)Buffer, Vcb->SectorSize); return; } // end UDFVUpdateBlock() @@ -259,7 +259,7 @@ UDFVWrite( Link = Link->Blink; if (vItem->lba >= LBA && vItem->lba < LBA+BCount) { ASSERT(UDFGetBit(VerifyCtx->StoredBitMap, vItem->lba)); - UDFVUpdateBlock(Vcb, ((PUCHAR)Buffer)+(vItem->lba-LBA)*Vcb->BlockSize, vItem); + UDFVUpdateBlock(Vcb, ((PUCHAR)Buffer)+(vItem->lba-LBA)*Vcb->SectorSize, vItem); n++; if (n == BCount) { // all updated @@ -350,7 +350,7 @@ UDFVWrite( // remember all blocks for(i=0; iStoredBitMap, LBA+i)); - UDFVStoreBlock(Vcb, LBA+i, ((PUCHAR)Buffer)+i*Vcb->BlockSize, &(VerifyCtx->vrfList)); + UDFVStoreBlock(Vcb, LBA+i, ((PUCHAR)Buffer)+i*Vcb->SectorSize, &(VerifyCtx->vrfList)); } } @@ -417,10 +417,10 @@ UDFVRead( ASSERT(UDFGetBit(VerifyCtx->StoredBitMap, vItem->lba)); i++; if (!(Flags & PH_READ_VERIFY_CACHE)) { - crc = crc32((PUCHAR)Buffer+(vItem->lba - LBA)*Vcb->BlockSize, Vcb->BlockSize); + crc = crc32((PUCHAR)Buffer+(vItem->lba - LBA)*Vcb->SectorSize, Vcb->SectorSize); if (vItem->crc != crc) { UDFPrint(("UDFVRead: stored %x != %x\n", vItem->crc, crc)); - RtlCopyMemory((PUCHAR)Buffer+(vItem->lba - LBA)*Vcb->BlockSize, vItem->Buffer, Vcb->BlockSize); + RtlCopyMemory((PUCHAR)Buffer+(vItem->lba - LBA)*Vcb->SectorSize, vItem->Buffer, Vcb->SectorSize); status = STATUS_FT_WRITE_RECOVERY; if (!(bm = (uint32*)(Vcb->BSBM_Bitmap))) { @@ -436,19 +436,18 @@ UDFVRead( UDFSetBit(bm, vItem->lba); UDFPrint(("Set BB @ %#x\n", vItem->lba)); } -#ifdef _BROWSE_UDF_ + bm = (uint32*)(Vcb->FSBM_Bitmap); if (bm) { UDFSetUsedBit(bm, vItem->lba); UDFPrint(("Set BB @ %#x as used\n", vItem->lba)); } -#endif //_BROWSE_UDF_ } else { // ok } } else { UDFPrint(("UDFVRead: get cached @ %x\n", vItem->lba)); - RtlCopyMemory((PUCHAR)Buffer+(vItem->lba - LBA)*Vcb->BlockSize, vItem->Buffer, Vcb->BlockSize); + RtlCopyMemory((PUCHAR)Buffer+(vItem->lba - LBA)*Vcb->SectorSize, vItem->Buffer, Vcb->SectorSize); } if (i >= n) { // no more blocks expected @@ -567,7 +566,7 @@ UDFVWorkItem( UDFTIOVerify(&IrpContext, Vcb, VerifyReq->Buffer, // Target buffer - VerifyReq->vr[i].BCount << Vcb->BlockSizeBits, + VerifyReq->vr[i].BCount << Vcb->SectorShift, VerifyReq->vr[i].lba, &ReadBytes, PH_TMP_BUFFER | PH_VCB_IN_RETLEN /*| PH_LOCK_CACHE*/); @@ -712,7 +711,7 @@ UDFVVerify( if ((VerifyReq->nReq >= MAX_VREQ_RANGES) || (i == 1)) { - VerifyReq->Buffer = (PUCHAR)DbgAllocatePoolWithTag(NonPagedPool, max_len * Vcb->BlockSize, 'bNWD'); + VerifyReq->Buffer = (PUCHAR)DbgAllocatePoolWithTag(NonPagedPool, max_len * Vcb->SectorSize, 'bNWD'); if (VerifyReq->Buffer) { InterlockedIncrement((PLONG)&(VerifyCtx->QueuedCount)); @@ -782,7 +781,7 @@ UDFCheckArea( uint32 i, d; BOOLEAN ext_ok = TRUE; EXTENT_MAP Map[2]; - uint32 PS = Vcb->WriteBlockSize >> Vcb->BlockSizeBits; + uint32 PS = Vcb->WriteBlockSize >> Vcb->SectorShift; buff = (uint8*)DbgAllocatePoolWithTag(NonPagedPool, Vcb->WriteBlockSize, 'bNWD' ); if (buff) { @@ -796,14 +795,14 @@ UDFCheckArea( RC = UDFTRead(IrpContext, Vcb, buff, - d << Vcb->BlockSizeBits, + d << Vcb->SectorShift, LBA+i, &ReadBytes, PH_TMP_BUFFER); if (RC != STATUS_SUCCESS) { Map[0].extLocation = LBA+i; - Map[0].extLength = d << Vcb->BlockSizeBits; + Map[0].extLength = d << Vcb->SectorShift; UDFMarkSpaceAsXXXNoProtect(Vcb, 0, &(Map[0]), AS_DISCARDED | AS_BAD); // free ext_ok = FALSE; } @@ -1054,7 +1053,7 @@ UDFRelocateSectors( // create new entry if the extent in not contigous if ( ((NewLba = UDFRelocateSector(Vcb, Lba+i+1)) != (LastLba+1)) || (i==(BlockCount-1)) ) { - locExt.extLength = j << Vcb->BlockSizeBits; + locExt.extLength = j << Vcb->SectorShift; locExt.extLocation = LastLba-j+1; Extent2 = UDFExtentToMapping(&locExt); if (!Extent) { diff --git a/drivers/filesystems/udfs/udf_info/udf_info.cpp b/drivers/filesystems/udfs/udf_info/udf_info.cpp index a521d35574ae5..67f3e3e827b9c 100644 --- a/drivers/filesystems/udfs/udf_info/udf_info.cpp +++ b/drivers/filesystems/udfs/udf_info/udf_info.cpp @@ -951,7 +951,7 @@ UDFBuildFileEntry( ASSERT(!ExtAttrSz); // calculate the length required l = (Extended ? sizeof(EXTENDED_FILE_ENTRY) : sizeof(FILE_ENTRY)) + ExtAttrSz; - if (l > Vcb->LBlockSize) return STATUS_INVALID_PARAMETER; + if (l > Vcb->SectorSize) return STATUS_INVALID_PARAMETER; // allocate block for FE if (!NT_SUCCESS(status = UDFAllocateFESpace(IrpContext, Vcb, DirInfo, PartNum, &_FEExtInfo, l) )) return status; @@ -1493,9 +1493,9 @@ UDFChangeFileCounter( if (*counter == (ULONG)-1) return; if (Increase) { - UDFInterlockedIncrement((int32*)counter); + InterlockedIncrement((int32*)counter); } else { - UDFInterlockedDecrement((int32*)counter); + InterlockedDecrement((int32*)counter); } } // end UDFChangeFileCounter() @@ -1523,7 +1523,6 @@ UDFReadEntityID_Domain( ) { domainIdentSuffix* dis; - uint8 flags; dis = (domainIdentSuffix*)&(eID->identSuffix); @@ -1542,26 +1541,18 @@ UDFReadEntityID_Domain( if (Vcb->UdfRevision >= 0x200) { Vcb->NSRDesc = VRS_NSR03_FOUND; - Vcb->UseExtendedFE = FALSE; } else { Vcb->NSRDesc = VRS_NSR02_FOUND; - Vcb->UseExtendedFE = FALSE; } } + // Get Read-Only flags - flags = dis->flags; - UDFPrint(("Flags: %x\n", flags)); - if ((flags & ENTITYID_FLAGS_SOFT_RO) && - (Vcb->CompatFlags & UDF_VCB_IC_SOFT_RO)) { - Vcb->VcbState |= VCB_STATE_VOLUME_READ_ONLY; - UDFPrint((" Soft-RO\n")); - } - if ((flags & ENTITYID_FLAGS_HARD_RO) && - (Vcb->CompatFlags & UDF_VCB_IC_HW_RO)) { + + if (FlagOn(dis->flags, ENTITYID_FLAGS_HARD_RO | ENTITYID_FLAGS_SOFT_RO)) { + Vcb->VcbState |= VCB_STATE_VOLUME_READ_ONLY; - UDFPrint((" Hard-RO\n")); } } // end UDFReadEntityID_Domain() @@ -1627,7 +1618,7 @@ UDFWriteFile__( ExtPrint((" w2k-compat -> rebuild allocs\n")); Dloc->DataLoc.Modified = TRUE; } else - if ((ULONG)((elen+Vcb->LBlockSize-1) >> Vcb->LBlockSizeBits) != (ULONG)((t+Vcb->LBlockSize-1) >> Vcb->LBlockSizeBits)) { + if ((ULONG)((elen+Vcb->SectorSize-1) >> Vcb->SectorShift) != (ULONG)((t+Vcb->SectorSize-1) >> Vcb->SectorShift)) { ExtPrint((" LBS boundary crossed -> rebuild allocs\n")); Dloc->DataLoc.Modified = TRUE; } @@ -1723,8 +1714,8 @@ UDFWriteFile__( if (Vcb->CompatFlags & UDF_VCB_IC_W2K_COMPAT_ALLOC_DESCS) { ASSERT(UDFGetFileSize(FileInfo) <= UDFGetExtentLength(FileInfo->Dloc->DataLoc.Mapping)); } else { - ASSERT(((UDFGetFileSize(FileInfo)+Vcb->LBlockSize-1) & (Vcb->LBlockSize-1)) == - ((UDFGetExtentLength(FileInfo->Dloc->DataLoc.Mapping)+Vcb->LBlockSize-1) & (Vcb->LBlockSize-1))); + ASSERT(((UDFGetFileSize(FileInfo)+Vcb->SectorSize-1) & (Vcb->SectorSize-1)) == + ((UDFGetExtentLength(FileInfo->Dloc->DataLoc.Mapping)+Vcb->SectorSize-1) & (Vcb->SectorSize-1))); } #endif // UDF_DBG return STATUS_SUCCESS; @@ -1777,7 +1768,7 @@ UDFUnlinkFile__( // we can't delete modified file // it should be closed & reopened (or flushed) before deletion DirNdx = UDFDirIndex(hDirNdx,Index); -#if defined UDF_DBG || defined PRINT_ALWAYS +#if defined UDF_DBG if (DirNdx && DirNdx->FName.Buffer) { AdPrint(("Unlink: %ws\n",DirNdx->FName.Buffer)); } @@ -2081,7 +2072,7 @@ UDFOpenFile__( if (FileInfo->Dloc->FileEntry) goto init_tree_entry; // read (Ex)FileEntry - FileInfo->Dloc->FileEntry = (tag*)MyAllocatePoolTag__(NonPagedPool, Vcb->LBlockSize, MEM_FE_TAG); + FileInfo->Dloc->FileEntry = (tag*)MyAllocatePoolTag__(NonPagedPool, Vcb->SectorSize, MEM_FE_TAG); if (!(FileInfo->Dloc->FileEntry)) return STATUS_INSUFFICIENT_RESOURCES; if (!NT_SUCCESS(status = UDFReadFileEntry(IrpContext, Vcb, &FileInfo->FileIdent->icb, (PFILE_ENTRY)(FileInfo->Dloc->FileEntry), &Ident))) return status; @@ -2118,7 +2109,7 @@ UDFOpenFile__( DirNdx->FI_Flags &= ~UDF_FI_FLAG_LINKED; } // resize FE cache (0x800 instead of 0x40 is not a good idea) - if (!MyReallocPool__((int8*)((FileInfo->Dloc->FileEntry)), Vcb->LBlockSize, + if (!MyReallocPool__((int8*)((FileInfo->Dloc->FileEntry)), Vcb->SectorSize, (int8**)&((FileInfo->Dloc->FileEntry)), FileInfo->Dloc->FileEntryLen)) return STATUS_INSUFFICIENT_RESOURCES; // check if this file has a SDir @@ -2169,7 +2160,7 @@ UDFOpenRootFile__( uint32 RootLBA; NTSTATUS status; // uint32 PartNum = RootLoc->partitionReferenceNum; - uint32 LBS = Vcb->LBlockSize; + uint32 LBS = Vcb->SectorSize; uint16 Ident; LONG_AD FELoc; EXTENT_AD FEExt; @@ -2575,7 +2566,7 @@ UDFCreateFile__( UDF_DIR_SCAN_CONTEXT ScanContext; PDIR_INDEX_HDR hDirNdx = DirInfo->Dloc->DirIndex; PDIR_INDEX_ITEM DirNdx; - uint32 LBS = Vcb->LBlockSize; + uint32 LBS = Vcb->SectorSize; PUDF_FILE_INFO FileInfo; *_FileInfo = NULL; BOOLEAN undel = FALSE; @@ -2826,7 +2817,7 @@ UDFCreateFile__( FileInfo->Dloc->FELoc.Mapping[0].extLength &= UDF_EXTENT_LENGTH_MASK; // zero sector for FileEntry if (!Vcb->CDR_Mode) { - status = UDFWriteData(IrpContext, Vcb, TRUE, ((int64)(FileInfo->Dloc->FELoc.Mapping[0].extLocation)) << Vcb->BlockSizeBits, LBS, FALSE, Vcb->ZBuffer, &ReadBytes); + status = UDFWriteData(IrpContext, Vcb, TRUE, ((int64)(FileInfo->Dloc->FELoc.Mapping[0].extLocation)) << Vcb->SectorShift, LBS, FALSE, Vcb->ZBuffer, &ReadBytes); if (!NT_SUCCESS(status)) { UDFFlushFI(IrpContext, Vcb, FileInfo, PartNum); try_return (status); @@ -2955,7 +2946,7 @@ UDFPadLastSector( // Length should not be zero int64 Offset = ExtInfo->Length + ExtInfo->Offset; // data is sector-size-aligned, we needn't any padding - if (Offset && !((uint32)Offset & (Vcb->LBlockSize-1) )) return STATUS_SUCCESS; + if (Offset && !((uint32)Offset & (Vcb->SectorSize-1) )) return STATUS_SUCCESS; // get Lba of the last sector Lba = UDFExtentOffsetToLba(Vcb, Extent, Offset, §_offs, &to_write, &flags, NULL); // EOF check. If we have valid ExtInfo this will not happen, but who knows.. @@ -2963,7 +2954,7 @@ UDFPadLastSector( (flags == EXTENT_NOT_RECORDED_NOT_ALLOCATED)) return STATUS_END_OF_FILE; // write tail - status = UDFWriteData(IrpContext, Vcb, TRUE, (((int64)Lba) << Vcb->BlockSizeBits) + sect_offs, to_write, FALSE, Vcb->ZBuffer, &WrittenBytes); + status = UDFWriteData(IrpContext, Vcb, TRUE, (((int64)Lba) << Vcb->SectorShift) + sect_offs, to_write, FALSE, Vcb->ZBuffer, &WrittenBytes); return status; } // UDFPadLastSector() @@ -2984,10 +2975,10 @@ UDFCloseFile__( if (FileInfo->Index<2 && (FileInfo->ParentFile) && !UDFIsAStreamDir(FileInfo)) { UDFPrint(("Closing Current or Parent Directory... :-\\\n")); if (FileInfo->RefCount) { - UDFInterlockedDecrement((PLONG)&(FileInfo->RefCount)); + InterlockedDecrement((PLONG)&FileInfo->RefCount); ASSERT(FileInfo->Dloc); if (FileInfo->Dloc) - UDFInterlockedDecrement((PLONG)&(FileInfo->Dloc->LinkRefCount)); + InterlockedDecrement((PLONG)&FileInfo->Dloc->LinkRefCount); #ifdef UDF_DBG } else { BrutePoint(); @@ -2995,7 +2986,7 @@ UDFCloseFile__( #endif // UDF_DBG } if (FileInfo->ParentFile->OpenCount) { - UDFInterlockedDecrement((PLONG)&(FileInfo->ParentFile->OpenCount)); + InterlockedDecrement((PLONG)&FileInfo->ParentFile->OpenCount); #ifdef UDF_DBG } else { BrutePoint(); @@ -3008,10 +2999,10 @@ UDFCloseFile__( NTSTATUS status; uint32 PartNum; if (FileInfo->RefCount) { - UDFInterlockedDecrement((PLONG)&(FileInfo->RefCount)); + InterlockedDecrement((PLONG)&FileInfo->RefCount); ASSERT(FileInfo->Dloc); if (FileInfo->Dloc) - UDFInterlockedDecrement((PLONG)&(FileInfo->Dloc->LinkRefCount)); + InterlockedDecrement((PLONG)&FileInfo->Dloc->LinkRefCount); #ifdef UDF_DBG } else { BrutePoint(); @@ -3023,7 +3014,7 @@ UDFCloseFile__( ValidateFileInfo(DirInfo); if (DirInfo->OpenCount) { - UDFInterlockedDecrement((PLONG)&(DirInfo->OpenCount)); + InterlockedDecrement((PLONG)&DirInfo->OpenCount); #ifdef UDF_DBG } else { BrutePoint(); @@ -3295,8 +3286,8 @@ UDFRenameMoveFile__( DirNdx1->FileInfo = NULL; ASSERT(FileInfo->Dloc->FELoc.Mapping[0].extLocation); UDFFlushFI(IrpContext, Vcb, FileInfo, UDFGetRefPartNumByPhysLba(Vcb, FileInfo->Dloc->FELoc.Mapping[0].extLocation)); - UDFInterlockedExchangeAdd((PLONG)&(DirInfo1->OpenCount), - -((LONG)(FileInfo->RefCount))); + InterlockedExchangeAdd((PLONG)&(DirInfo1->OpenCount), + -((LONG)(FileInfo->RefCount))); // PHASE 2 // copy all necessary info from FileInfo to FileInfo2 @@ -3313,8 +3304,8 @@ UDFRenameMoveFile__( DirNdx2->FileCharacteristics = DirNdx1->FileCharacteristics & ~FILE_DELETED; DirNdx2->FileEntryLoc = DirNdx1->FileEntryLoc; DirNdx2->FI_Flags = (DirNdx1->FI_Flags & ~UDF_FI_FLAG_SYS_ATTR) | UDF_FI_FLAG_FI_MODIFIED; - UDFInterlockedExchangeAdd((PLONG)&(DirInfo2->OpenCount), - FileInfo->RefCount - FileInfo2->RefCount); + InterlockedExchangeAdd((PLONG)&(DirInfo2->OpenCount), + FileInfo->RefCount - FileInfo2->RefCount); UDFAttributesToUDF(DirNdx2, FileInfo2->Dloc->FileEntry, NTAttr); @@ -3406,7 +3397,7 @@ UDFRecordDirectory__( lba = DirInfo->Dloc->FELoc.Mapping[0].extLocation; ASSERT(lba); PartNum = UDFGetRefPartNumByPhysLba(Vcb, lba); - FEicb.extLength = Vcb->LBlockSize; + FEicb.extLength = Vcb->SectorSize; FEicb.extLocation.logicalBlockNum = UDFPhysLbaToPart(Vcb, PartNum, lba); FEicb.extLocation.partitionReferenceNum = (uint16)PartNum; RtlZeroMemory(&(FEicb.impUse), sizeof(FEicb.impUse)); @@ -3431,8 +3422,8 @@ UDFRecordDirectory__( if (Vcb->CompatFlags & UDF_VCB_IC_W2K_COMPAT_ALLOC_DESCS) { ASSERT(UDFGetFileSize(DirInfo) <= UDFGetExtentLength(DirInfo->Dloc->DataLoc.Mapping)); } else { - ASSERT(((UDFGetFileSize(DirInfo)+Vcb->LBlockSize-1) & (Vcb->LBlockSize-1)) == - ((UDFGetExtentLength(DirInfo->Dloc->DataLoc.Mapping)+Vcb->LBlockSize-1) & (Vcb->LBlockSize-1))); + ASSERT(((UDFGetFileSize(DirInfo)+Vcb->SectorSize-1) & (Vcb->SectorSize-1)) == + ((UDFGetExtentLength(DirInfo->Dloc->DataLoc.Mapping)+Vcb->SectorSize-1) & (Vcb->SectorSize-1))); } #endif // UDF_DBG @@ -3464,7 +3455,7 @@ UDFResizeFile__( ValidateFileInfo(FileInfo); // ASSERT(FileInfo->RefCount >= 1); - if ((NewLength >> Vcb->LBlockSizeBits) > Vcb->TotalAllocUnits) { + if ((NewLength >> Vcb->SectorShift) > Vcb->TotalAllocUnits) { UDFPrint(("STATUS_DISK_FULL\n")); return STATUS_DISK_FULL; } @@ -3477,7 +3468,7 @@ UDFResizeFile__( return UDFWriteFile__(IrpContext, Vcb, FileInfo, NewLength, 0, FALSE, NULL, &WrittenBytes); } // truncate file - if (NewLength <= (Vcb->LBlockSize - FileInfo->Dloc->FileEntryLen)) { + if (NewLength <= (Vcb->SectorSize - FileInfo->Dloc->FileEntryLen)) { // check if we are already in IN_ICB mode if ((((PFILE_ENTRY)(FileInfo->Dloc->FileEntry))->icbTag.flags & ICB_FLAG_ALLOC_MASK) != ICB_FLAG_AD_IN_ICB) { // read data from old location @@ -3507,19 +3498,19 @@ UDFResizeFile__( UDFMarkSpaceAsXXX(Vcb, FileInfo->Dloc, FileInfo->Dloc->DataLoc.Mapping, AS_DISCARDED); // free } else { if ((FileInfo->Dloc->DataLoc.Mapping[0].extLength & UDF_EXTENT_LENGTH_MASK) - > Vcb->LBlockSize) { + > Vcb->SectorSize) { BrutePoint(); - FileInfo->Dloc->DataLoc.Mapping[0].extLength -= Vcb->LBlockSize; - FileInfo->Dloc->DataLoc.Mapping[0].extLocation += (1 << Vcb->LB2B_Bits); + FileInfo->Dloc->DataLoc.Mapping[0].extLength -= Vcb->SectorSize; + FileInfo->Dloc->DataLoc.Mapping[0].extLocation += 1; goto mark_data_map_0; } UDFMarkSpaceAsXXX(Vcb, FileInfo->Dloc, &(FileInfo->Dloc->DataLoc.Mapping[1]), AS_DISCARDED); // free } if (FileInfo->Dloc->AllocLoc.Mapping) { if ((FileInfo->Dloc->AllocLoc.Mapping[0].extLength & UDF_EXTENT_LENGTH_MASK) - > Vcb->LBlockSize) { - FileInfo->Dloc->AllocLoc.Mapping[0].extLength -= Vcb->LBlockSize; - FileInfo->Dloc->AllocLoc.Mapping[0].extLocation += (1 << Vcb->LB2B_Bits); + > Vcb->SectorSize) { + FileInfo->Dloc->AllocLoc.Mapping[0].extLength -= Vcb->SectorSize; + FileInfo->Dloc->AllocLoc.Mapping[0].extLocation += 1; UDFMarkSpaceAsXXX(Vcb, FileInfo->Dloc, FileInfo->Dloc->AllocLoc.Mapping, AS_DISCARDED); // free } else { UDFMarkSpaceAsXXX(Vcb, FileInfo->Dloc, &(FileInfo->Dloc->AllocLoc.Mapping[1]), AS_DISCARDED); // free @@ -3569,8 +3560,8 @@ UDFResizeFile__( if (Vcb->CompatFlags & UDF_VCB_IC_W2K_COMPAT_ALLOC_DESCS) { ASSERT(UDFGetFileSize(FileInfo) <= UDFGetExtentLength(FileInfo->Dloc->DataLoc.Mapping)); } else { - ASSERT(((UDFGetFileSize(FileInfo)+Vcb->LBlockSize-1) & (Vcb->LBlockSize-1)) == - ((UDFGetExtentLength(FileInfo->Dloc->DataLoc.Mapping)+Vcb->LBlockSize-1) & (Vcb->LBlockSize-1))); + ASSERT(((UDFGetFileSize(FileInfo)+Vcb->SectorSize-1) & (Vcb->SectorSize-1)) == + ((UDFGetExtentLength(FileInfo->Dloc->DataLoc.Mapping)+Vcb->SectorSize-1) & (Vcb->SectorSize-1))); } #endif // UDF_DBG @@ -3610,10 +3601,7 @@ UDFLoadVAT( Vcb->CDR_Mode = FALSE; PartNum = Vcb->Partitions[PartNdx].PartitionNum; root = Vcb->Partitions[PartNdx].PartitionRoot; - if (Vcb->LBlockSize != Vcb->BlockSize) { - // don't know how to operate... :((( - return STATUS_UNRECOGNIZED_VOLUME; - } + if ((Vcb->LastTrackNum > 1) && (Vcb->LastLBA == Vcb->TrackMap[Vcb->LastTrackNum-1].LastLba)) { UDFPrint(("Hardware Read-only volume\n")); @@ -3898,8 +3886,8 @@ UDFFlushFE( if (Vcb->CompatFlags & UDF_VCB_IC_W2K_COMPAT_ALLOC_DESCS) { ASSERT(UDFGetFileSize(FileInfo) <= UDFGetExtentLength(FileInfo->Dloc->DataLoc.Mapping)); } else { - ASSERT(((UDFGetFileSize(FileInfo)+Vcb->LBlockSize-1) & (Vcb->LBlockSize-1)) == - ((UDFGetExtentLength(FileInfo->Dloc->DataLoc.Mapping)+Vcb->LBlockSize-1) & (Vcb->LBlockSize-1))); + ASSERT(((UDFGetFileSize(FileInfo)+Vcb->SectorSize-1) & (Vcb->SectorSize-1)) == + ((UDFGetExtentLength(FileInfo->Dloc->DataLoc.Mapping)+Vcb->SectorSize-1) & (Vcb->SectorSize-1))); } AllocMode = ((PFILE_ENTRY)(FileInfo->Dloc->FileEntry))->icbTag.flags & ICB_FLAG_ALLOC_MASK; #endif // UDF_DBG @@ -3933,8 +3921,8 @@ UDFFlushFE( if (Vcb->CompatFlags & UDF_VCB_IC_W2K_COMPAT_ALLOC_DESCS) { ASSERT(UDFGetFileSize(FileInfo) <= UDFGetExtentLength(FileInfo->Dloc->DataLoc.Mapping)); } else { - ASSERT(((UDFGetFileSize(FileInfo)+Vcb->LBlockSize-1) & (Vcb->LBlockSize-1)) == - ((UDFGetExtentLength(FileInfo->Dloc->DataLoc.Mapping)+Vcb->LBlockSize-1) & (Vcb->LBlockSize-1))); + ASSERT(((UDFGetFileSize(FileInfo)+Vcb->SectorSize-1) & (Vcb->SectorSize-1)) == + ((UDFGetExtentLength(FileInfo->Dloc->DataLoc.Mapping)+Vcb->SectorSize-1) & (Vcb->SectorSize-1))); } } #endif // UDF_DBG @@ -4428,7 +4416,7 @@ UDFReadTagged( } // Verify the descriptor CRC - if (((PTag->descCRCLength) + sizeof(tag) > Vcb->BlockSize) || + if (((PTag->descCRCLength) + sizeof(tag) > Vcb->SectorSize) || ((PTag->descCRC) == UDFCrc((uint8 *)Buf + sizeof(tag), PTag->descCRCLength, 0)) || !(PTag->descCRC)) { /* UDFPrint(("Tag ID: %x, ver %x\t", PTag->tagIdent, PTag->descVersion )); @@ -4645,7 +4633,7 @@ UDFCreateRootFile__( if (!NT_SUCCESS(status = UDFBuildFileEntry(IrpContext, Vcb, NULL, FileInfo, PartNum, ICB_FLAG_AD_IN_ICB, ExtAttrSz, Extended) )) return status; - FEicb.extLength = Vcb->LBlockSize; + FEicb.extLength = Vcb->SectorSize; FEicb.extLocation.logicalBlockNum = UDFPhysLbaToPart(Vcb, PartNum, FileInfo->Dloc->FELoc.Mapping[0].extLocation); FEicb.extLocation.partitionReferenceNum = (uint16)PartNum; RtlZeroMemory(&(FEicb.impUse), sizeof(FEicb.impUse)); @@ -4662,7 +4650,7 @@ UDFCreateRootFile__( // zero sector for FileEntry FileInfo->Dloc->DataLoc.Mapping[0].extLength &= UDF_EXTENT_LENGTH_MASK; FileInfo->Dloc->FELoc.Mapping[0].extLength &= UDF_EXTENT_LENGTH_MASK; - status = UDFWriteData(IrpContext, Vcb, TRUE, ((int64)(FileInfo->Dloc->FELoc.Mapping[0].extLocation)) << Vcb->BlockSizeBits, Vcb->LBlockSize, FALSE, Vcb->ZBuffer, &ReadBytes); + status = UDFWriteData(IrpContext, Vcb, TRUE, ((int64)(FileInfo->Dloc->FELoc.Mapping[0].extLocation)) << Vcb->SectorShift, Vcb->SectorSize, FALSE, Vcb->ZBuffer, &ReadBytes); if (!NT_SUCCESS(status)) return status; @@ -4691,7 +4679,7 @@ UDFCreateStreamDir__( *_SDirInfo = NULL; ValidateFileInfo(FileInfo); // check currently recorded UDF revision - if (!UDFStreamsSupported(Vcb)) + if (!UDFIsStreamsSupported(Vcb)) return STATUS_INVALID_PARAMETER; // check if we are allowed to associate Stream Dir with this file if ((FileInfo->ParentFile && UDFIsAStreamDir(FileInfo->ParentFile)) || @@ -4723,7 +4711,7 @@ UDFCreateStreamDir__( status = UDFRecordDirectory__(IrpContext, Vcb, SDirInfo); UDFDecDirCounter(Vcb); - UDFInterlockedIncrement((PLONG)&(FileInfo->OpenCount)); + InterlockedIncrement((PLONG)&FileInfo->OpenCount); if (!NT_SUCCESS(status)) { UDFUnlinkFile__(IrpContext, Vcb, SDirInfo, TRUE); UDFCloseFile__(IrpContext, Vcb, SDirInfo); @@ -4736,7 +4724,7 @@ UDFCreateStreamDir__( } *_SDirInfo = SDirInfo; // do some init - ((PEXTENDED_FILE_ENTRY)(FileInfo->Dloc->FileEntry))->streamDirectoryICB.extLength = Vcb->LBlockSize; + ((PEXTENDED_FILE_ENTRY)(FileInfo->Dloc->FileEntry))->streamDirectoryICB.extLength = Vcb->SectorSize; ((PEXTENDED_FILE_ENTRY)(FileInfo->Dloc->FileEntry))->streamDirectoryICB.extLocation.partitionReferenceNum = (uint16)PartNum; ((PEXTENDED_FILE_ENTRY)(FileInfo->Dloc->FileEntry))->streamDirectoryICB.extLocation.logicalBlockNum = UDFPhysLbaToPart(Vcb, PartNum, SDirInfo->Dloc->FELoc.Mapping[0].extLocation); @@ -4824,7 +4812,7 @@ UDFOpenStreamDir__( FileInfo->Dloc->SDirInfo = SDirInfo; SDirInfo->ParentFile = FileInfo; - UDFInterlockedIncrement((PLONG)&(FileInfo->OpenCount)); + InterlockedIncrement((PLONG)&FileInfo->OpenCount); return STATUS_SUCCESS; } // end UDFOpenStreamDir__() @@ -4858,7 +4846,7 @@ UDFRecordVAT( uint8 AllocMode; uint32 VatLen; uint32 PacketOffset; - uint32 BSh = Vcb->BlockSizeBits; + uint32 BSh = Vcb->SectorShift; uint32 MaxPacket = Vcb->WriteBlockSize >> BSh; uint32 OldLen; EntityID* eID; @@ -4978,7 +4966,7 @@ UDFRecordVAT( // the last packet will be recorded if (!PacketOffset) { // add padding - UDFWriteData(IrpContext, Vcb, TRUE, ((uint64)Vcb->NWA) << Vcb->BlockSizeBits, 1, FALSE, Old, &ReadBytes); + UDFWriteData(IrpContext, Vcb, TRUE, ((uint64)Vcb->NWA) << Vcb->SectorShift, 1, FALSE, Old, &ReadBytes); PacketOffset++; } else { Vcb->Vat = (uint32*)(New+Offset); @@ -5011,7 +4999,7 @@ UDFRecordVAT( Mapping = VatFileInfo->Dloc->DataLoc.Mapping; off=0; - BS = Vcb->BlockSize; + BS = Vcb->SectorSize; NWA = Vcb->NWA; VatLen += hdrLen; // record modified parts of VAT & update mapping @@ -5085,9 +5073,9 @@ UDFRecordVAT( Mapping[i].extLength = 0; if ( !PacketOffset && - (VatFileInfo->Dloc->AllocLoc.Length <= (Vcb->BlockSize - (uint32)(VatFileInfo->Dloc->AllocLoc.Offset)) ) ) { + (VatFileInfo->Dloc->AllocLoc.Length <= (Vcb->SectorSize - (uint32)(VatFileInfo->Dloc->AllocLoc.Offset)) ) ) { // add padding - UDFWriteData(IrpContext, Vcb, TRUE, ((uint64)NWA) << Vcb->BlockSizeBits, 1, FALSE, Old, &ReadBytes); + UDFWriteData(IrpContext, Vcb, TRUE, ((uint64)NWA) << Vcb->SectorShift, 1, FALSE, Old, &ReadBytes); PacketOffset++; } // now we'll place FE & built-in data to the last sector of diff --git a/drivers/filesystems/udfs/udf_info/udf_info.h b/drivers/filesystems/udfs/udf_info/udf_info.h index a8b61b3e330cf..8c2ae7abeaa6c 100644 --- a/drivers/filesystems/udfs/udf_info/udf_info.h +++ b/drivers/filesystems/udfs/udf_info/udf_info.h @@ -501,17 +501,12 @@ UDFBuildFileEntry( // find reference partition number containing given physical sector uint32 __fastcall UDFGetRefPartNumByPhysLba(IN PVCB Vcb, IN uint32 Lba); -// add given bitmap to existing one -#define UDF_FSPACE_BM 0x00 -#define UDF_ZSPACE_BM 0x01 - NTSTATUS UDFAddXSpaceBitmap( IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN uint32 PartNum, - IN PSHORT_AD bm, - IN ULONG bm_type + IN PSHORT_AD bm ); // subtract given Bitmap to existing one @@ -1000,7 +995,7 @@ PDIR_INDEX_HDR UDFGetDirIndexByFileInfo(IN PUDF_FILE_INFO FileInfo); /*int64 UDFGetFileAllocationSize(IN PVCB Vcb, IN PUDF_FILE_INFO FileInfo);*/ #define UDFGetFileAllocationSize(Vcb, FileInfo) \ - (((FileInfo)->Dloc->DataLoc.Mapping) ? UDFGetExtentLength((FileInfo)->Dloc->DataLoc.Mapping) : Vcb->LBlockSize) + (((FileInfo)->Dloc->DataLoc.Mapping) ? UDFGetExtentLength((FileInfo)->Dloc->DataLoc.Mapping) : Vcb->SectorSize) // check if the directory is empty BOOLEAN UDFIsDirEmpty(IN PDIR_INDEX_HDR hCurDirNdx); @@ -1105,7 +1100,7 @@ __fastcall UDFPartLbaToPhys(IN PVCB Vcb, // look for Anchor(s) at all possible locations lba_t -UDFFindAnchor( +UDFFindAnchorVolumeDescriptor( IN PIRP_CONTEXT IrpContext, IN PVCB Vcb ); @@ -1343,36 +1338,30 @@ __fastcall UDFPartLen(PVCB Vcb, NTSTATUS UDFPretendFileDeleted__(IN PVCB Vcb, IN PUDF_FILE_INFO FileInfo); -#define UDFStreamsSupported(Vcb) \ - (Vcb->maxUDFWriteRev >= 0x0200) - -#define UDFNtAclSupported(Vcb) \ - (Vcb->maxUDFWriteRev >= 0x0200) - #define UDFReferenceFile__(fi) \ { \ - UDFInterlockedIncrement((PLONG)&((fi)->RefCount)); \ - UDFInterlockedIncrement((PLONG)&((fi)->Dloc->LinkRefCount)); \ + InterlockedIncrement((PLONG)&((fi)->RefCount)); \ + InterlockedIncrement((PLONG)&((fi)->Dloc->LinkRefCount)); \ if ((fi)->ParentFile) { \ - UDFInterlockedIncrement((PLONG)&((fi)->ParentFile->OpenCount)); \ + InterlockedIncrement((PLONG)&((fi)->ParentFile->OpenCount)); \ } \ } #define UDFReferenceFileEx__(fi,i) \ { \ - UDFInterlockedExchangeAdd((PLONG)&((fi)->RefCount),i); \ - UDFInterlockedExchangeAdd((PLONG)&((fi)->Dloc->LinkRefCount),i); \ + InterlockedExchangeAdd((PLONG)&((fi)->RefCount),i); \ + InterlockedExchangeAdd((PLONG)&((fi)->Dloc->LinkRefCount),i); \ if ((fi)->ParentFile) { \ - UDFInterlockedExchangeAdd((PLONG)&((fi)->ParentFile->OpenCount),i); \ + InterlockedExchangeAdd((PLONG)&((fi)->ParentFile->OpenCount),i); \ } \ } #define UDFDereferenceFile__(fi) \ { \ - UDFInterlockedDecrement((PLONG)&((fi)->RefCount)); \ - UDFInterlockedDecrement((PLONG)&((fi)->Dloc->LinkRefCount)); \ + InterlockedDecrement((PLONG)&((fi)->RefCount)); \ + InterlockedDecrement((PLONG)&((fi)->Dloc->LinkRefCount)); \ if ((fi)->ParentFile) { \ - UDFInterlockedDecrement((PLONG)&((fi)->ParentFile->OpenCount)); \ + InterlockedDecrement((PLONG)&((fi)->ParentFile->OpenCount)); \ } \ } diff --git a/drivers/filesystems/udfs/udf_info/udf_rel.h b/drivers/filesystems/udfs/udf_info/udf_rel.h index 9698a2a1c5818..c48249d08d54d 100644 --- a/drivers/filesystems/udfs/udf_info/udf_rel.h +++ b/drivers/filesystems/udfs/udf_info/udf_rel.h @@ -40,12 +40,6 @@ typedef struct _UDFTrackMap { uint8 NWA_V; uint8 Flags; -#define TrackMap_AllowCopyBit_variated 0x01 -#define TrackMap_CopyBit_variated 0x02 -#define TrackMap_Try_variation 0x04 -#define TrackMap_Use_variation 0x08 -#define TrackMap_FixFPAddressing 0x10 -#define TrackMap_FixMRWAddressing 0x20 // are used only if FixFPAddressing is enabled uint32 TrackFPOffset; diff --git a/drivers/filesystems/udfs/udfdata.cpp b/drivers/filesystems/udfs/udfdata.cpp new file mode 100644 index 0000000000000..d1674b7727e54 --- /dev/null +++ b/drivers/filesystems/udfs/udfdata.cpp @@ -0,0 +1,280 @@ +//////////////////////////////////////////////////////////////////// +// Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine +// All rights reserved +// This file was released under the GPLv2 on June 2015. +//////////////////////////////////////////////////////////////////// +/************************************************************************* +* +* File: Close.cpp +* +* Module: UDF File System Driver (Kernel mode execution only) +* +* Description: +* Contains code to handle the "Close" dispatch entry point. +* +*************************************************************************/ + +#include "udffs.h" + +_IRQL_requires_max_(APC_LEVEL) +__drv_dispatchType(DRIVER_DISPATCH) +__drv_dispatchType(IRP_MJ_CREATE) +__drv_dispatchType(IRP_MJ_CLOSE) +__drv_dispatchType(IRP_MJ_READ) +__drv_dispatchType(IRP_MJ_WRITE) +__drv_dispatchType(IRP_MJ_QUERY_INFORMATION) +__drv_dispatchType(IRP_MJ_SET_INFORMATION) +__drv_dispatchType(IRP_MJ_QUERY_VOLUME_INFORMATION) +__drv_dispatchType(IRP_MJ_DIRECTORY_CONTROL) +__drv_dispatchType(IRP_MJ_FILE_SYSTEM_CONTROL) +__drv_dispatchType(IRP_MJ_DEVICE_CONTROL) +__drv_dispatchType(IRP_MJ_LOCK_CONTROL) +__drv_dispatchType(IRP_MJ_CLEANUP) +__drv_dispatchType(IRP_MJ_PNP) +__drv_dispatchType(IRP_MJ_SHUTDOWN) +NTSTATUS +NTAPI +UDFFsdDispatch( + _In_ PDEVICE_OBJECT DeviceObject, + _Inout_ PIRP Irp + ) + +/*++ + +Routine Description: + + This is the driver entry to all of the Fsd dispatch points. + + Conceptually the Io routine will call this routine on all requests + to the file system. We case on the type of request and invoke the + correct handler for this type of request. There is an exception filter + to catch any exceptions in the CDFS code as well as the CDFS process + exception routine. + + This routine allocates and initializes the IrpContext for this request as + well as updating the top-level thread context as necessary. We may loop + in this routine if we need to retry the request for any reason. The + status code STATUS_CANT_WAIT is used to indicate this. Suppose the disk + in the drive has changed. An Fsd request will proceed normally until it + recognizes this condition. STATUS_VERIFY_REQUIRED is raised at that point + and the exception code will handle the verify and either return + STATUS_CANT_WAIT or STATUS_PENDING depending on whether the request was + posted. + +Arguments: + + DeviceObject - Supplies the volume device object for this request + + Irp - Supplies the Irp being processed + +Return Value: + + NTSTATUS - The FSD status for the IRP + +--*/ + +{ + THREAD_CONTEXT ThreadContext = {0}; + PIRP_CONTEXT IrpContext = NULL; + BOOLEAN Wait; + +#ifdef UDF_SANITY + PVOID PreviousTopLevel; +#endif + + NTSTATUS Status; + +#if DBG + + KIRQL SaveIrql = KeGetCurrentIrql(); + +#endif + + ASSERT_OPTIONAL_IRP(Irp); + + UNREFERENCED_PARAMETER(DeviceObject); + + FsRtlEnterFileSystem(); + +#ifdef UDF_SANITY + PreviousTopLevel = IoGetTopLevelIrp(); +#endif + + // Loop until this request has been completed or posted. + + do { + + // Use a try-except to handle the exception cases. + + _SEH2_TRY { + + // If the IrpContext is NULL then this is the first pass through + // this loop. + + if (IrpContext == NULL) { + + // Decide if this request is waitable an allocate the IrpContext. + // If the file object in the stack location is NULL then this + // is a mount which is always waitable. Otherwise we look at + // the file object flags. + + if (IoGetCurrentIrpStackLocation(Irp)->FileObject == NULL) { + + Wait = TRUE; + + } else { + + Wait = CanFsdWait(Irp); + } + + IrpContext = UDFCreateIrpContext(Irp, Wait); + + // Update the thread context information. + + UDFSetThreadContext(IrpContext, &ThreadContext); + +#ifdef UDF_SANITY + NT_ASSERT(SafeNodeType(IrpContext->TopLevel) == UDF_NODE_TYPE_IRP_CONTEXT); +#endif + + // Otherwise cleanup the IrpContext for the retry. + + } else { + + // Set the MORE_PROCESSING flag to make sure the IrpContext + // isn't inadvertently deleted here. Then cleanup the + // IrpContext to perform the retry. + + SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_MORE_PROCESSING); + UDFCleanupIrpContext(IrpContext, FALSE); + } + + // Case on the major irp code. + + switch (IrpContext->MajorFunction) { + + case IRP_MJ_CREATE: + + Status = UDFCommonCreate(IrpContext, Irp); + break; + + case IRP_MJ_CLOSE: + + Status = UDFCommonClose(IrpContext, Irp); + break; + + case IRP_MJ_READ: + + // If this is an Mdl complete request, don't go through + // common read. + + if (FlagOn(IrpContext->MinorFunction, IRP_MN_COMPLETE)) { + + Status = UDFCompleteMdl(IrpContext, Irp); + + } else { + + Status = UDFCommonRead(IrpContext, Irp); + } + + break; + + case IRP_MJ_WRITE: + + // If this is an Mdl complete request, don't go through + // common write. + + if (FlagOn(IrpContext->MinorFunction, IRP_MN_COMPLETE)) { + + Status = UDFCompleteMdl(IrpContext, Irp); + + } else { + + Status = UDFCommonWrite(IrpContext, Irp); + } + + break; + + case IRP_MJ_QUERY_INFORMATION: + + Status = UDFCommonQueryInfo(IrpContext, Irp); + break; + + case IRP_MJ_SET_INFORMATION: + + Status = UDFCommonSetInfo(IrpContext, Irp); + break; + + case IRP_MJ_FLUSH_BUFFERS: + + Status = UDFCommonFlush(IrpContext, Irp); + break; + + case IRP_MJ_QUERY_VOLUME_INFORMATION: + + Status = UDFCommonQueryVolInfo(IrpContext, Irp); + break; + + case IRP_MJ_SET_VOLUME_INFORMATION: + + Status = UDFCommonSetVolInfo(IrpContext, Irp); + break; + + case IRP_MJ_DIRECTORY_CONTROL: + + Status = UDFCommonDirControl(IrpContext, Irp); + break; + + case IRP_MJ_FILE_SYSTEM_CONTROL: + + Status = UDFCommonFsControl(IrpContext, Irp); + break; + + case IRP_MJ_DEVICE_CONTROL: + + Status = UDFCommonDevControl(IrpContext, Irp); + break; + + case IRP_MJ_LOCK_CONTROL: + + Status = UDFCommonLockControl(IrpContext, Irp); + break; + + case IRP_MJ_CLEANUP: + + Status = UDFCommonCleanup(IrpContext, Irp); + break; + + case IRP_MJ_PNP: + + Status = UDFCommonPnp(IrpContext, Irp); + break; + + case IRP_MJ_SHUTDOWN: + + Status = UDFCommonShutdown(IrpContext, Irp); + break; + + default : + + Status = STATUS_INVALID_DEVICE_REQUEST; + UDFCompleteRequest(IrpContext, Irp, Status); + } + + } _SEH2_EXCEPT(UDFExceptionFilter(IrpContext, _SEH2_GetExceptionInformation())) { + + Status = UDFProcessException(IrpContext, Irp, _SEH2_GetExceptionCode()); + } _SEH2_END; + + } while (Status == STATUS_CANT_WAIT); + +#ifdef UDF_SANITY + NT_ASSERT((PreviousTopLevel == IoGetTopLevelIrp())); +#endif + + FsRtlExitFileSystem(); + + NT_ASSERT(SaveIrql == KeGetCurrentIrql()); + + return Status; +} diff --git a/drivers/filesystems/udfs/udffs.h b/drivers/filesystems/udfs/udffs.h index 2418dc603f240..a919ed985007f 100644 --- a/drivers/filesystems/udfs/udffs.h +++ b/drivers/filesystems/udfs/udffs.h @@ -34,7 +34,6 @@ #endif //UDF_LIMIT_NAME_LEN #define IFS_40 -//#define PRETEND_NTFS //#define UDF_ASYNC_IO @@ -122,8 +121,6 @@ typedef FILE_ID *PFILE_ID; #define NonPagedPoolNx NonPagedPool #endif -#define PEXTENDED_IO_STACK_LOCATION PIO_STACK_LOCATION - // #define NDEBUG #ifndef NDEBUG #define UDF_DBG @@ -138,6 +135,7 @@ typedef FILE_ID *PFILE_ID; #include "wcache.h" #include "Include/regtools.h" +#include "Include/udf_reg.h" #include "struct.h" // global variables - minimize these @@ -203,7 +201,7 @@ UDFIllegalFcbAccess( BooleanFlagOn(DesiredAccess, WriteMask); } -#if !defined(UDF_DBG) && !defined(PRINT_ALWAYS) +#if !defined(UDF_DBG) #define UDFPrint(Args) #else #define UDFPrint(Args) KdPrint(Args) @@ -216,33 +214,31 @@ UDFIllegalFcbAccess( #define UDFReleaseDevice(IrpContext, Vcb, ResourceThreadId) \ ((void)0) /* No operation - CD/DVD write modes not currently supported */ -// -#if !defined(UDF_DBG) && !defined(PRINT_ALWAYS) #define UDFAcquireResourceExclusive(Resource,CanWait) \ (ExAcquireResourceExclusiveLite((Resource),(CanWait))) + #define UDFAcquireResourceShared(Resource,CanWait) \ (ExAcquireResourceSharedLite((Resource),(CanWait))) + // a convenient macro (must be invoked in the context of the thread that acquired the resource) #define UDFReleaseResource(Resource) \ (ExReleaseResourceForThreadLite((Resource), ExGetCurrentResourceThread())) + #define UDFDeleteResource(Resource) \ (ExDeleteResourceLite((Resource))) + #define UDFConvertExclusiveToSharedLite(Resource) \ (ExConvertExclusiveToSharedLite((Resource))) -#define UDFInitializeResourceLite(Resource) \ - (ExInitializeResourceLite((Resource))) + #define UDFAcquireSharedStarveExclusive(Resource,CanWait) \ (ExAcquireSharedStarveExclusive((Resource),(CanWait))) + #define UDFAcquireSharedWaitForExclusive(Resource,CanWait) \ (ExAcquireSharedWaitForExclusive((Resource),(CanWait))) -#define UDFInterlockedIncrement(addr) \ - (InterlockedIncrement((addr))) -#define UDFInterlockedDecrement(addr) \ - (InterlockedDecrement((addr))) -#define UDFInterlockedExchangeAdd(addr,i) \ - (InterlockedExchangeAdd((addr),(i))) +// +#if !defined(UDF_DBG) #define UDF_CHECK_PAGING_IO_RESOURCE(NTReqFCB) #define UDF_CHECK_EXVCB_RESOURCE(Vcb) @@ -250,33 +246,6 @@ UDFIllegalFcbAccess( #else //UDF_DBG -#define UDFAcquireResourceExclusive(Resource,CanWait) \ - (UDFDebugAcquireResourceExclusiveLite((Resource),(CanWait),UDF_BUG_CHECK_ID,__LINE__)) - -#define UDFAcquireResourceShared(Resource,CanWait) \ - (UDFDebugAcquireResourceSharedLite((Resource),(CanWait),UDF_BUG_CHECK_ID,__LINE__)) -// a convenient macro (must be invoked in the context of the thread that acquired the resource) -#define UDFReleaseResource(Resource) \ - (UDFDebugReleaseResourceForThreadLite((Resource), ExGetCurrentResourceThread(),UDF_BUG_CHECK_ID,__LINE__)) - -#define UDFDeleteResource(Resource) \ - (UDFDebugDeleteResource((Resource), ExGetCurrentResourceThread(),UDF_BUG_CHECK_ID,__LINE__)) -#define UDFConvertExclusiveToSharedLite(Resource) \ - (UDFDebugConvertExclusiveToSharedLite((Resource), ExGetCurrentResourceThread(),UDF_BUG_CHECK_ID,__LINE__)) -#define UDFInitializeResourceLite(Resource) \ - (UDFDebugInitializeResourceLite((Resource), ExGetCurrentResourceThread(),UDF_BUG_CHECK_ID,__LINE__)) -#define UDFAcquireSharedStarveExclusive(Resource,CanWait) \ - (UDFDebugAcquireSharedStarveExclusive((Resource), (CanWait), UDF_BUG_CHECK_ID,__LINE__)) -#define UDFAcquireSharedWaitForExclusive(Resource,CanWait) \ - (UDFDebugAcquireSharedWaitForExclusive((Resource), (CanWait), UDF_BUG_CHECK_ID,__LINE__)) - -#define UDFInterlockedIncrement(addr) \ - (UDFDebugInterlockedIncrement((addr), UDF_BUG_CHECK_ID,__LINE__)) -#define UDFInterlockedDecrement(addr) \ - (UDFDebugInterlockedDecrement((addr), UDF_BUG_CHECK_ID,__LINE__)) -#define UDFInterlockedExchangeAdd(addr,i) \ - (UDFDebugInterlockedExchangeAdd((addr),(i), UDF_BUG_CHECK_ID,__LINE__)) - #define UDF_CHECK_PAGING_IO_RESOURCE(Fcb) \ ASSERT(!ExIsResourceAcquiredExclusiveLite(&Fcb->FcbNonpaged->FcbPagingIoResource)); \ ASSERT(!ExIsResourceAcquiredSharedLite(&Fcb->FcbNonpaged->FcbPagingIoResource)); @@ -348,10 +317,6 @@ UDFIllegalFcbAccess( #define UDF_FILE_UDF_INFO_MOUNT (0x00000103) #define UDF_FILE_UDF_INFO_EXTENT (0x00000104) #define UDF_FILE_UDF_INFO_REMAP (0x00000105) -//#define UDF_FILE_UDF_INFO_ (0x0000010x) - -#define UDF_FILE_PROTECT (0x00000300) -//#define UDF_FILE_PROTECT_ (0x0000030x) #define UDF_PART_DAMAGED_RW (0x00) #define UDF_PART_DAMAGED_RO (0x01) @@ -362,13 +327,10 @@ UDFIllegalFcbAccess( #define UDF_ROOTDIR_NAME L"\\" -#define SystemAllocatePool(hernya,size) ExAllocatePoolWithTag(hernya, size, 'Snwd') -#define SystemFreePool(addr) ExFreePool((PVOID)(addr)) - -//Device names - -#include "Include/udf_reg.h" -#include +#if DBG +#undef UDF_SANITY +#define UDF_SANITY +#endif #if DBG diff --git a/drivers/filesystems/udfs/udfinit.cpp b/drivers/filesystems/udfs/udfinit.cpp index ef125d5a15102..0453c669d109f 100644 --- a/drivers/filesystems/udfs/udfinit.cpp +++ b/drivers/filesystems/udfs/udfinit.cpp @@ -73,13 +73,7 @@ DriverEntry( UdfData.NodeIdentifier.NodeTypeCode = UDF_NODE_TYPE_GLOBAL_DATA; UdfData.NodeIdentifier.NodeByteSize = sizeof(UdfData); - // initialize the global data resource and remember the fact that - // the resource has been initialized - RC = UDFInitializeResourceLite(&UdfData.GlobalDataResource); - ASSERT(NT_SUCCESS(RC)); - SetFlag(UdfData.Flags, UDF_DATA_FLAGS_RESOURCE_INITIALIZED); - -// SetFlag(UDFGlobalData.UDFFlags, UDF_DATA_FLAGS_RESOURCE_INITIALIZED); + ExInitializeResourceLite(&UdfData.GlobalDataResource); // keep a ptr to the driver object sent to us by the I/O Mgr UdfData.DriverObject = DriverObject; @@ -213,14 +207,6 @@ DriverEntry( if (UdfData.Flags & UDF_DATA_FLAGS_ZONES_INITIALIZED) { UDFDestroyZones(); } - - // delete the resource we may have initialized - if (UdfData.Flags & UDF_DATA_FLAGS_RESOURCE_INITIALIZED) { - // un-initialize this resource - UDFDeleteResource(&UdfData.GlobalDataResource); - ClearFlag(UdfData.Flags, UDF_DATA_FLAGS_RESOURCE_INITIALIZED); - } -// } else { } } _SEH2_END; @@ -252,49 +238,49 @@ UDFInitializeFunctionPointers( { PFAST_IO_DISPATCH PtrFastIoDispatch = NULL; - // initialize the function pointers for the IRP major - // functions that this FSD is prepared to handle ... - // NT Version 4.0 has 28 possible functions that a - // kernel mode driver can handle. - // NT Version 3.51 and before has only 22 such functions, - // of which 18 are typically interesting to most FSD's. - - // The only interesting new functions that a FSD might - // want to respond to beginning with Version 4.0 are the - // IRP_MJ_QUERY_QUOTA and the IRP_MJ_SET_QUOTA requests. - - // The code below does not handle quota manipulation, neither - // does the NT Version 4.0 operating system (or I/O Manager). - // However, you should be on the lookout for any such new - // functionality that the FSD might have to implement in - // the near future. - - DriverObject->MajorFunction[IRP_MJ_CREATE] = UDFCreate; - DriverObject->MajorFunction[IRP_MJ_CLOSE] = UDFClose; - DriverObject->MajorFunction[IRP_MJ_READ] = UDFRead; - DriverObject->MajorFunction[IRP_MJ_WRITE] = UDFWrite; - DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = UDFQueryInfo; - DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = UDFSetInfo; - DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = UDFFlushBuffers; +#pragma prefast(push) +#pragma prefast(disable: 28155, "the dispatch routine has the correct type, prefast is just being paranoid.") +#pragma prefast(disable: 28168, "the dispatch routine has the correct type, prefast is just being paranoid.") +#pragma prefast(disable: 28169, "the dispatch routine has the correct type, prefast is just being paranoid.") +#pragma prefast(disable: 28175, "we're allowed to change these.") + + // Note that because of the way data caching is done, we set neither + // the Direct I/O or Buffered I/O bit in DeviceObject->Flags. If + // data is not in the cache, or the request is not buffered, we may, + // set up for Direct I/O by hand. + + // Initialize the driver object with this driver's entry points. + // + // NOTE - Each entry in the dispatch table must have an entry in + // the Fsp/Fsd dispatch switch statements. + + DriverObject->MajorFunction[IRP_MJ_CREATE] = + DriverObject->MajorFunction[IRP_MJ_CLOSE] = + DriverObject->MajorFunction[IRP_MJ_READ] = + DriverObject->MajorFunction[IRP_MJ_WRITE] = + DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = + DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = + DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = // To implement support for querying and modifying volume attributes // (volume information query/set operations), enable initialization // of the following two function pointers and then implement the supporting // functions. - DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = UDFQueryVolInfo; - DriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION] = UDFSetVolInfo; - DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = UDFDirControl; + DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = + DriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION] = + DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = // To implement support for file system IOCTL calls, enable initialization // of the following function pointer and implement appropriate support. - DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = UDFFSControl; - DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = UDFDeviceControl; - DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = UDFShutdown; + DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = + DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = + DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = // For byte-range lock support, enable initialization of the following // function pointer and implement appropriate support. - DriverObject->MajorFunction[IRP_MJ_LOCK_CONTROL] = UDFLockControl; - DriverObject->MajorFunction[IRP_MJ_CLEANUP] = UDFCleanup; + DriverObject->MajorFunction[IRP_MJ_LOCK_CONTROL] = + DriverObject->MajorFunction[IRP_MJ_CLEANUP] = - DriverObject->MajorFunction[IRP_MJ_PNP] = UDFPnp; + DriverObject->MajorFunction[IRP_MJ_PNP] = (PDRIVER_DISPATCH)UDFFsdDispatch; +#pragma prefast(pop) // Now, it is time to initialize the fast-io stuff ... PtrFastIoDispatch = DriverObject->FastIoDispatch = &UdfData.UDFFastIoDispatch; diff --git a/drivers/filesystems/udfs/verfysup.cpp b/drivers/filesystems/udfs/verfysup.cpp index 45a7924a2a163..68349d00d08e9 100644 --- a/drivers/filesystems/udfs/verfysup.cpp +++ b/drivers/filesystems/udfs/verfysup.cpp @@ -50,6 +50,7 @@ Return Value: IoAcquireVpbSpinLock(&SavedIrql); +#pragma prefast(suppress: 28175, "this is a filesystem driver, touching the size member is allowed") if (Vcb->Vpb == Vcb->Vpb->RealDevice->Vpb) { SetFlag(Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME); @@ -259,34 +260,50 @@ UDFVerifyVolume( IO_STATUS_BLOCK Iosb; ULONG MediaChangeCount = 0; NTSTATUS RC; + BOOLEAN ReleaseVcb = FALSE; ULONG Mode; - BOOLEAN UnsafeIoctl = (Vcb->VcbState & UDF_VCB_FLAGS_UNSAFE_IOCTL) ? TRUE : FALSE; + //BOOLEAN UnsafeIoctl = (Vcb->VcbState & UDF_VCB_FLAGS_UNSAFE_IOCTL) ? TRUE : FALSE; - // Update the real device in the IrpContext from the Vpb. There was no available - // file object when the IrpContext was created. - // IrpContext->RealDevice = Vpb->RealDevice; - UDFPrint(("UDFVerifyVolume:\n")); + PAGED_CODE(); + + // We check that we are talking to a Cdrom or HDD device. + + ASSERT(Vpb->RealDevice->DeviceType == FILE_DEVICE_CD_ROM || + Vpb->RealDevice->DeviceType == FILE_DEVICE_DISK); + ASSERT(FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)); + + // Update the real device in the IrpContext from the Vpb. There was no available + // file object when the IrpContext was created. + + IrpContext->RealDevice = Vpb->RealDevice; // Acquire the global resource to synchronise against mounts and teardown, // finally clause releases. UDFAcquireUdfData(IrpContext); - UDFAcquireResourceExclusive(&(Vcb->VcbResource),TRUE); - _SEH2_TRY { - UDFPrint(("UDFVerifyVolume: Modified=%d\n", Vcb->Modified)); + UDFAcquireVcbExclusive(IrpContext, Vcb, FALSE); + ReleaseVcb = TRUE; + + if (Vcb->VcbCondition == VcbDismountInProgress || + Vcb->VcbCondition == VcbInvalid) { + + try_return(RC = STATUS_WRONG_VOLUME); + } + // Check if the real device still needs to be verified. If it doesn't // then obviously someone beat us here and already did the work // so complete the verify irp with success. Otherwise reenable // the real device and get to work. - if ( !(Vpb->RealDevice->Flags & DO_VERIFY_VOLUME) && - ((Vcb->VcbState & UDF_VCB_FLAGS_MEDIA_LOCKED) && !UnsafeIoctl) ) { - UDFPrint(("UDFVerifyVolume: STATUS_SUCCESS (1)\n")); + + if (!FlagOn(Vpb->RealDevice->Flags, DO_VERIFY_VOLUME)) { + + UDFPrint(("UDFVerifyVolume: RealDevice has already been verified\n")); try_return(RC = STATUS_SUCCESS); } - Vcb->VcbState &= ~UDF_VCB_FLAGS_UNSAFE_IOCTL; + // Verify that there is a disk here. RC = UDFPhSendIOCTL( IOCTL_STORAGE_CHECK_VERIFY, Vcb->TargetDeviceObject, @@ -294,34 +311,30 @@ UDFVerifyVolume( &MediaChangeCount,sizeof(ULONG), TRUE,&Iosb ); - if (!NT_SUCCESS( RC )) { + if (!NT_SUCCESS(RC)) { + // If we will allow a raw mount then return WRONG_VOLUME to // allow the volume to be mounted by raw. - if (FlagOn( IrpSp->Flags, SL_ALLOW_RAW_MOUNT )) { + + if (FlagOn(IrpSp->Flags, SL_ALLOW_RAW_MOUNT)) { + UDFPrint(("UDFVerifyVolume: STATUS_WRONG_VOLUME (1)\n")); RC = STATUS_WRONG_VOLUME; } - if (UDFIsRawDevice(RC)) { - UDFPrint(("UDFVerifyVolume: STATUS_WRONG_VOLUME (2)\n")); - RC = STATUS_WRONG_VOLUME; - } - try_return( RC ); + try_return(RC); } if (Iosb.Information != sizeof(ULONG)) { + // Be safe about the count in case the driver didn't fill it in MediaChangeCount = 0; } - UDFPrint(("UDFVerifyVolume: Modified=%d\n", Vcb->Modified)); - UDFPrint(("UDFVerifyVolume: MediaChangeCount=%x, Vcb->MediaChangeCount=%x, UnsafeIoctl=%x\n", - MediaChangeCount, Vcb->MediaChangeCount, UnsafeIoctl)); // Verify that the device actually saw a change. If the driver does not // support the MCC, then we must verify the volume in any case. if (MediaChangeCount == 0 || - (Vcb->MediaChangeCount != MediaChangeCount) || - UnsafeIoctl ) { + (Vcb->MediaChangeCount != MediaChangeCount)) { UDFPrint(("UDFVerifyVolume: compare\n")); @@ -358,11 +371,11 @@ UDFVerifyVolume( UdfData.WCacheMaxFrames, UdfData.WCacheMaxBlocks, NewVcb->WriteBlockSize, - 5, NewVcb->BlockSizeBits, + 5, NewVcb->SectorShift, UdfData.WCacheBlocksPerFrameSh, 0/*NewVcb->FirstLBA*/, NewVcb->LastPossibleLBA, Mode, /*WCACHE_CACHE_WHOLE_PACKET*/ 0 | - (Vcb->DoNotCompareBeforeWrite ? WCACHE_DO_NOT_COMPARE : 0) | + WCACHE_DO_NOT_COMPARE | WCACHE_MARK_BAD_BLOCKS | WCACHE_RO_BAD_BLOCKS, // speed up mount on bad disks UdfData.WCacheFramesToKeepFree, UDFTWrite, UDFTRead, @@ -443,12 +456,12 @@ try_exit: NOTHING; Vcb->WCacheMaxFrames, Vcb->WCacheMaxBlocks, Vcb->WriteBlockSize, - 5, Vcb->BlockSizeBits, + 5, Vcb->SectorShift, Vcb->WCacheBlocksPerFrameSh, 0/*Vcb->FirstLBA*/, Vcb->LastPossibleLBA, Mode, /*WCACHE_CACHE_WHOLE_PACKET*/ 0 | - (Vcb->DoNotCompareBeforeWrite ? WCACHE_DO_NOT_COMPARE : 0) | - (Vcb->CacheChainedIo ? WCACHE_CHAINED_IO : 0), + WCACHE_DO_NOT_COMPARE | + WCACHE_CHAINED_IO, Vcb->WCacheFramesToKeepFree, // UDFTWrite, UDFTRead, UDFTWriteVerify, UDFTReadVerify, @@ -487,10 +500,6 @@ try_exit: NOTHING; WCACHE_CACHE_WHOLE_PACKET, // enable cache whole packet WCACHE_MARK_BAD_BLOCKS | WCACHE_RO_BAD_BLOCKS); // let user retry request on Bad Blocks } - // we can't record ACL on old format disks - if (!UDFNtAclSupported(Vcb)) { - Vcb->UseExtendedFE = FALSE; - } } } @@ -502,7 +511,15 @@ try_exit: NOTHING; UDFCleanupVCB(NewVcb); MyFreePool__(NewVcb); } - UDFReleaseResource(&(Vcb->VcbResource)); + + if (ReleaseVcb) { + + UDFReleaseVcb(IrpContext, Vcb); + } + else { + _Analysis_assume_lock_not_held_(Vcb->VcbResource); + } + UDFReleaseUdfData(IrpContext); } _SEH2_END; @@ -555,7 +572,7 @@ UDFPerformVerify( ((IrpContext->MinorFunction == IRP_MN_MOUNT_VOLUME) || (IrpContext->MinorFunction == IRP_MN_VERIFY_VOLUME))) { - return UDFPostRequest(IrpContext, Irp); + return UDFFsdPostRequest(IrpContext, Irp); } // Extract a pointer to the Vcb from the VolumeDeviceObject. @@ -626,10 +643,7 @@ UDFPerformVerify( Irp->IoStatus.Information = IO_REMOUNT; - Irp->IoStatus.Status = STATUS_REPARSE; - IoCompleteRequest(Irp,IO_DISK_INCREMENT); - - UDFCleanupIrpContext(IrpContext); + UDFCompleteRequest(IrpContext, Irp, STATUS_REPARSE); RC = STATUS_REPARSE; Irp = NULL; @@ -652,14 +666,14 @@ UDFPerformVerify( // If there is still an Irp, send it off to an Ex Worker thread. if (IrpContext != NULL) { - RC = UDFPostRequest( IrpContext, Irp ); + RC = UDFFsdPostRequest(IrpContext, Irp); } } _SEH2_EXCEPT(UDFExceptionFilter( IrpContext, _SEH2_GetExceptionInformation())) { // We had some trouble trying to perform the verify or raised // an error ourselves. So we'll abort the I/O request with // the error status that we get back from the execption code. - RC = UDFProcessException( IrpContext, Irp); + RC = UDFProcessException( IrpContext, Irp, _SEH2_GetExceptionCode()); } _SEH2_END; UDFPrint(("UDFPerformVerify: RC = %x\n", RC)); @@ -839,6 +853,8 @@ UDFDismountVcb( // we have last crack at it. If this is a failed mount then we // want to return the Vpb to the IO system to use for the next // mount request. + +#pragma prefast(suppress: 28175, "this is a filesystem driver, touching the vpb is allowed") if (OldVpb->RealDevice->Vpb == OldVpb) { // If not the final reference then swap out the Vpb. @@ -852,6 +868,7 @@ UDFDismountVcb( Vcb->SwapVpb->Size = sizeof( VPB ); Vcb->SwapVpb->RealDevice = OldVpb->RealDevice; +#pragma prefast(suppress: 28175, "this is a filesystem driver, touching the size member is allowed") Vcb->SwapVpb->RealDevice->Vpb = Vcb->SwapVpb; Vcb->SwapVpb->Flags = FlagOn(OldVpb->Flags, VPB_REMOVE_PENDING); @@ -918,12 +935,6 @@ UDFCompareVcb( UDF_FILE_INFO RootFileInfo; BOOLEAN SimpleLogicalCheck = FALSE; - UDFPrint(("UDFCompareVcb:\n")); - if (UdfData.Flags & UDF_DATA_FLAGS_SHUTDOWN) { - UDFPrint((" WRONG_VOLUME\n")); - return STATUS_WRONG_VOLUME; - } - #define VCB_NE(x) (OldVcb->x != NewVcb->x) // compare physical parameters @@ -936,8 +947,6 @@ UDFCompareVcb( VCB_NE(NWA) || VCB_NE(LastPossibleLBA) || VCB_NE(PhSerialNumber) || - VCB_NE(PhErasable) || - VCB_NE(PhDiskType) || VCB_NE(MediaClassEx) || /* We cannot compare these flags, because NewVcb is in unconditional ReadOnly */ diff --git a/drivers/filesystems/udfs/volinfo.cpp b/drivers/filesystems/udfs/volinfo.cpp index 72c39f732cb2e..d8be1796c6138 100644 --- a/drivers/filesystems/udfs/volinfo.cpp +++ b/drivers/filesystems/udfs/volinfo.cpp @@ -69,66 +69,6 @@ UDFSetLabelInfo ( IN PFILE_FS_LABEL_INFORMATION Buffer, IN OUT PULONG Length); -/* - This is the routine for querying volume information - -Arguments: - - Irp - Supplies the Irp being processed - -Return Value: - - NTSTATUS - The return status for the operation - - */ -NTSTATUS -NTAPI -UDFQueryVolInfo( - PDEVICE_OBJECT DeviceObject, // the logical volume device object - PIRP Irp // I/O Request Packet - ) -{ - NTSTATUS RC = STATUS_SUCCESS; - PIRP_CONTEXT IrpContext = NULL; - BOOLEAN AreWeTopLevel = FALSE; - - UDFPrint(("UDFQueryVolInfo: \n")); - - FsRtlEnterFileSystem(); - ASSERT(DeviceObject); - ASSERT(Irp); - - // set the top level context - AreWeTopLevel = UDFIsIrpTopLevel(Irp); - - _SEH2_TRY { - - // get an IRP context structure and issue the request - IrpContext = UDFCreateIrpContext(Irp, DeviceObject); - if (IrpContext) { - RC = UDFCommonQueryVolInfo(IrpContext, Irp); - } else { - - UDFCompleteRequest(IrpContext, Irp, STATUS_INSUFFICIENT_RESOURCES); - RC = STATUS_INSUFFICIENT_RESOURCES; - } - - } _SEH2_EXCEPT(UDFExceptionFilter(IrpContext, _SEH2_GetExceptionInformation())) { - - RC = UDFProcessException(IrpContext, Irp); - - UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC); - } _SEH2_END; - - if (AreWeTopLevel) { - IoSetTopLevelIrp(NULL); - } - - FsRtlExitFileSystem(); - - return(RC); -} // end UDFQueryVolInfo() - /* This is the common routine for querying volume information called by both the fsd and fsp threads. @@ -271,29 +211,38 @@ UDFQueryFsVolumeInfo( PAGED_CODE(); - UDFPrint((" UDFQueryFsVolumeInfo: \n")); - // Fill in the data from the Vcb. + // Fill in the data from the Vcb. + Buffer->VolumeCreationTime.QuadPart = Vcb->VolCreationTime; Buffer->VolumeSerialNumber = Vcb->PhSerialNumber; - UDFPrint((" SN %x\n", Vcb->PhSerialNumber)); Buffer->SupportsObjects = FALSE; - *Length -= FIELD_OFFSET( FILE_FS_VOLUME_INFORMATION, VolumeLabel[0] ); + *Length -= FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION, VolumeLabel[0]); // Check if the buffer we're given is long enough + if (*Length >= (ULONG) Vcb->VolIdent.Length) { + BytesToCopy = Vcb->VolIdent.Length; Status = STATUS_SUCCESS; + } else { + BytesToCopy = *Length; Status = STATUS_BUFFER_OVERFLOW; } - // Copy over what we can of the volume label, and adjust *Length + + // Copy over what we can of the volume label, and adjust *Length + Buffer->VolumeLabelLength = BytesToCopy; - if (BytesToCopy) - RtlCopyMemory( &(Buffer->VolumeLabel[0]), Vcb->VolIdent.Buffer, BytesToCopy ); + if (BytesToCopy) { + + RtlCopyMemory(&Buffer->VolumeLabel[0], Vcb->VolIdent.Buffer, BytesToCopy); + + } + *Length -= BytesToCopy; return Status; @@ -335,12 +284,8 @@ UDFQueryFsSizeInfo( Vcb->LowFreeSpace = (Vcb->FreeAllocUnits < max(Vcb->FECharge,UDF_DEFAULT_FE_CHARGE)*128); if (!Buffer->TotalAllocationUnits.QuadPart) Buffer->TotalAllocationUnits.QuadPart = max(1, Vcb->LastPossibleLBA); - Buffer->SectorsPerAllocationUnit = Vcb->LBlockSize / Vcb->BlockSize; - if (!Buffer->SectorsPerAllocationUnit) - Buffer->SectorsPerAllocationUnit = 1; - Buffer->BytesPerSector = Vcb->BlockSize; - if (!Buffer->BytesPerSector) - Buffer->BytesPerSector = 2048; + Buffer->SectorsPerAllocationUnit = Vcb->SectorSize >> Vcb->SectorShift; + Buffer->BytesPerSector = Vcb->SectorSize; UDFPrint((" Space: Total %I64x, Free %I64x\n", Buffer->TotalAllocationUnits.QuadPart, @@ -388,12 +333,8 @@ UDFQueryFsFullSizeInfo( } if (!Buffer->TotalAllocationUnits.QuadPart) Buffer->TotalAllocationUnits.QuadPart = max(1, Vcb->LastPossibleLBA); - Buffer->SectorsPerAllocationUnit = Vcb->LBlockSize / Vcb->BlockSize; - if (!Buffer->SectorsPerAllocationUnit) - Buffer->SectorsPerAllocationUnit = 1; - Buffer->BytesPerSector = Vcb->BlockSize; - if (!Buffer->BytesPerSector) - Buffer->BytesPerSector = 2048; + Buffer->SectorsPerAllocationUnit = Vcb->SectorSize >> Vcb->SectorShift; + Buffer->BytesPerSector = Vcb->SectorSize; UDFPrint((" Space: Total %I64x, Free %I64x\n", Buffer->TotalAllocationUnits.QuadPart, @@ -473,7 +414,7 @@ UDFQueryFsAttributeInfo( // Fill out the fixed portion of the buffer. Buffer->FileSystemAttributes = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES | - (UDFStreamsSupported(Vcb) ? FILE_NAMED_STREAMS : 0) | + (UDFIsStreamsSupported(Vcb) ? FILE_NAMED_STREAMS : 0) | #ifdef ALLOW_SPARSE FILE_SUPPORTS_SPARSE_FILES | #endif //ALLOW_SPARSE @@ -514,51 +455,6 @@ UDFQueryFsAttributeInfo( return Status; } // end UDFQueryFsAttributeInfo() -NTSTATUS -NTAPI -UDFSetVolInfo( - PDEVICE_OBJECT DeviceObject, // the logical volume device object - PIRP Irp // I/O Request Packet - ) -{ - NTSTATUS RC = STATUS_SUCCESS; - PIRP_CONTEXT IrpContext = NULL; - BOOLEAN AreWeTopLevel = FALSE; - - UDFPrint(("UDFSetVolInfo: \n")); - - FsRtlEnterFileSystem(); - ASSERT(DeviceObject); - ASSERT(Irp); - - // set the top level context - AreWeTopLevel = UDFIsIrpTopLevel(Irp); - - _SEH2_TRY { - - // get an IRP context structure and issue the request - IrpContext = UDFCreateIrpContext(Irp, DeviceObject); - ASSERT(IrpContext); - - RC = UDFCommonSetVolInfo(IrpContext, Irp); - - } _SEH2_EXCEPT(UDFExceptionFilter(IrpContext, _SEH2_GetExceptionInformation())) { - - RC = UDFProcessException(IrpContext, Irp); - - UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC); - } _SEH2_END; - - if (AreWeTopLevel) { - IoSetTopLevelIrp(NULL); - } - - FsRtlExitFileSystem(); - - return(RC); -} // end UDFSetVolInfo() - - /* This is the common routine for setting volume information called by both the fsd and fsp threads. diff --git a/drivers/filesystems/udfs/write.cpp b/drivers/filesystems/udfs/write.cpp index dd9187f5b0008..e76a9426f2f4b 100644 --- a/drivers/filesystems/udfs/write.cpp +++ b/drivers/filesystems/udfs/write.cpp @@ -19,80 +19,6 @@ // define the file specific bug-check id #define UDF_BUG_CHECK_ID UDF_FILE_WRITE -/************************************************************************* -* -* Function: UDFWrite() -* -* Description: -* The I/O Manager will invoke this routine to handle a write -* request -* -* Expected Interrupt Level (for execution) : -* -* IRQL_PASSIVE_LEVEL (invocation at higher IRQL will cause execution -* to be deferred to a worker thread context) -* -* Return Value: STATUS_SUCCESS/Error -* -*************************************************************************/ -NTSTATUS -NTAPI -UDFWrite( - PDEVICE_OBJECT DeviceObject, // the logical volume device object - PIRP Irp // I/O Request Packet - ) -{ - NTSTATUS RC = STATUS_SUCCESS; - PIRP_CONTEXT IrpContext = NULL; - BOOLEAN AreWeTopLevel = FALSE; - - TmPrint(("UDFWrite: , thrd:%8.8x\n",PsGetCurrentThread())); - - FsRtlEnterFileSystem(); - ASSERT(DeviceObject); - ASSERT(Irp); - - // set the top level context - AreWeTopLevel = UDFIsIrpTopLevel(Irp); - - _SEH2_TRY { - - // get an IRP context structure and issue the request - IrpContext = UDFCreateIrpContext(Irp, DeviceObject); - if (IrpContext) { - - if (FlagOn(IrpContext->MinorFunction, IRP_MN_COMPLETE)) { - - RC = UDFCompleteMdl(IrpContext, Irp); - - } else { - - RC = UDFCommonWrite(IrpContext, Irp); - } - - } else { - - UDFCompleteRequest(IrpContext, Irp, STATUS_INSUFFICIENT_RESOURCES); - RC = STATUS_INSUFFICIENT_RESOURCES; - } - - } _SEH2_EXCEPT (UDFExceptionFilter(IrpContext, _SEH2_GetExceptionInformation())) { - - RC = UDFProcessException(IrpContext, Irp); - - UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC); - } _SEH2_END; - - if (AreWeTopLevel) { - IoSetTopLevelIrp(NULL); - } - - FsRtlExitFileSystem(); - - return(RC); -} // end UDFWrite() - - /************************************************************************* * * Function: UDFCommonWrite() @@ -189,9 +115,6 @@ UDFCommonWrite( IrpSp = IoGetCurrentIrpStackLocation(Irp); ASSERT(IrpSp); MmPrint((" Enter Irp, MDL=%x\n", Irp->MdlAddress)); - if (Irp->MdlAddress) { - UDFTouch(Irp->MdlAddress); - } FileObject = IrpSp->FileObject; ASSERT(FileObject); @@ -302,16 +225,13 @@ UDFCommonWrite( SystemBuffer = UDFMapUserBuffer(Irp); if (!SystemBuffer) try_return(RC = STATUS_INVALID_USER_BUFFER); - // Indicate, that volume contents can change after this operation - // This flag will force VerifyVolume in future - UDFPrint((" set UnsafeIoctl\n")); - Vcb->VcbState |= UDF_VCB_FLAGS_UNSAFE_IOCTL; + // Make sure, that volume will never be quick-remounted // It is very important for ChkUdf utility. Vcb->SerialNumber--; // Perform actual Write RC = UDFTWrite(IrpContext, Vcb, SystemBuffer, WriteLength, - (ULONG)(ByteOffset.QuadPart >> Vcb->BlockSizeBits), + (ULONG)(ByteOffset.QuadPart >> Vcb->SectorShift), &NumberBytesWritten); UDFUnlockCallersBuffer(IrpContext, Irp, SystemBuffer); try_return(RC); @@ -505,7 +425,8 @@ UDFCommonWrite( // This clause determines if the top level request was // in the FastIo path. - if ((ULONG_PTR)TopIrp > FSRTL_MAX_TOP_LEVEL_IRP_FLAG) { + if ((ULONG_PTR)TopIrp > FSRTL_MAX_TOP_LEVEL_IRP_FLAG && + NodeType(TopIrp) == IO_TYPE_IRP) { PIO_STACK_LOCATION IrpStack; ASSERT( TopIrp->Type == IO_TYPE_IRP ); @@ -693,7 +614,7 @@ UDFCommonWrite( try_return(RC = STATUS_INVALID_USER_BUFFER); ASSERT(SystemBuffer); Fcb->NtReqFCBFlags |= UDF_NTREQ_FCB_MODIFIED; - PerfPrint(("UDFCommonWrite: CcCopyWrite %x bytes at %x\n", TruncatedLength, ByteOffset.LowPart)); + MmPrint((" CcCopyWrite()\n")); if (!CcCopyWrite(FileObject, &(ByteOffset), TruncatedLength, CanWait, SystemBuffer)) { // The caller was not prepared to block and data is not immediately @@ -745,9 +666,8 @@ UDFCommonWrite( try_return(RC = STATUS_PENDING); } - PerfPrint(("UDFCommonWrite: Physical write %x bytes at %x\n", TruncatedLength, ByteOffset.LowPart)); - // Lock the callers buffer + if (!NT_SUCCESS(RC = UDFLockUserBuffer(IrpContext, TruncatedLength, IoReadAccess))) { try_return(RC); } @@ -775,7 +695,6 @@ try_exit: NOTHING; WCacheEODirect__(&(Vcb->FastCache), Vcb); } - // Post IRP if required if (RC == STATUS_PENDING) { // Release any resources acquired here ... @@ -791,16 +710,6 @@ try_exit: NOTHING; if (VcbAcquired) { UDFReleaseResource(&Vcb->VcbResource); } - // Lock the callers buffer here. Then invoke a common routine to - // perform the post operation. - if (!(IrpSp->MinorFunction & IRP_MN_MDL)) { - RC = UDFLockUserBuffer(IrpContext, WriteLength, IoReadAccess); - ASSERT(NT_SUCCESS(RC)); - } - - // Perform the post operation which will mark the IRP pending - // and will return STATUS_PENDING back to us - RC = UDFPostRequest(IrpContext, Irp); } else { // For synchronous I/O, the FSD must maintain the current byte offset @@ -879,19 +788,21 @@ try_exit: NOTHING; Irp) { Irp->IoStatus.Status = RC; Irp->IoStatus.Information = NumberBytesWritten; - // complete the IRP - MmPrint((" Complete Irp, MDL=%x\n", Irp->MdlAddress)); - if (Irp->MdlAddress) { - UDFTouch(Irp->MdlAddress); - } - IoCompleteRequest(Irp, IO_DISK_INCREMENT); } - // Free up the Irp Context - UDFCleanupIrpContext(IrpContext); - - } // can we complete the IRP ? + } } _SEH2_END; // end of "__finally" processing + // Post IRP if required + + if (RC == STATUS_PENDING) { + + RC = UDFFsdPostRequest(IrpContext, Irp); + } + else { + + UDFCompleteRequest(IrpContext, Irp, RC); + } + UDFPrint(("\n")); return(RC); } // end UDFCommonWrite() @@ -926,7 +837,7 @@ UDFDeferredWriteCallBack( // could not be completed because the caller could not block). // Once we post the request, return from this routine. The write // will then be retried in the context of a system worker thread - UDFPostRequest((PIRP_CONTEXT)Context1, (PIRP)Context2); + UDFAddToWorkque((PIRP_CONTEXT)Context1, (PIRP)Context2); } // end UDFDeferredWriteCallBack() @@ -1117,7 +1028,7 @@ UDFZeroData ( PAGED_CODE(); - ULONG LBS = Vcb->LBlockSize; + ULONG LBS = Vcb->SectorSize; ZeroStart.LowPart = (StartingZero + (LBS - 1)) & ~(LBS - 1); From a3a7243a36c74ddb1bfcc570be334b0bddab7d0f Mon Sep 17 00:00:00 2001 From: Gleb Lamm Date: Fri, 26 Dec 2025 01:21:57 +0400 Subject: [PATCH 2/9] try-fix-write --- drivers/filesystems/udfs/CMakeLists.txt | 1 - drivers/filesystems/udfs/Include/phys_lib.cpp | 702 +--- drivers/filesystems/udfs/Include/phys_lib.h | 66 +- drivers/filesystems/udfs/Include/udf_reg.h | 5 - .../filesystems/udfs/Include/wcache_lib.cpp | 3685 ----------------- drivers/filesystems/udfs/Include/wcache_lib.h | 340 -- drivers/filesystems/udfs/cleanup.cpp | 21 +- drivers/filesystems/udfs/create.cpp | 5 + drivers/filesystems/udfs/env_spec.cpp | 29 +- drivers/filesystems/udfs/env_spec.h | 2 +- drivers/filesystems/udfs/fastio.cpp | 99 +- drivers/filesystems/udfs/flush.cpp | 9 - drivers/filesystems/udfs/fscntrl.cpp | 303 +- drivers/filesystems/udfs/misc.cpp | 310 +- drivers/filesystems/udfs/protos.h | 70 +- drivers/filesystems/udfs/read.cpp | 734 ++-- drivers/filesystems/udfs/shutdown.cpp | 2 +- drivers/filesystems/udfs/strucsup.cpp | 10 +- drivers/filesystems/udfs/struct.h | 62 +- drivers/filesystems/udfs/udf_dbg.h | 8 +- drivers/filesystems/udfs/udf_info/alloc.cpp | 36 - drivers/filesystems/udfs/udf_info/dirtree.cpp | 12 +- drivers/filesystems/udfs/udf_info/extent.cpp | 66 +- drivers/filesystems/udfs/udf_info/mount.cpp | 103 +- .../filesystems/udfs/udf_info/phys_eject.cpp | 3 - drivers/filesystems/udfs/udf_info/remap.cpp | 749 +--- .../filesystems/udfs/udf_info/udf_info.cpp | 45 +- drivers/filesystems/udfs/udf_info/udf_info.h | 97 +- drivers/filesystems/udfs/udf_info/udf_rel.h | 11 - drivers/filesystems/udfs/udffs.h | 8 +- drivers/filesystems/udfs/udfinit.cpp | 2 +- drivers/filesystems/udfs/verfysup.cpp | 281 +- drivers/filesystems/udfs/volinfo.cpp | 4 - drivers/filesystems/udfs/wcache.cpp | 11 - drivers/filesystems/udfs/wcache.h | 12 - drivers/filesystems/udfs/write.cpp | 687 ++- 36 files changed, 1184 insertions(+), 7406 deletions(-) delete mode 100644 drivers/filesystems/udfs/Include/wcache_lib.cpp delete mode 100644 drivers/filesystems/udfs/Include/wcache_lib.h delete mode 100644 drivers/filesystems/udfs/wcache.cpp delete mode 100644 drivers/filesystems/udfs/wcache.h diff --git a/drivers/filesystems/udfs/CMakeLists.txt b/drivers/filesystems/udfs/CMakeLists.txt index d15da5fdf6c01..53ce00f1bd62f 100644 --- a/drivers/filesystems/udfs/CMakeLists.txt +++ b/drivers/filesystems/udfs/CMakeLists.txt @@ -34,7 +34,6 @@ list(APPEND SOURCE unload.cpp verfysup.cpp volinfo.cpp - wcache.cpp write.cpp strucsup.cpp filobsup.cpp diff --git a/drivers/filesystems/udfs/Include/phys_lib.cpp b/drivers/filesystems/udfs/Include/phys_lib.cpp index ee76d63404c16..bba91e86d1c06 100644 --- a/drivers/filesystems/udfs/Include/phys_lib.cpp +++ b/drivers/filesystems/udfs/Include/phys_lib.cpp @@ -53,19 +53,8 @@ #define DEFAULT_LAST_LBA_FP_CD 276159 #define TOC_LastTrack_ID 0xAA #define MediaType_UnknownSize_CDRW 0x20 - -#define MRW_DMA_OFFSET 0x500 -#define MRW_DA_SIZE (136*32) -#define MRW_SA_SIZE (8*32) -#define MRW_DMA_SEGMENT_SIZE (MRW_DA_SIZE+MRW_SA_SIZE) - // Local functions: -NTSTATUS -UDFSetCaching( - IN PVCB Vcb - ); - NTSTATUS UDFRecoverFromError( IN PVCB Vcb, @@ -101,357 +90,6 @@ UDFReallocTrackMap( return STATUS_SUCCESS; } // end UDFReallocTrackMap() -NTSTATUS -__fastcall -UDFTIOVerify( - IN PIRP_CONTEXT IrpContext, - IN void* _Vcb, - IN void* Buffer, // Target buffer - IN SIZE_T Length, - IN uint32 LBA, - OUT PSIZE_T IOBytes, - IN uint32 Flags - ) -{ - NTSTATUS RC = STATUS_SUCCESS; - uint32 i, j; - SIZE_T mask; - uint32 lba0, len, lba1; - PUCHAR tmp_buff; - PUCHAR p; - PCHAR cached_block; - SIZE_T tmp_wb; - BOOLEAN need_remap; - NTSTATUS final_RC = STATUS_SUCCESS; - BOOLEAN zero; - BOOLEAN non_zero; - BOOLEAN packet_ok; - BOOLEAN free_tmp = FALSE; - BOOLEAN single_packet = FALSE; - -#define Vcb ((PVCB)_Vcb) - // ATTENTION! Do not touch bad block bitmap here, since it describes PHYSICAL addresses WITHOUT remapping, - // while here we work with LOGICAL addresses - - if (Vcb->VerifyCtx.ItemCount > UDF_MAX_VERIFY_CACHE) { - UDFVVerify(Vcb, 0/*UFD_VERIFY_FLAG_WAIT*/); - } - - UDFAcquireResourceExclusive(&(Vcb->IoResource), TRUE); - Flags |= PH_IO_LOCKED; - - tmp_wb = (SIZE_T)_Vcb; - if (Flags & PH_EX_WRITE) { - UDFPrint(("IO-Write-Verify\n")); - RC = UDFTWrite(IrpContext, _Vcb, Buffer, Length, LBA, &tmp_wb, Flags | PH_VCB_IN_RETLEN); - } else { - UDFPrint(("IO-Read-Verify\n")); - RC = UDFTRead(IrpContext, _Vcb, Buffer, Length, LBA, &tmp_wb, Flags | PH_VCB_IN_RETLEN); - } - (*IOBytes) = tmp_wb; - - switch(RC) { - default: - UDFReleaseResource(&(Vcb->IoResource)); - return RC; - case STATUS_FT_WRITE_RECOVERY: - case STATUS_DEVICE_DATA_ERROR: - case STATUS_IO_DEVICE_ERROR: - break; - /* FALL THROUGH */ - } // end switch(RC) - - if (!Vcb->SparingCount || - !Vcb->SparingCountFree || - Vcb->CDR_Mode) { - UDFPrint(("Can't remap\n")); - UDFReleaseResource(&(Vcb->IoResource)); - return RC; - } - - if (Flags & PH_EX_WRITE) { - UDFPrint(("Write failed, try relocation\n")); - } else { - if (Vcb->Modified) { - UDFPrint(("Read failed, try relocation\n")); - } else { - UDFPrint(("no remap on not modified volume\n")); - UDFReleaseResource(&(Vcb->IoResource)); - return RC; - } - } - if (Flags & PH_LOCK_CACHE) { - UDFReleaseResource(&(Vcb->IoResource)); - WCacheStartDirect__(&(Vcb->FastCache), Vcb, TRUE); - UDFAcquireResourceExclusive(&(Vcb->IoResource), TRUE); - } - - Flags &= ~PH_KEEP_VERIFY_CACHE; - - // NOTE: SparingBlockSize may be not equal to PacketSize - // perform recovery - mask = Vcb->SparingBlockSize-1; - lba0 = LBA & ~mask; - len = ((LBA+(Length>>Vcb->SectorShift)+mask) & ~mask) - lba0; - j=0; - if ((lba0 == LBA) && (len == mask+1) && (len == (Length>>Vcb->SectorShift))) { - single_packet = TRUE; - tmp_buff = NULL; - } else { - tmp_buff = (PUCHAR)DbgAllocatePoolWithTag(NonPagedPool, Vcb->SparingBlockSize << Vcb->SectorShift, 'bNWD'); - if (!tmp_buff) { - UDFPrint((" can't alloc tmp\n")); - UDFReleaseResource(&(Vcb->IoResource)); - return STATUS_DEVICE_DATA_ERROR; - } - free_tmp = TRUE; - } - - for(i=0; iSparingCountFree) { - UDFPrint((" no more free spare blocks, abort verification\n")); - break; - } - UDFPrint((" read LBA %x (%x)\n", lba0+i, j)); - if (!j) { - need_remap = FALSE; - lba1 = lba0+i; - non_zero = FALSE; - if (single_packet) { - // single packet requested - tmp_buff = (PUCHAR)Buffer; - if (Flags & PH_EX_WRITE) { - UDFPrint((" remap single write\n")); - UDFPrint((" try del from verify cache @ %x, %x\n", lba0, len)); - UDFVForget(Vcb, len, UDFRelocateSector(Vcb, lba0), 0); - goto do_remap; - } else { - UDFPrint((" recover and remap single read\n")); - } - } - } - p = tmp_buff+(j<SectorShift); - // not cached, try to read - // prepare for error, if block cannot be read, assume it is zero-filled - RtlZeroMemory(p, Vcb->SectorSize); - - // check if block valid - if (Vcb->BSBM_Bitmap) { - if (UDFGetBit((uint32*)(Vcb->BSBM_Bitmap), UDFRelocateSector(Vcb, lba0+i))) { - UDFPrint((" remap: known BB @ %x, mapped to %x\n", lba0+i, UDFRelocateSector(Vcb, lba0+i))); - need_remap = TRUE; - } - } - zero = FALSE; - if (Vcb->FSBM_Bitmap) { - if (UDFGetFreeBit((uint32*)(Vcb->FSBM_Bitmap), lba0+i)) { - UDFPrint((" unused @ %x\n", lba0+i)); - zero = TRUE; - } - } - - non_zero |= !zero; - - if (!j) { - packet_ok = FALSE; - if (!single_packet) { - // try to read entire packet, this returs error more often then sequential reading of all blocks one by one - tmp_wb = (SIZE_T)_Vcb; - RC = UDFTRead(IrpContext, _Vcb, p, Vcb->SparingBlockSize << Vcb->SectorShift, lba0+i, &tmp_wb, - Flags | PH_READ_VERIFY_CACHE | PH_TMP_BUFFER | PH_VCB_IN_RETLEN); - } else { - // Note: we get here ONLY if original request failed - // do not retry if it was single-packet request - RC = STATUS_UNSUCCESSFUL; - } - if (RC == STATUS_SUCCESS) { - UDFPrint((" packet ok @ %x\n", lba0+i)); - packet_ok = TRUE; - i += Vcb->SparingBlockSize-1; - continue; - } else { - need_remap = TRUE; - } - } - - if (!zero) { - if (WCacheIsCached__(&(Vcb->FastCache), lba0+i, 1)) { - // even if block is cached, we have to verify if it is readable - if (!packet_ok && !UDFVIsStored(Vcb, lba0+i)) { - - tmp_wb = (SIZE_T)_Vcb; - RC = UDFTRead(IrpContext, _Vcb, p, Vcb->SectorSize, lba0+i, &tmp_wb, - Flags | PH_FORGET_VERIFIED | PH_READ_VERIFY_CACHE | PH_TMP_BUFFER | PH_VCB_IN_RETLEN); - if (!NT_SUCCESS(RC)) { - UDFPrint((" Found BB @ %x\n", lba0+i)); - } - - } - RC = WCacheDirect__(IrpContext, &Vcb->FastCache, _Vcb, lba0+i, FALSE, &cached_block, TRUE/* cached only */); - } else { - cached_block = NULL; - if (!packet_ok) { - RC = STATUS_UNSUCCESSFUL; - } else { - RC = STATUS_SUCCESS; - } - } - if (NT_SUCCESS(RC)) { - // cached or successfully read - if (cached_block) { - // we can get from cache the most fresh data - RtlCopyMemory(p, cached_block, Vcb->SectorSize); - } - - } else { - if (!UDFVIsStored(Vcb, lba0+i)) { - tmp_wb = (SIZE_T)_Vcb; - RC = UDFTRead(IrpContext, _Vcb, p, Vcb->SectorSize, lba0+i, &tmp_wb, - Flags | PH_FORGET_VERIFIED | PH_READ_VERIFY_CACHE | PH_TMP_BUFFER | PH_VCB_IN_RETLEN); - } else { - // get it from verify-cache - RC = STATUS_UNSUCCESSFUL; - } - if (!NT_SUCCESS(RC)) { -/* - UDFPrint((" retry @ %x\n", lba0+i)); - tmp_wb = (uint32)_Vcb; - RC = UDFTRead(_Vcb, p, Vcb->BlockSize, lba0+i, &tmp_wb, - Flags | PH_FORGET_VERIFIED | PH_READ_VERIFY_CACHE | PH_TMP_BUFFER | PH_VCB_IN_RETLEN); -*/ - UDFPrint((" try get from verify cache @ %x\n", lba0+i)); - RC = UDFVRead(Vcb, p, 1, UDFRelocateSector(Vcb, lba0+i), - Flags | PH_FORGET_VERIFIED | PH_READ_VERIFY_CACHE | PH_TMP_BUFFER); - need_remap = TRUE; - } - } - } else { - RtlZeroMemory(p, Vcb->SectorSize); - } - if (!packet_ok) { - UDFPrint((" try del from verify cache @ %x\n", lba0+i)); - RC = UDFVForget(Vcb, 1, UDFRelocateSector(Vcb, lba0+i), 0); - } - - if (!packet_ok || need_remap) { - UDFPrint((" block in bad packet @ %x\n", lba0+i)); - if (Vcb->BSBM_Bitmap) { - UDFSetBit(Vcb->BSBM_Bitmap, lba0+i); - } - if (Vcb->FSBM_Bitmap) { - UDFSetUsedBit(Vcb->FSBM_Bitmap, lba0+i); - } - } - - j++; - if (j >= Vcb->SparingBlockSize) { - // remap this packet - if (need_remap) { - ASSERT(!packet_ok); - if (!non_zero) { - UDFPrint((" forget Z packet @ %x\n", lba1)); - UDFUnmapRange(Vcb, lba1, Vcb->SparingBlockSize); - RC = STATUS_SUCCESS; - } else { -do_remap: - for(j=0; j<3; j++) { - UDFPrint((" remap packet @ %x\n", lba1)); - RC = UDFRemapPacket(IrpContext, Vcb, lba1, FALSE); - if (!NT_SUCCESS(RC)) { - if (RC == STATUS_SHARING_VIOLATION) { - UDFPrint((" remap2\n")); - // remapped location have died - RC = UDFRemapPacket(IrpContext, Vcb, lba1, TRUE); - } - if (!NT_SUCCESS(RC)) { - // packet cannot be remapped :( - RC = STATUS_DEVICE_DATA_ERROR; - } - } - UDFPrint((" remap status %x\n", RC)); - if (NT_SUCCESS(RC)) { - // write to remapped area - tmp_wb = (SIZE_T)_Vcb; - RC = UDFTWrite(IrpContext, _Vcb, tmp_buff, Vcb->SparingBlockSize << Vcb->SectorShift, lba1, &tmp_wb, - Flags | PH_FORGET_VERIFIED | PH_READ_VERIFY_CACHE | PH_TMP_BUFFER | PH_VCB_IN_RETLEN); - UDFPrint((" write status %x\n", RC)); - if (RC != STATUS_SUCCESS) { - // will be remapped - UDFPrint((" retry remap\n")); - - // Note: when remap of already remapped block is requested, verify of - // entire sparing are will be performed. - - } else { - UDFPrint((" remap OK\n")); - break; - } - } else { - UDFPrint((" failed remap\n")); - break; - } - } // for - } - if (!NT_SUCCESS(RC) && !NT_SUCCESS(final_RC)) { - final_RC = RC; - } - } else { - UDFPrint((" NO remap for @ %x\n", (lba0+i) & ~mask)); - } - j=0; - } - } - if (free_tmp) { - DbgFreePool(tmp_buff); - } - - tmp_wb = (SIZE_T)_Vcb; - if (Flags & PH_EX_WRITE) { - UDFPrint(("IO-Write-Verify (2)\n")); - //RC = UDFTWrite(_Vcb, Buffer, Length, LBA, &tmp_wb, Flags | PH_FORGET_VERIFIED | PH_VCB_IN_RETLEN); - } else { - UDFPrint(("IO-Read-Verify (2)\n")); - RC = UDFTRead(IrpContext, _Vcb, Buffer, Length, LBA, &tmp_wb, Flags | PH_FORGET_VERIFIED | PH_VCB_IN_RETLEN); - } - (*IOBytes) = tmp_wb; - UDFPrint(("Final %x\n", RC)); - - UDFReleaseResource(&(Vcb->IoResource)); - if (Flags & PH_LOCK_CACHE) { - WCacheEODirect__(&(Vcb->FastCache), Vcb); - } - - return RC; -} // end UDFTIOVerify() - -NTSTATUS -UDFTWriteVerify( - IN PIRP_CONTEXT IrpContext, - IN void* _Vcb, - IN void* Buffer, // Target buffer - IN SIZE_T Length, - IN uint32 LBA, - OUT PSIZE_T WrittenBytes, - IN uint32 Flags - ) -{ - return UDFTIOVerify(IrpContext, _Vcb, Buffer, Length, LBA, WrittenBytes, Flags | PH_VCB_IN_RETLEN | PH_EX_WRITE | PH_KEEP_VERIFY_CACHE); -} // end UDFTWriteVerify() - -NTSTATUS -UDFTReadVerify( - IN PIRP_CONTEXT IrpContext, - IN void* _Vcb, - IN void* Buffer, // Target buffer - IN SIZE_T Length, - IN uint32 LBA, - OUT PSIZE_T ReadBytes, - IN uint32 Flags - ) -{ - return UDFTIOVerify(IrpContext, _Vcb, Buffer, Length, LBA, ReadBytes, Flags | PH_VCB_IN_RETLEN | PH_KEEP_VERIFY_CACHE); -} // end UDFTReadVerify() - /* This routine performs low-level write @@ -495,7 +133,7 @@ UDFTWrite( return STATUS_NO_SUCH_DEVICE; } - Vcb->VcbState |= (UDF_VCB_SKIP_EJECT_CHECK | UDF_VCB_LAST_WRITE); + Vcb->VcbState |= UDF_VCB_LAST_WRITE; if (!Vcb->CDR_Mode) { RelocExtent = UDFRelocateSectors(Vcb, LBA, BCount); if (!RelocExtent) { @@ -528,14 +166,10 @@ UDFTWrite( UDFPrint(("prepare failed\n")); try_return(RC); } - if (Flags & PH_VCB_IN_RETLEN) { - (*WrittenBytes) = (ULONG_PTR)Vcb; - } + RC = UDFPhWriteSynchronous(Vcb->TargetDeviceObject, Buffer, Length, ((uint64)rLba) << Vcb->SectorShift, WrittenBytes, Flags); - Vcb->VcbState |= UDF_VCB_SKIP_EJECT_CHECK; - if (!NT_SUCCESS(RC) && NT_SUCCESS(RC = UDFRecoverFromError(Vcb, TRUE, RC, rLba, BCount, &retry)) ) goto retry_1; @@ -554,12 +188,10 @@ UDFTWrite( UDFPrint(("prepare failed (2)\n")); break; } - if (Flags & PH_VCB_IN_RETLEN) { - _WrittenBytes = (ULONG_PTR)Vcb; - } + RC = UDFPhWriteSynchronous(Vcb->TargetDeviceObject, Buffer, RelocExtent->extLength, ((uint64)rLba) << Vcb->SectorShift, &_WrittenBytes, Flags); - Vcb->VcbState |= UDF_VCB_SKIP_EJECT_CHECK; + if (!NT_SUCCESS(RC) && NT_SUCCESS(RC = UDFRecoverFromError(Vcb, TRUE, RC, rLba, BCount, &retry)) ) goto retry_2; @@ -593,7 +225,7 @@ UDFTRead( IN void* Buffer, // Target buffer IN SIZE_T Length, IN uint32 LBA, - OUT PSIZE_T ReadBytes, + OUT PULONG ReadBytes, IN uint32 Flags ) { @@ -607,7 +239,6 @@ UDFTRead( PEXTENT_MAP RelocExtent_saved = NULL; BOOLEAN res_acq = FALSE; // LARGE_INTEGER delay; - Vcb->VcbState |= UDF_VCB_SKIP_EJECT_CHECK; ASSERT(Buffer); @@ -638,13 +269,10 @@ UDFTRead( if (!NT_SUCCESS(RC)) try_return(RC); rLba = UDFFixFPAddress(Vcb, rLba); - if (Flags & PH_VCB_IN_RETLEN) { - (*ReadBytes) = (SIZE_T)Vcb; - } RC = UDFPhReadSynchronous(IrpContext, Vcb->TargetDeviceObject, Buffer, Length, ((uint64)rLba) << Vcb->SectorShift, ReadBytes, Flags); Vcb->VcbState &= ~UDF_VCB_LAST_WRITE; - Vcb->VcbState |= UDF_VCB_SKIP_EJECT_CHECK; + if (!NT_SUCCESS(RC) && NT_SUCCESS(RC = UDFRecoverFromError(Vcb, FALSE, RC, rLba, BCount, &retry)) ) { if (RC != STATUS_BUFFER_ALL_ZEROS) { @@ -660,7 +288,7 @@ UDFTRead( // read according to relocation table RelocExtent_saved = RelocExtent; for(i=0; RelocExtent->extLength; i++, RelocExtent++) { - SIZE_T _ReadBytes; + ULONG _ReadBytes; rLba = RelocExtent->extLocation; if (rLba >= (Vcb->CDR_Mode ? Vcb->NWA : Vcb->LastLBA + 1)) { RtlZeroMemory(Buffer, _ReadBytes = RelocExtent->extLength); @@ -673,13 +301,11 @@ UDFTRead( RC = UDFPrepareForReadOperation(IrpContext, Vcb, rLba, RelocExtent->extLength >> Vcb->SectorShift); if (!NT_SUCCESS(RC)) break; rLba = UDFFixFPAddress(Vcb, rLba); - if (Flags & PH_VCB_IN_RETLEN) { - _ReadBytes = (SIZE_T)Vcb; - } + RC = UDFPhReadSynchronous(IrpContext, Vcb->TargetDeviceObject, Buffer, RelocExtent->extLength, ((uint64)rLba) << Vcb->SectorShift, &_ReadBytes, Flags); Vcb->VcbState &= ~UDF_VCB_LAST_WRITE; - Vcb->VcbState |= UDF_VCB_SKIP_EJECT_CHECK; + if (!NT_SUCCESS(RC) && NT_SUCCESS(RC = UDFRecoverFromError(Vcb, FALSE, RC, rLba, BCount, &retry)) ) { if (RC != STATUS_BUFFER_ALL_ZEROS) { @@ -855,26 +481,38 @@ UDFDetermineVolumeLayout( PIRP_CONTEXT IrpContext, PDEVICE_OBJECT DeviceObject, PVCB Vcb, - PULONG SessionStart, - PULONG SessionEnd + PULONG SessionStartLba, + PULONG SessionEndLba ) { - NTSTATUS RC = STATUS_SUCCESS; - CDROM_TOC_LARGE* toc = (CDROM_TOC_LARGE*)MyAllocatePool__(NonPagedPool, sizeof(CDROM_TOC_LARGE)); - CDROM_TOC_SESSION_DATA* LastSes = (CDROM_TOC_SESSION_DATA*)MyAllocatePool__(NonPagedPool, sizeof(CDROM_TOC_SESSION_DATA)); - uint32 LocalTrackCount; - uint32 TocEntry; - void* TempBuffer = NULL; - uint32 OldTrkNum; - uint32 TrkNum; - SIZE_T ReadBytes, i, len; - - UDFPrint(("UDFUseStandard\n")); + NTSTATUS Status; + CDROM_TOC_LARGE* toc = NULL; + CDROM_TOC_SESSION_DATA* LastSes = NULL; + ULONG LocalTrackCount; + ULONG TocEntry; + void* TempBuffer = NULL; + ULONG OldTrkNum; + ULONG TrkNum; + ULONG ReadBytes; + SIZE_T i, len; + + *SessionStartLba = 0; + *SessionEndLba = 0; + + //// Only process CD-ROM devices + + //if (DeviceObject->DeviceType != FILE_DEVICE_CD_ROM) { + + // return STATUS_SUCCESS; + //} + + toc = (CDROM_TOC_LARGE*)MyAllocatePool__(NonPagedPool, sizeof(CDROM_TOC_LARGE)); + LastSes = (CDROM_TOC_SESSION_DATA*)MyAllocatePool__(NonPagedPool, sizeof(CDROM_TOC_SESSION_DATA)); _SEH2_TRY { if (!toc || !LastSes) { - try_return (RC = STATUS_INSUFFICIENT_RESOURCES); + try_return (Status = STATUS_INSUFFICIENT_RESOURCES); } RtlZeroMemory(toc, sizeof(CDROM_TOC_LARGE)); @@ -883,21 +521,7 @@ UDFDetermineVolumeLayout( RtlZeroMemory(&Command, sizeof(Command)); - RC = UDFPhSendIOCTL(IOCTL_CDROM_READ_TOC_EX, - DeviceObject, - &Command, - sizeof(Command), - toc, - sizeof(CDROM_TOC_LARGE), - TRUE, - NULL); - - if (!NT_SUCCESS(RC)) { - - // try using the MSF mode - Command.Msf = 1; - - RC = UDFPhSendIOCTL(IOCTL_CDROM_READ_TOC_EX, + Status = UDFPhSendIOCTL(IOCTL_CDROM_READ_TOC_EX, DeviceObject, &Command, sizeof(Command), @@ -905,14 +529,34 @@ UDFDetermineVolumeLayout( sizeof(CDROM_TOC_LARGE), TRUE, NULL); + + if (!NT_SUCCESS(Status) && + (Status != STATUS_INSUFFICIENT_RESOURCES)) { + + // try using the MSF mode + Command.Msf = 1; + + Status = UDFPhSendIOCTL(IOCTL_CDROM_READ_TOC_EX, + DeviceObject, + &Command, + sizeof(Command), + toc, + sizeof(CDROM_TOC_LARGE), + TRUE, + NULL); + } + + if (Status == STATUS_INSUFFICIENT_RESOURCES) { + + UDFRaiseStatus(IrpContext, Status); } // If even standard read toc does not work, then use default values - if (!NT_SUCCESS(RC)) { + if (!NT_SUCCESS(Status)) { - RC = UDFReallocTrackMap(Vcb, 2); - if (!NT_SUCCESS(RC)) { - try_return(RC); + Status = UDFReallocTrackMap(Vcb, 2); + if (!NT_SUCCESS(Status)) { + try_return(Status); } Vcb->LastSession=1; @@ -925,7 +569,7 @@ UDFDetermineVolumeLayout( if (UDFGetDevType(DeviceObject) == FILE_DEVICE_DISK) { - try_return(RC = STATUS_SUCCESS); + try_return(Status = STATUS_SUCCESS); } Vcb->LastPossibleLBA = max(Vcb->LastLBA, DEFAULT_LAST_LBA_FP_CD); @@ -933,14 +577,15 @@ UDFDetermineVolumeLayout( Vcb->TrackMap[1].TrackParam = TrkInfo_Trk_XA; Vcb->TrackMap[1].NWA = 0xffffffff; Vcb->NWA = DEFAULT_LAST_LBA_FP_CD + 7 + 1; - try_return(RC = STATUS_SUCCESS); + try_return(Status = STATUS_SUCCESS); } LocalTrackCount = toc->LastTrack - toc->FirstTrack + 1; // Get out if there is an immediate problem with the TOC. + if (toc->LastTrack - toc->FirstTrack >= MAXIMUM_NUMBER_TRACKS_LARGE) { - try_return(RC = STATUS_DISK_CORRUPT_ERROR); + try_return(Status = STATUS_DISK_CORRUPT_ERROR); } Vcb->LastTrackNum = toc->LastTrack; @@ -948,14 +593,14 @@ UDFDetermineVolumeLayout( // some devices report LastTrackNum=0 for full disks Vcb->LastTrackNum = max(Vcb->LastTrackNum, Vcb->FirstTrackNum); - RC = UDFReallocTrackMap(Vcb, MAXIMUM_NUMBER_TRACKS_LARGE+1); + Status = UDFReallocTrackMap(Vcb, MAXIMUM_NUMBER_TRACKS_LARGE+1); - if (!NT_SUCCESS(RC)) { + if (!NT_SUCCESS(Status)) { BrutePoint(); - try_return(RC); + try_return(Status); } // find 1st and last session - RC = UDFPhSendIOCTL(IOCTL_CDROM_GET_LAST_SESSION, + Status = UDFPhSendIOCTL(IOCTL_CDROM_GET_LAST_SESSION, DeviceObject, NULL, 0, @@ -964,7 +609,18 @@ UDFDetermineVolumeLayout( TRUE, NULL); - if (NT_SUCCESS(RC)) { + if (NT_SUCCESS(Status) && + LastSes->FirstCompleteSession != LastSes->LastCompleteSession) { + + SwapCopyUchar4(SessionStartLba, &LastSes->TrackData[0].Address); + + // Validate: SessionStartLba must be greater than SessionEndLba + + if (*SessionEndLba <= *SessionStartLba) { + + *SessionStartLba = 0; + *SessionEndLba = 0; + } TrkNum = LastSes->TrackData[0].TrackNumber; @@ -989,7 +645,7 @@ UDFDetermineVolumeLayout( TrkNum != TOC_LastTrack_ID) { UDFPrint(("UDFUseStandard: Array out of bounds\n")); BrutePoint(); - try_return(RC = STATUS_SUCCESS); + try_return(Status = STATUS_SUCCESS); } UDFPrint(("Track N %d (0x%x) first LBA %ld (%lx) \n",TrkNum,TrkNum, MSF_TO_LBA(TempMSF[1],TempMSF[2],TempMSF[3]), @@ -1041,12 +697,12 @@ UDFDetermineVolumeLayout( } TrkNum = Vcb->LastTrackNum; - RC = STATUS_SUCCESS; + Status = STATUS_SUCCESS; // find last _valid_ track for(;TrkNum;TrkNum--) { if ((Vcb->TrackMap[TrkNum].DataParam != TrkInfo_Dat_unknown) && (Vcb->TrackMap[TrkNum].TrackParam != TrkInfo_Trk_unknown)) { - RC = STATUS_UNSUCCESSFUL; + Status = STATUS_UNSUCCESSFUL; Vcb->LastTrackNum = TrkNum; break; } @@ -1054,7 +710,7 @@ UDFDetermineVolumeLayout( // no valid tracks... if (!TrkNum) { UDFPrint(("UDFUseStandard: no valid tracks...\n")); - try_return(RC = STATUS_UNRECOGNIZED_VOLUME); + try_return(Status = STATUS_UNRECOGNIZED_VOLUME); } i = 0; @@ -1068,12 +724,12 @@ UDFDetermineVolumeLayout( return STATUS_INSUFFICIENT_RESOURCES; } - while(!NT_SUCCESS(RC) && (i<8)) { - RC = UDFPhReadSynchronous(IrpContext, Vcb->TargetDeviceObject, TempBuffer, Vcb->SectorSize, + while(!NT_SUCCESS(Status) && (i<8)) { + Status = UDFPhReadSynchronous(IrpContext, Vcb->TargetDeviceObject, TempBuffer, Vcb->SectorSize, ((uint64)(Vcb->TrackMap[TrkNum].LastLba-i)) << Vcb->SectorShift, &ReadBytes, PH_TMP_BUFFER); i++; } - if (NT_SUCCESS(RC)) { + if (NT_SUCCESS(Status)) { Vcb->LastLBA = Vcb->TrackMap[TrkNum].LastLba-i+1; /* if (i) { Vcb->TrackMap[TrkNum].PacketSize = PACKETSIZE_UDF; @@ -1089,20 +745,20 @@ UDFDetermineVolumeLayout( len = Vcb->TrackMap[TrkNum].LastLba - Vcb->TrackMap[TrkNum].FirstLba + 1; len = (uint32)(((int64)len*PACKETSIZE_UDF) / (PACKETSIZE_UDF+7)); - while(!NT_SUCCESS(RC) && (i<9)) { - RC = UDFPhReadSynchronous(IrpContext, Vcb->TargetDeviceObject, TempBuffer, Vcb->SectorSize, + while(!NT_SUCCESS(Status) && (i<9)) { + Status = UDFPhReadSynchronous(IrpContext, Vcb->TargetDeviceObject, TempBuffer, Vcb->SectorSize, ((uint64)(Vcb->TrackMap[TrkNum].FirstLba-i+len)) << Vcb->SectorShift, &ReadBytes, PH_TMP_BUFFER); i++; } - if (NT_SUCCESS(RC)) { + if (NT_SUCCESS(Status)) { Vcb->LastLBA = Vcb->TrackMap[TrkNum].LastLba = Vcb->TrackMap[TrkNum].FirstLba-i+len+1; Vcb->TrackMap[TrkNum].PacketSize = PACKETSIZE_UDF; // Vcb->TrackMap[TrkNum].; } else - if (RC == STATUS_INVALID_DEVICE_REQUEST) { + if (Status == STATUS_INVALID_DEVICE_REQUEST) { // wrap return code from Audio-disk - RC = STATUS_SUCCESS; + Status = STATUS_SUCCESS; } } @@ -1121,7 +777,7 @@ try_exit: NOTHING; if (TempBuffer) MyFreePool__(TempBuffer); } _SEH2_END; - return RC; + return Status; } // end UDFUseStandard() /* @@ -1143,7 +799,7 @@ UDFGetBlockSize( 0,NULL, &DiskGeometryEx,sizeof(DISK_GEOMETRY_EX), TRUE,NULL ); - Vcb->SectorSize = (NT_SUCCESS(RC)) ? DiskGeometryEx.Geometry.BytesPerSector : 512; + if (!NT_SUCCESS(RC)) try_return(RC); RC = UDFPhSendIOCTL(IOCTL_DISK_GET_PARTITION_INFO,DeviceObject, @@ -1171,8 +827,6 @@ UDFGetBlockSize( UserPrint((" busy (0)\n")); try_return(RC); } - - Vcb->SectorSize = (NT_SUCCESS(RC)) ? DiskGeometryEx.Geometry.BytesPerSector : 2048; } if ( @@ -1191,7 +845,8 @@ UDFGetBlockSize( ASSERT(FALSE); } } else { - ASSERT(FALSE); + + try_return(RC = STATUS_UNRECOGNIZED_VOLUME); } Vcb->LastPossibleLBA = Vcb->LastLBA; } @@ -1265,6 +920,9 @@ UDFGetDiskInfo( try_return(RC); } + Vcb->SessionStartLba = SessionStart; + Vcb->SessionEndLba = SessionEnd; + try_exit: NOTHING; } _SEH2_FINALLY { @@ -1297,10 +955,6 @@ try_exit: NOTHING; if (!(Vcb->LastPossibleLBA >> i)) break; } - if (i > 20) { - Vcb->WCacheBlocksPerFrameSh = max(Vcb->WCacheBlocksPerFrameSh, (2*i)/5+2); - Vcb->WCacheBlocksPerFrameSh = min(Vcb->WCacheBlocksPerFrameSh, 16); - } if (Vcb->VcbState & VCB_STATE_VOLUME_READ_ONLY) { if (!Vcb->BlankCD && Vcb->MediaType != MediaType_UnknownSize_CDRW) { @@ -1349,9 +1003,6 @@ UDFPrepareForReadOperation( return STATUS_SUCCESS; } uint32 i = Vcb->LastReadTrack; - PUCHAR tmp; - NTSTATUS RC; - SIZE_T ReadBytes; #ifdef _UDF_STRUCTURES_H_ if (Vcb->BSBM_Bitmap) { @@ -1367,52 +1018,6 @@ UDFPrepareForReadOperation( } #endif //_UDF_STRUCTURES_H_ - if (UDFIsDvdMedia(Vcb)) - return STATUS_SUCCESS; - - if (Vcb->LastReadTrack && - ((Vcb->TrackMap[i].FirstLba <= Lba) || (Vcb->TrackMap[i].FirstLba & 0x80000000)) && - (Vcb->TrackMap[i].LastLba >= Lba)) { -check_for_data_track: - // check track mode (Mode1/XA) - switch((Vcb->TrackMap[i].DataParam & TrkInfo_Dat_Mask)) { - case TrkInfo_Dat_Mode1: // Mode1 - case TrkInfo_Dat_XA: // XA Mode2 - case TrkInfo_Dat_Unknown: // for some stupid irons - break; - default: - Vcb->IncrementalSeekState = INCREMENTAL_SEEK_NONE; - return STATUS_INVALID_PARAMETER; - } - } else { - for(i=Vcb->FirstTrackNum; i<=Vcb->LastTrackNum; i++) { - if (((Vcb->TrackMap[i].FirstLba > Lba) && !(Vcb->TrackMap[i].FirstLba & 0x80000000)) || - (Vcb->TrackMap[i].LastLba < Lba)) - continue; - Vcb->LastReadTrack = i; - goto check_for_data_track; - } - Vcb->LastReadTrack = 0; - } - if (Vcb->IncrementalSeekState != INCREMENTAL_SEEK_WORKAROUND) { - Vcb->IncrementalSeekState = INCREMENTAL_SEEK_NONE; - return STATUS_SUCCESS; - } - UDFPrint((" UDFPrepareForReadOperation: seek workaround...\n")); - Vcb->IncrementalSeekState = INCREMENTAL_SEEK_DONE; - - tmp = (PUCHAR)DbgAllocatePoolWithTag(NonPagedPool, Vcb->SectorSize, 'bNWD'); - if (!tmp) { - Vcb->IncrementalSeekState = INCREMENTAL_SEEK_NONE; - return STATUS_INSUFFICIENT_RESOURCES; - } - for(i=0x1000; i<=Lba; i+=0x1000) { - RC = UDFPhReadSynchronous(IrpContext, Vcb->TargetDeviceObject, tmp, Vcb->SectorSize, - ((uint64)UDFFixFPAddress(Vcb,i)) << Vcb->SectorShift, &ReadBytes, 0); - UDFPrint((" seek workaround, LBA %x, status %x\n", i, RC)); - } - DbgFreePool(tmp); - return STATUS_SUCCESS; } // end UDFPrepareForReadOperation() @@ -1428,12 +1033,9 @@ UDFReadSectors( IN uint32 BCount, IN BOOLEAN Direct, OUT int8* Buffer, - OUT PSIZE_T ReadBytes + OUT PULONG ReadBytes ) { - if (Vcb->FastCache.ReadProc && (KeGetCurrentIrql() < DISPATCH_LEVEL)) { - return WCacheReadBlocks__(IrpContext, &Vcb->FastCache, Vcb, Buffer, Lba, BCount, ReadBytes, Direct); - } return UDFTRead(IrpContext, Vcb, Buffer, BCount*Vcb->SectorSize, Lba, ReadBytes); } // end UDFReadSectors() @@ -1450,34 +1052,29 @@ UDFReadInSector( IN uint32 l, // transfer length IN BOOLEAN Direct, // Disable access to non-cached data OUT int8* Buffer, - OUT PSIZE_T ReadBytes + OUT PULONG ReadBytes ) { int8* tmp_buff; NTSTATUS status; - SIZE_T _ReadBytes; + ULONG _ReadBytes; (*ReadBytes) = 0; - if (Vcb->FastCache.ReadProc && (KeGetCurrentIrql() < DISPATCH_LEVEL)) { - status = WCacheDirect__(IrpContext, &Vcb->FastCache, Vcb, Lba, FALSE, &tmp_buff, Direct); - if (NT_SUCCESS(status)) { - (*ReadBytes) += l; - RtlCopyMemory(Buffer, tmp_buff+i, l); - } - if (!Direct) WCacheEODirect__(&Vcb->FastCache, Vcb); - } else { - if (Direct) { - return STATUS_INVALID_PARAMETER; - } - tmp_buff = (int8*)MyAllocatePool__(NonPagedPool, Vcb->SectorSize); - if (!tmp_buff) return STATUS_INSUFFICIENT_RESOURCES; - status = UDFReadSectors(IrpContext, Vcb, Translate, Lba, 1, FALSE, tmp_buff, &_ReadBytes); - if (NT_SUCCESS(status)) { - (*ReadBytes) += l; - RtlCopyMemory(Buffer, tmp_buff+i, l); - } - MyFreePool__(tmp_buff); + + if (Direct) { + + return STATUS_INVALID_PARAMETER; } + + tmp_buff = (int8*)MyAllocatePool__(NonPagedPool, Vcb->SectorSize); + if (!tmp_buff) return STATUS_INSUFFICIENT_RESOURCES; + status = UDFReadSectors(IrpContext, Vcb, Translate, Lba, 1, FALSE, tmp_buff, &_ReadBytes); + if (NT_SUCCESS(status)) { + (*ReadBytes) += l; + RtlCopyMemory(Buffer, tmp_buff+i, l); + } + MyFreePool__(tmp_buff); + return status; } // end UDFReadInSector() @@ -1493,14 +1090,13 @@ UDFReadData( IN uint32 Length, IN BOOLEAN Direct, // Disable access to non-cached data OUT int8* Buffer, - OUT PSIZE_T ReadBytes + OUT PULONG ReadBytes ) { uint32 i, l, Lba, BS=Vcb->SectorSize; uint32 BSh=Vcb->SectorShift; NTSTATUS status; - SIZE_T _ReadBytes = 0; - Vcb->VcbState |= UDF_VCB_SKIP_EJECT_CHECK; + ULONG _ReadBytes = 0; uint32 to_read; (*ReadBytes) = 0; @@ -1571,13 +1167,6 @@ UDFWriteSectors( Vcb->LastLBA = Lba+BCount-1; } - if (Vcb->FastCache.WriteProc && (KeGetCurrentIrql() < DISPATCH_LEVEL)) { - status = WCacheWriteBlocks__(IrpContext, &Vcb->FastCache, Vcb, Buffer, Lba, BCount, WrittenBytes, Direct); - ASSERT(NT_SUCCESS(status)); - - return status; - } - status = UDFTWrite(IrpContext, Vcb, Buffer, BCount<SectorShift, Lba, WrittenBytes); ASSERT(NT_SUCCESS(status)); @@ -1600,7 +1189,7 @@ UDFWriteInSector( int8* tmp_buff; NTSTATUS status; SIZE_T _WrittenBytes; - SIZE_T ReadBytes; + ULONG ReadBytes; if (!Vcb->Modified) { UDFSetModified(Vcb); @@ -1615,38 +1204,28 @@ UDFWriteInSector( (*WrittenBytes) = 0; - if (Vcb->FastCache.WriteProc && (KeGetCurrentIrql() < DISPATCH_LEVEL)) { - - status = WCacheDirect__(IrpContext, &Vcb->FastCache, Vcb, Lba, TRUE, &tmp_buff, Direct); - if (NT_SUCCESS(status)) { - - (*WrittenBytes) += l; - RtlCopyMemory(tmp_buff+i, Buffer, l); - } - if (!Direct) WCacheEODirect__(&(Vcb->FastCache), Vcb); - } else { - // If Direct = TRUE we should never get here, but... - if (Direct) { - BrutePoint(); - return STATUS_INVALID_PARAMETER; - } - tmp_buff = (int8*)MyAllocatePool__(NonPagedPool, Vcb->SectorSize); - if (!tmp_buff) { - BrutePoint(); - return STATUS_INSUFFICIENT_RESOURCES; - } - // read packet - status = UDFReadSectors(IrpContext, Vcb, Translate, Lba, 1, FALSE, tmp_buff, &ReadBytes); - if (!NT_SUCCESS(status)) goto EO_WrSctD; - // modify packet - RtlCopyMemory(tmp_buff+i, Buffer, l); - // write modified packet - status = UDFWriteSectors(IrpContext, Vcb, Translate, Lba, 1, FALSE, tmp_buff, &_WrittenBytes); - if (NT_SUCCESS(status)) - (*WrittenBytes) += l; -EO_WrSctD: - MyFreePool__(tmp_buff); + // If Direct = TRUE we should never get here, but... + if (Direct) { + BrutePoint(); + return STATUS_INVALID_PARAMETER; + } + tmp_buff = (int8*)MyAllocatePool__(NonPagedPool, Vcb->SectorSize); + if (!tmp_buff) { + BrutePoint(); + return STATUS_INSUFFICIENT_RESOURCES; } + // read packet + status = UDFReadSectors(IrpContext, Vcb, Translate, Lba, 1, FALSE, tmp_buff, &ReadBytes); + if (!NT_SUCCESS(status)) goto EO_WrSctD; + // modify packet + RtlCopyMemory(tmp_buff+i, Buffer, l); + // write modified packet + status = UDFWriteSectors(IrpContext, Vcb, Translate, Lba, 1, FALSE, tmp_buff, &_WrittenBytes); + if (NT_SUCCESS(status)) + (*WrittenBytes) += l; +EO_WrSctD: + MyFreePool__(tmp_buff); + ASSERT(NT_SUCCESS(status)); if (!NT_SUCCESS(status)) { UDFPrint(("UDFWriteInSector() for LBA %x failed\n", Lba)); @@ -1675,7 +1254,6 @@ UDFWriteData( uint32 BSh=Vcb->SectorShift; NTSTATUS status; SIZE_T _WrittenBytes; - Vcb->VcbState |= UDF_VCB_SKIP_EJECT_CHECK; (*WrittenBytes) = 0; if (!Length) return STATUS_SUCCESS; diff --git a/drivers/filesystems/udfs/Include/phys_lib.h b/drivers/filesystems/udfs/Include/phys_lib.h index ce71d63482975..747b95450acf7 100644 --- a/drivers/filesystems/udfs/Include/phys_lib.h +++ b/drivers/filesystems/udfs/Include/phys_lib.h @@ -7,46 +7,6 @@ #ifndef __UDF_PHYS_LIB__H__ #define __UDF_PHYS_LIB__H__ -#ifndef UDF_FORMAT_MEDIA -extern BOOLEAN open_as_device; -extern BOOLEAN opt_invalidate_volume; -extern ULONG LockMode; -#endif //UDF_FORMAT_MEDIA - -NTSTATUS -__fastcall -UDFTIOVerify( - IN PIRP_CONTEXT IrpContext, - IN void* _Vcb, - IN void* Buffer, // Target buffer - IN SIZE_T Length, - IN uint32 LBA, - OUT PSIZE_T IOBytes, - IN uint32 Flags - ); - -extern NTSTATUS -UDFTWriteVerify( - IN PIRP_CONTEXT IrpContext, - IN void* _Vcb, - IN void* Buffer, // Target buffer - IN SIZE_T Length, - IN uint32 LBA, - OUT PSIZE_T WrittenBytes, - IN uint32 Flags - ); - -NTSTATUS -UDFTReadVerify( - IN PIRP_CONTEXT IrpContext, - IN void* _Vcb, - IN void* Buffer, // Target buffer - IN SIZE_T Length, - IN uint32 LBA, - OUT PSIZE_T ReadBytes, - IN uint32 Flags - ); - NTSTATUS UDFTRead( PIRP_CONTEXT IrpContext, @@ -54,7 +14,7 @@ UDFTRead( PVOID Buffer, // Target buffer SIZE_T Length, ULONG LBA, - PSIZE_T ReadBytes, + PULONG ReadBytes, ULONG Flags = 0 ); @@ -70,7 +30,6 @@ UDFTWrite( ); #define PH_TMP_BUFFER 1 -#define PH_VCB_IN_RETLEN 2 #define PH_LOCK_CACHE 0x10000000 #define PH_EX_WRITE 0x80000000 @@ -121,7 +80,7 @@ UDFReadSectors( IN ULONG BCount, IN BOOLEAN Direct, OUT PCHAR Buffer, - OUT PSIZE_T ReadBytes + OUT PULONG ReadBytes ); // read data inside physical sector @@ -135,7 +94,7 @@ UDFReadInSector( IN ULONG l, // transfer length IN BOOLEAN Direct, OUT PCHAR Buffer, - OUT PSIZE_T ReadBytes + OUT PULONG ReadBytes ); // read unaligned data @@ -148,7 +107,7 @@ UDFReadData( IN ULONG Length, IN BOOLEAN Direct, OUT PCHAR Buffer, - OUT PSIZE_T ReadBytes + OUT PULONG ReadBytes ); // write physical sectors @@ -187,23 +146,10 @@ UDFWriteData( OUT PSIZE_T WrittenBytes ); -NTSTATUS UDFResetDeviceDriver(IN PVCB Vcb, - IN PDEVICE_OBJECT TargetDeviceObject, - IN BOOLEAN Unlock); - // This macro copies an unaligned src longword to a dst longword, // performing an little/big endian swap. -typedef union _UCHAR1 { - UCHAR Uchar[1]; - UCHAR ForceAlignment; -} UCHAR1, *PUCHAR1; - -#define SwapCopyUchar4(Dst,Src) { \ - *((UNALIGNED UCHAR1 *)(Dst)) = *((UNALIGNED UCHAR1 *)(Src) + 3); \ - *((UNALIGNED UCHAR1 *)(Dst) + 1) = *((UNALIGNED UCHAR1 *)(Src) + 2); \ - *((UNALIGNED UCHAR1 *)(Dst) + 2) = *((UNALIGNED UCHAR1 *)(Src) + 1); \ - *((UNALIGNED UCHAR1 *)(Dst) + 3) = *((UNALIGNED UCHAR1 *)(Src)); \ -} +#define SwapCopyUchar4(Dst, Src) \ + (*(UNALIGNED ULONG*)(Dst) = _byteswap_ulong(*(UNALIGNED ULONG*)(Src))) #endif //__UDF_PHYS_LIB__H__ diff --git a/drivers/filesystems/udfs/Include/udf_reg.h b/drivers/filesystems/udfs/Include/udf_reg.h index 88f6cbffc0472..68d3ac3034da8 100644 --- a/drivers/filesystems/udfs/Include/udf_reg.h +++ b/drivers/filesystems/udfs/Include/udf_reg.h @@ -7,9 +7,6 @@ #ifndef __DWUDF_REGISTRY__H__ #define __DWUDF_REGISTRY__H__ -#define REG_DEFAULT_UNKNOWN L"_Default\\Unknown" -#define REG_NAMELESS_DEV L"\\_Nameless_" - #define UDF_FS_TITLE_BLANK L"Blank media" #define UDF_BLANK_VOLUME_LABEL L"Blank CD" #define REG_DEFALLOCMODE_NAME L"DefaultAllocMode" @@ -20,7 +17,6 @@ #define UDF_TREE_FLUSH_PERIOD_NAME L"DirTreeFlushPeriod" #define UDF_NO_UPDATE_PERIOD_NAME L"MaxNoUpdatePeriod" #define UDF_SPARSE_THRESHOLD_NAME L"SparseThreshold" -#define UDF_VERIFY_ON_WRITE_NAME L"VerifyOnWrite" #define UDF_UPDATE_TIMES_ATTR L"UpdateFileTimesAttrChg" #define UDF_UPDATE_TIMES_MOD L"UpdateFileTimesLastWrite" #define UDF_UPDATE_TIMES_ACCS L"UpdateFileTimesLastAccess" @@ -34,7 +30,6 @@ #define UDF_INSTANT_COMPAT_ALLOC_DESCS L"AllocDescCompatInstantBurner" #define UDF_HANDLE_HW_RO L"HandleHWReadOnly" #define UDF_HANDLE_SOFT_RO L"HandleSoftReadOnly" -#define UDF_CACHE_SIZE_MULTIPLIER L"WCacheSizeMultiplier" #define UDF_IGNORE_SEQUENTIAL_IO L"IgnoreSequantialIo" #define UDF_NO_SPARE_BEHAVIOR L"NoFreeRelocationSpaceVolumeAction" #define UDF_DIRTY_VOLUME_BEHAVIOR L"DirtyVolumeVolumeAction" diff --git a/drivers/filesystems/udfs/Include/wcache_lib.cpp b/drivers/filesystems/udfs/Include/wcache_lib.cpp deleted file mode 100644 index 404b0c98b4e31..0000000000000 --- a/drivers/filesystems/udfs/Include/wcache_lib.cpp +++ /dev/null @@ -1,3685 +0,0 @@ -//////////////////////////////////////////////////////////////////// -// Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine -// All rights reserved -// This file was released under the GPLv2 on June 2015. -//////////////////////////////////////////////////////////////////// - -/*********************************************************************/ - -NTSTATUS -__fastcall -WCacheCheckLimits( - IN PIRP_CONTEXT IrpContext, - IN PW_CACHE Cache, - IN PVOID Context, - IN lba_t ReqLba, - IN ULONG BCount - ); - -NTSTATUS -__fastcall -WCacheCheckLimitsRAM( - IN PIRP_CONTEXT IrpContext, - IN PW_CACHE Cache, - IN PVOID Context, - IN lba_t ReqLba, - IN ULONG BCount - ); - -NTSTATUS -__fastcall -WCacheCheckLimitsRW( - IN PIRP_CONTEXT IrpContext, - IN PW_CACHE Cache, - IN PVOID Context, - IN lba_t ReqLba, - IN ULONG BCount - ); - -NTSTATUS -__fastcall -WCacheCheckLimitsR( - IN PIRP_CONTEXT IrpContext, - IN PW_CACHE Cache, - IN PVOID Context, - IN lba_t ReqLba, - IN ULONG BCount - ); - -VOID -__fastcall -WCachePurgeAllRW( - IN PIRP_CONTEXT IrpContext, - IN PW_CACHE Cache, - IN PVOID Context - ); - -VOID -__fastcall -WCacheFlushAllRW( - IN PIRP_CONTEXT IrpContext, - IN PW_CACHE Cache, - IN PVOID Context - ); - -VOID -__fastcall -WCachePurgeAllR( - IN PIRP_CONTEXT IrpContext, - IN PW_CACHE Cache, - IN PVOID Context - ); - -NTSTATUS __fastcall WCacheDecodeFlags(IN PW_CACHE Cache, - IN ULONG Flags); - -#define ASYNC_STATE_NONE 0 -#define ASYNC_STATE_READ_PRE 1 -#define ASYNC_STATE_READ 2 -#define ASYNC_STATE_WRITE_PRE 3 -#define ASYNC_STATE_WRITE 4 -#define ASYNC_STATE_DONE 5 - -#define ASYNC_CMD_NONE 0 -#define ASYNC_CMD_READ 1 -#define ASYNC_CMD_UPDATE 2 - -#define WCACHE_MAX_CHAIN (0x10) - -#define MEM_WCCTX_TAG 'xtCW' -#define MEM_WCFRM_TAG 'rfCW' -#define MEM_WCBUF_TAG 'fbCW' - -#define USE_WC_PRINT - -#ifdef USE_WC_PRINT - #define WcPrint UDFPrint -#else - #define WcPrint(x) {;} -#endif - -typedef struct _W_CACHE_ASYNC { - UDF_PH_CALL_CONTEXT PhContext; - ULONG State; - ULONG Cmd; - PW_CACHE Cache; - PVOID Buffer; - PVOID Buffer2; - SIZE_T TransferredBytes; - ULONG BCount; - lba_t Lba; - struct _W_CACHE_ASYNC* NextWContext; - struct _W_CACHE_ASYNC* PrevWContext; -} W_CACHE_ASYNC, *PW_CACHE_ASYNC; - -VOID -WCacheUpdatePacketComplete( - IN PIRP_CONTEXT IrpContext, - IN PW_CACHE Cache, // pointer to the Cache Control structure - IN PVOID Context, // user-supplied context for IO callbacks - IN OUT PW_CACHE_ASYNC* FirstWContext, // pointer to head async IO context - IN OUT PW_CACHE_ASYNC* PrevWContext, // pointer to tail async IO context - IN BOOLEAN FreePacket = TRUE - ); - -BOOLEAN -ValidateFrameBlocksList( - IN PW_CACHE Cache, - IN lba_t Lba); - -/*********************************************************************/ -ULONG WCache_random; - -/* - WCacheInit__() fills all necesary fileds in passed in PW_CACHE Cache - structure, allocates memory and synchronization resources. - Cacheable area is subdiveded on Frames - contiguous sets of blocks. - Internally each Frame is an array of pointers and attributes of cached - Blocks. To optimize memory usage WCache keeps in memory limited number - of frames (MaxFrames). - Frame length (number of Blocks) must be be a power of 2 and aligned on - minimum writeable block size - Packet. - Packet size must be a power of 2 (2, 4, 8, 16, etc.). - Each cached Block belongs to one of the Frames. To optimize memory usage - WCache keeps in memory limited number of Blocks (MaxBlocks). Block size - must be a power of 2. - WCache splits low-level request(s) into some parts if requested data length - exceeds MaxBytesToRead. - If requested data length exceeds maximum cache size WCache makes - recursive calls to read/write routines with shorter requests - - WCacheInit__() returns initialization status. If initialization failed, - all allocated memory and resources are automaticelly freed. - - Public routine - */ -NTSTATUS -WCacheInit__( - IN PW_CACHE Cache, // pointer to the Cache Control structure to be initialized - IN ULONG MaxFrames, // maximum number of Frames to be kept in memory - // simultaneously - IN ULONG MaxBlocks, // maximum number of Blocks to be kept in memory - // simultaneously - IN SIZE_T MaxBytesToRead, // maximum IO length (split boundary) - IN ULONG PacketSizeSh, // number of blocks in packet (bit shift) - // Packes size = 2^PacketSizeSh - IN ULONG BlockSizeSh, // Block size (bit shift) - // Block size = 2^BlockSizeSh - IN ULONG BlocksPerFrameSh,// number of blocks in Frame (bit shift) - // Frame size = 2^BlocksPerFrameSh - IN lba_t FirstLba, // Logical Block Address (LBA) of the 1st block - // in cacheable area - IN lba_t LastLba, // Logical Block Address (LBA) of the last block - // in cacheable area - IN ULONG Mode, // media mode: - // WCACHE_MODE_ROM - // WCACHE_MODE_RW - // WCACHE_MODE_R - // WCACHE_MODE_RAM - // the following modes are planned to be implemented: - // WCACHE_MODE_EWR - IN ULONG Flags, // cache mode flags: - // WCACHE_CACHE_WHOLE_PACKET - // read long (Packet-sized) blocks of - // data from media - IN ULONG FramesToKeepFree, - // number of Frames to be flushed & purged from cache - // when Frame counter reaches top-limit and allocation - // of a new Frame required - IN PWRITE_BLOCK WriteProc, - // pointer to synchronous physical write call-back routine - IN PREAD_BLOCK ReadProc, - // pointer to synchronous physical read call-back routine - IN PWRITE_BLOCK_ASYNC WriteProcAsync, - // pointer to _asynchronous_ physical write call-back routine - // currently must be set to NULL because async support - // is not completly implemented - IN PREAD_BLOCK_ASYNC ReadProcAsync, - // pointer to _asynchronous_ physical read call-back routine - // must be set to NULL (see above) - IN PCHECK_BLOCK CheckUsedProc, - // pointer to call-back routine that checks whether the Block - // specified (by LBA) is allocated for some data or should - // be treated as unused (and thus, zero-filled). - // Is used to avoid physical reads and writes from/to such Blocks - IN PUPDATE_RELOC UpdateRelocProc, - // pointer to call-back routine that updates caller's - // relocation table _after_ physical write (append) in WORM - // (WCACHE_MODE_R) mode. WCache sends original and new - // (derived from last LBA) logical addresses to this routine - IN PWC_ERROR_HANDLER ErrorHandlerProc - ) -{ - ULONG l1, l2, l3; - ULONG PacketSize = (1) << PacketSizeSh; - ULONG BlockSize = (1) << BlockSizeSh; - ULONG BlocksPerFrame = (1) << BlocksPerFrameSh; - NTSTATUS RC = STATUS_SUCCESS; - LARGE_INTEGER rseed; - ULONG res_init_flags = 0; - -#define WCLOCK_RES 1 - - _SEH2_TRY { - // check input parameters - if (Mode == WCACHE_MODE_R) { - UDFPrint(("Disable Async-Write for WORM media\n")); - WriteProcAsync = NULL; - } - if ((MaxBlocks % PacketSize) || !MaxBlocks) { - UDFPrint(("Total number of sectors must be packet-size-aligned\n")); - try_return(RC = STATUS_INVALID_PARAMETER); - } - if (BlocksPerFrame % PacketSize) { - UDFPrint(("Number of sectors per Frame must be packet-size-aligned\n")); - try_return(RC = STATUS_INVALID_PARAMETER); - } - if (!ReadProc) { - UDFPrint(("Read routine pointer must be valid\n")); - try_return(RC = STATUS_INVALID_PARAMETER); - } - if (FirstLba >= LastLba) { - UDFPrint(("Invalid cached area parameters: (%x - %x)\n",FirstLba, LastLba)); - try_return(RC = STATUS_INVALID_PARAMETER); - } - if (!MaxFrames) { - UDFPrint(("Total frame number must be non-zero\n",FirstLba, LastLba)); - try_return(RC = STATUS_INVALID_PARAMETER); - } - if (Mode > WCACHE_MODE_MAX) { - UDFPrint(("Invalid media mode. Should be 0-%x\n",WCACHE_MODE_MAX)); - try_return(RC = STATUS_INVALID_PARAMETER); - } - if (FramesToKeepFree >= MaxFrames/2) { - UDFPrint(("Invalid FramesToKeepFree (%x). Should be Less or equal to MaxFrames/2 (%x)\n", FramesToKeepFree, MaxFrames/2)); - try_return(RC = STATUS_INVALID_PARAMETER); - } - // check 'features' - if (!WriteProc) { - UDFPrint(("Write routine not specified\n")); - UDFPrint(("Read-only mode enabled\n")); - } - MaxBlocks = max(MaxBlocks, BlocksPerFrame*3); - // initialize required structures - // we'll align structure size on system page size to - // avoid system crashes caused by pool fragmentation - if (!(Cache->FrameList = - (PW_CACHE_FRAME)MyAllocatePoolTag__(NonPagedPool, l1 = (((LastLba >> BlocksPerFrameSh)+1)*sizeof(W_CACHE_FRAME)), MEM_WCFRM_TAG) )) { - UDFPrint(("Cache init err 1\n")); - try_return(RC = STATUS_INSUFFICIENT_RESOURCES); - } - if (!(Cache->CachedBlocksList = - (PULONG)MyAllocatePoolTag__(NonPagedPool, l2 = ((MaxBlocks+2)*sizeof(lba_t)), MEM_WCFRM_TAG) )) { - UDFPrint(("Cache init err 2\n")); - try_return(RC = STATUS_INSUFFICIENT_RESOURCES); - } - if (!(Cache->CachedModifiedBlocksList = - (PULONG)MyAllocatePoolTag__(NonPagedPool, l2, MEM_WCFRM_TAG) )) { - UDFPrint(("Cache init err 3\n")); - try_return(RC = STATUS_INSUFFICIENT_RESOURCES); - } - if (!(Cache->CachedFramesList = - (PULONG)MyAllocatePoolTag__(NonPagedPool, l3 = ((MaxFrames+2)*sizeof(lba_t)), MEM_WCFRM_TAG) )) { - UDFPrint(("Cache init err 4\n")); - try_return(RC = STATUS_INSUFFICIENT_RESOURCES); - } - RtlZeroMemory(Cache->FrameList, l1); - RtlZeroMemory(Cache->CachedBlocksList, l2); - RtlZeroMemory(Cache->CachedModifiedBlocksList, l2); - RtlZeroMemory(Cache->CachedFramesList, l3); - // remember all useful parameters - Cache->BlocksPerFrame = BlocksPerFrame; - Cache->BlocksPerFrameSh = BlocksPerFrameSh; - Cache->BlockCount = 0; - Cache->MaxBlocks = MaxBlocks; - Cache->MaxBytesToRead = MaxBytesToRead; - Cache->FrameCount = 0; - Cache->MaxFrames = MaxFrames; - Cache->PacketSize = PacketSize; - Cache->PacketSizeSh = PacketSizeSh; - Cache->BlockSize = BlockSize; - Cache->BlockSizeSh = BlockSizeSh; - Cache->WriteCount = 0; - Cache->FirstLba = FirstLba; - Cache->LastLba = LastLba; - Cache->Mode = Mode; - - if (!NT_SUCCESS(RC = WCacheDecodeFlags(Cache, Flags))) { - return RC; - } - - Cache->FramesToKeepFree = FramesToKeepFree; - Cache->WriteProc = WriteProc; - Cache->ReadProc = ReadProc; - Cache->WriteProcAsync = WriteProcAsync; - Cache->ReadProcAsync = ReadProcAsync; - Cache->CheckUsedProc = CheckUsedProc; - Cache->UpdateRelocProc = UpdateRelocProc; - Cache->ErrorHandlerProc = ErrorHandlerProc; - // init permanent tmp buffers - if (!(Cache->tmp_buff = - (PCHAR)MyAllocatePoolTag__(NonPagedPool, PacketSize*BlockSize, MEM_WCFRM_TAG))) { - UDFPrint(("Cache init err 5.W\n")); - try_return(RC = STATUS_INSUFFICIENT_RESOURCES); - } - if (!(Cache->tmp_buff_r = - (PCHAR)MyAllocatePoolTag__(NonPagedPool, PacketSize*BlockSize, MEM_WCFRM_TAG))) { - UDFPrint(("Cache init err 5.R\n")); - try_return(RC = STATUS_INSUFFICIENT_RESOURCES); - } - if (!(Cache->reloc_tab = - (PULONG)MyAllocatePoolTag__(NonPagedPool, Cache->PacketSize*sizeof(ULONG), MEM_WCFRM_TAG))) { - UDFPrint(("Cache init err 6\n")); - try_return(RC = STATUS_INSUFFICIENT_RESOURCES); - } - if (!NT_SUCCESS(RC = ExInitializeResourceLite(&(Cache->WCacheLock)))) { - UDFPrint(("Cache init err (res)\n")); - try_return(RC); - } - res_init_flags |= WCLOCK_RES; - KeQuerySystemTime((PLARGE_INTEGER)(&rseed)); - WCache_random = rseed.LowPart; - -try_exit: NOTHING; - - } _SEH2_FINALLY { - - if (!NT_SUCCESS(RC)) { - if (res_init_flags & WCLOCK_RES) - ExDeleteResourceLite(&(Cache->WCacheLock)); - if (Cache->FrameList) - MyFreePool__(Cache->FrameList); - if (Cache->CachedBlocksList) - MyFreePool__(Cache->CachedBlocksList); - if (Cache->CachedModifiedBlocksList) - MyFreePool__(Cache->CachedModifiedBlocksList); - if (Cache->CachedFramesList) - MyFreePool__(Cache->CachedFramesList); - if (Cache->tmp_buff_r) - MyFreePool__(Cache->tmp_buff_r); - if (Cache->tmp_buff) - MyFreePool__(Cache->tmp_buff); - if (Cache->reloc_tab) - MyFreePool__(Cache->reloc_tab); - RtlZeroMemory(Cache, sizeof(W_CACHE)); - } else { - Cache->Tag = 0xCAC11E00; - } - - } _SEH2_END; - - return RC; -} // end WCacheInit__() - -/* - WCacheRandom() - just a random generator - Returns random LONGLONG number - Internal routine - */ -LONGLONG -WCacheRandom(VOID) -{ - WCache_random = (WCache_random * 0x8088405 + 1); - return WCache_random; -} // end WCacheRandom() - -/* - WCacheFindLbaToRelease() finds Block to be flushed and purged from cache - Returns random LBA - Internal routine - */ -lba_t -__fastcall -WCacheFindLbaToRelease( - IN PW_CACHE Cache - ) -{ - if (!(Cache->BlockCount)) - return WCACHE_INVALID_LBA; - return(Cache->CachedBlocksList[((ULONG)WCacheRandom() % Cache->BlockCount)]); -} // end WCacheFindLbaToRelease() - -/* - WCacheFindModifiedLbaToRelease() finds Block to be flushed and purged from cache. - This routine looks for Blocks among modified ones - Returns random LBA (nodified) - Internal routine - */ -lba_t -__fastcall -WCacheFindModifiedLbaToRelease( - IN PW_CACHE Cache - ) -{ - if (!(Cache->WriteCount)) - return WCACHE_INVALID_LBA; - return(Cache->CachedModifiedBlocksList[((ULONG)WCacheRandom() % Cache->WriteCount)]); -} // end WCacheFindModifiedLbaToRelease() - -/* - WCacheFindFrameToRelease() finds Frame to be flushed and purged with all - Blocks (from this Frame) from cache - Returns random Frame number - Internal routine - */ -lba_t -__fastcall -WCacheFindFrameToRelease( - IN PW_CACHE Cache - ) -{ - ULONG i, j; - ULONG frame = 0; - ULONG prev_uc = -1; - ULONG uc = -1; - lba_t lba; - BOOLEAN mod = FALSE; - - if (!(Cache->FrameCount)) - return 0; - /* - return(Cache->CachedFramesList[((ULONG)WCacheRandom() % Cache->FrameCount)]); - */ - - for(i=0; iFrameCount; i++) { - - j = Cache->CachedFramesList[i]; - - mod |= (Cache->FrameList[j].UpdateCount != 0); - uc = Cache->FrameList[j].UpdateCount*32 + Cache->FrameList[j].AccessCount; - - if (prev_uc > uc) { - prev_uc = uc; - frame = j; - } - } - if (!mod) { - frame = Cache->CachedFramesList[((ULONG)WCacheRandom() % Cache->FrameCount)]; - lba = frame << Cache->BlocksPerFrameSh; - WcPrint(("WC:-frm %x\n", lba)); - } else { - lba = frame << Cache->BlocksPerFrameSh; - WcPrint(("WC:-frm(mod) %x\n", lba)); - for(i=0; iFrameCount; i++) { - - j = Cache->CachedFramesList[i]; - Cache->FrameList[j].UpdateCount = (Cache->FrameList[j].UpdateCount*2)/3; - Cache->FrameList[j].AccessCount = (Cache->FrameList[j].AccessCount*3)/4; - } - } - return frame; -} // end WCacheFindFrameToRelease() - -/* - WCacheGetSortedListIndex() returns index of searched Lba - (Lba is ULONG in sorted array) or index of minimal cached Lba - greater than searched. - If requested Lba is less than minimum cached, 0 is returned. - If requested Lba is greater than maximum cached, BlockCount value - is returned. - Internal routine - */ - -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable:4035) // re-enable below -#endif - -__inline -ULONG -WCacheGetSortedListIndex( - IN ULONG BlockCount, // number of items in array (pointed by List) - IN lba_t* List, // pointer to sorted (ASC) array of ULONGs - IN lba_t Lba // ULONG value to be searched for - ) -{ - if (!BlockCount) - return 0; - - ULONG pos; - ULONG left; - ULONG right; - - if (!BlockCount) - return 0; - - left = 0; - right = BlockCount - 1; - pos = 0; - while(left != right) { - pos = (left + right) >> 1; - if (List[pos] == Lba) - return pos; - if (right - left == 1) { - if (List[pos+1] < Lba) - return (pos+2); - break; - } - if (List[pos] < Lba) { - left = pos; - } else { - right = pos; - } - } - if ((List[pos] < Lba) && ((pos+1) <= BlockCount)) pos++; - - return pos; -} - -#ifdef _MSC_VER -#pragma warning(pop) // re-enable warning #4035 -#endif - -/* - WCacheInsertRangeToList() inserts values laying in range described - by Lba (1st value) and BCount (number of sequentially incremented - values) in sorted array of ULONGs pointed by List. - Ex.: (Lba, BCount)=(7,3) will insert values {7,8,9}. - If target array already contains one or more values falling in - requested range, they will be removed before insertion. - WCacheInsertRangeToList() updates value of (*BlockCount) to reflect - performed changes. - WCacheInsertRangeToList() assumes that target array is of enough size. - Internal routine - */ -VOID -__fastcall -WCacheInsertRangeToList( - IN lba_t* List, // pointer to sorted (ASC) array of ULONGs - IN PULONG BlockCount, // pointer to number of items in array (pointed by List) - IN lba_t Lba, // initial value for insertion - IN ULONG BCount // number of sequentially incremented values to be inserted - ) -{ - if (!BCount) - return; - - ASSERT(!(BCount & 0x80000000)); - - ULONG firstPos = WCacheGetSortedListIndex(*BlockCount, List, Lba); - ULONG lastPos = WCacheGetSortedListIndex(*BlockCount, List, Lba+BCount); - ULONG offs = firstPos + BCount - lastPos; - - if (offs) { - // move list tail -// ASSERT(lastPos+offs + ((*BlockCount) - lastPos) <= qq); - if (*BlockCount) { -#ifdef WCACHE_BOUND_CHECKS - MyCheckArray(List, lastPos+offs+(*BlockCount)-lastPos-1); -#endif //WCACHE_BOUND_CHECKS - DbgMoveMemory(&(List[lastPos+offs]), &(List[lastPos]), ((*BlockCount) - lastPos) * sizeof(ULONG)); - } - lastPos += offs; - for(; firstPosFrameCount; -#endif //DBG - - // We are about to add new cache frame. - // Thus check if we have enough free entries and - // flush unused ones if it is neccessary. - if (Cache->FrameCount >= Cache->MaxFrames) { - BrutePoint(); - WCacheCheckLimits(IrpContext, Cache, Context, frame << Cache->BlocksPerFrameSh, Cache->PacketSize*2); - } - ASSERT(Cache->FrameCount < Cache->MaxFrames); - block_array = (PW_CACHE_ENTRY)MyAllocatePoolTag__(NonPagedPool, l = sizeof(W_CACHE_ENTRY) << Cache->BlocksPerFrameSh, MEM_WCFRM_TAG); - ASSERT(Cache->FrameList[frame].Frame == NULL); - Cache->FrameList[frame].Frame = block_array; - - // Keep history !!! - //Cache->FrameList[frame].UpdateCount = 0; - //Cache->FrameList[frame].AccessCount = 0; - - if (block_array) { - ASSERT((ULONG_PTR)block_array > 0x1000); - WCacheInsertItemToList(Cache->CachedFramesList, &(Cache->FrameCount), frame); - RtlZeroMemory(block_array, l); - } else { - BrutePoint(); - } - ASSERT(Cache->FrameCount <= Cache->MaxFrames); -#ifdef DBG - ASSERT(old_count < Cache->FrameCount); -#endif //DBG - return block_array; -} // end WCacheInitFrame() - -/* - WCacheRemoveFrame() frees storage for Frame (block_array) with - index 'frame' and removes it's index from sorted array of - frame indexes. - Internal routine - */ -VOID -__fastcall -WCacheRemoveFrame( - IN PW_CACHE Cache, // pointer to the Cache Control structure - IN PVOID Context, // user's context (currently unused) - IN ULONG frame // frame index - ) -{ - PW_CACHE_ENTRY block_array; -#ifdef DBG - ULONG old_count = Cache->FrameCount; -#endif //DBG - - ASSERT(Cache->FrameCount <= Cache->MaxFrames); - ASSERT(Cache->FrameList[frame].BlockCount == 0); - block_array = Cache->FrameList[frame].Frame; - - WCacheRemoveItemFromList(Cache->CachedFramesList, &(Cache->FrameCount), frame); - MyFreePool__(block_array); -// ASSERT(!(Cache->FrameList[frame].WriteCount)); -// ASSERT(!(Cache->FrameList[frame].WriteCount)); - Cache->FrameList[frame].Frame = NULL; - ASSERT(Cache->FrameCount < Cache->MaxFrames); -#ifdef DBG - ASSERT(old_count > Cache->FrameCount); -#endif //DBG - -} // end WCacheRemoveFrame() - -/* - WCacheSetModFlag() sets Modified flag for Block with offset 'i' - in Frame 'block_array' - Internal routine - */ -#define WCacheSetModFlag(block_array, i) \ - *((PULONG)&(block_array[i].Sector)) |= WCACHE_FLAG_MODIFIED - -/* - WCacheClrModFlag() clears Modified flag for Block with offset 'i' - in Frame 'block_array' - Internal routine - */ -#define WCacheClrModFlag(block_array, i) \ - *((PULONG)&(block_array[i].Sector)) &= ~WCACHE_FLAG_MODIFIED - -/* - WCacheGetModFlag() returns non-zero value if Modified flag for - Block with offset 'i' in Frame 'block_array' is set. Otherwise - 0 is returned. - Internal routine - */ -#define WCacheGetModFlag(block_array, i) \ - (*((PULONG)&(block_array[i].Sector)) & WCACHE_FLAG_MODIFIED) - -#if 0 -/* - WCacheSetBadFlag() sets Modified flag for Block with offset 'i' - in Frame 'block_array' - Internal routine - */ -#define WCacheSetBadFlag(block_array, i) \ - *((PULONG)&(block_array[i].Sector)) |= WCACHE_FLAG_BAD - -/* - WCacheClrBadFlag() clears Modified flag for Block with offset 'i' - in Frame 'block_array' - Internal routine - */ -#define WCacheClrBadFlag(block_array, i) \ - *((PULONG)&(block_array[i].Sector)) &= ~WCACHE_FLAG_BAD - -/* - WCacheGetBadFlag() returns non-zero value if Modified flag for - Block with offset 'i' in Frame 'block_array' is set. Otherwise - 0 is returned. - Internal routine - */ -#define WCacheGetBadFlag(block_array, i) \ - (((UCHAR)(block_array[i].Sector)) & WCACHE_FLAG_BAD) -#endif //0 - -/* - WCacheSectorAddr() returns pointer to memory block containing cached - data for Block described by Frame (block_array) and offset in this - Frame (i). If requested Block is not cached yet NULL is returned. - Internal routine - */ -#define WCacheSectorAddr(block_array, i) \ - ((ULONG_PTR)(block_array[i].Sector) & WCACHE_ADDR_MASK) - -/* - WCacheFreeSector() releases memory block containing cached - data for Block described by Frame (block_array) and offset in this - Frame (i). Should never be called for non-cached Blocks. - Internal routine - */ -#define WCacheFreeSector(frame, offs) \ -{ \ - DbgFreePool((PVOID)WCacheSectorAddr(block_array, offs)); \ - block_array[offs].Sector = NULL; \ - Cache->FrameList[frame].BlockCount--; \ -} - -/* - WCacheAllocAsyncEntry() allocates storage for async IO context, - links it to previously allocated async IO context (if any), - initializes synchronization (completion) event - and allocates temporary IO buffers. - Async IO contexts are used to create chained set of IO requests - durring top-level request precessing and wait for their completion. - Internal routine - */ -PW_CACHE_ASYNC -WCacheAllocAsyncEntry( - IN PW_CACHE Cache, // pointer to the Cache Control structure - IN OUT PW_CACHE_ASYNC* FirstWContext, // pointer to the pointer to - // the head of async IO context chain - IN OUT PW_CACHE_ASYNC* PrevWContext, // pointer to the storage for pointer - // to newly allocated async IO context chain - IN ULONG BufferSize // requested IO buffer size - ) -{ - PW_CACHE_ASYNC WContext; - PCHAR Buffer; - - WContext = (PW_CACHE_ASYNC)MyAllocatePoolTag__(NonPagedPool,sizeof(W_CACHE_ASYNC), MEM_WCCTX_TAG); - if (!WContext) - return NULL; - Buffer = (PCHAR)DbgAllocatePoolWithTag(NonPagedPool, BufferSize*(2-Cache->Chained), MEM_WCBUF_TAG); - if (!Buffer) { - MyFreePool__(WContext); - return NULL; - } - - if (!Cache->Chained) - KeInitializeEvent(&(WContext->PhContext.event), SynchronizationEvent, FALSE); - WContext->Cache = Cache; - if (*PrevWContext) - (*PrevWContext)->NextWContext = WContext; -// WContext->NextWContext = (*PrevWContext); - WContext->NextWContext = NULL; - WContext->Buffer = Buffer; - WContext->Buffer2 = Buffer+(Cache->Chained ? 0 : BufferSize); - - if (!(*FirstWContext)) - (*FirstWContext) = WContext; - (*PrevWContext) = WContext; - - return WContext; -} // end WCacheAllocAsyncEntry() - -/* - WCacheFreeAsyncEntry() releases storage previously allocated for - async IO context. - Internal routine - */ -VOID -WCacheFreeAsyncEntry( - IN PW_CACHE Cache, // pointer to the Cache Control structure - PW_CACHE_ASYNC WContext // pointer to async IO context to release - ) -{ - DbgFreePool(WContext->Buffer); - MyFreePool__(WContext); -} // end WCacheFreeAsyncEntry() - -//#define WCacheRaiseIoError(c, ct, s, l, bc, b, o, r) - -NTSTATUS -WCacheRaiseIoError( - IN PW_CACHE Cache, // pointer to the Cache Control structure - IN PVOID Context, - IN NTSTATUS Status, - IN ULONG Lba, - IN ULONG BCount, - IN PVOID Buffer, - IN BOOLEAN ReadOp, - IN PBOOLEAN Retry - ) -{ - if (!Cache->ErrorHandlerProc) - return Status; - - WCACHE_ERROR_CONTEXT ec; - - ec.WCErrorCode = ReadOp ? WCACHE_ERROR_READ : WCACHE_ERROR_WRITE; - ec.Status = Status; - ec.ReadWrite.Lba = Lba; - ec.ReadWrite.BCount = BCount; - ec.ReadWrite.Buffer = Buffer; - Status = Cache->ErrorHandlerProc(Context, &ec); - if (Retry) - (*Retry) = ec.Retry; - - return Status; - -} // end WCacheRaiseIoError() - -/* - WCacheUpdatePacket() attempts to updates packet containing target Block. - If async IO is enabled new IO context is added to the chain. - If packet containing target Block is modified and PrefereWrite flag - is NOT set, function returns with status STATUS_RETRY. This setting is - user in WCACHE_MODE_R mode to reduce physical writes on flush. - 'State' parameter is used in async mode to determine the next processing - stege for given request - Internal routine - */ -NTSTATUS -WCacheUpdatePacket( - IN PIRP_CONTEXT IrpContext, - IN PW_CACHE Cache, // pointer to the Cache Control structure - IN PVOID Context, // user's context to be passed to user-supplied - // low-level IO routines (IO callbacks) - IN OUT PW_CACHE_ASYNC* FirstWContext, // pointer to head async IO context - IN OUT PW_CACHE_ASYNC* PrevWContext, // pointer to tail async IO context - IN PW_CACHE_ENTRY block_array, // pointer to target Frame - IN lba_t firstLba, // LBA of the 1st block in target Frame - IN lba_t Lba, // LBA of target Block - IN ULONG BSh, // bit shift for Block size - IN ULONG BS, // Block size (bytes) - IN ULONG PS, // Packet size (bytes) - IN ULONG PSs, // Packet size (sectors) - IN PSIZE_T ReadBytes, // pointer to number of successfully read/written bytes - IN BOOLEAN PrefereWrite, // allow physical write (flush) of modified packet - IN ULONG State // callers state - ) -{ - NTSTATUS status; - PCHAR tmp_buff = Cache->tmp_buff; - PCHAR tmp_buff2 = Cache->tmp_buff; - BOOLEAN mod; - BOOLEAN read; - BOOLEAN zero; - ULONG i; - lba_t Lba0; - PW_CACHE_ASYNC WContext; - BOOLEAN Async = (Cache->ReadProcAsync && Cache->WriteProcAsync); - ULONG block_type; - BOOLEAN Chained = Cache->Chained; - - // Check if we are going to write down to disk - // all prewiously prepared (chained) data - if (State == ASYNC_STATE_WRITE) { - WContext = (*PrevWContext); - tmp_buff = (PCHAR)(WContext->Buffer); - tmp_buff2 = (PCHAR)(WContext->Buffer2); - if (!Chained) - mod = (DbgCompareMemory(tmp_buff2, tmp_buff, PS) != PS); - goto try_write; - } - - // Check if packet contains modified blocks - // If packet contains non-cached and unchanged, but used - // blocks, it must be read from media before modification - mod = read = zero = FALSE; - Lba0 = Lba - firstLba; - for(i=0; iCheckUsedProc(Context, Lba+i)) & WCACHE_BLOCK_USED) ) { - // - if (block_type & WCACHE_BLOCK_ZERO) { - zero = TRUE; - } else { - read = TRUE; - } - } - } - // check if we are allowed to write to media - if (mod && !PrefereWrite) { - return STATUS_RETRY; - } - // return STATUS_SUCCESS if requested packet contains no modified blocks - if (!mod) { - (*ReadBytes) = PS; - return STATUS_SUCCESS; - } - - // pefrorm full update cycle: prepare(optional)/read/modify/write - - // do some preparations - if (Chained || Async) { - // For chained and async I/O we allocates context entry - // and add it to list (chain) - // We shall only read data to temporary buffer and - // modify it. Write operations will be invoked later. - // This is introduced in order to avoid frequent - // read.write mode switching, because it significantly degrades - // performance - WContext = WCacheAllocAsyncEntry(Cache, FirstWContext, PrevWContext, PS); - if (!WContext) { - //return STATUS_INSUFFICIENT_RESOURCES; - // try to recover - Chained = FALSE; - Async = FALSE; - } else { - tmp_buff = tmp_buff2 = (PCHAR)(WContext->Buffer); - WContext->Lba = Lba; - WContext->Cmd = ASYNC_CMD_UPDATE; - WContext->State = ASYNC_STATE_NONE; - } - } - - // read packet (if it necessary) - if (read) { - if (Async) { - WContext->State = ASYNC_STATE_READ; - status = Cache->ReadProcAsync(Context, WContext, tmp_buff, PS, Lba, - &(WContext->TransferredBytes)); -// tmp_buff2 = (PCHAR)(WContext->Buffer2); - (*ReadBytes) = PS; - return status; - } else { - status = Cache->ReadProc(IrpContext, Context, tmp_buff, PS, Lba, ReadBytes, PH_TMP_BUFFER); - } - if (!NT_SUCCESS(status)) { - status = WCacheRaiseIoError(Cache, Context, status, Lba, PSs, tmp_buff, WCACHE_R_OP, NULL); - if (!NT_SUCCESS(status)) { - return status; - } - } - } else - if (zero) { - RtlZeroMemory(tmp_buff, PS); - } - - if (Chained) { - // indicate that we prepared for writing block to disk - WContext->State = ASYNC_STATE_WRITE_PRE; - tmp_buff2 = tmp_buff; - status = STATUS_SUCCESS; - } - - // modify packet - - // If we didn't read packet from media, we can't - // perform comparison to assure that packet was really modified. - // Thus, assume that it is modified in this case. - mod = !read || Cache->DoNotCompare; - Lba0 = Lba - firstLba; - for(i=0; i= MM_SYSTEM_RANGE_START); -#endif //_NTDEF_ - if (!mod) { - ASSERT(read); - mod = (DbgCompareMemory(tmp_buff2 + (i << BSh), - (PVOID)WCacheSectorAddr(block_array, Lba0), - BS) != BS); - } - if (mod) { - DbgCopyMemory(tmp_buff2 + (i << BSh), - (PVOID)WCacheSectorAddr(block_array, Lba0), - BS); - } - } - } - - if (Chained && - WContext->State == ASYNC_STATE_WRITE_PRE) { - // Return if block is prepared for write and we are in chained mode. - if (!mod) { - // Mark block as written if we have found that data in it - // is not actually modified. - WContext->State = ASYNC_STATE_DONE; - (*ReadBytes) = PS; - } - return STATUS_SUCCESS; - } - - // write packet - - // If the check above reported some changes in packet - // we should write packet out to media. - // Otherwise, just complete request. - if (mod) { -try_write: - if (Async) { - WContext->State = ASYNC_STATE_WRITE; - status = Cache->WriteProcAsync(Context, WContext, tmp_buff2, PS, Lba, - &(WContext->TransferredBytes), FALSE); - (*ReadBytes) = PS; - } else { - status = Cache->WriteProc(IrpContext, Context, tmp_buff2, PS, Lba, ReadBytes, 0); - if (!NT_SUCCESS(status)) { - status = WCacheRaiseIoError(Cache, Context, status, Lba, PSs, tmp_buff2, WCACHE_W_OP, NULL); - } - } - } else { - if (Async) - WCacheCompleteAsync__(WContext, STATUS_SUCCESS); - (*ReadBytes) = PS; - return STATUS_SUCCESS; - } - - return status; -} // end WCacheUpdatePacket() - -/* - WCacheFreePacket() releases storage for all Blocks in packet. - 'frame' describes Frame, offset - Block in Frame. offset should be - aligned on Packet size. - Internal routine - */ -VOID -WCacheFreePacket( - IN PW_CACHE Cache, // pointer to the Cache Control structure -// IN PVOID Context, - IN ULONG frame, // Frame index - IN PW_CACHE_ENTRY block_array, // Frame - IN ULONG offs, // offset in Frame - IN ULONG PSs // Packet size (in Blocks) - ) -{ - ULONG i; - // mark as non-cached & free pool - for(i=0; iBlockSize << Cache->PacketSizeSh; // packet size (bytes) - ULONG PSs = Cache->PacketSize; - ULONG frame; - lba_t firstLba; - - // Walk through all chained blocks and wait - // for completion of read operations. - // Also invoke writes of already prepared packets. - while(WContext) { - if (WContext->Cmd == ASYNC_CMD_UPDATE && - WContext->State == ASYNC_STATE_READ) { - // wait for async read for update - DbgWaitForSingleObject(&(WContext->PhContext.event), NULL); - - WContext->State = ASYNC_STATE_WRITE; - WCacheUpdatePacket(IrpContext, Cache, Context, NULL, &WContext, NULL, -1, WContext->Lba, -1, -1, - PS, -1, &(WContext->TransferredBytes), TRUE, ASYNC_STATE_WRITE); - } else - if (WContext->Cmd == ASYNC_CMD_UPDATE && - WContext->State == ASYNC_STATE_WRITE_PRE) { - // invoke physical write it the packet is prepared for writing - // by previuous call to WCacheUpdatePacket() - WContext->State = ASYNC_STATE_WRITE; - WCacheUpdatePacket(IrpContext, Cache, Context, NULL, &WContext, NULL, -1, WContext->Lba, -1, -1, - PS, -1, &(WContext->TransferredBytes), TRUE, ASYNC_STATE_WRITE); - WContext->State = ASYNC_STATE_DONE; - } else - if (WContext->Cmd == ASYNC_CMD_READ && - WContext->State == ASYNC_STATE_READ) { - // wait for async read - DbgWaitForSingleObject(&(WContext->PhContext.event), NULL); - } - WContext = WContext->NextWContext; - } - // Walk through all chained blocks and wait - // and wait for completion of async writes (if any). - // Also free temporary buffers containing already written blocks. - WContext = (*FirstWContext); - while(WContext) { - NextWContext = WContext->NextWContext; - if (WContext->Cmd == ASYNC_CMD_UPDATE && - WContext->State == ASYNC_STATE_WRITE) { - - if (!Cache->Chained) - DbgWaitForSingleObject(&(WContext->PhContext.event), NULL); - - frame = WContext->Lba >> Cache->BlocksPerFrameSh; - firstLba = frame << Cache->BlocksPerFrameSh; - - if (FreePacket) { - WCacheFreePacket(Cache, frame, - Cache->FrameList[frame].Frame, - WContext->Lba - firstLba, PSs); - } - } - WCacheFreeAsyncEntry(Cache, WContext); - WContext = NextWContext; - } - (*FirstWContext) = NULL; - (*PrevWContext) = NULL; -} // end WCacheUpdatePacketComplete() - -/* - WCacheCheckLimits() checks if we've enough free Frame- & - Block-entries under Frame- and Block-limit to feet - requested Blocks. - If there is not enough entries, WCache initiates flush & purge - process to satisfy request. - This is dispatch routine, which calls - WCacheCheckLimitsR() or WCacheCheckLimitsRW() depending on - media type. - Internal routine - */ -NTSTATUS -__fastcall -WCacheCheckLimits( - IN PIRP_CONTEXT IrpContext, - IN PW_CACHE Cache, // pointer to the Cache Control structure - IN PVOID Context, // user-supplied context for IO callbacks - IN lba_t ReqLba, // first LBA to access/cache - IN ULONG BCount // number of Blocks to access/cache - ) -{ -/* if (!Cache->FrameCount || !Cache->BlockCount) { - ASSERT(!Cache->FrameCount); - ASSERT(!Cache->BlockCount); - if (!Cache->FrameCount) - return STATUS_SUCCESS; - }*/ - - // check if we have reached Frame or Block limit - if (!Cache->FrameCount && !Cache->BlockCount) { - return STATUS_SUCCESS; - } - - // check for empty frames - if (Cache->FrameCount > (Cache->MaxFrames*3)/4) { - ULONG frame; - ULONG i; - for(i=Cache->FrameCount; i>0; i--) { - frame = Cache->CachedFramesList[i-1]; - // check if frame is empty - if (!(Cache->FrameList[frame].BlockCount)) { - WCacheRemoveFrame(Cache, Context, frame); - } else { - ASSERT(Cache->FrameList[frame].Frame); - } - } - } - - if (!Cache->BlockCount) { - return STATUS_SUCCESS; - } - - // invoke media-specific limit-checker - switch(Cache->Mode) { - case WCACHE_MODE_RAM: - return WCacheCheckLimitsRAM(IrpContext, Cache, Context, ReqLba, BCount); - case WCACHE_MODE_ROM: - case WCACHE_MODE_RW: - return WCacheCheckLimitsRW(IrpContext, Cache, Context, ReqLba, BCount); - case WCACHE_MODE_R: - return WCacheCheckLimitsR(IrpContext, Cache, Context, ReqLba, BCount); - } - return STATUS_DRIVER_INTERNAL_ERROR; -} // end WCacheCheckLimits() - -/* - WCacheCheckLimitsRW() implements automatic flush and purge of - unused blocks to keep enough free cache entries for newly - read/written blocks for Random Access and ReWritable media - using Read/Modify/Write technology. - See also WCacheCheckLimits() - Internal routine - */ -NTSTATUS -__fastcall -WCacheCheckLimitsRW( - IN PIRP_CONTEXT IrpContext, - IN PW_CACHE Cache, // pointer to the Cache Control structure - IN PVOID Context, // user-supplied context for IO callbacks - IN lba_t ReqLba, // first LBA to access/cache - IN ULONG BCount // number of Blocks to access/cache - ) -{ - ULONG frame; - lba_t firstLba; - lba_t* List = Cache->CachedBlocksList; - lba_t lastLba; - lba_t Lba; -// PCHAR tmp_buff = Cache->tmp_buff; - ULONG firstPos; - ULONG lastPos; - ULONG BSh = Cache->BlockSizeSh; - ULONG BS = Cache->BlockSize; - ULONG PS = BS << Cache->PacketSizeSh; // packet size (bytes) - ULONG PSs = Cache->PacketSize; - ULONG try_count = 0; - PW_CACHE_ENTRY block_array; - NTSTATUS status; - SIZE_T ReadBytes; - ULONG FreeFrameCount = 0; -// PVOID addr; - PW_CACHE_ASYNC FirstWContext = NULL; - PW_CACHE_ASYNC PrevWContext = NULL; - ULONG chain_count = 0; - - if (Cache->FrameCount >= Cache->MaxFrames) { - FreeFrameCount = Cache->FramesToKeepFree; - } else - if ((Cache->BlockCount + WCacheGetSortedListIndex(Cache->BlockCount, List, ReqLba) + - BCount - WCacheGetSortedListIndex(Cache->BlockCount, List, ReqLba+BCount)) > Cache->MaxBlocks) { - // we need free space to grow WCache without flushing data - // for some period of time - FreeFrameCount = Cache->FramesToKeepFree; - goto Try_Another_Frame; - } - // remove(flush) some frames - while((Cache->FrameCount >= Cache->MaxFrames) || FreeFrameCount) { -Try_Another_Frame: - if (!Cache->FrameCount || !Cache->BlockCount) { - //ASSERT(!Cache->FrameCount); - if (Cache->FrameCount) { - UDFPrint(("ASSERT: Cache->FrameCount = %d, when 0 is expected\n", Cache->FrameCount)); - } - ASSERT(!Cache->BlockCount); - if (!Cache->FrameCount) - break; - } - - frame = WCacheFindFrameToRelease(Cache); -#if 0 - if (Cache->FrameList[frame].WriteCount) { - try_count++; - if (try_count < MAX_TRIES_FOR_NA) goto Try_Another_Frame; - } else { - try_count = 0; - } -#else - if (Cache->FrameList[frame].UpdateCount) { - try_count = MAX_TRIES_FOR_NA; - } else { - try_count = 0; - } -#endif - - if (FreeFrameCount) - FreeFrameCount--; - - firstLba = frame << Cache->BlocksPerFrameSh; - lastLba = firstLba + Cache->BlocksPerFrame; - firstPos = WCacheGetSortedListIndex(Cache->BlockCount, List, firstLba); - lastPos = WCacheGetSortedListIndex(Cache->BlockCount, List, lastLba); - block_array = Cache->FrameList[frame].Frame; - - if (!block_array) { - UDFPrint(("Hmm...\n")); - BrutePoint(); - return STATUS_DRIVER_INTERNAL_ERROR; - } - - while(firstPos < lastPos) { - // flush packet - Lba = List[firstPos] & ~(PSs-1); - - // write packet out or prepare and add to chain (if chained mode enabled) - status = WCacheUpdatePacket(IrpContext, Cache, Context, &FirstWContext, &PrevWContext, block_array, firstLba, - Lba, BSh, BS, PS, PSs, &ReadBytes, TRUE, ASYNC_STATE_NONE); - - if (status != STATUS_PENDING) { - // free memory - WCacheFreePacket(Cache, frame, block_array, Lba-firstLba, PSs); - } - - Lba += PSs; - while((firstPos < lastPos) && (Lba > List[firstPos])) { - firstPos++; - } - chain_count++; - // write chained packets - if (chain_count >= WCACHE_MAX_CHAIN) { - WCacheUpdatePacketComplete(IrpContext, Cache, Context, &FirstWContext, &PrevWContext, FALSE); - chain_count = 0; - } - } - // remove flushed blocks from all lists - WCacheRemoveRangeFromList(List, &(Cache->BlockCount), firstLba, Cache->BlocksPerFrame); - ASSERT(ValidateFrameBlocksList(Cache, Lba)); - WCacheRemoveRangeFromList(Cache->CachedModifiedBlocksList, &(Cache->WriteCount), firstLba, Cache->BlocksPerFrame); - - WCacheRemoveFrame(Cache, Context, frame); - } - - // check if we try to read too much data - if (BCount > Cache->MaxBlocks) { - WCacheUpdatePacketComplete(IrpContext, Cache, Context, &FirstWContext, &PrevWContext); - return STATUS_INVALID_PARAMETER; - } - - // remove(flush) packet - while((Cache->BlockCount + WCacheGetSortedListIndex(Cache->BlockCount, List, ReqLba) + - BCount - WCacheGetSortedListIndex(Cache->BlockCount, List, ReqLba+BCount)) > Cache->MaxBlocks) { - try_count = 0; -Try_Another_Block: - - Lba = WCacheFindLbaToRelease(Cache) & ~(PSs-1); - if (Lba == WCACHE_INVALID_LBA) { - ASSERT(!Cache->FrameCount); - ASSERT(!Cache->BlockCount); - break; - } - frame = Lba >> Cache->BlocksPerFrameSh; - firstLba = frame << Cache->BlocksPerFrameSh; - firstPos = WCacheGetSortedListIndex(Cache->BlockCount, List, Lba); - lastPos = WCacheGetSortedListIndex(Cache->BlockCount, List, Lba+PSs); - block_array = Cache->FrameList[frame].Frame; - if (!block_array) { - // write already prepared blocks to disk and return error - WCacheUpdatePacketComplete(IrpContext, Cache, Context, &FirstWContext, &PrevWContext); - ASSERT(FALSE); - return STATUS_DRIVER_INTERNAL_ERROR; - } - - // write packet out or prepare and add to chain (if chained mode enabled) - status = WCacheUpdatePacket(IrpContext, Cache, Context, &FirstWContext, &PrevWContext, block_array, firstLba, - Lba, BSh, BS, PS, PSs, &ReadBytes, (try_count >= MAX_TRIES_FOR_NA), ASYNC_STATE_NONE); - - if (status == STATUS_RETRY) { - try_count++; - goto Try_Another_Block; - } - - // free memory - WCacheFreePacket(Cache, frame, block_array, Lba-firstLba, PSs); - - WCacheRemoveRangeFromList(List, &(Cache->BlockCount), Lba, PSs); - ASSERT(ValidateFrameBlocksList(Cache, Lba)); - WCacheRemoveRangeFromList(Cache->CachedModifiedBlocksList, &(Cache->WriteCount), Lba, PSs); - // check if frame is empty - if (!(Cache->FrameList[frame].BlockCount)) { - WCacheRemoveFrame(Cache, Context, frame); - } else { - ASSERT(Cache->FrameList[frame].Frame); - } - chain_count++; - if (chain_count >= WCACHE_MAX_CHAIN) { - WCacheUpdatePacketComplete(IrpContext, Cache, Context, &FirstWContext, &PrevWContext, FALSE); - chain_count = 0; - } - } - WCacheUpdatePacketComplete(IrpContext, Cache, Context, &FirstWContext, &PrevWContext); - return STATUS_SUCCESS; -} // end WCacheCheckLimitsRW() - -NTSTATUS -__fastcall -WCacheFlushBlocksRAM( - IN PIRP_CONTEXT IrpContext, - IN PW_CACHE Cache, // pointer to the Cache Control structure - IN PVOID Context, // user-supplied context for IO callbacks - PW_CACHE_ENTRY block_array, - lba_t* List, - ULONG firstPos, - ULONG lastPos, - BOOLEAN Purge - ) -{ - ULONG frame; - lba_t Lba; - lba_t PrevLba; - lba_t firstLba; - PCHAR tmp_buff = NULL; - ULONG n; - ULONG BSh = Cache->BlockSizeSh; - ULONG BS = Cache->BlockSize; -// ULONG PS = BS << Cache->PacketSizeSh; // packet size (bytes) - ULONG PSs = Cache->PacketSize; - SIZE_T _WrittenBytes; - NTSTATUS status = STATUS_SUCCESS; - - frame = List[firstPos] >> Cache->BlocksPerFrameSh; - firstLba = frame << Cache->BlocksPerFrameSh; - - while(firstPos < lastPos) { - // flush blocks - ASSERT(Cache->FrameCount <= Cache->MaxFrames); - Lba = List[firstPos]; - if (!WCacheGetModFlag(block_array, Lba - firstLba)) { - // free memory - if (Purge) { - WCacheFreePacket(Cache, frame, block_array, Lba-firstLba, 1); - } - firstPos++; - continue; - } - tmp_buff = Cache->tmp_buff; - PrevLba = Lba; - n=1; - while((firstPos+n < lastPos) && - (List[firstPos+n] == PrevLba+1)) { - PrevLba++; - if (!WCacheGetModFlag(block_array, PrevLba - firstLba)) - break; - DbgCopyMemory(tmp_buff + (n << BSh), - (PVOID)WCacheSectorAddr(block_array, PrevLba - firstLba), - BS); - n++; - if (n >= PSs) - break; - } - if (n > 1) { - DbgCopyMemory(tmp_buff, - (PVOID)WCacheSectorAddr(block_array, Lba - firstLba), - BS); - } else { - tmp_buff = (PCHAR)WCacheSectorAddr(block_array, Lba - firstLba); - } - // write sectors out - status = Cache->WriteProc(IrpContext, Context, tmp_buff, n<CachedBlocksList; - lba_t lastLba; - lba_t Lba; -// PCHAR tmp_buff = Cache->tmp_buff; - ULONG firstPos; - ULONG lastPos; -// ULONG BSh = Cache->BlockSizeSh; -// ULONG BS = Cache->BlockSize; -// ULONG PS = BS << Cache->PacketSizeSh; // packet size (bytes) - ULONG PSs = Cache->PacketSize; -// ULONG try_count = 0; - PW_CACHE_ENTRY block_array; -// NTSTATUS status; - ULONG FreeFrameCount = 0; -// PVOID addr; - - if (Cache->FrameCount >= Cache->MaxFrames) { - FreeFrameCount = Cache->FramesToKeepFree; - } else - if ((Cache->BlockCount + WCacheGetSortedListIndex(Cache->BlockCount, List, ReqLba) + - BCount - WCacheGetSortedListIndex(Cache->BlockCount, List, ReqLba+BCount)) > Cache->MaxBlocks) { - // we need free space to grow WCache without flushing data - // for some period of time - FreeFrameCount = Cache->FramesToKeepFree; - goto Try_Another_Frame; - } - // remove(flush) some frames - while((Cache->FrameCount >= Cache->MaxFrames) || FreeFrameCount) { - ASSERT(Cache->FrameCount <= Cache->MaxFrames); -Try_Another_Frame: - if (!Cache->FrameCount || !Cache->BlockCount) { - ASSERT(!Cache->FrameCount); - ASSERT(!Cache->BlockCount); - if (!Cache->FrameCount) - break; - } - - frame = WCacheFindFrameToRelease(Cache); -#if 0 - if (Cache->FrameList[frame].WriteCount) { - try_count++; - if (try_count < MAX_TRIES_FOR_NA) goto Try_Another_Frame; - } else { - try_count = 0; - } -#else -/* - if (Cache->FrameList[frame].UpdateCount) { - try_count = MAX_TRIES_FOR_NA; - } else { - try_count = 0; - } -*/ -#endif - - if (FreeFrameCount) - FreeFrameCount--; - - firstLba = frame << Cache->BlocksPerFrameSh; - lastLba = firstLba + Cache->BlocksPerFrame; - firstPos = WCacheGetSortedListIndex(Cache->BlockCount, List, firstLba); - lastPos = WCacheGetSortedListIndex(Cache->BlockCount, List, lastLba); - block_array = Cache->FrameList[frame].Frame; - - if (!block_array) { - UDFPrint(("Hmm...\n")); - BrutePoint(); - return STATUS_DRIVER_INTERNAL_ERROR; - } - WCacheFlushBlocksRAM(IrpContext, Cache, Context, block_array, List, firstPos, lastPos, TRUE); - - WCacheRemoveRangeFromList(List, &(Cache->BlockCount), firstLba, Cache->BlocksPerFrame); - ASSERT(ValidateFrameBlocksList(Cache, firstLba)); - WCacheRemoveRangeFromList(Cache->CachedModifiedBlocksList, &(Cache->WriteCount), firstLba, Cache->BlocksPerFrame); - ASSERT(Cache->FrameList[frame].BlockCount == 0); - WCacheRemoveFrame(Cache, Context, frame); - } - - // check if we try to read too much data - if (BCount > Cache->MaxBlocks) { - return STATUS_INVALID_PARAMETER; - } - - // remove(flush) packet - while((Cache->BlockCount + WCacheGetSortedListIndex(Cache->BlockCount, List, ReqLba) + - BCount - WCacheGetSortedListIndex(Cache->BlockCount, List, ReqLba+BCount)) > Cache->MaxBlocks) { -// try_count = 0; -//Try_Another_Block: - - ASSERT(Cache->FrameCount <= Cache->MaxFrames); - Lba = WCacheFindLbaToRelease(Cache) & ~(PSs-1); - if (Lba == WCACHE_INVALID_LBA) { - ASSERT(!Cache->FrameCount); - ASSERT(!Cache->BlockCount); - break; - } - frame = Lba >> Cache->BlocksPerFrameSh; - firstLba = frame << Cache->BlocksPerFrameSh; - firstPos = WCacheGetSortedListIndex(Cache->BlockCount, List, Lba); - lastPos = WCacheGetSortedListIndex(Cache->BlockCount, List, Lba+PSs); - block_array = Cache->FrameList[frame].Frame; - if (!block_array) { - ASSERT(FALSE); - return STATUS_DRIVER_INTERNAL_ERROR; - } - WCacheFlushBlocksRAM(IrpContext, Cache, Context, block_array, List, firstPos, lastPos, TRUE); - WCacheRemoveRangeFromList(List, &(Cache->BlockCount), Lba, PSs); - ASSERT(ValidateFrameBlocksList(Cache, Lba)); - WCacheRemoveRangeFromList(Cache->CachedModifiedBlocksList, &(Cache->WriteCount), Lba, PSs); - // check if frame is empty - if (!(Cache->FrameList[frame].BlockCount)) { - WCacheRemoveFrame(Cache, Context, frame); - } else { - ASSERT(Cache->FrameList[frame].Frame); - } - } - return STATUS_SUCCESS; -} // end WCacheCheckLimitsRAM() - -/* - WCachePurgeAllRAM() - Internal routine - */ -NTSTATUS -__fastcall -WCachePurgeAllRAM( - IN PIRP_CONTEXT IrpContext, - IN PW_CACHE Cache, // pointer to the Cache Control structure - IN PVOID Context // user-supplied context for IO callbacks - ) -{ - ULONG frame; - lba_t firstLba; - lba_t* List = Cache->CachedBlocksList; - lba_t lastLba; - ULONG firstPos; - ULONG lastPos; - PW_CACHE_ENTRY block_array; -// NTSTATUS status; - - // remove(flush) some frames - while(Cache->FrameCount) { - - frame = Cache->CachedFramesList[0]; - - firstLba = frame << Cache->BlocksPerFrameSh; - lastLba = firstLba + Cache->BlocksPerFrame; - firstPos = WCacheGetSortedListIndex(Cache->BlockCount, List, firstLba); - lastPos = WCacheGetSortedListIndex(Cache->BlockCount, List, lastLba); - block_array = Cache->FrameList[frame].Frame; - - if (!block_array) { - UDFPrint(("Hmm...\n")); - BrutePoint(); - return STATUS_DRIVER_INTERNAL_ERROR; - } - WCacheFlushBlocksRAM(IrpContext, Cache, Context, block_array, List, firstPos, lastPos, TRUE); - - WCacheRemoveRangeFromList(List, &(Cache->BlockCount), firstLba, Cache->BlocksPerFrame); - ASSERT(ValidateFrameBlocksList(Cache, firstLba)); - WCacheRemoveRangeFromList(Cache->CachedModifiedBlocksList, &(Cache->WriteCount), firstLba, Cache->BlocksPerFrame); - WCacheRemoveFrame(Cache, Context, frame); - } - - ASSERT(!Cache->FrameCount); - ASSERT(!Cache->BlockCount); - return STATUS_SUCCESS; -} // end WCachePurgeAllRAM() - -/* - WCacheFlushAllRAM() - Internal routine - */ -NTSTATUS -__fastcall -WCacheFlushAllRAM( - IN PIRP_CONTEXT IrpContext, - IN PW_CACHE Cache, // pointer to the Cache Control structure - IN PVOID Context // user-supplied context for IO callbacks - ) -{ - ULONG frame; - lba_t firstLba; - lba_t* List = Cache->CachedBlocksList; - lba_t lastLba; - ULONG firstPos; - ULONG lastPos; - PW_CACHE_ENTRY block_array; -// NTSTATUS status; - - // flush frames - while(Cache->WriteCount) { - - frame = Cache->CachedModifiedBlocksList[0] >> Cache->BlocksPerFrameSh; - - firstLba = frame << Cache->BlocksPerFrameSh; - lastLba = firstLba + Cache->BlocksPerFrame; - firstPos = WCacheGetSortedListIndex(Cache->BlockCount, List, firstLba); - lastPos = WCacheGetSortedListIndex(Cache->BlockCount, List, lastLba); - block_array = Cache->FrameList[frame].Frame; - - if (!block_array) { - UDFPrint(("Hmm...\n")); - BrutePoint(); - return STATUS_DRIVER_INTERNAL_ERROR; - } - WCacheFlushBlocksRAM(IrpContext, Cache, Context, block_array, List, firstPos, lastPos, FALSE); - - WCacheRemoveRangeFromList(Cache->CachedModifiedBlocksList, &(Cache->WriteCount), firstLba, Cache->BlocksPerFrame); - } - - return STATUS_SUCCESS; -} // end WCacheFlushAllRAM() - -/* - WCachePreReadPacket__() reads & caches the whole packet containing - requested LBA. This routine just caches data, it doesn't copy anything - to user buffer. - In general we have no user buffer here... ;) - Public routine -*/ -NTSTATUS -WCachePreReadPacket__( - IN PIRP_CONTEXT IrpContext, - IN PW_CACHE Cache, // pointer to the Cache Control structure - IN PVOID Context, // user-supplied context for IO callbacks - IN lba_t Lba // LBA to cache together with whole packet - ) -{ - ULONG frame; - NTSTATUS status = STATUS_SUCCESS; - PW_CACHE_ENTRY block_array; - ULONG BSh = Cache->BlockSizeSh; - ULONG BS = Cache->BlockSize; - PCHAR addr; - SIZE_T _ReadBytes; - ULONG PS = Cache->PacketSize; // (in blocks) - ULONG BCount = PS; - ULONG i, n, err_count; - BOOLEAN sector_added = FALSE; - ULONG block_type; - BOOLEAN zero = FALSE;//TRUE; -/* - ULONG first_zero=0, last_zero=0; - BOOLEAN count_first_zero = TRUE; -*/ - - Lba &= ~(PS-1); - frame = Lba >> Cache->BlocksPerFrameSh; - i = Lba - (frame << Cache->BlocksPerFrameSh); - - // assume successful operation - block_array = Cache->FrameList[frame].Frame; - if (!block_array) { - ASSERT(Cache->FrameCount < Cache->MaxFrames); - block_array = WCacheInitFrame(IrpContext, Cache, Context, frame); - if (!block_array) - return STATUS_INSUFFICIENT_RESOURCES; - } - - // skip cached extent (if any) - n=0; - while((n < BCount) && - (n < Cache->BlocksPerFrame)) { - - addr = (PCHAR)WCacheSectorAddr(block_array, i+n); - block_type = Cache->CheckUsedProc(Context, Lba+n); - if (/*WCacheGetBadFlag(block_array,i+n)*/ - block_type & WCACHE_BLOCK_BAD) { - // bad packet. no pre-read - return STATUS_DEVICE_DATA_ERROR; - } - if (!(block_type & WCACHE_BLOCK_ZERO)) { - zero = FALSE; - //count_first_zero = FALSE; - //last_zero = 0; - if (!addr) { - // sector is not cached, stop search - break; - } - } else { -/* - if (count_first_zero) { - first_zero++; - } - last_zero++; -*/ - } - n++; - } - // do nothing if all sectors are already cached - if (n < BCount) { - - // read whole packet - if (!zero) { - status = Cache->ReadProc(IrpContext, Context, Cache->tmp_buff_r, PS<tmp_buff_r, WCACHE_R_OP, NULL); - } - } else { - status = STATUS_SUCCESS; - //RtlZeroMemory(Cache->tmp_buff_r, PS<tmp_buff_r+(n<FrameList[frame].BlockCount++; - } - } else { - // read sectors one by one and copy them to cache - // unreadable sectors will be treated as zero-filled - err_count = 0; - for(n=0; nReadProc(IrpContext, Context, Cache->tmp_buff_r, BS, Lba+n, &_ReadBytes, PH_TMP_BUFFER); - if (!NT_SUCCESS(status)) { - status = WCacheRaiseIoError(Cache, Context, status, Lba+n, 1, Cache->tmp_buff_r, WCACHE_R_OP, NULL); - if (!NT_SUCCESS(status)) { - err_count++; - } - } - if (!zero && NT_SUCCESS(status)) { - DbgCopyMemory(addr, Cache->tmp_buff_r, BS); - } else - if (Cache->RememberBB) { - RtlZeroMemory(addr, BS); - /* - if (!NT_SUCCESS(status)) { - WCacheSetBadFlag(block_array,i); - } - */ - } - Cache->FrameList[frame].BlockCount++; - if (err_count >= 2) { - break; - } - } -// _ReadBytes = n<CachedBlocksList, &(Cache->BlockCount), Lba, n); - ASSERT(ValidateFrameBlocksList(Cache, Lba)); - } - - return status; -} // end WCachePreReadPacket__() - -/* - WCacheReadBlocks__() reads data from cache or - read it form media and store in cache. - Public routine - */ -NTSTATUS -WCacheReadBlocks__( - IN PIRP_CONTEXT IrpContext, - IN PW_CACHE Cache, // pointer to the Cache Control structure - IN PVOID Context, // user-supplied context for IO callbacks - IN PCHAR Buffer, // user-supplied buffer for read blocks - IN lba_t Lba, // LBA to start read from - IN ULONG BCount, // number of blocks to be read - OUT PSIZE_T ReadBytes, // user-supplied pointer to ULONG that will - // recieve number of actually read bytes - IN BOOLEAN CachedOnly // specifies that cache is already locked - ) -{ - ULONG frame; - ULONG i, saved_i, saved_BC = BCount, n; - NTSTATUS status = STATUS_SUCCESS; - PW_CACHE_ENTRY block_array; - ULONG BSh = Cache->BlockSizeSh; - SIZE_T BS = Cache->BlockSize; - PCHAR addr; - ULONG to_read, saved_to_read; -// PCHAR saved_buff = Buffer; - SIZE_T _ReadBytes; - ULONG PS = Cache->PacketSize; - ULONG MaxR = Cache->MaxBytesToRead; - ULONG PacketMask = PS-1; // here we assume that Packet Size value is 2^n - ULONG d; - ULONG block_type; - - WcPrint(("WC:R %x (%x)\n", Lba, BCount)); - - (*ReadBytes) = 0; - // check if we try to read too much data - if (BCount >= Cache->MaxBlocks) { - i = 0; - if (CachedOnly) { - status = STATUS_INVALID_PARAMETER; - goto EO_WCache_R2; - } - while(TRUE) { - status = WCacheReadBlocks__(IrpContext, Cache, Context, Buffer + (i<FirstLba) || - (Lba + BCount - 1 > Cache->LastLba)) { - status = Cache->ReadProc(IrpContext, Context, Buffer, BCount, Lba, ReadBytes, 0); - if (!NT_SUCCESS(status)) { - status = WCacheRaiseIoError(Cache, Context, status, Lba, BCount, Buffer, WCACHE_R_OP, NULL); - } - return status; - } - if (!CachedOnly) { - ExAcquireResourceExclusiveLite(&(Cache->WCacheLock), TRUE); - } - - frame = Lba >> Cache->BlocksPerFrameSh; - i = Lba - (frame << Cache->BlocksPerFrameSh); - - if (Cache->CacheWholePacket && (BCount < PS)) { - if (!CachedOnly && - !NT_SUCCESS(status = WCacheCheckLimits(IrpContext, Cache, Context, Lba & ~(PS-1), PS*2)) ) { - ExReleaseResourceForThreadLite(&(Cache->WCacheLock), ExGetCurrentResourceThread()); - return status; - } - } else { - if (!CachedOnly && - !NT_SUCCESS(status = WCacheCheckLimits(IrpContext, Cache, Context, Lba, BCount))) { - ExReleaseResourceForThreadLite(&(Cache->WCacheLock), ExGetCurrentResourceThread()); - return status; - } - } - if (!CachedOnly) { - // convert to shared -// ExConvertExclusiveToSharedLite(&(Cache->WCacheLock)); - } - - // pre-read packet. It is very useful for - // highly fragmented files - if (Cache->CacheWholePacket && (BCount < PS)) { -// status = WCacheReadBlocks__(Cache, Context, Cache->tmp_buff_r, Lba & (~PacketMask), PS, &_ReadBytes, TRUE); - // we should not perform IO if user requested CachedOnly data - if (!CachedOnly) { - status = WCachePreReadPacket__(IrpContext, Cache, Context, Lba); - } - status = STATUS_SUCCESS; - } - - // assume successful operation - block_array = Cache->FrameList[frame].Frame; - if (!block_array) { - ASSERT(!CachedOnly); - ASSERT(Cache->FrameCount < Cache->MaxFrames); - block_array = WCacheInitFrame(IrpContext, Cache, Context, frame); - if (!block_array) { - status = STATUS_INSUFFICIENT_RESOURCES; - goto EO_WCache_R; - } - } - - Cache->FrameList[frame].AccessCount++; - while(BCount) { - if (i >= Cache->BlocksPerFrame) { - frame++; - block_array = Cache->FrameList[frame].Frame; - i -= Cache->BlocksPerFrame; - } - if (!block_array) { - ASSERT(Cache->FrameCount < Cache->MaxFrames); - block_array = WCacheInitFrame(IrpContext, Cache, Context, frame); - if (!block_array) { - status = STATUS_INSUFFICIENT_RESOURCES; - goto EO_WCache_R; - } - } - // 'read' cached extent (if any) - // it is just copying - while(BCount && - (i < Cache->BlocksPerFrame) && - (addr = (PCHAR)WCacheSectorAddr(block_array, i)) ) { - block_type = Cache->CheckUsedProc(Context, Lba+saved_BC-BCount); - if (block_type & WCACHE_BLOCK_BAD) { - //if (WCacheGetBadFlag(block_array,i)) { - status = STATUS_DEVICE_DATA_ERROR; - goto EO_WCache_R; - } - DbgCopyMemory(Buffer, addr, BS); - Buffer += BS; - *ReadBytes += BS; - i++; - BCount--; - } - // read non-cached packet-size-aligned extent (if any) - // now we'll calculate total length & decide if it has enough size - if (!((d = Lba+saved_BC-BCount) & PacketMask) && d ) { - n = 0; - while(BCount && - (i < Cache->BlocksPerFrame) && - (!WCacheSectorAddr(block_array, i)) ) { - n++; - BCount--; - } - BCount += n; - n &= ~PacketMask; - if (n>PS) { - if (!NT_SUCCESS(status = Cache->ReadProc(IrpContext, Context, Buffer, BS*n, Lba+saved_BC-BCount, &_ReadBytes, 0))) { - status = WCacheRaiseIoError(Cache, Context, status, Lba+saved_BC-BCount, n, Buffer, WCACHE_R_OP, NULL); - if (!NT_SUCCESS(status)) { - goto EO_WCache_R; - } - } -// WCacheInsertRangeToList(Cache->CachedBlocksList, &(Cache->BlockCount), Lba, saved_BC - BCount); - BCount -= n; - Lba += saved_BC - BCount; - // If reading non-cached packet-size-aligned data, it is not added to the cache. - // Therefore, we reset the saved_BC variable to zero in this case. - saved_BC = BCount; - i += n; - Buffer += BS*n; - *ReadBytes += BS*n; - } -// } else { -// UDFPrint(("Unaligned\n")); - } - // read non-cached extent (if any) - // firstable, we'll get total number of sectors to read - to_read = 0; - saved_i = i; - d = BCount; - while(d && - (i < Cache->BlocksPerFrame) && - (!WCacheSectorAddr(block_array, i)) ) { - i++; - to_read += BS; - d--; - } - // read some not cached sectors - if (to_read) { - i = saved_i; - saved_to_read = to_read; - d = BCount - d; - // split request if necessary - if (saved_to_read > MaxR) { - WCacheInsertRangeToList(Cache->CachedBlocksList, &(Cache->BlockCount), Lba, saved_BC - BCount); - ASSERT(ValidateFrameBlocksList(Cache, Lba)); - n = MaxR >> BSh; - do { - status = Cache->ReadProc(IrpContext, Context, Buffer, MaxR, i + (frame << Cache->BlocksPerFrameSh), &_ReadBytes, 0); - *ReadBytes += _ReadBytes; - if (!NT_SUCCESS(status)) { - _ReadBytes &= ~(BS-1); - BCount -= _ReadBytes >> BSh; - saved_to_read -= _ReadBytes; - Buffer += _ReadBytes; - // Can the variable saved_BC be modified here? Most likely not. This requires debugging. - ASSERT(FALSE); - saved_BC = BCount; - goto store_read_data_1; - } - Buffer += MaxR; - saved_to_read -= MaxR; - i += n; - BCount -= n; - d -= n; - } while(saved_to_read > MaxR); - // The variable saved_BC should not be modified, as it holds the original value of BCount - // and is used by WCacheInsertRangeToList below. Modifying it has led to memory leaks, - // causing WCacheFlushBlocksRAM to not release all sectors and to delete a block without freeing the memory. - //saved_BC = BCount; - } - if (saved_to_read) { - status = Cache->ReadProc(IrpContext, Context, Buffer, saved_to_read, i + (frame << Cache->BlocksPerFrameSh), &_ReadBytes, 0); - *ReadBytes += _ReadBytes; - if (!NT_SUCCESS(status)) { - _ReadBytes &= ~(BS-1); - BCount -= _ReadBytes >> BSh; - saved_to_read -= _ReadBytes; - Buffer += _ReadBytes; - goto store_read_data_1; - } - Buffer += saved_to_read; - saved_to_read = 0; - BCount -= d; - } - -store_read_data_1: - // and now we'll copy them to cache - - // - Buffer -= (to_read - saved_to_read); - i = saved_i; - while(to_read - saved_to_read) { - ASSERT(block_array[i].Sector == NULL); - block_array[i].Sector = (PCHAR)DbgAllocatePoolWithTag(CACHED_BLOCK_MEMORY_TYPE, BS, MEM_WCBUF_TAG); - if (!block_array[i].Sector) { - BCount += to_read >> BSh; - status = STATUS_INSUFFICIENT_RESOURCES; - goto EO_WCache_R; - } - DbgCopyMemory(block_array[i].Sector, Buffer, BS); - Cache->FrameList[frame].BlockCount++; - i++; - Buffer += BS; - to_read -= BS; - } - if (!NT_SUCCESS(status)) - goto EO_WCache_R; - to_read = 0; - } - } - -EO_WCache_R: - - // we know the number of unread sectors if an error occured - // so we can need to update BlockCount - // return number of read bytes - WCacheInsertRangeToList(Cache->CachedBlocksList, &(Cache->BlockCount), Lba, saved_BC - BCount); - ASSERT(ValidateFrameBlocksList(Cache, Lba)); -// Cache->FrameList[frame].BlockCount -= BCount; -EO_WCache_R2: - if (!CachedOnly) { - ExReleaseResourceForThreadLite(&(Cache->WCacheLock), ExGetCurrentResourceThread()); - } - - return status; -} // end WCacheReadBlocks__() - -/* - WCacheWriteBlocks__() writes data to cache. - Data is written directly to media if: - 1) requested block is Packet-aligned - 2) requested Lba(s) lays beyond cached area - Public routine - */ -NTSTATUS -WCacheWriteBlocks__( - IN PIRP_CONTEXT IrpContext, - IN PW_CACHE Cache, // pointer to the Cache Control structure - IN PVOID Context, // user-supplied context for IO callbacks - IN PCHAR Buffer, // user-supplied buffer containing data to be written - IN lba_t Lba, // LBA to start write from - IN ULONG BCount, // number of blocks to be written - OUT PSIZE_T WrittenBytes, // user-supplied pointer to ULONG that will - // recieve number of actually written bytes - IN BOOLEAN CachedOnly // specifies that cache is already locked - ) -{ - ULONG frame; - ULONG i, saved_BC = BCount, n, d; - NTSTATUS status = STATUS_SUCCESS; - PW_CACHE_ENTRY block_array; - ULONG BSh = Cache->BlockSizeSh; - ULONG BS = Cache->BlockSize; - PCHAR addr; -// PCHAR saved_buff = Buffer; - SIZE_T _WrittenBytes; - ULONG PS = Cache->PacketSize; - ULONG PacketMask = PS-1; // here we assume that Packet Size value is 2^n - ULONG block_type; -// BOOLEAN Aligned = FALSE; - - BOOLEAN WriteThrough = FALSE; - lba_t WTh_Lba; - ULONG WTh_BCount; - - WcPrint(("WC:W %x (%x)\n", Lba, BCount)); - - *WrittenBytes = 0; -// UDFPrint(("BCount:%x\n",BCount)); - // check if we try to read too much data - if (BCount >= Cache->MaxBlocks) { - i = 0; - if (CachedOnly) { - status = STATUS_INVALID_PARAMETER; - goto EO_WCache_W2; - } - while(TRUE) { -// UDFPrint((" BCount:%x\n",BCount)); - status = WCacheWriteBlocks__(IrpContext, Cache, Context, Buffer + (i<FirstLba) || - (Lba + BCount - 1 > Cache->LastLba)) { - return STATUS_INVALID_PARAMETER; - } - if (!CachedOnly) { - ExAcquireResourceExclusiveLite(&(Cache->WCacheLock), TRUE); - } - - frame = Lba >> Cache->BlocksPerFrameSh; - i = Lba - (frame << Cache->BlocksPerFrameSh); - - if (!CachedOnly && - !NT_SUCCESS(status = WCacheCheckLimits(IrpContext, Cache, Context, Lba, BCount))) { - ExReleaseResourceForThreadLite(&(Cache->WCacheLock), ExGetCurrentResourceThread()); - return status; - } - - // assume successful operation - block_array = Cache->FrameList[frame].Frame; - if (!block_array) { - - if (BCount && !(BCount & (PS-1)) && !(Lba & (PS-1)) && - (Cache->Mode != WCACHE_MODE_R) && - (i+BCount <= Cache->BlocksPerFrame) && - !Cache->NoWriteThrough) { - status = Cache->WriteProc(IrpContext, Context, Buffer, BCount<FrameCount < Cache->MaxFrames); - block_array = WCacheInitFrame(IrpContext, Cache, Context, frame); - if (!block_array) { - status = STATUS_INSUFFICIENT_RESOURCES; - goto EO_WCache_W; - } - } - - if (Cache->Mode == WCACHE_MODE_RAM && - BCount && -// !(Lba & (PS-1)) && - (!(BCount & (PS-1)) || (BCount > PS)) ) { - WriteThrough = TRUE; - WTh_Lba = Lba; - WTh_BCount = BCount; - } else - if (Cache->Mode == WCACHE_MODE_RAM && - ((Lba & ~PacketMask) != ((Lba+BCount-1) & ~PacketMask)) - ) { - WriteThrough = TRUE; - WTh_Lba = Lba & ~PacketMask; - WTh_BCount = PS; - } - - Cache->FrameList[frame].UpdateCount++; -// UDFPrint((" BCount:%x\n",BCount)); - while(BCount) { - if (i >= Cache->BlocksPerFrame) { - frame++; - block_array = Cache->FrameList[frame].Frame; - i -= Cache->BlocksPerFrame; - } - if (!block_array) { - ASSERT(Cache->FrameCount < Cache->MaxFrames); - block_array = WCacheInitFrame(IrpContext, Cache, Context, frame); - if (!block_array) { - status = STATUS_INSUFFICIENT_RESOURCES; - goto EO_WCache_W; - } - } - // 'write' cached extent (if any) - // it is just copying - while(BCount && - (i < Cache->BlocksPerFrame) && - (addr = (PCHAR)WCacheSectorAddr(block_array, i)) ) { -// UDFPrint(("addr:%x:Buffer:%x:BS:%x:BCount:%x\n",addr, Buffer, BS, BCount)); - block_type = Cache->CheckUsedProc(Context, Lba+saved_BC-BCount); - if (Cache->NoWriteBB && - /*WCacheGetBadFlag(block_array,i)*/ - (block_type & WCACHE_BLOCK_BAD)) { - // bad packet. no cached write - status = STATUS_DEVICE_DATA_ERROR; - goto EO_WCache_W; - } - DbgCopyMemory(addr, Buffer, BS); - WCacheSetModFlag(block_array, i); - Buffer += BS; - *WrittenBytes += BS; - i++; - BCount--; - } - // write non-cached not-aligned extent (if any) till aligned one - while(BCount && - (i & PacketMask) && - (Cache->Mode != WCACHE_MODE_R) && - (i < Cache->BlocksPerFrame) && - (!WCacheSectorAddr(block_array, i)) ) { - ASSERT(block_array[i].Sector == NULL); - block_array[i].Sector = (PCHAR)DbgAllocatePoolWithTag(CACHED_BLOCK_MEMORY_TYPE, BS, MEM_WCBUF_TAG); - if (!block_array[i].Sector) { - status = STATUS_INSUFFICIENT_RESOURCES; - goto EO_WCache_W; - } -// UDFPrint(("addr:%x:Buffer:%x:BS:%x:BCount:%x\n",block_array[i].Sector, Buffer, BS, BCount)); - DbgCopyMemory(block_array[i].Sector, Buffer, BS); - WCacheSetModFlag(block_array, i); - i++; - Buffer += BS; - *WrittenBytes += BS; - BCount--; - Cache->FrameList[frame].BlockCount ++; - } - // write non-cached packet-size-aligned extent (if any) - // now we'll calculate total length & decide if has enough size - if (!Cache->NoWriteThrough - && - ( !(i & PacketMask) || - ((Cache->Mode == WCACHE_MODE_R) && (BCount >= PS)) )) { - n = 0; - while(BCount && - (i < Cache->BlocksPerFrame) && - (!WCacheSectorAddr(block_array, i)) ) { - n++; - BCount--; - } - BCount += n; - n &= ~PacketMask; -// if (!NT_SUCCESS(status = Cache->WriteProcAsync(Context, Buffer, BS*n, Lba+saved_BC-BCount, &_WrittenBytes, FALSE))) - if (n) { - // add previously written data to list - d = saved_BC - BCount; - WCacheInsertRangeToList(Cache->CachedBlocksList, &(Cache->BlockCount), Lba, d); - ASSERT(ValidateFrameBlocksList(Cache, Lba)); - WCacheInsertRangeToList(Cache->CachedModifiedBlocksList, &(Cache->WriteCount), Lba, d); - Lba += d; - saved_BC = BCount; - - while(n) { - if (Cache->Mode == WCACHE_MODE_R) - Cache->UpdateRelocProc(Context, Lba, NULL, PS); - if (!NT_SUCCESS(status = Cache->WriteProc(IrpContext, Context, Buffer, PS<BlocksPerFrame) && - (!WCacheSectorAddr(block_array, i)) ) { - ASSERT(block_array[i].Sector == NULL); - block_array[i].Sector = (PCHAR)DbgAllocatePoolWithTag(CACHED_BLOCK_MEMORY_TYPE, BS, MEM_WCBUF_TAG); - if (!block_array[i].Sector) { - status = STATUS_INSUFFICIENT_RESOURCES; - goto EO_WCache_W; - } -// UDFPrint(("addr:%x:Buffer:%x:BS:%x:BCount:%x\n",block_array[i].Sector, Buffer, BS, BCount)); - DbgCopyMemory(block_array[i].Sector, Buffer, BS); - WCacheSetModFlag(block_array, i); - i++; - Buffer += BS; - *WrittenBytes += BS; - BCount--; - Cache->FrameList[frame].BlockCount ++; - } - } - -EO_WCache_W: - - // we know the number of unread sectors if an error occured - // so we can need to update BlockCount - // return number of read bytes - WCacheInsertRangeToList(Cache->CachedBlocksList, &(Cache->BlockCount), Lba, saved_BC - BCount); - ASSERT(ValidateFrameBlocksList(Cache, Lba)); - WCacheInsertRangeToList(Cache->CachedModifiedBlocksList, &(Cache->WriteCount), Lba, saved_BC - BCount); - - if (WriteThrough && !BCount) { - ULONG d; -// lba_t lastLba; - ULONG firstPos; - ULONG lastPos; - - BCount = WTh_BCount; - Lba = WTh_Lba; - while(BCount) { - frame = Lba >> Cache->BlocksPerFrameSh; -// firstLba = frame << Cache->BlocksPerFrameSh; - firstPos = WCacheGetSortedListIndex(Cache->BlockCount, Cache->CachedBlocksList, Lba); - d = min(Lba+BCount, (frame+1) << Cache->BlocksPerFrameSh) - Lba; - lastPos = WCacheGetSortedListIndex(Cache->BlockCount, Cache->CachedBlocksList, Lba+d); - block_array = Cache->FrameList[frame].Frame; - if (!block_array) { - // write was non-cached, so skip this cache frame without asserting - // ASSERT(FALSE); - BCount -= d; - Lba += d; - continue; - } - status = WCacheFlushBlocksRAM(IrpContext, Cache, Context, block_array, Cache->CachedBlocksList, firstPos, lastPos, FALSE); - WCacheRemoveRangeFromList(Cache->CachedModifiedBlocksList, &(Cache->WriteCount), Lba, d); - BCount -= d; - Lba += d; - } - } - -EO_WCache_W2: - - if (!CachedOnly) { - ExReleaseResourceForThreadLite(&(Cache->WCacheLock), ExGetCurrentResourceThread()); - } - return status; -} // end WCacheWriteBlocks__() - -/* - WCacheFlushAll__() copies all data stored in cache to media. - Flushed blocks are kept in cache. - Public routine - */ -VOID -WCacheFlushAll__( - IN PIRP_CONTEXT IrpContext, - IN PW_CACHE Cache, // pointer to the Cache Control structure - IN PVOID Context) // user-supplied context for IO callbacks -{ - if (!(Cache->ReadProc)) return; - ExAcquireResourceExclusiveLite(&(Cache->WCacheLock), TRUE); - - switch(Cache->Mode) { - case WCACHE_MODE_RAM: - WCacheFlushAllRAM(IrpContext, Cache, Context); - break; - case WCACHE_MODE_ROM: - case WCACHE_MODE_RW: - WCacheFlushAllRW(IrpContext, Cache, Context); - break; - case WCACHE_MODE_R: - WCachePurgeAllR(IrpContext, Cache, Context); - break; - } - - ExReleaseResourceForThreadLite(&(Cache->WCacheLock), ExGetCurrentResourceThread()); - return; -} // end WCacheFlushAll__() - -/* - WCachePurgeAll__() copies all data stored in cache to media. - Flushed blocks are removed cache. - Public routine - */ -VOID -WCachePurgeAll__( - IN PIRP_CONTEXT IrpContext, - IN PW_CACHE Cache, // pointer to the Cache Control structure - IN PVOID Context) // user-supplied context for IO callbacks -{ - if (!(Cache->ReadProc)) return; - ExAcquireResourceExclusiveLite(&(Cache->WCacheLock), TRUE); - - switch(Cache->Mode) { - case WCACHE_MODE_RAM: - WCachePurgeAllRAM(IrpContext, Cache, Context); - break; - case WCACHE_MODE_ROM: - case WCACHE_MODE_RW: - WCachePurgeAllRW(IrpContext, Cache, Context); - break; - case WCACHE_MODE_R: - WCachePurgeAllR(IrpContext, Cache, Context); - break; - } - - ExReleaseResourceForThreadLite(&(Cache->WCacheLock), ExGetCurrentResourceThread()); - return; -} // end WCachePurgeAll__() -/* - WCachePurgeAllRW() copies modified blocks from cache to media - and removes them from cache - This routine can be used for RAM, RW and ROM media. - For ROM media blocks are just removed. - Internal routine - */ -VOID -__fastcall -WCachePurgeAllRW( - IN PIRP_CONTEXT IrpContext, - IN PW_CACHE Cache, // pointer to the Cache Control structure - IN PVOID Context) // user-supplied context for IO callbacks -{ - ULONG frame; - lba_t firstLba; - lba_t* List = Cache->CachedBlocksList; - lba_t Lba; -// ULONG firstPos; -// ULONG lastPos; - ULONG BSh = Cache->BlockSizeSh; - ULONG BS = Cache->BlockSize; - ULONG PS = BS << Cache->PacketSizeSh; // packet size (bytes) - ULONG PSs = Cache->PacketSize; - PW_CACHE_ENTRY block_array; -// NTSTATUS status; - SIZE_T ReadBytes; - PW_CACHE_ASYNC FirstWContext = NULL; - PW_CACHE_ASYNC PrevWContext = NULL; - ULONG chain_count = 0; - - if (!(Cache->ReadProc)) return; - - while(Cache->BlockCount) { - Lba = List[0] & ~(PSs-1); - frame = Lba >> Cache->BlocksPerFrameSh; - firstLba = frame << Cache->BlocksPerFrameSh; -// firstPos = WCacheGetSortedListIndex(Cache->BlockCount, List, Lba); -// lastPos = WCacheGetSortedListIndex(Cache->BlockCount, List, Lba+PSs); - block_array = Cache->FrameList[frame].Frame; - if (!block_array) { - BrutePoint(); - return; - } - - WCacheUpdatePacket(IrpContext, Cache, Context, &FirstWContext, &PrevWContext, block_array, firstLba, - Lba, BSh, BS, PS, PSs, &ReadBytes, TRUE, ASYNC_STATE_NONE); - - // free memory - WCacheFreePacket(Cache, frame, block_array, Lba-firstLba, PSs); - - WCacheRemoveRangeFromList(List, &(Cache->BlockCount), Lba, PSs); - ASSERT(ValidateFrameBlocksList(Cache, Lba)); - WCacheRemoveRangeFromList(Cache->CachedModifiedBlocksList, &(Cache->WriteCount), Lba, PSs); - // check if frame is empty - if (!(Cache->FrameList[frame].BlockCount)) { - WCacheRemoveFrame(Cache, Context, frame); - } else { - ASSERT(Cache->FrameList[frame].Frame); - } - chain_count++; - if (chain_count >= WCACHE_MAX_CHAIN) { - WCacheUpdatePacketComplete(IrpContext, Cache, Context, &FirstWContext, &PrevWContext, FALSE); - chain_count = 0; - } - } - WCacheUpdatePacketComplete(IrpContext, Cache, Context, &FirstWContext, &PrevWContext); - return; -} // end WCachePurgeAllRW() - -/* - WCacheFlushAllRW() copies modified blocks from cache to media. - All blocks are not removed from cache. - This routine can be used for RAM, RW and ROM media. - Internal routine - */ -VOID -__fastcall -WCacheFlushAllRW( - IN PIRP_CONTEXT IrpContext, - IN PW_CACHE Cache, // pointer to the Cache Control structure - IN PVOID Context) // user-supplied context for IO callbacks -{ - ULONG frame; - lba_t firstLba; - lba_t* List = Cache->CachedModifiedBlocksList; - lba_t Lba; -// ULONG firstPos; -// ULONG lastPos; - ULONG BSh = Cache->BlockSizeSh; - ULONG BS = Cache->BlockSize; - ULONG PS = BS << Cache->PacketSizeSh; // packet size (bytes) - ULONG PSs = Cache->PacketSize; - ULONG BFs = Cache->BlocksPerFrameSh; - PW_CACHE_ENTRY block_array; -// NTSTATUS status; - SIZE_T ReadBytes; - PW_CACHE_ASYNC FirstWContext = NULL; - PW_CACHE_ASYNC PrevWContext = NULL; - ULONG i; - ULONG chain_count = 0; - - if (!(Cache->ReadProc)) return; - - // walk through modified blocks - while(Cache->WriteCount) { - Lba = List[0] & ~(PSs-1); - frame = Lba >> BFs; - firstLba = frame << BFs; -// firstPos = WCacheGetSortedListIndex(Cache->WriteCount, List, Lba); -// lastPos = WCacheGetSortedListIndex(Cache->WriteCount, List, Lba+PSs); - block_array = Cache->FrameList[frame].Frame; - if (!block_array) { - BrutePoint(); - continue;; - } - // queue modify request - WCacheUpdatePacket(IrpContext, Cache, Context, &FirstWContext, &PrevWContext, block_array, firstLba, - Lba, BSh, BS, PS, PSs, &ReadBytes, TRUE, ASYNC_STATE_NONE); - // clear MODIFIED flag for queued blocks - WCacheRemoveRangeFromList(List, &(Cache->WriteCount), Lba, PSs); - Lba -= firstLba; - for(i=0; i= WCACHE_MAX_CHAIN) { - WCacheUpdatePacketComplete(IrpContext, Cache, Context, &FirstWContext, &PrevWContext, FALSE); - chain_count = 0; - } - } - WCacheUpdatePacketComplete(IrpContext, Cache, Context, &FirstWContext, &PrevWContext, FALSE); -#ifdef DBG -#if 1 - // check consistency - List = Cache->CachedBlocksList; - for(i=0; iBlockCount; i++) { - Lba = List[i] /*& ~(PSs-1)*/; - frame = Lba >> Cache->BlocksPerFrameSh; - firstLba = frame << Cache->BlocksPerFrameSh; - block_array = Cache->FrameList[frame].Frame; - if (!block_array) { - BrutePoint(); - } - ASSERT(!WCacheGetModFlag(block_array, Lba-firstLba)); - } -#endif // 1 -#endif // DBG - return; -} // end WCacheFlushAllRW() - -/* - WCacheRelease__() frees all allocated memory blocks and - deletes synchronization resources - Public routine - */ -VOID -WCacheRelease__( - IN PW_CACHE Cache // pointer to the Cache Control structure - ) -{ - ULONG i, j, k; - PW_CACHE_ENTRY block_array; - - Cache->Tag = 0xDEADCACE; - if (!(Cache->ReadProc)) return; -// ASSERT(Cache->Tag == 0xCAC11E00); - ExAcquireResourceExclusiveLite(&(Cache->WCacheLock), TRUE); - for(i=0; iFrameCount; i++) { - j = Cache->CachedFramesList[i]; - block_array = Cache->FrameList[j].Frame; - if (block_array) { - for(k=0; kBlocksPerFrame; k++) { - if (WCacheSectorAddr(block_array, k)) { - WCacheFreeSector(j, k); - } - } - MyFreePool__(block_array); - } - } - if (Cache->FrameList) - MyFreePool__(Cache->FrameList); - if (Cache->CachedBlocksList) - MyFreePool__(Cache->CachedBlocksList); - if (Cache->CachedModifiedBlocksList) - MyFreePool__(Cache->CachedModifiedBlocksList); - if (Cache->CachedFramesList) - MyFreePool__(Cache->CachedFramesList); - if (Cache->tmp_buff_r) - MyFreePool__(Cache->tmp_buff_r); - if (Cache->CachedFramesList) - MyFreePool__(Cache->tmp_buff); - if (Cache->CachedFramesList) - MyFreePool__(Cache->reloc_tab); - ExReleaseResourceForThreadLite(&(Cache->WCacheLock), ExGetCurrentResourceThread()); - ExDeleteResourceLite(&(Cache->WCacheLock)); - RtlZeroMemory(Cache, sizeof(W_CACHE)); - return; -} // end WCacheRelease__() - -/* - WCacheIsInitialized__() checks if the pointer supplied points - to initialized cache structure. - Public routine - */ -BOOLEAN -WCacheIsInitialized__( - IN PW_CACHE Cache - ) -{ - return (Cache->ReadProc != NULL); -} // end WCacheIsInitialized__() - -NTSTATUS -WCacheFlushBlocksRW( - IN PIRP_CONTEXT IrpContext, - IN PW_CACHE Cache, // pointer to the Cache Control structure - IN PVOID Context, // user-supplied context for IO callbacks - IN lba_t _Lba, // LBA to start flush from - IN ULONG BCount // number of blocks to be flushed - ) -{ - ULONG frame; - lba_t firstLba; - lba_t* List = Cache->CachedModifiedBlocksList; - lba_t Lba; -// ULONG firstPos; -// ULONG lastPos; - ULONG BSh = Cache->BlockSizeSh; - ULONG BS = Cache->BlockSize; - ULONG PS = BS << Cache->PacketSizeSh; // packet size (bytes) - ULONG PSs = Cache->PacketSize; - ULONG BFs = Cache->BlocksPerFrameSh; - PW_CACHE_ENTRY block_array; -// NTSTATUS status; - SIZE_T ReadBytes; - PW_CACHE_ASYNC FirstWContext = NULL; - PW_CACHE_ASYNC PrevWContext = NULL; - ULONG i; - ULONG chain_count = 0; - lba_t lim; - - if (!(Cache->ReadProc)) return STATUS_INVALID_PARAMETER; - - // walk through modified blocks - lim = (_Lba+BCount+PSs-1) & ~(PSs-1); - for(Lba = _Lba & ~(PSs-1);Lba < lim ; Lba += PSs) { - frame = Lba >> BFs; - firstLba = frame << BFs; -// firstPos = WCacheGetSortedListIndex(Cache->WriteCount, List, Lba); -// lastPos = WCacheGetSortedListIndex(Cache->WriteCount, List, Lba+PSs); - block_array = Cache->FrameList[frame].Frame; - if (!block_array) { - // not cached block may be requested for flush - Lba += (1 << BFs) - PSs; - continue; - } - // queue modify request - WCacheUpdatePacket(IrpContext, Cache, Context, &FirstWContext, &PrevWContext, block_array, firstLba, - Lba, BSh, BS, PS, PSs, &ReadBytes, TRUE, ASYNC_STATE_NONE); - // clear MODIFIED flag for queued blocks - WCacheRemoveRangeFromList(List, &(Cache->WriteCount), Lba, PSs); - Lba -= firstLba; - for(i=0; i= WCACHE_MAX_CHAIN) { - WCacheUpdatePacketComplete(IrpContext, Cache, Context, &FirstWContext, &PrevWContext, FALSE); - chain_count = 0; - } - } - WCacheUpdatePacketComplete(IrpContext, Cache, Context, &FirstWContext, &PrevWContext, FALSE); -/* - if (Cache->Mode != WCACHE_MODE_RAM) - return STATUS_SUCCESS; -*/ - - return STATUS_SUCCESS; -} // end WCacheFlushBlocksRW() - -/* - WCacheFlushBlocks__() copies specified blocks stored in cache to media. - Flushed blocks are kept in cache. - Public routine - */ -NTSTATUS -WCacheFlushBlocks__( - IN PIRP_CONTEXT IrpContext, - IN PW_CACHE Cache, // pointer to the Cache Control structure - IN PVOID Context, // user-supplied context for IO callbacks - IN lba_t Lba, // LBA to start flush from - IN ULONG BCount // number of blocks to be flushed - ) -{ - NTSTATUS status = STATUS_INVALID_PARAMETER; - - if (!(Cache->ReadProc)) return STATUS_INVALID_PARAMETER; - ExAcquireResourceExclusiveLite(&(Cache->WCacheLock), TRUE); - - // check if we try to access beyond cached area - if ((Lba < Cache->FirstLba) || - (Lba+BCount-1 > Cache->LastLba)) { - UDFPrint(("LBA %#x (%x) is beyond cacheable area\n", Lba, BCount)); - BrutePoint(); - status = STATUS_INVALID_PARAMETER; - goto EO_WCache_F; - } - - switch(Cache->Mode) { - case WCACHE_MODE_RAM: -// WCacheFlushBlocksRW(Cache, Context); -// break; - case WCACHE_MODE_ROM: - case WCACHE_MODE_RW: - status = WCacheFlushBlocksRW(IrpContext, Cache, Context, Lba, BCount); - break; - case WCACHE_MODE_R: - status = STATUS_SUCCESS; - break; - } -EO_WCache_F: - ExReleaseResourceForThreadLite(&(Cache->WCacheLock), ExGetCurrentResourceThread()); - return status; -} // end WCacheFlushBlocks__() - -/* - WCacheDirect__() returns pointer to memory block where - requested block is stored in. - If no #CachedOnly flag specified this routine locks cache, - otherwise it assumes that cache is already locked by previous call - to WCacheStartDirect__(). - Cache can be unlocked by WCacheEODirect__(). - Using this routine caller can access cached block directly in memory - without Read_to_Tmp and Modify/Write steps. - Public routine - */ -NTSTATUS -WCacheDirect__( - IN PIRP_CONTEXT IrpContext, - IN PW_CACHE Cache, // pointer to the Cache Control structure - IN PVOID Context, // user-supplied context for IO callbacks - IN lba_t Lba, // LBA of block to get pointer to - IN BOOLEAN Modified, // indicates that block will be modified - OUT PCHAR* CachedBlock, // address for pointer to cached block to be stored in - IN BOOLEAN CachedOnly // specifies that cache is already locked - ) -{ - ULONG frame; - ULONG i; - NTSTATUS status = STATUS_SUCCESS; - PW_CACHE_ENTRY block_array; - ULONG BS = Cache->BlockSize; - PCHAR addr; - SIZE_T _ReadBytes; - ULONG block_type; - - WcPrint(("WC:%sD %x (1)\n", Modified ? "W" : "R", Lba)); - - // lock cache if nececcary - if (!CachedOnly) { - ExAcquireResourceExclusiveLite(&(Cache->WCacheLock), TRUE); - } - // check if we try to access beyond cached area - if ((Lba < Cache->FirstLba) || - (Lba > Cache->LastLba)) { - UDFPrint(("LBA %#x is beyond cacheable area\n", Lba)); - BrutePoint(); - status = STATUS_INVALID_PARAMETER; - goto EO_WCache_D; - } - - frame = Lba >> Cache->BlocksPerFrameSh; - i = Lba - (frame << Cache->BlocksPerFrameSh); - // check if we have enough space to store requested block - if (!CachedOnly && - !NT_SUCCESS(status = WCacheCheckLimits(IrpContext, Cache, Context, Lba, 1))) { - BrutePoint(); - goto EO_WCache_D; - } - - // small updates are more important - block_array = Cache->FrameList[frame].Frame; - if (Modified) { - Cache->FrameList[frame].UpdateCount+=8; - } else { - Cache->FrameList[frame].AccessCount+=8; - } - if (!block_array) { - ASSERT(Cache->FrameCount < Cache->MaxFrames); - block_array = WCacheInitFrame(IrpContext, Cache, Context, frame); - if (!block_array) { - status = STATUS_INSUFFICIENT_RESOURCES; - goto EO_WCache_D; - } - } - // check if requested block is already cached - if ( !(addr = (PCHAR)WCacheSectorAddr(block_array, i)) ) { - // block is not cached - // allocate memory and read block from media - // do not set block_array[i].Sector here, because if media access fails and recursive access to cache - // comes, this block should not be marked as 'cached' - addr = (PCHAR)DbgAllocatePoolWithTag(CACHED_BLOCK_MEMORY_TYPE, BS, MEM_WCBUF_TAG); - if (!addr) { - status = STATUS_INSUFFICIENT_RESOURCES; - goto EO_WCache_D; - } - block_type = Cache->CheckUsedProc(Context, Lba); - if (block_type == WCACHE_BLOCK_USED) { - status = Cache->ReadProc(IrpContext, Context, addr, BS, Lba, &_ReadBytes, PH_TMP_BUFFER); - if (Cache->RememberBB) { - if (!NT_SUCCESS(status)) { - RtlZeroMemory(addr, BS); - //WCacheSetBadFlag(block_array,i); - } - } - } else { - if (block_type & WCACHE_BLOCK_BAD) { - DbgFreePool(addr); - addr = NULL; - status = STATUS_DEVICE_DATA_ERROR; - goto EO_WCache_D; - } - if (!(block_type & WCACHE_BLOCK_ZERO)) { - BrutePoint(); - } - status = STATUS_SUCCESS; - RtlZeroMemory(addr, BS); - } - // now add pointer to buffer to common storage - ASSERT(block_array[i].Sector == NULL); - block_array[i].Sector = addr; - WCacheInsertItemToList(Cache->CachedBlocksList, &(Cache->BlockCount), Lba); - if (Modified) { - WCacheInsertItemToList(Cache->CachedModifiedBlocksList, &(Cache->WriteCount), Lba); - WCacheSetModFlag(block_array, i); - } - Cache->FrameList[frame].BlockCount ++; - ASSERT(ValidateFrameBlocksList(Cache, Lba)); - } else { - // block is not cached - // just return pointer - block_type = Cache->CheckUsedProc(Context, Lba); - if (block_type & WCACHE_BLOCK_BAD) { - //if (WCacheGetBadFlag(block_array,i)) { - // bad packet. no pre-read - status = STATUS_DEVICE_DATA_ERROR; - goto EO_WCache_D; - } -#ifndef UDF_CHECK_UTIL - ASSERT(block_type & WCACHE_BLOCK_USED); -#else - if (!(block_type & WCACHE_BLOCK_USED)) { - UDFPrint(("LBA %#x is not marked as used\n", Lba)); - } -#endif - if (Modified && - !WCacheGetModFlag(block_array, i)) { - WCacheInsertItemToList(Cache->CachedModifiedBlocksList, &(Cache->WriteCount), Lba); - WCacheSetModFlag(block_array, i); - } - } - (*CachedBlock) = addr; - -EO_WCache_D: - - return status; -} // end WCacheDirect__() - -/* - WCacheEODirect__() must be used to unlock cache after calls to - to WCacheStartDirect__(). - Public routine - */ -NTSTATUS -WCacheEODirect__( - IN PW_CACHE Cache, // pointer to the Cache Control structure - IN PVOID Context // user-supplied context for IO callbacks - ) -{ - ExReleaseResourceForThreadLite(&(Cache->WCacheLock), ExGetCurrentResourceThread()); - return STATUS_SUCCESS; -} // end WCacheEODirect__() - -/* - WCacheStartDirect__() locks cache for exclusive use. - Using this routine caller can access cached block directly in memory - without Read_to_Tmp and Modify/Write steps. - See also WCacheDirect__() - Cache can be unlocked by WCacheEODirect__(). - Public routine - */ -NTSTATUS -WCacheStartDirect__( - IN PW_CACHE Cache, // pointer to the Cache Control structure - IN PVOID Context, // user-supplied context for IO callbacks - IN BOOLEAN Exclusive // lock cache for exclusive use, - // currently must be TRUE. - ) -{ - if (Exclusive) { - ExAcquireResourceExclusiveLite(&(Cache->WCacheLock), TRUE); - } else { - BrutePoint(); - ExAcquireResourceSharedLite(&(Cache->WCacheLock), TRUE); - } - return STATUS_SUCCESS; -} // end WCacheStartDirect__() - -/* - WCacheIsCached__() checks if requested blocks are immediately available. - Cache must be previously locked for exclusive use with WCacheStartDirect__(). - Using this routine caller can access cached block directly in memory - without Read_to_Tmp and Modify/Write steps. - See also WCacheDirect__(). - Cache can be unlocked by WCacheEODirect__(). - Public routine - */ -BOOLEAN -WCacheIsCached__( - IN PW_CACHE Cache, // pointer to the Cache Control structure - IN lba_t Lba, // LBA to start check from - IN ULONG BCount // number of blocks to be checked - ) -{ - ULONG frame; - ULONG i; - PW_CACHE_ENTRY block_array; - - // check if we try to access beyond cached area - if ((Lba < Cache->FirstLba) || - (Lba + BCount - 1 > Cache->LastLba)) { - return FALSE; - } - - frame = Lba >> Cache->BlocksPerFrameSh; - i = Lba - (frame << Cache->BlocksPerFrameSh); - - block_array = Cache->FrameList[frame].Frame; - if (!block_array) { - return FALSE; - } - - while(BCount) { - if (i >= Cache->BlocksPerFrame) { - frame++; - block_array = Cache->FrameList[frame].Frame; - i -= Cache->BlocksPerFrame; - } - if (!block_array) { - return FALSE; - } - // 'read' cached extent (if any) - while(BCount && - (i < Cache->BlocksPerFrame) && - WCacheSectorAddr(block_array, i) && - /*!WCacheGetBadFlag(block_array, i)*/ - /*!(Cache->CheckUsedProc(Context, Lba) & WCACHE_BLOCK_BAD)*/ - TRUE ) { - i++; - BCount--; - Lba++; - } - if (BCount && - (i < Cache->BlocksPerFrame) /*&& - (!WCacheSectorAddr(block_array, i))*/ ) { - return FALSE; - } - } - return TRUE; -} // end WCacheIsCached__() - -/* - WCacheCheckLimitsR() implements automatic flush and purge of - unused blocks to keep enough free cache entries for newly - read/written blocks for WORM media. - See also WCacheCheckLimits() - Internal routine - */ -NTSTATUS -__fastcall -WCacheCheckLimitsR( - IN PIRP_CONTEXT IrpContext, - IN PW_CACHE Cache, // pointer to the Cache Control structure - IN PVOID Context, // user-supplied context for IO callbacks - IN lba_t ReqLba, // first LBA to access/cache - IN ULONG BCount // number of Blocks to access/cache - ) -{ - ULONG frame; - lba_t firstLba; - lba_t* List = Cache->CachedBlocksList; - lba_t Lba; - PCHAR tmp_buff = Cache->tmp_buff; - ULONG firstPos; - ULONG BSh = Cache->BlockSizeSh; - ULONG BS = Cache->BlockSize; - ULONG PS = BS << Cache->PacketSizeSh; // packet size (bytes) - ULONG PSs = Cache->PacketSize; - ULONG i; - PW_CACHE_ENTRY block_array; - BOOLEAN mod; - NTSTATUS status; - SIZE_T ReadBytes; - ULONG MaxReloc = Cache->PacketSize; - PULONG reloc_tab = Cache->reloc_tab; - - // check if we try to read too much data - if (BCount > Cache->MaxBlocks) { - return STATUS_INVALID_PARAMETER; - } - - // remove(flush) packets from entire frame(s) - while( ((Cache->BlockCount + WCacheGetSortedListIndex(Cache->BlockCount, List, ReqLba) + - BCount - WCacheGetSortedListIndex(Cache->BlockCount, List, ReqLba+BCount)) > Cache->MaxBlocks) || - (Cache->FrameCount >= Cache->MaxFrames) ) { - -WCCL_retry_1: - - Lba = WCacheFindLbaToRelease(Cache); - if (Lba == WCACHE_INVALID_LBA) { - ASSERT(!Cache->FrameCount); - ASSERT(!Cache->BlockCount); - break; - } - frame = Lba >> Cache->BlocksPerFrameSh; - firstLba = frame << Cache->BlocksPerFrameSh; - firstPos = WCacheGetSortedListIndex(Cache->BlockCount, List, Lba); - block_array = Cache->FrameList[frame].Frame; - if (!block_array) { - return STATUS_DRIVER_INTERNAL_ERROR; - } - // check if modified - mod = WCacheGetModFlag(block_array, Lba - firstLba); - // read/modify/write - if (mod && (Cache->CheckUsedProc(Context, Lba) & WCACHE_BLOCK_USED)) { - if (Cache->WriteCount < MaxReloc) goto WCCL_retry_1; - firstPos = WCacheGetSortedListIndex(Cache->WriteCount, Cache->CachedModifiedBlocksList, Lba); - if (!block_array) { - return STATUS_DRIVER_INTERNAL_ERROR; - } - // prepare packet & reloc table - for(i=0; iCachedModifiedBlocksList[firstPos]; - frame = Lba >> Cache->BlocksPerFrameSh; - firstLba = frame << Cache->BlocksPerFrameSh; - block_array = Cache->FrameList[frame].Frame; - DbgCopyMemory(tmp_buff + (i << BSh), - (PVOID)WCacheSectorAddr(block_array, Lba-firstLba), - BS); - reloc_tab[i] = Lba; - WCacheRemoveItemFromList(List, &(Cache->BlockCount), Lba); - WCacheRemoveItemFromList(Cache->CachedModifiedBlocksList, &(Cache->WriteCount), Lba); - // mark as non-cached & free pool - WCacheFreeSector(frame, Lba-firstLba); - ASSERT(ValidateFrameBlocksList(Cache, Lba)); - // check if frame is empty - if (!Cache->FrameList[frame].BlockCount) { - WCacheRemoveFrame(Cache, Context, frame); - } - if (firstPos >= Cache->WriteCount) firstPos=0; - } - // write packet -// status = Cache->WriteProcAsync(Context, tmp_buff, PS, Lba, &ReadBytes, FALSE); - Cache->UpdateRelocProc(Context, NULL, reloc_tab, MaxReloc); - status = Cache->WriteProc(IrpContext, Context, tmp_buff, PS, NULL, &ReadBytes, 0); - if (!NT_SUCCESS(status)) { - status = WCacheRaiseIoError(Cache, Context, status, NULL, PSs, tmp_buff, WCACHE_W_OP, NULL); - } - } else { - - if ((i = Cache->BlockCount - Cache->WriteCount) > MaxReloc) i = MaxReloc; - // discard blocks - for(; i; i--) { - Lba = List[firstPos]; - frame = Lba >> Cache->BlocksPerFrameSh; - firstLba = frame << Cache->BlocksPerFrameSh; - block_array = Cache->FrameList[frame].Frame; - - if ( (mod = WCacheGetModFlag(block_array, Lba - firstLba)) && - (Cache->CheckUsedProc(Context, Lba) & WCACHE_BLOCK_USED) ) - continue; - WCacheRemoveItemFromList(List, &(Cache->BlockCount), Lba); - if (mod) - WCacheRemoveItemFromList(Cache->CachedModifiedBlocksList, &(Cache->WriteCount), Lba); - // mark as non-cached & free pool - WCacheFreeSector(frame, Lba-firstLba); - ASSERT(ValidateFrameBlocksList(Cache, Lba)); - // check if frame is empty - if (!Cache->FrameList[frame].BlockCount) { - WCacheRemoveFrame(Cache, Context, frame); - } - if (firstPos >= Cache->WriteCount) firstPos=0; - } - } - } - return STATUS_SUCCESS; -} // end WCacheCheckLimitsR() - -/* - WCachePurgeAllR() copies modified blocks from cache to media - and removes them from cache - This routine can be used for R media only. - Internal routine - */ -VOID -__fastcall -WCachePurgeAllR( - IN PIRP_CONTEXT IrpContext, - IN PW_CACHE Cache, // pointer to the Cache Control structure - IN PVOID Context) // user-supplied context for IO callbacks -{ - ULONG frame; - lba_t firstLba; - lba_t* List = Cache->CachedBlocksList; - lba_t Lba; - PCHAR tmp_buff = Cache->tmp_buff; - ULONG BSh = Cache->BlockSizeSh; - ULONG BS = Cache->BlockSize; -// ULONG PS = BS << Cache->PacketSizeSh; // packet size (bytes) -// ULONG PSs = Cache->PacketSize; - PW_CACHE_ENTRY block_array; - BOOLEAN mod; - NTSTATUS status; - SIZE_T ReadBytes; - ULONG MaxReloc = Cache->PacketSize; - PULONG reloc_tab = Cache->reloc_tab; - ULONG RelocCount = 0; - BOOLEAN IncompletePacket; - ULONG i=0; - ULONG PacketTail; - - while(Cache->WriteCount < Cache->BlockCount) { - - Lba = List[i]; - frame = Lba >> Cache->BlocksPerFrameSh; - firstLba = frame << Cache->BlocksPerFrameSh; - block_array = Cache->FrameList[frame].Frame; - if (!block_array) { - BrutePoint(); - return; - } - // check if modified - mod = WCacheGetModFlag(block_array, Lba - firstLba); - // just discard - if (!mod || !(Cache->CheckUsedProc(Context, Lba) & WCACHE_BLOCK_USED)) { - // mark as non-cached & free pool - if (WCacheSectorAddr(block_array,Lba-firstLba)) { - WCacheRemoveItemFromList(List, &(Cache->BlockCount), Lba); - if (mod) - WCacheRemoveItemFromList(Cache->CachedModifiedBlocksList, &(Cache->WriteCount), Lba); - // mark as non-cached & free pool - WCacheFreeSector(frame, Lba-firstLba); - ASSERT(ValidateFrameBlocksList(Cache, Lba)); - // check if frame is empty - if (!Cache->FrameList[frame].BlockCount) { - WCacheRemoveFrame(Cache, Context, frame); - } - } else { - BrutePoint(); - } - } else { - i++; - } - } - - PacketTail = Cache->WriteCount & (MaxReloc-1); - IncompletePacket = (Cache->WriteCount >= MaxReloc) ? FALSE : TRUE; - - // remove(flush) packet - while((Cache->WriteCount > PacketTail) || (Cache->WriteCount && IncompletePacket)) { - - Lba = List[0]; - frame = Lba >> Cache->BlocksPerFrameSh; - firstLba = frame << Cache->BlocksPerFrameSh; - block_array = Cache->FrameList[frame].Frame; - if (!block_array) { - BrutePoint(); - return; - } - // check if modified - mod = WCacheGetModFlag(block_array, Lba - firstLba); - // pack/reloc/write - if (mod) { - DbgCopyMemory(tmp_buff + (RelocCount << BSh), - (PVOID)WCacheSectorAddr(block_array, Lba-firstLba), - BS); - reloc_tab[RelocCount] = Lba; - RelocCount++; - // write packet - if ((RelocCount >= MaxReloc) || (Cache->BlockCount == 1)) { -// status = Cache->WriteProcAsync(Context, tmp_buff, PS, Lba, &ReadBytes, FALSE); - Cache->UpdateRelocProc(Context, NULL, reloc_tab, RelocCount); - status = Cache->WriteProc(IrpContext, Context, tmp_buff, RelocCount<CachedModifiedBlocksList, &(Cache->WriteCount), Lba); - } else { - BrutePoint(); - } - // mark as non-cached & free pool - if (WCacheSectorAddr(block_array,Lba-firstLba)) { - WCacheRemoveItemFromList(List, &(Cache->BlockCount), Lba); - // mark as non-cached & free pool - WCacheFreeSector(frame, Lba-firstLba); - ASSERT(ValidateFrameBlocksList(Cache, Lba)); - // check if frame is empty - if (!Cache->FrameList[frame].BlockCount) { - WCacheRemoveFrame(Cache, Context, frame); - } - } else { - BrutePoint(); - } - } -} // end WCachePurgeAllR() - -/* - WCacheSetMode__() changes cache operating mode (ROM/R/RW/RAM). - Public routine - */ -NTSTATUS -WCacheSetMode__( - IN PW_CACHE Cache, // pointer to the Cache Control structure - IN ULONG Mode // cache mode/media type to be used - ) -{ - if (Mode > WCACHE_MODE_MAX) return STATUS_INVALID_PARAMETER; - Cache->Mode = Mode; - return STATUS_SUCCESS; -} // end WCacheSetMode__() - -/* - WCacheGetMode__() returns cache operating mode (ROM/R/RW/RAM). - Public routine - */ -ULONG -WCacheGetMode__( - IN PW_CACHE Cache - ) -{ - return Cache->Mode; -} // end WCacheGetMode__() - -/* - WCacheGetWriteBlockCount__() returns number of modified blocks, those are - not flushed to media. Is usually used to preallocate blocks for - relocation table on WORM (R) media. - Public routine - */ -ULONG -WCacheGetWriteBlockCount__( - IN PW_CACHE Cache - ) -{ - return Cache->WriteCount; -} // end WCacheGetWriteBlockCount__() - -/* - WCacheSyncReloc__() builds list of all modified blocks, currently - stored in cache. For each modified block WCacheSyncReloc__() calls - user-supplied callback routine in order to update relocation table - on WORM (R) media. - Public routine - */ -VOID -WCacheSyncReloc__( - IN PW_CACHE Cache, - IN PVOID Context) -{ - ULONG frame; - lba_t firstLba; - lba_t* List = Cache->CachedBlocksList; - lba_t Lba; -// ULONG BSh = Cache->BlockSizeSh; -// ULONG BS = Cache->BlockSize; -// ULONG PS = BS << Cache->PacketSizeSh; // packet size (bytes) -// ULONG PSs = Cache->PacketSize; - PW_CACHE_ENTRY block_array; - BOOLEAN mod; - ULONG MaxReloc = Cache->PacketSize; - PULONG reloc_tab = Cache->reloc_tab; - ULONG RelocCount = 0; - BOOLEAN IncompletePacket; - - IncompletePacket = (Cache->WriteCount >= MaxReloc) ? FALSE : TRUE; - // enumerate modified blocks - for(ULONG i=0; IncompletePacket && (iBlockCount); i++) { - - Lba = List[i]; - frame = Lba >> Cache->BlocksPerFrameSh; - firstLba = frame << Cache->BlocksPerFrameSh; - block_array = Cache->FrameList[frame].Frame; - if (!block_array) { - return; - } - // check if modified - mod = WCacheGetModFlag(block_array, Lba - firstLba); - // update relocation table for modified sectors - if (mod && (Cache->CheckUsedProc(Context, Lba) & WCACHE_BLOCK_USED)) { - reloc_tab[RelocCount] = Lba; - RelocCount++; - if (RelocCount >= Cache->WriteCount) { - Cache->UpdateRelocProc(Context, NULL, reloc_tab, RelocCount); - break; - } - } - } -} // end WCacheSyncReloc__() - -/* - WCacheDiscardBlocks__() removes specified blocks from cache. - Blocks are not flushed to media. - Public routine - */ -VOID -WCacheDiscardBlocks__( - IN PW_CACHE Cache, - IN PVOID Context, - IN lba_t ReqLba, - IN ULONG BCount - ) -{ - ULONG frame; - lba_t firstLba; - lba_t* List; - lba_t Lba; - PW_CACHE_ENTRY block_array; - BOOLEAN mod; - ULONG i; - - ExAcquireResourceExclusiveLite(&(Cache->WCacheLock), TRUE); - - UDFPrint((" Discard req: %x@%x\n",BCount, ReqLba)); - - List = Cache->CachedBlocksList; - if (!List) { - ExReleaseResourceForThreadLite(&(Cache->WCacheLock), ExGetCurrentResourceThread()); - return; - } - i = WCacheGetSortedListIndex(Cache->BlockCount, List, ReqLba); - - // enumerate requested blocks - while((List[i] < (ReqLba+BCount)) && (i < Cache->BlockCount)) { - - Lba = List[i]; - frame = Lba >> Cache->BlocksPerFrameSh; - firstLba = frame << Cache->BlocksPerFrameSh; - block_array = Cache->FrameList[frame].Frame; - if (!block_array) { - ExReleaseResourceForThreadLite(&(Cache->WCacheLock), ExGetCurrentResourceThread()); - BrutePoint(); - return; - } - // check if modified - mod = WCacheGetModFlag(block_array, Lba - firstLba); - // just discard - - // mark as non-cached & free pool - if (WCacheSectorAddr(block_array,Lba-firstLba)) { - WCacheRemoveItemFromList(List, &(Cache->BlockCount), Lba); - if (mod) - WCacheRemoveItemFromList(Cache->CachedModifiedBlocksList, &(Cache->WriteCount), Lba); - // mark as non-cached & free pool - WCacheFreeSector(frame, Lba-firstLba); - ASSERT(ValidateFrameBlocksList(Cache, Lba)); - // check if frame is empty - if (!Cache->FrameList[frame].BlockCount) { - WCacheRemoveFrame(Cache, Context, frame); - } else { - ASSERT(Cache->FrameList[frame].Frame); - } - } else { - // we should never get here !!! - // getting this part of code means that we have - // placed non-cached block in CachedBlocksList - BrutePoint(); - } - } - ExReleaseResourceForThreadLite(&(Cache->WCacheLock), ExGetCurrentResourceThread()); -} // end WCacheDiscardBlocks__() - -NTSTATUS -WCacheCompleteAsync__( - IN PVOID WContext, - IN NTSTATUS Status - ) -{ - PW_CACHE_ASYNC AsyncCtx = (PW_CACHE_ASYNC)WContext; -// PW_CACHE Cache = AsyncCtx->Cache; - - AsyncCtx->PhContext.IosbToUse.Status = Status; - KeSetEvent(&(AsyncCtx->PhContext.event), 0, FALSE); - - return STATUS_SUCCESS; -} // end WCacheSetMode__() - -/* - WCacheDecodeFlags() updates internal BOOLEANs according to Flags - Internal routine - */ -NTSTATUS -__fastcall -WCacheDecodeFlags( - IN PW_CACHE Cache, // pointer to the Cache Control structure - IN ULONG Flags // cache mode flags - ) -{ - //ULONG OldFlags; - if (Flags & ~WCACHE_VALID_FLAGS) { - UDFPrint(("Invalid flags: %x\n", Flags & ~WCACHE_VALID_FLAGS)); - return STATUS_INVALID_PARAMETER; - } - Cache->CacheWholePacket = (Flags & WCACHE_CACHE_WHOLE_PACKET) ? TRUE : FALSE; - Cache->DoNotCompare = (Flags & WCACHE_DO_NOT_COMPARE) ? TRUE : FALSE; - Cache->Chained = (Flags & WCACHE_CHAINED_IO) ? TRUE : FALSE; - Cache->RememberBB = (Flags & WCACHE_MARK_BAD_BLOCKS) ? TRUE : FALSE; - if (Cache->RememberBB) { - Cache->NoWriteBB = (Flags & WCACHE_RO_BAD_BLOCKS) ? TRUE : FALSE; - } - Cache->NoWriteThrough = (Flags & WCACHE_NO_WRITE_THROUGH) ? TRUE : FALSE; - - Cache->Flags = Flags; - - return STATUS_SUCCESS; -} - -/* - WCacheChFlags__() changes cache flags. - Public routine - */ -ULONG -WCacheChFlags__( - IN PW_CACHE Cache, // pointer to the Cache Control structure - IN ULONG SetFlags, // cache mode/media type to be set - IN ULONG ClrFlags // cache mode/media type to be cleared - ) -{ - ULONG Flags; - - if (SetFlags || ClrFlags) { - Flags = (Cache->Flags & ~ClrFlags) | SetFlags; - - if (!NT_SUCCESS(WCacheDecodeFlags(Cache, Flags))) { - return -1; - } - } else { - return Cache->Flags; - } - return Flags; -} // end WCacheSetMode__() - -BOOLEAN -ValidateFrameBlocksList( - IN PW_CACHE Cache, - IN lba_t Lba) -{ - ULONG Frame = Lba >> Cache->BlocksPerFrameSh; - lba_t FirstLba = Frame << Cache->BlocksPerFrameSh; - lba_t LastLba = FirstLba + Cache->BlocksPerFrame; - ULONG FirstPos = WCacheGetSortedListIndex(Cache->BlockCount, Cache->CachedBlocksList, FirstLba); - ULONG LastPos = WCacheGetSortedListIndex(Cache->BlockCount, Cache->CachedBlocksList, LastLba); - - ULONG BlockCount = Cache->FrameList[Frame].BlockCount; - ULONG RangeSize = LastPos - FirstPos; - - return (BlockCount == RangeSize); -} diff --git a/drivers/filesystems/udfs/Include/wcache_lib.h b/drivers/filesystems/udfs/Include/wcache_lib.h deleted file mode 100644 index 22a35a821a8e0..0000000000000 --- a/drivers/filesystems/udfs/Include/wcache_lib.h +++ /dev/null @@ -1,340 +0,0 @@ -//////////////////////////////////////////////////////////////////// -// Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine -// All rights reserved -// This file was released under the GPLv2 on June 2015. -//////////////////////////////////////////////////////////////////// - -#ifndef __CDRW_WCACHE_LIB_H__ -#define __CDRW_WCACHE_LIB_H__ - -extern "C" { - -#include "platform.h" - -#define WCACHE_BOUND_CHECKS - -struct IRP_CONTEXT; -typedef struct IRP_CONTEXT *PIRP_CONTEXT; - -typedef NTSTATUS (*PWRITE_BLOCK) (IN PIRP_CONTEXT IrpContext, - IN PVOID Context, - IN PVOID Buffer, // Target buffer - IN SIZE_T Length, - IN lba_t Lba, - OUT PSIZE_T WrittenBytes, - IN uint32 Flags); - -typedef NTSTATUS (*PREAD_BLOCK) (IN PIRP_CONTEXT IrpContext, - IN PVOID Context, - IN PVOID Buffer, // Target buffer - IN SIZE_T Length, - IN lba_t Lba, - OUT PSIZE_T ReadBytes, - IN uint32 Flags); - -typedef NTSTATUS (*PWRITE_BLOCK_ASYNC) (IN PVOID Context, - IN PVOID WContext, - IN PVOID Buffer, // Target buffer - IN SIZE_T Length, - IN lba_t Lba, - OUT PSIZE_T WrittenBytes, - IN BOOLEAN FreeBuffer); - -typedef NTSTATUS (*PREAD_BLOCK_ASYNC) (IN PVOID Context, - IN PVOID WContext, - IN PVOID Buffer, // Source buffer - IN SIZE_T Length, - IN lba_t Lba, - OUT PSIZE_T ReadBytes); - -/*typedef BOOLEAN (*PCHECK_BLOCK) (IN PVOID Context, - IN lba_t Lba);*/ - -#define WCACHE_BLOCK_USED 0x01 -#define WCACHE_BLOCK_ZERO 0x02 -#define WCACHE_BLOCK_BAD 0x04 - -typedef ULONG (*PCHECK_BLOCK) (IN PVOID Context, - IN lba_t Lba); - -typedef NTSTATUS (*PUPDATE_RELOC) (IN PVOID Context, - IN lba_t Lba, - IN PULONG RelocTab, - IN ULONG BCount); - -#define WCACHE_ERROR_READ 0x0001 -#define WCACHE_ERROR_WRITE 0x0002 -#define WCACHE_ERROR_INTERNAL 0x0003 - -#define WCACHE_W_OP FALSE -#define WCACHE_R_OP TRUE - -typedef struct _WCACHE_ERROR_CONTEXT { - ULONG WCErrorCode; - NTSTATUS Status; - BOOLEAN Retry; - UCHAR Padding[3]; - union { - struct { - ULONG Lba; - ULONG BCount; - PVOID Buffer; - } ReadWrite; - struct { - ULONG p1; - ULONG p2; - ULONG p3; - ULONG p4; - } Internal; - }; -} WCACHE_ERROR_CONTEXT, *PWCACHE_ERROR_CONTEXT; - -typedef NTSTATUS (*PWC_ERROR_HANDLER) (IN PVOID Context, - IN PWCACHE_ERROR_CONTEXT ErrorInfo); -// array of pointers to cached data -// each entry corresponds to logical block on disk -typedef struct _W_CACHE_ENTRY { - union { - PCHAR Sector; - UCHAR Flags:3; - }; -} W_CACHE_ENTRY, *PW_CACHE_ENTRY; - -// array of pointers to cache frames -// each frame corresponds to extent of logical blocks -typedef struct _W_CACHE_FRAME { - PW_CACHE_ENTRY Frame; - ULONG BlockCount; - //ULONG WriteCount; // number of modified packets in cache frame, is always 0, shall be removed - ULONG UpdateCount; // number of updates in cache frame - ULONG AccessCount; // number of accesses to cache frame -} W_CACHE_FRAME, *PW_CACHE_FRAME; - -// memory type for cached blocks -#define CACHED_BLOCK_MEMORY_TYPE PagedPool -#define MAX_TRIES_FOR_NA 3 - -#ifdef _WIN64 - #define WCACHE_ADDR_MASK 0xfffffffffffffff8 -#else - #define WCACHE_ADDR_MASK 0xfffffff8 -#endif -#define WCACHE_FLAG_MASK 0x00000007 -#define WCACHE_FLAG_MODIFIED 0x00000001 -#define WCACHE_FLAG_ZERO 0x00000002 -#define WCACHE_FLAG_BAD 0x00000004 - -#define WCACHE_MODE_ROM 0x00000000 // read only (CD-ROM) -#define WCACHE_MODE_RW 0x00000001 // rewritable (CD-RW) -#define WCACHE_MODE_R 0x00000002 // WORM (CD-R) -#define WCACHE_MODE_RAM 0x00000003 // random writable device (HDD) -#define WCACHE_MODE_EWR 0x00000004 // ERASE-cycle required (MO) -#define WCACHE_MODE_MAX WCACHE_MODE_RAM - -#define PH_TMP_BUFFER 1 - -struct _W_CACHE_ASYNC; - -typedef struct _W_CACHE { - // cache tables - ULONG Tag; - PW_CACHE_FRAME FrameList; // pointer to list of Frames - lba_t* CachedBlocksList; // sorted list of cached blocks - lba_t* CachedFramesList; // sorted list of cached frames - lba_t* CachedModifiedBlocksList; // sorted list of cached modified blocks - // settings & current state - ULONG BlocksPerFrame; - ULONG BlocksPerFrameSh; - ULONG BlockCount; - ULONG MaxBlocks; - ULONG MaxBytesToRead; - ULONG FrameCount; - ULONG MaxFrames; - ULONG PacketSize; // number of blocks in packet - ULONG PacketSizeSh; - ULONG BlockSize; - ULONG BlockSizeSh; - ULONG WriteCount; // number of modified packets in cache - lba_t FirstLba; - lba_t LastLba; - ULONG Mode; // RO/WOR/RW/EWR - - ULONG Flags; - BOOLEAN CacheWholePacket; - BOOLEAN DoNotCompare; - BOOLEAN Chained; - BOOLEAN RememberBB; - BOOLEAN NoWriteBB; - BOOLEAN NoWriteThrough; - UCHAR Padding[2]; - - ULONG RBalance; - ULONG WBalance; - ULONG FramesToKeepFree; - // callbacks - PWRITE_BLOCK WriteProc; - PREAD_BLOCK ReadProc; - PWRITE_BLOCK_ASYNC WriteProcAsync; - PREAD_BLOCK_ASYNC ReadProcAsync; - PCHECK_BLOCK CheckUsedProc; - PUPDATE_RELOC UpdateRelocProc; - PWC_ERROR_HANDLER ErrorHandlerProc; - // sync resource - ERESOURCE WCacheLock; -// BOOLEAN WCResInit; - // preallocated tmp buffers - PCHAR tmp_buff; - PCHAR tmp_buff_r; - PULONG reloc_tab; - -} W_CACHE, *PW_CACHE; - -#define WCACHE_INVALID_LBA ((lba_t)(-1)) - -#define WCACHE_CACHE_WHOLE_PACKET 0x01 -#define WCACHE_DO_NOT_COMPARE 0x02 -#define WCACHE_CHAINED_IO 0x04 -#define WCACHE_MARK_BAD_BLOCKS 0x08 -#define WCACHE_RO_BAD_BLOCKS 0x10 -#define WCACHE_NO_WRITE_THROUGH 0x20 - -#define WCACHE_VALID_FLAGS (WCACHE_CACHE_WHOLE_PACKET | \ - WCACHE_DO_NOT_COMPARE | \ - WCACHE_CHAINED_IO | \ - WCACHE_MARK_BAD_BLOCKS | \ - WCACHE_RO_BAD_BLOCKS | \ - WCACHE_NO_WRITE_THROUGH) - -#define WCACHE_INVALID_FLAGS (0xffffffff) - -// init cache -NTSTATUS WCacheInit__(IN PW_CACHE Cache, - IN ULONG MaxFrames, - IN ULONG MaxBlocks, - IN SIZE_T MaxBytesToRead, - IN ULONG PacketSizeSh, // number of blocks in packet (bit shift) - IN ULONG BlockSizeSh, // bit shift - IN ULONG BlocksPerFrameSh,// bit shift - IN lba_t FirstLba, - IN lba_t LastLba, - IN ULONG Mode, - IN ULONG Flags, - IN ULONG FramesToKeepFree, - IN PWRITE_BLOCK WriteProc, - IN PREAD_BLOCK ReadProc, - IN PWRITE_BLOCK_ASYNC WriteProcAsync, - IN PREAD_BLOCK_ASYNC ReadProcAsync, - IN PCHECK_BLOCK CheckUsedProc, - IN PUPDATE_RELOC UpdateRelocProc, - IN PWC_ERROR_HANDLER ErrorHandlerProc); - -// write cached -NTSTATUS -WCacheWriteBlocks__( - IN PIRP_CONTEXT IrpContext, - IN PW_CACHE Cache, - IN PVOID Context, - IN PCHAR Buffer, - IN lba_t Lba, - IN ULONG BCount, - OUT PSIZE_T WrittenBytes, - IN BOOLEAN CachedOnly - ); - -// read cached -NTSTATUS -WCacheReadBlocks__( - IN PIRP_CONTEXT IrpContext, - IN PW_CACHE Cache, - IN PVOID Context, - IN PCHAR Buffer, - IN lba_t Lba, - IN ULONG BCount, - OUT PSIZE_T ReadBytes, - IN BOOLEAN CachedOnly - ); - -// flush blocks -NTSTATUS WCacheFlushBlocks__(IN PIRP_CONTEXT IrpContext, - IN PW_CACHE Cache, - IN PVOID Context, - IN lba_t Lba, - IN ULONG BCount); -// discard blocks -VOID WCacheDiscardBlocks__(IN PW_CACHE Cache, - IN PVOID Context, - IN lba_t Lba, - IN ULONG BCount); -// flush whole cache -VOID -WCacheFlushAll__( - IN PIRP_CONTEXT IrpContext, - IN PW_CACHE Cache, - IN PVOID Context - ); - -// purge whole cache -VOID -WCachePurgeAll__( - IN PIRP_CONTEXT IrpContext, - IN PW_CACHE Cache, - IN PVOID Context - ); - -// free structures -VOID WCacheRelease__(IN PW_CACHE Cache); - -// check if initialized -BOOLEAN WCacheIsInitialized__(IN PW_CACHE Cache); - -// direct access to cached data -NTSTATUS -WCacheDirect__( - IN PIRP_CONTEXT IrpContext, - IN PW_CACHE Cache, - IN PVOID Context, - IN lba_t Lba, - IN BOOLEAN Modified, - OUT PCHAR* CachedBlock, - IN BOOLEAN CachedOnly - ); - -// release resources after direct access -NTSTATUS WCacheEODirect__(IN PW_CACHE Cache, - IN PVOID Context); -// release resources before direct access -NTSTATUS WCacheStartDirect__(IN PW_CACHE Cache, - IN PVOID Context, - IN BOOLEAN Exclusive); -// check if requested extent completly cached -BOOLEAN WCacheIsCached__(IN PW_CACHE Cache, - IN lba_t Lba, - IN ULONG BCount); - -// change cache media mode -NTSTATUS WCacheSetMode__(IN PW_CACHE Cache, - IN ULONG Mode); -// -ULONG WCacheGetMode__(IN PW_CACHE Cache); -// -ULONG WCacheGetWriteBlockCount__(IN PW_CACHE Cache); -// -VOID WCacheSyncReloc__(IN PW_CACHE Cache, - IN PVOID Context); - -VOID WCacheDiscardBlocks__(IN PW_CACHE Cache, - IN PVOID Context, - IN lba_t ReqLba, - IN ULONG BCount); - -ULONG WCacheChFlags__(IN PW_CACHE Cache, - IN ULONG SetFlags, - IN ULONG ClrFlags); - -}; - -// complete async request (callback) -NTSTATUS WCacheCompleteAsync__(IN PVOID WContext, - IN NTSTATUS Status); - -#endif // __CDRW_WCACHE_LIB_H__ diff --git a/drivers/filesystems/udfs/cleanup.cpp b/drivers/filesystems/udfs/cleanup.cpp index 22788214d386c..678dcb3e10b5a 100644 --- a/drivers/filesystems/udfs/cleanup.cpp +++ b/drivers/filesystems/udfs/cleanup.cpp @@ -501,11 +501,28 @@ UDFCommonCleanup( ASize = UDFGetFileAllocationSize(Vcb, NextFileInfo); // Fcb->CommonFCBHeader.AllocationSize.QuadPart; UDFSetFileSizeInDirNdx(Vcb, NextFileInfo, &ASize); - } else - if (FileObject->Flags & FO_FILE_SIZE_CHANGED) { + + } else if (FileObject->Flags & FO_FILE_SIZE_CHANGED) { + ASize = //UDFGetFileAllocationSize(Vcb, NextFileInfo); Fcb->Header.AllocationSize.QuadPart; UDFSetFileSizeInDirNdx(Vcb, NextFileInfo, &ASize); + + if (UDFIsAStream(Fcb->FileInfo)) { + + UDFNotifyFullReportChange(Vcb, + Fcb, + FILE_NOTIFY_CHANGE_STREAM_SIZE, + FILE_ACTION_MODIFIED_STREAM); + } + else { + + UDFNotifyFullReportChange(Vcb, + Fcb, + FILE_NOTIFY_CHANGE_SIZE, + FILE_ACTION_MODIFIED); + } + } } // AccessTime diff --git a/drivers/filesystems/udfs/create.cpp b/drivers/filesystems/udfs/create.cpp index a72893b61512f..a7f63b1512a91 100644 --- a/drivers/filesystems/udfs/create.cpp +++ b/drivers/filesystems/udfs/create.cpp @@ -2211,6 +2211,11 @@ UDFFirstOpenFile( UDFUnlockVcb(IrpContext, Vcb); return RC; } + // Set embedded data flag if file data is stored in ICB + if (!UDFIsADirectory(NewFileInfo) && + (((PFILE_ENTRY)(NewFileInfo->Dloc->FileEntry))->icbTag.flags & ICB_FLAG_ALLOC_MASK) == ICB_FLAG_AD_IN_ICB) { + (*PtrNewFcb)->FcbState |= UDF_FCB_EMBEDDED_DATA; + } // set Read-only attribute if (!UDFIsAStreamDir(NewFileInfo)) { hDirIndex = UDFGetDirIndexByFileInfo(NewFileInfo); diff --git a/drivers/filesystems/udfs/env_spec.cpp b/drivers/filesystems/udfs/env_spec.cpp index 22ee33064feef..f0d1c8dcffd34 100644 --- a/drivers/filesystems/udfs/env_spec.cpp +++ b/drivers/filesystems/udfs/env_spec.cpp @@ -123,7 +123,7 @@ UDFPhReadSynchronous( PVOID Buffer, ULONG ByteCount, LONGLONG Offset, - PSIZE_T ReadBytes, + PULONG ReadBytes, ULONG Flags ) { @@ -136,10 +136,6 @@ UDFPhReadSynchronous( PVOID IoBuf = NULL; PVCB Vcb = NULL; - if (Flags & PH_VCB_IN_RETLEN) { - Vcb = (PVCB)(*ReadBytes); - } - ROffset.QuadPart = Offset; (*ReadBytes) = 0; /* @@ -216,17 +212,6 @@ UDFPhReadSynchronous( RtlCopyMemory(Buffer, IoBuf, *ReadBytes); } - if (NT_SUCCESS(RC)) { -/* - for(i=0; i<(*ReadBytes); i+=2048) { - UDFPrint(("IOCRC %8.8x R %x\n", crc32((PUCHAR)Buffer+i, 2048), (ULONG)((Offset+i)/2048) )); - } -*/ - if (Vcb) { - RC = UDFVRead(Vcb, IoBuf, ByteCount >> Vcb->SectorShift, (ULONG)(Offset >> Vcb->SectorShift), Flags); - } - } - try_exit: NOTHING; if (Context) MyFreePool__(Context); @@ -268,10 +253,6 @@ UDFPhWriteSynchronous( PVOID IoBuf = NULL; PVCB Vcb = NULL; - if (Flags & PH_VCB_IN_RETLEN) { - Vcb = (PVCB)(*WrittenBytes); - } - #ifdef DBG if (UDF_SIMULATE_WRITES) { @@ -322,14 +303,6 @@ UDFPhWriteSynchronous( (IoGetNextIrpStackLocation(irp))->Flags |= SL_OVERRIDE_VERIFY_VOLUME; RC = IoCallDriver(DeviceObject, irp); -/* - for(i=0; i> Vcb->SectorShift, (ULONG)(Offset >> Vcb->SectorShift), Flags); - } if (RC == STATUS_PENDING) { DbgWaitForSingleObject(&(Context->event), NULL); diff --git a/drivers/filesystems/udfs/env_spec.h b/drivers/filesystems/udfs/env_spec.h index d2d9236cc5473..69f7b8df43564 100644 --- a/drivers/filesystems/udfs/env_spec.h +++ b/drivers/filesystems/udfs/env_spec.h @@ -26,7 +26,7 @@ UDFPhReadSynchronous( PVOID Buffer, ULONG ByteCount, LONGLONG Offset, - PSIZE_T ReadBytes, + PULONG ReadBytes, ULONG Flags ); diff --git a/drivers/filesystems/udfs/fastio.cpp b/drivers/filesystems/udfs/fastio.cpp index 3709db14a7745..31b3bfac4c051 100644 --- a/drivers/filesystems/udfs/fastio.cpp +++ b/drivers/filesystems/udfs/fastio.cpp @@ -399,12 +399,17 @@ BOOLEAN NTAPI UDFAcqLazyWrite( MmPrint((" UDFAcqLazyWrite()\n")); - // Acquire the MainResource in the NT_REQ_FCB exclusively. Then, set the - // lazy-writer thread id in the NT_REQ_FCB structure for identification - // when an actual write request is received by the FSD. + // Acquire the MainResource in the NT_REQ_FCB. For embedded data files + // (data stored in ICB), acquire exclusively since data shares sector with + // metadata. For normal files, acquire shared to allow concurrent access. // Note: The lazy-writer typically always supplies WAIT set to TRUE. - if (!UDFAcquireResourceExclusive(&Fcb->FcbNonpaged->FcbResource, Wait)) - return FALSE; + if (Fcb->FcbState & UDF_FCB_EMBEDDED_DATA) { + if (!UDFAcquireResourceExclusive(&Fcb->FcbNonpaged->FcbResource, Wait)) + return FALSE; + } else { + if (!UDFAcquireResourceShared(&Fcb->FcbNonpaged->FcbResource, Wait)) + return FALSE; + } // Now, set the lazy-writer thread id. ASSERT(!(Fcb->LazyWriteThread)); @@ -869,14 +874,10 @@ UDFFastIoAcqModWrite( OUT PERESOURCE *ResourceToRelease, IN PDEVICE_OBJECT DeviceObject) { - NTSTATUS RC = STATUS_SUCCESS; - - FsRtlEnterFileSystem(); - - MmPrint((" AcqModW %I64x\n", EndingOffset->QuadPart)); - PFCB Fcb = (PFCB)FileObject->FsContext; + *ResourceToRelease = NULL; + // We must determine which resource(s) we would like to // acquire at this time. We know that a write is imminent; // we will probably therefore acquire appropriate resources @@ -897,63 +898,23 @@ UDFFastIoAcqModWrite( // the resource that we acquired (single return value). This pointer // will be returned back to we in the release call (below). - if (UDFAcquireResourceShared(&Fcb->FcbNonpaged->FcbPagingIoResource, FALSE)) { - - if (EndingOffset->QuadPart <= Fcb->Header.ValidDataLength.QuadPart) { - - UDFReleaseResource(&Fcb->FcbNonpaged->FcbPagingIoResource); - RC = STATUS_CANT_WAIT; - } else { - - *ResourceToRelease = &Fcb->FcbNonpaged->FcbPagingIoResource; - MmPrint((" AcqModW OK\n")); - } - + // For embedded data files, acquire exclusive since data shares sector with metadata + // For normal files, shared is enough + BOOLEAN Acquired; + if (Fcb->FcbState & UDF_FCB_EMBEDDED_DATA) { + Acquired = UDFAcquireResourceExclusive(&Fcb->FcbNonpaged->FcbResource, FALSE); } else { - RC = STATUS_CANT_WAIT; + Acquired = UDFAcquireResourceShared(&Fcb->FcbNonpaged->FcbResource, FALSE); } - return RC; -} // end UDFFastIoAcqModWrite() - - -/************************************************************************* -* -* Function: UDFFastIoRelModWrite() -* -* Description: -* Not really a fast-io operation. Used by the VMM to release FSD resources -* after processing a modified page/block write operation. -* -* Expected Interrupt Level (for execution) : -* -* IRQL_PASSIVE_LEVEL -* -* Return Value: STATUS_SUCCESS/Error (an error returned here is really not expected!) -* -*************************************************************************/ -NTSTATUS -NTAPI -UDFFastIoRelModWrite( - IN PFILE_OBJECT FileObject, - IN PERESOURCE ResourceToRelease, - IN PDEVICE_OBJECT DeviceObject) -{ - MmPrint((" RelModW\n")); - - PFCB Fcb = (PFCB)FileObject->FsContext; - - // The MPW has complete the write for modified pages and therefore - // wants us to release pre-acquired resource(s). - - // We must undo here whatever it is that we did in the - // UDFFastIoAcqModWrite() call above. + if (!Acquired) { + return STATUS_CANT_WAIT; + } - ASSERT(ResourceToRelease == &Fcb->FcbNonpaged->FcbPagingIoResource); - UDFReleaseResource(ResourceToRelease); + *ResourceToRelease = &Fcb->FcbNonpaged->FcbResource; - return(STATUS_SUCCESS); -} // end UDFFastIoRelModWrite() + return STATUS_SUCCESS; +} // end UDFFastIoAcqModWrite() /************************************************************************* @@ -999,8 +960,13 @@ UDFFastIoAcqCcFlush( PFCB Fcb = (PFCB)FileObject->FsContext; - UDFAcquireResourceExclusive(&Fcb->FcbNonpaged->FcbResource, TRUE); - UDFAcquireResourceShared(&Fcb->FcbNonpaged->FcbPagingIoResource, TRUE); + // For embedded data files, acquire exclusive since data shares sector with metadata + // For normal files, shared is enough + if (Fcb->FcbState & UDF_FCB_EMBEDDED_DATA) { + UDFAcquireResourceExclusive(&Fcb->FcbNonpaged->FcbResource, TRUE); + } else { + UDFAcquireResourceShared(&Fcb->FcbNonpaged->FcbResource, TRUE); + } return STATUS_SUCCESS; @@ -1036,10 +1002,9 @@ UDFFastIoRelCcFlush( IoSetTopLevelIrp(NULL); } - // Release resources acquired in UDFFastIoAcqCcFlush() above. + // Release resource acquired in UDFFastIoAcqCcFlush() above. PFCB Fcb = (PFCB)FileObject->FsContext; - UDFReleaseResource(&Fcb->FcbNonpaged->FcbPagingIoResource); UDFReleaseResource(&Fcb->FcbNonpaged->FcbResource); return STATUS_SUCCESS; diff --git a/drivers/filesystems/udfs/flush.cpp b/drivers/filesystems/udfs/flush.cpp index 797f98341d0e5..76357b7eef143 100644 --- a/drivers/filesystems/udfs/flush.cpp +++ b/drivers/filesystems/udfs/flush.cpp @@ -112,8 +112,6 @@ UDFCommonFlush( // action we take. if ((Fcb == Fcb->Vcb->VolumeDasdFcb) || (Fcb->FcbState & UDF_FCB_ROOT_DIRECTORY)) { - Vcb->VcbState |= UDF_VCB_SKIP_EJECT_CHECK; - #ifdef UDF_DELAYED_CLOSE UDFFspClose(Vcb); #endif //UDF_DELAYED_CLOSE @@ -464,17 +462,10 @@ UDFFlushVolume( if (FlushFlags & UDF_FLUSH_FLAGS_LITE) { UDFPrint((" Lite flush, keep Modified=%d.\n", Vcb->Modified)); } else { - if (Vcb->VerifyOnWrite) { - UDFPrint(("UDF: Flushing cache for verify\n")); - //WCacheFlushAll__(&(Vcb->FastCache), Vcb); - WCacheFlushBlocks__(IrpContext, &Vcb->FastCache, Vcb, 0, Vcb->LastLBA); - UDFVFlush(Vcb); - } // umount (this is internal operation, NT will "dismount" volume later) UDFUmount__(IrpContext, Vcb); UDFPreClrModified(Vcb); - WCacheFlushAll__(IrpContext, &Vcb->FastCache, Vcb); UDFClrModified(Vcb); } diff --git a/drivers/filesystems/udfs/fscntrl.cpp b/drivers/filesystems/udfs/fscntrl.cpp index b5674a0a4d7c3..ab7c0799f8078 100644 --- a/drivers/filesystems/udfs/fscntrl.cpp +++ b/drivers/filesystems/udfs/fscntrl.cpp @@ -24,6 +24,12 @@ PDIR_INDEX_HDR UDFDirIndexAlloc(IN uint_di i); +NTSTATUS +UDFAllowExtendedDasdIo( + _In_ PIRP_CONTEXT IrpContext, + _In_ PIRP Irp + ); + /* Function: UDFCommonFsControl() @@ -97,10 +103,9 @@ Return Value: */ NTSTATUS -NTAPI UDFUserFsCtrlRequest( PIRP_CONTEXT IrpContext, - PIRP Irp + PIRP Irp ) { NTSTATUS RC; @@ -142,12 +147,7 @@ UDFUserFsCtrlRequest( case FSCTL_ALLOW_EXTENDED_DASD_IO: - UDFPrint(("UDFUserFsCtrlRequest: FSCTL_ALLOW_EXTENDED_DASD_IO\n")); - // DASD i/o is always permitted - // So, no-op this call - - UDFCompleteRequest(IrpContext, Irp, STATUS_SUCCESS); - RC = STATUS_SUCCESS; + RC = UDFAllowExtendedDasdIo(IrpContext, Irp); break; case FSCTL_DISMOUNT_VOLUME: @@ -184,7 +184,7 @@ UDFUserFsCtrlRequest( case FSCTL_GET_RETRIEVAL_POINTERS: UDFPrint(("UDFUserFsCtrlRequest: FSCTL_GET_RETRIEVAL_POINTERS\n")); - RC = UDFGetRetrievalPointers(IrpContext, Irp, 0); + RC = UDFGetRetrievalPointers(IrpContext, Irp); break; case FSCTL_MOVE_FILE: @@ -289,7 +289,6 @@ UDFMountVolume( BOOLEAN RestoreDoVerify = FALSE; BOOLEAN RemovableMedia = TRUE; BOOLEAN SetDoVerifyOnFail; - ULONG Mode; BOOLEAN VcbAcquired = FALSE; BOOLEAN DeviceNotTouched = TRUE; DISK_GEOMETRY DiskGeometry; @@ -448,45 +447,11 @@ UDFMountVolume( Vcb->MountPhErrorCount = 0; -#ifdef UDF_USE_WCACHE - // Initialize internal cache - Mode = WCACHE_MODE_ROM; - RC = WCacheInit__(&(Vcb->FastCache), - Vcb->WCacheMaxFrames, - Vcb->WCacheMaxBlocks, - Vcb->WriteBlockSize, - 5, Vcb->BlockSizeBits, - Vcb->WCacheBlocksPerFrameSh, - 0/*Vcb->FirstLBA*/, Vcb->LastPossibleLBA, Mode, - 0/*WCACHE_CACHE_WHOLE_PACKET*/ | - WCACHE_DO_NOT_COMPARE | - WCACHE_CHAINED_IO | - WCACHE_MARK_BAD_BLOCKS | WCACHE_RO_BAD_BLOCKS, // this will be cleared after mount - Vcb->WCacheFramesToKeepFree, -// UDFTWrite, UDFTRead, - UDFTWriteVerify, UDFTReadVerify, -#ifdef UDF_ASYNC_IO - UDFTWriteAsync, UDFTReadAsync, -#else //UDF_ASYNC_IO - NULL, NULL, -#endif //UDF_ASYNC_IO - UDFIsBlockAllocated, - UDFUpdateVAT, - UDFWCacheErrorHandler); - if (!NT_SUCCESS(RC)) try_return(RC); -#endif //UDF_USE_WCACHE - - RC = UDFVInit(Vcb); - if (!NT_SUCCESS(RC)) try_return(RC); - UDFAcquireResourceExclusive(&(Vcb->BitMapResource1),TRUE); RC = UDFGetDiskInfoAndVerify(IrpContext, DeviceObjectWeTalkTo,Vcb); UDFReleaseResource(&(Vcb->BitMapResource1)); ASSERT(!Vcb->Modified); - WCacheChFlags__(&(Vcb->FastCache), - WCACHE_CACHE_WHOLE_PACKET, // enable cache whole packet - WCACHE_MARK_BAD_BLOCKS | WCACHE_RO_BAD_BLOCKS); // let user retry request on Bad Blocks if (!NT_SUCCESS(RC)) { @@ -495,26 +460,6 @@ UDFMountVolume( } else { Vcb->MountPhErrorCount = -1; - // set cache mode according to media type - if (!(Vcb->VcbState & VCB_STATE_MEDIA_WRITE_PROTECT)) { - UDFPrint(("UDFMountVolume: writable volume\n")); - if (!Vcb->CDR_Mode) { - if (FsDeviceType == FILE_DEVICE_DISK_FILE_SYSTEM) { - UDFPrint(("UDFMountVolume: RAM mode\n")); - Mode = WCACHE_MODE_RAM; - } else { - UDFPrint(("UDFMountVolume: RW mode\n")); - Mode = WCACHE_MODE_RW; - } - } else { - UDFPrint(("UDFMountVolume: R mode\n")); - Mode = WCACHE_MODE_R; - } - } -#ifdef UDF_USE_WCACHE - WCacheSetMode__(&(Vcb->FastCache), Mode); -#endif //UDF_USE_WCACHE - // Complete mount operations: create root FCB UDFAcquireResourceExclusive(&(Vcb->BitMapResource1),TRUE); RC = UDFCompleteMount(IrpContext, Vcb); @@ -556,12 +501,6 @@ UDFMountVolume( Vcb->TotalAllocUnits = UDFGetTotalSpace(Vcb); Vcb->FreeAllocUnits = UDFGetFreeSpace(Vcb); - if (UdfData.MountEvent) - { - Vcb->IsVolumeJustMounted = TRUE; - KeSetEvent(UdfData.MountEvent, 0, FALSE); - } - // The new mount is complete. UDFReleaseResource( &(Vcb->VcbResource) ); VcbAcquired = FALSE; @@ -790,7 +729,7 @@ UDFScanForDismountedVcb( while (Link != &(UdfData.VcbQueue)) { - Vcb = CONTAINING_RECORD( Link, VCB, NextVCB ); + Vcb = CONTAINING_RECORD(Link, VCB, VcbLinks); // Move to the next link now since the current Vcb may be deleted. Link = Link->Flink; @@ -1308,104 +1247,122 @@ UDFGetVolumeBitmap( IN PIRP Irp ) { -// NTSTATUS RC; + NTSTATUS Status = STATUS_SUCCESS; PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); - UDFPrint(("UDFGetVolumeBitmap\n")); - - TYPE_OF_OPEN TypeOfOpen; PFCB Fcb; PCCB Ccb; - PVCB Vcb; + PVCB Vcb = IrpContext->Vcb; ULONG BytesToCopy; ULONG TotalClusters; - ULONG DesiredClusters; ULONG StartingCluster; + ULONG DesiredClusters; ULONG InputBufferLength; ULONG OutputBufferLength; LARGE_INTEGER StartingLcn; PVOLUME_BITMAP_BUFFER OutputBuffer; ULONG i, lim; PULONG FSBM; -// PULONG Dest; + BOOLEAN VcbAcquired = FALSE; - // Decode the file object, the only type of opens we accept are - // user volume opens. + ASSERT_VCB(Vcb); - TypeOfOpen = UDFDecodeFileObject(IrpSp->FileObject, &Fcb, &Ccb); + // Make this a synchronous IRP because we need access to the input buffer and + // this Irp is marked METHOD_NEITHER. - ASSERT_CCB(Ccb); - ASSERT_FCB(Fcb); + SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); - if (!Ccb) { + InputBufferLength = IrpSp->Parameters.FileSystemControl.InputBufferLength; + OutputBufferLength = IrpSp->Parameters.FileSystemControl.OutputBufferLength; - UDFPrintErr((" !Ccb\n")); - UDFCompleteRequest(IrpContext, Irp, STATUS_INVALID_PARAMETER); - return STATUS_INVALID_PARAMETER; - } + TotalClusters = Vcb->FSBM_BitCount; - Vcb = Fcb->Vcb; - ASSERT_FCB(Fcb); + _SEH2_TRY { - InputBufferLength = IrpSp->Parameters.FileSystemControl.InputBufferLength; - OutputBufferLength = IrpSp->Parameters.FileSystemControl.OutputBufferLength; + // Decode the file object, the only type of opens we accept are + // user volume opens. - OutputBuffer = (PVOLUME_BITMAP_BUFFER)UDFMapUserBuffer(Irp); + if (UDFDecodeFileObject(IrpSp->FileObject, &Fcb, &Ccb) != UserVolumeOpen) { - if (!OutputBuffer) { + try_return(Status = STATUS_INVALID_USER_BUFFER); + } - UDFCompleteRequest(IrpContext, Irp, STATUS_INVALID_USER_BUFFER); - return STATUS_INVALID_USER_BUFFER; - } + ASSERT_CCB(Ccb); + ASSERT_FCB(Fcb); - // Check for a minimum length on the input and output buffers. - if ((InputBufferLength < sizeof(STARTING_LCN_INPUT_BUFFER)) || - (OutputBufferLength < sizeof(VOLUME_BITMAP_BUFFER))) { + // Check for a minimum length on the input and output buffers. - UDFUnlockCallersBuffer(IrpContext, Irp, OutputBuffer); + if ((InputBufferLength < sizeof(STARTING_LCN_INPUT_BUFFER)) || + (OutputBufferLength < sizeof(VOLUME_BITMAP_BUFFER))) { - UDFCompleteRequest(IrpContext, Irp, STATUS_BUFFER_TOO_SMALL); - return STATUS_BUFFER_TOO_SMALL; - } + try_return(Status = STATUS_BUFFER_TOO_SMALL); + } - // Check if a starting cluster was specified. - TotalClusters = Vcb->FSBM_BitCount; - StartingLcn = ((PSTARTING_LCN_INPUT_BUFFER)IrpSp->Parameters.FileSystemControl.Type3InputBuffer)->StartingLcn; + OutputBuffer = (PVOLUME_BITMAP_BUFFER)UDFMapUserBuffer(Irp); - if (StartingLcn.HighPart || StartingLcn.LowPart >= TotalClusters) { + _SEH2_TRY { - UDFUnlockCallersBuffer(IrpContext, Irp, OutputBuffer); + if (Irp->RequestorMode != KernelMode) { - UDFCompleteRequest(IrpContext, Irp, STATUS_INVALID_PARAMETER); - return STATUS_INVALID_PARAMETER; + ProbeForRead(IrpSp->Parameters.FileSystemControl.Type3InputBuffer, + InputBufferLength, + sizeof(UCHAR)); - } else { + ProbeForWrite(OutputBuffer, OutputBufferLength, sizeof(UCHAR)); + } + + StartingLcn = ((PSTARTING_LCN_INPUT_BUFFER)IrpSp->Parameters.FileSystemControl.Type3InputBuffer)->StartingLcn; + + } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { + + try_return(Status = STATUS_INVALID_USER_BUFFER); + } _SEH2_END + + if (StartingLcn.HighPart || StartingLcn.LowPart >= TotalClusters) { + + try_return(Status = STATUS_INVALID_PARAMETER); + } + + // Align starting block to 8-bit boundary StartingCluster = StartingLcn.LowPart & ~7; - } - OutputBufferLength -= FIELD_OFFSET(VOLUME_BITMAP_BUFFER, Buffer); - DesiredClusters = TotalClusters - StartingCluster; + DesiredClusters = TotalClusters - StartingCluster; - if (OutputBufferLength < (DesiredClusters + 7) / 8) { + // Fill in the fixed part of the output buffer - BytesToCopy = OutputBufferLength; -// RC = STATUS_BUFFER_OVERFLOW; + __try { - } else { + // StartingLcn in output = aligned starting block - BytesToCopy = (DesiredClusters + 7) / 8; -// RC = STATUS_SUCCESS; - } + OutputBuffer->StartingLcn.QuadPart = StartingCluster; - UDFAcquireResourceExclusive(&(Vcb->VcbResource), TRUE ); + // BitmapSize = remaining blocks from starting position - _SEH2_TRY { + OutputBuffer->BitmapSize.QuadPart = DesiredClusters; + + } __except (EXCEPTION_EXECUTE_HANDLER) { + + try_return(Status = STATUS_INVALID_USER_BUFFER); + } + + OutputBufferLength -= FIELD_OFFSET(VOLUME_BITMAP_BUFFER, Buffer); + + + if (OutputBufferLength < (DesiredClusters + 7) / 8) { - // Fill in the fixed part of the output buffer - OutputBuffer->StartingLcn.QuadPart = StartingCluster; - OutputBuffer->BitmapSize.QuadPart = DesiredClusters; + BytesToCopy = OutputBufferLength; + Status = STATUS_BUFFER_OVERFLOW; + + } else { + + BytesToCopy = (DesiredClusters + 7) / 8; + Status = STATUS_SUCCESS; + } + + UDFAcquireVcbShared(IrpContext, Vcb, FALSE); + VcbAcquired = TRUE; RtlZeroMemory( &OutputBuffer->Buffer[0], BytesToCopy ); lim = BytesToCopy * 8; @@ -1418,30 +1375,24 @@ UDFGetVolumeBitmap( UDFSetFreeBit(FSBM, i); } - } _SEH2_EXCEPT(UDFExceptionFilter(IrpContext, _SEH2_GetExceptionInformation())) { + Irp->IoStatus.Information = FIELD_OFFSET(VOLUME_BITMAP_BUFFER, Buffer) + BytesToCopy; - BrutePoint(); - UDFPrintErr(("UDFGetVolumeBitmap: Exception\n")); -// UDFUnlockCallersBuffer(IrpContext, Irp, OutputBuffer); - BrutePoint(); -// RC = UDFExceptionHandler(IrpContext, Irp); - UDFReleaseResource(&(Vcb->VcbResource)); - UDFUnlockCallersBuffer(IrpContext, Irp, OutputBuffer); +try_exit: NOTHING; - Irp->IoStatus.Information = 0; - Irp->IoStatus.Status = STATUS_INVALID_USER_BUFFER; - return STATUS_INVALID_USER_BUFFER; - } _SEH2_END; + } _SEH2_FINALLY { + + if (VcbAcquired) { - UDFReleaseResource(&(Vcb->VcbResource)); + UDFReleaseVcb(IrpContext, Vcb); + } + + } _SEH2_END; - UDFUnlockCallersBuffer(IrpContext, Irp, OutputBuffer); - Irp->IoStatus.Information = FIELD_OFFSET(VOLUME_BITMAP_BUFFER, Buffer) + - BytesToCopy; + // Complete the request - UDFCompleteRequest(IrpContext, Irp, STATUS_SUCCESS); + UDFCompleteRequest(IrpContext, Irp, Status); - return STATUS_SUCCESS; + return Status; } // end UDFGetVolumeBitmap() @@ -1450,8 +1401,7 @@ UDFGetVolumeBitmap( NTSTATUS UDFGetRetrievalPointers( IN PIRP_CONTEXT IrpContext, - IN PIRP Irp, - IN ULONG Special + IN PIRP Irp ) { NTSTATUS RC; @@ -1471,6 +1421,7 @@ UDFGetRetrievalPointers( PCCB Ccb; PFCB Fcb; PVCB Vcb; + TYPE_OF_OPEN TypeOfOpen; PEXTENT_MAP SubMapping = NULL; ULONG SubExtInfoSz; @@ -1480,7 +1431,18 @@ UDFGetRetrievalPointers( UDFPrint(("UDFGetRetrievalPointers\n")); - UDFDecodeFileObject(IrpSp->FileObject, &Fcb, &Ccb); + // Make this a synchronous IRP because we need access to the input buffer and + // this Irp is marked METHOD_NEITHER. + + SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); + + TypeOfOpen = UDFDecodeFileObject(IrpSp->FileObject, &Fcb, &Ccb); + + if ((TypeOfOpen != UserFileOpen) && (TypeOfOpen != UserDirectoryOpen)) { + + UDFCompleteRequest(IrpContext, Irp, STATUS_INVALID_PARAMETER); + return STATUS_INVALID_PARAMETER; + } Vcb = Fcb->Vcb; @@ -1500,12 +1462,8 @@ UDFGetRetrievalPointers( InputBufferLength = IrpSp->Parameters.FileSystemControl.InputBufferLength; OutputBufferLength = IrpSp->Parameters.FileSystemControl.OutputBufferLength; - //OutputBuffer = (PRETRIEVAL_POINTERS_BUFFER)UDFGetCallersBuffer( IrpContext, Irp ); - if (Special) { - OutputBuffer = (PRETRIEVAL_POINTERS_BUFFER)Irp->AssociatedIrp.SystemBuffer; - } else { - OutputBuffer = (PRETRIEVAL_POINTERS_BUFFER)Irp->UserBuffer; - } + OutputBuffer = (PRETRIEVAL_POINTERS_BUFFER)UDFMapUserBuffer(Irp); + InputBuffer = (PSTARTING_VCN_INPUT_BUFFER)IrpSp->Parameters.FileSystemControl.Type3InputBuffer; if (!InputBuffer) { InputBuffer = (PSTARTING_VCN_INPUT_BUFFER)OutputBuffer; @@ -1539,16 +1497,7 @@ UDFGetRetrievalPointers( try_return(RC); } _SEH2_END; - switch(Special) { - case 0: - FileInfo = Fcb->FileInfo; - break; - case 1: - FileInfo = Vcb->NonAllocFileInfo; - break; - default: - try_return( RC = STATUS_INVALID_PARAMETER ); - } + FileInfo = Fcb->FileInfo; if (!FileInfo) { try_return( RC = STATUS_OBJECT_NAME_NOT_FOUND ); @@ -1676,6 +1625,30 @@ UDFIsVolumeDirty( } // end UDFIsVolumeDirty() +NTSTATUS +UDFAllowExtendedDasdIo( + _In_ PIRP_CONTEXT IrpContext, + _In_ PIRP Irp + ) +{ + PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); + PFCB Fcb; + PCCB Ccb; + + // Extract and decode the file object and check for type of open. + + if (UDFDecodeFileObject(IrpSp->FileObject, &Fcb, &Ccb) != UserVolumeOpen) { + + UDFCompleteRequest(IrpContext, Irp, STATUS_INVALID_PARAMETER); + return STATUS_INVALID_PARAMETER; + } + + SetFlag(Ccb->Flags, CCB_FLAG_ALLOW_EXTENDED_DASD_IO); + + UDFCompleteRequest(IrpContext, Irp, STATUS_SUCCESS); + return STATUS_SUCCESS; +} + NTSTATUS UDFInvalidateVolumes( @@ -1777,7 +1750,7 @@ UDFInvalidateVolumes( while (Links != &UdfData.VcbQueue) { // Get 'next' Vcb - Vcb = CONTAINING_RECORD(Links, VCB, NextVCB); + Vcb = CONTAINING_RECORD(Links, VCB, VcbLinks); // Move to the next link now since the current Vcb may be deleted. Links = Links->Flink; diff --git a/drivers/filesystems/udfs/misc.cpp b/drivers/filesystems/udfs/misc.cpp index 1c3d198845ed7..c78f45461cc12 100644 --- a/drivers/filesystems/udfs/misc.cpp +++ b/drivers/filesystems/udfs/misc.cpp @@ -57,27 +57,15 @@ UDFInitializeZones(VOID) case MmMediumSystem: UdfData.MaxDelayedCloseCount = 32; UdfData.MinDelayedCloseCount = 8; - UdfData.WCacheMaxFrames = 8*4; - UdfData.WCacheMaxBlocks = 16*64; - UdfData.WCacheBlocksPerFrameSh = 8; - UdfData.WCacheFramesToKeepFree = 4; break; case MmLargeSystem: UdfData.MaxDelayedCloseCount = 72; UdfData.MinDelayedCloseCount = 18; - UdfData.WCacheMaxFrames = 2*16*4; - UdfData.WCacheMaxBlocks = 2*16*64; - UdfData.WCacheBlocksPerFrameSh = 8; - UdfData.WCacheFramesToKeepFree = 8; break; case MmSmallSystem: default: UdfData.MaxDelayedCloseCount = 10; UdfData.MinDelayedCloseCount = 2; - UdfData.WCacheMaxFrames = 8*4/2; - UdfData.WCacheMaxBlocks = 16*64/2; - UdfData.WCacheBlocksPerFrameSh = 8; - UdfData.WCacheFramesToKeepFree = 2; } ExInitializeNPagedLookasideList(&UdfData.IrpContextLookasideList, @@ -1440,11 +1428,8 @@ UDFReadRegKeys( BOOLEAN UseCfg ) { - ULONG mult = 1; ptrUDFGetParameter UDFGetParameter = UDFGetRegParameter; - Vcb->DefaultRegName = REG_DEFAULT_UNKNOWN; - // What type of AllocDescs should we use Vcb->DefaultAllocMode = (USHORT)UDFGetParameter(Vcb, REG_DEFALLOCMODE_NAME, Update ? Vcb->DefaultAllocMode : ICB_FLAG_AD_SHORT); @@ -1494,9 +1479,6 @@ UDFReadRegKeys( Update ? Vcb->SparseThreshold : 0); if (!Vcb->SparseThreshold) Vcb->SparseThreshold = UDF_DEFAULT_SPARSE_THRESHOLD; - // This option is used to VERIFY all the data written. It decreases performance - Vcb->VerifyOnWrite = UDFGetParameter(Vcb, UDF_VERIFY_ON_WRITE_NAME, - Update ? Vcb->VerifyOnWrite : FALSE) ? TRUE : FALSE; // Should we update AttrFileTime on Attr changes UDFUpdateCompatOption(Vcb, Update, UseCfg, UDF_UPDATE_TIMES_ATTR, UDF_VCB_IC_UPDATE_ATTR_TIME, FALSE); @@ -1537,11 +1519,6 @@ UDFReadRegKeys( if (UDFGetParameter(Vcb, UDF_DIRTY_VOLUME_BEHAVIOR, UDF_PART_DAMAGED_RO)) { Vcb->CompatFlags |= UDF_VCB_IC_DIRTY_RO; } - - mult = UDFGetParameter(Vcb, UDF_CACHE_SIZE_MULTIPLIER, 1); - if (!mult) mult = 1; - Vcb->WCacheMaxBlocks *= mult; - Vcb->WCacheMaxFrames *= mult; } return; } // end UDFReadRegKeys() @@ -1553,11 +1530,7 @@ UDFGetRegParameter( IN ULONG DefValue ) { - return UDFRegCheckParameterValue(&(UdfData.SavedRegPath), - Name, - NULL, - Vcb ? Vcb->DefaultRegName : NULL, - DefValue); + return DefValue; } // end UDFGetRegParameter() VOID @@ -1581,16 +1554,6 @@ UDFDeleteVCB( delay.QuadPart -= 500000; // grow delay 0.05 sec } - _SEH2_TRY { - UDFPrint(("UDF: Flushing buffers\n")); - UDFVRelease(Vcb); - WCacheFlushAll__(IrpContext, &Vcb->FastCache, Vcb); - WCacheRelease__(&Vcb->FastCache); - - } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { - BrutePoint(); - } _SEH2_END; - #ifdef UDF_DBG _SEH2_TRY { if (!ExIsResourceAcquiredShared(&UdfData.GlobalDataResource)) { @@ -1604,7 +1567,7 @@ UDFDeleteVCB( #endif _SEH2_TRY { - RemoveEntryList(&(Vcb->NextVCB)); + RemoveEntryList(&(Vcb->VcbLinks)); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { BrutePoint(); } _SEH2_END; @@ -1644,186 +1607,6 @@ UDFDeleteVCB( } // end UDFDeleteVCB() -/* - Read DWORD from Registry -*/ -ULONG -UDFRegCheckParameterValue( - IN PUNICODE_STRING RegistryPath, - IN PCWSTR Name, - IN PUNICODE_STRING PtrVolumePath, - IN PCWSTR DefaultPath, - IN ULONG DefValue - ) -{ - NTSTATUS status; - - ULONG val = DefValue; - - UNICODE_STRING paramStr; - UNICODE_STRING defaultParamStr; - UNICODE_STRING paramPathUnknownStr; - - UNICODE_STRING paramSuffix; - UNICODE_STRING paramPath; - UNICODE_STRING paramPathUnknown; - UNICODE_STRING paramDevPath; - UNICODE_STRING defaultParamPath; - - _SEH2_TRY { - - paramPath.Buffer = NULL; - paramDevPath.Buffer = NULL; - paramPathUnknown.Buffer = NULL; - defaultParamPath.Buffer = NULL; - - // First append \Parameters to the passed in registry path - // Note, RtlInitUnicodeString doesn't allocate memory - RtlInitUnicodeString(¶mStr, L"\\Parameters"); - RtlInitUnicodeString(¶mPath, NULL); - - RtlInitUnicodeString(¶mPathUnknownStr, REG_DEFAULT_UNKNOWN); - RtlInitUnicodeString(¶mPathUnknown, NULL); - - paramPathUnknown.MaximumLength = RegistryPath->Length + paramPathUnknownStr.Length + paramStr.Length + sizeof(WCHAR); - paramPath.MaximumLength = RegistryPath->Length + paramStr.Length + sizeof(WCHAR); - - paramPath.Buffer = (PWCH)MyAllocatePool__(PagedPool, paramPath.MaximumLength); - if (!paramPath.Buffer) { - UDFPrint(("UDFCheckRegValue: couldn't allocate paramPath\n")); - try_return(val = DefValue); - } - paramPathUnknown.Buffer = (PWCH)MyAllocatePool__(PagedPool, paramPathUnknown.MaximumLength); - if (!paramPathUnknown.Buffer) { - UDFPrint(("UDFCheckRegValue: couldn't allocate paramPathUnknown\n")); - try_return(val = DefValue); - } - - RtlZeroMemory(paramPath.Buffer, paramPath.MaximumLength); - status = RtlAppendUnicodeToString(¶mPath, RegistryPath->Buffer); - if (!NT_SUCCESS(status)) { - try_return(val = DefValue); - } - status = RtlAppendUnicodeToString(¶mPath, paramStr.Buffer); - if (!NT_SUCCESS(status)) { - try_return(val = DefValue); - } - UDFPrint(("UDFCheckRegValue: (1) |%S|\n", paramPath.Buffer)); - - RtlZeroMemory(paramPathUnknown.Buffer, paramPathUnknown.MaximumLength); - status = RtlAppendUnicodeToString(¶mPathUnknown, RegistryPath->Buffer); - if (!NT_SUCCESS(status)) { - try_return(val = DefValue); - } - status = RtlAppendUnicodeToString(¶mPathUnknown, paramStr.Buffer); - if (!NT_SUCCESS(status)) { - try_return(val = DefValue); - } - status = RtlAppendUnicodeToString(¶mPathUnknown, paramPathUnknownStr.Buffer); - if (!NT_SUCCESS(status)) { - try_return(val = DefValue); - } - UDFPrint(("UDFCheckRegValue: (2) |%S|\n", paramPathUnknown.Buffer)); - - // First append \Parameters\Default_XXX to the passed in registry path - if (DefaultPath) { - RtlInitUnicodeString(&defaultParamStr, DefaultPath); - RtlInitUnicodeString(&defaultParamPath, NULL); - defaultParamPath.MaximumLength = paramPath.Length + defaultParamStr.Length + sizeof(WCHAR); - defaultParamPath.Buffer = (PWCH)MyAllocatePool__(PagedPool, defaultParamPath.MaximumLength); - if (!defaultParamPath.Buffer) { - UDFPrint(("UDFCheckRegValue: couldn't allocate defaultParamPath\n")); - try_return(val = DefValue); - } - - RtlZeroMemory(defaultParamPath.Buffer, defaultParamPath.MaximumLength); - status = RtlAppendUnicodeToString(&defaultParamPath, paramPath.Buffer); - if (!NT_SUCCESS(status)) { - try_return(val = DefValue); - } - status = RtlAppendUnicodeToString(&defaultParamPath, defaultParamStr.Buffer); - if (!NT_SUCCESS(status)) { - try_return(val = DefValue); - } - UDFPrint(("UDFCheckRegValue: (3) |%S|\n", defaultParamPath.Buffer)); - } - - if (PtrVolumePath) { - paramSuffix = *PtrVolumePath; - } else { - RtlInitUnicodeString(¶mSuffix, NULL); - } - - RtlInitUnicodeString(¶mDevPath, NULL); - // now build the device specific path - paramDevPath.MaximumLength = paramPath.Length + paramSuffix.Length + sizeof(WCHAR); - paramDevPath.Buffer = (PWCH)MyAllocatePool__(PagedPool, paramDevPath.MaximumLength); - if (!paramDevPath.Buffer) { - try_return(val = DefValue); - } - - RtlZeroMemory(paramDevPath.Buffer, paramDevPath.MaximumLength); - status = RtlAppendUnicodeToString(¶mDevPath, paramPath.Buffer); - if (!NT_SUCCESS(status)) { - try_return(val = DefValue); - } - if (paramSuffix.Buffer) { - status = RtlAppendUnicodeToString(¶mDevPath, paramSuffix.Buffer); - if (!NT_SUCCESS(status)) { - try_return(val = DefValue); - } - } - - UDFPrint(( " Parameter = %ws\n", Name)); - - { - HKEY hk = NULL; - status = RegTGetKeyHandle(NULL, RegistryPath->Buffer, &hk); - if (NT_SUCCESS(status)) { - RegTCloseKeyHandle(hk); - } - } - - - // *** Read GLOBAL_DEFAULTS from - // "\DwUdf\Parameters_Unknown\" - - status = RegTGetDwordValue(NULL, paramPath.Buffer, Name, &val); - - // *** Read DEV_CLASS_SPEC_DEFAULTS (if any) from - // "\DwUdf\Parameters_%DevClass%\" - - if (DefaultPath) { - status = RegTGetDwordValue(NULL, defaultParamPath.Buffer, Name, &val); - } - - // *** Read DEV_SPEC_PARAMS from (if device supports GetDevName) - // "\DwUdf\Parameters\%DevName%\" - - status = RegTGetDwordValue(NULL, paramDevPath.Buffer, Name, &val); - -try_exit: NOTHING; - - } _SEH2_FINALLY { - - if (DefaultPath && defaultParamPath.Buffer) { - MyFreePool__(defaultParamPath.Buffer); - } - if (paramPath.Buffer) { - MyFreePool__(paramPath.Buffer); - } - if (paramDevPath.Buffer) { - MyFreePool__(paramDevPath.Buffer); - } - if (paramPathUnknown.Buffer) { - MyFreePool__(paramPathUnknown.Buffer); - } - } _SEH2_END; - - UDFPrint(( "UDFCheckRegValue: %ws for drive %s is %x\n\n", Name, PtrVolumePath, val)); - return val; -} // end UDFRegCheckParameterValue() - /* Routine Description: This routine is called to initialize an IrpContext for the current @@ -1937,16 +1720,6 @@ UDFAcquireResourceSharedWithCheck( return FALSE; } // end UDFAcquireResourceSharedWithCheck() -NTSTATUS -UDFWCacheErrorHandler( - IN PVOID Context, - IN PWCACHE_ERROR_CONTEXT ErrorInfo - ) -{ - InterlockedIncrement((PLONG)&(((PVCB)Context)->IoErrorCounter)); - return ErrorInfo->Status; -} - VOID UDFSetModified( IN PVCB Vcb @@ -2254,5 +2027,84 @@ Return Value: return Acquired; } +VOID +UDFFinishIoAtEof( + IN PFCB Fcb + ) +{ + PEOF_WAIT_BLOCK EofWaitBlock; + + PAGED_CODE(); + + // Check if list is empty + + if (IsListEmpty(&Fcb->EofListHead)) { + + // No waiters - clear the EOF advance flag + + ClearFlag(Fcb->Header.Flags, FSRTL_FLAG_EOF_ADVANCE_ACTIVE); + + } else { + + // Remove first waiter from list + + EofWaitBlock = (PEOF_WAIT_BLOCK)RemoveHeadList(&Fcb->EofListHead); + + // Signal the waiter's event + + KeSetEvent(&EofWaitBlock->Event, 0, FALSE); + } +} + +BOOLEAN +UDFWaitForIoAtEof( + IN PFCB Fcb, + IN LONGLONG FileOffset, + IN ULONG Length + ) +{ + EOF_WAIT_BLOCK WaitBlock; + + PAGED_CODE(); + + ASSERT(Fcb->Header.FileSize.QuadPart >= Fcb->Header.ValidDataLength.QuadPart); + + // Initialize wait block + + RtlZeroMemory(&WaitBlock, sizeof(EOF_WAIT_BLOCK)); + + // Initialize event as synchronization event (NotificationEvent = FALSE) + + KeInitializeEvent(&WaitBlock.Event, SynchronizationEvent, FALSE); + + // Insert wait block at end of list + + InsertTailList(&Fcb->EofListHead, &WaitBlock.EofWaitLinks); + + ExReleaseFastMutex(Fcb->Header.FastMutex); + + // Wait for event to be signaled + + KeWaitForSingleObject(&WaitBlock.Event, + Executive, + KernelMode, + FALSE, + NULL); + + ExAcquireFastMutex(Fcb->Header.FastMutex); + + // Check if we still need to extend EOF + + if ((FileOffset >= 0) && + ((FileOffset + Length) <= Fcb->Header.ValidDataLength.QuadPart)) { + + UDFFinishIoAtEof(Fcb); + + return FALSE; + } + + return TRUE; +} + #include "Include/regtools.cpp" diff --git a/drivers/filesystems/udfs/protos.h b/drivers/filesystems/udfs/protos.h index ebed36f05d1c0..59cb00cc0abe4 100644 --- a/drivers/filesystems/udfs/protos.h +++ b/drivers/filesystems/udfs/protos.h @@ -312,11 +312,13 @@ IN PLARGE_INTEGER FileOffset, OUT PMDL MdlChain, IN PDEVICE_OBJECT DeviceObject); -extern NTSTATUS NTAPI UDFFastIoAcqModWrite( -IN PFILE_OBJECT FileObject, -IN PLARGE_INTEGER EndingOffset, -OUT PERESOURCE* ResourceToRelease, -IN PDEVICE_OBJECT DeviceObject); +NTSTATUS +NTAPI +UDFFastIoAcqModWrite( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER EndingOffset, + OUT PERESOURCE* ResourceToRelease, + IN PDEVICE_OBJECT DeviceObject); extern NTSTATUS NTAPI UDFFastIoRelModWrite( IN PFILE_OBJECT FileObject, @@ -574,9 +576,10 @@ UDFCommonFsControl( PIRP Irp ); -extern NTSTATUS NTAPI UDFUserFsCtrlRequest( -PIRP_CONTEXT IrpContext, -PIRP Irp); +NTSTATUS +UDFUserFsCtrlRequest( + PIRP_CONTEXT IrpContext, + PIRP Irp); extern NTSTATUS NTAPI UDFMountVolume( PIRP_CONTEXT IrpContext, @@ -644,8 +647,7 @@ extern NTSTATUS UDFGetVolumeBitmap(IN PIRP_CONTEXT IrpContext, IN PIRP Irp); extern NTSTATUS UDFGetRetrievalPointers(IN PIRP_CONTEXT IrpContext, - IN PIRP Irp, - IN ULONG Special); + IN PIRP Irp); extern NTSTATUS UDFInvalidateVolumes(IN PIRP_CONTEXT IrpContext, IN PIRP Irp); @@ -848,13 +850,6 @@ UDFDeleteVCB( PVCB Vcb ); -extern ULONG UDFRegCheckParameterValue( - IN PUNICODE_STRING RegistryPath, - IN PCWSTR Name, - IN PUNICODE_STRING PtrVolumePath, - IN PCWSTR DefaultPath, - IN ULONG DefValue = 0); - extern VOID UDFInitializeStackIrpContextFromLite( OUT PIRP_CONTEXT IrpContext, IN PIRP_CONTEXT_LITE IrpContextLite); @@ -872,11 +867,6 @@ extern BOOLEAN UDFAcquireResourceSharedWithCheck( IN PERESOURCE Resource ); -extern NTSTATUS UDFWCacheErrorHandler( - IN PVOID Context, - IN PWCACHE_ERROR_CONTEXT ErrorInfo - ); - extern NTSTATUS NTAPI UDFFilterCallbackAcquireForCreateSection( IN PFS_FILTER_CALLBACK_DATA CallbackData, IN PVOID *CompletionContext @@ -914,11 +904,6 @@ extern NTSTATUS NTAPI UDFRead( PDEVICE_OBJECT DeviceObject, // the logical volume device object PIRP Irp); // I/O Request Packet -extern NTSTATUS UDFPostStackOverflowRead( - IN PIRP_CONTEXT IrpContext, - IN PIRP Irp, - IN PFCB Fcb); - extern VOID NTAPI UDFStackOverflowRead( IN PVOID Context, IN PKEVENT Event); @@ -1274,6 +1259,9 @@ UDFAcquireResource( #define UDFAcquireFcbShared(IC,F,I) \ UDFAcquireResource((IC), &(F)->FcbNonpaged->FcbResource, (I), AcquireShared) +#define UDFAcquireFcbSharedStarveExclusive(IC,F,I) \ + UDFAcquireResource((IC), &(F)->FcbNonpaged->FcbResource, (I), AcquireSharedStarveExclusive) + #define UDFReleaseFcb(IC,F) \ ExReleaseResourceLite(&(F)->FcbNonpaged->FcbResource) @@ -1317,6 +1305,16 @@ SectorAlign( return (Length + (Vcb->SectorSize - 1)) & ~(Vcb->SectorSize - 1); } +inline +ULONGLONG +LlSectorAlign( + PVCB Vcb, + ULONGLONG Length +) { + + return (Length + (Vcb->SectorSize - 1)) & ~(ULONGLONG)(Vcb->SectorSize - 1); +} + VOID UDFSetThreadContext( _Inout_ PIRP_CONTEXT IrpContext, @@ -1345,4 +1343,22 @@ BOOLEAN UDFIsStreamsSupported( return Vcb->UdfRevision >= 0x0200; } +VOID +UDFFinishIoAtEof( + IN PFCB Fcb + ); + +BOOLEAN +UDFWaitForIoAtEof( + IN PFCB Fcb, + IN LONGLONG FileOffset, + IN ULONG Length + ); + +VOID +UDFPrePostIrp( + _Inout_ PIRP_CONTEXT IrpContext, + _Inout_ PIRP Irp + ); + #endif // _UDF_PROTOS_H_ diff --git a/drivers/filesystems/udfs/read.cpp b/drivers/filesystems/udfs/read.cpp index 7d274994cd361..ca1795add66de 100644 --- a/drivers/filesystems/udfs/read.cpp +++ b/drivers/filesystems/udfs/read.cpp @@ -19,16 +19,6 @@ // define the file specific bug-check id #define UDF_BUG_CHECK_ID UDF_FILE_READ -#ifdef _M_IX86 -#if DBG -#define OVERFLOW_READ_THRESHHOLD (0xE00) -#else -#define OVERFLOW_READ_THRESHHOLD (0xA00) -#endif // UDF_DBG -#else // defined(_M_IX86) -#define OVERFLOW_READ_THRESHHOLD (0x1000) -#endif // defined(_M_IX86) - // This macro just puts a nice little try-except around RtlZeroMemory #define SafeZeroMemory(AT,BYTE_COUNT) { \ @@ -39,115 +29,6 @@ } _SEH2_END; \ } -/************************************************************************* -* -* Function: UDFPostStackOverflowRead() -* -* Description: -* Post a read request that could not be processed by -* the fsp thread because of stack overflow potential. -* -* Arguments: -* Irp - Supplies the request to process. -* Fcb - Supplies the file. -* -* Return Value: STATUS_PENDING. -* -*************************************************************************/ -NTSTATUS -UDFPostStackOverflowRead( - IN PIRP_CONTEXT IrpContext, - IN PIRP Irp, - IN PFCB Fcb - ) -{ - PKEVENT Event; - PERESOURCE Resource; - - UDFPrint(("Getting too close to stack limit pass request to Fsp\n")); - - // Allocate an event and get shared on the resource we will - // be later using the common read. - Event = (PKEVENT)MyAllocatePool__(NonPagedPool, sizeof(KEVENT)); - if (!Event) - return STATUS_INSUFFICIENT_RESOURCES; - KeInitializeEvent( Event, NotificationEvent, FALSE ); - - if (Irp->Flags & IRP_PAGING_IO && Fcb->Header.PagingIoResource) { - Resource = Fcb->Header.PagingIoResource; - } else { - Resource = Fcb->Header.Resource; - } - - UDFAcquireResourceShared(Resource, TRUE); - - _SEH2_TRY { - // If this read is the result of a verify, we have to - // tell the overflow read routne to temporarily - // hijack the Vcb->VerifyThread field so that reads - // can go through. - FsRtlPostStackOverflow(IrpContext, Event, UDFStackOverflowRead); - // And wait for the worker thread to complete the item - DbgWaitForSingleObject(Event, NULL); - - } _SEH2_FINALLY { - - UDFReleaseResource( Resource ); - MyFreePool__( Event ); - } _SEH2_END; - - return STATUS_PENDING; - -} // end UDFPostStackOverflowRead() - -/************************************************************************* -* -* Function: UDFStackOverflowRead() -* -* Description: -* Process a read request that could not be processed by -* the fsp thread because of stack overflow potential. -* -* Arguments: -* Context - Supplies the IrpContext being processed -* Event - Supplies the event to be signaled when we are done processing this -* request. -* -* Expected Interrupt Level (for execution) : -* -* IRQL_PASSIVE_LEVEL -* -* Return Value: None. -* -*************************************************************************/ -VOID -NTAPI -UDFStackOverflowRead( - IN PVOID Context, - IN PKEVENT Event - ) -{ - PIRP_CONTEXT IrpContext = (PIRP_CONTEXT)Context; - NTSTATUS RC; - - UDFPrint(("UDFStackOverflowRead: \n")); - // Make it now look like we can wait for I/O to complete - IrpContext->Flags |= IRP_CONTEXT_FLAG_WAIT; - - // Do the read operation protected by a try-except clause - _SEH2_TRY { - UDFCommonRead(IrpContext, IrpContext->Irp); - } _SEH2_EXCEPT(UDFExceptionFilter(IrpContext, _SEH2_GetExceptionInformation())) { - - RC = UDFProcessException(IrpContext, IrpContext->Irp, _SEH2_GetExceptionCode()); - } _SEH2_END; - - // Set the stack overflow item's event to tell the original - // thread that we're done. - KeSetEvent( Event, 0, FALSE ); -} // end UDFStackOverflowRead() - - /************************************************************************* * * Function: UDFCommonRead() @@ -171,27 +52,44 @@ UDFCommonRead( PIRP Irp ) { - NTSTATUS RC = STATUS_SUCCESS; - PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); - LARGE_INTEGER ByteOffset; - ULONG ReadLength = 0, TruncatedLength = 0; - SIZE_T NumberBytesRead = 0; - PFILE_OBJECT FileObject = NULL; + NTSTATUS Status = STATUS_SUCCESS; + PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); + LONGLONG StartingOffset; + LONGLONG ByteRange; + ULONG ReadLength; + ULONG ByteCount; + ULONG NumberBytesRead = 0; + LONGLONG FileSize; TYPE_OF_OPEN TypeOfOpen; PFCB Fcb = NULL; PCCB Ccb = NULL; PVCB Vcb = NULL; BOOLEAN VcbAcquired = FALSE; - BOOLEAN MainResourceAcquired = FALSE; - BOOLEAN PagingIoResourceAcquired = FALSE; + BOOLEAN FcbAcquired = FALSE; PVOID SystemBuffer = NULL; - BOOLEAN CacheLocked = FALSE; - - BOOLEAN CanWait = FALSE; - BOOLEAN PagingIo = FALSE; - BOOLEAN NonCachedIo = FALSE; - BOOLEAN SynchronousIo = FALSE; + BOOLEAN Wait; + BOOLEAN PagingIo; + BOOLEAN NonCachedIo; + BOOLEAN SynchronousIo; + + // Read request byte range visualization: + // + // File: [=========================================] + // 0 1000 1500 FileSize + // + // Read request: + // StartingOffset ByteRange + // ↓ ↓ + // [. . . . .[â– â– â– â– â– â– â– â– â– â– â– â– â– â– â– â– â– â– ]. . . . . . ] + // 0 1000 1500 + // + // |<── ByteCount ────>| + // (500 bytes) + // + // StartingOffset - where to start reading + // ByteCount - how many bytes to read + // ByteRange - end position (StartingOffset + ByteCount) PAGED_CODE(); @@ -221,377 +119,195 @@ UDFCommonRead( return STATUS_SUCCESS; } - _SEH2_TRY { + // Examine our input parameters to determine if this is noncached and/or + // a paging io operation. - FileObject = IrpSp->FileObject; - ASSERT(FileObject); + Wait = BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); + PagingIo = FlagOn(Irp->Flags, IRP_PAGING_IO); + NonCachedIo = FlagOn(Irp->Flags, IRP_NOCACHE); + SynchronousIo = FlagOn(IrpSp->FileObject->Flags, FO_SYNCHRONOUS_IO); - if (Fcb->FcbState & UDF_FCB_DELETED) { - ASSERT(FALSE); - try_return(RC = STATUS_ACCESS_DENIED); - } + // Extract the range of the Io. - // check for stack overflow - if (IoGetRemainingStackSize() < OVERFLOW_READ_THRESHHOLD) { - RC = UDFPostStackOverflowRead( IrpContext, Irp, Fcb ); - try_return(RC); - } + StartingOffset = IrpSp->Parameters.Read.ByteOffset.QuadPart; + ReadLength = ByteCount = IrpSp->Parameters.Read.Length; - // Disk based file systems might decide to verify the logical volume - // (if required and only if removable media are supported) at this time - // As soon as Tray is locked, we needn't call UDFVerifyVcb() + ByteRange = StartingOffset + ByteCount; - ByteOffset = IrpSp->Parameters.Read.ByteOffset; + // Watch for overflow - CanWait = (IrpContext->Flags & IRP_CONTEXT_FLAG_WAIT) ? TRUE : FALSE; - PagingIo = (Irp->Flags & IRP_PAGING_IO) ? TRUE : FALSE; - NonCachedIo = (Irp->Flags & IRP_NOCACHE) ? TRUE : FALSE; - SynchronousIo = (FileObject->Flags & FO_SYNCHRONOUS_IO) ? TRUE : FALSE; - UDFPrint((" Flags: %s %s %s %s\n", - CanWait ? "W" : "w", PagingIo ? "Pg" : "pg", - NonCachedIo ? "NonCached" : "Cached", SynchronousIo ? "Snc" : "Asc")); + if ((MAXLONGLONG - StartingOffset) < ByteCount) { - if (!NonCachedIo && - (Fcb->NodeIdentifier.NodeTypeCode != UDF_NODE_TYPE_VCB)) { + UDFCompleteRequest(IrpContext, Irp, STATUS_INVALID_PARAMETER); + return STATUS_INVALID_PARAMETER; + } - if (UDFIsAStream(Fcb->FileInfo)) { + // Make sure that Dasd access is always non-cached. - UDFNotifyFullReportChange(Vcb, - Fcb, - FILE_NOTIFY_CHANGE_LAST_ACCESS, - FILE_ACTION_MODIFIED_STREAM); - } else { + if (TypeOfOpen == UserVolumeOpen) { - UDFNotifyFullReportChange(Vcb, - Fcb, - FILE_NOTIFY_CHANGE_LAST_ACCESS, - FILE_ACTION_MODIFIED); - } - } + NonCachedIo = TRUE; + } - // Get some of the parameters supplied to us - ReadLength = IrpSp->Parameters.Read.Length; - if (ReadLength == 0) { - // a 0 byte read can be immediately succeeded - try_return(RC); - } - UDFPrint((" ByteOffset = %I64x, ReadLength = %x\n", ByteOffset.QuadPart, ReadLength)); + _SEH2_TRY { - // Is this a read of the volume itself ? - if (Fcb == Fcb->Vcb->VolumeDasdFcb) { - // Yup, we need to send this on to the disk driver after - // validation of the offset and length. + // Acquire the appropriate FCB resource shared - Vcb->VcbState |= UDF_VCB_SKIP_EJECT_CHECK; - if (!CanWait) - try_return(RC = STATUS_PENDING); + if (PagingIo) { - if (IrpContext->Flags & UDF_IRP_CONTEXT_FLUSH2_REQUIRED) { + UDFAcquireFcbSharedStarveExclusive(IrpContext, Fcb, FALSE); + FcbAcquired = TRUE; - UDFPrint((" UDF_IRP_CONTEXT_FLUSH2_REQUIRED\n")); - IrpContext->Flags &= ~UDF_IRP_CONTEXT_FLUSH2_REQUIRED; + } else { -#ifdef UDF_DELAYED_CLOSE - UDFFspClose(Vcb); -#endif //UDF_DELAYED_CLOSE + // Try to acquire the FCB MainResource shared - } + if (NonCachedIo && Fcb->FcbNonpaged->SegmentObject.DataSectionObject) { - if (IrpContext->Flags & UDF_IRP_CONTEXT_FLUSH_REQUIRED) { + // We hold the main resource exclusive here because the flush + // may generate a recursive write in this thread. - UDFPrint((" UDF_IRP_CONTEXT_FLUSH_REQUIRED\n")); - IrpContext->Flags &= ~UDF_IRP_CONTEXT_FLUSH_REQUIRED; + UDFAcquireFcbExclusive(IrpContext, Fcb, FALSE); + FcbAcquired = TRUE; - // Acquire the volume resource exclusive - UDFAcquireResourceExclusive(&Vcb->VcbResource, TRUE); - VcbAcquired = TRUE; + CcFlushCache(&Fcb->FcbNonpaged->SegmentObject, + (PLARGE_INTEGER)&StartingOffset, + ReadLength, + &Irp->IoStatus); - UDFFlushVolume(IrpContext, Vcb); + // If the flush failed, return error to the caller - UDFReleaseResource(&Vcb->VcbResource); - VcbAcquired = FALSE; - } + if (!NT_SUCCESS(Status = Irp->IoStatus.Status)) { - // Acquire the volume resource shared ... - UDFAcquireResourceShared(&Vcb->VcbResource, TRUE); - VcbAcquired = TRUE; + try_return(Status); + } - // Forward the request to the lower level driver - // Lock the callers buffer - if (!NT_SUCCESS(RC = UDFLockUserBuffer(IrpContext, ReadLength, IoWriteAccess))) { - try_return(RC); - } - SystemBuffer = UDFMapUserBuffer(Irp); - if (!SystemBuffer) { - try_return(RC = STATUS_INVALID_USER_BUFFER); - } - if (Vcb->VcbCondition == VcbMounted) { - RC = UDFReadData(IrpContext, Vcb, TRUE, ByteOffset.QuadPart, - ReadLength, FALSE, (PCHAR)SystemBuffer, - &NumberBytesRead); - } else { - RC = UDFTRead(IrpContext, Vcb, SystemBuffer, ReadLength, - (ULONG)(ByteOffset.QuadPart >> Vcb->SectorShift), - &NumberBytesRead); - } - UDFUnlockCallersBuffer(IrpContext, Irp, SystemBuffer); - try_return(RC); - } - Vcb->VcbState |= UDF_VCB_SKIP_EJECT_CHECK; + UDFConvertExclusiveToSharedLite(&Fcb->FcbNonpaged->FcbResource); - // If the read request is directed to a page file (if your FSD - // supports paging files), send the request directly to the disk - // driver. For requests directed to a page file, you have to trust - // that the offsets will be set correctly by the VMM. You should not - // attempt to acquire any FSD resources either. + } else { - if (ByteOffset.HighPart == -1) { - if (ByteOffset.LowPart == FILE_USE_FILE_POINTER_POSITION) { - ByteOffset = FileObject->CurrentByteOffset; + UDFAcquireFcbShared(IrpContext, Fcb, FALSE); + FcbAcquired = TRUE; } } - // If this read is directed to a directory, it is not allowed - // by the UDF FSD. - if (Fcb->FcbState & UDF_FCB_DIRECTORY) { - RC = STATUS_INVALID_DEVICE_REQUEST; - try_return(RC); - } - - // There are certain complications that arise when the same file stream - // has been opened for cached and non-cached access. The FSD is then - // responsible for maintaining a consistent view of the data seen by - // the caller. - // Also, it is possible for file streams to be mapped in both as data files - // and as an executable. This could also lead to consistency problems since - // there now exist two separate sections (and pages) containing file - // information. - - // The test below flushes the data cached in system memory if the current - // request madates non-cached access (file stream must be cached) and - // (a) the current request is not paging-io which indicates it is not - // a recursive I/O operation OR originating in the Cache Manager - // (b) OR the current request is paging-io BUT it did not originate via - // the Cache Manager (or is a recursive I/O operation) and we do - // have an image section that has been initialized. - - // Acquire the appropriate FCB resource shared - if (PagingIo) { - - // Don't offload jobs when doing paging IO - otherwise this can lead to - // deadlocks in CcCopyRead. - CanWait = true; - // Try to acquire the FCB PagingIoResource shared - if (!UDFAcquireSharedStarveExclusive(&Fcb->FcbNonpaged->FcbPagingIoResource, CanWait)) { - try_return(RC = STATUS_PENDING); - } - PagingIoResourceAcquired = TRUE; - - } else { - // Try to acquire the FCB MainResource shared - if (NonCachedIo && Fcb->FcbNonpaged->SegmentObject.DataSectionObject) { - - // We hold the main resource exclusive here because the flush - // may generate a recursive write in this thread. - UDF_CHECK_PAGING_IO_RESOURCE(Fcb); - if (!UDFAcquireResourceExclusive(&Fcb->FcbNonpaged->FcbResource, CanWait)) { - try_return(RC = STATUS_PENDING); - } - MainResourceAcquired = TRUE; + // Verify the Fcb. Allow reads if this is a DASD handle that is + // dismounting the volume. - // We hold PagingIo shared around the flush to fix a - // cache coherency problem. - UDFAcquireResourceShared(&Fcb->FcbNonpaged->FcbPagingIoResource, TRUE ); + if ((TypeOfOpen != UserVolumeOpen) || (NULL == Ccb) || + !FlagOn(Ccb->Flags, CCB_FLAG_DISMOUNT_ON_CLOSE)) { + + UDFVerifyFcbOperation(IrpContext, Fcb, Ccb); + } - MmPrint((" CcFlushCache()\n")); - CcFlushCache(&Fcb->FcbNonpaged->SegmentObject, &ByteOffset, ReadLength, &Irp->IoStatus); + // If this is a user request then verify the oplock and filelock state. - UDFReleaseResource(&Fcb->FcbNonpaged->FcbPagingIoResource); + if (!PagingIo && TypeOfOpen == UserFileOpen) { - // If the flush failed, return error to the caller - if (!NT_SUCCESS(RC = Irp->IoStatus.Status)) { - try_return(RC); - } + if (Fcb->FileLock != NULL && + !FsRtlCheckLockForReadAccess(Fcb->FileLock, Irp)) { - UDFConvertExclusiveToSharedLite(&Fcb->FcbNonpaged->FcbResource); - - } else { - UDF_CHECK_PAGING_IO_RESOURCE(Fcb); - if (!UDFAcquireResourceShared(&Fcb->FcbNonpaged->FcbResource, CanWait)) { - try_return(RC = STATUS_PENDING); - } - MainResourceAcquired = TRUE; + try_return(Status = STATUS_FILE_LOCK_CONFLICT); } } - // This is a good place for oplock related processing. + // Handle I/O at EOF synchronization - // If this is the normal file we have to check for - // write access according to the current state of the file locks. + ExAcquireFastMutex(Fcb->Header.FastMutex); + if (!PagingIo && - Fcb->FileLock != NULL && - !FsRtlCheckLockForReadAccess(Fcb->FileLock, Irp)) { - - try_return( RC = STATUS_FILE_LOCK_CONFLICT ); + FlagOn(Fcb->Header.Flags, FSRTL_FLAG_EOF_ADVANCE_ACTIVE) && + ByteRange > Fcb->Header.ValidDataLength.QuadPart && + StartingOffset < Fcb->Header.FileSize.QuadPart) { + + if (UDFWaitForIoAtEof(Fcb, StartingOffset, ByteCount)) { + UDFFinishIoAtEof(Fcb); + } } - // Validate start offset and length supplied. - // If start offset is > end-of-file, return an appropriate error. Note - // that since a FCB resource has already been acquired, and since all - // file size changes require acquisition of both FCB resources, - // the contents of the FCB and associated data structures - // can safely be examined. - - // Also note that we are using the file size in the "Common FCB Header" - // to perform the check. However, your FSD might decide to keep a - // separate copy in the FCB (or some other representation of the - // file associated with the FCB). - - TruncatedLength = ReadLength; - if (ByteOffset.QuadPart >= Fcb->Header.FileSize.QuadPart) { - // Starting offset is >= file size - try_return(RC = STATUS_END_OF_FILE); - } - // We can also go ahead and truncate the read length here - // such that it is contained within the file size - if (Fcb->Header.FileSize.QuadPart < (ByteOffset.QuadPart + ReadLength)) { - TruncatedLength = (ULONG)(Fcb->Header.FileSize.QuadPart - ByteOffset.QuadPart); - // we can't get ZERO here - } - UDFPrint((" TruncatedLength = %x\n", TruncatedLength)); + // Capture current file size - // This is also a good place to set whether fast-io can be performed - // on this particular file or not. Your FSD must make it's own - // determination on whether or not to allow fast-io operations. - // Commonly, fast-io is not allowed if any byte range locks exist - // on the file or if oplocks prevent fast-io. Practically any reason - // choosen by your FSD could result in your setting FastIoIsNotPossible - // OR FastIoIsQuestionable instead of FastIoIsPossible. + FileSize = Fcb->Header.FileSize.QuadPart; - Fcb->Header.IsFastIoPossible = UDFIsFastIoPossible(Fcb); -/* if (NtReqFcb->CommonFCBHeader.IsFastIoPossible == FastIoIsPossible) - NtReqFcb->CommonFCBHeader.IsFastIoPossible = FastIoIsQuestionable;*/ + ExReleaseFastMutex(Fcb->Header.FastMutex); -#ifdef UDF_DISABLE_SYSTEM_CACHE_MANAGER - NonCachedIo = TRUE; -#endif + ByteCount = ReadLength; - if (Fcb && Fcb->FileInfo && Fcb->FileInfo->Dloc) { - AdPrint(("UDFCommonRead: DataLoc %x, Mapping %x\n", &Fcb->FileInfo->Dloc->DataLoc, Fcb->FileInfo->Dloc->DataLoc.Mapping)); - } + // Check request beyond end of file if this is not a read on a volume + // handle marked for extended DASD IO. - // Branch here for cached vs non-cached I/O - if (!NonCachedIo) { - - // The caller wishes to perform cached I/O. Initiate caching if - // this is the first cached I/O operation using this file object - if (!(FileObject->PrivateCacheMap)) { - // This is the first cached I/O operation. You must ensure - // that the FCB Common FCB Header contains valid sizes at this time - MmPrint((" CcInitializeCacheMap()\n")); - CcInitializeCacheMap(FileObject, (PCC_FILE_SIZES)&Fcb->Header.AllocationSize, - FALSE, // We will not utilize pin access for this file - &(UdfData.CacheMgrCallBacks), // callbacks - Fcb); // The context used in callbacks - MmPrint((" CcSetReadAheadGranularity()\n")); - CcSetReadAheadGranularity(FileObject, READ_AHEAD_GRANULARITY); - } + if ((TypeOfOpen != UserVolumeOpen) || + (!FlagOn(Ccb->Flags, CCB_FLAG_ALLOW_EXTENDED_DASD_IO))) { - // Check and see if this request requires a MDL returned to the caller - if (IrpSp->MinorFunction & IRP_MN_MDL) { - // Caller does want a MDL returned. Note that this mode - // implies that the caller is prepared to block - MmPrint((" CcMdlRead()\n")); -// CcMdlRead(FileObject, &ByteOffset, TruncatedLength, &(Irp->MdlAddress), &(Irp->IoStatus)); -// NumberBytesRead = Irp->IoStatus.Information; -// RC = Irp->IoStatus.Status; - NumberBytesRead = 0; - RC = STATUS_INVALID_PARAMETER; + // Complete the request if it begins beyond the end of file. - try_return(RC); - } + if (StartingOffset >= FileSize) { - // This is a regular run-of-the-mill cached I/O request. Let the - // Cache Manager worry about it! - // First though, we need a buffer pointer (address) that is valid - SystemBuffer = UDFMapUserBuffer(Irp); - if (!SystemBuffer) - try_return(RC = STATUS_INVALID_USER_BUFFER); - ASSERT(SystemBuffer); - MmPrint((" CcCopyRead()\n")); - if (!CcCopyRead(FileObject, &(ByteOffset), TruncatedLength, CanWait, SystemBuffer, &Irp->IoStatus)) { - // The caller was not prepared to block and data is not immediately - // available in the system cache - try_return(RC = STATUS_PENDING); + try_return(Status = STATUS_END_OF_FILE); } - UDFUnlockCallersBuffer(IrpContext, Irp, SystemBuffer); - // We have the data - RC = Irp->IoStatus.Status; - NumberBytesRead = Irp->IoStatus.Information; + // Truncate the read if it extends beyond the end of the file. - try_return(RC); + if (ByteRange > FileSize) { - } else { + ByteCount = (ULONG)(FileSize - StartingOffset); + ByteRange = FileSize; + } + } - MmPrint((" Read NonCachedIo\n")); + // Handle the non-cached read first. - if (!CanWait && UDFIsFileCached__(Vcb, Fcb->FileInfo, ByteOffset.QuadPart, TruncatedLength, FALSE)) { - MmPrint((" Locked => CanWait\n")); - CacheLocked = TRUE; - CanWait = TRUE; - } + if (NonCachedIo) { // Send the request to lower level drivers - if (!CanWait) { - try_return(RC = STATUS_PENDING); - } -// ASSERT(NT_SUCCESS(RC)); + if (!Wait) { + try_return(Status = STATUS_CANT_WAIT); + } - RC = UDFLockUserBuffer(IrpContext, TruncatedLength, IoWriteAccess); - if (!NT_SUCCESS(RC)) { - try_return(RC); + Status = UDFLockUserBuffer(IrpContext, ByteCount, IoWriteAccess); + if (!NT_SUCCESS(Status)) { + try_return(Status); } SystemBuffer = UDFMapUserBuffer(Irp); if (!SystemBuffer) { - try_return(RC = STATUS_INVALID_USER_BUFFER); + try_return(Status = STATUS_INVALID_USER_BUFFER); } // Start by zeroing any part of the read after Valid Data LARGE_INTEGER ValidDataLength = Fcb->Header.ValidDataLength; - if (ByteOffset.QuadPart + TruncatedLength > ValidDataLength.QuadPart) { + if (StartingOffset + ByteCount > ValidDataLength.QuadPart) { - if (ByteOffset.QuadPart < ValidDataLength.QuadPart) { + if (StartingOffset < ValidDataLength.QuadPart) { ULONG LBS = Vcb->SectorSize; - ULONG ZeroingOffset = ((ValidDataLength.QuadPart - ByteOffset.QuadPart) + (LBS - 1)) & ~(LBS - 1); + ULONG ZeroingOffset = ((ValidDataLength.QuadPart - StartingOffset) + (LBS - 1)) & ~(LBS - 1); // If the offset is at or above the byte count, no harm: just means // that the read ends in the last sector and the zeroing will be // done at completion. - if (TruncatedLength > ZeroingOffset) { + if (ByteCount > ZeroingOffset) { - SafeZeroMemory((PUCHAR)SystemBuffer + ZeroingOffset, TruncatedLength - ZeroingOffset); + SafeZeroMemory((PUCHAR)SystemBuffer + ZeroingOffset, ByteCount - ZeroingOffset); } } else { // All we have to do now is sit here and zero the // user's buffer, no reading is required. - SafeZeroMemory(SystemBuffer, TruncatedLength); - NumberBytesRead = TruncatedLength; + SafeZeroMemory(SystemBuffer, ByteCount); + NumberBytesRead = ByteCount; UDFUnlockCallersBuffer(IrpContext, Irp, SystemBuffer); try_return(STATUS_SUCCESS); } } - RC = UDFReadFile__(IrpContext, Vcb, Fcb->FileInfo, ByteOffset.QuadPart, TruncatedLength, - CacheLocked, (PCHAR)SystemBuffer, &NumberBytesRead); + Status = UDFReadFile__(IrpContext, Vcb, Fcb->FileInfo, StartingOffset, ByteCount, + FALSE, (PCHAR)SystemBuffer, &NumberBytesRead); /* // AFAIU, CacheManager wants this: if (!NT_SUCCESS(RC)) { NumberBytesRead = 0; @@ -599,7 +315,7 @@ UDFCommonRead( UDFUnlockCallersBuffer(IrpContext, Irp, SystemBuffer); - try_return(RC); + try_return(Status); // For paging-io, the FSD has to trust the VMM to do the right thing @@ -617,60 +333,118 @@ UDFCommonRead( // return zeroes to the caller for reads extending beyond current // valid data length. + } else { + + // Handle the cached case. Start by initializing the private + // cache map. + + if (IrpSp->FileObject->PrivateCacheMap == NULL) { + + // Now initialize the cache map. + + CcInitializeCacheMap(IrpSp->FileObject, + (PCC_FILE_SIZES)&Fcb->Header.AllocationSize, + FALSE, + &UdfData.CacheMgrCallBacks, + Fcb); + + CcSetReadAheadGranularity(IrpSp->FileObject, READ_AHEAD_GRANULARITY); + } + + // Read from the cache if this is not an Mdl read. + + if (!FlagOn(IrpContext->MinorFunction, IRP_MN_MDL)) { + + // If we are in the Fsp now because we had to wait earlier, + // we must map the user buffer, otherwise we can use the + // user's buffer directly. + + SystemBuffer = UDFMapUserBuffer(Irp); + + // Now try to do the copy. + + if (!CcCopyRead(IrpSp->FileObject, + (PLARGE_INTEGER)&StartingOffset, + ByteCount, + Wait, + SystemBuffer, + &Irp->IoStatus)) { + + try_return(Status = STATUS_CANT_WAIT); + } + + // If the call didn't succeed, raise the error status + + if (!NT_SUCCESS(Irp->IoStatus.Status)) { + + UDFNormalizeAndRaiseStatus(IrpContext, Irp->IoStatus.Status); + } + + Status = Irp->IoStatus.Status; + + // Otherwise perform the MdlRead operation. + } + else { + + CcMdlRead(IrpSp->FileObject, + (PLARGE_INTEGER)&StartingOffset, + ByteCount, + &Irp->MdlAddress, + &Irp->IoStatus); + + Status = Irp->IoStatus.Status; + } + + NumberBytesRead = Irp->IoStatus.Information; + + try_return(Status); + } try_exit: NOTHING; } _SEH2_FINALLY { - if (CacheLocked) { - WCacheEODirect__(&(Vcb->FastCache), Vcb); - } - - // Release any resources acquired here ... - if (PagingIoResourceAcquired) { - UDFReleaseResource(&Fcb->FcbNonpaged->FcbPagingIoResource); - } + if (FcbAcquired) { - if (MainResourceAcquired) { - UDF_CHECK_PAGING_IO_RESOURCE(Fcb); - UDFReleaseResource(&Fcb->FcbNonpaged->FcbResource); + UDFReleaseFcb(IrpContext, Fcb); } if (VcbAcquired) { - UDFReleaseResource(&Vcb->VcbResource); + + UDFReleaseVcb(IrpContext, Vcb); } } _SEH2_END; // end of "__finally" processing // Post the request if we got CANT_WAIT. - if (RC == STATUS_PENDING) { + if (Status == STATUS_CANT_WAIT) { - RC = UDFFsdPostRequest(IrpContext, Irp); + Status = UDFFsdPostRequest(IrpContext, Irp); } else { // For synchronous I/O, the FSD must maintain the current byte offset // Do not do this however, if I/O is marked as paging-io - if (SynchronousIo && !PagingIo && NT_SUCCESS(RC)) { + if (SynchronousIo && !PagingIo && NT_SUCCESS(Status)) { - FileObject->CurrentByteOffset.QuadPart = ByteOffset.QuadPart + NumberBytesRead; + IrpSp->FileObject->CurrentByteOffset.QuadPart = StartingOffset + NumberBytesRead; } // If the read completed successfully and this was not a paging-io // operation, set a flag in the CCB that indicates that a read was // performed and that the file time should be updated at cleanup - if (NT_SUCCESS(RC) && !PagingIo) { - FileObject->Flags |= FO_FILE_FAST_IO_READ; + if (NT_SUCCESS(Status) && !PagingIo) { + IrpSp->FileObject->Flags |= FO_FILE_FAST_IO_READ; } Irp->IoStatus.Information = NumberBytesRead; - UDFCompleteRequest(IrpContext, Irp, RC); + UDFCompleteRequest(IrpContext, Irp, Status); } - return(RC); + return Status; } // end UDFCommonRead() @@ -706,7 +480,14 @@ UDFMapUserBuffer( } else { - return MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority | MdlMappingNoExecute); + PVOID Address = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority | MdlMappingNoExecute); + + if (Address == NULL) { + + ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES); + } + + return Address; } } // end UDFMapUserBuffer() @@ -834,27 +615,82 @@ UDFCompleteMdl( ) { PFILE_OBJECT FileObject; - PIO_STACK_LOCATION IrpSp; + PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); + PFCB Fcb; - UDFPrint(("UDFCompleteMdl: \n")); - - IrpSp = IoGetCurrentIrpStackLocation(Irp); + // Do completion processing. FileObject = IrpSp->FileObject; - ASSERT(FileObject); - // Not much to do here. - if (IrpContext->MajorFunction == IRP_MJ_READ) { + switch(IrpContext->MajorFunction) { + + case IRP_MJ_READ: - MmPrint((" CcMdlReadComplete() MDL=%x\n", Irp->MdlAddress)); CcMdlReadComplete(FileObject, Irp->MdlAddress); + break; - } else { + case IRP_MJ_WRITE: + + UDFFastDecodeFileObject(FileObject, &Fcb); + + ASSERT(FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)); + + // Check if EOF advance is active. + + if (FlagOn(Fcb->Header.Flags, FSRTL_FLAG_EOF_ADVANCE_ACTIVE)) { + + LONGLONG ByteRange = IrpSp->Parameters.Write.ByteOffset.QuadPart; + + PMDL MdlChain = Irp->MdlAddress; + while (MdlChain != NULL) + { + ByteRange += MmGetMdlByteCount(MdlChain); + MdlChain = MdlChain->Next; + } + + // Acquire the fast mutex and check if we extended valid data. + + ExAcquireFastMutex(Fcb->Header.FastMutex); + + if (ByteRange > Fcb->Header.ValidDataLength.QuadPart) { + + // Extend valid data length to file size. + + Fcb->Header.ValidDataLength.QuadPart = Fcb->Header.FileSize.QuadPart; + + // Notify cache manager of new file sizes if caching is active. + + if (CcIsFileCached(FileObject)) { + + _SEH2_TRY { + + CcSetFileSizes(FileObject, (PCC_FILE_SIZES)&Fcb->Header.AllocationSize); + + } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { + + NOTHING; + + } _SEH2_END; + } + + // Complete the EOF advance operation. + + UDFFinishIoAtEof(Fcb); + } + + ExReleaseFastMutex(Fcb->Header.FastMutex); + + } - ASSERT(IrpContext->MajorFunction == IRP_MJ_WRITE); - // The Cache Manager needs the byte offset in the I/O stack location. - MmPrint((" CcMdlWriteComplete() MDL=%x\n", Irp->MdlAddress)); CcMdlWriteComplete(FileObject, &IrpSp->Parameters.Write.ByteOffset, Irp->MdlAddress); + + Irp->IoStatus.Status = STATUS_SUCCESS; + + break; + + default: + + UDFBugCheck(IrpContext->MajorFunction, 0, 0); } // Mdl is now deallocated. diff --git a/drivers/filesystems/udfs/shutdown.cpp b/drivers/filesystems/udfs/shutdown.cpp index bb2afb2d128c8..f8b0a7fb4b859 100644 --- a/drivers/filesystems/udfs/shutdown.cpp +++ b/drivers/filesystems/udfs/shutdown.cpp @@ -91,7 +91,7 @@ UDFCommonShutdown( while (Link != &(UdfData.VcbQueue)) { - Vcb = CONTAINING_RECORD( Link, VCB, NextVCB ); + Vcb = CONTAINING_RECORD(Link, VCB, VcbLinks); // Move to the next link now since the current Vcb may be deleted. diff --git a/drivers/filesystems/udfs/strucsup.cpp b/drivers/filesystems/udfs/strucsup.cpp index 9add5f14e35ed..6e00af7d5bd4f 100644 --- a/drivers/filesystems/udfs/strucsup.cpp +++ b/drivers/filesystems/udfs/strucsup.cpp @@ -552,6 +552,7 @@ UDFInitializeFCB( ASSERT(!Fcb->Header.Resource); Fcb->Header.Resource = &Fcb->FcbNonpaged->FcbResource; Fcb->Header.PagingIoResource = &Fcb->FcbNonpaged->FcbPagingIoResource; + InitializeListHead(&Fcb->EofListHead); FsRtlSetupAdvancedHeader(&Fcb->Header, &Fcb->FcbNonpaged->AdvancedFcbHeaderMutex); Fcb->FileLock = NULL; @@ -801,11 +802,6 @@ UDFInitializeVCB( Vcb->VcbReference = 1 + Vcb->VcbResidualReference; - Vcb->WCacheMaxBlocks = UdfData.WCacheMaxBlocks; - Vcb->WCacheMaxFrames = UdfData.WCacheMaxFrames; - Vcb->WCacheBlocksPerFrameSh = UdfData.WCacheBlocksPerFrameSh; - Vcb->WCacheFramesToKeepFree = UdfData.WCacheFramesToKeepFree; - // Create a stream file object for this volume. //Vcb->PtrStreamFileObject = IoCreateStreamFileObject(NULL, // Vcb->Vpb->RealDevice); @@ -821,7 +817,7 @@ UDFInitializeVCB( // Insert this Vcb record on the CdData.VcbQueue. ASSERT_EXCLUSIVE_CDDATA; - InsertTailList(&(UdfData.VcbQueue), &(Vcb->NextVCB)); + InsertTailList(&(UdfData.VcbQueue), &(Vcb->VcbLinks)); // Initialize caching for the stream file object. //CcInitializeCacheMap(Vcb->PtrStreamFileObject, (PCC_FILE_SIZES)(&(Vcb->AllocationSize)), @@ -1106,8 +1102,6 @@ UDFCompleteMount( if (NT_SUCCESS(Status)) { - Vcb->UniqueIDMapFileInfo->Dloc->DataLoc.Flags |= EXTENT_FLAG_VERIFY; - } else if (Status == STATUS_OBJECT_NAME_NOT_FOUND) { Vcb->UniqueIDMapFileInfo = NULL; diff --git a/drivers/filesystems/udfs/struct.h b/drivers/filesystems/udfs/struct.h index a1fbba1b12c91..fb48f5e8b0cac 100644 --- a/drivers/filesystems/udfs/struct.h +++ b/drivers/filesystems/udfs/struct.h @@ -102,6 +102,7 @@ using PCCB = CCB*; // the CCB has had an IRP_MJ_CLEANUP issued on it. we must // no longer allow the file object / CCB to be used in I/O requests. #define UDF_CCB_CLEANED (0x00000008) +#define CCB_FLAG_ALLOW_EXTENDED_DASD_IO (0x00000010) // if an application process set the file date time, we must // honor that request and *not* overwrite the values at cleanup #define UDF_CCB_ACCESS_TIME_SET (0x00000040) @@ -207,6 +208,7 @@ struct FCB { FSRTL_ADVANCED_FCB_HEADER Header; }; + LIST_ENTRY EofListHead; ULONG NtReqFCBFlags; // UDF related data @@ -295,6 +297,9 @@ using PFCB = FCB*; values are bit fields; therefore we can test whether a bit position is set (1) or not set (0). **************************************************************************/ +// File data is embedded in ICB (IN_ICB allocation mode) +// Requires exclusive lock for writes since data shares sector with metadata +#define UDF_FCB_EMBEDDED_DATA (0x00000001) #define UDF_FCB_VALID (0x00000002) #define UDF_FCB_DIRECTORY (0x00000008) #define UDF_FCB_ROOT_DIRECTORY (0x00000010) @@ -354,8 +359,16 @@ struct VCB { ULONG VcbResidualReference; ULONG VcbResidualUserReference; ERESOURCE FlushResource; - // each VCB is accessible off a global linked list - LIST_ENTRY NextVCB; + + // Link into queue of Vcb's in the CdData structure. We will create a union with + // a LONGLONG to force the Vcb to be quad-aligned. + + union { + + LIST_ENTRY VcbLinks; + LONGLONG Alignment; + }; + // each VCB points to a VPB structure created by the NT I/O Manager PVPB Vpb; // we will maintain a global list of IRP's that are pending @@ -363,11 +376,12 @@ struct VCB { LIST_ENTRY NextNotifyIRP; // the above list is protected only by the mutex declared below PNOTIFY_SYNC NotifySync; + // We also retain a pointer to the physical device object on which we // have mounted ourselves. The I/O Manager passes us a pointer to this // device object when requesting a mount operation. PDEVICE_OBJECT TargetDeviceObject; - PCWSTR DefaultRegName; + // the volume structure contains a pointer to the root directory FCB FCB* RootIndexFcb; FCB* VolumeDasdFcb; @@ -399,8 +413,6 @@ struct VCB { // ULONG MediaLockCount; - BOOLEAN IsVolumeJustMounted; - // FS size cache LONGLONG TotalAllocUnits; LONGLONG FreeAllocUnits; @@ -431,7 +443,10 @@ struct VCB { ULONG SectorSize; ULONG SectorShift; ULONG WriteBlockSize; - + + ULONG SessionStartLba; + ULONG SessionEndLba; + // Number of last session ULONG LastSession; ULONG FirstTrackNum; @@ -462,19 +477,6 @@ struct VCB { BOOLEAN CDR_Mode; BOOLEAN DVD_Mode; -#define SYNC_CACHE_RECOVERY_NONE 0 -#define SYNC_CACHE_RECOVERY_ATTEMPT 1 -#define SYNC_CACHE_RECOVERY_RETRY 2 - - UCHAR SyncCacheState; - - // W-cache - W_CACHE FastCache; - ULONG WCacheMaxFrames; - ULONG WCacheMaxBlocks; - ULONG WCacheBlocksPerFrameSh; - ULONG WCacheFramesToKeepFree; - PCHAR ZBuffer; PCHAR fZBuffer; ULONG fZBufferSize; @@ -482,18 +484,10 @@ struct VCB { ULONG IoErrorCounter; // Media change count (equal to the same field in CDFS VCB) ULONG MediaChangeCount; - -#define INCREMENTAL_SEEK_NONE 0 -#define INCREMENTAL_SEEK_WORKAROUND 1 -#define INCREMENTAL_SEEK_DONE 2 - - UCHAR IncrementalSeekState; - BOOLEAN VerifyOnWrite; ULONG MountPhErrorCount; // a set of flags that might mean something useful uint32 VcbState; - BOOLEAN FP_disc; //--------------- // UDF related data @@ -502,9 +496,6 @@ struct VCB { // Anchors LBA #define MAX_ANCHOR_LOCATIONS 11 ULONG Anchor[MAX_ANCHOR_LOCATIONS]; - ULONG BadSeqLoc[MAX_ANCHOR_LOCATIONS * 2]; - NTSTATUS BadSeqStatus[MAX_ANCHOR_LOCATIONS * 2]; - ULONG BadSeqLocIndex; // Volume label UNICODE_STRING VolIdent; // Volume creation time @@ -606,8 +597,6 @@ struct VCB { PUDF_ALLOCATION_CACHE_ITEM PreallocCache; ULONG PreallocCacheMaxSize; - UDF_VERIFY_CTX VerifyCtx; - uint32 CompatFlags; // Fcb table. Synchronized with the Vcb fast mutex. @@ -873,19 +862,11 @@ typedef struct _UDFData { LARGE_INTEGER UDFLargeZero; - // mount event (for udf gui app) - PKEVENT MountEvent; - UNICODE_STRING SavedRegPath; UNICODE_STRING UnicodeStrRoot; UNICODE_STRING UnicodeStrSDir; UNICODE_STRING AclName; - ULONG WCacheMaxFrames; - ULONG WCacheMaxBlocks; - ULONG WCacheBlocksPerFrameSh; - ULONG WCacheFramesToKeepFree; - } UDFData, *PUDFData; #define UDFS_FLAGS_SHUTDOWN (0x0001) @@ -911,7 +892,6 @@ typedef struct _UDFData { #define VCB_STATE_MEDIA_WRITE_PROTECT (0x00000080) #define VCB_STATE_REMOVABLE_MEDIA (0x00000100) #define UDF_VCB_FLAGS_MEDIA_LOCKED (0x00000200) -#define UDF_VCB_SKIP_EJECT_CHECK (0x00000400) #define UDF_VCB_LAST_WRITE (0x00001000) #define UDF_VCB_FLAGS_TRACKMAP (0x00002000) #define UDF_VCB_ASSUME_ALL_USED (0x00004000) diff --git a/drivers/filesystems/udfs/udf_dbg.h b/drivers/filesystems/udfs/udf_dbg.h index a0bbe56e39d10..63fc430bc3c83 100644 --- a/drivers/filesystems/udfs/udf_dbg.h +++ b/drivers/filesystems/udfs/udf_dbg.h @@ -35,10 +35,10 @@ //#define UDF_SIMULATE_WRITES -#define USE_KD_PRINT -#define USE_MM_PRINT -#define USE_AD_PRINT -#define UDF_DUMP_EXTENT +//#define USE_KD_PRINT +//#define USE_MM_PRINT +//#define USE_AD_PRINT +//#define UDF_DUMP_EXTENT //#define USE_TH_PRINT //#define USE_TIME_PRINT diff --git a/drivers/filesystems/udfs/udf_info/alloc.cpp b/drivers/filesystems/udfs/udf_info/alloc.cpp index ab008b415cf4d..530d6b168767e 100644 --- a/drivers/filesystems/udfs/udf_info/alloc.cpp +++ b/drivers/filesystems/udfs/udf_info/alloc.cpp @@ -644,7 +644,6 @@ UDFMarkSpaceAsXXXNoProtect_( if (asXXX & AS_DISCARDED) { UDFUnmapRange(Vcb, lba, len); - WCacheDiscardBlocks__(&(Vcb->FastCache), Vcb, lba, len); } if (Vcb->Vat) { // mark logical blocks in VAT as free @@ -896,38 +895,3 @@ UDFGetTotalSpace( } return s; } // end UDFGetTotalSpace() - -/* - Callback for WCache - returns Allocated and Zero-filled flags for given block - any data in 'unallocated' blocks may be changed during flush process - */ -uint32 -UDFIsBlockAllocated( - IN void* _Vcb, - IN uint32 Lba - ) -{ - ULONG ret_val = 0; - uint32* bm; -// return TRUE; - if (!(((PVCB)_Vcb)->VcbState & UDF_VCB_ASSUME_ALL_USED)) { - // check used - if ((bm = (uint32*)(((PVCB)_Vcb)->FSBM_Bitmap))) - ret_val = (UDFGetUsedBit(bm, Lba) ? WCACHE_BLOCK_USED : 0); - } else { - ret_val = WCACHE_BLOCK_USED; - } - // check bad block - - // WCache works with LOGICAL addresses, not PHYSICAL, BB check must be performed UNDER cache -/* - if (bm = (uint32*)(((PVCB)_Vcb)->BSBM_Bitmap)) { - ret_val |= (UDFGetBadBit(bm, Lba) ? WCACHE_BLOCK_BAD : 0); - if (ret_val & WCACHE_BLOCK_BAD) { - UDFPrint(("Marked BB @ %#x\n", Lba)); - } - } -*/ - return ret_val; -} // end UDFIsBlockAllocated() diff --git a/drivers/filesystems/udfs/udf_info/dirtree.cpp b/drivers/filesystems/udfs/udf_info/dirtree.cpp index 16c4cde304419..247376ff93ce7 100644 --- a/drivers/filesystems/udfs/udf_info/dirtree.cpp +++ b/drivers/filesystems/udfs/udf_info/dirtree.cpp @@ -471,7 +471,7 @@ UDFIndexDirectory( int8* buff; PEXTENT_INFO ExtInfo; // Extent array for directory uint16 PartNum; - SIZE_T ReadBytes; + ULONG ReadBytes; uint16 valueCRC; if (!FileInfo) return STATUS_INVALID_PARAMETER; @@ -707,7 +707,8 @@ UDFPackDirectory__( uint32 Offset, curOffset; int8* Buf; NTSTATUS status; - SIZE_T ReadBytes; + ULONG ReadBytes; + SIZE_T WrittenBytes; int8* storedFI; PUDF_FILE_INFO curFileInfo; PDIR_INDEX_ITEM DirNdx = NULL, DirNdx2; @@ -815,7 +816,7 @@ UDFPackDirectory__( UDFExtentOffsetToLba(Vcb, FileInfo->Dloc->DataLoc.Mapping, Offset, NULL, NULL, NULL, NULL)), 0); - status = UDFWriteFile__(IrpContext, Vcb, FileInfo, Offset, l, FALSE, Buf, &ReadBytes); + status = UDFWriteFile__(IrpContext, Vcb, FileInfo, Offset, l, FALSE, Buf, &WrittenBytes); if (!NT_SUCCESS(status)) { DbgFreePool(Buf); return status; @@ -863,7 +864,8 @@ UDFReTagDirectory( uint32 Offset; int8* Buf; NTSTATUS status; - SIZE_T ReadBytes; + ULONG ReadBytes; + SIZE_T WrittenBytes; PUDF_FILE_INFO curFileInfo; PDIR_INDEX_ITEM DirNdx; UDF_DIR_SCAN_CONTEXT ScanContext; @@ -917,7 +919,7 @@ UDFReTagDirectory( FileInfo->Dloc->FE_Flags |= UDF_FE_FLAG_FE_MODIFIED; } - status = UDFWriteFile__(IrpContext, Vcb, FileInfo, Offset, l, FALSE, Buf, &ReadBytes); + status = UDFWriteFile__(IrpContext, Vcb, FileInfo, Offset, l, FALSE, Buf, &WrittenBytes); if (!NT_SUCCESS(status)) { DbgFreePool(Buf); return status; diff --git a/drivers/filesystems/udfs/udf_info/extent.cpp b/drivers/filesystems/udfs/udf_info/extent.cpp index 05793bd06c12e..a23ae904189ad 100644 --- a/drivers/filesystems/udfs/udf_info/extent.cpp +++ b/drivers/filesystems/udfs/udf_info/extent.cpp @@ -272,7 +272,7 @@ UDFShortAllocDescToMapping( EXTENT_AD AllocExt; PALLOC_EXT_DESC NextAllocDesc; lb_addr locAddr; - SIZE_T ReadBytes; + ULONG ReadBytes; EXTENT_INFO NextAllocLoc; BOOLEAN w2k_compat = FALSE; @@ -466,7 +466,7 @@ UDFLongAllocDescToMapping( PEXTENT_MAP Extent, Extent2, AllocMap; EXTENT_AD AllocExt; PALLOC_EXT_DESC NextAllocDesc; - SIZE_T ReadBytes; + ULONG ReadBytes; EXTENT_INFO NextAllocLoc; ExtPrint(("UDFLongAllocDescToMapping: len=%x\n", AllocDescLength)); @@ -605,7 +605,7 @@ UDFExtAllocDescToMapping( PEXTENT_MAP Extent, Extent2, AllocMap; EXTENT_AD AllocExt; PALLOC_EXT_DESC NextAllocDesc; - SIZE_T ReadBytes; + ULONG ReadBytes; EXTENT_INFO NextAllocLoc; ExtPrint(("UDFExtAllocDescToMapping: len=%x\n", AllocDescLength)); @@ -783,7 +783,6 @@ UDFReadMappingFromXEntry( // if (!(Vcb->UDF_VCB_IC_ADAPTEC_NONALLOC_COMPAT)) AllocLoc->Length=len; - AllocLoc->Flags |= EXTENT_FLAG_VERIFY; // for metadata switch (AllocMode) { case ICB_FLAG_AD_SHORT: { @@ -2920,60 +2919,6 @@ UDFRelocateExtent( return STATUS_ACCESS_DENIED; } -/* - This routine checks if all the data required is in cache. - */ -BOOLEAN -UDFIsExtentCached( - IN PVCB Vcb, - IN PEXTENT_INFO ExtInfo, // Extent array - IN int64 Offset, // offset in extent - IN uint32 Length, - IN BOOLEAN ForWrite - ) -{ - BOOLEAN retstat = FALSE; - PEXTENT_MAP Extent = ExtInfo->Mapping; // Extent array - SIZE_T to_read; - uint32 Lba, sect_offs, flags, i; - - WCacheStartDirect__(&(Vcb->FastCache), Vcb, TRUE/*FALSE*//*ForWrite*/); - if (!ExtInfo || !ExtInfo->Mapping) goto EO_IsCached; - if (!Length) { - retstat = TRUE; - goto EO_IsCached; - } - - // prevent reading out of data space - if (Offset > ExtInfo->Length) goto EO_IsCached; - if (Offset+Length > ExtInfo->Length) goto EO_IsCached; - Offset += ExtInfo->Offset; // used for in-ICB data - // read maximal possible part of each frag of extent - Lba = UDFExtentOffsetToLba(Vcb, Extent, Offset, §_offs, &to_read, &flags, &i); - while(((LONG)Length) > 0) { - // EOF check - if (Lba == LBA_OUT_OF_EXTENT) goto EO_IsCached; - Extent += (i + 1); - // check for reading tail - to_read = min(to_read, Length); - if (flags == EXTENT_RECORDED_ALLOCATED) { - retstat = UDFIsDataCached(Vcb, Lba, (to_read+sect_offs+Vcb->SectorSize-1)>>Vcb->SectorShift); - if (!retstat) goto EO_IsCached; - } else if (ForWrite) { - goto EO_IsCached; - } - Offset += to_read; - Length -= to_read; - Lba = UDFNextExtentToLba(Vcb, Extent, &to_read, &flags, &i); - } - retstat = TRUE; -EO_IsCached: - if (!retstat) { - WCacheEODirect__(&(Vcb->FastCache), Vcb); - } - return retstat; -} // end UDFIsExtentCached() - /* This routine reads cached data only. */ @@ -3035,7 +2980,7 @@ UDFReadExtent( IN SIZE_T Length, IN BOOLEAN Direct, OUT int8* Buffer, - OUT PSIZE_T ReadBytes + OUT PULONG ReadBytes ) { (*ReadBytes) = 0; @@ -3045,7 +2990,8 @@ UDFReadExtent( AdPrint(("Read ExtInfo %x, Mapping %x\n", ExtInfo, ExtInfo->Mapping)); PEXTENT_MAP Extent = ExtInfo->Mapping; // Extent array - SIZE_T to_read, _ReadBytes; + SIZE_T to_read; + ULONG _ReadBytes; uint32 Lba, sect_offs, flags; uint32 index; NTSTATUS status; diff --git a/drivers/filesystems/udfs/udf_info/mount.cpp b/drivers/filesystems/udfs/udf_info/mount.cpp index 8c6281fd7e487..3fc100aba5a3f 100644 --- a/drivers/filesystems/udfs/udf_info/mount.cpp +++ b/drivers/filesystems/udfs/udf_info/mount.cpp @@ -64,7 +64,7 @@ UDFPrepareXSpaceBitmap( lb_addr locAddr; int8* _XSBM; uint16 Ident; - SIZE_T ReadBytes; + ULONG ReadBytes; uint32 RefPartNum; if (!(XSpaceBitmap->extLength)) { @@ -450,7 +450,6 @@ UDFUpdateLogicalVolInt( Vcb->IntegrityType = INTEGRITY_TYPE_OPEN; // make happy auto-dirty RC = UDFWriteSectors(IrpContext, Vcb, TRUE, PTag->tagLocation, len >> Vcb->SectorShift, FALSE, (int8*)(lvid), &WrittenBytes); - WCacheFlushBlocks__(IrpContext, &Vcb->FastCache, Vcb, PTag->tagLocation, len >> Vcb->SectorShift); // update it here to prevent recursion Vcb->IntegrityType = lvid->integrityType; @@ -473,7 +472,7 @@ UDFUpdateSparingTable( NTSTATUS status2 = STATUS_SUCCESS; uint32 i=0, BC, BC2; PSPARING_TABLE SparTable; - SIZE_T ReadBytes; + ULONG ReadBytes; // uint32 n,m; // BOOLEAN merged; BOOLEAN sorted; @@ -942,9 +941,7 @@ UDFUmount__( // prevent discarding metadata Vcb->VcbState |= UDF_VCB_ASSUME_ALL_USED; if (Vcb->CDR_Mode) { - // flush internal cache - if (WCacheGetWriteBlockCount__(&(Vcb->FastCache)) >= (Vcb->WriteBlockSize >> Vcb->SectorShift) ) - WCacheFlushAll__(IrpContext, &Vcb->FastCache, Vcb); + // record VAT return UDFRecordVAT(IrpContext, Vcb); } @@ -952,13 +949,6 @@ UDFUmount__( UDFFlushAllCachedAllocations(Vcb, UDF_PREALLOC_CLASS_FE); UDFFlushAllCachedAllocations(Vcb, UDF_PREALLOC_CLASS_DIR); - if (Vcb->VerifyOnWrite) { - UDFPrint(("UDF: Flushing cache for verify\n")); - //WCacheFlushAll__(&(Vcb->FastCache), Vcb); - WCacheFlushBlocks__(IrpContext, &Vcb->FastCache, Vcb, 0, Vcb->LastLBA); - UDFVFlush(Vcb); - } - // synchronize BAD Block bitmap and NonAllocatable UDFUpdateNonAllocated(IrpContext, Vcb); @@ -1103,7 +1093,7 @@ UDFFindVRS( uint32 BeginOffset = Vcb->FirstLBA; NTSTATUS RC; int8* buffer = (int8*)MyAllocatePool__(NonPagedPool,Vcb->SectorSize); - SIZE_T ReadBytes; + ULONG ReadBytes; if (!buffer) return 0; // Relative to First LBA in Last Session @@ -1234,7 +1224,6 @@ UDFLoadLogicalVolInt( NTSTATUS RC = STATUS_SUCCESS; uint32 Len; uint32 Lbn; - uint32 SectorSize; int8* Buf = NULL; int8* TempBuf = NULL; uint16 ident; @@ -1253,19 +1242,18 @@ UDFLoadLogicalVolInt( Len = loc.extLength; Lbn = loc.extLocation; - SectorSize = Vcb->SectorSize; // Validate: length must be non-zero and sector-aligned - if (Len == 0 || ((Len & (SectorSize - 1)) != 0)) { + if (Len == 0 || ((Len & (SectorSize(Vcb) - 1)) != 0)) { return STATUS_DISK_CORRUPT_ERROR; } // Allocate sector buffer - Buf = (int8*)MyAllocatePool__(NonPagedPool, SectorSize); + Buf = (int8*)MyAllocatePool__(NonPagedPool, SectorSize(Vcb)); if (!Buf) { return STATUS_INSUFFICIENT_RESOURCES; } @@ -1332,7 +1320,7 @@ UDFLoadLogicalVolInt( // // Validate next extent alignment // - if ((NextLen & (SectorSize - 1)) != 0) { + if ((NextLen & (SectorSize(Vcb) - 1)) != 0) { try_return(RC = STATUS_DISK_CORRUPT_ERROR); } @@ -1341,7 +1329,7 @@ UDFLoadLogicalVolInt( // After "Len -= SectorSize; Lbn++;" below, we'll have // Len = NextLen and Lbn = nextIntegrityExt.extLocation - Len = NextLen + SectorSize; + Len = NextLen + SectorSize(Vcb); Lbn = lvid->nextIntegrityExt.extLocation - 1; } @@ -1356,8 +1344,8 @@ UDFLoadLogicalVolInt( // // Allocate new buffer for next iteration if needed // - if (Buf == NULL && Len > SectorSize) { - Buf = (int8*)MyAllocatePool__(NonPagedPool, SectorSize); + if (Buf == NULL && Len > SectorSize(Vcb)) { + Buf = (int8*)MyAllocatePool__(NonPagedPool, SectorSize(Vcb)); if (!Buf) { try_return(RC = STATUS_INSUFFICIENT_RESOURCES); } @@ -1365,7 +1353,7 @@ UDFLoadLogicalVolInt( // Advance to next sector - Len -= SectorSize; + Len -= SectorSize(Vcb); Lbn++; } @@ -1383,7 +1371,7 @@ UDFLoadLogicalVolInt( Vcb->origIntegrityType = Vcb->IntegrityType = Vcb->LVid->integrityType; - Vcb->LVid_loc.extLength = SectorSize; + Vcb->LVid_loc.extLength = SectorSize(Vcb); Vcb->LVid_loc.extLocation = Lbn - 1; // Last read sector LVID_iUse = UDFGetLVIDiUse(Vcb); @@ -1643,7 +1631,7 @@ UDFAddXSpaceBitmap( uint16 Ident; uint32 flags; SIZE_T Length; - SIZE_T ReadBytes; + ULONG ReadBytes; BOOLEAN bit_set; UDF_CHECK_BITMAP_RESOURCE(Vcb); @@ -1724,7 +1712,7 @@ UDFVerifyXSpaceBitmap( uint16 Ident; uint32 flags; uint32 Length; - SIZE_T ReadBytes; + ULONG ReadBytes; // BOOLEAN bit_set; UDF_CHECK_BITMAP_RESOURCE(Vcb); @@ -2157,8 +2145,6 @@ UDFLoadPartDesc( RC = UDFLoadVAT(IrpContext, Vcb, i); if (!NT_SUCCESS(RC)) return RC; - WCacheFlushAll__(IrpContext, &Vcb->FastCache, Vcb); - WCacheSetMode__(&Vcb->FastCache, WCACHE_MODE_R); Vcb->LastModifiedTrack = 0; } } @@ -2621,41 +2607,6 @@ UDFLoadFileset( } // end UDFLoadFileset() -NTSTATUS -UDFIsCachedBadSequence( - IN PVCB Vcb, - IN uint32 Lba - ) -{ - ULONG j; - NTSTATUS RC = STATUS_SUCCESS; - // Check if it is known bad sequence - for(j=0; jBadSeqLocIndex; j++) { - if (Vcb->BadSeqLoc[j] == Lba) { - RC = Vcb->BadSeqStatus[j]; - break; - } - } - return RC; -} // end UDFIsCachedBadSequence() - -VOID -UDFRememberBadSequence( - IN PVCB Vcb, - IN uint32 Lba, - IN NTSTATUS RC - ) -{ - int j; - if (!NT_SUCCESS(UDFIsCachedBadSequence(Vcb, Lba))) - return; - // Remenber bad sequence - j = Vcb->BadSeqLocIndex; - Vcb->BadSeqLocIndex++; - Vcb->BadSeqLoc[j] = Lba; - Vcb->BadSeqStatus[j] = RC; -} // end UDFRememberBadSequence() - /* load partition info */ @@ -2699,19 +2650,13 @@ UDFLoadPartition( reserve_e = reserve_e >> Vcb->SectorShift; reserve_e += reserve_s; - // Check if it is known bad sequence - RC = UDFIsCachedBadSequence(Vcb, main_s); - if (NT_SUCCESS(RC)) { - // Process the main & reserve sequences - // responsible for finding the PartitionDesc(s) - UDFPrint(("-----------------------------------\n")); - UDFPrint(("UDF: Main sequence:\n")); - RC = UDFProcessSequence(IrpContext, DeviceObject, Vcb, main_s, main_e, fileset, &mainVolDesc); - } + // Process the main & reserve sequences + // responsible for finding the PartitionDesc(s) + UDFPrint(("-----------------------------------\n")); + UDFPrint(("UDF: Main sequence:\n")); + RC = UDFProcessSequence(IrpContext, DeviceObject, Vcb, main_s, main_e, fileset, &mainVolDesc); if (!NT_SUCCESS(RC)) { - // Remenber bad sequence - UDFRememberBadSequence(Vcb, main_s, RC); UDFPrint(("-----------------------------------\n")); UDFPrint(("UDF: Main sequence failed.\n")); @@ -2719,10 +2664,7 @@ UDFLoadPartition( if (Vcb->LVid) MyFreePool__(Vcb->LVid); Vcb->LVid = NULL; - RC2 = UDFIsCachedBadSequence(Vcb, reserve_s); - if (NT_SUCCESS(RC2)) { - RC2 = UDFProcessSequence(IrpContext, DeviceObject, Vcb, reserve_s, reserve_e, fileset, &reserveVolDesc); - } + RC2 = UDFProcessSequence(IrpContext, DeviceObject, Vcb, reserve_s, reserve_e, fileset, &reserveVolDesc); if (NT_SUCCESS(RC2)) { UDFPrint(("-----------------------------------\n")); @@ -2734,9 +2676,6 @@ UDFLoadPartition( // Vcb->VDS1_Len = 0; // Vcb->VDS1 = 0; break; - } else { - // This is also bad sequence. Remenber it too - UDFRememberBadSequence(Vcb, reserve_s, RC); } } else { // remember these values for umount__ @@ -2838,7 +2777,7 @@ UDFLoadSparingTable( uint32 i=0, BC, BC2; PSPARING_TABLE SparTable; uint32 TabSize, NewSize; - SIZE_T ReadBytes; + ULONG ReadBytes; uint32 SparTableLoc; uint32 n,m; BOOLEAN merged; diff --git a/drivers/filesystems/udfs/udf_info/phys_eject.cpp b/drivers/filesystems/udfs/udf_info/phys_eject.cpp index f24e3012140a0..2a7a794d27839 100644 --- a/drivers/filesystems/udfs/udf_info/phys_eject.cpp +++ b/drivers/filesystems/udfs/udf_info/phys_eject.cpp @@ -34,9 +34,6 @@ UDFDoDismountSequence( delay.QuadPart = -1000000; // 0.1 sec KeDelayExecutionThread(KernelMode, FALSE, &delay); - // release WCache - WCacheRelease__(&(Vcb->FastCache)); - UDFAcquireResourceExclusive(&(Vcb->IoResource), TRUE); // unlock media, drop our own Locks diff --git a/drivers/filesystems/udfs/udf_info/remap.cpp b/drivers/filesystems/udfs/udf_info/remap.cpp index b1e2e09587377..72a4079b07021 100644 --- a/drivers/filesystems/udfs/udf_info/remap.cpp +++ b/drivers/filesystems/udfs/udf_info/remap.cpp @@ -19,753 +19,6 @@ #define UDF_BUG_CHECK_ID UDF_FILE_UDF_INFO_REMAP -typedef struct _UDF_VERIFY_ITEM { - lba_t lba; - ULONG crc; - PUCHAR Buffer; - LIST_ENTRY vrfList; - BOOLEAN queued; -} UDF_VERIFY_ITEM, *PUDF_VERIFY_ITEM; - -typedef struct _UDF_VERIFY_REQ_RANGE { - lba_t lba; - uint32 BCount; -} UDF_VERIFY_REQ_RANGE, *PUDF_VERIFY_REQ_RANGE; - -#define MAX_VREQ_RANGES 128 - -typedef struct _UDF_VERIFY_REQ { - PVCB Vcb; - PUCHAR Buffer; - ULONG nReq; - UDF_VERIFY_REQ_RANGE vr[MAX_VREQ_RANGES]; - WORK_QUEUE_ITEM VerifyItem; -} UDF_VERIFY_REQ, *PUDF_VERIFY_REQ; - -VOID -UDFVRemoveBlock( - PUDF_VERIFY_CTX VerifyCtx, - PUDF_VERIFY_ITEM vItem - ); - -NTSTATUS -UDFVInit( - IN PVCB Vcb - ) -{ - PUDF_VERIFY_CTX VerifyCtx = &Vcb->VerifyCtx; - uint32 i; - NTSTATUS status = STATUS_SUCCESS; - BOOLEAN res_inited = FALSE; - - if (VerifyCtx->VInited) { - UDFPrint(("Already inited\n")); - return STATUS_SUCCESS; - } - - _SEH2_TRY { - RtlZeroMemory(VerifyCtx, sizeof(UDF_VERIFY_CTX)); - if (!Vcb->VerifyOnWrite) { - UDFPrint(("Verify is disabled\n")); - return STATUS_SUCCESS; - } - if (Vcb->CDR_Mode) { - UDFPrint(("Verify is not intended for CD/DVD-R\n")); - return STATUS_SUCCESS; - } - - ExInitializeResourceLite(&VerifyCtx->VerifyLock); - - res_inited = TRUE; - VerifyCtx->ItemCount = 0; - VerifyCtx->StoredBitMap = (uint8*)DbgAllocatePoolWithTag(PagedPool, (i = (Vcb->LastPossibleLBA+1+7)>>3), 'mNWD' ); - if (VerifyCtx->StoredBitMap) { - RtlZeroMemory(VerifyCtx->StoredBitMap, i); - } else { - UDFPrint(("Can't alloc verify bitmap for %x blocks\n", Vcb->LastPossibleLBA)); - try_return(status = STATUS_INSUFFICIENT_RESOURCES); - } - InitializeListHead(&(VerifyCtx->vrfList)); - KeInitializeEvent(&(VerifyCtx->vrfEvent), SynchronizationEvent, FALSE); - VerifyCtx->WaiterCount = 0; - VerifyCtx->VInited = TRUE; - -try_exit: NOTHING; - - } _SEH2_FINALLY { - - if (!NT_SUCCESS(status)) { - if (res_inited) { - ExDeleteResourceLite(&(VerifyCtx->VerifyLock)); - } - } - } _SEH2_END; - return status; -} // end UDFVInit() - -VOID -UDFVWaitQueued( - PUDF_VERIFY_CTX VerifyCtx - ) -{ - ULONG w; - - while(VerifyCtx->QueuedCount) { - UDFPrint(("UDFVWaitQueued: wait for completion (%d)\n", VerifyCtx->QueuedCount)); - w = InterlockedIncrement((PLONG)&(VerifyCtx->WaiterCount)); - UDFPrint((" %d waiters\n", w)); - DbgWaitForSingleObject(&(VerifyCtx->vrfEvent), NULL); - if ((w = InterlockedDecrement((PLONG)&(VerifyCtx->WaiterCount)))) { - UDFPrint((" still %d waiters, q %d\n", w, VerifyCtx->QueuedCount)); - if (!VerifyCtx->QueuedCount) { - UDFPrint((" pulse event\n", w)); - KeSetEvent(&(VerifyCtx->vrfEvent), 0, FALSE); - } - } - } - return; -} // end UDFVWaitQueued() - -VOID -UDFVRelease( - IN PVCB Vcb - ) -{ - PUDF_VERIFY_CTX VerifyCtx = &Vcb->VerifyCtx; - PLIST_ENTRY Link; - PUDF_VERIFY_ITEM vItem; - - if (!VerifyCtx->VInited) { - return; - } - - UDFPrint(("UDFVRelease: wait for completion\n")); - UDFVWaitQueued(VerifyCtx); - - UDFAcquireResourceExclusive(&(VerifyCtx->VerifyLock), TRUE); - - Link = VerifyCtx->vrfList.Flink; - - while(Link != &(VerifyCtx->vrfList)) { - vItem = CONTAINING_RECORD( Link, UDF_VERIFY_ITEM, vrfList ); - Link = Link->Flink; - //DbgFreePool(vItem); - UDFVRemoveBlock(VerifyCtx, vItem); - } - VerifyCtx->VInited = FALSE; - - UDFReleaseResource(&(VerifyCtx->VerifyLock)); - - ExDeleteResourceLite(&(VerifyCtx->VerifyLock)); - DbgFreePool(VerifyCtx->StoredBitMap); - - RtlZeroMemory(VerifyCtx, sizeof(UDF_VERIFY_CTX)); - - return; -} // end UDFVRelease() - -PUDF_VERIFY_ITEM -UDFVStoreBlock( - IN PVCB Vcb, - IN uint32 LBA, - IN PVOID Buffer, - PLIST_ENTRY Link - ) -{ - PUDF_VERIFY_CTX VerifyCtx = &Vcb->VerifyCtx; - PUDF_VERIFY_ITEM vItem; - - UDFPrint(("v-add %x\n", LBA)); - - vItem = (PUDF_VERIFY_ITEM)DbgAllocatePoolWithTag(PagedPool, sizeof(UDF_VERIFY_ITEM)+Vcb->SectorSize, 'bvWD'); - if (!vItem) - return NULL; - RtlCopyMemory(vItem+1, Buffer, Vcb->SectorSize); - vItem->lba = LBA; - vItem->crc = crc32((PUCHAR)Buffer, Vcb->SectorSize); - vItem->Buffer = (PUCHAR)(vItem+1); - vItem->queued = FALSE; - InitializeListHead(&(vItem->vrfList)); - InsertTailList(Link, &(vItem->vrfList)); - UDFSetBit(VerifyCtx->StoredBitMap, LBA); - VerifyCtx->ItemCount++; - return vItem; -} // end UDFVStoreBlock() - -VOID -UDFVUpdateBlock( - IN PVCB Vcb, - IN PVOID Buffer, - PUDF_VERIFY_ITEM vItem - ) -{ - UDFPrint(("v-upd %x\n", vItem->lba)); - RtlCopyMemory(vItem+1, Buffer, Vcb->SectorSize); - vItem->crc = crc32((PUCHAR)Buffer, Vcb->SectorSize); - return; -} // end UDFVUpdateBlock() - -VOID -UDFVRemoveBlock( - PUDF_VERIFY_CTX VerifyCtx, - PUDF_VERIFY_ITEM vItem - ) -{ - UDFPrint(("v-del %x\n", vItem->lba)); - UDFClrBit(VerifyCtx->StoredBitMap, vItem->lba); - RemoveEntryList(&(vItem->vrfList)); - VerifyCtx->ItemCount--; - DbgFreePool(vItem); - return; -} // end UDFVUpdateBlock() - -NTSTATUS -UDFVWrite( - IN PVCB Vcb, - IN void* Buffer, // Target buffer - IN uint32 BCount, - IN uint32 LBA, -// OUT PSIZE_T WrittenBytes, - IN uint32 Flags - ) -{ - PLIST_ENTRY Link; - PUDF_VERIFY_ITEM vItem; - //PUDF_VERIFY_ITEM vItem1; - PUDF_VERIFY_CTX VerifyCtx = &Vcb->VerifyCtx; - ULONG i; - ULONG n; - //uint32 prev_lba; - - if (!VerifyCtx->VInited) { - return STATUS_SUCCESS; - } - - UDFAcquireResourceExclusive(&(VerifyCtx->VerifyLock), TRUE); - - for(i=0, n=0; iStoredBitMap, LBA+i)) { - // some blocks are remembered - n++; - } - } - - if (n == BCount) { - // update all blocks - n = 0; - Link = VerifyCtx->vrfList.Blink; - while(Link != &(VerifyCtx->vrfList)) { - vItem = CONTAINING_RECORD( Link, UDF_VERIFY_ITEM, vrfList ); - Link = Link->Blink; - if (vItem->lba >= LBA && vItem->lba < LBA+BCount) { - ASSERT(UDFGetBit(VerifyCtx->StoredBitMap, vItem->lba)); - UDFVUpdateBlock(Vcb, ((PUCHAR)Buffer)+(vItem->lba-LBA)*Vcb->SectorSize, vItem); - n++; - if (n == BCount) { - // all updated - break; - } - } - } - } else - if (n) { -#if 0 - // find remembered blocks (the 1st one) - Link = VerifyCtx->vrfList.Blink; - while(Link != &(VerifyCtx->vrfList)) { - vItem = CONTAINING_RECORD( Link, UDF_VERIFY_ITEM, vrfList ); - Link = Link->Blink; - if (vItem->lba >= LBA && vItem->lba < LBA+BCount) { - //UDFVRemoveBlock(VerifyCtx, vItem); - break; - } - } - - // check if contiguous - i=1; - prev_lba = vItem->lba; - vItem1 = vItem; - Link = Link->Blink; - while((i < n) && (Link != &(VerifyCtx->vrfList))) { - vItem = CONTAINING_RECORD( Link, UDF_VERIFY_ITEM, vrfList ); - Link = Link->Blink; - if (vItem->lba > LBA || vItem->lba >= LBA+BCount) { - // end - break; - } - if (vItem->lba < prev_lba) { - // not sorted - break; - } - prev_lba = vItem->lba; - i++; - } - - if (i == n) { - // cont - } else { - // drop all and add again - } - - vItem1 = vItem; - for(i=0; ilba == LBA+i) { - ASSERT(UDFGetBit(VerifyCtx->StoredBitMap, LBA+i)); - UDFVUpdateBlock(Vcb, ((PUCHAR)Buffer)+i*Vcb->BlockSize, vItem); - continue; - } - if (vItem1->lba == LBA+i) { - ASSERT(UDFGetBit(VerifyCtx->StoredBitMap, LBA+i)); - UDFVUpdateBlock(Vcb, ((PUCHAR)Buffer)+i*Vcb->BlockSize, vItem1); - continue; - } - if (vItem1->lba > LBA+i) { - // just insert this block - ASSERT(!UDFGetBit(VerifyCtx->StoredBitMap, LBA+i)); - UDFVStoreBlock(Vcb, LBA+i, ((PUCHAR)Buffer)+i*Vcb->BlockSize, &(vItem1->vrfList)); - } else { - vItem = CONTAINING_RECORD( vItem->vrfList.Blink, UDF_VERIFY_ITEM, vrfList ); - } - } -#else - Link = VerifyCtx->vrfList.Blink; - i=0; - while(Link != &(VerifyCtx->vrfList)) { - vItem = CONTAINING_RECORD( Link, UDF_VERIFY_ITEM, vrfList ); - Link = Link->Blink; - if (vItem->lba >= LBA && vItem->lba < LBA+BCount) { - UDFVRemoveBlock(VerifyCtx, vItem); - i++; - if (i == n) { - // all killed - break; - } - } - } - goto remember_all; -#endif - - } else { -remember_all: - // remember all blocks - for(i=0; iStoredBitMap, LBA+i)); - UDFVStoreBlock(Vcb, LBA+i, ((PUCHAR)Buffer)+i*Vcb->SectorSize, &(VerifyCtx->vrfList)); - } - } - - if (VerifyCtx->ItemCount > UDF_MAX_VERIFY_CACHE) { - UDFVVerify(Vcb, UFD_VERIFY_FLAG_LOCKED); - } - - UDFReleaseResource(&(VerifyCtx->VerifyLock)); - - if (VerifyCtx->ItemCount > UDF_MAX_VERIFY_CACHE*2) { - //UDFVVerify(Vcb, UFD_VERIFY_FLAG_LOCKED); - // TODO: make some delay - } - - return STATUS_SUCCESS; - -} // end UDFVWrite() - -NTSTATUS -UDFVRead( - IN PVCB Vcb, - IN void* Buffer, // Target buffer - IN uint32 BCount, - IN uint32 LBA, -// OUT uint32* ReadBytes, - IN uint32 Flags - ) -{ - PLIST_ENTRY Link; - PUDF_VERIFY_ITEM vItem; - PUDF_VERIFY_CTX VerifyCtx = &Vcb->VerifyCtx; - ULONG crc; - ULONG i; - ULONG n; - NTSTATUS status = STATUS_SUCCESS; - uint32* bm; - - if (!VerifyCtx->VInited) { - return STATUS_SUCCESS; - //return STATUS_UNSUCCESSFUL; - } - - UDFAcquireResourceExclusive(&(VerifyCtx->VerifyLock), TRUE); - - for(i=0, n=0; iStoredBitMap, LBA+i)) { - // some blocks are remembered - n++; - } - } - - if (!n) { - // no blocks are remembered - UDFReleaseResource(&(VerifyCtx->VerifyLock)); - return STATUS_SUCCESS; - } - - Link = VerifyCtx->vrfList.Flink; - i=0; - while(Link != &(VerifyCtx->vrfList)) { - vItem = CONTAINING_RECORD( Link, UDF_VERIFY_ITEM, vrfList ); - Link = Link->Flink; - if (vItem->lba >= LBA && vItem->lba < LBA+BCount) { - ASSERT(UDFGetBit(VerifyCtx->StoredBitMap, vItem->lba)); - i++; - if (!(Flags & PH_READ_VERIFY_CACHE)) { - crc = crc32((PUCHAR)Buffer+(vItem->lba - LBA)*Vcb->SectorSize, Vcb->SectorSize); - if (vItem->crc != crc) { - UDFPrint(("UDFVRead: stored %x != %x\n", vItem->crc, crc)); - RtlCopyMemory((PUCHAR)Buffer+(vItem->lba - LBA)*Vcb->SectorSize, vItem->Buffer, Vcb->SectorSize); - status = STATUS_FT_WRITE_RECOVERY; - - if (!(bm = (uint32*)(Vcb->BSBM_Bitmap))) { - crc = (Vcb->LastPossibleLBA+1+7) >> 3; // reuse 'crc' variable - bm = (uint32*)(Vcb->BSBM_Bitmap = (int8*)DbgAllocatePoolWithTag(NonPagedPool, crc, 'mNWD' )); - if (bm) { - RtlZeroMemory(bm, crc); - } else { - UDFPrint(("Can't alloc BSBM for %x blocks\n", Vcb->LastPossibleLBA)); - } - } - if (bm) { - UDFSetBit(bm, vItem->lba); - UDFPrint(("Set BB @ %#x\n", vItem->lba)); - } - - bm = (uint32*)(Vcb->FSBM_Bitmap); - if (bm) { - UDFSetUsedBit(bm, vItem->lba); - UDFPrint(("Set BB @ %#x as used\n", vItem->lba)); - } - } else { - // ok - } - } else { - UDFPrint(("UDFVRead: get cached @ %x\n", vItem->lba)); - RtlCopyMemory((PUCHAR)Buffer+(vItem->lba - LBA)*Vcb->SectorSize, vItem->Buffer, Vcb->SectorSize); - } - if (i >= n) { - // no more blocks expected - break; - } - } - } - - if ((status == STATUS_SUCCESS && !(Flags & PH_KEEP_VERIFY_CACHE)) || (Flags & PH_FORGET_VERIFIED)) { - // ok, forget this, no errors found - Link = VerifyCtx->vrfList.Flink; - i = 0; - while(Link != &(VerifyCtx->vrfList)) { - vItem = CONTAINING_RECORD( Link, UDF_VERIFY_ITEM, vrfList ); - Link = Link->Flink; - if (vItem->lba >= LBA && vItem->lba < LBA+BCount) { - i++; - UDFVRemoveBlock(VerifyCtx, vItem); - if (i >= n) { - // no more blocks expected - break; - } - } - } - } - - UDFReleaseResource(&(VerifyCtx->VerifyLock)); - return status; - -} // end UDFVRead() - -NTSTATUS -UDFVForget( - IN PVCB Vcb, - IN uint32 BCount, - IN uint32 LBA, - IN uint32 Flags - ) -{ - PLIST_ENTRY Link; - PUDF_VERIFY_ITEM vItem; - PUDF_VERIFY_CTX VerifyCtx = &Vcb->VerifyCtx; - ULONG i; - ULONG n; - NTSTATUS status = STATUS_SUCCESS; - - if (!VerifyCtx->VInited) { - return STATUS_UNSUCCESSFUL; - } - - UDFAcquireResourceExclusive(&(VerifyCtx->VerifyLock), TRUE); - - for(i=0, n=0; iStoredBitMap, LBA+i)) { - // some blocks are remembered - n++; - } - } - - if (!n) { - // no blocks are remembered - UDFReleaseResource(&(VerifyCtx->VerifyLock)); - return STATUS_SUCCESS; - } - - Link = VerifyCtx->vrfList.Flink; - i = 0; - while(Link != &(VerifyCtx->vrfList)) { - vItem = CONTAINING_RECORD( Link, UDF_VERIFY_ITEM, vrfList ); - Link = Link->Flink; - if (vItem->lba >= LBA && vItem->lba < LBA+BCount) { - i++; - UDFVRemoveBlock(VerifyCtx, vItem); - if (i >= n) { - // no more blocks expected - break; - } - } - } - - UDFReleaseResource(&(VerifyCtx->VerifyLock)); - return status; - -} // end UDFVForget() - -VOID -NTAPI -UDFVWorkItem( - PVOID Context - ) -{ - PUDF_VERIFY_REQ VerifyReq = (PUDF_VERIFY_REQ)Context; - PVCB Vcb = VerifyReq->Vcb; - SIZE_T ReadBytes; - ULONG i; - IRP_CONTEXT IrpContext; - - // Make us appear as a top level FSP request so that we will - // receive any errors from the operation. - - IoSetTopLevelIrp((PIRP)FSRTL_FSP_TOP_LEVEL_IRP); - - // Dummy up and Irp Context so we can call our worker routines - - RtlZeroMemory(&IrpContext, sizeof(IRP_CONTEXT)); - - SetFlag(IrpContext.Flags, IRP_CONTEXT_FLAG_ON_STACK | IRP_CONTEXT_FLAG_WAIT); - IrpContext.NodeIdentifier.NodeTypeCode = UDF_NODE_TYPE_IRP_CONTEXT; - IrpContext.Vcb = Vcb; - - ReadBytes = (SIZE_T)Vcb; -#if 1 - if (Vcb->SparingCountFree) { - WCacheStartDirect__(&(Vcb->FastCache), Vcb, TRUE); - for(i=0; inReq; i++) { - UDFTIOVerify(&IrpContext, - Vcb, - VerifyReq->Buffer, // Target buffer - VerifyReq->vr[i].BCount << Vcb->SectorShift, - VerifyReq->vr[i].lba, - &ReadBytes, - PH_TMP_BUFFER | PH_VCB_IN_RETLEN /*| PH_LOCK_CACHE*/); - } - WCacheEODirect__(&(Vcb->FastCache), Vcb); - } else { - for(i=0; inReq; i++) { - UDFPrint(("!!! No more space for remap !!!\n")); - UDFPrint((" try del from verify cache @ %x\n", VerifyReq->vr[i].lba)); - UDFVRead(Vcb, VerifyReq->Buffer, VerifyReq->vr[i].BCount, VerifyReq->vr[i].lba, - PH_FORGET_VERIFIED | PH_READ_VERIFY_CACHE | PH_TMP_BUFFER); - } - } -#else - for(i=0; inReq; i++) { - if (Vcb->SparingCountFree) { - WCacheStartDirect__(&(Vcb->FastCache), Vcb, TRUE); - RC = UDFTIOVerify(Vcb, - VerifyReq->Buffer, // Target buffer - VerifyReq->vr[i].BCount << Vcb->BlockSizeBits, - VerifyReq->vr[i].lba, - &ReadBytes, - PH_TMP_BUFFER | PH_VCB_IN_RETLEN /*| PH_LOCK_CACHE*/); - WCacheEODirect__(&(Vcb->FastCache), Vcb); - } else { - UDFPrint(("!!! No more space for remap !!!\n")); - UDFPrint((" try del from verify cache @ %x\n", VerifyReq->vr[i].lba)); - RC = UDFVRead(Vcb, VerifyReq->Buffer, VerifyReq->vr[i].BCount, VerifyReq->vr[i].lba, - PH_FORGET_VERIFIED | PH_READ_VERIFY_CACHE | PH_TMP_BUFFER); - } - } -#endif - DbgFreePool(VerifyReq->Buffer); - DbgFreePool(VerifyReq); - InterlockedDecrement((PLONG)&(Vcb->VerifyCtx.QueuedCount)); - UDFPrint((" QueuedCount = %d\n", Vcb->VerifyCtx.QueuedCount)); - UDFPrint((" Setting event...\n")); - KeSetEvent(&(Vcb->VerifyCtx.vrfEvent), 0, FALSE); - return; -} // end UDFVWorkItem() - -VOID -UDFVVerify( - IN PVCB Vcb, - IN ULONG Flags - ) -{ - PUDF_VERIFY_CTX VerifyCtx = &Vcb->VerifyCtx; - PLIST_ENTRY Link; - PUDF_VERIFY_ITEM vItem; - PUDF_VERIFY_REQ VerifyReq = NULL; - ULONG len, max_len=0; - lba_t prev_lba; - //PUCHAR tmp_buff; - ULONG i; - BOOLEAN do_vrf = FALSE; - - if (!VerifyCtx->VInited) { - return; - } - if (VerifyCtx->QueuedCount) { - if (Flags & UFD_VERIFY_FLAG_WAIT) { - UDFPrint((" wait for verify flush\n")); - goto wait; - } - UDFPrint((" verify flush already queued\n")); - return; - } - - if (!(Flags & (UFD_VERIFY_FLAG_FORCE | UFD_VERIFY_FLAG_BG))) { - if (VerifyCtx->ItemCount < UDF_MAX_VERIFY_CACHE) { - return; - } - - } - if (!(Flags & UFD_VERIFY_FLAG_LOCKED)) { - UDFAcquireResourceExclusive(&(VerifyCtx->VerifyLock), TRUE); - } - - if (Flags & UFD_VERIFY_FLAG_FORCE) { - i = VerifyCtx->ItemCount; - } else { - if (VerifyCtx->ItemCount >= UDF_MAX_VERIFY_CACHE) { - i = VerifyCtx->ItemCount - UDF_VERIFY_CACHE_LOW; - } else { - i = min(UDF_VERIFY_CACHE_GRAN, VerifyCtx->ItemCount); - } - } - - Link = VerifyCtx->vrfList.Flink; - prev_lba = -2; - len = 0; - - while(i) { - ASSERT(Link != &(VerifyCtx->vrfList)); -/* - if (Link == &(VerifyCtx->vrfList)) { - if (!len) - break; - i=1; - goto queue_req; - } -*/ - vItem = CONTAINING_RECORD( Link, UDF_VERIFY_ITEM, vrfList ); - Link = Link->Flink; - - // - if (!vItem->queued && (prev_lba+len == vItem->lba)) { - vItem->queued = TRUE; - len++; - } else { - if (len) { - do_vrf = TRUE; - } else { - len = 1; - prev_lba = vItem->lba; - } - } - if ((i == 1) && len) { - do_vrf = TRUE; - } - if (len >= 0x100) { - do_vrf = TRUE; - } - if (do_vrf) { -//queue_req: - if (!VerifyReq) { - VerifyReq = (PUDF_VERIFY_REQ)DbgAllocatePoolWithTag(NonPagedPool, sizeof(UDF_VERIFY_REQ), 'bNWD'); - if (VerifyReq) { - RtlZeroMemory(VerifyReq, sizeof(UDF_VERIFY_REQ)); - VerifyReq->Vcb = Vcb; - } - } - if (VerifyReq) { - - VerifyReq->vr[VerifyReq->nReq].lba = prev_lba; - VerifyReq->vr[VerifyReq->nReq].BCount = len; - VerifyReq->nReq++; - if (max_len < len) { - max_len = len; - } - - if ((VerifyReq->nReq >= MAX_VREQ_RANGES) || (i == 1)) { - - VerifyReq->Buffer = (PUCHAR)DbgAllocatePoolWithTag(NonPagedPool, max_len * Vcb->SectorSize, 'bNWD'); - if (VerifyReq->Buffer) { - InterlockedIncrement((PLONG)&(VerifyCtx->QueuedCount)); - - ExInitializeWorkItem( &(VerifyReq->VerifyItem), - UDFVWorkItem, - VerifyReq ); - ExQueueWorkItem( &(VerifyReq->VerifyItem), CriticalWorkQueue ); - } else { - DbgFreePool(VerifyReq); - } - VerifyReq = NULL; - max_len = 0; - } else { - } - } - len = 1; - prev_lba = vItem->lba; - do_vrf = FALSE; - } - i--; - } - - if (!(Flags & UFD_VERIFY_FLAG_LOCKED)) { - UDFReleaseResource(&(VerifyCtx->VerifyLock)); - } - if (Flags & UFD_VERIFY_FLAG_WAIT) { -wait: - UDFPrint(("UDFVVerify: wait for completion\n")); - UDFVWaitQueued(VerifyCtx); - } - - return; -} // end UDFVVerify() - -VOID -UDFVFlush( - IN PVCB Vcb - ) -{ - PUDF_VERIFY_CTX VerifyCtx = &Vcb->VerifyCtx; - - if (!VerifyCtx->VInited) { - return; - } - - UDFPrint(("UDFVFlush: wait for completion\n")); - UDFVWaitQueued(VerifyCtx); - - UDFVVerify(Vcb, UFD_VERIFY_FLAG_FORCE); - - UDFPrint(("UDFVFlush: wait for completion (2)\n")); - UDFVWaitQueued(VerifyCtx); -} // end UDFVFlush() - BOOLEAN __fastcall UDFCheckArea( @@ -777,7 +30,7 @@ UDFCheckArea( { uint8* buff; NTSTATUS RC; - SIZE_T ReadBytes; + ULONG ReadBytes; uint32 i, d; BOOLEAN ext_ok = TRUE; EXTENT_MAP Map[2]; diff --git a/drivers/filesystems/udfs/udf_info/udf_info.cpp b/drivers/filesystems/udfs/udf_info/udf_info.cpp index 67f3e3e827b9c..e5d0b699e4947 100644 --- a/drivers/filesystems/udfs/udf_info/udf_info.cpp +++ b/drivers/filesystems/udfs/udf_info/udf_info.cpp @@ -1579,7 +1579,7 @@ UDFWriteFile__( NTSTATUS status; int8* OldInIcb = NULL; ValidateFileInfo(FileInfo); - SIZE_T ReadBytes; + ULONG ReadBytes; SIZE_T _WrittenBytes; PUDF_DATALOC_INFO Dloc; // unwind staff @@ -1645,6 +1645,9 @@ UDFWriteFile__( ((PFILE_ENTRY)(Dloc->FileEntry))->icbTag.flags &= ~ICB_FLAG_ALLOC_MASK; ((PFILE_ENTRY)(Dloc->FileEntry))->icbTag.flags |= Vcb->DefaultAllocMode; WasInIcb = TRUE; + // Clear embedded data flag since file is no longer in ICB mode + ASSERT(FileInfo->Fcb); + FileInfo->Fcb->FcbState &= ~UDF_FCB_EMBEDDED_DATA; } // increase extent ExtPrint((" %s %s %s\n", @@ -1987,7 +1990,7 @@ UDFOpenFile__( PDIR_INDEX_ITEM DirNdx; PUDF_FILE_INFO FileInfo; PUDF_FILE_INFO ParFileInfo; - SIZE_T ReadBytes; + ULONG ReadBytes; *_FileInfo = NULL; if (!hDirNdx) return STATUS_NOT_A_DIRECTORY; @@ -2570,7 +2573,8 @@ UDFCreateFile__( PUDF_FILE_INFO FileInfo; *_FileInfo = NULL; BOOLEAN undel = FALSE; - SIZE_T ReadBytes; + ULONG ReadBytes; + SIZE_T WrittenBytes; // BOOLEAN PackDir = FALSE; BOOLEAN FEAllocated = FALSE; @@ -2817,7 +2821,7 @@ UDFCreateFile__( FileInfo->Dloc->FELoc.Mapping[0].extLength &= UDF_EXTENT_LENGTH_MASK; // zero sector for FileEntry if (!Vcb->CDR_Mode) { - status = UDFWriteData(IrpContext, Vcb, TRUE, ((int64)(FileInfo->Dloc->FELoc.Mapping[0].extLocation)) << Vcb->SectorShift, LBS, FALSE, Vcb->ZBuffer, &ReadBytes); + status = UDFWriteData(IrpContext, Vcb, TRUE, ((int64)(FileInfo->Dloc->FELoc.Mapping[0].extLocation)) << Vcb->SectorShift, LBS, FALSE, Vcb->ZBuffer, &WrittenBytes); if (!NT_SUCCESS(status)) { UDFFlushFI(IrpContext, Vcb, FileInfo, PartNum); try_return (status); @@ -3445,6 +3449,7 @@ UDFResizeFile__( IN int64 NewLength ) { + ULONG ReadBytes; SIZE_T WrittenBytes; NTSTATUS status; uint32 PartNum; @@ -3475,7 +3480,7 @@ UDFResizeFile__( if (NewLength) { OldInIcb = (int8*)MyAllocatePool__(NonPagedPool, (uint32)NewLength); if (!OldInIcb) return STATUS_INSUFFICIENT_RESOURCES; - status = UDFReadExtent(IrpContext, Vcb, &FileInfo->Dloc->DataLoc, 0, (uint32)NewLength, FALSE, OldInIcb, &WrittenBytes); + status = UDFReadExtent(IrpContext, Vcb, &FileInfo->Dloc->DataLoc, 0, (uint32)NewLength, FALSE, OldInIcb, &ReadBytes); if (!NT_SUCCESS(status)) { MyFreePool__(OldInIcb); return status; @@ -3525,6 +3530,9 @@ UDFResizeFile__( // switch to IN_ICB mode ((PFILE_ENTRY)(FileInfo->Dloc->FileEntry))->icbTag.flags &= ~ICB_FLAG_ALLOC_MASK; ((PFILE_ENTRY)(FileInfo->Dloc->FileEntry))->icbTag.flags |= ICB_FLAG_AD_IN_ICB; + // Set embedded data flag since file is now in ICB mode + ASSERT(FileInfo->Fcb); + FileInfo->Fcb->FcbState |= UDF_FCB_EMBEDDED_DATA; // init new data location descriptors FileInfo->Dloc->DataLoc.Mapping = NewMap; RtlZeroMemory((int8*)(FileInfo->Dloc->DataLoc.Mapping), 2*sizeof(EXTENT_MAP)); @@ -3583,7 +3591,7 @@ UDFLoadVAT( PUDF_FILE_INFO VatFileInfo; uint32 len, i=0, j, to_read; uint32 Offset, hdrOffset; - SIZE_T ReadBytes; + ULONG ReadBytes; uint32 root; uint16 PartNum; // uint32 VatFirstLba = 0; @@ -4374,7 +4382,7 @@ UDFReadTagged( // icbtag* Icb = (icbtag*)(Buf+1); uint8 checksum; unsigned int i; - SIZE_T ReadBytes; + ULONG ReadBytes; int8* tb; // Read the block @@ -4831,7 +4839,8 @@ UDFRecordVAT( uint32 hdrOffset, hdrOffsetNew; uint32 hdrLen; NTSTATUS status; - SIZE_T ReadBytes; + ULONG ReadBytes; + SIZE_T WrittenBytes; uint32 len; uint16 PartNdx = (uint16)Vcb->VatPartNdx; uint16 PartNum = UDFGetPartNumByPartRef(Vcb, PartNdx); @@ -4960,17 +4969,17 @@ UDFRecordVAT( } UDFMarkSpaceAsXXX(Vcb, VatFileInfo->Dloc, VatFileInfo->Dloc->DataLoc.Mapping, AS_DISCARDED); //free } - PacketOffset = WCacheGetWriteBlockCount__(&(Vcb->FastCache)); + //PacketOffset = WCacheGetWriteBlockCount__(&(Vcb->FastCache)); + PacketOffset = 0; if ( ((((PFILE_ENTRY)(VatFileInfo->Dloc->FileEntry))->icbTag.flags & ICB_FLAG_ALLOC_MASK) == ICB_FLAG_AD_IN_ICB) ) { // now we'll place FE & built-in data to the last sector of // the last packet will be recorded if (!PacketOffset) { // add padding - UDFWriteData(IrpContext, Vcb, TRUE, ((uint64)Vcb->NWA) << Vcb->SectorShift, 1, FALSE, Old, &ReadBytes); + UDFWriteData(IrpContext, Vcb, TRUE, ((uint64)Vcb->NWA) << Vcb->SectorShift, 1, FALSE, Old, &WrittenBytes); PacketOffset++; } else { Vcb->Vat = (uint32*)(New+Offset); - WCacheSyncReloc__(&(Vcb->FastCache), Vcb); Vcb->Vat = NULL; } VatFileInfo->Dloc->FELoc.Mapping[0].extLocation = @@ -4981,7 +4990,7 @@ UDFRecordVAT( ((PFILE_ENTRY)(VatFileInfo->Dloc->FileEntry))->descTag.tagLocation = UDFPhysLbaToPart(Vcb, PartNum, VatFileInfo->Dloc->DataLoc.Mapping[0].extLocation); // record data - if (NT_SUCCESS(status = UDFWriteFile__(IrpContext, Vcb, VatFileInfo, 0, VatLen + hdrLen, FALSE, New, &ReadBytes))) { + if (NT_SUCCESS(status = UDFWriteFile__(IrpContext, Vcb, VatFileInfo, 0, VatLen + hdrLen, FALSE, New, &WrittenBytes))) { status = UDFFlushFile__(IrpContext, Vcb, VatFileInfo); } return status; @@ -4993,7 +5002,6 @@ UDFRecordVAT( // update VAT with locations of not flushed blocks if (PacketOffset) { Vcb->Vat = (uint32*)(New+Offset); - WCacheSyncReloc__(&(Vcb->FastCache), Vcb); Vcb->Vat = NULL; } @@ -5014,7 +5022,7 @@ UDFRecordVAT( NWA += (MaxPacket + 7); PacketOffset = 0; } - status = UDFWriteFile__(IrpContext, Vcb, VatFileInfo, off, to_read, FALSE, New+off, &ReadBytes); + status = UDFWriteFile__(IrpContext, Vcb, VatFileInfo, off, to_read, FALSE, New+off, &WrittenBytes); if (!NT_SUCCESS(status)) { return status; } @@ -5075,7 +5083,7 @@ UDFRecordVAT( if ( !PacketOffset && (VatFileInfo->Dloc->AllocLoc.Length <= (Vcb->SectorSize - (uint32)(VatFileInfo->Dloc->AllocLoc.Offset)) ) ) { // add padding - UDFWriteData(IrpContext, Vcb, TRUE, ((uint64)NWA) << Vcb->SectorShift, 1, FALSE, Old, &ReadBytes); + UDFWriteData(IrpContext, Vcb, TRUE, ((uint64)NWA) << Vcb->SectorShift, 1, FALSE, Old, &WrittenBytes); PacketOffset++; } // now we'll place FE & built-in data to the last sector of @@ -5092,7 +5100,7 @@ UDFRecordVAT( status = UDFFlushFile__(IrpContext, Vcb, VatFileInfo); if (!NT_SUCCESS(status)) return status; - WCacheFlushAll__(IrpContext, &Vcb->FastCache, Vcb); + return STATUS_SUCCESS; } // end UDFRecordVAT() @@ -5149,7 +5157,8 @@ UDFConvertFEToExtended( PFILE_ENTRY FileEntry; uint32 Length, NewLength, l; NTSTATUS status; - SIZE_T ReadBytes; + ULONG ReadBytes; + SIZE_T WrittenBytes; if (!FileInfo) return STATUS_INVALID_PARAMETER; ValidateFileInfo(FileInfo); @@ -5211,7 +5220,7 @@ UDFConvertFEToExtended( MyFreePool__(FileInfo->Dloc->FileEntry); FileInfo->Dloc->FileEntry = (tag*)ExFileEntry; if (!NT_SUCCESS(status = UDFResizeFile__(IrpContext, Vcb, FileInfo, l)) || - !NT_SUCCESS(status = UDFWriteFile__(IrpContext, Vcb, FileInfo, 0, l, FALSE, tmp_buff, &ReadBytes)) ) { + !NT_SUCCESS(status = UDFWriteFile__(IrpContext, Vcb, FileInfo, 0, l, FALSE, tmp_buff, &WrittenBytes)) ) { MyFreePool__(ExFileEntry); MyFreePool__(tmp_buff); return status; diff --git a/drivers/filesystems/udfs/udf_info/udf_info.h b/drivers/filesystems/udfs/udf_info/udf_info.h index 8c2ae7abeaa6c..c10108ae41195 100644 --- a/drivers/filesystems/udfs/udf_info/udf_info.h +++ b/drivers/filesystems/udfs/udf_info/udf_info.h @@ -10,7 +10,6 @@ #include "ecma_167.h" #include "osta_misc.h" #include "udf_rel.h" -#include "wcache.h" // memory re-allocation (returns new buffer size) uint32 UDFMemRealloc(IN int8* OldBuff, // old buffer @@ -49,7 +48,7 @@ NTSTATUS UDFReadExtent( IN SIZE_T Length, IN BOOLEAN Direct, OUT int8* Buffer, - OUT PSIZE_T ReadBytes + OUT PULONG ReadBytes ); // builds mapping for specified amount of data at any offset from specified extent. @@ -793,7 +792,7 @@ UDFReadFile__( IN SIZE_T Length, IN BOOLEAN Direct, OUT int8* Buffer, - OUT PSIZE_T ReadBytes + OUT PULONG ReadBytes ) { ValidateFileInfo(FileInfo); @@ -1041,22 +1040,7 @@ BOOLEAN UDFCompareFileInfo(IN PUDF_FILE_INFO f1, void __fastcall UDFPackMapping(IN PVCB Vcb, IN PEXTENT_INFO ExtInfo); // Extent array -// check if all the data is in cache. -BOOLEAN UDFIsExtentCached(IN PVCB Vcb, - IN PEXTENT_INFO ExtInfo, // Extent array - IN int64 Offset, // offset in extent - IN uint32 Length, - IN BOOLEAN ForWrite); -/*BOOLEAN UDFIsFileCached__(IN PVCB Vcb, - IN PUDF_FILE_INFO FileInfo, - IN int64 Offset, // offset in extent - IN uint32 Length, - IN BOOLEAN ForWrite);*/ -#define UDFIsFileCached__(Vcb, FileInfo, Offset, Length, ForWrite) \ - (UDFIsExtentCached(Vcb, &((FileInfo)->Dloc->DataLoc), Offset, Length, ForWrite)) -// check if specified sector belongs to a file -ULONG UDFIsBlockAllocated(IN void* _Vcb, - IN uint32 Lba); + // record VolIdent NTSTATUS UDFUpdateVolIdent( @@ -1464,81 +1448,6 @@ UDFDirIndex( extern const char hexChar[]; -#define UDF_MAX_VERIFY_CACHE (8*1024*1024/2048) -#define UDF_VERIFY_CACHE_LOW (4*1024*1024/2048) -#define UDF_VERIFY_CACHE_GRAN (512*1024/2048) -#define UDF_SYS_CACHE_STOP_THR (10*1024*1024/2048) - -NTSTATUS -UDFVInit( - IN PVCB Vcb - ); - -VOID -UDFVRelease( - IN PVCB Vcb - ); - -#define PH_FORGET_VERIFIED 0x00800000 -#define PH_READ_VERIFY_CACHE 0x00400000 -#define PH_KEEP_VERIFY_CACHE 0x00200000 - -NTSTATUS -UDFVWrite( - IN PVCB Vcb, - IN void* Buffer, // Target buffer - IN uint32 BCount, - IN uint32 LBA, -// OUT PSIZE_T WrittenBytes, - IN uint32 Flags - ); - -NTSTATUS -UDFVRead( - IN PVCB Vcb, - IN void* Buffer, // Target buffer - IN uint32 BCount, - IN uint32 LBA, -// OUT uint32* ReadBytes, - IN uint32 Flags - ); - -NTSTATUS -UDFVForget( - IN PVCB Vcb, - IN uint32 BCount, - IN uint32 LBA, - IN uint32 Flags - ); - -#define UFD_VERIFY_FLAG_FORCE 0x01 -#define UFD_VERIFY_FLAG_WAIT 0x02 -#define UFD_VERIFY_FLAG_BG 0x04 -#define UFD_VERIFY_FLAG_LOCKED 0x10 - -VOID -UDFVVerify( - IN PVCB Vcb, - IN ULONG Flags - ); - -VOID -UDFVFlush( - IN PVCB Vcb - ); - -__inline -BOOLEAN -__fastcall UDFVIsStored( - IN PVCB Vcb, - IN lba_t lba - ) -{ - if (!Vcb->VerifyCtx.VInited) - return FALSE; - return UDFGetBit(Vcb->VerifyCtx.StoredBitMap, lba); -} // end UDFVIsStored() - BOOLEAN __fastcall UDFCheckArea( diff --git a/drivers/filesystems/udfs/udf_info/udf_rel.h b/drivers/filesystems/udfs/udf_info/udf_rel.h index c48249d08d54d..602a8f6e2cafa 100644 --- a/drivers/filesystems/udfs/udf_info/udf_rel.h +++ b/drivers/filesystems/udfs/udf_info/udf_rel.h @@ -534,15 +534,4 @@ typedef struct _UDF_ALLOCATION_CACHE_ITEM { #endif //UDF_DBG -typedef struct _UDF_VERIFY_CTX { - uint8* StoredBitMap; - ULONG ItemCount; - LIST_ENTRY vrfList; - ERESOURCE VerifyLock; - KEVENT vrfEvent; - uint32 WaiterCount; - uint32 QueuedCount; - BOOLEAN VInited; -} UDF_VERIFY_CTX, *PUDF_VERIFY_CTX; - #endif /* _UDF_REL_H_ */ diff --git a/drivers/filesystems/udfs/udffs.h b/drivers/filesystems/udfs/udffs.h index a919ed985007f..5eff0e08995b0 100644 --- a/drivers/filesystems/udfs/udffs.h +++ b/drivers/filesystems/udfs/udffs.h @@ -17,6 +17,8 @@ #ifndef _UDF_UDF_H_ #define _UDF_UDF_H_ +#pragma warning(disable : 28172) + /**************** OPTIONS *****************/ //#define UDF_TRACK_UNICODE_STR @@ -39,7 +41,6 @@ // WCACHE was disabled due to errors in it. // Test case: Running 'git clone https://github.com/reactos/reactos' under ReactOS results in an error. -//#define UDF_USE_WCACHE #define UDF_ALLOW_FRAG_AD @@ -55,7 +56,7 @@ #define UDF_DEFAULT_SPARSE_THRESHOLD (256*PACKETSIZE_UDF) -#define ALLOW_SPARSE +//#define ALLOW_SPARSE #define UDF_PACK_DIRS @@ -72,8 +73,6 @@ FILE_ATTRIBUTE_TEMPORARY | \ FILE_ATTRIBUTE_SPARSE_FILE) -//#define UDF_DISABLE_SYSTEM_CACHE_MANAGER - //#define UDF_CDRW_EMULATION_ON_ROM #define UDF_DELAYED_CLOSE @@ -132,7 +131,6 @@ typedef FILE_ID *PFILE_ID; #include #include #include -#include "wcache.h" #include "Include/regtools.h" #include "Include/udf_reg.h" diff --git a/drivers/filesystems/udfs/udfinit.cpp b/drivers/filesystems/udfs/udfinit.cpp index 0453c669d109f..41e2a087633af 100644 --- a/drivers/filesystems/udfs/udfinit.cpp +++ b/drivers/filesystems/udfs/udfinit.cpp @@ -312,7 +312,7 @@ UDFInitializeFunctionPointers( PtrFastIoDispatch->FastIoQueryNetworkOpenInfo = UDFFastIoQueryNetInfo; PtrFastIoDispatch->AcquireForModWrite = UDFFastIoAcqModWrite; - PtrFastIoDispatch->ReleaseForModWrite = UDFFastIoRelModWrite; + PtrFastIoDispatch->ReleaseForModWrite = NULL; PtrFastIoDispatch->AcquireForCcFlush = UDFFastIoAcqCcFlush; PtrFastIoDispatch->ReleaseForCcFlush = UDFFastIoRelCcFlush; diff --git a/drivers/filesystems/udfs/verfysup.cpp b/drivers/filesystems/udfs/verfysup.cpp index 68349d00d08e9..13cd25b17a2a9 100644 --- a/drivers/filesystems/udfs/verfysup.cpp +++ b/drivers/filesystems/udfs/verfysup.cpp @@ -123,7 +123,7 @@ UDFVerifyVcb( Status = UDFTSendIOCTL( (Vcb->Vpb->RealDevice->DeviceType == FILE_DEVICE_CD_ROM ? - IOCTL_CDROM_CHECK_VERIFY : IOCTL_DISK_CHECK_VERIFY ), + IOCTL_CDROM_CHECK_VERIFY : IOCTL_DISK_CHECK_VERIFY), Vcb, NULL, 0, &MediaChangeCount, sizeof(ULONG), @@ -259,17 +259,16 @@ UDFVerifyVolume( PVCB NewVcb = NULL; IO_STATUS_BLOCK Iosb; ULONG MediaChangeCount = 0; - NTSTATUS RC; + NTSTATUS Status; BOOLEAN ReleaseVcb = FALSE; - ULONG Mode; - //BOOLEAN UnsafeIoctl = (Vcb->VcbState & UDF_VCB_FLAGS_UNSAFE_IOCTL) ? TRUE : FALSE; PAGED_CODE(); // We check that we are talking to a Cdrom or HDD device. ASSERT(Vpb->RealDevice->DeviceType == FILE_DEVICE_CD_ROM || - Vpb->RealDevice->DeviceType == FILE_DEVICE_DISK); + Vpb->RealDevice->DeviceType == FILE_DEVICE_DISK); + ASSERT(FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)); // Update the real device in the IrpContext from the Vpb. There was no available @@ -290,7 +289,7 @@ UDFVerifyVolume( if (Vcb->VcbCondition == VcbDismountInProgress || Vcb->VcbCondition == VcbInvalid) { - try_return(RC = STATUS_WRONG_VOLUME); + try_return(Status = STATUS_WRONG_VOLUME); } // Check if the real device still needs to be verified. If it doesn't @@ -301,17 +300,23 @@ UDFVerifyVolume( if (!FlagOn(Vpb->RealDevice->Flags, DO_VERIFY_VOLUME)) { UDFPrint(("UDFVerifyVolume: RealDevice has already been verified\n")); - try_return(RC = STATUS_SUCCESS); + try_return(Status = STATUS_SUCCESS); } // Verify that there is a disk here. - RC = UDFPhSendIOCTL( IOCTL_STORAGE_CHECK_VERIFY, - Vcb->TargetDeviceObject, - NULL,0, - &MediaChangeCount,sizeof(ULONG), - TRUE,&Iosb ); - if (!NT_SUCCESS(RC)) { + Status = UDFPhSendIOCTL((Vpb->RealDevice->DeviceType == FILE_DEVICE_CD_ROM ? + IOCTL_CDROM_CHECK_VERIFY : + IOCTL_DISK_CHECK_VERIFY), + Vcb->TargetDeviceObject, + NULL, + 0, + &MediaChangeCount, + sizeof(ULONG), + TRUE, + &Iosb); + + if (!NT_SUCCESS(Status)) { // If we will allow a raw mount then return WRONG_VOLUME to // allow the volume to be mounted by raw. @@ -319,10 +324,10 @@ UDFVerifyVolume( if (FlagOn(IrpSp->Flags, SL_ALLOW_RAW_MOUNT)) { UDFPrint(("UDFVerifyVolume: STATUS_WRONG_VOLUME (1)\n")); - RC = STATUS_WRONG_VOLUME; + Status = STATUS_WRONG_VOLUME; } - try_return(RC); + try_return(Status); } if (Iosb.Information != sizeof(ULONG)) { @@ -340,8 +345,8 @@ UDFVerifyVolume( NewVcb = (PVCB)MyAllocatePool__(NonPagedPool,sizeof(VCB)); if (!NewVcb) - try_return(RC=STATUS_INSUFFICIENT_RESOURCES); - RtlZeroMemory(NewVcb,sizeof(VCB)); + try_return(Status = STATUS_INSUFFICIENT_RESOURCES); + RtlZeroMemory(NewVcb, sizeof(VCB)); NewVcb->TargetDeviceObject = Vcb->TargetDeviceObject; NewVcb->Vpb = Vpb; @@ -353,71 +358,37 @@ UDFVerifyVolume( SetFlag(NewVcb->VcbState, VCB_STATE_REMOVABLE_MEDIA); } - RC = UDFGetDiskInfo(IrpContext, NewVcb->TargetDeviceObject,NewVcb); - if (!NT_SUCCESS(RC)) try_return(RC); + Status = UDFGetDiskInfo(IrpContext, NewVcb->TargetDeviceObject,NewVcb); + if (!NT_SUCCESS(Status)) try_return(Status); // Prevent modification attempts durring Verify NewVcb->VcbState |= VCB_STATE_VOLUME_READ_ONLY | VCB_STATE_MEDIA_WRITE_PROTECT; // Compare physical parameters (phase 1) UDFPrint(("UDFVerifyVolume: Modified=%d\n", Vcb->Modified)); - RC = UDFCompareVcb(IrpContext, Vcb, NewVcb, TRUE); - if (!NT_SUCCESS(RC)) try_return(RC); - - // Initialize internal cache - // in *** READ ONLY *** mode - Mode = WCACHE_MODE_ROM; - - RC = WCacheInit__(&(NewVcb->FastCache), - UdfData.WCacheMaxFrames, - UdfData.WCacheMaxBlocks, - NewVcb->WriteBlockSize, - 5, NewVcb->SectorShift, - UdfData.WCacheBlocksPerFrameSh, - 0/*NewVcb->FirstLBA*/, NewVcb->LastPossibleLBA, Mode, - /*WCACHE_CACHE_WHOLE_PACKET*/ 0 | - WCACHE_DO_NOT_COMPARE | - WCACHE_MARK_BAD_BLOCKS | WCACHE_RO_BAD_BLOCKS, // speed up mount on bad disks - UdfData.WCacheFramesToKeepFree, - UDFTWrite, UDFTRead, -#ifdef UDF_ASYNC_IO - UDFTWriteAsync, UDFTReadAsync, -#else //UDF_ASYNC_IO - NULL, NULL, -#endif //UDF_ASYNC_IO - UDFIsBlockAllocated, UDFUpdateVAT, - UDFWCacheErrorHandler); - if (!NT_SUCCESS(RC)) try_return(RC); + Status = UDFCompareVcb(IrpContext, Vcb, NewVcb, TRUE); + if (!NT_SUCCESS(Status)) try_return(Status); - UDFPrint(("UDFVerifyVolume: Modified=%d\n", Vcb->Modified)); - RC = UDFGetDiskInfoAndVerify(IrpContext, NewVcb->TargetDeviceObject,NewVcb); + Status = UDFGetDiskInfoAndVerify(IrpContext, NewVcb->TargetDeviceObject,NewVcb); UDFPrint((" NewVcb->NSRDesc=%x\n", NewVcb->NSRDesc)); - if (!NT_SUCCESS(RC)) { + if (!NT_SUCCESS(Status)) { if ((Vcb->VcbState & UDF_VCB_FLAGS_RAW_DISK) && (NewVcb->VcbState & UDF_VCB_FLAGS_RAW_DISK) && !(NewVcb->NSRDesc & VRS_ISO9660_FOUND)) { UDFPrint(("UDFVerifyVolume: both are RAW -> remount\n", Vcb->Modified)); - RC = STATUS_SUCCESS; + Status = STATUS_SUCCESS; goto skip_logical_check; } - if (RC == STATUS_UNRECOGNIZED_VOLUME) { - try_return(RC = STATUS_WRONG_VOLUME); + if (Status == STATUS_UNRECOGNIZED_VOLUME) { + try_return(Status = STATUS_WRONG_VOLUME); } - try_return(RC); + try_return(Status); } - WCacheChFlags__(&(Vcb->FastCache), - WCACHE_CACHE_WHOLE_PACKET, // enable cache whole packet - WCACHE_MARK_BAD_BLOCKS | WCACHE_RO_BAD_BLOCKS); // let user retry request on Bad Blocks - NewVcb->VcbCondition = VcbMounted; // Compare logical parameters (phase 2) UDFPrint(("UDFVerifyVolume: Modified=%d\n", Vcb->Modified)); - RC = UDFCompareVcb(IrpContext, Vcb, NewVcb, FALSE); - if (!NT_SUCCESS(RC)) try_return(RC); - // We have unitialized WCache, so it is better to - // force MOUNT_VOLUME call - if (!WCacheIsInitialized__(&(Vcb->FastCache))) - try_return(RC = STATUS_WRONG_VOLUME); + Status = UDFCompareVcb(IrpContext, Vcb, NewVcb, FALSE); + if (!NT_SUCCESS(Status)) try_return(Status); skip_logical_check:; @@ -440,74 +411,19 @@ try_exit: NOTHING; Vcb->MediaChangeCount = MediaChangeCount; // If we got the wrong volume, mark the Vcb as not mounted. - if (RC == STATUS_WRONG_VOLUME) { + if (Status == STATUS_WRONG_VOLUME) { UDFPrint(("UDFVerifyVolume: clear UDF_VCB_FLAGS_VOLUME_MOUNTED\n")); Vcb->VcbCondition = VcbNotMounted; } else - if (NT_SUCCESS(RC) && + if (NT_SUCCESS(Status) && Vcb->VcbCondition == VcbMounted) { - BOOLEAN CacheInitialized = FALSE; - UDFPrint((" !!! VerifyVolume - QUICK REMOUNT !!!\n")); - // Initialize internal cache - CacheInitialized = WCacheIsInitialized__(&(Vcb->FastCache)); - if (!CacheInitialized) { - Mode = WCACHE_MODE_ROM; - RC = WCacheInit__(&(Vcb->FastCache), - Vcb->WCacheMaxFrames, - Vcb->WCacheMaxBlocks, - Vcb->WriteBlockSize, - 5, Vcb->SectorShift, - Vcb->WCacheBlocksPerFrameSh, - 0/*Vcb->FirstLBA*/, Vcb->LastPossibleLBA, Mode, - /*WCACHE_CACHE_WHOLE_PACKET*/ 0 | - WCACHE_DO_NOT_COMPARE | - WCACHE_CHAINED_IO, - Vcb->WCacheFramesToKeepFree, -// UDFTWrite, UDFTRead, - UDFTWriteVerify, UDFTReadVerify, -#ifdef UDF_ASYNC_IO - UDFTWriteAsync, UDFTReadAsync, -#else //UDF_ASYNC_IO - NULL, NULL, -#endif //UDF_ASYNC_IO - UDFIsBlockAllocated, UDFUpdateVAT, - UDFWCacheErrorHandler); - } - if (NT_SUCCESS(RC)) { - if (!Vcb->VerifyCtx.VInited) { - RC = UDFVInit(Vcb); - } - } - if (NT_SUCCESS(RC)) { - - if (!CacheInitialized) { - if (!(Vcb->VcbState & VCB_STATE_MEDIA_WRITE_PROTECT)) { - if (!Vcb->CDR_Mode) { - if (Vcb->TargetDeviceObject->DeviceType == FILE_DEVICE_DISK) { - UDFPrint(("UDFMountVolume: RAM mode\n")); - Mode = WCACHE_MODE_RAM; - } else { - UDFPrint(("UDFMountVolume: RW mode\n")); - Mode = WCACHE_MODE_RW; - } - } else { - Mode = WCACHE_MODE_R; - } - } - WCacheSetMode__(&(Vcb->FastCache), Mode); - - WCacheChFlags__(&(Vcb->FastCache), - WCACHE_CACHE_WHOLE_PACKET, // enable cache whole packet - WCACHE_MARK_BAD_BLOCKS | WCACHE_RO_BAD_BLOCKS); // let user retry request on Bad Blocks - } - } + + } if (NewVcb) { // Release internal cache UDFPrint(("UDFVerifyVolume: delete NewVcb\n")); - WCacheFlushAll__(IrpContext, &NewVcb->FastCache, NewVcb); - WCacheRelease__(&NewVcb->FastCache); UDFCleanupVCB(NewVcb); MyFreePool__(NewVcb); } @@ -525,11 +441,9 @@ try_exit: NOTHING; // Complete the request if no exception. - UDFCompleteRequest(IrpContext, Irp, RC); - - UDFPrint(("UDFVerifyVolume: RC = %x\n", RC)); + UDFCompleteRequest(IrpContext, Irp, Status); - return RC; + return Status; } // end UDFVerifyVolume () /* @@ -931,123 +845,24 @@ UDFCompareVcb( IN BOOLEAN PhysicalOnly ) { - NTSTATUS RC; - UDF_FILE_INFO RootFileInfo; - BOOLEAN SimpleLogicalCheck = FALSE; - -#define VCB_NE(x) (OldVcb->x != NewVcb->x) - - // compare physical parameters - if (PhysicalOnly) { - UDFPrint((" PhysicalOnly\n")); - if (VCB_NE(FirstLBA) || - VCB_NE(LastLBA) || - VCB_NE(FirstTrackNum) || - VCB_NE(LastTrackNum) || - VCB_NE(NWA) || - VCB_NE(LastPossibleLBA) || - VCB_NE(PhSerialNumber) || - VCB_NE(MediaClassEx) || - - /* We cannot compare these flags, because NewVcb is in unconditional ReadOnly */ - - /*((OldVcb->VcbState & UDF_VCB_FLAGS_VOLUME_READ_ONLY) != (NewVcb->VcbState & UDF_VCB_FLAGS_VOLUME_READ_ONLY)) || - ((OldVcb->VcbState & UDF_VCB_FLAGS_MEDIA_READ_ONLY) != (NewVcb->VcbState & UDF_VCB_FLAGS_MEDIA_READ_ONLY)) ||*/ - - VCB_NE(TargetDeviceObject) || - // VCB_NE(xxx) || - // VCB_NE(xxx) || - VCB_NE(LastSession) ) { - - UDFPrint((" WRONG_VOLUME (2)\n")); - return STATUS_WRONG_VOLUME; - } - // Note, MRWStatus can change while media is mounted (stoppped/in-progress/complete) - // We can compare only (Vcb->MRWStatus == 0) values - if ((OldVcb->MRWStatus == 0) != (NewVcb->MRWStatus == 0)) { - UDFPrint((" WRONG_VOLUME (4), missmatch MRW status\n")); - } - for(uint32 i=OldVcb->FirstTrackNum; i<=OldVcb->LastTrackNum; i++) { - if (VCB_NE(TrackMap[i].FirstLba) || - VCB_NE(TrackMap[i].LastLba) || - VCB_NE(TrackMap[i].PacketSize) || - VCB_NE(TrackMap[i].TrackParam) || - VCB_NE(TrackMap[i].DataParam) || - VCB_NE(TrackMap[i].NWA_V) ) { - UDFPrint((" WRONG_VOLUME (3), missmatch trk %d\n", i)); - return STATUS_WRONG_VOLUME; - } - } - UDFPrint((" Vcb compare Ok\n")); - return STATUS_SUCCESS; - } + PAGED_CODE(); - // Something is nasty!!! We perform verify for not flushed volume - // This should never happen, but some devices/buses and their drivers - // can lead us to such condition. For example with help of RESET. - // Now, we hope, that nobody changed media. - // We shall make simplified logical structure check - if (OldVcb->Modified) { - UDFPrint((" Vcb SIMPLE compare on !!!MODIFIED!!! volume\n")); - ASSERT(FALSE); - SimpleLogicalCheck = TRUE; - } + ASSERT_IRP_CONTEXT( IrpContext ); - // compare logical structure - if (!SimpleLogicalCheck && (OldVcb->InitVatCount != NewVcb->InitVatCount)) { - UDFPrint((" InitVatCount %d != %d \n", OldVcb->InitVatCount, NewVcb->InitVatCount)); - return STATUS_WRONG_VOLUME; - } + if (OldVcb->PartitionMaps != NewVcb->PartitionMaps) { - // Compare volume creation time - if (OldVcb->VolCreationTime != NewVcb->VolCreationTime) { - UDFPrint((" VolCreationTime %I64x != %I64x \n", OldVcb->VolCreationTime, NewVcb->VolCreationTime)); return STATUS_WRONG_VOLUME; } - // Compare serial numbers - if (OldVcb->SerialNumber != NewVcb->SerialNumber) { - UDFPrint((" SerialNumber %x != %x \n", OldVcb->SerialNumber, NewVcb->SerialNumber)); - return STATUS_WRONG_VOLUME; - } - // Compare volume idents - if (!SimpleLogicalCheck && - RtlCompareUnicodeString(&(OldVcb->VolIdent),&(NewVcb->VolIdent),FALSE)) { - UDFPrint((" VolIdent missmatch \n")); - return STATUS_WRONG_VOLUME; - } - if (SimpleLogicalCheck) { - // do not touch RootDir. It can be partially recorded - UDFPrint((" SimpleLogicalCheck Ok\n")); - return STATUS_SUCCESS; - } - RC = UDFOpenRootFile__(IrpContext, NewVcb, &NewVcb->RootLbAddr, &RootFileInfo); - if (!NT_SUCCESS(RC)) { - UDFPrint((" Can't open root file, status %x\n", RC)); - UDFCleanUpFile__(NewVcb, &RootFileInfo); - return STATUS_WRONG_VOLUME; - } - // perform exhaustive check - if (!(OldVcb->RootIndexFcb)) { - UDFPrint((" !(OldVcb->RootDirFCB)\n")); -wr_vol: - UDFCloseFile__(IrpContext, NewVcb, &RootFileInfo); - UDFCleanUpFile__(NewVcb, &RootFileInfo); - return STATUS_WRONG_VOLUME; - } + for (USHORT RefPartNum = 0; RefPartNum < OldVcb->PartitionMaps; ++RefPartNum) { + + if (OldVcb->Partitions != NewVcb->Partitions) { - if (!UDFCompareFileInfo(&RootFileInfo, OldVcb->RootIndexFcb->FileInfo)) { - UDFPrint((" !UDFCompareFileInfo\n")); - goto wr_vol; + return STATUS_WRONG_VOLUME; + } } - UDFCloseFile__(IrpContext, NewVcb, &RootFileInfo); - UDFCleanUpFile__(NewVcb, &RootFileInfo); - UDFPrint(("UDFCompareVcb: Ok\n")); return STATUS_SUCCESS; - -#undef VCB_NE - } // end UDFCompareVcb() NTSTATUS diff --git a/drivers/filesystems/udfs/volinfo.cpp b/drivers/filesystems/udfs/volinfo.cpp index d8be1796c6138..21e41a4011d70 100644 --- a/drivers/filesystems/udfs/volinfo.cpp +++ b/drivers/filesystems/udfs/volinfo.cpp @@ -415,11 +415,7 @@ UDFQueryFsAttributeInfo( Buffer->FileSystemAttributes = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES | (UDFIsStreamsSupported(Vcb) ? FILE_NAMED_STREAMS : 0) | -#ifdef ALLOW_SPARSE - FILE_SUPPORTS_SPARSE_FILES | -#endif //ALLOW_SPARSE ((Vcb->VcbState & VCB_STATE_VOLUME_READ_ONLY) ? FILE_READ_ONLY_VOLUME : 0) | - FILE_UNICODE_ON_DISK; Buffer->MaximumComponentNameLength = UDF_X_NAME_LEN-1; diff --git a/drivers/filesystems/udfs/wcache.cpp b/drivers/filesystems/udfs/wcache.cpp deleted file mode 100644 index f8c5c86c580a2..0000000000000 --- a/drivers/filesystems/udfs/wcache.cpp +++ /dev/null @@ -1,11 +0,0 @@ -//////////////////////////////////////////////////////////////////// -// Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine -// All rights reserved -// This file was released under the GPLv2 on June 2015. -//////////////////////////////////////////////////////////////////// -#include "udffs.h" - -// define the file specific bug-check id -#define UDF_BUG_CHECK_ID UDF_FILE_WCACHE - -#include "Include/wcache_lib.cpp" diff --git a/drivers/filesystems/udfs/wcache.h b/drivers/filesystems/udfs/wcache.h deleted file mode 100644 index 8ce897d6f18dd..0000000000000 --- a/drivers/filesystems/udfs/wcache.h +++ /dev/null @@ -1,12 +0,0 @@ -//////////////////////////////////////////////////////////////////// -// Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine -// All rights reserved -// This file was released under the GPLv2 on June 2015. -//////////////////////////////////////////////////////////////////// - -#ifndef __CDRW_WCACHE_H__ -#define __CDRW_WCACHE_H__ - -#include "Include/wcache_lib.h" - -#endif // __CDRW_WCACHE_H__ diff --git a/drivers/filesystems/udfs/write.cpp b/drivers/filesystems/udfs/write.cpp index e76a9426f2f4b..5977f3ead1138 100644 --- a/drivers/filesystems/udfs/write.cpp +++ b/drivers/filesystems/udfs/write.cpp @@ -39,12 +39,12 @@ NTSTATUS UDFCommonWrite( PIRP_CONTEXT IrpContext, - PIRP Irp) + PIRP Irp) { - NTSTATUS RC = STATUS_SUCCESS; - PIO_STACK_LOCATION IrpSp = NULL; - LARGE_INTEGER ByteOffset; - ULONG WriteLength = 0, TruncatedLength = 0; + NTSTATUS Status = STATUS_SUCCESS; + PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); + LONGLONG StartingOffset; + ULONG ByteCount = 0, TruncatedLength = 0; SIZE_T NumberBytesWritten = 0; PFILE_OBJECT FileObject = NULL; TYPE_OF_OPEN TypeOfOpen; @@ -52,7 +52,6 @@ UDFCommonWrite( PCCB Ccb = NULL; PVCB Vcb = NULL; PVOID SystemBuffer = NULL; - PIRP TopIrp; LONGLONG ASize; LONGLONG OldVDL; @@ -64,121 +63,145 @@ UDFCommonWrite( BOOLEAN MainResourceAcquiredExclusive = FALSE; BOOLEAN MainResourceCanDemoteToShared = FALSE; - BOOLEAN CacheLocked = FALSE; - - BOOLEAN CanWait = FALSE; + BOOLEAN Wait = FALSE; BOOLEAN PagingIo = FALSE; BOOLEAN NonCachedIo = FALSE; BOOLEAN SynchronousIo = FALSE; - BOOLEAN IsThisADeferredWrite = FALSE; + BOOLEAN IsLazyWriteThread = FALSE; BOOLEAN WriteToEOF = FALSE; BOOLEAN FileSizesChanged = FALSE; BOOLEAN RecursiveWriteThrough = FALSE; - BOOLEAN WriteFileSizeToDirNdx = FALSE; BOOLEAN ZeroBlock = FALSE; BOOLEAN ZeroBlockDone = FALSE; - TmPrint(("UDFCommonWrite: irp %x\n", Irp)); + FileObject = IrpSp->FileObject; - _SEH2_TRY { + // Extract and decode the file object. + TypeOfOpen = UDFDecodeFileObject(IrpSp->FileObject, &Fcb, &Ccb); - TopIrp = IoGetTopLevelIrp(); - - switch((ULONG_PTR)TopIrp) { - case FSRTL_FSP_TOP_LEVEL_IRP: - UDFPrint((" FSRTL_FSP_TOP_LEVEL_IRP\n")); - break; - case FSRTL_CACHE_TOP_LEVEL_IRP: - UDFPrint((" FSRTL_CACHE_TOP_LEVEL_IRP\n")); - break; - case FSRTL_MOD_WRITE_TOP_LEVEL_IRP: - UDFPrint((" FSRTL_MOD_WRITE_TOP_LEVEL_IRP\n")); - break; - case FSRTL_FAST_IO_TOP_LEVEL_IRP: - UDFPrint((" FSRTL_FAST_IO_TOP_LEVEL_IRP\n")); - BrutePoint(); - break; - case NULL: - UDFPrint((" NULL TOP_LEVEL_IRP\n")); - break; - default: - if (TopIrp == Irp) { - UDFPrint((" TOP_LEVEL_IRP\n")); - } else { - UDFPrint((" RECURSIVE_IRP, TOP = %x\n", TopIrp)); - } - break; - } + if (TypeOfOpen != UserFileOpen && + TypeOfOpen != UserVolumeOpen && + (TypeOfOpen != StreamFileOpen || !NonCachedIo || !PagingIo)) { - // First, get a pointer to the current I/O stack location - IrpSp = IoGetCurrentIrpStackLocation(Irp); - ASSERT(IrpSp); - MmPrint((" Enter Irp, MDL=%x\n", Irp->MdlAddress)); + UDFCompleteRequest(IrpContext, Irp, STATUS_INVALID_DEVICE_REQUEST); + return STATUS_INVALID_DEVICE_REQUEST; + } - FileObject = IrpSp->FileObject; - ASSERT(FileObject); + Vcb = Fcb->Vcb; - // If this is a request at IRQL DISPATCH_LEVEL, then post the request - if (IrpSp->MinorFunction & IRP_MN_DPC) { - try_return(RC = STATUS_PENDING); - } + ASSERT_CCB(Ccb); + ASSERT_FCB(Fcb); + ASSERT_VCB(Vcb); - // Decode the file object and verify we support read on this. It - // must be a user file, stream file or volume file (for a data disk). + // Examine our input parameters to determine if this is noncached and/or + // a paging io operation. - TypeOfOpen = UDFDecodeFileObject(IrpSp->FileObject, &Fcb, &Ccb); + Wait = BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); + PagingIo = FlagOn(Irp->Flags, IRP_PAGING_IO); + NonCachedIo = FlagOn(Irp->Flags, IRP_NOCACHE); + SynchronousIo = FlagOn(IrpSp->FileObject->Flags, FO_SYNCHRONOUS_IO); - Vcb = Fcb->Vcb; + // Check if this volume has already been shut down. If it has, fail + // this write request. - ASSERT_CCB(Ccb); - ASSERT_FCB(Fcb); - ASSERT_VCB(Vcb); + if (FlagOn(Vcb->VcbState, VCB_STATE_SHUTDOWN)) { - if (Fcb->FcbState & UDF_FCB_DELETED) { - ASSERT(FALSE); - try_return(RC = STATUS_TOO_LATE); - } + UDFCompleteRequest(IrpContext, Irp, STATUS_TOO_LATE); + return STATUS_TOO_LATE; + } + + if (FlagOn(Vcb->VcbState, VCB_STATE_VOLUME_READ_ONLY) && (TypeOfOpen != UserVolumeOpen)) { - // is this operation allowed ? - if (Vcb->VcbState & VCB_STATE_MEDIA_WRITE_PROTECT) { - try_return(RC = STATUS_ACCESS_DENIED); + if (FlagOn(Vcb->VcbState, VCB_STATE_MEDIA_WRITE_PROTECT)) { + Status = STATUS_MEDIA_WRITE_PROTECTED; } - Vcb->VcbState |= UDF_VCB_SKIP_EJECT_CHECK; - - // Disk based file systems might decide to verify the logical volume - // (if required and only if removable media are supported) at this time - // As soon as Tray is locked, we needn't call UDFVerifyVcb() - - ByteOffset = IrpSp->Parameters.Write.ByteOffset; - - CanWait = (IrpContext->Flags & IRP_CONTEXT_FLAG_WAIT) ? TRUE : FALSE; - PagingIo = (Irp->Flags & IRP_PAGING_IO) ? TRUE : FALSE; - NonCachedIo = (Irp->Flags & IRP_NOCACHE) ? TRUE : FALSE; - SynchronousIo = (FileObject->Flags & FO_SYNCHRONOUS_IO) ? TRUE : FALSE; - UDFPrint((" Flags: %s; %s; %s; %s; Irp(W): %8.8x\n", - CanWait ? "Wt" : "nw", PagingIo ? "Pg" : "np", - NonCachedIo ? "NonCached" : "Cached", SynchronousIo ? "Snc" : "Asc", - Irp->Flags)); - - // Get some of the parameters supplied to us - WriteLength = IrpSp->Parameters.Write.Length; - if (WriteLength == 0) { - // a 0 byte write can be immediately succeeded - if (SynchronousIo && !PagingIo && NT_SUCCESS(RC)) { - // NT expects changing CurrentByteOffset to zero in this case - FileObject->CurrentByteOffset.QuadPart = 0; - } - try_return(RC); + else if (PagingIo) { + Status = STATUS_FILE_INVALID; + } + else { + Status = FlagOn(Vcb->VcbState, VCB_STATE_MOUNTED_DIRTY) ? + STATUS_VOLUME_DIRTY : STATUS_ACCESS_DENIED; } - // If this is the normal file we have to check for - // write access according to the current state of the file locks. - if (!PagingIo && - Fcb->FileLock != NULL && - !FsRtlCheckLockForWriteAccess(Fcb->FileLock, Irp) ) { + UDFCompleteRequest(IrpContext, Irp, Status); + return Status; + } + + // If this is async paging io then check if we are being called by the mapped page writer. + // Convert it back to synchronous if not. + + if (!Wait && PagingIo) { + + Wait = TRUE; + SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); + } + + StartingOffset = IrpSp->Parameters.Write.ByteOffset.QuadPart; + ByteCount = IrpSp->Parameters.Write.Length; + + Irp->IoStatus.Information = 0; + + // Check if writing to end of file (FILE_WRITE_TO_END_OF_FILE = -1) + + BOOLEAN WriteToEof = (StartingOffset < 0); + + // Validate file offset - overflow check only for normal offsets + + if (((MAXLONGLONG - StartingOffset) < ByteCount) && !WriteToEof) { + + UDFCompleteRequest(IrpContext, Irp, STATUS_INVALID_PARAMETER); + return STATUS_INVALID_PARAMETER; + } + + // Handle zero-length write + if (ByteCount == 0) { + + UDFCompleteRequest(IrpContext, Irp, STATUS_SUCCESS); + return STATUS_SUCCESS; + } + + // See if we have to defer the write. + + if (!NonCachedIo && + !CcCanIWrite(FileObject, + ByteCount, + (BOOLEAN)(Wait && !BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_IN_FSP)), + BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED_WRITE))) { + + BOOLEAN Retrying = BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED_WRITE); + + UDFPrePostIrp(IrpContext, Irp); + + SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED_WRITE); + + CcDeferWrite(FileObject, UDFDeferredWriteCallBack, IrpContext, Irp, ByteCount, Retrying); + return STATUS_PENDING; + } + + _SEH2_TRY { - try_return( RC = STATUS_FILE_LOCK_CONFLICT ); + // If this is a request at IRQL DISPATCH_LEVEL, then post the request + if (IrpSp->MinorFunction & IRP_MN_DPC) { + try_return(Status = STATUS_PENDING); + } + + // If this is a non paging write to a data stream object we have to + // check for access according to the current state op/filelocks. + // + // Note that after this point, operations will be performed on the file. + // No modifying activity can occur prior to this point in the write + // path. + + if (!PagingIo && TypeOfOpen == UserFileOpen) { + + // And finally check the regular file locks. + + if (Fcb->FileLock != NULL && + !FsRtlCheckLockForWriteAccess(Fcb->FileLock, Irp )) { + + try_return(Status = STATUS_FILE_LOCK_CONFLICT); + } } // ********** @@ -188,11 +211,11 @@ UDFCommonWrite( // Yup, we need to send this on to the disk driver after // validation of the offset and length. - if (!CanWait) - try_return(RC = STATUS_PENDING); + if (!Wait) + try_return(Status = STATUS_PENDING); // I dislike the idea of writing to not locked media if (!(Vcb->VcbState & VCB_STATE_LOCKED)) { - try_return(RC = STATUS_ACCESS_DENIED); + try_return(Status = STATUS_ACCESS_DENIED); } if (IrpContext->Flags & UDF_IRP_CONTEXT_FLUSH2_REQUIRED) { @@ -219,89 +242,31 @@ UDFCommonWrite( // Forward the request to the lower level driver // Lock the callers buffer - if (!NT_SUCCESS(RC = UDFLockUserBuffer(IrpContext, WriteLength, IoReadAccess))) { - try_return(RC); + if (!NT_SUCCESS(Status = UDFLockUserBuffer(IrpContext, ByteCount, IoReadAccess))) { + try_return(Status); } SystemBuffer = UDFMapUserBuffer(Irp); if (!SystemBuffer) - try_return(RC = STATUS_INVALID_USER_BUFFER); + try_return(Status = STATUS_INVALID_USER_BUFFER); // Make sure, that volume will never be quick-remounted // It is very important for ChkUdf utility. Vcb->SerialNumber--; // Perform actual Write - RC = UDFTWrite(IrpContext, Vcb, SystemBuffer, WriteLength, - (ULONG)(ByteOffset.QuadPart >> Vcb->SectorShift), + Status = UDFTWrite(IrpContext, Vcb, SystemBuffer, ByteCount, + (ULONG)(StartingOffset >> Vcb->SectorShift), &NumberBytesWritten); UDFUnlockCallersBuffer(IrpContext, Irp, SystemBuffer); - try_return(RC); - } - - if (Vcb->VcbState & VCB_STATE_VOLUME_READ_ONLY) { - try_return(RC = STATUS_ACCESS_DENIED); - } - - // back pressure for very smart and fast system cache ;) - if (!NonCachedIo) { - // cached IO - if (Vcb->VerifyCtx.QueuedCount || - Vcb->VerifyCtx.ItemCount >= UDF_MAX_VERIFY_CACHE) { - UDFVVerify(Vcb, UFD_VERIFY_FLAG_WAIT); - } - } else { - if (Vcb->VerifyCtx.ItemCount > UDF_SYS_CACHE_STOP_THR) { - UDFVVerify(Vcb, UFD_VERIFY_FLAG_WAIT); - } - } - - // The FSD (if it is a "nice" FSD) should check whether it is - // convenient to allow the write to proceed by utilizing the - // CcCanIWrite() function call. If it is not convenient to perform - // the write at this time, we should defer the request for a while. - // The check should not however be performed for non-cached write - // operations. To determine whether we are retrying the operation - // or now, use Flags in the IrpContext structure we have created - - IsThisADeferredWrite = BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED_WRITE); - - if (!NonCachedIo && - !CcCanIWrite(FileObject, WriteLength, CanWait, IsThisADeferredWrite)) { - - // Cache Manager and/or the VMM does not want us to perform - // the write at this time. Post the request. - - SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED_WRITE); - - CcDeferWrite(FileObject, UDFDeferredWriteCallBack, IrpContext, Irp, WriteLength, IsThisADeferredWrite); - try_return(RC = STATUS_PENDING); - } - - // We can continue. Check whether this write operation is targeted - // to a directory object in which case the UDF FSD will disallow - // the write request. - if (Fcb->FcbState & UDF_FCB_DIRECTORY) { - RC = STATUS_INVALID_DEVICE_REQUEST; - try_return(RC); + try_return(Status); } // Validate start offset and length supplied. // Here is a special check that determines whether the caller wishes to // begin the write at current end-of-file (whatever the value of that // offset might be) - if (ByteOffset.HighPart == (LONG)0xFFFFFFFF) { - if (ByteOffset.LowPart == FILE_WRITE_TO_END_OF_FILE) { - WriteToEOF = TRUE; - ByteOffset = Fcb->Header.FileSize; - } else - if (ByteOffset.LowPart == FILE_USE_FILE_POINTER_POSITION) { - ByteOffset = FileObject->CurrentByteOffset; - } - } - - // Check if this volume has already been shut down. If it has, fail - // this write request. - if (Vcb->VcbState & VCB_STATE_SHUTDOWN) { - try_return(RC = STATUS_TOO_LATE); + if (StartingOffset == -1) { + WriteToEOF = TRUE; + StartingOffset = Fcb->Header.FileSize.QuadPart; } // Paging I/O write operations are special. If paging i/o write @@ -309,15 +274,15 @@ UDFCommonWrite( // If paging i/o // requests extend beyond current end of file, they should be truncated // to current end-of-file. - if (PagingIo && (WriteToEOF || ((ByteOffset.QuadPart + WriteLength) > Fcb->Header.FileSize.QuadPart))) { - if (ByteOffset.QuadPart > Fcb->Header.FileSize.QuadPart) { + if (PagingIo && (WriteToEOF || ((StartingOffset + ByteCount) > Fcb->Header.FileSize.QuadPart))) { + if (StartingOffset > Fcb->Header.FileSize.QuadPart) { TruncatedLength = 0; } else { - TruncatedLength = (ULONG)(Fcb->Header.FileSize.QuadPart - ByteOffset.QuadPart); + TruncatedLength = (ULONG)(Fcb->Header.FileSize.QuadPart - StartingOffset); } - if (!TruncatedLength) try_return(RC = STATUS_SUCCESS); + if (!TruncatedLength) try_return(Status = STATUS_SUCCESS); } else { - TruncatedLength = WriteLength; + TruncatedLength = ByteCount; } // There are certain complications that arise when the same file stream @@ -330,67 +295,65 @@ UDFCommonWrite( // information though the purge will probably fail if the file has been // mapped into some process' virtual address space // WARNING !!! we should not flush data beyond valid data length - if (NonCachedIo && - !PagingIo && + if (!PagingIo && + NonCachedIo && Fcb->FcbNonpaged->SegmentObject.DataSectionObject && TruncatedLength && - (ByteOffset.QuadPart < Fcb->Header.FileSize.QuadPart)) { + (StartingOffset < Fcb->Header.FileSize.QuadPart)) { - // Try to acquire the FCB MainResource exclusively - if (!UDFAcquireResourceExclusive(&Fcb->FcbNonpaged->FcbResource, CanWait)) { - try_return(RC = STATUS_PENDING); - } - MainResourceAcquired = TRUE; + UDFAcquireFcbExclusive(IrpContext, Fcb, FALSE); - // We hold PagingIo exclusive around the flush and CcPurgeCacheSection to fix a - // cache coherency problem. - UDFAcquireResourceExclusive(&Fcb->FcbNonpaged->FcbPagingIoResource, TRUE); - PagingIoResourceAcquired = TRUE; + MainResourceAcquired = TRUE; // Flush and then attempt to purge the cache - if ((ByteOffset.QuadPart + TruncatedLength) > Fcb->Header.FileSize.QuadPart) { + if ((StartingOffset + TruncatedLength) > Fcb->Header.FileSize.QuadPart) { NumberBytesWritten = TruncatedLength; } else { - NumberBytesWritten = (ULONG)(Fcb->Header.FileSize.QuadPart - ByteOffset.QuadPart); + NumberBytesWritten = (ULONG)(Fcb->Header.FileSize.QuadPart - StartingOffset); } - MmPrint((" CcFlushCache()\n")); - CcFlushCache(&Fcb->FcbNonpaged->SegmentObject, &ByteOffset, NumberBytesWritten, &Irp->IoStatus); + CcFlushCache(&Fcb->FcbNonpaged->SegmentObject, + WriteToEof ? &Fcb->Header.FileSize : (PLARGE_INTEGER)&StartingOffset, + NumberBytesWritten, + &Irp->IoStatus); // If the flush failed, return error to the caller - if (!NT_SUCCESS(RC = Irp->IoStatus.Status)) { + if (!NT_SUCCESS(Status = Irp->IoStatus.Status)) { NumberBytesWritten = 0; - try_return(RC); + try_return(Status); } // Attempt the purge - MmPrint((" CcPurgeCacheSection()\n")); - BOOLEAN SuccessfulPurge = CcPurgeCacheSection(&Fcb->FcbNonpaged->SegmentObject, &ByteOffset, - NumberBytesWritten, FALSE); + BOOLEAN SuccessfulPurge = CcPurgeCacheSection(&Fcb->FcbNonpaged->SegmentObject, + (PLARGE_INTEGER)&StartingOffset, + NumberBytesWritten, + FALSE); NumberBytesWritten = 0; - UDFReleaseResource(&Fcb->FcbNonpaged->FcbPagingIoResource); - PagingIoResourceAcquired = FALSE; - // We are finished with our flushing and purging if (!SuccessfulPurge) { - try_return(RC = STATUS_PURGE_FAILED); + try_return(Status = STATUS_PURGE_FAILED); } MainResourceCanDemoteToShared = TRUE; } // Determine if we were called by the lazywriter. - // We reuse 'IsThisADeferredWrite' here to decrease stack usage - IsThisADeferredWrite = (Fcb->LazyWriteThread == PsGetCurrentThread()); + + IsLazyWriteThread = (Fcb->LazyWriteThread == PsGetCurrentThread()); // Acquire the appropriate FCB resource if (PagingIo) { - if (!UDFAcquireResourceShared(&Fcb->FcbNonpaged->FcbPagingIoResource, TRUE)) { - try_return(RC = STATUS_PENDING); + // For PagingIo: FcbResource already acquired by UDFAcqLazyWrite/UDFFastIoAcqModWrite + // callback before this function is called + + if (Fcb->FcbState & UDF_FCB_EMBEDDED_DATA) { + ASSERT_EXCLUSIVE_FCB(Fcb); + } + else { + ASSERT_SHARED_FCB(Fcb); } - PagingIoResourceAcquired = TRUE; ASSERT(NonCachedIo); @@ -398,49 +361,25 @@ UDFCommonWrite( // Try to acquire the FCB MainResource shared if (NonCachedIo) { if (!MainResourceAcquired) { - if (!UDFAcquireSharedWaitForExclusive(&Fcb->FcbNonpaged->FcbResource, CanWait)) { - try_return(RC = STATUS_PENDING); + if (!UDFAcquireSharedWaitForExclusive(&Fcb->FcbNonpaged->FcbResource, Wait)) { + try_return(Status = STATUS_PENDING); } MainResourceAcquired = TRUE; } } else { if (!MainResourceAcquired) { UDF_CHECK_PAGING_IO_RESOURCE(Fcb); - if (!UDFAcquireResourceShared(&Fcb->FcbNonpaged->FcbResource, CanWait)) { - try_return(RC = STATUS_PENDING); + if (!UDFAcquireResourceShared(&Fcb->FcbNonpaged->FcbResource, Wait)) { + try_return(Status = STATUS_PENDING); } MainResourceAcquired = TRUE; } } } - // Set the flag indicating if Fast I/O is possible - Fcb->Header.IsFastIoPossible = UDFIsFastIoPossible(Fcb); -/* if (Fcb->CommonFCBHeader.IsFastIoPossible == FastIoIsPossible) { - Fcb->CommonFCBHeader.IsFastIoPossible = FastIoIsQuestionable; - }*/ + if (!Ccb || !FlagOn(Ccb->Flags, CCB_FLAG_DISMOUNT_ON_CLOSE)) { - if ((Irp->Flags & IRP_SYNCHRONOUS_PAGING_IO) && - (IrpContext->Flags & UDF_IRP_CONTEXT_NOT_TOP_LEVEL)) { - - // This clause determines if the top level request was - // in the FastIo path. - if ((ULONG_PTR)TopIrp > FSRTL_MAX_TOP_LEVEL_IRP_FLAG && - NodeType(TopIrp) == IO_TYPE_IRP) { - - PIO_STACK_LOCATION IrpStack; - ASSERT( TopIrp->Type == IO_TYPE_IRP ); - IrpStack = IoGetCurrentIrpStackLocation(TopIrp); - - // Finally this routine detects if the Top irp was a - // write to this file and thus we are the writethrough. - if ((IrpStack->MajorFunction == IRP_MJ_WRITE) && - (IrpStack->FileObject->FsContext == FileObject->FsContext)) { - - RecursiveWriteThrough = TRUE; - IrpContext->Flags |= IRP_CONTEXT_FLAG_WRITE_THROUGH; - } - } + UDFVerifyFcbOperation(IrpContext, Fcb, Ccb); } // Here is the deal with ValidDataLength and FileSize: @@ -466,21 +405,21 @@ UDFCommonWrite( // will subsequently not fail due to lack of disk space. OldVDL = Fcb->Header.ValidDataLength.QuadPart; - ZeroBlock = (ByteOffset.QuadPart > OldVDL); + ZeroBlock = (StartingOffset > OldVDL); if (!PagingIo && !RecursiveWriteThrough && - !IsThisADeferredWrite) { + !IsLazyWriteThread) { BOOLEAN ExtendFS; - ExtendFS = (ByteOffset.QuadPart + TruncatedLength > Fcb->Header.FileSize.QuadPart); + ExtendFS = (StartingOffset + TruncatedLength > Fcb->Header.FileSize.QuadPart); if ( WriteToEOF || ZeroBlock || ExtendFS) { // we are extending the file; - if (!CanWait) - try_return(RC = STATUS_PENDING); + if (!Wait) + try_return(Status = STATUS_PENDING); // CanWait = TRUE; // Try to acquire the FCB MainResource exclusively @@ -490,8 +429,8 @@ UDFCommonWrite( MainResourceAcquired = FALSE; UDF_CHECK_PAGING_IO_RESOURCE(Fcb); - if (!UDFAcquireResourceExclusive(&Fcb->FcbNonpaged->FcbResource, CanWait)) { - try_return(RC = STATUS_PENDING); + if (!UDFAcquireResourceExclusive(&Fcb->FcbNonpaged->FcbResource, Wait)) { + try_return(Status = STATUS_PENDING); } MainResourceAcquired = TRUE; } @@ -500,28 +439,25 @@ UDFCommonWrite( PagingIoResourceAcquired = TRUE; if (ExtendFS) { - RC = UDFResizeFile__(IrpContext, Vcb, Fcb->FileInfo, ByteOffset.QuadPart + TruncatedLength); + Status = UDFResizeFile__(IrpContext, Vcb, Fcb->FileInfo, StartingOffset + TruncatedLength); - if (!NT_SUCCESS(RC)) { - try_return(RC); + if (!NT_SUCCESS(Status)) { + try_return(Status); } FileSizesChanged = TRUE; // ... and inform the Cache Manager about it - Fcb->Header.FileSize.QuadPart = ByteOffset.QuadPart + TruncatedLength; - Fcb->Header.AllocationSize.QuadPart = UDFGetFileAllocationSize(Vcb, Fcb->FileInfo); - if (!Vcb->LowFreeSpace) { - Fcb->Header.AllocationSize.QuadPart += (PAGE_SIZE*9-1); - } else { - Fcb->Header.AllocationSize.QuadPart += (PAGE_SIZE-1); + Fcb->Header.FileSize.QuadPart = StartingOffset + TruncatedLength; + + if (Fcb->Header.AllocationSize.QuadPart < (LONGLONG)LlSectorAlign(Vcb, Fcb->Header.FileSize.QuadPart)) { + + Fcb->Header.AllocationSize.QuadPart = LlSectorAlign(Vcb, Fcb->Header.FileSize.QuadPart); } - Fcb->Header.AllocationSize.LowPart &= ~(PAGE_SIZE-1); } UDFReleaseResource(&Fcb->FcbNonpaged->FcbPagingIoResource); PagingIoResourceAcquired = FALSE; - UDFPrint(("UDFCommonWrite: Set size %x (alloc size %x)\n", ByteOffset.LowPart + TruncatedLength, Fcb->Header.AllocationSize.LowPart)); if (CcIsFileCached(FileObject)) { if (ExtendFS) { MmPrint((" CcSetFileSizes()\n")); @@ -540,7 +476,7 @@ UDFCommonWrite( FileObject, OldVDL, Fcb->Header.FileSize.QuadPart - OldVDL, - CanWait); + Wait); #ifdef UDF_DBG ZeroBlockDone = TRUE; #endif //UDF_DBG @@ -550,29 +486,24 @@ UDFCommonWrite( } -#ifdef UDF_DISABLE_SYSTEM_CACHE_MANAGER - NonCachedIo = TRUE; -#endif - if (Fcb && Fcb->FileInfo && Fcb->FileInfo->Dloc) { - AdPrint(("UDFCommonWrite: DataLoc %x, Mapping %x\n", Fcb->FileInfo->Dloc->DataLoc, Fcb->FileInfo->Dloc->DataLoc.Mapping)); - } + // Branch here for cached vs non-cached I/O - // Branch here for cached vs non-cached I/O if (!NonCachedIo) { // The caller wishes to perform cached I/O. Initiate caching if // this is the first cached I/O operation using this file object + if (!FileObject->PrivateCacheMap) { // This is the first cached I/O operation. You must ensure // that the FCB Header contains valid sizes at this time - UDFPrint(("UDFCommonWrite: Init system cache\n")); - MmPrint((" CcInitializeCacheMap()\n")); - CcInitializeCacheMap(FileObject, (PCC_FILE_SIZES)&Fcb->Header.AllocationSize, - FALSE, // We will not utilize pin access for this file - &(UdfData.CacheMgrCallBacks), // callbacks - Fcb); // The context used in callbacks - MmPrint((" CcSetReadAheadGranularity()\n")); + + CcInitializeCacheMap(FileObject, + (PCC_FILE_SIZES)&Fcb->Header.AllocationSize, + FALSE, + &UdfData.CacheMgrCallBacks, + Fcb); + CcSetReadAheadGranularity(FileObject, READ_AHEAD_GRANULARITY); } @@ -581,16 +512,44 @@ UDFCommonWrite( UDFZeroData(Vcb, FileObject, OldVDL, - ByteOffset.QuadPart + TruncatedLength - OldVDL, - CanWait); - if (ByteOffset.LowPart & (PAGE_SIZE-1)) { + StartingOffset + TruncatedLength - OldVDL, + Wait); + if (StartingOffset & (PAGE_SIZE-1)) { } } - WriteFileSizeToDirNdx = (IrpContext->Flags & IRP_CONTEXT_FLAG_WRITE_THROUGH) ? - TRUE : FALSE; - // Check and see if this request requires a MDL returned to the caller - if (IrpSp->MinorFunction & IRP_MN_MDL) { + // Write to the cache if this is not an Mdl read. + + if (!FlagOn( IrpContext->MinorFunction, IRP_MN_MDL)) { + + // Get hold of the user's buffer. + + SystemBuffer = UDFMapUserBuffer(Irp); + + Fcb->NtReqFCBFlags |= UDF_NTREQ_FCB_MODIFIED; + + if (!CcCopyWrite(FileObject, + (PLARGE_INTEGER)&StartingOffset, + TruncatedLength, + Wait, + SystemBuffer)) { + + // The caller was not prepared to block and data is not immediately + // available in the system cache + // Mark Irp Pending ... + try_return(Status = STATUS_PENDING); + } + + UDFUnlockCallersBuffer(IrpContext, Irp, SystemBuffer); + // We have the data + Status = STATUS_SUCCESS; + NumberBytesWritten = TruncatedLength; + + try_return(Status); + + // Otherwise perform the MdlRead operation. + + } else { // Caller does want a MDL returned. Note that this mode // implies that the caller is prepared to block MmPrint((" CcPrepareMdlWrite()\n")); @@ -599,37 +558,10 @@ UDFCommonWrite( // RC = Irp->IoStatus.Status; NumberBytesWritten = 0; - RC = STATUS_INVALID_PARAMETER; + Status = STATUS_INVALID_PARAMETER; - try_return(RC); + try_return(Status); } - - // This is a regular run-of-the-mill cached I/O request. Let the - // Cache Manager worry about it! - // First though, we need a buffer pointer (address) that is valid - - // We needn't call CcZeroData 'cause udf_info.cpp will care about it - SystemBuffer = UDFMapUserBuffer(Irp); - if (!SystemBuffer) - try_return(RC = STATUS_INVALID_USER_BUFFER); - ASSERT(SystemBuffer); - Fcb->NtReqFCBFlags |= UDF_NTREQ_FCB_MODIFIED; - - MmPrint((" CcCopyWrite()\n")); - if (!CcCopyWrite(FileObject, &(ByteOffset), TruncatedLength, CanWait, SystemBuffer)) { - // The caller was not prepared to block and data is not immediately - // available in the system cache - // Mark Irp Pending ... - try_return(RC = STATUS_PENDING); - } - - UDFUnlockCallersBuffer(IrpContext, Irp, SystemBuffer); - // We have the data - RC = STATUS_SUCCESS; - NumberBytesWritten = TruncatedLength; - - try_return(RC); - } else { MmPrint((" Write NonCachedIo\n")); @@ -638,125 +570,91 @@ UDFCommonWrite( // 'cause we've already done it above // (see call to UDFZeroDataEx() ) if (!RecursiveWriteThrough && - !IsThisADeferredWrite && - (OldVDL < ByteOffset.QuadPart)) { + !IsLazyWriteThread && + (OldVDL < StartingOffset)) { #ifdef UDF_DBG ASSERT(!ZeroBlockDone); #endif //UDF_DBG UDFZeroData(Vcb, FileObject, OldVDL, - ByteOffset.QuadPart - OldVDL, - CanWait); + StartingOffset - OldVDL, + Wait); } - if (OldVDL < (ByteOffset.QuadPart + TruncatedLength)) { - Fcb->Header.ValidDataLength.QuadPart = ByteOffset.QuadPart + TruncatedLength; + if (OldVDL < (StartingOffset + TruncatedLength)) { + Fcb->Header.ValidDataLength.QuadPart = StartingOffset + TruncatedLength; } - // Successful check will cause WCache lock - if (!CanWait && UDFIsFileCached__(Vcb, Fcb->FileInfo, ByteOffset.QuadPart, TruncatedLength, TRUE)) { - UDFPrint(("UDFCommonWrite: Cached => CanWait\n")); - CacheLocked = TRUE; - CanWait = TRUE; - } // Send the request to lower level drivers - if (!CanWait) { - UDFPrint(("UDFCommonWrite: Post physical write %x bytes at %x\n", TruncatedLength, ByteOffset.LowPart)); + if (!Wait) { + UDFPrint(("UDFCommonWrite: Post physical write %x bytes at %x\n", TruncatedLength, StartingOffset.LowPart)); - try_return(RC = STATUS_PENDING); + try_return(Status = STATUS_PENDING); } // Lock the callers buffer - if (!NT_SUCCESS(RC = UDFLockUserBuffer(IrpContext, TruncatedLength, IoReadAccess))) { - try_return(RC); + if (!NT_SUCCESS(Status = UDFLockUserBuffer(IrpContext, TruncatedLength, IoReadAccess))) { + try_return(Status); } SystemBuffer = UDFMapUserBuffer(Irp); if (!SystemBuffer) { - try_return(RC = STATUS_INVALID_USER_BUFFER); + try_return(Status = STATUS_INVALID_USER_BUFFER); } Fcb->NtReqFCBFlags |= UDF_NTREQ_FCB_MODIFIED; - RC = UDFWriteFile__(IrpContext, Vcb, Fcb->FileInfo, ByteOffset.QuadPart, TruncatedLength, - CacheLocked, (PCHAR)SystemBuffer, &NumberBytesWritten); + Status = UDFWriteFile__(IrpContext, Vcb, Fcb->FileInfo, StartingOffset, TruncatedLength, + FALSE, (PCHAR)SystemBuffer, &NumberBytesWritten); UDFUnlockCallersBuffer(IrpContext, Irp, SystemBuffer); - WriteFileSizeToDirNdx = TRUE; + ASize = UDFGetFileAllocationSize(Vcb, Fcb->FileInfo); + UDFSetFileSizeInDirNdx(Vcb, Fcb->FileInfo, &ASize); - try_return(RC); + try_return(Status); } try_exit: NOTHING; } _SEH2_FINALLY { - if (CacheLocked) { - WCacheEODirect__(&(Vcb->FastCache), Vcb); + if (Irp != NULL) { + Irp->IoStatus.Information = NumberBytesWritten; + Irp->IoStatus.Status = Status; } - if (RC == STATUS_PENDING) { - - // Release any resources acquired here ... - if (PagingIoResourceAcquired) { - UDFReleaseResource(&Fcb->FcbNonpaged->FcbPagingIoResource); - } - - if (MainResourceAcquired) { - UDF_CHECK_PAGING_IO_RESOURCE(Fcb); - UDFReleaseResource(&Fcb->FcbNonpaged->FcbResource); - } + if (NT_SUCCESS(Status) && !AbnormalTermination()) { - if (VcbAcquired) { - UDFReleaseResource(&Vcb->VcbResource); - } - - } else { // For synchronous I/O, the FSD must maintain the current byte offset // Do not do this however, if I/O is marked as paging-io - if (SynchronousIo && !PagingIo && NT_SUCCESS(RC)) { - FileObject->CurrentByteOffset.QuadPart = ByteOffset.QuadPart + NumberBytesWritten; + + if (SynchronousIo && !PagingIo && NT_SUCCESS(Status)) { + FileObject->CurrentByteOffset.QuadPart = StartingOffset + NumberBytesWritten; } + // If the write completed successfully and this was not a paging-io // operation, set a flag in the CCB that indicates that a write was // performed and that the file time should be updated at cleanup - if (NT_SUCCESS(RC) && !PagingIo) { + + if (NT_SUCCESS(Status) && !PagingIo) { + // If the file size was changed, set a flag in the FCB indicating that // this occurred. - SetFlag(FileObject->Flags, FO_FILE_MODIFIED); - - if (FileSizesChanged) { - if (!WriteFileSizeToDirNdx) { - - FileObject->Flags |= FO_FILE_SIZE_CHANGED; - } else { - - ASize = UDFGetFileAllocationSize(Vcb, Fcb->FileInfo); - UDFSetFileSizeInDirNdx(Vcb, Fcb->FileInfo, &ASize); - - if (UDFIsAStream(Fcb->FileInfo)) { - - UDFNotifyFullReportChange(Vcb, - Fcb, - FILE_NOTIFY_CHANGE_STREAM_SIZE, - FILE_ACTION_MODIFIED_STREAM); - } else { - - UDFNotifyFullReportChange(Vcb, - Fcb, - FILE_NOTIFY_CHANGE_SIZE, - FILE_ACTION_MODIFIED); - } - } + SetFlag(FileObject->Flags, FO_FILE_MODIFIED); + + if (FileSizesChanged) { + + SetFlag(FileObject->Flags, FO_FILE_SIZE_CHANGED); } + // Update ValidDataLength - if (!IsThisADeferredWrite) { + if (!IsLazyWriteThread) { - if (Fcb->Header.ValidDataLength.QuadPart < (ByteOffset.QuadPart + NumberBytesWritten)) { + if (Fcb->Header.ValidDataLength.QuadPart < (StartingOffset + NumberBytesWritten)) { Fcb->Header.ValidDataLength.QuadPart = min(Fcb->Header.FileSize.QuadPart, - ByteOffset.QuadPart + NumberBytesWritten); + StartingOffset + NumberBytesWritten); if (NonCachedIo && CcIsFileCached(FileObject)) { CcSetFileSizes(FileObject, (PCC_FILE_SIZES)&Fcb->Header.AllocationSize); @@ -764,47 +662,38 @@ try_exit: NOTHING; } } } + } - // Release any resources acquired here ... - if (PagingIoResourceAcquired) { - UDFReleaseResource(&Fcb->FcbNonpaged->FcbPagingIoResource); - } + // Release any resources acquired here ... - if (MainResourceAcquired) { - UDF_CHECK_PAGING_IO_RESOURCE(Fcb); - UDFReleaseResource(&Fcb->FcbNonpaged->FcbResource); - } + if (PagingIoResourceAcquired) { + UDFReleaseResource(&Fcb->FcbNonpaged->FcbPagingIoResource); + } - if (VcbAcquired) { - UDFReleaseResource(&Vcb->VcbResource); - } - // If the request failed, and we had done some nasty stuff like - // extending the file size (including informing the Cache Manager - // about the new file size), and allocating on-disk space etc., undo - // it at this time. - - // Can complete the IRP here if no exception was encountered - if (!_SEH2_AbnormalTermination() && - Irp) { - Irp->IoStatus.Status = RC; - Irp->IoStatus.Information = NumberBytesWritten; - } + if (MainResourceAcquired) { + UDF_CHECK_PAGING_IO_RESOURCE(Fcb); + UDFReleaseResource(&Fcb->FcbNonpaged->FcbResource); } + + if (VcbAcquired) { + UDFReleaseResource(&Vcb->VcbResource); + } + } _SEH2_END; // end of "__finally" processing // Post IRP if required - if (RC == STATUS_PENDING) { + if (Status == STATUS_PENDING) { - RC = UDFFsdPostRequest(IrpContext, Irp); - } - else { + Status = UDFFsdPostRequest(IrpContext, Irp); + + } else { - UDFCompleteRequest(IrpContext, Irp, RC); + UDFCompleteRequest(IrpContext, Irp, Status); } UDFPrint(("\n")); - return(RC); + return(Status); } // end UDFCommonWrite() /************************************************************************* From cffe655cef17faa700e627e74e593b186cab11a5 Mon Sep 17 00:00:00 2001 From: Gleb Lamm Date: Tue, 3 Feb 2026 01:26:59 +0400 Subject: [PATCH 3/9] refactoring --- drivers/filesystems/udfs/CMakeLists.txt | 1 + drivers/filesystems/udfs/Include/phys_lib.cpp | 3 +- drivers/filesystems/udfs/cleanup.cpp | 185 +--- drivers/filesystems/udfs/close.cpp | 240 +----- drivers/filesystems/udfs/create.cpp | 798 +++++++++++------- drivers/filesystems/udfs/dircntrl.cpp | 17 +- drivers/filesystems/udfs/fastio.cpp | 99 +-- drivers/filesystems/udfs/fileinfo.cpp | 168 ++-- drivers/filesystems/udfs/flush.cpp | 23 +- drivers/filesystems/udfs/fscntrl.cpp | 208 ++--- drivers/filesystems/udfs/lockctrl.cpp | 35 +- drivers/filesystems/udfs/misc.cpp | 18 +- drivers/filesystems/udfs/nodetype.h | 1 + drivers/filesystems/udfs/protos.h | 108 ++- drivers/filesystems/udfs/read.cpp | 88 +- drivers/filesystems/udfs/strucsup.cpp | 506 ++++++++--- drivers/filesystems/udfs/struct.h | 66 +- drivers/filesystems/udfs/udf_info/dirtree.cpp | 45 + .../filesystems/udfs/udf_info/udf_info.cpp | 186 +++- drivers/filesystems/udfs/udf_info/udf_info.h | 17 + drivers/filesystems/udfs/udf_info/udf_rel.h | 12 + drivers/filesystems/udfs/udffs.h | 4 +- drivers/filesystems/udfs/udfinit.cpp | 2 +- drivers/filesystems/udfs/volinfo.cpp | 4 - drivers/filesystems/udfs/write.cpp | 673 +++++++-------- 25 files changed, 1981 insertions(+), 1526 deletions(-) diff --git a/drivers/filesystems/udfs/CMakeLists.txt b/drivers/filesystems/udfs/CMakeLists.txt index 53ce00f1bd62f..1ae3d50d9b070 100644 --- a/drivers/filesystems/udfs/CMakeLists.txt +++ b/drivers/filesystems/udfs/CMakeLists.txt @@ -24,6 +24,7 @@ list(APPEND SOURCE mem.cpp misc.cpp namesup.cpp + prefxsup.cpp pnp.cpp read.cpp secursup.cpp diff --git a/drivers/filesystems/udfs/Include/phys_lib.cpp b/drivers/filesystems/udfs/Include/phys_lib.cpp index 656441f1790dc..bba91e86d1c06 100644 --- a/drivers/filesystems/udfs/Include/phys_lib.cpp +++ b/drivers/filesystems/udfs/Include/phys_lib.cpp @@ -845,7 +845,8 @@ UDFGetBlockSize( ASSERT(FALSE); } } else { - ASSERT(FALSE); + + try_return(RC = STATUS_UNRECOGNIZED_VOLUME); } Vcb->LastPossibleLBA = Vcb->LastLBA; } diff --git a/drivers/filesystems/udfs/cleanup.cpp b/drivers/filesystems/udfs/cleanup.cpp index 22788214d386c..355a7e22bbb53 100644 --- a/drivers/filesystems/udfs/cleanup.cpp +++ b/drivers/filesystems/udfs/cleanup.cpp @@ -50,7 +50,6 @@ UDFCommonCleanup( { IO_STATUS_BLOCK IoStatus; NTSTATUS RC = STATUS_SUCCESS; - NTSTATUS RC2; PFILE_OBJECT FileObject = NULL; PFCB Fcb = NULL; PCCB Ccb = NULL; @@ -78,13 +77,13 @@ UDFCommonCleanup( return STATUS_SUCCESS; } - // Get the file object out of the Irp and decode the type of open. + // Get the file object out of the Irp and decode the type of open. FileObject = IoGetCurrentIrpStackLocation(Irp)->FileObject; TypeOfOpen = UDFDecodeFileObject(FileObject, &Fcb, &Ccb); - // No work here for either an UnopenedFile object or a StreamFileObject. + // No work here for either an UnopenedFile object or a StreamFileObject. if (TypeOfOpen <= StreamFileOpen) { @@ -174,15 +173,8 @@ UDFCommonCleanup( AcquiredVcb = TRUE; } - // Acquire parent object - if (Fcb->FileInfo->ParentFile) { - UDF_CHECK_PAGING_IO_RESOURCE(Fcb->FileInfo->ParentFile->Fcb); - UDFAcquireResourceExclusive(&(Fcb->FileInfo->ParentFile->Fcb->FcbNonpaged->FcbResource), TRUE); - } else { - UDFAcquireResourceShared(&(Vcb->VcbResource), TRUE); - } - AcquiredParentFCB = TRUE; - // Acquire current object + // Acquire current object only + // Parent is acquired later only for delete operations (Child → Parent order) UDF_CHECK_PAGING_IO_RESOURCE(Fcb); UDFAcquireResourceExclusive(&Fcb->FcbNonpaged->FcbResource, TRUE); AcquiredFCB = TRUE; @@ -242,40 +234,12 @@ UDFCommonCleanup( !UDFIsSDirDeleted(Fcb->FileInfo->Dloc->SDirInfo)) { RC = UDFMarkStreamsForDeletion(IrpContext, Vcb, Fcb, TRUE); // Delete } - // we can release these resources 'cause UDF_FCB_DELETE_ON_CLOSE - // flag is already set & the file can't be opened - UDF_CHECK_PAGING_IO_RESOURCE(Fcb); - UDFReleaseResource(&Fcb->FcbNonpaged->FcbResource); - AcquiredFCB = FALSE; - if (Fcb->FileInfo->ParentFile) { - UDF_CHECK_PAGING_IO_RESOURCE(Fcb->ParentFcb); - UDFReleaseResource(&Fcb->ParentFcb->FcbNonpaged->FcbResource); - } else { - UDFReleaseResource(&Vcb->VcbResource); - } - AcquiredParentFCB = FALSE; - UDFReleaseResource(&(Vcb->VcbResource)); - AcquiredVcb = FALSE; - - // Make system to issue last Close request - // for our Target ... - -#ifdef UDF_DELAYED_CLOSE - UDFFspClose(Fcb->Vcb); -#endif //UDF_DELAYED_CLOSE - - UDFAcquireResourceShared(&Vcb->VcbResource, TRUE); - AcquiredVcb = TRUE; + // Acquire parent for delete operation (after current - child first order) if (Fcb->FileInfo->ParentFile) { UDF_CHECK_PAGING_IO_RESOURCE(Fcb->ParentFcb); UDFAcquireResourceExclusive(&(Fcb->ParentFcb->FcbNonpaged->FcbResource), TRUE); - } else { - UDFAcquireResourceShared(&Vcb->VcbResource, TRUE); + AcquiredParentFCB = TRUE; } - AcquiredParentFCB = TRUE; - UDF_CHECK_PAGING_IO_RESOURCE(Fcb); - UDFAcquireResourceExclusive(&Fcb->FcbNonpaged->FcbResource, TRUE); - AcquiredFCB = TRUE; // we should set file sizes to zero if there are no more // links to this file @@ -292,14 +256,6 @@ UDFCommonCleanup( } } -#ifdef UDF_DELAYED_CLOSE - if ((Fcb->FcbReference == 1) && - /*(Fcb->NodeIdentifier.NodeType != UDF_NODE_TYPE_VCB) &&*/ // see above - (!(Fcb->FcbState & UDF_FCB_DELETE_ON_CLOSE)) ) { - Fcb->FcbState |= UDF_FCB_DELAY_CLOSE; - } -#endif //UDF_DELAYED_CLOSE - NextFileInfo = Fcb->FileInfo; // do we need to delete it now ? @@ -460,7 +416,7 @@ UDFCommonCleanup( /* MmPrint((" CcPurgeCacheSection()\n")); CcPurgeCacheSection(&Fcb->SectionObject, NULL, 0, FALSE);*/ } - // we needn't Flush here. It will be done in UDFCloseFileInfoChain() + // we needn't Flush here. It will be done in UDFCloseFile__ } // Update FileTimes & Attrs @@ -501,11 +457,28 @@ UDFCommonCleanup( ASize = UDFGetFileAllocationSize(Vcb, NextFileInfo); // Fcb->CommonFCBHeader.AllocationSize.QuadPart; UDFSetFileSizeInDirNdx(Vcb, NextFileInfo, &ASize); - } else - if (FileObject->Flags & FO_FILE_SIZE_CHANGED) { + + } else if (FileObject->Flags & FO_FILE_SIZE_CHANGED) { + ASize = //UDFGetFileAllocationSize(Vcb, NextFileInfo); Fcb->Header.AllocationSize.QuadPart; UDFSetFileSizeInDirNdx(Vcb, NextFileInfo, &ASize); + + if (UDFIsAStream(Fcb->FileInfo)) { + + UDFNotifyFullReportChange(Vcb, + Fcb, + FILE_NOTIFY_CHANGE_STREAM_SIZE, + FILE_ACTION_MODIFIED_STREAM); + } + else { + + UDFNotifyFullReportChange(Vcb, + Fcb, + FILE_NOTIFY_CHANGE_SIZE, + FILE_ACTION_MODIFIED); + } + } } // AccessTime @@ -539,23 +512,22 @@ UDFCommonCleanup( } // release resources now. - // they'll be acquired in UDFCloseFileInfoChain() UDF_CHECK_PAGING_IO_RESOURCE(Fcb); UDFReleaseResource(&Fcb->FcbNonpaged->FcbResource); AcquiredFCB = FALSE; - if (Fcb->FileInfo->ParentFile) { + if (AcquiredParentFCB && Fcb->FileInfo->ParentFile) { UDF_CHECK_PAGING_IO_RESOURCE(Fcb->FileInfo->ParentFile->Fcb); UDFReleaseResource(&Fcb->FileInfo->ParentFile->Fcb->FcbNonpaged->FcbResource); - } else { - UDFReleaseResource(&Vcb->VcbResource); + AcquiredParentFCB = FALSE; } - AcquiredParentFCB = FALSE; - // close the chain + + // Close the target file's FileInfo - this decrements FileInfo->RefCount + // Parent FileInfo references are now handled by LCB mechanism in UDFTeardownStructures ASSERT(AcquiredVcb); - RC2 = UDFCloseFileInfoChain(IrpContext, Vcb, NextFileInfo, Ccb->TreeLength, TRUE); - if (NT_SUCCESS(RC)) - RC = RC2; + if (NextFileInfo) { + UDFCloseFile__(IrpContext, Vcb, NextFileInfo); + } Ccb->Flags |= UDF_CCB_CLEANED; @@ -577,13 +549,9 @@ try_exit: NOTHING; UDFReleaseResource(&Fcb->FcbNonpaged->FcbResource); } - if (AcquiredParentFCB) { - if (Fcb->FileInfo->ParentFile) { - UDF_CHECK_PAGING_IO_RESOURCE(Fcb->FileInfo->ParentFile->Fcb); - UDFReleaseResource(&Fcb->FileInfo->ParentFile->Fcb->FcbNonpaged->FcbResource); - } else { - UDFReleaseResource(&Vcb->VcbResource); - } + if (AcquiredParentFCB && Fcb->FileInfo->ParentFile) { + UDF_CHECK_PAGING_IO_RESOURCE(Fcb->FileInfo->ParentFile->Fcb); + UDFReleaseResource(&Fcb->FileInfo->ParentFile->Fcb->FcbNonpaged->FcbResource); } if (AcquiredVcb) { @@ -605,85 +573,6 @@ try_exit: NOTHING; return(RC); } // end UDFCommonCleanup() -/* - This routine walks through the tree to RootDir & - calls UDFCloseFile__() for each file instance - imho, Useful feature - */ -NTSTATUS -UDFCloseFileInfoChain( - IN PIRP_CONTEXT IrpContext, - IN PVCB Vcb, - IN PUDF_FILE_INFO fi, - IN ULONG TreeLength, - IN BOOLEAN VcbAcquired - ) -{ - PUDF_FILE_INFO ParentFI; - PFCB Fcb; - PFCB ParentFcb = NULL; - NTSTATUS RC = STATUS_SUCCESS; - NTSTATUS RC2; - - // we can't process Tree until we can acquire Vcb - if (!VcbAcquired) - UDFAcquireResourceShared(&(Vcb->VcbResource),TRUE); - - AdPrint(("UDFCloseFileInfoChain\n")); - for(; TreeLength && fi; TreeLength--) { - - // close parent chain (if any) - // if we started path parsing not from RootDir on Create, - // we would never get RootDir here - ValidateFileInfo(fi); - - // acquire parent - if ((ParentFI = fi->ParentFile)) { - ParentFcb = fi->Fcb->ParentFcb; - ASSERT(ParentFcb); - UDF_CHECK_PAGING_IO_RESOURCE(ParentFcb); - UDFAcquireResourceExclusive(&ParentFcb->FcbNonpaged->FcbResource, TRUE); - ASSERT_FCB(ParentFcb); - } else { - AdPrint(("Acquiring VCB...\n")); - UDFAcquireResourceShared(&Vcb->VcbResource, TRUE); - AdPrint(("Done\n")); - } - // acquire current file/dir - // we must assure that no more threads try to reuse this object - if ((Fcb = fi->Fcb)) { - UDF_CHECK_PAGING_IO_RESOURCE(Fcb); - UDFAcquireResourceExclusive(&Fcb->FcbNonpaged->FcbResource, TRUE); - ASSERT(Fcb->FcbReference >= fi->RefCount); - RC2 = UDFCloseFile__(IrpContext, Vcb, fi); - if (!NT_SUCCESS(RC2)) - RC = RC2; - ASSERT(Fcb->FcbReference > fi->RefCount); - UDF_CHECK_PAGING_IO_RESOURCE(Fcb); - UDFReleaseResource(&Fcb->FcbNonpaged->FcbResource); - } else { - BrutePoint(); - RC2 = UDFCloseFile__(IrpContext, Vcb, fi); - if (!NT_SUCCESS(RC2)) - RC = RC2; - } - - if (ParentFI) { - UDF_CHECK_PAGING_IO_RESOURCE(ParentFcb); - UDFReleaseResource(&ParentFcb->FcbNonpaged->FcbResource); - } else { - UDFReleaseResource(&Vcb->VcbResource); - } - fi = ParentFI; - } - - if (!VcbAcquired) - UDFReleaseResource(&Vcb->VcbResource); - - return RC; - -} // end UDFCloseFileInfoChain() - VOID UDFAutoUnlock ( IN PVCB Vcb diff --git a/drivers/filesystems/udfs/close.cpp b/drivers/filesystems/udfs/close.cpp index 664f54f599dbf..8b99cc498ff61 100644 --- a/drivers/filesystems/udfs/close.cpp +++ b/drivers/filesystems/udfs/close.cpp @@ -78,7 +78,6 @@ UDFCommonClose( PFCB Fcb = NULL; PCCB Ccb = NULL; PVCB Vcb = NULL; - ULONG i = 0; TYPE_OF_OPEN TypeOfOpen; ULONG UserReference = 0; BOOLEAN PotentialVcbTeardown = FALSE; @@ -121,8 +120,7 @@ UDFCommonClose( if (Irp) { UserReference = 1; - IrpContext->TreeLength = - i = Ccb->TreeLength; + // TreeLength no longer used - LCB model handles parent tracking // remember the number of incomplete Close requests InterlockedIncrement((PLONG)&(Fcb->CcbCount)); // we can release CCB in any case @@ -159,7 +157,7 @@ UDFCommonClose( InterlockedDecrement((PLONG)&Vcb->VcbReference); - if (!i || (Fcb == Fcb->Vcb->VolumeDasdFcb)) { + if (Fcb == Vcb->VolumeDasdFcb) { AdPrint(("UDF: Closing volume\n")); AdPrint(("UDF: ReferenceCount: %x\n",Fcb->FcbReference)); @@ -209,7 +207,16 @@ UDFCommonClose( } // try to clean up as long chain as it is possible - UDFTeardownStructures(IrpContext, Fcb, i, NULL); + // TODO: refactor to use UDFCommonClosePrivate + { + BOOLEAN RemovedFcb = FALSE; + UDFAcquireFcbExclusive(IrpContext, Fcb, FALSE); + // LCB-based teardown: walks ParentLcbQueue to find and remove LCBs + UDFTeardownStructures(IrpContext, Fcb, FALSE, &RemovedFcb); + if (!RemovedFcb) { + UDFReleaseFcb(IrpContext, Fcb); + } + } } try_exit: NOTHING; @@ -232,224 +239,6 @@ try_exit: NOTHING; return STATUS_SUCCESS; } // end UDFCommonClose() -/* - This routine walks through the tree to RootDir & kills all unreferenced - structures.... - imho, Useful feature - */ -_Requires_lock_held_(_Global_critical_region_) -VOID -UDFTeardownStructures( - _In_ PIRP_CONTEXT IrpContext, - _Inout_ PFCB StartingFcb, - _In_ ULONG TreeLength, - _Out_ PBOOLEAN RemovedStartingFcb - ) -{ - PVCB Vcb = StartingFcb->Vcb; - PFCB CurrentFcb = StartingFcb; - PFCB ParentFcb = NULL; - - LONG RefCount; - BOOLEAN Delete = FALSE; - - ValidateFileInfo(CurrentFcb->FileInfo); - AdPrint(("UDFCleanUpFcbChain\n")); - - ASSERT(TreeLength); - //TODO: - //ASSERT_EXCLUSIVE_FCB(StartingFcb); - //ASSERT_SHARED_VCB(Vcb); - - if (RemovedStartingFcb) { - *RemovedStartingFcb = FALSE; - } - - // Use a try-finally to safely clear the top-level field. - - _SEH2_TRY { - - // Loop until we find an Fcb we can't remove. - do { - - // If the reference count is non-zero then break. - - if (CurrentFcb->FcbReference != 0) { - - break; - } - - ParentFcb = CurrentFcb->ParentFcb; - - // acquire parent - if (ParentFcb != NULL) { - - UDFAcquireFcbExclusive(IrpContext, ParentFcb, FALSE); - } - - // acquire current file/dir - // we must assure that no more threads try to re-use this object - #ifdef UDF_DBG - _SEH2_TRY { - #endif // UDF_DBG - UDFAcquireResourceExclusive(&CurrentFcb->FcbNonpaged->FcbResource,TRUE); - #ifdef UDF_DBG - } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { - BrutePoint(); - if (ParentFcb) { - UDFReleaseResource(&ParentFcb->FcbNonpaged->FcbResource); - } - break; - } _SEH2_END; - #endif // UDF_DBG - ASSERT((CurrentFcb->FcbReference > CurrentFcb->FileInfo->RefCount) || !TreeLength); - // If we haven't pass through all files opened - // in UDFCommonCreate before target file (TreeLength specfies - // the number of such files) dereference them. - // Otherwise we'll just check if the file has no references. - #ifdef UDF_DBG - if (CurrentFcb) { - if (TreeLength) { - ASSERT(CurrentFcb->FcbReference); - RefCount = InterlockedDecrement((PLONG)&CurrentFcb->FcbReference); - } - } else { - BrutePoint(); - } - if (TreeLength) - TreeLength--; - ASSERT(CurrentFcb->FcbCleanup <= CurrentFcb->FcbReference); - #else - if (TreeLength) { - RefCount = InterlockedDecrement((PLONG)&CurrentFcb->FcbReference); - TreeLength--; - } - #endif - - // ...and delete if it has gone - - if (!RefCount && !CurrentFcb->FcbCleanup) { - - // no more references... current file/dir MUST DIE!!! - if (Delete) { - /* if (!(Fcb->FCBFlags & UDF_FCB_DIRECTORY)) { - // set file size to zero (for UdfInfo package) - // we should not do this for directories - UDFResizeFile__(Vcb, fi, 0); - }*/ - UDFReferenceFile__(CurrentFcb->FileInfo); - ASSERT(CurrentFcb->FcbReference < CurrentFcb->FileInfo->RefCount); - UDFFlushFile__(IrpContext, Vcb, CurrentFcb->FileInfo); - UDFUnlinkFile__(IrpContext, Vcb, CurrentFcb->FileInfo, TRUE); - UDFCloseFile__(IrpContext, Vcb, CurrentFcb->FileInfo); - ASSERT(CurrentFcb->FcbReference == CurrentFcb->FileInfo->RefCount); - CurrentFcb->FcbState |= UDF_FCB_DELETED; - Delete = FALSE; - } - else if (!(CurrentFcb->FcbState & UDF_FCB_DELETED)) { - UDFFlushFile__(IrpContext, Vcb, CurrentFcb->FileInfo); - } else { - // BrutePoint(); - } - - // check if we should try to delete Parent for the next time - if (CurrentFcb->FcbState & UDF_FCB_DELETE_PARENT) - Delete = TRUE; - - // remove references to OS-specific structures - // to let UDF_INFO release FI & Co - CurrentFcb->FileInfo->Fcb = NULL; - CurrentFcb->FileInfo->Dloc->CommonFcb = NULL; - - if (UDFCleanUpFile__(Vcb, CurrentFcb->FileInfo) == (UDF_FREE_FILEINFO | UDF_FREE_DLOC)) { - // Check, if we can uninitialize & deallocate CommonFcb part - // kill some cross links - // release allocated resources - // Obviously, it is a good time & place to release - // CommonFcb structure - - // NtReqFcb->NtReqFCBFlags &= ~UDF_NTREQ_FCB_VALID; - // Unitialize byte-range locks support structure - if (CurrentFcb->FileLock != NULL) { - - FsRtlFreeFileLock(CurrentFcb->FileLock); - } - - FsRtlTeardownPerStreamContexts(&CurrentFcb->Header); - - // Remove resources - UDF_CHECK_PAGING_IO_RESOURCE(CurrentFcb); - UDFReleaseResource(&CurrentFcb->FcbNonpaged->FcbResource); - if (CurrentFcb->Header.Resource) { - UDFDeleteResource(&CurrentFcb->FcbNonpaged->FcbResource); - UDFDeleteResource(&CurrentFcb->FcbNonpaged->FcbPagingIoResource); - } - - CurrentFcb->Header.Resource = - CurrentFcb->Header.PagingIoResource = NULL; - - UDFPrint(("UDFRelease Fcb: %x\n", CurrentFcb)); - - // remove some references & free Fcb structure - CurrentFcb->ParentFcb = NULL; - UDFCleanUpFCB(CurrentFcb); - MyFreePool__(CurrentFcb->FileInfo); - CurrentFcb->FileInfo = NULL; - - // get pointer to parent FCB - CurrentFcb = ParentFcb; - // free old parent's resource... - if (CurrentFcb) { - UDFReleaseResource(&ParentFcb->FcbNonpaged->FcbResource); - } - } else { - // Stop cleaning up - - // Restore pointers - CurrentFcb->FileInfo->Fcb = CurrentFcb; - CurrentFcb->FileInfo->Dloc->CommonFcb = CurrentFcb; - // free all acquired resources - UDF_CHECK_PAGING_IO_RESOURCE(CurrentFcb); - UDFReleaseResource(&CurrentFcb->FcbNonpaged->FcbResource); - CurrentFcb = ParentFcb; - if (CurrentFcb) { - UDF_CHECK_PAGING_IO_RESOURCE(ParentFcb); - UDFReleaseResource(&ParentFcb->FcbNonpaged->FcbResource); - } - // If we have dereferenced all parents 'associated' - // with input file & current file is still in use - // then it isn't worth walking down the tree - // 'cause in this case all the rest files are also used - if (!TreeLength) - break; - // AdPrint(("Stop on referenced File/Dir\n")); - } - } else { - // we get to referenced file/dir. Stop search & release resource - - UDFReleaseResource(&CurrentFcb->FcbNonpaged->FcbResource); - if (ParentFcb) { - - UDFReleaseResource(&ParentFcb->FcbNonpaged->FcbResource); - } - Delete = FALSE; - if (!TreeLength) - break; - CurrentFcb = ParentFcb; - } - - } while (CurrentFcb != NULL); - - } _SEH2_FINALLY { - - } _SEH2_END; - - if (RemovedStartingFcb) { - *RemovedStartingFcb = (CurrentFcb != StartingFcb); - } - -} // end UDFCleanUpFcbChain() - PIRP_CONTEXT UDFRemoveClose( _In_opt_ PVCB Vcb @@ -620,7 +409,6 @@ Return Value: // Copy RealDevice for workque algorithms. - IrpContext->TreeLength = IrpContextLite->TreeLength; IrpContext->RealDevice = IrpContextLite->RealDevice; // The Vcb is found in the Fcb. @@ -722,8 +510,9 @@ Return Value: // Call our teardown routine to see if this object can go away. // If we don't remove the Fcb then release it. + // LCB-based teardown: walks ParentLcbQueue to find and remove LCBs - UDFTeardownStructures(IrpContext, Fcb, IrpContext->TreeLength, &RemovedFcb); + UDFTeardownStructures(IrpContext, Fcb, FALSE, &RemovedFcb); if (!RemovedFcb) { @@ -990,7 +779,6 @@ UDFQueueClose( IrpContextLite->NodeIdentifier.NodeTypeCode = UDF_NODE_TYPE_IRP_CONTEXT_LITE; IrpContextLite->NodeIdentifier.NodeByteSize = sizeof(IRP_CONTEXT_LITE); IrpContextLite->Fcb = Fcb; - IrpContextLite->TreeLength = IrpContext->TreeLength; IrpContextLite->UserReference = UserReference; IrpContextLite->RealDevice = IrpContext->RealDevice; diff --git a/drivers/filesystems/udfs/create.cpp b/drivers/filesystems/udfs/create.cpp index a72893b61512f..27d68fb7a8b14 100644 --- a/drivers/filesystems/udfs/create.cpp +++ b/drivers/filesystems/udfs/create.cpp @@ -41,54 +41,132 @@ UDFNormalizeFileNames( _Inout_ PUNICODE_STRING RemainingName ); -/* - */ -VOID -__fastcall -UDFReleaseResFromCreate( - IN PERESOURCE* PagingIoRes, - IN PERESOURCE* Res1, - IN PERESOURCE* Res2 +NTSTATUS +UDFSupersedeOrOverwriteFile( + IN PIRP_CONTEXT IrpContext, + IN PFILE_OBJECT FileObject, + IN PVCB Vcb, + IN PFCB Fcb, + IN PUDF_FILE_INFO FileInfo, + IN LONGLONG AllocationSize, + IN ULONG FileAttributes, + IN BOOLEAN Supersede ) { - if (*PagingIoRes) { - UDFReleaseResource(*PagingIoRes); - (*PagingIoRes) = NULL; - } - if (*Res1) { - UDFReleaseResource(*Res1); - (*Res1) = NULL; - } - if (*Res2) { - UDFReleaseResource(*Res2); - (*Res2) = NULL; - } -} // end UDFReleaseResFromCreate() + NTSTATUS RC; + ULONG NewFileAttributes; -/* - */ -VOID -__fastcall -UDFAcquireParent( - IN PUDF_FILE_INFO RelatedFileInfo, - IN PERESOURCE* Res1, - IN PERESOURCE* Res2 + UDFAcquirePagingIoExclusive(IrpContext, Fcb); + + _SEH2_TRY { + + if (!MmCanFileBeTruncated(&Fcb->FcbNonpaged->SegmentObject, &UdfData.UDFLargeZero)) { + + AdPrint((" Can't truncate. File is mapped\n")); + try_return(RC = STATUS_USER_MAPPED_FILE); + } + + // Truncate file to zero + RC = UDFResizeFile__(IrpContext, Vcb, FileInfo, 0); + + if (!NT_SUCCESS(RC)) { + + AdPrint((" Error during resize operation\n")); + try_return(RC); + } + + // Set file sizes + Fcb->Header.AllocationSize.QuadPart = UDFSysGetAllocSize(Vcb, AllocationSize); + Fcb->Header.FileSize.QuadPart = 0; + Fcb->Header.ValidDataLength.QuadPart = 0; + Fcb->FcbState &= ~UDF_FCB_DELAY_CLOSE; + + MmPrint((" CcSetFileSizes()\n")); + CcSetFileSizes(FileObject, (PCC_FILE_SIZES)&Fcb->Header.AllocationSize); + Fcb->NtReqFCBFlags |= UDF_NTREQ_FCB_MODIFIED; + + // Set attributes + NewFileAttributes = FileAttributes | FILE_ATTRIBUTE_ARCHIVE; + if (!Supersede) { + // For Overwrite, combine with current attributes (get from FileInfo) + NewFileAttributes |= UDFAttributesToNT( + UDFDirIndex(UDFGetDirIndexByFileInfo(FileInfo), FileInfo->Index), + FileInfo->Dloc->FileEntry); + } + UDFAttributesToUDF(UDFDirIndex(UDFGetDirIndexByFileInfo(FileInfo), FileInfo->Index), + FileInfo->Dloc->FileEntry, NewFileAttributes); + +try_exit: NOTHING; + + } _SEH2_FINALLY { + + UDFReleasePagingIo(IrpContext, Fcb); + } _SEH2_END; + + return RC; +} // end UDFSupersedeOrOverwriteFile() + + +/************************************************************************* +* +* Function: UDFOpenExistingFcb() +* +* Description: +* Open an existing FCB. Determines the type of open, sets CCB flags, +* and calls UDFCompleteFcbOpen. +* +* Opens an existing FCB with proper type detection. +* +* Expected Interrupt Level (for execution) : +* +* IRQL_PASSIVE_LEVEL +* +* Return Value: STATUS_SUCCESS/Error +* +*************************************************************************/ +NTSTATUS +UDFOpenExistingFcb( + IN PIRP_CONTEXT IrpContext, + IN PIO_STACK_LOCATION IrpSp, + IN PVCB Vcb, + IN OUT PFCB *CurrentFcb, + IN BOOLEAN IgnoreCase, + IN BOOLEAN OpenByFileId, + IN ULONG CreateDisposition ) { - if (RelatedFileInfo->Fcb && - RelatedFileInfo->Fcb->ParentFcb) { + ULONG CcbFlags = 0; + TYPE_OF_OPEN TypeOfOpen; + + ASSERT_FCB(*CurrentFcb); - UDF_CHECK_PAGING_IO_RESOURCE(RelatedFileInfo->Fcb->ParentFcb); - UDFAcquireResourceExclusive((*Res2) = &RelatedFileInfo->Fcb->ParentFcb->FcbNonpaged->FcbResource, TRUE); + // Determine type of open based on FCB type + if (UDFIsADirectory((*CurrentFcb)->FileInfo)) { + TypeOfOpen = UserDirectoryOpen; + } else { + TypeOfOpen = UserFileOpen; + } + + // Set CCB flags + if (IgnoreCase) { + SetFlag(CcbFlags, CCB_FLAG_IGNORE_CASE); } - UDF_CHECK_PAGING_IO_RESOURCE(RelatedFileInfo->Fcb); - UDFAcquireResourceExclusive((*Res1) = &RelatedFileInfo->Fcb->FcbNonpaged->FcbResource, TRUE); + if (OpenByFileId) { + SetFlag(CcbFlags, CCB_FLAG_OPEN_BY_ID); + } + + // Complete the open + return UDFCompleteFcbOpen(IrpContext, + IrpSp, + Vcb, + CurrentFcb, + TypeOfOpen, + CcbFlags, + CreateDisposition); + +} // end UDFOpenExistingFcb() - InterlockedIncrement((PLONG)&RelatedFileInfo->Fcb->FcbReference); - UDFReferenceFile__(RelatedFileInfo); - ASSERT(RelatedFileInfo->Fcb->FcbReference >= RelatedFileInfo->RefCount); -} // end UDFAcquireParent() /************************************************************************* * @@ -128,9 +206,10 @@ UDFCommonCreate( PVCB Vcb = NULL; BOOLEAN OpenExisting = FALSE; - PERESOURCE Res1 = NULL; - PERESOURCE Res2 = NULL; - PERESOURCE PagingIoRes = NULL; + // Hold two locks during tree traversal (child + parent) + // CurrentFcb = current node lock, PreviousFcb = parent node lock (released after operations) + PFCB CurrentFcb = NULL; + PFCB PreviousFcb = NULL; BOOLEAN DeleteOnClose; BOOLEAN OpenByFileId; @@ -173,16 +252,17 @@ UDFCommonCreate( PUDF_FILE_INFO NewFileInfo = NULL; PUDF_FILE_INFO LastGoodFileInfo = NULL; PWCHAR TmpBuffer; - ULONG TreeLength = 0; BOOLEAN VolumeOpen = FALSE; BOOLEAN StreamOpen = FALSE; BOOLEAN StreamTargetOpen = FALSE; BOOLEAN StreamExists = FALSE; BOOLEAN RestoreShareAccess = FALSE; + BOOLEAN SkipPathTraversal = FALSE; PWCHAR TailNameBuffer = NULL; ULONG SNameIndex = 0; DECLARE_CONST_UNICODE_STRING(StreamSuffix, L":$DATA"); + DIR_ENUM_CONTEXT DirContext; PAGED_CODE(); @@ -545,33 +625,31 @@ UDFCommonCreate( RC = UDFCompleteFcbOpen(IrpContext, IrpSp, Vcb, &PtrNewFcb, UserVolumeOpen, 0, CreateDisposition); - if (!NT_SUCCESS(RC)) - goto op_vol_accs_dnd; - - PtrNewCcb = UDFDecodeFileObjectCcb(FileObject); + if (NT_SUCCESS(RC)) { + PtrNewCcb = UDFDecodeFileObjectCcb(FileObject); - // Check _Security_ - RC = UDFCheckAccessRights(NULL, AccessState, Vcb->RootIndexFcb, PtrNewCcb, DesiredAccess, ShareAccess); - if (!NT_SUCCESS(RC)) { - AdPrint((" Access violation (Volume)\n")); - goto op_vol_accs_dnd; - } - // Check _ShareAccess_ - RC = UDFCheckAccessRights(FileObject, AccessState, PtrNewFcb, PtrNewCcb, DesiredAccess, ShareAccess); - if (!NT_SUCCESS(RC)) { - AdPrint((" Sharing violation (Volume)\n")); -op_vol_accs_dnd: - if (UndoLock) { - Vcb->VcbState &= ~VCB_STATE_LOCKED; - Vcb->VolumeLockFileObject = NULL; + // Check _Security_ + RC = UDFCheckAccessRights(NULL, AccessState, Vcb->RootIndexFcb, PtrNewCcb, DesiredAccess, ShareAccess); + if (NT_SUCCESS(RC)) { + // Check _ShareAccess_ + RC = UDFCheckAccessRights(FileObject, AccessState, PtrNewFcb, PtrNewCcb, DesiredAccess, ShareAccess); + if (NT_SUCCESS(RC)) { + Options |= FILE_NO_INTERMEDIATE_BUFFERING; + ReturnedInformation = FILE_OPENED; + try_return(RC); + } else { + AdPrint((" Sharing violation (Volume)\n")); + } + } else { + AdPrint((" Access violation (Volume)\n")); } - try_return(RC); } - Options |= FILE_NO_INTERMEDIATE_BUFFERING; - - ReturnedInformation = FILE_OPENED; - + // Error cleanup + if (UndoLock) { + Vcb->VcbState &= ~VCB_STATE_LOCKED; + Vcb->VolumeLockFileObject = NULL; + } try_return(RC); } @@ -798,10 +876,9 @@ UDFCommonCreate( PtrNewFcb = Vcb->RootIndexFcb; RC = UDFCompleteFcbOpen(IrpContext, IrpSp, Vcb, &PtrNewFcb, UserDirectoryOpen, 0, CreateDisposition); if (!NT_SUCCESS(RC)) try_return(RC); -// DbgPrint("UDF: Open/Create RootDir : ReferenceCount %x\n",PtrNewFcb->ReferenceCount); + // Reference root's FileInfo (root has no parent, so no LCB) UDFReferenceFile__(PtrNewFcb->FileInfo); PtrNewCcb = UDFDecodeFileObjectCcb(FileObject); - TreeLength = 1; RC = UDFCheckAccessRights(FileObject, AccessState, PtrNewFcb, PtrNewCcb, DesiredAccess, ShareAccess); if (!NT_SUCCESS(RC)) { @@ -846,25 +923,30 @@ UDFCommonCreate( RelatedFileInfo = OldRelatedFileInfo = RelatedFileInfo->ParentFile; NextFcb = NextFcb->ParentFcb; - // prevent releasing parent structures - UDFAcquireParent(RelatedFileInfo, &Res1, &Res2); - TreeLength++; + // Parent references are now handled by LCB in UDFCompleteFcbOpen - if (Res1) UDFReleaseResource(Res1); - if (Res2) UDFReleaseResource(Res2); - - UDF_CHECK_PAGING_IO_RESOURCE(RelatedFileInfo->Fcb); - UDFAcquireResourceExclusive(Res2 = &RelatedFileInfo->Fcb->FcbNonpaged->FcbResource, TRUE); + // Acquire FCB lock for tree traversal + // Skip if same FCB to avoid recursive acquire leading to lock leak PtrNewFcb = NewFileInfo->Fcb; + if (PtrNewFcb != CurrentFcb) { + UDF_CHECK_PAGING_IO_RESOURCE(PtrNewFcb); + UDFAcquireFcbExclusive(IrpContext, PtrNewFcb, FALSE); + // Release grandparent lock from previous iteration + if (PreviousFcb && PreviousFcb != CurrentFcb) { + UDFReleaseResource(&PreviousFcb->FcbNonpaged->FcbResource); + } + PreviousFcb = CurrentFcb; + CurrentFcb = PtrNewFcb; + } - UDF_CHECK_PAGING_IO_RESOURCE(PtrNewFcb); - UDFAcquireResourceExclusive(Res1 = &PtrNewFcb->FcbNonpaged->FcbResource, TRUE); + // Reference target file's FileInfo (balanced by cleanup) UDFReferenceFile__(NewFileInfo); - TreeLength++; - goto AlreadyOpened; + SkipPathTraversal = TRUE; } + if (!SkipPathTraversal) { + //AdPrint((" Opening file %ws %8.8x\n",AbsolutePathName.Buffer, PtrNewFileObject)); if (AbsolutePathName.Length > UDF_X_PATH_LEN*sizeof(WCHAR)) { @@ -925,8 +1007,13 @@ UDFCommonCreate( LastGoodName.Length = 0; LastGoodFileInfo = RelatedFileInfo; // reference RelatedObject to prevent releasing parent structures - UDFAcquireParent(RelatedFileInfo, &Res1, &Res2); - TreeLength++; + // Acquire only CurrentFcb (= LastGoodFileInfo->Fcb) + CurrentFcb = RelatedFileInfo->Fcb; + UDF_CHECK_PAGING_IO_RESOURCE(CurrentFcb); + UDFAcquireFcbExclusive(IrpContext, CurrentFcb, FALSE); + + // Parent references are now handled by LCB in UDFCompleteFcbOpen + // when child files are opened through this directory. // go into a loop parsing the supplied name @@ -984,11 +1071,11 @@ UDFCommonCreate( try_return(RC); } - ASSERT(RelatedFileInfo->Fcb->FcbReference >= RelatedFileInfo->RefCount); + // Note: FcbReference may be 0 for intermediate directories during path traversal; + // it will be incremented when CCB is created in UDFCompleteFcbOpen - if (RelatedFileInfo && (TreeLength>1)) { - // it was an internal Open operation. Thus, assume - // RelatedFileInfo's Fcb to be valid + // Mark intermediate directory FCB as valid (internal open) + if (RelatedFileInfo && RelatedFileInfo->ParentFile) { RelatedFileInfo->Fcb->NtReqFCBFlags |= UDF_NTREQ_FCB_VALID; RelatedFileInfo->Fcb->FcbState |= UDF_FCB_VALID; } @@ -997,100 +1084,97 @@ UDFCommonCreate( AdPrint((" Path component is too long\n")); try_return(RC = STATUS_OBJECT_NAME_INVALID); } - // ...and now release previously acquired objects, - if (Res1) UDFReleaseResource(Res1); - if (Res2) { - UDFReleaseResource(Res2); - Res2 = NULL; + // Acquire FCB lock for tree traversal + // Skip if same FCB to avoid recursive acquire leading to lock leak + { + PFCB NewFcb = RelatedFileInfo->Fcb; + if (NewFcb != CurrentFcb) { + UDF_CHECK_PAGING_IO_RESOURCE(NewFcb); + UDFAcquireFcbExclusive(IrpContext, NewFcb, FALSE); + if (PreviousFcb && PreviousFcb != CurrentFcb) { + UDFReleaseResource(&PreviousFcb->FcbNonpaged->FcbResource); + } + PreviousFcb = CurrentFcb; + CurrentFcb = NewFcb; + } } - // acquire new _parent_ directory & try to open what - // we want. - UDF_CHECK_PAGING_IO_RESOURCE(RelatedFileInfo->Fcb); - UDFAcquireResourceExclusive(Res1 = &RelatedFileInfo->Fcb->FcbNonpaged->FcbResource, TRUE); - - // check traverse rights + // check traverse rights (uses RelatedFileInfo->Fcb which is now locked as PreviousFcb) RC = UDFCheckAccessRights(NULL, NULL, RelatedFileInfo->Fcb, RelatedCcb, FILE_TRAVERSE, 0); if (!NT_SUCCESS(RC)) { NewFileInfo = NULL; AdPrint((" Traverse check failed\n")); - goto Skip_open_attempt; - } - // check if we should open normal File/Dir or SDir - if (CurName.Buffer[0] != ':') { - // standard open, nothing interesting.... - RC = UDFOpenFile__(IrpContext, - Vcb, - IgnoreCase,TRUE,&CurName, - RelatedFileInfo,&NewFileInfo,NULL); - if (RC == STATUS_FILE_DELETED) { - // file has gone, but system still remembers it... - NewFileInfo = NULL; - AdPrint((" File deleted\n")); - RC = STATUS_ACCESS_DENIED; + } else if (CurName.Buffer[0] != ':') { + // standard open: first find, then open + RC = UDFFindDirEntry(Vcb, RelatedFileInfo, &CurName, IgnoreCase, TRUE, &DirContext); + if (NT_SUCCESS(RC)) { + // Check if intermediate path component is a directory + if (TailName.Length && + !(DirContext.DirNdx->FileCharacteristics & FILE_DIRECTORY)) { + AdPrint((" Not a directory\n")); + RC = STATUS_NOT_A_DIRECTORY; + } else { + RC = UDFOpenObjectFromDirContext(IrpContext, Vcb, &DirContext, TRUE, &NewFileInfo); + if (RC == STATUS_FILE_DELETED) { + // file has gone, but system still remembers it... + NewFileInfo = NULL; + AdPrint((" File deleted\n")); + RC = STATUS_ACCESS_DENIED; + } else + if (RC == STATUS_SHARING_PAUSED) { + AdPrint((" Dloc is being initialized\n")); + BrutePoint(); + RC = STATUS_SHARING_VIOLATION; + } + } + } #ifdef UDF_DBG - } else - if (RC == STATUS_NOT_A_DIRECTORY) { + else if (RC == STATUS_NOT_A_DIRECTORY) { AdPrint((" Not a directory\n")); -#endif // UDF_DBG - } else - if (RC == STATUS_SHARING_PAUSED) { - AdPrint((" Dloc is being initialized\n")); - BrutePoint(); - RC = STATUS_SHARING_VIOLATION; } +#endif // UDF_DBG } else { - // And here we should open Stream Dir (if any, of cource) + // And here we should open Stream Dir (if any, of course) RC = UDFOpenStreamDir__(IrpContext, Vcb, RelatedFileInfo, &NewFileInfo); if (NT_SUCCESS(RC)) { -SuccessOpen_SDir: // this indicates that we needn't Stream Dir creation StreamExists = TRUE; StreamName.Buffer++; - StreamName.Length-=sizeof(WCHAR); + StreamName.Length -= sizeof(WCHAR); // update TailName TailName = StreamName; } else if (RC == STATUS_NOT_FOUND) { - // Stream Dir doesn't exist, but caller wants it to be // created. Lets try to help him... if ((CreateDisposition == FILE_CREATE) || (CreateDisposition == FILE_OPEN_IF) || (CreateDisposition == FILE_OVERWRITE_IF) || - OpenTargetDirectory ) { + OpenTargetDirectory) { RC = UDFCreateStreamDir__(IrpContext, Vcb, RelatedFileInfo, &NewFileInfo); - if (NT_SUCCESS(RC)) - goto SuccessOpen_SDir; + if (NT_SUCCESS(RC)) { + StreamExists = TRUE; + StreamName.Buffer++; + StreamName.Length -= sizeof(WCHAR); + TailName = StreamName; + } } } -/* } else { - AdPrint((" File deleted (2)\n")); - RC = STATUS_ACCESS_DENIED;*/ } -Skip_open_attempt: - // check if we have successfully opened path component if (NT_SUCCESS(RC)) { - // Yesss !!! + // Get or create FCB for the opened FileInfo if (!(PtrNewFcb = NewFileInfo->Fcb)) { - // It is a first open operation - // Allocate new FCB - // Here we set FileObject pointer to NULL to avoid - // new CCB allocation - RC = UDFFirstOpenFile(IrpContext, - IrpSp, - Vcb, + // First open - create FCB + RC = UDFFirstOpenFile(IrpContext, IrpSp, Vcb, NULL, &PtrNewFcb, RelatedFileInfo, NewFileInfo, &LocalPath, &CurName, CreateDisposition); - if (!NT_SUCCESS(RC)) { BrutePoint(); AdPrint((" Can't perform FirstOpen\n")); UDFCloseFile__(IrpContext, Vcb, NewFileInfo); - if (PtrNewFcb) UDFCleanUpFCB(PtrNewFcb); - PtrNewFcb = NULL; + if (PtrNewFcb) UDFDeleteFcb(IrpContext, PtrNewFcb); NewFileInfo->Fcb = NULL; if (UDFCleanUpFile__(Vcb, NewFileInfo)) { MyFreePool__(NewFileInfo); @@ -1099,14 +1183,11 @@ UDFCommonCreate( try_return(RC); } } else { - // It is not a first open operation - // Validate Fcb. It is possible to get - // not completly initialized Fcb here. + // Validate existing FCB if (!(PtrNewFcb->FcbState & UDF_FCB_VALID)) { BrutePoint(); AdPrint((" Fcb not valid\n")); UDFCloseFile__(IrpContext, Vcb, NewFileInfo); - PtrNewFcb = NULL; if (UDFCleanUpFile__(Vcb, NewFileInfo)) { MyFreePool__(NewFileInfo); NewFileInfo = NULL; @@ -1114,23 +1195,54 @@ UDFCommonCreate( try_return(RC = STATUS_ACCESS_DENIED); } } - // Acquire newly opened File... - Res2 = Res1; - UDF_CHECK_PAGING_IO_RESOURCE(NewFileInfo->Fcb); - UDFAcquireResourceExclusive(Res1 = &NewFileInfo->Fcb->FcbNonpaged->FcbResource, TRUE); - // ...and reference it - InterlockedIncrement((PLONG)&PtrNewFcb->FcbReference); - - ASSERT(PtrNewFcb->FcbReference >= NewFileInfo->RefCount); - // update unwind information + + // Acquire FCB lock for tree traversal (try-lock to prevent deadlock) + { + PFCB NewFcb = NewFileInfo->Fcb; + if (NewFcb != CurrentFcb) { + UDF_CHECK_PAGING_IO_RESOURCE(NewFcb); + if (!UDFAcquireFcbExclusive(IrpContext, NewFcb, TRUE)) { + // Try-lock failed - rollback and reacquire in order + UDFLockVcb(IrpContext, Vcb); + NewFcb->FcbCleanup++; + UDFUnlockVcb(IrpContext, Vcb); + + if (PreviousFcb && PreviousFcb != CurrentFcb) { + UDFReleaseResource(&PreviousFcb->FcbNonpaged->FcbResource); + } + PFCB OldCurrentFcb = CurrentFcb; + UDF_CHECK_PAGING_IO_RESOURCE(OldCurrentFcb); + UDFReleaseResource(&OldCurrentFcb->FcbNonpaged->FcbResource); + + UDFAcquireFcbExclusive(IrpContext, NewFcb, FALSE); + UDFAcquireFcbExclusive(IrpContext, OldCurrentFcb, FALSE); + PreviousFcb = OldCurrentFcb; + + UDFLockVcb(IrpContext, Vcb); + NewFcb->FcbCleanup--; + UDFUnlockVcb(IrpContext, Vcb); + } else { + if (PreviousFcb && PreviousFcb != CurrentFcb) { + UDFReleaseResource(&PreviousFcb->FcbNonpaged->FcbResource); + } + PreviousFcb = CurrentFcb; + } + CurrentFcb = NewFcb; + } + } + + // FCB references are handled by LCB in UDFCompleteFcbOpen + // Note: FcbReference may be 0 here during path traversal; + // it will be incremented when CCB is created + + // Update state LastGoodFileInfo = NewFileInfo; LastGoodName = CurName; - TreeLength++; - // update current path + + // Update current path if (!StreamOpen || ((CurName.Buffer[0] != L':') && (!LocalPath.Length || (LocalPath.Buffer[LocalPath.Length/sizeof(WCHAR)-1] != L':'))) ) { - // we should not insert '\' before or after ':' ASSERT(!LocalPath.Length || (LocalPath.Buffer[LocalPath.Length/2-1] != L'\\')); RC = MyAppendUnicodeToString(&LocalPath, L"\\"); @@ -1139,7 +1251,6 @@ UDFCommonCreate( RC = MyAppendUnicodeStringToStringTag(&LocalPath, &CurName, MEM_USLOC_TAG); if (!NT_SUCCESS(RC)) try_return(RC); -// DbgPrint("UDF: Open/Create File %ws : ReferenceCount %x\n",CurName.Buffer,PtrNewFcb->ReferenceCount); } else { AdPrint((" Can't open file\n")); // We have failed durring last Open attempt @@ -1148,11 +1259,11 @@ UDFCommonCreate( // Cleanup FileInfo if any if (NewFileInfo) { PtrNewFcb = NewFileInfo->Fcb; - // acquire appropriate resource if possible + // Temporarily acquire NewFcb for cleanup, + // but keep CurrentFcb unchanged (= LastGoodFileInfo->Fcb) if (PtrNewFcb) { - Res2 = Res1; UDF_CHECK_PAGING_IO_RESOURCE(PtrNewFcb); - UDFAcquireResourceExclusive(Res1 = &PtrNewFcb->FcbNonpaged->FcbResource, TRUE); + UDFAcquireFcbExclusive(IrpContext, PtrNewFcb, FALSE); } // cleanup pointer to Fcb in FileInfo to allow // UDF_INFO package release FileInfo if there are @@ -1175,7 +1286,7 @@ UDFCommonCreate( ASSERT(!PtrNewFcb); if (PtrNewFcb) { BrutePoint(); - UDFCleanUpFCB(PtrNewFcb); + UDFDeleteFcb(IrpContext, PtrNewFcb); } MyFreePool__(NewFileInfo); } else { @@ -1186,6 +1297,10 @@ UDFCommonCreate( if (PtrNewFcb) NewFileInfo->Dloc->CommonFcb = PtrNewFcb; } + // Release NewFcb lock after cleanup + if (PtrNewFcb) { + UDFReleaseResource(&PtrNewFcb->FcbNonpaged->FcbResource); + } // forget about last FileInfo & Fcb, // further unwind staff needs only last good // structures @@ -1227,8 +1342,8 @@ UDFCommonCreate( // ... and exit with error try_return(RC); } - // discard changes for last successfully opened file - InterlockedDecrement((PLONG)&PtrNewFcb->FcbReference); + // Note: With LCB model, FcbReference is not incremented during path traversal, + // so no decrement is needed here (removed the old InterlockedDecrement). RC = STATUS_SUCCESS; ASSERT(!OpenTargetDirectory); // break open loop and continue with Open @@ -1292,18 +1407,18 @@ UDFCommonCreate( // to reflect the fact that the parent directory of the // target has been opened PtrNewFcb = NewFileInfo->Fcb; - InterlockedDecrement((PLONG)&PtrNewFcb->FcbReference); + // Note: Removed FcbReference decrement - no longer needed with LCB model. + // The old TreeLength model incremented parent FcbReference during path traversal, + // but LCB model handles parent references differently (via UDFAcquirePrefix). RC = UDFCompleteFcbOpen(IrpContext, IrpSp, Vcb, &PtrNewFcb, UserDirectoryOpen, 0, CreateDisposition); - - ASSERT(PtrNewFcb->FcbReference >= NewFileInfo->RefCount); if (!NT_SUCCESS(RC)) { AdPrint((" Can't perform OpenFile operation for target\n")); try_return(RC); } PtrNewCcb = UDFDecodeFileObjectCcb(FileObject); - ASSERT(Res1); + ASSERT(CurrentFcb); RC = UDFCheckAccessRights(FileObject, AccessState, PtrNewFcb, PtrNewCcb, DesiredAccess, ShareAccess); if (!NT_SUCCESS(RC)) { AdPrint((" Access/Share access check failed (Open Target)\n")); @@ -1367,7 +1482,7 @@ UDFCommonCreate( try_return(RC = STATUS_INVALID_PARAMETER); } // check access rights - ASSERT(Res1); + ASSERT(CurrentFcb); RC = UDFCheckAccessRights(NULL, NULL, OldRelatedFileInfo->Fcb, RelatedCcb, DirectoryFile ? FILE_ADD_SUBDIRECTORY : FILE_ADD_FILE, 0); if (!NT_SUCCESS(RC)) { AdPrint((" Creation of File/Dir not permitted\n")); @@ -1385,30 +1500,6 @@ UDFCommonCreate( (CreateDisposition == FILE_CREATE), RelatedFileInfo, &NewFileInfo); if (!NT_SUCCESS(RC)) { AdPrint((" Creation error\n")); -Creation_Err_1: - if (NewFileInfo) { - PtrNewFcb = NewFileInfo->Fcb; - ASSERT(!PtrNewFcb); - if (PtrNewFcb && - !PtrNewFcb->FcbReference && - !PtrNewFcb->FcbCleanup) { - NewFileInfo->Fcb = NULL; - } - if (NewFileInfo->Dloc && - !NewFileInfo->Dloc->LinkRefCount) { - NewFileInfo->Dloc->CommonFcb = NULL; - } - if (UDFCleanUpFile__(Vcb, NewFileInfo)) { - if (PtrNewFcb) { - BrutePoint(); - UDFCleanUpFCB(PtrNewFcb); - } - MyFreePool__(NewFileInfo); - } else { - NewFileInfo->Fcb = PtrNewFcb; - } - PtrNewFcb = NULL; - } try_return(RC); } // Update parent object @@ -1423,8 +1514,8 @@ UDFCommonCreate( // user wants the directory to be created RC = UDFRecordDirectory__(IrpContext, Vcb, NewFileInfo); if (!NT_SUCCESS(RC)) { - AdPrint((" Can't transform to directory\n")); -Undo_Create_1: + AdPrint((" Can't transform to directory\n")); + // Undo create - flush and unlink from disk if ((RC != STATUS_FILE_IS_A_DIRECTORY) && (RC != STATUS_NOT_A_DIRECTORY) && (RC != STATUS_ACCESS_DENIED)) { @@ -1432,16 +1523,8 @@ UDFCommonCreate( UDFUnlinkFile__(IrpContext, Vcb, NewFileInfo, TRUE); } UDFCloseFile__(IrpContext, Vcb, NewFileInfo); - BrutePoint(); - goto Creation_Err_1; + try_return(RC); } - - } else if (AllocationSize) { - // set initial file size -/* if (!NT_SUCCESS(RC = UDFResizeFile__(Vcb, NewFileInfo, AllocationSize))) { - AdPrint((" Can't set initial file size\n")); - goto Undo_Create_1; - };*/ } if (StreamOpen && !StreamExists) { @@ -1462,25 +1545,42 @@ UDFCommonCreate( if (!NT_SUCCESS(RC)) { AdPrint((" Can't perform FirstOpenFile operation for file to contain stream\n")); BrutePoint(); - UDFCleanUpFCB(NewFileInfo->Fcb); + if (PtrNewFcb) { + UDFDeleteFcb(IrpContext, PtrNewFcb); + PtrNewFcb = NULL; + } NewFileInfo->Fcb = NULL; - goto Creation_Err_1; + try_return(RC); } } else { BrutePoint(); } - // Update unwind information - TreeLength++; + // Update state + // FCB references are now handled by LCB in UDFCompleteFcbOpen LastGoodFileInfo = NewFileInfo; + // Acquire FCB lock for tree traversal + // Skip if same FCB to avoid recursive acquire leading to lock leak + { + PFCB NewFcb = NewFileInfo->Fcb; + if (NewFcb != CurrentFcb) { + UDF_CHECK_PAGING_IO_RESOURCE(NewFcb); + UDFAcquireFcbExclusive(IrpContext, NewFcb, FALSE); + if (PreviousFcb && PreviousFcb != CurrentFcb) { + UDFReleaseResource(&PreviousFcb->FcbNonpaged->FcbResource); + } + PreviousFcb = CurrentFcb; + CurrentFcb = NewFcb; + } + } // update FCB tree RC = MyAppendUnicodeToString(&LocalPath, L"\\"); if (!NT_SUCCESS(RC)) try_return(RC); RC = MyAppendUnicodeStringToStringTag(&LocalPath, &LastGoodTail, MEM_USLOC_TAG); - if (!NT_SUCCESS(RC)) - goto Creation_Err_1; - InterlockedIncrement((PLONG)&PtrNewFcb->FcbReference); - ASSERT(PtrNewFcb->FcbReference >= NewFileInfo->RefCount); + if (!NT_SUCCESS(RC)) { + try_return(RC); + } + // Note: FcbReference will be set when CCB is created in UDFCompleteFcbOpen PtrNewFcb->NtReqFCBFlags |= UDF_NTREQ_FCB_VALID; PtrNewFcb->FcbState |= UDF_FCB_VALID; @@ -1496,7 +1596,7 @@ UDFCommonCreate( if (!NT_SUCCESS(RC)) { AdPrint((" Can't create SDir\n")); BrutePoint(); - goto Creation_Err_1; + try_return(RC); } // normalize stream name @@ -1519,21 +1619,34 @@ UDFCommonCreate( if (!NT_SUCCESS(RC)) { AdPrint((" Can't perform OpenFile operation for SDir\n")); BrutePoint(); - goto Creation_Err_1; + try_return(RC); } - // Update unwind information - TreeLength++; + // Update state + // FCB references are now handled by LCB in UDFCompleteFcbOpen LastGoodFileInfo = NewFileInfo; + // Acquire FCB lock for tree traversal + // Skip if same FCB to avoid recursive acquire leading to lock leak + { + PFCB NewFcb = NewFileInfo->Fcb; + if (NewFcb != CurrentFcb) { + UDF_CHECK_PAGING_IO_RESOURCE(NewFcb); + UDFAcquireFcbExclusive(IrpContext, NewFcb, FALSE); + if (PreviousFcb && PreviousFcb != CurrentFcb) { + UDFReleaseResource(&PreviousFcb->FcbNonpaged->FcbResource); + } + PreviousFcb = CurrentFcb; + CurrentFcb = NewFcb; + } + } // update FCB tree RC = MyAppendUnicodeStringToStringTag(&LocalPath, &(UdfData.UnicodeStrSDir), MEM_USLOC_TAG); if (!NT_SUCCESS(RC)) { AdPrint((" Can't append UNC str\n")); BrutePoint(); - goto Creation_Err_1; + try_return(RC); } - InterlockedIncrement((PLONG)&PtrNewFcb->FcbReference); - ASSERT(PtrNewFcb->FcbReference >= NewFileInfo->RefCount); + // Note: FcbReference will be set when CCB is created in UDFCompleteFcbOpen PtrNewFcb->NtReqFCBFlags |= UDF_NTREQ_FCB_VALID; PtrNewFcb->FcbState |= UDF_FCB_VALID; @@ -1547,7 +1660,7 @@ UDFCommonCreate( if (!NT_SUCCESS(RC)) { AdPrint((" Can't create Stream\n")); BrutePoint(); - goto Creation_Err_1; + try_return(RC); } // Update unwind information @@ -1579,7 +1692,15 @@ UDFCommonCreate( if (!NT_SUCCESS(RC)) { AdPrint((" Can't perform OpenFile operation for file or stream\n")); BrutePoint(); - goto Undo_Create_1; + // Undo create - flush and unlink from disk + if ((RC != STATUS_FILE_IS_A_DIRECTORY) && + (RC != STATUS_NOT_A_DIRECTORY) && + (RC != STATUS_ACCESS_DENIED)) { + UDFFlushFile__(IrpContext, Vcb, NewFileInfo); + UDFUnlinkFile__(IrpContext, Vcb, NewFileInfo, TRUE); + } + UDFCloseFile__(IrpContext, Vcb, NewFileInfo); + try_return(RC); } PtrNewFcb->Header.FileSize.QuadPart = @@ -1596,9 +1717,23 @@ UDFCommonCreate( } } - // Update unwind information - TreeLength++; + // Update state + // FCB references are now handled by LCB in UDFCompleteFcbOpen LastGoodFileInfo = NewFileInfo; + // Acquire FCB lock for tree traversal + // Skip if same FCB to avoid recursive acquire leading to lock leak + { + PFCB NewFcb = NewFileInfo->Fcb; + if (NewFcb != CurrentFcb) { + UDF_CHECK_PAGING_IO_RESOURCE(NewFcb); + UDFAcquireFcbExclusive(IrpContext, NewFcb, FALSE); + if (PreviousFcb && PreviousFcb != CurrentFcb) { + UDFReleaseResource(&PreviousFcb->FcbNonpaged->FcbResource); + } + PreviousFcb = CurrentFcb; + CurrentFcb = NewFcb; + } + } // Set the Share Access for the file stream. // The FCBShareAccess field will be set by the I/O Manager. @@ -1608,8 +1743,10 @@ UDFCommonCreate( if (!NT_SUCCESS(RC)) { AdPrint((" Can't set Access Rights on Create\n")); BrutePoint(); + // Undo create - flush, unlink and close UDFFlushFile__(IrpContext, Vcb, NewFileInfo); UDFUnlinkFile__(IrpContext, Vcb, NewFileInfo, TRUE); + UDFCloseFile__(IrpContext, Vcb, NewFileInfo); try_return(RC); } @@ -1650,26 +1787,14 @@ UDFCommonCreate( try_return(RC); } -AlreadyOpened: + } // end if (!SkipPathTraversal) // **************** // we have always STATUS_SUCCESS here // **************** - ASSERT(NewFileInfo != OldRelatedFileInfo); - // A new CCB will be allocated. - // Assume that this structure named PtrNewCcb - - TYPE_OF_OPEN TypeOfOpen; - - if (UDFIsADirectory(PtrNewFcb->FileInfo)) { - TypeOfOpen = UserDirectoryOpen; - } else { - TypeOfOpen = UserFileOpen; - } - - RC = UDFCompleteFcbOpen(IrpContext, IrpSp, Vcb, &PtrNewFcb, TypeOfOpen, 0, DesiredAccess); + RC = UDFOpenExistingFcb(IrpContext, IrpSp, Vcb, &PtrNewFcb, IgnoreCase, OpenByFileId, CreateDisposition); if (!NT_SUCCESS(RC)) try_return(RC); PtrNewCcb = UDFDecodeFileObjectCcb(FileObject); @@ -1709,8 +1834,7 @@ UDFCommonCreate( } // Check share access and fail if the share conflicts with an existing // open. - ASSERT(Res1 != NULL); - ASSERT(Res2 != NULL); + ASSERT(CurrentFcb); RC = UDFCheckAccessRights(FileObject, AccessState, PtrNewFcb, PtrNewCcb, DesiredAccess, ShareAccess); if (!NT_SUCCESS(RC)) { AdPrint((" Access/Share access check failed\n")); @@ -1766,8 +1890,7 @@ UDFCommonCreate( if (DeleteOnClose && (TmpFileAttributes & FILE_ATTRIBUTE_READONLY)) { - ASSERT(Res1 != NULL); - ASSERT(Res2 != NULL); + ASSERT(CurrentFcb); RC = UDFCheckAccessRights(NULL, NULL, OldRelatedFileInfo->Fcb, RelatedCcb, FILE_DELETE_CHILD, 0); if (!NT_SUCCESS(RC)) { AdPrint((" Read-only. DeleteOnClose attempt failed\n")); @@ -1786,8 +1909,7 @@ UDFCommonCreate( if (CreateDisposition == FILE_SUPERSEDE) { BOOLEAN RestoreRO = FALSE; - ASSERT(Res1 != NULL); - ASSERT(Res2 != NULL); + ASSERT(CurrentFcb); // NT wants us to allow Supersede on RO files if (PtrNewFcb->FcbState & UDF_FCB_READ_ONLY) { // Imagine, that file is not RO and check other permissions @@ -1804,8 +1926,7 @@ UDFCommonCreate( try_return (RC); } } else { - ASSERT(Res1 != NULL); - ASSERT(Res2 != NULL); + ASSERT(CurrentFcb); RC = UDFCheckAccessRights(NULL, NULL, PtrNewFcb, PtrNewCcb, FILE_WRITE_DATA | FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES, 0); if (!NT_SUCCESS(RC)) { @@ -1820,58 +1941,24 @@ UDFCommonCreate( try_return(RC = STATUS_ACCESS_DENIED); } - // Before we actually truncate, check to see if the purge - // is going to fail. - MmPrint((" MmCanFileBeTruncated()\n")); - if (!MmCanFileBeTruncated(&PtrNewFcb->FcbNonpaged->SegmentObject, - &UdfData.UDFLargeZero)) { - AdPrint((" Can't truncate. File is mapped\n")); - try_return(RC = STATUS_USER_MAPPED_FILE); - } + ASSERT(CurrentFcb); - ASSERT(Res1 != NULL); - ASSERT(Res2 != NULL); - - // Synchronize with PagingIo - UDFAcquireResourceExclusive(PagingIoRes = &PtrNewFcb->FcbNonpaged->FcbPagingIoResource, TRUE); - // Set file sizes - if (!NT_SUCCESS(RC = UDFResizeFile__(IrpContext, Vcb, NewFileInfo, 0))) { - AdPrint((" Error during resize operation\n")); + // Truncate file and set attributes (acquires PagingIoResource internally, checks MmCanFileBeTruncated) + RC = UDFSupersedeOrOverwriteFile( + IrpContext, + FileObject, + Vcb, + PtrNewFcb, + NewFileInfo, + AllocationSize, + FileAttributes, + (BOOLEAN)(CreateDisposition == FILE_SUPERSEDE) + ); + if (!NT_SUCCESS(RC)) { try_return(RC); } -/* if (AllocationSize) { - if (!NT_SUCCESS(RC = UDFResizeFile__(Vcb, NewFileInfo, AllocationSize))) { - AdPrint((" Error during resize operation (2)\n")); - try_return(RC); - } - }*/ - PtrNewFcb->Header.AllocationSize.QuadPart = UDFSysGetAllocSize(Vcb, AllocationSize); - PtrNewFcb->Header.FileSize.QuadPart = - PtrNewFcb->Header.ValidDataLength.QuadPart = 0 /*AllocationSize*/; - PtrNewFcb->FcbState &= ~UDF_FCB_DELAY_CLOSE; - MmPrint((" CcSetFileSizes()\n")); - CcSetFileSizes(FileObject, (PCC_FILE_SIZES)&PtrNewFcb->Header.AllocationSize); - PtrNewFcb->NtReqFCBFlags |= UDF_NTREQ_FCB_MODIFIED; - // Release PagingIoResource - UDFReleaseResource(PagingIoRes); - PagingIoRes = NULL; - if (NT_SUCCESS(RC)) { - FileAttributes |= FILE_ATTRIBUTE_ARCHIVE; - if (CreateDisposition == FILE_SUPERSEDE) { - // Set attributes for the file ... - UDFAttributesToUDF(UDFDirIndex(UDFGetDirIndexByFileInfo(NewFileInfo), NewFileInfo->Index), - NewFileInfo->Dloc->FileEntry, FileAttributes); - ReturnedInformation = FILE_SUPERSEDED; - } else { - // Get attributes for the file ... - FileAttributes |= TmpFileAttributes; - // Set attributes for the file ... - UDFAttributesToUDF(UDFDirIndex(UDFGetDirIndexByFileInfo(NewFileInfo), NewFileInfo->Index), - NewFileInfo->Dloc->FileEntry, FileAttributes); - ReturnedInformation = FILE_OVERWRITTEN; - } - } + ReturnedInformation = (CreateDisposition == FILE_SUPERSEDE) ? FILE_SUPERSEDED : FILE_OVERWRITTEN; // notify changes UDFNotifyFullReportChange( Vcb, NewFileInfo->Fcb, FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_SIZE, @@ -1966,14 +2053,9 @@ try_exit: NOTHING; UDFUnlockVcb(IrpContext, Vcb); - - if (FileObject->Flags & FO_CACHE_SUPPORTED) - InterlockedIncrement((PLONG)&PtrNewFcb->CachedOpenHandleCount); // Store some flags in CCB if (PtrNewCcb) { - PtrNewCcb->TreeLength = TreeLength; // delete on close - if (DeleteOnClose) { ASSERT(!(PtrNewFcb->FcbState & UDF_FCB_ROOT_DIRECTORY)); PtrNewCcb->Flags |= UDF_CCB_DELETE_ON_CLOSE; @@ -1996,16 +2078,10 @@ try_exit: NOTHING; InterlockedIncrement((PLONG)&Vcb->VcbReference); PtrNewFcb->NtReqFCBFlags |= UDF_NTREQ_FCB_VALID; PtrNewFcb->FcbState |= UDF_FCB_VALID; -#ifdef UDF_DBG - // We have no FileInfo for Volume - if (PtrNewFcb->FileInfo) { - ASSERT(PtrNewFcb->FcbReference >= PtrNewFcb->FileInfo->RefCount); - } -#endif // UDF_DBG + // Note: With LCB model, FcbReference may not always be >= RefCount + // for intermediate files (e.g., parent of a stream) AdPrint((" FCB %x, CCB %x, FO %x, Flags %x\n", PtrNewFcb, PtrNewCcb, FileObject, PtrNewFcb->FcbState)); - UDFReleaseResFromCreate(&PagingIoRes, &Res1, &Res2); - } else if (!NT_SUCCESS(RC)) { // Perform failure related post-processing now if (RestoreShareAccess && PtrNewFcb && FileObject) { @@ -2027,30 +2103,76 @@ try_exit: NOTHING; LastGoodFileInfo->Fcb->NtReqFCBFlags |= UDF_NTREQ_FCB_VALID; } } - // Release resources... - UDFReleaseResFromCreate(&PagingIoRes, &Res1, &Res2); - // close the chain - UDFCloseFileInfoChain(IrpContext, Vcb, LastGoodFileInfo, TreeLength, TRUE); // cleanup FCBs (if any) + // Note: UDFTeardownStructures calls UDFCloseFile__ when CallCloseFile=TRUE + // (CloseFileInfoChain is NOT called in Create finally) + // Note: UDFTeardownStructures releases lock when FCB is removed + ASSERT(!LastGoodFileInfo || !LastGoodFileInfo->Fcb || CurrentFcb == LastGoodFileInfo->Fcb); if ( Vcb && (PtrNewFcb != Vcb->RootIndexFcb) && LastGoodFileInfo ) { - UDFTeardownStructures(IrpContext, LastGoodFileInfo->Fcb, TreeLength, NULL); + // + // LOCK LEAK FIX: + // TeardownStructures walks up the FCB tree and acquires parent locks. + // If we hold PreviousFcb (= CurrentFcb->ParentFcb), TeardownStructures will: + // - Recursively acquire it (OwnerCount: 1->2) + // - Process and release (OwnerCount: 2->1) + // Our original lock is still held (count=1). + // + // Old bug: Code set PreviousFcb=NULL when RemovedFcb=TRUE, leaking our lock. + // + // Fix: Protect PreviousFcb from deletion via FcbReference++. + // Using FcbReference (not FcbCleanup) because TeardownStructures + // may decrement parent FcbReferences via LCB removal. + // If we used FcbCleanup++, ASSERT(FcbCleanup <= FcbReference) would fail + // when FcbReference is decremented to 0 but FcbCleanup is still 1. + // After TeardownStructures, decrement FcbReference. + // Let finally block release our lock normally. + // DON'T set PreviousFcb=NULL! + // + BOOLEAN ProtectedPreviousFcb = FALSE; + if (PreviousFcb && PreviousFcb != CurrentFcb) { + UDFLockVcb(IrpContext, Vcb); + PreviousFcb->FcbReference++; + UDFUnlockVcb(IrpContext, Vcb); + ProtectedPreviousFcb = TRUE; + } + + BOOLEAN RemovedFcb = FALSE; + // LCB-based teardown: walks ParentLcbQueue to find and remove LCBs + UDFTeardownStructures(IrpContext, LastGoodFileInfo->Fcb, FALSE, &RemovedFcb); + // If FCB was removed, lock is already released by TeardownStructures + if (RemovedFcb) { + CurrentFcb = NULL; + } + + // Unprotect PreviousFcb + if (ProtectedPreviousFcb) { + UDFLockVcb(IrpContext, Vcb); + PreviousFcb->FcbReference--; + UDFUnlockVcb(IrpContext, Vcb); + } + // PreviousFcb lock will be released by finally block below } else { ASSERT(!LastGoodFileInfo); } - } else { - UDFReleaseResFromCreate(&PagingIoRes, &Res1, &Res2); } - // As long as this unwinding is not being performed as a result of - // an exception condition, complete the IRP ... - if (!_SEH2_AbnormalTermination()) { + } - Irp->IoStatus.Information = ReturnedInformation; + // Release parent lock first (PreviousFcb before CurrentFcb) + if (PreviousFcb && PreviousFcb != CurrentFcb) { + UDFReleaseResource(&PreviousFcb->FcbNonpaged->FcbResource); + } - UDFCompleteRequest(IrpContext, Irp, RC); - } - } else { - UDFReleaseResFromCreate(&PagingIoRes, &Res1, &Res2); + // Release current lock + if (CurrentFcb) { + UDFReleaseResource(&CurrentFcb->FcbNonpaged->FcbResource); + } + + if (RC != STATUS_PENDING && !_SEH2_AbnormalTermination()) { + + Irp->IoStatus.Information = ReturnedInformation; + + UDFCompleteRequest(IrpContext, Irp, RC); } // free allocated tmp buffers (if any) @@ -2211,6 +2333,11 @@ UDFFirstOpenFile( UDFUnlockVcb(IrpContext, Vcb); return RC; } + // Set embedded data flag if file data is stored in ICB + if (!UDFIsADirectory(NewFileInfo) && + (((PFILE_ENTRY)(NewFileInfo->Dloc->FileEntry))->icbTag.flags & ICB_FLAG_ALLOC_MASK) == ICB_FLAG_AD_IN_ICB) { + (*PtrNewFcb)->FcbState |= UDF_FCB_EMBEDDED_DATA; + } // set Read-only attribute if (!UDFIsAStreamDir(NewFileInfo)) { hDirIndex = UDFGetDirIndexByFileInfo(NewFileInfo); @@ -2254,6 +2381,14 @@ UDFFirstOpenFile( } } + // Insert FCB into table only on success (matching MS pattern where + // UdfInsertFcbTable is called at the END of initialization after + // everything succeeds). This ensures FCB is not in table if error + // occurs and UDFDeleteFcb is called from error path. + if (NT_SUCCESS(RC)) { + UDFInsertFcbIntoTable(IrpContext, *PtrNewFcb); + } + UDFUnlockVcb(IrpContext, Vcb); // end transaction @@ -2440,6 +2575,17 @@ UDFCompleteFcbOpen( // initialize the CCB to point to the file object Ccb->FileObject = IrpSp->FileObject; + // Acquire or create LCB to link parent directory FCB to this file FCB + // Skip for root directory (no parent) + // UDFAcquirePrefix will find existing LCB and increment Reference, + // or create new LCB and increment parent's FcbReference + if (Fcb->ParentFcb) { + Ccb->Lcb = UDFAcquirePrefix(IrpContext, + Fcb->ParentFcb, + Fcb, + Fcb->FileInfo ? Fcb->FileInfo->Index : 0); + } + // Set the file object type. UDFSetFileObject(IrpSp->FileObject, TypeOfOpen, Fcb, Ccb); @@ -2476,8 +2622,12 @@ try_exit: NOTHING; } _SEH2_FINALLY { if (Ccb) { - // TODO: fix NextCCB list - //UDFDeleteCcb(Ccb); + // CCB was allocated but create failed - clean up + if (Ccb->Lcb) { + UDFRemovePrefix(IrpContext, Ccb->Lcb); + Ccb->Lcb = NULL; + } + UDFReleaseCCB(Ccb); } } _SEH2_END; diff --git a/drivers/filesystems/udfs/dircntrl.cpp b/drivers/filesystems/udfs/dircntrl.cpp index 772b7a53a4446..bd46beecc851b 100644 --- a/drivers/filesystems/udfs/dircntrl.cpp +++ b/drivers/filesystems/udfs/dircntrl.cpp @@ -413,16 +413,21 @@ UDFQueryDirectory( DirInformation->FileIndex = NextMatch; FileNameBytes = DirInformation->FileNameLength; + // If this won't fit and we have returned a previous entry then just + // return STATUS_SUCCESS. + if ((BaseLength + FileNameBytes) > BytesRemainingInBuffer) { - // If this won't fit and we have returned a previous entry then just - // return STATUS_SUCCESS. Otherwise - // use a status code of STATUS_BUFFER_OVERFLOW. - if (CurrentOffset) { + + // If we already found an entry then just exit. + + if (CurrentOffset != 0) { try_return(RC = STATUS_SUCCESS); } - // strange policy... + + // Reduce the FileNameBytes to just fit in the buffer. + + FileNameBytes = BytesRemainingInBuffer - BaseLength; ReturnSingleEntry = TRUE; - FileNameBytes = BaseLength + FileNameBytes - BytesRemainingInBuffer; RC = STATUS_BUFFER_OVERFLOW; } // Now we have an entry to return to our caller. diff --git a/drivers/filesystems/udfs/fastio.cpp b/drivers/filesystems/udfs/fastio.cpp index 3709db14a7745..31b3bfac4c051 100644 --- a/drivers/filesystems/udfs/fastio.cpp +++ b/drivers/filesystems/udfs/fastio.cpp @@ -399,12 +399,17 @@ BOOLEAN NTAPI UDFAcqLazyWrite( MmPrint((" UDFAcqLazyWrite()\n")); - // Acquire the MainResource in the NT_REQ_FCB exclusively. Then, set the - // lazy-writer thread id in the NT_REQ_FCB structure for identification - // when an actual write request is received by the FSD. + // Acquire the MainResource in the NT_REQ_FCB. For embedded data files + // (data stored in ICB), acquire exclusively since data shares sector with + // metadata. For normal files, acquire shared to allow concurrent access. // Note: The lazy-writer typically always supplies WAIT set to TRUE. - if (!UDFAcquireResourceExclusive(&Fcb->FcbNonpaged->FcbResource, Wait)) - return FALSE; + if (Fcb->FcbState & UDF_FCB_EMBEDDED_DATA) { + if (!UDFAcquireResourceExclusive(&Fcb->FcbNonpaged->FcbResource, Wait)) + return FALSE; + } else { + if (!UDFAcquireResourceShared(&Fcb->FcbNonpaged->FcbResource, Wait)) + return FALSE; + } // Now, set the lazy-writer thread id. ASSERT(!(Fcb->LazyWriteThread)); @@ -869,14 +874,10 @@ UDFFastIoAcqModWrite( OUT PERESOURCE *ResourceToRelease, IN PDEVICE_OBJECT DeviceObject) { - NTSTATUS RC = STATUS_SUCCESS; - - FsRtlEnterFileSystem(); - - MmPrint((" AcqModW %I64x\n", EndingOffset->QuadPart)); - PFCB Fcb = (PFCB)FileObject->FsContext; + *ResourceToRelease = NULL; + // We must determine which resource(s) we would like to // acquire at this time. We know that a write is imminent; // we will probably therefore acquire appropriate resources @@ -897,63 +898,23 @@ UDFFastIoAcqModWrite( // the resource that we acquired (single return value). This pointer // will be returned back to we in the release call (below). - if (UDFAcquireResourceShared(&Fcb->FcbNonpaged->FcbPagingIoResource, FALSE)) { - - if (EndingOffset->QuadPart <= Fcb->Header.ValidDataLength.QuadPart) { - - UDFReleaseResource(&Fcb->FcbNonpaged->FcbPagingIoResource); - RC = STATUS_CANT_WAIT; - } else { - - *ResourceToRelease = &Fcb->FcbNonpaged->FcbPagingIoResource; - MmPrint((" AcqModW OK\n")); - } - + // For embedded data files, acquire exclusive since data shares sector with metadata + // For normal files, shared is enough + BOOLEAN Acquired; + if (Fcb->FcbState & UDF_FCB_EMBEDDED_DATA) { + Acquired = UDFAcquireResourceExclusive(&Fcb->FcbNonpaged->FcbResource, FALSE); } else { - RC = STATUS_CANT_WAIT; + Acquired = UDFAcquireResourceShared(&Fcb->FcbNonpaged->FcbResource, FALSE); } - return RC; -} // end UDFFastIoAcqModWrite() - - -/************************************************************************* -* -* Function: UDFFastIoRelModWrite() -* -* Description: -* Not really a fast-io operation. Used by the VMM to release FSD resources -* after processing a modified page/block write operation. -* -* Expected Interrupt Level (for execution) : -* -* IRQL_PASSIVE_LEVEL -* -* Return Value: STATUS_SUCCESS/Error (an error returned here is really not expected!) -* -*************************************************************************/ -NTSTATUS -NTAPI -UDFFastIoRelModWrite( - IN PFILE_OBJECT FileObject, - IN PERESOURCE ResourceToRelease, - IN PDEVICE_OBJECT DeviceObject) -{ - MmPrint((" RelModW\n")); - - PFCB Fcb = (PFCB)FileObject->FsContext; - - // The MPW has complete the write for modified pages and therefore - // wants us to release pre-acquired resource(s). - - // We must undo here whatever it is that we did in the - // UDFFastIoAcqModWrite() call above. + if (!Acquired) { + return STATUS_CANT_WAIT; + } - ASSERT(ResourceToRelease == &Fcb->FcbNonpaged->FcbPagingIoResource); - UDFReleaseResource(ResourceToRelease); + *ResourceToRelease = &Fcb->FcbNonpaged->FcbResource; - return(STATUS_SUCCESS); -} // end UDFFastIoRelModWrite() + return STATUS_SUCCESS; +} // end UDFFastIoAcqModWrite() /************************************************************************* @@ -999,8 +960,13 @@ UDFFastIoAcqCcFlush( PFCB Fcb = (PFCB)FileObject->FsContext; - UDFAcquireResourceExclusive(&Fcb->FcbNonpaged->FcbResource, TRUE); - UDFAcquireResourceShared(&Fcb->FcbNonpaged->FcbPagingIoResource, TRUE); + // For embedded data files, acquire exclusive since data shares sector with metadata + // For normal files, shared is enough + if (Fcb->FcbState & UDF_FCB_EMBEDDED_DATA) { + UDFAcquireResourceExclusive(&Fcb->FcbNonpaged->FcbResource, TRUE); + } else { + UDFAcquireResourceShared(&Fcb->FcbNonpaged->FcbResource, TRUE); + } return STATUS_SUCCESS; @@ -1036,10 +1002,9 @@ UDFFastIoRelCcFlush( IoSetTopLevelIrp(NULL); } - // Release resources acquired in UDFFastIoAcqCcFlush() above. + // Release resource acquired in UDFFastIoAcqCcFlush() above. PFCB Fcb = (PFCB)FileObject->FsContext; - UDFReleaseResource(&Fcb->FcbNonpaged->FcbPagingIoResource); UDFReleaseResource(&Fcb->FcbNonpaged->FcbResource); return STATUS_SUCCESS; diff --git a/drivers/filesystems/udfs/fileinfo.cpp b/drivers/filesystems/udfs/fileinfo.cpp index d527a8902ac7c..82fe4faf266ef 100644 --- a/drivers/filesystems/udfs/fileinfo.cpp +++ b/drivers/filesystems/udfs/fileinfo.cpp @@ -311,7 +311,15 @@ UDFCommonSetInfo( if ((FunctionalityRequested != FilePositionInformation) && (FunctionalityRequested != FileRenameInformation) && (FunctionalityRequested != FileLinkInformation)) { - // Acquire the Parent & Main Resources exclusive. + // Child-first lock ordering + // Acquire Main (child) resource first + if (!UDFAcquireResourceExclusive(&Fcb->FcbNonpaged->FcbResource, CanWait)) { + PostRequest = TRUE; + try_return(Status = STATUS_PENDING); + } + MainResourceAcquired = TRUE; + + // Acquire Parent resource second if (Fcb->FileInfo->ParentFile) { UDF_CHECK_PAGING_IO_RESOURCE(Fcb->ParentFcb); if (!UDFAcquireResourceExclusive(&Fcb->ParentFcb->FcbNonpaged->FcbResource, CanWait)) { @@ -321,12 +329,6 @@ UDFCommonSetInfo( ParentResourceAcquired = TRUE; } - if (!UDFAcquireResourceExclusive(&Fcb->FcbNonpaged->FcbResource, CanWait)) { - PostRequest = TRUE; - try_return(Status = STATUS_PENDING); - } - MainResourceAcquired = TRUE; - if (!UDFAcquireResourceExclusive(&Fcb->FcbNonpaged->FcbPagingIoResource, CanWait)) { PostRequest = TRUE; try_return(Status = STATUS_PENDING); @@ -426,22 +428,23 @@ try_exit: NOTHING; } _SEH2_FINALLY { + // Release in reverse order of acquisition if (PagingIoResourceAcquired) { UDFReleaseResource(&Fcb->FcbNonpaged->FcbPagingIoResource); PagingIoResourceAcquired = FALSE; } - if (MainResourceAcquired) { - UDFReleaseResource(&Fcb->FcbNonpaged->FcbResource); - MainResourceAcquired = FALSE; - } - if (ParentResourceAcquired) { UDF_CHECK_PAGING_IO_RESOURCE(Fcb->ParentFcb); UDFReleaseResource(&(Fcb->ParentFcb->FcbNonpaged->FcbResource)); ParentResourceAcquired = FALSE; } + if (MainResourceAcquired) { + UDFReleaseResource(&Fcb->FcbNonpaged->FcbResource); + MainResourceAcquired = FALSE; + } + if (VcbAcquired) { UDFReleaseVcb(IrpContext, Vcb); @@ -1908,7 +1911,7 @@ UDFPrepareForRenameMoveLink( // There is a pair of objects among input dirs & // one of them is a parent of another. Sequential resource // acquisition may lead to deadlock due to concurrent - // CleanUpFcbChain() or UDFCloseFileInfoChain() + // cleanup operations or UDFTeardownStructures() InterlockedIncrement((PLONG)&Vcb->VcbReference); @@ -1920,13 +1923,15 @@ UDFPrepareForRenameMoveLink( } else { InterlockedDecrement((PLONG)&Vcb->VcbReference); - UDF_CHECK_PAGING_IO_RESOURCE(Dir1->Fcb); - UDFAcquireResourceExclusive(&Dir1->Fcb->FcbNonpaged->FcbResource, TRUE); - (*AcquiredDir1) = TRUE; - + // Child-first lock ordering + // File1 (child) first, Dir1 (parent) second UDF_CHECK_PAGING_IO_RESOURCE(File1->Fcb); UDFAcquireResourceExclusive(&File1->Fcb->FcbNonpaged->FcbResource, TRUE); (*AcquiredFcb1) = TRUE; + + UDF_CHECK_PAGING_IO_RESOURCE(Dir1->Fcb); + UDFAcquireResourceExclusive(&Dir1->Fcb->FcbNonpaged->FcbResource, TRUE); + (*AcquiredDir1) = TRUE; } return STATUS_SUCCESS; } // end UDFPrepareForRenameMoveLink() @@ -1958,19 +1963,16 @@ UDFSetRenameInfo( BOOLEAN TargetParentFcbAcquired = FALSE; BOOLEAN SingleDir = TRUE; BOOLEAN UseClose; + BOOLEAN IsStreamRename; PUDF_FILE_INFO FileInfo; PUDF_FILE_INFO DirInfo; PUDF_FILE_INFO TargetDirInfo; - PUDF_FILE_INFO NextFileInfo, fi; UNICODE_STRING NewName; UNICODE_STRING LocalPath; PCCB CurCcb = NULL; PLIST_ENTRY Link; - ULONG i; - ULONG DirRefCount; - ULONG FileInfoRefCount; ULONG Attr; PDIR_INDEX_ITEM DirNdx; @@ -2005,6 +2007,8 @@ UDFSetRenameInfo( if (!TargetFileObject) { TargetDirInfo = FileInfo->ParentFile; + // For streams or same-dir rename, target FCB is the parent + TargetFcb = TargetDirInfo->Fcb; } else { @@ -2087,6 +2091,13 @@ UDFSetRenameInfo( IgnoreCase = FlagOn(Ccb->Flags, CCB_FLAG_IGNORE_CASE); + // Check if renaming to stream name - only allowed for streams + if (!TargetFileObject && NewName.Length >= sizeof(WCHAR) && NewName.Buffer[0] == L':') { + if (!UDFIsAStream(FileInfo)) { + try_return(RC = STATUS_OBJECT_NAME_INVALID); + } + } + if (UDFIsDirOpened__(FileInfo)) { // We can't rename file because of unclean references. // UDF_INFO package can safely do it, but NT side cannot. @@ -2106,9 +2117,8 @@ UDFSetRenameInfo( } } - ASSERT(Fcb->FcbReference >= FileInfo->RefCount); - ASSERT(DirInfo->Fcb->FcbReference >= DirInfo->RefCount); - ASSERT(TargetDirInfo->Fcb->FcbReference >= TargetDirInfo->RefCount); + // Note: With LCB model, FcbReference may not always be >= RefCount + // for directories opened internally during path traversal RC = UDFRenameMoveFile__(IrpContext, Vcb, IgnoreCase, &ReplaceIfExists, &NewName, DirInfo, TargetDirInfo, FileInfo); } @@ -2123,7 +2133,9 @@ UDFSetRenameInfo( if (!NT_SUCCESS(RC)) try_return (RC); // RC = MyAppendUnicodeStringToString(&LocalPath, (Dir2->Fcb->FCBFlags & UDF_FCB_ROOT_DIRECTORY) ? &(UDFGlobalData.UnicodeStrRoot) : &(Dir2->Fcb->FCBName->ObjectName)); // if (!NT_SUCCESS(RC)) try_return (RC); - if (TargetDirInfo->ParentFile) { + // Don't append '\\' for streams (names starting with ':') + IsStreamRename = (NewName.Length >= sizeof(WCHAR) && NewName.Buffer[0] == L':'); + if (TargetDirInfo->ParentFile && !IsStreamRename) { RC = MyAppendUnicodeToString(&LocalPath, L"\\"); if (!NT_SUCCESS(RC)) try_return (RC); } @@ -2203,71 +2215,51 @@ UDFSetRenameInfo( } } - // this will prevent structutre release before call to - // UDFCleanUpFcbChain() + // this will prevent structure release before cleanup InterlockedIncrement((PLONG)&DirInfo->Fcb->FcbReference); - ASSERT(DirInfo->Fcb->FcbReference >= DirInfo->RefCount); - // Look through Ccb list & decrement OpenHandleCounter(s) - // acquire CcbList + // Switch LCBs from old parent to new parent for each CCB + // With LCB model, each CCB has one LCB linking to its immediate parent. + // When renaming across directories, we release the old LCB and acquire + // a new one from the target directory. if (!SingleDir) { UDFAcquireResourceExclusive(&Fcb->FcbNonpaged->CcbListResource, TRUE); Link = Fcb->NextCCB.Flink; - DirRefCount = 0; - FileInfoRefCount = 0; ASSERT(Link != &Fcb->NextCCB); while (Link != &Fcb->NextCCB) { - NextFileInfo = DirInfo; CurCcb = CONTAINING_RECORD(Link, CCB, NextCCB); - ASSERT(CurCcb->TreeLength); - i = (CurCcb->TreeLength) ? (CurCcb->TreeLength - 1) : 0; Link = Link->Flink; UseClose = (CurCcb->Flags & UDF_CCB_CLEANED) ? FALSE : TRUE; - AdPrint((" Ccb:%x:%s:i:%x\n", CurCcb, UseClose ? "Close" : "",i)); - // cleanup old parent chain - for(; i && NextFileInfo; i--) { - // remember parent file now - // it will prevent us from data losses - // due to eventual structure release - fi = NextFileInfo->ParentFile; - if (UseClose) { - ASSERT(NextFileInfo->Fcb->FcbReference >= NextFileInfo->RefCount); - UDFCloseFile__(IrpContext, Vcb, NextFileInfo); - } - ASSERT(NextFileInfo->Fcb->FcbReference > NextFileInfo->RefCount); - ASSERT(NextFileInfo->Fcb->FcbReference); - InterlockedDecrement((PLONG)&NextFileInfo->Fcb->FcbReference); - ASSERT(NextFileInfo->Fcb->FcbReference >= NextFileInfo->RefCount); - NextFileInfo = fi; + AdPrint((" Ccb:%x:%s\n", CurCcb, UseClose ? "Close" : "")); + + // + // Release old LCB and acquire new one from TargetDir + // UDFReleasePrefixImmediate will decrement old parent's refs + // when the last CCB releases (LCB->Reference becomes 0). + // UDFAcquirePrefix will increment new parent's refs when + // creating a new LCB (or just increment LCB->Reference if exists). + // + if (CurCcb->Lcb) { + UDFReleasePrefixImmediate(IrpContext, CurCcb->Lcb, UseClose); + CurCcb->Lcb = NULL; } - if (CurCcb->TreeLength > 1) { - DirRefCount++; - if (UseClose) - FileInfoRefCount++; - CurCcb->TreeLength = 2; -#ifdef UDF_DBG - } else { - BrutePoint(); -#endif // UDF_DBG + // Acquire new LCB from TargetDir + CurCcb->Lcb = UDFAcquirePrefix(IrpContext, TargetDirInfo->Fcb, Fcb, + FileInfo->Index); + if (!CurCcb->Lcb) { + // Allocation failure - continue, but log error + AdPrint((" Failed to allocate LCB for CCB %x\n", CurCcb)); } } UDFReleaseResource(&Fcb->FcbNonpaged->CcbListResource); - ASSERT(DirRefCount >= FileInfoRefCount); - // update counters & pointers + // Update parent pointer Fcb->ParentFcb = TargetDirInfo->Fcb; - // move references to TargetDir - InterlockedExchangeAdd((PLONG)&TargetDirInfo->Fcb->FcbReference, DirRefCount); - ASSERT(TargetDirInfo->Fcb->FcbReference > TargetDirInfo->RefCount); - UDFReferenceFileEx__(TargetDirInfo, FileInfoRefCount); - ASSERT(TargetDirInfo->Fcb->FcbReference >= TargetDirInfo->RefCount); } - ASSERT(TargetDirInfo->Fcb->FcbReference >= TargetDirInfo->RefCount); ASSERT(TargetDirInfo->RefCount); - ASSERT(DirInfo->Fcb->FcbReference >= DirInfo->RefCount); // Modify name in Fcb1 if (Fcb->FCBName) { if (Fcb->FCBName->ObjectName.Buffer) { @@ -2290,7 +2282,15 @@ UDFSetRenameInfo( UDFReleaseResource(&DirInfo->Fcb->FcbNonpaged->FcbResource); ParentFcbAcquired = FALSE; } - UDFTeardownStructures(IrpContext, DirInfo->Fcb, 1, NULL); + { + BOOLEAN RemovedFcb = FALSE; + UDFAcquireFcbExclusive(IrpContext, DirInfo->Fcb, FALSE); + // LCB-based teardown: walks ParentLcbQueue to find and remove LCBs + UDFTeardownStructures(IrpContext, DirInfo->Fcb, FALSE, &RemovedFcb); + if (!RemovedFcb) { + UDFReleaseFcb(IrpContext, DirInfo->Fcb); + } + } try_return(RC = STATUS_INSUFFICIENT_RESOURCES); } @@ -2302,7 +2302,9 @@ UDFSetRenameInfo( goto insuf_res;*/ // if Dir2 is a RootDir, we shoud not append '\\' because // uit will be the 2nd '\\' character (RootDir's name is also '\\') - if (TargetDirInfo->ParentFile) { + // Also don't append '\\' for streams (names starting with ':') + // IsStreamRename already set above + if (TargetDirInfo->ParentFile && !IsStreamRename) { RC = MyAppendUnicodeToString(&Fcb->FCBName->ObjectName, L"\\"); if (!NT_SUCCESS(RC)) goto insuf_res; @@ -2311,10 +2313,6 @@ UDFSetRenameInfo( if (!NT_SUCCESS(RC)) goto insuf_res; - ASSERT(Fcb->FcbReference >= FileInfo->RefCount); - ASSERT(DirInfo->Fcb->FcbReference >= DirInfo->RefCount); - ASSERT(TargetDirInfo->Fcb->FcbReference >= TargetDirInfo->RefCount); - RC = STATUS_SUCCESS; try_exit: NOTHING; @@ -2332,10 +2330,13 @@ try_exit: NOTHING; // perform protected structure release if (NT_SUCCESS(RC) && (RC != STATUS_PENDING)) { - - UDFTeardownStructures(IrpContext, DirInfo->Fcb, 1, NULL); - ASSERT(Fcb->FcbReference >= FileInfo->RefCount); - ASSERT(TargetDirInfo->Fcb->FcbReference >= TargetDirInfo->RefCount); + BOOLEAN RemovedFcb = FALSE; + UDFAcquireFcbExclusive(IrpContext, DirInfo->Fcb, FALSE); + // LCB-based teardown: walks ParentLcbQueue to find and remove LCBs + UDFTeardownStructures(IrpContext, DirInfo->Fcb, FALSE, &RemovedFcb); + if (!RemovedFcb) { + UDFReleaseFcb(IrpContext, DirInfo->Fcb); + } } if (LocalPath.Buffer) { @@ -2641,14 +2642,15 @@ try_exit: NOTHING; } _SEH2_FINALLY { - if (AcquiredFcb1) { - UDF_CHECK_PAGING_IO_RESOURCE(Fcb1); - UDFReleaseResource(&Fcb1->FcbNonpaged->FcbResource); - } + // Release in reverse order of acquisition (parent first, then child) if (AcquiredDir1) { UDF_CHECK_PAGING_IO_RESOURCE(Dir1->Fcb); UDFReleaseResource(&Dir1->Fcb->FcbNonpaged->FcbResource); } + if (AcquiredFcb1) { + UDF_CHECK_PAGING_IO_RESOURCE(Fcb1); + UDFReleaseResource(&Fcb1->FcbNonpaged->FcbResource); + } if (LocalPath.Buffer) { MyFreePool__(LocalPath.Buffer); diff --git a/drivers/filesystems/udfs/flush.cpp b/drivers/filesystems/udfs/flush.cpp index 76357b7eef143..56ab64c51c051 100644 --- a/drivers/filesystems/udfs/flush.cpp +++ b/drivers/filesystems/udfs/flush.cpp @@ -139,16 +139,18 @@ UDFCommonFlush( Vcb = Fcb->Vcb; ASSERT(Vcb); + // Child-first lock ordering + UDF_CHECK_PAGING_IO_RESOURCE(Fcb); + UDFAcquireResourceExclusive(&Fcb->FcbNonpaged->FcbResource, TRUE); + AcquiredFCB = TRUE; + + // Parent second (needed for DirIndex modification in UDFSetFileSizeInDirNdx) if (Fcb->FileInfo->ParentFile && Fcb->FileInfo->ParentFile->Fcb) { UDF_CHECK_PAGING_IO_RESOURCE(Fcb->FileInfo->ParentFile->Fcb); UDFAcquireResourceExclusive(&Fcb->FileInfo->ParentFile->Fcb->FcbNonpaged->FcbResource, TRUE); AcquiredParentFcb = TRUE; } - UDF_CHECK_PAGING_IO_RESOURCE(Fcb); - UDFAcquireResourceExclusive(&Fcb->FcbNonpaged->FcbResource, TRUE); - AcquiredFCB = TRUE; - // Request the Cache Manager to perform a flush operation. // Further, instruct the Cache Manager that we wish to flush the // entire file stream. @@ -168,18 +170,19 @@ try_exit: NOTHING; } _SEH2_FINALLY { - if (AcquiredFCB) { - UDF_CHECK_PAGING_IO_RESOURCE(Fcb); - UDFReleaseResource(&Fcb->FcbNonpaged->FcbResource); - AcquiredFCB = FALSE; - } - + // Release in reverse order of acquisition (parent first, then child) if (AcquiredParentFcb) { UDF_CHECK_PAGING_IO_RESOURCE(Fcb->FileInfo->ParentFile->Fcb); UDFReleaseResource(&Fcb->FileInfo->ParentFile->Fcb->FcbNonpaged->FcbResource); AcquiredParentFcb = FALSE; } + if (AcquiredFCB) { + UDF_CHECK_PAGING_IO_RESOURCE(Fcb); + UDFReleaseResource(&Fcb->FcbNonpaged->FcbResource); + AcquiredFCB = FALSE; + } + if (AcquiredVCB) { UDFReleaseResource(&Vcb->VcbResource); AcquiredVCB = FALSE; diff --git a/drivers/filesystems/udfs/fscntrl.cpp b/drivers/filesystems/udfs/fscntrl.cpp index c86050d2029d2..61b864ee94ada 100644 --- a/drivers/filesystems/udfs/fscntrl.cpp +++ b/drivers/filesystems/udfs/fscntrl.cpp @@ -184,7 +184,7 @@ UDFUserFsCtrlRequest( case FSCTL_GET_RETRIEVAL_POINTERS: UDFPrint(("UDFUserFsCtrlRequest: FSCTL_GET_RETRIEVAL_POINTERS\n")); - RC = UDFGetRetrievalPointers(IrpContext, Irp, 0); + RC = UDFGetRetrievalPointers(IrpContext, Irp); break; case FSCTL_MOVE_FILE: @@ -639,7 +639,15 @@ UDFCloseResidual( UDFCloseFile__(IrpContext, Vcb, Vcb->RootIndexFcb->FileInfo); if (Vcb->RootIndexFcb->FcbCleanup) Vcb->RootIndexFcb->FcbCleanup--; - UDFTeardownStructures(IrpContext, Vcb->RootIndexFcb, 1, NULL); + { + BOOLEAN RemovedFcb = FALSE; + UDFAcquireFcbExclusive(IrpContext, Vcb->RootIndexFcb, FALSE); + // LCB-based teardown: walks ParentLcbQueue to find and remove LCBs + UDFTeardownStructures(IrpContext, Vcb->RootIndexFcb, FALSE, &RemovedFcb); + if (!RemovedFcb) { + UDFReleaseFcb(IrpContext, Vcb->RootIndexFcb); + } + } // Remove root FCB reference in vcb if (Vcb->VcbReference) InterlockedDecrement((PLONG)&Vcb->VcbReference); @@ -1247,104 +1255,122 @@ UDFGetVolumeBitmap( IN PIRP Irp ) { -// NTSTATUS RC; + NTSTATUS Status = STATUS_SUCCESS; PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); - UDFPrint(("UDFGetVolumeBitmap\n")); - - TYPE_OF_OPEN TypeOfOpen; PFCB Fcb; PCCB Ccb; - PVCB Vcb; + PVCB Vcb = IrpContext->Vcb; ULONG BytesToCopy; ULONG TotalClusters; - ULONG DesiredClusters; ULONG StartingCluster; + ULONG DesiredClusters; ULONG InputBufferLength; ULONG OutputBufferLength; LARGE_INTEGER StartingLcn; PVOLUME_BITMAP_BUFFER OutputBuffer; ULONG i, lim; PULONG FSBM; -// PULONG Dest; + BOOLEAN VcbAcquired = FALSE; - // Decode the file object, the only type of opens we accept are - // user volume opens. + ASSERT_VCB(Vcb); - TypeOfOpen = UDFDecodeFileObject(IrpSp->FileObject, &Fcb, &Ccb); + // Make this a synchronous IRP because we need access to the input buffer and + // this Irp is marked METHOD_NEITHER. - ASSERT_CCB(Ccb); - ASSERT_FCB(Fcb); + SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); - if (!Ccb) { + InputBufferLength = IrpSp->Parameters.FileSystemControl.InputBufferLength; + OutputBufferLength = IrpSp->Parameters.FileSystemControl.OutputBufferLength; - UDFPrintErr((" !Ccb\n")); - UDFCompleteRequest(IrpContext, Irp, STATUS_INVALID_PARAMETER); - return STATUS_INVALID_PARAMETER; - } + TotalClusters = Vcb->FSBM_BitCount; - Vcb = Fcb->Vcb; - ASSERT_FCB(Fcb); + _SEH2_TRY { - InputBufferLength = IrpSp->Parameters.FileSystemControl.InputBufferLength; - OutputBufferLength = IrpSp->Parameters.FileSystemControl.OutputBufferLength; + // Decode the file object, the only type of opens we accept are + // user volume opens. - OutputBuffer = (PVOLUME_BITMAP_BUFFER)UDFMapUserBuffer(Irp); + if (UDFDecodeFileObject(IrpSp->FileObject, &Fcb, &Ccb) != UserVolumeOpen) { - if (!OutputBuffer) { + try_return(Status = STATUS_INVALID_USER_BUFFER); + } - UDFCompleteRequest(IrpContext, Irp, STATUS_INVALID_USER_BUFFER); - return STATUS_INVALID_USER_BUFFER; - } + ASSERT_CCB(Ccb); + ASSERT_FCB(Fcb); - // Check for a minimum length on the input and output buffers. - if ((InputBufferLength < sizeof(STARTING_LCN_INPUT_BUFFER)) || - (OutputBufferLength < sizeof(VOLUME_BITMAP_BUFFER))) { + // Check for a minimum length on the input and output buffers. - UDFUnlockCallersBuffer(IrpContext, Irp, OutputBuffer); + if ((InputBufferLength < sizeof(STARTING_LCN_INPUT_BUFFER)) || + (OutputBufferLength < sizeof(VOLUME_BITMAP_BUFFER))) { - UDFCompleteRequest(IrpContext, Irp, STATUS_BUFFER_TOO_SMALL); - return STATUS_BUFFER_TOO_SMALL; - } + try_return(Status = STATUS_BUFFER_TOO_SMALL); + } - // Check if a starting cluster was specified. - TotalClusters = Vcb->FSBM_BitCount; - StartingLcn = ((PSTARTING_LCN_INPUT_BUFFER)IrpSp->Parameters.FileSystemControl.Type3InputBuffer)->StartingLcn; + OutputBuffer = (PVOLUME_BITMAP_BUFFER)UDFMapUserBuffer(Irp); - if (StartingLcn.HighPart || StartingLcn.LowPart >= TotalClusters) { + _SEH2_TRY { - UDFUnlockCallersBuffer(IrpContext, Irp, OutputBuffer); + if (Irp->RequestorMode != KernelMode) { - UDFCompleteRequest(IrpContext, Irp, STATUS_INVALID_PARAMETER); - return STATUS_INVALID_PARAMETER; + ProbeForRead(IrpSp->Parameters.FileSystemControl.Type3InputBuffer, + InputBufferLength, + sizeof(UCHAR)); - } else { + ProbeForWrite(OutputBuffer, OutputBufferLength, sizeof(UCHAR)); + } + + StartingLcn = ((PSTARTING_LCN_INPUT_BUFFER)IrpSp->Parameters.FileSystemControl.Type3InputBuffer)->StartingLcn; + + } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { + + try_return(Status = STATUS_INVALID_USER_BUFFER); + } _SEH2_END + + if (StartingLcn.HighPart || StartingLcn.LowPart >= TotalClusters) { + + try_return(Status = STATUS_INVALID_PARAMETER); + } + + // Align starting block to 8-bit boundary StartingCluster = StartingLcn.LowPart & ~7; - } - OutputBufferLength -= FIELD_OFFSET(VOLUME_BITMAP_BUFFER, Buffer); - DesiredClusters = TotalClusters - StartingCluster; + DesiredClusters = TotalClusters - StartingCluster; - if (OutputBufferLength < (DesiredClusters + 7) / 8) { + // Fill in the fixed part of the output buffer - BytesToCopy = OutputBufferLength; -// RC = STATUS_BUFFER_OVERFLOW; + __try { - } else { + // StartingLcn in output = aligned starting block - BytesToCopy = (DesiredClusters + 7) / 8; -// RC = STATUS_SUCCESS; - } + OutputBuffer->StartingLcn.QuadPart = StartingCluster; - UDFAcquireResourceExclusive(&(Vcb->VcbResource), TRUE ); + // BitmapSize = remaining blocks from starting position - _SEH2_TRY { + OutputBuffer->BitmapSize.QuadPart = DesiredClusters; + + } __except (EXCEPTION_EXECUTE_HANDLER) { + + try_return(Status = STATUS_INVALID_USER_BUFFER); + } + + OutputBufferLength -= FIELD_OFFSET(VOLUME_BITMAP_BUFFER, Buffer); + + + if (OutputBufferLength < (DesiredClusters + 7) / 8) { + + BytesToCopy = OutputBufferLength; + Status = STATUS_BUFFER_OVERFLOW; - // Fill in the fixed part of the output buffer - OutputBuffer->StartingLcn.QuadPart = StartingCluster; - OutputBuffer->BitmapSize.QuadPart = DesiredClusters; + } else { + + BytesToCopy = (DesiredClusters + 7) / 8; + Status = STATUS_SUCCESS; + } + + UDFAcquireVcbShared(IrpContext, Vcb, FALSE); + VcbAcquired = TRUE; RtlZeroMemory( &OutputBuffer->Buffer[0], BytesToCopy ); lim = BytesToCopy * 8; @@ -1357,30 +1383,24 @@ UDFGetVolumeBitmap( UDFSetFreeBit(FSBM, i); } - } _SEH2_EXCEPT(UDFExceptionFilter(IrpContext, _SEH2_GetExceptionInformation())) { + Irp->IoStatus.Information = FIELD_OFFSET(VOLUME_BITMAP_BUFFER, Buffer) + BytesToCopy; - BrutePoint(); - UDFPrintErr(("UDFGetVolumeBitmap: Exception\n")); -// UDFUnlockCallersBuffer(IrpContext, Irp, OutputBuffer); - BrutePoint(); -// RC = UDFExceptionHandler(IrpContext, Irp); - UDFReleaseResource(&(Vcb->VcbResource)); - UDFUnlockCallersBuffer(IrpContext, Irp, OutputBuffer); +try_exit: NOTHING; - Irp->IoStatus.Information = 0; - Irp->IoStatus.Status = STATUS_INVALID_USER_BUFFER; - return STATUS_INVALID_USER_BUFFER; - } _SEH2_END; + } _SEH2_FINALLY { - UDFReleaseResource(&(Vcb->VcbResource)); + if (VcbAcquired) { - UDFUnlockCallersBuffer(IrpContext, Irp, OutputBuffer); - Irp->IoStatus.Information = FIELD_OFFSET(VOLUME_BITMAP_BUFFER, Buffer) + - BytesToCopy; + UDFReleaseVcb(IrpContext, Vcb); + } + + } _SEH2_END; - UDFCompleteRequest(IrpContext, Irp, STATUS_SUCCESS); + // Complete the request - return STATUS_SUCCESS; + UDFCompleteRequest(IrpContext, Irp, Status); + + return Status; } // end UDFGetVolumeBitmap() @@ -1389,8 +1409,7 @@ UDFGetVolumeBitmap( NTSTATUS UDFGetRetrievalPointers( IN PIRP_CONTEXT IrpContext, - IN PIRP Irp, - IN ULONG Special + IN PIRP Irp ) { NTSTATUS RC; @@ -1410,6 +1429,7 @@ UDFGetRetrievalPointers( PCCB Ccb; PFCB Fcb; PVCB Vcb; + TYPE_OF_OPEN TypeOfOpen; PEXTENT_MAP SubMapping = NULL; ULONG SubExtInfoSz; @@ -1419,7 +1439,18 @@ UDFGetRetrievalPointers( UDFPrint(("UDFGetRetrievalPointers\n")); - UDFDecodeFileObject(IrpSp->FileObject, &Fcb, &Ccb); + // Make this a synchronous IRP because we need access to the input buffer and + // this Irp is marked METHOD_NEITHER. + + SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); + + TypeOfOpen = UDFDecodeFileObject(IrpSp->FileObject, &Fcb, &Ccb); + + if ((TypeOfOpen != UserFileOpen) && (TypeOfOpen != UserDirectoryOpen)) { + + UDFCompleteRequest(IrpContext, Irp, STATUS_INVALID_PARAMETER); + return STATUS_INVALID_PARAMETER; + } Vcb = Fcb->Vcb; @@ -1439,12 +1470,8 @@ UDFGetRetrievalPointers( InputBufferLength = IrpSp->Parameters.FileSystemControl.InputBufferLength; OutputBufferLength = IrpSp->Parameters.FileSystemControl.OutputBufferLength; - //OutputBuffer = (PRETRIEVAL_POINTERS_BUFFER)UDFGetCallersBuffer( IrpContext, Irp ); - if (Special) { - OutputBuffer = (PRETRIEVAL_POINTERS_BUFFER)Irp->AssociatedIrp.SystemBuffer; - } else { - OutputBuffer = (PRETRIEVAL_POINTERS_BUFFER)Irp->UserBuffer; - } + OutputBuffer = (PRETRIEVAL_POINTERS_BUFFER)UDFMapUserBuffer(Irp); + InputBuffer = (PSTARTING_VCN_INPUT_BUFFER)IrpSp->Parameters.FileSystemControl.Type3InputBuffer; if (!InputBuffer) { InputBuffer = (PSTARTING_VCN_INPUT_BUFFER)OutputBuffer; @@ -1478,16 +1505,7 @@ UDFGetRetrievalPointers( try_return(RC); } _SEH2_END; - switch(Special) { - case 0: - FileInfo = Fcb->FileInfo; - break; - case 1: - FileInfo = Vcb->NonAllocFileInfo; - break; - default: - try_return( RC = STATUS_INVALID_PARAMETER ); - } + FileInfo = Fcb->FileInfo; if (!FileInfo) { try_return( RC = STATUS_OBJECT_NAME_NOT_FOUND ); diff --git a/drivers/filesystems/udfs/lockctrl.cpp b/drivers/filesystems/udfs/lockctrl.cpp index 60f52a880cf62..e0124fa1bbe0d 100644 --- a/drivers/filesystems/udfs/lockctrl.cpp +++ b/drivers/filesystems/udfs/lockctrl.cpp @@ -141,39 +141,35 @@ UDFFastLock ( IN PDEVICE_OBJECT DeviceObject ) { + BOOLEAN FcbAcquired = FALSE; BOOLEAN Results = FALSE; - -// BOOLEAN AcquiredFCB = FALSE; TYPE_OF_OPEN TypeOfOpen; - PFCB Fcb = NULL; - - UDFPrint(("UDFFastLock\n")); + PFCB Fcb = NULL; // Decode the type of file object we're being asked to process and // make sure that is is only a user file open. TypeOfOpen = UDFFastDecodeFileObject(FileObject, &Fcb); - ASSERT_FCB(Fcb); - - // Validate the sent-in FCB - if ( (Fcb == Fcb->Vcb->VolumeDasdFcb) || - (Fcb->FcbState & UDF_FCB_DIRECTORY)) { + if (TypeOfOpen != UserFileOpen) { IoStatus->Status = STATUS_INVALID_PARAMETER; - IoStatus->Information = 0; return TRUE; } - // Acquire exclusive access to the Fcb this operation can always wait + ASSERT_FCB(Fcb); FsRtlEnterFileSystem(); - // BUGBUG: kenr - // (VOID) ExAcquireResourceShared( Fcb->Header.Resource, TRUE ); - _SEH2_TRY { + FcbAcquired = UDFAcquireFcbShared(NULL, Fcb, TRUE); + + if (FcbAcquired == FALSE) { + + try_return(NOTHING); + } + // If we don't have a file lock, then get one now. if ((Fcb->FileLock == NULL) && !UDFCreateFileLock(NULL, Fcb, FALSE)) { @@ -204,10 +200,13 @@ UDFFastLock ( try_exit: NOTHING; } _SEH2_FINALLY { - // Release the Fcb, and return to our caller + // Release the Fcb, and return to our caller + + if (FcbAcquired) { + + UDFReleaseFcb(NULL, Fcb); + } - // BUGBUG: kenr - // UDFReleaseResource( (Fcb)->Header.Resource ); FsRtlExitFileSystem(); diff --git a/drivers/filesystems/udfs/misc.cpp b/drivers/filesystems/udfs/misc.cpp index c78f45461cc12..c3dbe0b321e5e 100644 --- a/drivers/filesystems/udfs/misc.cpp +++ b/drivers/filesystems/udfs/misc.cpp @@ -125,6 +125,14 @@ UDFInitializeZones(VOID) TAG_CCB, 0); + ExInitializePagedLookasideList(&UdfData.LcbLookasideList, + NULL, + NULL, + POOL_NX_ALLOCATION | POOL_RAISE_IF_ALLOCATION_FAILURE, + SIZEOF_LOOKASIDE_LCB, + TAG_LCB, + 0); + try_return(RC = STATUS_SUCCESS); try_exit: NOTHING; @@ -165,6 +173,7 @@ VOID UDFDestroyZones(VOID) ExDeleteNPagedLookasideList(&UdfData.NonPagedFcbLookasideList); ExDeletePagedLookasideList(&UdfData.CcbLookasideList); + ExDeletePagedLookasideList(&UdfData.LcbLookasideList); } /************************************************************************* @@ -626,6 +635,14 @@ UDFDeleteCcb( Ccb->DirectorySearchPattern = NULL; } + // Release LCB reference + // The LCB will be removed and parent references decremented + // by UDFTeardownStructures when the child FCB is torn down + if (Ccb->Lcb) { + UDFReleasePrefix(NULL, Ccb->Lcb); + Ccb->Lcb = NULL; + } + UDFReleaseCCB(Ccb); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { BrutePoint(); @@ -1644,7 +1661,6 @@ UDFInitializeStackIrpContextFromLite( IrpContext->MajorFunction = IRP_MJ_CLOSE; IrpContext->Vcb = IrpContextLite->Fcb->Vcb; IrpContext->Fcb = IrpContextLite->Fcb; - IrpContext->TreeLength = IrpContextLite->TreeLength; IrpContext->RealDevice = IrpContextLite->RealDevice; // Note that this is from the stack. diff --git a/drivers/filesystems/udfs/nodetype.h b/drivers/filesystems/udfs/nodetype.h index 5027a9e327fbf..c9709c170741d 100644 --- a/drivers/filesystems/udfs/nodetype.h +++ b/drivers/filesystems/udfs/nodetype.h @@ -19,6 +19,7 @@ typedef CSHORT NODE_BYTE_SIZE; #define UDF_NODE_TYPE_UDFFS_DEVOBJ ((NODE_TYPE_CODE)0x0908) #define UDF_NODE_TYPE_IRP_CONTEXT_LITE ((NODE_TYPE_CODE)0x0909) #define UDF_NODE_TYPE_UDFFS_DRVOBJ ((NODE_TYPE_CODE)0x090a) +#define UDF_NODE_TYPE_LCB ((NODE_TYPE_CODE)0x090b) // So all records start with // diff --git a/drivers/filesystems/udfs/protos.h b/drivers/filesystems/udfs/protos.h index 73fe5eeff7dcd..bf470a5a92233 100644 --- a/drivers/filesystems/udfs/protos.h +++ b/drivers/filesystems/udfs/protos.h @@ -110,6 +110,17 @@ UDFCompleteFcbOpen( _In_ ULONG CreateDisposition ); +NTSTATUS +UDFOpenExistingFcb( + _In_ PIRP_CONTEXT IrpContext, + _In_ PIO_STACK_LOCATION IrpSp, + _In_ PVCB Vcb, + _Inout_ PFCB *CurrentFcb, + _In_ BOOLEAN IgnoreCase, + _In_ BOOLEAN OpenByFileId, + _In_ ULONG CreateDisposition + ); + NTSTATUS UDFInitializeFCB( IN PFCB PtrNewFcb, // FCB structure to be initialized @@ -130,15 +141,6 @@ extern NTSTATUS UDFCommonCleanup( PIRP_CONTEXT IrpContext, PIRP Irp); -NTSTATUS -UDFCloseFileInfoChain( - IN PIRP_CONTEXT IrpContext, - IN PVCB Vcb, - IN PUDF_FILE_INFO fi, - IN ULONG TreeLength, - IN BOOLEAN VcbAcquired - ); - /************************************************************************* * Prototypes for the file close.cpp *************************************************************************/ @@ -158,7 +160,7 @@ VOID UDFTeardownStructures( _In_ PIRP_CONTEXT IrpContext, _Inout_ PFCB StartingFcb, - _In_ ULONG TreeLength, + _In_ BOOLEAN Recursive, // TRUE if this is a recursive call (for hard links) _Out_ PBOOLEAN RemovedStartingFcb ); @@ -312,11 +314,13 @@ IN PLARGE_INTEGER FileOffset, OUT PMDL MdlChain, IN PDEVICE_OBJECT DeviceObject); -extern NTSTATUS NTAPI UDFFastIoAcqModWrite( -IN PFILE_OBJECT FileObject, -IN PLARGE_INTEGER EndingOffset, -OUT PERESOURCE* ResourceToRelease, -IN PDEVICE_OBJECT DeviceObject); +NTSTATUS +NTAPI +UDFFastIoAcqModWrite( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER EndingOffset, + OUT PERESOURCE* ResourceToRelease, + IN PDEVICE_OBJECT DeviceObject); extern NTSTATUS NTAPI UDFFastIoRelModWrite( IN PFILE_OBJECT FileObject, @@ -645,8 +649,7 @@ extern NTSTATUS UDFGetVolumeBitmap(IN PIRP_CONTEXT IrpContext, IN PIRP Irp); extern NTSTATUS UDFGetRetrievalPointers(IN PIRP_CONTEXT IrpContext, - IN PIRP Irp, - IN ULONG Special); + IN PIRP Irp); extern NTSTATUS UDFInvalidateVolumes(IN PIRP_CONTEXT IrpContext, IN PIRP Irp); @@ -669,7 +672,9 @@ extern NTSTATUS NTAPI UDFCommonLockControl( IN PIRP_CONTEXT IrpContext, IN PIRP Irp); -extern BOOLEAN NTAPI UDFFastLock( +BOOLEAN +NTAPI +UDFFastLock( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER Length, @@ -768,6 +773,49 @@ UDFDeleteCcb( PCCB Ccb ); +// prefxsup.cpp - LCB functions +PLCB +UDFInsertPrefix( + IN PIRP_CONTEXT IrpContext, + IN PFCB ParentFcb, + IN PFCB ChildFcb, + IN ULONG Index + ); + +VOID +UDFRemovePrefix( + IN PIRP_CONTEXT IrpContext, + IN PLCB Lcb + ); + +PLCB +UDFFindPrefix( + IN PIRP_CONTEXT IrpContext, + IN PFCB ParentFcb, + IN PFCB ChildFcb + ); + +PLCB +UDFAcquirePrefix( + IN PIRP_CONTEXT IrpContext, + IN PFCB ParentFcb, + IN PFCB ChildFcb, + IN ULONG Index + ); + +VOID +UDFReleasePrefix( + IN PIRP_CONTEXT IrpContext, + IN PLCB Lcb + ); + +BOOLEAN +UDFReleasePrefixImmediate( + IN PIRP_CONTEXT IrpContext, + IN PLCB Lcb, + IN BOOLEAN CloseParentFileInfo + ); + PFCB UDFCreateFcb ( _In_ PIRP_CONTEXT IrpContext, @@ -778,11 +826,15 @@ UDFCreateFcb ( VOID UDFDeleteFcb( - _In_ PIRP_CONTEXT IrpContext, + _In_opt_ PIRP_CONTEXT IrpContext, _In_ PFCB Fcb ); -VOID UDFCleanUpFCB(PFCB Fcb); +VOID +UDFInsertFcbIntoTable( + _In_ PIRP_CONTEXT IrpContext, + _In_ PFCB Fcb + ); _Ret_valid_ PIRP_CONTEXT UDFCreateIrpContext( @@ -1304,6 +1356,16 @@ SectorAlign( return (Length + (Vcb->SectorSize - 1)) & ~(Vcb->SectorSize - 1); } +inline +ULONGLONG +LlSectorAlign( + PVCB Vcb, + ULONGLONG Length +) { + + return (Length + (Vcb->SectorSize - 1)) & ~(ULONGLONG)(Vcb->SectorSize - 1); +} + VOID UDFSetThreadContext( _Inout_ PIRP_CONTEXT IrpContext, @@ -1344,4 +1406,10 @@ UDFWaitForIoAtEof( IN ULONG Length ); +VOID +UDFPrePostIrp( + _Inout_ PIRP_CONTEXT IrpContext, + _Inout_ PIRP Irp + ); + #endif // _UDF_PROTOS_H_ diff --git a/drivers/filesystems/udfs/read.cpp b/drivers/filesystems/udfs/read.cpp index 0f56677fb5d2d..ca1795add66de 100644 --- a/drivers/filesystems/udfs/read.cpp +++ b/drivers/filesystems/udfs/read.cpp @@ -480,7 +480,14 @@ UDFMapUserBuffer( } else { - return MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority | MdlMappingNoExecute); + PVOID Address = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority | MdlMappingNoExecute); + + if (Address == NULL) { + + ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES); + } + + return Address; } } // end UDFMapUserBuffer() @@ -608,27 +615,82 @@ UDFCompleteMdl( ) { PFILE_OBJECT FileObject; - PIO_STACK_LOCATION IrpSp; - - UDFPrint(("UDFCompleteMdl: \n")); + PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); + PFCB Fcb; - IrpSp = IoGetCurrentIrpStackLocation(Irp); + // Do completion processing. FileObject = IrpSp->FileObject; - ASSERT(FileObject); - // Not much to do here. - if (IrpContext->MajorFunction == IRP_MJ_READ) { + switch(IrpContext->MajorFunction) { + + case IRP_MJ_READ: - MmPrint((" CcMdlReadComplete() MDL=%x\n", Irp->MdlAddress)); CcMdlReadComplete(FileObject, Irp->MdlAddress); + break; - } else { + case IRP_MJ_WRITE: + + UDFFastDecodeFileObject(FileObject, &Fcb); + + ASSERT(FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)); + + // Check if EOF advance is active. + + if (FlagOn(Fcb->Header.Flags, FSRTL_FLAG_EOF_ADVANCE_ACTIVE)) { + + LONGLONG ByteRange = IrpSp->Parameters.Write.ByteOffset.QuadPart; + + PMDL MdlChain = Irp->MdlAddress; + while (MdlChain != NULL) + { + ByteRange += MmGetMdlByteCount(MdlChain); + MdlChain = MdlChain->Next; + } + + // Acquire the fast mutex and check if we extended valid data. + + ExAcquireFastMutex(Fcb->Header.FastMutex); + + if (ByteRange > Fcb->Header.ValidDataLength.QuadPart) { + + // Extend valid data length to file size. + + Fcb->Header.ValidDataLength.QuadPart = Fcb->Header.FileSize.QuadPart; + + // Notify cache manager of new file sizes if caching is active. + + if (CcIsFileCached(FileObject)) { + + _SEH2_TRY { + + CcSetFileSizes(FileObject, (PCC_FILE_SIZES)&Fcb->Header.AllocationSize); + + } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { + + NOTHING; + + } _SEH2_END; + } + + // Complete the EOF advance operation. + + UDFFinishIoAtEof(Fcb); + } + + ExReleaseFastMutex(Fcb->Header.FastMutex); + + } - ASSERT(IrpContext->MajorFunction == IRP_MJ_WRITE); - // The Cache Manager needs the byte offset in the I/O stack location. - MmPrint((" CcMdlWriteComplete() MDL=%x\n", Irp->MdlAddress)); CcMdlWriteComplete(FileObject, &IrpSp->Parameters.Write.ByteOffset, Irp->MdlAddress); + + Irp->IoStatus.Status = STATUS_SUCCESS; + + break; + + default: + + UDFBugCheck(IrpContext->MajorFunction, 0, 0); } // Mdl is now deallocated. diff --git a/drivers/filesystems/udfs/strucsup.cpp b/drivers/filesystems/udfs/strucsup.cpp index 6e00af7d5bd4f..a4818726c1a9a 100644 --- a/drivers/filesystems/udfs/strucsup.cpp +++ b/drivers/filesystems/udfs/strucsup.cpp @@ -29,6 +29,23 @@ typedef struct _FCB_TABLE_ELEMENT { RtlDeleteElementGenericTable( &(F)->Vcb->FcbTable, &_Key ); \ } +// +// Public wrapper for inserting FCB into FcbTable. +// Called from create.cpp after FCB is fully initialized. +// VCB must be locked by caller. +// +VOID +UDFInsertFcbIntoTable( + _In_ PIRP_CONTEXT IrpContext, + _In_ PFCB Fcb + ) +{ + UNREFERENCED_PARAMETER(IrpContext); + + UDFInsertFcbTable(IrpContext, Fcb); + SetFlag(Fcb->FcbState, FCB_STATE_IN_FCB_TABLE); +} + inline PFCB_NONPAGED UDFAllocateFcbNonpaged( @@ -173,7 +190,7 @@ Return Value: VOID UDFDeleteFcb( - _In_ PIRP_CONTEXT IrpContext, + _In_opt_ PIRP_CONTEXT IrpContext, _In_ PFCB Fcb ) @@ -185,9 +202,16 @@ Routine Description: are no references remaining. We cleanup any auxilary structures and deallocate this Fcb. + NOTE: Caller should remove FCB from FcbTable before calling this routine + (typically done by UDFTeardownStructures while holding VCB lock). + FCB should NOT be in FcbTable when this is called - either it was removed + by TeardownStructures, or it was never inserted (error path in create). + Arguments: - Fcb - This is the Fcb to deallcoate. + IrpContext - Optional IrpContext (unused but kept for API consistency). + + Fcb - This is the Fcb to deallocate. Return Value: @@ -197,101 +221,391 @@ Return Value: { PVCB Vcb = NULL; + PAGED_CODE(); - // Sanity check the counts. + UNREFERENCED_PARAMETER(IrpContext); - NT_ASSERT( Fcb->FcbCleanup == 0 ); - NT_ASSERT( Fcb->FcbReference == 0 ); + UDFPrint(("UDFDeleteFcb: %x\n", Fcb)); - // Release any Filter Context structures associated with this FCB + ASSERT_FCB(Fcb); - // FsRtlTeardownPerStreamContexts(&Fcb->Header); + // Sanity check the counts. - // Start with the common structures. + NT_ASSERT( Fcb->FcbCleanup == 0 ); + NT_ASSERT( Fcb->FcbReference == 0 ); - // CdUninitializeMcb( IrpContext, Fcb ); + // FCB must NOT be in FcbTable - either TeardownStructures removed it, + // or it was never inserted (error path before UDFInsertFcbIntoTable). + NT_ASSERT(!FlagOn(Fcb->FcbState, FCB_STATE_IN_FCB_TABLE)); - // CdDeleteFcbNonpaged( IrpContext, Fcb->FcbNonpaged ); + // LCB queues must be empty - all LCBs should be removed during teardown + NT_ASSERT(IsListEmpty(&Fcb->ParentLcbQueue)); + NT_ASSERT(IsListEmpty(&Fcb->ChildLcbQueue)); - // - // Check if we need to deallocate the prefix name buffer. - // + // Deinitialize FCBName field. - // if ((Fcb->FileNamePrefix.ExactCaseName.FileName.Buffer != (PWCHAR) Fcb->FileNamePrefix.FileNameBuffer) && - // (Fcb->FileNamePrefix.ExactCaseName.FileName.Buffer != NULL)) { + if (Fcb->FCBName) { + if (Fcb->FCBName->ObjectName.Buffer) { + MyFreePool__(Fcb->FCBName->ObjectName.Buffer); + } + UDFReleaseObjectName(Fcb->FCBName); + Fcb->FCBName = NULL; + } - // CdFreePool( &Fcb->FileNamePrefix.ExactCaseName.FileName.Buffer ); - // } + // Release any Filter Context structures associated with this FCB. + // Only if FCB was fully initialized (Header.Resource is set by + // UDFInitializeFCB). - // - // Now look at the short name prefix. - // + if (Fcb->Header.Resource) { + FsRtlTeardownPerStreamContexts(&Fcb->Header); + } - // if (Fcb->ShortNamePrefix != NULL) { + // Delete non-paged portion (resources + dealloc). - // CdFreePool( &Fcb->ShortNamePrefix ); - // } + UDFDeleteFcbNonpaged(IrpContext, Fcb->FcbNonpaged); - // - // Now do the type specific structures. - // + // Now do the type specific structures. switch (Fcb->Header.NodeTypeCode) { case UDF_NODE_TYPE_INDEX: - // NT_ASSERT( Fcb->FileObject == NULL ); - // NT_ASSERT( IsListEmpty( &Fcb->FcbQueue )); - - // if (Fcb == Fcb->Vcb->RootIndexFcb) { - - // Vcb = Fcb->Vcb; - // Vcb->RootIndexFcb = NULL; + if (Fcb == Fcb->Vcb->RootIndexFcb) { - // } else if (Fcb == Fcb->Vcb->PathTableFcb) { - - // Vcb = Fcb->Vcb; - // Vcb->PathTableFcb = NULL; - // } + Vcb = Fcb->Vcb; + Vcb->RootIndexFcb = NULL; + } UDFDeallocateFcbIndex(Fcb); break; case UDF_NODE_TYPE_DATA: - // if (Fcb->FileLock != NULL) { - - // FsRtlFreeFileLock( Fcb->FileLock ); - // } + if (Fcb->FileLock != NULL) { - // FsRtlUninitializeOplock( CdGetFcbOplock(Fcb) ); - - if (Fcb == Fcb->Vcb->VolumeDasdFcb) { + FsRtlFreeFileLock( Fcb->FileLock ); + } - __debugbreak(); + if (Fcb == Fcb->Vcb->VolumeDasdFcb) { - Vcb = Fcb->Vcb; - Vcb->VolumeDasdFcb = NULL; - } + Vcb = Fcb->Vcb; + Vcb->VolumeDasdFcb = NULL; + } UDFDeallocateFcbData(Fcb); + break; } - // - // Decrement the Vcb reference count if this is a system - // Fcb. - // + // Decrement the Vcb reference count if this is a system + // Fcb. if (Vcb != NULL) { - // InterlockedDecrement( (LONG*)&Vcb->VcbReference ); - // InterlockedDecrement( (LONG*)&Vcb->VcbUserReference ); + InterlockedDecrement( (LONG*)&Vcb->VcbReference ); + InterlockedDecrement( (LONG*)&Vcb->VcbUserReference ); } return; } +/* + This routine walks through the tree to RootDir & kills all unreferenced + structures using LCB-based parent traversal (similar to MS UdfTeardownStructures). + + StartingFcb must be acquired exclusively by caller. + This function will acquire locks for parent FCBs as needed. + + The algorithm: + 1. If FcbReference != 0, break (FCB still in use) + 2. Walk ParentLcbQueue to find LCBs with Reference == 0 + 3. For each such LCB: remove it and decrement parent's FcbReference/FileInfo->RefCount + 4. If parent's FcbReference goes to 0, recursively tear down parent + 5. Delete the FCB when all LCBs are processed + */ +_Requires_lock_held_(_Global_critical_region_) +VOID +UDFTeardownStructures( + _In_ PIRP_CONTEXT IrpContext, + _Inout_ PFCB StartingFcb, + _In_ BOOLEAN Recursive, // TRUE if this is a recursive call (for hard links) + _Out_ PBOOLEAN RemovedStartingFcb + ) +{ + PVCB Vcb = StartingFcb->Vcb; + PFCB CurrentFcb = StartingFcb; + PFCB ParentFcb = NULL; + PLCB Lcb; + PLIST_ENTRY ListLinks; + + BOOLEAN Delete = FALSE; + BOOLEAN AcquiredCurrentFcb = FALSE; + BOOLEAN Abort = FALSE; + BOOLEAN Removed; + + AdPrint(("UDFTeardownStructures, StartingFcb %p %s\n", + StartingFcb, Recursive ? "Recursive" : "Flat")); + + ASSERT_EXCLUSIVE_FCB(StartingFcb); + + *RemovedStartingFcb = FALSE; + + // + // If this is not an intentionally recursive call we need to check if this + // is a layered close and we're already in another instance of teardown. + // + if (!Recursive) { + if (FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_IN_TEARDOWN)) { + return; + } + SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_IN_TEARDOWN); + } + + _SEH2_TRY { + + // + // Loop until we find an Fcb we can't remove. + // + do { + + // + // If the reference count is non-zero then break. + // + if (CurrentFcb->FcbReference != 0) { + break; + } + + // + // It looks like we have a candidate for removal here. We + // will need to walk the list of prefixes (LCBs) and delete them + // from their parents. If it turns out that we have multiple + // parents of this Fcb (hard links), we are going to recursively + // teardown on each of these. + // + for (ListLinks = CurrentFcb->ParentLcbQueue.Flink; + ListLinks != &CurrentFcb->ParentLcbQueue; ) { + + Lcb = CONTAINING_RECORD(ListLinks, LCB, ChildFcbLinks); + + ASSERT(Lcb->NodeIdentifier.NodeTypeCode == UDF_NODE_TYPE_LCB); + + // + // We advance the pointer now because we will be toasting this guy, + // invalidating whatever is here. + // + ListLinks = ListLinks->Flink; + + // + // We may have multiple parents through hard links. If the previous parent we + // dealt with is not the parent of this new Lcb, lets do some work. + // + if (ParentFcb != Lcb->ParentFcb) { + + // + // We need to deal with the previous parent. It may now be the case that + // we deleted the last child reference and it wants to go away at this point. + // + if (ParentFcb) { + // + // It should never be the case that we have to recurse more than one level on + // any teardown since no cross-linkage of directories is possible. + // + ASSERT(!Recursive); + + UDFTeardownStructures(IrpContext, ParentFcb, TRUE, &Removed); + + if (!Removed) { + UDFReleaseResource(&ParentFcb->FcbNonpaged->FcbResource); + } + } + + // + // Get this new parent Fcb to work on. + // + ParentFcb = Lcb->ParentFcb; + UDFAcquireResourceExclusive(&ParentFcb->FcbNonpaged->FcbResource, TRUE); + } + + // + // Lock the Vcb so we can look at references. + // + UDFLockVcb(IrpContext, Vcb); + + // + // Now check that the reference counts on the Lcb are zero. + // + if (Lcb->Reference != 0) { + // + // A create is interested in getting in here, so we should + // stop right now. + // + UDFUnlockVcb(IrpContext, Vcb); + UDFReleaseResource(&ParentFcb->FcbNonpaged->FcbResource); + ParentFcb = NULL; + Abort = TRUE; + break; + } + + // + // Now remove this prefix and drop the references to the parent. + // + ASSERT(Lcb->ChildFcb == CurrentFcb); + ASSERT(Lcb->ParentFcb == ParentFcb); + + AdPrint(("UDFTeardownStructures, removing Lcb %p P %p <-> C %p\n", + Lcb, ParentFcb, CurrentFcb)); + + // + // Remove LCB from queues + // + UDFRemovePrefix(IrpContext, Lcb); + + // + // Decrement parent's references + // (UDFAcquirePrefix incremented both when LCB was created) + // + if (ParentFcb->FileInfo) { + UDFCloseFile__(IrpContext, Vcb, ParentFcb->FileInfo); + } + InterlockedDecrement((PLONG)&ParentFcb->FcbReference); + + UDFUnlockVcb(IrpContext, Vcb); + } + + // + // Now really leave if we have to. + // + if (Abort) { + break; + } + + // + // Now that we have removed all of the prefixes of this Fcb we can make the final check. + // Lock the Vcb again so we can inspect the child's references. + // + UDFLockVcb(IrpContext, Vcb); + + if (CurrentFcb->FcbReference != 0) { + // + // Nope, nothing more to do. Stop right now. + // + UDFUnlockVcb(IrpContext, Vcb); + + if (ParentFcb != NULL) { + UDFReleaseResource(&ParentFcb->FcbNonpaged->FcbResource); + } + break; + } + + // + // This Fcb is toast. Remove it from the Fcb Table as appropriate and delete. + // + if (FlagOn(CurrentFcb->FcbState, FCB_STATE_IN_FCB_TABLE)) { + UDFDeleteFcbTable(IrpContext, CurrentFcb); + ClearFlag(CurrentFcb->FcbState, FCB_STATE_IN_FCB_TABLE); + } + + // + // Check FcbCleanup while still holding VcbMutex + // + BOOLEAN ShouldDelete = !CurrentFcb->FcbCleanup; + UDFUnlockVcb(IrpContext, Vcb); + + if (ShouldDelete && CurrentFcb->FileInfo) { + + // no more references... current file/dir MUST DIE!!! + if (Delete) { + UDFReferenceFile__(CurrentFcb->FileInfo); + UDFFlushFile__(IrpContext, Vcb, CurrentFcb->FileInfo); + UDFUnlinkFile__(IrpContext, Vcb, CurrentFcb->FileInfo, TRUE); + UDFCloseFile__(IrpContext, Vcb, CurrentFcb->FileInfo); + CurrentFcb->FcbState |= UDF_FCB_DELETED; + Delete = FALSE; + } + else if (!(CurrentFcb->FcbState & UDF_FCB_DELETED)) { + UDFFlushFile__(IrpContext, Vcb, CurrentFcb->FileInfo); + } + + // check if we should try to delete Parent for the next time + if (CurrentFcb->FcbState & UDF_FCB_DELETE_PARENT) { + Delete = TRUE; + } + + // remove references to OS-specific structures + // to let UDF_INFO release FI & Co + CurrentFcb->FileInfo->Fcb = NULL; + if (CurrentFcb->FileInfo->Dloc) { + CurrentFcb->FileInfo->Dloc->CommonFcb = NULL; + } + + if (UDFCleanUpFile__(Vcb, CurrentFcb->FileInfo) == (UDF_FREE_FILEINFO | UDF_FREE_DLOC)) { + + AdPrint(("UDFTeardownStructures, deleting Fcb %p\n", CurrentFcb)); + + // Release the exclusive FCB lock before deleting the FCB. + UDF_CHECK_PAGING_IO_RESOURCE(CurrentFcb); + UDFReleaseResource(&CurrentFcb->FcbNonpaged->FcbResource); + + // Save FileInfo before freeing FCB (avoid use-after-free) + PUDF_FILE_INFO FileInfoToFree = CurrentFcb->FileInfo; + CurrentFcb->ParentFcb = NULL; + UDFDeleteFcb(IrpContext, CurrentFcb); + MyFreePool__(FileInfoToFree); + + // Move to the parent Fcb. + CurrentFcb = ParentFcb; + ParentFcb = NULL; + AcquiredCurrentFcb = TRUE; + + } else { + // Stop cleaning up - restore pointers + CurrentFcb->FileInfo->Fcb = CurrentFcb; + if (CurrentFcb->FileInfo->Dloc) { + CurrentFcb->FileInfo->Dloc->CommonFcb = CurrentFcb; + } + + UDFReleaseResource(&CurrentFcb->FcbNonpaged->FcbResource); + CurrentFcb = ParentFcb; + ParentFcb = NULL; + AcquiredCurrentFcb = TRUE; + } + } else { + // Cannot delete - release and move to parent + if (CurrentFcb != StartingFcb || AcquiredCurrentFcb) { + UDFReleaseResource(&CurrentFcb->FcbNonpaged->FcbResource); + } + CurrentFcb = ParentFcb; + ParentFcb = NULL; + AcquiredCurrentFcb = TRUE; + } + + } while (CurrentFcb != NULL); + + } _SEH2_FINALLY { + + // + // Release the current Fcb if we have acquired it. + // + if (AcquiredCurrentFcb && (CurrentFcb != NULL)) { + UDFReleaseResource(&CurrentFcb->FcbNonpaged->FcbResource); + } + + // + // Clear the teardown flag. + // + if (!Recursive) { + ClearFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_IN_TEARDOWN); + } + + } _SEH2_END; + + *RemovedStartingFcb = (CurrentFcb != StartingFcb); + + AdPrint(("UDFTeardownStructures, RemovedStartingFcb -> %c\n", + *RemovedStartingFcb ? 'T' : 'F')); + +} // end UDFTeardownStructures() + PFCB UDFLookupFcbTable ( _In_ PIRP_CONTEXT IrpContext, @@ -558,11 +872,15 @@ UDFInitializeFCB( Fcb->FcbState = Flags; - UDFInsertFcbTable(IrpContext, Fcb); - SetFlag(Fcb->FcbState, FCB_STATE_IN_FCB_TABLE); + // NOTE: FCB is NOT added to FcbTable here. + // Caller is responsible for calling UDFInsertFcbTable after + // FCB is fully initialized (matching MS pattern where + // UdfInsertFcbTable is called at the END of initialization). // initialize the various list heads InitializeListHead(&Fcb->NextCCB); + InitializeListHead(&Fcb->ParentLcbQueue); + InitializeListHead(&Fcb->ChildLcbQueue); Fcb->FcbReference = 0; Fcb->FcbCleanup = 0; @@ -837,65 +1155,6 @@ UDFInitializeVCB( } _SEH2_END; } // end UDFInitializeVCB() -VOID -UDFCleanUpFCB( - PFCB Fcb - ) -{ - UDFPrint(("UDFCleanUpFCB: %x\n", Fcb)); - if (!Fcb) return; - - ASSERT_FCB(Fcb); - - _SEH2_TRY { - // Deinitialize FCBName field - if (Fcb->FCBName) { - if (Fcb->FCBName->ObjectName.Buffer) { - MyFreePool__(Fcb->FCBName->ObjectName.Buffer); - Fcb->FCBName->ObjectName.Buffer = NULL; -#ifdef UDF_DBG - Fcb->FCBName->ObjectName.Length = - Fcb->FCBName->ObjectName.MaximumLength = 0; -#endif - } -#ifdef UDF_DBG - else { - UDFPrint(("UDF: Fcb has invalid FCBName Buffer\n")); - BrutePoint(); - } -#endif - UDFReleaseObjectName(Fcb->FCBName); - Fcb->FCBName = NULL; - } -#ifdef UDF_DBG - else { - UDFPrint(("UDF: Fcb has invalid FCBName field\n")); - BrutePoint(); - } -#endif - - - // begin transaction { - - UDFLockVcb(IrpContext, Fcb->Vcb); - - if (FlagOn(Fcb->FcbState, FCB_STATE_IN_FCB_TABLE)) { - - UDFDeleteFcbTable(IrpContext, Fcb); - ClearFlag(Fcb->FcbState, FCB_STATE_IN_FCB_TABLE); - } - - UDFUnlockVcb(IrpContext, Fcb->Vcb); - - // } end transaction - - // Free memory - UDFDeleteFcb(0, Fcb); - } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { - BrutePoint(); - } _SEH2_END; -} // end UDFCleanUpFCB() - NTSTATUS UDFCompleteMount( IN PIRP_CONTEXT IrpContext, @@ -945,7 +1204,7 @@ UDFCompleteMount( if (!RootName) { - UDFCleanUpFCB(Vcb->RootIndexFcb); + UDFDeleteFcb(IrpContext, Vcb->RootIndexFcb); Vcb->RootIndexFcb = NULL; try_return(Status = STATUS_INSUFFICIENT_RESOURCES); } @@ -961,7 +1220,7 @@ UDFCompleteMount( insuf_res_1: MyFreePool__(RootName->ObjectName.Buffer); UDFReleaseObjectName(RootName); - UDFCleanUpFCB(Vcb->RootIndexFcb); + UDFDeleteFcb(IrpContext, Vcb->RootIndexFcb); Vcb->RootIndexFcb = NULL; try_return(Status); } @@ -996,11 +1255,20 @@ UDFCompleteMount( UDFCleanUpFile__(Vcb, Vcb->RootIndexFcb->FileInfo); MyFreePool__(Vcb->RootIndexFcb->FileInfo); - UDFCleanUpFCB(Vcb->RootIndexFcb); + + // FCB was not inserted into table (UDFInitializeFCB failed + // before UDFInsertFcbIntoTable was called) + UDFUnlockVcb(IrpContext, Vcb); + UnlockVcb = FALSE; + + UDFDeleteFcb(IrpContext, Vcb->RootIndexFcb); Vcb->RootIndexFcb = NULL; try_return(Status); } + // Insert into FcbTable after successful initialization + UDFInsertFcbIntoTable(IrpContext, Vcb->RootIndexFcb); + // this is a part of UDF_RESIDUAL_REFERENCE InterlockedIncrement((PLONG)&Vcb->VcbReference); Vcb->RootIndexFcb->FcbCleanup = 1; diff --git a/drivers/filesystems/udfs/struct.h b/drivers/filesystems/udfs/struct.h index 35a44a8d443fd..d934d36a4a914 100644 --- a/drivers/filesystems/udfs/struct.h +++ b/drivers/filesystems/udfs/struct.h @@ -36,6 +36,8 @@ struct IRP_CONTEXT_LITE; struct IO_CONTEXT; struct IRP_CONTEXT; +struct LCB; +typedef struct LCB *PLCB; /************************************************************************** every structure has a node type, and a node size associated with it. @@ -82,6 +84,8 @@ struct CCB { UDFIdentifier NodeIdentifier; // ptr to the associated FCB FCB* Fcb; + // ptr to the LCB used to open this file + PLCB Lcb; // all CCB structures for a FCB are linked together LIST_ENTRY NextCCB; // each CCB is associated with a file object @@ -94,7 +98,6 @@ struct CCB { // need to maintain a search pattern PUNICODE_STRING DirectorySearchPattern; HASH_ENTRY hashes; - ULONG TreeLength; }; using PCCB = CCB*; @@ -267,6 +270,13 @@ struct FCB { PVOID LazyWriteThread; FCB* ParentFcb; + + // LCB queues for parent-child relationships + // ParentLcbQueue - LCBs linking this FCB to parent directories (for hardlinks, usually 1) + LIST_ENTRY ParentLcbQueue; + // ChildLcbQueue - LCBs linking child files to this directory FCB + LIST_ENTRY ChildLcbQueue; + // Pointer to IrpContextLite in delayed queue. IRP_CONTEXT_LITE* IrpContextLite; uint32 CcbCount; @@ -297,6 +307,9 @@ using PFCB = FCB*; values are bit fields; therefore we can test whether a bit position is set (1) or not set (0). **************************************************************************/ +// File data is embedded in ICB (IN_ICB allocation mode) +// Requires exclusive lock for writes since data shares sector with metadata +#define UDF_FCB_EMBEDDED_DATA (0x00000001) #define UDF_FCB_VALID (0x00000002) #define UDF_FCB_DIRECTORY (0x00000008) #define UDF_FCB_ROOT_DIRECTORY (0x00000010) @@ -334,6 +347,53 @@ enum UDFFSD_MEDIA_TYPE { MediaDvdrw }; +//*************************************************************************** +// LCB (Link Control Block) +//*************************************************************************** + +/** + Link Control Block (LCB) - links parent directory to child file. + Similar to MS UDF driver's LCB structure. + + Used to defer directory linkage until create operation completes successfully. + This prevents partial creates from being visible in directory lookups. +*/ +struct LCB { + UDFIdentifier NodeIdentifier; // Node type = UDFS_NTC_LCB + + // Links in parent FCB's ChildLcbQueue + LIST_ENTRY ParentFcbLinks; + // Links in child FCB's ParentLcbQueue + LIST_ENTRY ChildFcbLinks; + + // Parent directory FCB + PFCB ParentFcb; + // Child file FCB + PFCB ChildFcb; + + // Reference count (incremented by CCB, decremented on cleanup) + ULONG Reference; + // LCB flags + ULONG Flags; + // Index in parent's DirIndex (for quick lookup) + ULONG Index; +}; + +// LCB Flags +#define UDF_LCB_FLAG_DELETE_ON_CLEANUP 0x00000001 // Delete file on cleanup +#define UDF_LCB_FLAG_LINK_DELETED 0x00000002 // Link has been deleted +#define UDF_LCB_FLAG_PENDING_CREATE 0x00000004 // Create not yet complete +#define UDF_LCB_FLAG_POOL_ALLOCATED 0x00000008 // Allocated from pool (not lookaside) +#define UDF_LCB_FLAG_IGNORE_CASE 0x00000010 // Case-insensitive name +#define UDF_LCB_FLAG_SHORT_NAME 0x00000020 // Short name match + +// LCB lookaside size - fits LCB + 16 WCHARs for short names +#define SIZEOF_LOOKASIDE_LCB (sizeof(LCB) + (sizeof(WCHAR) * 16)) + +//*************************************************************************** +// VCB (Volume Control Block) +//*************************************************************************** + enum VCB_CONDITION { VcbNotMounted = 0, @@ -704,7 +764,6 @@ struct IRP_CONTEXT { NTSTATUS ExceptionStatus; // For queued close operation we save Fcb FCB* Fcb; - ULONG TreeLength; // Io context for a read request. // Address of Fcb for teardown oplock in create case. @@ -789,7 +848,6 @@ struct IRP_CONTEXT_LITE { ULONG UserReference; // Real device object. This represents the physical device closest to the media. PDEVICE_OBJECT RealDevice; - ULONG TreeLength; }; using PIRP_CONTEXT_LITE = IRP_CONTEXT_LITE*; @@ -834,6 +892,7 @@ typedef struct _UDFData { PAGED_LOOKASIDE_LIST UDFFcbDataLookasideList; PAGED_LOOKASIDE_LIST CcbLookasideList; + PAGED_LOOKASIDE_LIST LcbLookasideList; LIST_ENTRY AsyncCloseQueue; ULONG AsyncCloseCount; @@ -874,6 +933,7 @@ typedef struct _UDFData { #define TAG_FCB_NONPAGED 'nfdU' #define TAG_FCB 'pfdU' #define TAG_CCB 'ccdU' +#define TAG_LCB 'lcdU' #define TAG_VPB 'pvdU' #define TAG_FCB_TABLE 'tfdU' #define TAG_FILE_NAME 'nFdU' diff --git a/drivers/filesystems/udfs/udf_info/dirtree.cpp b/drivers/filesystems/udfs/udf_info/dirtree.cpp index 247376ff93ce7..b4e1e1a5f0aec 100644 --- a/drivers/filesystems/udfs/udf_info/dirtree.cpp +++ b/drivers/filesystems/udfs/udf_info/dirtree.cpp @@ -1048,6 +1048,51 @@ UDFFindFile( } // end UDFFindFile() +/* + Find file in directory and fill enumeration context. + This separates search from open, allowing caller to inspect + the found entry before opening. +*/ +NTSTATUS +UDFFindDirEntry( + IN PVCB Vcb, + IN PUDF_FILE_INFO DirInfo, + IN PUNICODE_STRING FileName, + IN BOOLEAN IgnoreCase, + IN BOOLEAN NotDeleted, + OUT PDIR_ENUM_CONTEXT DirContext + ) +{ + NTSTATUS status; + uint_di Index = 0; + + // Initialize context + RtlZeroMemory(DirContext, sizeof(DIR_ENUM_CONTEXT)); + DirContext->ParentInfo = DirInfo; + + if (!DirInfo->Dloc->DirIndex) { + return STATUS_NOT_A_DIRECTORY; + } + + DirContext->DirIndex = DirInfo->Dloc->DirIndex; + + // Find the file + status = UDFFindFile(Vcb, IgnoreCase, NotDeleted, FileName, DirInfo, &Index); + if (!NT_SUCCESS(status)) { + return status; + } + + // Get the directory entry + DirContext->DirNdx = UDFDirIndex(DirContext->DirIndex, Index); + if (!DirContext->DirNdx) { + return STATUS_OBJECT_NAME_NOT_FOUND; + } + + DirContext->Index = Index; + return STATUS_SUCCESS; + +} // end UDFFindDirEntry() + /* This routine returns pointer to parent DirIndex */ diff --git a/drivers/filesystems/udfs/udf_info/udf_info.cpp b/drivers/filesystems/udfs/udf_info/udf_info.cpp index 6042fd6339a47..f42028d4bb8f0 100644 --- a/drivers/filesystems/udfs/udf_info/udf_info.cpp +++ b/drivers/filesystems/udfs/udf_info/udf_info.cpp @@ -1645,6 +1645,9 @@ UDFWriteFile__( ((PFILE_ENTRY)(Dloc->FileEntry))->icbTag.flags &= ~ICB_FLAG_ALLOC_MASK; ((PFILE_ENTRY)(Dloc->FileEntry))->icbTag.flags |= Vcb->DefaultAllocMode; WasInIcb = TRUE; + // Clear embedded data flag since file is no longer in ICB mode + ASSERT(FileInfo->Fcb); + FileInfo->Fcb->FcbState &= ~UDF_FCB_EMBEDDED_DATA; } // increase extent ExtPrint((" %s %s %s\n", @@ -2146,6 +2149,178 @@ UDFOpenFile__( } // end UDFOpenFile__() +/* + Open file from directory context. + This is called after UDFFindDirEntry to open the found file. + */ +NTSTATUS +UDFOpenObjectFromDirContext( + IN PIRP_CONTEXT IrpContext, + IN PVCB Vcb, + IN PDIR_ENUM_CONTEXT DirContext, + IN BOOLEAN NotDeleted, + OUT PUDF_FILE_INFO* _FileInfo + ) +{ + NTSTATUS status; + EXTENT_AD FEExt; + uint16 Ident; + PDIR_INDEX_ITEM DirNdx = DirContext->DirNdx; + PUDF_FILE_INFO DirInfo = DirContext->ParentInfo; + PUDF_FILE_INFO FileInfo; + PUDF_FILE_INFO ParFileInfo; + ULONG ReadBytes; + uint_di i = DirContext->Index; + + *_FileInfo = NULL; + + if (!DirNdx) { + return STATUS_OBJECT_NAME_NOT_FOUND; + } + + if ((FileInfo = DirNdx->FileInfo)) { + // file is already opened + if ((DirNdx->FileCharacteristics & FILE_DELETED) && NotDeleted) { + AdPrint((" FILE_DELETED on open\n")); + return STATUS_FILE_DELETED; + } + if ((FileInfo->ParentFile != DirInfo) && + (FileInfo->Index >= 2)) { + ParFileInfo = UDFLocateParallelFI(DirInfo, i, FileInfo); + BrutePoint(); + if (ParFileInfo->ParentFile != DirInfo) { + FileInfo = (PUDF_FILE_INFO)MyAllocatePoolTag__(UDF_FILE_INFO_MT, sizeof(UDF_FILE_INFO), MEM_FINF_TAG); + *_FileInfo = FileInfo; + if (!FileInfo) return STATUS_INSUFFICIENT_RESOURCES; + RtlCopyMemory(FileInfo, DirNdx->FileInfo, sizeof(UDF_FILE_INFO)); + UDFInsertLinkedFile(FileInfo, DirNdx->FileInfo); + DirNdx->FI_Flags |= UDF_FI_FLAG_LINKED; + FileInfo->RefCount = 0; + FileInfo->ParentFile = DirInfo; + FileInfo->Fcb = NULL; + } else { + FileInfo = ParFileInfo; + } + } + // Just increase some counters & exit + UDFReferenceFile__(FileInfo); + + ASSERT(FileInfo->ParentFile == DirInfo); + ValidateFileInfo(FileInfo); + + *_FileInfo = FileInfo; + return STATUS_SUCCESS; + } + + // Check deleted for new open + if ((DirNdx->FileCharacteristics & FILE_DELETED) && NotDeleted) { + AdPrint((" FILE_DELETED on open (2)\n")); + return STATUS_FILE_DELETED; + } + + FileInfo = (PUDF_FILE_INFO)MyAllocatePoolTag__(UDF_FILE_INFO_MT, sizeof(UDF_FILE_INFO), MEM_FINF_TAG); + *_FileInfo = FileInfo; + if (!FileInfo) return STATUS_INSUFFICIENT_RESOURCES; + RtlZeroMemory(FileInfo, sizeof(UDF_FILE_INFO)); + // init horizontal links + FileInfo->NextLinkedFile = + FileInfo->PrevLinkedFile = FileInfo; + // read FileIdent + FileInfo->FileIdent = (PFILE_IDENT_DESC)MyAllocatePoolTag__(NonPagedPool, DirNdx->Length, MEM_FID_TAG); + if (!(FileInfo->FileIdent)) return STATUS_INSUFFICIENT_RESOURCES; + FileInfo->FileIdentLen = DirNdx->Length; + if (!NT_SUCCESS(status = UDFReadExtent(IrpContext, Vcb, &DirInfo->Dloc->DataLoc, DirNdx->Offset, + DirNdx->Length, FALSE, (int8*)(FileInfo->FileIdent), &ReadBytes))) + return status; + if (FileInfo->FileIdent->descTag.tagIdent != TID_FILE_IDENT_DESC) { + BrutePoint(); + return STATUS_FILE_CORRUPT_ERROR; + } + // check for opened links + if (!NT_SUCCESS(status = UDFStoreDloc(Vcb, FileInfo, UDFPartLbaToPhys(Vcb, &(FileInfo->FileIdent->icb.extLocation))))) + return status; + // init pointer to parent object + FileInfo->Index = i; + FileInfo->ParentFile = DirInfo; + // init pointers to linked files (if any) + if (FileInfo->Dloc->LinkedFileInfo != FileInfo) + UDFInsertLinkedFile(FileInfo, FileInfo->Dloc->LinkedFileInfo); + if (FileInfo->Dloc->FileEntry) + goto init_tree_entry; + // read (Ex)FileEntry + FileInfo->Dloc->FileEntry = (tag*)MyAllocatePoolTag__(NonPagedPool, Vcb->SectorSize, MEM_FE_TAG); + if (!(FileInfo->Dloc->FileEntry)) return STATUS_INSUFFICIENT_RESOURCES; + if (!NT_SUCCESS(status = UDFReadFileEntry(IrpContext, Vcb, &FileInfo->FileIdent->icb, (PFILE_ENTRY)(FileInfo->Dloc->FileEntry), &Ident))) + return status; + // build mappings for Data & AllocDescs + if (!FileInfo->Dloc->AllocLoc.Mapping) { + FEExt.extLength = FileInfo->FileIdent->icb.extLength; + FEExt.extLocation = UDFPartLbaToPhys(Vcb, &(FileInfo->FileIdent->icb.extLocation)); + if (FEExt.extLocation == LBA_OUT_OF_EXTENT) + return STATUS_FILE_CORRUPT_ERROR; + FileInfo->Dloc->AllocLoc.Mapping = UDFExtentToMapping(&FEExt); + if (!(FileInfo->Dloc->AllocLoc.Mapping)) + return STATUS_INSUFFICIENT_RESOURCES; + } + // read location info + status = UDFLoadExtInfo(IrpContext, Vcb, (PFILE_ENTRY)(FileInfo->Dloc->FileEntry), &FileInfo->FileIdent->icb, + &FileInfo->Dloc->DataLoc, &FileInfo->Dloc->AllocLoc); + if (!NT_SUCCESS(status)) + return status; + // init (Ex)FileEntry mapping + FileInfo->Dloc->FELoc.Length = (FileInfo->Dloc->DataLoc.Offset) ? FileInfo->Dloc->DataLoc.Offset : + FileInfo->Dloc->AllocLoc.Offset; + FileInfo->Dloc->FELoc.Mapping = UDFExtentToMapping(&FEExt); + FileInfo->Dloc->FileEntryLen = (uint32)(FileInfo->Dloc->FELoc.Length); + // we get here immediately when opened link encountered +init_tree_entry: + // init back pointer from parent object + ASSERT(!DirNdx->FileInfo); + DirNdx->FileInfo = FileInfo; + // init DirIndex + if (UDFGetFileLinkCount(FileInfo) > 1) { + DirNdx->FI_Flags |= UDF_FI_FLAG_LINKED; + } else { + DirNdx->FI_Flags &= ~UDF_FI_FLAG_LINKED; + } + // resize FE cache + if (!MyReallocPool__((int8*)((FileInfo->Dloc->FileEntry)), Vcb->SectorSize, + (int8**)&((FileInfo->Dloc->FileEntry)), FileInfo->Dloc->FileEntryLen)) + return STATUS_INSUFFICIENT_RESOURCES; + // check if this file has a SDir + if ((FileInfo->Dloc->FileEntry->tagIdent == TID_EXTENDED_FILE_ENTRY) && + ((PEXTENDED_FILE_ENTRY)(FileInfo->Dloc->FileEntry))->streamDirectoryICB.extLength) + FileInfo->Dloc->FE_Flags |= UDF_FE_FLAG_HAS_SDIR; + if (!(FileInfo->FileIdent->fileCharacteristics & FILE_DIRECTORY)) { + UDFReferenceFile__(FileInfo); + ASSERT(FileInfo->ParentFile == DirInfo); + UDFReleaseDloc(Vcb, FileInfo->Dloc); + return STATUS_SUCCESS; + } + + UDFCheckSpaceAllocation(Vcb, 0, FileInfo->Dloc->DataLoc.Mapping, AS_USED); + + // build index for directories + if (!FileInfo->Dloc->DirIndex) { + status = UDFIndexDirectory(IrpContext, Vcb, FileInfo); + if (!NT_SUCCESS(status)) + return status; + + if ((FileInfo->Dloc->DirIndex->DelCount > Vcb->PackDirThreshold) && + !(Vcb->VcbState & VCB_STATE_VOLUME_READ_ONLY)) { + status = UDFPackDirectory__(IrpContext, Vcb, FileInfo); + if (!NT_SUCCESS(status)) + return status; + } + } + UDFReferenceFile__(FileInfo); + UDFReleaseDloc(Vcb, FileInfo->Dloc); + ASSERT(FileInfo->ParentFile == DirInfo); + + return status; +} // end UDFOpenObjectFromDirContext() + + /* This routine inits UDF_FILE_INFO structure for root directory */ @@ -2860,8 +3035,12 @@ try_exit: NOTHING; } _SEH2_FINALLY { if (!NT_SUCCESS(status)) { - if (FEAllocated) + if (FEAllocated && FileInfo->Dloc) { + // Free FE space first (needs Dloc->FELoc), then remove Dloc entry UDFFreeFESpace(Vcb, DirInfo, &(FileInfo->Dloc->FELoc)); + UDFRemoveDloc(Vcb, FileInfo->Dloc); + FileInfo->Dloc = NULL; + } } } _SEH2_END return status; @@ -3527,6 +3706,9 @@ UDFResizeFile__( // switch to IN_ICB mode ((PFILE_ENTRY)(FileInfo->Dloc->FileEntry))->icbTag.flags &= ~ICB_FLAG_ALLOC_MASK; ((PFILE_ENTRY)(FileInfo->Dloc->FileEntry))->icbTag.flags |= ICB_FLAG_AD_IN_ICB; + // Set embedded data flag since file is now in ICB mode + ASSERT(FileInfo->Fcb); + FileInfo->Fcb->FcbState |= UDF_FCB_EMBEDDED_DATA; // init new data location descriptors FileInfo->Dloc->DataLoc.Mapping = NewMap; RtlZeroMemory((int8*)(FileInfo->Dloc->DataLoc.Mapping), 2*sizeof(EXTENT_MAP)); @@ -3612,6 +3794,8 @@ UDFLoadVAT( VatFileInfo = Vcb->VatFileInfo = (PUDF_FILE_INFO)MyAllocatePoolTag__(UDF_FILE_INFO_MT, sizeof(UDF_FILE_INFO), MEM_VATFINF_TAG); if (!VatFileInfo) return STATUS_INSUFFICIENT_RESOURCES; + RtlZeroMemory(VatFileInfo, sizeof(UDF_FILE_INFO)); + VatFileInfo->NextLinkedFile = VatFileInfo->PrevLinkedFile = VatFileInfo; // load VAT FE (we know its location) VatFELoc.partitionReferenceNum = PartNum; retry_load_vat: diff --git a/drivers/filesystems/udfs/udf_info/udf_info.h b/drivers/filesystems/udfs/udf_info/udf_info.h index c10108ae41195..630953010e080 100644 --- a/drivers/filesystems/udfs/udf_info/udf_info.h +++ b/drivers/filesystems/udfs/udf_info/udf_info.h @@ -131,6 +131,23 @@ __inline NTSTATUS UDFFindFile__(IN PVCB Vcb, return UDFFindFile(Vcb, IgnoreCase, TRUE, Name, DirInfo, &i); } +// Find file in directory and fill enumeration context +NTSTATUS UDFFindDirEntry( + IN PVCB Vcb, + IN PUDF_FILE_INFO DirInfo, + IN PUNICODE_STRING FileName, + IN BOOLEAN IgnoreCase, + IN BOOLEAN NotDeleted, + OUT PDIR_ENUM_CONTEXT DirContext); + +// Open file from directory context (after UDFFindDirEntry) +NTSTATUS UDFOpenObjectFromDirContext( + IN PIRP_CONTEXT IrpContext, + IN PVCB Vcb, + IN PDIR_ENUM_CONTEXT DirContext, + IN BOOLEAN NotDeleted, + OUT PUDF_FILE_INFO* FileInfo); + // calculate file mapping length (in bytes) including ZERO-terminator uint32 UDFGetMappingLength(IN PEXTENT_MAP Extent); // merge 2 sequencial file mappings diff --git a/drivers/filesystems/udfs/udf_info/udf_rel.h b/drivers/filesystems/udfs/udf_info/udf_rel.h index 602a8f6e2cafa..0a8a6089dd19c 100644 --- a/drivers/filesystems/udfs/udf_info/udf_rel.h +++ b/drivers/filesystems/udfs/udf_info/udf_rel.h @@ -441,6 +441,18 @@ typedef struct _UDF_DIR_SCAN_CONTEXT { uint_di i; } UDF_DIR_SCAN_CONTEXT, *PUDF_DIR_SCAN_CONTEXT; +/** + Directory enumeration context for find/open operations. + Separates directory search from file open operations. +*/ +typedef struct _DIR_ENUM_CONTEXT { + PUDF_FILE_INFO ParentInfo; // Parent directory FileInfo + PDIR_INDEX_HDR DirIndex; // Directory index header + PDIR_INDEX_ITEM DirNdx; // Found directory entry (or NULL) + uint_di Index; // Index of found entry + BOOLEAN ShortNameMatch; // TRUE if matched by 8.3 short name +} DIR_ENUM_CONTEXT, *PDIR_ENUM_CONTEXT; + typedef EXT_RELOCATION_ENTRY EXT_RELOC_MAP; typedef PEXT_RELOCATION_ENTRY PEXT_RELOC_MAP; diff --git a/drivers/filesystems/udfs/udffs.h b/drivers/filesystems/udfs/udffs.h index 80af91080509b..5eff0e08995b0 100644 --- a/drivers/filesystems/udfs/udffs.h +++ b/drivers/filesystems/udfs/udffs.h @@ -17,6 +17,8 @@ #ifndef _UDF_UDF_H_ #define _UDF_UDF_H_ +#pragma warning(disable : 28172) + /**************** OPTIONS *****************/ //#define UDF_TRACK_UNICODE_STR @@ -54,7 +56,7 @@ #define UDF_DEFAULT_SPARSE_THRESHOLD (256*PACKETSIZE_UDF) -#define ALLOW_SPARSE +//#define ALLOW_SPARSE #define UDF_PACK_DIRS diff --git a/drivers/filesystems/udfs/udfinit.cpp b/drivers/filesystems/udfs/udfinit.cpp index 0453c669d109f..41e2a087633af 100644 --- a/drivers/filesystems/udfs/udfinit.cpp +++ b/drivers/filesystems/udfs/udfinit.cpp @@ -312,7 +312,7 @@ UDFInitializeFunctionPointers( PtrFastIoDispatch->FastIoQueryNetworkOpenInfo = UDFFastIoQueryNetInfo; PtrFastIoDispatch->AcquireForModWrite = UDFFastIoAcqModWrite; - PtrFastIoDispatch->ReleaseForModWrite = UDFFastIoRelModWrite; + PtrFastIoDispatch->ReleaseForModWrite = NULL; PtrFastIoDispatch->AcquireForCcFlush = UDFFastIoAcqCcFlush; PtrFastIoDispatch->ReleaseForCcFlush = UDFFastIoRelCcFlush; diff --git a/drivers/filesystems/udfs/volinfo.cpp b/drivers/filesystems/udfs/volinfo.cpp index d8be1796c6138..21e41a4011d70 100644 --- a/drivers/filesystems/udfs/volinfo.cpp +++ b/drivers/filesystems/udfs/volinfo.cpp @@ -415,11 +415,7 @@ UDFQueryFsAttributeInfo( Buffer->FileSystemAttributes = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES | (UDFIsStreamsSupported(Vcb) ? FILE_NAMED_STREAMS : 0) | -#ifdef ALLOW_SPARSE - FILE_SUPPORTS_SPARSE_FILES | -#endif //ALLOW_SPARSE ((Vcb->VcbState & VCB_STATE_VOLUME_READ_ONLY) ? FILE_READ_ONLY_VOLUME : 0) | - FILE_UNICODE_ON_DISK; Buffer->MaximumComponentNameLength = UDF_X_NAME_LEN-1; diff --git a/drivers/filesystems/udfs/write.cpp b/drivers/filesystems/udfs/write.cpp index 92919033cd68f..75feee29a023a 100644 --- a/drivers/filesystems/udfs/write.cpp +++ b/drivers/filesystems/udfs/write.cpp @@ -39,12 +39,14 @@ NTSTATUS UDFCommonWrite( PIRP_CONTEXT IrpContext, - PIRP Irp) + PIRP Irp) { - NTSTATUS RC = STATUS_SUCCESS; - PIO_STACK_LOCATION IrpSp = NULL; - LARGE_INTEGER ByteOffset; - ULONG WriteLength = 0, TruncatedLength = 0; + NTSTATUS Status = STATUS_SUCCESS; + PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); + LONGLONG StartingOffset; + ULONG ByteCount; + LONGLONG ByteRange; + ULONG TruncatedLength; SIZE_T NumberBytesWritten = 0; PFILE_OBJECT FileObject = NULL; TYPE_OF_OPEN TypeOfOpen; @@ -52,7 +54,6 @@ UDFCommonWrite( PCCB Ccb = NULL; PVCB Vcb = NULL; PVOID SystemBuffer = NULL; - PIRP TopIrp; LONGLONG ASize; LONGLONG OldVDL; @@ -61,121 +62,146 @@ UDFCommonWrite( BOOLEAN MainResourceAcquired = FALSE; BOOLEAN VcbAcquired = FALSE; - BOOLEAN MainResourceAcquiredExclusive = FALSE; - BOOLEAN MainResourceCanDemoteToShared = FALSE; - - BOOLEAN CanWait = FALSE; + BOOLEAN Wait = FALSE; BOOLEAN PagingIo = FALSE; BOOLEAN NonCachedIo = FALSE; BOOLEAN SynchronousIo = FALSE; - BOOLEAN IsThisADeferredWrite = FALSE; + BOOLEAN IsLazyWriteThread = FALSE; BOOLEAN WriteToEOF = FALSE; BOOLEAN FileSizesChanged = FALSE; BOOLEAN RecursiveWriteThrough = FALSE; - BOOLEAN WriteFileSizeToDirNdx = FALSE; BOOLEAN ZeroBlock = FALSE; BOOLEAN ZeroBlockDone = FALSE; - TmPrint(("UDFCommonWrite: irp %x\n", Irp)); + // Examine our input parameters to determine if this is noncached and/or + // a paging io operation. - _SEH2_TRY { + Wait = BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); + PagingIo = FlagOn(Irp->Flags, IRP_PAGING_IO); + NonCachedIo = FlagOn(Irp->Flags, IRP_NOCACHE); + SynchronousIo = FlagOn(IrpSp->FileObject->Flags, FO_SYNCHRONOUS_IO); + FileObject = IrpSp->FileObject; - TopIrp = IoGetTopLevelIrp(); - - switch((ULONG_PTR)TopIrp) { - case FSRTL_FSP_TOP_LEVEL_IRP: - UDFPrint((" FSRTL_FSP_TOP_LEVEL_IRP\n")); - break; - case FSRTL_CACHE_TOP_LEVEL_IRP: - UDFPrint((" FSRTL_CACHE_TOP_LEVEL_IRP\n")); - break; - case FSRTL_MOD_WRITE_TOP_LEVEL_IRP: - UDFPrint((" FSRTL_MOD_WRITE_TOP_LEVEL_IRP\n")); - break; - case FSRTL_FAST_IO_TOP_LEVEL_IRP: - UDFPrint((" FSRTL_FAST_IO_TOP_LEVEL_IRP\n")); - BrutePoint(); - break; - case NULL: - UDFPrint((" NULL TOP_LEVEL_IRP\n")); - break; - default: - if (TopIrp == Irp) { - UDFPrint((" TOP_LEVEL_IRP\n")); - } else { - UDFPrint((" RECURSIVE_IRP, TOP = %x\n", TopIrp)); - } - break; - } + // Extract and decode the file object. - // First, get a pointer to the current I/O stack location - IrpSp = IoGetCurrentIrpStackLocation(Irp); - ASSERT(IrpSp); - MmPrint((" Enter Irp, MDL=%x\n", Irp->MdlAddress)); + TypeOfOpen = UDFDecodeFileObject(IrpSp->FileObject, &Fcb, &Ccb); - FileObject = IrpSp->FileObject; - ASSERT(FileObject); + if (TypeOfOpen != UserFileOpen && + TypeOfOpen != UserVolumeOpen && + (TypeOfOpen != StreamFileOpen || !NonCachedIo || !PagingIo)) { - // If this is a request at IRQL DISPATCH_LEVEL, then post the request - if (IrpSp->MinorFunction & IRP_MN_DPC) { - try_return(RC = STATUS_PENDING); - } + UDFCompleteRequest(IrpContext, Irp, STATUS_INVALID_DEVICE_REQUEST); + return STATUS_INVALID_DEVICE_REQUEST; + } - // Decode the file object and verify we support read on this. It - // must be a user file, stream file or volume file (for a data disk). + Vcb = Fcb->Vcb; - TypeOfOpen = UDFDecodeFileObject(IrpSp->FileObject, &Fcb, &Ccb); + ASSERT_CCB(Ccb); + ASSERT_FCB(Fcb); + ASSERT_VCB(Vcb); - Vcb = Fcb->Vcb; + // Check if this volume has already been shut down. If it has, fail + // this write request. - ASSERT_CCB(Ccb); - ASSERT_FCB(Fcb); - ASSERT_VCB(Vcb); + if (FlagOn(Vcb->VcbState, VCB_STATE_SHUTDOWN)) { - if (Fcb->FcbState & UDF_FCB_DELETED) { - ASSERT(FALSE); - try_return(RC = STATUS_TOO_LATE); - } + UDFCompleteRequest(IrpContext, Irp, STATUS_TOO_LATE); + return STATUS_TOO_LATE; + } + + if (FlagOn(Vcb->VcbState, VCB_STATE_VOLUME_READ_ONLY) && (TypeOfOpen != UserVolumeOpen)) { - // is this operation allowed ? - if (Vcb->VcbState & VCB_STATE_MEDIA_WRITE_PROTECT) { - try_return(RC = STATUS_ACCESS_DENIED); + if (FlagOn(Vcb->VcbState, VCB_STATE_MEDIA_WRITE_PROTECT)) { + Status = STATUS_MEDIA_WRITE_PROTECTED; + } + else if (PagingIo) { + Status = STATUS_FILE_INVALID; + } + else { + Status = FlagOn(Vcb->VcbState, VCB_STATE_MOUNTED_DIRTY) ? + STATUS_VOLUME_DIRTY : STATUS_ACCESS_DENIED; } - // Disk based file systems might decide to verify the logical volume - // (if required and only if removable media are supported) at this time - // As soon as Tray is locked, we needn't call UDFVerifyVcb() - - ByteOffset = IrpSp->Parameters.Write.ByteOffset; - - CanWait = (IrpContext->Flags & IRP_CONTEXT_FLAG_WAIT) ? TRUE : FALSE; - PagingIo = (Irp->Flags & IRP_PAGING_IO) ? TRUE : FALSE; - NonCachedIo = (Irp->Flags & IRP_NOCACHE) ? TRUE : FALSE; - SynchronousIo = (FileObject->Flags & FO_SYNCHRONOUS_IO) ? TRUE : FALSE; - UDFPrint((" Flags: %s; %s; %s; %s; Irp(W): %8.8x\n", - CanWait ? "Wt" : "nw", PagingIo ? "Pg" : "np", - NonCachedIo ? "NonCached" : "Cached", SynchronousIo ? "Snc" : "Asc", - Irp->Flags)); - - // Get some of the parameters supplied to us - WriteLength = IrpSp->Parameters.Write.Length; - if (WriteLength == 0) { - // a 0 byte write can be immediately succeeded - if (SynchronousIo && !PagingIo && NT_SUCCESS(RC)) { - // NT expects changing CurrentByteOffset to zero in this case - FileObject->CurrentByteOffset.QuadPart = 0; - } - try_return(RC); + UDFCompleteRequest(IrpContext, Irp, Status); + return Status; + } + + // If this is async paging io then check if we are being called by the mapped page writer. + // Convert it back to synchronous if not. + + if (!Wait && PagingIo) { + + Wait = TRUE; + SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); + } + + StartingOffset = IrpSp->Parameters.Write.ByteOffset.QuadPart; + ByteCount = IrpSp->Parameters.Write.Length; + ByteRange = StartingOffset + ByteCount; + + Irp->IoStatus.Information = 0; + + // Check if writing to end of file (FILE_WRITE_TO_END_OF_FILE = -1) + + BOOLEAN WriteToEof = (StartingOffset < 0); + + // Validate file offset - overflow check only for normal offsets + + if (((MAXLONGLONG - StartingOffset) < ByteCount) && !WriteToEof) { + + UDFCompleteRequest(IrpContext, Irp, STATUS_INVALID_PARAMETER); + return STATUS_INVALID_PARAMETER; + } + + // Handle zero-length write + if (ByteCount == 0) { + + UDFCompleteRequest(IrpContext, Irp, STATUS_SUCCESS); + return STATUS_SUCCESS; + } + + // See if we have to defer the write. + + if (!NonCachedIo && + !CcCanIWrite(FileObject, + ByteCount, + (BOOLEAN)(Wait && !BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_IN_FSP)), + BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED_WRITE))) { + + BOOLEAN Retrying = BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED_WRITE); + + UDFPrePostIrp(IrpContext, Irp); + + SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED_WRITE); + + CcDeferWrite(FileObject, UDFDeferredWriteCallBack, IrpContext, Irp, ByteCount, Retrying); + return STATUS_PENDING; + } + + _SEH2_TRY { + + // If this is a request at IRQL DISPATCH_LEVEL, then post the request + if (IrpSp->MinorFunction & IRP_MN_DPC) { + try_return(Status = STATUS_PENDING); } - // If this is the normal file we have to check for - // write access according to the current state of the file locks. - if (!PagingIo && - Fcb->FileLock != NULL && - !FsRtlCheckLockForWriteAccess(Fcb->FileLock, Irp) ) { + // If this is a non paging write to a data stream object we have to + // check for access according to the current state op/filelocks. + // + // Note that after this point, operations will be performed on the file. + // No modifying activity can occur prior to this point in the write + // path. + + if (!PagingIo && TypeOfOpen == UserFileOpen) { + + // And finally check the regular file locks. - try_return( RC = STATUS_FILE_LOCK_CONFLICT ); + if (Fcb->FileLock != NULL && + !FsRtlCheckLockForWriteAccess(Fcb->FileLock, Irp )) { + + try_return(Status = STATUS_FILE_LOCK_CONFLICT); + } } // ********** @@ -185,11 +211,11 @@ UDFCommonWrite( // Yup, we need to send this on to the disk driver after // validation of the offset and length. - if (!CanWait) - try_return(RC = STATUS_PENDING); + if (!Wait) + try_return(Status = STATUS_PENDING); // I dislike the idea of writing to not locked media if (!(Vcb->VcbState & VCB_STATE_LOCKED)) { - try_return(RC = STATUS_ACCESS_DENIED); + try_return(Status = STATUS_ACCESS_DENIED); } if (IrpContext->Flags & UDF_IRP_CONTEXT_FLUSH2_REQUIRED) { @@ -216,76 +242,31 @@ UDFCommonWrite( // Forward the request to the lower level driver // Lock the callers buffer - if (!NT_SUCCESS(RC = UDFLockUserBuffer(IrpContext, WriteLength, IoReadAccess))) { - try_return(RC); + if (!NT_SUCCESS(Status = UDFLockUserBuffer(IrpContext, ByteCount, IoReadAccess))) { + try_return(Status); } SystemBuffer = UDFMapUserBuffer(Irp); if (!SystemBuffer) - try_return(RC = STATUS_INVALID_USER_BUFFER); + try_return(Status = STATUS_INVALID_USER_BUFFER); // Make sure, that volume will never be quick-remounted // It is very important for ChkUdf utility. Vcb->SerialNumber--; // Perform actual Write - RC = UDFTWrite(IrpContext, Vcb, SystemBuffer, WriteLength, - (ULONG)(ByteOffset.QuadPart >> Vcb->SectorShift), + Status = UDFTWrite(IrpContext, Vcb, SystemBuffer, ByteCount, + (ULONG)(StartingOffset >> Vcb->SectorShift), &NumberBytesWritten); UDFUnlockCallersBuffer(IrpContext, Irp, SystemBuffer); - try_return(RC); - } - - if (Vcb->VcbState & VCB_STATE_VOLUME_READ_ONLY) { - try_return(RC = STATUS_ACCESS_DENIED); - } - - // The FSD (if it is a "nice" FSD) should check whether it is - // convenient to allow the write to proceed by utilizing the - // CcCanIWrite() function call. If it is not convenient to perform - // the write at this time, we should defer the request for a while. - // The check should not however be performed for non-cached write - // operations. To determine whether we are retrying the operation - // or now, use Flags in the IrpContext structure we have created - - IsThisADeferredWrite = BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED_WRITE); - - if (!NonCachedIo && - !CcCanIWrite(FileObject, WriteLength, CanWait, IsThisADeferredWrite)) { - - // Cache Manager and/or the VMM does not want us to perform - // the write at this time. Post the request. - - SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED_WRITE); - - CcDeferWrite(FileObject, UDFDeferredWriteCallBack, IrpContext, Irp, WriteLength, IsThisADeferredWrite); - try_return(RC = STATUS_PENDING); - } - - // We can continue. Check whether this write operation is targeted - // to a directory object in which case the UDF FSD will disallow - // the write request. - if (Fcb->FcbState & UDF_FCB_DIRECTORY) { - RC = STATUS_INVALID_DEVICE_REQUEST; - try_return(RC); + try_return(Status); } // Validate start offset and length supplied. // Here is a special check that determines whether the caller wishes to // begin the write at current end-of-file (whatever the value of that // offset might be) - if (ByteOffset.HighPart == (LONG)0xFFFFFFFF) { - if (ByteOffset.LowPart == FILE_WRITE_TO_END_OF_FILE) { - WriteToEOF = TRUE; - ByteOffset = Fcb->Header.FileSize; - } else - if (ByteOffset.LowPart == FILE_USE_FILE_POINTER_POSITION) { - ByteOffset = FileObject->CurrentByteOffset; - } - } - - // Check if this volume has already been shut down. If it has, fail - // this write request. - if (Vcb->VcbState & VCB_STATE_SHUTDOWN) { - try_return(RC = STATUS_TOO_LATE); + if (StartingOffset == -1) { + WriteToEOF = TRUE; + StartingOffset = Fcb->Header.FileSize.QuadPart; } // Paging I/O write operations are special. If paging i/o write @@ -293,15 +274,15 @@ UDFCommonWrite( // If paging i/o // requests extend beyond current end of file, they should be truncated // to current end-of-file. - if (PagingIo && (WriteToEOF || ((ByteOffset.QuadPart + WriteLength) > Fcb->Header.FileSize.QuadPart))) { - if (ByteOffset.QuadPart > Fcb->Header.FileSize.QuadPart) { + if (PagingIo && (WriteToEOF || ((StartingOffset + ByteCount) > Fcb->Header.FileSize.QuadPart))) { + if (StartingOffset > Fcb->Header.FileSize.QuadPart) { TruncatedLength = 0; } else { - TruncatedLength = (ULONG)(Fcb->Header.FileSize.QuadPart - ByteOffset.QuadPart); + TruncatedLength = (ULONG)(Fcb->Header.FileSize.QuadPart - StartingOffset); } - if (!TruncatedLength) try_return(RC = STATUS_SUCCESS); + if (!TruncatedLength) try_return(Status = STATUS_SUCCESS); } else { - TruncatedLength = WriteLength; + TruncatedLength = ByteCount; } // There are certain complications that arise when the same file stream @@ -314,67 +295,63 @@ UDFCommonWrite( // information though the purge will probably fail if the file has been // mapped into some process' virtual address space // WARNING !!! we should not flush data beyond valid data length - if (NonCachedIo && - !PagingIo && + if (!PagingIo && + NonCachedIo && Fcb->FcbNonpaged->SegmentObject.DataSectionObject && TruncatedLength && - (ByteOffset.QuadPart < Fcb->Header.FileSize.QuadPart)) { + (StartingOffset < Fcb->Header.FileSize.QuadPart)) { - // Try to acquire the FCB MainResource exclusively - if (!UDFAcquireResourceExclusive(&Fcb->FcbNonpaged->FcbResource, CanWait)) { - try_return(RC = STATUS_PENDING); - } - MainResourceAcquired = TRUE; + UDFAcquireFcbExclusive(IrpContext, Fcb, FALSE); - // We hold PagingIo exclusive around the flush and CcPurgeCacheSection to fix a - // cache coherency problem. - UDFAcquireResourceExclusive(&Fcb->FcbNonpaged->FcbPagingIoResource, TRUE); - PagingIoResourceAcquired = TRUE; + MainResourceAcquired = TRUE; // Flush and then attempt to purge the cache - if ((ByteOffset.QuadPart + TruncatedLength) > Fcb->Header.FileSize.QuadPart) { + if ((StartingOffset + TruncatedLength) > Fcb->Header.FileSize.QuadPart) { NumberBytesWritten = TruncatedLength; } else { - NumberBytesWritten = (ULONG)(Fcb->Header.FileSize.QuadPart - ByteOffset.QuadPart); + NumberBytesWritten = (ULONG)(Fcb->Header.FileSize.QuadPart - StartingOffset); } - MmPrint((" CcFlushCache()\n")); - CcFlushCache(&Fcb->FcbNonpaged->SegmentObject, &ByteOffset, NumberBytesWritten, &Irp->IoStatus); + CcFlushCache(&Fcb->FcbNonpaged->SegmentObject, + WriteToEof ? &Fcb->Header.FileSize : (PLARGE_INTEGER)&StartingOffset, + NumberBytesWritten, + &Irp->IoStatus); // If the flush failed, return error to the caller - if (!NT_SUCCESS(RC = Irp->IoStatus.Status)) { + if (!NT_SUCCESS(Status = Irp->IoStatus.Status)) { NumberBytesWritten = 0; - try_return(RC); + try_return(Status); } // Attempt the purge - MmPrint((" CcPurgeCacheSection()\n")); - BOOLEAN SuccessfulPurge = CcPurgeCacheSection(&Fcb->FcbNonpaged->SegmentObject, &ByteOffset, - NumberBytesWritten, FALSE); + BOOLEAN SuccessfulPurge = CcPurgeCacheSection(&Fcb->FcbNonpaged->SegmentObject, + (PLARGE_INTEGER)&StartingOffset, + NumberBytesWritten, + FALSE); NumberBytesWritten = 0; - UDFReleaseResource(&Fcb->FcbNonpaged->FcbPagingIoResource); - PagingIoResourceAcquired = FALSE; - // We are finished with our flushing and purging if (!SuccessfulPurge) { - try_return(RC = STATUS_PURGE_FAILED); + try_return(Status = STATUS_PURGE_FAILED); } - - MainResourceCanDemoteToShared = TRUE; } // Determine if we were called by the lazywriter. - // We reuse 'IsThisADeferredWrite' here to decrease stack usage - IsThisADeferredWrite = (Fcb->LazyWriteThread == PsGetCurrentThread()); + + IsLazyWriteThread = (Fcb->LazyWriteThread == PsGetCurrentThread()); // Acquire the appropriate FCB resource if (PagingIo) { - if (!UDFAcquireResourceShared(&Fcb->FcbNonpaged->FcbPagingIoResource, TRUE)) { - try_return(RC = STATUS_PENDING); + // For PagingIo: FcbResource already acquired by UDFAcqLazyWrite/UDFFastIoAcqModWrite + // callback before this function is called + + if (Fcb->FcbState & UDF_FCB_EMBEDDED_DATA) { + ASSERT_EXCLUSIVE_FCB(Fcb); + } + else { + ASSERT_SHARED_FCB(Fcb); } - PagingIoResourceAcquired = TRUE; ASSERT(NonCachedIo); @@ -382,49 +359,25 @@ UDFCommonWrite( // Try to acquire the FCB MainResource shared if (NonCachedIo) { if (!MainResourceAcquired) { - if (!UDFAcquireSharedWaitForExclusive(&Fcb->FcbNonpaged->FcbResource, CanWait)) { - try_return(RC = STATUS_PENDING); + if (!UDFAcquireSharedWaitForExclusive(&Fcb->FcbNonpaged->FcbResource, Wait)) { + try_return(Status = STATUS_PENDING); } MainResourceAcquired = TRUE; } } else { if (!MainResourceAcquired) { UDF_CHECK_PAGING_IO_RESOURCE(Fcb); - if (!UDFAcquireResourceShared(&Fcb->FcbNonpaged->FcbResource, CanWait)) { - try_return(RC = STATUS_PENDING); + if (!UDFAcquireResourceShared(&Fcb->FcbNonpaged->FcbResource, Wait)) { + try_return(Status = STATUS_PENDING); } MainResourceAcquired = TRUE; } } } - // Set the flag indicating if Fast I/O is possible - Fcb->Header.IsFastIoPossible = UDFIsFastIoPossible(Fcb); -/* if (Fcb->CommonFCBHeader.IsFastIoPossible == FastIoIsPossible) { - Fcb->CommonFCBHeader.IsFastIoPossible = FastIoIsQuestionable; - }*/ - - if ((Irp->Flags & IRP_SYNCHRONOUS_PAGING_IO) && - (IrpContext->Flags & UDF_IRP_CONTEXT_NOT_TOP_LEVEL)) { + if (!Ccb || !FlagOn(Ccb->Flags, CCB_FLAG_DISMOUNT_ON_CLOSE)) { - // This clause determines if the top level request was - // in the FastIo path. - if ((ULONG_PTR)TopIrp > FSRTL_MAX_TOP_LEVEL_IRP_FLAG && - NodeType(TopIrp) == IO_TYPE_IRP) { - - PIO_STACK_LOCATION IrpStack; - ASSERT( TopIrp->Type == IO_TYPE_IRP ); - IrpStack = IoGetCurrentIrpStackLocation(TopIrp); - - // Finally this routine detects if the Top irp was a - // write to this file and thus we are the writethrough. - if ((IrpStack->MajorFunction == IRP_MJ_WRITE) && - (IrpStack->FileObject->FsContext == FileObject->FsContext)) { - - RecursiveWriteThrough = TRUE; - IrpContext->Flags |= IRP_CONTEXT_FLAG_WRITE_THROUGH; - } - } + UDFVerifyFcbOperation(IrpContext, Fcb, Ccb); } // Here is the deal with ValidDataLength and FileSize: @@ -450,62 +403,46 @@ UDFCommonWrite( // will subsequently not fail due to lack of disk space. OldVDL = Fcb->Header.ValidDataLength.QuadPart; - ZeroBlock = (ByteOffset.QuadPart > OldVDL); + ZeroBlock = (StartingOffset > OldVDL); if (!PagingIo && !RecursiveWriteThrough && - !IsThisADeferredWrite) { + !IsLazyWriteThread) { BOOLEAN ExtendFS; - ExtendFS = (ByteOffset.QuadPart + TruncatedLength > Fcb->Header.FileSize.QuadPart); + ExtendFS = (StartingOffset + TruncatedLength > Fcb->Header.FileSize.QuadPart); if ( WriteToEOF || ZeroBlock || ExtendFS) { // we are extending the file; - if (!CanWait) - try_return(RC = STATUS_PENDING); + if (!Wait) + try_return(Status = STATUS_PENDING); // CanWait = TRUE; - // Try to acquire the FCB MainResource exclusively - if (!MainResourceAcquiredExclusive) { - - UDFReleaseResource(&Fcb->FcbNonpaged->FcbResource); - MainResourceAcquired = FALSE; - - UDF_CHECK_PAGING_IO_RESOURCE(Fcb); - if (!UDFAcquireResourceExclusive(&Fcb->FcbNonpaged->FcbResource, CanWait)) { - try_return(RC = STATUS_PENDING); - } - MainResourceAcquired = TRUE; - } - UDFAcquireResourceExclusive(&Fcb->FcbNonpaged->FcbPagingIoResource, TRUE); PagingIoResourceAcquired = TRUE; if (ExtendFS) { - RC = UDFResizeFile__(IrpContext, Vcb, Fcb->FileInfo, ByteOffset.QuadPart + TruncatedLength); + Status = UDFResizeFile__(IrpContext, Vcb, Fcb->FileInfo, StartingOffset + TruncatedLength); - if (!NT_SUCCESS(RC)) { - try_return(RC); + if (!NT_SUCCESS(Status)) { + try_return(Status); } FileSizesChanged = TRUE; // ... and inform the Cache Manager about it - Fcb->Header.FileSize.QuadPart = ByteOffset.QuadPart + TruncatedLength; - Fcb->Header.AllocationSize.QuadPart = UDFGetFileAllocationSize(Vcb, Fcb->FileInfo); - if (!Vcb->LowFreeSpace) { - Fcb->Header.AllocationSize.QuadPart += (PAGE_SIZE*9-1); - } else { - Fcb->Header.AllocationSize.QuadPart += (PAGE_SIZE-1); + Fcb->Header.FileSize.QuadPart = StartingOffset + TruncatedLength; + + if (Fcb->Header.AllocationSize.QuadPart < (LONGLONG)LlSectorAlign(Vcb, Fcb->Header.FileSize.QuadPart)) { + + Fcb->Header.AllocationSize.QuadPart = LlSectorAlign(Vcb, Fcb->Header.FileSize.QuadPart); } - Fcb->Header.AllocationSize.LowPart &= ~(PAGE_SIZE-1); } UDFReleaseResource(&Fcb->FcbNonpaged->FcbPagingIoResource); PagingIoResourceAcquired = FALSE; - UDFPrint(("UDFCommonWrite: Set size %x (alloc size %x)\n", ByteOffset.LowPart + TruncatedLength, Fcb->Header.AllocationSize.LowPart)); if (CcIsFileCached(FileObject)) { if (ExtendFS) { MmPrint((" CcSetFileSizes()\n")); @@ -524,7 +461,7 @@ UDFCommonWrite( FileObject, OldVDL, Fcb->Header.FileSize.QuadPart - OldVDL, - CanWait); + Wait); #ifdef UDF_DBG ZeroBlockDone = TRUE; #endif //UDF_DBG @@ -534,26 +471,24 @@ UDFCommonWrite( } - if (Fcb && Fcb->FileInfo && Fcb->FileInfo->Dloc) { - AdPrint(("UDFCommonWrite: DataLoc %x, Mapping %x\n", Fcb->FileInfo->Dloc->DataLoc, Fcb->FileInfo->Dloc->DataLoc.Mapping)); - } + // Branch here for cached vs non-cached I/O - // Branch here for cached vs non-cached I/O if (!NonCachedIo) { // The caller wishes to perform cached I/O. Initiate caching if // this is the first cached I/O operation using this file object + if (!FileObject->PrivateCacheMap) { // This is the first cached I/O operation. You must ensure // that the FCB Header contains valid sizes at this time - UDFPrint(("UDFCommonWrite: Init system cache\n")); - MmPrint((" CcInitializeCacheMap()\n")); - CcInitializeCacheMap(FileObject, (PCC_FILE_SIZES)&Fcb->Header.AllocationSize, - FALSE, // We will not utilize pin access for this file - &(UdfData.CacheMgrCallBacks), // callbacks - Fcb); // The context used in callbacks - MmPrint((" CcSetReadAheadGranularity()\n")); + + CcInitializeCacheMap(FileObject, + (PCC_FILE_SIZES)&Fcb->Header.AllocationSize, + FALSE, + &UdfData.CacheMgrCallBacks, + Fcb); + CcSetReadAheadGranularity(FileObject, READ_AHEAD_GRANULARITY); } @@ -562,16 +497,44 @@ UDFCommonWrite( UDFZeroData(Vcb, FileObject, OldVDL, - ByteOffset.QuadPart + TruncatedLength - OldVDL, - CanWait); - if (ByteOffset.LowPart & (PAGE_SIZE-1)) { + StartingOffset + TruncatedLength - OldVDL, + Wait); + if (StartingOffset & (PAGE_SIZE-1)) { } } - WriteFileSizeToDirNdx = (IrpContext->Flags & IRP_CONTEXT_FLAG_WRITE_THROUGH) ? - TRUE : FALSE; - // Check and see if this request requires a MDL returned to the caller - if (IrpSp->MinorFunction & IRP_MN_MDL) { + // Write to the cache if this is not an Mdl read. + + if (!FlagOn( IrpContext->MinorFunction, IRP_MN_MDL)) { + + // Get hold of the user's buffer. + + SystemBuffer = UDFMapUserBuffer(Irp); + + Fcb->NtReqFCBFlags |= UDF_NTREQ_FCB_MODIFIED; + + if (!CcCopyWrite(FileObject, + (PLARGE_INTEGER)&StartingOffset, + TruncatedLength, + Wait, + SystemBuffer)) { + + // The caller was not prepared to block and data is not immediately + // available in the system cache + // Mark Irp Pending ... + try_return(Status = STATUS_PENDING); + } + + UDFUnlockCallersBuffer(IrpContext, Irp, SystemBuffer); + // We have the data + Status = STATUS_SUCCESS; + NumberBytesWritten = TruncatedLength; + + try_return(Status); + + // Otherwise perform the MdlRead operation. + + } else { // Caller does want a MDL returned. Note that this mode // implies that the caller is prepared to block MmPrint((" CcPrepareMdlWrite()\n")); @@ -580,37 +543,10 @@ UDFCommonWrite( // RC = Irp->IoStatus.Status; NumberBytesWritten = 0; - RC = STATUS_INVALID_PARAMETER; + Status = STATUS_INVALID_PARAMETER; - try_return(RC); + try_return(Status); } - - // This is a regular run-of-the-mill cached I/O request. Let the - // Cache Manager worry about it! - // First though, we need a buffer pointer (address) that is valid - - // We needn't call CcZeroData 'cause udf_info.cpp will care about it - SystemBuffer = UDFMapUserBuffer(Irp); - if (!SystemBuffer) - try_return(RC = STATUS_INVALID_USER_BUFFER); - ASSERT(SystemBuffer); - Fcb->NtReqFCBFlags |= UDF_NTREQ_FCB_MODIFIED; - - MmPrint((" CcCopyWrite()\n")); - if (!CcCopyWrite(FileObject, &(ByteOffset), TruncatedLength, CanWait, SystemBuffer)) { - // The caller was not prepared to block and data is not immediately - // available in the system cache - // Mark Irp Pending ... - try_return(RC = STATUS_PENDING); - } - - UDFUnlockCallersBuffer(IrpContext, Irp, SystemBuffer); - // We have the data - RC = STATUS_SUCCESS; - NumberBytesWritten = TruncatedLength; - - try_return(RC); - } else { MmPrint((" Write NonCachedIo\n")); @@ -619,115 +555,91 @@ UDFCommonWrite( // 'cause we've already done it above // (see call to UDFZeroDataEx() ) if (!RecursiveWriteThrough && - !IsThisADeferredWrite && - (OldVDL < ByteOffset.QuadPart)) { + !IsLazyWriteThread && + (OldVDL < StartingOffset)) { #ifdef UDF_DBG ASSERT(!ZeroBlockDone); #endif //UDF_DBG UDFZeroData(Vcb, FileObject, OldVDL, - ByteOffset.QuadPart - OldVDL, - CanWait); + StartingOffset - OldVDL, + Wait); } - if (OldVDL < (ByteOffset.QuadPart + TruncatedLength)) { - Fcb->Header.ValidDataLength.QuadPart = ByteOffset.QuadPart + TruncatedLength; + if (OldVDL < (StartingOffset + TruncatedLength)) { + Fcb->Header.ValidDataLength.QuadPart = StartingOffset + TruncatedLength; } // Send the request to lower level drivers - if (!CanWait) { - UDFPrint(("UDFCommonWrite: Post physical write %x bytes at %x\n", TruncatedLength, ByteOffset.LowPart)); + if (!Wait) { + UDFPrint(("UDFCommonWrite: Post physical write %x bytes at %x\n", TruncatedLength, StartingOffset.LowPart)); - try_return(RC = STATUS_PENDING); + try_return(Status = STATUS_PENDING); } // Lock the callers buffer - if (!NT_SUCCESS(RC = UDFLockUserBuffer(IrpContext, TruncatedLength, IoReadAccess))) { - try_return(RC); + if (!NT_SUCCESS(Status = UDFLockUserBuffer(IrpContext, TruncatedLength, IoReadAccess))) { + try_return(Status); } SystemBuffer = UDFMapUserBuffer(Irp); if (!SystemBuffer) { - try_return(RC = STATUS_INVALID_USER_BUFFER); + try_return(Status = STATUS_INVALID_USER_BUFFER); } Fcb->NtReqFCBFlags |= UDF_NTREQ_FCB_MODIFIED; - RC = UDFWriteFile__(IrpContext, Vcb, Fcb->FileInfo, ByteOffset.QuadPart, TruncatedLength, + Status = UDFWriteFile__(IrpContext, Vcb, Fcb->FileInfo, StartingOffset, TruncatedLength, FALSE, (PCHAR)SystemBuffer, &NumberBytesWritten); UDFUnlockCallersBuffer(IrpContext, Irp, SystemBuffer); - WriteFileSizeToDirNdx = TRUE; + ASize = UDFGetFileAllocationSize(Vcb, Fcb->FileInfo); + UDFSetFileSizeInDirNdx(Vcb, Fcb->FileInfo, &ASize); - try_return(RC); + try_return(Status); } try_exit: NOTHING; } _SEH2_FINALLY { - if (RC == STATUS_PENDING) { - - // Release any resources acquired here ... - if (PagingIoResourceAcquired) { - UDFReleaseResource(&Fcb->FcbNonpaged->FcbPagingIoResource); - } - - if (MainResourceAcquired) { - UDF_CHECK_PAGING_IO_RESOURCE(Fcb); - UDFReleaseResource(&Fcb->FcbNonpaged->FcbResource); - } + if (Irp != NULL) { + Irp->IoStatus.Information = NumberBytesWritten; + Irp->IoStatus.Status = Status; + } - if (VcbAcquired) { - UDFReleaseResource(&Vcb->VcbResource); - } + if (NT_SUCCESS(Status) && !AbnormalTermination()) { - } else { // For synchronous I/O, the FSD must maintain the current byte offset // Do not do this however, if I/O is marked as paging-io - if (SynchronousIo && !PagingIo && NT_SUCCESS(RC)) { - FileObject->CurrentByteOffset.QuadPart = ByteOffset.QuadPart + NumberBytesWritten; + + if (SynchronousIo && !PagingIo && NT_SUCCESS(Status)) { + FileObject->CurrentByteOffset.QuadPart = StartingOffset + NumberBytesWritten; } + // If the write completed successfully and this was not a paging-io // operation, set a flag in the CCB that indicates that a write was // performed and that the file time should be updated at cleanup - if (NT_SUCCESS(RC) && !PagingIo) { + + if (NT_SUCCESS(Status) && !PagingIo) { + // If the file size was changed, set a flag in the FCB indicating that // this occurred. - SetFlag(FileObject->Flags, FO_FILE_MODIFIED); - - if (FileSizesChanged) { - if (!WriteFileSizeToDirNdx) { - - FileObject->Flags |= FO_FILE_SIZE_CHANGED; - } else { - - ASize = UDFGetFileAllocationSize(Vcb, Fcb->FileInfo); - UDFSetFileSizeInDirNdx(Vcb, Fcb->FileInfo, &ASize); - - if (UDFIsAStream(Fcb->FileInfo)) { - - UDFNotifyFullReportChange(Vcb, - Fcb, - FILE_NOTIFY_CHANGE_STREAM_SIZE, - FILE_ACTION_MODIFIED_STREAM); - } else { - - UDFNotifyFullReportChange(Vcb, - Fcb, - FILE_NOTIFY_CHANGE_SIZE, - FILE_ACTION_MODIFIED); - } - } + SetFlag(FileObject->Flags, FO_FILE_MODIFIED); + + if (FileSizesChanged) { + + SetFlag(FileObject->Flags, FO_FILE_SIZE_CHANGED); } + // Update ValidDataLength - if (!IsThisADeferredWrite) { + if (!IsLazyWriteThread) { - if (Fcb->Header.ValidDataLength.QuadPart < (ByteOffset.QuadPart + NumberBytesWritten)) { + if (Fcb->Header.ValidDataLength.QuadPart < (StartingOffset + NumberBytesWritten)) { Fcb->Header.ValidDataLength.QuadPart = min(Fcb->Header.FileSize.QuadPart, - ByteOffset.QuadPart + NumberBytesWritten); + StartingOffset + NumberBytesWritten); if (NonCachedIo && CcIsFileCached(FileObject)) { CcSetFileSizes(FileObject, (PCC_FILE_SIZES)&Fcb->Header.AllocationSize); @@ -735,47 +647,38 @@ try_exit: NOTHING; } } } + } - // Release any resources acquired here ... - if (PagingIoResourceAcquired) { - UDFReleaseResource(&Fcb->FcbNonpaged->FcbPagingIoResource); - } + // Release any resources acquired here ... - if (MainResourceAcquired) { - UDF_CHECK_PAGING_IO_RESOURCE(Fcb); - UDFReleaseResource(&Fcb->FcbNonpaged->FcbResource); - } + if (PagingIoResourceAcquired) { + UDFReleaseResource(&Fcb->FcbNonpaged->FcbPagingIoResource); + } - if (VcbAcquired) { - UDFReleaseResource(&Vcb->VcbResource); - } - // If the request failed, and we had done some nasty stuff like - // extending the file size (including informing the Cache Manager - // about the new file size), and allocating on-disk space etc., undo - // it at this time. - - // Can complete the IRP here if no exception was encountered - if (!_SEH2_AbnormalTermination() && - Irp) { - Irp->IoStatus.Status = RC; - Irp->IoStatus.Information = NumberBytesWritten; - } + if (MainResourceAcquired) { + UDF_CHECK_PAGING_IO_RESOURCE(Fcb); + UDFReleaseResource(&Fcb->FcbNonpaged->FcbResource); } + + if (VcbAcquired) { + UDFReleaseResource(&Vcb->VcbResource); + } + } _SEH2_END; // end of "__finally" processing // Post IRP if required - if (RC == STATUS_PENDING) { + if (Status == STATUS_PENDING) { - RC = UDFFsdPostRequest(IrpContext, Irp); - } - else { + Status = UDFFsdPostRequest(IrpContext, Irp); + + } else { - UDFCompleteRequest(IrpContext, Irp, RC); + UDFCompleteRequest(IrpContext, Irp, Status); } UDFPrint(("\n")); - return(RC); + return(Status); } // end UDFCommonWrite() /************************************************************************* From a3305a9413f031174379812c5f74f0142dea4899 Mon Sep 17 00:00:00 2001 From: Gleb Lamm Date: Sun, 15 Feb 2026 02:28:45 +0400 Subject: [PATCH 4/9] UDFInsertPrefix --- drivers/filesystems/udfs/prefxsup.cpp | 352 ++++++++++++++++++++++++++ 1 file changed, 352 insertions(+) create mode 100644 drivers/filesystems/udfs/prefxsup.cpp diff --git a/drivers/filesystems/udfs/prefxsup.cpp b/drivers/filesystems/udfs/prefxsup.cpp new file mode 100644 index 0000000000000..a520cef8ac3e8 --- /dev/null +++ b/drivers/filesystems/udfs/prefxsup.cpp @@ -0,0 +1,352 @@ +//////////////////////////////////////////////////////////////////// +// Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine +// All rights reserved +// This file was released under the GPLv2 on June 2015. +//////////////////////////////////////////////////////////////////// +/* + + File: PrefxSup.cpp + + Module: UDF File System Driver (Kernel mode execution only) + + Description: + This module implements the UDF Prefix support routines. + Based on Microsoft UDF driver pattern. + +*/ + +#include "udffs.h" + +// define the file specific bug-check id +#define UDF_BUG_CHECK_ID UDF_FILE_MISC + +/* + This routine creates and inserts an LCB linking the parent FCB to child FCB. + + Similar to MS UdfInsertPrefix but simplified - we don't use splay trees + for prefix lookup since we use FileInfo-based navigation. + + The LCB is linked into: + - ParentFcb->ChildLcbQueue (via Lcb->ParentFcbLinks) + - ChildFcb->ParentLcbQueue (via Lcb->ChildFcbLinks) +*/ +PLCB +UDFInsertPrefix( + IN PIRP_CONTEXT IrpContext, + IN PFCB ParentFcb, + IN PFCB ChildFcb, + IN ULONG Index + ) +{ + PLCB Lcb; + ULONG Flags = 0; + + UNREFERENCED_PARAMETER(IrpContext); + + ASSERT(ParentFcb); + ASSERT(ChildFcb); + + // + // Allocate LCB - use lookaside for small allocations + // + if (sizeof(LCB) > SIZEOF_LOOKASIDE_LCB) { + + Lcb = (PLCB)FsRtlAllocatePoolWithTag(PagedPool, + sizeof(LCB), + TAG_LCB); + if (!Lcb) { + return NULL; + } + + SetFlag(Flags, UDF_LCB_FLAG_POOL_ALLOCATED); + + } else { + + Lcb = (PLCB)ExAllocateFromPagedLookasideList(&UdfData.LcbLookasideList); + if (!Lcb) { + return NULL; + } + } + + // + // Initialize LCB + // + RtlZeroMemory(Lcb, sizeof(LCB)); + + Lcb->NodeIdentifier.NodeTypeCode = UDF_NODE_TYPE_LCB; + Lcb->NodeIdentifier.NodeByteSize = sizeof(LCB); + + // Set up FCB pointers + Lcb->ParentFcb = ParentFcb; + Lcb->ChildFcb = ChildFcb; + Lcb->Index = Index; + + // Set flags + Lcb->Flags = Flags; + + // Initial reference count + Lcb->Reference = 0; + + // + // Link LCB into the FCB queues + // + // Insert into parent's child queue + InsertHeadList(&ParentFcb->ChildLcbQueue, &Lcb->ParentFcbLinks); + // Insert into child's parent queue + InsertHeadList(&ChildFcb->ParentLcbQueue, &Lcb->ChildFcbLinks); + + return Lcb; +} // end UDFInsertPrefix() + + +/* + This routine removes an LCB from FCB queues and frees it. +*/ +VOID +UDFRemovePrefix( + IN PIRP_CONTEXT IrpContext, + IN PLCB Lcb + ) +{ + UNREFERENCED_PARAMETER(IrpContext); + + if (!Lcb) { + return; + } + + ASSERT(Lcb->NodeIdentifier.NodeTypeCode == UDF_NODE_TYPE_LCB); + + // + // Remove from parent FCB's ChildLcbQueue + // + RemoveEntryList(&Lcb->ParentFcbLinks); + InitializeListHead(&Lcb->ParentFcbLinks); + + // + // Remove from child FCB's ParentLcbQueue + // + RemoveEntryList(&Lcb->ChildFcbLinks); + InitializeListHead(&Lcb->ChildFcbLinks); + + // + // Free the LCB based on how it was allocated + // + if (FlagOn(Lcb->Flags, UDF_LCB_FLAG_POOL_ALLOCATED)) { + + ExFreePool(Lcb); + + } else { + + ExFreeToPagedLookasideList(&UdfData.LcbLookasideList, Lcb); + } +} // end UDFRemovePrefix() + + +/* + This routine finds an existing LCB linking the parent FCB to child FCB. + Returns NULL if no such LCB exists. +*/ +PLCB +UDFFindPrefix( + IN PIRP_CONTEXT IrpContext, + IN PFCB ParentFcb, + IN PFCB ChildFcb + ) +{ + PLIST_ENTRY ListEntry; + PLCB Lcb; + + UNREFERENCED_PARAMETER(IrpContext); + + ASSERT(ParentFcb); + ASSERT(ChildFcb); + + // + // Walk the child FCB's ParentLcbQueue to find LCB pointing to this parent + // + for (ListEntry = ChildFcb->ParentLcbQueue.Flink; + ListEntry != &ChildFcb->ParentLcbQueue; + ListEntry = ListEntry->Flink) { + + Lcb = CONTAINING_RECORD(ListEntry, LCB, ChildFcbLinks); + + ASSERT(Lcb->NodeIdentifier.NodeTypeCode == UDF_NODE_TYPE_LCB); + + if (Lcb->ParentFcb == ParentFcb) { + return Lcb; + } + } + + return NULL; +} // end UDFFindPrefix() + + +/* + This routine acquires or creates an LCB linking the parent FCB to child FCB. + If LCB already exists, increments its Reference count. + If new LCB is created: + - Increments parent FCB's FcbReference + - Increments parent's FileInfo->RefCount (if available) + + This is the primary function to call when establishing a parent-child + relationship during file open. + + Returns the LCB (existing or newly created), or NULL on allocation failure. +*/ +PLCB +UDFAcquirePrefix( + IN PIRP_CONTEXT IrpContext, + IN PFCB ParentFcb, + IN PFCB ChildFcb, + IN ULONG Index + ) +{ + PLCB Lcb; + + UNREFERENCED_PARAMETER(IrpContext); + + ASSERT(ParentFcb); + ASSERT(ChildFcb); + + // + // First try to find existing LCB + // + Lcb = UDFFindPrefix(IrpContext, ParentFcb, ChildFcb); + + if (Lcb) { + // + // Found existing LCB - just increment reference + // + InterlockedIncrement((PLONG)&Lcb->Reference); + return Lcb; + } + + // + // Need to create new LCB + // + Lcb = UDFInsertPrefix(IrpContext, ParentFcb, ChildFcb, Index); + + if (Lcb) { + // + // New LCB created - set initial reference and increment parent's references + // The parent's FcbReference represents this LCB's existence + // + Lcb->Reference = 1; + InterlockedIncrement((PLONG)&ParentFcb->FcbReference); + + // + // Also reference parent's FileInfo if available + // This mirrors how TreeLength used to work - parent is referenced + // for each child link. When LCB is removed, we'll call UDFCloseFile__. + // + if (ParentFcb->FileInfo) { + UDFReferenceFile__(ParentFcb->FileInfo); + } + } + + return Lcb; +} // end UDFAcquirePrefix() + + +/* + This routine releases a reference to an LCB. + If Reference goes to zero, the LCB is eligible for removal during teardown. + + Note: This does NOT remove the LCB or decrement parent's FcbReference. + That is done during teardown when walking the ParentLcbQueue. +*/ +VOID +UDFReleasePrefix( + IN PIRP_CONTEXT IrpContext, + IN PLCB Lcb + ) +{ + UNREFERENCED_PARAMETER(IrpContext); + + if (!Lcb) { + return; + } + + ASSERT(Lcb->NodeIdentifier.NodeTypeCode == UDF_NODE_TYPE_LCB); + ASSERT(Lcb->Reference > 0); + + InterlockedDecrement((PLONG)&Lcb->Reference); +} // end UDFReleasePrefix() + + +/* + This routine releases a reference to an LCB and, if Reference becomes 0, + immediately removes the LCB and decrements parent references. + + This is used during rename operations where we need immediate cleanup + of the old parent link rather than waiting for teardown. + + Parameters: + IrpContext - The IRP context + Lcb - The LCB to release + CloseParentFileInfo - If TRUE and LCB is removed, call UDFCloseFile__ + on parent's FileInfo + + Returns: + TRUE if the LCB was removed, FALSE if it still has references +*/ +BOOLEAN +UDFReleasePrefixImmediate( + IN PIRP_CONTEXT IrpContext, + IN PLCB Lcb, + IN BOOLEAN CloseParentFileInfo + ) +{ + PFCB ParentFcb; + PUDF_FILE_INFO ParentFileInfo; + PVCB Vcb; + LONG NewRef; + + if (!Lcb) { + return FALSE; + } + + ASSERT(Lcb->NodeIdentifier.NodeTypeCode == UDF_NODE_TYPE_LCB); + ASSERT(Lcb->Reference > 0); + + // + // Decrement reference + // + NewRef = InterlockedDecrement((PLONG)&Lcb->Reference); + + if (NewRef > 0) { + // + // Still has references, leave it in place + // + return FALSE; + } + + // + // Reference is now 0 - remove LCB and decrement parent refs + // + ParentFcb = Lcb->ParentFcb; + ParentFileInfo = ParentFcb ? ParentFcb->FileInfo : NULL; + Vcb = ParentFcb ? ParentFcb->Vcb : NULL; + + // + // Remove LCB from queues and free it + // + UDFRemovePrefix(IrpContext, Lcb); + + // + // Decrement parent's FcbReference + // + if (ParentFcb) { + ASSERT(ParentFcb->FcbReference > 0); + InterlockedDecrement((PLONG)&ParentFcb->FcbReference); + + // + // Close parent's FileInfo if requested + // + if (CloseParentFileInfo && ParentFileInfo && Vcb) { + UDFCloseFile__(IrpContext, Vcb, ParentFileInfo); + } + } + + return TRUE; +} // end UDFReleasePrefixImmediate() From c56cb496a49151d9f02f8033d3853e4bb9c5e930 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 6 Apr 2026 17:12:26 +0000 Subject: [PATCH 5/9] Initial plan From b2e30f32014c74e181e381835f40b516d1395e31 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 6 Apr 2026 17:20:03 +0000 Subject: [PATCH 6/9] [UDFS] Add NULL guard in UDFDOSName to prevent BSOD on shutdown Agent-Logs-Url: https://github.com/Zero3K20/reactos/sessions/c1c0cdb3-4750-45b4-9a7b-e6a44af0a863 Co-authored-by: Zero3K20 <258969903+Zero3K20@users.noreply.github.com> --- drivers/filesystems/udfs/udf_info/udf_info.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/filesystems/udfs/udf_info/udf_info.cpp b/drivers/filesystems/udfs/udf_info/udf_info.cpp index e5d0b699e4947..b46b5e6cd695f 100644 --- a/drivers/filesystems/udfs/udf_info/udf_info.cpp +++ b/drivers/filesystems/udfs/udf_info/udf_info.cpp @@ -392,6 +392,11 @@ UDFDOSName( IN BOOLEAN KeepIntact ) { + if (!UdfName->Buffer) { + DosName->Length = 0; + return; + } + switch(Vcb->UdfRevision) { case 0x0100: case 0x0101: From d0a5c761a7c1124318c6e6a6fa2de40ad1d95679 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 6 Apr 2026 17:34:07 +0000 Subject: [PATCH 7/9] [UDFS] Fix NULL-free in UDFBuildHashEntry causing BSOD (0xC4/0x10) Agent-Logs-Url: https://github.com/Zero3K20/reactos/sessions/3dcd238c-3d98-44d0-8304-bcccad17e060 Co-authored-by: Zero3K20 <258969903+Zero3K20@users.noreply.github.com> --- drivers/filesystems/udfs/udf_info/dirtree.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/filesystems/udfs/udf_info/dirtree.cpp b/drivers/filesystems/udfs/udf_info/dirtree.cpp index 247376ff93ce7..b21c4b68f4573 100644 --- a/drivers/filesystems/udfs/udf_info/dirtree.cpp +++ b/drivers/filesystems/udfs/udf_info/dirtree.cpp @@ -401,10 +401,10 @@ UDFBuildHashEntry( RetFlags |= UDF_FI_FLAG_LFN; }*/ hashes->hLfn = crc32((uint8*)(UName.Buffer), UName.Length); + MyFreePool__(UName.Buffer); } else { BrutePoint(); } - MyFreePool__(UName.Buffer); } if (Mask & HASH_DOS) { From e6abf0823ff53484026679bfd411f710c4803964 Mon Sep 17 00:00:00 2001 From: Zero3K20 Date: Wed, 15 Apr 2026 10:03:20 -0400 Subject: [PATCH 8/9] Revert "[UDFS] Fix NULL-free in UDFBuildHashEntry causing BSOD (0xC4/0x10)" This reverts commit d0a5c761a7c1124318c6e6a6fa2de40ad1d95679. --- drivers/filesystems/udfs/udf_info/dirtree.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/filesystems/udfs/udf_info/dirtree.cpp b/drivers/filesystems/udfs/udf_info/dirtree.cpp index b21c4b68f4573..247376ff93ce7 100644 --- a/drivers/filesystems/udfs/udf_info/dirtree.cpp +++ b/drivers/filesystems/udfs/udf_info/dirtree.cpp @@ -401,10 +401,10 @@ UDFBuildHashEntry( RetFlags |= UDF_FI_FLAG_LFN; }*/ hashes->hLfn = crc32((uint8*)(UName.Buffer), UName.Length); - MyFreePool__(UName.Buffer); } else { BrutePoint(); } + MyFreePool__(UName.Buffer); } if (Mask & HASH_DOS) { From 25c7f67bdb10afbb8d927374e7f70b4432377ba4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 27 Apr 2026 15:24:05 +0000 Subject: [PATCH 9/9] [UDFS] Fix NULL-free in UDFBuildHashEntry by moving free to success branch Agent-Logs-Url: https://github.com/Zero3K20/reactos/sessions/9e27b4ec-27d9-43e4-901c-8ea09c8ae9dd Co-authored-by: Zero3K20 <258969903+Zero3K20@users.noreply.github.com> --- drivers/filesystems/udfs/udf_info/dirtree.cpp | 8 +++++--- drivers/filesystems/udfs/udf_info/udf_info.cpp | 5 ----- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/drivers/filesystems/udfs/udf_info/dirtree.cpp b/drivers/filesystems/udfs/udf_info/dirtree.cpp index e4ed3534956e4..fea350ca82c9a 100644 --- a/drivers/filesystems/udfs/udf_info/dirtree.cpp +++ b/drivers/filesystems/udfs/udf_info/dirtree.cpp @@ -398,9 +398,11 @@ UDFBuildHashEntry( UName.MaximumLength = Name->Length; UName.Buffer = (PWCHAR)FsRtlAllocatePoolWithTag(NonPagedPool, UName.MaximumLength, TAG_FILE_NAME); - RtlUpcaseUnicodeString(&UName, Name, FALSE); - hashes->hLfn = crc32((uint8*)(UName.Buffer), UName.Length); - ExFreePoolWithTag(UName.Buffer, TAG_FILE_NAME); + if (UName.Buffer) { + RtlUpcaseUnicodeString(&UName, Name, FALSE); + hashes->hLfn = crc32((uint8*)(UName.Buffer), UName.Length); + ExFreePoolWithTag(UName.Buffer, TAG_FILE_NAME); + } } if (Mask & HASH_DOS) { diff --git a/drivers/filesystems/udfs/udf_info/udf_info.cpp b/drivers/filesystems/udfs/udf_info/udf_info.cpp index e70ef86baa42e..e9556aa93de31 100644 --- a/drivers/filesystems/udfs/udf_info/udf_info.cpp +++ b/drivers/filesystems/udfs/udf_info/udf_info.cpp @@ -367,11 +367,6 @@ UDFDOSName( IN BOOLEAN KeepIntact ) { - if (!UdfName->Buffer) { - DosName->Length = 0; - return; - } - switch(Vcb->UdfRevision) { case 0x0100: case 0x0101: