Author: fireball
Date: Sun Oct 28 21:46:09 2007
New Revision: 29936
URL:
http://svn.reactos.org/svn/reactos?rev=29936&view=rev
Log:
- It seems Alex's code was half-right, the cache tables still have to be zeroed out.
- Rename "Ncb" functions to "NameControlBlock" functions.
- Finish implementing CmpGetNameControlBlock and fix some bugs in it.
- Fix CmpDereferenceNameControlBlockWithLock.
- Fix bugs in CmpCreateKeyControlBlock and other style changes.
- Add new macros for NCB lock acquire/release (based on the KCB macros).
- The code doesn't seem to crash anymore, it just dies in the ASSERTs Alex added for
unimplemented code -- it would seem all the bugs are now fixed (or the code is behaving
properly).
Modified:
branches/alex-cm-branch/reactos/ntoskrnl/cm/cm_x.h
branches/alex-cm-branch/reactos/ntoskrnl/cm/cmkcbncb.c
Modified: branches/alex-cm-branch/reactos/ntoskrnl/cm/cm_x.h
URL:
http://svn.reactos.org/svn/reactos/branches/alex-cm-branch/reactos/ntoskrnl…
==============================================================================
--- branches/alex-cm-branch/reactos/ntoskrnl/cm/cm_x.h (original)
+++ branches/alex-cm-branch/reactos/ntoskrnl/cm/cm_x.h Sun Oct 28 21:46:09 2007
@@ -221,6 +221,15 @@
}
//
+// Exclusively acquires an NCB by key
+//
+#define CmpAcquireNcbLockExclusiveByKey(k) \
+{ \
+ ExAcquirePushLockExclusive(&GET_HASH_ENTRY(CmpNameCacheTable, \
+ (k)).Lock); \
+}
+
+//
// Releases an exlusively or shared acquired NCB
//
#define CmpReleaseNcbLock(k) \
@@ -228,3 +237,12 @@
ExReleasePushLock(&GET_HASH_ENTRY(CmpNameCacheTable, \
(k)->ConvKey).Lock); \
}
+
+//
+// Releases an exlusively or shared acquired NCB by key
+//
+#define CmpReleaseNcbLockByKey(k) \
+{ \
+ ExReleasePushLock(&GET_HASH_ENTRY(CmpNameCacheTable, \
+ (k)).Lock); \
+}
Modified: branches/alex-cm-branch/reactos/ntoskrnl/cm/cmkcbncb.c
URL:
http://svn.reactos.org/svn/reactos/branches/alex-cm-branch/reactos/ntoskrnl…
==============================================================================
--- branches/alex-cm-branch/reactos/ntoskrnl/cm/cmkcbncb.c (original)
+++ branches/alex-cm-branch/reactos/ntoskrnl/cm/cmkcbncb.c Sun Oct 28 21:46:09 2007
@@ -110,6 +110,9 @@
KeBugCheckEx(CONFIG_INITIALIZATION_FAILED, 3, 1, 0, 0);
}
+ /* Zero out the table */
+ RtlZeroMemory(CmpCacheTable, Length);
+
/* Initialize the locks */
for (i = 0;i < CmpHashTableSize; i++)
{
@@ -128,6 +131,9 @@
KeBugCheckEx(CONFIG_INITIALIZATION_FAILED, 3, 3, 0, 0);
}
+ /* Zero out the table */
+ RtlZeroMemory(CmpNameCacheTable, Length);
+
/* Initialize the locks */
for (i = 0;i < CmpHashTableSize; i++)
{
@@ -272,18 +278,17 @@
return NULL;
}
-// FIXME: NEEDS COMPLETION
PCM_NAME_CONTROL_BLOCK
NTAPI
-CmpGetNcb(IN PUNICODE_STRING NodeName)
+CmpGetNameControlBlock(IN PUNICODE_STRING NodeName)
{
PCM_NAME_CONTROL_BLOCK Ncb = NULL;
ULONG ConvKey = 0;
PWCHAR p, pp;
ULONG i;
- BOOLEAN IsCompressed = TRUE, Found;
+ BOOLEAN IsCompressed = TRUE, Found = FALSE;
PCM_NAME_HASH HashEntry;
- ULONG Length;
+ ULONG Length, NcbSize;
/* Loop the name */
p = NodeName->Buffer;
@@ -312,6 +317,9 @@
IsCompressed = FALSE;
}
}
+
+ /* Lock the NCB entry */
+ CmpAcquireNcbLockExclusiveByKey(ConvKey);
/* Get the hash entry */
HashEntry = GET_HASH_ENTRY(CmpNameCacheTable, ConvKey).Entry;
@@ -352,21 +360,74 @@
}
/* Next chars */
- //*p++;
- //*pp++;
+ p++;
+ pp++;
}
}
/* Check if we found a name */
if (Found)
{
-
+ /* Reference it */
+ Ncb->RefCount++;
}
}
/* Go to the next hash */
HashEntry = HashEntry->NextHash;
}
+
+ /* Check if we didn't find it */
+ if (!Found)
+ {
+ /* Allocate one */
+ NcbSize = FIELD_OFFSET(CM_NAME_CONTROL_BLOCK, Name) + Length;
+ Ncb = ExAllocatePoolWithTag(PagedPool, NcbSize, TAG_CM);
+ if (!Ncb)
+ {
+ /* Release the lock and fail */
+ CmpReleaseNcbLockByKey(ConvKey);
+ return NULL;
+ }
+
+ /* Clear it out */
+ RtlZeroMemory(Ncb, NcbSize);
+
+ /* Check if the name was compressed */
+ if (IsCompressed)
+ {
+ /* Copy the compressed name */
+ Ncb->Compressed = TRUE;
+ for (i = 0; i < Length; i++)
+ {
+ /* Copy Unicode to ANSI */
+ ((PCHAR)Ncb->Name)[i] =
(CHAR)RtlUpcaseUnicodeChar(NodeName->Buffer[i]);
+ }
+ }
+ else
+ {
+ /* Copy the name directly */
+ Ncb->Compressed = FALSE;
+ for (i = 0; i < Length; i++)
+ {
+ /* Copy each unicode character */
+ Ncb->Name[i] = RtlUpcaseUnicodeChar(NodeName->Buffer[i]);
+ }
+ }
+
+ /* Setup the rest of the NCB */
+ Ncb->ConvKey = ConvKey;
+ Ncb->RefCount++;
+ Ncb->NameLength = Length;
+
+ /* Insert the name in the hash table */
+ HashEntry = &Ncb->NameHash;
+ HashEntry->NextHash = GET_HASH_ENTRY(CmpNameCacheTable, ConvKey).Entry;
+ GET_HASH_ENTRY(CmpNameCacheTable, ConvKey).Entry = HashEntry;
+ }
+
+ /* Release NCB lock */
+ CmpReleaseNcbLockByKey(ConvKey);
/* Return the NCB found */
return Ncb;
@@ -446,9 +507,9 @@
VOID
NTAPI
-CmpDereferenceNcbWithLock(IN PCM_NAME_CONTROL_BLOCK Ncb)
-{
- PCM_NAME_HASH Current, Next;
+CmpDereferenceNameControlBlockWithLock(IN PCM_NAME_CONTROL_BLOCK Ncb)
+{
+ PCM_NAME_HASH Current, *Next;
/* Lock the NCB */
CmpAcquireNcbLockExclusive(Ncb);
@@ -457,20 +518,24 @@
if (!(--Ncb->RefCount))
{
/* Find the NCB in the table */
- Next = GET_HASH_ENTRY(CmpNameCacheTable, Ncb->ConvKey).Entry;
+ Next = &GET_HASH_ENTRY(CmpNameCacheTable, Ncb->ConvKey).Entry;
while (TRUE)
{
/* Check the current entry */
- Current = Next;
+ Current = *Next;
ASSERT(Current != NULL);
- if (Current == &Ncb->NameHash) break;
+ if (Current == &Ncb->NameHash)
+ {
+ /* Unlink it */
+ *Next = Current->NextHash;
+ break;
+ }
/* Get to the next one */
- Next = Current->NextHash;
- }
-
- /* Found it, now unlink it and free it */
- Current->NextHash = Next->NextHash;
+ Next = &Current->NextHash;
+ }
+
+ /* Found it, now free it */
ExFreePool(Ncb);
}
@@ -705,7 +770,7 @@
CmpCleanUpKcbValueCache(Kcb);
/* Reference the NCB */
- CmpDereferenceNcbWithLock(Kcb->NameBlock);
+ CmpDereferenceNameControlBlockWithLock(Kcb->NameBlock);
/* Check if we have an index hint block and free it */
if (Kcb->ExtFlags & CM_KCB_SUBKEY_HINT) ExFreePool(Kcb->IndexHint);
@@ -957,12 +1022,16 @@
BOOLEAN IsFake, HashLock;
PWCHAR p;
- /* Make sure we own this hive */
- ASSERT(FALSE);
- if (((PCMHIVE)Hive)->CreatorOwner != KeGetCurrentThread()) return NULL;
+ /* Make sure we own this hive in case it's being unloaded */
+ if ((Hive->HiveFlags & HIVE_IS_UNLOADING) &&
+ (((PCMHIVE)Hive)->CreatorOwner != KeGetCurrentThread()))
+ {
+ /* Fail */
+ return NULL;
+ }
/* Check if this is a fake KCB */
- IsFake = (BOOLEAN)(Flags & CMP_CREATE_FAKE_KCB);
+ IsFake = Flags & CMP_CREATE_FAKE_KCB ? TRUE : FALSE;
/* If we have a parent, use its ConvKey */
if (Parent) ConvKey = Parent->ConvKey;
@@ -986,7 +1055,7 @@
for (i = 0; i < NodeName.Length; i += sizeof(WCHAR))
{
/* Make sure it's a valid character */
- if ((*p != OBJ_NAME_PATH_SEPARATOR) && (*p))
+ if (*p != OBJ_NAME_PATH_SEPARATOR)
{
/* Add this key to the hash */
ConvKey = 37 * ConvKey + RtlUpcaseUnicodeChar(*p);
@@ -1010,9 +1079,10 @@
Kcb->KeyCell = Index;
Kcb->ConvKey = ConvKey;
Kcb->DelayedCloseIndex = CmpDelayedCloseSize;
+ Kcb->InDelayClose = 0;
/* Check if we have two hash entires */
- HashLock = (BOOLEAN)(Flags & CMP_LOCK_HASHES_FOR_KCB);
+ HashLock = Flags & CMP_LOCK_HASHES_FOR_KCB ? TRUE : FALSE;
if (HashLock)
{
/* Not yet implemented */
@@ -1054,8 +1124,8 @@
CM_KCB_SUBKEY_HINT)))
{
/* Calculate the index hint */
- Kcb->SubKeyCount = Node->SubKeyCounts[0] +
- Node->SubKeyCounts[1];
+ Kcb->SubKeyCount = Node->SubKeyCounts[Stable] +
+ Node->SubKeyCounts[Volatile];
/* Cached information is now valid */
Kcb->ExtFlags &= ~CM_KCB_INVALID_CACHED_INFO;
@@ -1100,7 +1170,7 @@
if (Kcb)
{
/* Get the NCB */
- Kcb->NameBlock = CmpGetNcb(&NodeName);
+ Kcb->NameBlock = CmpGetNameControlBlock(&NodeName);
if (Kcb->NameBlock)
{
/* Fill it out */
@@ -1114,8 +1184,8 @@
if (IsFake) Kcb->ExtFlags |= CM_KCB_KEY_NON_EXIST;
/* Setup the other data */
- Kcb->SubKeyCount = Node->SubKeyCounts[0] +
- Node->SubKeyCounts[1];
+ Kcb->SubKeyCount = Node->SubKeyCounts[Stable] +
+ Node->SubKeyCounts[Volatile];
Kcb->KcbLastWriteTime = Node->LastWriteTime;
Kcb->KcbMaxNameLen = (USHORT)Node->MaxNameLen;
Kcb->KcbMaxValueNameLen = (USHORT)Node->MaxValueNameLen;
@@ -1133,6 +1203,9 @@
}
}
}
+
+ /* Sanity check */
+ ASSERT((!Kcb) || (Kcb->Delete == FALSE));
/* Check if we had locked the hashes */
if (HashLock)