Author: arty
Date: Wed Feb 29 09:18:01 2012
New Revision: 55914

URL: http://svn.reactos.org/svn/reactos?rev=55914&view=rev
Log:
[FSRTL]
Import code from Pierre Schweitzer's fsrtl branch.
- Large MCB and MCB
- Change notification

Added:
    trunk/reactos/ntoskrnl/fsrtl/mcb.c   (with props)
Modified:
    trunk/reactos/ntoskrnl/CMakeLists.txt
    trunk/reactos/ntoskrnl/fsrtl/fsrtlpc.c
    trunk/reactos/ntoskrnl/fsrtl/largemcb.c
    trunk/reactos/ntoskrnl/fsrtl/notify.c
    trunk/reactos/ntoskrnl/include/internal/fsrtl.h

Modified: trunk/reactos/ntoskrnl/CMakeLists.txt
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/CMakeLists.txt?rev=55914&r1=55913&r2=55914&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/CMakeLists.txt [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/CMakeLists.txt [iso-8859-1] Wed Feb 29 09:18:01 2012
@@ -119,6 +119,7 @@
     fsrtl/fsfilter.c
     fsrtl/fsrtlpc.c
     fsrtl/largemcb.c
+    fsrtl/mcb.c
     fsrtl/name.c
     fsrtl/notify.c
     fsrtl/oplock.c

Modified: trunk/reactos/ntoskrnl/fsrtl/fsrtlpc.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/fsrtl/fsrtlpc.c?rev=55914&r1=55913&r2=55914&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/fsrtl/fsrtlpc.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/fsrtl/fsrtlpc.c [iso-8859-1] Wed Feb 29 09:18:01 2012
@@ -169,6 +169,8 @@
                                    IFS_POOL_TAG,
                                    0);
 
+    FsRtlInitializeLargeMcbs();
+
     /* Allocate the Resource Buffer */
     FsRtlPagingIoResources = FsRtlAllocatePoolWithTag(NonPagedPool,
                                                       FSRTL_MAX_RESOURCES *

Modified: trunk/reactos/ntoskrnl/fsrtl/largemcb.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/fsrtl/largemcb.c?rev=55914&r1=55913&r2=55914&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/fsrtl/largemcb.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/fsrtl/largemcb.c [iso-8859-1] Wed Feb 29 09:18:01 
2012
@@ -2,20 +2,138 @@
  * 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 ([email protected])
+ *                  Pierre Schweitzer ([email protected]) 
+ *                  Art Yerkes ([email protected])
  */
 
 /* INCLUDES ******************************************************************/
 
 #include <ntoskrnl.h>
-#define NDEBUG
+//#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 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
+(RTL_GENERIC_TABLE Table, PVOID PtrA, PVOID PtrB)
+{
+       PLARGE_MCB_MAPPING_ENTRY A = PtrA, B = PtrB;
+       return 
+               (A->RunStartVbn.QuadPart + A->SectorCount.QuadPart <
+                B->RunStartVbn.QuadPart) ? GenericLessThan :
+               (A->RunStartVbn.QuadPart > 
+                B->RunStartVbn.QuadPart + B->SectorCount.QuadPart) ? 
+               GenericGreaterThan : GenericEqual;
+}
+
 /* 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;
+
+       Node.RunStartVbn.QuadPart = Vbn;
+       Node.StartingLbn.QuadPart = Lbn;
+       Node.SectorCount.QuadPart = SectorCount;
+
+       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);
+       return !!Existing;
+}
+
+/*
+ * @implemented
  */
 BOOLEAN
 NTAPI
@@ -24,30 +142,57 @@
                       IN LONGLONG Lbn,
                       IN LONGLONG SectorCount)
 {
-    KeBugCheck(FILE_SYSTEM);
-    return FALSE;
-}
-
-/*
- * @implemented
- */
-BOOLEAN
-NTAPI
-FsRtlAddMcbEntry(IN PMCB Mcb,
-                 IN VBN Vbn,
-                 IN LBN Lbn,
-                 IN ULONG SectorCount)
-{
-    /* Call the newer function */
-    return FsRtlAddLargeMcbEntry(&Mcb->
-                                 DummyFieldThatSizesThisStructureCorrectly,
-                                 (LONGLONG)Vbn,
-                                 (LONGLONG)Lbn,
-                                 (LONGLONG)SectorCount);
+    BOOLEAN Result;
+
+       DPRINT("Mcb %x Vbn %x Lbn %x SectorCount %x\n", Mcb, Vbn, Lbn, 
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
@@ -57,55 +202,78 @@
                           OUT PLONGLONG Lbn,
                           OUT PLONGLONG SectorCount)
 {
-    KeBugCheck(FILE_SYSTEM);
-    *Vbn = 0;
-    *Lbn = 0;
-    *SectorCount= 0;
-    return FALSE;
-}
-
-/*
- * @implemented
- */
-BOOLEAN
-NTAPI
-FsRtlGetNextMcbEntry(IN PMCB Mcb,
-                     IN ULONG RunIndex,
-                     OUT PVBN Vbn,
-                     OUT PLBN Lbn,
-                     OUT PULONG SectorCount)
-{
-    BOOLEAN Return = FALSE;
-    LONGLONG llVbn;
-    LONGLONG llLbn;
-    LONGLONG llSectorCount;
-
-    /* Call the Large version */
-    Return = FsRtlGetNextLargeMcbEntry(
-        &Mcb->DummyFieldThatSizesThisStructureCorrectly,
-        RunIndex,
-        &llVbn,
-        &llLbn,
-        &llSectorCount);
-
-    /* Return the lower 32 bits */
-    *Vbn = (ULONG)llVbn;
-    *Lbn = (ULONG)llLbn;
-    *SectorCount = (ULONG)llSectorCount;
-
-    /* And return the original value */
-    return Return;
-}
-
-/*
- * @unimplemented
+    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);
+    }
+    else
+    {
+        Mcb->Mapping = ExAllocatePoolWithTag(PoolType | 
POOL_RAISE_IF_ALLOCATION_FAILURE,
+                                                                               
         sizeof(RTL_GENERIC_TABLE) + sizeof(LIST_ENTRY),
+                                             'FSBC');
+    }
+
+    Mcb->PoolType = PoolType;
+    Mcb->MaximumPairCount = MAXIMUM_PAIR_COUNT;
+       RtlInitializeGenericTable
+               (Mcb->Mapping,
+                (PRTL_GENERIC_COMPARE_ROUTINE)McbMappingCompare,
+                McbMappingAllocate,
+                McbMappingFree,
+                Mcb);
+       InitializeListHead(GET_LIST_HEAD(Mcb->Mapping));
+}
+
+/*
+ * @implemented
  */
 VOID
 NTAPI
 FsRtlInitializeLargeMcb(IN PLARGE_MCB Mcb,
                         IN POOL_TYPE PoolType)
 {
-    KeBugCheck(FILE_SYSTEM);
+    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;
 }
 
 /*
@@ -113,16 +281,80 @@
  */
 VOID
 NTAPI
-FsRtlInitializeMcb(IN PMCB Mcb,
-                   IN POOL_TYPE PoolType)
-{
-    /* Call the newer function */
-    FsRtlInitializeLargeMcb(&Mcb->DummyFieldThatSizesThisStructureCorrectly,
-                            PoolType);
+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
@@ -134,14 +366,61 @@
                          OUT PLONGLONG SectorCountFromStartingLbn OPTIONAL,
                          OUT PULONG Index OPTIONAL)
 {
-    KeBugCheck(FILE_SYSTEM);
-    *Lbn = 0;
-    *SectorCountFromLbn = 0;
-    return FALSE;
+    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\n", Result);
+
+    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
@@ -150,15 +429,49 @@
                                      OUT PLONGLONG LargeLbn,
                                      OUT PULONG Index)
 {
-    KeBugCheck(FILE_SYSTEM);
-    *LargeVbn = 0;
-    *LargeLbn = 0;
-    *Index = 0;
-    return FALSE;
+    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
@@ -166,68 +479,19 @@
                              OUT PLONGLONG Vbn,
                              OUT PLONGLONG Lbn)
 {
-    KeBugCheck(FILE_SYSTEM);
-    return(FALSE);
-}
-
-/*
- * @implemented
- */
-BOOLEAN
-NTAPI
-FsRtlLookupLastMcbEntry(IN PMCB Mcb,
-                        OUT PVBN Vbn,
-                        OUT PLBN Lbn)
-{
-    BOOLEAN Return = FALSE;
-    LONGLONG llVbn = 0;
-    LONGLONG llLbn = 0;
-
-    /* Call the Large version */
-    Return = FsRtlLookupLastLargeMcbEntry(
-        &Mcb->DummyFieldThatSizesThisStructureCorrectly,
-        &llVbn,
-        &llLbn);
-
-    /* Return the lower 32-bits */
-    *Vbn = (ULONG)llVbn;
-    *Lbn = (ULONG)llLbn;
-
-    /* And return the original value */
-    return Return;
-}
-
-/*
- * @implemented
- */
-BOOLEAN
-NTAPI
-FsRtlLookupMcbEntry(IN PMCB Mcb,
-                    IN VBN Vbn,
-                    OUT PLBN Lbn,
-                    OUT PULONG SectorCount OPTIONAL,
-                    OUT PULONG Index)
-{
-    BOOLEAN Return = FALSE;
-    LONGLONG llLbn;
-    LONGLONG llSectorCount;
-
-    /* Call the Large version */
-    Return = FsRtlLookupLargeMcbEntry(&Mcb->
-                                      
DummyFieldThatSizesThisStructureCorrectly,
-                                      (LONGLONG)Vbn,
-                                      &llLbn,
-                                      &llSectorCount,
-                                      NULL,
-                                      NULL,
-                                      Index);
-
-    /* Return the lower 32-bits */
-    *Lbn = (ULONG)llLbn;
-    if (SectorCount) *SectorCount = (ULONG)llSectorCount;
-
-    /* And return the original value */
-    return Return;
+    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;
 }
 
 /*
@@ -235,33 +499,131 @@
  */
 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;
 }
 
 /*
- * @implemented
- */
-ULONG
-NTAPI
-FsRtlNumberOfRunsInMcb (IN PMCB Mcb)
-{
-    /* Call the newer function */
-    return FsRtlNumberOfRunsInLargeMcb(
-        &Mcb->DummyFieldThatSizesThisStructureCorrectly);
-}
-
-/*
  * @unimplemented
+ */
+BOOLEAN
+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++;                       
+               }
+       }
+
+       return TRUE;
+}
+
+/*
+ * @implemented
  */
 VOID
 NTAPI
@@ -269,7 +631,15 @@
                          IN LONGLONG Vbn,
                          IN LONGLONG SectorCount)
 {
-    KeBugCheck(FILE_SYSTEM);
+       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");
 }
 
 /*
@@ -277,29 +647,157 @@
  */
 VOID
 NTAPI
-FsRtlRemoveMcbEntry(IN PMCB Mcb,
-                    IN VBN Vbn,
-                    IN ULONG SectorCount)
-{
-    /* Call the large function */
-    FsRtlRemoveLargeMcbEntry(&Mcb->DummyFieldThatSizesThisStructureCorrectly,
-                             (LONGLONG)Vbn,
-                             (LONGLONG)SectorCount);
-}
-
-/*
- * @unimplemented
+FsRtlResetBaseMcb(IN PBASE_MCB Mcb)
+{
+       PLARGE_MCB_MAPPING_ENTRY Element;
+
+       while (RtlNumberGenericTableElements(Mcb->Mapping) &&
+                  (Element = 
(PLARGE_MCB_MAPPING_ENTRY)RtlGetElementGenericTable(Mcb->Mapping, 0)))
+       {
+               RtlDeleteElementGenericTable(Mcb->Mapping, Element);
+       }
+
+       Mcb->PairCount = 0;
+       Mcb->MaximumPairCount = 0;
+}
+
+/*
+ * @implemented
  */
 VOID
 NTAPI
 FsRtlResetLargeMcb(IN PLARGE_MCB Mcb,
                    IN BOOLEAN SelfSynchronized)
 {
-    KeBugCheck(FILE_SYSTEM);
+    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
@@ -307,19 +805,62 @@
                    IN LONGLONG Vbn,
                    IN LONGLONG Amount)
 {
-    KeBugCheck(FILE_SYSTEM);
-    return FALSE;
+    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)
+{
+       if (!Vbn)
+       {
+               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)))
+               {
+                       RemoveEntryList(&Found->Sequence);
+                       RtlDeleteElementGenericTable(Mcb->Mapping, Found);
+                       Mcb->PairCount--;
+               }
+       }
+}
+
+/*
+ * @implemented
  */
 VOID
 NTAPI
 FsRtlTruncateLargeMcb(IN PLARGE_MCB Mcb,
                       IN LONGLONG Vbn)
 {
-    KeBugCheck(FILE_SYSTEM);
+       DPRINT("FsRtlTruncateLargeMcb %x Vbn %x\n", Mcb, (ULONG)Vbn);
+    KeAcquireGuardedMutex(Mcb->GuardedMutex);
+    FsRtlTruncateBaseMcb(&(Mcb->BaseMcb),
+                         Vbn);
+    KeReleaseGuardedMutex(Mcb->GuardedMutex);
+       DPRINT("Done\n");
 }
 
 /*
@@ -327,32 +868,33 @@
  */
 VOID
 NTAPI
-FsRtlTruncateMcb (IN PMCB Mcb,
-                  IN VBN  Vbn)
-{
-    /* Call the newer function */
-    FsRtlTruncateLargeMcb(&Mcb->DummyFieldThatSizesThisStructureCorrectly,
-                          (LONGLONG)Vbn);
-}
-
-/*
- * @unimplemented
+FsRtlUninitializeBaseMcb(IN PBASE_MCB Mcb)
+{
+       FsRtlResetBaseMcb(Mcb);
+
+    if ((Mcb->PoolType == PagedPool) && (Mcb->MaximumPairCount == 
MAXIMUM_PAIR_COUNT))
+    {
+        ExFreeToPagedLookasideList(&FsRtlFirstMappingLookasideList,
+                                   Mcb->Mapping);
+    }
+    else
+    {
+        ExFreePoolWithTag(Mcb->Mapping, 'FSBC');
+    }
+}
+
+/*
+ * @implemented
  */
 VOID
 NTAPI
 FsRtlUninitializeLargeMcb(IN PLARGE_MCB Mcb)
 {
-    KeBugCheck(FILE_SYSTEM);
-}
-
-/*
- * @implemented
- */
-VOID
-NTAPI
-FsRtlUninitializeMcb(IN PMCB Mcb)
-{
-    /* Call the newer function */
-    FsRtlUninitializeLargeMcb(&Mcb->DummyFieldThatSizesThisStructureCorrectly);
-}
-
+    if (Mcb->GuardedMutex)
+    {
+        ExFreeToNPagedLookasideList(&FsRtlFastMutexLookasideList,
+                                    Mcb->GuardedMutex);
+        FsRtlUninitializeBaseMcb(&(Mcb->BaseMcb));
+    }
+}
+

Added: trunk/reactos/ntoskrnl/fsrtl/mcb.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/fsrtl/mcb.c?rev=55914&view=auto
==============================================================================
--- trunk/reactos/ntoskrnl/fsrtl/mcb.c (added)
+++ trunk/reactos/ntoskrnl/fsrtl/mcb.c [iso-8859-1] Wed Feb 29 09:18:01 2012
@@ -1,0 +1,190 @@
+/*
+ * PROJECT:         ReactOS Kernel
+ * LICENSE:         GPL - See COPYING in the top level directory
+ * FILE:            ntoskrnl/fsrtl/mcb.c
+ * PURPOSE:         Mapped Control Block (MCB) support for File System Drivers
+ * PROGRAMMERS:     Alex Ionescu ([email protected])
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include <ntoskrnl.h>
+#define NDEBUG
+#include <debug.h>
+
+/* PUBLIC FUNCTIONS **********************************************************/
+
+/*
+ * @implemented
+ */
+BOOLEAN
+NTAPI
+FsRtlAddMcbEntry(IN PMCB Mcb,
+                 IN VBN Vbn,
+                 IN LBN Lbn,
+                 IN ULONG SectorCount)
+{
+    /* Call the newer function */
+    return FsRtlAddLargeMcbEntry(&Mcb->
+                                 DummyFieldThatSizesThisStructureCorrectly,
+                                 (LONGLONG)Vbn,
+                                 (LONGLONG)Lbn,
+                                 (LONGLONG)SectorCount);
+}
+
+/*
+ * @implemented
+ */
+BOOLEAN
+NTAPI
+FsRtlGetNextMcbEntry(IN PMCB Mcb,
+                     IN ULONG RunIndex,
+                     OUT PVBN Vbn,
+                     OUT PLBN Lbn,
+                     OUT PULONG SectorCount)
+{
+    BOOLEAN Return = FALSE;
+    LONGLONG llVbn;
+    LONGLONG llLbn;
+    LONGLONG llSectorCount;
+
+    /* Call the Large version */
+    Return = FsRtlGetNextLargeMcbEntry(
+        &Mcb->DummyFieldThatSizesThisStructureCorrectly,
+        RunIndex,
+        &llVbn,
+        &llLbn,
+        &llSectorCount);
+
+    /* Return the lower 32 bits */
+    *Vbn = (ULONG)llVbn;
+    *Lbn = (ULONG)llLbn;
+    *SectorCount = (ULONG)llSectorCount;
+
+    /* And return the original value */
+    return Return;
+}
+
+/*
+ * @implemented
+ */
+VOID
+NTAPI
+FsRtlInitializeMcb(IN PMCB Mcb,
+                   IN POOL_TYPE PoolType)
+{
+    /* Call the newer function */
+    FsRtlInitializeLargeMcb(&Mcb->DummyFieldThatSizesThisStructureCorrectly,
+                            PoolType);
+}
+
+/*
+ * @implemented
+ */
+BOOLEAN
+NTAPI
+FsRtlLookupLastMcbEntry(IN PMCB Mcb,
+                        OUT PVBN Vbn,
+                        OUT PLBN Lbn)
+{
+    BOOLEAN Return = FALSE;
+    LONGLONG llVbn = 0;
+    LONGLONG llLbn = 0;
+
+    /* Call the Large version */
+    Return = FsRtlLookupLastLargeMcbEntry(
+        &Mcb->DummyFieldThatSizesThisStructureCorrectly,
+        &llVbn,
+        &llLbn);
+
+    /* Return the lower 32-bits */
+    *Vbn = (ULONG)llVbn;
+    *Lbn = (ULONG)llLbn;
+
+    /* And return the original value */
+    return Return;
+}
+
+/*
+ * @implemented
+ */
+BOOLEAN
+NTAPI
+FsRtlLookupMcbEntry(IN PMCB Mcb,
+                    IN VBN Vbn,
+                    OUT PLBN Lbn,
+                    OUT PULONG SectorCount OPTIONAL,
+                    OUT PULONG Index)
+{
+    BOOLEAN Return = FALSE;
+    LONGLONG llLbn;
+    LONGLONG llSectorCount;
+
+    /* Call the Large version */
+    Return = FsRtlLookupLargeMcbEntry(&Mcb->
+                                      
DummyFieldThatSizesThisStructureCorrectly,
+                                      (LONGLONG)Vbn,
+                                      &llLbn,
+                                      &llSectorCount,
+                                      NULL,
+                                      NULL,
+                                      Index);
+
+    /* Return the lower 32-bits */
+    *Lbn = (ULONG)llLbn;
+    if (SectorCount) *SectorCount = (ULONG)llSectorCount;
+
+    /* And return the original value */
+    return Return;
+}
+
+/*
+ * @implemented
+ */
+ULONG
+NTAPI
+FsRtlNumberOfRunsInMcb(IN PMCB Mcb)
+{
+    /* Call the newer function */
+    return FsRtlNumberOfRunsInLargeMcb(
+        &Mcb->DummyFieldThatSizesThisStructureCorrectly);
+}
+
+/*
+ * @implemented
+ */
+VOID
+NTAPI
+FsRtlRemoveMcbEntry(IN PMCB Mcb,
+                    IN VBN Vbn,
+                    IN ULONG SectorCount)
+{
+    /* Call the large function */
+    FsRtlRemoveLargeMcbEntry(&Mcb->DummyFieldThatSizesThisStructureCorrectly,
+                             (LONGLONG)Vbn,
+                             (LONGLONG)SectorCount);
+}
+
+/*
+ * @implemented
+ */
+VOID
+NTAPI
+FsRtlTruncateMcb(IN PMCB Mcb,
+                 IN VBN  Vbn)
+{
+    /* Call the newer function */
+    FsRtlTruncateLargeMcb(&Mcb->DummyFieldThatSizesThisStructureCorrectly,
+                          (LONGLONG)Vbn);
+}
+
+/*
+ * @implemented
+ */
+VOID
+NTAPI
+FsRtlUninitializeMcb(IN PMCB Mcb)
+{
+    /* Call the newer function */
+    FsRtlUninitializeLargeMcb(&Mcb->DummyFieldThatSizesThisStructureCorrectly);
+}

Propchange: trunk/reactos/ntoskrnl/fsrtl/mcb.c
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: trunk/reactos/ntoskrnl/fsrtl/notify.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/fsrtl/notify.c?rev=55914&r1=55913&r2=55914&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/fsrtl/notify.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/fsrtl/notify.c [iso-8859-1] Wed Feb 29 09:18:01 2012
@@ -12,6 +12,68 @@
 #define NDEBUG
 #include <debug.h>
 
+/* PRIVATE FUNCTIONS *********************************************************/
+
+PNOTIFY_CHANGE
+FsRtlIsNotifyOnList(IN PLIST_ENTRY NotifyList,
+                    IN PVOID FsContext)
+{
+    PLIST_ENTRY NextEntry;
+    PNOTIFY_CHANGE NotifyChange;
+
+    if (!IsListEmpty(NotifyList))
+    {
+        /* Browse the notifications list to find the matching entry */
+        for (NextEntry = NotifyList->Flink;
+             NextEntry != NotifyList;
+             NextEntry = NextEntry->Flink)
+        {
+            NotifyChange = CONTAINING_RECORD(NextEntry, NOTIFY_CHANGE, 
NotifyList);
+            /* If the current record matches with the given context, it's the 
good one */
+            if (NotifyChange->FsContext == FsContext)
+            {
+                return NotifyChange;
+            }
+        }
+    }
+    return NULL;
+}
+
+VOID
+FORCEINLINE
+FsRtlNotifyAcquireFastMutex(IN PREAL_NOTIFY_SYNC RealNotifySync)
+{
+    ULONG_PTR CurrentThread = (ULONG_PTR)KeGetCurrentThread();
+
+    /* Only acquire fast mutex if it's not already acquired by the current 
thread */
+    if (RealNotifySync->OwningThread != CurrentThread)
+    {
+        ExAcquireFastMutexUnsafe(&(RealNotifySync->FastMutex));
+        RealNotifySync->OwningThread = CurrentThread;
+    }
+    /* Whatever the case, keep trace of the attempt to acquire fast mutex */
+    RealNotifySync->OwnerCount++;
+}
+
+VOID
+FsRtlNotifyCompleteIrpList(IN PNOTIFY_CHANGE NotifyChange,
+                           IN NTSTATUS Status)
+{
+}
+
+VOID
+FORCEINLINE
+FsRtlNotifyReleaseFastMutex(IN PREAL_NOTIFY_SYNC RealNotifySync)
+{
+    RealNotifySync->OwnerCount--;
+    /* Release the fast mutex only if no other instance needs it */
+    if (!RealNotifySync->OwnerCount)
+    {
+        ExReleaseFastMutexUnsafe(&(RealNotifySync->FastMutex));
+        RealNotifySync->OwningThread = (ULONG_PTR)0;
+    }
+}
+
 /* PUBLIC FUNCTIONS **********************************************************/
 
 /*++
@@ -44,8 +106,7 @@
  *
  * @return None
  *
- * @remarks This function only redirects to FsRtlNotifyFullChangeDirectory.
- * So, it's better to call the entire function.  
+ * @remarks This function only redirects to FsRtlNotifyFilterChangeDirectory.
  *
  *--*/
 VOID
@@ -58,32 +119,33 @@
                            IN ULONG CompletionFilter,
                            IN PIRP NotifyIrp)
 {
-    FsRtlNotifyFullChangeDirectory(NotifySync,
-                                   NotifyList,
-                                   FsContext,
-                                   FullDirectoryName,
-                                   WatchTree,
-                                   TRUE,
-                                   CompletionFilter,
-                                   NotifyIrp,
-                                   NULL,
-                                   NULL);
+    FsRtlNotifyFilterChangeDirectory(NotifySync,
+                                     NotifyList,
+                                     FsContext,
+                                     FullDirectoryName,
+                                     WatchTree,
+                                     TRUE,
+                                     CompletionFilter,
+                                     NotifyIrp,
+                                     NULL,
+                                     NULL,
+                                     NULL);
 }
 
 /*++
  * @name FsRtlNotifyCleanup
- * @unimplemented
+ * @implemented
  *
  * Called by FSD when all handles to FileObject (identified by FsContext) are 
closed
  *
  * @param NotifySync
- *        FILLME
- *
- * @param NotifyList
- *        FILLME
+ *        Synchronization object pointer
+ *
+ * @param NotifyList
+ *        Notify list pointer (to head) 
  *
  * @param FsContext
- *        FILLME
+ *        Used to identify the notify structure
  *
  * @return None
  *
@@ -96,7 +158,67 @@
                    IN PLIST_ENTRY NotifyList,
                    IN PVOID FsContext)
 {
-    KeBugCheck(FILE_SYSTEM);
+    PNOTIFY_CHANGE NotifyChange;
+    PREAL_NOTIFY_SYNC RealNotifySync;
+    PSECURITY_SUBJECT_CONTEXT SubjectContext = NULL;
+
+    /* Get real structure hidden behind the opaque pointer */
+    RealNotifySync = (PREAL_NOTIFY_SYNC)NotifySync;
+
+    /* Acquire the fast mutex */
+    FsRtlNotifyAcquireFastMutex(RealNotifySync);
+
+    _SEH2_TRY
+    {
+        /* Find if there's a matching notification with the FsContext */
+        NotifyChange = FsRtlIsNotifyOnList(NotifyList, FsContext);
+        if (NotifyChange)
+        {
+            /* Mark it as to know that cleanup is in process */
+            NotifyChange->Flags |= CLEANUP_IN_PROCESS;
+
+            /* If there are pending IRPs, complete them using the 
STATUS_NOTIFY_CLEANUP status */
+            if (!IsListEmpty(NotifyChange->NotifyIrps))
+            {
+                FsRtlNotifyCompleteIrpList(NotifyChange, 
STATUS_NOTIFY_CLEANUP);
+            }
+            /* Remove from the list */
+            RemoveEntryList(NotifyChange->NotifyList);
+
+            /* Downcrease reference number and if 0 is reached, it's time to 
do complete cleanup */
+            if (!InterlockedDecrement((PLONG)&(NotifyChange->ReferenceCount)))
+            {
+                /* In case there was an allocated buffer, free it */
+                if (NotifyChange->AllocatedBuffer)
+                {
+                    PsReturnProcessPagedPoolQuota(NotifyChange->OwningProcess, 
NotifyChange->ThisBufferLength);
+                    ExFreePool(NotifyChange->AllocatedBuffer);
+                }
+
+                /* In case there the string was set, get the captured subject 
security context */
+                if (NotifyChange->FullDirectoryName)
+                {
+                    SubjectContext = NotifyChange->SubjectContext;
+                }
+
+                /* Finally, free the notification, as it's not needed anymore 
*/
+                ExFreePool(NotifyChange);
+            }
+        }
+    }
+    _SEH2_FINALLY
+    {
+      /* Release fast mutex */
+      FsRtlNotifyReleaseFastMutex(RealNotifySync);
+
+      /* If the subject security context was captured, release and free it */
+      if (SubjectContext)
+      {
+          SeReleaseSubjectContext(SubjectContext);
+          ExFreePool(SubjectContext);
+      }
+    }
+    _SEH2_END;
 }
 
 /*++
@@ -219,43 +341,46 @@
 
 /*++
  * @name FsRtlNotifyFullChangeDirectory
- * @unimplemented
- *
- * FILLME
- *
- * @param NotifySync
- *        FILLME
- *
- * @param NotifyList
- *        FILLME
+ * @implemented
+ *
+ * Lets FSD know if changes occures in the specified directory. 
+ *
+ * @param NotifySync
+ *        Synchronization object pointer
+ *
+ * @param NotifyList
+ *        Notify list pointer (to head) 
  *
  * @param FsContext
- *        FILLME
+ *        Used to identify the notify structure
  *
  * @param FullDirectoryName
- *        FILLME
+ *        String (A or W) containing the full directory name 
  *
  * @param WatchTree
- *        FILLME
+ *        True to notify changes in subdirectories too
  *
  * @param IgnoreBuffer
- *        FILLME
+ *        True to reenumerate directory. It's ignored it NotifyIrp is null
  *
  * @param CompletionFilter
- *        FILLME
- *
- * @param Irp
- *        FILLME
+ *        Used to define types of changes to notify
+ *
+ * @param NotifyIrp
+ *        IRP pointer to complete notify operation. It can be null
  *
  * @param TraverseCallback
- *        FILLME
+ *        Pointer to a callback function. It's called each time a change is
+ *        done in a subdirectory of the main directory. It's ignored it 
NotifyIrp
+ *        is null
  *
  * @param SubjectContext
- *        FILLME
- *
- * @return None
- *
- * @remarks None
+ *        Pointer to pass to SubjectContext member of TraverseCallback.
+ *        It's freed after use. It's ignored it NotifyIrp is null
+ *
+ * @return None
+ *
+ * @remarks This function only redirects to FsRtlNotifyFilterChangeDirectory.
  *
  *--*/
 VOID
@@ -267,49 +392,60 @@
                                IN BOOLEAN WatchTree,
                                IN BOOLEAN IgnoreBuffer,
                                IN ULONG CompletionFilter,
-                               IN PIRP Irp,
+                               IN PIRP NotifyIrp,
                                IN PCHECK_FOR_TRAVERSE_ACCESS TraverseCallback 
OPTIONAL,
                                IN PSECURITY_SUBJECT_CONTEXT SubjectContext 
OPTIONAL)
 {
-    KeBugCheck(FILE_SYSTEM);
+    FsRtlNotifyFilterChangeDirectory(NotifySync,
+                                     NotifyList,
+                                     FsContext,
+                                     FullDirectoryName,
+                                     WatchTree,
+                                     IgnoreBuffer,
+                                     CompletionFilter,
+                                     NotifyIrp,
+                                     TraverseCallback,
+                                     SubjectContext,
+                                     NULL);
 }
 
 /*++
  * @name FsRtlNotifyFullReportChange
- * @unimplemented
- *
- * FILLME
- *
- * @param NotifySync
- *        FILLME
- *
- * @param NotifyList
- *        FILLME
+ * @implemented
+ *
+ * Complets the pending notify IRPs.
+ *
+ * @param NotifySync
+ *        Synchronization object pointer
+ *
+ * @param NotifyList
+ *        Notify list pointer (to head) 
  *
  * @param FullTargetName
- *        FILLME
+ *        String (A or W) containing the full directory name that changed
  *
  * @param TargetNameOffset
- *        FILLME
+ *        Offset, in FullTargetName, of the final component that is in the 
changed directory 
  *
  * @param StreamName
- *        FILLME
+ *        String (A or W) containing a stream name
  *
  * @param NormalizedParentName
- *        FILLME
+ *        String (A or W) containing the full directory name that changed with 
long names
  *
  * @param FilterMatch
- *        FILLME
+ *        Flags that will be compared to the completion filter
  *
  * @param Action
- *        FILLME
+ *        Action code to store in user's buffer
  *
  * @param TargetContext
- *        FILLME
- *
- * @return None
- *
- * @remarks None
+ *        Pointer to a callback function. It's called each time a change is
+ *        done in a subdirectory of the main directory.
+ *
+ * @return None
+ *
+ * @remarks This function only redirects to FsRtlNotifyFilterReportChange.
  *
  *--*/
 VOID
@@ -324,54 +460,73 @@
                             IN ULONG Action,
                             IN PVOID TargetContext)
 {
-    KeBugCheck(FILE_SYSTEM);
+    FsRtlNotifyFilterReportChange(NotifySync,
+                                  NotifyList,
+                                  FullTargetName,
+                                  TargetNameOffset,
+                                  StreamName,
+                                  NormalizedParentName,
+                                  FilterMatch,
+                                  Action,
+                                  TargetContext,
+                                  NULL);
 }
 
 /*++
  * @name FsRtlNotifyInitializeSync
- * @unimplemented
- *
- * FILLME
- *
- * @param NotifySync
- *        FILLME
- *
- * @return None
- *
- * @remarks None
+ * @implemented
+ *
+ * Allocates the internal structure associated with notifications.
+ *
+ * @param NotifySync
+ *        Opaque pointer. It will receive the address of the allocated 
internal structure.
+ *
+ * @return None
+ *
+ * @remarks This function raise an exception in case of a failure.
  *
  *--*/
 VOID
 NTAPI
 FsRtlNotifyInitializeSync(IN PNOTIFY_SYNC *NotifySync)
 {
-    KeBugCheck(FILE_SYSTEM);
+    PREAL_NOTIFY_SYNC RealNotifySync;
+
+    *NotifySync = NULL;
+    
+    RealNotifySync = ExAllocatePoolWithTag(NonPagedPool | 
POOL_RAISE_IF_ALLOCATION_FAILURE,
+                                           sizeof(REAL_NOTIFY_SYNC), TAG('F', 
'S', 'N', 'S'));
+    ExInitializeFastMutex(&(RealNotifySync->FastMutex));
+    RealNotifySync->OwningThread = 0;
+    RealNotifySync->OwnerCount = 0;
+
+    *NotifySync = RealNotifySync;
 }
 
 /*++
  * @name FsRtlNotifyReportChange
- * @unimplemented
- *
- * FILLME
- *
- * @param NotifySync
- *        FILLME
- *
- * @param NotifyList
- *        FILLME
+ * @implemented
+ *
+ * Complets the pending notify IRPs.
+ *
+ * @param NotifySync
+ *        Synchronization object pointer
+ *
+ * @param NotifyList
+ *        Notify list pointer (to head) 
  *
  * @param FullTargetName
- *        FILLME
+ *        String (A or W) containing the full directory name that changed
  *
  * @param FileNamePartLength
- *        FILLME
+ *        Length of the final component that is in the changed directory
  *
  * @param FilterMatch
- *        FILLME
- *
- * @return None
- *
- * @remarks None
+ *        Flags that will be compared to the completion filter
+ *
+ * @return None
+ *
+ * @remarks This function only redirects to FsRtlNotifyFilterReportChange.
  *
  *--*/
 VOID
@@ -382,11 +537,20 @@
                         IN PUSHORT FileNamePartLength,
                         IN ULONG FilterMatch)
 {
-    KeBugCheck(FILE_SYSTEM);
-}
-
-/*++
- * @name FsRtlCurrentBatchOplock
+      FsRtlNotifyFilterReportChange(NotifySync,
+                                    NotifyList,
+                                    FullTargetName,
+                                    FullTargetName->Length - 
*FileNamePartLength,
+                                    NULL,
+                                    NULL,
+                                    FilterMatch,
+                                    0,
+                                    NULL,
+                                    NULL); 
+}
+
+/*++
+ * @name FsRtlNotifyUninitializeSync
  * @implemented
  *
  * Uninitialize a NOTIFY_SYNC object
@@ -404,6 +568,10 @@
 NTAPI
 FsRtlNotifyUninitializeSync(IN PNOTIFY_SYNC *NotifySync)
 {
-    KeBugCheck(FILE_SYSTEM);
-}
-
+    if (*NotifySync)
+    {
+        ExFreePoolWithTag(*NotifySync, TAG('F', 'S', 'N', 'S'));
+        *NotifySync = NULL;
+    }
+}
+

Modified: trunk/reactos/ntoskrnl/include/internal/fsrtl.h
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/fsrtl.h?rev=55914&r1=55913&r2=55914&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/fsrtl.h [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/include/internal/fsrtl.h [iso-8859-1] Wed Feb 29 
09:18:01 2012
@@ -5,6 +5,10 @@
  * PURPOSE:         Internal header for the File System Runtime Library
  * PROGRAMMERS:     Alex Ionescu ([email protected])
  */
+
+#ifndef TAG
+#define TAG(w,x,y,z) (((w)<<24)|((x)<<16)|((y)<<8)|(z))
+#endif
 
 //
 // Define this if you want debugging support
@@ -36,7 +40,7 @@
     if (x & FsRtlpTraceLevel) DbgPrint(__VA_ARGS__)
 #endif
 #else
-#define FSTRACE(x, fmt, ...) DPRINT(fmt, ##__VA_ARGS__)
+#define FSTRACE(x, ...) DPRINT(__VA_ARGS__)
 #endif
 
 //
@@ -45,11 +49,67 @@
 #define FSRTL_MAX_RESOURCES 16
 
 //
+// Number of maximum pair count per MCB
+//
+#define MAXIMUM_PAIR_COUNT  15
+
+//
+// Notifications flags
+//
+#define CLEANUP_IN_PROCESS 4
+
+//
+// Internal structure for NOTIFY_SYNC
+//
+typedef struct _REAL_NOTIFY_SYNC
+{
+    FAST_MUTEX FastMutex;
+    ULONG_PTR OwningThread;
+    ULONG OwnerCount;
+} REAL_NOTIFY_SYNC, * PREAL_NOTIFY_SYNC;
+
+//
+// Internal structure for notifications
+//
+typedef struct _NOTIFY_CHANGE
+{
+    PREAL_NOTIFY_SYNC NotifySync;
+    PVOID FsContext;
+    PVOID StreamID;
+    PCHECK_FOR_TRAVERSE_ACCESS TraverseCallback;
+    PSECURITY_SUBJECT_CONTEXT SubjectContext;
+    PSTRING FullDirectoryName;
+    PLIST_ENTRY NotifyList;
+    PLIST_ENTRY NotifyIrps;
+    PFILTER_REPORT_CHANGE FilterCallback;
+    USHORT Flags;
+    UCHAR CharacterSize;
+    ULONG CompletionFilter;
+    PVOID AllocatedBuffer;
+    PVOID Buffer;
+    ULONG BufferLength;
+    ULONG ThisBufferLength;
+    ULONG DataLength;
+    ULONG LastEntry;
+    ULONG ReferenceCount;
+    PEPROCESS OwningProcess;
+} NOTIFY_CHANGE, *PNOTIFY_CHANGE;
+
+//
+// Internal structure for MCB Mapping pointer
+//
+typedef struct _INT_MAPPING
+{
+    VBN Vbn;
+    LBN Lbn;
+} INT_MAPPING, *PINT_MAPPING;
+
+//
 // Initialization Routines
 //
-BOOLEAN
+VOID
 NTAPI
-FsRtlInitSystem(
+FsRtlInitializeLargeMcbs(
     VOID
 );
 
@@ -62,6 +122,12 @@
     IN PFILE_OBJECT FileObject
 );
 
+BOOLEAN
+NTAPI
+FsRtlInitSystem(
+    VOID
+);
+
 //
 // Global data inside the File System Runtime Library
 //


Reply via email to