Author: pschweitzer Date: Wed Feb 23 12:04:08 2011 New Revision: 50873 URL: http://svn.reactos.org/svn/reactos?rev=50873&view=rev Log: [NTOSKRNL] One-line fix for FsRtlIs*InExpression(). This fixes failing tests, but not overrun. Added some breaks to reach more quickly the end
Modified: trunk/reactos/ntoskrnl/fsrtl/dbcsname.c trunk/reactos/ntoskrnl/fsrtl/largemcb.c Modified: trunk/reactos/ntoskrnl/fsrtl/dbcsname.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/fsrtl/dbcsname.c?rev=50873&r1=50872&r2=50873&view=diff ============================================================================== --- trunk/reactos/ntoskrnl/fsrtl/dbcsname.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/fsrtl/dbcsname.c [iso-8859-1] Wed Feb 23 12:04:08 2011 @@ -181,7 +181,7 @@ switch (Expression->Buffer[ExpressionPosition]) { case '*': - StarFound = ExpressionPosition++; + StarFound = MAXUSHORT; break; case '?': @@ -226,6 +226,7 @@ if (ExpressionPosition == Expression->Length) { NamePosition = Name->Length; + break; } } else if (Expression->Buffer[ExpressionPosition] == ANSI_DOS_STAR) @@ -253,7 +254,7 @@ } else { - NamePosition = Name->Length; + break; } } if (ExpressionPosition + 1 == Expression->Length && NamePosition == Name->Length && Modified: trunk/reactos/ntoskrnl/fsrtl/largemcb.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/fsrtl/largemcb.c?rev=50873&r1=50872&r2=50873&view=diff ============================================================================== --- trunk/reactos/ntoskrnl/fsrtl/largemcb.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/fsrtl/largemcb.c [iso-8859-1] Wed Feb 23 12:04:08 2011 @@ -2,8 +2,10 @@ * PROJECT: ReactOS Kernel * LICENSE: GPL - See COPYING in the top level directory * FILE: ntoskrnl/fsrtl/largemcb.c - * PURPOSE: Mapping Control Block (MCB) support for File System Drivers + * PURPOSE: Large Mapped Control Block (MCB) support for File System Drivers * PROGRAMMERS: Alex Ionescu (alex.ione...@reactos.org) + * Pierre Schweitzer (heis_spi...@hotmail.com) + * Art Yerkes (art.yer...@gmail.com) */ /* INCLUDES ******************************************************************/ @@ -12,10 +14,158 @@ #define NDEBUG #include <debug.h> +/* GLOBALS *******************************************************************/ + +#define GET_LIST_HEAD(x) ((PLIST_ENTRY)(&((PRTL_GENERIC_TABLE)x)[1])) + +PAGED_LOOKASIDE_LIST FsRtlFirstMappingLookasideList; +NPAGED_LOOKASIDE_LIST FsRtlFastMutexLookasideList; + +typedef struct _LARGE_MCB_MAPPING_ENTRY +{ + LARGE_INTEGER RunStartVbn; + LARGE_INTEGER SectorCount; + LARGE_INTEGER StartingLbn; + LIST_ENTRY Sequence; +} LARGE_MCB_MAPPING_ENTRY, *PLARGE_MCB_MAPPING_ENTRY; + +static VOID McbPrintTree(PBASE_MCB Mcb) +{ + PLARGE_MCB_MAPPING_ENTRY Entry; + for (Entry = (PLARGE_MCB_MAPPING_ENTRY) + RtlEnumerateGenericTable(Mcb->Mapping, TRUE); + Entry; + Entry = (PLARGE_MCB_MAPPING_ENTRY) + RtlEnumerateGenericTable(Mcb->Mapping, FALSE)) + { + DPRINT1 + ("Vbn %x Lbn %x Count %x\n", + Entry->RunStartVbn.LowPart, + Entry->StartingLbn.LowPart, + Entry->SectorCount.LowPart); + } +} + +static PVOID NTAPI McbMappingAllocate(PRTL_GENERIC_TABLE Table, CLONG Bytes) +{ + PVOID Result; + PBASE_MCB Mcb = (PBASE_MCB)Table->TableContext; + Result = ExAllocatePoolWithTag(Mcb->PoolType, Bytes, 'LMCB'); + DPRINT("McbMappingAllocate(%d) => %p\n", Bytes, Result); + return Result; +} + +static VOID NTAPI McbMappingFree(PRTL_GENERIC_TABLE Table, PVOID Buffer) +{ + DPRINT("McbMappingFree(%p)\n", Buffer); + ExFreePoolWithTag(Buffer, 'LMCB'); +} + +static RTL_GENERIC_COMPARE_RESULTS NTAPI McbMappingCompare +(PRTL_GENERIC_TABLE Table, PVOID PtrA, PVOID PtrB) +{ + PLARGE_MCB_MAPPING_ENTRY A = PtrA, B = PtrB; + RTL_GENERIC_COMPARE_RESULTS Result; + DPRINT("Starting to compare element %x to element %x\n", PtrA, PtrB); + Result = + (A->RunStartVbn.QuadPart + A->SectorCount.QuadPart <= + B->RunStartVbn.QuadPart) ? GenericLessThan : + (A->RunStartVbn.QuadPart >= + B->RunStartVbn.QuadPart + B->SectorCount.QuadPart) ? + GenericGreaterThan : GenericEqual; + DPRINT("Compare(%x:%x): %x:%x to %x:%x => %d\n", + A,B, + A->RunStartVbn.LowPart, A->SectorCount.LowPart, + B->RunStartVbn.LowPart, B->SectorCount.LowPart, + Result); + return Result; +} + /* PUBLIC FUNCTIONS **********************************************************/ /* - * @unimplemented + * @implemented + */ +BOOLEAN +NTAPI +FsRtlAddBaseMcbEntry(IN PBASE_MCB Mcb, + IN LONGLONG Vbn, + IN LONGLONG Lbn, + IN LONGLONG SectorCount) +{ + LARGE_MCB_MAPPING_ENTRY Node; + PLARGE_MCB_MAPPING_ENTRY Existing = NULL; + BOOLEAN NewElement = FALSE; + + McbPrintTree(Mcb); + + Node.RunStartVbn.QuadPart = Vbn; + Node.StartingLbn.QuadPart = Lbn; + Node.SectorCount.QuadPart = SectorCount; + + DPRINT("RunStartVbn %x\n", Node.RunStartVbn.LowPart); + DPRINT("StartingLbn %x\n", Node.StartingLbn.LowPart); + DPRINT("SectorCount %x\n", Node.SectorCount.LowPart); + + while (!NewElement) + { + DPRINT("Inserting %x:%x\n", Node.RunStartVbn.LowPart, Node.SectorCount.LowPart); + Existing = RtlInsertElementGenericTable + (Mcb->Mapping, &Node, sizeof(Node), &NewElement); + DPRINT("Existing %x\n", Existing); + if (!Existing) break; + + DPRINT("NewElement %d\n", NewElement); + if (!NewElement) + { + // We merge the existing runs + LARGE_INTEGER StartVbn, FinalVbn; + DPRINT("Existing: %x:%x\n", + Existing->RunStartVbn.LowPart, Node.SectorCount.LowPart); + if (Existing->RunStartVbn.QuadPart < Node.RunStartVbn.QuadPart) + { + StartVbn = Existing->RunStartVbn; + Node.StartingLbn = Existing->StartingLbn; + } + else + { + StartVbn = Node.RunStartVbn; + } + DPRINT("StartVbn %x\n", StartVbn.LowPart); + if (Existing->RunStartVbn.QuadPart + Existing->SectorCount.QuadPart > + Node.RunStartVbn.QuadPart + Node.SectorCount.QuadPart) + { + FinalVbn.QuadPart = + Existing->RunStartVbn.QuadPart + Existing->SectorCount.QuadPart; + } + else + { + FinalVbn.QuadPart = + Node.RunStartVbn.QuadPart + Node.SectorCount.QuadPart; + } + DPRINT("FinalVbn %x\n", FinalVbn.LowPart); + Node.RunStartVbn.QuadPart = StartVbn.QuadPart; + Node.SectorCount.QuadPart = FinalVbn.QuadPart - StartVbn.QuadPart; + RemoveHeadList(&Existing->Sequence); + RtlDeleteElementGenericTable(Mcb->Mapping, Existing); + Mcb->PairCount--; + } + else + { + DPRINT("Mapping added %x\n", Existing); + Mcb->MaximumPairCount++; + Mcb->PairCount++; + InsertHeadList(GET_LIST_HEAD(Mcb->Mapping), &Existing->Sequence); + } + } + + DPRINT("!!Existing %d\n", !!Existing); + McbPrintTree(Mcb); + return !!Existing; +} + +/* + * @implemented */ BOOLEAN NTAPI @@ -24,9 +174,780 @@ IN LONGLONG Lbn, IN LONGLONG SectorCount) { - KeBugCheck(FILE_SYSTEM); - return FALSE; -} + BOOLEAN Result; + + DPRINT + ("Mcb %x Vbn %x Lbn %x SectorCount %x\n", + Mcb, (ULONG)Vbn, (ULONG)Lbn, (ULONG)SectorCount); + + KeAcquireGuardedMutex(Mcb->GuardedMutex); + Result = FsRtlAddBaseMcbEntry(&(Mcb->BaseMcb), + Vbn, + Lbn, + SectorCount); + KeReleaseGuardedMutex(Mcb->GuardedMutex); + + DPRINT("Done %d\n", Result); + + return Result; +} + +/* + * @unimplemented + */ +BOOLEAN +NTAPI +FsRtlGetNextBaseMcbEntry(IN PBASE_MCB Mcb, + IN ULONG RunIndex, + OUT PLONGLONG Vbn, + OUT PLONGLONG Lbn, + OUT PLONGLONG SectorCount) +{ + ULONG i = 0; + BOOLEAN Result = FALSE; + PLARGE_MCB_MAPPING_ENTRY Entry; + for (Entry = (PLARGE_MCB_MAPPING_ENTRY) + RtlEnumerateGenericTable(Mcb->Mapping, TRUE); + Entry && i < RunIndex; + Entry = (PLARGE_MCB_MAPPING_ENTRY) + RtlEnumerateGenericTable(Mcb->Mapping, FALSE), i++); + if (Entry) + { + Result = TRUE; + if (Vbn) + *Vbn = Entry->RunStartVbn.QuadPart; + if (Lbn) + *Lbn = Entry->StartingLbn.QuadPart; + if (SectorCount) + *SectorCount = Entry->SectorCount.QuadPart; + } + + return Result; +} + +/* + * @implemented + */ +BOOLEAN +NTAPI +FsRtlGetNextLargeMcbEntry(IN PLARGE_MCB Mcb, + IN ULONG RunIndex, + OUT PLONGLONG Vbn, + OUT PLONGLONG Lbn, + OUT PLONGLONG SectorCount) +{ + BOOLEAN Result; + + DPRINT("FsRtlGetNextLargeMcbEntry Mcb %x RunIndex %x\n", Mcb, RunIndex); + + KeAcquireGuardedMutex(Mcb->GuardedMutex); + Result = FsRtlGetNextBaseMcbEntry(&(Mcb->BaseMcb), + RunIndex, + Vbn, + Lbn, + SectorCount); + KeReleaseGuardedMutex(Mcb->GuardedMutex); + + DPRINT("Done %d\n", Result); + + return Result; +} + +/* + * @implemented + */ +VOID +NTAPI +FsRtlInitializeBaseMcb(IN PBASE_MCB Mcb, + IN POOL_TYPE PoolType) +{ + Mcb->PairCount = 0; + + if (PoolType == PagedPool) + { + Mcb->Mapping = ExAllocateFromPagedLookasideList(&FsRtlFirstMappingLookasideList); + DPRINT("Get from lookaside list\n"); + } + else + { + Mcb->Mapping = ExAllocatePoolWithTag(PoolType | POOL_RAISE_IF_ALLOCATION_FAILURE, + sizeof(RTL_GENERIC_TABLE) + sizeof(LIST_ENTRY), + 'FSBC'); + DPRINT("Allocate\n"); + } + + DPRINT("Mcb->Mapping %x\n", Mcb->Mapping); + Mcb->PoolType = PoolType; + Mcb->MaximumPairCount = MAXIMUM_PAIR_COUNT; + RtlInitializeGenericTable + (Mcb->Mapping, + McbMappingCompare, + McbMappingAllocate, + McbMappingFree, + Mcb); + InitializeListHead(GET_LIST_HEAD(Mcb->Mapping)); +} + +/* + * @implemented + */ +VOID +NTAPI +FsRtlInitializeLargeMcb(IN PLARGE_MCB Mcb, + IN POOL_TYPE PoolType) +{ + Mcb->GuardedMutex = ExAllocateFromNPagedLookasideList(&FsRtlFastMutexLookasideList); + + KeInitializeGuardedMutex(Mcb->GuardedMutex); + + _SEH2_TRY + { + FsRtlInitializeBaseMcb(&(Mcb->BaseMcb), PoolType); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + ExFreeToNPagedLookasideList(&FsRtlFastMutexLookasideList, + Mcb->GuardedMutex); + Mcb->GuardedMutex = NULL; + } + _SEH2_END; +} + +/* + * @implemented + */ +VOID +NTAPI +FsRtlInitializeLargeMcbs(VOID) +{ + /* Initialize the list for the MCB */ + ExInitializePagedLookasideList(&FsRtlFirstMappingLookasideList, + NULL, + NULL, + POOL_RAISE_IF_ALLOCATION_FAILURE, + sizeof(RTL_GENERIC_TABLE) + sizeof(LIST_ENTRY), + IFS_POOL_TAG, + 0); /* FIXME: Should be 4 */ + + /* Initialize the list for the guarded mutex */ + ExInitializeNPagedLookasideList(&FsRtlFastMutexLookasideList, + NULL, + NULL, + POOL_RAISE_IF_ALLOCATION_FAILURE, + sizeof(KGUARDED_MUTEX), + IFS_POOL_TAG, + 0); /* FIXME: Should be 32 */ +} + +/* + * @unimplemented + */ +BOOLEAN +NTAPI +FsRtlLookupBaseMcbEntry(IN PBASE_MCB Mcb, + IN LONGLONG Vbn, + OUT PLONGLONG Lbn OPTIONAL, + OUT PLONGLONG SectorCountFromLbn OPTIONAL, + OUT PLONGLONG StartingLbn OPTIONAL, + OUT PLONGLONG SectorCountFromStartingLbn OPTIONAL, + OUT PULONG Index OPTIONAL) +{ + BOOLEAN Result = FALSE; + LARGE_MCB_MAPPING_ENTRY ToLookup; + PLARGE_MCB_MAPPING_ENTRY Entry; + + ToLookup.RunStartVbn.QuadPart = Vbn; + ToLookup.SectorCount.QuadPart = 1; + + Entry = RtlLookupElementGenericTable(Mcb->Mapping, &ToLookup); + if (!Entry) + { + // Find out if we have a following entry. The spec says we should return + // found with Lbn == -1 when we're beneath the largest map. + ToLookup.SectorCount.QuadPart = (1ull<<62) - ToLookup.RunStartVbn.QuadPart; + Entry = RtlLookupElementGenericTable(Mcb->Mapping, &ToLookup); + if (Entry) + { + Result = TRUE; + if (Lbn) *Lbn = ~0ull; + } + else + { + Result = FALSE; + } + } + else + { + LARGE_INTEGER Offset; + Offset.QuadPart = Vbn - Entry->RunStartVbn.QuadPart; + Result = TRUE; + if (Lbn) *Lbn = Entry->StartingLbn.QuadPart + Offset.QuadPart; + if (SectorCountFromLbn) *SectorCountFromLbn = Entry->SectorCount.QuadPart - Offset.QuadPart; + if (StartingLbn) *StartingLbn = Entry->StartingLbn.QuadPart; + if (SectorCountFromStartingLbn) *SectorCountFromStartingLbn = Entry->SectorCount.QuadPart; + } + + return Result; +} + +/* + * @implemented + */ +BOOLEAN +NTAPI +FsRtlLookupLargeMcbEntry(IN PLARGE_MCB Mcb, + IN LONGLONG Vbn, + OUT PLONGLONG Lbn OPTIONAL, + OUT PLONGLONG SectorCountFromLbn OPTIONAL, + OUT PLONGLONG StartingLbn OPTIONAL, + OUT PLONGLONG SectorCountFromStartingLbn OPTIONAL, + OUT PULONG Index OPTIONAL) +{ + BOOLEAN Result; + + DPRINT("FsRtlLookupLargeMcbEntry Mcb %x Vbn %x\n", Mcb, (ULONG)Vbn); + + KeAcquireGuardedMutex(Mcb->GuardedMutex); + Result = FsRtlLookupBaseMcbEntry(&(Mcb->BaseMcb), + Vbn, + Lbn, + SectorCountFromLbn, + StartingLbn, + SectorCountFromStartingLbn, + Index); + KeReleaseGuardedMutex(Mcb->GuardedMutex); + + DPRINT("Done %d (%x)\n", Result, Lbn ? (ULONG)*Lbn : 0); + + return Result; +} + +/* + * @unimplemented + */ +BOOLEAN +NTAPI +FsRtlLookupLastBaseMcbEntryAndIndex(IN PBASE_MCB OpaqueMcb, + IN OUT PLONGLONG LargeVbn, + IN OUT PLONGLONG LargeLbn, + IN OUT PULONG Index) +{ + ULONG i = 0; + BOOLEAN Result = FALSE; + PLIST_ENTRY ListEntry; + PLARGE_MCB_MAPPING_ENTRY Entry; + PLARGE_MCB_MAPPING_ENTRY CountEntry; + + ListEntry = GET_LIST_HEAD(OpaqueMcb->Mapping); + if (!IsListEmpty(ListEntry)) + { + Entry = CONTAINING_RECORD(ListEntry->Flink, LARGE_MCB_MAPPING_ENTRY, Sequence); + Result = TRUE; + *LargeVbn = Entry->RunStartVbn.QuadPart; + *LargeLbn = Entry->StartingLbn.QuadPart; + + for (i = 0, CountEntry = RtlEnumerateGenericTable(OpaqueMcb->Mapping, TRUE); + CountEntry != Entry; + CountEntry = RtlEnumerateGenericTable(OpaqueMcb->Mapping, FALSE)); + + *Index = i; + } + + return Result; +} + +/* + * @implemented + */ +BOOLEAN +NTAPI +FsRtlLookupLastLargeMcbEntryAndIndex(IN PLARGE_MCB OpaqueMcb, + OUT PLONGLONG LargeVbn, + OUT PLONGLONG LargeLbn, + OUT PULONG Index) +{ + BOOLEAN Result; + + DPRINT("FsRtlLookupLastLargeMcbEntryAndIndex %x\n", OpaqueMcb); + + KeAcquireGuardedMutex(OpaqueMcb->GuardedMutex); + Result = FsRtlLookupLastBaseMcbEntryAndIndex(&(OpaqueMcb->BaseMcb), + LargeVbn, + LargeLbn, + Index); + KeReleaseGuardedMutex(OpaqueMcb->GuardedMutex); + + DPRINT("Done %d\n", Result); + + return Result; +} + +/* + * @unimplemented + */ +BOOLEAN +NTAPI +FsRtlLookupLastBaseMcbEntry(IN PBASE_MCB Mcb, + OUT PLONGLONG Vbn, + OUT PLONGLONG Lbn) +{ + BOOLEAN Result = FALSE; + PLIST_ENTRY ListEntry; + PLARGE_MCB_MAPPING_ENTRY Entry; + + ListEntry = GET_LIST_HEAD(Mcb->Mapping); + if (!IsListEmpty(ListEntry)) + { + Entry = CONTAINING_RECORD(ListEntry->Flink, LARGE_MCB_MAPPING_ENTRY, Sequence); + Result = TRUE; + *Vbn = Entry->RunStartVbn.QuadPart; + *Lbn = Entry->StartingLbn.QuadPart; + } + + return Result; +} + +/* + * @implemented + */ +BOOLEAN +NTAPI +FsRtlLookupLastLargeMcbEntry(IN PLARGE_MCB Mcb, + OUT PLONGLONG Vbn, + OUT PLONGLONG Lbn) +{ + BOOLEAN Result; + + DPRINT("FsRtlLookupLastLargeMcbEntry Mcb %x\n", Mcb); + + KeAcquireGuardedMutex(Mcb->GuardedMutex); + Result = FsRtlLookupLastBaseMcbEntry(&(Mcb->BaseMcb), + Vbn, + Lbn); + KeReleaseGuardedMutex(Mcb->GuardedMutex); + + DPRINT("Done %d\n", Result); + + return Result; +} + +/* + * @implemented + */ +ULONG +NTAPI +FsRtlNumberOfRunsInBaseMcb(IN PBASE_MCB Mcb) +{ + /* Return the count */ + return Mcb->PairCount; +} + +/* + * @implemented + */ +ULONG +NTAPI +FsRtlNumberOfRunsInLargeMcb(IN PLARGE_MCB Mcb) +{ + ULONG NumberOfRuns; + + DPRINT("FsRtlNumberOfRunsInLargeMcb Mcb %x\n", Mcb); + + /* Read the number of runs while holding the MCB lock */ + KeAcquireGuardedMutex(Mcb->GuardedMutex); + NumberOfRuns = Mcb->BaseMcb.PairCount; + KeReleaseGuardedMutex(Mcb->GuardedMutex); + + DPRINT("Done %d\n", NumberOfRuns); + + /* Return the count */ + return NumberOfRuns; +} + +/* + * @unimplemented + */ +VOID +NTAPI +FsRtlRemoveBaseMcbEntry(IN PBASE_MCB Mcb, + IN LONGLONG Vbn, + IN LONGLONG SectorCount) +{ + LARGE_MCB_MAPPING_ENTRY Node; + PLARGE_MCB_MAPPING_ENTRY Element; + + Node.RunStartVbn.QuadPart = Vbn; + Node.SectorCount.QuadPart = SectorCount; + + while ((Element = RtlLookupElementGenericTable(Mcb->Mapping, &Node))) + { + // Must split + if (Element->RunStartVbn.QuadPart < Node.RunStartVbn.QuadPart && + Element->SectorCount.QuadPart > Node.SectorCount.QuadPart) + { + LARGE_MCB_MAPPING_ENTRY Upper, Reinsert; + PLARGE_MCB_MAPPING_ENTRY Reinserted, Inserted; + LARGE_INTEGER StartHole = Node.RunStartVbn; + LARGE_INTEGER EndHole; + EndHole.QuadPart = Node.RunStartVbn.QuadPart + Node.SectorCount.QuadPart; + Upper.RunStartVbn.QuadPart = EndHole.QuadPart; + Upper.StartingLbn.QuadPart = + Element->StartingLbn.QuadPart + + EndHole.QuadPart - + Element->RunStartVbn.QuadPart; + Upper.SectorCount.QuadPart = + Element->SectorCount.QuadPart - + (EndHole.QuadPart - Element->RunStartVbn.QuadPart); + Reinsert = *Element; + Reinsert.SectorCount.QuadPart = + Element->RunStartVbn.QuadPart - StartHole.QuadPart; + RemoveEntryList(&Element->Sequence); + RtlDeleteElementGenericTable(Mcb->Mapping, Element); + Mcb->PairCount--; + + Reinserted = RtlInsertElementGenericTable + (Mcb->Mapping, &Reinsert, sizeof(Reinsert), NULL); + InsertHeadList(GET_LIST_HEAD(Mcb->Mapping), &Reinserted->Sequence); + Mcb->PairCount++; + + Inserted = RtlInsertElementGenericTable + (Mcb->Mapping, &Upper, sizeof(Upper), NULL); + InsertHeadList(GET_LIST_HEAD(Mcb->Mapping), &Inserted->Sequence); + Mcb->PairCount++; + } + else if (Element->RunStartVbn.QuadPart < Node.RunStartVbn.QuadPart) + { + LARGE_MCB_MAPPING_ENTRY NewElement; + PLARGE_MCB_MAPPING_ENTRY Reinserted; + LARGE_INTEGER StartHole = Node.RunStartVbn; + NewElement.RunStartVbn = Element->RunStartVbn; + NewElement.StartingLbn = Element->StartingLbn; + NewElement.SectorCount.QuadPart = StartHole.QuadPart - Element->StartingLbn.QuadPart; + + RemoveEntryList(&Element->Sequence); + RtlDeleteElementGenericTable(Mcb->Mapping, Element); + Mcb->PairCount--; + + Reinserted = RtlInsertElementGenericTable + (Mcb->Mapping, &NewElement, sizeof(NewElement), NULL); + InsertHeadList(GET_LIST_HEAD(Mcb->Mapping), &Reinserted->Sequence); + Mcb->PairCount++; + } + else + { + LARGE_MCB_MAPPING_ENTRY NewElement; + PLARGE_MCB_MAPPING_ENTRY Reinserted; + LARGE_INTEGER EndHole = Element->RunStartVbn; + LARGE_INTEGER EndRun; + EndRun.QuadPart = Element->RunStartVbn.QuadPart + Element->SectorCount.QuadPart; + NewElement.RunStartVbn = EndHole; + NewElement.StartingLbn.QuadPart = Element->StartingLbn.QuadPart + + (EndHole.QuadPart - Element->RunStartVbn.QuadPart); + NewElement.SectorCount.QuadPart = EndRun.QuadPart - EndHole.QuadPart; + + RemoveEntryList(&Element->Sequence); + RtlDeleteElementGenericTable(Mcb->Mapping, Element); + Mcb->PairCount--; + + Reinserted = RtlInsertElementGenericTable + (Mcb->Mapping, &NewElement, sizeof(NewElement), NULL); + InsertHeadList(GET_LIST_HEAD(Mcb->Mapping), &Reinserted->Sequence); + Mcb->PairCount++; + } + } +} + +/* + * @implemented + */ +VOID +NTAPI +FsRtlRemoveLargeMcbEntry(IN PLARGE_MCB Mcb, + IN LONGLONG Vbn, + IN LONGLONG SectorCount) +{ + DPRINT("FsRtlRemoveLargeMcbEntry Mcb %x, Vbn %x, SectorCount %x\n", Mcb, (ULONG)Vbn, (ULONG)SectorCount); + + KeAcquireGuardedMutex(Mcb->GuardedMutex); + FsRtlRemoveBaseMcbEntry(&(Mcb->BaseMcb), + Vbn, + SectorCount); + KeReleaseGuardedMutex(Mcb->GuardedMutex); + + DPRINT("Done\n"); +} + +/* + * @implemented + */ +VOID +NTAPI +FsRtlResetBaseMcb(IN PBASE_MCB Mcb) +{ + PLARGE_MCB_MAPPING_ENTRY Element; + + DPRINT("Reset MCB %x\n", Mcb); + while (RtlNumberGenericTableElements(Mcb->Mapping) && + (Element = (PLARGE_MCB_MAPPING_ENTRY)RtlGetElementGenericTable(Mcb->Mapping, 0))) + { + DPRINT("Deleting %x\n", Element); + RtlDeleteElementGenericTable(Mcb->Mapping, Element); + } + + Mcb->PairCount = 0; + Mcb->MaximumPairCount = 0; + DPRINT("Done\n"); +} + +/* + * @implemented + */ +VOID +NTAPI +FsRtlResetLargeMcb(IN PLARGE_MCB Mcb, + IN BOOLEAN SelfSynchronized) +{ + if (!SelfSynchronized) + { + KeAcquireGuardedMutex(Mcb->GuardedMutex); + } + + FsRtlResetBaseMcb(&Mcb->BaseMcb); + + + if (!SelfSynchronized) + { + KeReleaseGuardedMutex(Mcb->GuardedMutex); + } +} + +#define MCB_BUMP_NO_MORE 0 +#define MCB_BUMP_AGAIN 1 + +static ULONG NTAPI McbBump(PBASE_MCB Mcb, PLARGE_MCB_MAPPING_ENTRY FixedPart) +{ + LARGE_MCB_MAPPING_ENTRY Reimagined; + PLARGE_MCB_MAPPING_ENTRY Found = NULL; + + DPRINT("McbBump %x (%x:%x)\n", Mcb, FixedPart->RunStartVbn.LowPart, FixedPart->SectorCount.LowPart); + + Reimagined = *FixedPart; + while ((Found = RtlLookupElementGenericTable(Mcb->Mapping, &Reimagined))) + { + Reimagined = *Found; + Reimagined.RunStartVbn.QuadPart = + FixedPart->RunStartVbn.QuadPart + FixedPart->SectorCount.QuadPart; + DPRINT("Reimagined %x\n", Reimagined.RunStartVbn.LowPart); + } + + DPRINT("Found %x\n", Found); + if (!Found) return MCB_BUMP_NO_MORE; + DPRINT1 + ("Moving %x-%x to %x because %x-%x overlaps\n", + Found->RunStartVbn.LowPart, + Found->RunStartVbn.LowPart + Found->SectorCount.QuadPart, + Reimagined.RunStartVbn.LowPart + Reimagined.SectorCount.LowPart, + Reimagined.RunStartVbn.LowPart, + Reimagined.RunStartVbn.LowPart + Reimagined.SectorCount.LowPart); + Found->RunStartVbn.QuadPart = Reimagined.RunStartVbn.QuadPart + Reimagined.SectorCount.QuadPart; + Found->StartingLbn.QuadPart = Reimagined.StartingLbn.QuadPart + Reimagined.SectorCount.QuadPart; + + DPRINT("Again\n"); + return MCB_BUMP_AGAIN; +} + +/* + * @unimplemented + */ +BOOLEAN +NTAPI +FsRtlSplitBaseMcb(IN PBASE_MCB Mcb, + IN LONGLONG Vbn, + IN LONGLONG Amount) +{ + ULONG Result; + LARGE_MCB_MAPPING_ENTRY Node; + PLARGE_MCB_MAPPING_ENTRY Existing = NULL; + + Node.RunStartVbn.QuadPart = Vbn; + Node.SectorCount.QuadPart = 0; + + Existing = RtlLookupElementGenericTable(Mcb->Mapping, &Node); + + if (Existing) + { + // We're in the middle of a run + LARGE_MCB_MAPPING_ENTRY UpperPart; + LARGE_MCB_MAPPING_ENTRY LowerPart; + PLARGE_MCB_MAPPING_ENTRY InsertedUpper; + + UpperPart.RunStartVbn.QuadPart = Node.RunStartVbn.QuadPart + Amount; + UpperPart.SectorCount.QuadPart = Existing->RunStartVbn.QuadPart + + (Existing->SectorCount.QuadPart - Node.RunStartVbn.QuadPart); + UpperPart.StartingLbn.QuadPart = Existing->StartingLbn.QuadPart + + (Node.RunStartVbn.QuadPart - Existing->RunStartVbn.QuadPart); + LowerPart.RunStartVbn.QuadPart = Existing->RunStartVbn.QuadPart; + LowerPart.SectorCount.QuadPart = Node.RunStartVbn.QuadPart - Existing->RunStartVbn.QuadPart; + LowerPart.StartingLbn.QuadPart = Existing->StartingLbn.QuadPart; + + Node = UpperPart; + + DPRINT("Loop: %x\n", Node.RunStartVbn.LowPart); + while ((Result = McbBump(Mcb, &Node)) == MCB_BUMP_AGAIN) + { + DPRINT("Node: %x\n", Node.RunStartVbn.LowPart); + } + DPRINT("Done\n"); + + if (Result == MCB_BUMP_NO_MORE) + { + Node = *Existing; + RemoveHeadList(&Existing->Sequence); + RtlDeleteElementGenericTable(Mcb->Mapping, Existing); + Mcb->PairCount--; + + // Adjust the element we found. + Existing->SectorCount = LowerPart.SectorCount; + + InsertedUpper = RtlInsertElementGenericTable + (Mcb->Mapping, &UpperPart, sizeof(UpperPart), NULL); + if (!InsertedUpper) + { + // Just make it like it was + Existing->SectorCount = Node.SectorCount; + return FALSE; + } + InsertHeadList(GET_LIST_HEAD(Mcb->Mapping), &InsertedUpper->Sequence); + Mcb->PairCount++; + } + else + { + Node.RunStartVbn.QuadPart = Vbn; + Node.SectorCount.QuadPart = Amount; + while ((Result = McbBump(Mcb, &Node)) == MCB_BUMP_AGAIN); + return Result == MCB_BUMP_NO_MORE; + } + } + + DPRINT("Done\n"); + + return TRUE; +} + +/* + * @implemented + */ +BOOLEAN +NTAPI +FsRtlSplitLargeMcb(IN PLARGE_MCB Mcb, + IN LONGLONG Vbn, + IN LONGLONG Amount) +{ + BOOLEAN Result; + + DPRINT("FsRtlSplitLargeMcb %x, Vbn %x, Amount %x\n", Mcb, (ULONG)Vbn, (ULONG)Amount); + + KeAcquireGuardedMutex(Mcb->GuardedMutex); + Result = FsRtlSplitBaseMcb(&(Mcb->BaseMcb), + Vbn, + Amount); + KeReleaseGuardedMutex(Mcb->GuardedMutex); + + DPRINT("Done %d\n", Result); + + return Result; +} + +/* + * @unimplemented + */ +VOID +NTAPI +FsRtlTruncateBaseMcb(IN PBASE_MCB Mcb, + IN LONGLONG Vbn) +{ + DPRINT("FsRtlTruncateBaseMcb(%x,%x)\n", Mcb, (ULONG)Vbn); + if (!Vbn) + { + DPRINT("Resetting\n"); + FsRtlResetBaseMcb(Mcb); + } + else + { + LARGE_MCB_MAPPING_ENTRY Truncate; + PLARGE_MCB_MAPPING_ENTRY Found; + Truncate.RunStartVbn.QuadPart = Vbn; + Truncate.SectorCount.QuadPart = (1ull<<62) - Truncate.RunStartVbn.QuadPart; + while ((Found = RtlLookupElementGenericTable(Mcb->Mapping, &Truncate))) + { + DPRINT("Deleting %x\n", Found); + RemoveEntryList(&Found->Sequence); + RtlDeleteElementGenericTable(Mcb->Mapping, Found); + Mcb->PairCount--; + } + } + DPRINT("Done\n"); +} + +/* + * @implemented + */ +VOID +NTAPI +FsRtlTruncateLargeMcb(IN PLARGE_MCB Mcb, + IN LONGLONG Vbn) +{ + DPRINT("FsRtlTruncateLargeMcb %x Vbn %x\n", Mcb, (ULONG)Vbn); + KeAcquireGuardedMutex(Mcb->GuardedMutex); + FsRtlTruncateBaseMcb(&(Mcb->BaseMcb), + Vbn); + KeReleaseGuardedMutex(Mcb->GuardedMutex); + DPRINT("Done\n"); +} + +/* + * @implemented + */ +VOID +NTAPI +FsRtlUninitializeBaseMcb(IN PBASE_MCB Mcb) +{ + DPRINT("FsRtlUninitializeBaseMcb(%x)\n", Mcb); + FsRtlResetBaseMcb(Mcb); + + DPRINT("Mcb->Mapping %x\n", Mcb->Mapping); + if (Mcb->PoolType == PagedPool) + { + DPRINT("Deallocate to lookaside list\n"); + ExFreeToPagedLookasideList(&FsRtlFirstMappingLookasideList, + Mcb->Mapping); + } + else + { + DPRINT("Deallocate\n"); + ExFreePoolWithTag(Mcb->Mapping, 'FSBC'); + } + Mcb->Mapping = NULL; + DPRINT("Done\n"); +} + +/* + * @implemented + */ +VOID +NTAPI +FsRtlUninitializeLargeMcb(IN PLARGE_MCB Mcb) +{ + if (Mcb->GuardedMutex) + { + ExFreeToNPagedLookasideList(&FsRtlFastMutexLookasideList, + Mcb->GuardedMutex); + Mcb->GuardedMutex = NULL; + FsRtlUninitializeBaseMcb(&(Mcb->BaseMcb)); + } +} + +// MCB /* * @implemented @@ -44,24 +965,6 @@ (LONGLONG)Vbn, (LONGLONG)Lbn, (LONGLONG)SectorCount); -} - -/* - * @unimplemented - */ -BOOLEAN -NTAPI -FsRtlGetNextLargeMcbEntry(IN PLARGE_MCB Mcb, - IN ULONG RunIndex, - OUT PLONGLONG Vbn, - OUT PLONGLONG Lbn, - OUT PLONGLONG SectorCount) -{ - KeBugCheck(FILE_SYSTEM); - *Vbn = 0; - *Lbn = 0; - *SectorCount= 0; - return FALSE; } /* @@ -98,17 +1001,6 @@ } /* - * @unimplemented - */ -VOID -NTAPI -FsRtlInitializeLargeMcb(IN PLARGE_MCB Mcb, - IN POOL_TYPE PoolType) -{ - KeBugCheck(FILE_SYSTEM); -} - -/* * @implemented */ VOID @@ -119,55 +1011,6 @@ /* Call the newer function */ FsRtlInitializeLargeMcb(&Mcb->DummyFieldThatSizesThisStructureCorrectly, PoolType); -} - -/* - * @unimplemented - */ -BOOLEAN -NTAPI -FsRtlLookupLargeMcbEntry(IN PLARGE_MCB Mcb, - IN LONGLONG Vbn, - OUT PLONGLONG Lbn OPTIONAL, - OUT PLONGLONG SectorCountFromLbn OPTIONAL, - OUT PLONGLONG StartingLbn OPTIONAL, - OUT PLONGLONG SectorCountFromStartingLbn OPTIONAL, - OUT PULONG Index OPTIONAL) -{ - KeBugCheck(FILE_SYSTEM); - *Lbn = 0; - *SectorCountFromLbn = 0; - return FALSE; -} - -/* - * @unimplemented - */ -BOOLEAN -NTAPI -FsRtlLookupLastLargeMcbEntryAndIndex(IN PLARGE_MCB OpaqueMcb, - OUT PLONGLONG LargeVbn, - OUT PLONGLONG LargeLbn, - OUT PULONG Index) -{ - KeBugCheck(FILE_SYSTEM); - *LargeVbn = 0; - *LargeLbn = 0; - *Index = 0; - return FALSE; -} - -/* - * @unimplemented - */ -BOOLEAN -NTAPI -FsRtlLookupLastLargeMcbEntry(IN PLARGE_MCB Mcb, - OUT PLONGLONG Vbn, - OUT PLONGLONG Lbn) -{ - KeBugCheck(FILE_SYSTEM); - return(FALSE); } /* @@ -235,41 +1078,11 @@ */ ULONG NTAPI -FsRtlNumberOfRunsInLargeMcb(IN PLARGE_MCB Mcb) -{ - ULONG NumberOfRuns; - - /* Read the number of runs while holding the MCB lock */ - KeAcquireGuardedMutex(Mcb->GuardedMutex); - NumberOfRuns = Mcb->BaseMcb.PairCount; - KeReleaseGuardedMutex(Mcb->GuardedMutex); - - /* Return the count */ - return NumberOfRuns; -} - -/* - * @implemented - */ -ULONG -NTAPI -FsRtlNumberOfRunsInMcb (IN PMCB Mcb) +FsRtlNumberOfRunsInMcb(IN PMCB Mcb) { /* Call the newer function */ return FsRtlNumberOfRunsInLargeMcb( &Mcb->DummyFieldThatSizesThisStructureCorrectly); -} - -/* - * @unimplemented - */ -VOID -NTAPI -FsRtlRemoveLargeMcbEntry(IN PLARGE_MCB Mcb, - IN LONGLONG Vbn, - IN LONGLONG SectorCount) -{ - KeBugCheck(FILE_SYSTEM); } /* @@ -288,47 +1101,12 @@ } /* - * @unimplemented - */ -VOID -NTAPI -FsRtlResetLargeMcb(IN PLARGE_MCB Mcb, - IN BOOLEAN SelfSynchronized) -{ - KeBugCheck(FILE_SYSTEM); -} - -/* - * @unimplemented - */ -BOOLEAN -NTAPI -FsRtlSplitLargeMcb(IN PLARGE_MCB Mcb, - IN LONGLONG Vbn, - IN LONGLONG Amount) -{ - KeBugCheck(FILE_SYSTEM); - return FALSE; -} - -/* - * @unimplemented - */ -VOID -NTAPI -FsRtlTruncateLargeMcb(IN PLARGE_MCB Mcb, - IN LONGLONG Vbn) -{ - KeBugCheck(FILE_SYSTEM); -} - -/* - * @implemented - */ -VOID -NTAPI -FsRtlTruncateMcb (IN PMCB Mcb, - IN VBN Vbn) + * @implemented + */ +VOID +NTAPI +FsRtlTruncateMcb(IN PMCB Mcb, + IN VBN Vbn) { /* Call the newer function */ FsRtlTruncateLargeMcb(&Mcb->DummyFieldThatSizesThisStructureCorrectly, @@ -336,16 +1114,6 @@ } /* - * @unimplemented - */ -VOID -NTAPI -FsRtlUninitializeLargeMcb(IN PLARGE_MCB Mcb) -{ - KeBugCheck(FILE_SYSTEM); -} - -/* * @implemented */ VOID