Author: fireball
Date: Fri Dec 7 20:38:03 2007
New Revision: 31059
URL:
http://svn.reactos.org/svn/reactos?rev=31059&view=rev
Log:
- Fix a bug in delay dereferencing which could lead to an ASSERT.
- Try to work around the ReactOS hack of saving user-mode registry flags in the keynode,
by at least masking out the REG_OPTION_CREATE_LINK flag which interferes with HIVE_EXIT.
- Implement symbolic link parsing and resolution in the new parse routine (with
CmpGetSymbolicLink).
Modified:
trunk/reactos/ntoskrnl/config/cmdelay.c
trunk/reactos/ntoskrnl/config/cmparse.c
Modified: trunk/reactos/ntoskrnl/config/cmdelay.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/config/cmdelay.c?…
==============================================================================
--- trunk/reactos/ntoskrnl/config/cmdelay.c (original)
+++ trunk/reactos/ntoskrnl/config/cmdelay.c Fri Dec 7 20:38:03 2007
@@ -163,6 +163,7 @@
if (!CmpDelayDerefKCBWorkItemActive)
{
/* Yes, we have no work item, setup the interval */
+ CmpDelayDerefKCBWorkItemActive = TRUE;
Timeout.QuadPart = CmpDelayDerefKCBIntervalInSeconds * -10000000;
KeSetTimer(&CmpDelayDerefKCBTimer, Timeout, &CmpDelayDerefKCBDpc);
}
@@ -305,3 +306,4 @@
Kcb->DelayedCloseIndex = CmpDelayedCloseSize;
}
+
Modified: trunk/reactos/ntoskrnl/config/cmparse.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/config/cmparse.c?…
==============================================================================
--- trunk/reactos/ntoskrnl/config/cmparse.c (original)
+++ trunk/reactos/ntoskrnl/config/cmparse.c Fri Dec 7 20:38:03 2007
@@ -72,6 +72,135 @@
/* If there's nothing left, we're last */
*LastName = !RemainingName->Length;
return NameValid;
+}
+
+BOOLEAN
+NTAPI
+CmpGetSymbolicLink(IN PHHIVE Hive,
+ IN OUT PUNICODE_STRING ObjectName,
+ IN OUT PCM_KEY_CONTROL_BLOCK SymbolicKcb,
+ IN PUNICODE_STRING RemainingName OPTIONAL)
+{
+ HCELL_INDEX LinkCell = HCELL_NIL;
+ PCM_KEY_VALUE LinkValue = NULL;
+ PWSTR LinkName = NULL;
+ BOOLEAN LinkNameAllocated = FALSE;
+ PWSTR NewBuffer;
+ ULONG Length = 0;
+ ULONG ValueLength = 0;
+ BOOLEAN Result = FALSE;
+ HCELL_INDEX CellToRelease = HCELL_NIL;
+ PCM_KEY_NODE Node;
+ UNICODE_STRING NewObjectName;
+
+ /* Make sure we're not being deleted */
+ if (SymbolicKcb->Delete) return FALSE;
+
+ /* Get the key node */
+ Node = (PCM_KEY_NODE)HvGetCell(SymbolicKcb->KeyHive, SymbolicKcb->KeyCell);
+ if (!Node) goto Exit;
+
+ /* Find the symbolic link key */
+ LinkCell = CmpFindValueByName(Hive, Node, &CmSymbolicLinkValueName);
+ HvReleaseCell(SymbolicKcb->KeyHive, SymbolicKcb->KeyCell);
+ if (LinkCell == HCELL_NIL) goto Exit;
+
+ /* Get the value cell */
+ LinkValue = (PCM_KEY_VALUE)HvGetCell(Hive, LinkCell);
+ if (!LinkValue) goto Exit;
+
+ /* Make sure it's a registry link */
+ if (LinkValue->Type != REG_LINK) goto Exit;
+
+ /* Now read the value data */
+ if (!CmpGetValueData(Hive,
+ LinkValue,
+ &ValueLength,
+ (PVOID)&LinkName,
+ &LinkNameAllocated,
+ &CellToRelease))
+ {
+ /* Fail */
+ goto Exit;
+ }
+
+ /* Get the length */
+ Length = ValueLength + sizeof(WCHAR);
+
+ /* Make sure we start with a slash */
+ if (*LinkName != OBJ_NAME_PATH_SEPARATOR) goto Exit;
+
+ /* Add the remaining name if needed */
+ if (RemainingName) Length += RemainingName->Length + sizeof(WCHAR);
+
+ /* Check for overflow */
+ if (Length > 0xFFFF) goto Exit;
+
+ /* Check if we need a new buffer */
+ if (Length > ObjectName->MaximumLength)
+ {
+ /* We do -- allocate one */
+ NewBuffer = ExAllocatePoolWithTag(PagedPool, Length, TAG_CM);
+ if (!NewBuffer) goto Exit;
+
+ /* Setup the new string and copy the symbolic target */
+ NewObjectName.Buffer = NewBuffer;
+ NewObjectName.MaximumLength = (USHORT)Length;
+ NewObjectName.Length = (USHORT)ValueLength;
+ RtlCopyMemory(NewBuffer, LinkName, ValueLength);
+
+ /* Check if we need to add anything else */
+ if (RemainingName)
+ {
+ /* Add the remaining name */
+ NewBuffer[ValueLength / sizeof(WCHAR)] = OBJ_NAME_PATH_SEPARATOR;
+ NewObjectName.Length += sizeof(WCHAR);
+ RtlAppendUnicodeStringToString(&NewObjectName, RemainingName);
+ }
+
+ /* Free the old buffer */
+ ExFreePool(ObjectName->Buffer);
+ *ObjectName = NewObjectName;
+ }
+ else
+ {
+ /* The old name is large enough -- update the length */
+ ObjectName->Length = (USHORT)ValueLength;
+ if (RemainingName)
+ {
+ /* Copy the remaining name inside */
+ RtlMoveMemory(&ObjectName->Buffer[(ValueLength / sizeof(WCHAR)) + 1],
+ RemainingName->Buffer,
+ RemainingName->Length);
+
+ /* Add the slash and update the length */
+ ObjectName->Buffer[ValueLength / sizeof(WCHAR)] =
OBJ_NAME_PATH_SEPARATOR;
+ ObjectName->Length += RemainingName->Length + sizeof(WCHAR);
+ }
+
+ /* Copy the symbolic link target name */
+ RtlCopyMemory(ObjectName->Buffer, LinkName, ValueLength);
+ }
+
+ /* Null-terminate the whole thing */
+ ObjectName->Buffer[ObjectName->Length / sizeof(WCHAR)] = UNICODE_NULL;
+ Result = TRUE;
+
+Exit:
+ /* Free the link name */
+ if (LinkNameAllocated) ExFreePool(LinkName);
+
+ /* Check if we had a value cell */
+ if (LinkValue)
+ {
+ /* Release it */
+ ASSERT(LinkCell != HCELL_NIL);
+ HvReleaseCell(Hive, LinkCell);
+ }
+
+ /* Check if we had an active cell and release it, then return the result */
+ if (CellToRelease != HCELL_NIL) HvReleaseCell(Hive, CellToRelease);
+ return Result;
}
NTSTATUS
@@ -196,7 +325,7 @@
/* Fill out the key node */
KeyNode->Signature = CM_KEY_NODE_SIGNATURE;
- KeyNode->Flags = Flags;
+ KeyNode->Flags = Flags &~ REG_OPTION_CREATE_LINK;
KeQuerySystemTime(&SystemTime);
KeyNode->LastWriteTime = SystemTime;
KeyNode->Spare = 0;
@@ -903,9 +1032,52 @@
/* Check if this is a symlink */
if (Kcb->Flags & KEY_SYM_LINK)
{
+ DPRINT1("Parsing sym link: %lx %lx %lx\n", Kcb->Flags, Status,
+ CompleteName);
+
+ /* Get the next name */
+ Result = CmpGetNextName(&Current, &NextName, &Last);
+ Current.Buffer = NextName.Buffer;
+
+ /* Validate the current name string length */
+ if (Current.Length + NextName.Length > MAXUSHORT)
+ {
+ /* too long */
+ Status = STATUS_NAME_TOO_LONG;
+ goto Quickie;
+ }
+ Current.Length += NextName.Length;
+
+ /* Validate the current name string maximum length */
+ if (Current.MaximumLength + NextName.MaximumLength > MAXUSHORT)
+ {
+ /* too long */
+ Status = STATUS_NAME_TOO_LONG;
+ goto Quickie;
+ }
+ Current.MaximumLength += NextName.MaximumLength;
+
+ /* Parse the symlink */
+ if (CmpGetSymbolicLink(Hive,
+ CompleteName,
+ Kcb,
+ &Current))
+ {
+ /* Symlink parse succeeded */
+ Status = STATUS_REPARSE;
+ }
+ else
+ {
+ /* Couldn't find symlink */
+ Status = STATUS_OBJECT_NAME_NOT_FOUND;
+ }
+
/* Not implemented */
- DPRINT1("Parsing sym link\n");
- while (TRUE);
+ DPRINT1("Parsing sym link: %lx %wZ %wZ\n", Status,
+ CompleteName, &Current);
+
+ /* We're done */
+ goto Quickie;
}
/* Get the key node */
@@ -967,8 +1139,22 @@
Object);
if (Status == STATUS_REPARSE)
{
+ DPRINT1("Parsing sym link: %lx %lx\n", Status,
+ CompleteName);
+
+ /* Parse the symlink */
+ if (!CmpGetSymbolicLink(Hive,
+ CompleteName,
+ Kcb,
+ NULL))
+ {
+ /* Symlink parse failed */
+ Status = STATUS_OBJECT_NAME_NOT_FOUND;
+ }
+
/* Not implemented */
- DPRINT1("Parsing sym link\n");
+ DPRINT1("Parsing sym link: %lx %wZ\n", Status,
+ CompleteName);
while (TRUE);
}
@@ -1056,9 +1242,51 @@
}
else
{
+ DPRINT1("Parsing sym link: %lx %lx\n", Status,
+ CompleteName);
+
+ /* Save the next name */
+ Current.Buffer = NextName.Buffer;
+
+ /* Validate the current name string length */
+ if (Current.Length + NextName.Length > MAXUSHORT)
+ {
+ /* too long */
+ Status = STATUS_NAME_TOO_LONG;
+ break;
+ }
+ Current.Length += NextName.Length;
+
+ /* Validate the current name string maximum length */
+ if (Current.MaximumLength + NextName.MaximumLength > MAXUSHORT)
+ {
+ /* too long */
+ Status = STATUS_NAME_TOO_LONG;
+ break;
+ }
+ Current.MaximumLength += NextName.MaximumLength;
+
+ /* Parse the symlink */
+ if (CmpGetSymbolicLink(Hive,
+ CompleteName,
+ Kcb,
+ &Current))
+ {
+ /* Symlink parse succeeded */
+ Status = STATUS_REPARSE;
+ }
+ else
+ {
+ /* Couldn't find symlink */
+ Status = STATUS_OBJECT_NAME_NOT_FOUND;
+ }
+
/* Not implemented */
- DPRINT1("Parsing sym link\n");
- while (TRUE);
+ DPRINT1("Parsing sym link: %lx %wZ %wZ\n", Status,
+ CompleteName, &Current);
+
+ /* We're done */
+ break;
}
}
else if ((Result) && (Last))
@@ -1076,6 +1304,7 @@
}
/* Dereference the parent if it exists */
+Quickie:
if (ParentKcb) CmpDereferenceKeyControlBlock(ParentKcb);
/* Unlock the registry */