From cffe655cef17faa700e627e74e593b186cab11a5 Mon Sep 17 00:00:00 2001 From: Gleb Lamm Date: Tue, 3 Feb 2026 01:26:59 +0400 Subject: [PATCH 01/20] 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 02/20] 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 bb810f0c2a2e0c8d7dc450bfba1db480c3d1c469 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 6 Mar 2026 02:33:27 +0000 Subject: [PATCH 03/20] Initial plan From f6f605d1fdda9a865513219ecbce27e77b08474d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 6 Mar 2026 02:41:01 +0000 Subject: [PATCH 04/20] [UDFS] Convert C++ to C for MinGW compatibility Co-authored-by: Zero3K20 <258969903+Zero3K20@users.noreply.github.com> --- drivers/filesystems/udfs/CMakeLists.txt | 77 +++++++++---------- .../{Sys_spec_lib.cpp => Sys_spec_lib.c} | 2 +- .../Include/{mem_tools.cpp => mem_tools.c} | 0 .../udfs/Include/{phys_lib.cpp => phys_lib.c} | 2 +- .../udfs/Include/{regtools.cpp => regtools.c} | 0 .../Include/{string_lib.cpp => string_lib.c} | 4 - .../udfs/{cleanup.cpp => cleanup.c} | 2 +- .../filesystems/udfs/{close.cpp => close.c} | 2 +- .../filesystems/udfs/{create.cpp => create.c} | 0 .../udfs/{devcntrl.cpp => devcntrl.c} | 2 +- .../udfs/{dircntrl.cpp => dircntrl.c} | 2 +- .../udfs/{env_spec.cpp => env_spec.c} | 2 +- .../filesystems/udfs/{fastio.cpp => fastio.c} | 2 +- .../udfs/{fileinfo.cpp => fileinfo.c} | 2 +- .../udfs/{filobsup.cpp => filobsup.c} | 0 .../filesystems/udfs/{flush.cpp => flush.c} | 2 +- .../udfs/{fscntrl.cpp => fscntrl.c} | 2 +- .../udfs/{lockctrl.cpp => lockctrl.c} | 2 +- drivers/filesystems/udfs/{mem.cpp => mem.c} | 2 +- drivers/filesystems/udfs/{misc.cpp => misc.c} | 6 +- .../udfs/{namesup.cpp => namesup.c} | 2 +- drivers/filesystems/udfs/{pnp.cpp => pnp.c} | 2 +- .../udfs/{prefxsup.cpp => prefxsup.c} | 2 +- drivers/filesystems/udfs/protos.h | 52 ++++++------- drivers/filesystems/udfs/{read.cpp => read.c} | 2 +- .../udfs/{secursup.cpp => secursup.c} | 2 +- .../udfs/{shutdown.cpp => shutdown.c} | 2 +- .../udfs/{strucsup.cpp => strucsup.c} | 16 ++-- .../udfs/{sys_spec.cpp => sys_spec.c} | 6 +- .../udfs/{udf_dbg.cpp => udf_dbg.c} | 0 .../udfs/udf_info/{alloc.cpp => alloc.c} | 2 +- .../udfs/udf_info/{dirtree.cpp => dirtree.c} | 2 +- .../udfs/udf_info/{extent.cpp => extent.c} | 2 +- .../udfs/udf_info/{mount.cpp => mount.c} | 2 +- .../udf_info/{phys_eject.cpp => phys_eject.c} | 2 +- .../udf_info/{physical.cpp => physical.c} | 4 +- .../udfs/udf_info/{remap.cpp => remap.c} | 2 +- .../udf_info/{udf_info.cpp => udf_info.c} | 2 +- .../udfs/{udfdata.cpp => udfdata.c} | 2 +- drivers/filesystems/udfs/udffs.h | 6 +- .../udfs/{udfinit.cpp => udfinit.c} | 2 +- .../filesystems/udfs/{unload.cpp => unload.c} | 0 .../udfs/{verfysup.cpp => verfysup.c} | 2 +- .../udfs/{volinfo.cpp => volinfo.c} | 2 +- .../filesystems/udfs/{write.cpp => write.c} | 4 +- 45 files changed, 114 insertions(+), 121 deletions(-) rename drivers/filesystems/udfs/Include/{Sys_spec_lib.cpp => Sys_spec_lib.c} (99%) rename drivers/filesystems/udfs/Include/{mem_tools.cpp => mem_tools.c} (100%) rename drivers/filesystems/udfs/Include/{phys_lib.cpp => phys_lib.c} (99%) rename drivers/filesystems/udfs/Include/{regtools.cpp => regtools.c} (100%) rename drivers/filesystems/udfs/Include/{string_lib.cpp => string_lib.c} (98%) rename drivers/filesystems/udfs/{cleanup.cpp => cleanup.c} (99%) rename drivers/filesystems/udfs/{close.cpp => close.c} (99%) rename drivers/filesystems/udfs/{create.cpp => create.c} (100%) rename drivers/filesystems/udfs/{devcntrl.cpp => devcntrl.c} (99%) rename drivers/filesystems/udfs/{dircntrl.cpp => dircntrl.c} (99%) rename drivers/filesystems/udfs/{env_spec.cpp => env_spec.c} (99%) rename drivers/filesystems/udfs/{fastio.cpp => fastio.c} (99%) rename drivers/filesystems/udfs/{fileinfo.cpp => fileinfo.c} (99%) rename drivers/filesystems/udfs/{filobsup.cpp => filobsup.c} (100%) rename drivers/filesystems/udfs/{flush.cpp => flush.c} (99%) rename drivers/filesystems/udfs/{fscntrl.cpp => fscntrl.c} (99%) rename drivers/filesystems/udfs/{lockctrl.cpp => lockctrl.c} (99%) rename drivers/filesystems/udfs/{mem.cpp => mem.c} (93%) rename drivers/filesystems/udfs/{misc.cpp => misc.c} (99%) rename drivers/filesystems/udfs/{namesup.cpp => namesup.c} (99%) rename drivers/filesystems/udfs/{pnp.cpp => pnp.c} (99%) rename drivers/filesystems/udfs/{prefxsup.cpp => prefxsup.c} (99%) rename drivers/filesystems/udfs/{read.cpp => read.c} (99%) rename drivers/filesystems/udfs/{secursup.cpp => secursup.c} (99%) rename drivers/filesystems/udfs/{shutdown.cpp => shutdown.c} (99%) rename drivers/filesystems/udfs/{strucsup.cpp => strucsup.c} (99%) rename drivers/filesystems/udfs/{sys_spec.cpp => sys_spec.c} (89%) rename drivers/filesystems/udfs/{udf_dbg.cpp => udf_dbg.c} (100%) rename drivers/filesystems/udfs/udf_info/{alloc.cpp => alloc.c} (99%) rename drivers/filesystems/udfs/udf_info/{dirtree.cpp => dirtree.c} (99%) rename drivers/filesystems/udfs/udf_info/{extent.cpp => extent.c} (99%) rename drivers/filesystems/udfs/udf_info/{mount.cpp => mount.c} (99%) rename drivers/filesystems/udfs/udf_info/{phys_eject.cpp => phys_eject.c} (98%) rename drivers/filesystems/udfs/udf_info/{physical.cpp => physical.c} (90%) rename drivers/filesystems/udfs/udf_info/{remap.cpp => remap.c} (99%) rename drivers/filesystems/udfs/udf_info/{udf_info.cpp => udf_info.c} (99%) rename drivers/filesystems/udfs/{udfdata.cpp => udfdata.c} (99%) rename drivers/filesystems/udfs/{udfinit.cpp => udfinit.c} (99%) rename drivers/filesystems/udfs/{unload.cpp => unload.c} (100%) rename drivers/filesystems/udfs/{verfysup.cpp => verfysup.c} (99%) rename drivers/filesystems/udfs/{volinfo.cpp => volinfo.c} (99%) rename drivers/filesystems/udfs/{write.cpp => write.c} (99%) diff --git a/drivers/filesystems/udfs/CMakeLists.txt b/drivers/filesystems/udfs/CMakeLists.txt index 1ae3d50d9b070..09e4e7d57f7f4 100644 --- a/drivers/filesystems/udfs/CMakeLists.txt +++ b/drivers/filesystems/udfs/CMakeLists.txt @@ -2,55 +2,52 @@ include_directories(Include) list(APPEND SOURCE - udf_info/alloc.cpp - udf_info/dirtree.cpp - udf_info/extent.cpp - udf_info/mount.cpp - udf_info/phys_eject.cpp - udf_info/physical.cpp - udf_info/remap.cpp - udf_info/udf_info.cpp - cleanup.cpp - close.cpp - create.cpp - devcntrl.cpp - dircntrl.cpp - env_spec.cpp - fastio.cpp - fileinfo.cpp - flush.cpp - fscntrl.cpp - lockctrl.cpp - mem.cpp - misc.cpp - namesup.cpp - prefxsup.cpp - pnp.cpp - read.cpp - secursup.cpp - shutdown.cpp - sys_spec.cpp - udf_dbg.cpp - udfinit.cpp - unload.cpp - verfysup.cpp - volinfo.cpp - write.cpp - strucsup.cpp - filobsup.cpp - udfdata.cpp + udf_info/alloc.c + udf_info/dirtree.c + udf_info/extent.c + udf_info/mount.c + udf_info/phys_eject.c + udf_info/physical.c + udf_info/remap.c + udf_info/udf_info.c + cleanup.c + close.c + create.c + devcntrl.c + dircntrl.c + env_spec.c + fastio.c + fileinfo.c + flush.c + fscntrl.c + lockctrl.c + mem.c + misc.c + namesup.c + prefxsup.c + pnp.c + read.c + secursup.c + shutdown.c + sys_spec.c + udf_dbg.c + udfinit.c + unload.c + verfysup.c + volinfo.c + write.c + strucsup.c + filobsup.c + udfdata.c udffs.h) add_library(udfs MODULE ${SOURCE} udffs.rc) if(CMAKE_C_COMPILER_ID STREQUAL "GNU") target_compile_options(udfs PRIVATE -Wno-unused-but-set-variable) - target_compile_options(udfs PRIVATE -Wno-invalid-offsetof) - target_compile_options(udfs PRIVATE -Wno-error -fpermissive) endif() if(CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_compile_options(udfs PRIVATE -Wno-extern-c-compat -Wno-unused-value) target_compile_options(udfs PRIVATE -Wno-tautological-constant-out-of-range-compare) target_compile_options(udfs PRIVATE -Wno-tautological-unsigned-zero-compare -Wno-self-assign) target_compile_options(udfs PRIVATE -Wno-sometimes-uninitialized -Wno-parentheses-equality) diff --git a/drivers/filesystems/udfs/Include/Sys_spec_lib.cpp b/drivers/filesystems/udfs/Include/Sys_spec_lib.c similarity index 99% rename from drivers/filesystems/udfs/Include/Sys_spec_lib.cpp rename to drivers/filesystems/udfs/Include/Sys_spec_lib.c index b740b6a8a9e73..02258caf5148c 100644 --- a/drivers/filesystems/udfs/Include/Sys_spec_lib.cpp +++ b/drivers/filesystems/udfs/Include/Sys_spec_lib.c @@ -5,7 +5,7 @@ //////////////////////////////////////////////////////////////////// /************************************************************************* * -* File: Sys_Spec.cpp +* File: Sys_Spec.c * * Module: UDF File System Driver * (both User and Kernel mode execution) diff --git a/drivers/filesystems/udfs/Include/mem_tools.cpp b/drivers/filesystems/udfs/Include/mem_tools.c similarity index 100% rename from drivers/filesystems/udfs/Include/mem_tools.cpp rename to drivers/filesystems/udfs/Include/mem_tools.c diff --git a/drivers/filesystems/udfs/Include/phys_lib.cpp b/drivers/filesystems/udfs/Include/phys_lib.c similarity index 99% rename from drivers/filesystems/udfs/Include/phys_lib.cpp rename to drivers/filesystems/udfs/Include/phys_lib.c index bba91e86d1c06..3c4fd17eca371 100644 --- a/drivers/filesystems/udfs/Include/phys_lib.cpp +++ b/drivers/filesystems/udfs/Include/phys_lib.c @@ -4,7 +4,7 @@ // This file was released under the GPLv2 on June 2015. //////////////////////////////////////////////////////////////////// /* - Module Name: Phys_lib.cpp + Module Name: Phys_lib.c Execution: Kernel mode only diff --git a/drivers/filesystems/udfs/Include/regtools.cpp b/drivers/filesystems/udfs/Include/regtools.c similarity index 100% rename from drivers/filesystems/udfs/Include/regtools.cpp rename to drivers/filesystems/udfs/Include/regtools.c diff --git a/drivers/filesystems/udfs/Include/string_lib.cpp b/drivers/filesystems/udfs/Include/string_lib.c similarity index 98% rename from drivers/filesystems/udfs/Include/string_lib.cpp rename to drivers/filesystems/udfs/Include/string_lib.c index 1750feb27ff16..37bd1d894879a 100644 --- a/drivers/filesystems/udfs/Include/string_lib.cpp +++ b/drivers/filesystems/udfs/Include/string_lib.c @@ -4,7 +4,6 @@ // This file was released under the GPLv2 on June 2015. //////////////////////////////////////////////////////////////////// -extern "C" ULONG MyRtlCompareMemory( PVOID s1, @@ -26,7 +25,6 @@ MyRtlCompareMemory( #ifndef NT_NATIVE_MODE -extern "C" ULONG RtlCompareUnicodeString( PUNICODE_STRING s1, @@ -41,7 +39,6 @@ RtlCompareUnicodeString( return i; } -extern "C" NTSTATUS RtlUpcaseUnicodeString( PUNICODE_STRING dst, @@ -57,7 +54,6 @@ RtlUpcaseUnicodeString( return STATUS_SUCCESS; } -extern "C" NTSTATUS RtlAppendUnicodeToString( IN PUNICODE_STRING Str1, diff --git a/drivers/filesystems/udfs/cleanup.cpp b/drivers/filesystems/udfs/cleanup.c similarity index 99% rename from drivers/filesystems/udfs/cleanup.cpp rename to drivers/filesystems/udfs/cleanup.c index 4a42b7da33427..bc41f7c394c08 100644 --- a/drivers/filesystems/udfs/cleanup.cpp +++ b/drivers/filesystems/udfs/cleanup.c @@ -5,7 +5,7 @@ //////////////////////////////////////////////////////////////////// /* - Module name: Cleanup.cpp + Module name: Cleanup.c Abstract: diff --git a/drivers/filesystems/udfs/close.cpp b/drivers/filesystems/udfs/close.c similarity index 99% rename from drivers/filesystems/udfs/close.cpp rename to drivers/filesystems/udfs/close.c index 88b74886c080c..b62034772d992 100644 --- a/drivers/filesystems/udfs/close.cpp +++ b/drivers/filesystems/udfs/close.c @@ -5,7 +5,7 @@ //////////////////////////////////////////////////////////////////// /************************************************************************* * -* File: Close.cpp +* File: Close.c * * Module: UDF File System Driver (Kernel mode execution only) * diff --git a/drivers/filesystems/udfs/create.cpp b/drivers/filesystems/udfs/create.c similarity index 100% rename from drivers/filesystems/udfs/create.cpp rename to drivers/filesystems/udfs/create.c diff --git a/drivers/filesystems/udfs/devcntrl.cpp b/drivers/filesystems/udfs/devcntrl.c similarity index 99% rename from drivers/filesystems/udfs/devcntrl.cpp rename to drivers/filesystems/udfs/devcntrl.c index dd0bb0a651baf..54971f04e1149 100644 --- a/drivers/filesystems/udfs/devcntrl.cpp +++ b/drivers/filesystems/udfs/devcntrl.c @@ -5,7 +5,7 @@ //////////////////////////////////////////////////////////////////// /************************************************************************* * -* File: Devcntrl.cpp +* File: Devcntrl.c * * Module: UDF File System Driver (Kernel mode execution only) * diff --git a/drivers/filesystems/udfs/dircntrl.cpp b/drivers/filesystems/udfs/dircntrl.c similarity index 99% rename from drivers/filesystems/udfs/dircntrl.cpp rename to drivers/filesystems/udfs/dircntrl.c index c9b2f7d62cf64..66af398b8acd0 100644 --- a/drivers/filesystems/udfs/dircntrl.cpp +++ b/drivers/filesystems/udfs/dircntrl.c @@ -5,7 +5,7 @@ //////////////////////////////////////////////////////////////////// /************************************************************************* * -* File: DirCntrl.cpp +* File: DirCntrl.c * * Module: UDF File System Driver (Kernel mode execution only) * diff --git a/drivers/filesystems/udfs/env_spec.cpp b/drivers/filesystems/udfs/env_spec.c similarity index 99% rename from drivers/filesystems/udfs/env_spec.cpp rename to drivers/filesystems/udfs/env_spec.c index 52e1cb5382576..bc5dba5108d52 100644 --- a/drivers/filesystems/udfs/env_spec.cpp +++ b/drivers/filesystems/udfs/env_spec.c @@ -5,7 +5,7 @@ //////////////////////////////////////////////////////////////////// /************************************************************************* * -* File: Env_Spec.cpp +* File: Env_Spec.c * * Module: UDF File System Driver (Kernel mode execution only) * diff --git a/drivers/filesystems/udfs/fastio.cpp b/drivers/filesystems/udfs/fastio.c similarity index 99% rename from drivers/filesystems/udfs/fastio.cpp rename to drivers/filesystems/udfs/fastio.c index 9bdbac17b3f40..024810d6fd484 100644 --- a/drivers/filesystems/udfs/fastio.cpp +++ b/drivers/filesystems/udfs/fastio.c @@ -5,7 +5,7 @@ //////////////////////////////////////////////////////////////////// /************************************************************************* * -* File: Fastio.cpp +* File: Fastio.c * * Module: UDF File System Driver (Kernel mode execution only) * diff --git a/drivers/filesystems/udfs/fileinfo.cpp b/drivers/filesystems/udfs/fileinfo.c similarity index 99% rename from drivers/filesystems/udfs/fileinfo.cpp rename to drivers/filesystems/udfs/fileinfo.c index 92fcd88eaf98e..0b46fe7560ae7 100644 --- a/drivers/filesystems/udfs/fileinfo.cpp +++ b/drivers/filesystems/udfs/fileinfo.c @@ -5,7 +5,7 @@ //////////////////////////////////////////////////////////////////// /************************************************************************* * -* File: Fileinfo.cpp +* File: Fileinfo.c * * Module: UDF File System Driver (Kernel mode execution only) * diff --git a/drivers/filesystems/udfs/filobsup.cpp b/drivers/filesystems/udfs/filobsup.c similarity index 100% rename from drivers/filesystems/udfs/filobsup.cpp rename to drivers/filesystems/udfs/filobsup.c diff --git a/drivers/filesystems/udfs/flush.cpp b/drivers/filesystems/udfs/flush.c similarity index 99% rename from drivers/filesystems/udfs/flush.cpp rename to drivers/filesystems/udfs/flush.c index 65240f50e2a7e..15e630b051a2d 100644 --- a/drivers/filesystems/udfs/flush.cpp +++ b/drivers/filesystems/udfs/flush.c @@ -5,7 +5,7 @@ //////////////////////////////////////////////////////////////////// /************************************************************************* * -* File: Flush.cpp +* File: Flush.c * * Module: UDF File System Driver (Kernel mode execution only) * diff --git a/drivers/filesystems/udfs/fscntrl.cpp b/drivers/filesystems/udfs/fscntrl.c similarity index 99% rename from drivers/filesystems/udfs/fscntrl.cpp rename to drivers/filesystems/udfs/fscntrl.c index 74982610e6a43..7847ba14fa429 100644 --- a/drivers/filesystems/udfs/fscntrl.cpp +++ b/drivers/filesystems/udfs/fscntrl.c @@ -5,7 +5,7 @@ //////////////////////////////////////////////////////////////////// /* - Module Name: FsCntrl.cpp + Module Name: FsCntrl.c Abstract: diff --git a/drivers/filesystems/udfs/lockctrl.cpp b/drivers/filesystems/udfs/lockctrl.c similarity index 99% rename from drivers/filesystems/udfs/lockctrl.cpp rename to drivers/filesystems/udfs/lockctrl.c index da046e9434329..a8fd105af7517 100644 --- a/drivers/filesystems/udfs/lockctrl.cpp +++ b/drivers/filesystems/udfs/lockctrl.c @@ -5,7 +5,7 @@ //////////////////////////////////////////////////////////////////// /************************************************************************* * -* File: LockCtrl.cpp.cpp +* File: LockCtrl.c * * Module: UDF File System Driver (Kernel mode execution only) * diff --git a/drivers/filesystems/udfs/mem.cpp b/drivers/filesystems/udfs/mem.c similarity index 93% rename from drivers/filesystems/udfs/mem.cpp rename to drivers/filesystems/udfs/mem.c index 072602c852327..301ead0d8ba72 100644 --- a/drivers/filesystems/udfs/mem.cpp +++ b/drivers/filesystems/udfs/mem.c @@ -8,4 +8,4 @@ // define the file specific bug-check id #define UDF_BUG_CHECK_ID UDF_FILE_MEM -#include "Include/mem_tools.cpp" +#include "Include/mem_tools.c" diff --git a/drivers/filesystems/udfs/misc.cpp b/drivers/filesystems/udfs/misc.c similarity index 99% rename from drivers/filesystems/udfs/misc.cpp rename to drivers/filesystems/udfs/misc.c index 75765fe90ce48..70c69df9c3679 100644 --- a/drivers/filesystems/udfs/misc.cpp +++ b/drivers/filesystems/udfs/misc.c @@ -5,7 +5,7 @@ //////////////////////////////////////////////////////////////////// /* - File: Misc.cpp + File: Misc.c Module: UDF File System Driver (Kernel mode execution only) @@ -501,7 +501,7 @@ UDFCreateIrpContext( } // TODO: fix - if (false && IrpSp->FileObject != NULL) { + if (FALSE && IrpSp->FileObject != NULL) { PFILE_OBJECT FileObject = IrpSp->FileObject; @@ -1867,5 +1867,5 @@ UDFWaitForIoAtEof( return TRUE; } -#include "Include/regtools.cpp" +#include "Include/regtools.c" diff --git a/drivers/filesystems/udfs/namesup.cpp b/drivers/filesystems/udfs/namesup.c similarity index 99% rename from drivers/filesystems/udfs/namesup.cpp rename to drivers/filesystems/udfs/namesup.c index cab84c4f5873b..021bf48856e6e 100644 --- a/drivers/filesystems/udfs/namesup.cpp +++ b/drivers/filesystems/udfs/namesup.c @@ -5,7 +5,7 @@ //////////////////////////////////////////////////////////////////// /* Module: - Namesup.cpp + Namesup.c Abstract: FileName support routines */ diff --git a/drivers/filesystems/udfs/pnp.cpp b/drivers/filesystems/udfs/pnp.c similarity index 99% rename from drivers/filesystems/udfs/pnp.cpp rename to drivers/filesystems/udfs/pnp.c index 55b1e02f0eeb3..51a0df7daa116 100644 --- a/drivers/filesystems/udfs/pnp.cpp +++ b/drivers/filesystems/udfs/pnp.c @@ -5,7 +5,7 @@ //////////////////////////////////////////////////////////////////// /************************************************************************* * -* File: Pnp.cpp +* File: Pnp.c * * Module: UDF File System Driver (Kernel mode execution only) * diff --git a/drivers/filesystems/udfs/prefxsup.cpp b/drivers/filesystems/udfs/prefxsup.c similarity index 99% rename from drivers/filesystems/udfs/prefxsup.cpp rename to drivers/filesystems/udfs/prefxsup.c index 5bc2a4ff3aeda..2b0dc9b25ed50 100644 --- a/drivers/filesystems/udfs/prefxsup.cpp +++ b/drivers/filesystems/udfs/prefxsup.c @@ -5,7 +5,7 @@ //////////////////////////////////////////////////////////////////// /* - File: PrefxSup.cpp + File: PrefxSup.c Module: UDF File System Driver (Kernel mode execution only) diff --git a/drivers/filesystems/udfs/protos.h b/drivers/filesystems/udfs/protos.h index acaa3cd52b8b4..6f51baedaf9f2 100644 --- a/drivers/filesystems/udfs/protos.h +++ b/drivers/filesystems/udfs/protos.h @@ -67,7 +67,7 @@ UDFFastDecodeFileObject ( ); /************************************************************************* -* Prototypes for the file create.cpp +* Prototypes for the file create.c *************************************************************************/ extern NTSTATUS NTAPI UDFCreate( IN PDEVICE_OBJECT DeviceObject, // the logical volume device object @@ -104,7 +104,7 @@ UDFInitializeFCB( ); /************************************************************************* -* Prototypes for the file cleanup.cpp +* Prototypes for the file cleanup.c *************************************************************************/ extern NTSTATUS NTAPI UDFCleanup( PDEVICE_OBJECT DeviceObject, // the logical volume device object @@ -115,7 +115,7 @@ PIRP_CONTEXT IrpContext, PIRP Irp); /************************************************************************* -* Prototypes for the file close.cpp +* Prototypes for the file close.c *************************************************************************/ extern NTSTATUS NTAPI UDFClose( PDEVICE_OBJECT DeviceObject, // the logical volume device object @@ -151,7 +151,7 @@ UDFFspClose( UDFCloseAllSystemDelayedInDir((Fcb)->Vcb, (Fcb)->FileInfo) /************************************************************************* -* Prototypes for the file dircntrl.cpp +* Prototypes for the file dircntrl.c *************************************************************************/ extern NTSTATUS NTAPI UDFDirControl( PDEVICE_OBJECT DeviceObject, // the logical volume device object @@ -178,7 +178,7 @@ PFCB Fcb, PCCB Ccb); /************************************************************************* -* Prototypes for the file devcntrl.cpp +* Prototypes for the file devcntrl.c *************************************************************************/ extern NTSTATUS NTAPI UDFDeviceControl( PDEVICE_OBJECT DeviceObject, // the logical volume device object @@ -199,7 +199,7 @@ extern NTSTATUS NTAPI UDFHandleQueryPath( PVOID BufferPointer); /************************************************************************* -* Prototypes for the file fastio.cpp +* Prototypes for the file fastio.c *************************************************************************/ extern BOOLEAN NTAPI UDFFastIoCheckIfPossible( IN PFILE_OBJECT FileObject, @@ -335,7 +335,7 @@ UDFFastIoCopyWrite( ); /************************************************************************* -* Prototypes for the file fileinfo.cpp +* Prototypes for the file fileinfo.c *************************************************************************/ extern NTSTATUS UDFCommonQueryInfo( @@ -497,7 +497,7 @@ UDFHardLink( ); /************************************************************************* -* Prototypes for the file flush.cpp +* Prototypes for the file flush.c *************************************************************************/ extern NTSTATUS NTAPI UDFFlushBuffers( PDEVICE_OBJECT DeviceObject, // the logical volume device object @@ -544,7 +544,7 @@ extern VOID UDFFlushTryBreak( IN PVCB Vcb); /************************************************************************* -* Prototypes for the file fscntrl.cpp +* Prototypes for the file fscntrl.c *************************************************************************/ extern NTSTATUS NTAPI UDFFSControl( @@ -640,7 +640,7 @@ UDFCommonPnp( ); /************************************************************************* -* Prototypes for the file LockCtrl.cpp +* Prototypes for the file LockCtrl.c *************************************************************************/ extern NTSTATUS NTAPI UDFLockControl( @@ -690,7 +690,7 @@ UDFFastUnlockAllByKey( ); /************************************************************************* -* Prototypes for the file misc.cpp +* Prototypes for the file misc.c *************************************************************************/ _IRQL_requires_max_(APC_LEVEL) @@ -750,7 +750,7 @@ UDFDeleteCcb( PCCB Ccb ); -// prefxsup.cpp - LCB functions +// prefxsup.c - LCB functions PLCB UDFInsertPrefix( IN PIRP_CONTEXT IrpContext, @@ -965,13 +965,13 @@ UDFCreateFileLock( ); /************************************************************************* -* Prototypes for the file NameSup.cpp +* Prototypes for the file NameSup.c *************************************************************************/ #include "namesup.h" /************************************************************************* -* Prototypes for the file Pnp.cpp +* Prototypes for the file Pnp.c *************************************************************************/ NTSTATUS NTAPI @@ -981,7 +981,7 @@ UDFPnp ( ); /************************************************************************* -* Prototypes for the file read.cpp +* Prototypes for the file read.c *************************************************************************/ extern NTSTATUS NTAPI UDFRead( PDEVICE_OBJECT DeviceObject, // the logical volume device object @@ -1035,7 +1035,7 @@ UDFSetAccessRights( USHORT ShareAccess); /************************************************************************* -* Prototypes for the file Shutdown.cpp +* Prototypes for the file Shutdown.c *************************************************************************/ NTSTATUS @@ -1045,9 +1045,9 @@ UDFCommonShutdown( ); /************************************************************************* -* Prototypes for the file UDFinit.cpp +* Prototypes for the file UDFinit.c *************************************************************************/ -extern "C" NTSTATUS NTAPI DriverEntry( +NTSTATUS NTAPI DriverEntry( PDRIVER_OBJECT DriverObject, // created by the I/O sub-system PUNICODE_STRING RegistryPath); // path to the registry key @@ -1055,7 +1055,7 @@ extern VOID NTAPI UDFInitializeFunctionPointers( PDRIVER_OBJECT DriverObject); // created by the I/O sub-system /************************************************************************* -* Prototypes for the file verify.cpp +* Prototypes for the file verify.c *************************************************************************/ VOID @@ -1107,7 +1107,7 @@ UDFCompareVcb( ); /************************************************************************* -* Prototypes for the file VolInfo.cpp +* Prototypes for the file VolInfo.c *************************************************************************/ extern NTSTATUS NTAPI UDFQueryVolInfo(PDEVICE_OBJECT DeviceObject, PIRP Irp); @@ -1134,7 +1134,7 @@ UDFCommonSetVolInfo( ); /************************************************************************* -* Prototypes for the file write.cpp +* Prototypes for the file write.c *************************************************************************/ extern NTSTATUS NTAPI UDFWrite( PDEVICE_OBJECT DeviceObject, // the logical volume device object @@ -1383,7 +1383,7 @@ UDFAcquireResource( #define UDFReleasePagingIo(IC,F) \ ExReleaseResourceLite((F)->Header.PagingIoResource) -inline +static inline ULONG UDFHighBit( ULONG Word @@ -1407,7 +1407,7 @@ UDFHighBit( #define SectorSize(V) ((V)->SectorSize) -inline +static inline ULONG SectorAlign( PVCB Vcb, @@ -1417,7 +1417,7 @@ SectorAlign( return (Length + (Vcb->SectorSize - 1)) & ~(Vcb->SectorSize - 1); } -inline +static inline ULONGLONG LlSectorAlign( PVCB Vcb, @@ -1439,7 +1439,7 @@ UDFSetThreadContext( (IC)->ThreadContext = NULL -inline +static inline BOOLEAN UdfIsExtendedFESupported( _In_ PVCB Vcb ) @@ -1447,7 +1447,7 @@ BOOLEAN UdfIsExtendedFESupported( return Vcb->NSRDesc == VRS_NSR03_FOUND; } -inline +static inline BOOLEAN UDFIsStreamsSupported( _In_ PVCB Vcb ) diff --git a/drivers/filesystems/udfs/read.cpp b/drivers/filesystems/udfs/read.c similarity index 99% rename from drivers/filesystems/udfs/read.cpp rename to drivers/filesystems/udfs/read.c index c920331dee579..214c2470608fb 100644 --- a/drivers/filesystems/udfs/read.cpp +++ b/drivers/filesystems/udfs/read.c @@ -5,7 +5,7 @@ //////////////////////////////////////////////////////////////////// /************************************************************************* * -* File: Read.cpp +* File: Read.c * * Module: UDF File System Driver (Kernel mode execution only) * diff --git a/drivers/filesystems/udfs/secursup.cpp b/drivers/filesystems/udfs/secursup.c similarity index 99% rename from drivers/filesystems/udfs/secursup.cpp rename to drivers/filesystems/udfs/secursup.c index 8328d7599e110..3b64f057b7ff5 100644 --- a/drivers/filesystems/udfs/secursup.cpp +++ b/drivers/filesystems/udfs/secursup.c @@ -5,7 +5,7 @@ //////////////////////////////////////////////////////////////////// /************************************************************************* * -* File: SecurSup.cpp +* File: SecurSup.c * * Module: UDF File System Driver (Kernel mode execution only) * diff --git a/drivers/filesystems/udfs/shutdown.cpp b/drivers/filesystems/udfs/shutdown.c similarity index 99% rename from drivers/filesystems/udfs/shutdown.cpp rename to drivers/filesystems/udfs/shutdown.c index 93dd97b067f36..cabdf93c38ecc 100644 --- a/drivers/filesystems/udfs/shutdown.cpp +++ b/drivers/filesystems/udfs/shutdown.c @@ -5,7 +5,7 @@ //////////////////////////////////////////////////////////////////// /************************************************************************* * -* File: Shutdown.cpp +* File: Shutdown.c * * Module: UDF File System Driver (Kernel mode execution only) * diff --git a/drivers/filesystems/udfs/strucsup.cpp b/drivers/filesystems/udfs/strucsup.c similarity index 99% rename from drivers/filesystems/udfs/strucsup.cpp rename to drivers/filesystems/udfs/strucsup.c index 6e746f30fc8a4..42a861b518d5e 100644 --- a/drivers/filesystems/udfs/strucsup.cpp +++ b/drivers/filesystems/udfs/strucsup.c @@ -31,7 +31,7 @@ typedef struct _FCB_TABLE_ELEMENT { // // Public wrapper for inserting FCB into FcbTable. -// Called from create.cpp after FCB is fully initialized. +// Called from create.c after FCB is fully initialized. // VCB must be locked by caller. // VOID @@ -46,7 +46,7 @@ UDFInsertFcbIntoTable( SetFlag(Fcb->FcbState, FCB_STATE_IN_FCB_TABLE); } -inline +static inline PFCB_NONPAGED UDFAllocateFcbNonpaged( ) @@ -54,7 +54,7 @@ UDFAllocateFcbNonpaged( return (PFCB_NONPAGED)ExAllocateFromNPagedLookasideList(&UdfData.UDFNonPagedFcbLookasideList); } -inline +static inline PFCB UDFAllocateFcbIndex( ) @@ -62,7 +62,7 @@ UDFAllocateFcbIndex( return (PFCB)ExAllocateFromPagedLookasideList(&UdfData.UDFFcbIndexLookasideList); } -inline +static inline PFCB UDFAllocateFcbData( ) @@ -70,7 +70,7 @@ UDFAllocateFcbData( return (PFCB)ExAllocateFromPagedLookasideList(&UdfData.UDFFcbDataLookasideList); } -inline +static inline PFCB UDFAllocateFcb( ) @@ -78,7 +78,7 @@ UDFAllocateFcb( return (PFCB)ExAllocatePoolWithTag(NonPagedPool, sizeof(FCB), TAG_FCB); } -inline +static inline VOID UDFDeallocateFcbNonpaged( PFCB_NONPAGED FcbNonpaged @@ -87,7 +87,7 @@ UDFDeallocateFcbNonpaged( ExFreeToNPagedLookasideList(&UdfData.UDFNonPagedFcbLookasideList, FcbNonpaged); } -inline +static inline VOID UDFDeallocateFcbIndex( PFCB Fcb @@ -96,7 +96,7 @@ UDFDeallocateFcbIndex( ExFreeToPagedLookasideList(&UdfData.UDFFcbIndexLookasideList, Fcb); } -inline +static inline VOID UDFDeallocateFcbData( PFCB Fcb diff --git a/drivers/filesystems/udfs/sys_spec.cpp b/drivers/filesystems/udfs/sys_spec.c similarity index 89% rename from drivers/filesystems/udfs/sys_spec.cpp rename to drivers/filesystems/udfs/sys_spec.c index e9a11ab152817..cd77a8f55de81 100644 --- a/drivers/filesystems/udfs/sys_spec.cpp +++ b/drivers/filesystems/udfs/sys_spec.c @@ -5,7 +5,7 @@ //////////////////////////////////////////////////////////////////// /************************************************************************* * -* File: Sys_Spec.cpp +* File: Sys_Spec.c * * Module: UDF File System Driver * (both User and Kernel mode execution) @@ -20,6 +20,6 @@ // define the file specific bug-check id #define UDF_BUG_CHECK_ID UDF_FILE_SYS_SPEC -#include "Include/Sys_spec_lib.cpp" +#include "Include/Sys_spec_lib.c" -//#include "Include/tools.cpp" +//#include "Include/tools.c" diff --git a/drivers/filesystems/udfs/udf_dbg.cpp b/drivers/filesystems/udfs/udf_dbg.c similarity index 100% rename from drivers/filesystems/udfs/udf_dbg.cpp rename to drivers/filesystems/udfs/udf_dbg.c diff --git a/drivers/filesystems/udfs/udf_info/alloc.cpp b/drivers/filesystems/udfs/udf_info/alloc.c similarity index 99% rename from drivers/filesystems/udfs/udf_info/alloc.cpp rename to drivers/filesystems/udfs/udf_info/alloc.c index 530d6b168767e..6e05b33b40a34 100644 --- a/drivers/filesystems/udfs/udf_info/alloc.cpp +++ b/drivers/filesystems/udfs/udf_info/alloc.c @@ -6,7 +6,7 @@ /* Module name: - alloc.cpp + alloc.c Abstract: diff --git a/drivers/filesystems/udfs/udf_info/dirtree.cpp b/drivers/filesystems/udfs/udf_info/dirtree.c similarity index 99% rename from drivers/filesystems/udfs/udf_info/dirtree.cpp rename to drivers/filesystems/udfs/udf_info/dirtree.c index e4ed3534956e4..4402f28ae167a 100644 --- a/drivers/filesystems/udfs/udf_info/dirtree.cpp +++ b/drivers/filesystems/udfs/udf_info/dirtree.c @@ -6,7 +6,7 @@ /* Module name: - udf_info.cpp + udf_info.c Abstract: diff --git a/drivers/filesystems/udfs/udf_info/extent.cpp b/drivers/filesystems/udfs/udf_info/extent.c similarity index 99% rename from drivers/filesystems/udfs/udf_info/extent.cpp rename to drivers/filesystems/udfs/udf_info/extent.c index f76d82b4577c0..7b56c5321f541 100644 --- a/drivers/filesystems/udfs/udf_info/extent.cpp +++ b/drivers/filesystems/udfs/udf_info/extent.c @@ -6,7 +6,7 @@ /* Module name: - extent.cpp + extent.c Abstract: diff --git a/drivers/filesystems/udfs/udf_info/mount.cpp b/drivers/filesystems/udfs/udf_info/mount.c similarity index 99% rename from drivers/filesystems/udfs/udf_info/mount.cpp rename to drivers/filesystems/udfs/udf_info/mount.c index 62fa4048fc624..9e8b3d24c1e2a 100644 --- a/drivers/filesystems/udfs/udf_info/mount.cpp +++ b/drivers/filesystems/udfs/udf_info/mount.c @@ -6,7 +6,7 @@ /* Module name: - mount.cpp + mount.c Abstract: diff --git a/drivers/filesystems/udfs/udf_info/phys_eject.cpp b/drivers/filesystems/udfs/udf_info/phys_eject.c similarity index 98% rename from drivers/filesystems/udfs/udf_info/phys_eject.cpp rename to drivers/filesystems/udfs/udf_info/phys_eject.c index 2a7a794d27839..f8b6333b187ab 100644 --- a/drivers/filesystems/udfs/udf_info/phys_eject.cpp +++ b/drivers/filesystems/udfs/udf_info/phys_eject.c @@ -4,7 +4,7 @@ // This file was released under the GPLv2 on June 2015. //////////////////////////////////////////////////////////////////// /* - Module Name: Phys_eject.cpp + Module Name: Phys_eject.c Execution: Kernel mode only diff --git a/drivers/filesystems/udfs/udf_info/physical.cpp b/drivers/filesystems/udfs/udf_info/physical.c similarity index 90% rename from drivers/filesystems/udfs/udf_info/physical.cpp rename to drivers/filesystems/udfs/udf_info/physical.c index 1ba8a147f02f1..97bd642b3690c 100644 --- a/drivers/filesystems/udfs/udf_info/physical.cpp +++ b/drivers/filesystems/udfs/udf_info/physical.c @@ -4,7 +4,7 @@ // This file was released under the GPLv2 on June 2015. //////////////////////////////////////////////////////////////////// /* - Module Name: Physical.cpp + Module Name: Physical.c Execution: Kernel mode only @@ -17,5 +17,5 @@ // define the file specific bug-check id #define UDF_BUG_CHECK_ID UDF_FILE_PHYSICAL -#include "Include/phys_lib.cpp" +#include "Include/phys_lib.c" diff --git a/drivers/filesystems/udfs/udf_info/remap.cpp b/drivers/filesystems/udfs/udf_info/remap.c similarity index 99% rename from drivers/filesystems/udfs/udf_info/remap.cpp rename to drivers/filesystems/udfs/udf_info/remap.c index 72a4079b07021..d134b40f5ecc8 100644 --- a/drivers/filesystems/udfs/udf_info/remap.cpp +++ b/drivers/filesystems/udfs/udf_info/remap.c @@ -6,7 +6,7 @@ /* Module name: - remap.cpp + remap.c Abstract: diff --git a/drivers/filesystems/udfs/udf_info/udf_info.cpp b/drivers/filesystems/udfs/udf_info/udf_info.c similarity index 99% rename from drivers/filesystems/udfs/udf_info/udf_info.cpp rename to drivers/filesystems/udfs/udf_info/udf_info.c index e9556aa93de31..2ffa371740a76 100644 --- a/drivers/filesystems/udfs/udf_info/udf_info.cpp +++ b/drivers/filesystems/udfs/udf_info/udf_info.c @@ -6,7 +6,7 @@ /* Module name: - udf_info.cpp + udf_info.c Abstract: diff --git a/drivers/filesystems/udfs/udfdata.cpp b/drivers/filesystems/udfs/udfdata.c similarity index 99% rename from drivers/filesystems/udfs/udfdata.cpp rename to drivers/filesystems/udfs/udfdata.c index d1674b7727e54..7dda3e1232d72 100644 --- a/drivers/filesystems/udfs/udfdata.cpp +++ b/drivers/filesystems/udfs/udfdata.c @@ -5,7 +5,7 @@ //////////////////////////////////////////////////////////////////// /************************************************************************* * -* File: Close.cpp +* File: Close.c * * Module: UDF File System Driver (Kernel mode execution only) * diff --git a/drivers/filesystems/udfs/udffs.h b/drivers/filesystems/udfs/udffs.h index 272046b907e62..2aae42ef2fa5f 100644 --- a/drivers/filesystems/udfs/udffs.h +++ b/drivers/filesystems/udfs/udffs.h @@ -133,7 +133,7 @@ extern UDFData UdfData; // Encapsulate safe pool freeing -inline +static inline VOID UDFFreePool( _Inout_ _At_(*Pool, __drv_freesMem(Mem) _Post_null_) PVOID *Pool @@ -152,7 +152,7 @@ UDFFreePool( // small check for illegal open mode (desired access) if volume is // read only (on standard CD-ROM device or another like this) -inline +static inline BOOLEAN UDFIllegalFcbAccess( IN PVCB Vcb, @@ -398,7 +398,7 @@ UDFIllegalFcbAccess( #define FID_DIR_MASK 0x80000000 // high order bit means directory. -inline +static inline FILE_ID UdfGetFidFromLbAddr(lb_addr lbAddr) { diff --git a/drivers/filesystems/udfs/udfinit.cpp b/drivers/filesystems/udfs/udfinit.c similarity index 99% rename from drivers/filesystems/udfs/udfinit.cpp rename to drivers/filesystems/udfs/udfinit.c index 657034565142c..ff89febf2f6ef 100644 --- a/drivers/filesystems/udfs/udfinit.cpp +++ b/drivers/filesystems/udfs/udfinit.c @@ -5,7 +5,7 @@ //////////////////////////////////////////////////////////////////// /************************************************************************* * -* File: UDFinit.cpp +* File: UDFinit.c * * Module: UDF File System Driver (Kernel mode execution only) * diff --git a/drivers/filesystems/udfs/unload.cpp b/drivers/filesystems/udfs/unload.c similarity index 100% rename from drivers/filesystems/udfs/unload.cpp rename to drivers/filesystems/udfs/unload.c diff --git a/drivers/filesystems/udfs/verfysup.cpp b/drivers/filesystems/udfs/verfysup.c similarity index 99% rename from drivers/filesystems/udfs/verfysup.cpp rename to drivers/filesystems/udfs/verfysup.c index 015af5a6b423b..441a0e62852c5 100644 --- a/drivers/filesystems/udfs/verfysup.cpp +++ b/drivers/filesystems/udfs/verfysup.c @@ -5,7 +5,7 @@ //////////////////////////////////////////////////////////////////// /* - Module Name: VerfySup.cpp + Module Name: VerfySup.c Abstract: diff --git a/drivers/filesystems/udfs/volinfo.cpp b/drivers/filesystems/udfs/volinfo.c similarity index 99% rename from drivers/filesystems/udfs/volinfo.cpp rename to drivers/filesystems/udfs/volinfo.c index c6ab4d3da9bf9..d62501d1b6cef 100644 --- a/drivers/filesystems/udfs/volinfo.cpp +++ b/drivers/filesystems/udfs/volinfo.c @@ -7,7 +7,7 @@ Module Name: - VolInfo.cpp + VolInfo.c Abstract: diff --git a/drivers/filesystems/udfs/write.cpp b/drivers/filesystems/udfs/write.c similarity index 99% rename from drivers/filesystems/udfs/write.cpp rename to drivers/filesystems/udfs/write.c index 076e5a6cbe305..233d8b9e532db 100644 --- a/drivers/filesystems/udfs/write.cpp +++ b/drivers/filesystems/udfs/write.c @@ -5,7 +5,7 @@ //////////////////////////////////////////////////////////////////// /************************************************************************* * -* File: Write.cpp +* File: Write.c * * Module: UDF File System Driver (Kernel mode execution only) * @@ -739,7 +739,7 @@ UDFPurgeCacheEx_( // We'll just purge cache section here, // without call to CcZeroData() - // 'cause udf_info.cpp will care about it + // 'cause udf_info.c will care about it #define PURGE_BLOCK_SZ 0x10000000 From 9f38e09b01197271359611388be89b28d7a513d7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 6 Mar 2026 02:58:27 +0000 Subject: [PATCH 05/20] Add udfs-for-write-branch.patch targeting the write branch directly Co-authored-by: Zero3K20 <258969903+Zero3K20@users.noreply.github.com> --- udfs-for-write-branch.patch | 500 ++++++++++++++++++++++++++++++++++++ 1 file changed, 500 insertions(+) create mode 100644 udfs-for-write-branch.patch diff --git a/udfs-for-write-branch.patch b/udfs-for-write-branch.patch new file mode 100644 index 0000000000000..a01c250057268 --- /dev/null +++ b/udfs-for-write-branch.patch @@ -0,0 +1,500 @@ +diff --git a/drivers/filesystems/udfs/CMakeLists.txt b/drivers/filesystems/udfs/CMakeLists.txt +index 53ce00f..4332487 100644 +--- a/drivers/filesystems/udfs/CMakeLists.txt ++++ b/drivers/filesystems/udfs/CMakeLists.txt +@@ -1,55 +1,51 @@ +- + include_directories(Include) + + list(APPEND SOURCE +- udf_info/alloc.cpp +- udf_info/dirtree.cpp +- udf_info/extent.cpp +- udf_info/mount.cpp +- udf_info/phys_eject.cpp +- udf_info/physical.cpp +- udf_info/remap.cpp +- udf_info/udf_info.cpp +- cleanup.cpp +- close.cpp +- create.cpp +- devcntrl.cpp +- dircntrl.cpp +- env_spec.cpp +- fastio.cpp +- fileinfo.cpp +- flush.cpp +- fscntrl.cpp +- lockctrl.cpp +- mem.cpp +- misc.cpp +- namesup.cpp +- pnp.cpp +- read.cpp +- secursup.cpp +- shutdown.cpp +- sys_spec.cpp +- udf_dbg.cpp +- udfinit.cpp +- unload.cpp +- verfysup.cpp +- volinfo.cpp +- write.cpp +- strucsup.cpp +- filobsup.cpp +- udfdata.cpp ++ udf_info/alloc.c ++ udf_info/dirtree.c ++ udf_info/extent.c ++ udf_info/mount.c ++ udf_info/phys_eject.c ++ udf_info/physical.c ++ udf_info/remap.c ++ udf_info/udf_info.c ++ cleanup.c ++ close.c ++ create.c ++ devcntrl.c ++ dircntrl.c ++ env_spec.c ++ fastio.c ++ fileinfo.c ++ flush.c ++ fscntrl.c ++ lockctrl.c ++ mem.c ++ misc.c ++ namesup.c ++ pnp.c ++ read.c ++ secursup.c ++ shutdown.c ++ sys_spec.c ++ udf_dbg.c ++ udfinit.c ++ unload.c ++ verfysup.c ++ volinfo.c ++ write.c ++ strucsup.c ++ filobsup.c ++ udfdata.c + udffs.h) + + add_library(udfs MODULE ${SOURCE} udffs.rc) + + if(CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_compile_options(udfs PRIVATE -Wno-unused-but-set-variable) +- target_compile_options(udfs PRIVATE -Wno-invalid-offsetof) +- target_compile_options(udfs PRIVATE -Wno-error -fpermissive) + endif() + + if(CMAKE_C_COMPILER_ID STREQUAL "Clang") +- target_compile_options(udfs PRIVATE -Wno-extern-c-compat -Wno-unused-value) + target_compile_options(udfs PRIVATE -Wno-tautological-constant-out-of-range-compare) + target_compile_options(udfs PRIVATE -Wno-tautological-unsigned-zero-compare -Wno-self-assign) + target_compile_options(udfs PRIVATE -Wno-sometimes-uninitialized -Wno-parentheses-equality) +diff --git a/drivers/filesystems/udfs/Include/Sys_spec_lib.cpp b/drivers/filesystems/udfs/Include/Sys_spec_lib.c +similarity index 100% +rename from drivers/filesystems/udfs/Include/Sys_spec_lib.cpp +rename to drivers/filesystems/udfs/Include/Sys_spec_lib.c +diff --git a/drivers/filesystems/udfs/Include/mem_tools.cpp b/drivers/filesystems/udfs/Include/mem_tools.c +similarity index 100% +rename from drivers/filesystems/udfs/Include/mem_tools.cpp +rename to drivers/filesystems/udfs/Include/mem_tools.c +diff --git a/drivers/filesystems/udfs/Include/phys_lib.cpp b/drivers/filesystems/udfs/Include/phys_lib.c +similarity index 100% +rename from drivers/filesystems/udfs/Include/phys_lib.cpp +rename to drivers/filesystems/udfs/Include/phys_lib.c +diff --git a/drivers/filesystems/udfs/Include/regtools.cpp b/drivers/filesystems/udfs/Include/regtools.c +similarity index 100% +rename from drivers/filesystems/udfs/Include/regtools.cpp +rename to drivers/filesystems/udfs/Include/regtools.c +diff --git a/drivers/filesystems/udfs/Include/string_lib.cpp b/drivers/filesystems/udfs/Include/string_lib.c +similarity index 98% +rename from drivers/filesystems/udfs/Include/string_lib.cpp +rename to drivers/filesystems/udfs/Include/string_lib.c +index 1750feb..37bd1d8 100644 +--- a/drivers/filesystems/udfs/Include/string_lib.cpp ++++ b/drivers/filesystems/udfs/Include/string_lib.c +@@ -4,7 +4,6 @@ + // This file was released under the GPLv2 on June 2015. + //////////////////////////////////////////////////////////////////// + +-extern "C" + ULONG + MyRtlCompareMemory( + PVOID s1, +@@ -26,7 +25,6 @@ MyRtlCompareMemory( + + #ifndef NT_NATIVE_MODE + +-extern "C" + ULONG + RtlCompareUnicodeString( + PUNICODE_STRING s1, +@@ -41,7 +39,6 @@ RtlCompareUnicodeString( + return i; + } + +-extern "C" + NTSTATUS + RtlUpcaseUnicodeString( + PUNICODE_STRING dst, +@@ -57,7 +54,6 @@ RtlUpcaseUnicodeString( + return STATUS_SUCCESS; + } + +-extern "C" + NTSTATUS + RtlAppendUnicodeToString( + IN PUNICODE_STRING Str1, +diff --git a/drivers/filesystems/udfs/cleanup.cpp b/drivers/filesystems/udfs/cleanup.c +similarity index 100% +rename from drivers/filesystems/udfs/cleanup.cpp +rename to drivers/filesystems/udfs/cleanup.c +diff --git a/drivers/filesystems/udfs/close.cpp b/drivers/filesystems/udfs/close.c +similarity index 100% +rename from drivers/filesystems/udfs/close.cpp +rename to drivers/filesystems/udfs/close.c +diff --git a/drivers/filesystems/udfs/create.cpp b/drivers/filesystems/udfs/create.c +similarity index 100% +rename from drivers/filesystems/udfs/create.cpp +rename to drivers/filesystems/udfs/create.c +diff --git a/drivers/filesystems/udfs/devcntrl.cpp b/drivers/filesystems/udfs/devcntrl.c +similarity index 100% +rename from drivers/filesystems/udfs/devcntrl.cpp +rename to drivers/filesystems/udfs/devcntrl.c +diff --git a/drivers/filesystems/udfs/dircntrl.cpp b/drivers/filesystems/udfs/dircntrl.c +similarity index 100% +rename from drivers/filesystems/udfs/dircntrl.cpp +rename to drivers/filesystems/udfs/dircntrl.c +diff --git a/drivers/filesystems/udfs/env_spec.cpp b/drivers/filesystems/udfs/env_spec.c +similarity index 100% +rename from drivers/filesystems/udfs/env_spec.cpp +rename to drivers/filesystems/udfs/env_spec.c +diff --git a/drivers/filesystems/udfs/fastio.cpp b/drivers/filesystems/udfs/fastio.c +similarity index 100% +rename from drivers/filesystems/udfs/fastio.cpp +rename to drivers/filesystems/udfs/fastio.c +diff --git a/drivers/filesystems/udfs/fileinfo.cpp b/drivers/filesystems/udfs/fileinfo.c +similarity index 100% +rename from drivers/filesystems/udfs/fileinfo.cpp +rename to drivers/filesystems/udfs/fileinfo.c +diff --git a/drivers/filesystems/udfs/filobsup.cpp b/drivers/filesystems/udfs/filobsup.c +similarity index 100% +rename from drivers/filesystems/udfs/filobsup.cpp +rename to drivers/filesystems/udfs/filobsup.c +diff --git a/drivers/filesystems/udfs/flush.cpp b/drivers/filesystems/udfs/flush.c +similarity index 100% +rename from drivers/filesystems/udfs/flush.cpp +rename to drivers/filesystems/udfs/flush.c +diff --git a/drivers/filesystems/udfs/fscntrl.cpp b/drivers/filesystems/udfs/fscntrl.c +similarity index 100% +rename from drivers/filesystems/udfs/fscntrl.cpp +rename to drivers/filesystems/udfs/fscntrl.c +diff --git a/drivers/filesystems/udfs/lockctrl.cpp b/drivers/filesystems/udfs/lockctrl.c +similarity index 100% +rename from drivers/filesystems/udfs/lockctrl.cpp +rename to drivers/filesystems/udfs/lockctrl.c +diff --git a/drivers/filesystems/udfs/mem.cpp b/drivers/filesystems/udfs/mem.c +similarity index 93% +rename from drivers/filesystems/udfs/mem.cpp +rename to drivers/filesystems/udfs/mem.c +index 072602c..301ead0 100644 +--- a/drivers/filesystems/udfs/mem.cpp ++++ b/drivers/filesystems/udfs/mem.c +@@ -8,4 +8,4 @@ + // define the file specific bug-check id + #define UDF_BUG_CHECK_ID UDF_FILE_MEM + +-#include "Include/mem_tools.cpp" ++#include "Include/mem_tools.c" +diff --git a/drivers/filesystems/udfs/misc.cpp b/drivers/filesystems/udfs/misc.c +similarity index 99% +rename from drivers/filesystems/udfs/misc.cpp +rename to drivers/filesystems/udfs/misc.c +index c78f454..d9cf307 100644 +--- a/drivers/filesystems/udfs/misc.cpp ++++ b/drivers/filesystems/udfs/misc.c +@@ -711,7 +711,7 @@ UDFCreateIrpContext( + } + + // TODO: fix +- if (false && IrpSp->FileObject != NULL) { ++ if (FALSE && IrpSp->FileObject != NULL) { + + PFILE_OBJECT FileObject = IrpSp->FileObject; + +@@ -2106,5 +2106,5 @@ UDFWaitForIoAtEof( + return TRUE; + } + +-#include "Include/regtools.cpp" ++#include "Include/regtools.c" + +diff --git a/drivers/filesystems/udfs/namesup.cpp b/drivers/filesystems/udfs/namesup.c +similarity index 100% +rename from drivers/filesystems/udfs/namesup.cpp +rename to drivers/filesystems/udfs/namesup.c +diff --git a/drivers/filesystems/udfs/pnp.cpp b/drivers/filesystems/udfs/pnp.c +similarity index 100% +rename from drivers/filesystems/udfs/pnp.cpp +rename to drivers/filesystems/udfs/pnp.c +diff --git a/drivers/filesystems/udfs/protos.h b/drivers/filesystems/udfs/protos.h +index 59cb00c..7898d13 100644 +--- a/drivers/filesystems/udfs/protos.h ++++ b/drivers/filesystems/udfs/protos.h +@@ -964,7 +964,7 @@ UDFCommonShutdown( + /************************************************************************* + * Prototypes for the file UDFinit.cpp + *************************************************************************/ +-extern "C" NTSTATUS NTAPI DriverEntry( ++NTSTATUS NTAPI DriverEntry( + PDRIVER_OBJECT DriverObject, // created by the I/O sub-system + PUNICODE_STRING RegistryPath); // path to the registry key + +@@ -1271,7 +1271,7 @@ UDFAcquireResource( + #define UDFReleasePagingIo(IC,F) \ + ExReleaseResourceLite((F)->Header.PagingIoResource) + +-inline ++static inline + ULONG + UDFHighBit( + ULONG Word +@@ -1295,7 +1295,7 @@ UDFHighBit( + + #define SectorSize(V) ((V)->SectorSize) + +-inline ++static inline + ULONG + SectorAlign( + PVCB Vcb, +@@ -1305,7 +1305,7 @@ SectorAlign( + return (Length + (Vcb->SectorSize - 1)) & ~(Vcb->SectorSize - 1); + } + +-inline ++static inline + ULONGLONG + LlSectorAlign( + PVCB Vcb, +@@ -1327,7 +1327,7 @@ UDFSetThreadContext( + (IC)->ThreadContext = NULL + + +-inline ++static inline + BOOLEAN UdfIsExtendedFESupported( + _In_ PVCB Vcb + ) +@@ -1335,7 +1335,7 @@ BOOLEAN UdfIsExtendedFESupported( + return Vcb->NSRDesc == VRS_NSR03_FOUND; + } + +-inline ++static inline + BOOLEAN UDFIsStreamsSupported( + _In_ PVCB Vcb + ) +diff --git a/drivers/filesystems/udfs/read.cpp b/drivers/filesystems/udfs/read.c +similarity index 100% +rename from drivers/filesystems/udfs/read.cpp +rename to drivers/filesystems/udfs/read.c +diff --git a/drivers/filesystems/udfs/secursup.cpp b/drivers/filesystems/udfs/secursup.c +similarity index 100% +rename from drivers/filesystems/udfs/secursup.cpp +rename to drivers/filesystems/udfs/secursup.c +diff --git a/drivers/filesystems/udfs/shutdown.cpp b/drivers/filesystems/udfs/shutdown.c +similarity index 100% +rename from drivers/filesystems/udfs/shutdown.cpp +rename to drivers/filesystems/udfs/shutdown.c +diff --git a/drivers/filesystems/udfs/strucsup.cpp b/drivers/filesystems/udfs/strucsup.c +similarity index 99% +rename from drivers/filesystems/udfs/strucsup.cpp +rename to drivers/filesystems/udfs/strucsup.c +index 6e00af7..7964ebb 100644 +--- a/drivers/filesystems/udfs/strucsup.cpp ++++ b/drivers/filesystems/udfs/strucsup.c +@@ -29,7 +29,7 @@ typedef struct _FCB_TABLE_ELEMENT { + RtlDeleteElementGenericTable( &(F)->Vcb->FcbTable, &_Key ); \ + } + +-inline ++static inline + PFCB_NONPAGED + UDFAllocateFcbNonpaged( + ) +@@ -37,7 +37,7 @@ UDFAllocateFcbNonpaged( + return (PFCB_NONPAGED)ExAllocateFromNPagedLookasideList(&UdfData.UDFNonPagedFcbLookasideList); + } + +-inline ++static inline + PFCB + UDFAllocateFcbIndex( + ) +@@ -45,7 +45,7 @@ UDFAllocateFcbIndex( + return (PFCB)ExAllocateFromPagedLookasideList(&UdfData.UDFFcbIndexLookasideList); + } + +-inline ++static inline + PFCB + UDFAllocateFcbData( + ) +@@ -53,7 +53,7 @@ UDFAllocateFcbData( + return (PFCB)ExAllocateFromPagedLookasideList(&UdfData.UDFFcbDataLookasideList); + } + +-inline ++static inline + PFCB + UDFAllocateFcb( + ) +@@ -61,7 +61,7 @@ UDFAllocateFcb( + return (PFCB)ExAllocatePoolWithTag(NonPagedPool, sizeof(FCB), TAG_FCB); + } + +-inline ++static inline + VOID + UDFDeallocateFcbNonpaged( + PFCB_NONPAGED FcbNonpaged +@@ -70,7 +70,7 @@ UDFDeallocateFcbNonpaged( + ExFreeToNPagedLookasideList(&UdfData.UDFNonPagedFcbLookasideList, FcbNonpaged); + } + +-inline ++static inline + VOID + UDFDeallocateFcbIndex( + PFCB Fcb +@@ -79,7 +79,7 @@ UDFDeallocateFcbIndex( + ExFreeToPagedLookasideList(&UdfData.UDFFcbIndexLookasideList, Fcb); + } + +-inline ++static inline + VOID + UDFDeallocateFcbData( + PFCB Fcb +diff --git a/drivers/filesystems/udfs/sys_spec.cpp b/drivers/filesystems/udfs/sys_spec.c +similarity index 91% +rename from drivers/filesystems/udfs/sys_spec.cpp +rename to drivers/filesystems/udfs/sys_spec.c +index e9a11ab..82f2665 100644 +--- a/drivers/filesystems/udfs/sys_spec.cpp ++++ b/drivers/filesystems/udfs/sys_spec.c +@@ -20,6 +20,6 @@ + // define the file specific bug-check id + #define UDF_BUG_CHECK_ID UDF_FILE_SYS_SPEC + +-#include "Include/Sys_spec_lib.cpp" ++#include "Include/Sys_spec_lib.c" + +-//#include "Include/tools.cpp" ++//#include "Include/tools.c" +diff --git a/drivers/filesystems/udfs/udf_dbg.cpp b/drivers/filesystems/udfs/udf_dbg.c +similarity index 100% +rename from drivers/filesystems/udfs/udf_dbg.cpp +rename to drivers/filesystems/udfs/udf_dbg.c +diff --git a/drivers/filesystems/udfs/udf_info/alloc.cpp b/drivers/filesystems/udfs/udf_info/alloc.c +similarity index 100% +rename from drivers/filesystems/udfs/udf_info/alloc.cpp +rename to drivers/filesystems/udfs/udf_info/alloc.c +diff --git a/drivers/filesystems/udfs/udf_info/dirtree.cpp b/drivers/filesystems/udfs/udf_info/dirtree.c +similarity index 100% +rename from drivers/filesystems/udfs/udf_info/dirtree.cpp +rename to drivers/filesystems/udfs/udf_info/dirtree.c +diff --git a/drivers/filesystems/udfs/udf_info/extent.cpp b/drivers/filesystems/udfs/udf_info/extent.c +similarity index 100% +rename from drivers/filesystems/udfs/udf_info/extent.cpp +rename to drivers/filesystems/udfs/udf_info/extent.c +diff --git a/drivers/filesystems/udfs/udf_info/mount.cpp b/drivers/filesystems/udfs/udf_info/mount.c +similarity index 100% +rename from drivers/filesystems/udfs/udf_info/mount.cpp +rename to drivers/filesystems/udfs/udf_info/mount.c +diff --git a/drivers/filesystems/udfs/udf_info/phys_eject.cpp b/drivers/filesystems/udfs/udf_info/phys_eject.c +similarity index 100% +rename from drivers/filesystems/udfs/udf_info/phys_eject.cpp +rename to drivers/filesystems/udfs/udf_info/phys_eject.c +diff --git a/drivers/filesystems/udfs/udf_info/physical.cpp b/drivers/filesystems/udfs/udf_info/physical.c +similarity index 95% +rename from drivers/filesystems/udfs/udf_info/physical.cpp +rename to drivers/filesystems/udfs/udf_info/physical.c +index 1ba8a14..9468996 100644 +--- a/drivers/filesystems/udfs/udf_info/physical.cpp ++++ b/drivers/filesystems/udfs/udf_info/physical.c +@@ -17,5 +17,5 @@ + // define the file specific bug-check id + #define UDF_BUG_CHECK_ID UDF_FILE_PHYSICAL + +-#include "Include/phys_lib.cpp" ++#include "Include/phys_lib.c" + +diff --git a/drivers/filesystems/udfs/udf_info/remap.cpp b/drivers/filesystems/udfs/udf_info/remap.c +similarity index 100% +rename from drivers/filesystems/udfs/udf_info/remap.cpp +rename to drivers/filesystems/udfs/udf_info/remap.c +diff --git a/drivers/filesystems/udfs/udf_info/udf_info.cpp b/drivers/filesystems/udfs/udf_info/udf_info.c +similarity index 100% +rename from drivers/filesystems/udfs/udf_info/udf_info.cpp +rename to drivers/filesystems/udfs/udf_info/udf_info.c +diff --git a/drivers/filesystems/udfs/udfdata.cpp b/drivers/filesystems/udfs/udfdata.c +similarity index 100% +rename from drivers/filesystems/udfs/udfdata.cpp +rename to drivers/filesystems/udfs/udfdata.c +diff --git a/drivers/filesystems/udfs/udffs.h b/drivers/filesystems/udfs/udffs.h +index 5eff0e0..770bbcc 100644 +--- a/drivers/filesystems/udfs/udffs.h ++++ b/drivers/filesystems/udfs/udffs.h +@@ -161,7 +161,7 @@ extern UDFData UdfData; + + // Encapsulate safe pool freeing + +-inline ++static inline + VOID + UDFFreePool( + _Inout_ _At_(*Pool, __drv_freesMem(Mem) _Post_null_) PVOID *Pool +@@ -180,7 +180,7 @@ UDFFreePool( + + // small check for illegal open mode (desired access) if volume is + // read only (on standard CD-ROM device or another like this) +-inline ++static inline + BOOLEAN + UDFIllegalFcbAccess( + IN PVCB Vcb, +@@ -426,7 +426,7 @@ UDFIllegalFcbAccess( + + #define FID_DIR_MASK 0x80000000 // high order bit means directory. + +-inline ++static inline + FILE_ID + UdfGetFidFromLbAddr(lb_addr lbAddr) + { +diff --git a/drivers/filesystems/udfs/udfinit.cpp b/drivers/filesystems/udfs/udfinit.c +similarity index 100% +rename from drivers/filesystems/udfs/udfinit.cpp +rename to drivers/filesystems/udfs/udfinit.c +diff --git a/drivers/filesystems/udfs/unload.cpp b/drivers/filesystems/udfs/unload.c +similarity index 100% +rename from drivers/filesystems/udfs/unload.cpp +rename to drivers/filesystems/udfs/unload.c +diff --git a/drivers/filesystems/udfs/verfysup.cpp b/drivers/filesystems/udfs/verfysup.c +similarity index 100% +rename from drivers/filesystems/udfs/verfysup.cpp +rename to drivers/filesystems/udfs/verfysup.c +diff --git a/drivers/filesystems/udfs/volinfo.cpp b/drivers/filesystems/udfs/volinfo.c +similarity index 100% +rename from drivers/filesystems/udfs/volinfo.cpp +rename to drivers/filesystems/udfs/volinfo.c +diff --git a/drivers/filesystems/udfs/write.cpp b/drivers/filesystems/udfs/write.c +similarity index 100% +rename from drivers/filesystems/udfs/write.cpp +rename to drivers/filesystems/udfs/write.c From 880986ee567c56300f8a756fbd21d179dc943692 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 6 Mar 2026 03:21:26 +0000 Subject: [PATCH 06/20] Fix C++ constructs in struct.h, udf_rel.h, ecma_167.h, osta_misc.h, protos.h for MSVC C compilation Co-authored-by: Zero3K20 <258969903+Zero3K20@users.noreply.github.com> --- drivers/filesystems/udfs/protos.h | 4 +- drivers/filesystems/udfs/struct.h | 47 +- drivers/filesystems/udfs/udf_info/ecma_167.h | 33 + drivers/filesystems/udfs/udf_info/osta_misc.h | 11 + drivers/filesystems/udfs/udf_info/udf_rel.h | 2 +- udfs-for-write-branch.patch | 667 +++++++++++++++++- 6 files changed, 733 insertions(+), 31 deletions(-) diff --git a/drivers/filesystems/udfs/protos.h b/drivers/filesystems/udfs/protos.h index 6f51baedaf9f2..8d10e7455139f 100644 --- a/drivers/filesystems/udfs/protos.h +++ b/drivers/filesystems/udfs/protos.h @@ -1329,13 +1329,13 @@ UDFMarkDevForVerifyIfVcbMounted( UdfData.UdfDataLockThread = NULL; \ ExReleaseFastMutexUnsafe(&UdfData.UdfDataMutex) -enum TYPE_OF_ACQUIRE { +typedef enum TYPE_OF_ACQUIRE { AcquireExclusive, AcquireShared, AcquireSharedStarveExclusive -}; +} TYPE_OF_ACQUIRE; _Requires_lock_held_(_Global_critical_region_) _When_(Type == AcquireExclusive && return != FALSE, _Acquires_exclusive_lock_(*Resource)) diff --git a/drivers/filesystems/udfs/struct.h b/drivers/filesystems/udfs/struct.h index 74c032224266d..128770c2bcc3a 100644 --- a/drivers/filesystems/udfs/struct.h +++ b/drivers/filesystems/udfs/struct.h @@ -38,6 +38,22 @@ struct IO_CONTEXT; struct IRP_CONTEXT; struct LCB; +/* C typedef aliases – allow plain name usage without the 'struct' keyword */ +typedef struct IRP_CONTEXT_LITE IRP_CONTEXT_LITE; +typedef struct IO_CONTEXT IO_CONTEXT; +typedef struct IRP_CONTEXT IRP_CONTEXT; +typedef struct LCB LCB; +typedef struct UDFIdentifier UDFIdentifier; +typedef struct UDFObjectName UDFObjectName; +typedef struct CCB CCB; +typedef struct FCB_NONPAGED FCB_NONPAGED; +typedef struct FCB_DATA FCB_DATA; +typedef struct FCB_INDEX FCB_INDEX; +typedef struct FCB FCB; +typedef struct VCB VCB; +typedef struct VOLUME_DEVICE_OBJECT VOLUME_DEVICE_OBJECT; +typedef struct THREAD_CONTEXT THREAD_CONTEXT; + /************************************************************************** every structure has a node type, and a node size associated with it. The node type serves as a signature field. The size is used for @@ -48,8 +64,7 @@ struct UDFIdentifier { NODE_BYTE_SIZE NodeByteSize; // computed as sizeof(structure) }; -static_assert(sizeof(UDFIdentifier) == offsetof(FSRTL_ADVANCED_FCB_HEADER, Flags), - "UDFIdentifier size mismatch with NodeTypeCode and NodeByteSize in FSRTL_ADVANCED_FCB_HEADER"); +C_ASSERT(sizeof(UDFIdentifier) == offsetof(FSRTL_ADVANCED_FCB_HEADER, Flags)); /************************************************************************** Every open on-disk object must have a name associated with it @@ -68,7 +83,7 @@ struct UDFObjectName { // an absolute pathname of the object is stored below UNICODE_STRING ObjectName; }; -using PtrUDFObjectName = UDFObjectName*; +typedef UDFObjectName* PtrUDFObjectName; /************************************************************************** Each file open instance is represented by a context control block. @@ -107,7 +122,7 @@ struct CCB { PUNICODE_STRING DirectorySearchPattern; HASH_ENTRY hashes; }; -using PCCB = CCB*; +typedef CCB* PCCB; #define CCB_FLAG_IGNORE_CASE (0x00000004) // the CCB has had an IRP_MJ_CLEANUP issued on it. we must @@ -165,7 +180,7 @@ struct FCB_NONPAGED { FAST_MUTEX FcbFastMutex; }; -using PFCB_NONPAGED = FCB_NONPAGED*; +typedef FCB_NONPAGED* PFCB_NONPAGED; /************************************************************************** each open file/directory/volume is represented by a file control block. @@ -206,11 +221,11 @@ using PFCB_NONPAGED = FCB_NONPAGED*; /***************************************************/ struct FCB_DATA { - + UCHAR Placeholder; }; struct FCB_INDEX { - + UCHAR Placeholder; }; struct FCB { @@ -312,7 +327,7 @@ struct FCB { FCB_INDEX FcbIndex; }; }; -using PFCB = FCB*; +typedef FCB* PFCB; #define SIZEOF_FCB_DATA \ (FIELD_OFFSET(FCB, FcbType) + sizeof(FCB_DATA)) @@ -355,7 +370,7 @@ using PFCB = FCB*; **************************************************************************/ -enum UDFFSD_MEDIA_TYPE { +typedef enum UDFFSD_MEDIA_TYPE { MediaUnknown = 0, MediaHdd, MediaCdr, @@ -365,7 +380,7 @@ enum UDFFSD_MEDIA_TYPE { MediaFloppy, MediaDvdr, MediaDvdrw -}; +} UDFFSD_MEDIA_TYPE; //*************************************************************************** // LCB (Link Control Block) @@ -465,14 +480,14 @@ using PLCB = LCB*; // VCB (Volume Control Block) //*************************************************************************** -enum VCB_CONDITION { +typedef enum VCB_CONDITION { VcbNotMounted = 0, VcbMountInProgress, VcbMounted, VcbInvalid, VcbDismountInProgress -}; +} VCB_CONDITION; struct VCB { @@ -736,7 +751,7 @@ struct VCB { PVPB SwapVpb; }; -using PVCB = VCB*; +typedef VCB* PVCB; // One for root #define UDFS_BASE_RESIDUAL_REFERENCE (4)//(6) @@ -810,7 +825,7 @@ struct THREAD_CONTEXT { // will store the IrpContext for the request in this stack location. IRP_CONTEXT* TopLevelIrpContext; }; -using PTHREAD_CONTEXT = THREAD_CONTEXT*; +typedef THREAD_CONTEXT* PTHREAD_CONTEXT; /************************************************************************** The IRP context encapsulates the current request. This structure is @@ -854,7 +869,7 @@ struct IRP_CONTEXT { VCB* Vcb; }; -using PIRP_CONTEXT = IRP_CONTEXT*; +typedef IRP_CONTEXT* PIRP_CONTEXT; #define IRP_CONTEXT_FLAG_ON_STACK (0x00000001) #define IRP_CONTEXT_FLAG_MORE_PROCESSING (0x00000002) @@ -919,7 +934,7 @@ struct IRP_CONTEXT_LITE { // Real device object. This represents the physical device closest to the media. PDEVICE_OBJECT RealDevice; }; -using PIRP_CONTEXT_LITE = IRP_CONTEXT_LITE*; +typedef IRP_CONTEXT_LITE* PIRP_CONTEXT_LITE; /************************************************************************** we will store all of our global variables in one structure. diff --git a/drivers/filesystems/udfs/udf_info/ecma_167.h b/drivers/filesystems/udfs/udf_info/ecma_167.h index 6ca06a7c47fc2..36ace5e01cda5 100644 --- a/drivers/filesystems/udfs/udf_info/ecma_167.h +++ b/drivers/filesystems/udfs/udf_info/ecma_167.h @@ -770,6 +770,39 @@ typedef struct _EXTENDED_FILE_ENTRY { typedef EXTENDED_FILE_ENTRY ExtendedFileEntry; +/* C typedef aliases for all non-typedef struct declarations */ +typedef struct VolStructDesc VolStructDesc; +typedef struct BeginningExtendedAreaDesc BeginningExtendedAreaDesc; +typedef struct TerminatingExtendedAreaDesc TerminatingExtendedAreaDesc; +typedef struct NSRDesc NSRDesc; +typedef struct PrimaryVolDesc PrimaryVolDesc; +typedef struct AnchorVolDescPtr AnchorVolDescPtr; +typedef struct VolDescPtr VolDescPtr; +typedef struct ImpUseVolDesc ImpUseVolDesc; +typedef struct PartitionDesc PartitionDesc; +typedef struct LogicalVolDesc LogicalVolDesc; +typedef struct GenericPartitionMap GenericPartitionMap; +typedef struct GenericPartitionMap1 GenericPartitionMap1; +typedef struct GenericPartitionMap2 GenericPartitionMap2; +typedef struct TerminatingDesc TerminatingDesc; +typedef struct GenericDesc GenericDesc; +typedef struct LogicalVolIntegrityDesc LogicalVolIntegrityDesc; +typedef struct IndirectEntry IndirectEntry; +typedef struct TerminalEntry TerminalEntry; +typedef struct ExtendedAttrHeaderDesc ExtendedAttrHeaderDesc; +typedef struct GenericAttrFormat GenericAttrFormat; +typedef struct CharSetAttrFormat CharSetAttrFormat; +typedef struct AlternatePermissionsExtendedAttr AlternatePermissionsExtendedAttr; +typedef struct FileTimesExtendedAttr FileTimesExtendedAttr; +typedef struct InfoTimesExtendedAttr InfoTimesExtendedAttr; +typedef struct DeviceSpecificationExtendedAttr DeviceSpecificationExtendedAttr; +typedef struct ImpUseExtendedAttr ImpUseExtendedAttr; +typedef struct AppUseExtendedAttr AppUseExtendedAttr; +typedef struct UnallocatedSpaceEntry UnallocatedSpaceEntry; +typedef struct PartitionIntegrityEntry PartitionIntegrityEntry; +typedef struct LogicalVolHeaderDesc LogicalVolHeaderDesc; +typedef struct PathComponent PathComponent; + #pragma pack(pop) #endif /* __ECMA_167_H__ */ diff --git a/drivers/filesystems/udfs/udf_info/osta_misc.h b/drivers/filesystems/udfs/udf_info/osta_misc.h index f9813bfb321c7..60b522c380bae 100644 --- a/drivers/filesystems/udfs/udf_info/osta_misc.h +++ b/drivers/filesystems/udfs/udf_info/osta_misc.h @@ -348,6 +348,17 @@ typedef UID_MAPPING_TABLE* PUID_MAPPING_TABLE; #define TID_ADAPTEC_LOGICAL_VOL_DESC 0x9999U +/* C typedef aliases for all non-typedef struct declarations */ +typedef struct LogicalVolIntegrityDescImpUse LogicalVolIntegrityDescImpUse; +typedef struct ImpUseVolDescImpUse ImpUseVolDescImpUse; +typedef struct UdfPartitionMap2 UdfPartitionMap2; +typedef struct VirtualPartitionMap VirtualPartitionMap; +typedef struct DVDCopyrightImpUse DVDCopyrightImpUse; +typedef struct ADImpUse ADImpUse; +typedef struct FidADImpUse FidADImpUse; +typedef struct VirtualAllocationTable15 VirtualAllocationTable15; +typedef struct VirtualAllocationTable20 VirtualAllocationTable20; + #pragma pack(pop) #endif /* _OSTA_MISC_H */ diff --git a/drivers/filesystems/udfs/udf_info/udf_rel.h b/drivers/filesystems/udfs/udf_info/udf_rel.h index cefcb3b8c2d0c..59a6ddcc2f887 100644 --- a/drivers/filesystems/udfs/udf_info/udf_rel.h +++ b/drivers/filesystems/udfs/udf_info/udf_rel.h @@ -244,7 +244,7 @@ typedef struct _UDF_DATALOC_INFO { NT-specific field. As soon as NT supports HardLink concept it has own structure describing the file's actual data. */ - FCB* CommonFcb; // pointer to corresponding FCB + struct FCB* CommonFcb; // pointer to corresponding FCB /** Describes on-disk location of user data. If the file is recorded using IN_ICB method this structure points to the diff --git a/udfs-for-write-branch.patch b/udfs-for-write-branch.patch index a01c250057268..b31797e4e0990 100644 --- a/udfs-for-write-branch.patch +++ b/udfs-for-write-branch.patch @@ -242,19 +242,314 @@ similarity index 100% rename from drivers/filesystems/udfs/pnp.cpp rename to drivers/filesystems/udfs/pnp.c diff --git a/drivers/filesystems/udfs/protos.h b/drivers/filesystems/udfs/protos.h -index 59cb00c..7898d13 100644 +index 59cb00c..72a70d6 100644 --- a/drivers/filesystems/udfs/protos.h +++ b/drivers/filesystems/udfs/protos.h -@@ -964,7 +964,7 @@ UDFCommonShutdown( +@@ -73,7 +73,7 @@ UDFDecodeFileObjectCcb( + + + /************************************************************************* +-* Prototypes for the file create.cpp ++* Prototypes for the file create.c + *************************************************************************/ + extern NTSTATUS NTAPI UDFCreate( + IN PDEVICE_OBJECT DeviceObject, // the logical volume device object +@@ -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 +@@ -120,7 +131,7 @@ UDFInitializeFCB( + ); + + /************************************************************************* +-* Prototypes for the file cleanup.cpp ++* Prototypes for the file cleanup.c + *************************************************************************/ + extern NTSTATUS NTAPI UDFCleanup( + PDEVICE_OBJECT DeviceObject, // the logical volume device object +@@ -130,17 +141,8 @@ 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 ++* Prototypes for the file close.c + *************************************************************************/ + extern NTSTATUS NTAPI UDFClose( + PDEVICE_OBJECT DeviceObject, // the logical volume device object +@@ -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 + ); + +@@ -176,7 +178,7 @@ UDFFspClose( + UDFCloseAllSystemDelayedInDir((Fcb)->Vcb, (Fcb)->FileInfo) + /************************************************************************* - * Prototypes for the file UDFinit.cpp +-* Prototypes for the file dircntrl.cpp ++* Prototypes for the file dircntrl.c + *************************************************************************/ + extern NTSTATUS NTAPI UDFDirControl( + PDEVICE_OBJECT DeviceObject, // the logical volume device object +@@ -203,7 +205,7 @@ PFCB Fcb, + PCCB Ccb); + + /************************************************************************* +-* Prototypes for the file devcntrl.cpp ++* Prototypes for the file devcntrl.c + *************************************************************************/ + extern NTSTATUS NTAPI UDFDeviceControl( + PDEVICE_OBJECT DeviceObject, // the logical volume device object +@@ -224,7 +226,7 @@ extern NTSTATUS NTAPI UDFHandleQueryPath( + PVOID BufferPointer); + + /************************************************************************* +-* Prototypes for the file fastio.cpp ++* Prototypes for the file fastio.c + *************************************************************************/ + extern BOOLEAN NTAPI UDFFastIoCheckIfPossible( + IN PFILE_OBJECT FileObject, +@@ -360,7 +362,7 @@ UDFFastIoCopyWrite( + ); + + /************************************************************************* +-* Prototypes for the file fileinfo.cpp ++* Prototypes for the file fileinfo.c + *************************************************************************/ + + extern NTSTATUS UDFCommonQueryInfo( +@@ -516,7 +518,7 @@ UDFHardLink( + ); + + /************************************************************************* +-* Prototypes for the file flush.cpp ++* Prototypes for the file flush.c + *************************************************************************/ + extern NTSTATUS NTAPI UDFFlushBuffers( + PDEVICE_OBJECT DeviceObject, // the logical volume device object +@@ -563,7 +565,7 @@ extern VOID UDFFlushTryBreak( + IN PVCB Vcb); + + /************************************************************************* +-* Prototypes for the file fscntrl.cpp ++* Prototypes for the file fscntrl.c + *************************************************************************/ + + extern NTSTATUS NTAPI UDFFSControl( +@@ -659,7 +661,7 @@ UDFCommonPnp( + ); + + /************************************************************************* +-* Prototypes for the file LockCtrl.cpp ++* Prototypes for the file LockCtrl.c + *************************************************************************/ + + extern NTSTATUS NTAPI UDFLockControl( +@@ -670,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, +@@ -707,7 +711,7 @@ UDFFastUnlockAllByKey( + ); + + /************************************************************************* +-* Prototypes for the file misc.cpp ++* Prototypes for the file misc.c + *************************************************************************/ + extern NTSTATUS UDFInitializeZones( + VOID); +@@ -769,6 +773,49 @@ UDFDeleteCcb( + PCCB Ccb + ); + ++// prefxsup.c - 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, +@@ -779,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( +@@ -882,13 +933,13 @@ UDFCreateFileLock( + ); + + /************************************************************************* +-* Prototypes for the file NameSup.cpp ++* Prototypes for the file NameSup.c + *************************************************************************/ + + #include "namesup.h" + + /************************************************************************* +-* Prototypes for the file Pnp.cpp ++* Prototypes for the file Pnp.c + *************************************************************************/ + NTSTATUS + NTAPI +@@ -898,7 +949,7 @@ UDFPnp ( + ); + + /************************************************************************* +-* Prototypes for the file read.cpp ++* Prototypes for the file read.c + *************************************************************************/ + extern NTSTATUS NTAPI UDFRead( + PDEVICE_OBJECT DeviceObject, // the logical volume device object +@@ -952,7 +1003,7 @@ UDFSetAccessRights( + USHORT ShareAccess); + + /************************************************************************* +-* Prototypes for the file Shutdown.cpp ++* Prototypes for the file Shutdown.c + *************************************************************************/ + + NTSTATUS +@@ -962,9 +1013,9 @@ UDFCommonShutdown( + ); + + /************************************************************************* +-* Prototypes for the file UDFinit.cpp ++* Prototypes for the file UDFinit.c *************************************************************************/ -extern "C" NTSTATUS NTAPI DriverEntry( +NTSTATUS NTAPI DriverEntry( PDRIVER_OBJECT DriverObject, // created by the I/O sub-system PUNICODE_STRING RegistryPath); // path to the registry key -@@ -1271,7 +1271,7 @@ UDFAcquireResource( +@@ -972,7 +1023,7 @@ extern VOID NTAPI UDFInitializeFunctionPointers( + PDRIVER_OBJECT DriverObject); // created by the I/O sub-system + + /************************************************************************* +-* Prototypes for the file verify.cpp ++* Prototypes for the file verify.c + *************************************************************************/ + + VOID +@@ -1024,7 +1075,7 @@ UDFCompareVcb( + ); + + /************************************************************************* +-* Prototypes for the file VolInfo.cpp ++* Prototypes for the file VolInfo.c + *************************************************************************/ + extern NTSTATUS NTAPI UDFQueryVolInfo(PDEVICE_OBJECT DeviceObject, + PIRP Irp); +@@ -1051,7 +1102,7 @@ UDFCommonSetVolInfo( + ); + + /************************************************************************* +-* Prototypes for the file write.cpp ++* Prototypes for the file write.c + *************************************************************************/ + extern NTSTATUS NTAPI UDFWrite( + PDEVICE_OBJECT DeviceObject, // the logical volume device object +@@ -1217,13 +1268,13 @@ UDFMarkDevForVerifyIfVcbMounted( + UdfData.UdfDataLockThread = NULL; \ + ExReleaseFastMutexUnsafe(&UdfData.UdfDataMutex) + +-enum TYPE_OF_ACQUIRE { ++typedef enum TYPE_OF_ACQUIRE { + + AcquireExclusive, + AcquireShared, + AcquireSharedStarveExclusive + +-}; ++} TYPE_OF_ACQUIRE; + + _Requires_lock_held_(_Global_critical_region_) + _When_(Type == AcquireExclusive && return != FALSE, _Acquires_exclusive_lock_(*Resource)) +@@ -1271,7 +1322,7 @@ UDFAcquireResource( #define UDFReleasePagingIo(IC,F) \ ExReleaseResourceLite((F)->Header.PagingIoResource) @@ -263,7 +558,7 @@ index 59cb00c..7898d13 100644 ULONG UDFHighBit( ULONG Word -@@ -1295,7 +1295,7 @@ UDFHighBit( +@@ -1295,7 +1346,7 @@ UDFHighBit( #define SectorSize(V) ((V)->SectorSize) @@ -272,7 +567,7 @@ index 59cb00c..7898d13 100644 ULONG SectorAlign( PVCB Vcb, -@@ -1305,7 +1305,7 @@ SectorAlign( +@@ -1305,7 +1356,7 @@ SectorAlign( return (Length + (Vcb->SectorSize - 1)) & ~(Vcb->SectorSize - 1); } @@ -281,7 +576,7 @@ index 59cb00c..7898d13 100644 ULONGLONG LlSectorAlign( PVCB Vcb, -@@ -1327,7 +1327,7 @@ UDFSetThreadContext( +@@ -1327,7 +1378,7 @@ UDFSetThreadContext( (IC)->ThreadContext = NULL @@ -290,7 +585,7 @@ index 59cb00c..7898d13 100644 BOOLEAN UdfIsExtendedFESupported( _In_ PVCB Vcb ) -@@ -1335,7 +1335,7 @@ BOOLEAN UdfIsExtendedFESupported( +@@ -1335,7 +1386,7 @@ BOOLEAN UdfIsExtendedFESupported( return Vcb->NSRDesc == VRS_NSR03_FOUND; } @@ -381,11 +676,262 @@ index 6e00af7..7964ebb 100644 VOID UDFDeallocateFcbData( PFCB Fcb +diff --git a/drivers/filesystems/udfs/struct.h b/drivers/filesystems/udfs/struct.h +index fb48f5e..53eb53b 100644 +--- a/drivers/filesystems/udfs/struct.h ++++ b/drivers/filesystems/udfs/struct.h +@@ -36,6 +36,24 @@ + struct IRP_CONTEXT_LITE; + struct IO_CONTEXT; + struct IRP_CONTEXT; ++struct LCB; ++typedef struct LCB *PLCB; ++ ++/* C typedef aliases – allow plain name usage without the 'struct' keyword */ ++typedef struct IRP_CONTEXT_LITE IRP_CONTEXT_LITE; ++typedef struct IO_CONTEXT IO_CONTEXT; ++typedef struct IRP_CONTEXT IRP_CONTEXT; ++typedef struct LCB LCB; ++typedef struct UDFIdentifier UDFIdentifier; ++typedef struct UDFObjectName UDFObjectName; ++typedef struct CCB CCB; ++typedef struct FCB_NONPAGED FCB_NONPAGED; ++typedef struct FCB_DATA FCB_DATA; ++typedef struct FCB_INDEX FCB_INDEX; ++typedef struct FCB FCB; ++typedef struct VCB VCB; ++typedef struct VOLUME_DEVICE_OBJECT VOLUME_DEVICE_OBJECT; ++typedef struct THREAD_CONTEXT THREAD_CONTEXT; + + /************************************************************************** + every structure has a node type, and a node size associated with it. +@@ -47,8 +65,7 @@ struct UDFIdentifier { + NODE_BYTE_SIZE NodeByteSize; // computed as sizeof(structure) + }; + +-static_assert(sizeof(UDFIdentifier) == offsetof(FSRTL_ADVANCED_FCB_HEADER, Flags), +- "UDFIdentifier size mismatch with NodeTypeCode and NodeByteSize in FSRTL_ADVANCED_FCB_HEADER"); ++C_ASSERT(sizeof(UDFIdentifier) == offsetof(FSRTL_ADVANCED_FCB_HEADER, Flags)); + + /************************************************************************** + Every open on-disk object must have a name associated with it +@@ -67,7 +84,7 @@ struct UDFObjectName { + // an absolute pathname of the object is stored below + UNICODE_STRING ObjectName; + }; +-using PtrUDFObjectName = UDFObjectName*; ++typedef UDFObjectName* PtrUDFObjectName; + + /************************************************************************** + Each file open instance is represented by a context control block. +@@ -82,6 +99,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,9 +113,8 @@ struct CCB { + // need to maintain a search pattern + PUNICODE_STRING DirectorySearchPattern; + HASH_ENTRY hashes; +- ULONG TreeLength; + }; +-using PCCB = CCB*; ++typedef CCB* PCCB; + + #define CCB_FLAG_IGNORE_CASE (0x00000004) + // the CCB has had an IRP_MJ_CLEANUP issued on it. we must +@@ -152,7 +170,7 @@ struct FCB_NONPAGED { + FAST_MUTEX AdvancedFcbHeaderMutex; + + }; +-using PFCB_NONPAGED = FCB_NONPAGED*; ++typedef FCB_NONPAGED* PFCB_NONPAGED; + + /************************************************************************** + each open file/directory/volume is represented by a file control block. +@@ -193,11 +211,11 @@ using PFCB_NONPAGED = FCB_NONPAGED*; + /***************************************************/ + + struct FCB_DATA { +- ++ UCHAR Placeholder; + }; + + struct FCB_INDEX { +- ++ UCHAR Placeholder; + }; + + struct FCB { +@@ -267,6 +285,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; +@@ -284,7 +309,7 @@ struct FCB { + FCB_INDEX FcbIndex; + }; + }; +-using PFCB = FCB*; ++typedef FCB* PFCB; + + #define SIZEOF_FCB_DATA \ + (FIELD_OFFSET(FCB, FcbType) + sizeof(FCB_DATA)) +@@ -325,7 +350,7 @@ using PFCB = FCB*; + + **************************************************************************/ + +-enum UDFFSD_MEDIA_TYPE { ++typedef enum UDFFSD_MEDIA_TYPE { + MediaUnknown = 0, + MediaHdd, + MediaCdr, +@@ -335,16 +360,63 @@ enum UDFFSD_MEDIA_TYPE { + MediaFloppy, + MediaDvdr, + MediaDvdrw ++} UDFFSD_MEDIA_TYPE; ++ ++//*************************************************************************** ++// 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; + }; + +-enum VCB_CONDITION { ++// 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) ++//*************************************************************************** ++ ++typedef enum VCB_CONDITION { + + VcbNotMounted = 0, + VcbMountInProgress, + VcbMounted, + VcbInvalid, + VcbDismountInProgress +-}; ++} VCB_CONDITION; + + struct VCB { + +@@ -608,7 +680,7 @@ struct VCB { + PVPB SwapVpb; + }; + +-using PVCB = VCB*; ++typedef VCB* PVCB; + + // One for root + #define UDFS_BASE_RESIDUAL_REFERENCE (4)//(6) +@@ -682,7 +754,7 @@ struct THREAD_CONTEXT { + // will store the IrpContext for the request in this stack location. + IRP_CONTEXT* TopLevelIrpContext; + }; +-using PTHREAD_CONTEXT = THREAD_CONTEXT*; ++typedef THREAD_CONTEXT* PTHREAD_CONTEXT; + + /************************************************************************** + The IRP context encapsulates the current request. This structure is +@@ -707,7 +779,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. +@@ -727,7 +798,7 @@ struct IRP_CONTEXT { + + VCB* Vcb; + }; +-using PIRP_CONTEXT = IRP_CONTEXT*; ++typedef IRP_CONTEXT* PIRP_CONTEXT; + + #define IRP_CONTEXT_FLAG_ON_STACK (0x00000001) + #define IRP_CONTEXT_FLAG_MORE_PROCESSING (0x00000002) +@@ -792,9 +863,8 @@ 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*; ++typedef IRP_CONTEXT_LITE* PIRP_CONTEXT_LITE; + + /************************************************************************** + we will store all of our global variables in one structure. +@@ -837,6 +907,7 @@ typedef struct _UDFData { + PAGED_LOOKASIDE_LIST UDFFcbDataLookasideList; + + PAGED_LOOKASIDE_LIST CcbLookasideList; ++ PAGED_LOOKASIDE_LIST LcbLookasideList; + + LIST_ENTRY AsyncCloseQueue; + ULONG AsyncCloseCount; +@@ -877,6 +948,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/sys_spec.cpp b/drivers/filesystems/udfs/sys_spec.c -similarity index 91% +similarity index 95% rename from drivers/filesystems/udfs/sys_spec.cpp rename to drivers/filesystems/udfs/sys_spec.c -index e9a11ab..82f2665 100644 +index e9a11ab..df66b8c 100644 --- a/drivers/filesystems/udfs/sys_spec.cpp +++ b/drivers/filesystems/udfs/sys_spec.c @@ -20,6 +20,6 @@ @@ -395,8 +941,7 @@ index e9a11ab..82f2665 100644 -#include "Include/Sys_spec_lib.cpp" +#include "Include/Sys_spec_lib.c" --//#include "Include/tools.cpp" -+//#include "Include/tools.c" + //#include "Include/tools.cpp" diff --git a/drivers/filesystems/udfs/udf_dbg.cpp b/drivers/filesystems/udfs/udf_dbg.c similarity index 100% rename from drivers/filesystems/udfs/udf_dbg.cpp @@ -409,6 +954,50 @@ diff --git a/drivers/filesystems/udfs/udf_info/dirtree.cpp b/drivers/filesystems similarity index 100% rename from drivers/filesystems/udfs/udf_info/dirtree.cpp rename to drivers/filesystems/udfs/udf_info/dirtree.c +diff --git a/drivers/filesystems/udfs/udf_info/ecma_167.h b/drivers/filesystems/udfs/udf_info/ecma_167.h +index 6ca06a7..36ace5e 100644 +--- a/drivers/filesystems/udfs/udf_info/ecma_167.h ++++ b/drivers/filesystems/udfs/udf_info/ecma_167.h +@@ -770,6 +770,39 @@ typedef struct _EXTENDED_FILE_ENTRY { + + typedef EXTENDED_FILE_ENTRY ExtendedFileEntry; + ++/* C typedef aliases for all non-typedef struct declarations */ ++typedef struct VolStructDesc VolStructDesc; ++typedef struct BeginningExtendedAreaDesc BeginningExtendedAreaDesc; ++typedef struct TerminatingExtendedAreaDesc TerminatingExtendedAreaDesc; ++typedef struct NSRDesc NSRDesc; ++typedef struct PrimaryVolDesc PrimaryVolDesc; ++typedef struct AnchorVolDescPtr AnchorVolDescPtr; ++typedef struct VolDescPtr VolDescPtr; ++typedef struct ImpUseVolDesc ImpUseVolDesc; ++typedef struct PartitionDesc PartitionDesc; ++typedef struct LogicalVolDesc LogicalVolDesc; ++typedef struct GenericPartitionMap GenericPartitionMap; ++typedef struct GenericPartitionMap1 GenericPartitionMap1; ++typedef struct GenericPartitionMap2 GenericPartitionMap2; ++typedef struct TerminatingDesc TerminatingDesc; ++typedef struct GenericDesc GenericDesc; ++typedef struct LogicalVolIntegrityDesc LogicalVolIntegrityDesc; ++typedef struct IndirectEntry IndirectEntry; ++typedef struct TerminalEntry TerminalEntry; ++typedef struct ExtendedAttrHeaderDesc ExtendedAttrHeaderDesc; ++typedef struct GenericAttrFormat GenericAttrFormat; ++typedef struct CharSetAttrFormat CharSetAttrFormat; ++typedef struct AlternatePermissionsExtendedAttr AlternatePermissionsExtendedAttr; ++typedef struct FileTimesExtendedAttr FileTimesExtendedAttr; ++typedef struct InfoTimesExtendedAttr InfoTimesExtendedAttr; ++typedef struct DeviceSpecificationExtendedAttr DeviceSpecificationExtendedAttr; ++typedef struct ImpUseExtendedAttr ImpUseExtendedAttr; ++typedef struct AppUseExtendedAttr AppUseExtendedAttr; ++typedef struct UnallocatedSpaceEntry UnallocatedSpaceEntry; ++typedef struct PartitionIntegrityEntry PartitionIntegrityEntry; ++typedef struct LogicalVolHeaderDesc LogicalVolHeaderDesc; ++typedef struct PathComponent PathComponent; ++ + #pragma pack(pop) + + #endif /* __ECMA_167_H__ */ diff --git a/drivers/filesystems/udfs/udf_info/extent.cpp b/drivers/filesystems/udfs/udf_info/extent.c similarity index 100% rename from drivers/filesystems/udfs/udf_info/extent.cpp @@ -417,6 +1006,28 @@ diff --git a/drivers/filesystems/udfs/udf_info/mount.cpp b/drivers/filesystems/u similarity index 100% rename from drivers/filesystems/udfs/udf_info/mount.cpp rename to drivers/filesystems/udfs/udf_info/mount.c +diff --git a/drivers/filesystems/udfs/udf_info/osta_misc.h b/drivers/filesystems/udfs/udf_info/osta_misc.h +index f9813bf..60b522c 100644 +--- a/drivers/filesystems/udfs/udf_info/osta_misc.h ++++ b/drivers/filesystems/udfs/udf_info/osta_misc.h +@@ -348,6 +348,17 @@ typedef UID_MAPPING_TABLE* PUID_MAPPING_TABLE; + + #define TID_ADAPTEC_LOGICAL_VOL_DESC 0x9999U + ++/* C typedef aliases for all non-typedef struct declarations */ ++typedef struct LogicalVolIntegrityDescImpUse LogicalVolIntegrityDescImpUse; ++typedef struct ImpUseVolDescImpUse ImpUseVolDescImpUse; ++typedef struct UdfPartitionMap2 UdfPartitionMap2; ++typedef struct VirtualPartitionMap VirtualPartitionMap; ++typedef struct DVDCopyrightImpUse DVDCopyrightImpUse; ++typedef struct ADImpUse ADImpUse; ++typedef struct FidADImpUse FidADImpUse; ++typedef struct VirtualAllocationTable15 VirtualAllocationTable15; ++typedef struct VirtualAllocationTable20 VirtualAllocationTable20; ++ + #pragma pack(pop) + + #endif /* _OSTA_MISC_H */ diff --git a/drivers/filesystems/udfs/udf_info/phys_eject.cpp b/drivers/filesystems/udfs/udf_info/phys_eject.c similarity index 100% rename from drivers/filesystems/udfs/udf_info/phys_eject.cpp @@ -443,6 +1054,38 @@ diff --git a/drivers/filesystems/udfs/udf_info/udf_info.cpp b/drivers/filesystem similarity index 100% rename from drivers/filesystems/udfs/udf_info/udf_info.cpp rename to drivers/filesystems/udfs/udf_info/udf_info.c +diff --git a/drivers/filesystems/udfs/udf_info/udf_rel.h b/drivers/filesystems/udfs/udf_info/udf_rel.h +index 602a8f6..f62ef96 100644 +--- a/drivers/filesystems/udfs/udf_info/udf_rel.h ++++ b/drivers/filesystems/udfs/udf_info/udf_rel.h +@@ -246,7 +246,7 @@ typedef struct _UDF_DATALOC_INFO { + NT-specific field. As soon as NT supports HardLink concept it + has own structure describing the file's actual data. + */ +- FCB* CommonFcb; // pointer to corresponding FCB ++ struct FCB* CommonFcb; // pointer to corresponding FCB + /** + Describes on-disk location of user data. If the file is + recorded using IN_ICB method this structure points to the +@@ -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/udfdata.cpp b/drivers/filesystems/udfs/udfdata.c similarity index 100% rename from drivers/filesystems/udfs/udfdata.cpp From ff8baff70a807df2c2c8b2746d9a5b1b928d9cf2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 6 Mar 2026 05:30:28 +0000 Subject: [PATCH 07/20] Regenerate write-branch patch with only C++->C syntax fixes, no udf-dev additions Co-authored-by: Zero3K20 <258969903+Zero3K20@users.noreply.github.com> --- udfs-for-write-branch.patch | 371 +++++------------------------------- 1 file changed, 45 insertions(+), 326 deletions(-) diff --git a/udfs-for-write-branch.patch b/udfs-for-write-branch.patch index b31797e4e0990..8d94a397be2b1 100644 --- a/udfs-for-write-branch.patch +++ b/udfs-for-write-branch.patch @@ -1,9 +1,8 @@ diff --git a/drivers/filesystems/udfs/CMakeLists.txt b/drivers/filesystems/udfs/CMakeLists.txt -index 53ce00f..4332487 100644 +index 53ce00f..6d1cb9c 100644 --- a/drivers/filesystems/udfs/CMakeLists.txt +++ b/drivers/filesystems/udfs/CMakeLists.txt -@@ -1,55 +1,51 @@ -- +@@ -2,54 +2,51 @@ include_directories(Include) list(APPEND SOURCE @@ -242,7 +241,7 @@ similarity index 100% rename from drivers/filesystems/udfs/pnp.cpp rename to drivers/filesystems/udfs/pnp.c diff --git a/drivers/filesystems/udfs/protos.h b/drivers/filesystems/udfs/protos.h -index 59cb00c..72a70d6 100644 +index 59cb00c..e911a28 100644 --- a/drivers/filesystems/udfs/protos.h +++ b/drivers/filesystems/udfs/protos.h @@ -73,7 +73,7 @@ UDFDecodeFileObjectCcb( @@ -254,25 +253,7 @@ index 59cb00c..72a70d6 100644 *************************************************************************/ extern NTSTATUS NTAPI UDFCreate( IN PDEVICE_OBJECT DeviceObject, // the logical volume device object -@@ -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 -@@ -120,7 +131,7 @@ UDFInitializeFCB( +@@ -120,7 +120,7 @@ UDFInitializeFCB( ); /************************************************************************* @@ -281,35 +262,16 @@ index 59cb00c..72a70d6 100644 *************************************************************************/ extern NTSTATUS NTAPI UDFCleanup( PDEVICE_OBJECT DeviceObject, // the logical volume device object -@@ -130,17 +141,8 @@ 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 -- ); -- +@@ -140,7 +140,7 @@ UDFCloseFileInfoChain( + ); + /************************************************************************* -* Prototypes for the file close.cpp +* Prototypes for the file close.c *************************************************************************/ extern NTSTATUS NTAPI UDFClose( PDEVICE_OBJECT DeviceObject, // the logical volume device object -@@ -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 - ); - -@@ -176,7 +178,7 @@ UDFFspClose( +@@ -176,7 +176,7 @@ UDFFspClose( UDFCloseAllSystemDelayedInDir((Fcb)->Vcb, (Fcb)->FileInfo) /************************************************************************* @@ -318,7 +280,7 @@ index 59cb00c..72a70d6 100644 *************************************************************************/ extern NTSTATUS NTAPI UDFDirControl( PDEVICE_OBJECT DeviceObject, // the logical volume device object -@@ -203,7 +205,7 @@ PFCB Fcb, +@@ -203,7 +203,7 @@ PFCB Fcb, PCCB Ccb); /************************************************************************* @@ -327,7 +289,7 @@ index 59cb00c..72a70d6 100644 *************************************************************************/ extern NTSTATUS NTAPI UDFDeviceControl( PDEVICE_OBJECT DeviceObject, // the logical volume device object -@@ -224,7 +226,7 @@ extern NTSTATUS NTAPI UDFHandleQueryPath( +@@ -224,7 +224,7 @@ extern NTSTATUS NTAPI UDFHandleQueryPath( PVOID BufferPointer); /************************************************************************* @@ -336,7 +298,7 @@ index 59cb00c..72a70d6 100644 *************************************************************************/ extern BOOLEAN NTAPI UDFFastIoCheckIfPossible( IN PFILE_OBJECT FileObject, -@@ -360,7 +362,7 @@ UDFFastIoCopyWrite( +@@ -360,7 +360,7 @@ UDFFastIoCopyWrite( ); /************************************************************************* @@ -345,7 +307,7 @@ index 59cb00c..72a70d6 100644 *************************************************************************/ extern NTSTATUS UDFCommonQueryInfo( -@@ -516,7 +518,7 @@ UDFHardLink( +@@ -516,7 +516,7 @@ UDFHardLink( ); /************************************************************************* @@ -354,7 +316,7 @@ index 59cb00c..72a70d6 100644 *************************************************************************/ extern NTSTATUS NTAPI UDFFlushBuffers( PDEVICE_OBJECT DeviceObject, // the logical volume device object -@@ -563,7 +565,7 @@ extern VOID UDFFlushTryBreak( +@@ -563,7 +563,7 @@ extern VOID UDFFlushTryBreak( IN PVCB Vcb); /************************************************************************* @@ -363,7 +325,7 @@ index 59cb00c..72a70d6 100644 *************************************************************************/ extern NTSTATUS NTAPI UDFFSControl( -@@ -659,7 +661,7 @@ UDFCommonPnp( +@@ -659,7 +659,7 @@ UDFCommonPnp( ); /************************************************************************* @@ -372,18 +334,7 @@ index 59cb00c..72a70d6 100644 *************************************************************************/ extern NTSTATUS NTAPI UDFLockControl( -@@ -670,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, -@@ -707,7 +711,7 @@ UDFFastUnlockAllByKey( +@@ -707,7 +707,7 @@ UDFFastUnlockAllByKey( ); /************************************************************************* @@ -392,75 +343,7 @@ index 59cb00c..72a70d6 100644 *************************************************************************/ extern NTSTATUS UDFInitializeZones( VOID); -@@ -769,6 +773,49 @@ UDFDeleteCcb( - PCCB Ccb - ); - -+// prefxsup.c - 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, -@@ -779,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( -@@ -882,13 +933,13 @@ UDFCreateFileLock( +@@ -882,13 +882,13 @@ UDFCreateFileLock( ); /************************************************************************* @@ -476,7 +359,7 @@ index 59cb00c..72a70d6 100644 *************************************************************************/ NTSTATUS NTAPI -@@ -898,7 +949,7 @@ UDFPnp ( +@@ -898,7 +898,7 @@ UDFPnp ( ); /************************************************************************* @@ -485,7 +368,7 @@ index 59cb00c..72a70d6 100644 *************************************************************************/ extern NTSTATUS NTAPI UDFRead( PDEVICE_OBJECT DeviceObject, // the logical volume device object -@@ -952,7 +1003,7 @@ UDFSetAccessRights( +@@ -952,7 +952,7 @@ UDFSetAccessRights( USHORT ShareAccess); /************************************************************************* @@ -494,7 +377,7 @@ index 59cb00c..72a70d6 100644 *************************************************************************/ NTSTATUS -@@ -962,9 +1013,9 @@ UDFCommonShutdown( +@@ -962,9 +962,9 @@ UDFCommonShutdown( ); /************************************************************************* @@ -506,7 +389,7 @@ index 59cb00c..72a70d6 100644 PDRIVER_OBJECT DriverObject, // created by the I/O sub-system PUNICODE_STRING RegistryPath); // path to the registry key -@@ -972,7 +1023,7 @@ extern VOID NTAPI UDFInitializeFunctionPointers( +@@ -972,7 +972,7 @@ extern VOID NTAPI UDFInitializeFunctionPointers( PDRIVER_OBJECT DriverObject); // created by the I/O sub-system /************************************************************************* @@ -515,7 +398,7 @@ index 59cb00c..72a70d6 100644 *************************************************************************/ VOID -@@ -1024,7 +1075,7 @@ UDFCompareVcb( +@@ -1024,7 +1024,7 @@ UDFCompareVcb( ); /************************************************************************* @@ -524,7 +407,7 @@ index 59cb00c..72a70d6 100644 *************************************************************************/ extern NTSTATUS NTAPI UDFQueryVolInfo(PDEVICE_OBJECT DeviceObject, PIRP Irp); -@@ -1051,7 +1102,7 @@ UDFCommonSetVolInfo( +@@ -1051,7 +1051,7 @@ UDFCommonSetVolInfo( ); /************************************************************************* @@ -533,7 +416,7 @@ index 59cb00c..72a70d6 100644 *************************************************************************/ extern NTSTATUS NTAPI UDFWrite( PDEVICE_OBJECT DeviceObject, // the logical volume device object -@@ -1217,13 +1268,13 @@ UDFMarkDevForVerifyIfVcbMounted( +@@ -1217,13 +1217,13 @@ UDFMarkDevForVerifyIfVcbMounted( UdfData.UdfDataLockThread = NULL; \ ExReleaseFastMutexUnsafe(&UdfData.UdfDataMutex) @@ -549,51 +432,6 @@ index 59cb00c..72a70d6 100644 _Requires_lock_held_(_Global_critical_region_) _When_(Type == AcquireExclusive && return != FALSE, _Acquires_exclusive_lock_(*Resource)) -@@ -1271,7 +1322,7 @@ UDFAcquireResource( - #define UDFReleasePagingIo(IC,F) \ - ExReleaseResourceLite((F)->Header.PagingIoResource) - --inline -+static inline - ULONG - UDFHighBit( - ULONG Word -@@ -1295,7 +1346,7 @@ UDFHighBit( - - #define SectorSize(V) ((V)->SectorSize) - --inline -+static inline - ULONG - SectorAlign( - PVCB Vcb, -@@ -1305,7 +1356,7 @@ SectorAlign( - return (Length + (Vcb->SectorSize - 1)) & ~(Vcb->SectorSize - 1); - } - --inline -+static inline - ULONGLONG - LlSectorAlign( - PVCB Vcb, -@@ -1327,7 +1378,7 @@ UDFSetThreadContext( - (IC)->ThreadContext = NULL - - --inline -+static inline - BOOLEAN UdfIsExtendedFESupported( - _In_ PVCB Vcb - ) -@@ -1335,7 +1386,7 @@ BOOLEAN UdfIsExtendedFESupported( - return Vcb->NSRDesc == VRS_NSR03_FOUND; - } - --inline -+static inline - BOOLEAN UDFIsStreamsSupported( - _In_ PVCB Vcb - ) diff --git a/drivers/filesystems/udfs/read.cpp b/drivers/filesystems/udfs/read.c similarity index 100% rename from drivers/filesystems/udfs/read.cpp @@ -677,21 +515,17 @@ index 6e00af7..7964ebb 100644 UDFDeallocateFcbData( PFCB Fcb diff --git a/drivers/filesystems/udfs/struct.h b/drivers/filesystems/udfs/struct.h -index fb48f5e..53eb53b 100644 +index fb48f5e..75638fa 100644 --- a/drivers/filesystems/udfs/struct.h +++ b/drivers/filesystems/udfs/struct.h -@@ -36,6 +36,24 @@ - struct IRP_CONTEXT_LITE; +@@ -37,6 +37,21 @@ struct IRP_CONTEXT_LITE; struct IO_CONTEXT; struct IRP_CONTEXT; -+struct LCB; -+typedef struct LCB *PLCB; -+ -+/* C typedef aliases – allow plain name usage without the 'struct' keyword */ + ++/* C typedef aliases - allow plain name usage without the 'struct' keyword */ +typedef struct IRP_CONTEXT_LITE IRP_CONTEXT_LITE; +typedef struct IO_CONTEXT IO_CONTEXT; +typedef struct IRP_CONTEXT IRP_CONTEXT; -+typedef struct LCB LCB; +typedef struct UDFIdentifier UDFIdentifier; +typedef struct UDFObjectName UDFObjectName; +typedef struct CCB CCB; @@ -702,10 +536,11 @@ index fb48f5e..53eb53b 100644 +typedef struct VCB VCB; +typedef struct VOLUME_DEVICE_OBJECT VOLUME_DEVICE_OBJECT; +typedef struct THREAD_CONTEXT THREAD_CONTEXT; - ++ /************************************************************************** every structure has a node type, and a node size associated with it. -@@ -47,8 +65,7 @@ struct UDFIdentifier { + The node type serves as a signature field. The size is used for +@@ -47,8 +62,7 @@ struct UDFIdentifier { NODE_BYTE_SIZE NodeByteSize; // computed as sizeof(structure) }; @@ -715,7 +550,7 @@ index fb48f5e..53eb53b 100644 /************************************************************************** Every open on-disk object must have a name associated with it -@@ -67,7 +84,7 @@ struct UDFObjectName { +@@ -67,7 +81,7 @@ struct UDFObjectName { // an absolute pathname of the object is stored below UNICODE_STRING ObjectName; }; @@ -724,27 +559,16 @@ index fb48f5e..53eb53b 100644 /************************************************************************** Each file open instance is represented by a context control block. -@@ -82,6 +99,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,9 +113,8 @@ struct CCB { - // need to maintain a search pattern - PUNICODE_STRING DirectorySearchPattern; +@@ -96,7 +110,7 @@ struct CCB { HASH_ENTRY hashes; -- ULONG TreeLength; + ULONG TreeLength; }; -using PCCB = CCB*; +typedef CCB* PCCB; #define CCB_FLAG_IGNORE_CASE (0x00000004) // the CCB has had an IRP_MJ_CLEANUP issued on it. we must -@@ -152,7 +170,7 @@ struct FCB_NONPAGED { +@@ -152,7 +166,7 @@ struct FCB_NONPAGED { FAST_MUTEX AdvancedFcbHeaderMutex; }; @@ -753,7 +577,7 @@ index fb48f5e..53eb53b 100644 /************************************************************************** each open file/directory/volume is represented by a file control block. -@@ -193,11 +211,11 @@ using PFCB_NONPAGED = FCB_NONPAGED*; +@@ -193,11 +207,11 @@ using PFCB_NONPAGED = FCB_NONPAGED*; /***************************************************/ struct FCB_DATA { @@ -767,21 +591,7 @@ index fb48f5e..53eb53b 100644 }; struct FCB { -@@ -267,6 +285,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; -@@ -284,7 +309,7 @@ struct FCB { +@@ -284,7 +298,7 @@ struct FCB { FCB_INDEX FcbIndex; }; }; @@ -790,7 +600,7 @@ index fb48f5e..53eb53b 100644 #define SIZEOF_FCB_DATA \ (FIELD_OFFSET(FCB, FcbType) + sizeof(FCB_DATA)) -@@ -325,7 +350,7 @@ using PFCB = FCB*; +@@ -325,7 +339,7 @@ using PFCB = FCB*; **************************************************************************/ @@ -799,60 +609,14 @@ index fb48f5e..53eb53b 100644 MediaUnknown = 0, MediaHdd, MediaCdr, -@@ -335,16 +360,63 @@ enum UDFFSD_MEDIA_TYPE { +@@ -335,16 +349,16 @@ enum UDFFSD_MEDIA_TYPE { MediaFloppy, MediaDvdr, MediaDvdrw +-}; +} UDFFSD_MEDIA_TYPE; -+ -+//*************************************************************************** -+// 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; - }; -enum VCB_CONDITION { -+// 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) -+//*************************************************************************** -+ +typedef enum VCB_CONDITION { VcbNotMounted = 0, @@ -865,7 +629,7 @@ index fb48f5e..53eb53b 100644 struct VCB { -@@ -608,7 +680,7 @@ struct VCB { +@@ -608,7 +622,7 @@ struct VCB { PVPB SwapVpb; }; @@ -874,7 +638,7 @@ index fb48f5e..53eb53b 100644 // One for root #define UDFS_BASE_RESIDUAL_REFERENCE (4)//(6) -@@ -682,7 +754,7 @@ struct THREAD_CONTEXT { +@@ -682,7 +696,7 @@ struct THREAD_CONTEXT { // will store the IrpContext for the request in this stack location. IRP_CONTEXT* TopLevelIrpContext; }; @@ -883,15 +647,7 @@ index fb48f5e..53eb53b 100644 /************************************************************************** The IRP context encapsulates the current request. This structure is -@@ -707,7 +779,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. -@@ -727,7 +798,7 @@ struct IRP_CONTEXT { +@@ -727,7 +741,7 @@ struct IRP_CONTEXT { VCB* Vcb; }; @@ -900,33 +656,15 @@ index fb48f5e..53eb53b 100644 #define IRP_CONTEXT_FLAG_ON_STACK (0x00000001) #define IRP_CONTEXT_FLAG_MORE_PROCESSING (0x00000002) -@@ -792,9 +863,8 @@ struct IRP_CONTEXT_LITE { - ULONG UserReference; - // Real device object. This represents the physical device closest to the media. +@@ -794,7 +808,7 @@ struct IRP_CONTEXT_LITE { PDEVICE_OBJECT RealDevice; -- ULONG TreeLength; + ULONG TreeLength; }; -using PIRP_CONTEXT_LITE = IRP_CONTEXT_LITE*; +typedef IRP_CONTEXT_LITE* PIRP_CONTEXT_LITE; /************************************************************************** we will store all of our global variables in one structure. -@@ -837,6 +907,7 @@ typedef struct _UDFData { - PAGED_LOOKASIDE_LIST UDFFcbDataLookasideList; - - PAGED_LOOKASIDE_LIST CcbLookasideList; -+ PAGED_LOOKASIDE_LIST LcbLookasideList; - - LIST_ENTRY AsyncCloseQueue; - ULONG AsyncCloseCount; -@@ -877,6 +948,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/sys_spec.cpp b/drivers/filesystems/udfs/sys_spec.c similarity index 95% rename from drivers/filesystems/udfs/sys_spec.cpp @@ -1055,7 +793,7 @@ similarity index 100% rename from drivers/filesystems/udfs/udf_info/udf_info.cpp rename to drivers/filesystems/udfs/udf_info/udf_info.c diff --git a/drivers/filesystems/udfs/udf_info/udf_rel.h b/drivers/filesystems/udfs/udf_info/udf_rel.h -index 602a8f6..f62ef96 100644 +index 602a8f6..2b26348 100644 --- a/drivers/filesystems/udfs/udf_info/udf_rel.h +++ b/drivers/filesystems/udfs/udf_info/udf_rel.h @@ -246,7 +246,7 @@ typedef struct _UDF_DATALOC_INFO { @@ -1067,25 +805,6 @@ index 602a8f6..f62ef96 100644 /** Describes on-disk location of user data. If the file is recorded using IN_ICB method this structure points to the -@@ -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/udfdata.cpp b/drivers/filesystems/udfs/udfdata.c similarity index 100% rename from drivers/filesystems/udfs/udfdata.cpp From fb5b8733450b0122b4f4bb6a6560bd3d41ffecfc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 6 Mar 2026 05:57:49 +0000 Subject: [PATCH 08/20] Fix C++ default parameter values and DbgPrint declaration for MSVC C compilation Co-authored-by: Zero3K20 <258969903+Zero3K20@users.noreply.github.com> --- drivers/filesystems/udfs/Include/phys_lib.c | 4 +- drivers/filesystems/udfs/Include/phys_lib.h | 4 +- drivers/filesystems/udfs/cleanup.c | 285 ++++++------ drivers/filesystems/udfs/flush.c | 2 +- drivers/filesystems/udfs/fscntrl.c | 6 +- drivers/filesystems/udfs/protos.h | 10 +- drivers/filesystems/udfs/shutdown.c | 2 +- drivers/filesystems/udfs/strucsup.c | 4 +- drivers/filesystems/udfs/udf_dbg.h | 2 +- drivers/filesystems/udfs/udf_info/mount.c | 2 +- .../filesystems/udfs/udf_info/phys_eject.c | 2 +- drivers/filesystems/udfs/udf_info/udf_info.c | 384 ++++++++--------- drivers/filesystems/udfs/udf_info/udf_info.h | 40 +- drivers/filesystems/udfs/write.c | 4 +- udfs-for-write-branch.patch | 405 +++++++++++++++++- 15 files changed, 756 insertions(+), 400 deletions(-) diff --git a/drivers/filesystems/udfs/Include/phys_lib.c b/drivers/filesystems/udfs/Include/phys_lib.c index 3c4fd17eca371..d85a499e219a8 100644 --- a/drivers/filesystems/udfs/Include/phys_lib.c +++ b/drivers/filesystems/udfs/Include/phys_lib.c @@ -1036,7 +1036,7 @@ UDFReadSectors( OUT PULONG ReadBytes ) { - return UDFTRead(IrpContext, Vcb, Buffer, BCount*Vcb->SectorSize, Lba, ReadBytes); + return UDFTRead(IrpContext, Vcb, Buffer, BCount*Vcb->SectorSize, Lba, ReadBytes, 0); } // end UDFReadSectors() /* @@ -1167,7 +1167,7 @@ UDFWriteSectors( Vcb->LastLBA = Lba+BCount-1; } - status = UDFTWrite(IrpContext, Vcb, Buffer, BCount<SectorShift, Lba, WrittenBytes); + status = UDFTWrite(IrpContext, Vcb, Buffer, BCount<SectorShift, Lba, WrittenBytes, 0); ASSERT(NT_SUCCESS(status)); return status; diff --git a/drivers/filesystems/udfs/Include/phys_lib.h b/drivers/filesystems/udfs/Include/phys_lib.h index 747b95450acf7..19203d202daa5 100644 --- a/drivers/filesystems/udfs/Include/phys_lib.h +++ b/drivers/filesystems/udfs/Include/phys_lib.h @@ -15,7 +15,7 @@ UDFTRead( SIZE_T Length, ULONG LBA, PULONG ReadBytes, - ULONG Flags = 0 + ULONG Flags ); NTSTATUS @@ -26,7 +26,7 @@ UDFTWrite( IN SIZE_T Length, IN ULONG LBA, OUT PSIZE_T WrittenBytes, - IN ULONG Flags = 0 + IN ULONG Flags ); #define PH_TMP_BUFFER 1 diff --git a/drivers/filesystems/udfs/cleanup.c b/drivers/filesystems/udfs/cleanup.c index bc41f7c394c08..1d6c600d47bf9 100644 --- a/drivers/filesystems/udfs/cleanup.c +++ b/drivers/filesystems/udfs/cleanup.c @@ -154,6 +154,8 @@ UDFCommonCleanup( // we've cached close InterlockedDecrement((PLONG)&Fcb->CachedOpenHandleCount); } + ASSERT(Fcb->FcbCleanup <= (Fcb->FcbReference-1)); + MmPrint((" CcUninitializeCacheMap()\n")); CcUninitializeCacheMap(FileObject, NULL, NULL); @@ -174,26 +176,20 @@ UDFCommonCleanup( // Acquire current object only // Parent is acquired later only for delete operations (Child → Parent order) UDF_CHECK_PAGING_IO_RESOURCE(Fcb); - UDFAcquireFcbExclusive(IrpContext, Fcb, FALSE); + UDFAcquireResourceExclusive(&Fcb->FcbNonpaged->FcbResource, TRUE); AcquiredFCB = TRUE; // Decrement the cleanup counts in the Vcb and Fcb. - // Also decrement LCB reference count. UDFLockVcb(IrpContext, Vcb); UDFDecrementCleanupCounts(IrpContext, Fcb); - if (Ccb->Lcb) { - ASSERT(Ccb->Lcb->Reference > 0); - Ccb->Lcb->Reference--; - } UDFUnlockVcb(IrpContext, Vcb); if (FileObject->Flags & FO_CACHE_SUPPORTED) { // we've cached close InterlockedDecrement((PLONG)&Fcb->CachedOpenHandleCount); } - // No ASSERT on FcbCleanup vs FcbReference here - FcbCleanup - // can be temporarily bumped by try-lock reordering in create.cpp + ASSERT(Fcb->FcbCleanup <= (Fcb->FcbReference-1)); // check if Ccb being cleaned up has DeleteOnClose flag set if (Ccb->Flags & UDF_CCB_DELETE_ON_CLOSE) { @@ -224,147 +220,145 @@ UDFCommonCleanup( // get Link count lc = UDFGetFileLinkCount(Fcb->FileInfo); - NextFileInfo = Fcb->FileInfo; - - // Attempt delete if this is the last cleanup and DELETE_ON_CLOSE is set - if ((Fcb->FcbState & UDF_FCB_DELETE_ON_CLOSE) && + if ( (Fcb->FcbState & UDF_FCB_DELETE_ON_CLOSE) && !(Fcb->FcbCleanup)) { - - BOOLEAN DeleteAttempted = FALSE; - // This can be useful for Streams, those were brutally deleted // (together with parent object) ASSERT(!(Fcb->FcbState & UDF_FCB_ROOT_DIRECTORY)); FileObject->DeletePending = TRUE; - // Check if directory is non-empty — if so, discard delete - if ((Fcb->FcbState & UDF_FCB_DIRECTORY) && - !UDFIsDirEmpty__(NextFileInfo)) { - - Fcb->FcbState &= ~UDF_FCB_DELETE_ON_CLOSE; + // we should mark all streams of the file being deleted + // for deletion too, if there are no more Links to + // main data stream + if ((lc <= 1) && + !UDFIsSDirDeleted(Fcb->FileInfo->Dloc->SDirInfo)) { + RC = UDFMarkStreamsForDeletion(IrpContext, Vcb, Fcb, TRUE); // Delete + } + // 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); + AcquiredParentFCB = TRUE; + } - } else { + // we should set file sizes to zero if there are no more + // links to this file + if (lc <= 1) { + // Synchronize here with paging IO + UDFAcquireResourceExclusive(&Fcb->FcbNonpaged->FcbPagingIoResource, TRUE); + // set file size to zero (for system cache manager) +// Fcb->CommonFCBHeader.ValidDataLength.QuadPart = + Fcb->Header.FileSize.QuadPart = + Fcb->Header.ValidDataLength.QuadPart = 0; + CcSetFileSizes(FileObject, (PCC_FILE_SIZES)&Fcb->Header.AllocationSize); + + UDFReleaseResource(&Fcb->FcbNonpaged->FcbPagingIoResource); + } + } - DeleteAttempted = TRUE; + NextFileInfo = Fcb->FileInfo; - // Mark all streams for deletion if no more links - if ((lc <= 1) && - !UDFIsSDirDeleted(Fcb->FileInfo->Dloc->SDirInfo)) { - RC = UDFMarkStreamsForDeletion(IrpContext, Vcb, Fcb, TRUE); // Delete - } + // do we need to delete it now ? + if ( (Fcb->FcbState & UDF_FCB_DELETE_ON_CLOSE) && + !(Fcb->FcbCleanup)) { - // Acquire parent for delete operation (after current — child first order) - if (Fcb->FileInfo->ParentFile) { - UDF_CHECK_PAGING_IO_RESOURCE(Fcb->ParentFcb); - UDFAcquireFcbExclusive(IrpContext, Fcb->ParentFcb, FALSE); - AcquiredParentFCB = TRUE; + // can we do it ? + if (Fcb->FcbState & UDF_FCB_DIRECTORY) { + ASSERT(!(Fcb->FcbState & UDF_FCB_ROOT_DIRECTORY)); + if (!UDFIsDirEmpty__(NextFileInfo)) { + // forget about it + Fcb->FcbState &= ~UDF_FCB_DELETE_ON_CLOSE; + goto DiscardDelete; } - - // Note: do NOT set file sizes to zero here before unlink. - // If unlink fails (STATUS_CANNOT_DELETE), the file stays visible - // with FSize=0 — other threads see truncated data. - - // Mark parent object for deletion if requested - if ((Fcb->FcbState & UDF_FCB_DELETE_PARENT) && - Fcb->ParentFcb) { - ASSERT(!(Fcb->ParentFcb->FcbState & UDF_FCB_ROOT_DIRECTORY)); - Fcb->ParentFcb->FcbState |= UDF_FCB_DELETE_ON_CLOSE; + } else + if (lc <= 1) { + // Synchronize here with paging IO + BOOLEAN AcquiredPagingIo; + AcquiredPagingIo = UDFAcquireResourceExclusiveWithCheck(&Fcb->FcbNonpaged->FcbPagingIoResource); + // set file size to zero (for UdfInfo package) + // we should not do this for directories and linked files + UDFResizeFile__(IrpContext, Vcb, NextFileInfo, 0); + if (AcquiredPagingIo) { + UDFReleaseResource(&Fcb->FcbNonpaged->FcbPagingIoResource); } - - // Flush file. It is required by UDFUnlinkFile__() - RC = UDFFlushFile__(IrpContext, Vcb, NextFileInfo); - if (!NT_SUCCESS(RC)) { - AdPrint(("Error flushing file !!!\n")); - } - - // Try to unlink - RC = UDFUnlinkFile__(IrpContext, Vcb, NextFileInfo, TRUE); - - if (RC == STATUS_CANNOT_DELETE) { - - if (NextFileInfo->Dloc && - NextFileInfo->Dloc->SDirInfo && - NextFileInfo->Dloc->SDirInfo->Fcb) { - - // Can't delete file with open streams — pretend deleted. - // Streams will trigger parent deletion on their cleanup. - BrutePoint(); - if (!UDFIsSDirDeleted(NextFileInfo->Dloc->SDirInfo)) { - UDFPretendFileDeleted__(Vcb, Fcb->FileInfo); - } - - } else { - - // Can't delete due to references/permissions/other. - BrutePoint(); - ForcedCleanUp = TRUE; - Fcb->FcbState |= UDF_FCB_DELETED; - // Remove LCB from parent's splay trees immediately. - // Parent is held exclusive (AcquiredParentFCB). - if (Ccb->Lcb && Ccb->Lcb->ParentFcb) { - UdfRemoveNameLinks(Ccb->Lcb->ParentFcb, Ccb->Lcb); - } - RC = STATUS_SUCCESS; + } + // mark parent object for deletion if requested + if ((Fcb->FcbState & UDF_FCB_DELETE_PARENT) && + Fcb->ParentFcb) { + ASSERT(!(Fcb->ParentFcb->FcbState & UDF_FCB_ROOT_DIRECTORY)); + Fcb->ParentFcb->FcbState |= UDF_FCB_DELETE_ON_CLOSE; + } + // flush file. It is required by UDFUnlinkFile__() + RC = UDFFlushFile__(IrpContext, Vcb, NextFileInfo, 0); + if (!NT_SUCCESS(RC)) { + AdPrint(("Error flushing file !!!\n")); + } + // try to unlink + if ((RC = UDFUnlinkFile__(IrpContext, Vcb, NextFileInfo, TRUE)) == STATUS_CANNOT_DELETE) { + // If we can't delete file with Streams due to references, + // mark SDir & Streams + // for Deletion. We shall also set DELETE_PARENT flag to + // force Deletion of the current file later... when curently + // opened Streams would be cleaned up. + + // WARNING! We should keep SDir & Streams if there is a + // link to this file + if (NextFileInfo->Dloc && + NextFileInfo->Dloc->SDirInfo && + NextFileInfo->Dloc->SDirInfo->Fcb) { + + BrutePoint(); + if (!UDFIsSDirDeleted(NextFileInfo->Dloc->SDirInfo)) { +// RC = UDFMarkStreamsForDeletion(Vcb, Fcb, TRUE); // Delete +//#ifdef UDF_ALLOW_PRETEND_DELETED + UDFPretendFileDeleted__(Vcb, Fcb->FileInfo); +//#endif //UDF_ALLOW_PRETEND_DELETED } + goto NotifyDelete; } else { - - // Unlink completed (success or other error) — mark as deleted - ASSERT(!(Fcb->FcbState & UDF_FCB_ROOT_DIRECTORY)); - ForcedCleanUp = TRUE; - if (NT_SUCCESS(RC)) - Fcb->FcbState &= ~UDF_FCB_DELETE_ON_CLOSE; - Fcb->FcbState |= UDF_FCB_DELETED; - // Remove LCB from parent's splay trees immediately. - // Parent is held exclusive (AcquiredParentFCB). - if (Ccb->Lcb && Ccb->Lcb->ParentFcb) { - UdfRemoveNameLinks(Ccb->Lcb->ParentFcb, Ccb->Lcb); - } - // Note: do NOT call CcSetFileSizes(0) here. - // CcUninitializeCacheMap with TruncateSize=0 below (ForcedCleanUp path) - // already purges the cache. Setting Fcb->Header.FileSize=0 here would - // leave a stale FCB with FSize=0 in the prefix table — if the FCB is - // reused (e.g., by rename), the renamed file appears as 0-byte. - RC = STATUS_SUCCESS; + // Getting here means that we can't delete file because of + // References/PemissionsDenied/Smth.Else, + // but not Linked+OpenedStream + BrutePoint(); +// RC = STATUS_SUCCESS; + goto DiscardDelete_1; } + } else { +DiscardDelete_1: + // We have got an ugly ERROR, or + // file is deleted, so forget about it + ASSERT(!(Fcb->FcbState & UDF_FCB_ROOT_DIRECTORY)); + ForcedCleanUp = TRUE; + if (NT_SUCCESS(RC)) + Fcb->FcbState &= ~UDF_FCB_DELETE_ON_CLOSE; + Fcb->FcbState |= UDF_FCB_DELETED; + RC = STATUS_SUCCESS; } - - if (DeleteAttempted) { - // Prevent SetEOF operations on completely deleted data streams - if (lc < 1) { - Fcb->NtReqFCBFlags |= UDF_NTREQ_FCB_DELETED; - } - // Report that we have removed an entry. - if (UDFIsAStream(NextFileInfo)) { - UDFNotifyReportChange( IrpContext, Vcb, NextFileInfo->Fcb, - FILE_NOTIFY_CHANGE_STREAM_NAME, - FILE_ACTION_REMOVED_STREAM, - Ccb->Lcb, FileObject); - } else { - UDFNotifyReportChange( IrpContext, Vcb, NextFileInfo->Fcb, - UDFIsADirectory(NextFileInfo) ? FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME, - FILE_ACTION_REMOVED, - Ccb->Lcb, FileObject); - } +NotifyDelete: + // We should prevent SetEOF operations on completly + // deleted data streams + if (lc < 1) { + Fcb->NtReqFCBFlags |= UDF_NTREQ_FCB_DELETED; + } + // Report that we have removed an entry. + if (UDFIsAStream(NextFileInfo)) { + UDFNotifyFullReportChange( Vcb, NextFileInfo->Fcb, + FILE_NOTIFY_CHANGE_STREAM_NAME, + FILE_ACTION_REMOVED_STREAM); } else { - // Delete discarded (e.g. non-empty directory) — notify modification - UDFNotifyReportChange( IrpContext, Vcb, NextFileInfo->Fcb, - ((Ccb->Flags & UDF_CCB_ACCESS_TIME_SET) ? FILE_NOTIFY_CHANGE_LAST_ACCESS : 0) | - ((Ccb->Flags & UDF_CCB_WRITE_TIME_SET) ? (FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_LAST_WRITE) : 0) | - 0, - UDFIsAStream(NextFileInfo) ? FILE_ACTION_MODIFIED_STREAM : FILE_ACTION_MODIFIED, - Ccb->Lcb, FileObject); + UDFNotifyFullReportChange( Vcb, NextFileInfo->Fcb, + UDFIsADirectory(NextFileInfo) ? FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME, + FILE_ACTION_REMOVED); } - - } else if (Fcb->FcbState & UDF_FCB_DELETE_ON_CLOSE) { - - // DELETE_ON_CLOSE is set but FcbCleanup > 0 (other handles still open) - UDFNotifyReportChange( IrpContext, Vcb, NextFileInfo->Fcb, + } else + if (Fcb->FcbState & UDF_FCB_DELETE_ON_CLOSE) { +DiscardDelete: + UDFNotifyFullReportChange( Vcb, NextFileInfo->Fcb, ((Ccb->Flags & UDF_CCB_ACCESS_TIME_SET) ? FILE_NOTIFY_CHANGE_LAST_ACCESS : 0) | ((Ccb->Flags & UDF_CCB_WRITE_TIME_SET) ? (FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_LAST_WRITE) : 0) | 0, - UDFIsAStream(NextFileInfo) ? FILE_ACTION_MODIFIED_STREAM : FILE_ACTION_MODIFIED, - Ccb->Lcb, FileObject); + UDFIsAStream(NextFileInfo) ? FILE_ACTION_MODIFIED_STREAM : FILE_ACTION_MODIFIED); } if (Fcb->FcbState & UDF_FCB_DIRECTORY) { @@ -472,19 +466,17 @@ UDFCommonCleanup( if (UDFIsAStream(Fcb->FileInfo)) { - UDFNotifyReportChange(IrpContext, Vcb, + UDFNotifyFullReportChange(Vcb, Fcb, FILE_NOTIFY_CHANGE_STREAM_SIZE, - FILE_ACTION_MODIFIED_STREAM, - Ccb->Lcb, FileObject); + FILE_ACTION_MODIFIED_STREAM); } else { - UDFNotifyReportChange(IrpContext, Vcb, + UDFNotifyFullReportChange(Vcb, Fcb, FILE_NOTIFY_CHANGE_SIZE, - FILE_ACTION_MODIFIED, - Ccb->Lcb, FileObject); + FILE_ACTION_MODIFIED); } } @@ -509,19 +501,6 @@ UDFCommonCleanup( } } - // Flush FE (File Entry) to disk on last cleanup of non-deleted files. - // This prevents a race in UDFTeardownStructures where the FCB is removed - // from the FCB table (line ~497) before UDFFlushFile__ writes the FE to - // disk (line ~520). Without this, a concurrent open between those two - // points reads stale FE from disk with informationLength=0. - if (!Fcb->FcbCleanup && - !ForcedCleanUp && - !(Fcb->FcbState & UDF_FCB_DELETED) && - !(Vcb->VcbState & VCB_STATE_VOLUME_READ_ONLY) && - NextFileInfo) { - UDFFlushFile__(IrpContext, Vcb, NextFileInfo); - } - if (!(Fcb->FcbState & UDF_FCB_DIRECTORY) && ForcedCleanUp) { // flush system cache @@ -533,11 +512,13 @@ UDFCommonCleanup( } // release resources now. - UDFReleaseFcb(IrpContext, Fcb); + UDF_CHECK_PAGING_IO_RESOURCE(Fcb); + UDFReleaseResource(&Fcb->FcbNonpaged->FcbResource); AcquiredFCB = FALSE; if (AcquiredParentFCB && Fcb->FileInfo->ParentFile) { - UDFReleaseFcb(IrpContext, Fcb->FileInfo->ParentFile->Fcb); + UDF_CHECK_PAGING_IO_RESOURCE(Fcb->FileInfo->ParentFile->Fcb); + UDFReleaseResource(&Fcb->FileInfo->ParentFile->Fcb->FcbNonpaged->FcbResource); AcquiredParentFCB = FALSE; } @@ -564,15 +545,17 @@ try_exit: NOTHING; } _SEH2_FINALLY { if (AcquiredFCB) { - UDFReleaseFcb(IrpContext, Fcb); + UDF_CHECK_PAGING_IO_RESOURCE(Fcb); + UDFReleaseResource(&Fcb->FcbNonpaged->FcbResource); } if (AcquiredParentFCB && Fcb->FileInfo->ParentFile) { - UDFReleaseFcb(IrpContext, Fcb->FileInfo->ParentFile->Fcb); + UDF_CHECK_PAGING_IO_RESOURCE(Fcb->FileInfo->ParentFile->Fcb); + UDFReleaseResource(&Fcb->FileInfo->ParentFile->Fcb->FcbNonpaged->FcbResource); } if (AcquiredVcb) { - UDFReleaseVcb(IrpContext, Vcb); + UDFReleaseResource(&Vcb->VcbResource); AcquiredVcb = FALSE; } diff --git a/drivers/filesystems/udfs/flush.c b/drivers/filesystems/udfs/flush.c index 15e630b051a2d..52cbe2b9b4b61 100644 --- a/drivers/filesystems/udfs/flush.c +++ b/drivers/filesystems/udfs/flush.c @@ -125,7 +125,7 @@ UDFCommonFlush( UDFVerifyVcb(IrpContext, Vcb); - UDFFlushVolume(IrpContext, Vcb); + UDFFlushVolume(IrpContext, Vcb, 0); UDFReleaseVcb(IrpContext, Vcb); AcquiredVCB = FALSE; diff --git a/drivers/filesystems/udfs/fscntrl.c b/drivers/filesystems/udfs/fscntrl.c index 7847ba14fa429..a1d1a39014e33 100644 --- a/drivers/filesystems/udfs/fscntrl.c +++ b/drivers/filesystems/udfs/fscntrl.c @@ -997,7 +997,7 @@ Return Value: // remaining after the purge then we can allow the volume to be locked. // - UDFFlushVolume(IrpContext, Vcb); + UDFFlushVolume(IrpContext, Vcb, 0); //CdPurgeVolume( IrpContext, Vcb, FALSE ); // @@ -1181,7 +1181,7 @@ UDFDismountVolume( } else { - UDFFlushVolume(IrpContext, Vcb); + UDFFlushVolume(IrpContext, Vcb, 0); // Invalidate the volume right now. // @@ -1807,7 +1807,7 @@ UDFInvalidateVolumes( UDFAcquireVcbExclusive(IrpContext, Vcb, FALSE); - UDFFlushVolume(IrpContext, Vcb); + UDFFlushVolume(IrpContext, Vcb, 0); UDFDoDismountSequence(Vcb, FALSE); diff --git a/drivers/filesystems/udfs/protos.h b/drivers/filesystems/udfs/protos.h index 8d10e7455139f..d2c13f3a016d1 100644 --- a/drivers/filesystems/udfs/protos.h +++ b/drivers/filesystems/udfs/protos.h @@ -512,7 +512,7 @@ ULONG UDFFlushAFile( IN PFCB Fcb, IN PCCB Ccb, OUT PIO_STATUS_BLOCK PtrIoStatus, - IN ULONG FlushFlags = 0 + IN ULONG FlushFlags ); ULONG @@ -521,14 +521,14 @@ UDFFlushADirectory( IN PVCB Vcb, IN PUDF_FILE_INFO FI, OUT PIO_STATUS_BLOCK PtrIoStatus, - ULONG FlushFlags = 0 + ULONG FlushFlags ); NTSTATUS UDFFlushVolume( PIRP_CONTEXT IrpContext, PVCB Vcb, - ULONG FlushFlags = 0 + ULONG FlushFlags ); extern NTSTATUS NTAPI UDFFlushCompletion( @@ -538,7 +538,7 @@ PVOID Context); extern BOOLEAN UDFFlushIsBreaking( IN PVCB Vcb, -IN ULONG FlushFlags = 0); +IN ULONG FlushFlags); extern VOID UDFFlushTryBreak( IN PVCB Vcb); @@ -925,7 +925,7 @@ UDFReadRegKeys( extern ULONG UDFGetRegParameter( IN PVCB Vcb, IN PCWSTR Name, - IN ULONG DefValue = 0); + IN ULONG DefValue); VOID UDFDeleteVCB( diff --git a/drivers/filesystems/udfs/shutdown.c b/drivers/filesystems/udfs/shutdown.c index cabdf93c38ecc..682630e26c6ff 100644 --- a/drivers/filesystems/udfs/shutdown.c +++ b/drivers/filesystems/udfs/shutdown.c @@ -109,7 +109,7 @@ UDFCommonShutdown( UDFAcquireVcbExclusive(IrpContext, Vcb, FALSE); - UDFFlushVolume(IrpContext, Vcb); + UDFFlushVolume(IrpContext, Vcb, 0); ASSERT(CONTAINING_RECORD(IoGetCurrentIrpStackLocation(Irp)->DeviceObject, VOLUME_DEVICE_OBJECT, diff --git a/drivers/filesystems/udfs/strucsup.c b/drivers/filesystems/udfs/strucsup.c index 42a861b518d5e..6b3b815452fc4 100644 --- a/drivers/filesystems/udfs/strucsup.c +++ b/drivers/filesystems/udfs/strucsup.c @@ -510,14 +510,14 @@ UDFTeardownStructures( // no more references... current file/dir MUST DIE!!! if (Delete) { UDFReferenceFile__(CurrentFcb->FileInfo); - UDFFlushFile__(IrpContext, Vcb, CurrentFcb->FileInfo); + UDFFlushFile__(IrpContext, Vcb, CurrentFcb->FileInfo, 0); 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); + UDFFlushFile__(IrpContext, Vcb, CurrentFcb->FileInfo, 0); } else { // File is already deleted - clear Modified flags without flushing to disk. diff --git a/drivers/filesystems/udfs/udf_dbg.h b/drivers/filesystems/udfs/udf_dbg.h index 63fc430bc3c83..d176b88eca8bb 100644 --- a/drivers/filesystems/udfs/udf_dbg.h +++ b/drivers/filesystems/udfs/udf_dbg.h @@ -49,7 +49,7 @@ ULONG _cdecl DbgPrint( - PCH Format, + PCSTR Format, ... ); diff --git a/drivers/filesystems/udfs/udf_info/mount.c b/drivers/filesystems/udfs/udf_info/mount.c index 9e8b3d24c1e2a..47cb4b371a8df 100644 --- a/drivers/filesystems/udfs/udf_info/mount.c +++ b/drivers/filesystems/udfs/udf_info/mount.c @@ -911,7 +911,7 @@ UDFUpdateNonAllocated( } UDFPackMapping(Vcb, DataLoc); DataLoc->Length = UDFGetExtentLength(DataLoc->Mapping); - UDFFlushFile__(IrpContext, Vcb, Vcb->NonAllocFileInfo); + UDFFlushFile__(IrpContext, Vcb, Vcb->NonAllocFileInfo, 0); // ensure that BAD space is marked as USED UDFMarkSpaceAsXXX(Vcb, 0, &(DataLoc->Mapping[0]), AS_USED); // mark as used diff --git a/drivers/filesystems/udfs/udf_info/phys_eject.c b/drivers/filesystems/udfs/udf_info/phys_eject.c index f8b6333b187ab..32e98abd31501 100644 --- a/drivers/filesystems/udfs/udf_info/phys_eject.c +++ b/drivers/filesystems/udfs/udf_info/phys_eject.c @@ -28,7 +28,7 @@ UDFDoDismountSequence( ULONG i; // flush system cache - UDFFlushVolume(NULL, Vcb); + UDFFlushVolume(NULL, Vcb, 0); UDFPrint(("UDFDoDismountSequence:\n")); delay.QuadPart = -1000000; // 0.1 sec diff --git a/drivers/filesystems/udfs/udf_info/udf_info.c b/drivers/filesystems/udfs/udf_info/udf_info.c index 2ffa371740a76..b218cdc639d0d 100644 --- a/drivers/filesystems/udfs/udf_info/udf_info.c +++ b/drivers/filesystems/udfs/udf_info/udf_info.c @@ -138,10 +138,35 @@ static const uint32 crc32_tab[] = { 0x2d02ef8dL }; +/* + This routine allocates new memory block, copies data there & free old one +*/ +/*uint32 +UDFMemRealloc( + int8* OldBuff, + uint32 OldLength, + int8** NewBuff, + uint32 NewLength + ) +{ + int8* new_buff; + + (*NewBuff) = OldBuff; + if (OldLength == NewLength) return OldLength; + new_buff = (int8*)MyAllocatePool__(NonPagedPool, NewLength); + if (!new_buff) return 0; + if (OldLength > NewLength) OldLength = NewLength; + RtlCopyMemory(new_buff, OldBuff, OldLength); + MyFreePool__(OldBuff); + (*NewBuff) = new_buff; + return OldLength; +} // end UDFMemRealloc()*/ + /* This routine converts compressed Unicode to standard */ -VOID +void +__fastcall UDFDecompressUnicode( IN OUT PUNICODE_STRING UName, IN uint8* CS0, @@ -1232,7 +1257,8 @@ UDFSetAllocDescLen( fe->lengthAllocDescs = min(FileInfo->Dloc->AllocLoc.Mapping[0].extLength - FileInfo->Dloc->AllocLoc.Offset, (uint32)(FileInfo->Dloc->AllocLoc.Length)); - } else { + } else + if (Vcb->CompatFlags & UDF_VCB_IC_W2K_COMPAT_ALLOC_DESCS) { fe->lengthAllocDescs = (uint32)(FileInfo->Dloc->DataLoc.Length); } } else if (Ident == TID_EXTENDED_FILE_ENTRY) { @@ -1241,7 +1267,8 @@ UDFSetAllocDescLen( fe->lengthAllocDescs = min(FileInfo->Dloc->AllocLoc.Mapping[0].extLength - FileInfo->Dloc->AllocLoc.Offset, (uint32)(FileInfo->Dloc->AllocLoc.Length)); - } else { + } else + if (Vcb->CompatFlags & UDF_VCB_IC_W2K_COMPAT_ALLOC_DESCS) { fe->lengthAllocDescs = (uint32)(FileInfo->Dloc->DataLoc.Length); } } @@ -1587,7 +1614,14 @@ UDFWriteFile__( elen - Dloc->DataLoc.Offset, Dloc->DataLoc.Length)); UDFSetFileSize(FileInfo, t); - Dloc->DataLoc.Modified = TRUE; + if (Vcb->CompatFlags & UDF_VCB_IC_W2K_COMPAT_ALLOC_DESCS) { + ExtPrint((" w2k-compat -> rebuild allocs\n")); + Dloc->DataLoc.Modified = TRUE; + } else + 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; + } Dloc->DataLoc.Length = t; return UDFWriteExtent(IrpContext, Vcb, &Dloc->DataLoc, Offset, Length, Direct, Buffer, WrittenBytes); } @@ -1609,13 +1643,11 @@ UDFWriteFile__( ExtPrint((" init Alloc mode\n")); if ((((PFILE_ENTRY)(Dloc->FileEntry))->icbTag.flags & ICB_FLAG_ALLOC_MASK) == ICB_FLAG_AD_IN_ICB) { ((PFILE_ENTRY)(Dloc->FileEntry))->icbTag.flags &= ~ICB_FLAG_ALLOC_MASK; - ((PFILE_ENTRY)(Dloc->FileEntry))->icbTag.flags |= ICB_FLAG_AD_SHORT; + ((PFILE_ENTRY)(Dloc->FileEntry))->icbTag.flags |= Vcb->DefaultAllocMode; WasInIcb = TRUE; // Clear embedded data flag since file is no longer in ICB mode - // Fcb may be NULL during directory operations (FCB not yet created) - if (FileInfo->Fcb) { - FileInfo->Fcb->FcbState &= ~UDF_FCB_EMBEDDED_DATA; - } + ASSERT(FileInfo->Fcb); + FileInfo->Fcb->FcbState &= ~UDF_FCB_EMBEDDED_DATA; } // increase extent ExtPrint((" %s %s %s\n", @@ -1624,7 +1656,7 @@ UDFWriteFile__( Vcb->LowFreeSpace ? "LowSpace" : "")); if (UDFIsADirectory(FileInfo) && !WasInIcb && !Vcb->LowFreeSpace) { FileInfo->Dloc->DataLoc.Flags |= EXTENT_FLAG_ALLOC_SEQUENTIAL; - status = UDFResizeExtent(IrpContext, Vcb, PartNum, (t*2+Vcb->WriteBlockSize-1) & ~(ULONGLONG)(Vcb->WriteBlockSize-1), FALSE, &(Dloc->DataLoc)); + status = UDFResizeExtent(IrpContext, Vcb, PartNum, (t*2+Vcb->WriteBlockSize-1) & ~(SIZE_T)(Vcb->WriteBlockSize-1), FALSE, &(Dloc->DataLoc)); if (NT_SUCCESS(status)) { AdPrint((" preallocated space for Dir\n")); FileInfo->Dloc->DataLoc.Flags |= EXTENT_FLAG_PREALLOCATED; @@ -1681,7 +1713,14 @@ UDFWriteFile__( return status; UDFSetFileSize(FileInfo, t); Dloc->DataLoc.Modified = TRUE; - ASSERT(UDFGetFileSize(FileInfo) <= UDFGetExtentLength(FileInfo->Dloc->DataLoc.Mapping)); +#ifdef UDF_DBG + if (Vcb->CompatFlags & UDF_VCB_IC_W2K_COMPAT_ALLOC_DESCS) { + ASSERT(UDFGetFileSize(FileInfo) <= UDFGetExtentLength(FileInfo->Dloc->DataLoc.Mapping)); + } else { + 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; } // end UDFWriteFile__() @@ -1719,30 +1758,11 @@ UDFUnlinkFile__( // check references Dloc = FileInfo->Dloc; - // Original check was too strict: (OpenCount) || (RefCount > 1) - // Problem: When we open a file via UDFOpenFile__ to delete it during rename, - // that adds +1 to RefCount. If there's also a delayed-close reference, - // RefCount becomes 2 and unlink fails even though OpenCount=0. - // Fix: Only check OpenCount. RefCount will be properly managed by Close/CleanUp. - // The key insight is: OpenCount tracks actual user handles, RefCount tracks - // internal references. If no user has the file open (OpenCount=0), we should - // be able to unlink it. - // When FreeSpace=FALSE (rename/move), we only unlink the FID from the - // directory — the file data stays intact. OpenCount/RefCount/SDirInfo checks - // are not relevant because the file remains alive under a new name. - if (FreeSpace) { - if (FileInfo->OpenCount) { - AdPrint(("UDFUnlinkFile__: OpenCount=%d, cannot delete\n", FileInfo->OpenCount)); - return STATUS_CANNOT_DELETE; - } - if (FileInfo->RefCount > 2) { - AdPrint(("UDFUnlinkFile__: RefCount=%d > 2, cannot delete\n", FileInfo->RefCount)); - return STATUS_CANNOT_DELETE; - } - if (Dloc->SDirInfo) - return STATUS_CANNOT_DELETE; - } - ASSERT(FileInfo->RefCount >= 1); + if ((FileInfo->OpenCount /*> (uint32)(UDFHasAStreamDir(FileInfo) ? 1 : 0)*/) || + (FileInfo->RefCount>1)) return STATUS_CANNOT_DELETE; + if (Dloc->SDirInfo) + return STATUS_CANNOT_DELETE; + ASSERT(FileInfo->RefCount == 1); DirInfo = FileInfo->ParentFile; // root dir or self if (!DirInfo || ((FileInfo->Index < 2) && !UDFIsAStreamDir(FileInfo))) return STATUS_CANNOT_DELETE; @@ -1815,7 +1835,7 @@ UDFUnlinkFile__( PUDF_FILE_INFO SFileInfo; // ... try to open it if (Dloc->SDirInfo) { - UDFFlushFile__(IrpContext, Vcb, FileInfo); + UDFFlushFile__(IrpContext, Vcb, FileInfo, 0); return STATUS_CANNOT_DELETE; } // open SDir @@ -1826,7 +1846,7 @@ UDFUnlinkFile__( cleanup_SDir: UDFCleanUpFile__(Vcb, SFileInfo); if (SFileInfo) MyFreePool__(SFileInfo); - UDFFlushFile__(IrpContext, Vcb, FileInfo); + UDFFlushFile__(IrpContext, Vcb, FileInfo, 0); return status; } SDirInfo = Dloc->SDirInfo; @@ -1840,7 +1860,7 @@ UDFUnlinkFile__( goto cleanup_SDir; } // delete SDir - UDFFlushFile__(IrpContext, Vcb, SDirInfo); + UDFFlushFile__(IrpContext, Vcb, SDirInfo, 0); AdPrint((" ")); UDFUnlinkFile__(IrpContext, Vcb, SDirInfo, TRUE); // close SDir @@ -1861,7 +1881,7 @@ UDFUnlinkFile__( // do deltree for Streams status = UDFUnlinkAllFilesInDir(IrpContext, Vcb, FileInfo); if (!NT_SUCCESS(status)) { - UDFFlushFile__(IrpContext, Vcb, FileInfo); + UDFFlushFile__(IrpContext, Vcb, FileInfo, 0); return status; } // update parent FileInfo @@ -1873,8 +1893,11 @@ UDFUnlinkFile__( FileInfo->Dloc->FE_Flags |= UDF_FE_FLAG_IS_DEL_SDIR; UDFDecFileLinkCount(FileInfo->ParentFile); } + if (Dloc->DirIndex) { + UDFFlushFESpace(Vcb, Dloc, FLUSH_FE_FOR_DEL); + } // flush file - UDFFlushFile__(IrpContext, Vcb, FileInfo); + UDFFlushFile__(IrpContext, Vcb, FileInfo, 0); UDFUnlinkDloc(Vcb, Dloc); // free allocation UDFFreeFileAllocation(Vcb, DirInfo, FileInfo); @@ -1929,7 +1952,7 @@ UDFUnlinkAllFilesInDir( return status; } - UDFFlushFile__(IrpContext, Vcb, FileInfo); + UDFFlushFile__(IrpContext, Vcb, FileInfo, 0); AdPrint((" ")); UDFUnlinkFile__(IrpContext, Vcb, FileInfo, TRUE); UDFCloseFile__(IrpContext, Vcb, FileInfo); @@ -2049,10 +2072,8 @@ UDFOpenFile__( // init pointers to linked files (if any) if (FileInfo->Dloc->LinkedFileInfo != FileInfo) UDFInsertLinkedFile(FileInfo, FileInfo->Dloc->LinkedFileInfo); - if (FileInfo->Dloc->FileEntry) { - // Dloc cached in UDFOpenFile__ — skip FE read from disk + 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; @@ -2112,6 +2133,13 @@ UDFOpenFile__( 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); @@ -2126,7 +2154,7 @@ UDFOpenFile__( This is called after UDFFindDirEntry to open the found file. */ NTSTATUS -UDFOpenFileInfoFromDirContext( +UDFOpenObjectFromDirContext( IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN PDIR_ENUM_CONTEXT DirContext, @@ -2277,13 +2305,20 @@ UDFOpenFileInfoFromDirContext( 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 UDFOpenFileInfoFromDirContext() +} // end UDFOpenObjectFromDirContext() /* @@ -2362,6 +2397,12 @@ UDFOpenRootFile__( 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); @@ -2457,70 +2498,11 @@ UDFCleanUpFile__( for(i=2; (DirNdx = UDFDirIndex(Dloc->DirIndex,i)); i++) { if (DirNdx->FileInfo) { if (!KeepDloc) { - // Orphaned FileInfo in DirIndex: loaded by - // UDFOpenFileInfoFromDirContext during path traversal - // but never opened as final component (no LCB). - // Recursively clean up instead of ASSERTing. - UDFPrint(("UDF: Cleaning orphaned FileInfo %x in DirIndex[%d]\n", - DirNdx->FileInfo, i)); - PUDF_FILE_INFO OrphanFi = DirNdx->FileInfo; - // Orphan must have a valid Dloc (loaded by UDFOpenFileInfoFromDirContext) - ASSERT(OrphanFi->Dloc); - // Orphan should be self-linked (not part of a parallel/linked chain) - ASSERT(OrphanFi->NextLinkedFile == OrphanFi); - // ParentFile must point to the FileInfo we're currently cleaning up - ASSERT(OrphanFi->ParentFile == FileInfo); - // Clear CommonFcb to ensure KeepDloc=FALSE in recursive call - // (floating FCB may have set CommonFcb != NULL). - // The floating FCB itself will leak until unmount — acceptable. - if (OrphanFi->Dloc->CommonFcb) { - UDFPrint(("UDF: Orphan %x has floating CommonFcb %x\n", - OrphanFi, OrphanFi->Dloc->CommonFcb)); - OrphanFi->Dloc->CommonFcb = NULL; - } - // Clear Fcb so UDFCleanUpFile__ doesn't bail at line 2465 - if (OrphanFi->Fcb) { - UDFPrint(("UDF: Orphan %x has floating Fcb %x\n", - OrphanFi, OrphanFi->Fcb)); - OrphanFi->Fcb->FileInfo = NULL; - OrphanFi->Fcb = NULL; - } - // Log original counts for diagnostics - UDFPrint(("UDF: Orphan counts: RefCount=%d, LinkRefCount=%d, OpenCount=%d\n", - OrphanFi->RefCount, - OrphanFi->Dloc->LinkRefCount, - OrphanFi->OpenCount)); - // Reset OpenCount — orphan's children (also orphans) may - // have incremented it via UDFReferenceFile__. These children - // will be recursively cleaned up by UDFCleanUpFile__. - OrphanFi->OpenCount = 0; - // Reset RefCount/LinkRefCount — may be non-zero if - // UDFCloseFile__ was never called for this orphan - OrphanFi->RefCount = 0; - OrphanFi->Dloc->LinkRefCount = 0; - // Clear Modified flags — orphan is being discarded along - // with the parent directory's DirIndex, so unflushed - // modifications would be lost anyway. Without this, - // recursive UDFCleanUpFile__ asserts !Modified when - // KeepDloc=FALSE (e.g., after rename-replace sets - // FI_MODIFIED on directory entries during UDFUnlinkFile__). - DirNdx->FI_Flags &= ~UDF_FI_FLAG_FI_MODIFIED; - OrphanFi->Dloc->FE_Flags &= ~UDF_FE_FLAG_FE_MODIFIED; - OrphanFi->Dloc->DataLoc.Modified = FALSE; - OrphanFi->Dloc->DataLoc.Flags &= ~EXTENT_FLAG_PREALLOCATED; - OrphanFi->Dloc->AllocLoc.Modified = FALSE; - OrphanFi->Dloc->FELoc.Modified = FALSE; - // UDFCleanUpFile__ handles Dloc cleanup (frees via - // UDFRemoveDloc/UDFFreeDloc) and sets DirNdx->FileInfo=NULL - // in parent's DirIndex. We also free the FileInfo struct. - ULONG cleanupResult = UDFCleanUpFile__(Vcb, OrphanFi); - // Cleanup must have freed the Dloc (KeepDloc=FALSE path) - ASSERT(OrphanFi->Dloc == NULL); - ASSERT(cleanupResult & UDF_FREE_FILEINFO); - // Only free the FileInfo struct itself. - MyFreePool__(OrphanFi); - DirNdx->FileInfo = NULL; - continue; + ASSERT(FALSE); + UDFPrint(("UDF: Found not cleaned up reference.\n")); + UDFPrint((" Skipping cleanup (1)\n")); +// BrutePoint(); + return UDF_FREE_NOTHING; } // The file being cleaned up may have not closed Dirs // (linked Dir). In this case each of them may have @@ -2610,6 +2592,8 @@ UDFCleanUpFile__( if (DirNdx->FName.Buffer) MyFreePool__(DirNdx->FName.Buffer); } + // The only place where we can free FE_Charge extent is here + UDFFlushFESpace(Vcb, Dloc, FLUSH_FE_KEEP); UDFDirIndexFree(Dloc->DirIndex); Dloc->DirIndex = NULL; #ifdef UDF_TRACK_ONDISK_ALLOCATION @@ -2902,23 +2886,31 @@ UDFCreateFile__( // try to find suitable unused FileIdent in DirIndex l = FileInfo->FileIdentLen; if (undel) goto CrF__2; - // search for suitable unused (deleted) entry to reuse - if (UDFDirIndexInitScan(DirInfo, &ScanContext, 2)) { - while((DirNdx = UDFDirIndexScan(&ScanContext, NULL))) { - if ((DirNdx->Length == l) && UDFIsDeleted(DirNdx) && - !DirNdx->FileInfo ) { - // free unicode-buffer with old name - if (DirNdx->FName.Buffer) { - MyFreePool__(DirNdx->FName.Buffer); - DirNdx->FName.Buffer = NULL; +#ifndef UDF_LIMIT_DIR_SIZE + if (Vcb->CDR_Mode) { +#endif // UDF_LIMIT_DIR_SIZE + // search for suitable unused entry + if (UDFDirIndexInitScan(DirInfo, &ScanContext, 2)) { + while((DirNdx = UDFDirIndexScan(&ScanContext, NULL))) { + if ((DirNdx->Length == l) && UDFIsDeleted(DirNdx) && + !DirNdx->FileInfo ) { + // free unicode-buffer with old name + if (DirNdx->FName.Buffer) { + MyFreePool__(DirNdx->FName.Buffer); + DirNdx->FName.Buffer = NULL; + } + i = ScanContext.i; + goto CrF__1; } - i = ScanContext.i; - goto CrF__1; } } +#ifndef UDF_LIMIT_DIR_SIZE + } else { +#endif // UDF_LIMIT_DIR_SIZE + i = UDFDirIndexGetLastIndex(hDirNdx); // 'i' points beyond EO DirIndex +#ifndef UDF_LIMIT_DIR_SIZE } - // no suitable deleted entry found, append new one - i = UDFDirIndexGetLastIndex(hDirNdx); +#endif // UDF_LIMIT_DIR_SIZE // append entry if (!NT_SUCCESS(status = UDFDirIndexGrow(&(DirInfo->Dloc->DirIndex), 1))) { @@ -2970,12 +2962,11 @@ UDFCreateFile__( RtlCopyMemory(DirNdx->FName.Buffer, _fn->Buffer, _fn->Length); DirNdx->FName.Buffer[_fn->Length/sizeof(WCHAR)] = 0; CrF__2: - // Reset all flags: stale FI_INTERNAL from deleted entry would - // hide the new file from enumeration. - DirNdx->FI_Flags = UDFBuildHashEntry(Vcb, &(DirNdx->FName), &(DirNdx->hashes), HASH_ALL) - | UDF_FI_FLAG_FI_MODIFIED; + DirNdx->FI_Flags |= UDFBuildHashEntry(Vcb, &(DirNdx->FName), &(DirNdx->hashes), HASH_ALL); // we get here immediately when 'undel' occured FileInfo->Index = i; + DirNdx->FI_Flags |= UDF_FI_FLAG_FI_MODIFIED; + DirNdx->FI_Flags &= ~UDF_FI_FLAG_SYS_ATTR; ASSERT(!DirNdx->FileInfo); DirNdx->FileInfo = FileInfo; DirNdx->FileEntryLoc = FEicb.extLocation; @@ -3280,10 +3271,11 @@ UDFCloseFile__( // we needn't flushing FE & Allocs untill all links are closed... if (!FileInfo->Dloc->LinkRefCount) { - // flush pre-allocation charge for directories + // flush FE and pre-allocation charge for directories if (FileInfo->Dloc && FileInfo->Dloc->DirIndex) { + UDFFlushFESpace(Vcb, FileInfo->Dloc, FLUSH_FE_KEEP); if (FileInfo->Dloc->DataLoc.Flags & EXTENT_FLAG_PREALLOCATED) { FileInfo->Dloc->DataLoc.Flags |= EXTENT_FLAG_CUT_PREALLOCATED; status = UDFResizeExtent(IrpContext, Vcb, PartNum, UDFGetFileSize(FileInfo), FALSE, &(FileInfo->Dloc->DataLoc)); @@ -3411,60 +3403,35 @@ UDFRenameMoveFile__( if ((*Replace) && !Recovery) { Recovery = TRUE; status = UDFOpenFile__(IrpContext, Vcb, IgnoreCase, TRUE, fn, DirInfo2, &FileInfo2, NULL); - if (!NT_SUCCESS(status)) { - - goto cleanup_and_abort_rename; - } - // file opened successfully -; - status = UDFDoesOSAllowFileToBeTargetForRename__(FileInfo2); - - if (!NT_SUCCESS(status)) { - - UDFCloseFile__(IrpContext, Vcb, FileInfo2); - goto cleanup_and_abort_rename; - } - - // TODO: Refactor — don't use UDFCreateFile__ in rename path. - // Use direct FID unlink + create link instead. - // Quick fix: if target's Dloc == source's Dloc, the internal open got the - // wrong file (shared Dloc bug). Unlink would destroy the source data. - if (FileInfo2->Dloc == FileInfo->Dloc) { - + if (NT_SUCCESS(status)) { + status = UDFDoesOSAllowFileToBeTargetForRename__(FileInfo2); + if (!NT_SUCCESS(status)) { + UDFCloseFile__(IrpContext, Vcb, FileInfo2); + goto cleanup_and_abort_rename; + } + status = UDFUnlinkFile__(IrpContext, Vcb, FileInfo2, TRUE); +// UDFPretendFileDeleted__(Vcb, FileInfo2); UDFCloseFile__(IrpContext, Vcb, FileInfo2); - status = STATUS_ACCESS_DENIED; - goto cleanup_and_abort_rename; - } - status = UDFUnlinkFile__(IrpContext, Vcb, FileInfo2, TRUE); - - // Mark FCB as deleted to prevent it from going into delayed close queue - if (FileInfo2->Fcb) { - - FileInfo2->Fcb->FcbState |= UDF_FCB_DELETED; - } - UDFCloseFile__(IrpContext, Vcb, FileInfo2); - - if (UDFCleanUpFile__(Vcb, FileInfo2)) { - - MyFreePool__(FileInfo2); - FileInfo2 = NULL; - if (SameFE) - return status; - } else { - // we get here if the FileInfo has associated - // system-specific Fcb - // Such fact means that not all system references - // has already gone (except Linked file case) - - // Note: After UDFUnlinkFile__ link count is 0, which is expected - // Only return ACCESS_DENIED if unlink itself failed - if (!NT_SUCCESS(status)) - status = STATUS_ACCESS_DENIED; + if (UDFCleanUpFile__(Vcb, FileInfo2)) { + MyFreePool__(FileInfo2); + FileInfo2 = NULL; + if (SameFE) + return status; + } else { + // we get here if the FileInfo has associated + // system-specific Fcb + // Such fact means that not all system references + // has already gone (except Linked file case) +/* if (SameFE) + return status;*/ +// UDFRemoveOSReferences__(FileInfo2); + if (!NT_SUCCESS(status) || + (UDFGetFileLinkCount(FileInfo2) < 1)) + status = STATUS_ACCESS_DENIED; + } + if (NT_SUCCESS(status)) goto RenameRetry; } - - if (NT_SUCCESS(status)) goto RenameRetry; cleanup_and_abort_rename: - if (FileInfo2 && UDFCleanUpFile__(Vcb, FileInfo2)) { MyFreePool__(FileInfo2); FileInfo2 = NULL; @@ -3485,7 +3452,7 @@ UDFRenameMoveFile__( // unlink source FileIdent if (!NT_SUCCESS(status = UDFUnlinkFile__(IrpContext, Vcb, FileInfo, FALSE))) { // kill newly created entry - UDFFlushFile__(IrpContext, Vcb, FileInfo2); + UDFFlushFile__(IrpContext, Vcb, FileInfo2, 0); UDFUnlinkFile__(IrpContext, Vcb, FileInfo2, TRUE); UDFCloseFile__(IrpContext, Vcb, FileInfo2); UDFCleanUpFile__(Vcb, FileInfo2); @@ -3631,7 +3598,14 @@ UDFRecordDirectory__( status = UDFWriteFile__(IrpContext, Vcb, DirInfo, 0, FileInfo.FileIdentLen, FALSE, (int8*)(FileInfo.FileIdent), &WrittenBytes); // status = UDFFlushFI(Vcb, &FileInfo, PartNum); - ASSERT(UDFGetFileSize(DirInfo) <= UDFGetExtentLength(DirInfo->Dloc->DataLoc.Mapping)); +#ifdef UDF_DBG + if (Vcb->CompatFlags & UDF_VCB_IC_W2K_COMPAT_ALLOC_DESCS) { + ASSERT(UDFGetFileSize(DirInfo) <= UDFGetExtentLength(DirInfo->Dloc->DataLoc.Mapping)); + } else { + ASSERT(((UDFGetFileSize(DirInfo)+Vcb->SectorSize-1) & (Vcb->SectorSize-1)) == + ((UDFGetExtentLength(DirInfo->Dloc->DataLoc.Mapping)+Vcb->SectorSize-1) & (Vcb->SectorSize-1))); + } +#endif // UDF_DBG MyFreePool__(FileInfo.FileIdent); if (!NT_SUCCESS(status)) return status; @@ -3733,10 +3707,8 @@ UDFResizeFile__( ((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 - // Fcb may be NULL during directory operations (FCB not yet created) - if (FileInfo->Fcb) { - FileInfo->Fcb->FcbState |= UDF_FCB_EMBEDDED_DATA; - } + 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)); @@ -3768,7 +3740,14 @@ UDFResizeFile__( UDFSetFileSize(FileInfo, NewLength); } - ASSERT(UDFGetFileSize(FileInfo) <= UDFGetExtentLength(FileInfo->Dloc->DataLoc.Mapping)); +#ifdef UDF_DBG + if (Vcb->CompatFlags & UDF_VCB_IC_W2K_COMPAT_ALLOC_DESCS) { + ASSERT(UDFGetFileSize(FileInfo) <= UDFGetExtentLength(FileInfo->Dloc->DataLoc.Mapping)); + } else { + 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; } // end UDFResizeFile__() @@ -4090,7 +4069,12 @@ UDFFlushFE( return status; } #ifdef UDF_DBG - ASSERT(UDFGetFileSize(FileInfo) <= UDFGetExtentLength(FileInfo->Dloc->DataLoc.Mapping)); + if (Vcb->CompatFlags & UDF_VCB_IC_W2K_COMPAT_ALLOC_DESCS) { + ASSERT(UDFGetFileSize(FileInfo) <= UDFGetExtentLength(FileInfo->Dloc->DataLoc.Mapping)); + } else { + 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 // initiate update of lengthAllocDescs @@ -4120,7 +4104,12 @@ UDFFlushFE( ASSERT(UDFGetExtentLength(FileInfo->Dloc->DataLoc.Mapping) == 0); } else { - ASSERT(UDFGetFileSize(FileInfo) <= UDFGetExtentLength(FileInfo->Dloc->DataLoc.Mapping)); + if (Vcb->CompatFlags & UDF_VCB_IC_W2K_COMPAT_ALLOC_DESCS) { + ASSERT(UDFGetFileSize(FileInfo) <= UDFGetExtentLength(FileInfo->Dloc->DataLoc.Mapping)); + } else { + ASSERT(((UDFGetFileSize(FileInfo)+Vcb->SectorSize-1) & (Vcb->SectorSize-1)) == + ((UDFGetExtentLength(FileInfo->Dloc->DataLoc.Mapping)+Vcb->SectorSize-1) & (Vcb->SectorSize-1))); + } } #endif // UDF_DBG } @@ -4166,20 +4155,6 @@ UDFFlushFE( // FileInfo->Dloc->FELoc.Length += UDFGetFileSize(FileInfo); // FileInfo->Dloc->FELoc.Length = FileInfo->Dloc->FileEntry->descCRCLength + sizeof(tag); UDFPrint(("descCRCLength %x\n", FileInfo->Dloc->FileEntry->descCRCLength)); - { - int64 _infoLen = (FileInfo->Dloc->FileEntry->tagIdent == TID_FILE_ENTRY) ? - ((PFILE_ENTRY)(FileInfo->Dloc->FileEntry))->informationLength : - ((PEXTENDED_FILE_ENTRY)(FileInfo->Dloc->FileEntry))->informationLength; - if (_infoLen != FileInfo->Dloc->DataLoc.Length) { - - // Safety-net: correct informationLength from DataLoc.Length - UDFSetFileSize(FileInfo, FileInfo->Dloc->DataLoc.Length); - // Re-compute CRC after changing FE content - UDFSetUpTag( - Vcb, FileInfo->Dloc->FileEntry, (uint16)(FileInfo->Dloc->FileEntryLen), - UDFPhysLbaToPart(Vcb, PartNum, lba), 0); - } - } status = UDFWriteExtent( IrpContext, Vcb, &FileInfo->Dloc->FELoc, 0, (uint32)(FileInfo->Dloc->FELoc.Length), FALSE, @@ -4377,6 +4352,7 @@ UDFFlushFile__( // if Lite Flush is used, keep preallocations if (!(FlushFlags & UDF_FLUSH_FLAGS_LITE)) { full_flush: + UDFFlushFESpace(Vcb, FileInfo->Dloc, FLUSH_FE_KEEP); if (FileInfo->Dloc->DataLoc.Flags & EXTENT_FLAG_PREALLOCATED) { FileInfo->Dloc->DataLoc.Flags |= EXTENT_FLAG_CUT_PREALLOCATED; status = UDFResizeExtent(IrpContext, Vcb, PartNum, UDFGetFileSize(FileInfo), FALSE, &(FileInfo->Dloc->DataLoc)); @@ -5193,7 +5169,7 @@ UDFRecordVAT( UDFPhysLbaToPart(Vcb, PartNum, VatFileInfo->Dloc->DataLoc.Mapping[0].extLocation); // record data if (NT_SUCCESS(status = UDFWriteFile__(IrpContext, Vcb, VatFileInfo, 0, VatLen + hdrLen, FALSE, New, &WrittenBytes))) { - status = UDFFlushFile__(IrpContext, Vcb, VatFileInfo); + status = UDFFlushFile__(IrpContext, Vcb, VatFileInfo, 0); } return status; } @@ -5299,7 +5275,7 @@ UDFRecordVAT( UDFPhysLbaToPart(Vcb, PartNum, VatFileInfo->Dloc->FELoc.Mapping[0].extLocation); VatFileInfo->Dloc->DataLoc.Modified = TRUE; - status = UDFFlushFile__(IrpContext, Vcb, VatFileInfo); + status = UDFFlushFile__(IrpContext, Vcb, VatFileInfo, 0); if (!NT_SUCCESS(status)) return status; diff --git a/drivers/filesystems/udfs/udf_info/udf_info.h b/drivers/filesystems/udfs/udf_info/udf_info.h index d68b0d6437f3f..e61fa21dc3edf 100644 --- a/drivers/filesystems/udfs/udf_info/udf_info.h +++ b/drivers/filesystems/udfs/udf_info/udf_info.h @@ -11,6 +11,11 @@ #include "osta_misc.h" #include "udf_rel.h" +// memory re-allocation (returns new buffer size) +uint32 UDFMemRealloc(IN int8* OldBuff, // old buffer + IN uint32 OldLength, // old buffer size + OUT int8** NewBuff, // address to store new pointer + IN uint32 NewLength); // required size // convert offset in extent to Lba & calculate block parameters // it also returns pointer to last valid entry & flags uint32 @@ -58,16 +63,12 @@ UDFReadExtentLocation(IN PVCB Vcb, ); // calculate total length of extent int64 UDFGetExtentLength(IN PEXTENT_MAP Extent); // Extent array - // convert compressed Unicode to standard -VOID -UDFDecompressUnicode( - IN OUT PUNICODE_STRING UName, - IN uint8* CS0, - IN SIZE_T Length, - OUT uint16* valueCRC -); - +void +__fastcall UDFDecompressUnicode(IN OUT PUNICODE_STRING UName, + IN uint8* CS0, + IN SIZE_T Length, + OUT uint16* valueCRC); // calculate hashes for directory search uint8 UDFBuildHashEntry(IN PVCB Vcb, IN PUNICODE_STRING Name, @@ -140,7 +141,7 @@ NTSTATUS UDFFindDirEntry( OUT PDIR_ENUM_CONTEXT DirContext); // Open file from directory context (after UDFFindDirEntry) -NTSTATUS UDFOpenFileInfoFromDirContext( +NTSTATUS UDFOpenObjectFromDirContext( IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN PDIR_ENUM_CONTEXT DirContext, @@ -410,7 +411,8 @@ uint32 __fastcall UDFGetPartFreeSpace(IN PVCB Vcb, IN uint32 partNum); -#define UDF_PREALLOC_CLASS_DIR 0x00 +#define UDF_PREALLOC_CLASS_FE 0x00 +#define UDF_PREALLOC_CLASS_DIR 0x01 // try to find cached allocation NTSTATUS @@ -453,6 +455,13 @@ void UDFFreeFESpace(IN PVCB Vcb, IN PUDF_FILE_INFO DirInfo, IN PEXTENT_INFO FEExtInfo); +#define FLUSH_FE_KEEP FALSE +#define FLUSH_FE_FOR_DEL TRUE + +// flush FE charge +void UDFFlushFESpace(IN PVCB Vcb, + IN PUDF_DATALOC_INFO Dloc, + IN BOOLEAN Discard); // discard file allocation void UDFFreeFileAllocation(IN PVCB Vcb, IN PUDF_FILE_INFO DirInfo, @@ -954,6 +963,13 @@ UDFRecordDirectory__( IN OUT PUDF_FILE_INFO DirInfo // source (opened) ); +// remove all DELETED entries from Dir & resize it. +NTSTATUS +UDFPackDirectory__( + IN PIRP_CONTEXT IrpContext, + IN PVCB Vcb, + IN OUT PUDF_FILE_INFO FileInfo // source (opened) + ); // rebuild tags for all entries from Dir. NTSTATUS @@ -1023,7 +1039,7 @@ UDFFlushFile__( IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN PUDF_FILE_INFO FileInfo, - IN ULONG FlushFlags = 0 + IN ULONG FlushFlags ); // check if the file is flushed diff --git a/drivers/filesystems/udfs/write.c b/drivers/filesystems/udfs/write.c index 233d8b9e532db..170ee91393348 100644 --- a/drivers/filesystems/udfs/write.c +++ b/drivers/filesystems/udfs/write.c @@ -225,7 +225,7 @@ UDFCommonWrite( // I dislike the idea of writing to mounted media too, but M$ has another point of view... if (Vcb->VcbCondition == VcbMounted) { // flush system cache - UDFFlushVolume(IrpContext, Vcb); + UDFFlushVolume(IrpContext, Vcb, 0); } // Forward the request to the lower level driver @@ -243,7 +243,7 @@ UDFCommonWrite( // Perform actual Write Status = UDFTWrite(IrpContext, Vcb, SystemBuffer, ByteCount, (ULONG)(StartingOffset >> Vcb->SectorShift), - &NumberBytesWritten); + &NumberBytesWritten, 0); UDFUnlockCallersBuffer(IrpContext, Irp, SystemBuffer); try_return(Status); } diff --git a/udfs-for-write-branch.patch b/udfs-for-write-branch.patch index 8d94a397be2b1..fc42ab5e75852 100644 --- a/udfs-for-write-branch.patch +++ b/udfs-for-write-branch.patch @@ -102,9 +102,52 @@ similarity index 100% rename from drivers/filesystems/udfs/Include/mem_tools.cpp rename to drivers/filesystems/udfs/Include/mem_tools.c diff --git a/drivers/filesystems/udfs/Include/phys_lib.cpp b/drivers/filesystems/udfs/Include/phys_lib.c -similarity index 100% +similarity index 99% rename from drivers/filesystems/udfs/Include/phys_lib.cpp rename to drivers/filesystems/udfs/Include/phys_lib.c +index bba91e8..944d35b 100644 +--- a/drivers/filesystems/udfs/Include/phys_lib.cpp ++++ b/drivers/filesystems/udfs/Include/phys_lib.c +@@ -1036,7 +1036,7 @@ UDFReadSectors( + OUT PULONG ReadBytes + ) + { +- return UDFTRead(IrpContext, Vcb, Buffer, BCount*Vcb->SectorSize, Lba, ReadBytes); ++ return UDFTRead(IrpContext, Vcb, Buffer, BCount*Vcb->SectorSize, Lba, ReadBytes, 0); + } // end UDFReadSectors() + + /* +@@ -1167,7 +1167,7 @@ UDFWriteSectors( + Vcb->LastLBA = Lba+BCount-1; + } + +- status = UDFTWrite(IrpContext, Vcb, Buffer, BCount<SectorShift, Lba, WrittenBytes); ++ status = UDFTWrite(IrpContext, Vcb, Buffer, BCount<SectorShift, Lba, WrittenBytes, 0); + ASSERT(NT_SUCCESS(status)); + + return status; +diff --git a/drivers/filesystems/udfs/Include/phys_lib.h b/drivers/filesystems/udfs/Include/phys_lib.h +index 747b954..19203d2 100644 +--- a/drivers/filesystems/udfs/Include/phys_lib.h ++++ b/drivers/filesystems/udfs/Include/phys_lib.h +@@ -15,7 +15,7 @@ UDFTRead( + SIZE_T Length, + ULONG LBA, + PULONG ReadBytes, +- ULONG Flags = 0 ++ ULONG Flags + ); + + NTSTATUS +@@ -26,7 +26,7 @@ UDFTWrite( + IN SIZE_T Length, + IN ULONG LBA, + OUT PSIZE_T WrittenBytes, +- IN ULONG Flags = 0 ++ IN ULONG Flags + ); + + #define PH_TMP_BUFFER 1 diff --git a/drivers/filesystems/udfs/Include/regtools.cpp b/drivers/filesystems/udfs/Include/regtools.c similarity index 100% rename from drivers/filesystems/udfs/Include/regtools.cpp @@ -149,17 +192,68 @@ index 1750feb..37bd1d8 100644 RtlAppendUnicodeToString( IN PUNICODE_STRING Str1, diff --git a/drivers/filesystems/udfs/cleanup.cpp b/drivers/filesystems/udfs/cleanup.c -similarity index 100% +similarity index 99% rename from drivers/filesystems/udfs/cleanup.cpp rename to drivers/filesystems/udfs/cleanup.c +index 678dcb3..b85c16a 100644 +--- a/drivers/filesystems/udfs/cleanup.cpp ++++ b/drivers/filesystems/udfs/cleanup.c +@@ -333,7 +333,7 @@ UDFCommonCleanup( + Fcb->ParentFcb->FcbState |= UDF_FCB_DELETE_ON_CLOSE; + } + // flush file. It is required by UDFUnlinkFile__() +- RC = UDFFlushFile__(IrpContext, Vcb, NextFileInfo); ++ RC = UDFFlushFile__(IrpContext, Vcb, NextFileInfo, 0); + if (!NT_SUCCESS(RC)) { + AdPrint(("Error flushing file !!!\n")); + } diff --git a/drivers/filesystems/udfs/close.cpp b/drivers/filesystems/udfs/close.c similarity index 100% rename from drivers/filesystems/udfs/close.cpp rename to drivers/filesystems/udfs/close.c diff --git a/drivers/filesystems/udfs/create.cpp b/drivers/filesystems/udfs/create.c -similarity index 100% +similarity index 99% rename from drivers/filesystems/udfs/create.cpp rename to drivers/filesystems/udfs/create.c +index a7f63b1..ed77722 100644 +--- a/drivers/filesystems/udfs/create.cpp ++++ b/drivers/filesystems/udfs/create.c +@@ -524,7 +524,7 @@ UDFCommonCreate( + + InterlockedDecrement((PLONG)&Vcb->VcbReference); + +- UDFFlushVolume(IrpContext, Vcb); ++ UDFFlushVolume(IrpContext, Vcb, 0); + } + // Lock the volume + if (!(ShareAccess & FILE_SHARE_READ)) { +@@ -1428,7 +1428,7 @@ Undo_Create_1: + if ((RC != STATUS_FILE_IS_A_DIRECTORY) && + (RC != STATUS_NOT_A_DIRECTORY) && + (RC != STATUS_ACCESS_DENIED)) { +- UDFFlushFile__(IrpContext, Vcb, NewFileInfo); ++ UDFFlushFile__(IrpContext, Vcb, NewFileInfo, 0); + UDFUnlinkFile__(IrpContext, Vcb, NewFileInfo, TRUE); + } + UDFCloseFile__(IrpContext, Vcb, NewFileInfo); +@@ -1608,7 +1608,7 @@ Undo_Create_1: + if (!NT_SUCCESS(RC)) { + AdPrint((" Can't set Access Rights on Create\n")); + BrutePoint(); +- UDFFlushFile__(IrpContext, Vcb, NewFileInfo); ++ UDFFlushFile__(IrpContext, Vcb, NewFileInfo, 0); + UDFUnlinkFile__(IrpContext, Vcb, NewFileInfo, TRUE); + try_return(RC); + } +@@ -2368,7 +2368,7 @@ UDFCompleteFcbOpen( + // Flush the volume and make sure all of the user references + // are gone. + +- Status = UDFFlushVolume(IrpContext, Vcb); ++ Status = UDFFlushVolume(IrpContext, Vcb, 0); + + if (!NT_SUCCESS(Status)) { + diff --git a/drivers/filesystems/udfs/devcntrl.cpp b/drivers/filesystems/udfs/devcntrl.c similarity index 100% rename from drivers/filesystems/udfs/devcntrl.cpp @@ -185,13 +279,55 @@ similarity index 100% rename from drivers/filesystems/udfs/filobsup.cpp rename to drivers/filesystems/udfs/filobsup.c diff --git a/drivers/filesystems/udfs/flush.cpp b/drivers/filesystems/udfs/flush.c -similarity index 100% +similarity index 99% rename from drivers/filesystems/udfs/flush.cpp rename to drivers/filesystems/udfs/flush.c +index 76357b7..ebe9dd1 100644 +--- a/drivers/filesystems/udfs/flush.cpp ++++ b/drivers/filesystems/udfs/flush.c +@@ -127,7 +127,7 @@ UDFCommonFlush( + + UDFVerifyVcb(IrpContext, Vcb); + +- UDFFlushVolume(IrpContext, Vcb); ++ UDFFlushVolume(IrpContext, Vcb, 0); + + UDFReleaseResource(&(Vcb->VcbResource)); + AcquiredVCB = FALSE; diff --git a/drivers/filesystems/udfs/fscntrl.cpp b/drivers/filesystems/udfs/fscntrl.c -similarity index 100% +similarity index 99% rename from drivers/filesystems/udfs/fscntrl.cpp rename to drivers/filesystems/udfs/fscntrl.c +index ab7c079..84a9e18 100644 +--- a/drivers/filesystems/udfs/fscntrl.cpp ++++ b/drivers/filesystems/udfs/fscntrl.c +@@ -989,7 +989,7 @@ Return Value: + // remaining after the purge then we can allow the volume to be locked. + // + +- UDFFlushVolume(IrpContext, Vcb); ++ UDFFlushVolume(IrpContext, Vcb, 0); + //CdPurgeVolume( IrpContext, Vcb, FALSE ); + + // +@@ -1174,7 +1174,7 @@ UDFDismountVolume( + + } else { + +- UDFFlushVolume(IrpContext, Vcb); ++ UDFFlushVolume(IrpContext, Vcb, 0); + + // Invalidate the volume right now. + // +@@ -1800,7 +1800,7 @@ UDFInvalidateVolumes( + + UDFAcquireVcbExclusive(IrpContext, Vcb, FALSE); + +- UDFFlushVolume(IrpContext, Vcb); ++ UDFFlushVolume(IrpContext, Vcb, 0); + + UDFDoDismountSequence(Vcb, FALSE); + diff --git a/drivers/filesystems/udfs/lockctrl.cpp b/drivers/filesystems/udfs/lockctrl.c similarity index 100% rename from drivers/filesystems/udfs/lockctrl.cpp @@ -241,7 +377,7 @@ similarity index 100% rename from drivers/filesystems/udfs/pnp.cpp rename to drivers/filesystems/udfs/pnp.c diff --git a/drivers/filesystems/udfs/protos.h b/drivers/filesystems/udfs/protos.h -index 59cb00c..e911a28 100644 +index 59cb00c..c8d0637 100644 --- a/drivers/filesystems/udfs/protos.h +++ b/drivers/filesystems/udfs/protos.h @@ -73,7 +73,7 @@ UDFDecodeFileObjectCcb( @@ -316,7 +452,40 @@ index 59cb00c..e911a28 100644 *************************************************************************/ extern NTSTATUS NTAPI UDFFlushBuffers( PDEVICE_OBJECT DeviceObject, // the logical volume device object -@@ -563,7 +563,7 @@ extern VOID UDFFlushTryBreak( +@@ -531,7 +531,7 @@ ULONG UDFFlushAFile( + IN PFCB Fcb, + IN PCCB Ccb, + OUT PIO_STATUS_BLOCK PtrIoStatus, +- IN ULONG FlushFlags = 0 ++ IN ULONG FlushFlags + ); + + ULONG +@@ -540,14 +540,14 @@ UDFFlushADirectory( + IN PVCB Vcb, + IN PUDF_FILE_INFO FI, + OUT PIO_STATUS_BLOCK PtrIoStatus, +- ULONG FlushFlags = 0 ++ ULONG FlushFlags + ); + + NTSTATUS + UDFFlushVolume( + PIRP_CONTEXT IrpContext, + PVCB Vcb, +- ULONG FlushFlags = 0 ++ ULONG FlushFlags + ); + + extern NTSTATUS NTAPI UDFFlushCompletion( +@@ -557,13 +557,13 @@ PVOID Context); + + extern BOOLEAN UDFFlushIsBreaking( + IN PVCB Vcb, +-IN ULONG FlushFlags = 0); ++IN ULONG FlushFlags); + + extern VOID UDFFlushTryBreak( IN PVCB Vcb); /************************************************************************* @@ -343,6 +512,15 @@ index 59cb00c..e911a28 100644 *************************************************************************/ extern NTSTATUS UDFInitializeZones( VOID); +@@ -842,7 +842,7 @@ UDFReadRegKeys( + extern ULONG UDFGetRegParameter( + IN PVCB Vcb, + IN PCWSTR Name, +- IN ULONG DefValue = 0); ++ IN ULONG DefValue); + + VOID + UDFDeleteVCB( @@ -882,13 +882,13 @@ UDFCreateFileLock( ); @@ -441,9 +619,21 @@ similarity index 100% rename from drivers/filesystems/udfs/secursup.cpp rename to drivers/filesystems/udfs/secursup.c diff --git a/drivers/filesystems/udfs/shutdown.cpp b/drivers/filesystems/udfs/shutdown.c -similarity index 100% +similarity index 99% rename from drivers/filesystems/udfs/shutdown.cpp rename to drivers/filesystems/udfs/shutdown.c +index f8b0a7f..314b0e2 100644 +--- a/drivers/filesystems/udfs/shutdown.cpp ++++ b/drivers/filesystems/udfs/shutdown.c +@@ -109,7 +109,7 @@ UDFCommonShutdown( + + UDFAcquireVcbExclusive(IrpContext, Vcb, FALSE); + +- UDFFlushVolume(IrpContext, Vcb); ++ UDFFlushVolume(IrpContext, Vcb, 0); + + ASSERT(CONTAINING_RECORD(IoGetCurrentIrpStackLocation(Irp)->DeviceObject, + VOLUME_DEVICE_OBJECT, diff --git a/drivers/filesystems/udfs/strucsup.cpp b/drivers/filesystems/udfs/strucsup.c similarity index 99% rename from drivers/filesystems/udfs/strucsup.cpp @@ -684,6 +874,19 @@ diff --git a/drivers/filesystems/udfs/udf_dbg.cpp b/drivers/filesystems/udfs/udf similarity index 100% rename from drivers/filesystems/udfs/udf_dbg.cpp rename to drivers/filesystems/udfs/udf_dbg.c +diff --git a/drivers/filesystems/udfs/udf_dbg.h b/drivers/filesystems/udfs/udf_dbg.h +index 63fc430..d176b88 100644 +--- a/drivers/filesystems/udfs/udf_dbg.h ++++ b/drivers/filesystems/udfs/udf_dbg.h +@@ -49,7 +49,7 @@ + ULONG + _cdecl + DbgPrint( +- PCH Format, ++ PCSTR Format, + ... + ); + diff --git a/drivers/filesystems/udfs/udf_info/alloc.cpp b/drivers/filesystems/udfs/udf_info/alloc.c similarity index 100% rename from drivers/filesystems/udfs/udf_info/alloc.cpp @@ -741,9 +944,21 @@ similarity index 100% rename from drivers/filesystems/udfs/udf_info/extent.cpp rename to drivers/filesystems/udfs/udf_info/extent.c diff --git a/drivers/filesystems/udfs/udf_info/mount.cpp b/drivers/filesystems/udfs/udf_info/mount.c -similarity index 100% +similarity index 99% rename from drivers/filesystems/udfs/udf_info/mount.cpp rename to drivers/filesystems/udfs/udf_info/mount.c +index 3fc100a..cd60aa4 100644 +--- a/drivers/filesystems/udfs/udf_info/mount.cpp ++++ b/drivers/filesystems/udfs/udf_info/mount.c +@@ -915,7 +915,7 @@ UDFUpdateNonAllocated( + } + UDFPackMapping(Vcb, DataLoc); + DataLoc->Length = UDFGetExtentLength(DataLoc->Mapping); +- UDFFlushFile__(IrpContext, Vcb, Vcb->NonAllocFileInfo); ++ UDFFlushFile__(IrpContext, Vcb, Vcb->NonAllocFileInfo, 0); + + // ensure that BAD space is marked as USED + UDFMarkSpaceAsXXX(Vcb, 0, &(DataLoc->Mapping[0]), AS_USED); // mark as used diff --git a/drivers/filesystems/udfs/udf_info/osta_misc.h b/drivers/filesystems/udfs/udf_info/osta_misc.h index f9813bf..60b522c 100644 --- a/drivers/filesystems/udfs/udf_info/osta_misc.h @@ -767,9 +982,21 @@ index f9813bf..60b522c 100644 #endif /* _OSTA_MISC_H */ diff --git a/drivers/filesystems/udfs/udf_info/phys_eject.cpp b/drivers/filesystems/udfs/udf_info/phys_eject.c -similarity index 100% +similarity index 98% rename from drivers/filesystems/udfs/udf_info/phys_eject.cpp rename to drivers/filesystems/udfs/udf_info/phys_eject.c +index 2a7a794..d07cced 100644 +--- a/drivers/filesystems/udfs/udf_info/phys_eject.cpp ++++ b/drivers/filesystems/udfs/udf_info/phys_eject.c +@@ -28,7 +28,7 @@ UDFDoDismountSequence( + ULONG i; + + // flush system cache +- UDFFlushVolume(NULL, Vcb); ++ UDFFlushVolume(NULL, Vcb, 0); + UDFPrint(("UDFDoDismountSequence:\n")); + + delay.QuadPart = -1000000; // 0.1 sec diff --git a/drivers/filesystems/udfs/udf_info/physical.cpp b/drivers/filesystems/udfs/udf_info/physical.c similarity index 95% rename from drivers/filesystems/udfs/udf_info/physical.cpp @@ -789,9 +1016,142 @@ similarity index 100% rename from drivers/filesystems/udfs/udf_info/remap.cpp rename to drivers/filesystems/udfs/udf_info/remap.c diff --git a/drivers/filesystems/udfs/udf_info/udf_info.cpp b/drivers/filesystems/udfs/udf_info/udf_info.c -similarity index 100% +similarity index 99% rename from drivers/filesystems/udfs/udf_info/udf_info.cpp rename to drivers/filesystems/udfs/udf_info/udf_info.c +index e5d0b69..86f90dd 100644 +--- a/drivers/filesystems/udfs/udf_info/udf_info.cpp ++++ b/drivers/filesystems/udfs/udf_info/udf_info.c +@@ -1835,7 +1835,7 @@ UDFUnlinkFile__( + PUDF_FILE_INFO SFileInfo; + // ... try to open it + if (Dloc->SDirInfo) { +- UDFFlushFile__(IrpContext, Vcb, FileInfo); ++ UDFFlushFile__(IrpContext, Vcb, FileInfo, 0); + return STATUS_CANNOT_DELETE; + } + // open SDir +@@ -1846,7 +1846,7 @@ UDFUnlinkFile__( + cleanup_SDir: + UDFCleanUpFile__(Vcb, SFileInfo); + if (SFileInfo) MyFreePool__(SFileInfo); +- UDFFlushFile__(IrpContext, Vcb, FileInfo); ++ UDFFlushFile__(IrpContext, Vcb, FileInfo, 0); + return status; + } + SDirInfo = Dloc->SDirInfo; +@@ -1860,7 +1860,7 @@ cleanup_SDir: + goto cleanup_SDir; + } + // delete SDir +- UDFFlushFile__(IrpContext, Vcb, SDirInfo); ++ UDFFlushFile__(IrpContext, Vcb, SDirInfo, 0); + AdPrint((" ")); + UDFUnlinkFile__(IrpContext, Vcb, SDirInfo, TRUE); + // close SDir +@@ -1881,7 +1881,7 @@ cleanup_SDir: + // do deltree for Streams + status = UDFUnlinkAllFilesInDir(IrpContext, Vcb, FileInfo); + if (!NT_SUCCESS(status)) { +- UDFFlushFile__(IrpContext, Vcb, FileInfo); ++ UDFFlushFile__(IrpContext, Vcb, FileInfo, 0); + return status; + } + // update parent FileInfo +@@ -1897,7 +1897,7 @@ cleanup_SDir: + UDFFlushFESpace(Vcb, Dloc, FLUSH_FE_FOR_DEL); + } + // flush file +- UDFFlushFile__(IrpContext, Vcb, FileInfo); ++ UDFFlushFile__(IrpContext, Vcb, FileInfo, 0); + UDFUnlinkDloc(Vcb, Dloc); + // free allocation + UDFFreeFileAllocation(Vcb, DirInfo, FileInfo); +@@ -1952,7 +1952,7 @@ err_del_stream: + return status; + } + +- UDFFlushFile__(IrpContext, Vcb, FileInfo); ++ UDFFlushFile__(IrpContext, Vcb, FileInfo, 0); + AdPrint((" ")); + UDFUnlinkFile__(IrpContext, Vcb, FileInfo, TRUE); + UDFCloseFile__(IrpContext, Vcb, FileInfo); +@@ -2421,7 +2421,7 @@ UDFCleanUpFile__( + MyFreePool__(DirNdx->FName.Buffer); + } + // The only place where we can free FE_Charge extent is here +- UDFFlushFESpace(Vcb, Dloc); ++ UDFFlushFESpace(Vcb, Dloc, FLUSH_FE_KEEP); + UDFDirIndexFree(Dloc->DirIndex); + Dloc->DirIndex = NULL; + #ifdef UDF_TRACK_ONDISK_ALLOCATION +@@ -3099,7 +3099,7 @@ UDFCloseFile__( + if (FileInfo->Dloc && + FileInfo->Dloc->DirIndex) { + +- UDFFlushFESpace(Vcb, FileInfo->Dloc); ++ UDFFlushFESpace(Vcb, FileInfo->Dloc, FLUSH_FE_KEEP); + if (FileInfo->Dloc->DataLoc.Flags & EXTENT_FLAG_PREALLOCATED) { + FileInfo->Dloc->DataLoc.Flags |= EXTENT_FLAG_CUT_PREALLOCATED; + status = UDFResizeExtent(IrpContext, Vcb, PartNum, UDFGetFileSize(FileInfo), FALSE, &(FileInfo->Dloc->DataLoc)); +@@ -3276,7 +3276,7 @@ cleanup_and_abort_rename: + // unlink source FileIdent + if (!NT_SUCCESS(status = UDFUnlinkFile__(IrpContext, Vcb, FileInfo, FALSE))) { + // kill newly created entry +- UDFFlushFile__(IrpContext, Vcb, FileInfo2); ++ UDFFlushFile__(IrpContext, Vcb, FileInfo2, 0); + UDFUnlinkFile__(IrpContext, Vcb, FileInfo2, TRUE); + UDFCloseFile__(IrpContext, Vcb, FileInfo2); + UDFCleanUpFile__(Vcb, FileInfo2); +@@ -4174,7 +4174,7 @@ UDFFlushFile__( + // if Lite Flush is used, keep preallocations + if (!(FlushFlags & UDF_FLUSH_FLAGS_LITE)) { + full_flush: +- UDFFlushFESpace(Vcb, FileInfo->Dloc); ++ UDFFlushFESpace(Vcb, FileInfo->Dloc, FLUSH_FE_KEEP); + if (FileInfo->Dloc->DataLoc.Flags & EXTENT_FLAG_PREALLOCATED) { + FileInfo->Dloc->DataLoc.Flags |= EXTENT_FLAG_CUT_PREALLOCATED; + status = UDFResizeExtent(IrpContext, Vcb, PartNum, UDFGetFileSize(FileInfo), FALSE, &(FileInfo->Dloc->DataLoc)); +@@ -4991,7 +4991,7 @@ UDFRecordVAT( + UDFPhysLbaToPart(Vcb, PartNum, VatFileInfo->Dloc->DataLoc.Mapping[0].extLocation); + // record data + if (NT_SUCCESS(status = UDFWriteFile__(IrpContext, Vcb, VatFileInfo, 0, VatLen + hdrLen, FALSE, New, &WrittenBytes))) { +- status = UDFFlushFile__(IrpContext, Vcb, VatFileInfo); ++ status = UDFFlushFile__(IrpContext, Vcb, VatFileInfo, 0); + } + return status; + } +@@ -5097,7 +5097,7 @@ UDFRecordVAT( + UDFPhysLbaToPart(Vcb, PartNum, VatFileInfo->Dloc->FELoc.Mapping[0].extLocation); + VatFileInfo->Dloc->DataLoc.Modified = TRUE; + +- status = UDFFlushFile__(IrpContext, Vcb, VatFileInfo); ++ status = UDFFlushFile__(IrpContext, Vcb, VatFileInfo, 0); + if (!NT_SUCCESS(status)) + return status; + +diff --git a/drivers/filesystems/udfs/udf_info/udf_info.h b/drivers/filesystems/udfs/udf_info/udf_info.h +index c10108a..d284982 100644 +--- a/drivers/filesystems/udfs/udf_info/udf_info.h ++++ b/drivers/filesystems/udfs/udf_info/udf_info.h +@@ -444,7 +444,7 @@ void UDFFreeFESpace(IN PVCB Vcb, + // flush FE charge + void UDFFlushFESpace(IN PVCB Vcb, + IN PUDF_DATALOC_INFO Dloc, +- IN BOOLEAN Discard = FLUSH_FE_KEEP); ++ IN BOOLEAN Discard); + // discard file allocation + void UDFFreeFileAllocation(IN PVCB Vcb, + IN PUDF_FILE_INFO DirInfo, +@@ -1022,7 +1022,7 @@ UDFFlushFile__( + IN PIRP_CONTEXT IrpContext, + IN PVCB Vcb, + IN PUDF_FILE_INFO FileInfo, +- IN ULONG FlushFlags = 0 ++ IN ULONG FlushFlags + ); + + // check if the file is flushed diff --git a/drivers/filesystems/udfs/udf_info/udf_rel.h b/drivers/filesystems/udfs/udf_info/udf_rel.h index 602a8f6..2b26348 100644 --- a/drivers/filesystems/udfs/udf_info/udf_rel.h @@ -857,6 +1217,27 @@ similarity index 100% rename from drivers/filesystems/udfs/volinfo.cpp rename to drivers/filesystems/udfs/volinfo.c diff --git a/drivers/filesystems/udfs/write.cpp b/drivers/filesystems/udfs/write.c -similarity index 100% +similarity index 99% rename from drivers/filesystems/udfs/write.cpp rename to drivers/filesystems/udfs/write.c +index 5977f3e..1f236e6 100644 +--- a/drivers/filesystems/udfs/write.cpp ++++ b/drivers/filesystems/udfs/write.c +@@ -237,7 +237,7 @@ UDFCommonWrite( + // I dislike the idea of writing to mounted media too, but M$ has another point of view... + if (Vcb->VcbCondition == VcbMounted) { + // flush system cache +- UDFFlushVolume(IrpContext, Vcb); ++ UDFFlushVolume(IrpContext, Vcb, 0); + } + + // Forward the request to the lower level driver +@@ -255,7 +255,7 @@ UDFCommonWrite( + // Perform actual Write + Status = UDFTWrite(IrpContext, Vcb, SystemBuffer, ByteCount, + (ULONG)(StartingOffset >> Vcb->SectorShift), +- &NumberBytesWritten); ++ &NumberBytesWritten, 0); + UDFUnlockCallersBuffer(IrpContext, Irp, SystemBuffer); + try_return(Status); + } From f30e8ccc0a7ce23d6991f45af1e3998cda721216 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 6 Mar 2026 14:13:10 +0000 Subject: [PATCH 09/20] Fix C4047: uint32 assigned void* (NULL) in mount.c line 2738 Co-authored-by: Zero3K20 <258969903+Zero3K20@users.noreply.github.com> --- drivers/filesystems/udfs/udf_info/mount.c | 2 +- udfs-for-write-branch.patch | 3137 ++++++++++++++++++++- 2 files changed, 2994 insertions(+), 145 deletions(-) diff --git a/drivers/filesystems/udfs/udf_info/mount.c b/drivers/filesystems/udfs/udf_info/mount.c index 47cb4b371a8df..8546c63e137c0 100644 --- a/drivers/filesystems/udfs/udf_info/mount.c +++ b/drivers/filesystems/udfs/udf_info/mount.c @@ -2730,7 +2730,7 @@ UDFFindLastFileSet( uint16 Ident; uint32 relPrevExt, prevExt; - relPrevExt, prevExt = NULL; + relPrevExt = prevExt = 0; FileSetDesc->nextExt.extLength = 1; // ;) // walk through FileSet chain // we've just pre-init'd extent length to read 1st FileSet diff --git a/udfs-for-write-branch.patch b/udfs-for-write-branch.patch index fc42ab5e75852..3dd1d543cd011 100644 --- a/udfs-for-write-branch.patch +++ b/udfs-for-write-branch.patch @@ -1,8 +1,8 @@ diff --git a/drivers/filesystems/udfs/CMakeLists.txt b/drivers/filesystems/udfs/CMakeLists.txt -index 53ce00f..6d1cb9c 100644 +index 53ce00f..09e4e7d 100644 --- a/drivers/filesystems/udfs/CMakeLists.txt +++ b/drivers/filesystems/udfs/CMakeLists.txt -@@ -2,54 +2,51 @@ +@@ -2,54 +2,52 @@ include_directories(Include) list(APPEND SOURCE @@ -64,6 +64,7 @@ index 53ce00f..6d1cb9c 100644 + mem.c + misc.c + namesup.c ++ prefxsup.c + pnp.c + read.c + secursup.c @@ -105,9 +106,18 @@ diff --git a/drivers/filesystems/udfs/Include/phys_lib.cpp b/drivers/filesystems similarity index 99% rename from drivers/filesystems/udfs/Include/phys_lib.cpp rename to drivers/filesystems/udfs/Include/phys_lib.c -index bba91e8..944d35b 100644 +index bba91e8..d85a499 100644 --- a/drivers/filesystems/udfs/Include/phys_lib.cpp +++ b/drivers/filesystems/udfs/Include/phys_lib.c +@@ -4,7 +4,7 @@ + // This file was released under the GPLv2 on June 2015. + //////////////////////////////////////////////////////////////////// + /* +- Module Name: Phys_lib.cpp ++ Module Name: Phys_lib.c + + Execution: Kernel mode only + @@ -1036,7 +1036,7 @@ UDFReadSectors( OUT PULONG ReadBytes ) @@ -153,52 +163,126 @@ similarity index 100% rename from drivers/filesystems/udfs/Include/regtools.cpp rename to drivers/filesystems/udfs/Include/regtools.c diff --git a/drivers/filesystems/udfs/Include/string_lib.cpp b/drivers/filesystems/udfs/Include/string_lib.c -similarity index 98% +similarity index 100% rename from drivers/filesystems/udfs/Include/string_lib.cpp rename to drivers/filesystems/udfs/Include/string_lib.c -index 1750feb..37bd1d8 100644 ---- a/drivers/filesystems/udfs/Include/string_lib.cpp -+++ b/drivers/filesystems/udfs/Include/string_lib.c -@@ -4,7 +4,6 @@ - // This file was released under the GPLv2 on June 2015. +diff --git a/drivers/filesystems/udfs/cleanup.cpp b/drivers/filesystems/udfs/cleanup.c +similarity index 81% +rename from drivers/filesystems/udfs/cleanup.cpp +rename to drivers/filesystems/udfs/cleanup.c +index 678dcb3..1d6c600 100644 +--- a/drivers/filesystems/udfs/cleanup.cpp ++++ b/drivers/filesystems/udfs/cleanup.c +@@ -5,7 +5,7 @@ //////////////////////////////////////////////////////////////////// + /* --extern "C" - ULONG - MyRtlCompareMemory( - PVOID s1, -@@ -26,7 +25,6 @@ MyRtlCompareMemory( +- Module name: Cleanup.cpp ++ Module name: Cleanup.c - #ifndef NT_NATIVE_MODE + Abstract: --extern "C" - ULONG - RtlCompareUnicodeString( - PUNICODE_STRING s1, -@@ -41,7 +39,6 @@ RtlCompareUnicodeString( - return i; - } +@@ -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; + } --extern "C" - NTSTATUS - RtlUpcaseUnicodeString( - PUNICODE_STRING dst, -@@ -57,7 +54,6 @@ RtlUpcaseUnicodeString( - 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. --extern "C" - NTSTATUS - RtlAppendUnicodeToString( - IN PUNICODE_STRING Str1, -diff --git a/drivers/filesystems/udfs/cleanup.cpp b/drivers/filesystems/udfs/cleanup.c -similarity index 99% -rename from drivers/filesystems/udfs/cleanup.cpp -rename to drivers/filesystems/udfs/cleanup.c -index 678dcb3..b85c16a 100644 ---- a/drivers/filesystems/udfs/cleanup.cpp -+++ b/drivers/filesystems/udfs/cleanup.c -@@ -333,7 +333,7 @@ UDFCommonCleanup( + 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 ? +@@ -333,7 +289,7 @@ UDFCommonCleanup( Fcb->ParentFcb->FcbState |= UDF_FCB_DELETE_ON_CLOSE; } // flush file. It is required by UDFUnlinkFile__() @@ -207,18 +291,376 @@ index 678dcb3..b85c16a 100644 if (!NT_SUCCESS(RC)) { AdPrint(("Error flushing file !!!\n")); } +@@ -460,7 +416,7 @@ DiscardDelete: + /* 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 +@@ -556,23 +512,22 @@ DiscardDelete: + } + + // 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; + +@@ -594,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) { +@@ -622,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.c similarity index 100% rename from drivers/filesystems/udfs/close.cpp rename to drivers/filesystems/udfs/close.c diff --git a/drivers/filesystems/udfs/create.cpp b/drivers/filesystems/udfs/create.c -similarity index 99% +similarity index 82% rename from drivers/filesystems/udfs/create.cpp rename to drivers/filesystems/udfs/create.c -index a7f63b1..ed77722 100644 +index a7f63b1..203240f 100644 --- a/drivers/filesystems/udfs/create.cpp +++ b/drivers/filesystems/udfs/create.c -@@ -524,7 +524,7 @@ UDFCommonCreate( +@@ -5,7 +5,7 @@ + //////////////////////////////////////////////////////////////////// + /************************************************************************* + * +-* File: Create.cpp ++* File: Create.c + * + * Module: UDF File System Driver (Kernel mode execution only) + * +@@ -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); ++ } ++ ++ if (OpenByFileId) { ++ SetFlag(CcbFlags, CCB_FLAG_OPEN_BY_ID); + } + +- UDF_CHECK_PAGING_IO_RESOURCE(RelatedFileInfo->Fcb); +- UDFAcquireResourceExclusive((*Res1) = &RelatedFileInfo->Fcb->FcbNonpaged->FcbResource, TRUE); ++ // 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(); + +@@ -524,7 +604,7 @@ UDFCommonCreate( InterlockedDecrement((PLONG)&Vcb->VcbReference); @@ -227,7 +669,510 @@ index a7f63b1..ed77722 100644 } // Lock the volume if (!(ShareAccess & FILE_SHARE_READ)) { -@@ -1428,7 +1428,7 @@ Undo_Create_1: +@@ -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 @@ op_vol_accs_dnd: + 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 @@ op_vol_accs_dnd: + RelatedFileInfo = + OldRelatedFileInfo = RelatedFileInfo->ParentFile; + NextFcb = NextFcb->ParentFcb; +- // prevent releasing parent structures +- UDFAcquireParent(RelatedFileInfo, &Res1, &Res2); +- TreeLength++; +- +- if (Res1) UDFReleaseResource(Res1); +- if (Res2) UDFReleaseResource(Res2); ++ // Parent references are now handled by LCB in UDFCompleteFcbOpen + +- 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 @@ op_vol_accs_dnd: + 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 @@ op_vol_accs_dnd: + 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 @@ op_vol_accs_dnd: + 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 @@ Skip_open_attempt: + 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 @@ Skip_open_attempt: + 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 @@ Skip_open_attempt: + 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 @@ Skip_open_attempt: + // 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 @@ Skip_open_attempt: + ASSERT(!PtrNewFcb); + if (PtrNewFcb) { + BrutePoint(); +- UDFCleanUpFCB(PtrNewFcb); ++ UDFDeleteFcb(IrpContext, PtrNewFcb); + } + MyFreePool__(NewFileInfo); + } else { +@@ -1186,6 +1297,10 @@ Skip_open_attempt: + 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 @@ Skip_open_attempt: + // ... 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 @@ Skip_open_attempt: + // 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 @@ Skip_open_attempt: + 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 @@ Skip_open_attempt: + (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,25 +1514,17 @@ Creation_Err_1: + // 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)) { @@ -236,16 +1181,478 @@ index a7f63b1..ed77722 100644 UDFUnlinkFile__(IrpContext, Vcb, NewFileInfo, TRUE); } UDFCloseFile__(IrpContext, Vcb, NewFileInfo); -@@ -1608,7 +1608,7 @@ Undo_Create_1: +- 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 @@ Undo_Create_1: + 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 @@ Undo_Create_1: + 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 @@ Undo_Create_1: + 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 @@ Undo_Create_1: + 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 @@ Undo_Create_1: + 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, 0); ++ UDFUnlinkFile__(IrpContext, Vcb, NewFileInfo, TRUE); ++ } ++ UDFCloseFile__(IrpContext, Vcb, NewFileInfo); ++ try_return(RC); + } + + PtrNewFcb->Header.FileSize.QuadPart = +@@ -1596,9 +1717,23 @@ Undo_Create_1: + } + } + +- // 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 @@ Undo_Create_1: if (!NT_SUCCESS(RC)) { AdPrint((" Can't set Access Rights on Create\n")); BrutePoint(); - UDFFlushFile__(IrpContext, Vcb, NewFileInfo); ++ // Undo create - flush, unlink and close + UDFFlushFile__(IrpContext, Vcb, NewFileInfo, 0); UDFUnlinkFile__(IrpContext, Vcb, NewFileInfo, TRUE); ++ UDFCloseFile__(IrpContext, Vcb, NewFileInfo); + try_return(RC); + } + +@@ -1650,26 +1787,14 @@ Undo_Create_1: + 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 @@ AlreadyOpened: + } + // 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")); +@@ -1722,7 +1846,7 @@ AlreadyOpened: + if (NonDirectoryFile) { + // If the user wants 'write access' access to the file make sure there + // is not a process mapping this file as an image. Any attempt to +- // delete the file will be stopped in fileinfo.cpp ++ // delete the file will be stopped in fileinfo.c + // + // If the user wants to delete on close, we must check at this + // point though. +@@ -1766,8 +1890,7 @@ AlreadyOpened: + + 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 @@ AlreadyOpened: + 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 @@ AlreadyOpened: + 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 @@ AlreadyOpened: + 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(Res1 != NULL); +- ASSERT(Res2 != NULL); ++ ASSERT(CurrentFcb); + +- // 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); } -@@ -2368,7 +2368,7 @@ UDFCompleteFcbOpen( +-/* 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) +@@ -2259,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 + +@@ -2368,7 +2498,7 @@ UDFCompleteFcbOpen( // Flush the volume and make sure all of the user references // are gone. @@ -254,6 +1661,39 @@ index a7f63b1..ed77722 100644 if (!NT_SUCCESS(Status)) { +@@ -2445,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); + +@@ -2481,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/devcntrl.cpp b/drivers/filesystems/udfs/devcntrl.c similarity index 100% rename from drivers/filesystems/udfs/devcntrl.cpp @@ -279,12 +1719,21 @@ similarity index 100% rename from drivers/filesystems/udfs/filobsup.cpp rename to drivers/filesystems/udfs/filobsup.c diff --git a/drivers/filesystems/udfs/flush.cpp b/drivers/filesystems/udfs/flush.c -similarity index 99% +similarity index 98% rename from drivers/filesystems/udfs/flush.cpp rename to drivers/filesystems/udfs/flush.c -index 76357b7..ebe9dd1 100644 +index 76357b7..4d08e27 100644 --- a/drivers/filesystems/udfs/flush.cpp +++ b/drivers/filesystems/udfs/flush.c +@@ -5,7 +5,7 @@ + //////////////////////////////////////////////////////////////////// + /************************************************************************* + * +-* File: Flush.cpp ++* File: Flush.c + * + * Module: UDF File System Driver (Kernel mode execution only) + * @@ -127,7 +127,7 @@ UDFCommonFlush( UDFVerifyVcb(IrpContext, Vcb); @@ -294,14 +1743,89 @@ index 76357b7..ebe9dd1 100644 UDFReleaseResource(&(Vcb->VcbResource)); AcquiredVCB = FALSE; +@@ -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.c -similarity index 99% +similarity index 98% rename from drivers/filesystems/udfs/fscntrl.cpp rename to drivers/filesystems/udfs/fscntrl.c -index ab7c079..84a9e18 100644 +index ab7c079..ebfb7d6 100644 --- a/drivers/filesystems/udfs/fscntrl.cpp +++ b/drivers/filesystems/udfs/fscntrl.c -@@ -989,7 +989,7 @@ Return Value: +@@ -5,7 +5,7 @@ + //////////////////////////////////////////////////////////////////// + /* + +- Module Name: FsCntrl.cpp ++ Module Name: FsCntrl.c + + Abstract: + +@@ -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); +@@ -989,7 +997,7 @@ Return Value: // remaining after the purge then we can allow the volume to be locked. // @@ -310,7 +1834,7 @@ index ab7c079..84a9e18 100644 //CdPurgeVolume( IrpContext, Vcb, FALSE ); // -@@ -1174,7 +1174,7 @@ UDFDismountVolume( +@@ -1174,7 +1182,7 @@ UDFDismountVolume( } else { @@ -319,7 +1843,7 @@ index ab7c079..84a9e18 100644 // Invalidate the volume right now. // -@@ -1800,7 +1800,7 @@ UDFInvalidateVolumes( +@@ -1800,7 +1808,7 @@ UDFInvalidateVolumes( UDFAcquireVcbExclusive(IrpContext, Vcb, FALSE); @@ -346,13 +1870,60 @@ index 072602c..301ead0 100644 -#include "Include/mem_tools.cpp" +#include "Include/mem_tools.c" diff --git a/drivers/filesystems/udfs/misc.cpp b/drivers/filesystems/udfs/misc.c -similarity index 99% +similarity index 98% rename from drivers/filesystems/udfs/misc.cpp rename to drivers/filesystems/udfs/misc.c -index c78f454..d9cf307 100644 +index c78f454..63b9b0d 100644 --- a/drivers/filesystems/udfs/misc.cpp +++ b/drivers/filesystems/udfs/misc.c -@@ -711,7 +711,7 @@ UDFCreateIrpContext( +@@ -5,7 +5,7 @@ + //////////////////////////////////////////////////////////////////// + /* + +- File: Misc.cpp ++ File: Misc.c + + Module: UDF File System Driver (Kernel mode execution only) + +@@ -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(); +@@ -711,7 +728,7 @@ UDFCreateIrpContext( } // TODO: fix @@ -361,7 +1932,15 @@ index c78f454..d9cf307 100644 PFILE_OBJECT FileObject = IrpSp->FileObject; -@@ -2106,5 +2106,5 @@ UDFWaitForIoAtEof( +@@ -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. +@@ -2106,5 +2122,5 @@ UDFWaitForIoAtEof( return TRUE; } @@ -377,7 +1956,7 @@ similarity index 100% rename from drivers/filesystems/udfs/pnp.cpp rename to drivers/filesystems/udfs/pnp.c diff --git a/drivers/filesystems/udfs/protos.h b/drivers/filesystems/udfs/protos.h -index 59cb00c..c8d0637 100644 +index 59cb00c..08f3a9c 100644 --- a/drivers/filesystems/udfs/protos.h +++ b/drivers/filesystems/udfs/protos.h @@ -73,7 +73,7 @@ UDFDecodeFileObjectCcb( @@ -389,7 +1968,25 @@ index 59cb00c..c8d0637 100644 *************************************************************************/ extern NTSTATUS NTAPI UDFCreate( IN PDEVICE_OBJECT DeviceObject, // the logical volume device object -@@ -120,7 +120,7 @@ UDFInitializeFCB( +@@ -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 +@@ -120,7 +131,7 @@ UDFInitializeFCB( ); /************************************************************************* @@ -398,16 +1995,35 @@ index 59cb00c..c8d0637 100644 *************************************************************************/ extern NTSTATUS NTAPI UDFCleanup( PDEVICE_OBJECT DeviceObject, // the logical volume device object -@@ -140,7 +140,7 @@ UDFCloseFileInfoChain( - ); - +@@ -130,17 +141,8 @@ 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 +* Prototypes for the file close.c *************************************************************************/ extern NTSTATUS NTAPI UDFClose( PDEVICE_OBJECT DeviceObject, // the logical volume device object -@@ -176,7 +176,7 @@ UDFFspClose( +@@ -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 + ); + +@@ -176,7 +178,7 @@ UDFFspClose( UDFCloseAllSystemDelayedInDir((Fcb)->Vcb, (Fcb)->FileInfo) /************************************************************************* @@ -416,7 +2032,7 @@ index 59cb00c..c8d0637 100644 *************************************************************************/ extern NTSTATUS NTAPI UDFDirControl( PDEVICE_OBJECT DeviceObject, // the logical volume device object -@@ -203,7 +203,7 @@ PFCB Fcb, +@@ -203,7 +205,7 @@ PFCB Fcb, PCCB Ccb); /************************************************************************* @@ -425,7 +2041,7 @@ index 59cb00c..c8d0637 100644 *************************************************************************/ extern NTSTATUS NTAPI UDFDeviceControl( PDEVICE_OBJECT DeviceObject, // the logical volume device object -@@ -224,7 +224,7 @@ extern NTSTATUS NTAPI UDFHandleQueryPath( +@@ -224,7 +226,7 @@ extern NTSTATUS NTAPI UDFHandleQueryPath( PVOID BufferPointer); /************************************************************************* @@ -434,7 +2050,7 @@ index 59cb00c..c8d0637 100644 *************************************************************************/ extern BOOLEAN NTAPI UDFFastIoCheckIfPossible( IN PFILE_OBJECT FileObject, -@@ -360,7 +360,7 @@ UDFFastIoCopyWrite( +@@ -360,7 +362,7 @@ UDFFastIoCopyWrite( ); /************************************************************************* @@ -443,7 +2059,7 @@ index 59cb00c..c8d0637 100644 *************************************************************************/ extern NTSTATUS UDFCommonQueryInfo( -@@ -516,7 +516,7 @@ UDFHardLink( +@@ -516,7 +518,7 @@ UDFHardLink( ); /************************************************************************* @@ -452,7 +2068,7 @@ index 59cb00c..c8d0637 100644 *************************************************************************/ extern NTSTATUS NTAPI UDFFlushBuffers( PDEVICE_OBJECT DeviceObject, // the logical volume device object -@@ -531,7 +531,7 @@ ULONG UDFFlushAFile( +@@ -531,7 +533,7 @@ ULONG UDFFlushAFile( IN PFCB Fcb, IN PCCB Ccb, OUT PIO_STATUS_BLOCK PtrIoStatus, @@ -461,7 +2077,7 @@ index 59cb00c..c8d0637 100644 ); ULONG -@@ -540,14 +540,14 @@ UDFFlushADirectory( +@@ -540,14 +542,14 @@ UDFFlushADirectory( IN PVCB Vcb, IN PUDF_FILE_INFO FI, OUT PIO_STATUS_BLOCK PtrIoStatus, @@ -478,7 +2094,7 @@ index 59cb00c..c8d0637 100644 ); extern NTSTATUS NTAPI UDFFlushCompletion( -@@ -557,13 +557,13 @@ PVOID Context); +@@ -557,13 +559,13 @@ PVOID Context); extern BOOLEAN UDFFlushIsBreaking( IN PVCB Vcb, @@ -494,7 +2110,7 @@ index 59cb00c..c8d0637 100644 *************************************************************************/ extern NTSTATUS NTAPI UDFFSControl( -@@ -659,7 +659,7 @@ UDFCommonPnp( +@@ -659,7 +661,7 @@ UDFCommonPnp( ); /************************************************************************* @@ -503,7 +2119,18 @@ index 59cb00c..c8d0637 100644 *************************************************************************/ extern NTSTATUS NTAPI UDFLockControl( -@@ -707,7 +707,7 @@ UDFFastUnlockAllByKey( +@@ -670,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, +@@ -707,7 +711,7 @@ UDFFastUnlockAllByKey( ); /************************************************************************* @@ -512,7 +2139,75 @@ index 59cb00c..c8d0637 100644 *************************************************************************/ extern NTSTATUS UDFInitializeZones( VOID); -@@ -842,7 +842,7 @@ UDFReadRegKeys( +@@ -769,6 +773,49 @@ UDFDeleteCcb( + PCCB Ccb + ); + ++// prefxsup.c - 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, +@@ -779,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( +@@ -842,7 +893,7 @@ UDFReadRegKeys( extern ULONG UDFGetRegParameter( IN PVCB Vcb, IN PCWSTR Name, @@ -521,7 +2216,7 @@ index 59cb00c..c8d0637 100644 VOID UDFDeleteVCB( -@@ -882,13 +882,13 @@ UDFCreateFileLock( +@@ -882,13 +933,13 @@ UDFCreateFileLock( ); /************************************************************************* @@ -537,7 +2232,7 @@ index 59cb00c..c8d0637 100644 *************************************************************************/ NTSTATUS NTAPI -@@ -898,7 +898,7 @@ UDFPnp ( +@@ -898,7 +949,7 @@ UDFPnp ( ); /************************************************************************* @@ -546,7 +2241,7 @@ index 59cb00c..c8d0637 100644 *************************************************************************/ extern NTSTATUS NTAPI UDFRead( PDEVICE_OBJECT DeviceObject, // the logical volume device object -@@ -952,7 +952,7 @@ UDFSetAccessRights( +@@ -952,7 +1003,7 @@ UDFSetAccessRights( USHORT ShareAccess); /************************************************************************* @@ -555,7 +2250,7 @@ index 59cb00c..c8d0637 100644 *************************************************************************/ NTSTATUS -@@ -962,9 +962,9 @@ UDFCommonShutdown( +@@ -962,9 +1013,9 @@ UDFCommonShutdown( ); /************************************************************************* @@ -567,7 +2262,7 @@ index 59cb00c..c8d0637 100644 PDRIVER_OBJECT DriverObject, // created by the I/O sub-system PUNICODE_STRING RegistryPath); // path to the registry key -@@ -972,7 +972,7 @@ extern VOID NTAPI UDFInitializeFunctionPointers( +@@ -972,7 +1023,7 @@ extern VOID NTAPI UDFInitializeFunctionPointers( PDRIVER_OBJECT DriverObject); // created by the I/O sub-system /************************************************************************* @@ -576,7 +2271,7 @@ index 59cb00c..c8d0637 100644 *************************************************************************/ VOID -@@ -1024,7 +1024,7 @@ UDFCompareVcb( +@@ -1024,7 +1075,7 @@ UDFCompareVcb( ); /************************************************************************* @@ -585,7 +2280,7 @@ index 59cb00c..c8d0637 100644 *************************************************************************/ extern NTSTATUS NTAPI UDFQueryVolInfo(PDEVICE_OBJECT DeviceObject, PIRP Irp); -@@ -1051,7 +1051,7 @@ UDFCommonSetVolInfo( +@@ -1051,7 +1102,7 @@ UDFCommonSetVolInfo( ); /************************************************************************* @@ -594,7 +2289,7 @@ index 59cb00c..c8d0637 100644 *************************************************************************/ extern NTSTATUS NTAPI UDFWrite( PDEVICE_OBJECT DeviceObject, // the logical volume device object -@@ -1217,13 +1217,13 @@ UDFMarkDevForVerifyIfVcbMounted( +@@ -1217,13 +1268,13 @@ UDFMarkDevForVerifyIfVcbMounted( UdfData.UdfDataLockThread = NULL; \ ExReleaseFastMutexUnsafe(&UdfData.UdfDataMutex) @@ -610,6 +2305,51 @@ index 59cb00c..c8d0637 100644 _Requires_lock_held_(_Global_critical_region_) _When_(Type == AcquireExclusive && return != FALSE, _Acquires_exclusive_lock_(*Resource)) +@@ -1271,7 +1322,7 @@ UDFAcquireResource( + #define UDFReleasePagingIo(IC,F) \ + ExReleaseResourceLite((F)->Header.PagingIoResource) + +-inline ++static inline + ULONG + UDFHighBit( + ULONG Word +@@ -1295,7 +1346,7 @@ UDFHighBit( + + #define SectorSize(V) ((V)->SectorSize) + +-inline ++static inline + ULONG + SectorAlign( + PVCB Vcb, +@@ -1305,7 +1356,7 @@ SectorAlign( + return (Length + (Vcb->SectorSize - 1)) & ~(Vcb->SectorSize - 1); + } + +-inline ++static inline + ULONGLONG + LlSectorAlign( + PVCB Vcb, +@@ -1327,7 +1378,7 @@ UDFSetThreadContext( + (IC)->ThreadContext = NULL + + +-inline ++static inline + BOOLEAN UdfIsExtendedFESupported( + _In_ PVCB Vcb + ) +@@ -1335,7 +1386,7 @@ BOOLEAN UdfIsExtendedFESupported( + return Vcb->NSRDesc == VRS_NSR03_FOUND; + } + +-inline ++static inline + BOOLEAN UDFIsStreamsSupported( + _In_ PVCB Vcb + ) diff --git a/drivers/filesystems/udfs/read.cpp b/drivers/filesystems/udfs/read.c similarity index 100% rename from drivers/filesystems/udfs/read.cpp @@ -622,9 +2362,18 @@ diff --git a/drivers/filesystems/udfs/shutdown.cpp b/drivers/filesystems/udfs/sh similarity index 99% rename from drivers/filesystems/udfs/shutdown.cpp rename to drivers/filesystems/udfs/shutdown.c -index f8b0a7f..314b0e2 100644 +index f8b0a7f..79b132c 100644 --- a/drivers/filesystems/udfs/shutdown.cpp +++ b/drivers/filesystems/udfs/shutdown.c +@@ -5,7 +5,7 @@ + //////////////////////////////////////////////////////////////////// + /************************************************************************* + * +-* File: Shutdown.cpp ++* File: Shutdown.c + * + * Module: UDF File System Driver (Kernel mode execution only) + * @@ -109,7 +109,7 @@ UDFCommonShutdown( UDFAcquireVcbExclusive(IrpContext, Vcb, FALSE); @@ -635,22 +2384,39 @@ index f8b0a7f..314b0e2 100644 ASSERT(CONTAINING_RECORD(IoGetCurrentIrpStackLocation(Irp)->DeviceObject, VOLUME_DEVICE_OBJECT, diff --git a/drivers/filesystems/udfs/strucsup.cpp b/drivers/filesystems/udfs/strucsup.c -similarity index 99% +similarity index 68% rename from drivers/filesystems/udfs/strucsup.cpp rename to drivers/filesystems/udfs/strucsup.c -index 6e00af7..7964ebb 100644 +index 6e00af7..544b7ad 100644 --- a/drivers/filesystems/udfs/strucsup.cpp +++ b/drivers/filesystems/udfs/strucsup.c -@@ -29,7 +29,7 @@ typedef struct _FCB_TABLE_ELEMENT { +@@ -29,7 +29,24 @@ typedef struct _FCB_TABLE_ELEMENT { RtlDeleteElementGenericTable( &(F)->Vcb->FcbTable, &_Key ); \ } -inline ++// ++// Public wrapper for inserting FCB into FcbTable. ++// Called from create.c 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); ++} ++ +static inline PFCB_NONPAGED UDFAllocateFcbNonpaged( ) -@@ -37,7 +37,7 @@ UDFAllocateFcbNonpaged( +@@ -37,7 +54,7 @@ UDFAllocateFcbNonpaged( return (PFCB_NONPAGED)ExAllocateFromNPagedLookasideList(&UdfData.UDFNonPagedFcbLookasideList); } @@ -659,7 +2425,7 @@ index 6e00af7..7964ebb 100644 PFCB UDFAllocateFcbIndex( ) -@@ -45,7 +45,7 @@ UDFAllocateFcbIndex( +@@ -45,7 +62,7 @@ UDFAllocateFcbIndex( return (PFCB)ExAllocateFromPagedLookasideList(&UdfData.UDFFcbIndexLookasideList); } @@ -668,7 +2434,7 @@ index 6e00af7..7964ebb 100644 PFCB UDFAllocateFcbData( ) -@@ -53,7 +53,7 @@ UDFAllocateFcbData( +@@ -53,7 +70,7 @@ UDFAllocateFcbData( return (PFCB)ExAllocateFromPagedLookasideList(&UdfData.UDFFcbDataLookasideList); } @@ -677,7 +2443,7 @@ index 6e00af7..7964ebb 100644 PFCB UDFAllocateFcb( ) -@@ -61,7 +61,7 @@ UDFAllocateFcb( +@@ -61,7 +78,7 @@ UDFAllocateFcb( return (PFCB)ExAllocatePoolWithTag(NonPagedPool, sizeof(FCB), TAG_FCB); } @@ -686,7 +2452,7 @@ index 6e00af7..7964ebb 100644 VOID UDFDeallocateFcbNonpaged( PFCB_NONPAGED FcbNonpaged -@@ -70,7 +70,7 @@ UDFDeallocateFcbNonpaged( +@@ -70,7 +87,7 @@ UDFDeallocateFcbNonpaged( ExFreeToNPagedLookasideList(&UdfData.UDFNonPagedFcbLookasideList, FcbNonpaged); } @@ -695,7 +2461,7 @@ index 6e00af7..7964ebb 100644 VOID UDFDeallocateFcbIndex( PFCB Fcb -@@ -79,7 +79,7 @@ UDFDeallocateFcbIndex( +@@ -79,7 +96,7 @@ UDFDeallocateFcbIndex( ExFreeToPagedLookasideList(&UdfData.UDFFcbIndexLookasideList, Fcb); } @@ -704,18 +2470,618 @@ index 6e00af7..7964ebb 100644 VOID UDFDeallocateFcbData( PFCB Fcb +@@ -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, 0); ++ 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, 0); ++ } ++ ++ // 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 fb48f5e..75638fa 100644 +index fb48f5e..53eb53b 100644 --- a/drivers/filesystems/udfs/struct.h +++ b/drivers/filesystems/udfs/struct.h -@@ -37,6 +37,21 @@ struct IRP_CONTEXT_LITE; +@@ -36,6 +36,24 @@ + struct IRP_CONTEXT_LITE; struct IO_CONTEXT; struct IRP_CONTEXT; - -+/* C typedef aliases - allow plain name usage without the 'struct' keyword */ ++struct LCB; ++typedef struct LCB *PLCB; ++ ++/* C typedef aliases – allow plain name usage without the 'struct' keyword */ +typedef struct IRP_CONTEXT_LITE IRP_CONTEXT_LITE; +typedef struct IO_CONTEXT IO_CONTEXT; +typedef struct IRP_CONTEXT IRP_CONTEXT; ++typedef struct LCB LCB; +typedef struct UDFIdentifier UDFIdentifier; +typedef struct UDFObjectName UDFObjectName; +typedef struct CCB CCB; @@ -726,11 +3092,10 @@ index fb48f5e..75638fa 100644 +typedef struct VCB VCB; +typedef struct VOLUME_DEVICE_OBJECT VOLUME_DEVICE_OBJECT; +typedef struct THREAD_CONTEXT THREAD_CONTEXT; -+ + /************************************************************************** every structure has a node type, and a node size associated with it. - The node type serves as a signature field. The size is used for -@@ -47,8 +62,7 @@ struct UDFIdentifier { +@@ -47,8 +65,7 @@ struct UDFIdentifier { NODE_BYTE_SIZE NodeByteSize; // computed as sizeof(structure) }; @@ -740,7 +3105,7 @@ index fb48f5e..75638fa 100644 /************************************************************************** Every open on-disk object must have a name associated with it -@@ -67,7 +81,7 @@ struct UDFObjectName { +@@ -67,7 +84,7 @@ struct UDFObjectName { // an absolute pathname of the object is stored below UNICODE_STRING ObjectName; }; @@ -749,16 +3114,27 @@ index fb48f5e..75638fa 100644 /************************************************************************** Each file open instance is represented by a context control block. -@@ -96,7 +110,7 @@ struct CCB { +@@ -82,6 +99,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,9 +113,8 @@ struct CCB { + // need to maintain a search pattern + PUNICODE_STRING DirectorySearchPattern; HASH_ENTRY hashes; - ULONG TreeLength; +- ULONG TreeLength; }; -using PCCB = CCB*; +typedef CCB* PCCB; #define CCB_FLAG_IGNORE_CASE (0x00000004) // the CCB has had an IRP_MJ_CLEANUP issued on it. we must -@@ -152,7 +166,7 @@ struct FCB_NONPAGED { +@@ -152,7 +170,7 @@ struct FCB_NONPAGED { FAST_MUTEX AdvancedFcbHeaderMutex; }; @@ -767,7 +3143,7 @@ index fb48f5e..75638fa 100644 /************************************************************************** each open file/directory/volume is represented by a file control block. -@@ -193,11 +207,11 @@ using PFCB_NONPAGED = FCB_NONPAGED*; +@@ -193,11 +211,11 @@ using PFCB_NONPAGED = FCB_NONPAGED*; /***************************************************/ struct FCB_DATA { @@ -781,7 +3157,21 @@ index fb48f5e..75638fa 100644 }; struct FCB { -@@ -284,7 +298,7 @@ struct FCB { +@@ -267,6 +285,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; +@@ -284,7 +309,7 @@ struct FCB { FCB_INDEX FcbIndex; }; }; @@ -790,7 +3180,7 @@ index fb48f5e..75638fa 100644 #define SIZEOF_FCB_DATA \ (FIELD_OFFSET(FCB, FcbType) + sizeof(FCB_DATA)) -@@ -325,7 +339,7 @@ using PFCB = FCB*; +@@ -325,7 +350,7 @@ using PFCB = FCB*; **************************************************************************/ @@ -799,14 +3189,60 @@ index fb48f5e..75638fa 100644 MediaUnknown = 0, MediaHdd, MediaCdr, -@@ -335,16 +349,16 @@ enum UDFFSD_MEDIA_TYPE { +@@ -335,16 +360,63 @@ enum UDFFSD_MEDIA_TYPE { MediaFloppy, MediaDvdr, MediaDvdrw --}; +} UDFFSD_MEDIA_TYPE; ++ ++//*************************************************************************** ++// 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; + }; -enum VCB_CONDITION { ++// 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) ++//*************************************************************************** ++ +typedef enum VCB_CONDITION { VcbNotMounted = 0, @@ -819,7 +3255,7 @@ index fb48f5e..75638fa 100644 struct VCB { -@@ -608,7 +622,7 @@ struct VCB { +@@ -608,7 +680,7 @@ struct VCB { PVPB SwapVpb; }; @@ -828,7 +3264,7 @@ index fb48f5e..75638fa 100644 // One for root #define UDFS_BASE_RESIDUAL_REFERENCE (4)//(6) -@@ -682,7 +696,7 @@ struct THREAD_CONTEXT { +@@ -682,7 +754,7 @@ struct THREAD_CONTEXT { // will store the IrpContext for the request in this stack location. IRP_CONTEXT* TopLevelIrpContext; }; @@ -837,7 +3273,15 @@ index fb48f5e..75638fa 100644 /************************************************************************** The IRP context encapsulates the current request. This structure is -@@ -727,7 +741,7 @@ struct IRP_CONTEXT { +@@ -707,7 +779,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. +@@ -727,7 +798,7 @@ struct IRP_CONTEXT { VCB* Vcb; }; @@ -846,22 +3290,49 @@ index fb48f5e..75638fa 100644 #define IRP_CONTEXT_FLAG_ON_STACK (0x00000001) #define IRP_CONTEXT_FLAG_MORE_PROCESSING (0x00000002) -@@ -794,7 +808,7 @@ struct IRP_CONTEXT_LITE { +@@ -792,9 +863,8 @@ struct IRP_CONTEXT_LITE { + ULONG UserReference; + // Real device object. This represents the physical device closest to the media. PDEVICE_OBJECT RealDevice; - ULONG TreeLength; +- ULONG TreeLength; }; -using PIRP_CONTEXT_LITE = IRP_CONTEXT_LITE*; +typedef IRP_CONTEXT_LITE* PIRP_CONTEXT_LITE; /************************************************************************** we will store all of our global variables in one structure. +@@ -837,6 +907,7 @@ typedef struct _UDFData { + PAGED_LOOKASIDE_LIST UDFFcbDataLookasideList; + + PAGED_LOOKASIDE_LIST CcbLookasideList; ++ PAGED_LOOKASIDE_LIST LcbLookasideList; + + LIST_ENTRY AsyncCloseQueue; + ULONG AsyncCloseCount; +@@ -877,6 +948,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/sys_spec.cpp b/drivers/filesystems/udfs/sys_spec.c -similarity index 95% +similarity index 89% rename from drivers/filesystems/udfs/sys_spec.cpp rename to drivers/filesystems/udfs/sys_spec.c -index e9a11ab..df66b8c 100644 +index e9a11ab..cd77a8f 100644 --- a/drivers/filesystems/udfs/sys_spec.cpp +++ b/drivers/filesystems/udfs/sys_spec.c +@@ -5,7 +5,7 @@ + //////////////////////////////////////////////////////////////////// + /************************************************************************* + * +-* File: Sys_Spec.cpp ++* File: Sys_Spec.c + * + * Module: UDF File System Driver + * (both User and Kernel mode execution) @@ -20,6 +20,6 @@ // define the file specific bug-check id #define UDF_BUG_CHECK_ID UDF_FILE_SYS_SPEC @@ -869,7 +3340,8 @@ index e9a11ab..df66b8c 100644 -#include "Include/Sys_spec_lib.cpp" +#include "Include/Sys_spec_lib.c" - //#include "Include/tools.cpp" +-//#include "Include/tools.cpp" ++//#include "Include/tools.c" diff --git a/drivers/filesystems/udfs/udf_dbg.cpp b/drivers/filesystems/udfs/udf_dbg.c similarity index 100% rename from drivers/filesystems/udfs/udf_dbg.cpp @@ -947,9 +3419,18 @@ diff --git a/drivers/filesystems/udfs/udf_info/mount.cpp b/drivers/filesystems/u similarity index 99% rename from drivers/filesystems/udfs/udf_info/mount.cpp rename to drivers/filesystems/udfs/udf_info/mount.c -index 3fc100a..cd60aa4 100644 +index 3fc100a..97a77d4 100644 --- a/drivers/filesystems/udfs/udf_info/mount.cpp +++ b/drivers/filesystems/udfs/udf_info/mount.c +@@ -6,7 +6,7 @@ + /* + Module name: + +- mount.cpp ++ mount.c + + Abstract: + @@ -915,7 +915,7 @@ UDFUpdateNonAllocated( } UDFPackMapping(Vcb, DataLoc); @@ -959,6 +3440,15 @@ index 3fc100a..cd60aa4 100644 // ensure that BAD space is marked as USED UDFMarkSpaceAsXXX(Vcb, 0, &(DataLoc->Mapping[0]), AS_USED); // mark as used +@@ -2735,7 +2735,7 @@ UDFFindLastFileSet( + uint16 Ident; + uint32 relPrevExt, prevExt; + +- relPrevExt, prevExt = NULL; ++ relPrevExt = prevExt = 0; + FileSetDesc->nextExt.extLength = 1; // ;) + // walk through FileSet chain + // we've just pre-init'd extent length to read 1st FileSet diff --git a/drivers/filesystems/udfs/udf_info/osta_misc.h b/drivers/filesystems/udfs/udf_info/osta_misc.h index f9813bf..60b522c 100644 --- a/drivers/filesystems/udfs/udf_info/osta_misc.h @@ -982,12 +3472,21 @@ index f9813bf..60b522c 100644 #endif /* _OSTA_MISC_H */ diff --git a/drivers/filesystems/udfs/udf_info/phys_eject.cpp b/drivers/filesystems/udfs/udf_info/phys_eject.c -similarity index 98% +similarity index 97% rename from drivers/filesystems/udfs/udf_info/phys_eject.cpp rename to drivers/filesystems/udfs/udf_info/phys_eject.c -index 2a7a794..d07cced 100644 +index 2a7a794..32e98ab 100644 --- a/drivers/filesystems/udfs/udf_info/phys_eject.cpp +++ b/drivers/filesystems/udfs/udf_info/phys_eject.c +@@ -4,7 +4,7 @@ + // This file was released under the GPLv2 on June 2015. + //////////////////////////////////////////////////////////////////// + /* +- Module Name: Phys_eject.cpp ++ Module Name: Phys_eject.c + + Execution: Kernel mode only + @@ -28,7 +28,7 @@ UDFDoDismountSequence( ULONG i; @@ -998,30 +3497,29 @@ index 2a7a794..d07cced 100644 delay.QuadPart = -1000000; // 0.1 sec diff --git a/drivers/filesystems/udfs/udf_info/physical.cpp b/drivers/filesystems/udfs/udf_info/physical.c -similarity index 95% +similarity index 100% rename from drivers/filesystems/udfs/udf_info/physical.cpp rename to drivers/filesystems/udfs/udf_info/physical.c -index 1ba8a14..9468996 100644 ---- a/drivers/filesystems/udfs/udf_info/physical.cpp -+++ b/drivers/filesystems/udfs/udf_info/physical.c -@@ -17,5 +17,5 @@ - // define the file specific bug-check id - #define UDF_BUG_CHECK_ID UDF_FILE_PHYSICAL - --#include "Include/phys_lib.cpp" -+#include "Include/phys_lib.c" - diff --git a/drivers/filesystems/udfs/udf_info/remap.cpp b/drivers/filesystems/udfs/udf_info/remap.c similarity index 100% rename from drivers/filesystems/udfs/udf_info/remap.cpp rename to drivers/filesystems/udfs/udf_info/remap.c diff --git a/drivers/filesystems/udfs/udf_info/udf_info.cpp b/drivers/filesystems/udfs/udf_info/udf_info.c -similarity index 99% +similarity index 96% rename from drivers/filesystems/udfs/udf_info/udf_info.cpp rename to drivers/filesystems/udfs/udf_info/udf_info.c -index e5d0b69..86f90dd 100644 +index e5d0b69..b218cdc 100644 --- a/drivers/filesystems/udfs/udf_info/udf_info.cpp +++ b/drivers/filesystems/udfs/udf_info/udf_info.c +@@ -6,7 +6,7 @@ + /* + Module name: + +- udf_info.cpp ++ udf_info.c + + Abstract: + @@ -1835,7 +1835,7 @@ UDFUnlinkFile__( PUDF_FILE_INFO SFileInfo; // ... try to open it @@ -1076,7 +3574,186 @@ index e5d0b69..86f90dd 100644 AdPrint((" ")); UDFUnlinkFile__(IrpContext, Vcb, FileInfo, TRUE); UDFCloseFile__(IrpContext, Vcb, FileInfo); -@@ -2421,7 +2421,7 @@ UDFCleanUpFile__( +@@ -2149,6 +2149,178 @@ init_tree_entry: + } // 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 + */ +@@ -2421,7 +2593,7 @@ UDFCleanUpFile__( MyFreePool__(DirNdx->FName.Buffer); } // The only place where we can free FE_Charge extent is here @@ -1085,7 +3762,21 @@ index e5d0b69..86f90dd 100644 UDFDirIndexFree(Dloc->DirIndex); Dloc->DirIndex = NULL; #ifdef UDF_TRACK_ONDISK_ALLOCATION -@@ -3099,7 +3099,7 @@ UDFCloseFile__( +@@ -2863,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; +@@ -3099,7 +3275,7 @@ UDFCloseFile__( if (FileInfo->Dloc && FileInfo->Dloc->DirIndex) { @@ -1094,7 +3785,7 @@ index e5d0b69..86f90dd 100644 if (FileInfo->Dloc->DataLoc.Flags & EXTENT_FLAG_PREALLOCATED) { FileInfo->Dloc->DataLoc.Flags |= EXTENT_FLAG_CUT_PREALLOCATED; status = UDFResizeExtent(IrpContext, Vcb, PartNum, UDFGetFileSize(FileInfo), FALSE, &(FileInfo->Dloc->DataLoc)); -@@ -3276,7 +3276,7 @@ cleanup_and_abort_rename: +@@ -3276,7 +3452,7 @@ cleanup_and_abort_rename: // unlink source FileIdent if (!NT_SUCCESS(status = UDFUnlinkFile__(IrpContext, Vcb, FileInfo, FALSE))) { // kill newly created entry @@ -1103,7 +3794,16 @@ index e5d0b69..86f90dd 100644 UDFUnlinkFile__(IrpContext, Vcb, FileInfo2, TRUE); UDFCloseFile__(IrpContext, Vcb, FileInfo2); UDFCleanUpFile__(Vcb, FileInfo2); -@@ -4174,7 +4174,7 @@ UDFFlushFile__( +@@ -3618,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: +@@ -4174,7 +4352,7 @@ UDFFlushFile__( // if Lite Flush is used, keep preallocations if (!(FlushFlags & UDF_FLUSH_FLAGS_LITE)) { full_flush: @@ -1112,7 +3812,7 @@ index e5d0b69..86f90dd 100644 if (FileInfo->Dloc->DataLoc.Flags & EXTENT_FLAG_PREALLOCATED) { FileInfo->Dloc->DataLoc.Flags |= EXTENT_FLAG_CUT_PREALLOCATED; status = UDFResizeExtent(IrpContext, Vcb, PartNum, UDFGetFileSize(FileInfo), FALSE, &(FileInfo->Dloc->DataLoc)); -@@ -4991,7 +4991,7 @@ UDFRecordVAT( +@@ -4991,7 +5169,7 @@ UDFRecordVAT( UDFPhysLbaToPart(Vcb, PartNum, VatFileInfo->Dloc->DataLoc.Mapping[0].extLocation); // record data if (NT_SUCCESS(status = UDFWriteFile__(IrpContext, Vcb, VatFileInfo, 0, VatLen + hdrLen, FALSE, New, &WrittenBytes))) { @@ -1121,7 +3821,7 @@ index e5d0b69..86f90dd 100644 } return status; } -@@ -5097,7 +5097,7 @@ UDFRecordVAT( +@@ -5097,7 +5275,7 @@ UDFRecordVAT( UDFPhysLbaToPart(Vcb, PartNum, VatFileInfo->Dloc->FELoc.Mapping[0].extLocation); VatFileInfo->Dloc->DataLoc.Modified = TRUE; @@ -1131,10 +3831,34 @@ index e5d0b69..86f90dd 100644 return status; diff --git a/drivers/filesystems/udfs/udf_info/udf_info.h b/drivers/filesystems/udfs/udf_info/udf_info.h -index c10108a..d284982 100644 +index c10108a..e61fa21 100644 --- a/drivers/filesystems/udfs/udf_info/udf_info.h +++ b/drivers/filesystems/udfs/udf_info/udf_info.h -@@ -444,7 +444,7 @@ void UDFFreeFESpace(IN PVCB Vcb, +@@ -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 +@@ -444,7 +461,7 @@ void UDFFreeFESpace(IN PVCB Vcb, // flush FE charge void UDFFlushFESpace(IN PVCB Vcb, IN PUDF_DATALOC_INFO Dloc, @@ -1143,7 +3867,7 @@ index c10108a..d284982 100644 // discard file allocation void UDFFreeFileAllocation(IN PVCB Vcb, IN PUDF_FILE_INFO DirInfo, -@@ -1022,7 +1022,7 @@ UDFFlushFile__( +@@ -1022,7 +1039,7 @@ UDFFlushFile__( IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN PUDF_FILE_INFO FileInfo, @@ -1153,7 +3877,7 @@ index c10108a..d284982 100644 // check if the file is flushed diff --git a/drivers/filesystems/udfs/udf_info/udf_rel.h b/drivers/filesystems/udfs/udf_info/udf_rel.h -index 602a8f6..2b26348 100644 +index 602a8f6..f62ef96 100644 --- a/drivers/filesystems/udfs/udf_info/udf_rel.h +++ b/drivers/filesystems/udfs/udf_info/udf_rel.h @@ -246,7 +246,7 @@ typedef struct _UDF_DATALOC_INFO { @@ -1165,6 +3889,25 @@ index 602a8f6..2b26348 100644 /** Describes on-disk location of user data. If the file is recorded using IN_ICB method this structure points to the +@@ -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/udfdata.cpp b/drivers/filesystems/udfs/udfdata.c similarity index 100% rename from drivers/filesystems/udfs/udfdata.cpp @@ -1217,12 +3960,80 @@ similarity index 100% rename from drivers/filesystems/udfs/volinfo.cpp rename to drivers/filesystems/udfs/volinfo.c diff --git a/drivers/filesystems/udfs/write.cpp b/drivers/filesystems/udfs/write.c -similarity index 99% +similarity index 97% rename from drivers/filesystems/udfs/write.cpp rename to drivers/filesystems/udfs/write.c -index 5977f3e..1f236e6 100644 +index 5977f3e..d2309ee 100644 --- a/drivers/filesystems/udfs/write.cpp +++ b/drivers/filesystems/udfs/write.c +@@ -5,7 +5,7 @@ + //////////////////////////////////////////////////////////////////// + /************************************************************************* + * +-* File: Write.cpp ++* File: Write.c + * + * Module: UDF File System Driver (Kernel mode execution only) + * +@@ -44,7 +44,9 @@ UDFCommonWrite( + NTSTATUS Status = STATUS_SUCCESS; + PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); + LONGLONG StartingOffset; +- ULONG ByteCount = 0, TruncatedLength = 0; ++ ULONG ByteCount; ++ LONGLONG ByteRange; ++ ULONG TruncatedLength; + SIZE_T NumberBytesWritten = 0; + PFILE_OBJECT FileObject = NULL; + TYPE_OF_OPEN TypeOfOpen; +@@ -60,9 +62,6 @@ UDFCommonWrite( + BOOLEAN MainResourceAcquired = FALSE; + BOOLEAN VcbAcquired = FALSE; + +- BOOLEAN MainResourceAcquiredExclusive = FALSE; +- BOOLEAN MainResourceCanDemoteToShared = FALSE; +- + BOOLEAN Wait = FALSE; + BOOLEAN PagingIo = FALSE; + BOOLEAN NonCachedIo = FALSE; +@@ -74,6 +73,14 @@ UDFCommonWrite( + BOOLEAN ZeroBlock = FALSE; + BOOLEAN ZeroBlockDone = FALSE; + ++ // Examine our input parameters to determine if this is noncached and/or ++ // a paging io operation. ++ ++ 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; + + // Extract and decode the file object. +@@ -94,14 +101,6 @@ UDFCommonWrite( + ASSERT_FCB(Fcb); + ASSERT_VCB(Vcb); + +- // Examine our input parameters to determine if this is noncached and/or +- // a paging io operation. +- +- 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); +- + // Check if this volume has already been shut down. If it has, fail + // this write request. + +@@ -139,6 +138,7 @@ UDFCommonWrite( + + StartingOffset = IrpSp->Parameters.Write.ByteOffset.QuadPart; + ByteCount = IrpSp->Parameters.Write.Length; ++ ByteRange = StartingOffset + ByteCount; + + Irp->IoStatus.Information = 0; + @@ -237,7 +237,7 @@ UDFCommonWrite( // I dislike the idea of writing to mounted media too, but M$ has another point of view... if (Vcb->VcbCondition == VcbMounted) { @@ -1241,3 +4052,41 @@ index 5977f3e..1f236e6 100644 UDFUnlockCallersBuffer(IrpContext, Irp, SystemBuffer); try_return(Status); } +@@ -334,8 +334,6 @@ UDFCommonWrite( + if (!SuccessfulPurge) { + try_return(Status = STATUS_PURGE_FAILED); + } +- +- MainResourceCanDemoteToShared = TRUE; + } + + // Determine if we were called by the lazywriter. +@@ -422,19 +420,6 @@ UDFCommonWrite( + 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, Wait)) { +- try_return(Status = STATUS_PENDING); +- } +- MainResourceAcquired = TRUE; +- } +- + UDFAcquireResourceExclusive(&Fcb->FcbNonpaged->FcbPagingIoResource, TRUE); + PagingIoResourceAcquired = TRUE; + +@@ -755,7 +740,7 @@ UDFPurgeCacheEx_( + + // We'll just purge cache section here, + // without call to CcZeroData() +- // 'cause udf_info.cpp will care about it ++ // 'cause udf_info.c will care about it + + #define PURGE_BLOCK_SZ 0x10000000 + From 52a2c597b38ceabb47b4128306410a57a8a54453 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 6 Mar 2026 15:04:30 +0000 Subject: [PATCH 10/20] Fix patch: remove udf-dev content, base on write branch only with C++ to C conversion Co-authored-by: Zero3K20 <258969903+Zero3K20@users.noreply.github.com> --- drivers/filesystems/udfs/CMakeLists.txt | 4 +- .../filesystems/udfs/Include/Sys_spec_lib.c | 2 +- drivers/filesystems/udfs/Include/phys_lib.c | 2 +- drivers/filesystems/udfs/Include/string_lib.c | 4 + drivers/filesystems/udfs/cleanup.c | 166 +- drivers/filesystems/udfs/close.c | 273 +- drivers/filesystems/udfs/devcntrl.c | 2 +- drivers/filesystems/udfs/dircntrl.c | 19 +- drivers/filesystems/udfs/env_spec.c | 2 +- drivers/filesystems/udfs/fastio.c | 2 +- drivers/filesystems/udfs/fileinfo.c | 855 ++-- drivers/filesystems/udfs/flush.c | 37 +- drivers/filesystems/udfs/fscntrl.c | 12 +- drivers/filesystems/udfs/lockctrl.c | 35 +- drivers/filesystems/udfs/mem.c | 2 +- drivers/filesystems/udfs/misc.c | 247 +- drivers/filesystems/udfs/namesup.c | 2 +- drivers/filesystems/udfs/nodetype.h | 1 - drivers/filesystems/udfs/pnp.c | 2 +- drivers/filesystems/udfs/prefxsup.c | 1338 ------- drivers/filesystems/udfs/protos.h | 258 +- drivers/filesystems/udfs/read.c | 2 +- drivers/filesystems/udfs/secursup.c | 2 +- drivers/filesystems/udfs/shutdown.c | 2 +- drivers/filesystems/udfs/strucsup.c | 665 +--- drivers/filesystems/udfs/struct.h | 215 +- drivers/filesystems/udfs/sys_spec.c | 6 +- drivers/filesystems/udfs/udf_info/alloc.c | 2 +- drivers/filesystems/udfs/udf_info/dirtree.c | 47 +- drivers/filesystems/udfs/udf_info/ecma_167.h | 10 +- drivers/filesystems/udfs/udf_info/extent.c | 2 +- drivers/filesystems/udfs/udf_info/mount.c | 2 +- .../filesystems/udfs/udf_info/phys_eject.c | 2 +- drivers/filesystems/udfs/udf_info/physical.c | 4 +- drivers/filesystems/udfs/udf_info/remap.c | 2 +- drivers/filesystems/udfs/udf_info/udf_info.c | 182 +- drivers/filesystems/udfs/udf_info/udf_info.h | 17 - drivers/filesystems/udfs/udf_info/udf_rel.h | 12 - drivers/filesystems/udfs/udfdata.c | 2 +- drivers/filesystems/udfs/udffs.h | 6 +- drivers/filesystems/udfs/udfinit.c | 2 +- drivers/filesystems/udfs/verfysup.c | 2 +- drivers/filesystems/udfs/volinfo.c | 2 +- drivers/filesystems/udfs/write.c | 80 +- udfs-for-write-branch.patch | 3448 +---------------- 45 files changed, 1565 insertions(+), 6416 deletions(-) delete mode 100644 drivers/filesystems/udfs/prefxsup.c diff --git a/drivers/filesystems/udfs/CMakeLists.txt b/drivers/filesystems/udfs/CMakeLists.txt index 09e4e7d57f7f4..fa427875e2a51 100644 --- a/drivers/filesystems/udfs/CMakeLists.txt +++ b/drivers/filesystems/udfs/CMakeLists.txt @@ -24,7 +24,6 @@ list(APPEND SOURCE mem.c misc.c namesup.c - prefxsup.c pnp.c read.c secursup.c @@ -45,9 +44,12 @@ add_library(udfs MODULE ${SOURCE} udffs.rc) if(CMAKE_C_COMPILER_ID STREQUAL "GNU") target_compile_options(udfs PRIVATE -Wno-unused-but-set-variable) + target_compile_options(udfs PRIVATE -Wno-invalid-offsetof) + target_compile_options(udfs PRIVATE -Wno-error -fpermissive) endif() if(CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_compile_options(udfs PRIVATE -Wno-extern-c-compat -Wno-unused-value) target_compile_options(udfs PRIVATE -Wno-tautological-constant-out-of-range-compare) target_compile_options(udfs PRIVATE -Wno-tautological-unsigned-zero-compare -Wno-self-assign) target_compile_options(udfs PRIVATE -Wno-sometimes-uninitialized -Wno-parentheses-equality) diff --git a/drivers/filesystems/udfs/Include/Sys_spec_lib.c b/drivers/filesystems/udfs/Include/Sys_spec_lib.c index 02258caf5148c..b740b6a8a9e73 100644 --- a/drivers/filesystems/udfs/Include/Sys_spec_lib.c +++ b/drivers/filesystems/udfs/Include/Sys_spec_lib.c @@ -5,7 +5,7 @@ //////////////////////////////////////////////////////////////////// /************************************************************************* * -* File: Sys_Spec.c +* File: Sys_Spec.cpp * * Module: UDF File System Driver * (both User and Kernel mode execution) diff --git a/drivers/filesystems/udfs/Include/phys_lib.c b/drivers/filesystems/udfs/Include/phys_lib.c index d85a499e219a8..944d35bf7e2c8 100644 --- a/drivers/filesystems/udfs/Include/phys_lib.c +++ b/drivers/filesystems/udfs/Include/phys_lib.c @@ -4,7 +4,7 @@ // This file was released under the GPLv2 on June 2015. //////////////////////////////////////////////////////////////////// /* - Module Name: Phys_lib.c + Module Name: Phys_lib.cpp Execution: Kernel mode only diff --git a/drivers/filesystems/udfs/Include/string_lib.c b/drivers/filesystems/udfs/Include/string_lib.c index 37bd1d894879a..1750feb27ff16 100644 --- a/drivers/filesystems/udfs/Include/string_lib.c +++ b/drivers/filesystems/udfs/Include/string_lib.c @@ -4,6 +4,7 @@ // This file was released under the GPLv2 on June 2015. //////////////////////////////////////////////////////////////////// +extern "C" ULONG MyRtlCompareMemory( PVOID s1, @@ -25,6 +26,7 @@ MyRtlCompareMemory( #ifndef NT_NATIVE_MODE +extern "C" ULONG RtlCompareUnicodeString( PUNICODE_STRING s1, @@ -39,6 +41,7 @@ RtlCompareUnicodeString( return i; } +extern "C" NTSTATUS RtlUpcaseUnicodeString( PUNICODE_STRING dst, @@ -54,6 +57,7 @@ RtlUpcaseUnicodeString( return STATUS_SUCCESS; } +extern "C" NTSTATUS RtlAppendUnicodeToString( IN PUNICODE_STRING Str1, diff --git a/drivers/filesystems/udfs/cleanup.c b/drivers/filesystems/udfs/cleanup.c index 1d6c600d47bf9..b85c16a7d32c7 100644 --- a/drivers/filesystems/udfs/cleanup.c +++ b/drivers/filesystems/udfs/cleanup.c @@ -5,7 +5,7 @@ //////////////////////////////////////////////////////////////////// /* - Module name: Cleanup.c + Module name: Cleanup.cpp Abstract: @@ -50,6 +50,7 @@ UDFCommonCleanup( { IO_STATUS_BLOCK IoStatus; NTSTATUS RC = STATUS_SUCCESS; + NTSTATUS RC2; PFILE_OBJECT FileObject = NULL; PFCB Fcb = NULL; PCCB Ccb = NULL; @@ -77,13 +78,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) { @@ -173,8 +174,15 @@ UDFCommonCleanup( AcquiredVcb = TRUE; } - // Acquire current object only - // Parent is acquired later only for delete operations (Child → Parent order) + // 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 UDF_CHECK_PAGING_IO_RESOURCE(Fcb); UDFAcquireResourceExclusive(&Fcb->FcbNonpaged->FcbResource, TRUE); AcquiredFCB = TRUE; @@ -234,12 +242,40 @@ UDFCommonCleanup( !UDFIsSDirDeleted(Fcb->FileInfo->Dloc->SDirInfo)) { RC = UDFMarkStreamsForDeletion(IrpContext, Vcb, Fcb, TRUE); // Delete } - // Acquire parent for delete operation (after current - child first order) + // 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; if (Fcb->FileInfo->ParentFile) { UDF_CHECK_PAGING_IO_RESOURCE(Fcb->ParentFcb); UDFAcquireResourceExclusive(&(Fcb->ParentFcb->FcbNonpaged->FcbResource), TRUE); - AcquiredParentFCB = TRUE; + } else { + UDFAcquireResourceShared(&Vcb->VcbResource, 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 @@ -256,6 +292,14 @@ 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 ? @@ -416,7 +460,7 @@ UDFCommonCleanup( /* MmPrint((" CcPurgeCacheSection()\n")); CcPurgeCacheSection(&Fcb->SectionObject, NULL, 0, FALSE);*/ } - // we needn't Flush here. It will be done in UDFCloseFile__ + // we needn't Flush here. It will be done in UDFCloseFileInfoChain() } // Update FileTimes & Attrs @@ -512,22 +556,23 @@ UDFCommonCleanup( } // release resources now. + // they'll be acquired in UDFCloseFileInfoChain() UDF_CHECK_PAGING_IO_RESOURCE(Fcb); UDFReleaseResource(&Fcb->FcbNonpaged->FcbResource); AcquiredFCB = FALSE; - if (AcquiredParentFCB && Fcb->FileInfo->ParentFile) { + if (Fcb->FileInfo->ParentFile) { UDF_CHECK_PAGING_IO_RESOURCE(Fcb->FileInfo->ParentFile->Fcb); UDFReleaseResource(&Fcb->FileInfo->ParentFile->Fcb->FcbNonpaged->FcbResource); - AcquiredParentFCB = FALSE; + } else { + UDFReleaseResource(&Vcb->VcbResource); } - - // Close the target file's FileInfo - this decrements FileInfo->RefCount - // Parent FileInfo references are now handled by LCB mechanism in UDFTeardownStructures + AcquiredParentFCB = FALSE; + // close the chain ASSERT(AcquiredVcb); - if (NextFileInfo) { - UDFCloseFile__(IrpContext, Vcb, NextFileInfo); - } + RC2 = UDFCloseFileInfoChain(IrpContext, Vcb, NextFileInfo, Ccb->TreeLength, TRUE); + if (NT_SUCCESS(RC)) + RC = RC2; Ccb->Flags |= UDF_CCB_CLEANED; @@ -549,9 +594,13 @@ try_exit: NOTHING; UDFReleaseResource(&Fcb->FcbNonpaged->FcbResource); } - if (AcquiredParentFCB && Fcb->FileInfo->ParentFile) { - UDF_CHECK_PAGING_IO_RESOURCE(Fcb->FileInfo->ParentFile->Fcb); - UDFReleaseResource(&Fcb->FileInfo->ParentFile->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 (AcquiredVcb) { @@ -573,6 +622,85 @@ 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.c b/drivers/filesystems/udfs/close.c index b62034772d992..367523a1f40d1 100644 --- a/drivers/filesystems/udfs/close.c +++ b/drivers/filesystems/udfs/close.c @@ -5,7 +5,7 @@ //////////////////////////////////////////////////////////////////// /************************************************************************* * -* File: Close.c +* File: Close.cpp * * Module: UDF File System Driver (Kernel mode execution only) * @@ -78,6 +78,7 @@ UDFCommonClose( PFCB Fcb = NULL; PCCB Ccb = NULL; PVCB Vcb = NULL; + ULONG i = 0; TYPE_OF_OPEN TypeOfOpen; ULONG UserReference = 0; BOOLEAN PotentialVcbTeardown = FALSE; @@ -120,6 +121,10 @@ UDFCommonClose( if (Irp) { UserReference = 1; + IrpContext->TreeLength = + i = Ccb->TreeLength; + // remember the number of incomplete Close requests + InterlockedIncrement((PLONG)&(Fcb->CcbCount)); // we can release CCB in any case UDFDeleteCcb(Ccb); FileObject->FsContext2 = NULL; @@ -132,6 +137,7 @@ UDFCommonClose( if ((Fcb->FcbState & UDF_FCB_DELAY_CLOSE) && (Vcb->VcbCondition == VcbMounted) && (Fcb->FcbState & UDF_FCB_DELETED) == 0 && + (Fcb->FcbState & UDF_FCB_POSTED_RENAME) == 0 && //(Fcb->FcbCondition == FcbGood) && (Fcb->FcbReference == 1) && ((TypeOfOpen == UserFileOpen) || @@ -146,34 +152,36 @@ UDFCommonClose( } else { - // Decrement reference counts - // These were incremented in UDFCompleteFcbOpen. + // 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); - UDFLockVcb(IrpContext, Vcb); + InterlockedDecrement((PLONG)&Vcb->VcbReference); - Fcb->FcbReference--; - Fcb->FcbUserReference--; - Vcb->VcbReference--; - Vcb->VcbUserReference--; - - if (Fcb == Vcb->VolumeDasdFcb) { + if (!i || (Fcb == Fcb->Vcb->VolumeDasdFcb)) { AdPrint(("UDF: Closing volume\n")); AdPrint(("UDF: ReferenceCount: %x\n",Fcb->FcbReference)); - ASSERT(Fcb == Fcb->Vcb->VolumeDasdFcb); - UDFUnlockVcb(IrpContext, Vcb); - if (Vcb->VcbCleanup > 0) { + ASSERT(Fcb == Fcb->Vcb->VolumeDasdFcb); + InterlockedDecrement((PLONG)&Fcb->FcbReference); + ASSERT(Fcb); + try_return(RC = STATUS_SUCCESS); } + ASSERT(Fcb == Fcb->Vcb->VolumeDasdFcb); + InterlockedDecrement((PLONG)&Fcb->FcbReference); + ASSERT(Fcb); + if ((Vcb->VcbCleanup == 0) && (Vcb->VcbCondition != VcbMounted)) { // Possible dismount. Acquire CdData to synchronise with the remount path // before looking at the vcb condition again. - + UDFAcquireUdfData(IrpContext); if ((Vcb->VcbCleanup == 0) && @@ -200,20 +208,8 @@ UDFCommonClose( try_return(RC = STATUS_SUCCESS); } - // Release VcbMutex BEFORE TeardownStructures - UDFUnlockVcb(IrpContext, Vcb); - // try to clean up as long chain as it is possible - // 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); - } - } + UDFTeardownStructures(IrpContext, Fcb, i, NULL); } try_exit: NOTHING; @@ -236,6 +232,224 @@ 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, 0); + 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, 0); + } 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 @@ -406,6 +620,7 @@ Return Value: // Copy RealDevice for workque algorithms. + IrpContext->TreeLength = IrpContextLite->TreeLength; IrpContext->RealDevice = IrpContextLite->RealDevice; // The Vcb is found in the Fcb. @@ -507,9 +722,8 @@ 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, FALSE, &RemovedFcb); + UDFTeardownStructures(IrpContext, Fcb, IrpContext->TreeLength, &RemovedFcb); if (!RemovedFcb) { @@ -776,6 +990,7 @@ 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/devcntrl.c b/drivers/filesystems/udfs/devcntrl.c index 54971f04e1149..dd0bb0a651baf 100644 --- a/drivers/filesystems/udfs/devcntrl.c +++ b/drivers/filesystems/udfs/devcntrl.c @@ -5,7 +5,7 @@ //////////////////////////////////////////////////////////////////// /************************************************************************* * -* File: Devcntrl.c +* File: Devcntrl.cpp * * Module: UDF File System Driver (Kernel mode execution only) * diff --git a/drivers/filesystems/udfs/dircntrl.c b/drivers/filesystems/udfs/dircntrl.c index 66af398b8acd0..854597afbdb6b 100644 --- a/drivers/filesystems/udfs/dircntrl.c +++ b/drivers/filesystems/udfs/dircntrl.c @@ -5,7 +5,7 @@ //////////////////////////////////////////////////////////////////// /************************************************************************* * -* File: DirCntrl.c +* File: DirCntrl.cpp * * Module: UDF File System Driver (Kernel mode execution only) * @@ -413,21 +413,16 @@ 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 we already found an entry then just exit. - - if (CurrentOffset != 0) { + // 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) { try_return(RC = STATUS_SUCCESS); } - - // Reduce the FileNameBytes to just fit in the buffer. - - FileNameBytes = BytesRemainingInBuffer - BaseLength; + // strange policy... 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/env_spec.c b/drivers/filesystems/udfs/env_spec.c index bc5dba5108d52..52e1cb5382576 100644 --- a/drivers/filesystems/udfs/env_spec.c +++ b/drivers/filesystems/udfs/env_spec.c @@ -5,7 +5,7 @@ //////////////////////////////////////////////////////////////////// /************************************************************************* * -* File: Env_Spec.c +* File: Env_Spec.cpp * * Module: UDF File System Driver (Kernel mode execution only) * diff --git a/drivers/filesystems/udfs/fastio.c b/drivers/filesystems/udfs/fastio.c index 024810d6fd484..9bdbac17b3f40 100644 --- a/drivers/filesystems/udfs/fastio.c +++ b/drivers/filesystems/udfs/fastio.c @@ -5,7 +5,7 @@ //////////////////////////////////////////////////////////////////// /************************************************************************* * -* File: Fastio.c +* File: Fastio.cpp * * Module: UDF File System Driver (Kernel mode execution only) * diff --git a/drivers/filesystems/udfs/fileinfo.c b/drivers/filesystems/udfs/fileinfo.c index 0b46fe7560ae7..d527a8902ac7c 100644 --- a/drivers/filesystems/udfs/fileinfo.c +++ b/drivers/filesystems/udfs/fileinfo.c @@ -5,7 +5,7 @@ //////////////////////////////////////////////////////////////////// /************************************************************************* * -* File: Fileinfo.c +* File: Fileinfo.cpp * * Module: UDF File System Driver (Kernel mode execution only) * @@ -229,6 +229,8 @@ UDFCommonSetInfo( PCCB Ccb = NULL; PVCB Vcb = NULL; BOOLEAN MainResourceAcquired = FALSE; + BOOLEAN ParentResourceAcquired = FALSE; + BOOLEAN PagingIoResourceAcquired = FALSE; PVOID Buffer = NULL; FILE_INFORMATION_CLASS FunctionalityRequested; BOOLEAN CanWait = FALSE; @@ -300,21 +302,73 @@ UDFCommonSetInfo( VcbAcquired = TRUE; } - // - // Acquire FcbResource exclusive for all operations except - // rename/link (those acquire resources in their own functions). - // - if ((FunctionalityRequested != FileRenameInformation) && + // Rename, and link operations require creation of a directory + // entry and possibly deletion of another directory entry. + + // Unless this is an operation on a page file, we should go ahead and + // acquire the FCB exclusively at this time. Note that we will pretty + // much block out anything being done to the FCB from this point on. + if ((FunctionalityRequested != FilePositionInformation) && + (FunctionalityRequested != FileRenameInformation) && (FunctionalityRequested != FileLinkInformation)) { + // Acquire the Parent & Main Resources exclusive. + if (Fcb->FileInfo->ParentFile) { + UDF_CHECK_PAGING_IO_RESOURCE(Fcb->ParentFcb); + if (!UDFAcquireResourceExclusive(&Fcb->ParentFcb->FcbNonpaged->FcbResource, CanWait)) { + PostRequest = TRUE; + try_return(Status = STATUS_PENDING); + } + ParentResourceAcquired = TRUE; + } + + if (!UDFAcquireResourceExclusive(&Fcb->FcbNonpaged->FcbResource, CanWait)) { + PostRequest = TRUE; + try_return(Status = STATUS_PENDING); + } + MainResourceAcquired = TRUE; - UDFAcquireFcbExclusive(IrpContext, Fcb, FALSE); + if (!UDFAcquireResourceExclusive(&Fcb->FcbNonpaged->FcbPagingIoResource, CanWait)) { + PostRequest = TRUE; + try_return(Status = STATUS_PENDING); + } + PagingIoResourceAcquired = TRUE; + } else + // The only operations that could conceivably proceed from this point + // on are paging-IO read/write operations. For delete, link (rename), + // set allocation size, and set EOF, should also acquire the paging-IO + // resource, thereby synchronizing with paging-IO requests. + if ((FunctionalityRequested == FileDispositionInformation) || + (FunctionalityRequested == FileAllocationInformation) || + (FunctionalityRequested == FileEndOfFileInformation)) { + + // Acquire the MainResource shared. + UDF_CHECK_PAGING_IO_RESOURCE(Fcb); + if (!UDFAcquireResourceShared(&Fcb->FcbNonpaged->FcbResource, CanWait)) { + PostRequest = TRUE; + try_return(Status = STATUS_PENDING); + } + MainResourceAcquired = TRUE; + // Acquire the PagingResource exclusive. + if (!UDFAcquireResourceExclusive(&Fcb->FcbNonpaged->FcbPagingIoResource, CanWait)) { + PostRequest = TRUE; + try_return(Status = STATUS_PENDING); + } + PagingIoResourceAcquired = TRUE; + } else if ((FunctionalityRequested != FileRenameInformation) && + (FunctionalityRequested != FileLinkInformation)) { + // Acquire the MainResource shared. + UDF_CHECK_PAGING_IO_RESOURCE(Fcb); + if (!UDFAcquireResourceShared(&Fcb->FcbNonpaged->FcbResource, CanWait)) { + PostRequest = TRUE; + try_return(Status = STATUS_PENDING); + } MainResourceAcquired = TRUE; } // Do whatever the caller asked us to do switch (FunctionalityRequested) { case FileBasicInformation: - Status = UDFSetBasicInformation(IrpContext, Fcb, Ccb, FileObject, (PFILE_BASIC_INFORMATION)Buffer); + Status = UDFSetBasicInformation(Fcb, Ccb, FileObject, (PFILE_BASIC_INFORMATION)Buffer); break; case FilePositionInformation: { // Check if no intermediate buffering has been specified. @@ -372,11 +426,22 @@ try_exit: NOTHING; } _SEH2_FINALLY { + if (PagingIoResourceAcquired) { + UDFReleaseResource(&Fcb->FcbNonpaged->FcbPagingIoResource); + PagingIoResourceAcquired = FALSE; + } + if (MainResourceAcquired) { - UDFReleaseFcb(IrpContext, Fcb); + UDFReleaseResource(&Fcb->FcbNonpaged->FcbResource); MainResourceAcquired = FALSE; } + if (ParentResourceAcquired) { + UDF_CHECK_PAGING_IO_RESOURCE(Fcb->ParentFcb); + UDFReleaseResource(&(Fcb->ParentFcb->FcbNonpaged->FcbResource)); + ParentResourceAcquired = FALSE; + } + if (VcbAcquired) { UDFReleaseVcb(IrpContext, Vcb); @@ -397,12 +462,14 @@ try_exit: NOTHING; if (!_SEH2_AbnormalTermination()) { +#ifdef UDF_DELAYED_CLOSE if (NT_SUCCESS(Status)) { if (FunctionalityRequested == FileDispositionInformation) { UDFFspClose(Vcb); } } +#endif //UDF_DELAYED_CLOSE UDFCompleteRequest(IrpContext, Irp, Status); } @@ -813,7 +880,7 @@ UDFGetFileStreamInformation( PUDF_FILE_INFO FileInfo; PUDF_FILE_INFO SDirInfo; PVCB Vcb; - + BOOLEAN FcbAcquired = FALSE; uint_di i; ULONG CurrentSize; PDIR_INDEX_HDR hSDirIndex; @@ -831,6 +898,9 @@ UDFGetFileStreamInformation( _SEH2_TRY { + UDFAcquireResourceExclusive(&(Fcb->Vcb->FileIdResource), TRUE); + FcbAcquired = TRUE; + FileInfo = Fcb->FileInfo; if (!FileInfo) { AdPrint(("!!!!!!!! Bu-u-u-u-u-g !!!!!!!!!!!\n")); @@ -919,6 +989,8 @@ UDFGetFileStreamInformation( try_exit: NOTHING; } _SEH2_FINALLY { + if (FcbAcquired) + UDFReleaseResource(&(Fcb->Vcb->FileIdResource)); if (NTFileInfo) MyFreePool__(NTFileInfo); } _SEH2_END; @@ -931,7 +1003,6 @@ try_exit: NOTHING; */ NTSTATUS UDFSetBasicInformation( - IN PIRP_CONTEXT IrpContext, IN PFCB Fcb, IN PCCB Ccb, IN PFILE_OBJECT FileObject, @@ -1070,11 +1141,10 @@ UDFSetBasicInformation( if (NotifyFilter) { - UDFNotifyReportChange(IrpContext, Fcb->Vcb, + UDFNotifyFullReportChange(Fcb->Vcb, Fcb, NotifyFilter, - FILE_ACTION_MODIFIED, - Ccb->Lcb, FileObject); + FILE_ACTION_MODIFIED); UDFSetFileSizeInDirNdx(Fcb->Vcb, Fcb->FileInfo, NULL); Fcb->FileInfo->Dloc->FE_Flags |= UDF_FE_FLAG_FE_MODIFIED; @@ -1124,7 +1194,7 @@ UDFMarkStreamsForDeletion( if (SDirInfo->Fcb) { UDF_CHECK_PAGING_IO_RESOURCE(SDirInfo->Fcb); - UDFAcquireFcbExclusive(IrpContext, SDirInfo->Fcb, TRUE); + UDFAcquireResourceExclusive(&SDirInfo->Fcb->FcbNonpaged->FcbResource, TRUE); SDirAcq = TRUE; } @@ -1172,7 +1242,7 @@ UDFMarkStreamsForDeletion( if (FileInfo->Fcb) { UDF_CHECK_PAGING_IO_RESOURCE(FileInfo->Fcb); - UDFAcquireFcbExclusive(IrpContext, FileInfo->Fcb, TRUE); + UDFAcquireResourceExclusive(&FileInfo->Fcb->FcbNonpaged->FcbResource, TRUE); StrAcq = TRUE; #ifndef UDF_ALLOW_LINKS_TO_STREAMS @@ -1213,7 +1283,8 @@ UDFMarkStreamsForDeletion( MyFreePool__(FileInfo); } if (StrAcq) { - UDFReleaseFcb(IrpContext, FileInfo->Fcb); + UDF_CHECK_PAGING_IO_RESOURCE(FileInfo->Fcb); + UDFReleaseResource(&FileInfo->Fcb->FcbNonpaged->FcbResource); StrAcq = FALSE; } } @@ -1267,14 +1338,16 @@ try_exit: NOTHING; MyFreePool__(FileInfo); } if (StrAcq) { - UDFReleaseFcb(IrpContext, FileInfo->Fcb); + UDF_CHECK_PAGING_IO_RESOURCE(FileInfo->Fcb); + UDFReleaseResource(&FileInfo->Fcb->FcbNonpaged->FcbResource); } SDirInfo = NULL; } if (SDirInfo) { UDFCloseFile__(IrpContext, Vcb, SDirInfo); if (SDirAcq) { - UDFReleaseFcb(IrpContext, SDirInfo->Fcb); + UDF_CHECK_PAGING_IO_RESOURCE(SDirInfo->Fcb); + UDFReleaseResource(&SDirInfo->Fcb->FcbNonpaged->FcbResource); } if (UDFCleanUpFile__(Vcb, SDirInfo)) { MyFreePool__(SDirInfo); @@ -1548,15 +1621,13 @@ UDFSetAllocationInfo( // Inform any pending IRPs (notify change directory). if (UDFIsAStream(Fcb->FileInfo)) { - UDFNotifyReportChange(IrpContext, Vcb, Fcb, + UDFNotifyFullReportChange(Vcb, Fcb, FILE_NOTIFY_CHANGE_STREAM_SIZE, - FILE_ACTION_MODIFIED_STREAM, - Ccb->Lcb, FileObject); + FILE_ACTION_MODIFIED_STREAM); } else { - UDFNotifyReportChange(IrpContext, Vcb, Fcb, + UDFNotifyFullReportChange(Vcb, Fcb, FILE_NOTIFY_CHANGE_SIZE, - FILE_ACTION_MODIFIED, - Ccb->Lcb, FileObject); + FILE_ACTION_MODIFIED); } } @@ -1749,7 +1820,7 @@ UDFSetEndOfFileInfo( // NT expects AllocationSize to be decreased on Close only Fcb->Header.AllocationSize.QuadPart = PtrBuffer->EndOfFile.QuadPart; - +// UDFSysGetAllocSize(Vcb, UDFGetFileSize(Fcb->FileInfo)); UDFSetFileSizeInDirNdx(Vcb, Fcb->FileInfo, &(PtrBuffer->EndOfFile.QuadPart)); } @@ -1793,15 +1864,13 @@ UDFSetEndOfFileInfo( // Inform any pending IRPs (notify change directory). if (UDFIsAStream(Fcb->FileInfo)) { - UDFNotifyReportChange( IrpContext, Vcb, Fcb, + UDFNotifyFullReportChange( Vcb, Fcb, FILE_NOTIFY_CHANGE_STREAM_SIZE, - FILE_ACTION_MODIFIED_STREAM, - Ccb->Lcb, FileObject); + FILE_ACTION_MODIFIED_STREAM); } else { - UDFNotifyReportChange( IrpContext, Vcb, Fcb, + UDFNotifyFullReportChange( Vcb, Fcb, FILE_NOTIFY_CHANGE_SIZE, - FILE_ACTION_MODIFIED, - Ccb->Lcb, FileObject); + FILE_ACTION_MODIFIED); } } @@ -1823,7 +1892,6 @@ try_exit: NOTHING; NTSTATUS UDFPrepareForRenameMoveLink( - IN PIRP_CONTEXT IrpContext, PVCB Vcb, PBOOLEAN SingleDir, PBOOLEAN AcquiredDir1, @@ -1840,7 +1908,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 - // cleanup operations or UDFTeardownStructures() + // CleanUpFcbChain() or UDFCloseFileInfoChain() InterlockedIncrement((PLONG)&Vcb->VcbReference); @@ -1852,74 +1920,17 @@ UDFPrepareForRenameMoveLink( } else { InterlockedDecrement((PLONG)&Vcb->VcbReference); - // Child-first lock ordering - // File1 (child) first, Dir1 (parent) second - UDF_CHECK_PAGING_IO_RESOURCE(File1->Fcb); - UDFAcquireFcbExclusive(IrpContext, File1->Fcb, TRUE); - (*AcquiredFcb1) = TRUE; - UDF_CHECK_PAGING_IO_RESOURCE(Dir1->Fcb); - UDFAcquireFcbExclusive(IrpContext, Dir1->Fcb, TRUE); + UDFAcquireResourceExclusive(&Dir1->Fcb->FcbNonpaged->FcbResource, TRUE); (*AcquiredDir1) = TRUE; + + UDF_CHECK_PAGING_IO_RESOURCE(File1->Fcb); + UDFAcquireResourceExclusive(&File1->Fcb->FcbNonpaged->FcbResource, TRUE); + (*AcquiredFcb1) = TRUE; } return STATUS_SUCCESS; } // end UDFPrepareForRenameMoveLink() -/* - Check if a directory subtree has any open handles (FcbCleanup != 0). - Iterative depth-first walk via ChildLcbQueue — no recursion, kernel-safe. - Returns TRUE if subtree is clean (no open handles), FALSE otherwise. -*/ -BOOLEAN -UDFCheckDirOpenHandles( - IN PFCB DirectoryFcb - ) -{ - PFCB CheckFcb = DirectoryFcb; - PLIST_ENTRY CheckLink = CheckFcb->ChildLcbQueue.Flink; - - while (CheckFcb != NULL) { - - // Process all children at current level - while (CheckLink != &CheckFcb->ChildLcbQueue) { - PLCB ChildLcb = CONTAINING_RECORD(CheckLink, LCB, ParentFcbLinks); - PFCB ChildFcb = ChildLcb->ChildFcb; - CheckLink = CheckLink->Flink; - - if (!ChildFcb) continue; - - if (ChildFcb->FcbCleanup != 0) { - return FALSE; - } - - // If child is a directory with children, descend into it - if ((ChildFcb->FcbState & UDF_FCB_DIRECTORY) && - !IsListEmpty(&ChildFcb->ChildLcbQueue)) { - CheckFcb = ChildFcb; - CheckLink = CheckFcb->ChildLcbQueue.Flink; - } - } - - // Back to root — done - if (CheckFcb == DirectoryFcb) break; - - // Ascend: find our LCB in parent, advance to next sibling - PLIST_ENTRY ParentLink; - for (ParentLink = CheckFcb->ParentLcbQueue.Flink; - ParentLink != &CheckFcb->ParentLcbQueue; - ParentLink = ParentLink->Flink) { - PLCB ParentLcb = CONTAINING_RECORD(ParentLink, LCB, ChildFcbLinks); - if (ParentLcb->ParentFcb) { - CheckFcb = ParentLcb->ParentFcb; - CheckLink = ParentLcb->ParentFcbLinks.Flink; - break; - } - } - } - - return TRUE; -} - /* Rename or move file */ @@ -1945,30 +1956,27 @@ UDFSetRenameInfo( BOOLEAN IgnoreCase; BOOLEAN ParentFcbAcquired = FALSE; BOOLEAN TargetParentFcbAcquired = FALSE; - BOOLEAN StaleFcbAcquired = FALSE; - PFCB StaleFcb = NULL; - PLCB StaleLcb = NULL; - BOOLEAN NeedRemovePrefix = FALSE; BOOLEAN SingleDir = TRUE; + BOOLEAN UseClose; 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; LocalPath.Buffer = NULL; - // Make sure we can wait for this request. - - if (!FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)) { - - UDFRaiseStatus(IrpContext, STATUS_CANT_WAIT); - } - _SEH2_TRY { - // do we try to rename Volume ? if (ParentFcb == NULL) { @@ -1997,8 +2005,6 @@ UDFSetRenameInfo( if (!TargetFileObject) { TargetDirInfo = FileInfo->ParentFile; - // For streams or same-dir rename, target FCB is the parent - TargetFcb = TargetDirInfo->Fcb; } else { @@ -2011,24 +2017,7 @@ UDFSetRenameInfo( try_return (RC = STATUS_INVALID_PARAMETER); } - // Check if TargetFcb is a directory or a file - // TargetFileObject should be a directory. - // But if it points to a file (e.g., existing file to be replaced), - // we need to use its parent directory for correct SingleDir calculation - - if (UDFIsADirectory(TargetFcb->FileInfo)) { - - TargetDirInfo = TargetFcb->FileInfo; - - } else { - - // TargetFileObject points to a file, use its parent directory - TargetDirInfo = TargetFcb->FileInfo->ParentFile; - - if (!TargetDirInfo) { - try_return (RC = STATUS_INVALID_PARAMETER); - } - } + TargetDirInfo = TargetFcb->FileInfo; } // invalid destination ? @@ -2042,290 +2031,289 @@ UDFSetRenameInfo( } } - // Parse NewName before acquiring locks to enable early-out optimizations - if (!TargetFileObject) { - // Make sure the name is of legal length. - if (PtrBuffer->FileNameLength > UDF_NAME_LEN*sizeof(WCHAR)) { - try_return(RC = STATUS_OBJECT_NAME_INVALID); - } - NewName.Length = NewName.MaximumLength = (USHORT)(PtrBuffer->FileNameLength); - NewName.Buffer = (PWCHAR)&(PtrBuffer->FileName); - } else { - // TargetFileObject->FileName is set up by UDFCommonCreate for - // SL_OPEN_TARGET_DIRECTORY: - // Length = parent directory path (trimmed to last '\') - // MaximumLength = full original path (parent + '\' + filename) - // Extract the filename component starting after Length. - USHORT FileNameStart = TargetFileObject->FileName.Length; - - if (FileNameStart < TargetFileObject->FileName.MaximumLength && - TargetFileObject->FileName.Buffer[FileNameStart / sizeof(WCHAR)] == L'\\') { - FileNameStart += sizeof(WCHAR); - } - - NewName.Length = TargetFileObject->FileName.MaximumLength - FileNameStart; - NewName.MaximumLength = NewName.Length; - NewName.Buffer = (PWCHAR)((PCHAR)TargetFileObject->FileName.Buffer + FileNameStart); - } - - IgnoreCase = FlagOn(Ccb->Flags, CCB_FLAG_IGNORE_CASE); - SingleDir = (TargetDirInfo->Fcb == ParentFcb); - // Self-rename check: if same directory and same name → no-op - if (SingleDir && !ReplaceIfExists && Ccb->Lcb) { - if (FsRtlAreNamesEqual(&NewName, &Ccb->Lcb->FileName, IgnoreCase, NULL)) { - try_return(RC = STATUS_SUCCESS); - } - } - - // - // Always acquire source parent directory — needed for splay tree - // modifications in UDFRenameMovePrefix and UDFRemovePrefix. - // if (SingleDir) { - UDFAcquireFcbExclusive(IrpContext, ParentFcb, FALSE); - ParentFcbAcquired = TRUE; + //TODO: FsRtlAreNamesEqual - } else { + // Check ReplaceIfExists for same directory + if (ReplaceIfExists) { - // Cross-directory rename: acquire both parents. - // Use address ordering to prevent ABBA deadlock. - if ((ULONG_PTR)ParentFcb < (ULONG_PTR)TargetDirInfo->Fcb) { - UDFAcquireFcbExclusive(IrpContext, ParentFcb, FALSE); - ParentFcbAcquired = TRUE; - UDFAcquireFcbExclusive(IrpContext, TargetDirInfo->Fcb, FALSE); - TargetParentFcbAcquired = TRUE; - } else if (ParentFcb != TargetDirInfo->Fcb) { - UDFAcquireFcbExclusive(IrpContext, TargetDirInfo->Fcb, FALSE); - TargetParentFcbAcquired = TRUE; - UDFAcquireFcbExclusive(IrpContext, ParentFcb, FALSE); - ParentFcbAcquired = TRUE; - } else { - // Same directory (shouldn't happen for !SingleDir, but handle gracefully) UDFAcquireFcbExclusive(IrpContext, ParentFcb, FALSE); ParentFcbAcquired = TRUE; } - } - // check if the source file is in use - if (Fcb->FcbCleanup > 1) { + } else { - try_return (RC = STATUS_ACCESS_DENIED); + UDFAcquireFcbExclusive(IrpContext, TargetDirInfo->Fcb, FALSE); + TargetParentFcbAcquired = TRUE; } + // check if the source file is in use + if (Fcb->FcbCleanup > 1) + try_return (RC = STATUS_ACCESS_DENIED); ASSERT(Fcb->FcbCleanup); ASSERT(!Fcb->IrpContextLite); - if (Fcb->IrpContextLite) { try_return (RC = STATUS_ACCESS_DENIED); } - - // For directories: check that no descendant has open handles. - if ((Fcb->FcbState & UDF_FCB_DIRECTORY) && - !UDFCheckDirOpenHandles(Fcb)) { - try_return (RC = STATUS_ACCESS_DENIED); + // Check if we have parallel/pending Close threads + if (Fcb->CcbCount && !SingleDir) { + // if this is the 1st attempt, we'll try to + // synchronize with Close requests + // otherwise fail request + RC = STATUS_ACCESS_DENIED; +post_rename: + if (Fcb->FcbState & UDF_FCB_POSTED_RENAME) { + Fcb->FcbState &= ~UDF_FCB_POSTED_RENAME; + try_return (RC); + } + Fcb->FcbState |= UDF_FCB_POSTED_RENAME; + try_return (RC = STATUS_PENDING); } - // Check if renaming to stream name - only allowed for streams - if (!TargetFileObject && NewName.Length >= sizeof(WCHAR) && NewName.Buffer[0] == L':') { - - if (!UDFIsAStream(FileInfo)) { - + if (!TargetFileObject) { + // Make sure the name is of legal length. + if (PtrBuffer->FileNameLength > UDF_NAME_LEN*sizeof(WCHAR)) { try_return(RC = STATUS_OBJECT_NAME_INVALID); } + NewName.Length = NewName.MaximumLength = (USHORT)(PtrBuffer->FileNameLength); + NewName.Buffer = (PWCHAR)&(PtrBuffer->FileName); + } else { + // This name is by definition legal. + NewName = *((PUNICODE_STRING)&TargetFileObject->FileName); } - // UDFDoesOSAllowFileToBeMoved__ (= UDFDoesOSAllowFileToBeUnlinked__) - // checks DirNdx->FileInfo != NULL for each child — blocks if any - // child has a cached FileInfo structure, even with FcbCleanup=0 - // (no user handles). This is too strict for rename/move where file - // data stays intact. The subtree is already validated above via - // UDFCheckDirOpenHandles which checks FcbCleanup (user handles). - { - - // Note: With LCB model, FcbReference may not always be >= RefCount - // for directories opened internally during path traversal - - // Pre-validate target for ReplaceIfExists: look up the target name - // in the directory index, then search for its LCB by FCB pointer - // (not by name). This correctly handles case-insensitive matches, - // short name aliases, and avoids string comparison overhead. - if (ReplaceIfExists) { - - PFCB TargetParentFcb = TargetDirInfo->Fcb; - - if (TargetParentFcb) { - - // Look up target name in directory index - DIR_ENUM_CONTEXT TargetDirContext; - NTSTATUS FindStatus = UDFFindDirEntry(Vcb, TargetDirInfo, - &NewName, IgnoreCase, - TRUE, &TargetDirContext); - - if (NT_SUCCESS(FindStatus) && TargetDirContext.DirNdx) { - - PDIR_INDEX_ITEM FoundDirNdx = TargetDirContext.DirNdx; - - // Cannot replace a directory - if (FoundDirNdx->FileCharacteristics & FILE_DIRECTORY) { - - try_return(RC = STATUS_OBJECT_NAME_COLLISION); - } - - // Skip stale LCB logic for self-rename (e.g. case change) - BOOLEAN IsSelfRename = (SingleDir && - FoundDirNdx->FileInfo == FileInfo); - - if (!IsSelfRename) { - - // If target was previously opened, find its LCB - // by matching ChildFcb pointer - if (FoundDirNdx->FileInfo && - FoundDirNdx->FileInfo->Fcb) { - - PFCB TargetFileFcb = FoundDirNdx->FileInfo->Fcb; - - PLIST_ENTRY Link; - for (Link = TargetParentFcb->ChildLcbQueue.Flink; - Link != &TargetParentFcb->ChildLcbQueue; - Link = Link->Flink) { - PLCB TestLcb = CONTAINING_RECORD(Link, LCB, ParentFcbLinks); - if (TestLcb != Ccb->Lcb && - !(TestLcb->Flags & UDF_LCB_FLAG_LINK_DELETED) && - TestLcb->ChildFcb == TargetFileFcb) { - StaleLcb = TestLcb; - break; - } - } - } - // If FileInfo is NULL (never opened), no FCB/LCB exists. - // UDFRenameMoveFile__ will handle the on-disk deletion. - - if (StaleLcb) { - - StaleFcb = StaleLcb->ChildFcb; - - // Acquire target FCB to serialize with cleanup - if (StaleFcb) { - UDF_CHECK_PAGING_IO_RESOURCE(StaleFcb); - UDFAcquireFcbExclusive(IrpContext, StaleFcb, TRUE); - StaleFcbAcquired = TRUE; - } - - // Cannot remove LCB that still has open references. - if (StaleLcb->Reference != 0) { + IgnoreCase = FlagOn(Ccb->Flags, CCB_FLAG_IGNORE_CASE); - try_return(RC = STATUS_ACCESS_DENIED); - } - } - } - } - // If target not found in directory, proceed normally. - // UDFRenameMoveFile__ will create the new entry. + if (UDFIsDirOpened__(FileInfo)) { + // We can't rename file because of unclean references. + // UDF_INFO package can safely do it, but NT side cannot. + // In this case NT requires STATUS_OBJECT_NAME_COLLISION + // rather than STATUS_ACCESS_DENIED + if (NT_SUCCESS(UDFFindFile__(Vcb, IgnoreCase, &NewName, TargetDirInfo))) + try_return(RC = STATUS_OBJECT_NAME_COLLISION); + try_return (RC = STATUS_ACCESS_DENIED); + } else { + // Last check before Moving. + // We can't move across Dir referenced (even internally) file + if (!SingleDir) { + RC = UDFDoesOSAllowFileToBeMoved__(FileInfo); + if (!NT_SUCCESS(RC)) { +// try_return(RC); + goto post_rename; } } - // - // Pre-rename: mark stale LCB as deleted so concurrent - // create lookups won't find it during disk operations. - // Purge cache before modifying directory. - // - if (StaleLcb) { - StaleLcb->Flags |= UDF_LCB_FLAG_LINK_DELETED; - - // Remove from splay trees immediately so the renamed LCB - // can be inserted with the same name without duplicate conflict. - if (StaleLcb->ParentFcb) { - UdfRemoveNameLinks(StaleLcb->ParentFcb, StaleLcb); - } - - // Purge cache for target before disk operations - if (StaleFcb && StaleFcb->FcbNonpaged) { - if (StaleFcb->FcbNonpaged->SegmentObject.DataSectionObject || - StaleFcb->FcbNonpaged->SegmentObject.ImageSectionObject) { - MmPrint((" CcPurgeCacheSection() stale target\n")); - CcPurgeCacheSection(&StaleFcb->FcbNonpaged->SegmentObject, NULL, 0, FALSE); - } - } - } + ASSERT(Fcb->FcbReference >= FileInfo->RefCount); + ASSERT(DirInfo->Fcb->FcbReference >= DirInfo->RefCount); + ASSERT(TargetDirInfo->Fcb->FcbReference >= TargetDirInfo->RefCount); RC = UDFRenameMoveFile__(IrpContext, Vcb, IgnoreCase, &ReplaceIfExists, &NewName, DirInfo, TargetDirInfo, FileInfo); } - if (!NT_SUCCESS(RC)) { - // Rename failed — restore original state if target was not - // actually deleted on disk. - if (StaleLcb && !(StaleFcb && (StaleFcb->FcbState & UDF_FCB_DELETED))) { - ClearFlag(StaleLcb->Flags, UDF_LCB_FLAG_LINK_DELETED); - // Re-insert into splay trees (was removed before rename attempt) - if (StaleLcb->ParentFcb) { - UdfInsertNameLinks(StaleLcb->ParentFcb, StaleLcb); - } - } + if (!NT_SUCCESS(RC)) try_return (RC); - } - - // - // Rename succeeded — set NeedRemovePrefix so the finally - // handler removes the stale LCB from queues. - // - if (StaleLcb) { - NeedRemovePrefix = TRUE; - if (StaleFcb) { - StaleFcb->FcbState |= UDF_FCB_DELETED; - } - } ASSERT(UDFDirIndex(FileInfo->ParentFile->Dloc->DirIndex, FileInfo->Index)->FileInfo == FileInfo); - { - ULONG Filter = UDFIsADirectory(FileInfo) - ? FILE_NOTIFY_CHANGE_DIR_NAME - : FILE_NOTIFY_CHANGE_FILE_NAME; + RC = MyCloneUnicodeString(&LocalPath, (TargetDirInfo->Fcb->FcbState & UDF_FCB_ROOT_DIRECTORY) ? + &UdfData.UnicodeStrRoot : + &TargetDirInfo->Fcb->FCBName->ObjectName); + 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) { + RC = MyAppendUnicodeToString(&LocalPath, L"\\"); + if (!NT_SUCCESS(RC)) try_return (RC); + } + RC = MyAppendUnicodeStringToStringTag(&LocalPath, &NewName, MEM_USREN_TAG); + if (!NT_SUCCESS(RC)) try_return (RC); - // Step 1: Notify OLD location (LCB still points to old parent) - // Use FileObject->FileName — stable path independent of LCB chain - if (SingleDir && !ReplaceIfExists) { - UDFNotifyReportChange(IrpContext, Vcb, Fcb, Filter, FILE_ACTION_RENAMED_OLD_NAME, - Ccb->Lcb, FileObject); + // Set Archive bit + DirNdx = UDFDirIndex(FileInfo->ParentFile->Dloc->DirIndex, FileInfo->Index); + if (Vcb->CompatFlags & UDF_VCB_IC_UPDATE_ARCH_BIT) { + Attr = UDFAttributesToNT(DirNdx, FileInfo->Dloc->FileEntry); + if (!(Attr & FILE_ATTRIBUTE_ARCHIVE)) + UDFAttributesToUDF(DirNdx, FileInfo->Dloc->FileEntry, Attr | FILE_ATTRIBUTE_ARCHIVE); + } + // Update Parent Objects (mark 'em as modified) + if (Vcb->CompatFlags & UDF_VCB_IC_UPDATE_DIR_WRITE) { + if (TargetFileObject) { + TargetFileObject->Flags |= FO_FILE_MODIFIED; + if (!ReplaceIfExists) + TargetFileObject->Flags |= FO_FILE_SIZE_CHANGED; + } + } + // report changes + if (SingleDir && !ReplaceIfExists) { + UDFNotifyFullReportChange( Vcb, FileInfo->Fcb, + UDFIsADirectory(FileInfo) ? FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME, + FILE_ACTION_RENAMED_OLD_NAME); +/* UDFNotifyFullReportChange( Vcb, File2, + UDFIsADirectory(File2) ? FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME, + FILE_ACTION_RENAMED_NEW_NAME );*/ + FsRtlNotifyFullReportChange( Vcb->NotifySync, &(Vcb->NextNotifyIRP), + (PSTRING)&LocalPath, + ((TargetDirInfo->Fcb->FcbState & UDF_FCB_ROOT_DIRECTORY) ? 0 : TargetDirInfo->Fcb->FCBName->ObjectName.Length) + sizeof(WCHAR), + NULL,NULL, + UDFIsADirectory(FileInfo) ? FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME, + FILE_ACTION_RENAMED_NEW_NAME, + NULL); + } else { + UDFNotifyFullReportChange( Vcb, FileInfo->Fcb, + UDFIsADirectory(FileInfo) ? FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME, + FILE_ACTION_REMOVED); + if (ReplaceIfExists) { +/* UDFNotifyFullReportChange( Vcb, File2, + FILE_NOTIFY_CHANGE_ATTRIBUTES | + FILE_NOTIFY_CHANGE_SIZE | + FILE_NOTIFY_CHANGE_LAST_WRITE | + FILE_NOTIFY_CHANGE_LAST_ACCESS | + FILE_NOTIFY_CHANGE_CREATION | + FILE_NOTIFY_CHANGE_EA, + FILE_ACTION_MODIFIED );*/ + FsRtlNotifyFullReportChange( Vcb->NotifySync, &(Vcb->NextNotifyIRP), + (PSTRING)&LocalPath, + ((TargetDirInfo->Fcb->FcbState & UDF_FCB_ROOT_DIRECTORY) ? + 0 : TargetDirInfo->Fcb->FCBName->ObjectName.Length) + sizeof(WCHAR), + NULL,NULL, + FILE_NOTIFY_CHANGE_ATTRIBUTES | + FILE_NOTIFY_CHANGE_SIZE | + FILE_NOTIFY_CHANGE_LAST_WRITE | + FILE_NOTIFY_CHANGE_LAST_ACCESS | + FILE_NOTIFY_CHANGE_CREATION | + FILE_NOTIFY_CHANGE_EA, + FILE_ACTION_MODIFIED, + NULL); } else { - UDFNotifyReportChange(IrpContext, Vcb, Fcb, Filter, FILE_ACTION_REMOVED, - Ccb->Lcb, FileObject); +/* UDFNotifyFullReportChange( Vcb, File2, + UDFIsADirectory(File2) ? FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME, + FILE_ACTION_ADDED );*/ + FsRtlNotifyFullReportChange( Vcb->NotifySync, &(Vcb->NextNotifyIRP), + (PSTRING)&LocalPath, + ((TargetDirInfo->Fcb->FcbState & UDF_FCB_ROOT_DIRECTORY) ? + 0 : TargetDirInfo->Fcb->FCBName->ObjectName.Length) + sizeof(WCHAR), + NULL,NULL, + UDFIsADirectory(FileInfo) ? + FILE_NOTIFY_CHANGE_DIR_NAME : + FILE_NOTIFY_CHANGE_FILE_NAME, + FILE_ACTION_ADDED, + NULL); } + } - // Step 2: Move LCB to new parent and update name - if (Ccb->Lcb) { - RC = UDFRenameMovePrefix(IrpContext, Ccb->Lcb, &NewName, - SingleDir ? NULL : TargetDirInfo->Fcb); - if (!NT_SUCCESS(RC)) { - try_return (RC); + // this will prevent structutre release before call to + // UDFCleanUpFcbChain() + InterlockedIncrement((PLONG)&DirInfo->Fcb->FcbReference); + ASSERT(DirInfo->Fcb->FcbReference >= DirInfo->RefCount); + + // Look through Ccb list & decrement OpenHandleCounter(s) + // acquire CcbList + 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; } - } - // Step 3: Update FCB parent pointer for cross-directory rename - if (!SingleDir) { - Fcb->ParentFcb = TargetDirInfo->Fcb; + if (CurCcb->TreeLength > 1) { + DirRefCount++; + if (UseClose) + FileInfoRefCount++; + CurCcb->TreeLength = 2; +#ifdef UDF_DBG + } else { + BrutePoint(); +#endif // UDF_DBG + } } - - // Step 4: Notify NEW location (LCB now points to new parent) - // After UDFRenameMovePrefix, LCB has new name — pass it explicitly - if (SingleDir && !ReplaceIfExists) { - UDFNotifyReportChange(IrpContext, Vcb, Fcb, Filter, FILE_ACTION_RENAMED_NEW_NAME, - Ccb->Lcb, NULL); - } else if (ReplaceIfExists) { - UDFNotifyReportChange(IrpContext, Vcb, Fcb, - FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_SIZE | - FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_LAST_ACCESS | - FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_EA, - FILE_ACTION_MODIFIED, Ccb->Lcb, NULL); - } else { - UDFNotifyReportChange(IrpContext, Vcb, Fcb, Filter, FILE_ACTION_ADDED, - Ccb->Lcb, NULL); + UDFReleaseResource(&Fcb->FcbNonpaged->CcbListResource); + + ASSERT(DirRefCount >= FileInfoRefCount); + // update counters & pointers + 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) { + MyFreePool__(Fcb->FCBName->ObjectName.Buffer); + } + UDFReleaseObjectName(Fcb->FCBName); + } + Fcb->FCBName = UDFAllocateObjectName(); + if (!(Fcb->FCBName)) { +insuf_res: + BrutePoint(); + // UDFCleanUpFcbChain()... + if (TargetParentFcbAcquired) { + UDF_CHECK_PAGING_IO_RESOURCE(TargetDirInfo->Fcb); + UDFReleaseResource(&TargetDirInfo->Fcb->FcbNonpaged->FcbResource); + TargetParentFcbAcquired = FALSE; } + if (ParentFcbAcquired) { + UDF_CHECK_PAGING_IO_RESOURCE(DirInfo->Fcb); + UDFReleaseResource(&DirInfo->Fcb->FcbNonpaged->FcbResource); + ParentFcbAcquired = FALSE; + } + UDFTeardownStructures(IrpContext, DirInfo->Fcb, 1, NULL); + try_return(RC = STATUS_INSUFFICIENT_RESOURCES); } - ASSERT(TargetDirInfo->RefCount || SingleDir); + RC = MyCloneUnicodeString(&Fcb->FCBName->ObjectName, &TargetFcb->FCBName->ObjectName); + if (!NT_SUCCESS(RC)) + goto insuf_res; +/* RC = MyAppendUnicodeStringToString(&(Fcb1->FCBName->ObjectName), &(Fcb2->FCBName->ObjectName)); + if (!NT_SUCCESS(RC)) + 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) { + RC = MyAppendUnicodeToString(&Fcb->FCBName->ObjectName, L"\\"); + if (!NT_SUCCESS(RC)) + goto insuf_res; + } + RC = MyAppendUnicodeStringToStringTag(&Fcb->FCBName->ObjectName, &NewName, MEM_USREN2_TAG); + 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; @@ -2333,38 +2321,23 @@ try_exit: NOTHING; } _SEH2_FINALLY { - // - // Remove stale target LCB from queues (deferred here from - // success path). NeedRemovePrefix is only set after rename - // succeeded, so StaleFcb is already marked UDF_FCB_DELETED. - // Guard against concurrent teardown that may have already - // removed this LCB by checking ParentFcbLinks. - // - if (NeedRemovePrefix) { - if (StaleLcb->ParentFcbLinks.Flink != &StaleLcb->ParentFcbLinks) { - UDFRemovePrefix(IrpContext, StaleLcb); - } - if (StaleFcb) { - UDFLockFcbTable(IrpContext, Vcb); - UDFLockVcb(IrpContext, Vcb); - { - struct { FILE_ID FileId; PFCB Fcb; } _Key; - _Key.FileId = StaleFcb->FileId; - RtlDeleteElementGenericTable(&Vcb->FcbTable, &_Key); - } - UDFUnlockVcb(IrpContext, Vcb); - UDFUnlockFcbTable(IrpContext, Vcb); - } - } - if (StaleFcbAcquired) { - UDFReleaseFcb(IrpContext, StaleFcb); - } if (TargetParentFcbAcquired) { - UDFReleaseFcb(IrpContext, TargetDirInfo->Fcb); + UDF_CHECK_PAGING_IO_RESOURCE(TargetDirInfo->Fcb); + UDFReleaseResource(&TargetDirInfo->Fcb->FcbNonpaged->FcbResource); } if (ParentFcbAcquired) { - UDFReleaseFcb(IrpContext, DirInfo->Fcb); + UDF_CHECK_PAGING_IO_RESOURCE(DirInfo->Fcb); + UDFReleaseResource(&DirInfo->Fcb->FcbNonpaged->FcbResource); + } + // 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); } + if (LocalPath.Buffer) { MyFreePool__(LocalPath.Buffer); } @@ -2421,10 +2394,6 @@ UDFStoreFileId( LONG i; NTSTATUS RC = STATUS_SUCCESS; - // NOTE: This function appears to be unused legacy code (no callers found). - // TODO: If ever used, need to add IrpContext parameter and use UDFBuildFullPathFromLcb - // to build the path from LCB instead of FCBName (which no longer exists). - if ((i = UDFFindFileId(Vcb, FileId)) == (-1)) { if ((i = UDFFindFreeFileId(Vcb, FileId)) == (-1)) return STATUS_INSUFFICIENT_RESOURCES; } else { @@ -2432,11 +2401,10 @@ UDFStoreFileId( } Vcb->FileIdCache[i].Id = FileId; Vcb->FileIdCache[i].IgnoreCase = BooleanFlagOn(Ccb->Flags, CCB_FLAG_IGNORE_CASE); - - // TODO: Build path from LCB using UDFBuildFullPathFromLcb (requires IrpContext) - // For now, return error if this function is ever called - RC = STATUS_NOT_IMPLEMENTED; - + RC = MyCloneUnicodeString(&(Vcb->FileIdCache[i].FullName), &(Ccb->Fcb->FCBName->ObjectName)); +/* if (NT_SUCCESS(RC)) { + RC = MyAppendUnicodeStringToStringTag(&(Vcb->FileIdCache[i].FullName), &(Ccb->Fcb->FCBName->ObjectName), MEM_USFIDC_TAG); + }*/ return RC; } // end UDFStoreFileId() @@ -2573,7 +2541,7 @@ UDFHardLink( /* if (UDFIsAStreamDir(Dir2)) try_return (RC = STATUS_ACCESS_DENIED);*/ - RC = UDFPrepareForRenameMoveLink(IrpContext, Vcb, + RC = UDFPrepareForRenameMoveLink(Vcb, &SingleDir, &AcquiredDir1, &AcquiredFcb1, Ccb1, File1, @@ -2591,29 +2559,15 @@ UDFHardLink( NewName.Length = NewName.MaximumLength = (USHORT)(PtrBuffer->FileNameLength); NewName.Buffer = (PWCHAR)&(PtrBuffer->FileName); } else { - // After OpenTargetDirectory, FileName is split: - // Length = parent directory path (trimmed) - // MaximumLength = full original path (including target name) - USHORT FullLength = DirObject2->FileName.MaximumLength; - USHORT ParentLength = DirObject2->FileName.Length; - PWCHAR Buffer = DirObject2->FileName.Buffer; - USHORT FileNameStart; - - if (ParentLength < FullLength && - Buffer[ParentLength / sizeof(WCHAR)] == L'\\') { - FileNameStart = ParentLength + sizeof(WCHAR); - } else { - FileNameStart = ParentLength; - } - - NewName.Length = FullLength - FileNameStart; - NewName.MaximumLength = NewName.Length; - NewName.Buffer = (PWCHAR)((PCHAR)Buffer + FileNameStart); + // This name is by definition legal. + NewName = *((PUNICODE_STRING)&DirObject2->FileName); } IgnoreCase = FlagOn(Ccb1->Flags, CCB_FLAG_IGNORE_CASE); - // Note: Fcb1 no longer has FCBName - removed debug print + AdPrint((" %ws ->\n %ws\n", + Fcb1->FCBName->ObjectName.Buffer, + NewName.Buffer)); RC = UDFHardLinkFile__(IrpContext, Vcb, IgnoreCase, &Replace, &NewName, Dir1, Dir2, File1); if (!NT_SUCCESS(RC)) try_return (RC); @@ -2627,31 +2581,19 @@ UDFHardLink( } } // report changes - UDFNotifyReportChange( IrpContext, Vcb, File1->Fcb, + UDFNotifyFullReportChange( Vcb, File1->Fcb, FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_LAST_ACCESS, - FILE_ACTION_MODIFIED, - Ccb1->Lcb, FileObject1); - - // Build full path for hardlink target - if (Dir2->Fcb->FcbState & UDF_FCB_ROOT_DIRECTORY) { - RC = MyCloneUnicodeString(&LocalPath, &UdfData.UnicodeStrRoot); - if (!NT_SUCCESS(RC)) try_return (RC); - } else { - // Build parent path from LCB - PLCB Dir2Lcb = NULL; - if (!IsListEmpty(&Dir2->Fcb->ParentLcbQueue)) { - PLIST_ENTRY ListEntry = Dir2->Fcb->ParentLcbQueue.Flink; - Dir2Lcb = CONTAINING_RECORD(ListEntry, LCB, ChildFcbLinks); - RC = UDFBuildFullPathFromLcb(IrpContext, Dir2Lcb, &LocalPath, FALSE); - if (!NT_SUCCESS(RC)) try_return (RC); - } else { - RC = MyCloneUnicodeString(&LocalPath, &UdfData.UnicodeStrRoot); - if (!NT_SUCCESS(RC)) try_return (RC); - } - } + FILE_ACTION_MODIFIED ); - // Append separator and new name + RC = MyCloneUnicodeString(&LocalPath, (Dir2->Fcb->FcbState & UDF_FCB_ROOT_DIRECTORY) ? + &UdfData.UnicodeStrRoot : + &(Dir2->Fcb->FCBName->ObjectName)); + 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 Dir2 is a RootDir, we shoud not append '\\' because + // it will be the 2nd '\\' character (RootDir's name is also '\\') if (Dir2->ParentFile) { RC = MyAppendUnicodeToString(&LocalPath, L"\\"); if (!NT_SUCCESS(RC)) try_return (RC); @@ -2659,19 +2601,13 @@ UDFHardLink( RC = MyAppendUnicodeStringToStringTag(&LocalPath, &NewName, MEM_USHL_TAG); if (!NT_SUCCESS(RC)) try_return (RC); - // Calculate TargetNameOffset (parent path length) - USHORT HardLinkTargetNameOffset = (USHORT)(LocalPath.Length - NewName.Length); - if (Dir2->Fcb->FcbState & UDF_FCB_ROOT_DIRECTORY) { - HardLinkTargetNameOffset = 0; - } - if (!Replace) { /* UDFNotifyFullReportChange( Vcb, File2, UDFIsADirectory(File1) ? FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME, FILE_ACTION_ADDED );*/ FsRtlNotifyFullReportChange( Vcb->NotifySync, &(Vcb->NextNotifyIRP), (PSTRING)&LocalPath, - HardLinkTargetNameOffset, + ((Dir2->Fcb->FcbState & UDF_FCB_ROOT_DIRECTORY) ? 0 : Dir2->Fcb->FCBName->ObjectName.Length) + sizeof(WCHAR), NULL,NULL, UDFIsADirectory(File1) ? FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME, FILE_ACTION_ADDED, @@ -2687,7 +2623,7 @@ UDFHardLink( FILE_ACTION_MODIFIED );*/ FsRtlNotifyFullReportChange( Vcb->NotifySync, &(Vcb->NextNotifyIRP), (PSTRING)&LocalPath, - HardLinkTargetNameOffset, + ((Dir2->Fcb->FcbState & UDF_FCB_ROOT_DIRECTORY) ? 0 : Dir2->Fcb->FCBName->ObjectName.Length) + sizeof(WCHAR), NULL,NULL, UDFIsADirectory(File1) ? FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME, FILE_NOTIFY_CHANGE_ATTRIBUTES | @@ -2705,12 +2641,13 @@ try_exit: NOTHING; } _SEH2_FINALLY { - // Release in reverse order of acquisition (parent first, then child) - if (AcquiredDir1) { - UDFReleaseFcb(IrpContext, Dir1->Fcb); - } if (AcquiredFcb1) { - UDFReleaseFcb(IrpContext, Fcb1); + UDF_CHECK_PAGING_IO_RESOURCE(Fcb1); + UDFReleaseResource(&Fcb1->FcbNonpaged->FcbResource); + } + if (AcquiredDir1) { + UDF_CHECK_PAGING_IO_RESOURCE(Dir1->Fcb); + UDFReleaseResource(&Dir1->Fcb->FcbNonpaged->FcbResource); } if (LocalPath.Buffer) { diff --git a/drivers/filesystems/udfs/flush.c b/drivers/filesystems/udfs/flush.c index 52cbe2b9b4b61..ebe9dd16dffa1 100644 --- a/drivers/filesystems/udfs/flush.c +++ b/drivers/filesystems/udfs/flush.c @@ -5,7 +5,7 @@ //////////////////////////////////////////////////////////////////// /************************************************************************* * -* File: Flush.c +* File: Flush.cpp * * Module: UDF File System Driver (Kernel mode execution only) * @@ -112,9 +112,11 @@ UDFCommonFlush( // action we take. if ((Fcb == Fcb->Vcb->VolumeDasdFcb) || (Fcb->FcbState & UDF_FCB_ROOT_DIRECTORY)) { +#ifdef UDF_DELAYED_CLOSE UDFFspClose(Vcb); +#endif //UDF_DELAYED_CLOSE - UDFAcquireVcbExclusive(IrpContext, Vcb, FALSE); + UDFAcquireResourceExclusive(&(Vcb->VcbResource), TRUE); AcquiredVCB = TRUE; // The caller wishes to flush all files for the mounted // logical volume. The flush volume routine below should simply @@ -127,7 +129,7 @@ UDFCommonFlush( UDFFlushVolume(IrpContext, Vcb, 0); - UDFReleaseVcb(IrpContext, Vcb); + UDFReleaseResource(&(Vcb->VcbResource)); AcquiredVCB = FALSE; try_return(Status); @@ -137,18 +139,16 @@ UDFCommonFlush( Vcb = Fcb->Vcb; ASSERT(Vcb); - // Child-first lock ordering - UDF_CHECK_PAGING_IO_RESOURCE(Fcb); - UDFAcquireFcbExclusive(IrpContext, Fcb, FALSE); - 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); - UDFAcquireFcbExclusive(IrpContext, Fcb->FileInfo->ParentFile->Fcb, FALSE); + 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,19 +168,20 @@ try_exit: NOTHING; } _SEH2_FINALLY { - // Release in reverse order of acquisition (parent first, then child) - if (AcquiredParentFcb) { - UDFReleaseFcb(IrpContext, Fcb->FileInfo->ParentFile->Fcb); - AcquiredParentFcb = FALSE; - } - if (AcquiredFCB) { - UDFReleaseFcb(IrpContext, Fcb); + UDF_CHECK_PAGING_IO_RESOURCE(Fcb); + UDFReleaseResource(&Fcb->FcbNonpaged->FcbResource); AcquiredFCB = FALSE; } + if (AcquiredParentFcb) { + UDF_CHECK_PAGING_IO_RESOURCE(Fcb->FileInfo->ParentFile->Fcb); + UDFReleaseResource(&Fcb->FileInfo->ParentFile->Fcb->FcbNonpaged->FcbResource); + AcquiredParentFcb = FALSE; + } + if (AcquiredVCB) { - UDFReleaseVcb(IrpContext, Vcb); + UDFReleaseResource(&Vcb->VcbResource); AcquiredVCB = FALSE; } diff --git a/drivers/filesystems/udfs/fscntrl.c b/drivers/filesystems/udfs/fscntrl.c index a1d1a39014e33..0c0a872050d56 100644 --- a/drivers/filesystems/udfs/fscntrl.c +++ b/drivers/filesystems/udfs/fscntrl.c @@ -5,7 +5,7 @@ //////////////////////////////////////////////////////////////////// /* - Module Name: FsCntrl.c + Module Name: FsCntrl.cpp Abstract: @@ -639,15 +639,7 @@ UDFCloseResidual( UDFCloseFile__(IrpContext, Vcb, Vcb->RootIndexFcb->FileInfo); if (Vcb->RootIndexFcb->FcbCleanup) Vcb->RootIndexFcb->FcbCleanup--; - { - 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); - } - } + UDFTeardownStructures(IrpContext, Vcb->RootIndexFcb, 1, NULL); // Remove root FCB reference in vcb if (Vcb->VcbReference) InterlockedDecrement((PLONG)&Vcb->VcbReference); diff --git a/drivers/filesystems/udfs/lockctrl.c b/drivers/filesystems/udfs/lockctrl.c index a8fd105af7517..b6cbd095d38c4 100644 --- a/drivers/filesystems/udfs/lockctrl.c +++ b/drivers/filesystems/udfs/lockctrl.c @@ -141,34 +141,38 @@ UDFFastLock ( IN PDEVICE_OBJECT DeviceObject ) { - BOOLEAN FcbAcquired = FALSE; BOOLEAN Results = FALSE; + +// BOOLEAN AcquiredFCB = FALSE; TYPE_OF_OPEN TypeOfOpen; - PFCB Fcb = NULL; + PFCB Fcb = NULL; + + UDFPrint(("UDFFastLock\n")); // 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); - if (TypeOfOpen != UserFileOpen) { + ASSERT_FCB(Fcb); + + // Validate the sent-in FCB + if ( (Fcb == Fcb->Vcb->VolumeDasdFcb) || + (Fcb->FcbState & UDF_FCB_DIRECTORY)) { IoStatus->Status = STATUS_INVALID_PARAMETER; + IoStatus->Information = 0; return TRUE; } - ASSERT_FCB(Fcb); + // Acquire exclusive access to the Fcb this operation can always wait FsRtlEnterFileSystem(); - _SEH2_TRY { - - FcbAcquired = UDFAcquireFcbShared(NULL, Fcb, TRUE); - - if (FcbAcquired == FALSE) { + // BUGBUG: kenr + // (VOID) ExAcquireResourceShared( Fcb->Header.Resource, TRUE ); - try_return(NOTHING); - } + _SEH2_TRY { // If we don't have a file lock, then get one now. if ((Fcb->FileLock == NULL) && !UDFCreateFileLock(NULL, Fcb, FALSE)) { @@ -200,13 +204,10 @@ UDFFastLock ( try_exit: NOTHING; } _SEH2_FINALLY { - // Release the Fcb, and return to our caller - - if (FcbAcquired) { - - UDFReleaseFcb(NULL, Fcb); - } + // Release the Fcb, and return to our caller + // BUGBUG: kenr + // UDFReleaseResource( (Fcb)->Header.Resource ); FsRtlExitFileSystem(); diff --git a/drivers/filesystems/udfs/mem.c b/drivers/filesystems/udfs/mem.c index 301ead0d8ba72..072602c852327 100644 --- a/drivers/filesystems/udfs/mem.c +++ b/drivers/filesystems/udfs/mem.c @@ -8,4 +8,4 @@ // define the file specific bug-check id #define UDF_BUG_CHECK_ID UDF_FILE_MEM -#include "Include/mem_tools.c" +#include "Include/mem_tools.cpp" diff --git a/drivers/filesystems/udfs/misc.c b/drivers/filesystems/udfs/misc.c index 70c69df9c3679..c78f45461cc12 100644 --- a/drivers/filesystems/udfs/misc.c +++ b/drivers/filesystems/udfs/misc.c @@ -5,7 +5,7 @@ //////////////////////////////////////////////////////////////////// /* - File: Misc.c + File: Misc.cpp Module: UDF File System Driver (Kernel mode execution only) @@ -30,6 +30,143 @@ #define UDFFreeIoContext(IO) ExFreePool( &(IO) ) +/* + + Function: UDFInitializeZones() + + Description: + Allocates some memory for global zones used to allocate FSD structures. + Either all memory will be allocated or we will back out gracefully. + + Expected Interrupt Level (for execution) : + + IRQL_PASSIVE_LEVEL + + Return Value: STATUS_SUCCESS/Error + +*/ +NTSTATUS +UDFInitializeZones(VOID) +{ + NTSTATUS RC = STATUS_UNSUCCESSFUL; + + _SEH2_TRY { + + // determine memory requirements + switch (MmQuerySystemSize()) { + case MmMediumSystem: + UdfData.MaxDelayedCloseCount = 32; + UdfData.MinDelayedCloseCount = 8; + break; + case MmLargeSystem: + UdfData.MaxDelayedCloseCount = 72; + UdfData.MinDelayedCloseCount = 18; + break; + case MmSmallSystem: + default: + UdfData.MaxDelayedCloseCount = 10; + UdfData.MinDelayedCloseCount = 2; + } + + ExInitializeNPagedLookasideList(&UdfData.IrpContextLookasideList, + NULL, + NULL, + POOL_NX_ALLOCATION | POOL_RAISE_IF_ALLOCATION_FAILURE, + sizeof(IRP_CONTEXT), + TAG_IRP_CONTEXT, + 0); + + // TODO: move to Paged? + ExInitializeNPagedLookasideList(&UdfData.ObjectNameLookasideList, + NULL, + NULL, + POOL_NX_ALLOCATION | POOL_RAISE_IF_ALLOCATION_FAILURE, + sizeof(UDFObjectName), + TAG_OBJECT_NAME, + 0); + + ExInitializeNPagedLookasideList(&UdfData.NonPagedFcbLookasideList, + NULL, + NULL, + POOL_NX_ALLOCATION | POOL_RAISE_IF_ALLOCATION_FAILURE, + sizeof(FCB), + TAG_FCB_NONPAGED, + 0); + + ExInitializeNPagedLookasideList(&UdfData.UDFNonPagedFcbLookasideList, + NULL, + NULL, + POOL_NX_ALLOCATION | POOL_RAISE_IF_ALLOCATION_FAILURE, + sizeof(FCB_NONPAGED), + TAG_FCB_NONPAGED, + 0); + + ExInitializePagedLookasideList(&UdfData.UDFFcbIndexLookasideList, + NULL, + NULL, + POOL_NX_ALLOCATION | POOL_RAISE_IF_ALLOCATION_FAILURE, + sizeof(FCB), //TODO: + TAG_FCB_NONPAGED, + 0); + + ExInitializePagedLookasideList(&UdfData.UDFFcbDataLookasideList, + NULL, + NULL, + POOL_NX_ALLOCATION | POOL_RAISE_IF_ALLOCATION_FAILURE, + sizeof(FCB), //TODO: + TAG_FCB_NONPAGED, + 0); + + ExInitializePagedLookasideList(&UdfData.CcbLookasideList, + NULL, + NULL, + POOL_NX_ALLOCATION | POOL_RAISE_IF_ALLOCATION_FAILURE, + sizeof(CCB), + TAG_CCB, + 0); + + try_return(RC = STATUS_SUCCESS); + +try_exit: NOTHING; + + } _SEH2_FINALLY { + if (!NT_SUCCESS(RC)) { + // invoke the destroy routine now ... + UDFDestroyZones(); + } else { + // mark the fact that we have allocated zones ... + SetFlag(UdfData.Flags, UDF_DATA_FLAGS_ZONES_INITIALIZED); + } + } _SEH2_END; + + return(RC); +} + + +/************************************************************************* +* +* Function: UDFDestroyZones() +* +* Description: +* Free up the previously allocated memory. NEVER do this once the +* driver has been successfully loaded. +* +* Expected Interrupt Level (for execution) : +* +* IRQL_PASSIVE_LEVEL +* +* Return Value: None +* +*************************************************************************/ +VOID UDFDestroyZones(VOID) +{ + ExDeleteNPagedLookasideList(&UdfData.IrpContextLookasideList); + ExDeleteNPagedLookasideList(&UdfData.ObjectNameLookasideList); + ExDeleteNPagedLookasideList(&UdfData.NonPagedFcbLookasideList); + + ExDeletePagedLookasideList(&UdfData.CcbLookasideList); +} + /************************************************************************* * * Function: UDFExceptionFilter() @@ -422,6 +559,79 @@ UDFCreateCcb() return NewCcb; } // end UDFCreateCcb() + +/************************************************************************* +* +* Function: UDFReleaseCCB() +* +* Description: +* Deallocate a previously allocated structure. +* +* Expected Interrupt Level (for execution) : +* +* IRQL_PASSIVE_LEVEL +* +* Return Value: None +* +*************************************************************************/ +VOID +UDFReleaseCCB( + PCCB Ccb + ) +{ + ASSERT(Ccb); + + ExFreeToPagedLookasideList(&UdfData.CcbLookasideList, Ccb); + +} // end UDFReleaseCCB() + +/* + Function: UDFCleanupCCB() + + Description: + Cleanup and deallocate a previously allocated structure. + + Expected Interrupt Level (for execution) : + + IRQL_PASSIVE_LEVEL + + Return Value: None + +*/ +VOID +UDFDeleteCcb( + PCCB Ccb +) +{ + ASSERT(Ccb); + if (!Ccb) return; // probably, we havn't allocated it... + ASSERT(Ccb->NodeIdentifier.NodeTypeCode == UDF_NODE_TYPE_CCB); + + _SEH2_TRY { + if (Ccb->Fcb) { + UDFAcquireResourceExclusive(&Ccb->Fcb->FcbNonpaged->CcbListResource, TRUE); + RemoveEntryList(&(Ccb->NextCCB)); + UDFReleaseResource(&Ccb->Fcb->FcbNonpaged->CcbListResource); + } else { + BrutePoint(); + } + + if (Ccb->DirectorySearchPattern) { + if (Ccb->DirectorySearchPattern->Buffer) { + MyFreePool__(Ccb->DirectorySearchPattern->Buffer); + Ccb->DirectorySearchPattern->Buffer = NULL; + } + + MyFreePool__(Ccb->DirectorySearchPattern); + Ccb->DirectorySearchPattern = NULL; + } + + UDFReleaseCCB(Ccb); + } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { + BrutePoint(); + } _SEH2_END; +} // end UDFCleanUpCCB() + /************************************************************************* * * Function: UDFCreateIrpContext() @@ -501,7 +711,7 @@ UDFCreateIrpContext( } // TODO: fix - if (FALSE && IrpSp->FileObject != NULL) { + if (false && IrpSp->FileObject != NULL) { PFILE_OBJECT FileObject = IrpSp->FileObject; @@ -1220,6 +1430,27 @@ UDFReadRegKeys( { ptrUDFGetParameter UDFGetParameter = UDFGetRegParameter; + // What type of AllocDescs should we use + Vcb->DefaultAllocMode = (USHORT)UDFGetParameter(Vcb, REG_DEFALLOCMODE_NAME, + Update ? Vcb->DefaultAllocMode : ICB_FLAG_AD_SHORT); + if (Vcb->DefaultAllocMode > ICB_FLAG_AD_LONG) Vcb->DefaultAllocMode = ICB_FLAG_AD_SHORT; + + // FE allocation charge for plain Dirs + Vcb->FECharge = UDFGetParameter(Vcb, UDF_FE_CHARGE_NAME, Update ? Vcb->FECharge : 0); + if (!Vcb->FECharge) + Vcb->FECharge = UDF_DEFAULT_FE_CHARGE; + // FE allocation charge for Stream Dirs (SDir) + Vcb->FEChargeSDir = UDFGetParameter(Vcb, UDF_FE_CHARGE_SDIR_NAME, + Update ? Vcb->FEChargeSDir : 0); + if (!Vcb->FEChargeSDir) + Vcb->FEChargeSDir = UDF_DEFAULT_FE_CHARGE_SDIR; + // How many Deleted entries should contain Directory to make us + // start packing it. + Vcb->PackDirThreshold = UDFGetParameter(Vcb, UDF_DIR_PACK_THRESHOLD_NAME, + Update ? Vcb->PackDirThreshold : 0); + if (Vcb->PackDirThreshold == 0xffffffff) + Vcb->PackDirThreshold = UDF_DEFAULT_DIR_PACK_THRESHOLD; + // Timeouts for FreeSpaceBitMap & TheWholeDirTree flushes Vcb->BM_FlushPriod = UDFGetParameter(Vcb, UDF_BM_FLUSH_PERIOD_NAME, Update ? Vcb->BM_FlushPriod : 0); @@ -1262,10 +1493,17 @@ UDFReadRegKeys( UDFUpdateCompatOption(Vcb, Update, UseCfg, UDF_UPDATE_DIR_TIMES_ATTR_W, UDF_VCB_IC_UPDATE_DIR_WRITE, FALSE); // Should we update Dir's Times & Attrs on Access UDFUpdateCompatOption(Vcb, Update, UseCfg, UDF_UPDATE_DIR_TIMES_ATTR_R, UDF_VCB_IC_UPDATE_DIR_READ, FALSE); + // Should we allow user to write into Read-Only Directory + UDFUpdateCompatOption(Vcb, Update, UseCfg, UDF_ALLOW_WRITE_IN_RO_DIR, UDF_VCB_IC_WRITE_IN_RO_DIR, TRUE); // Should we allow user to change Access Time for unchanged Directory UDFUpdateCompatOption(Vcb, Update, UseCfg, UDF_ALLOW_UPDATE_TIMES_ACCS_UCHG_DIR, UDF_VCB_IC_UPDATE_UCHG_DIR_ACCESS_TIME, FALSE); + // Should we record Allocation Descriptors in W2k-compatible form + UDFUpdateCompatOption(Vcb, Update, UseCfg, UDF_W2K_COMPAT_ALLOC_DESCS, UDF_VCB_IC_W2K_COMPAT_ALLOC_DESCS, TRUE); // Should we read LONG_ADs with invalid PartitionReferenceNumber (generated by Nero Instant Burner) UDFUpdateCompatOption(Vcb, Update, UseCfg, UDF_INSTANT_COMPAT_ALLOC_DESCS, UDF_VCB_IC_INSTANT_COMPAT_ALLOC_DESCS, TRUE); + // 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 ignore FO_SEQUENTIAL_ONLY UDFUpdateCompatOption(Vcb, Update, UseCfg, UDF_IGNORE_SEQUENTIAL_IO, UDF_VCB_IC_IGNORE_SEQUENTIAL_IO, FALSE); @@ -1338,7 +1576,7 @@ UDFDeleteVCB( UDFPrint(("UDF: Delete resources\n")); UDFDeleteResource(&(Vcb->VcbResource)); UDFDeleteResource(&(Vcb->BitMapResource1)); - + UDFDeleteResource(&(Vcb->FileIdResource)); UDFDeleteResource(&(Vcb->DlocResource)); UDFDeleteResource(&(Vcb->DlocResource2)); UDFDeleteResource(&(Vcb->FlushResource)); @@ -1406,6 +1644,7 @@ 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. @@ -1867,5 +2106,5 @@ UDFWaitForIoAtEof( return TRUE; } -#include "Include/regtools.c" +#include "Include/regtools.cpp" diff --git a/drivers/filesystems/udfs/namesup.c b/drivers/filesystems/udfs/namesup.c index 021bf48856e6e..cab84c4f5873b 100644 --- a/drivers/filesystems/udfs/namesup.c +++ b/drivers/filesystems/udfs/namesup.c @@ -5,7 +5,7 @@ //////////////////////////////////////////////////////////////////// /* Module: - Namesup.c + Namesup.cpp Abstract: FileName support routines */ diff --git a/drivers/filesystems/udfs/nodetype.h b/drivers/filesystems/udfs/nodetype.h index c9709c170741d..5027a9e327fbf 100644 --- a/drivers/filesystems/udfs/nodetype.h +++ b/drivers/filesystems/udfs/nodetype.h @@ -19,7 +19,6 @@ 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/pnp.c b/drivers/filesystems/udfs/pnp.c index 51a0df7daa116..55b1e02f0eeb3 100644 --- a/drivers/filesystems/udfs/pnp.c +++ b/drivers/filesystems/udfs/pnp.c @@ -5,7 +5,7 @@ //////////////////////////////////////////////////////////////////// /************************************************************************* * -* File: Pnp.c +* File: Pnp.cpp * * Module: UDF File System Driver (Kernel mode execution only) * diff --git a/drivers/filesystems/udfs/prefxsup.c b/drivers/filesystems/udfs/prefxsup.c deleted file mode 100644 index 2b0dc9b25ed50..0000000000000 --- a/drivers/filesystems/udfs/prefxsup.c +++ /dev/null @@ -1,1338 +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. -//////////////////////////////////////////////////////////////////// -/* - - File: PrefxSup.c - - Module: UDF File System Driver (Kernel mode execution only) - - Description: - This module implements the UDF Prefix support routines. - -*/ - -#include "udffs.h" - -// define the file specific bug-check id -#define UDF_BUG_CHECK_ID UDF_FILE_MISC - -/* - Lexicographic comparison of two UNICODE_STRING names. - Returns LessThan, EqualTo, or GreaterThan. - Used for splay tree ordering. -*/ -static -FSRTL_COMPARISON_RESULT -UdfCompareNames( - IN PUNICODE_STRING NameA, - IN PUNICODE_STRING NameB - ) -{ - ULONG MinLength = NameA->Length; - FSRTL_COMPARISON_RESULT Result = LessThan; - - if (NameA->Length > NameB->Length) { - MinLength = NameB->Length; - Result = GreaterThan; - } else if (NameA->Length == NameB->Length) { - Result = EqualTo; - } - - ULONG i = (ULONG)RtlCompareMemory(NameA->Buffer, NameB->Buffer, MinLength); - - if (i < MinLength) { - return ((NameA->Buffer[i / 2] < NameB->Buffer[i / 2]) ? - LessThan : GreaterThan); - } - - return Result; -} - - -/* - Search a splay tree for an LCB matching the given name. - On match, rebalances the tree (splay) and returns the LCB. - Returns NULL if no match. - - LinksOffset: byte offset of RTL_SPLAY_LINKS within LCB structure - NameOffset: byte offset of UNICODE_STRING within LCB structure -*/ -static -PLCB -UdfFindNameLink( - IN PRTL_SPLAY_LINKS *RootNode, - IN PUNICODE_STRING Name, - IN ULONG LinksOffset, - IN ULONG NameOffset - ) -{ - PRTL_SPLAY_LINKS Links = *RootNode; - - while (Links != NULL) { - - PLCB Node = (PLCB)((PUCHAR)Links - LinksOffset); - PUNICODE_STRING NodeName = (PUNICODE_STRING)((PUCHAR)Node + NameOffset); - - FSRTL_COMPARISON_RESULT Comparison = UdfCompareNames(NodeName, Name); - - if (Comparison == GreaterThan) { - Links = RtlLeftChild(Links); - } else if (Comparison == LessThan) { - Links = RtlRightChild(Links); - } else { - *RootNode = RtlSplay(Links); - return Node; - } - } - - return NULL; -} - - -/* - Insert an LCB into a splay tree keyed by the given name. - Returns TRUE if inserted, FALSE if duplicate exists. - - LinksOffset: byte offset of RTL_SPLAY_LINKS within LCB structure - NameOffset: byte offset of UNICODE_STRING within LCB structure -*/ -static -BOOLEAN -UdfInsertNameLink( - IN PRTL_SPLAY_LINKS *RootNode, - IN PLCB NameLink, - IN ULONG LinksOffset, - IN ULONG NameOffset - ) -{ - PRTL_SPLAY_LINKS NewLinks = (PRTL_SPLAY_LINKS)((PUCHAR)NameLink + LinksOffset); - PUNICODE_STRING NewName = (PUNICODE_STRING)((PUCHAR)NameLink + NameOffset); - - RtlInitializeSplayLinks(NewLinks); - - if (*RootNode == NULL) { - *RootNode = NewLinks; - return TRUE; - } - - PLCB Node = (PLCB)((PUCHAR)*RootNode - LinksOffset); - - while (TRUE) { - - PRTL_SPLAY_LINKS NodeLinks = (PRTL_SPLAY_LINKS)((PUCHAR)Node + LinksOffset); - PUNICODE_STRING NodeName = (PUNICODE_STRING)((PUCHAR)Node + NameOffset); - - FSRTL_COMPARISON_RESULT Comparison = UdfCompareNames(NodeName, NewName); - - if (Comparison == EqualTo) { - // Duplicate name — not inserted. Caller will not set IN_TREE flag. - return FALSE; - } - - if (Comparison == GreaterThan) { - if (RtlLeftChild(NodeLinks) == NULL) { - RtlInsertAsLeftChild(NodeLinks, NewLinks); - break; - } - Node = (PLCB)((PUCHAR)RtlLeftChild(NodeLinks) - LinksOffset); - } else { - if (RtlRightChild(NodeLinks) == NULL) { - RtlInsertAsRightChild(NodeLinks, NewLinks); - break; - } - Node = (PLCB)((PUCHAR)RtlRightChild(NodeLinks) - LinksOffset); - } - } - - return TRUE; -} - - -/* - Insert LCB into all applicable splay trees of ParentFcb. - Called after LCB names are initialized. -*/ -VOID -UdfInsertNameLinks( - IN PFCB ParentFcb, - IN PLCB Lcb - ) -{ - // Exact case tree (keyed by FileName) - if (Lcb->FileName.Buffer && Lcb->FileName.Length > 0) { - if (UdfInsertNameLink(&ParentFcb->ExactCaseRoot, Lcb, - FIELD_OFFSET(LCB, ExactCaseLinks), - FIELD_OFFSET(LCB, FileName))) { - SetFlag(Lcb->Flags, UDF_LCB_FLAG_EXACT_CASE_IN_TREE); - } - } - - // Ignore case tree (keyed by IgnoreCaseLinkName) - if (Lcb->IgnoreCaseLinkName.Buffer && Lcb->IgnoreCaseLinkName.Length > 0) { - if (UdfInsertNameLink(&ParentFcb->IgnoreCaseRoot, Lcb, - FIELD_OFFSET(LCB, IgnoreCaseLinks), - FIELD_OFFSET(LCB, IgnoreCaseLinkName))) { - SetFlag(Lcb->Flags, UDF_LCB_FLAG_IGNORE_CASE_IN_TREE); - } - } - - // Short name tree (keyed by ShortName) - if (Lcb->ShortName.Buffer && Lcb->ShortName.Length > 0) { - if (UdfInsertNameLink(&ParentFcb->ShortNameRoot, Lcb, - FIELD_OFFSET(LCB, ShortNameLinks), - FIELD_OFFSET(LCB, ShortName))) { - SetFlag(Lcb->Flags, UDF_LCB_FLAG_SHORT_NAME_IN_TREE); - } - } -} - - -/* - Remove LCB from all splay trees of ParentFcb. - Uses IN_TREE flags to track which trees the LCB was inserted into. - After removal, clears all IN_TREE flags. - Idempotent — safe to call multiple times. -*/ -VOID -UdfRemoveNameLinks( - IN PFCB ParentFcb, - IN PLCB Lcb - ) -{ - if (FlagOn(Lcb->Flags, UDF_LCB_FLAG_EXACT_CASE_IN_TREE)) { - ParentFcb->ExactCaseRoot = RtlDelete(&Lcb->ExactCaseLinks); - } - - if (FlagOn(Lcb->Flags, UDF_LCB_FLAG_IGNORE_CASE_IN_TREE)) { - ParentFcb->IgnoreCaseRoot = RtlDelete(&Lcb->IgnoreCaseLinks); - } - - if (FlagOn(Lcb->Flags, UDF_LCB_FLAG_SHORT_NAME_IN_TREE)) { - ParentFcb->ShortNameRoot = RtlDelete(&Lcb->ShortNameLinks); - } - - ClearFlag(Lcb->Flags, UDF_LCB_FLAG_EXACT_CASE_IN_TREE | - UDF_LCB_FLAG_IGNORE_CASE_IN_TREE | - UDF_LCB_FLAG_SHORT_NAME_IN_TREE); -} - - -/* - This routine creates and inserts an LCB linking the parent FCB to child FCB. - - Creates LCB with dynamic name storage. - Names are stored in a buffer immediately after the LCB structure. - - The LCB is linked into: - - ParentFcb->ChildLcbQueue (via Lcb->ParentFcbLinks) - - ChildFcb->ParentLcbQueue (via Lcb->ChildFcbLinks) - - ParentFcb splay trees (ExactCaseRoot, IgnoreCaseRoot, ShortNameRoot) - - Parameters: - IrpContext - IRP context - ParentFcb - Parent directory FCB - ChildFcb - Child file FCB - FileName - File name (component name, may be NULL) - CaseFileName - Case-sensitive file name (may be NULL) - ShortName - 8.3 short name (may be NULL) - InitialOffset - Directory offset -*/ -PLCB -UDFInsertPrefix( - IN PIRP_CONTEXT IrpContext, - IN PFCB ParentFcb, - IN PFCB ChildFcb, - IN PUNICODE_STRING FileName OPTIONAL, - IN PUNICODE_STRING CaseFileName OPTIONAL, - IN PUNICODE_STRING ShortName OPTIONAL, - IN ULONGLONG InitialOffset - ) -{ - PLCB Lcb; - ULONG Flags = 0; - USHORT NameLength = 0; - ULONG AllocationSize; - PWCHAR NameBuffer; - - UNREFERENCED_PARAMETER(IrpContext); - - ASSERT(ParentFcb); - ASSERT(ChildFcb); - - // - // Calculate required allocation size for names - // Layout: FileName + padding(0x18) + CaseFileName + ShortName - // - if (FileName != NULL && FileName->Length > 0) { - // Size = FileName->Length + alignment(0x18) + CaseFileName->Length + ShortName->Length - NameLength = FileName->Length + 0x18; - if (CaseFileName != NULL && CaseFileName->Length > 0) { - NameLength += CaseFileName->Length; - } - if (ShortName != NULL && ShortName->Length > 0) { - NameLength += ShortName->Length; - } - } - - AllocationSize = UDF_LCB_BASE_SIZE + NameLength; - - // - // Allocate LCB - use lookaside for small allocations - // - if (AllocationSize > UDF_LCB_LOOKASIDE_SIZE) { - - Lcb = (PLCB)FsRtlAllocatePoolWithTag(PagedPool, - AllocationSize, - 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 structure - // - UDFPrint(("UDFInsertPrefix: Lcb=%p, AllocationSize=0x%X, sizeof(LCB)=%u, NameLength=%u\n", - Lcb, AllocationSize, (ULONG)sizeof(LCB), NameLength)); - - ULONG BytesToZero = min(AllocationSize, UDF_LCB_BASE_SIZE); - UDFPrint((" BytesToZero=0x%X (min of AllocationSize and UDF_LCB_BASE_SIZE=0x%X)\n", - BytesToZero, UDF_LCB_BASE_SIZE)); - - RtlZeroMemory(Lcb, BytesToZero); - - Lcb->NodeIdentifier.NodeTypeCode = UDF_NODE_TYPE_LCB; - Lcb->NodeIdentifier.NodeByteSize = (USHORT)AllocationSize; - - // Set up FCB pointers - Lcb->ParentFcb = ParentFcb; - Lcb->ChildFcb = ChildFcb; - Lcb->InitialOffset = InitialOffset; - - // Set flags - Lcb->Flags = Flags; - - // Initial reference count - Lcb->Reference = 0; - - // - // Initialize name buffer pointer - // Buffer is located immediately after LCB structure - // - if (NameLength > 0) { - Lcb->NameBuffer = (PVOID)((PUCHAR)Lcb + UDF_LCB_BASE_SIZE); - Lcb->FileName.MaximumLength = NameLength; - - NameBuffer = (PWCHAR)Lcb->NameBuffer; - - // - // Copy file names into buffer - // Layout: [FileName][padding 0x18][CaseFileName][ShortName] - // - if (FileName != NULL && FileName->Length > 0) { - // Copy FileName (exact case) - Lcb->FileName.Buffer = NameBuffer; - Lcb->FileName.Length = FileName->Length; - RtlCopyMemory(NameBuffer, FileName->Buffer, FileName->Length); - - // Copy CaseFileName (uppercase for ignore-case comparisons) - if (CaseFileName != NULL && CaseFileName->Length > 0) { - // Skip alignment padding (0x18 bytes) after FileName - NameBuffer = (PWCHAR)((PUCHAR)Lcb->NameBuffer + FileName->Length + 0x18); - - Lcb->IgnoreCaseLinkName.Buffer = NameBuffer; - Lcb->IgnoreCaseLinkName.Length = CaseFileName->Length; - Lcb->IgnoreCaseLinkName.MaximumLength = CaseFileName->Length; - RtlCopyMemory(NameBuffer, CaseFileName->Buffer, CaseFileName->Length); - - // Move pointer to next position for ShortName - NameBuffer += CaseFileName->Length / sizeof(WCHAR); - } else { - // No CaseFileName, position after FileName + padding - NameBuffer = (PWCHAR)((PUCHAR)Lcb->NameBuffer + FileName->Length + 0x18); - } - - // Copy ShortName (8.3 DOS name) - if (ShortName != NULL && ShortName->Length > 0) { - Lcb->ShortName.Buffer = NameBuffer; - Lcb->ShortName.Length = ShortName->Length; - Lcb->ShortName.MaximumLength = ShortName->Length; - RtlCopyMemory(NameBuffer, ShortName->Buffer, ShortName->Length); - - // Set flag indicating short name was created - SetFlag(Lcb->Flags, UDF_LCB_FLAG_SHORT_NAME_CREATED); - } - } - } - - // - // 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); - - // Insert into splay trees for O(log n) lookup by name. - // Caller must hold ParentFcb exclusive for splay tree protection. - UdfInsertNameLinks(ParentFcb, Lcb); - - return Lcb; -} // end UDFInsertPrefix() - - -/* - This routine removes an LCB from FCB queues and frees it. - Frees name buffer if separately allocated, then frees LCB structure - itself (from pool or lookaside list). -*/ -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 splay trees. - // All callers hold ParentFcb exclusive or VcbResource exclusive. - // - if (Lcb->ParentFcb) { - UdfRemoveNameLinks(Lcb->ParentFcb, 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 name buffer if separately allocated - // This flag indicates the NameBuffer was allocated independently, - // not as part of the LCB structure - // - if (FlagOn(Lcb->Flags, UDF_LCB_FLAG_HAS_NAME_BUFFER)) { - if (Lcb->NameBuffer != NULL) { - ExFreePool(Lcb->NameBuffer); - Lcb->NameBuffer = NULL; - } - } - - // - // Free FileName.Buffer if it was separately allocated (e.g., after rename) - // Check if it's not pointing to embedded buffer (within LCB structure) - // - if (Lcb->FileName.Buffer != NULL) { - BOOLEAN IsEmbedded = ((PUCHAR)Lcb->FileName.Buffer >= (PUCHAR)Lcb && - (PUCHAR)Lcb->FileName.Buffer < (PUCHAR)Lcb + Lcb->NodeIdentifier.NodeByteSize); - if (!IsEmbedded) { - MyFreePool__(Lcb->FileName.Buffer); - Lcb->FileName.Buffer = NULL; - } - } - - // - // Free Name.Buffer if present (ANSI name) - // - if (Lcb->Name.Buffer != NULL) { - ExFreePool(Lcb->Name.Buffer); - Lcb->Name.Buffer = NULL; - } - - // - // Free the LCB structure itself 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 PUNICODE_STRING FileName OPTIONAL, - IN PUNICODE_STRING CaseFileName OPTIONAL, - IN PUNICODE_STRING ShortName OPTIONAL, - IN ULONGLONG InitialOffset - ) -{ - 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 - return it as-is. - return Lcb; - } - - // - // Need to create new LCB with dynamic names - // - Lcb = UDFInsertPrefix(IrpContext, ParentFcb, ChildFcb, - FileName, CaseFileName, ShortName, InitialOffset); - - if (Lcb) { - // - // New LCB created - Reference=0 and stays 0. - // Lcb->Reference is only used for temporary lock protection, - // not for counting opens. Teardown checks Reference==0 before removal. - // - Lcb->Reference = 0; - - // - // Increment parent refs immediately after LCB creation. - // These will be decremented in UDFTeardownStructures when LCB is removed. - // - InterlockedIncrement((PLONG)&ParentFcb->FcbReference); - 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() - - -/* - Builds full path from LCB chain with caching support. - - Builds path by walking up the parent LCB chain from current LCB to root. - - Caching strategy: - - If Lcb->FileName.Buffer already contains full path → use cached value - - Otherwise, build path recursively and optionally cache it - - Uses FcbLockThread/FcbLockCount/FcbFastMutex for synchronization - - Parameters: - IrpContext - IRP context - Lcb - LCB to build path for (starting point) - FullPath - Output UNICODE_STRING for full path - CachePath - If TRUE, cache the built path in LCB->FileName - - Returns: - STATUS_SUCCESS - Path built successfully - STATUS_INSUFFICIENT_RESOURCES - Memory allocation failed -*/ -NTSTATUS -UDFBuildFullPathFromLcb( - IN PIRP_CONTEXT IrpContext, - IN PLCB Lcb, - OUT PUNICODE_STRING FullPath, - IN BOOLEAN CachePath - ) -{ - PLCB CurrentLcb; - PFCB CurrentFcb; - PFCB Fcb; - USHORT TotalLength = 0; - USHORT ComponentLength; - PWCHAR Buffer = NULL; - PWCHAR CurrentPosition; - PKTHREAD CurrentThread; - BOOLEAN CacheLockAcquired = FALSE; - NTSTATUS Status = STATUS_SUCCESS; - - if (!Lcb) { - return STATUS_INVALID_PARAMETER; - } - - CurrentFcb = Lcb->ChildFcb; - if (!CurrentFcb) { - return STATUS_INVALID_PARAMETER; - } - - Fcb = CurrentFcb; - - __try { - - // Check if path is already cached in this LCB - CurrentThread = KeGetCurrentThread(); - - if (CurrentThread != Fcb->FcbLockThread) { - ExAcquireFastMutex(&Fcb->FcbNonpaged->FcbFastMutex); - Fcb->FcbLockThread = CurrentThread; - } - - Fcb->FcbLockCount++; - CacheLockAcquired = TRUE; - - // Check if FileName contains cached full path (set by CachePath=TRUE) - if (FlagOn(Lcb->Flags, UDF_LCB_FLAG_HAS_NAME_BUFFER) && - Lcb->FileName.Buffer != NULL && Lcb->FileName.Length > 0) { - // Cached full path exists - use it - FullPath->Length = Lcb->FileName.Length; - FullPath->MaximumLength = Lcb->FileName.MaximumLength; - FullPath->Buffer = (PWCHAR)ExAllocatePoolWithTag(PagedPool, - FullPath->MaximumLength, - TAG_FILE_NAME); - if (!FullPath->Buffer) { - Status = STATUS_INSUFFICIENT_RESOURCES; - __leave; - } - - RtlCopyMemory(FullPath->Buffer, Lcb->FileName.Buffer, Lcb->FileName.Length); - __leave; - } - - // Release cache lock before building path - Fcb->FcbLockCount--; - if (Fcb->FcbLockCount == 0) { - Fcb->FcbLockThread = NULL; - ExReleaseFastMutex(&Fcb->FcbNonpaged->FcbFastMutex); - } - CacheLockAcquired = FALSE; - - // - // No cached path - build it from LCB chain - // - - // Calculate total path length by walking up parent chain - CurrentLcb = Lcb; - while (CurrentLcb) { - // Add component length + separator - if (CurrentLcb->FileName.Buffer && CurrentLcb->FileName.Length > 0) { - ComponentLength = CurrentLcb->FileName.Length; - } else if (CurrentLcb->ExactCaseLinkName.Buffer && CurrentLcb->ExactCaseLinkName.Length > 0) { - ComponentLength = CurrentLcb->ExactCaseLinkName.Length; - } else { - ComponentLength = 0; - } - - if (ComponentLength > 0) { - TotalLength += ComponentLength + sizeof(WCHAR); // +1 for backslash - } - - // Move to parent - CurrentFcb = CurrentLcb->ParentFcb; - if (!CurrentFcb || (CurrentFcb->FcbState & UDF_FCB_ROOT_DIRECTORY)) { - break; - } - - // Find parent LCB - if (!IsListEmpty(&CurrentFcb->ParentLcbQueue)) { - PLIST_ENTRY ListEntry = CurrentFcb->ParentLcbQueue.Flink; - CurrentLcb = CONTAINING_RECORD(ListEntry, LCB, ChildFcbLinks); - } else { - break; - } - } - - // Add root backslash - if (TotalLength == 0) { - TotalLength = sizeof(WCHAR); - } - - // Allocate buffer for full path - Buffer = (PWCHAR)ExAllocatePoolWithTag(PagedPool, TotalLength + sizeof(WCHAR), TAG_FILE_NAME); - if (!Buffer) { - Status = STATUS_INSUFFICIENT_RESOURCES; - __leave; - } - - // Build path backwards (from end to beginning) - CurrentPosition = (PWCHAR)((PUCHAR)Buffer + TotalLength); - *CurrentPosition = 0; // Null terminator - - // Walk up chain again and copy names - CurrentLcb = Lcb; - while (CurrentLcb) { - PUNICODE_STRING ComponentName; - - if (CurrentLcb->FileName.Buffer && CurrentLcb->FileName.Length > 0) { - ComponentName = &CurrentLcb->FileName; - } else if (CurrentLcb->ExactCaseLinkName.Buffer && CurrentLcb->ExactCaseLinkName.Length > 0) { - ComponentName = &CurrentLcb->ExactCaseLinkName; - } else { - ComponentName = NULL; - } - - if (ComponentName && ComponentName->Length > 0) { - // Add backslash - CurrentPosition--; - *CurrentPosition = L'\\'; - - // Add component name - CurrentPosition -= (ComponentName->Length / sizeof(WCHAR)); - RtlCopyMemory(CurrentPosition, ComponentName->Buffer, ComponentName->Length); - } - - // Move to parent - CurrentFcb = CurrentLcb->ParentFcb; - if (!CurrentFcb || (CurrentFcb->FcbState & UDF_FCB_ROOT_DIRECTORY)) { - break; - } - - // Find parent LCB - if (!IsListEmpty(&CurrentFcb->ParentLcbQueue)) { - PLIST_ENTRY ListEntry = CurrentFcb->ParentLcbQueue.Flink; - CurrentLcb = CONTAINING_RECORD(ListEntry, LCB, ChildFcbLinks); - } else { - break; - } - } - - // Add leading backslash if not already there - if (CurrentPosition > Buffer) { - CurrentPosition--; - *CurrentPosition = L'\\'; - } - - // Set output string - FullPath->Buffer = Buffer; - FullPath->Length = (USHORT)((PUCHAR)Buffer + TotalLength - (PUCHAR)CurrentPosition); - FullPath->MaximumLength = TotalLength + sizeof(WCHAR); - - // Move string to beginning of buffer if needed - if (CurrentPosition != Buffer) { - RtlMoveMemory(Buffer, CurrentPosition, FullPath->Length + sizeof(WCHAR)); - FullPath->Length = (USHORT)((PUCHAR)Buffer + TotalLength - (PUCHAR)CurrentPosition); - } - - // Optionally cache the path in LCB - if (CachePath && NT_SUCCESS(Status)) { - CurrentThread = KeGetCurrentThread(); - Fcb = Lcb->ChildFcb; - - if (CurrentThread != Fcb->FcbLockThread) { - ExAcquireFastMutex(&Fcb->FcbNonpaged->FcbFastMutex); - Fcb->FcbLockThread = CurrentThread; - } - - Fcb->FcbLockCount++; - CacheLockAcquired = TRUE; - - // Check if cache is still empty - if (Lcb->FileName.Buffer == NULL) { - // Allocate separate buffer for cache - PWCHAR CacheBuffer = (PWCHAR)ExAllocatePoolWithTag(PagedPool, - FullPath->Length + sizeof(WCHAR), - TAG_FILE_NAME); - if (CacheBuffer) { - RtlCopyMemory(CacheBuffer, FullPath->Buffer, FullPath->Length + sizeof(WCHAR)); - Lcb->FileName.Buffer = CacheBuffer; - Lcb->FileName.Length = FullPath->Length; - Lcb->FileName.MaximumLength = FullPath->Length + sizeof(WCHAR); - - // Set flag indicating separate buffer needs freeing - SetFlag(Lcb->Flags, UDF_LCB_FLAG_HAS_NAME_BUFFER); - } - } - } - - } __finally { - - if (CacheLockAcquired) { - Fcb->FcbLockCount--; - if (Fcb->FcbLockCount == 0) { - Fcb->FcbLockThread = NULL; - ExReleaseFastMutex(&Fcb->FcbNonpaged->FcbFastMutex); - } - } - - if (!NT_SUCCESS(Status) && Buffer) { - ExFreePool(Buffer); - FullPath->Buffer = NULL; - FullPath->Length = 0; - FullPath->MaximumLength = 0; - } - } - - return Status; -} // end UDFBuildFullPathFromLcb() - - -/* - 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() - - -/* - This routine searches for the maximum known prefix path in the LCB tree. - - Starting from StartFcb, walks through path components in RemainingName, - looking for matching LCBs in the ChildLcbQueue. Returns the LCB of the - deepest matched component and updates RemainingName to the unmatched portion. - - This optimization avoids redundant directory traversal - instead of always - starting from root, we find the deepest already-opened directory in the - path and start from there. - - Parameters: - IrpContext - IRP context - StartFcb - Starting FCB (usually RootIndexFcb or RelatedFcb) - IgnoreCase - Whether to use case-insensitive comparison - CurrentFcb - Output: FCB of the deepest matched component - RemainingName - Input: full path to search; Output: unmatched portion - ShortNameMatch - Output: TRUE if match was via short name - - Returns: - PLCB - LCB of the deepest matched component, or NULL if no match -*/ -/* - Walk path components starting from StartFcb, looking for the longest - match in the in-memory LCB tree. - - On entry: *CurrentFcb == StartFcb, caller holds StartFcb FcbResource exclusive. - On return: *CurrentFcb == deepest matched FCB (locked exclusive), - all ancestor FCB locks released. - RemainingName is advanced past matched components. - Returns the LCB used to reach *CurrentFcb, or NULL if no prefix found. - */ -PLCB -UDFFindPathPrefix( - IN PIRP_CONTEXT IrpContext, - IN PFCB StartFcb, - IN BOOLEAN IgnoreCase, - IN OUT PFCB *CurrentFcb, - IN OUT PUNICODE_STRING RemainingName, - OUT PBOOLEAN ShortNameMatch - ) -{ - PLCB CurrentLcb = NULL; - PLCB MatchLcb; - UNICODE_STRING LocalRemainingName; - UNICODE_STRING ComponentName; - WCHAR UpcaseBuffer[256]; - UNICODE_STRING UpcaseName; - - ASSERT(StartFcb); - ASSERT(CurrentFcb); - ASSERT(RemainingName); - ASSERT(ShortNameMatch); - - *ShortNameMatch = FALSE; - *CurrentFcb = StartFcb; - LocalRemainingName = *RemainingName; - - while (TRUE) { - - // Stop if no more path components or current FCB is not a directory - if (LocalRemainingName.Length == 0 || - !(*CurrentFcb) || - !((*CurrentFcb)->FcbState & UDF_FCB_DIRECTORY)) { - return CurrentLcb; - } - - // Skip leading backslashes - while (LocalRemainingName.Length >= sizeof(WCHAR) && - LocalRemainingName.Buffer[0] == L'\\') { - LocalRemainingName.Buffer++; - LocalRemainingName.Length -= sizeof(WCHAR); - } - - if (LocalRemainingName.Length == 0) { - return CurrentLcb; - } - - // Stop at stream boundary - if (LocalRemainingName.Buffer[0] == L':') { - return CurrentLcb; - } - - // Extract next component (up to next '\' or ':' or end) - ComponentName.Buffer = LocalRemainingName.Buffer; - ComponentName.Length = 0; - while (ComponentName.Length < LocalRemainingName.Length) { - WCHAR ch = ComponentName.Buffer[ComponentName.Length / sizeof(WCHAR)]; - if (ch == L'\\' || ch == L':') { - break; - } - ComponentName.Length += sizeof(WCHAR); - } - if (ComponentName.Length == 0) { - return CurrentLcb; - } - ComponentName.MaximumLength = ComponentName.Length; - - // Advance local remaining name past this component - LocalRemainingName.Buffer += ComponentName.Length / sizeof(WCHAR); - LocalRemainingName.Length -= ComponentName.Length; - - // - // Search for matching component. Try splay trees first (O(log n)), - // then fall back to list iteration (O(n)) for LCBs without names, - // duplicate-name LCBs, or names too long for upcase buffer. - // *CurrentFcb is held exclusive, so trees and queue are safe. - // - MatchLcb = NULL; - - // Splay tree search: try IgnoreCase or ExactCase tree - if (IgnoreCase && (*CurrentFcb)->IgnoreCaseRoot != NULL) { - // Upcase component for ignore-case tree lookup - if (ComponentName.Length <= sizeof(UpcaseBuffer)) { - UpcaseName.Buffer = UpcaseBuffer; - UpcaseName.MaximumLength = sizeof(UpcaseBuffer); - UpcaseName.Length = ComponentName.Length; - RtlCopyMemory(UpcaseBuffer, ComponentName.Buffer, ComponentName.Length); - RtlUpcaseUnicodeString(&UpcaseName, &UpcaseName, FALSE); - - MatchLcb = UdfFindNameLink(&(*CurrentFcb)->IgnoreCaseRoot, - &UpcaseName, - FIELD_OFFSET(LCB, IgnoreCaseLinks), - FIELD_OFFSET(LCB, IgnoreCaseLinkName)); - } - } else if (!IgnoreCase && (*CurrentFcb)->ExactCaseRoot != NULL) { - MatchLcb = UdfFindNameLink(&(*CurrentFcb)->ExactCaseRoot, - &ComponentName, - FIELD_OFFSET(LCB, ExactCaseLinks), - FIELD_OFFSET(LCB, FileName)); - } - - // Try short name splay tree if no match yet - if (!MatchLcb && (*CurrentFcb)->ShortNameRoot != NULL) { - if (ComponentName.Length <= sizeof(UpcaseBuffer)) { - UpcaseName.Buffer = UpcaseBuffer; - UpcaseName.MaximumLength = sizeof(UpcaseBuffer); - UpcaseName.Length = ComponentName.Length; - RtlCopyMemory(UpcaseBuffer, ComponentName.Buffer, ComponentName.Length); - RtlUpcaseUnicodeString(&UpcaseName, &UpcaseName, FALSE); - - MatchLcb = UdfFindNameLink(&(*CurrentFcb)->ShortNameRoot, - &UpcaseName, - FIELD_OFFSET(LCB, ShortNameLinks), - FIELD_OFFSET(LCB, ShortName)); - if (MatchLcb) { - *ShortNameMatch = TRUE; - } - } - } - - // List fallback: catches LCBs without names in splay trees - // (NULL names, duplicates, long names) and handles deleted-link filtering. - if (!MatchLcb) { - for (PLIST_ENTRY ListEntry = (*CurrentFcb)->ChildLcbQueue.Flink; - ListEntry != &(*CurrentFcb)->ChildLcbQueue; - ListEntry = ListEntry->Flink) { - - PLCB Lcb = CONTAINING_RECORD(ListEntry, LCB, ParentFcbLinks); - - ASSERT(Lcb->NodeIdentifier.NodeTypeCode == UDF_NODE_TYPE_LCB); - ASSERT(Lcb->ParentFcb == *CurrentFcb); - - if (FlagOn(Lcb->Flags, UDF_LCB_FLAG_LINK_DELETED)) { - continue; - } - - // Try FileName (exact or case-insensitive) - if (Lcb->FileName.Buffer && Lcb->FileName.Length > 0 && - RtlEqualUnicodeString(&ComponentName, &Lcb->FileName, IgnoreCase)) { - MatchLcb = Lcb; - break; - } - // Try IgnoreCaseLinkName - if (IgnoreCase && - Lcb->IgnoreCaseLinkName.Buffer && Lcb->IgnoreCaseLinkName.Length > 0 && - RtlEqualUnicodeString(&ComponentName, &Lcb->IgnoreCaseLinkName, TRUE)) { - MatchLcb = Lcb; - break; - } - // Try ShortName - if (Lcb->ShortName.Buffer && Lcb->ShortName.Length > 0 && - RtlEqualUnicodeString(&ComponentName, &Lcb->ShortName, TRUE)) { - MatchLcb = Lcb; - *ShortNameMatch = TRUE; - break; - } - } - } - - // - // Validate the match: skip deleted links and deleted FCBs. - // A deleted FCB can still have LCBs in the splay tree/list if - // teardown hasn't run yet (between cleanup and close). - // Clean up stale splay entries when found. - // - if (MatchLcb && !FlagOn(MatchLcb->Flags, UDF_LCB_FLAG_LINK_DELETED) && - MatchLcb->ChildFcb && - (MatchLcb->ChildFcb->FcbState & UDF_FCB_DELETED)) { - // Child FCB was deleted — remove LCB from splay trees - // (we hold ParentFcb exclusive) and mark as deleted. - UdfRemoveNameLinks(*CurrentFcb, MatchLcb); - MatchLcb->Flags |= UDF_LCB_FLAG_LINK_DELETED; - MatchLcb = NULL; - } - - if (!MatchLcb || FlagOn(MatchLcb->Flags, UDF_LCB_FLAG_LINK_DELETED)) { - // No match or deleted link — stop, *CurrentFcb stays locked - return CurrentLcb; - } - - // Found a match. Descend into child FCB with proper locking: - // acquire child exclusive, then release parent. - CurrentLcb = MatchLcb; - *RemainingName = LocalRemainingName; - - PFCB ChildFcb = MatchLcb->ChildFcb; - - UDF_CHECK_PAGING_IO_RESOURCE(ChildFcb); - if (!UDFAcquireFcbExclusive(IrpContext, ChildFcb, TRUE)) { - // Try-lock failed. Bump references to keep child alive, - // release parent, then wait-acquire child. - PVCB Vcb = (PVCB)IrpContext->Vcb; - - UDFLockVcb(IrpContext, Vcb); - ChildFcb->FcbReference += 1; - MatchLcb->Reference += 1; - UDFUnlockVcb(IrpContext, Vcb); - - UDFReleaseFcb(IrpContext, *CurrentFcb); - - UDFAcquireFcbExclusive(IrpContext, ChildFcb, FALSE); - - UDFLockVcb(IrpContext, Vcb); - ChildFcb->FcbReference -= 1; - MatchLcb->Reference -= 1; - UDFUnlockVcb(IrpContext, Vcb); - } else { - // Try-lock succeeded. Release parent. - UDFReleaseFcb(IrpContext, *CurrentFcb); - } - - *CurrentFcb = ChildFcb; - } - - return CurrentLcb; -} // end UDFFindPathPrefix() - - -/* - Atomically rename an LCB and optionally move it to a new parent directory. - Updates the file name, moves between parent ChildLcbQueue lists, - and adjusts parent reference counts — all in one call. - - NewParentFcb = NULL for same-directory rename (name change only). -*/ -NTSTATUS -UDFRenameMovePrefix( - IN PIRP_CONTEXT IrpContext, - IN PLCB Lcb, - IN PUNICODE_STRING NewName, - IN PFCB NewParentFcb OPTIONAL - ) -{ - PWCHAR NewBuffer; - USHORT NewLength; - BOOLEAN OldBufferEmbedded; - - if (!Lcb || !NewName || NewName->Length == 0) { - return STATUS_INVALID_PARAMETER; - } - - ASSERT(Lcb->NodeIdentifier.NodeTypeCode == UDF_NODE_TYPE_LCB); - - NewLength = NewName->Length; - - // Allocate new buffer for the name - NewBuffer = (PWCHAR)MyAllocatePool__(NonPagedPool, NewLength + sizeof(WCHAR)); - if (!NewBuffer) { - return STATUS_INSUFFICIENT_RESOURCES; - } - - RtlCopyMemory(NewBuffer, NewName->Buffer, NewLength); - NewBuffer[NewLength / sizeof(WCHAR)] = 0; - - // Remove from current parent's splay trees before changing names. - // Caller must hold ParentFcb exclusive (enforced in fileinfo.cpp). - if (Lcb->ParentFcb) { - UdfRemoveNameLinks(Lcb->ParentFcb, Lcb); - } - - // Check if old buffer was embedded in LCB structure - // or separately allocated. Only free if separately allocated. - OldBufferEmbedded = (Lcb->FileName.Buffer != NULL && - (PUCHAR)Lcb->FileName.Buffer >= (PUCHAR)Lcb && - (PUCHAR)Lcb->FileName.Buffer < (PUCHAR)Lcb + Lcb->NodeIdentifier.NodeByteSize); - - if (Lcb->FileName.Buffer && !OldBufferEmbedded) { - MyFreePool__(Lcb->FileName.Buffer); - } - - // Set new name (component name, not cached full path) - Lcb->FileName.Buffer = NewBuffer; - Lcb->FileName.Length = NewLength; - Lcb->FileName.MaximumLength = NewLength + sizeof(WCHAR); - - // Clear cached full path flag — FileName now holds component name only - ClearFlag(Lcb->Flags, UDF_LCB_FLAG_HAS_NAME_BUFFER); - - // Also update ExactCaseLinkName to point to same buffer - Lcb->ExactCaseLinkName = Lcb->FileName; - - // Free old IgnoreCaseLinkName if separately allocated - if (Lcb->IgnoreCaseLinkName.Buffer != NULL) { - BOOLEAN IgnoreCaseEmbedded = ((PUCHAR)Lcb->IgnoreCaseLinkName.Buffer >= (PUCHAR)Lcb && - (PUCHAR)Lcb->IgnoreCaseLinkName.Buffer < (PUCHAR)Lcb + Lcb->NodeIdentifier.NodeByteSize); - if (!IgnoreCaseEmbedded) { - ExFreePool(Lcb->IgnoreCaseLinkName.Buffer); - } - } - - // Rebuild IgnoreCaseLinkName — upcased version of new name. - // Required for IgnoreCase splay tree lookup (Windows opens case-insensitive). - { - PWCHAR UpcaseBuffer = (PWCHAR)ExAllocatePoolWithTag(PagedPool, - NewLength + sizeof(WCHAR), - TAG_FILE_NAME); - if (UpcaseBuffer) { - Lcb->IgnoreCaseLinkName.Buffer = UpcaseBuffer; - Lcb->IgnoreCaseLinkName.Length = NewLength; - Lcb->IgnoreCaseLinkName.MaximumLength = NewLength + sizeof(WCHAR); - RtlCopyMemory(UpcaseBuffer, NewBuffer, NewLength); - UpcaseBuffer[NewLength / sizeof(WCHAR)] = 0; - RtlUpcaseUnicodeString(&Lcb->IgnoreCaseLinkName, &Lcb->IgnoreCaseLinkName, FALSE); - } else { - // Allocation failed — clear IgnoreCaseLinkName. - // File will still be findable via list fallback. - Lcb->IgnoreCaseLinkName.Buffer = NULL; - Lcb->IgnoreCaseLinkName.Length = 0; - Lcb->IgnoreCaseLinkName.MaximumLength = 0; - } - } - - // Clear stale ShortName — old 8.3 name is invalid after rename. - // The embedded buffer data stays in LCB allocation but won't be used. - // Short name will be regenerated on next open if needed. - if (Lcb->ShortName.Buffer != NULL) { - BOOLEAN ShortNameEmbedded = ((PUCHAR)Lcb->ShortName.Buffer >= (PUCHAR)Lcb && - (PUCHAR)Lcb->ShortName.Buffer < (PUCHAR)Lcb + Lcb->NodeIdentifier.NodeByteSize); - if (!ShortNameEmbedded) { - ExFreePool(Lcb->ShortName.Buffer); - } - Lcb->ShortName.Buffer = NULL; - Lcb->ShortName.Length = 0; - Lcb->ShortName.MaximumLength = 0; - } - - // Move LCB to new parent directory if specified (cross-directory rename) - if (NewParentFcb && NewParentFcb != Lcb->ParentFcb) { - - PFCB OldParentFcb = Lcb->ParentFcb; - PUDF_FILE_INFO OldParentFileInfo = OldParentFcb ? OldParentFcb->FileInfo : NULL; - - // Remove from old parent's ChildLcbQueue - RemoveEntryList(&Lcb->ParentFcbLinks); - - // Insert into new parent's ChildLcbQueue - InsertHeadList(&NewParentFcb->ChildLcbQueue, &Lcb->ParentFcbLinks); - - // Update LCB to point to new parent - Lcb->ParentFcb = NewParentFcb; - - // Adjust reference counts - if (OldParentFcb) { - ASSERT(OldParentFcb->FcbReference > 0); - InterlockedDecrement((PLONG)&OldParentFcb->FcbReference); - - if (OldParentFileInfo && OldParentFcb->Vcb) { - UDFCloseFile__(IrpContext, OldParentFcb->Vcb, OldParentFileInfo); - } - } - - InterlockedIncrement((PLONG)&NewParentFcb->FcbReference); - - if (NewParentFcb->FileInfo) { - UDFReferenceFile__(NewParentFcb->FileInfo); - } - } - - // Re-insert into splay trees of (possibly new) parent. - // Caller must hold the (new) ParentFcb exclusive. - if (Lcb->ParentFcb) { - UdfInsertNameLinks(Lcb->ParentFcb, Lcb); - } - - return STATUS_SUCCESS; -} // end UDFRenameMovePrefix() diff --git a/drivers/filesystems/udfs/protos.h b/drivers/filesystems/udfs/protos.h index d2c13f3a016d1..584c9e4f57ab6 100644 --- a/drivers/filesystems/udfs/protos.h +++ b/drivers/filesystems/udfs/protos.h @@ -66,8 +66,14 @@ UDFFastDecodeFileObject ( _Out_ PFCB *Fcb ); +PCCB +UDFDecodeFileObjectCcb( + _In_ PFILE_OBJECT FileObject + ); + + /************************************************************************* -* Prototypes for the file create.c +* Prototypes for the file create.cpp *************************************************************************/ extern NTSTATUS NTAPI UDFCreate( IN PDEVICE_OBJECT DeviceObject, // the logical volume device object @@ -79,32 +85,42 @@ UDFCommonCreate( IN PIRP Irp ); -NTSTATUS -UDFOpenObjectByFileId( - _In_ PIRP_CONTEXT IrpContext, - _In_ PIO_STACK_LOCATION IrpSp, - _In_ PVCB Vcb, - _Inout_ PFCB *CurrentFcb - ); - NTSTATUS UDFFirstOpenFile( IN PIRP_CONTEXT IrpContext, + IN PIO_STACK_LOCATION IrpSp, IN PVCB Vcb, + IN PFILE_OBJECT PtrNewFileObject, OUT PFCB* PtrNewFcb, IN PUDF_FILE_INFO RelatedFileInfo, - IN PUDF_FILE_INFO NewFileInfo + IN PUDF_FILE_INFO NewFileInfo, + IN PUNICODE_STRING LocalPath, + IN PUNICODE_STRING CurName, + IN ULONG CreateDisposition + ); + +NTSTATUS +UDFCompleteFcbOpen( + _In_ PIRP_CONTEXT IrpContext, + _In_ PIO_STACK_LOCATION IrpSp, + _In_ PVCB Vcb, + _Inout_ PFCB *CurrentFcb, + _In_ TYPE_OF_OPEN TypeOfOpen, + _In_ ULONG UserCcbFlags, + _In_ ULONG CreateDisposition ); NTSTATUS UDFInitializeFCB( IN PFCB PtrNewFcb, // FCB structure to be initialized IN PVCB Vcb, // logical volume (VCB) pointer - IN ULONG Flags // is this a file/directory, etc. + IN PtrUDFObjectName PtrObjectName, // name of the object + IN ULONG Flags, // is this a file/directory, etc. + IN PFILE_OBJECT FileObject // optional file object to be initialized ); /************************************************************************* -* Prototypes for the file cleanup.c +* Prototypes for the file cleanup.cpp *************************************************************************/ extern NTSTATUS NTAPI UDFCleanup( PDEVICE_OBJECT DeviceObject, // the logical volume device object @@ -114,8 +130,17 @@ 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.c +* Prototypes for the file close.cpp *************************************************************************/ extern NTSTATUS NTAPI UDFClose( PDEVICE_OBJECT DeviceObject, // the logical volume device object @@ -133,7 +158,7 @@ VOID UDFTeardownStructures( _In_ PIRP_CONTEXT IrpContext, _Inout_ PFCB StartingFcb, - _In_ BOOLEAN Recursive, // TRUE if this is a recursive call (for hard links) + _In_ ULONG TreeLength, _Out_ PBOOLEAN RemovedStartingFcb ); @@ -151,7 +176,7 @@ UDFFspClose( UDFCloseAllSystemDelayedInDir((Fcb)->Vcb, (Fcb)->FileInfo) /************************************************************************* -* Prototypes for the file dircntrl.c +* Prototypes for the file dircntrl.cpp *************************************************************************/ extern NTSTATUS NTAPI UDFDirControl( PDEVICE_OBJECT DeviceObject, // the logical volume device object @@ -178,7 +203,7 @@ PFCB Fcb, PCCB Ccb); /************************************************************************* -* Prototypes for the file devcntrl.c +* Prototypes for the file devcntrl.cpp *************************************************************************/ extern NTSTATUS NTAPI UDFDeviceControl( PDEVICE_OBJECT DeviceObject, // the logical volume device object @@ -199,7 +224,7 @@ extern NTSTATUS NTAPI UDFHandleQueryPath( PVOID BufferPointer); /************************************************************************* -* Prototypes for the file fastio.c +* Prototypes for the file fastio.cpp *************************************************************************/ extern BOOLEAN NTAPI UDFFastIoCheckIfPossible( IN PFILE_OBJECT FileObject, @@ -335,7 +360,7 @@ UDFFastIoCopyWrite( ); /************************************************************************* -* Prototypes for the file fileinfo.c +* Prototypes for the file fileinfo.cpp *************************************************************************/ extern NTSTATUS UDFCommonQueryInfo( @@ -400,8 +425,7 @@ UDFGetFileStreamInformation( ); extern NTSTATUS UDFSetBasicInformation( - IN PIRP_CONTEXT IrpContext, - IN PFCB Fcb, + IN PFCB Fcb, IN PCCB Ccb, IN PFILE_OBJECT FileObject, IN PFILE_BASIC_INFORMATION PtrBuffer); @@ -445,11 +469,6 @@ UDFSetEndOfFileInfo( IN PFILE_END_OF_FILE_INFORMATION PtrBuffer ); -BOOLEAN -UDFCheckDirOpenHandles( - IN PFCB DirectoryFcb - ); - NTSTATUS UDFSetRenameInfo( IN PIRP_CONTEXT IrpContext, @@ -497,7 +516,7 @@ UDFHardLink( ); /************************************************************************* -* Prototypes for the file flush.c +* Prototypes for the file flush.cpp *************************************************************************/ extern NTSTATUS NTAPI UDFFlushBuffers( PDEVICE_OBJECT DeviceObject, // the logical volume device object @@ -544,7 +563,7 @@ extern VOID UDFFlushTryBreak( IN PVCB Vcb); /************************************************************************* -* Prototypes for the file fscntrl.c +* Prototypes for the file fscntrl.cpp *************************************************************************/ extern NTSTATUS NTAPI UDFFSControl( @@ -640,7 +659,7 @@ UDFCommonPnp( ); /************************************************************************* -* Prototypes for the file LockCtrl.c +* Prototypes for the file LockCtrl.cpp *************************************************************************/ extern NTSTATUS NTAPI UDFLockControl( @@ -651,9 +670,7 @@ extern NTSTATUS NTAPI UDFCommonLockControl( IN PIRP_CONTEXT IrpContext, IN PIRP Irp); -BOOLEAN -NTAPI -UDFFastLock( +extern BOOLEAN NTAPI UDFFastLock( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER Length, @@ -690,8 +707,13 @@ UDFFastUnlockAllByKey( ); /************************************************************************* -* Prototypes for the file misc.c +* Prototypes for the file misc.cpp *************************************************************************/ +extern NTSTATUS UDFInitializeZones( +VOID); + +extern VOID UDFDestroyZones( +VOID); _IRQL_requires_max_(APC_LEVEL) __drv_dispatchType(DRIVER_DISPATCH) @@ -740,114 +762,13 @@ PCCB UDFCreateCcb( ); -VOID -UDFDeallocateCcb( - PCCB Ccb - ); +extern VOID UDFReleaseCCB(PCCB Ccb); VOID UDFDeleteCcb( PCCB Ccb ); -// prefxsup.c - LCB functions -PLCB -UDFInsertPrefix( - IN PIRP_CONTEXT IrpContext, - IN PFCB ParentFcb, - IN PFCB ChildFcb, - IN PUNICODE_STRING FileName OPTIONAL, - IN PUNICODE_STRING CaseFileName OPTIONAL, - IN PUNICODE_STRING ShortName OPTIONAL, - IN ULONGLONG InitialOffset - ); - -VOID -UDFRemovePrefix( - IN PIRP_CONTEXT IrpContext, - IN PLCB Lcb - ); - -// Insert LCB into parent FCB's splay trees (ExactCase, IgnoreCase, ShortName). -// Caller must hold ParentFcb exclusive. -VOID -UdfInsertNameLinks( - IN PFCB ParentFcb, - IN PLCB Lcb - ); - -// Remove LCB from parent FCB's splay trees only (not from linked lists). -// Caller must hold ParentFcb exclusive. -VOID -UdfRemoveNameLinks( - IN PFCB ParentFcb, - 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 PUNICODE_STRING FileName OPTIONAL, - IN PUNICODE_STRING CaseFileName OPTIONAL, - IN PUNICODE_STRING ShortName OPTIONAL, - IN ULONGLONG InitialOffset - ); - -VOID -UDFReleasePrefix( - IN PIRP_CONTEXT IrpContext, - IN PLCB Lcb - ); - -NTSTATUS -UDFBuildFullPathFromLcb( - IN PIRP_CONTEXT IrpContext, - IN PLCB Lcb, - OUT PUNICODE_STRING FullPath, - IN BOOLEAN CachePath - ); - -BOOLEAN -UDFReleasePrefixImmediate( - IN PIRP_CONTEXT IrpContext, - IN PLCB Lcb, - IN BOOLEAN CloseParentFileInfo - ); - -NTSTATUS -UDFRenameMovePrefix( - IN PIRP_CONTEXT IrpContext, - IN PLCB Lcb, - IN PUNICODE_STRING NewName, - IN PFCB NewParentFcb OPTIONAL - ); - -PLCB -UDFFindPathPrefix( - IN PIRP_CONTEXT IrpContext, - IN PFCB StartFcb, - IN BOOLEAN IgnoreCase, - IN OUT PFCB *CurrentFcb, - IN OUT PUNICODE_STRING RemainingName, - OUT PBOOLEAN ShortNameMatch - ); - -PFCB -UDFLookupFcbTable ( - _In_ PIRP_CONTEXT IrpContext, - _In_ PVCB Vcb, - _In_ FILE_ID FileId - ); - PFCB UDFCreateFcb ( _In_ PIRP_CONTEXT IrpContext, @@ -858,16 +779,12 @@ UDFCreateFcb ( VOID UDFDeleteFcb( - _In_opt_ PIRP_CONTEXT IrpContext, - _In_ PFCB Fcb - ); - -VOID -UDFInsertFcbIntoTable( _In_ PIRP_CONTEXT IrpContext, _In_ PFCB Fcb ); +VOID UDFCleanUpFCB(PFCB Fcb); + _Ret_valid_ PIRP_CONTEXT UDFCreateIrpContext( _In_ PIRP Irp, @@ -965,13 +882,13 @@ UDFCreateFileLock( ); /************************************************************************* -* Prototypes for the file NameSup.c +* Prototypes for the file NameSup.cpp *************************************************************************/ #include "namesup.h" /************************************************************************* -* Prototypes for the file Pnp.c +* Prototypes for the file Pnp.cpp *************************************************************************/ NTSTATUS NTAPI @@ -981,7 +898,7 @@ UDFPnp ( ); /************************************************************************* -* Prototypes for the file read.c +* Prototypes for the file read.cpp *************************************************************************/ extern NTSTATUS NTAPI UDFRead( PDEVICE_OBJECT DeviceObject, // the logical volume device object @@ -1035,7 +952,7 @@ UDFSetAccessRights( USHORT ShareAccess); /************************************************************************* -* Prototypes for the file Shutdown.c +* Prototypes for the file Shutdown.cpp *************************************************************************/ NTSTATUS @@ -1045,9 +962,9 @@ UDFCommonShutdown( ); /************************************************************************* -* Prototypes for the file UDFinit.c +* Prototypes for the file UDFinit.cpp *************************************************************************/ -NTSTATUS NTAPI DriverEntry( +extern "C" NTSTATUS NTAPI DriverEntry( PDRIVER_OBJECT DriverObject, // created by the I/O sub-system PUNICODE_STRING RegistryPath); // path to the registry key @@ -1055,7 +972,7 @@ extern VOID NTAPI UDFInitializeFunctionPointers( PDRIVER_OBJECT DriverObject); // created by the I/O sub-system /************************************************************************* -* Prototypes for the file verify.c +* Prototypes for the file verify.cpp *************************************************************************/ VOID @@ -1107,7 +1024,7 @@ UDFCompareVcb( ); /************************************************************************* -* Prototypes for the file VolInfo.c +* Prototypes for the file VolInfo.cpp *************************************************************************/ extern NTSTATUS NTAPI UDFQueryVolInfo(PDEVICE_OBJECT DeviceObject, PIRP Irp); @@ -1134,7 +1051,7 @@ UDFCommonSetVolInfo( ); /************************************************************************* -* Prototypes for the file write.c +* Prototypes for the file write.cpp *************************************************************************/ extern NTSTATUS NTAPI UDFWrite( PDEVICE_OBJECT DeviceObject, // the logical volume device object @@ -1263,35 +1180,6 @@ UDFMarkDevForVerifyIfVcbMounted( (V)->VcbLockThread = NULL; \ ExReleaseFastMutexUnsafe( &(V)->VcbMutex ) -#define UDFLockFcbTable(IC,V) \ - ASSERT(KeAreApcsDisabled()); \ - ExAcquireFastMutexUnsafe( &(V)->FcbTableMutex ); \ - (V)->FcbTableLockThread = PsGetCurrentThread() - -#define UDFUnlockFcbTable(IC,V) \ - (V)->FcbTableLockThread = NULL; \ - ExReleaseFastMutexUnsafe( &(V)->FcbTableMutex ) - -#define UDFLockFcb(IC,F) { \ - PVOID _CurrentThread = PsGetCurrentThread(); \ - if (_CurrentThread != (F)->FcbLockThread) { \ - ASSERT(KeAreApcsDisabled()); \ - ExAcquireFastMutexUnsafe( &(F)->FcbNonpaged->FcbFastMutex ); \ - ASSERT( (F)->FcbLockCount == 0 ); \ - (F)->FcbLockThread = _CurrentThread; \ - } \ - (F)->FcbLockCount += 1; \ -} - -#define UDFUnlockFcb(IC,F) { \ - ASSERT( PsGetCurrentThread() == (F)->FcbLockThread); \ - (F)->FcbLockCount -= 1; \ - if ((F)->FcbLockCount == 0) { \ - (F)->FcbLockThread = NULL; \ - ExReleaseFastMutexUnsafe( &(F)->FcbNonpaged->FcbFastMutex ); \ - } \ -} - #define UDFIncrementCleanupCounts(IC,F) { \ ASSERT_LOCKED_VCB( (F)->Vcb ); \ (F)->FcbCleanup += 1; \ @@ -1329,13 +1217,13 @@ UDFMarkDevForVerifyIfVcbMounted( UdfData.UdfDataLockThread = NULL; \ ExReleaseFastMutexUnsafe(&UdfData.UdfDataMutex) -typedef enum TYPE_OF_ACQUIRE { +enum TYPE_OF_ACQUIRE { AcquireExclusive, AcquireShared, AcquireSharedStarveExclusive -} TYPE_OF_ACQUIRE; +}; _Requires_lock_held_(_Global_critical_region_) _When_(Type == AcquireExclusive && return != FALSE, _Acquires_exclusive_lock_(*Resource)) @@ -1383,7 +1271,7 @@ UDFAcquireResource( #define UDFReleasePagingIo(IC,F) \ ExReleaseResourceLite((F)->Header.PagingIoResource) -static inline +inline ULONG UDFHighBit( ULONG Word @@ -1407,7 +1295,7 @@ UDFHighBit( #define SectorSize(V) ((V)->SectorSize) -static inline +inline ULONG SectorAlign( PVCB Vcb, @@ -1417,7 +1305,7 @@ SectorAlign( return (Length + (Vcb->SectorSize - 1)) & ~(Vcb->SectorSize - 1); } -static inline +inline ULONGLONG LlSectorAlign( PVCB Vcb, @@ -1439,7 +1327,7 @@ UDFSetThreadContext( (IC)->ThreadContext = NULL -static inline +inline BOOLEAN UdfIsExtendedFESupported( _In_ PVCB Vcb ) @@ -1447,7 +1335,7 @@ BOOLEAN UdfIsExtendedFESupported( return Vcb->NSRDesc == VRS_NSR03_FOUND; } -static inline +inline BOOLEAN UDFIsStreamsSupported( _In_ PVCB Vcb ) diff --git a/drivers/filesystems/udfs/read.c b/drivers/filesystems/udfs/read.c index 214c2470608fb..c920331dee579 100644 --- a/drivers/filesystems/udfs/read.c +++ b/drivers/filesystems/udfs/read.c @@ -5,7 +5,7 @@ //////////////////////////////////////////////////////////////////// /************************************************************************* * -* File: Read.c +* File: Read.cpp * * Module: UDF File System Driver (Kernel mode execution only) * diff --git a/drivers/filesystems/udfs/secursup.c b/drivers/filesystems/udfs/secursup.c index 3b64f057b7ff5..8328d7599e110 100644 --- a/drivers/filesystems/udfs/secursup.c +++ b/drivers/filesystems/udfs/secursup.c @@ -5,7 +5,7 @@ //////////////////////////////////////////////////////////////////// /************************************************************************* * -* File: SecurSup.c +* File: SecurSup.cpp * * Module: UDF File System Driver (Kernel mode execution only) * diff --git a/drivers/filesystems/udfs/shutdown.c b/drivers/filesystems/udfs/shutdown.c index 682630e26c6ff..9dbb827bcfe09 100644 --- a/drivers/filesystems/udfs/shutdown.c +++ b/drivers/filesystems/udfs/shutdown.c @@ -5,7 +5,7 @@ //////////////////////////////////////////////////////////////////// /************************************************************************* * -* File: Shutdown.c +* File: Shutdown.cpp * * Module: UDF File System Driver (Kernel mode execution only) * diff --git a/drivers/filesystems/udfs/strucsup.c b/drivers/filesystems/udfs/strucsup.c index 6b3b815452fc4..6e00af7d5bd4f 100644 --- a/drivers/filesystems/udfs/strucsup.c +++ b/drivers/filesystems/udfs/strucsup.c @@ -29,24 +29,7 @@ typedef struct _FCB_TABLE_ELEMENT { RtlDeleteElementGenericTable( &(F)->Vcb->FcbTable, &_Key ); \ } -// -// Public wrapper for inserting FCB into FcbTable. -// Called from create.c 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); -} - -static inline +inline PFCB_NONPAGED UDFAllocateFcbNonpaged( ) @@ -54,7 +37,7 @@ UDFAllocateFcbNonpaged( return (PFCB_NONPAGED)ExAllocateFromNPagedLookasideList(&UdfData.UDFNonPagedFcbLookasideList); } -static inline +inline PFCB UDFAllocateFcbIndex( ) @@ -62,7 +45,7 @@ UDFAllocateFcbIndex( return (PFCB)ExAllocateFromPagedLookasideList(&UdfData.UDFFcbIndexLookasideList); } -static inline +inline PFCB UDFAllocateFcbData( ) @@ -70,7 +53,7 @@ UDFAllocateFcbData( return (PFCB)ExAllocateFromPagedLookasideList(&UdfData.UDFFcbDataLookasideList); } -static inline +inline PFCB UDFAllocateFcb( ) @@ -78,7 +61,7 @@ UDFAllocateFcb( return (PFCB)ExAllocatePoolWithTag(NonPagedPool, sizeof(FCB), TAG_FCB); } -static inline +inline VOID UDFDeallocateFcbNonpaged( PFCB_NONPAGED FcbNonpaged @@ -87,7 +70,7 @@ UDFDeallocateFcbNonpaged( ExFreeToNPagedLookasideList(&UdfData.UDFNonPagedFcbLookasideList, FcbNonpaged); } -static inline +inline VOID UDFDeallocateFcbIndex( PFCB Fcb @@ -96,7 +79,7 @@ UDFDeallocateFcbIndex( ExFreeToPagedLookasideList(&UdfData.UDFFcbIndexLookasideList, Fcb); } -static inline +inline VOID UDFDeallocateFcbData( PFCB Fcb @@ -146,7 +129,8 @@ Return Value: ExInitializeResourceLite(&FcbNonpaged->FcbResource); ExInitializeFastMutex(&FcbNonpaged->FcbMutex); ExInitializeFastMutex(&FcbNonpaged->AdvancedFcbHeaderMutex); - ExInitializeFastMutex(&FcbNonpaged->FcbFastMutex); + + ExInitializeResourceLite(&FcbNonpaged->CcbListResource); return FcbNonpaged; } @@ -180,6 +164,7 @@ Return Value: ExDeleteResourceLite(&FcbNonpaged->FcbResource); ExDeleteResourceLite(&FcbNonpaged->FcbPagingIoResource); + ExDeleteResourceLite(&FcbNonpaged->CcbListResource); UDFDeallocateFcbNonpaged(FcbNonpaged); @@ -188,7 +173,7 @@ Return Value: VOID UDFDeleteFcb( - _In_opt_ PIRP_CONTEXT IrpContext, + _In_ PIRP_CONTEXT IrpContext, _In_ PFCB Fcb ) @@ -200,16 +185,9 @@ 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: - IrpContext - Optional IrpContext (unused but kept for API consistency). - - Fcb - This is the Fcb to deallocate. + Fcb - This is the Fcb to deallcoate. Return Value: @@ -219,409 +197,101 @@ Return Value: { PVCB Vcb = NULL; - PAGED_CODE(); - UNREFERENCED_PARAMETER(IrpContext); + // Sanity check the counts. - UDFPrint(("UDFDeleteFcb: %x\n", Fcb)); + NT_ASSERT( Fcb->FcbCleanup == 0 ); + NT_ASSERT( Fcb->FcbReference == 0 ); - ASSERT_FCB(Fcb); + // Release any Filter Context structures associated with this FCB - // Sanity check the counts. + // FsRtlTeardownPerStreamContexts(&Fcb->Header); - NT_ASSERT( Fcb->FcbCleanup == 0 ); - NT_ASSERT( Fcb->FcbReference == 0 ); + // Start with the common structures. - // 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)); + // CdUninitializeMcb( IrpContext, Fcb ); - // LCB queues must be empty - all LCBs should be removed during teardown - NT_ASSERT(IsListEmpty(&Fcb->ParentLcbQueue)); - NT_ASSERT(IsListEmpty(&Fcb->ChildLcbQueue)); + // CdDeleteFcbNonpaged( IrpContext, Fcb->FcbNonpaged ); - // NOTE: FCB no longer stores FCBName - all names are stored in LCB. - // No FCBName cleanup needed. + // + // Check if we need to deallocate the prefix name buffer. + // - // Release any Filter Context structures associated with this FCB. - // Only if FCB was fully initialized (Header.Resource is set by - // UDFInitializeFCB). + // if ((Fcb->FileNamePrefix.ExactCaseName.FileName.Buffer != (PWCHAR) Fcb->FileNamePrefix.FileNameBuffer) && + // (Fcb->FileNamePrefix.ExactCaseName.FileName.Buffer != NULL)) { - if (Fcb->Header.Resource) { - FsRtlTeardownPerStreamContexts(&Fcb->Header); - } + // CdFreePool( &Fcb->FileNamePrefix.ExactCaseName.FileName.Buffer ); + // } - // Delete non-paged portion (resources + dealloc). + // + // Now look at the short name prefix. + // + + // if (Fcb->ShortNamePrefix != NULL) { - UDFDeleteFcbNonpaged(IrpContext, Fcb->FcbNonpaged); + // CdFreePool( &Fcb->ShortNamePrefix ); + // } - // Now do the type specific structures. + // + // Now do the type specific structures. + // switch (Fcb->Header.NodeTypeCode) { case UDF_NODE_TYPE_INDEX: - if (Fcb == Fcb->Vcb->RootIndexFcb) { + // NT_ASSERT( Fcb->FileObject == NULL ); + // NT_ASSERT( IsListEmpty( &Fcb->FcbQueue )); - Vcb = Fcb->Vcb; - Vcb->RootIndexFcb = NULL; - } + // if (Fcb == Fcb->Vcb->RootIndexFcb) { + + // Vcb = Fcb->Vcb; + // Vcb->RootIndexFcb = NULL; + + // } else if (Fcb == Fcb->Vcb->PathTableFcb) { + + // Vcb = Fcb->Vcb; + // Vcb->PathTableFcb = NULL; + // } UDFDeallocateFcbIndex(Fcb); break; case UDF_NODE_TYPE_DATA: - if (Fcb->FileLock != NULL) { + // if (Fcb->FileLock != NULL) { - FsRtlFreeFileLock( Fcb->FileLock ); - } + // FsRtlFreeFileLock( Fcb->FileLock ); + // } - if (Fcb == Fcb->Vcb->VolumeDasdFcb) { + // FsRtlUninitializeOplock( CdGetFcbOplock(Fcb) ); - Vcb = Fcb->Vcb; - Vcb->VolumeDasdFcb = NULL; - } + if (Fcb == Fcb->Vcb->VolumeDasdFcb) { + + __debugbreak(); + + 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. - - 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) { - UDFReleaseFcb(IrpContext, ParentFcb); - } - } - - // - // Get this new parent Fcb to work on. - // - ParentFcb = Lcb->ParentFcb; - UDFAcquireFcbExclusive(IrpContext, ParentFcb, FALSE); - } - - // - // 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); - UDFReleaseFcb(IrpContext, ParentFcb); - 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 (this frees the LCB) - // - UDFRemovePrefix(IrpContext, Lcb); - - // - // Decrement parent's references, - // parent refs were incremented in UDFAcquirePrefix 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 ordering: FcbTableMutex (outer) before VcbMutex (inner). - // - UDFLockFcbTable(IrpContext, Vcb); - UDFLockVcb(IrpContext, Vcb); - - if (CurrentFcb->FcbReference != 0) { - // - // Nope, nothing more to do. Stop right now. - // - UDFUnlockVcb(IrpContext, Vcb); - UDFUnlockFcbTable(IrpContext, Vcb); - - if (ParentFcb != NULL) { - UDFReleaseFcb(IrpContext, ParentFcb); - } - 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); - UDFUnlockFcbTable(IrpContext, Vcb); - - if (ShouldDelete && CurrentFcb->FileInfo) { - - // no more references... current file/dir MUST DIE!!! - if (Delete) { - UDFReferenceFile__(CurrentFcb->FileInfo); - UDFFlushFile__(IrpContext, Vcb, CurrentFcb->FileInfo, 0); - 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, 0); - } - else { - // File is already deleted - clear Modified flags without flushing to disk. - // The deletion was already written in cleanup.cpp via UDFUnlinkFile__. - // Any pending modifications are irrelevant for deleted files. - PUDF_FILE_INFO FileInfo = CurrentFcb->FileInfo; - PUDF_DATALOC_INFO Dloc = FileInfo->Dloc; - if (Dloc) { - Dloc->FE_Flags &= ~UDF_FE_FLAG_FE_MODIFIED; - Dloc->DataLoc.Modified = FALSE; - Dloc->DataLoc.Flags &= ~EXTENT_FLAG_PREALLOCATED; - Dloc->AllocLoc.Modified = FALSE; - Dloc->FELoc.Modified = FALSE; - } - // Also clear FI_Modified flag in parent's DirIndex - if (FileInfo->ParentFile && FileInfo->ParentFile->Dloc) { - PDIR_INDEX_ITEM DirNdx = UDFDirIndex( - FileInfo->ParentFile->Dloc->DirIndex, - FileInfo->Index); - if (DirNdx) { - DirNdx->FI_Flags &= ~UDF_FI_FLAG_FI_MODIFIED; - } - } - } - - // 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. - UDFReleaseFcb(IrpContext, CurrentFcb); - - // 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; - } - - UDFReleaseFcb(IrpContext, CurrentFcb); - CurrentFcb = ParentFcb; - ParentFcb = NULL; - AcquiredCurrentFcb = TRUE; - } - } else { - // Cannot delete - release and move to parent - if (CurrentFcb != StartingFcb || AcquiredCurrentFcb) { - UDFReleaseFcb(IrpContext, CurrentFcb); - } - CurrentFcb = ParentFcb; - ParentFcb = NULL; - AcquiredCurrentFcb = TRUE; - } - - } while (CurrentFcb != NULL); - - } _SEH2_FINALLY { - - // - // Release the current Fcb if we have acquired it. - // - if (AcquiredCurrentFcb && (CurrentFcb != NULL)) { - UDFReleaseFcb(IrpContext, CurrentFcb); - } - - // - // 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, @@ -871,7 +541,9 @@ NTSTATUS UDFInitializeFCB( IN PFCB Fcb, // FCB structure to be initialized IN PVCB Vcb, // logical volume (VCB) pointer - IN ULONG Flags) // is this a file/directory, etc. + IN PtrUDFObjectName PtrObjectName, // name of the object + IN ULONG Flags, // is this a file/directory, etc. + IN PFILE_OBJECT FileObject) // optional file object to be initialized { ASSERT_LOCKED_VCB(Vcb); @@ -886,25 +558,16 @@ UDFInitializeFCB( Fcb->FcbState = Flags; - // NOTE: FCB is NOT added to FcbTable here. - // Caller is responsible for calling UDFInsertFcbIntoTable after - // FCB is fully initialized. + UDFInsertFcbTable(IrpContext, Fcb); + SetFlag(Fcb->FcbState, FCB_STATE_IN_FCB_TABLE); // initialize the various list heads - InitializeListHead(&Fcb->ParentLcbQueue); - InitializeListHead(&Fcb->ChildLcbQueue); - - // Splay tree roots for fast child lookup by name - Fcb->ExactCaseRoot = NULL; - Fcb->IgnoreCaseRoot = NULL; - Fcb->ShortNameRoot = NULL; + InitializeListHead(&Fcb->NextCCB); Fcb->FcbReference = 0; Fcb->FcbCleanup = 0; - // Initialize file name cache synchronization - Fcb->FcbLockThread = NULL; - Fcb->FcbLockCount = 0; + Fcb->FCBName = PtrObjectName; Fcb->Vcb = Vcb; @@ -1075,7 +738,7 @@ UDFInitializeVCB( ExInitializeResourceLite(&Vcb->VcbResource); ExInitializeResourceLite(&Vcb->BitMapResource1); - + ExInitializeResourceLite(&Vcb->FileIdResource); ExInitializeResourceLite(&Vcb->DlocResource); ExInitializeResourceLite(&Vcb->DlocResource2); ExInitializeResourceLite(&Vcb->FlushResource); @@ -1083,7 +746,6 @@ UDFInitializeVCB( ExInitializeResourceLite(&Vcb->IoResource); ExInitializeFastMutex(&Vcb->VcbMutex); - ExInitializeFastMutex(&Vcb->FcbTableMutex); // Initialize the generic Fcb Table. @@ -1175,6 +837,65 @@ 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, @@ -1183,6 +904,7 @@ UDFCompleteMount( { NTSTATUS Status; UNICODE_STRING LocalPath; + PtrUDFObjectName RootName; ULONG LastSector = 0; BOOLEAN UnlockVcb = FALSE; FILE_ID FileId{}; @@ -1218,15 +940,32 @@ UDFCompleteMount( Vcb->RootIndexFcb->FileId = UdfGetFidFromLbAddr(Vcb->RootLbAddr); SetFlag(Vcb->RootIndexFcb->FileId.HighPart, FID_DIR_MASK); - Vcb->RootIndexFcb->FileInfo = (PUDF_FILE_INFO)MyAllocatePool__(NonPagedPool,sizeof(UDF_FILE_INFO)); + // Allocate and set root FCB unique name + RootName = UDFAllocateObjectName(); - if (!Vcb->RootIndexFcb->FileInfo) { + if (!RootName) { - UDFDeleteFcb(IrpContext, Vcb->RootIndexFcb); + UDFCleanUpFCB(Vcb->RootIndexFcb); Vcb->RootIndexFcb = NULL; try_return(Status = STATUS_INSUFFICIENT_RESOURCES); } + Status = MyInitUnicodeString(&RootName->ObjectName, UDF_ROOTDIR_NAME); + if (!NT_SUCCESS(Status)) + goto insuf_res_1; + + Vcb->RootIndexFcb->FileInfo = (PUDF_FILE_INFO)MyAllocatePool__(NonPagedPool,sizeof(UDF_FILE_INFO)); + + if (!Vcb->RootIndexFcb->FileInfo) { + Status = STATUS_INSUFFICIENT_RESOURCES; + insuf_res_1: + MyFreePool__(RootName->ObjectName.Buffer); + UDFReleaseObjectName(RootName); + UDFCleanUpFCB(Vcb->RootIndexFcb); + Vcb->RootIndexFcb = NULL; + try_return(Status); + } + UDFPrint(("UDFCompleteMount: open Root Dir\n")); // Open Root Directory Status = UDFOpenRootFile__(IrpContext, Vcb, &Vcb->RootLbAddr, Vcb->RootIndexFcb->FileInfo); @@ -1235,9 +974,7 @@ UDFCompleteMount( UDFCleanUpFile__(Vcb, Vcb->RootIndexFcb->FileInfo); MyFreePool__(Vcb->RootIndexFcb->FileInfo); - UDFDeleteFcb(IrpContext, Vcb->RootIndexFcb); - Vcb->RootIndexFcb = NULL; - try_return(Status); + goto insuf_res_1; } Vcb->RootIndexFcb->FileInfo->Fcb = Vcb->RootIndexFcb; @@ -1249,7 +986,7 @@ UDFCompleteMount( UDFLockVcb(IrpContext, Vcb); UnlockVcb = TRUE; - Status = UDFInitializeFCB(Vcb->RootIndexFcb, Vcb, UDF_FCB_ROOT_DIRECTORY | UDF_FCB_DIRECTORY); + Status = UDFInitializeFCB(Vcb->RootIndexFcb, Vcb, RootName, UDF_FCB_ROOT_DIRECTORY | UDF_FCB_DIRECTORY, NULL); if (!NT_SUCCESS(Status)) { @@ -1259,20 +996,11 @@ UDFCompleteMount( UDFCleanUpFile__(Vcb, Vcb->RootIndexFcb->FileInfo); MyFreePool__(Vcb->RootIndexFcb->FileInfo); - - // FCB was not inserted into table (UDFInitializeFCB failed - // before UDFInsertFcbIntoTable was called) - UDFUnlockVcb(IrpContext, Vcb); - UnlockVcb = FALSE; - - UDFDeleteFcb(IrpContext, Vcb->RootIndexFcb); + UDFCleanUpFCB(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; @@ -1305,8 +1033,11 @@ UDFCompleteMount( // Open Unallocatable space stream // Generally, it should be placed in SystemStreamDirectory, but some // stupid apps think that RootDirectory is much better place.... :(( - LocalPath = RTL_CONSTANT_STRING(UDF_FN_NON_ALLOCATABLE); - Status = UDFOpenFile__(IrpContext, Vcb, FALSE, TRUE, &LocalPath, Vcb->RootIndexFcb->FileInfo, &Vcb->NonAllocFileInfo, NULL); + Status = MyInitUnicodeString(&LocalPath, UDF_FN_NON_ALLOCATABLE); + if (NT_SUCCESS(Status)) { + Status = UDFOpenFile__(IrpContext, Vcb, FALSE, TRUE, &LocalPath, Vcb->RootIndexFcb->FileInfo, &Vcb->NonAllocFileInfo, NULL); + MyFreePool__(LocalPath.Buffer); + } if (!NT_SUCCESS(Status) && (Status != STATUS_OBJECT_NAME_NOT_FOUND)) { @@ -1328,8 +1059,12 @@ UDFCompleteMount( UDFDirIndex(UDFGetDirIndexByFileInfo(Vcb->NonAllocFileInfo), Vcb->NonAllocFileInfo->Index)->FI_Flags |= UDF_FI_FLAG_FI_INTERNAL; } else { /* try to read Non-allocatable from alternate locations */ - LocalPath = RTL_CONSTANT_STRING(UDF_FN_NON_ALLOCATABLE_2); + Status = MyInitUnicodeString(&LocalPath, UDF_FN_NON_ALLOCATABLE_2); + if (!NT_SUCCESS(Status)) { + goto unwind_1; + } Status = UDFOpenFile__(IrpContext, Vcb, FALSE, TRUE, &LocalPath, Vcb->RootIndexFcb->FileInfo, &(Vcb->NonAllocFileInfo), NULL); + MyFreePool__(LocalPath.Buffer); if (!NT_SUCCESS(Status) && (Status != STATUS_OBJECT_NAME_NOT_FOUND)) { goto unwind_1; } @@ -1338,8 +1073,12 @@ UDFCompleteMount( UDFDirIndex(UDFGetDirIndexByFileInfo(Vcb->NonAllocFileInfo), Vcb->NonAllocFileInfo->Index)->FI_Flags |= UDF_FI_FLAG_FI_INTERNAL; } else if (Vcb->SysSDirFileInfo) { - LocalPath = RTL_CONSTANT_STRING(UDF_SN_NON_ALLOCATABLE); + Status = MyInitUnicodeString(&LocalPath, UDF_SN_NON_ALLOCATABLE); + if (!NT_SUCCESS(Status)) { + goto unwind_1; + } Status = UDFOpenFile__(IrpContext, Vcb, FALSE, TRUE, &LocalPath, Vcb->SysSDirFileInfo , &(Vcb->NonAllocFileInfo), NULL); + MyFreePool__(LocalPath.Buffer); if (!NT_SUCCESS(Status) && (Status != STATUS_OBJECT_NAME_NOT_FOUND)) { goto unwind_1; } @@ -1420,6 +1159,8 @@ UDFCompleteMount( Vcb->VolumeDasdFcb = UDFCreateFcb(IrpContext, FileId, UDF_NODE_TYPE_DATA, NULL); + InitializeListHead(&Vcb->VolumeDasdFcb->NextCCB); + UDFIncrementReferenceCounts(IrpContext, Vcb->VolumeDasdFcb, 1, 1); UDFUnlockVcb(IrpContext, Vcb); UnlockVcb = FALSE; @@ -1475,61 +1216,3 @@ UDFCompleteMount( return Status; } // end UDFCompleteMount() - -/************************************************************************* -* -* Function: UDFDeallocateCcb() -* -* Description: -* Deallocate a previously allocated structure. -* -* Expected Interrupt Level (for execution) : -* -* IRQL_PASSIVE_LEVEL -* -* Return Value: None -* -*************************************************************************/ -VOID -UDFDeallocateCcb( - PCCB Ccb - ) -{ - ASSERT_CCB(Ccb); - - ExFreeToPagedLookasideList(&UdfData.CcbLookasideList, Ccb); - -} // end UDFDeallocateCcb() - -/* - Function: UDFDeleteCcb() - - Description: - Cleanup and deallocate a previously allocated structure. - - Expected Interrupt Level (for execution) : - - IRQL_PASSIVE_LEVEL - - Return Value: None - -*/ -VOID -UDFDeleteCcb( - PCCB Ccb -) -{ - if (Ccb->DirectorySearchPattern) { - - if (Ccb->DirectorySearchPattern->Buffer) { - - MyFreePool__(Ccb->DirectorySearchPattern->Buffer); - Ccb->DirectorySearchPattern->Buffer = NULL; - } - - MyFreePool__(Ccb->DirectorySearchPattern); - Ccb->DirectorySearchPattern = NULL; - } - - UDFDeallocateCcb(Ccb); -} // end UDFDeleteCcb() diff --git a/drivers/filesystems/udfs/struct.h b/drivers/filesystems/udfs/struct.h index 128770c2bcc3a..efd97d9d75f5c 100644 --- a/drivers/filesystems/udfs/struct.h +++ b/drivers/filesystems/udfs/struct.h @@ -36,13 +36,11 @@ struct IRP_CONTEXT_LITE; struct IO_CONTEXT; struct IRP_CONTEXT; -struct LCB; -/* C typedef aliases – allow plain name usage without the 'struct' keyword */ +/* C typedef aliases - allow plain name usage without the 'struct' keyword */ typedef struct IRP_CONTEXT_LITE IRP_CONTEXT_LITE; typedef struct IO_CONTEXT IO_CONTEXT; typedef struct IRP_CONTEXT IRP_CONTEXT; -typedef struct LCB LCB; typedef struct UDFIdentifier UDFIdentifier; typedef struct UDFObjectName UDFObjectName; typedef struct CCB CCB; @@ -64,7 +62,8 @@ struct UDFIdentifier { NODE_BYTE_SIZE NodeByteSize; // computed as sizeof(structure) }; -C_ASSERT(sizeof(UDFIdentifier) == offsetof(FSRTL_ADVANCED_FCB_HEADER, Flags)); +static_assert(sizeof(UDFIdentifier) == offsetof(FSRTL_ADVANCED_FCB_HEADER, Flags), + "UDFIdentifier size mismatch with NodeTypeCode and NodeByteSize in FSRTL_ADVANCED_FCB_HEADER"); /************************************************************************** Every open on-disk object must have a name associated with it @@ -96,31 +95,21 @@ typedef UDFObjectName* PtrUDFObjectName; **************************************************************************/ struct CCB { UDFIdentifier NodeIdentifier; - - // Fcb for the file being opened. - - FCB* Fcb; - - // Lcb for the file being opened. - - LCB* Lcb; - + // ptr to the associated FCB + FCB* Fcb; + // all CCB structures for a FCB are linked together + LIST_ENTRY NextCCB; // each CCB is associated with a file object PFILE_OBJECT FileObject; - - // Flags. Indicates flags to apply for the current open. - - ULONG Flags; - + // flags (see below) associated with this CCB + uint32 Flags; // current index in directory is required sometimes - ULONG CurrentIndex; - // if this CCB represents a directory object open, we may // need to maintain a search pattern - PUNICODE_STRING DirectorySearchPattern; HASH_ENTRY hashes; + ULONG TreeLength; }; typedef CCB* PCCB; @@ -166,6 +155,8 @@ struct FCB_NONPAGED { ERESOURCE FcbPagingIoResource; + ERESOURCE CcbListResource; + // This is the FastMutex for this Fcb. FAST_MUTEX FcbMutex; @@ -175,10 +166,6 @@ struct FCB_NONPAGED { FAST_MUTEX AdvancedFcbHeaderMutex; - // Fast mutex for file name cache synchronization - // Protects LCB->FileName when used as full path cache - FAST_MUTEX FcbFastMutex; - }; typedef FCB_NONPAGED* PFCB_NONPAGED; @@ -221,11 +208,11 @@ typedef FCB_NONPAGED* PFCB_NONPAGED; /***************************************************/ struct FCB_DATA { - UCHAR Placeholder; + }; struct FCB_INDEX { - UCHAR Placeholder; + }; struct FCB { @@ -248,6 +235,9 @@ struct FCB { FILE_ID FileId; + // all CCB's for this particular FCB are linked off the following + // list head. + LIST_ENTRY NextCCB; // whenever a file stream has a create/open operation performed, // the Reference count below is incremented AND the OpenHandle count // below is also incremented. @@ -271,14 +261,9 @@ struct FCB { ULONG FileAttributes; - // File name cache synchronization - // FcbLockThread - owner of the file name cache mutex - // FcbLockCount - reference count for cached names in LCBs - PVOID FcbLockThread; // Thread owning the cache mutex - ULONG FcbLockCount; // Reference count for cache - - // NOTE: FCBName field REMOVED - all names are now stored in LCB. - // Full paths are built dynamically from LCB chain via UDFBuildFullPathFromLcb(). + // for the UDF fsd, there exists a 1-1 correspondence between a + // full object pathname and a FCB + PtrUDFObjectName FCBName; // Pointer to the Fcb non-paged structures. @@ -297,22 +282,9 @@ 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; - - // Splay tree roots for fast child LCB lookup by name. - // Protected by this FCB's FcbResource (exclusive for insert/remove, - // shared is NOT safe — splay rebalances on lookup). - PRTL_SPLAY_LINKS ExactCaseRoot; - PRTL_SPLAY_LINKS IgnoreCaseRoot; - PRTL_SPLAY_LINKS ShortNameRoot; - // Pointer to IrpContextLite in delayed queue. IRP_CONTEXT_LITE* IrpContextLite; + uint32 CcbCount; // The following field is used by the filelock module // to maintain current byte range locking information. @@ -352,10 +324,8 @@ typedef FCB* PFCB; #define UDF_FCB_READ_ONLY (0x00001000) #define UDF_FCB_DELAY_CLOSE (0x00002000) #define UDF_FCB_DELETED (0x00004000) -// Verification failed — FID/ICB data on disk does not match FCB -#define UDF_FCB_NEEDS_VERIFICATION (0x00008000) -// Object not found on media during verification — stale FCB -#define UDF_FCB_NOT_FOUND_ON_MEDIA (0x00010000) +#define UDF_FCB_POSTED_RENAME (0x00010000) + #define FCB_STATE_INITIALIZED (0x00020000) #define FCB_STATE_IN_FCB_TABLE (0x00040000) @@ -370,7 +340,7 @@ typedef FCB* PFCB; **************************************************************************/ -typedef enum UDFFSD_MEDIA_TYPE { +enum UDFFSD_MEDIA_TYPE { MediaUnknown = 0, MediaHdd, MediaCdr, @@ -380,114 +350,16 @@ typedef enum UDFFSD_MEDIA_TYPE { MediaFloppy, MediaDvdr, MediaDvdrw -} UDFFSD_MEDIA_TYPE; - -//*************************************************************************** -// LCB (Link Control Block) -//*************************************************************************** - -/** - Link Control Block (LCB) - links parent directory to child file. - - Used to defer directory linkage until create operation completes successfully. - This prevents partial creates from being visible in directory lookups. -*/ -struct LCB { - UDFIdentifier NodeIdentifier; // +0x00 Node type = UDFS_NTC_LCB - - UCHAR Reserved1[4]; // +0x04 Padding for alignment - - // Links in parent FCB's ChildLcbQueue - LIST_ENTRY ParentFcbLinks; // +0x08 Links in parent FCB list - - // Parent directory FCB - PFCB ParentFcb; // +0x18 Pointer to parent FCB - - // Links in child FCB's ParentLcbQueue - LIST_ENTRY ChildFcbLinks; // +0x20 Links in child FCB list - - // Child file FCB - PFCB ChildFcb; // +0x30 Pointer to child FCB - - // Initial directory offset (for hard links and directory entries) - ULONGLONG InitialOffset; // +0x38 Initial offset - - // Reference count (incremented by CCB, decremented on cleanup) - ULONG Reference; // +0x40 Reference count - - // LCB flags - ULONG Flags; // +0x44 LCB flags - - // File attributes from directory entry - ULONG FileAttributes; // +0x48 File attributes - - UCHAR Reserved2[4]; // +0x4C Padding - - // ANSI name (for compatibility) - STRING Name; // +0x50 ANSI name (size 0x10) - - UCHAR Reserved3[8]; // +0x60 Padding - - // Splay tree links for exact case name matching - RTL_SPLAY_LINKS ExactCaseLinks; // +0x68 Exact case splay links - - // Exact case name (preserves original case from disk) - UNICODE_STRING ExactCaseLinkName; // +0x80 Exact case link name - - // Splay tree links for case-insensitive name matching - RTL_SPLAY_LINKS IgnoreCaseLinks; // +0x90 Ignore case splay links - - // Case-insensitive name (uppercased for fast comparison) - UNICODE_STRING IgnoreCaseLinkName; // +0xA8 Ignore case link name - - // Splay tree links for short (8.3) name matching - RTL_SPLAY_LINKS ShortNameLinks; // +0xB8 Short name splay links - - // Short (8.3) name for DOS compatibility - UNICODE_STRING ShortName; // +0xD0 Short name - - // Buffer pointer for dynamically allocated name data - // Points to memory immediately after LCB structure in most cases - PVOID NameBuffer; // +0xE0 Buffer pointer - - // Full file name (component name, not full path) - UNICODE_STRING FileName; // +0xE8 File name }; -using PLCB = LCB*; - -// LCB Flags -#define UDF_LCB_FLAG_POOL_ALLOCATED 0x00000001 // Allocated from pool (not lookaside) -#define UDF_LCB_FLAG_LINK_DELETED 0x00000002 // Link has been deleted -#define UDF_LCB_FLAG_HAS_NAME_BUFFER 0x00000004 // Name buffer needs freeing (separately allocated) -#define UDF_LCB_FLAG_DELETE_ON_CLEANUP 0x00000008 // Delete file on cleanup -#define UDF_LCB_FLAG_EXACT_CASE_IN_TREE 0x00000010 // In exact case splay tree -#define UDF_LCB_FLAG_IGNORE_CASE_IN_TREE 0x00000020 // In ignore case splay tree -#define UDF_LCB_FLAG_SHORT_NAME_IN_TREE 0x00000040 // In short name splay tree -#define UDF_LCB_FLAG_SHORT_NAME_CREATED 0x00000200 // Short name was created (bit 9) - -// LCB size constants -// Zero 0xF0 bytes (up to +0xE8, excluding FileName UNICODE_STRING buffer pointer) -// Actual structure size is 0xF8 (248 bytes) but we only zero first 0xF0 bytes -#define UDF_LCB_BASE_SIZE 0xF0 // 240 bytes - bytes to zero in RtlZeroMemory (excludes FileName buffer ptr) -#define UDF_LCB_LOOKASIDE_SIZE 0x158 // 344 bytes - max size for lookaside allocation - -// LCB lookaside size - fits LCB + 16 WCHARs for short names -// NOTE: SIZEOF_LOOKASIDE_LCB must be at least UDF_LCB_LOOKASIDE_SIZE (0x158) -#define SIZEOF_LOOKASIDE_LCB UDF_LCB_LOOKASIDE_SIZE - -//*************************************************************************** -// VCB (Volume Control Block) -//*************************************************************************** - -typedef enum VCB_CONDITION { +enum VCB_CONDITION { VcbNotMounted = 0, VcbMountInProgress, VcbMounted, VcbInvalid, VcbDismountInProgress -} VCB_CONDITION; +}; struct VCB { @@ -564,7 +436,7 @@ struct VCB { // a resource to protect the fields contained within the VCB ERESOURCE VcbResource; ERESOURCE BitMapResource1; - + ERESOURCE FileIdResource; ERESOURCE DlocResource; ERESOURCE DlocResource2; ERESOURCE PreallocResource; @@ -572,20 +444,13 @@ struct VCB { // Vcb fast mutex. This is used to synchronize the fields in the Vcb // when modified when the Vcb is not held exclusively. Included here - // are the count fields. + // are the count fields and Fcb table. // We also use this to synchronize changes to the Fcb reference field. FAST_MUTEX VcbMutex; PVOID VcbLockThread; - // FcbTable fast mutex. Protects Vcb->FcbTable operations (lookup, - // insert, delete) and ensures atomicity of FCB create + init sequence. - // Lock ordering: FcbTableMutex (outer) before VcbMutex (inner). - - FAST_MUTEX FcbTableMutex; - PVOID FcbTableLockThread; - //--------------- // Physical media parameters //--------------- @@ -726,6 +591,7 @@ struct VCB { PUDF_DATALOC_INDEX DlocList; ULONG DlocCount; // FS compatibility + USHORT DefaultAllocMode; // Default alloc mode (from registry) BOOLEAN LowFreeSpace; UDFFSD_MEDIA_TYPE MediaTypeEx; ULONG DefaultAttr; // Default file attributes (NT-style) @@ -735,14 +601,20 @@ struct VCB { UCHAR Reserved5[3]; // + ULONG FECharge; + ULONG FEChargeSDir; + ULONG PackDirThreshold; ULONG SparseThreshold; // in blocks + PUDF_ALLOCATION_CACHE_ITEM FEChargeCache; + ULONG FEChargeCacheMaxSize; + PUDF_ALLOCATION_CACHE_ITEM PreallocCache; ULONG PreallocCacheMaxSize; uint32 CompatFlags; - // Fcb table. Synchronized with FcbTableMutex. + // Fcb table. Synchronized with the Vcb fast mutex. RTL_GENERIC_TABLE FcbTable; @@ -850,6 +722,7 @@ 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. @@ -887,6 +760,7 @@ typedef IRP_CONTEXT* PIRP_CONTEXT; #define IRP_CONTEXT_FLAG_TRAIL_BACKSLASH (0x00080000) #define UDF_IRP_CONTEXT_NOT_TOP_LEVEL (0x10000000) #define UDF_IRP_CONTEXT_FLUSH_REQUIRED (0x20000000) +#define UDF_IRP_CONTEXT_FLUSH2_REQUIRED (0x40000000) #define IRP_CONTEXT_FLAG_ALLOW_MEDIA_EJECT (0x80000000) // The following flags need to be cleared when a request is posted. @@ -933,6 +807,7 @@ struct IRP_CONTEXT_LITE { ULONG UserReference; // Real device object. This represents the physical device closest to the media. PDEVICE_OBJECT RealDevice; + ULONG TreeLength; }; typedef IRP_CONTEXT_LITE* PIRP_CONTEXT_LITE; @@ -977,7 +852,6 @@ typedef struct _UDFData { PAGED_LOOKASIDE_LIST UDFFcbDataLookasideList; PAGED_LOOKASIDE_LIST CcbLookasideList; - PAGED_LOOKASIDE_LIST LcbLookasideList; LIST_ENTRY AsyncCloseQueue; ULONG AsyncCloseCount; @@ -1010,7 +884,7 @@ typedef struct _UDFData { } UDFData, *PUDFData; -#define UDF_DATA_FLAGS_SHUTDOWN (0x00000001) +#define UDFS_FLAGS_SHUTDOWN (0x0001) #define TAG_IRP_CONTEXT 'cidU' #define TAG_IRP_CONTEXT_LITE 'lidU' @@ -1018,7 +892,6 @@ 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' @@ -1055,7 +928,9 @@ typedef struct _UDFData { #define UDF_VCB_IC_UPDATE_ARCH_BIT (0x00000008) #define UDF_VCB_IC_UPDATE_DIR_WRITE (0x00000010) #define UDF_VCB_IC_UPDATE_DIR_READ (0x00000020) +#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_IGNORE_SEQUENTIAL_IO (0x00002000) #define UDF_VCB_IC_NO_SYNCCACHE_AFTER_WRITE (0x00004000) #define UDF_VCB_IC_BAD_RW_SEEK (0x00008000) @@ -1064,6 +939,12 @@ typedef struct _UDFData { #define UDF_VCB_IC_INSTANT_COMPAT_ALLOC_DESCS (0x00100000) #define UDF_VCB_IC_DIRTY_RO (0x04000000) +#define UDF_VCB_IC_W2K_COMPAT_VLABEL (0x08000000) +#define UDF_VCB_IC_ADAPTEC_NONALLOC_COMPAT (0x80000000) + +// valid flag values for the global data structure +#define UDF_DATA_FLAGS_ZONES_INITIALIZED (0x00000002) +#define UDF_DATA_FLAGS_SHUTDOWN (0x00000004) #define FILE_ID_CACHE_GRANULARITY 16 #define DLOC_LIST_GRANULARITY 16 diff --git a/drivers/filesystems/udfs/sys_spec.c b/drivers/filesystems/udfs/sys_spec.c index cd77a8f55de81..e9a11ab152817 100644 --- a/drivers/filesystems/udfs/sys_spec.c +++ b/drivers/filesystems/udfs/sys_spec.c @@ -5,7 +5,7 @@ //////////////////////////////////////////////////////////////////// /************************************************************************* * -* File: Sys_Spec.c +* File: Sys_Spec.cpp * * Module: UDF File System Driver * (both User and Kernel mode execution) @@ -20,6 +20,6 @@ // define the file specific bug-check id #define UDF_BUG_CHECK_ID UDF_FILE_SYS_SPEC -#include "Include/Sys_spec_lib.c" +#include "Include/Sys_spec_lib.cpp" -//#include "Include/tools.c" +//#include "Include/tools.cpp" diff --git a/drivers/filesystems/udfs/udf_info/alloc.c b/drivers/filesystems/udfs/udf_info/alloc.c index 6e05b33b40a34..530d6b168767e 100644 --- a/drivers/filesystems/udfs/udf_info/alloc.c +++ b/drivers/filesystems/udfs/udf_info/alloc.c @@ -6,7 +6,7 @@ /* Module name: - alloc.c + alloc.cpp Abstract: diff --git a/drivers/filesystems/udfs/udf_info/dirtree.c b/drivers/filesystems/udfs/udf_info/dirtree.c index 4402f28ae167a..2934f39e4e3f3 100644 --- a/drivers/filesystems/udfs/udf_info/dirtree.c +++ b/drivers/filesystems/udfs/udf_info/dirtree.c @@ -6,7 +6,7 @@ /* Module name: - udf_info.c + udf_info.cpp Abstract: @@ -883,51 +883,6 @@ 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/ecma_167.h b/drivers/filesystems/udfs/udf_info/ecma_167.h index 36ace5e01cda5..0c60fd3ed64a4 100644 --- a/drivers/filesystems/udfs/udf_info/ecma_167.h +++ b/drivers/filesystems/udfs/udf_info/ecma_167.h @@ -770,6 +770,11 @@ typedef struct _EXTENDED_FILE_ENTRY { typedef EXTENDED_FILE_ENTRY ExtendedFileEntry; +#pragma pack(pop) + +#endif /* __ECMA_167_H__ */ + + /* C typedef aliases for all non-typedef struct declarations */ typedef struct VolStructDesc VolStructDesc; typedef struct BeginningExtendedAreaDesc BeginningExtendedAreaDesc; @@ -802,8 +807,3 @@ typedef struct UnallocatedSpaceEntry UnallocatedSpaceEntry; typedef struct PartitionIntegrityEntry PartitionIntegrityEntry; typedef struct LogicalVolHeaderDesc LogicalVolHeaderDesc; typedef struct PathComponent PathComponent; - -#pragma pack(pop) - -#endif /* __ECMA_167_H__ */ - diff --git a/drivers/filesystems/udfs/udf_info/extent.c b/drivers/filesystems/udfs/udf_info/extent.c index 7b56c5321f541..f76d82b4577c0 100644 --- a/drivers/filesystems/udfs/udf_info/extent.c +++ b/drivers/filesystems/udfs/udf_info/extent.c @@ -6,7 +6,7 @@ /* Module name: - extent.c + extent.cpp Abstract: diff --git a/drivers/filesystems/udfs/udf_info/mount.c b/drivers/filesystems/udfs/udf_info/mount.c index 8546c63e137c0..9a5199263a4cc 100644 --- a/drivers/filesystems/udfs/udf_info/mount.c +++ b/drivers/filesystems/udfs/udf_info/mount.c @@ -6,7 +6,7 @@ /* Module name: - mount.c + mount.cpp Abstract: diff --git a/drivers/filesystems/udfs/udf_info/phys_eject.c b/drivers/filesystems/udfs/udf_info/phys_eject.c index 32e98abd31501..d07ccedf10ef0 100644 --- a/drivers/filesystems/udfs/udf_info/phys_eject.c +++ b/drivers/filesystems/udfs/udf_info/phys_eject.c @@ -4,7 +4,7 @@ // This file was released under the GPLv2 on June 2015. //////////////////////////////////////////////////////////////////// /* - Module Name: Phys_eject.c + Module Name: Phys_eject.cpp Execution: Kernel mode only diff --git a/drivers/filesystems/udfs/udf_info/physical.c b/drivers/filesystems/udfs/udf_info/physical.c index 97bd642b3690c..1ba8a147f02f1 100644 --- a/drivers/filesystems/udfs/udf_info/physical.c +++ b/drivers/filesystems/udfs/udf_info/physical.c @@ -4,7 +4,7 @@ // This file was released under the GPLv2 on June 2015. //////////////////////////////////////////////////////////////////// /* - Module Name: Physical.c + Module Name: Physical.cpp Execution: Kernel mode only @@ -17,5 +17,5 @@ // define the file specific bug-check id #define UDF_BUG_CHECK_ID UDF_FILE_PHYSICAL -#include "Include/phys_lib.c" +#include "Include/phys_lib.cpp" diff --git a/drivers/filesystems/udfs/udf_info/remap.c b/drivers/filesystems/udfs/udf_info/remap.c index d134b40f5ecc8..72a4079b07021 100644 --- a/drivers/filesystems/udfs/udf_info/remap.c +++ b/drivers/filesystems/udfs/udf_info/remap.c @@ -6,7 +6,7 @@ /* Module name: - remap.c + remap.cpp Abstract: diff --git a/drivers/filesystems/udfs/udf_info/udf_info.c b/drivers/filesystems/udfs/udf_info/udf_info.c index b218cdc639d0d..86f90dd8f2a34 100644 --- a/drivers/filesystems/udfs/udf_info/udf_info.c +++ b/drivers/filesystems/udfs/udf_info/udf_info.c @@ -6,7 +6,7 @@ /* Module name: - udf_info.c + udf_info.cpp Abstract: @@ -2149,178 +2149,6 @@ 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 */ @@ -3035,12 +2863,8 @@ try_exit: NOTHING; } _SEH2_FINALLY { if (!NT_SUCCESS(status)) { - if (FEAllocated && FileInfo->Dloc) { - // Free FE space first (needs Dloc->FELoc), then remove Dloc entry + if (FEAllocated) UDFFreeFESpace(Vcb, DirInfo, &(FileInfo->Dloc->FELoc)); - UDFRemoveDloc(Vcb, FileInfo->Dloc); - FileInfo->Dloc = NULL; - } } } _SEH2_END return status; @@ -3794,8 +3618,6 @@ 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 e61fa21dc3edf..d2849827772b6 100644 --- a/drivers/filesystems/udfs/udf_info/udf_info.h +++ b/drivers/filesystems/udfs/udf_info/udf_info.h @@ -131,23 +131,6 @@ __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 59a6ddcc2f887..867ce947f1494 100644 --- a/drivers/filesystems/udfs/udf_info/udf_rel.h +++ b/drivers/filesystems/udfs/udf_info/udf_rel.h @@ -439,18 +439,6 @@ 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/udfdata.c b/drivers/filesystems/udfs/udfdata.c index 7dda3e1232d72..d1674b7727e54 100644 --- a/drivers/filesystems/udfs/udfdata.c +++ b/drivers/filesystems/udfs/udfdata.c @@ -5,7 +5,7 @@ //////////////////////////////////////////////////////////////////// /************************************************************************* * -* File: Close.c +* File: Close.cpp * * Module: UDF File System Driver (Kernel mode execution only) * diff --git a/drivers/filesystems/udfs/udffs.h b/drivers/filesystems/udfs/udffs.h index 2aae42ef2fa5f..272046b907e62 100644 --- a/drivers/filesystems/udfs/udffs.h +++ b/drivers/filesystems/udfs/udffs.h @@ -133,7 +133,7 @@ extern UDFData UdfData; // Encapsulate safe pool freeing -static inline +inline VOID UDFFreePool( _Inout_ _At_(*Pool, __drv_freesMem(Mem) _Post_null_) PVOID *Pool @@ -152,7 +152,7 @@ UDFFreePool( // small check for illegal open mode (desired access) if volume is // read only (on standard CD-ROM device or another like this) -static inline +inline BOOLEAN UDFIllegalFcbAccess( IN PVCB Vcb, @@ -398,7 +398,7 @@ UDFIllegalFcbAccess( #define FID_DIR_MASK 0x80000000 // high order bit means directory. -static inline +inline FILE_ID UdfGetFidFromLbAddr(lb_addr lbAddr) { diff --git a/drivers/filesystems/udfs/udfinit.c b/drivers/filesystems/udfs/udfinit.c index ff89febf2f6ef..657034565142c 100644 --- a/drivers/filesystems/udfs/udfinit.c +++ b/drivers/filesystems/udfs/udfinit.c @@ -5,7 +5,7 @@ //////////////////////////////////////////////////////////////////// /************************************************************************* * -* File: UDFinit.c +* File: UDFinit.cpp * * Module: UDF File System Driver (Kernel mode execution only) * diff --git a/drivers/filesystems/udfs/verfysup.c b/drivers/filesystems/udfs/verfysup.c index 441a0e62852c5..015af5a6b423b 100644 --- a/drivers/filesystems/udfs/verfysup.c +++ b/drivers/filesystems/udfs/verfysup.c @@ -5,7 +5,7 @@ //////////////////////////////////////////////////////////////////// /* - Module Name: VerfySup.c + Module Name: VerfySup.cpp Abstract: diff --git a/drivers/filesystems/udfs/volinfo.c b/drivers/filesystems/udfs/volinfo.c index d62501d1b6cef..c6ab4d3da9bf9 100644 --- a/drivers/filesystems/udfs/volinfo.c +++ b/drivers/filesystems/udfs/volinfo.c @@ -7,7 +7,7 @@ Module Name: - VolInfo.c + VolInfo.cpp Abstract: diff --git a/drivers/filesystems/udfs/write.c b/drivers/filesystems/udfs/write.c index 170ee91393348..1f236e69585e0 100644 --- a/drivers/filesystems/udfs/write.c +++ b/drivers/filesystems/udfs/write.c @@ -5,7 +5,7 @@ //////////////////////////////////////////////////////////////////// /************************************************************************* * -* File: Write.c +* File: Write.cpp * * Module: UDF File System Driver (Kernel mode execution only) * @@ -44,9 +44,7 @@ UDFCommonWrite( NTSTATUS Status = STATUS_SUCCESS; PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); LONGLONG StartingOffset; - ULONG ByteCount; - LONGLONG ByteRange; - ULONG TruncatedLength; + ULONG ByteCount = 0, TruncatedLength = 0; SIZE_T NumberBytesWritten = 0; PFILE_OBJECT FileObject = NULL; TYPE_OF_OPEN TypeOfOpen; @@ -62,6 +60,9 @@ UDFCommonWrite( BOOLEAN MainResourceAcquired = FALSE; BOOLEAN VcbAcquired = FALSE; + BOOLEAN MainResourceAcquiredExclusive = FALSE; + BOOLEAN MainResourceCanDemoteToShared = FALSE; + BOOLEAN Wait = FALSE; BOOLEAN PagingIo = FALSE; BOOLEAN NonCachedIo = FALSE; @@ -73,14 +74,6 @@ UDFCommonWrite( BOOLEAN ZeroBlock = FALSE; BOOLEAN ZeroBlockDone = FALSE; - // Examine our input parameters to determine if this is noncached and/or - // a paging io operation. - - 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; // Extract and decode the file object. @@ -101,6 +94,14 @@ UDFCommonWrite( ASSERT_FCB(Fcb); ASSERT_VCB(Vcb); + // Examine our input parameters to determine if this is noncached and/or + // a paging io operation. + + 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); + // Check if this volume has already been shut down. If it has, fail // this write request. @@ -138,7 +139,6 @@ UDFCommonWrite( StartingOffset = IrpSp->Parameters.Write.ByteOffset.QuadPart; ByteCount = IrpSp->Parameters.Write.Length; - ByteRange = StartingOffset + ByteCount; Irp->IoStatus.Information = 0; @@ -218,8 +218,20 @@ UDFCommonWrite( try_return(Status = STATUS_ACCESS_DENIED); } + if (IrpContext->Flags & UDF_IRP_CONTEXT_FLUSH2_REQUIRED) { + + UDFPrint((" UDF_IRP_CONTEXT_FLUSH2_REQUIRED\n")); + IrpContext->Flags &= ~UDF_IRP_CONTEXT_FLUSH2_REQUIRED; + + +#ifdef UDF_DELAYED_CLOSE + UDFFspClose(Vcb); +#endif //UDF_DELAYED_CLOSE + + } + // Acquire the volume resource exclusive - UDFAcquireVcbExclusive(IrpContext, Vcb, FALSE); + UDFAcquireResourceExclusive(&(Vcb->VcbResource), TRUE); VcbAcquired = TRUE; // I dislike the idea of writing to mounted media too, but M$ has another point of view... @@ -322,6 +334,8 @@ UDFCommonWrite( if (!SuccessfulPurge) { try_return(Status = STATUS_PURGE_FAILED); } + + MainResourceCanDemoteToShared = TRUE; } // Determine if we were called by the lazywriter. @@ -408,7 +422,20 @@ UDFCommonWrite( try_return(Status = STATUS_PENDING); // CanWait = TRUE; - UDFAcquirePagingIoExclusive(IrpContext, Fcb); + // 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, Wait)) { + try_return(Status = STATUS_PENDING); + } + MainResourceAcquired = TRUE; + } + + UDFAcquireResourceExclusive(&Fcb->FcbNonpaged->FcbPagingIoResource, TRUE); PagingIoResourceAcquired = TRUE; if (ExtendFS) { @@ -428,7 +455,7 @@ UDFCommonWrite( } } - UDFReleasePagingIo(IrpContext, Fcb); + UDFReleaseResource(&Fcb->FcbNonpaged->FcbPagingIoResource); PagingIoResourceAcquired = FALSE; if (CcIsFileCached(FileObject)) { @@ -576,18 +603,6 @@ UDFCommonWrite( try_return(Status = STATUS_INVALID_USER_BUFFER); } Fcb->NtReqFCBFlags |= UDF_NTREQ_FCB_MODIFIED; - - // Acquire PagingIoResource exclusive to serialize with - // UDFMarkAllocatedAsRecorded which may free and replace - // ExtInfo->Mapping during NOT_RECORDED -> RECORDED conversion. - // Without this, a concurrent UDFResizeExtent (holding PagingIoResource - // exclusive for file extension) can use a stale Mapping pointer - // that was freed by our UDFMarkAllocatedAsRecorded call. - if (!PagingIoResourceAcquired) { - UDFAcquirePagingIoExclusive(IrpContext, Fcb); - PagingIoResourceAcquired = TRUE; - } - Status = UDFWriteFile__(IrpContext, Vcb, Fcb->FileInfo, StartingOffset, TruncatedLength, FALSE, (PCHAR)SystemBuffer, &NumberBytesWritten); @@ -652,15 +667,16 @@ try_exit: NOTHING; // Release any resources acquired here ... if (PagingIoResourceAcquired) { - UDFReleasePagingIo(IrpContext, Fcb); + UDFReleaseResource(&Fcb->FcbNonpaged->FcbPagingIoResource); } if (MainResourceAcquired) { - UDFReleaseFcb(IrpContext, Fcb); + UDF_CHECK_PAGING_IO_RESOURCE(Fcb); + UDFReleaseResource(&Fcb->FcbNonpaged->FcbResource); } if (VcbAcquired) { - UDFReleaseVcb(IrpContext, Vcb); + UDFReleaseResource(&Vcb->VcbResource); } } _SEH2_END; // end of "__finally" processing @@ -739,7 +755,7 @@ UDFPurgeCacheEx_( // We'll just purge cache section here, // without call to CcZeroData() - // 'cause udf_info.c will care about it + // 'cause udf_info.cpp will care about it #define PURGE_BLOCK_SZ 0x10000000 diff --git a/udfs-for-write-branch.patch b/udfs-for-write-branch.patch index 3dd1d543cd011..170421db945cd 100644 --- a/udfs-for-write-branch.patch +++ b/udfs-for-write-branch.patch @@ -1,8 +1,8 @@ diff --git a/drivers/filesystems/udfs/CMakeLists.txt b/drivers/filesystems/udfs/CMakeLists.txt -index 53ce00f..09e4e7d 100644 +index 53ce00f..fa42787 100644 --- a/drivers/filesystems/udfs/CMakeLists.txt +++ b/drivers/filesystems/udfs/CMakeLists.txt -@@ -2,54 +2,52 @@ +@@ -2,42 +2,42 @@ include_directories(Include) list(APPEND SOURCE @@ -64,7 +64,6 @@ index 53ce00f..09e4e7d 100644 + mem.c + misc.c + namesup.c -+ prefxsup.c + pnp.c + read.c + secursup.c @@ -82,18 +81,6 @@ index 53ce00f..09e4e7d 100644 udffs.h) add_library(udfs MODULE ${SOURCE} udffs.rc) - - if(CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_compile_options(udfs PRIVATE -Wno-unused-but-set-variable) -- target_compile_options(udfs PRIVATE -Wno-invalid-offsetof) -- target_compile_options(udfs PRIVATE -Wno-error -fpermissive) - endif() - - if(CMAKE_C_COMPILER_ID STREQUAL "Clang") -- target_compile_options(udfs PRIVATE -Wno-extern-c-compat -Wno-unused-value) - target_compile_options(udfs PRIVATE -Wno-tautological-constant-out-of-range-compare) - target_compile_options(udfs PRIVATE -Wno-tautological-unsigned-zero-compare -Wno-self-assign) - target_compile_options(udfs PRIVATE -Wno-sometimes-uninitialized -Wno-parentheses-equality) diff --git a/drivers/filesystems/udfs/Include/Sys_spec_lib.cpp b/drivers/filesystems/udfs/Include/Sys_spec_lib.c similarity index 100% rename from drivers/filesystems/udfs/Include/Sys_spec_lib.cpp @@ -106,18 +93,9 @@ diff --git a/drivers/filesystems/udfs/Include/phys_lib.cpp b/drivers/filesystems similarity index 99% rename from drivers/filesystems/udfs/Include/phys_lib.cpp rename to drivers/filesystems/udfs/Include/phys_lib.c -index bba91e8..d85a499 100644 +index bba91e8..944d35b 100644 --- a/drivers/filesystems/udfs/Include/phys_lib.cpp +++ b/drivers/filesystems/udfs/Include/phys_lib.c -@@ -4,7 +4,7 @@ - // This file was released under the GPLv2 on June 2015. - //////////////////////////////////////////////////////////////////// - /* -- Module Name: Phys_lib.cpp -+ Module Name: Phys_lib.c - - Execution: Kernel mode only - @@ -1036,7 +1036,7 @@ UDFReadSectors( OUT PULONG ReadBytes ) @@ -167,122 +145,13 @@ similarity index 100% rename from drivers/filesystems/udfs/Include/string_lib.cpp rename to drivers/filesystems/udfs/Include/string_lib.c diff --git a/drivers/filesystems/udfs/cleanup.cpp b/drivers/filesystems/udfs/cleanup.c -similarity index 81% +similarity index 99% rename from drivers/filesystems/udfs/cleanup.cpp rename to drivers/filesystems/udfs/cleanup.c -index 678dcb3..1d6c600 100644 +index 678dcb3..b85c16a 100644 --- a/drivers/filesystems/udfs/cleanup.cpp +++ b/drivers/filesystems/udfs/cleanup.c -@@ -5,7 +5,7 @@ - //////////////////////////////////////////////////////////////////// - /* - -- Module name: Cleanup.cpp -+ Module name: Cleanup.c - - Abstract: - -@@ -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 ? -@@ -333,7 +289,7 @@ UDFCommonCleanup( +@@ -333,7 +333,7 @@ UDFCommonCleanup( Fcb->ParentFcb->FcbState |= UDF_FCB_DELETE_ON_CLOSE; } // flush file. It is required by UDFUnlinkFile__() @@ -291,376 +160,39 @@ index 678dcb3..1d6c600 100644 if (!NT_SUCCESS(RC)) { AdPrint(("Error flushing file !!!\n")); } -@@ -460,7 +416,7 @@ DiscardDelete: - /* 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 -@@ -556,23 +512,22 @@ DiscardDelete: - } - - // 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; - -@@ -594,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) { -@@ -622,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.c -similarity index 100% +similarity index 99% rename from drivers/filesystems/udfs/close.cpp rename to drivers/filesystems/udfs/close.c +index 664f54f..367523a 100644 +--- a/drivers/filesystems/udfs/close.cpp ++++ b/drivers/filesystems/udfs/close.c +@@ -339,7 +339,7 @@ UDFTeardownStructures( + }*/ + UDFReferenceFile__(CurrentFcb->FileInfo); + ASSERT(CurrentFcb->FcbReference < CurrentFcb->FileInfo->RefCount); +- UDFFlushFile__(IrpContext, Vcb, CurrentFcb->FileInfo); ++ UDFFlushFile__(IrpContext, Vcb, CurrentFcb->FileInfo, 0); + UDFUnlinkFile__(IrpContext, Vcb, CurrentFcb->FileInfo, TRUE); + UDFCloseFile__(IrpContext, Vcb, CurrentFcb->FileInfo); + ASSERT(CurrentFcb->FcbReference == CurrentFcb->FileInfo->RefCount); +@@ -347,7 +347,7 @@ UDFTeardownStructures( + Delete = FALSE; + } + else if (!(CurrentFcb->FcbState & UDF_FCB_DELETED)) { +- UDFFlushFile__(IrpContext, Vcb, CurrentFcb->FileInfo); ++ UDFFlushFile__(IrpContext, Vcb, CurrentFcb->FileInfo, 0); + } else { + // BrutePoint(); + } diff --git a/drivers/filesystems/udfs/create.cpp b/drivers/filesystems/udfs/create.c -similarity index 82% +similarity index 99% rename from drivers/filesystems/udfs/create.cpp rename to drivers/filesystems/udfs/create.c -index a7f63b1..203240f 100644 +index a7f63b1..ed77722 100644 --- a/drivers/filesystems/udfs/create.cpp +++ b/drivers/filesystems/udfs/create.c -@@ -5,7 +5,7 @@ - //////////////////////////////////////////////////////////////////// - /************************************************************************* - * --* File: Create.cpp -+* File: Create.c - * - * Module: UDF File System Driver (Kernel mode execution only) - * -@@ -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); -+ } -+ -+ if (OpenByFileId) { -+ SetFlag(CcbFlags, CCB_FLAG_OPEN_BY_ID); - } - -- UDF_CHECK_PAGING_IO_RESOURCE(RelatedFileInfo->Fcb); -- UDFAcquireResourceExclusive((*Res1) = &RelatedFileInfo->Fcb->FcbNonpaged->FcbResource, TRUE); -+ // 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(); - -@@ -524,7 +604,7 @@ UDFCommonCreate( +@@ -524,7 +524,7 @@ UDFCommonCreate( InterlockedDecrement((PLONG)&Vcb->VcbReference); @@ -669,510 +201,7 @@ index a7f63b1..203240f 100644 } // Lock the volume if (!(ShareAccess & FILE_SHARE_READ)) { -@@ -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 @@ op_vol_accs_dnd: - 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 @@ op_vol_accs_dnd: - RelatedFileInfo = - OldRelatedFileInfo = RelatedFileInfo->ParentFile; - NextFcb = NextFcb->ParentFcb; -- // prevent releasing parent structures -- UDFAcquireParent(RelatedFileInfo, &Res1, &Res2); -- TreeLength++; -- -- if (Res1) UDFReleaseResource(Res1); -- if (Res2) UDFReleaseResource(Res2); -+ // Parent references are now handled by LCB in UDFCompleteFcbOpen - -- 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 @@ op_vol_accs_dnd: - 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 @@ op_vol_accs_dnd: - 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 @@ op_vol_accs_dnd: - 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 @@ Skip_open_attempt: - 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 @@ Skip_open_attempt: - 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 @@ Skip_open_attempt: - 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 @@ Skip_open_attempt: - // 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 @@ Skip_open_attempt: - ASSERT(!PtrNewFcb); - if (PtrNewFcb) { - BrutePoint(); -- UDFCleanUpFCB(PtrNewFcb); -+ UDFDeleteFcb(IrpContext, PtrNewFcb); - } - MyFreePool__(NewFileInfo); - } else { -@@ -1186,6 +1297,10 @@ Skip_open_attempt: - 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 @@ Skip_open_attempt: - // ... 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 @@ Skip_open_attempt: - // 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 @@ Skip_open_attempt: - 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 @@ Skip_open_attempt: - (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,25 +1514,17 @@ Creation_Err_1: - // 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 +@@ -1428,7 +1428,7 @@ Undo_Create_1: if ((RC != STATUS_FILE_IS_A_DIRECTORY) && (RC != STATUS_NOT_A_DIRECTORY) && (RC != STATUS_ACCESS_DENIED)) { @@ -1181,478 +210,16 @@ index a7f63b1..203240f 100644 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 @@ Undo_Create_1: - 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 @@ Undo_Create_1: - 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 @@ Undo_Create_1: - 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 @@ Undo_Create_1: - 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 @@ Undo_Create_1: - 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, 0); -+ UDFUnlinkFile__(IrpContext, Vcb, NewFileInfo, TRUE); -+ } -+ UDFCloseFile__(IrpContext, Vcb, NewFileInfo); -+ try_return(RC); - } - - PtrNewFcb->Header.FileSize.QuadPart = -@@ -1596,9 +1717,23 @@ Undo_Create_1: - } - } - -- // 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 @@ Undo_Create_1: +@@ -1608,7 +1608,7 @@ Undo_Create_1: if (!NT_SUCCESS(RC)) { AdPrint((" Can't set Access Rights on Create\n")); BrutePoint(); - UDFFlushFile__(IrpContext, Vcb, NewFileInfo); -+ // Undo create - flush, unlink and close + UDFFlushFile__(IrpContext, Vcb, NewFileInfo, 0); UDFUnlinkFile__(IrpContext, Vcb, NewFileInfo, TRUE); -+ UDFCloseFile__(IrpContext, Vcb, NewFileInfo); - try_return(RC); - } - -@@ -1650,26 +1787,14 @@ Undo_Create_1: - 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 @@ AlreadyOpened: - } - // 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")); -@@ -1722,7 +1846,7 @@ AlreadyOpened: - if (NonDirectoryFile) { - // If the user wants 'write access' access to the file make sure there - // is not a process mapping this file as an image. Any attempt to -- // delete the file will be stopped in fileinfo.cpp -+ // delete the file will be stopped in fileinfo.c - // - // If the user wants to delete on close, we must check at this - // point though. -@@ -1766,8 +1890,7 @@ AlreadyOpened: - - 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 @@ AlreadyOpened: - 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 @@ AlreadyOpened: - 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 @@ AlreadyOpened: - 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(Res1 != NULL); -- ASSERT(Res2 != NULL); -+ ASSERT(CurrentFcb); - -- // 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) -@@ -2259,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 - -@@ -2368,7 +2498,7 @@ UDFCompleteFcbOpen( +@@ -2368,7 +2368,7 @@ UDFCompleteFcbOpen( // Flush the volume and make sure all of the user references // are gone. @@ -1661,39 +228,6 @@ index a7f63b1..203240f 100644 if (!NT_SUCCESS(Status)) { -@@ -2445,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); - -@@ -2481,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/devcntrl.cpp b/drivers/filesystems/udfs/devcntrl.c similarity index 100% rename from drivers/filesystems/udfs/devcntrl.cpp @@ -1719,21 +253,12 @@ similarity index 100% rename from drivers/filesystems/udfs/filobsup.cpp rename to drivers/filesystems/udfs/filobsup.c diff --git a/drivers/filesystems/udfs/flush.cpp b/drivers/filesystems/udfs/flush.c -similarity index 98% +similarity index 99% rename from drivers/filesystems/udfs/flush.cpp rename to drivers/filesystems/udfs/flush.c -index 76357b7..4d08e27 100644 +index 76357b7..ebe9dd1 100644 --- a/drivers/filesystems/udfs/flush.cpp +++ b/drivers/filesystems/udfs/flush.c -@@ -5,7 +5,7 @@ - //////////////////////////////////////////////////////////////////// - /************************************************************************* - * --* File: Flush.cpp -+* File: Flush.c - * - * Module: UDF File System Driver (Kernel mode execution only) - * @@ -127,7 +127,7 @@ UDFCommonFlush( UDFVerifyVcb(IrpContext, Vcb); @@ -1743,89 +268,14 @@ index 76357b7..4d08e27 100644 UDFReleaseResource(&(Vcb->VcbResource)); AcquiredVCB = FALSE; -@@ -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.c -similarity index 98% +similarity index 99% rename from drivers/filesystems/udfs/fscntrl.cpp rename to drivers/filesystems/udfs/fscntrl.c -index ab7c079..ebfb7d6 100644 +index ab7c079..84a9e18 100644 --- a/drivers/filesystems/udfs/fscntrl.cpp +++ b/drivers/filesystems/udfs/fscntrl.c -@@ -5,7 +5,7 @@ - //////////////////////////////////////////////////////////////////// - /* - -- Module Name: FsCntrl.cpp -+ Module Name: FsCntrl.c - - Abstract: - -@@ -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); -@@ -989,7 +997,7 @@ Return Value: +@@ -989,7 +989,7 @@ Return Value: // remaining after the purge then we can allow the volume to be locked. // @@ -1834,7 +284,7 @@ index ab7c079..ebfb7d6 100644 //CdPurgeVolume( IrpContext, Vcb, FALSE ); // -@@ -1174,7 +1182,7 @@ UDFDismountVolume( +@@ -1174,7 +1174,7 @@ UDFDismountVolume( } else { @@ -1843,7 +293,7 @@ index ab7c079..ebfb7d6 100644 // Invalidate the volume right now. // -@@ -1800,7 +1808,7 @@ UDFInvalidateVolumes( +@@ -1800,7 +1800,7 @@ UDFInvalidateVolumes( UDFAcquireVcbExclusive(IrpContext, Vcb, FALSE); @@ -1853,100 +303,29 @@ index ab7c079..ebfb7d6 100644 UDFDoDismountSequence(Vcb, FALSE); diff --git a/drivers/filesystems/udfs/lockctrl.cpp b/drivers/filesystems/udfs/lockctrl.c -similarity index 100% +similarity index 99% rename from drivers/filesystems/udfs/lockctrl.cpp rename to drivers/filesystems/udfs/lockctrl.c +index 60f52a8..86489aa 100644 +--- a/drivers/filesystems/udfs/lockctrl.cpp ++++ b/drivers/filesystems/udfs/lockctrl.c +@@ -5,7 +5,7 @@ + //////////////////////////////////////////////////////////////////// + /************************************************************************* + * +-* File: LockCtrl.cpp.cpp ++* File: LockCtrl.c + * + * Module: UDF File System Driver (Kernel mode execution only) + * diff --git a/drivers/filesystems/udfs/mem.cpp b/drivers/filesystems/udfs/mem.c -similarity index 93% +similarity index 100% rename from drivers/filesystems/udfs/mem.cpp rename to drivers/filesystems/udfs/mem.c -index 072602c..301ead0 100644 ---- a/drivers/filesystems/udfs/mem.cpp -+++ b/drivers/filesystems/udfs/mem.c -@@ -8,4 +8,4 @@ - // define the file specific bug-check id - #define UDF_BUG_CHECK_ID UDF_FILE_MEM - --#include "Include/mem_tools.cpp" -+#include "Include/mem_tools.c" diff --git a/drivers/filesystems/udfs/misc.cpp b/drivers/filesystems/udfs/misc.c -similarity index 98% +similarity index 100% rename from drivers/filesystems/udfs/misc.cpp rename to drivers/filesystems/udfs/misc.c -index c78f454..63b9b0d 100644 ---- a/drivers/filesystems/udfs/misc.cpp -+++ b/drivers/filesystems/udfs/misc.c -@@ -5,7 +5,7 @@ - //////////////////////////////////////////////////////////////////// - /* - -- File: Misc.cpp -+ File: Misc.c - - Module: UDF File System Driver (Kernel mode execution only) - -@@ -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(); -@@ -711,7 +728,7 @@ UDFCreateIrpContext( - } - - // TODO: fix -- if (false && IrpSp->FileObject != NULL) { -+ if (FALSE && IrpSp->FileObject != NULL) { - - PFILE_OBJECT FileObject = IrpSp->FileObject; - -@@ -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. -@@ -2106,5 +2122,5 @@ UDFWaitForIoAtEof( - return TRUE; - } - --#include "Include/regtools.cpp" -+#include "Include/regtools.c" - diff --git a/drivers/filesystems/udfs/namesup.cpp b/drivers/filesystems/udfs/namesup.c similarity index 100% rename from drivers/filesystems/udfs/namesup.cpp @@ -1956,119 +335,10 @@ similarity index 100% rename from drivers/filesystems/udfs/pnp.cpp rename to drivers/filesystems/udfs/pnp.c diff --git a/drivers/filesystems/udfs/protos.h b/drivers/filesystems/udfs/protos.h -index 59cb00c..08f3a9c 100644 +index 59cb00c..584c9e4 100644 --- a/drivers/filesystems/udfs/protos.h +++ b/drivers/filesystems/udfs/protos.h -@@ -73,7 +73,7 @@ UDFDecodeFileObjectCcb( - - - /************************************************************************* --* Prototypes for the file create.cpp -+* Prototypes for the file create.c - *************************************************************************/ - extern NTSTATUS NTAPI UDFCreate( - IN PDEVICE_OBJECT DeviceObject, // the logical volume device object -@@ -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 -@@ -120,7 +131,7 @@ UDFInitializeFCB( - ); - - /************************************************************************* --* Prototypes for the file cleanup.cpp -+* Prototypes for the file cleanup.c - *************************************************************************/ - extern NTSTATUS NTAPI UDFCleanup( - PDEVICE_OBJECT DeviceObject, // the logical volume device object -@@ -130,17 +141,8 @@ 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 -+* Prototypes for the file close.c - *************************************************************************/ - extern NTSTATUS NTAPI UDFClose( - PDEVICE_OBJECT DeviceObject, // the logical volume device object -@@ -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 - ); - -@@ -176,7 +178,7 @@ UDFFspClose( - UDFCloseAllSystemDelayedInDir((Fcb)->Vcb, (Fcb)->FileInfo) - - /************************************************************************* --* Prototypes for the file dircntrl.cpp -+* Prototypes for the file dircntrl.c - *************************************************************************/ - extern NTSTATUS NTAPI UDFDirControl( - PDEVICE_OBJECT DeviceObject, // the logical volume device object -@@ -203,7 +205,7 @@ PFCB Fcb, - PCCB Ccb); - - /************************************************************************* --* Prototypes for the file devcntrl.cpp -+* Prototypes for the file devcntrl.c - *************************************************************************/ - extern NTSTATUS NTAPI UDFDeviceControl( - PDEVICE_OBJECT DeviceObject, // the logical volume device object -@@ -224,7 +226,7 @@ extern NTSTATUS NTAPI UDFHandleQueryPath( - PVOID BufferPointer); - - /************************************************************************* --* Prototypes for the file fastio.cpp -+* Prototypes for the file fastio.c - *************************************************************************/ - extern BOOLEAN NTAPI UDFFastIoCheckIfPossible( - IN PFILE_OBJECT FileObject, -@@ -360,7 +362,7 @@ UDFFastIoCopyWrite( - ); - - /************************************************************************* --* Prototypes for the file fileinfo.cpp -+* Prototypes for the file fileinfo.c - *************************************************************************/ - - extern NTSTATUS UDFCommonQueryInfo( -@@ -516,7 +518,7 @@ UDFHardLink( - ); - - /************************************************************************* --* Prototypes for the file flush.cpp -+* Prototypes for the file flush.c - *************************************************************************/ - extern NTSTATUS NTAPI UDFFlushBuffers( - PDEVICE_OBJECT DeviceObject, // the logical volume device object -@@ -531,7 +533,7 @@ ULONG UDFFlushAFile( +@@ -531,7 +531,7 @@ ULONG UDFFlushAFile( IN PFCB Fcb, IN PCCB Ccb, OUT PIO_STATUS_BLOCK PtrIoStatus, @@ -2077,7 +347,7 @@ index 59cb00c..08f3a9c 100644 ); ULONG -@@ -540,14 +542,14 @@ UDFFlushADirectory( +@@ -540,14 +540,14 @@ UDFFlushADirectory( IN PVCB Vcb, IN PUDF_FILE_INFO FI, OUT PIO_STATUS_BLOCK PtrIoStatus, @@ -2094,7 +364,7 @@ index 59cb00c..08f3a9c 100644 ); extern NTSTATUS NTAPI UDFFlushCompletion( -@@ -557,13 +559,13 @@ PVOID Context); +@@ -557,7 +557,7 @@ PVOID Context); extern BOOLEAN UDFFlushIsBreaking( IN PVCB Vcb, @@ -2103,111 +373,7 @@ index 59cb00c..08f3a9c 100644 extern VOID UDFFlushTryBreak( IN PVCB Vcb); - - /************************************************************************* --* Prototypes for the file fscntrl.cpp -+* Prototypes for the file fscntrl.c - *************************************************************************/ - - extern NTSTATUS NTAPI UDFFSControl( -@@ -659,7 +661,7 @@ UDFCommonPnp( - ); - - /************************************************************************* --* Prototypes for the file LockCtrl.cpp -+* Prototypes for the file LockCtrl.c - *************************************************************************/ - - extern NTSTATUS NTAPI UDFLockControl( -@@ -670,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, -@@ -707,7 +711,7 @@ UDFFastUnlockAllByKey( - ); - - /************************************************************************* --* Prototypes for the file misc.cpp -+* Prototypes for the file misc.c - *************************************************************************/ - extern NTSTATUS UDFInitializeZones( - VOID); -@@ -769,6 +773,49 @@ UDFDeleteCcb( - PCCB Ccb - ); - -+// prefxsup.c - 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, -@@ -779,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( -@@ -842,7 +893,7 @@ UDFReadRegKeys( +@@ -842,7 +842,7 @@ UDFReadRegKeys( extern ULONG UDFGetRegParameter( IN PVCB Vcb, IN PCWSTR Name, @@ -2216,140 +382,6 @@ index 59cb00c..08f3a9c 100644 VOID UDFDeleteVCB( -@@ -882,13 +933,13 @@ UDFCreateFileLock( - ); - - /************************************************************************* --* Prototypes for the file NameSup.cpp -+* Prototypes for the file NameSup.c - *************************************************************************/ - - #include "namesup.h" - - /************************************************************************* --* Prototypes for the file Pnp.cpp -+* Prototypes for the file Pnp.c - *************************************************************************/ - NTSTATUS - NTAPI -@@ -898,7 +949,7 @@ UDFPnp ( - ); - - /************************************************************************* --* Prototypes for the file read.cpp -+* Prototypes for the file read.c - *************************************************************************/ - extern NTSTATUS NTAPI UDFRead( - PDEVICE_OBJECT DeviceObject, // the logical volume device object -@@ -952,7 +1003,7 @@ UDFSetAccessRights( - USHORT ShareAccess); - - /************************************************************************* --* Prototypes for the file Shutdown.cpp -+* Prototypes for the file Shutdown.c - *************************************************************************/ - - NTSTATUS -@@ -962,9 +1013,9 @@ UDFCommonShutdown( - ); - - /************************************************************************* --* Prototypes for the file UDFinit.cpp -+* Prototypes for the file UDFinit.c - *************************************************************************/ --extern "C" NTSTATUS NTAPI DriverEntry( -+NTSTATUS NTAPI DriverEntry( - PDRIVER_OBJECT DriverObject, // created by the I/O sub-system - PUNICODE_STRING RegistryPath); // path to the registry key - -@@ -972,7 +1023,7 @@ extern VOID NTAPI UDFInitializeFunctionPointers( - PDRIVER_OBJECT DriverObject); // created by the I/O sub-system - - /************************************************************************* --* Prototypes for the file verify.cpp -+* Prototypes for the file verify.c - *************************************************************************/ - - VOID -@@ -1024,7 +1075,7 @@ UDFCompareVcb( - ); - - /************************************************************************* --* Prototypes for the file VolInfo.cpp -+* Prototypes for the file VolInfo.c - *************************************************************************/ - extern NTSTATUS NTAPI UDFQueryVolInfo(PDEVICE_OBJECT DeviceObject, - PIRP Irp); -@@ -1051,7 +1102,7 @@ UDFCommonSetVolInfo( - ); - - /************************************************************************* --* Prototypes for the file write.cpp -+* Prototypes for the file write.c - *************************************************************************/ - extern NTSTATUS NTAPI UDFWrite( - PDEVICE_OBJECT DeviceObject, // the logical volume device object -@@ -1217,13 +1268,13 @@ UDFMarkDevForVerifyIfVcbMounted( - UdfData.UdfDataLockThread = NULL; \ - ExReleaseFastMutexUnsafe(&UdfData.UdfDataMutex) - --enum TYPE_OF_ACQUIRE { -+typedef enum TYPE_OF_ACQUIRE { - - AcquireExclusive, - AcquireShared, - AcquireSharedStarveExclusive - --}; -+} TYPE_OF_ACQUIRE; - - _Requires_lock_held_(_Global_critical_region_) - _When_(Type == AcquireExclusive && return != FALSE, _Acquires_exclusive_lock_(*Resource)) -@@ -1271,7 +1322,7 @@ UDFAcquireResource( - #define UDFReleasePagingIo(IC,F) \ - ExReleaseResourceLite((F)->Header.PagingIoResource) - --inline -+static inline - ULONG - UDFHighBit( - ULONG Word -@@ -1295,7 +1346,7 @@ UDFHighBit( - - #define SectorSize(V) ((V)->SectorSize) - --inline -+static inline - ULONG - SectorAlign( - PVCB Vcb, -@@ -1305,7 +1356,7 @@ SectorAlign( - return (Length + (Vcb->SectorSize - 1)) & ~(Vcb->SectorSize - 1); - } - --inline -+static inline - ULONGLONG - LlSectorAlign( - PVCB Vcb, -@@ -1327,7 +1378,7 @@ UDFSetThreadContext( - (IC)->ThreadContext = NULL - - --inline -+static inline - BOOLEAN UdfIsExtendedFESupported( - _In_ PVCB Vcb - ) -@@ -1335,7 +1386,7 @@ BOOLEAN UdfIsExtendedFESupported( - return Vcb->NSRDesc == VRS_NSR03_FOUND; - } - --inline -+static inline - BOOLEAN UDFIsStreamsSupported( - _In_ PVCB Vcb - ) diff --git a/drivers/filesystems/udfs/read.cpp b/drivers/filesystems/udfs/read.c similarity index 100% rename from drivers/filesystems/udfs/read.cpp @@ -2362,18 +394,9 @@ diff --git a/drivers/filesystems/udfs/shutdown.cpp b/drivers/filesystems/udfs/sh similarity index 99% rename from drivers/filesystems/udfs/shutdown.cpp rename to drivers/filesystems/udfs/shutdown.c -index f8b0a7f..79b132c 100644 ---- a/drivers/filesystems/udfs/shutdown.cpp -+++ b/drivers/filesystems/udfs/shutdown.c -@@ -5,7 +5,7 @@ - //////////////////////////////////////////////////////////////////// - /************************************************************************* - * --* File: Shutdown.cpp -+* File: Shutdown.c - * - * Module: UDF File System Driver (Kernel mode execution only) - * +index f8b0a7f..314b0e2 100644 +--- a/drivers/filesystems/udfs/shutdown.cpp ++++ b/drivers/filesystems/udfs/shutdown.c @@ -109,7 +109,7 @@ UDFCommonShutdown( UDFAcquireVcbExclusive(IrpContext, Vcb, FALSE); @@ -2384,704 +407,21 @@ index f8b0a7f..79b132c 100644 ASSERT(CONTAINING_RECORD(IoGetCurrentIrpStackLocation(Irp)->DeviceObject, VOLUME_DEVICE_OBJECT, diff --git a/drivers/filesystems/udfs/strucsup.cpp b/drivers/filesystems/udfs/strucsup.c -similarity index 68% +similarity index 100% rename from drivers/filesystems/udfs/strucsup.cpp rename to drivers/filesystems/udfs/strucsup.c -index 6e00af7..544b7ad 100644 ---- a/drivers/filesystems/udfs/strucsup.cpp -+++ b/drivers/filesystems/udfs/strucsup.c -@@ -29,7 +29,24 @@ typedef struct _FCB_TABLE_ELEMENT { - RtlDeleteElementGenericTable( &(F)->Vcb->FcbTable, &_Key ); \ - } - --inline -+// -+// Public wrapper for inserting FCB into FcbTable. -+// Called from create.c 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); -+} -+ -+static inline - PFCB_NONPAGED - UDFAllocateFcbNonpaged( - ) -@@ -37,7 +54,7 @@ UDFAllocateFcbNonpaged( - return (PFCB_NONPAGED)ExAllocateFromNPagedLookasideList(&UdfData.UDFNonPagedFcbLookasideList); - } - --inline -+static inline - PFCB - UDFAllocateFcbIndex( - ) -@@ -45,7 +62,7 @@ UDFAllocateFcbIndex( - return (PFCB)ExAllocateFromPagedLookasideList(&UdfData.UDFFcbIndexLookasideList); - } - --inline -+static inline - PFCB - UDFAllocateFcbData( - ) -@@ -53,7 +70,7 @@ UDFAllocateFcbData( - return (PFCB)ExAllocateFromPagedLookasideList(&UdfData.UDFFcbDataLookasideList); - } - --inline -+static inline - PFCB - UDFAllocateFcb( - ) -@@ -61,7 +78,7 @@ UDFAllocateFcb( - return (PFCB)ExAllocatePoolWithTag(NonPagedPool, sizeof(FCB), TAG_FCB); - } - --inline -+static inline - VOID - UDFDeallocateFcbNonpaged( - PFCB_NONPAGED FcbNonpaged -@@ -70,7 +87,7 @@ UDFDeallocateFcbNonpaged( - ExFreeToNPagedLookasideList(&UdfData.UDFNonPagedFcbLookasideList, FcbNonpaged); - } - --inline -+static inline - VOID - UDFDeallocateFcbIndex( - PFCB Fcb -@@ -79,7 +96,7 @@ UDFDeallocateFcbIndex( - ExFreeToPagedLookasideList(&UdfData.UDFFcbIndexLookasideList, Fcb); - } - --inline -+static inline - VOID - UDFDeallocateFcbData( - PFCB Fcb -@@ -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, 0); -+ 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, 0); -+ } -+ -+ // 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 fb48f5e..53eb53b 100644 +index fb48f5e..efd97d9 100644 --- a/drivers/filesystems/udfs/struct.h +++ b/drivers/filesystems/udfs/struct.h -@@ -36,6 +36,24 @@ - struct IRP_CONTEXT_LITE; +@@ -37,6 +37,21 @@ struct IRP_CONTEXT_LITE; struct IO_CONTEXT; struct IRP_CONTEXT; -+struct LCB; -+typedef struct LCB *PLCB; -+ -+/* C typedef aliases – allow plain name usage without the 'struct' keyword */ + ++/* C typedef aliases - allow plain name usage without the 'struct' keyword */ +typedef struct IRP_CONTEXT_LITE IRP_CONTEXT_LITE; +typedef struct IO_CONTEXT IO_CONTEXT; +typedef struct IRP_CONTEXT IRP_CONTEXT; -+typedef struct LCB LCB; +typedef struct UDFIdentifier UDFIdentifier; +typedef struct UDFObjectName UDFObjectName; +typedef struct CCB CCB; @@ -3092,20 +432,11 @@ index fb48f5e..53eb53b 100644 +typedef struct VCB VCB; +typedef struct VOLUME_DEVICE_OBJECT VOLUME_DEVICE_OBJECT; +typedef struct THREAD_CONTEXT THREAD_CONTEXT; - ++ /************************************************************************** every structure has a node type, and a node size associated with it. -@@ -47,8 +65,7 @@ struct UDFIdentifier { - NODE_BYTE_SIZE NodeByteSize; // computed as sizeof(structure) - }; - --static_assert(sizeof(UDFIdentifier) == offsetof(FSRTL_ADVANCED_FCB_HEADER, Flags), -- "UDFIdentifier size mismatch with NodeTypeCode and NodeByteSize in FSRTL_ADVANCED_FCB_HEADER"); -+C_ASSERT(sizeof(UDFIdentifier) == offsetof(FSRTL_ADVANCED_FCB_HEADER, Flags)); - - /************************************************************************** - Every open on-disk object must have a name associated with it -@@ -67,7 +84,7 @@ struct UDFObjectName { + The node type serves as a signature field. The size is used for +@@ -67,7 +82,7 @@ struct UDFObjectName { // an absolute pathname of the object is stored below UNICODE_STRING ObjectName; }; @@ -3114,27 +445,16 @@ index fb48f5e..53eb53b 100644 /************************************************************************** Each file open instance is represented by a context control block. -@@ -82,6 +99,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,9 +113,8 @@ struct CCB { - // need to maintain a search pattern - PUNICODE_STRING DirectorySearchPattern; +@@ -96,7 +111,7 @@ struct CCB { HASH_ENTRY hashes; -- ULONG TreeLength; + ULONG TreeLength; }; -using PCCB = CCB*; +typedef CCB* PCCB; #define CCB_FLAG_IGNORE_CASE (0x00000004) // the CCB has had an IRP_MJ_CLEANUP issued on it. we must -@@ -152,7 +170,7 @@ struct FCB_NONPAGED { +@@ -152,7 +167,7 @@ struct FCB_NONPAGED { FAST_MUTEX AdvancedFcbHeaderMutex; }; @@ -3143,35 +463,7 @@ index fb48f5e..53eb53b 100644 /************************************************************************** each open file/directory/volume is represented by a file control block. -@@ -193,11 +211,11 @@ using PFCB_NONPAGED = FCB_NONPAGED*; - /***************************************************/ - - struct FCB_DATA { -- -+ UCHAR Placeholder; - }; - - struct FCB_INDEX { -- -+ UCHAR Placeholder; - }; - - struct FCB { -@@ -267,6 +285,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; -@@ -284,7 +309,7 @@ struct FCB { +@@ -284,7 +299,7 @@ struct FCB { FCB_INDEX FcbIndex; }; }; @@ -3180,82 +472,7 @@ index fb48f5e..53eb53b 100644 #define SIZEOF_FCB_DATA \ (FIELD_OFFSET(FCB, FcbType) + sizeof(FCB_DATA)) -@@ -325,7 +350,7 @@ using PFCB = FCB*; - - **************************************************************************/ - --enum UDFFSD_MEDIA_TYPE { -+typedef enum UDFFSD_MEDIA_TYPE { - MediaUnknown = 0, - MediaHdd, - MediaCdr, -@@ -335,16 +360,63 @@ enum UDFFSD_MEDIA_TYPE { - MediaFloppy, - MediaDvdr, - MediaDvdrw -+} UDFFSD_MEDIA_TYPE; -+ -+//*************************************************************************** -+// 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; - }; - --enum VCB_CONDITION { -+// 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) -+//*************************************************************************** -+ -+typedef enum VCB_CONDITION { - - VcbNotMounted = 0, - VcbMountInProgress, - VcbMounted, - VcbInvalid, - VcbDismountInProgress --}; -+} VCB_CONDITION; - - struct VCB { - -@@ -608,7 +680,7 @@ struct VCB { +@@ -608,7 +623,7 @@ struct VCB { PVPB SwapVpb; }; @@ -3264,7 +481,7 @@ index fb48f5e..53eb53b 100644 // One for root #define UDFS_BASE_RESIDUAL_REFERENCE (4)//(6) -@@ -682,7 +754,7 @@ struct THREAD_CONTEXT { +@@ -682,7 +697,7 @@ struct THREAD_CONTEXT { // will store the IrpContext for the request in this stack location. IRP_CONTEXT* TopLevelIrpContext; }; @@ -3273,15 +490,7 @@ index fb48f5e..53eb53b 100644 /************************************************************************** The IRP context encapsulates the current request. This structure is -@@ -707,7 +779,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. -@@ -727,7 +798,7 @@ struct IRP_CONTEXT { +@@ -727,7 +742,7 @@ struct IRP_CONTEXT { VCB* Vcb; }; @@ -3290,58 +499,19 @@ index fb48f5e..53eb53b 100644 #define IRP_CONTEXT_FLAG_ON_STACK (0x00000001) #define IRP_CONTEXT_FLAG_MORE_PROCESSING (0x00000002) -@@ -792,9 +863,8 @@ struct IRP_CONTEXT_LITE { - ULONG UserReference; - // Real device object. This represents the physical device closest to the media. +@@ -794,7 +809,7 @@ struct IRP_CONTEXT_LITE { PDEVICE_OBJECT RealDevice; -- ULONG TreeLength; + ULONG TreeLength; }; -using PIRP_CONTEXT_LITE = IRP_CONTEXT_LITE*; +typedef IRP_CONTEXT_LITE* PIRP_CONTEXT_LITE; /************************************************************************** we will store all of our global variables in one structure. -@@ -837,6 +907,7 @@ typedef struct _UDFData { - PAGED_LOOKASIDE_LIST UDFFcbDataLookasideList; - - PAGED_LOOKASIDE_LIST CcbLookasideList; -+ PAGED_LOOKASIDE_LIST LcbLookasideList; - - LIST_ENTRY AsyncCloseQueue; - ULONG AsyncCloseCount; -@@ -877,6 +948,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/sys_spec.cpp b/drivers/filesystems/udfs/sys_spec.c -similarity index 89% +similarity index 100% rename from drivers/filesystems/udfs/sys_spec.cpp rename to drivers/filesystems/udfs/sys_spec.c -index e9a11ab..cd77a8f 100644 ---- a/drivers/filesystems/udfs/sys_spec.cpp -+++ b/drivers/filesystems/udfs/sys_spec.c -@@ -5,7 +5,7 @@ - //////////////////////////////////////////////////////////////////// - /************************************************************************* - * --* File: Sys_Spec.cpp -+* File: Sys_Spec.c - * - * Module: UDF File System Driver - * (both User and Kernel mode execution) -@@ -20,6 +20,6 @@ - // define the file specific bug-check id - #define UDF_BUG_CHECK_ID UDF_FILE_SYS_SPEC - --#include "Include/Sys_spec_lib.cpp" -+#include "Include/Sys_spec_lib.c" - --//#include "Include/tools.cpp" -+//#include "Include/tools.c" diff --git a/drivers/filesystems/udfs/udf_dbg.cpp b/drivers/filesystems/udfs/udf_dbg.c similarity index 100% rename from drivers/filesystems/udfs/udf_dbg.cpp @@ -3368,13 +538,14 @@ similarity index 100% rename from drivers/filesystems/udfs/udf_info/dirtree.cpp rename to drivers/filesystems/udfs/udf_info/dirtree.c diff --git a/drivers/filesystems/udfs/udf_info/ecma_167.h b/drivers/filesystems/udfs/udf_info/ecma_167.h -index 6ca06a7..36ace5e 100644 +index 6ca06a7..0c60fd3 100644 --- a/drivers/filesystems/udfs/udf_info/ecma_167.h +++ b/drivers/filesystems/udfs/udf_info/ecma_167.h -@@ -770,6 +770,39 @@ typedef struct _EXTENDED_FILE_ENTRY { +@@ -774,3 +774,36 @@ typedef EXTENDED_FILE_ENTRY ExtendedFileEntry; - typedef EXTENDED_FILE_ENTRY ExtendedFileEntry; + #endif /* __ECMA_167_H__ */ ++ +/* C typedef aliases for all non-typedef struct declarations */ +typedef struct VolStructDesc VolStructDesc; +typedef struct BeginningExtendedAreaDesc BeginningExtendedAreaDesc; @@ -3407,10 +578,6 @@ index 6ca06a7..36ace5e 100644 +typedef struct PartitionIntegrityEntry PartitionIntegrityEntry; +typedef struct LogicalVolHeaderDesc LogicalVolHeaderDesc; +typedef struct PathComponent PathComponent; -+ - #pragma pack(pop) - - #endif /* __ECMA_167_H__ */ diff --git a/drivers/filesystems/udfs/udf_info/extent.cpp b/drivers/filesystems/udfs/udf_info/extent.c similarity index 100% rename from drivers/filesystems/udfs/udf_info/extent.cpp @@ -3419,18 +586,9 @@ diff --git a/drivers/filesystems/udfs/udf_info/mount.cpp b/drivers/filesystems/u similarity index 99% rename from drivers/filesystems/udfs/udf_info/mount.cpp rename to drivers/filesystems/udfs/udf_info/mount.c -index 3fc100a..97a77d4 100644 +index 3fc100a..370bb99 100644 --- a/drivers/filesystems/udfs/udf_info/mount.cpp +++ b/drivers/filesystems/udfs/udf_info/mount.c -@@ -6,7 +6,7 @@ - /* - Module name: - -- mount.cpp -+ mount.c - - Abstract: - @@ -915,7 +915,7 @@ UDFUpdateNonAllocated( } UDFPackMapping(Vcb, DataLoc); @@ -3472,21 +630,12 @@ index f9813bf..60b522c 100644 #endif /* _OSTA_MISC_H */ diff --git a/drivers/filesystems/udfs/udf_info/phys_eject.cpp b/drivers/filesystems/udfs/udf_info/phys_eject.c -similarity index 97% +similarity index 98% rename from drivers/filesystems/udfs/udf_info/phys_eject.cpp rename to drivers/filesystems/udfs/udf_info/phys_eject.c -index 2a7a794..32e98ab 100644 +index 2a7a794..d07cced 100644 --- a/drivers/filesystems/udfs/udf_info/phys_eject.cpp +++ b/drivers/filesystems/udfs/udf_info/phys_eject.c -@@ -4,7 +4,7 @@ - // This file was released under the GPLv2 on June 2015. - //////////////////////////////////////////////////////////////////// - /* -- Module Name: Phys_eject.cpp -+ Module Name: Phys_eject.c - - Execution: Kernel mode only - @@ -28,7 +28,7 @@ UDFDoDismountSequence( ULONG i; @@ -3505,21 +654,12 @@ similarity index 100% rename from drivers/filesystems/udfs/udf_info/remap.cpp rename to drivers/filesystems/udfs/udf_info/remap.c diff --git a/drivers/filesystems/udfs/udf_info/udf_info.cpp b/drivers/filesystems/udfs/udf_info/udf_info.c -similarity index 96% +similarity index 99% rename from drivers/filesystems/udfs/udf_info/udf_info.cpp rename to drivers/filesystems/udfs/udf_info/udf_info.c -index e5d0b69..b218cdc 100644 +index e5d0b69..86f90dd 100644 --- a/drivers/filesystems/udfs/udf_info/udf_info.cpp +++ b/drivers/filesystems/udfs/udf_info/udf_info.c -@@ -6,7 +6,7 @@ - /* - Module name: - -- udf_info.cpp -+ udf_info.c - - Abstract: - @@ -1835,7 +1835,7 @@ UDFUnlinkFile__( PUDF_FILE_INFO SFileInfo; // ... try to open it @@ -3574,186 +714,7 @@ index e5d0b69..b218cdc 100644 AdPrint((" ")); UDFUnlinkFile__(IrpContext, Vcb, FileInfo, TRUE); UDFCloseFile__(IrpContext, Vcb, FileInfo); -@@ -2149,6 +2149,178 @@ init_tree_entry: - } // 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 - */ -@@ -2421,7 +2593,7 @@ UDFCleanUpFile__( +@@ -2421,7 +2421,7 @@ UDFCleanUpFile__( MyFreePool__(DirNdx->FName.Buffer); } // The only place where we can free FE_Charge extent is here @@ -3762,21 +723,7 @@ index e5d0b69..b218cdc 100644 UDFDirIndexFree(Dloc->DirIndex); Dloc->DirIndex = NULL; #ifdef UDF_TRACK_ONDISK_ALLOCATION -@@ -2863,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; -@@ -3099,7 +3275,7 @@ UDFCloseFile__( +@@ -3099,7 +3099,7 @@ UDFCloseFile__( if (FileInfo->Dloc && FileInfo->Dloc->DirIndex) { @@ -3785,7 +732,7 @@ index e5d0b69..b218cdc 100644 if (FileInfo->Dloc->DataLoc.Flags & EXTENT_FLAG_PREALLOCATED) { FileInfo->Dloc->DataLoc.Flags |= EXTENT_FLAG_CUT_PREALLOCATED; status = UDFResizeExtent(IrpContext, Vcb, PartNum, UDFGetFileSize(FileInfo), FALSE, &(FileInfo->Dloc->DataLoc)); -@@ -3276,7 +3452,7 @@ cleanup_and_abort_rename: +@@ -3276,7 +3276,7 @@ cleanup_and_abort_rename: // unlink source FileIdent if (!NT_SUCCESS(status = UDFUnlinkFile__(IrpContext, Vcb, FileInfo, FALSE))) { // kill newly created entry @@ -3794,16 +741,7 @@ index e5d0b69..b218cdc 100644 UDFUnlinkFile__(IrpContext, Vcb, FileInfo2, TRUE); UDFCloseFile__(IrpContext, Vcb, FileInfo2); UDFCleanUpFile__(Vcb, FileInfo2); -@@ -3618,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: -@@ -4174,7 +4352,7 @@ UDFFlushFile__( +@@ -4174,7 +4174,7 @@ UDFFlushFile__( // if Lite Flush is used, keep preallocations if (!(FlushFlags & UDF_FLUSH_FLAGS_LITE)) { full_flush: @@ -3812,7 +750,7 @@ index e5d0b69..b218cdc 100644 if (FileInfo->Dloc->DataLoc.Flags & EXTENT_FLAG_PREALLOCATED) { FileInfo->Dloc->DataLoc.Flags |= EXTENT_FLAG_CUT_PREALLOCATED; status = UDFResizeExtent(IrpContext, Vcb, PartNum, UDFGetFileSize(FileInfo), FALSE, &(FileInfo->Dloc->DataLoc)); -@@ -4991,7 +5169,7 @@ UDFRecordVAT( +@@ -4991,7 +4991,7 @@ UDFRecordVAT( UDFPhysLbaToPart(Vcb, PartNum, VatFileInfo->Dloc->DataLoc.Mapping[0].extLocation); // record data if (NT_SUCCESS(status = UDFWriteFile__(IrpContext, Vcb, VatFileInfo, 0, VatLen + hdrLen, FALSE, New, &WrittenBytes))) { @@ -3821,7 +759,7 @@ index e5d0b69..b218cdc 100644 } return status; } -@@ -5097,7 +5275,7 @@ UDFRecordVAT( +@@ -5097,7 +5097,7 @@ UDFRecordVAT( UDFPhysLbaToPart(Vcb, PartNum, VatFileInfo->Dloc->FELoc.Mapping[0].extLocation); VatFileInfo->Dloc->DataLoc.Modified = TRUE; @@ -3831,34 +769,10 @@ index e5d0b69..b218cdc 100644 return status; diff --git a/drivers/filesystems/udfs/udf_info/udf_info.h b/drivers/filesystems/udfs/udf_info/udf_info.h -index c10108a..e61fa21 100644 +index c10108a..d284982 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 -@@ -444,7 +461,7 @@ void UDFFreeFESpace(IN PVCB Vcb, +@@ -444,7 +444,7 @@ void UDFFreeFESpace(IN PVCB Vcb, // flush FE charge void UDFFlushFESpace(IN PVCB Vcb, IN PUDF_DATALOC_INFO Dloc, @@ -3867,7 +781,7 @@ index c10108a..e61fa21 100644 // discard file allocation void UDFFreeFileAllocation(IN PVCB Vcb, IN PUDF_FILE_INFO DirInfo, -@@ -1022,7 +1039,7 @@ UDFFlushFile__( +@@ -1022,7 +1022,7 @@ UDFFlushFile__( IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN PUDF_FILE_INFO FileInfo, @@ -3877,7 +791,7 @@ index c10108a..e61fa21 100644 // check if the file is flushed diff --git a/drivers/filesystems/udfs/udf_info/udf_rel.h b/drivers/filesystems/udfs/udf_info/udf_rel.h -index 602a8f6..f62ef96 100644 +index 602a8f6..2b26348 100644 --- a/drivers/filesystems/udfs/udf_info/udf_rel.h +++ b/drivers/filesystems/udfs/udf_info/udf_rel.h @@ -246,7 +246,7 @@ typedef struct _UDF_DATALOC_INFO { @@ -3889,60 +803,10 @@ index 602a8f6..f62ef96 100644 /** Describes on-disk location of user data. If the file is recorded using IN_ICB method this structure points to the -@@ -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/udfdata.cpp b/drivers/filesystems/udfs/udfdata.c similarity index 100% rename from drivers/filesystems/udfs/udfdata.cpp rename to drivers/filesystems/udfs/udfdata.c -diff --git a/drivers/filesystems/udfs/udffs.h b/drivers/filesystems/udfs/udffs.h -index 5eff0e0..770bbcc 100644 ---- a/drivers/filesystems/udfs/udffs.h -+++ b/drivers/filesystems/udfs/udffs.h -@@ -161,7 +161,7 @@ extern UDFData UdfData; - - // Encapsulate safe pool freeing - --inline -+static inline - VOID - UDFFreePool( - _Inout_ _At_(*Pool, __drv_freesMem(Mem) _Post_null_) PVOID *Pool -@@ -180,7 +180,7 @@ UDFFreePool( - - // small check for illegal open mode (desired access) if volume is - // read only (on standard CD-ROM device or another like this) --inline -+static inline - BOOLEAN - UDFIllegalFcbAccess( - IN PVCB Vcb, -@@ -426,7 +426,7 @@ UDFIllegalFcbAccess( - - #define FID_DIR_MASK 0x80000000 // high order bit means directory. - --inline -+static inline - FILE_ID - UdfGetFidFromLbAddr(lb_addr lbAddr) - { diff --git a/drivers/filesystems/udfs/udfinit.cpp b/drivers/filesystems/udfs/udfinit.c similarity index 100% rename from drivers/filesystems/udfs/udfinit.cpp @@ -3960,80 +824,12 @@ similarity index 100% rename from drivers/filesystems/udfs/volinfo.cpp rename to drivers/filesystems/udfs/volinfo.c diff --git a/drivers/filesystems/udfs/write.cpp b/drivers/filesystems/udfs/write.c -similarity index 97% +similarity index 99% rename from drivers/filesystems/udfs/write.cpp rename to drivers/filesystems/udfs/write.c -index 5977f3e..d2309ee 100644 +index 5977f3e..1f236e6 100644 --- a/drivers/filesystems/udfs/write.cpp +++ b/drivers/filesystems/udfs/write.c -@@ -5,7 +5,7 @@ - //////////////////////////////////////////////////////////////////// - /************************************************************************* - * --* File: Write.cpp -+* File: Write.c - * - * Module: UDF File System Driver (Kernel mode execution only) - * -@@ -44,7 +44,9 @@ UDFCommonWrite( - NTSTATUS Status = STATUS_SUCCESS; - PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); - LONGLONG StartingOffset; -- ULONG ByteCount = 0, TruncatedLength = 0; -+ ULONG ByteCount; -+ LONGLONG ByteRange; -+ ULONG TruncatedLength; - SIZE_T NumberBytesWritten = 0; - PFILE_OBJECT FileObject = NULL; - TYPE_OF_OPEN TypeOfOpen; -@@ -60,9 +62,6 @@ UDFCommonWrite( - BOOLEAN MainResourceAcquired = FALSE; - BOOLEAN VcbAcquired = FALSE; - -- BOOLEAN MainResourceAcquiredExclusive = FALSE; -- BOOLEAN MainResourceCanDemoteToShared = FALSE; -- - BOOLEAN Wait = FALSE; - BOOLEAN PagingIo = FALSE; - BOOLEAN NonCachedIo = FALSE; -@@ -74,6 +73,14 @@ UDFCommonWrite( - BOOLEAN ZeroBlock = FALSE; - BOOLEAN ZeroBlockDone = FALSE; - -+ // Examine our input parameters to determine if this is noncached and/or -+ // a paging io operation. -+ -+ 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; - - // Extract and decode the file object. -@@ -94,14 +101,6 @@ UDFCommonWrite( - ASSERT_FCB(Fcb); - ASSERT_VCB(Vcb); - -- // Examine our input parameters to determine if this is noncached and/or -- // a paging io operation. -- -- 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); -- - // Check if this volume has already been shut down. If it has, fail - // this write request. - -@@ -139,6 +138,7 @@ UDFCommonWrite( - - StartingOffset = IrpSp->Parameters.Write.ByteOffset.QuadPart; - ByteCount = IrpSp->Parameters.Write.Length; -+ ByteRange = StartingOffset + ByteCount; - - Irp->IoStatus.Information = 0; - @@ -237,7 +237,7 @@ UDFCommonWrite( // I dislike the idea of writing to mounted media too, but M$ has another point of view... if (Vcb->VcbCondition == VcbMounted) { @@ -4052,41 +848,3 @@ index 5977f3e..d2309ee 100644 UDFUnlockCallersBuffer(IrpContext, Irp, SystemBuffer); try_return(Status); } -@@ -334,8 +334,6 @@ UDFCommonWrite( - if (!SuccessfulPurge) { - try_return(Status = STATUS_PURGE_FAILED); - } -- -- MainResourceCanDemoteToShared = TRUE; - } - - // Determine if we were called by the lazywriter. -@@ -422,19 +420,6 @@ UDFCommonWrite( - 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, Wait)) { -- try_return(Status = STATUS_PENDING); -- } -- MainResourceAcquired = TRUE; -- } -- - UDFAcquireResourceExclusive(&Fcb->FcbNonpaged->FcbPagingIoResource, TRUE); - PagingIoResourceAcquired = TRUE; - -@@ -755,7 +740,7 @@ UDFPurgeCacheEx_( - - // We'll just purge cache section here, - // without call to CcZeroData() -- // 'cause udf_info.cpp will care about it -+ // 'cause udf_info.c will care about it - - #define PURGE_BLOCK_SZ 0x10000000 - From 31d4a41d716f3a3ae9787ed6c375cc93eb7d71ea Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 6 Mar 2026 15:38:26 +0000 Subject: [PATCH 11/20] Fix MSVC C compilation errors: empty structs, enum typedefs, extern C, NSRDesc conflict Co-authored-by: Zero3K20 <258969903+Zero3K20@users.noreply.github.com> --- drivers/filesystems/udfs/protos.h | 3 +- drivers/filesystems/udfs/struct.h | 6 +- drivers/filesystems/udfs/udf_info/ecma_167.h | 1 - udfs-for-write-branch.patch | 64 +++++++++++++++++--- 4 files changed, 61 insertions(+), 13 deletions(-) diff --git a/drivers/filesystems/udfs/protos.h b/drivers/filesystems/udfs/protos.h index 584c9e4f57ab6..108b1ea853a56 100644 --- a/drivers/filesystems/udfs/protos.h +++ b/drivers/filesystems/udfs/protos.h @@ -964,7 +964,7 @@ UDFCommonShutdown( /************************************************************************* * Prototypes for the file UDFinit.cpp *************************************************************************/ -extern "C" NTSTATUS NTAPI DriverEntry( +NTSTATUS NTAPI DriverEntry( PDRIVER_OBJECT DriverObject, // created by the I/O sub-system PUNICODE_STRING RegistryPath); // path to the registry key @@ -1224,6 +1224,7 @@ enum TYPE_OF_ACQUIRE { AcquireSharedStarveExclusive }; +typedef enum TYPE_OF_ACQUIRE TYPE_OF_ACQUIRE; _Requires_lock_held_(_Global_critical_region_) _When_(Type == AcquireExclusive && return != FALSE, _Acquires_exclusive_lock_(*Resource)) diff --git a/drivers/filesystems/udfs/struct.h b/drivers/filesystems/udfs/struct.h index efd97d9d75f5c..be78aa74b4f76 100644 --- a/drivers/filesystems/udfs/struct.h +++ b/drivers/filesystems/udfs/struct.h @@ -208,11 +208,11 @@ typedef FCB_NONPAGED* PFCB_NONPAGED; /***************************************************/ struct FCB_DATA { - + UCHAR Pad; }; struct FCB_INDEX { - + UCHAR Pad; }; struct FCB { @@ -351,6 +351,7 @@ enum UDFFSD_MEDIA_TYPE { MediaDvdr, MediaDvdrw }; +typedef enum UDFFSD_MEDIA_TYPE UDFFSD_MEDIA_TYPE; enum VCB_CONDITION { @@ -360,6 +361,7 @@ enum VCB_CONDITION { VcbInvalid, VcbDismountInProgress }; +typedef enum VCB_CONDITION VCB_CONDITION; struct VCB { diff --git a/drivers/filesystems/udfs/udf_info/ecma_167.h b/drivers/filesystems/udfs/udf_info/ecma_167.h index 0c60fd3ed64a4..8343008f62eb6 100644 --- a/drivers/filesystems/udfs/udf_info/ecma_167.h +++ b/drivers/filesystems/udfs/udf_info/ecma_167.h @@ -779,7 +779,6 @@ typedef EXTENDED_FILE_ENTRY ExtendedFileEntry; typedef struct VolStructDesc VolStructDesc; typedef struct BeginningExtendedAreaDesc BeginningExtendedAreaDesc; typedef struct TerminatingExtendedAreaDesc TerminatingExtendedAreaDesc; -typedef struct NSRDesc NSRDesc; typedef struct PrimaryVolDesc PrimaryVolDesc; typedef struct AnchorVolDescPtr AnchorVolDescPtr; typedef struct VolDescPtr VolDescPtr; diff --git a/udfs-for-write-branch.patch b/udfs-for-write-branch.patch index 170421db945cd..ab1ab0a095574 100644 --- a/udfs-for-write-branch.patch +++ b/udfs-for-write-branch.patch @@ -335,7 +335,7 @@ similarity index 100% rename from drivers/filesystems/udfs/pnp.cpp rename to drivers/filesystems/udfs/pnp.c diff --git a/drivers/filesystems/udfs/protos.h b/drivers/filesystems/udfs/protos.h -index 59cb00c..584c9e4 100644 +index 59cb00c..108b1ea 100644 --- a/drivers/filesystems/udfs/protos.h +++ b/drivers/filesystems/udfs/protos.h @@ -531,7 +531,7 @@ ULONG UDFFlushAFile( @@ -382,6 +382,23 @@ index 59cb00c..584c9e4 100644 VOID UDFDeleteVCB( +@@ -964,7 +964,7 @@ UDFCommonShutdown( + /************************************************************************* + * Prototypes for the file UDFinit.cpp + *************************************************************************/ +-extern "C" NTSTATUS NTAPI DriverEntry( ++NTSTATUS NTAPI DriverEntry( + PDRIVER_OBJECT DriverObject, // created by the I/O sub-system + PUNICODE_STRING RegistryPath); // path to the registry key + +@@ -1224,6 +1224,7 @@ enum TYPE_OF_ACQUIRE { + AcquireSharedStarveExclusive + + }; ++typedef enum TYPE_OF_ACQUIRE TYPE_OF_ACQUIRE; + + _Requires_lock_held_(_Global_critical_region_) + _When_(Type == AcquireExclusive && return != FALSE, _Acquires_exclusive_lock_(*Resource)) diff --git a/drivers/filesystems/udfs/read.cpp b/drivers/filesystems/udfs/read.c similarity index 100% rename from drivers/filesystems/udfs/read.cpp @@ -411,7 +428,7 @@ similarity index 100% rename from drivers/filesystems/udfs/strucsup.cpp rename to drivers/filesystems/udfs/strucsup.c diff --git a/drivers/filesystems/udfs/struct.h b/drivers/filesystems/udfs/struct.h -index fb48f5e..efd97d9 100644 +index fb48f5e..be78aa7 100644 --- a/drivers/filesystems/udfs/struct.h +++ b/drivers/filesystems/udfs/struct.h @@ -37,6 +37,21 @@ struct IRP_CONTEXT_LITE; @@ -463,6 +480,20 @@ index fb48f5e..efd97d9 100644 /************************************************************************** each open file/directory/volume is represented by a file control block. +@@ -193,11 +208,11 @@ using PFCB_NONPAGED = FCB_NONPAGED*; + /***************************************************/ + + struct FCB_DATA { +- ++ UCHAR Pad; + }; + + struct FCB_INDEX { +- ++ UCHAR Pad; + }; + + struct FCB { @@ -284,7 +299,7 @@ struct FCB { FCB_INDEX FcbIndex; }; @@ -472,7 +503,23 @@ index fb48f5e..efd97d9 100644 #define SIZEOF_FCB_DATA \ (FIELD_OFFSET(FCB, FcbType) + sizeof(FCB_DATA)) -@@ -608,7 +623,7 @@ struct VCB { +@@ -336,6 +351,7 @@ enum UDFFSD_MEDIA_TYPE { + MediaDvdr, + MediaDvdrw + }; ++typedef enum UDFFSD_MEDIA_TYPE UDFFSD_MEDIA_TYPE; + + enum VCB_CONDITION { + +@@ -345,6 +361,7 @@ enum VCB_CONDITION { + VcbInvalid, + VcbDismountInProgress + }; ++typedef enum VCB_CONDITION VCB_CONDITION; + + struct VCB { + +@@ -608,7 +625,7 @@ struct VCB { PVPB SwapVpb; }; @@ -481,7 +528,7 @@ index fb48f5e..efd97d9 100644 // One for root #define UDFS_BASE_RESIDUAL_REFERENCE (4)//(6) -@@ -682,7 +697,7 @@ struct THREAD_CONTEXT { +@@ -682,7 +699,7 @@ struct THREAD_CONTEXT { // will store the IrpContext for the request in this stack location. IRP_CONTEXT* TopLevelIrpContext; }; @@ -490,7 +537,7 @@ index fb48f5e..efd97d9 100644 /************************************************************************** The IRP context encapsulates the current request. This structure is -@@ -727,7 +742,7 @@ struct IRP_CONTEXT { +@@ -727,7 +744,7 @@ struct IRP_CONTEXT { VCB* Vcb; }; @@ -499,7 +546,7 @@ index fb48f5e..efd97d9 100644 #define IRP_CONTEXT_FLAG_ON_STACK (0x00000001) #define IRP_CONTEXT_FLAG_MORE_PROCESSING (0x00000002) -@@ -794,7 +809,7 @@ struct IRP_CONTEXT_LITE { +@@ -794,7 +811,7 @@ struct IRP_CONTEXT_LITE { PDEVICE_OBJECT RealDevice; ULONG TreeLength; }; @@ -538,10 +585,10 @@ similarity index 100% rename from drivers/filesystems/udfs/udf_info/dirtree.cpp rename to drivers/filesystems/udfs/udf_info/dirtree.c diff --git a/drivers/filesystems/udfs/udf_info/ecma_167.h b/drivers/filesystems/udfs/udf_info/ecma_167.h -index 6ca06a7..0c60fd3 100644 +index 6ca06a7..8343008 100644 --- a/drivers/filesystems/udfs/udf_info/ecma_167.h +++ b/drivers/filesystems/udfs/udf_info/ecma_167.h -@@ -774,3 +774,36 @@ typedef EXTENDED_FILE_ENTRY ExtendedFileEntry; +@@ -774,3 +774,35 @@ typedef EXTENDED_FILE_ENTRY ExtendedFileEntry; #endif /* __ECMA_167_H__ */ @@ -550,7 +597,6 @@ index 6ca06a7..0c60fd3 100644 +typedef struct VolStructDesc VolStructDesc; +typedef struct BeginningExtendedAreaDesc BeginningExtendedAreaDesc; +typedef struct TerminatingExtendedAreaDesc TerminatingExtendedAreaDesc; -+typedef struct NSRDesc NSRDesc; +typedef struct PrimaryVolDesc PrimaryVolDesc; +typedef struct AnchorVolDescPtr AnchorVolDescPtr; +typedef struct VolDescPtr VolDescPtr; From 3995e05dc18a90d6ccd5095c6d24072f408fff1a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 6 Mar 2026 20:35:45 +0000 Subject: [PATCH 12/20] Apply remaining C++ to C compilation fixes from PR #105 Co-authored-by: Zero3K20 <258969903+Zero3K20@users.noreply.github.com> --- drivers/filesystems/udfs/Include/phys_lib.c | 4 ++-- drivers/filesystems/udfs/Include/string_lib.c | 4 ---- drivers/filesystems/udfs/fscntrl.c | 2 +- drivers/filesystems/udfs/misc.c | 2 +- drivers/filesystems/udfs/strucsup.c | 4 ++-- drivers/filesystems/udfs/struct.h | 3 +-- drivers/filesystems/udfs/udf_info/udf_info.c | 2 +- drivers/filesystems/udfs/udf_info/udf_info.h | 4 ++-- 8 files changed, 10 insertions(+), 15 deletions(-) diff --git a/drivers/filesystems/udfs/Include/phys_lib.c b/drivers/filesystems/udfs/Include/phys_lib.c index 944d35bf7e2c8..c840e74ed8051 100644 --- a/drivers/filesystems/udfs/Include/phys_lib.c +++ b/drivers/filesystems/udfs/Include/phys_lib.c @@ -796,14 +796,14 @@ UDFGetBlockSize( if (UDFGetDevType(DeviceObject) == FILE_DEVICE_DISK) { UDFPrint(("UDFGetBlockSize: HDD\n")); RC = UDFPhSendIOCTL(IOCTL_DISK_GET_DRIVE_GEOMETRY_EX,DeviceObject, - 0,NULL, + NULL,0, &DiskGeometryEx,sizeof(DISK_GEOMETRY_EX), TRUE,NULL ); if (!NT_SUCCESS(RC)) try_return(RC); RC = UDFPhSendIOCTL(IOCTL_DISK_GET_PARTITION_INFO,DeviceObject, - 0,NULL, + NULL,0, &PartitionInfo,sizeof(PARTITION_INFORMATION), TRUE,NULL ); if (!NT_SUCCESS(RC)) { diff --git a/drivers/filesystems/udfs/Include/string_lib.c b/drivers/filesystems/udfs/Include/string_lib.c index 1750feb27ff16..37bd1d894879a 100644 --- a/drivers/filesystems/udfs/Include/string_lib.c +++ b/drivers/filesystems/udfs/Include/string_lib.c @@ -4,7 +4,6 @@ // This file was released under the GPLv2 on June 2015. //////////////////////////////////////////////////////////////////// -extern "C" ULONG MyRtlCompareMemory( PVOID s1, @@ -26,7 +25,6 @@ MyRtlCompareMemory( #ifndef NT_NATIVE_MODE -extern "C" ULONG RtlCompareUnicodeString( PUNICODE_STRING s1, @@ -41,7 +39,6 @@ RtlCompareUnicodeString( return i; } -extern "C" NTSTATUS RtlUpcaseUnicodeString( PUNICODE_STRING dst, @@ -57,7 +54,6 @@ RtlUpcaseUnicodeString( return STATUS_SUCCESS; } -extern "C" NTSTATUS RtlAppendUnicodeToString( IN PUNICODE_STRING Str1, diff --git a/drivers/filesystems/udfs/fscntrl.c b/drivers/filesystems/udfs/fscntrl.c index 0c0a872050d56..ec8ba4f20c179 100644 --- a/drivers/filesystems/udfs/fscntrl.c +++ b/drivers/filesystems/udfs/fscntrl.c @@ -296,7 +296,7 @@ UDFMountVolume( ASSERT(IrpSp); UDFPrint(("\n !!! UDFMountVolume\n")); - auto RealDevice = Vpb->RealDevice; + PDEVICE_OBJECT RealDevice = Vpb->RealDevice; SetDoVerifyOnFail = UDFRealDevNeedsVerify(RealDevice); diff --git a/drivers/filesystems/udfs/misc.c b/drivers/filesystems/udfs/misc.c index c78f45461cc12..cd6ffd31d2860 100644 --- a/drivers/filesystems/udfs/misc.c +++ b/drivers/filesystems/udfs/misc.c @@ -711,7 +711,7 @@ UDFCreateIrpContext( } // TODO: fix - if (false && IrpSp->FileObject != NULL) { + if (FALSE && IrpSp->FileObject != NULL) { PFILE_OBJECT FileObject = IrpSp->FileObject; diff --git a/drivers/filesystems/udfs/strucsup.c b/drivers/filesystems/udfs/strucsup.c index 6e00af7d5bd4f..e0a608e013278 100644 --- a/drivers/filesystems/udfs/strucsup.c +++ b/drivers/filesystems/udfs/strucsup.c @@ -907,7 +907,7 @@ UDFCompleteMount( PtrUDFObjectName RootName; ULONG LastSector = 0; BOOLEAN UnlockVcb = FALSE; - FILE_ID FileId{}; + FILE_ID FileId = {0}; PAGED_CODE(); @@ -1096,7 +1096,7 @@ UDFCompleteMount( /* Read SN UID mapping */ if (Vcb->SysSDirFileInfo) { - LocalPath = RTL_CONSTANT_STRING(UDF_SN_UID_MAPPING); + RtlInitUnicodeString(&LocalPath, UDF_SN_UID_MAPPING); Status = UDFOpenFile__(IrpContext, Vcb, FALSE, TRUE, &LocalPath, Vcb->SysSDirFileInfo , &Vcb->UniqueIDMapFileInfo, NULL); diff --git a/drivers/filesystems/udfs/struct.h b/drivers/filesystems/udfs/struct.h index be78aa74b4f76..bd09e2b23fcd1 100644 --- a/drivers/filesystems/udfs/struct.h +++ b/drivers/filesystems/udfs/struct.h @@ -62,8 +62,7 @@ struct UDFIdentifier { NODE_BYTE_SIZE NodeByteSize; // computed as sizeof(structure) }; -static_assert(sizeof(UDFIdentifier) == offsetof(FSRTL_ADVANCED_FCB_HEADER, Flags), - "UDFIdentifier size mismatch with NodeTypeCode and NodeByteSize in FSRTL_ADVANCED_FCB_HEADER"); +C_ASSERT(sizeof(UDFIdentifier) == offsetof(FSRTL_ADVANCED_FCB_HEADER, Flags)); /************************************************************************** Every open on-disk object must have a name associated with it diff --git a/drivers/filesystems/udfs/udf_info/udf_info.c b/drivers/filesystems/udfs/udf_info/udf_info.c index 86f90dd8f2a34..8b29fdfd8b961 100644 --- a/drivers/filesystems/udfs/udf_info/udf_info.c +++ b/drivers/filesystems/udfs/udf_info/udf_info.c @@ -4387,7 +4387,7 @@ UDFReadTagged( // Read the block if (Block == 0xFFFFFFFF) - return NULL; + return STATUS_UNSUCCESSFUL; _SEH2_TRY { RC = UDFReadSectors(IrpContext, Vcb, FALSE, Block, 1, FALSE, Buf, &ReadBytes); diff --git a/drivers/filesystems/udfs/udf_info/udf_info.h b/drivers/filesystems/udfs/udf_info/udf_info.h index d2849827772b6..3bfd9be5d1afc 100644 --- a/drivers/filesystems/udfs/udf_info/udf_info.h +++ b/drivers/filesystems/udfs/udf_info/udf_info.h @@ -144,7 +144,7 @@ UDFShortAllocDescToMapping( IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN uint32 PartNum, - IN PLONG_AD AllocDesc, + IN PSHORT_AD AllocDesc, IN uint32 AllocDescLength, IN uint32 SubCallCount, OUT PEXTENT_INFO AllocLoc @@ -166,7 +166,7 @@ PEXTENT_MAP UDFExtAllocDescToMapping( IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, - IN PLONG_AD AllocDesc, + IN PEXT_AD AllocDesc, IN uint32 AllocDescLength, IN uint32 SubCallCount, OUT PEXTENT_INFO AllocLoc From b2f742e1e17856d3329b2957d6749a92028bb7c4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 6 Mar 2026 22:47:44 +0000 Subject: [PATCH 13/20] Fix MinGW/GCC build errors: remove C++-only flags, fix inline placement, fix case+declaration Co-authored-by: Zero3K20 <258969903+Zero3K20@users.noreply.github.com> --- drivers/filesystems/udfs/CMakeLists.txt | 3 +-- drivers/filesystems/udfs/Include/mem_tools.h | 8 ++++---- drivers/filesystems/udfs/udf_info/mount.c | 2 ++ 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/filesystems/udfs/CMakeLists.txt b/drivers/filesystems/udfs/CMakeLists.txt index fa427875e2a51..485676d28658f 100644 --- a/drivers/filesystems/udfs/CMakeLists.txt +++ b/drivers/filesystems/udfs/CMakeLists.txt @@ -44,8 +44,7 @@ add_library(udfs MODULE ${SOURCE} udffs.rc) if(CMAKE_C_COMPILER_ID STREQUAL "GNU") target_compile_options(udfs PRIVATE -Wno-unused-but-set-variable) - target_compile_options(udfs PRIVATE -Wno-invalid-offsetof) - target_compile_options(udfs PRIVATE -Wno-error -fpermissive) + target_compile_options(udfs PRIVATE -Wno-error) endif() if(CMAKE_C_COMPILER_ID STREQUAL "Clang") diff --git a/drivers/filesystems/udfs/Include/mem_tools.h b/drivers/filesystems/udfs/Include/mem_tools.h index fa06ad9708fb5..3499884aa2a15 100644 --- a/drivers/filesystems/udfs/Include/mem_tools.h +++ b/drivers/filesystems/udfs/Include/mem_tools.h @@ -130,7 +130,7 @@ MyFindMemBaseByAddr( #define MyAlignSize__(size) (size) #endif -BOOLEAN inline MyAllocInit(VOID) {return TRUE;} +static inline BOOLEAN MyAllocInit(VOID) {return TRUE;} #define MyAllocRelease() #ifndef MY_MEM_BOUNDS_CHECK @@ -176,7 +176,7 @@ PVOID inline MyAllocatePool__(ULONG type, ULONG len) { } */ -PVOID inline MyAllocatePoolTag__(ULONG type, ULONG len, /*PCHAR*/ULONG tag) { +static inline PVOID MyAllocatePoolTag__(ULONG type, ULONG len, /*PCHAR*/ULONG tag) { PCHAR newaddr; ULONG i; // newaddr = (PCHAR)MyAllocatePoolTag_(type, len+MY_HEAP_ALIGN+1, tag); @@ -193,7 +193,7 @@ PVOID inline MyAllocatePoolTag__(ULONG type, ULONG len, /*PCHAR*/ULONG tag) { return newaddr; } -VOID inline MyFreePool__(PVOID addr) { +static inline VOID MyFreePool__(PVOID addr) { PCHAR newaddr; // ULONG i; newaddr = (PCHAR)addr; @@ -220,7 +220,7 @@ VOID inline MyFreePool__(PVOID addr) { #pragma GCC diagnostic ignored "-Wstringop-overflow" #endif -ULONG inline MyReallocPool__(PCHAR addr, ULONG len, PCHAR *pnewaddr, ULONG newlen) { +static inline ULONG MyReallocPool__(PCHAR addr, ULONG len, PCHAR *pnewaddr, ULONG newlen) { ULONG _len, _newlen; _newlen = MyAlignSize__(newlen); _len = MyAlignSize__(len); diff --git a/drivers/filesystems/udfs/udf_info/mount.c b/drivers/filesystems/udfs/udf_info/mount.c index 9a5199263a4cc..4d425ecc52103 100644 --- a/drivers/filesystems/udfs/udf_info/mount.c +++ b/drivers/filesystems/udfs/udf_info/mount.c @@ -2312,6 +2312,7 @@ UDFReadVDS( } break; case TID_VOL_DESC_PTR: // ISO 13346 3/10.3 + { struct VolDescPtr* pVDP; if (vdsn >= vds[VDS_POS_VOL_DESC_PTR].volDescSeqNum) { @@ -2329,6 +2330,7 @@ UDFReadVDS( vds, Buf); } break; + } case TID_IMP_USE_VOL_DESC: // ISO 13346 3/10.4 if (vdsn >= vds[VDS_POS_IMP_USE_VOL_DESC].volDescSeqNum) { From 90a1c7eb6916f81d54e72fd7c31022ae0ed6d975 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 6 Mar 2026 22:53:56 +0000 Subject: [PATCH 14/20] Fix static/inline conflict in mem_tools.h and __inline forward decl warning in udf_info.h Co-authored-by: Zero3K20 <258969903+Zero3K20@users.noreply.github.com> --- drivers/filesystems/udfs/Include/mem_tools.h | 8 ++++---- drivers/filesystems/udfs/udf_info/udf_info.h | 2 -- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/filesystems/udfs/Include/mem_tools.h b/drivers/filesystems/udfs/Include/mem_tools.h index 3499884aa2a15..29c734fbc1175 100644 --- a/drivers/filesystems/udfs/Include/mem_tools.h +++ b/drivers/filesystems/udfs/Include/mem_tools.h @@ -130,7 +130,7 @@ MyFindMemBaseByAddr( #define MyAlignSize__(size) (size) #endif -static inline BOOLEAN MyAllocInit(VOID) {return TRUE;} +inline BOOLEAN MyAllocInit(VOID) {return TRUE;} #define MyAllocRelease() #ifndef MY_MEM_BOUNDS_CHECK @@ -176,7 +176,7 @@ PVOID inline MyAllocatePool__(ULONG type, ULONG len) { } */ -static inline PVOID MyAllocatePoolTag__(ULONG type, ULONG len, /*PCHAR*/ULONG tag) { +inline PVOID MyAllocatePoolTag__(ULONG type, ULONG len, /*PCHAR*/ULONG tag) { PCHAR newaddr; ULONG i; // newaddr = (PCHAR)MyAllocatePoolTag_(type, len+MY_HEAP_ALIGN+1, tag); @@ -193,7 +193,7 @@ static inline PVOID MyAllocatePoolTag__(ULONG type, ULONG len, /*PCHAR*/ULONG ta return newaddr; } -static inline VOID MyFreePool__(PVOID addr) { +inline VOID MyFreePool__(PVOID addr) { PCHAR newaddr; // ULONG i; newaddr = (PCHAR)addr; @@ -220,7 +220,7 @@ static inline VOID MyFreePool__(PVOID addr) { #pragma GCC diagnostic ignored "-Wstringop-overflow" #endif -static inline ULONG MyReallocPool__(PCHAR addr, ULONG len, PCHAR *pnewaddr, ULONG newlen) { +inline ULONG MyReallocPool__(PCHAR addr, ULONG len, PCHAR *pnewaddr, ULONG newlen) { ULONG _len, _newlen; _newlen = MyAlignSize__(newlen); _len = MyAlignSize__(len); diff --git a/drivers/filesystems/udfs/udf_info/udf_info.h b/drivers/filesystems/udfs/udf_info/udf_info.h index 3bfd9be5d1afc..764de6c5c61e0 100644 --- a/drivers/filesystems/udfs/udf_info/udf_info.h +++ b/drivers/filesystems/udfs/udf_info/udf_info.h @@ -824,7 +824,6 @@ NTSTATUS UDFReadFileLocation__(IN PVCB Vcb, */ // zero data in file described by FileInfo -__inline NTSTATUS UDFZeroFile__( IN PIRP_CONTEXT IrpContext, @@ -837,7 +836,6 @@ UDFZeroFile__( ); // make sparse area in file described by FileInfo -__inline NTSTATUS UDFSparseFile__( IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, From 1242147eef69e3c16962a58e3a7ccb69262c26e9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 7 Mar 2026 00:55:58 +0000 Subject: [PATCH 15/20] Fix stale .cpp include references after files were renamed to .c Co-authored-by: Zero3K20 <258969903+Zero3K20@users.noreply.github.com> --- drivers/filesystems/udfs/mem.c | 2 +- drivers/filesystems/udfs/misc.c | 2 +- drivers/filesystems/udfs/sys_spec.c | 2 +- drivers/filesystems/udfs/udf_info/physical.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/filesystems/udfs/mem.c b/drivers/filesystems/udfs/mem.c index 072602c852327..301ead0d8ba72 100644 --- a/drivers/filesystems/udfs/mem.c +++ b/drivers/filesystems/udfs/mem.c @@ -8,4 +8,4 @@ // define the file specific bug-check id #define UDF_BUG_CHECK_ID UDF_FILE_MEM -#include "Include/mem_tools.cpp" +#include "Include/mem_tools.c" diff --git a/drivers/filesystems/udfs/misc.c b/drivers/filesystems/udfs/misc.c index cd6ffd31d2860..d9cf307080076 100644 --- a/drivers/filesystems/udfs/misc.c +++ b/drivers/filesystems/udfs/misc.c @@ -2106,5 +2106,5 @@ UDFWaitForIoAtEof( return TRUE; } -#include "Include/regtools.cpp" +#include "Include/regtools.c" diff --git a/drivers/filesystems/udfs/sys_spec.c b/drivers/filesystems/udfs/sys_spec.c index e9a11ab152817..df66b8c66f22e 100644 --- a/drivers/filesystems/udfs/sys_spec.c +++ b/drivers/filesystems/udfs/sys_spec.c @@ -20,6 +20,6 @@ // define the file specific bug-check id #define UDF_BUG_CHECK_ID UDF_FILE_SYS_SPEC -#include "Include/Sys_spec_lib.cpp" +#include "Include/Sys_spec_lib.c" //#include "Include/tools.cpp" diff --git a/drivers/filesystems/udfs/udf_info/physical.c b/drivers/filesystems/udfs/udf_info/physical.c index 1ba8a147f02f1..9468996cacd37 100644 --- a/drivers/filesystems/udfs/udf_info/physical.c +++ b/drivers/filesystems/udfs/udf_info/physical.c @@ -17,5 +17,5 @@ // define the file specific bug-check id #define UDF_BUG_CHECK_ID UDF_FILE_PHYSICAL -#include "Include/phys_lib.cpp" +#include "Include/phys_lib.c" From b2878b9433beebb78000ac253ca0f0ca063fc65a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 7 Mar 2026 01:25:10 +0000 Subject: [PATCH 16/20] Remove udfs-for-write-branch.patch Co-authored-by: Zero3K20 <258969903+Zero3K20@users.noreply.github.com> --- udfs-for-write-branch.patch | 896 ------------------------------------ 1 file changed, 896 deletions(-) delete mode 100644 udfs-for-write-branch.patch diff --git a/udfs-for-write-branch.patch b/udfs-for-write-branch.patch deleted file mode 100644 index ab1ab0a095574..0000000000000 --- a/udfs-for-write-branch.patch +++ /dev/null @@ -1,896 +0,0 @@ -diff --git a/drivers/filesystems/udfs/CMakeLists.txt b/drivers/filesystems/udfs/CMakeLists.txt -index 53ce00f..fa42787 100644 ---- a/drivers/filesystems/udfs/CMakeLists.txt -+++ b/drivers/filesystems/udfs/CMakeLists.txt -@@ -2,42 +2,42 @@ - include_directories(Include) - - list(APPEND SOURCE -- udf_info/alloc.cpp -- udf_info/dirtree.cpp -- udf_info/extent.cpp -- udf_info/mount.cpp -- udf_info/phys_eject.cpp -- udf_info/physical.cpp -- udf_info/remap.cpp -- udf_info/udf_info.cpp -- cleanup.cpp -- close.cpp -- create.cpp -- devcntrl.cpp -- dircntrl.cpp -- env_spec.cpp -- fastio.cpp -- fileinfo.cpp -- flush.cpp -- fscntrl.cpp -- lockctrl.cpp -- mem.cpp -- misc.cpp -- namesup.cpp -- pnp.cpp -- read.cpp -- secursup.cpp -- shutdown.cpp -- sys_spec.cpp -- udf_dbg.cpp -- udfinit.cpp -- unload.cpp -- verfysup.cpp -- volinfo.cpp -- write.cpp -- strucsup.cpp -- filobsup.cpp -- udfdata.cpp -+ udf_info/alloc.c -+ udf_info/dirtree.c -+ udf_info/extent.c -+ udf_info/mount.c -+ udf_info/phys_eject.c -+ udf_info/physical.c -+ udf_info/remap.c -+ udf_info/udf_info.c -+ cleanup.c -+ close.c -+ create.c -+ devcntrl.c -+ dircntrl.c -+ env_spec.c -+ fastio.c -+ fileinfo.c -+ flush.c -+ fscntrl.c -+ lockctrl.c -+ mem.c -+ misc.c -+ namesup.c -+ pnp.c -+ read.c -+ secursup.c -+ shutdown.c -+ sys_spec.c -+ udf_dbg.c -+ udfinit.c -+ unload.c -+ verfysup.c -+ volinfo.c -+ write.c -+ strucsup.c -+ filobsup.c -+ udfdata.c - 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.c -similarity index 100% -rename from drivers/filesystems/udfs/Include/Sys_spec_lib.cpp -rename to drivers/filesystems/udfs/Include/Sys_spec_lib.c -diff --git a/drivers/filesystems/udfs/Include/mem_tools.cpp b/drivers/filesystems/udfs/Include/mem_tools.c -similarity index 100% -rename from drivers/filesystems/udfs/Include/mem_tools.cpp -rename to drivers/filesystems/udfs/Include/mem_tools.c -diff --git a/drivers/filesystems/udfs/Include/phys_lib.cpp b/drivers/filesystems/udfs/Include/phys_lib.c -similarity index 99% -rename from drivers/filesystems/udfs/Include/phys_lib.cpp -rename to drivers/filesystems/udfs/Include/phys_lib.c -index bba91e8..944d35b 100644 ---- a/drivers/filesystems/udfs/Include/phys_lib.cpp -+++ b/drivers/filesystems/udfs/Include/phys_lib.c -@@ -1036,7 +1036,7 @@ UDFReadSectors( - OUT PULONG ReadBytes - ) - { -- return UDFTRead(IrpContext, Vcb, Buffer, BCount*Vcb->SectorSize, Lba, ReadBytes); -+ return UDFTRead(IrpContext, Vcb, Buffer, BCount*Vcb->SectorSize, Lba, ReadBytes, 0); - } // end UDFReadSectors() - - /* -@@ -1167,7 +1167,7 @@ UDFWriteSectors( - Vcb->LastLBA = Lba+BCount-1; - } - -- status = UDFTWrite(IrpContext, Vcb, Buffer, BCount<SectorShift, Lba, WrittenBytes); -+ status = UDFTWrite(IrpContext, Vcb, Buffer, BCount<SectorShift, Lba, WrittenBytes, 0); - ASSERT(NT_SUCCESS(status)); - - return status; -diff --git a/drivers/filesystems/udfs/Include/phys_lib.h b/drivers/filesystems/udfs/Include/phys_lib.h -index 747b954..19203d2 100644 ---- a/drivers/filesystems/udfs/Include/phys_lib.h -+++ b/drivers/filesystems/udfs/Include/phys_lib.h -@@ -15,7 +15,7 @@ UDFTRead( - SIZE_T Length, - ULONG LBA, - PULONG ReadBytes, -- ULONG Flags = 0 -+ ULONG Flags - ); - - NTSTATUS -@@ -26,7 +26,7 @@ UDFTWrite( - IN SIZE_T Length, - IN ULONG LBA, - OUT PSIZE_T WrittenBytes, -- IN ULONG Flags = 0 -+ IN ULONG Flags - ); - - #define PH_TMP_BUFFER 1 -diff --git a/drivers/filesystems/udfs/Include/regtools.cpp b/drivers/filesystems/udfs/Include/regtools.c -similarity index 100% -rename from drivers/filesystems/udfs/Include/regtools.cpp -rename to drivers/filesystems/udfs/Include/regtools.c -diff --git a/drivers/filesystems/udfs/Include/string_lib.cpp b/drivers/filesystems/udfs/Include/string_lib.c -similarity index 100% -rename from drivers/filesystems/udfs/Include/string_lib.cpp -rename to drivers/filesystems/udfs/Include/string_lib.c -diff --git a/drivers/filesystems/udfs/cleanup.cpp b/drivers/filesystems/udfs/cleanup.c -similarity index 99% -rename from drivers/filesystems/udfs/cleanup.cpp -rename to drivers/filesystems/udfs/cleanup.c -index 678dcb3..b85c16a 100644 ---- a/drivers/filesystems/udfs/cleanup.cpp -+++ b/drivers/filesystems/udfs/cleanup.c -@@ -333,7 +333,7 @@ UDFCommonCleanup( - Fcb->ParentFcb->FcbState |= UDF_FCB_DELETE_ON_CLOSE; - } - // flush file. It is required by UDFUnlinkFile__() -- RC = UDFFlushFile__(IrpContext, Vcb, NextFileInfo); -+ RC = UDFFlushFile__(IrpContext, Vcb, NextFileInfo, 0); - if (!NT_SUCCESS(RC)) { - AdPrint(("Error flushing file !!!\n")); - } -diff --git a/drivers/filesystems/udfs/close.cpp b/drivers/filesystems/udfs/close.c -similarity index 99% -rename from drivers/filesystems/udfs/close.cpp -rename to drivers/filesystems/udfs/close.c -index 664f54f..367523a 100644 ---- a/drivers/filesystems/udfs/close.cpp -+++ b/drivers/filesystems/udfs/close.c -@@ -339,7 +339,7 @@ UDFTeardownStructures( - }*/ - UDFReferenceFile__(CurrentFcb->FileInfo); - ASSERT(CurrentFcb->FcbReference < CurrentFcb->FileInfo->RefCount); -- UDFFlushFile__(IrpContext, Vcb, CurrentFcb->FileInfo); -+ UDFFlushFile__(IrpContext, Vcb, CurrentFcb->FileInfo, 0); - UDFUnlinkFile__(IrpContext, Vcb, CurrentFcb->FileInfo, TRUE); - UDFCloseFile__(IrpContext, Vcb, CurrentFcb->FileInfo); - ASSERT(CurrentFcb->FcbReference == CurrentFcb->FileInfo->RefCount); -@@ -347,7 +347,7 @@ UDFTeardownStructures( - Delete = FALSE; - } - else if (!(CurrentFcb->FcbState & UDF_FCB_DELETED)) { -- UDFFlushFile__(IrpContext, Vcb, CurrentFcb->FileInfo); -+ UDFFlushFile__(IrpContext, Vcb, CurrentFcb->FileInfo, 0); - } else { - // BrutePoint(); - } -diff --git a/drivers/filesystems/udfs/create.cpp b/drivers/filesystems/udfs/create.c -similarity index 99% -rename from drivers/filesystems/udfs/create.cpp -rename to drivers/filesystems/udfs/create.c -index a7f63b1..ed77722 100644 ---- a/drivers/filesystems/udfs/create.cpp -+++ b/drivers/filesystems/udfs/create.c -@@ -524,7 +524,7 @@ UDFCommonCreate( - - InterlockedDecrement((PLONG)&Vcb->VcbReference); - -- UDFFlushVolume(IrpContext, Vcb); -+ UDFFlushVolume(IrpContext, Vcb, 0); - } - // Lock the volume - if (!(ShareAccess & FILE_SHARE_READ)) { -@@ -1428,7 +1428,7 @@ Undo_Create_1: - if ((RC != STATUS_FILE_IS_A_DIRECTORY) && - (RC != STATUS_NOT_A_DIRECTORY) && - (RC != STATUS_ACCESS_DENIED)) { -- UDFFlushFile__(IrpContext, Vcb, NewFileInfo); -+ UDFFlushFile__(IrpContext, Vcb, NewFileInfo, 0); - UDFUnlinkFile__(IrpContext, Vcb, NewFileInfo, TRUE); - } - UDFCloseFile__(IrpContext, Vcb, NewFileInfo); -@@ -1608,7 +1608,7 @@ Undo_Create_1: - if (!NT_SUCCESS(RC)) { - AdPrint((" Can't set Access Rights on Create\n")); - BrutePoint(); -- UDFFlushFile__(IrpContext, Vcb, NewFileInfo); -+ UDFFlushFile__(IrpContext, Vcb, NewFileInfo, 0); - UDFUnlinkFile__(IrpContext, Vcb, NewFileInfo, TRUE); - try_return(RC); - } -@@ -2368,7 +2368,7 @@ UDFCompleteFcbOpen( - // Flush the volume and make sure all of the user references - // are gone. - -- Status = UDFFlushVolume(IrpContext, Vcb); -+ Status = UDFFlushVolume(IrpContext, Vcb, 0); - - if (!NT_SUCCESS(Status)) { - -diff --git a/drivers/filesystems/udfs/devcntrl.cpp b/drivers/filesystems/udfs/devcntrl.c -similarity index 100% -rename from drivers/filesystems/udfs/devcntrl.cpp -rename to drivers/filesystems/udfs/devcntrl.c -diff --git a/drivers/filesystems/udfs/dircntrl.cpp b/drivers/filesystems/udfs/dircntrl.c -similarity index 100% -rename from drivers/filesystems/udfs/dircntrl.cpp -rename to drivers/filesystems/udfs/dircntrl.c -diff --git a/drivers/filesystems/udfs/env_spec.cpp b/drivers/filesystems/udfs/env_spec.c -similarity index 100% -rename from drivers/filesystems/udfs/env_spec.cpp -rename to drivers/filesystems/udfs/env_spec.c -diff --git a/drivers/filesystems/udfs/fastio.cpp b/drivers/filesystems/udfs/fastio.c -similarity index 100% -rename from drivers/filesystems/udfs/fastio.cpp -rename to drivers/filesystems/udfs/fastio.c -diff --git a/drivers/filesystems/udfs/fileinfo.cpp b/drivers/filesystems/udfs/fileinfo.c -similarity index 100% -rename from drivers/filesystems/udfs/fileinfo.cpp -rename to drivers/filesystems/udfs/fileinfo.c -diff --git a/drivers/filesystems/udfs/filobsup.cpp b/drivers/filesystems/udfs/filobsup.c -similarity index 100% -rename from drivers/filesystems/udfs/filobsup.cpp -rename to drivers/filesystems/udfs/filobsup.c -diff --git a/drivers/filesystems/udfs/flush.cpp b/drivers/filesystems/udfs/flush.c -similarity index 99% -rename from drivers/filesystems/udfs/flush.cpp -rename to drivers/filesystems/udfs/flush.c -index 76357b7..ebe9dd1 100644 ---- a/drivers/filesystems/udfs/flush.cpp -+++ b/drivers/filesystems/udfs/flush.c -@@ -127,7 +127,7 @@ UDFCommonFlush( - - UDFVerifyVcb(IrpContext, Vcb); - -- UDFFlushVolume(IrpContext, Vcb); -+ UDFFlushVolume(IrpContext, Vcb, 0); - - UDFReleaseResource(&(Vcb->VcbResource)); - AcquiredVCB = FALSE; -diff --git a/drivers/filesystems/udfs/fscntrl.cpp b/drivers/filesystems/udfs/fscntrl.c -similarity index 99% -rename from drivers/filesystems/udfs/fscntrl.cpp -rename to drivers/filesystems/udfs/fscntrl.c -index ab7c079..84a9e18 100644 ---- a/drivers/filesystems/udfs/fscntrl.cpp -+++ b/drivers/filesystems/udfs/fscntrl.c -@@ -989,7 +989,7 @@ Return Value: - // remaining after the purge then we can allow the volume to be locked. - // - -- UDFFlushVolume(IrpContext, Vcb); -+ UDFFlushVolume(IrpContext, Vcb, 0); - //CdPurgeVolume( IrpContext, Vcb, FALSE ); - - // -@@ -1174,7 +1174,7 @@ UDFDismountVolume( - - } else { - -- UDFFlushVolume(IrpContext, Vcb); -+ UDFFlushVolume(IrpContext, Vcb, 0); - - // Invalidate the volume right now. - // -@@ -1800,7 +1800,7 @@ UDFInvalidateVolumes( - - UDFAcquireVcbExclusive(IrpContext, Vcb, FALSE); - -- UDFFlushVolume(IrpContext, Vcb); -+ UDFFlushVolume(IrpContext, Vcb, 0); - - UDFDoDismountSequence(Vcb, FALSE); - -diff --git a/drivers/filesystems/udfs/lockctrl.cpp b/drivers/filesystems/udfs/lockctrl.c -similarity index 99% -rename from drivers/filesystems/udfs/lockctrl.cpp -rename to drivers/filesystems/udfs/lockctrl.c -index 60f52a8..86489aa 100644 ---- a/drivers/filesystems/udfs/lockctrl.cpp -+++ b/drivers/filesystems/udfs/lockctrl.c -@@ -5,7 +5,7 @@ - //////////////////////////////////////////////////////////////////// - /************************************************************************* - * --* File: LockCtrl.cpp.cpp -+* File: LockCtrl.c - * - * Module: UDF File System Driver (Kernel mode execution only) - * -diff --git a/drivers/filesystems/udfs/mem.cpp b/drivers/filesystems/udfs/mem.c -similarity index 100% -rename from drivers/filesystems/udfs/mem.cpp -rename to drivers/filesystems/udfs/mem.c -diff --git a/drivers/filesystems/udfs/misc.cpp b/drivers/filesystems/udfs/misc.c -similarity index 100% -rename from drivers/filesystems/udfs/misc.cpp -rename to drivers/filesystems/udfs/misc.c -diff --git a/drivers/filesystems/udfs/namesup.cpp b/drivers/filesystems/udfs/namesup.c -similarity index 100% -rename from drivers/filesystems/udfs/namesup.cpp -rename to drivers/filesystems/udfs/namesup.c -diff --git a/drivers/filesystems/udfs/pnp.cpp b/drivers/filesystems/udfs/pnp.c -similarity index 100% -rename from drivers/filesystems/udfs/pnp.cpp -rename to drivers/filesystems/udfs/pnp.c -diff --git a/drivers/filesystems/udfs/protos.h b/drivers/filesystems/udfs/protos.h -index 59cb00c..108b1ea 100644 ---- a/drivers/filesystems/udfs/protos.h -+++ b/drivers/filesystems/udfs/protos.h -@@ -531,7 +531,7 @@ ULONG UDFFlushAFile( - IN PFCB Fcb, - IN PCCB Ccb, - OUT PIO_STATUS_BLOCK PtrIoStatus, -- IN ULONG FlushFlags = 0 -+ IN ULONG FlushFlags - ); - - ULONG -@@ -540,14 +540,14 @@ UDFFlushADirectory( - IN PVCB Vcb, - IN PUDF_FILE_INFO FI, - OUT PIO_STATUS_BLOCK PtrIoStatus, -- ULONG FlushFlags = 0 -+ ULONG FlushFlags - ); - - NTSTATUS - UDFFlushVolume( - PIRP_CONTEXT IrpContext, - PVCB Vcb, -- ULONG FlushFlags = 0 -+ ULONG FlushFlags - ); - - extern NTSTATUS NTAPI UDFFlushCompletion( -@@ -557,7 +557,7 @@ PVOID Context); - - extern BOOLEAN UDFFlushIsBreaking( - IN PVCB Vcb, --IN ULONG FlushFlags = 0); -+IN ULONG FlushFlags); - - extern VOID UDFFlushTryBreak( - IN PVCB Vcb); -@@ -842,7 +842,7 @@ UDFReadRegKeys( - extern ULONG UDFGetRegParameter( - IN PVCB Vcb, - IN PCWSTR Name, -- IN ULONG DefValue = 0); -+ IN ULONG DefValue); - - VOID - UDFDeleteVCB( -@@ -964,7 +964,7 @@ UDFCommonShutdown( - /************************************************************************* - * Prototypes for the file UDFinit.cpp - *************************************************************************/ --extern "C" NTSTATUS NTAPI DriverEntry( -+NTSTATUS NTAPI DriverEntry( - PDRIVER_OBJECT DriverObject, // created by the I/O sub-system - PUNICODE_STRING RegistryPath); // path to the registry key - -@@ -1224,6 +1224,7 @@ enum TYPE_OF_ACQUIRE { - AcquireSharedStarveExclusive - - }; -+typedef enum TYPE_OF_ACQUIRE TYPE_OF_ACQUIRE; - - _Requires_lock_held_(_Global_critical_region_) - _When_(Type == AcquireExclusive && return != FALSE, _Acquires_exclusive_lock_(*Resource)) -diff --git a/drivers/filesystems/udfs/read.cpp b/drivers/filesystems/udfs/read.c -similarity index 100% -rename from drivers/filesystems/udfs/read.cpp -rename to drivers/filesystems/udfs/read.c -diff --git a/drivers/filesystems/udfs/secursup.cpp b/drivers/filesystems/udfs/secursup.c -similarity index 100% -rename from drivers/filesystems/udfs/secursup.cpp -rename to drivers/filesystems/udfs/secursup.c -diff --git a/drivers/filesystems/udfs/shutdown.cpp b/drivers/filesystems/udfs/shutdown.c -similarity index 99% -rename from drivers/filesystems/udfs/shutdown.cpp -rename to drivers/filesystems/udfs/shutdown.c -index f8b0a7f..314b0e2 100644 ---- a/drivers/filesystems/udfs/shutdown.cpp -+++ b/drivers/filesystems/udfs/shutdown.c -@@ -109,7 +109,7 @@ UDFCommonShutdown( - - UDFAcquireVcbExclusive(IrpContext, Vcb, FALSE); - -- UDFFlushVolume(IrpContext, Vcb); -+ UDFFlushVolume(IrpContext, Vcb, 0); - - ASSERT(CONTAINING_RECORD(IoGetCurrentIrpStackLocation(Irp)->DeviceObject, - VOLUME_DEVICE_OBJECT, -diff --git a/drivers/filesystems/udfs/strucsup.cpp b/drivers/filesystems/udfs/strucsup.c -similarity index 100% -rename from drivers/filesystems/udfs/strucsup.cpp -rename to drivers/filesystems/udfs/strucsup.c -diff --git a/drivers/filesystems/udfs/struct.h b/drivers/filesystems/udfs/struct.h -index fb48f5e..be78aa7 100644 ---- a/drivers/filesystems/udfs/struct.h -+++ b/drivers/filesystems/udfs/struct.h -@@ -37,6 +37,21 @@ struct IRP_CONTEXT_LITE; - struct IO_CONTEXT; - struct IRP_CONTEXT; - -+/* C typedef aliases - allow plain name usage without the 'struct' keyword */ -+typedef struct IRP_CONTEXT_LITE IRP_CONTEXT_LITE; -+typedef struct IO_CONTEXT IO_CONTEXT; -+typedef struct IRP_CONTEXT IRP_CONTEXT; -+typedef struct UDFIdentifier UDFIdentifier; -+typedef struct UDFObjectName UDFObjectName; -+typedef struct CCB CCB; -+typedef struct FCB_NONPAGED FCB_NONPAGED; -+typedef struct FCB_DATA FCB_DATA; -+typedef struct FCB_INDEX FCB_INDEX; -+typedef struct FCB FCB; -+typedef struct VCB VCB; -+typedef struct VOLUME_DEVICE_OBJECT VOLUME_DEVICE_OBJECT; -+typedef struct THREAD_CONTEXT THREAD_CONTEXT; -+ - /************************************************************************** - every structure has a node type, and a node size associated with it. - The node type serves as a signature field. The size is used for -@@ -67,7 +82,7 @@ struct UDFObjectName { - // an absolute pathname of the object is stored below - UNICODE_STRING ObjectName; - }; --using PtrUDFObjectName = UDFObjectName*; -+typedef UDFObjectName* PtrUDFObjectName; - - /************************************************************************** - Each file open instance is represented by a context control block. -@@ -96,7 +111,7 @@ struct CCB { - HASH_ENTRY hashes; - ULONG TreeLength; - }; --using PCCB = CCB*; -+typedef CCB* PCCB; - - #define CCB_FLAG_IGNORE_CASE (0x00000004) - // the CCB has had an IRP_MJ_CLEANUP issued on it. we must -@@ -152,7 +167,7 @@ struct FCB_NONPAGED { - FAST_MUTEX AdvancedFcbHeaderMutex; - - }; --using PFCB_NONPAGED = FCB_NONPAGED*; -+typedef FCB_NONPAGED* PFCB_NONPAGED; - - /************************************************************************** - each open file/directory/volume is represented by a file control block. -@@ -193,11 +208,11 @@ using PFCB_NONPAGED = FCB_NONPAGED*; - /***************************************************/ - - struct FCB_DATA { -- -+ UCHAR Pad; - }; - - struct FCB_INDEX { -- -+ UCHAR Pad; - }; - - struct FCB { -@@ -284,7 +299,7 @@ struct FCB { - FCB_INDEX FcbIndex; - }; - }; --using PFCB = FCB*; -+typedef FCB* PFCB; - - #define SIZEOF_FCB_DATA \ - (FIELD_OFFSET(FCB, FcbType) + sizeof(FCB_DATA)) -@@ -336,6 +351,7 @@ enum UDFFSD_MEDIA_TYPE { - MediaDvdr, - MediaDvdrw - }; -+typedef enum UDFFSD_MEDIA_TYPE UDFFSD_MEDIA_TYPE; - - enum VCB_CONDITION { - -@@ -345,6 +361,7 @@ enum VCB_CONDITION { - VcbInvalid, - VcbDismountInProgress - }; -+typedef enum VCB_CONDITION VCB_CONDITION; - - struct VCB { - -@@ -608,7 +625,7 @@ struct VCB { - PVPB SwapVpb; - }; - --using PVCB = VCB*; -+typedef VCB* PVCB; - - // One for root - #define UDFS_BASE_RESIDUAL_REFERENCE (4)//(6) -@@ -682,7 +699,7 @@ struct THREAD_CONTEXT { - // will store the IrpContext for the request in this stack location. - IRP_CONTEXT* TopLevelIrpContext; - }; --using PTHREAD_CONTEXT = THREAD_CONTEXT*; -+typedef THREAD_CONTEXT* PTHREAD_CONTEXT; - - /************************************************************************** - The IRP context encapsulates the current request. This structure is -@@ -727,7 +744,7 @@ struct IRP_CONTEXT { - - VCB* Vcb; - }; --using PIRP_CONTEXT = IRP_CONTEXT*; -+typedef IRP_CONTEXT* PIRP_CONTEXT; - - #define IRP_CONTEXT_FLAG_ON_STACK (0x00000001) - #define IRP_CONTEXT_FLAG_MORE_PROCESSING (0x00000002) -@@ -794,7 +811,7 @@ struct IRP_CONTEXT_LITE { - PDEVICE_OBJECT RealDevice; - ULONG TreeLength; - }; --using PIRP_CONTEXT_LITE = IRP_CONTEXT_LITE*; -+typedef IRP_CONTEXT_LITE* PIRP_CONTEXT_LITE; - - /************************************************************************** - we will store all of our global variables in one structure. -diff --git a/drivers/filesystems/udfs/sys_spec.cpp b/drivers/filesystems/udfs/sys_spec.c -similarity index 100% -rename from drivers/filesystems/udfs/sys_spec.cpp -rename to drivers/filesystems/udfs/sys_spec.c -diff --git a/drivers/filesystems/udfs/udf_dbg.cpp b/drivers/filesystems/udfs/udf_dbg.c -similarity index 100% -rename from drivers/filesystems/udfs/udf_dbg.cpp -rename to drivers/filesystems/udfs/udf_dbg.c -diff --git a/drivers/filesystems/udfs/udf_dbg.h b/drivers/filesystems/udfs/udf_dbg.h -index 63fc430..d176b88 100644 ---- a/drivers/filesystems/udfs/udf_dbg.h -+++ b/drivers/filesystems/udfs/udf_dbg.h -@@ -49,7 +49,7 @@ - ULONG - _cdecl - DbgPrint( -- PCH Format, -+ PCSTR Format, - ... - ); - -diff --git a/drivers/filesystems/udfs/udf_info/alloc.cpp b/drivers/filesystems/udfs/udf_info/alloc.c -similarity index 100% -rename from drivers/filesystems/udfs/udf_info/alloc.cpp -rename to drivers/filesystems/udfs/udf_info/alloc.c -diff --git a/drivers/filesystems/udfs/udf_info/dirtree.cpp b/drivers/filesystems/udfs/udf_info/dirtree.c -similarity index 100% -rename from drivers/filesystems/udfs/udf_info/dirtree.cpp -rename to drivers/filesystems/udfs/udf_info/dirtree.c -diff --git a/drivers/filesystems/udfs/udf_info/ecma_167.h b/drivers/filesystems/udfs/udf_info/ecma_167.h -index 6ca06a7..8343008 100644 ---- a/drivers/filesystems/udfs/udf_info/ecma_167.h -+++ b/drivers/filesystems/udfs/udf_info/ecma_167.h -@@ -774,3 +774,35 @@ typedef EXTENDED_FILE_ENTRY ExtendedFileEntry; - - #endif /* __ECMA_167_H__ */ - -+ -+/* C typedef aliases for all non-typedef struct declarations */ -+typedef struct VolStructDesc VolStructDesc; -+typedef struct BeginningExtendedAreaDesc BeginningExtendedAreaDesc; -+typedef struct TerminatingExtendedAreaDesc TerminatingExtendedAreaDesc; -+typedef struct PrimaryVolDesc PrimaryVolDesc; -+typedef struct AnchorVolDescPtr AnchorVolDescPtr; -+typedef struct VolDescPtr VolDescPtr; -+typedef struct ImpUseVolDesc ImpUseVolDesc; -+typedef struct PartitionDesc PartitionDesc; -+typedef struct LogicalVolDesc LogicalVolDesc; -+typedef struct GenericPartitionMap GenericPartitionMap; -+typedef struct GenericPartitionMap1 GenericPartitionMap1; -+typedef struct GenericPartitionMap2 GenericPartitionMap2; -+typedef struct TerminatingDesc TerminatingDesc; -+typedef struct GenericDesc GenericDesc; -+typedef struct LogicalVolIntegrityDesc LogicalVolIntegrityDesc; -+typedef struct IndirectEntry IndirectEntry; -+typedef struct TerminalEntry TerminalEntry; -+typedef struct ExtendedAttrHeaderDesc ExtendedAttrHeaderDesc; -+typedef struct GenericAttrFormat GenericAttrFormat; -+typedef struct CharSetAttrFormat CharSetAttrFormat; -+typedef struct AlternatePermissionsExtendedAttr AlternatePermissionsExtendedAttr; -+typedef struct FileTimesExtendedAttr FileTimesExtendedAttr; -+typedef struct InfoTimesExtendedAttr InfoTimesExtendedAttr; -+typedef struct DeviceSpecificationExtendedAttr DeviceSpecificationExtendedAttr; -+typedef struct ImpUseExtendedAttr ImpUseExtendedAttr; -+typedef struct AppUseExtendedAttr AppUseExtendedAttr; -+typedef struct UnallocatedSpaceEntry UnallocatedSpaceEntry; -+typedef struct PartitionIntegrityEntry PartitionIntegrityEntry; -+typedef struct LogicalVolHeaderDesc LogicalVolHeaderDesc; -+typedef struct PathComponent PathComponent; -diff --git a/drivers/filesystems/udfs/udf_info/extent.cpp b/drivers/filesystems/udfs/udf_info/extent.c -similarity index 100% -rename from drivers/filesystems/udfs/udf_info/extent.cpp -rename to drivers/filesystems/udfs/udf_info/extent.c -diff --git a/drivers/filesystems/udfs/udf_info/mount.cpp b/drivers/filesystems/udfs/udf_info/mount.c -similarity index 99% -rename from drivers/filesystems/udfs/udf_info/mount.cpp -rename to drivers/filesystems/udfs/udf_info/mount.c -index 3fc100a..370bb99 100644 ---- a/drivers/filesystems/udfs/udf_info/mount.cpp -+++ b/drivers/filesystems/udfs/udf_info/mount.c -@@ -915,7 +915,7 @@ UDFUpdateNonAllocated( - } - UDFPackMapping(Vcb, DataLoc); - DataLoc->Length = UDFGetExtentLength(DataLoc->Mapping); -- UDFFlushFile__(IrpContext, Vcb, Vcb->NonAllocFileInfo); -+ UDFFlushFile__(IrpContext, Vcb, Vcb->NonAllocFileInfo, 0); - - // ensure that BAD space is marked as USED - UDFMarkSpaceAsXXX(Vcb, 0, &(DataLoc->Mapping[0]), AS_USED); // mark as used -@@ -2735,7 +2735,7 @@ UDFFindLastFileSet( - uint16 Ident; - uint32 relPrevExt, prevExt; - -- relPrevExt, prevExt = NULL; -+ relPrevExt = prevExt = 0; - FileSetDesc->nextExt.extLength = 1; // ;) - // walk through FileSet chain - // we've just pre-init'd extent length to read 1st FileSet -diff --git a/drivers/filesystems/udfs/udf_info/osta_misc.h b/drivers/filesystems/udfs/udf_info/osta_misc.h -index f9813bf..60b522c 100644 ---- a/drivers/filesystems/udfs/udf_info/osta_misc.h -+++ b/drivers/filesystems/udfs/udf_info/osta_misc.h -@@ -348,6 +348,17 @@ typedef UID_MAPPING_TABLE* PUID_MAPPING_TABLE; - - #define TID_ADAPTEC_LOGICAL_VOL_DESC 0x9999U - -+/* C typedef aliases for all non-typedef struct declarations */ -+typedef struct LogicalVolIntegrityDescImpUse LogicalVolIntegrityDescImpUse; -+typedef struct ImpUseVolDescImpUse ImpUseVolDescImpUse; -+typedef struct UdfPartitionMap2 UdfPartitionMap2; -+typedef struct VirtualPartitionMap VirtualPartitionMap; -+typedef struct DVDCopyrightImpUse DVDCopyrightImpUse; -+typedef struct ADImpUse ADImpUse; -+typedef struct FidADImpUse FidADImpUse; -+typedef struct VirtualAllocationTable15 VirtualAllocationTable15; -+typedef struct VirtualAllocationTable20 VirtualAllocationTable20; -+ - #pragma pack(pop) - - #endif /* _OSTA_MISC_H */ -diff --git a/drivers/filesystems/udfs/udf_info/phys_eject.cpp b/drivers/filesystems/udfs/udf_info/phys_eject.c -similarity index 98% -rename from drivers/filesystems/udfs/udf_info/phys_eject.cpp -rename to drivers/filesystems/udfs/udf_info/phys_eject.c -index 2a7a794..d07cced 100644 ---- a/drivers/filesystems/udfs/udf_info/phys_eject.cpp -+++ b/drivers/filesystems/udfs/udf_info/phys_eject.c -@@ -28,7 +28,7 @@ UDFDoDismountSequence( - ULONG i; - - // flush system cache -- UDFFlushVolume(NULL, Vcb); -+ UDFFlushVolume(NULL, Vcb, 0); - UDFPrint(("UDFDoDismountSequence:\n")); - - delay.QuadPart = -1000000; // 0.1 sec -diff --git a/drivers/filesystems/udfs/udf_info/physical.cpp b/drivers/filesystems/udfs/udf_info/physical.c -similarity index 100% -rename from drivers/filesystems/udfs/udf_info/physical.cpp -rename to drivers/filesystems/udfs/udf_info/physical.c -diff --git a/drivers/filesystems/udfs/udf_info/remap.cpp b/drivers/filesystems/udfs/udf_info/remap.c -similarity index 100% -rename from drivers/filesystems/udfs/udf_info/remap.cpp -rename to drivers/filesystems/udfs/udf_info/remap.c -diff --git a/drivers/filesystems/udfs/udf_info/udf_info.cpp b/drivers/filesystems/udfs/udf_info/udf_info.c -similarity index 99% -rename from drivers/filesystems/udfs/udf_info/udf_info.cpp -rename to drivers/filesystems/udfs/udf_info/udf_info.c -index e5d0b69..86f90dd 100644 ---- a/drivers/filesystems/udfs/udf_info/udf_info.cpp -+++ b/drivers/filesystems/udfs/udf_info/udf_info.c -@@ -1835,7 +1835,7 @@ UDFUnlinkFile__( - PUDF_FILE_INFO SFileInfo; - // ... try to open it - if (Dloc->SDirInfo) { -- UDFFlushFile__(IrpContext, Vcb, FileInfo); -+ UDFFlushFile__(IrpContext, Vcb, FileInfo, 0); - return STATUS_CANNOT_DELETE; - } - // open SDir -@@ -1846,7 +1846,7 @@ UDFUnlinkFile__( - cleanup_SDir: - UDFCleanUpFile__(Vcb, SFileInfo); - if (SFileInfo) MyFreePool__(SFileInfo); -- UDFFlushFile__(IrpContext, Vcb, FileInfo); -+ UDFFlushFile__(IrpContext, Vcb, FileInfo, 0); - return status; - } - SDirInfo = Dloc->SDirInfo; -@@ -1860,7 +1860,7 @@ cleanup_SDir: - goto cleanup_SDir; - } - // delete SDir -- UDFFlushFile__(IrpContext, Vcb, SDirInfo); -+ UDFFlushFile__(IrpContext, Vcb, SDirInfo, 0); - AdPrint((" ")); - UDFUnlinkFile__(IrpContext, Vcb, SDirInfo, TRUE); - // close SDir -@@ -1881,7 +1881,7 @@ cleanup_SDir: - // do deltree for Streams - status = UDFUnlinkAllFilesInDir(IrpContext, Vcb, FileInfo); - if (!NT_SUCCESS(status)) { -- UDFFlushFile__(IrpContext, Vcb, FileInfo); -+ UDFFlushFile__(IrpContext, Vcb, FileInfo, 0); - return status; - } - // update parent FileInfo -@@ -1897,7 +1897,7 @@ cleanup_SDir: - UDFFlushFESpace(Vcb, Dloc, FLUSH_FE_FOR_DEL); - } - // flush file -- UDFFlushFile__(IrpContext, Vcb, FileInfo); -+ UDFFlushFile__(IrpContext, Vcb, FileInfo, 0); - UDFUnlinkDloc(Vcb, Dloc); - // free allocation - UDFFreeFileAllocation(Vcb, DirInfo, FileInfo); -@@ -1952,7 +1952,7 @@ err_del_stream: - return status; - } - -- UDFFlushFile__(IrpContext, Vcb, FileInfo); -+ UDFFlushFile__(IrpContext, Vcb, FileInfo, 0); - AdPrint((" ")); - UDFUnlinkFile__(IrpContext, Vcb, FileInfo, TRUE); - UDFCloseFile__(IrpContext, Vcb, FileInfo); -@@ -2421,7 +2421,7 @@ UDFCleanUpFile__( - MyFreePool__(DirNdx->FName.Buffer); - } - // The only place where we can free FE_Charge extent is here -- UDFFlushFESpace(Vcb, Dloc); -+ UDFFlushFESpace(Vcb, Dloc, FLUSH_FE_KEEP); - UDFDirIndexFree(Dloc->DirIndex); - Dloc->DirIndex = NULL; - #ifdef UDF_TRACK_ONDISK_ALLOCATION -@@ -3099,7 +3099,7 @@ UDFCloseFile__( - if (FileInfo->Dloc && - FileInfo->Dloc->DirIndex) { - -- UDFFlushFESpace(Vcb, FileInfo->Dloc); -+ UDFFlushFESpace(Vcb, FileInfo->Dloc, FLUSH_FE_KEEP); - if (FileInfo->Dloc->DataLoc.Flags & EXTENT_FLAG_PREALLOCATED) { - FileInfo->Dloc->DataLoc.Flags |= EXTENT_FLAG_CUT_PREALLOCATED; - status = UDFResizeExtent(IrpContext, Vcb, PartNum, UDFGetFileSize(FileInfo), FALSE, &(FileInfo->Dloc->DataLoc)); -@@ -3276,7 +3276,7 @@ cleanup_and_abort_rename: - // unlink source FileIdent - if (!NT_SUCCESS(status = UDFUnlinkFile__(IrpContext, Vcb, FileInfo, FALSE))) { - // kill newly created entry -- UDFFlushFile__(IrpContext, Vcb, FileInfo2); -+ UDFFlushFile__(IrpContext, Vcb, FileInfo2, 0); - UDFUnlinkFile__(IrpContext, Vcb, FileInfo2, TRUE); - UDFCloseFile__(IrpContext, Vcb, FileInfo2); - UDFCleanUpFile__(Vcb, FileInfo2); -@@ -4174,7 +4174,7 @@ UDFFlushFile__( - // if Lite Flush is used, keep preallocations - if (!(FlushFlags & UDF_FLUSH_FLAGS_LITE)) { - full_flush: -- UDFFlushFESpace(Vcb, FileInfo->Dloc); -+ UDFFlushFESpace(Vcb, FileInfo->Dloc, FLUSH_FE_KEEP); - if (FileInfo->Dloc->DataLoc.Flags & EXTENT_FLAG_PREALLOCATED) { - FileInfo->Dloc->DataLoc.Flags |= EXTENT_FLAG_CUT_PREALLOCATED; - status = UDFResizeExtent(IrpContext, Vcb, PartNum, UDFGetFileSize(FileInfo), FALSE, &(FileInfo->Dloc->DataLoc)); -@@ -4991,7 +4991,7 @@ UDFRecordVAT( - UDFPhysLbaToPart(Vcb, PartNum, VatFileInfo->Dloc->DataLoc.Mapping[0].extLocation); - // record data - if (NT_SUCCESS(status = UDFWriteFile__(IrpContext, Vcb, VatFileInfo, 0, VatLen + hdrLen, FALSE, New, &WrittenBytes))) { -- status = UDFFlushFile__(IrpContext, Vcb, VatFileInfo); -+ status = UDFFlushFile__(IrpContext, Vcb, VatFileInfo, 0); - } - return status; - } -@@ -5097,7 +5097,7 @@ UDFRecordVAT( - UDFPhysLbaToPart(Vcb, PartNum, VatFileInfo->Dloc->FELoc.Mapping[0].extLocation); - VatFileInfo->Dloc->DataLoc.Modified = TRUE; - -- status = UDFFlushFile__(IrpContext, Vcb, VatFileInfo); -+ status = UDFFlushFile__(IrpContext, Vcb, VatFileInfo, 0); - if (!NT_SUCCESS(status)) - return status; - -diff --git a/drivers/filesystems/udfs/udf_info/udf_info.h b/drivers/filesystems/udfs/udf_info/udf_info.h -index c10108a..d284982 100644 ---- a/drivers/filesystems/udfs/udf_info/udf_info.h -+++ b/drivers/filesystems/udfs/udf_info/udf_info.h -@@ -444,7 +444,7 @@ void UDFFreeFESpace(IN PVCB Vcb, - // flush FE charge - void UDFFlushFESpace(IN PVCB Vcb, - IN PUDF_DATALOC_INFO Dloc, -- IN BOOLEAN Discard = FLUSH_FE_KEEP); -+ IN BOOLEAN Discard); - // discard file allocation - void UDFFreeFileAllocation(IN PVCB Vcb, - IN PUDF_FILE_INFO DirInfo, -@@ -1022,7 +1022,7 @@ UDFFlushFile__( - IN PIRP_CONTEXT IrpContext, - IN PVCB Vcb, - IN PUDF_FILE_INFO FileInfo, -- IN ULONG FlushFlags = 0 -+ IN ULONG FlushFlags - ); - - // check if the file is flushed -diff --git a/drivers/filesystems/udfs/udf_info/udf_rel.h b/drivers/filesystems/udfs/udf_info/udf_rel.h -index 602a8f6..2b26348 100644 ---- a/drivers/filesystems/udfs/udf_info/udf_rel.h -+++ b/drivers/filesystems/udfs/udf_info/udf_rel.h -@@ -246,7 +246,7 @@ typedef struct _UDF_DATALOC_INFO { - NT-specific field. As soon as NT supports HardLink concept it - has own structure describing the file's actual data. - */ -- FCB* CommonFcb; // pointer to corresponding FCB -+ struct FCB* CommonFcb; // pointer to corresponding FCB - /** - Describes on-disk location of user data. If the file is - recorded using IN_ICB method this structure points to the -diff --git a/drivers/filesystems/udfs/udfdata.cpp b/drivers/filesystems/udfs/udfdata.c -similarity index 100% -rename from drivers/filesystems/udfs/udfdata.cpp -rename to drivers/filesystems/udfs/udfdata.c -diff --git a/drivers/filesystems/udfs/udfinit.cpp b/drivers/filesystems/udfs/udfinit.c -similarity index 100% -rename from drivers/filesystems/udfs/udfinit.cpp -rename to drivers/filesystems/udfs/udfinit.c -diff --git a/drivers/filesystems/udfs/unload.cpp b/drivers/filesystems/udfs/unload.c -similarity index 100% -rename from drivers/filesystems/udfs/unload.cpp -rename to drivers/filesystems/udfs/unload.c -diff --git a/drivers/filesystems/udfs/verfysup.cpp b/drivers/filesystems/udfs/verfysup.c -similarity index 100% -rename from drivers/filesystems/udfs/verfysup.cpp -rename to drivers/filesystems/udfs/verfysup.c -diff --git a/drivers/filesystems/udfs/volinfo.cpp b/drivers/filesystems/udfs/volinfo.c -similarity index 100% -rename from drivers/filesystems/udfs/volinfo.cpp -rename to drivers/filesystems/udfs/volinfo.c -diff --git a/drivers/filesystems/udfs/write.cpp b/drivers/filesystems/udfs/write.c -similarity index 99% -rename from drivers/filesystems/udfs/write.cpp -rename to drivers/filesystems/udfs/write.c -index 5977f3e..1f236e6 100644 ---- a/drivers/filesystems/udfs/write.cpp -+++ b/drivers/filesystems/udfs/write.c -@@ -237,7 +237,7 @@ UDFCommonWrite( - // I dislike the idea of writing to mounted media too, but M$ has another point of view... - if (Vcb->VcbCondition == VcbMounted) { - // flush system cache -- UDFFlushVolume(IrpContext, Vcb); -+ UDFFlushVolume(IrpContext, Vcb, 0); - } - - // Forward the request to the lower level driver -@@ -255,7 +255,7 @@ UDFCommonWrite( - // Perform actual Write - Status = UDFTWrite(IrpContext, Vcb, SystemBuffer, ByteCount, - (ULONG)(StartingOffset >> Vcb->SectorShift), -- &NumberBytesWritten); -+ &NumberBytesWritten, 0); - UDFUnlockCallersBuffer(IrpContext, Irp, SystemBuffer); - try_return(Status); - } From a5e52192795c9276656e60efbdde2b295877524d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 7 Mar 2026 01:27:31 +0000 Subject: [PATCH 17/20] Fix mixed SEH macro nesting in UDFGetVolumeBitmap (fscntrl.c) Co-authored-by: Zero3K20 <258969903+Zero3K20@users.noreply.github.com> --- drivers/filesystems/udfs/fscntrl.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/filesystems/udfs/fscntrl.c b/drivers/filesystems/udfs/fscntrl.c index ec8ba4f20c179..9e3be52d70309 100644 --- a/drivers/filesystems/udfs/fscntrl.c +++ b/drivers/filesystems/udfs/fscntrl.c @@ -1331,7 +1331,7 @@ UDFGetVolumeBitmap( // Fill in the fixed part of the output buffer - __try { + _SEH2_TRY { // StartingLcn in output = aligned starting block @@ -1341,10 +1341,10 @@ UDFGetVolumeBitmap( OutputBuffer->BitmapSize.QuadPart = DesiredClusters; - } __except (EXCEPTION_EXECUTE_HANDLER) { + } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { try_return(Status = STATUS_INVALID_USER_BUFFER); - } + } _SEH2_END OutputBufferLength -= FIELD_OFFSET(VOLUME_BITMAP_BUFFER, Buffer); From 960ca673c18ae82d751ce647df72325d3138fcdc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 7 Mar 2026 01:40:08 +0000 Subject: [PATCH 18/20] Fix multiple definition of MyAllocInit (and other inline funcs) in mem_tools.h Co-authored-by: Zero3K20 <258969903+Zero3K20@users.noreply.github.com> --- drivers/filesystems/udfs/Include/mem_tools.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/filesystems/udfs/Include/mem_tools.h b/drivers/filesystems/udfs/Include/mem_tools.h index 29c734fbc1175..3499884aa2a15 100644 --- a/drivers/filesystems/udfs/Include/mem_tools.h +++ b/drivers/filesystems/udfs/Include/mem_tools.h @@ -130,7 +130,7 @@ MyFindMemBaseByAddr( #define MyAlignSize__(size) (size) #endif -inline BOOLEAN MyAllocInit(VOID) {return TRUE;} +static inline BOOLEAN MyAllocInit(VOID) {return TRUE;} #define MyAllocRelease() #ifndef MY_MEM_BOUNDS_CHECK @@ -176,7 +176,7 @@ PVOID inline MyAllocatePool__(ULONG type, ULONG len) { } */ -inline PVOID MyAllocatePoolTag__(ULONG type, ULONG len, /*PCHAR*/ULONG tag) { +static inline PVOID MyAllocatePoolTag__(ULONG type, ULONG len, /*PCHAR*/ULONG tag) { PCHAR newaddr; ULONG i; // newaddr = (PCHAR)MyAllocatePoolTag_(type, len+MY_HEAP_ALIGN+1, tag); @@ -193,7 +193,7 @@ inline PVOID MyAllocatePoolTag__(ULONG type, ULONG len, /*PCHAR*/ULONG tag) { return newaddr; } -inline VOID MyFreePool__(PVOID addr) { +static inline VOID MyFreePool__(PVOID addr) { PCHAR newaddr; // ULONG i; newaddr = (PCHAR)addr; @@ -220,7 +220,7 @@ inline VOID MyFreePool__(PVOID addr) { #pragma GCC diagnostic ignored "-Wstringop-overflow" #endif -inline ULONG MyReallocPool__(PCHAR addr, ULONG len, PCHAR *pnewaddr, ULONG newlen) { +static inline ULONG MyReallocPool__(PCHAR addr, ULONG len, PCHAR *pnewaddr, ULONG newlen) { ULONG _len, _newlen; _newlen = MyAlignSize__(newlen); _len = MyAlignSize__(len); From 1de154ab182f248290a89f43d8bdc8e4f4c12b0d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 7 Mar 2026 01:48:45 +0000 Subject: [PATCH 19/20] [UDFS] Fix multiple definition / static-vs-non-static conflict for MyAllocInit in mem_tools.h Co-authored-by: Zero3K20 <258969903+Zero3K20@users.noreply.github.com> --- drivers/filesystems/udfs/Include/mem_tools.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/filesystems/udfs/Include/mem_tools.h b/drivers/filesystems/udfs/Include/mem_tools.h index 3499884aa2a15..54ce6574662ef 100644 --- a/drivers/filesystems/udfs/Include/mem_tools.h +++ b/drivers/filesystems/udfs/Include/mem_tools.h @@ -46,6 +46,7 @@ extern ULONG MemTotalAllocated; #define MY_HEAP_MAX_FRAMES 512 #define MY_HEAP_MAX_BLOCKS 4*1024 // blocks per frame +#ifdef MY_USE_INTERNAL_MEMMANAGER // Mem BOOLEAN MyAllocInit(VOID); VOID MyAllocRelease(VOID); @@ -65,6 +66,7 @@ PCHAR __fastcall MyAllocatePool(ULONG Type, ULONG size ULONG __fastcall MyReallocPool( PCHAR addr, ULONG OldLength, PCHAR* NewBuff, ULONG NewLength); #endif VOID __fastcall MyFreePool(PCHAR addr); +#endif // MY_USE_INTERNAL_MEMMANAGER #ifdef MY_HEAP_CHECK_BOUNDS #define MY_HEAP_ALIGN 63 From ad59893f1358547a449651e04c644f1ca072a887 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 7 Mar 2026 01:59:48 +0000 Subject: [PATCH 20/20] [UDFS] Fix compiler warnings in filesystem driver Co-authored-by: Zero3K20 <258969903+Zero3K20@users.noreply.github.com> --- drivers/filesystems/udfs/Include/Sys_spec_lib.h | 2 +- drivers/filesystems/udfs/Include/phys_lib.c | 1 - drivers/filesystems/udfs/env_spec.c | 3 --- drivers/filesystems/udfs/strucsup.c | 14 +++++++------- drivers/filesystems/udfs/verfysup.c | 3 +++ drivers/filesystems/udfs/write.c | 4 ++-- 6 files changed, 13 insertions(+), 14 deletions(-) diff --git a/drivers/filesystems/udfs/Include/Sys_spec_lib.h b/drivers/filesystems/udfs/Include/Sys_spec_lib.h index 7187ab6e0371b..696022e2d2d4c 100644 --- a/drivers/filesystems/udfs/Include/Sys_spec_lib.h +++ b/drivers/filesystems/udfs/Include/Sys_spec_lib.h @@ -104,7 +104,7 @@ __inline LARGE_INTEGER UDFMakeLargeInteger(LONGLONG value) { #define UDFGetNTFileId(Vcb, fi) \ UDFMakeLargeInteger((((fi)->Dloc->FELoc.Mapping[0].extLocation - UDFPartStart(Vcb, -2)) + \ - ((LONGLONG)Vcb<<32))) + ((LONGLONG)(ULONG_PTR)Vcb<<32))) #define UnicodeIsPrint(a) RtlIsValidOemCharacter(&(a)) diff --git a/drivers/filesystems/udfs/Include/phys_lib.c b/drivers/filesystems/udfs/Include/phys_lib.c index c840e74ed8051..b8da310d2e039 100644 --- a/drivers/filesystems/udfs/Include/phys_lib.c +++ b/drivers/filesystems/udfs/Include/phys_lib.c @@ -1002,7 +1002,6 @@ UDFPrepareForReadOperation( Vcb->VcbState &= ~UDF_VCB_LAST_WRITE; return STATUS_SUCCESS; } - uint32 i = Vcb->LastReadTrack; #ifdef _UDF_STRUCTURES_H_ if (Vcb->BSBM_Bitmap) { diff --git a/drivers/filesystems/udfs/env_spec.c b/drivers/filesystems/udfs/env_spec.c index 52e1cb5382576..6872a86d9924f 100644 --- a/drivers/filesystems/udfs/env_spec.c +++ b/drivers/filesystems/udfs/env_spec.c @@ -134,7 +134,6 @@ UDFPhReadSynchronous( PIO_STACK_LOCATION IrpSp; KIRQL CurIrql = KeGetCurrentIrql(); PVOID IoBuf = NULL; - PVCB Vcb = NULL; ROffset.QuadPart = Offset; (*ReadBytes) = 0; @@ -252,8 +251,6 @@ UDFPhWriteSynchronous( KIRQL CurIrql = KeGetCurrentIrql(); PVOID IoBuf = NULL; - PVCB Vcb = NULL; - #ifdef DBG if (UDF_SIMULATE_WRITES) { /* FIXME ReactOS diff --git a/drivers/filesystems/udfs/strucsup.c b/drivers/filesystems/udfs/strucsup.c index e0a608e013278..860179a50b33f 100644 --- a/drivers/filesystems/udfs/strucsup.c +++ b/drivers/filesystems/udfs/strucsup.c @@ -29,7 +29,7 @@ typedef struct _FCB_TABLE_ELEMENT { RtlDeleteElementGenericTable( &(F)->Vcb->FcbTable, &_Key ); \ } -inline +static inline PFCB_NONPAGED UDFAllocateFcbNonpaged( ) @@ -37,7 +37,7 @@ UDFAllocateFcbNonpaged( return (PFCB_NONPAGED)ExAllocateFromNPagedLookasideList(&UdfData.UDFNonPagedFcbLookasideList); } -inline +static inline PFCB UDFAllocateFcbIndex( ) @@ -45,7 +45,7 @@ UDFAllocateFcbIndex( return (PFCB)ExAllocateFromPagedLookasideList(&UdfData.UDFFcbIndexLookasideList); } -inline +static inline PFCB UDFAllocateFcbData( ) @@ -53,7 +53,7 @@ UDFAllocateFcbData( return (PFCB)ExAllocateFromPagedLookasideList(&UdfData.UDFFcbDataLookasideList); } -inline +static inline PFCB UDFAllocateFcb( ) @@ -61,7 +61,7 @@ UDFAllocateFcb( return (PFCB)ExAllocatePoolWithTag(NonPagedPool, sizeof(FCB), TAG_FCB); } -inline +static inline VOID UDFDeallocateFcbNonpaged( PFCB_NONPAGED FcbNonpaged @@ -70,7 +70,7 @@ UDFDeallocateFcbNonpaged( ExFreeToNPagedLookasideList(&UdfData.UDFNonPagedFcbLookasideList, FcbNonpaged); } -inline +static inline VOID UDFDeallocateFcbIndex( PFCB Fcb @@ -79,7 +79,7 @@ UDFDeallocateFcbIndex( ExFreeToPagedLookasideList(&UdfData.UDFFcbIndexLookasideList, Fcb); } -inline +static inline VOID UDFDeallocateFcbData( PFCB Fcb diff --git a/drivers/filesystems/udfs/verfysup.c b/drivers/filesystems/udfs/verfysup.c index 015af5a6b423b..aad0057c6650c 100644 --- a/drivers/filesystems/udfs/verfysup.c +++ b/drivers/filesystems/udfs/verfysup.c @@ -234,6 +234,9 @@ UDFVerifyVcb( UDFRaiseStatus(IrpContext, STATUS_FILE_INVALID); } break; + + default: + break; } } // end UDFVerifyVcb() diff --git a/drivers/filesystems/udfs/write.c b/drivers/filesystems/udfs/write.c index 1f236e69585e0..e18ef76786207 100644 --- a/drivers/filesystems/udfs/write.c +++ b/drivers/filesystems/udfs/write.c @@ -910,8 +910,8 @@ UDFZeroData ( --*/ { - LARGE_INTEGER ZeroStart = {0,0}; - LARGE_INTEGER BeyondZeroEnd = {0,0}; + LARGE_INTEGER ZeroStart = {{0, 0}}; + LARGE_INTEGER BeyondZeroEnd = {{0, 0}}; BOOLEAN Finished;