- Move NtCreateKey to regobj.c, delete ntfunc.c, now all those routines exist solely for creating keys.

- Move NtOpenKey to ntapi.c and rewrite it to use the new parse routine. It's now 6 lines of code instead of 80.
- Fix a bug in CmpDereferenceNameCnotrolBlockWithLock.
- Fix bugs during reference and dereference of KCB.
- Fix KCB structure.
- CmpDelayDerefKCBWorker is now called, don't make it assert anymore, just print out that it's not completed.
- Remove debug output from new parse routine, since it's now called for each key open.
- Add one more case to handle: opening the root \REGISTRY node.
- Don't dereference KCBs in the parse routine anymore: we have some bugs related to this and it would make ReactOS crash.

svn path=/trunk/; revision=31094
This commit is contained in:
Aleksey Bragin 2007-12-08 21:00:45 +00:00
parent f7d91421f8
commit 60fad32ecf
8 changed files with 310 additions and 397 deletions

View file

@ -1,289 +0,0 @@
/*
* PROJECT: ReactOS Kernel
* COPYRIGHT: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/cm/ntfunc.c
* PURPOSE: Ntxxx function for registry access
*
* PROGRAMMERS: Hartmut Birr
* Casper Hornstrup
* Alex Ionescu
* Rex Jolliff
* Eric Kohl
* Filip Navara
* Thomas Weidenmueller
*/
/* INCLUDES *****************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
#include <internal/debug.h>
#include "cm.h"
/* GLOBALS ******************************************************************/
NTSTATUS
NTAPI
CmpCreateHandle(PVOID ObjectBody,
ACCESS_MASK GrantedAccess,
ULONG HandleAttributes,
PHANDLE HandleReturn);
/* FUNCTIONS ****************************************************************/
NTSTATUS
NTAPI
NtCreateKey(OUT PHANDLE KeyHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN ULONG TitleIndex,
IN PUNICODE_STRING Class,
IN ULONG CreateOptions,
OUT PULONG Disposition)
{
UNICODE_STRING RemainingPath = {0}, ReturnedPath = {0};
ULONG LocalDisposition;
PCM_KEY_BODY KeyObject, Parent;
NTSTATUS Status = STATUS_SUCCESS;
UNICODE_STRING ObjectName;
OBJECT_CREATE_INFORMATION ObjectCreateInfo;
ULONG i;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
HANDLE hKey;
PCM_KEY_NODE Node, ParentNode;
CM_PARSE_CONTEXT ParseContext = {0};
PAGED_CODE();
/* Setup the parse context */
ParseContext.CreateOperation = TRUE;
ParseContext.CreateOptions = CreateOptions;
if (Class) ParseContext.Class = *Class;
/* Capture all the info */
Status = ObpCaptureObjectAttributes(ObjectAttributes,
PreviousMode,
FALSE,
&ObjectCreateInfo,
&ObjectName);
if (!NT_SUCCESS(Status)) return Status;
/* Find the key object */
Status = CmFindObject(&ObjectCreateInfo,
&ObjectName,
(PVOID*)&Parent,
&ReturnedPath,
CmpKeyObjectType,
NULL,
NULL);
if (!NT_SUCCESS(Status)) goto Cleanup;
/* Check if we found the entire path */
RemainingPath = ReturnedPath;
if (!RemainingPath.Length)
{
/* Check if the parent has been deleted */
if (Parent->KeyControlBlock->Delete)
{
/* Fail */
DPRINT1("Object marked for delete!\n");
Status = STATUS_UNSUCCESSFUL;
goto Cleanup;
}
/* Create a new handle to the parent */
Status = CmpCreateHandle(Parent,
DesiredAccess,
ObjectCreateInfo.Attributes,
&hKey);
if (!NT_SUCCESS(Status)) goto Cleanup;
/* Tell the caller we did this */
LocalDisposition = REG_OPENED_EXISTING_KEY;
goto SuccessReturn;
}
/* Loop every leading slash */
while ((RemainingPath.Length) &&
(*RemainingPath.Buffer == OBJ_NAME_PATH_SEPARATOR))
{
/* And remove it */
RemainingPath.Length -= sizeof(WCHAR);
RemainingPath.MaximumLength -= sizeof(WCHAR);
RemainingPath.Buffer++;
}
/* Loop every terminating slash */
while ((RemainingPath.Length) &&
(RemainingPath.Buffer[(RemainingPath.Length / sizeof(WCHAR)) - 1] ==
OBJ_NAME_PATH_SEPARATOR))
{
/* And remove it */
RemainingPath.Length -= sizeof(WCHAR);
RemainingPath.MaximumLength -= sizeof(WCHAR);
}
/* Now loop the entire path */
for (i = 0; i < RemainingPath.Length / sizeof(WCHAR); i++)
{
/* And check if we found slahes */
if (RemainingPath.Buffer[i] == OBJ_NAME_PATH_SEPARATOR)
{
/* We don't create trees -- parent key doesn't exist, so fail */
Status = STATUS_OBJECT_NAME_NOT_FOUND;
goto Cleanup;
}
}
/* Now check if we're left with no name by this point */
if (!(RemainingPath.Length) || (RemainingPath.Buffer[0] == UNICODE_NULL))
{
/* Then fail since we can't do anything */
Status = STATUS_OBJECT_NAME_NOT_FOUND;
goto Cleanup;
}
/* Lock the registry */
CmpLockRegistry();
/* Create the key */
Status = CmpDoCreate(Parent->KeyControlBlock->KeyHive,
Parent->KeyControlBlock->KeyCell,
NULL,
&RemainingPath,
KernelMode,
&ParseContext,
Parent->KeyControlBlock,
(PVOID*)&KeyObject);
if (!NT_SUCCESS(Status)) goto Cleanup;
/* If we got here, this is a new key */
LocalDisposition = REG_CREATED_NEW_KEY;
/* Get the parent node and the child node */
ParentNode = (PCM_KEY_NODE)HvGetCell(KeyObject->KeyControlBlock->ParentKcb->KeyHive,
KeyObject->KeyControlBlock->ParentKcb->KeyCell);
Node = (PCM_KEY_NODE)HvGetCell(KeyObject->KeyControlBlock->KeyHive,
KeyObject->KeyControlBlock->KeyCell);
/* Inherit some information */
Node->Parent = KeyObject->KeyControlBlock->ParentKcb->KeyCell;
Node->Security = ParentNode->Security;
KeyObject->KeyControlBlock->ValueCache.ValueList = Node->ValueList.List;
KeyObject->KeyControlBlock->ValueCache.Count = Node->ValueList.Count;
/* Link child to parent */
InsertTailList(&Parent->KeyControlBlock->KeyBodyListHead, &KeyObject->KeyBodyList);
/* Create the actual handle to the object */
Status = CmpCreateHandle(KeyObject,
DesiredAccess,
ObjectCreateInfo.Attributes,
&hKey);
/* Free the create information */
ObpFreeAndReleaseCapturedAttributes(OBJECT_TO_OBJECT_HEADER(KeyObject)->ObjectCreateInfo);
OBJECT_TO_OBJECT_HEADER(KeyObject)->ObjectCreateInfo = NULL;
if (!NT_SUCCESS(Status)) goto Cleanup;
/* Add the keep-alive reference */
ObReferenceObject(KeyObject);
/* Unlock registry */
CmpUnlockRegistry();
/* Force a lazy flush */
CmpLazyFlush();
SuccessReturn:
/* Return data to user */
*KeyHandle = hKey;
if (Disposition) *Disposition = LocalDisposition;
Cleanup:
/* Cleanup */
ObpReleaseCapturedAttributes(&ObjectCreateInfo);
if (ObjectName.Buffer) ObpFreeObjectNameBuffer(&ObjectName);
RtlFreeUnicodeString(&ReturnedPath);
if (Parent) ObDereferenceObject(Parent);
return Status;
}
NTSTATUS
NTAPI
NtOpenKey(OUT PHANDLE KeyHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes)
{
UNICODE_STRING RemainingPath = {0};
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
PCM_KEY_BODY Object = NULL;
HANDLE hKey = NULL;
NTSTATUS Status = STATUS_SUCCESS;
UNICODE_STRING ObjectName;
OBJECT_CREATE_INFORMATION ObjectCreateInfo;
PAGED_CODE();
/* Capture all the info */
Status = ObpCaptureObjectAttributes(ObjectAttributes,
PreviousMode,
FALSE,
&ObjectCreateInfo,
&ObjectName);
if (!NT_SUCCESS(Status)) return Status;
/* Loop every terminating slash */
while ((ObjectName.Length) &&
(ObjectName.Buffer[(ObjectName.Length / sizeof(WCHAR)) - 1] ==
OBJ_NAME_PATH_SEPARATOR))
{
/* And remove it */
ObjectName.Length -= sizeof(WCHAR);
ObjectName.MaximumLength -= sizeof(WCHAR);
}
/* Find the key */
Status = CmFindObject(&ObjectCreateInfo,
&ObjectName,
(PVOID*)&Object,
&RemainingPath,
CmpKeyObjectType,
NULL,
NULL);
if (!NT_SUCCESS(Status)) goto openkey_cleanup;
/* Make sure we don't have any remaining path */
if ((RemainingPath.Buffer) && (RemainingPath.Buffer[0] != UNICODE_NULL))
{
/* Fail */
Status = STATUS_OBJECT_NAME_NOT_FOUND;
goto openkey_cleanup;
}
/* Check if the key has been deleted */
if (Object->KeyControlBlock->Delete)
{
/* Fail */
Status = STATUS_UNSUCCESSFUL;
goto openkey_cleanup;
}
/* Create the actual handle */
Status = CmpCreateHandle(Object,
DesiredAccess,
ObjectCreateInfo.Attributes,
&hKey);
openkey_cleanup:
/* Cleanup */
ObpReleaseCapturedAttributes(&ObjectCreateInfo);
if (ObjectName.Buffer) ObpFreeObjectNameBuffer(&ObjectName);
RtlFreeUnicodeString(&RemainingPath);
if (Object) ObDereferenceObject(Object);
/* Return information and status to user */
*KeyHandle = hKey;
return Status;
}
/* EOF */

View file

@ -875,4 +875,181 @@ CmiGetLinkTarget(PCMHIVE RegistryHive,
return(STATUS_SUCCESS); return(STATUS_SUCCESS);
} }
NTSTATUS
NTAPI
NtCreateKey(OUT PHANDLE KeyHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN ULONG TitleIndex,
IN PUNICODE_STRING Class,
IN ULONG CreateOptions,
OUT PULONG Disposition)
{
UNICODE_STRING RemainingPath = {0}, ReturnedPath = {0};
ULONG LocalDisposition;
PCM_KEY_BODY KeyObject, Parent;
NTSTATUS Status = STATUS_SUCCESS;
UNICODE_STRING ObjectName;
OBJECT_CREATE_INFORMATION ObjectCreateInfo;
ULONG i;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
HANDLE hKey;
PCM_KEY_NODE Node, ParentNode;
CM_PARSE_CONTEXT ParseContext = {0};
PAGED_CODE();
/* Setup the parse context */
ParseContext.CreateOperation = TRUE;
ParseContext.CreateOptions = CreateOptions;
if (Class) ParseContext.Class = *Class;
/* Capture all the info */
Status = ObpCaptureObjectAttributes(ObjectAttributes,
PreviousMode,
FALSE,
&ObjectCreateInfo,
&ObjectName);
if (!NT_SUCCESS(Status)) return Status;
/* Find the key object */
Status = CmFindObject(&ObjectCreateInfo,
&ObjectName,
(PVOID*)&Parent,
&ReturnedPath,
CmpKeyObjectType,
NULL,
NULL);
if (!NT_SUCCESS(Status)) goto Cleanup;
/* Check if we found the entire path */
RemainingPath = ReturnedPath;
if (!RemainingPath.Length)
{
/* Check if the parent has been deleted */
if (Parent->KeyControlBlock->Delete)
{
/* Fail */
DPRINT1("Object marked for delete!\n");
Status = STATUS_UNSUCCESSFUL;
goto Cleanup;
}
/* Create a new handle to the parent */
Status = CmpCreateHandle(Parent,
DesiredAccess,
ObjectCreateInfo.Attributes,
&hKey);
if (!NT_SUCCESS(Status)) goto Cleanup;
/* Tell the caller we did this */
LocalDisposition = REG_OPENED_EXISTING_KEY;
goto SuccessReturn;
}
/* Loop every leading slash */
while ((RemainingPath.Length) &&
(*RemainingPath.Buffer == OBJ_NAME_PATH_SEPARATOR))
{
/* And remove it */
RemainingPath.Length -= sizeof(WCHAR);
RemainingPath.MaximumLength -= sizeof(WCHAR);
RemainingPath.Buffer++;
}
/* Loop every terminating slash */
while ((RemainingPath.Length) &&
(RemainingPath.Buffer[(RemainingPath.Length / sizeof(WCHAR)) - 1] ==
OBJ_NAME_PATH_SEPARATOR))
{
/* And remove it */
RemainingPath.Length -= sizeof(WCHAR);
RemainingPath.MaximumLength -= sizeof(WCHAR);
}
/* Now loop the entire path */
for (i = 0; i < RemainingPath.Length / sizeof(WCHAR); i++)
{
/* And check if we found slahes */
if (RemainingPath.Buffer[i] == OBJ_NAME_PATH_SEPARATOR)
{
/* We don't create trees -- parent key doesn't exist, so fail */
Status = STATUS_OBJECT_NAME_NOT_FOUND;
goto Cleanup;
}
}
/* Now check if we're left with no name by this point */
if (!(RemainingPath.Length) || (RemainingPath.Buffer[0] == UNICODE_NULL))
{
/* Then fail since we can't do anything */
Status = STATUS_OBJECT_NAME_NOT_FOUND;
goto Cleanup;
}
/* Lock the registry */
CmpLockRegistry();
/* Create the key */
Status = CmpDoCreate(Parent->KeyControlBlock->KeyHive,
Parent->KeyControlBlock->KeyCell,
NULL,
&RemainingPath,
KernelMode,
&ParseContext,
Parent->KeyControlBlock,
(PVOID*)&KeyObject);
if (!NT_SUCCESS(Status)) goto Cleanup;
/* If we got here, this is a new key */
LocalDisposition = REG_CREATED_NEW_KEY;
/* Get the parent node and the child node */
ParentNode = (PCM_KEY_NODE)HvGetCell(KeyObject->KeyControlBlock->ParentKcb->KeyHive,
KeyObject->KeyControlBlock->ParentKcb->KeyCell);
Node = (PCM_KEY_NODE)HvGetCell(KeyObject->KeyControlBlock->KeyHive,
KeyObject->KeyControlBlock->KeyCell);
/* Inherit some information */
Node->Parent = KeyObject->KeyControlBlock->ParentKcb->KeyCell;
Node->Security = ParentNode->Security;
KeyObject->KeyControlBlock->ValueCache.ValueList = Node->ValueList.List;
KeyObject->KeyControlBlock->ValueCache.Count = Node->ValueList.Count;
/* Link child to parent */
InsertTailList(&Parent->KeyControlBlock->KeyBodyListHead, &KeyObject->KeyBodyList);
/* Create the actual handle to the object */
Status = CmpCreateHandle(KeyObject,
DesiredAccess,
ObjectCreateInfo.Attributes,
&hKey);
/* Free the create information */
ObpFreeAndReleaseCapturedAttributes(OBJECT_TO_OBJECT_HEADER(KeyObject)->ObjectCreateInfo);
OBJECT_TO_OBJECT_HEADER(KeyObject)->ObjectCreateInfo = NULL;
if (!NT_SUCCESS(Status)) goto Cleanup;
/* Add the keep-alive reference */
ObReferenceObject(KeyObject);
/* Unlock registry */
CmpUnlockRegistry();
/* Force a lazy flush */
CmpLazyFlush();
SuccessReturn:
/* Return data to user */
*KeyHandle = hKey;
if (Disposition) *Disposition = LocalDisposition;
Cleanup:
/* Cleanup */
ObpReleaseCapturedAttributes(&ObjectCreateInfo);
if (ObjectName.Buffer) ObpFreeObjectNameBuffer(&ObjectName);
RtlFreeUnicodeString(&ReturnedPath);
if (Parent) ObDereferenceObject(Parent);
return Status;
}
/* EOF */ /* EOF */

View file

@ -231,11 +231,14 @@ typedef struct _CM_KEY_CONTROL_BLOCK
{ {
USHORT RefCount; USHORT RefCount;
USHORT Flags; USHORT Flags;
struct
{
ULONG ExtFlags:8; ULONG ExtFlags:8;
ULONG PrivateAlloc:1; ULONG PrivateAlloc:1;
ULONG Delete:1; ULONG Delete:1;
ULONG DelayedCloseIndex:12; ULONG DelayedCloseIndex:12;
ULONG TotalLevels:10; ULONG TotalLevels:10;
};
union union
{ {
CM_KEY_HASH KeyHash; CM_KEY_HASH KeyHash;
@ -251,9 +254,12 @@ typedef struct _CM_KEY_CONTROL_BLOCK
PCM_NAME_CONTROL_BLOCK NameBlock; PCM_NAME_CONTROL_BLOCK NameBlock;
PCM_KEY_SECURITY_CACHE CachedSecurity; PCM_KEY_SECURITY_CACHE CachedSecurity;
CACHED_CHILD_LIST ValueCache; CACHED_CHILD_LIST ValueCache;
union
{
PCM_INDEX_HINT_BLOCK IndexHint; PCM_INDEX_HINT_BLOCK IndexHint;
ULONG HashKey; ULONG HashKey;
ULONG SubKeyCount; ULONG SubKeyCount;
};
union union
{ {
LIST_ENTRY KeyBodyListHead; LIST_ENTRY KeyBodyListHead;

View file

@ -107,6 +107,8 @@ CmpDelayDerefKCBWorker(IN PVOID Context)
ASSERT(CmpDelayDerefKCBWorkItemActive); ASSERT(CmpDelayDerefKCBWorkItemActive);
/* FIXME: TODO */ /* FIXME: TODO */
DPRINT1("CmpDelayDerefKCBWorker has work to do!\n");
return;
ASSERT(FALSE); ASSERT(FALSE);
} }
@ -307,3 +309,4 @@ CmpRemoveFromDelayedClose(IN PCM_KEY_CONTROL_BLOCK Kcb)
} }

View file

@ -312,9 +312,10 @@ NTAPI
CmpDereferenceNameControlBlockWithLock(IN PCM_NAME_CONTROL_BLOCK Ncb) CmpDereferenceNameControlBlockWithLock(IN PCM_NAME_CONTROL_BLOCK Ncb)
{ {
PCM_NAME_HASH Current, *Next; PCM_NAME_HASH Current, *Next;
ULONG ConvKey = Ncb->ConvKey;
/* Lock the NCB */ /* Lock the NCB */
CmpAcquireNcbLockExclusive(Ncb); CmpAcquireNcbLockExclusiveByKey(ConvKey);
/* Decrease the reference count */ /* Decrease the reference count */
if (!(--Ncb->RefCount)) if (!(--Ncb->RefCount))
@ -342,7 +343,7 @@ CmpDereferenceNameControlBlockWithLock(IN PCM_NAME_CONTROL_BLOCK Ncb)
} }
/* Release the lock */ /* Release the lock */
CmpReleaseNcbLock(Ncb); CmpReleaseNcbLockByKey(ConvKey);
} }
BOOLEAN BOOLEAN
@ -387,7 +388,7 @@ CmpReferenceKeyControlBlock(IN PCM_KEY_CONTROL_BLOCK Kcb)
} }
/* Increase the reference count */ /* Increase the reference count */
if (InterlockedIncrement((PLONG)&Kcb->RefCount) == 0) if ((InterlockedIncrement((PLONG)&Kcb->RefCount) & 0xFFFF) == 0)
{ {
/* We've overflown to 64K references, bail out */ /* We've overflown to 64K references, bail out */
InterlockedDecrement((PLONG)&Kcb->RefCount); InterlockedDecrement((PLONG)&Kcb->RefCount);
@ -512,8 +513,8 @@ CmpDereferenceKeyControlBlock(IN PCM_KEY_CONTROL_BLOCK Kcb)
OldRefCount = *(PLONG)&Kcb->RefCount; OldRefCount = *(PLONG)&Kcb->RefCount;
NewRefCount = OldRefCount - 1; NewRefCount = OldRefCount - 1;
/* Check if we still have refenreces */ /* Check if we still have references */
if( (NewRefCount & 0xffff) > 0) if( (NewRefCount & 0xFFFF) > 0)
{ {
/* Do the dereference */ /* Do the dereference */
if (InterlockedCompareExchange((PLONG)&Kcb->RefCount, if (InterlockedCompareExchange((PLONG)&Kcb->RefCount,
@ -544,7 +545,7 @@ CmpDereferenceKeyControlBlockWithLock(IN PCM_KEY_CONTROL_BLOCK Kcb,
(CmpTestRegistryLockExclusive() == TRUE)); (CmpTestRegistryLockExclusive() == TRUE));
/* Check if this is the last reference */ /* Check if this is the last reference */
if (InterlockedDecrement((PLONG)&Kcb->RefCount) == 0) if ((InterlockedDecrement((PLONG)&Kcb->RefCount) & 0xFFFF) == 0)
{ {
/* Check if we should do a direct delete */ /* Check if we should do a direct delete */
if (((CmpHoldLazyFlush) && if (((CmpHoldLazyFlush) &&
@ -821,3 +822,4 @@ EnlistKeyBodyWithKCB(IN PCM_KEY_BODY KeyBody,
/* FIXME: Implement once we don't link parents to children anymore */ /* FIXME: Implement once we don't link parents to children anymore */
} }

View file

@ -782,7 +782,7 @@ CmpCreateLinkNode(IN PHHIVE Hive,
/* Release it */ /* Release it */
HvReleaseCell(Context->ChildHive.KeyHive, ChildCell); HvReleaseCell(Context->ChildHive.KeyHive, ChildCell);
/* Set the parent adn flags */ /* Set the parent and flags */
KeyNode->Parent = LinkCell; KeyNode->Parent = LinkCell;
KeyNode->Flags |= KEY_HIVE_ENTRY | KEY_NO_DELETE; KeyNode->Flags |= KEY_HIVE_ENTRY | KEY_NO_DELETE;
@ -977,7 +977,6 @@ CmpParseKey2(IN PVOID ParseObject,
PULONG LockedKcbs = NULL; PULONG LockedKcbs = NULL;
BOOLEAN Result, Last; BOOLEAN Result, Last;
PAGED_CODE(); PAGED_CODE();
DPRINT1("New style parse routine called: %wZ %wZ!\n", CompleteName, RemainingName);
/* Loop path separators at the end */ /* Loop path separators at the end */
while ((RemainingName->Length) && while ((RemainingName->Length) &&
@ -1003,7 +1002,6 @@ CmpParseKey2(IN PVOID ParseObject,
/* Grab the KCB */ /* Grab the KCB */
Kcb = ((PCM_KEY_BODY)ParseObject)->KeyControlBlock; Kcb = ((PCM_KEY_BODY)ParseObject)->KeyControlBlock;
DPRINT1("KCB Parse: %p\n", Kcb);
/* Lookup in the cache */ /* Lookup in the cache */
Status = CmpBuildHashStackAndLookupCache(ParseObject, Status = CmpBuildHashStackAndLookupCache(ParseObject,
@ -1019,9 +1017,6 @@ CmpParseKey2(IN PVOID ParseObject,
/* This is now the parent */ /* This is now the parent */
ParentKcb = Kcb; ParentKcb = Kcb;
DPRINT1("ParentKcb Parse: %p\n", ParentKcb);
DPRINT1("Hive Parse: %p\n", Hive);
DPRINT1("Cell Parse: %p\n", Cell);
/* Check if everything was found cached */ /* Check if everything was found cached */
if (!TotalRemainingSubkeys) ASSERTMSG("Caching not implemented", FALSE); if (!TotalRemainingSubkeys) ASSERTMSG("Caching not implemented", FALSE);
@ -1032,9 +1027,6 @@ CmpParseKey2(IN PVOID ParseObject,
/* Check if this is a symlink */ /* Check if this is a symlink */
if (Kcb->Flags & KEY_SYM_LINK) if (Kcb->Flags & KEY_SYM_LINK)
{ {
DPRINT1("Parsing sym link: %lx %lx %lx\n", Kcb->Flags, Status,
CompleteName);
/* Get the next name */ /* Get the next name */
Result = CmpGetNextName(&Current, &NextName, &Last); Result = CmpGetNextName(&Current, &NextName, &Last);
Current.Buffer = NextName.Buffer; Current.Buffer = NextName.Buffer;
@ -1072,10 +1064,6 @@ CmpParseKey2(IN PVOID ParseObject,
Status = STATUS_OBJECT_NAME_NOT_FOUND; Status = STATUS_OBJECT_NAME_NOT_FOUND;
} }
/* Not implemented */
DPRINT1("Parsing sym link: %lx %wZ %wZ\n", Status,
CompleteName, &Current);
/* We're done */ /* We're done */
goto Quickie; goto Quickie;
} }
@ -1083,7 +1071,6 @@ CmpParseKey2(IN PVOID ParseObject,
/* Get the key node */ /* Get the key node */
Node = (PCM_KEY_NODE)HvGetCell(Hive, Cell); Node = (PCM_KEY_NODE)HvGetCell(Hive, Cell);
if (!Node) return STATUS_INSUFFICIENT_RESOURCES; if (!Node) return STATUS_INSUFFICIENT_RESOURCES;
DPRINT1("Node Parse: %p\n", Node);
/* Start parsing */ /* Start parsing */
Status = STATUS_NOT_IMPLEMENTED; Status = STATUS_NOT_IMPLEMENTED;
@ -1091,7 +1078,6 @@ CmpParseKey2(IN PVOID ParseObject,
{ {
/* Get the next component */ /* Get the next component */
Result = CmpGetNextName(&Current, &NextName, &Last); Result = CmpGetNextName(&Current, &NextName, &Last);
DPRINT1("Result Parse: %p\n", Result);
if ((Result) && (NextName.Length)) if ((Result) && (NextName.Length))
{ {
/* See if this is a sym link */ /* See if this is a sym link */
@ -1099,13 +1085,11 @@ CmpParseKey2(IN PVOID ParseObject,
{ {
/* Find the subkey */ /* Find the subkey */
NextCell = CmpFindSubKeyByName(Hive, Node, &NextName); NextCell = CmpFindSubKeyByName(Hive, Node, &NextName);
DPRINT1("NextCell Parse: %lx %wZ\n", NextCell, &NextName);
if (NextCell != HCELL_NIL) if (NextCell != HCELL_NIL)
{ {
/* Get the new node */ /* Get the new node */
Cell = NextCell; Cell = NextCell;
Node = (PCM_KEY_NODE)HvGetCell(Hive, Cell); Node = (PCM_KEY_NODE)HvGetCell(Hive, Cell);
DPRINT1("Node Parse: %p\n", Node);
if (!Node) ASSERT(FALSE); if (!Node) ASSERT(FALSE);
/* Check if this was the last key */ /* Check if this was the last key */
@ -1115,13 +1099,11 @@ CmpParseKey2(IN PVOID ParseObject,
if (Node->Flags & KEY_HIVE_EXIT) if (Node->Flags & KEY_HIVE_EXIT)
{ {
/* Handle it */ /* Handle it */
DPRINT1("Exit node\n");
CmpHandleExitNode(&Hive, CmpHandleExitNode(&Hive,
&Cell, &Cell,
&Node, &Node,
&HiveToRelease, &HiveToRelease,
&CellToRelease); &CellToRelease);
DPRINT1("Node Parse: %p\n", Node);
if (!Node) ASSERT(FALSE); if (!Node) ASSERT(FALSE);
} }
@ -1139,9 +1121,6 @@ CmpParseKey2(IN PVOID ParseObject,
Object); Object);
if (Status == STATUS_REPARSE) if (Status == STATUS_REPARSE)
{ {
DPRINT1("Parsing sym link: %lx %lx\n", Status,
CompleteName);
/* Parse the symlink */ /* Parse the symlink */
if (!CmpGetSymbolicLink(Hive, if (!CmpGetSymbolicLink(Hive,
CompleteName, CompleteName,
@ -1151,15 +1130,9 @@ CmpParseKey2(IN PVOID ParseObject,
/* Symlink parse failed */ /* Symlink parse failed */
Status = STATUS_OBJECT_NAME_NOT_FOUND; Status = STATUS_OBJECT_NAME_NOT_FOUND;
} }
/* Not implemented */
DPRINT1("Parsing sym link: %lx %wZ\n", Status,
CompleteName);
while (TRUE);
} }
/* We are done */ /* We are done */
DPRINT1("Open of last key\n");
break; break;
} }
@ -1167,13 +1140,11 @@ CmpParseKey2(IN PVOID ParseObject,
if (Node->Flags & KEY_HIVE_EXIT) if (Node->Flags & KEY_HIVE_EXIT)
{ {
/* Handle it */ /* Handle it */
DPRINT1("Exit node: %lx\n", Node->Flags);
CmpHandleExitNode(&Hive, CmpHandleExitNode(&Hive,
&Cell, &Cell,
&Node, &Node,
&HiveToRelease, &HiveToRelease,
&CellToRelease); &CellToRelease);
DPRINT1("Node Parse: %p\n", Node);
if (!Node) ASSERT(FALSE); if (!Node) ASSERT(FALSE);
} }
@ -1185,10 +1156,9 @@ CmpParseKey2(IN PVOID ParseObject,
0, 0,
&NextName); &NextName);
if (!Kcb) ASSERT(FALSE); if (!Kcb) ASSERT(FALSE);
DPRINT1("Kcb Parse: %p\n", Kcb);
/* Dereference the parent and set the new one */ /* Dereference the parent and set the new one */
CmpDereferenceKeyControlBlock(ParentKcb); //CmpDereferenceKeyControlBlock(ParentKcb);
ParentKcb = Kcb; ParentKcb = Kcb;
} }
else else
@ -1211,7 +1181,6 @@ CmpParseKey2(IN PVOID ParseObject,
ParseContext, ParseContext,
ParentKcb, ParentKcb,
Object); Object);
DPRINT1("Link created: %lx\n", Status);
} }
else else
{ {
@ -1242,9 +1211,6 @@ CmpParseKey2(IN PVOID ParseObject,
} }
else else
{ {
DPRINT1("Parsing sym link: %lx %lx\n", Status,
CompleteName);
/* Save the next name */ /* Save the next name */
Current.Buffer = NextName.Buffer; Current.Buffer = NextName.Buffer;
@ -1281,19 +1247,46 @@ CmpParseKey2(IN PVOID ParseObject,
Status = STATUS_OBJECT_NAME_NOT_FOUND; Status = STATUS_OBJECT_NAME_NOT_FOUND;
} }
/* Not implemented */
DPRINT1("Parsing sym link: %lx %wZ %wZ\n", Status,
CompleteName, &Current);
/* We're done */ /* We're done */
break; break;
} }
} }
else if ((Result) && (Last)) else if ((Result) && (Last))
{ {
/* Opening root: unexpected */ /* Opening the root. Is this an exit node? */
DPRINT1("Unexpected: Opening root\n"); if (Node->Flags & KEY_HIVE_EXIT)
while (TRUE); {
/* Handle it */
CmpHandleExitNode(&Hive,
&Cell,
&Node,
&HiveToRelease,
&CellToRelease);
if (!Node) ASSERT(FALSE);
}
/* FIXME: This hack seems required? */
RtlInitUnicodeString(&NextName, L"\\REGISTRY");
/* Do the open */
Status = CmpDoOpen(Hive,
Cell,
Node,
AccessState,
AccessMode,
Attributes,
ParseContext,
0,
&Kcb,
&NextName,
Object);
if (Status == STATUS_REPARSE)
{
/* Nothing to do */
}
/* We're done */
break;
} }
else else
{ {
@ -1305,7 +1298,7 @@ CmpParseKey2(IN PVOID ParseObject,
/* Dereference the parent if it exists */ /* Dereference the parent if it exists */
Quickie: Quickie:
if (ParentKcb) CmpDereferenceKeyControlBlock(ParentKcb); //if (ParentKcb) CmpDereferenceKeyControlBlock(ParentKcb);
/* Unlock the registry */ /* Unlock the registry */
CmpUnlockRegistry(); CmpUnlockRegistry();

View file

@ -18,6 +18,25 @@ BOOLEAN CmFirstTime = TRUE;
/* FUNCTIONS *****************************************************************/ /* FUNCTIONS *****************************************************************/
NTSTATUS
NTAPI
NtOpenKey(OUT PHANDLE KeyHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes)
{
CM_PARSE_CONTEXT ParseContext = {0};
PAGED_CODE();
/* Just let the object manager handle this */
return ObOpenObjectByName(ObjectAttributes,
CmpKeyObjectType,
ExGetPreviousMode(),
NULL,
DesiredAccess,
&ParseContext,
KeyHandle);
}
NTSTATUS NTSTATUS
NTAPI NTAPI
NtDeleteKey(IN HANDLE KeyHandle) NtDeleteKey(IN HANDLE KeyHandle)
@ -470,28 +489,12 @@ NtFlushKey(IN HANDLE KeyHandle)
return Status; return Status;
} }
NTSTATUS
NTAPI
NtCompactKeys(IN ULONG Count,
IN PHANDLE KeyArray)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
NTAPI
NtCompressKey(IN HANDLE Key)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS NTSTATUS
NTAPI NTAPI
NtLoadKey(IN POBJECT_ATTRIBUTES KeyObjectAttributes, NtLoadKey(IN POBJECT_ATTRIBUTES KeyObjectAttributes,
IN POBJECT_ATTRIBUTES FileObjectAttributes) IN POBJECT_ATTRIBUTES FileObjectAttributes)
{ {
/* Call the newer API */
return NtLoadKey2(KeyObjectAttributes, FileObjectAttributes, 0); return NtLoadKey2(KeyObjectAttributes, FileObjectAttributes, 0);
} }
@ -501,6 +504,7 @@ NtLoadKey2(IN POBJECT_ATTRIBUTES KeyObjectAttributes,
IN POBJECT_ATTRIBUTES FileObjectAttributes, IN POBJECT_ATTRIBUTES FileObjectAttributes,
IN ULONG Flags) IN ULONG Flags)
{ {
/* Call the newer API */
return NtLoadKeyEx(KeyObjectAttributes, FileObjectAttributes, Flags, NULL); return NtLoadKeyEx(KeyObjectAttributes, FileObjectAttributes, Flags, NULL);
} }
@ -555,6 +559,34 @@ NtLoadKeyEx(IN POBJECT_ATTRIBUTES TargetKey,
return Status; return Status;
} }
NTSTATUS
NTAPI
NtNotifyChangeKey(IN HANDLE KeyHandle,
IN HANDLE Event,
IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
IN PVOID ApcContext OPTIONAL,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN ULONG CompletionFilter,
IN BOOLEAN WatchTree,
OUT PVOID Buffer,
IN ULONG Length,
IN BOOLEAN Asynchronous)
{
/* Call the newer API */
return NtNotifyChangeMultipleKeys(KeyHandle,
0,
NULL,
Event,
ApcRoutine,
ApcContext,
IoStatusBlock,
CompletionFilter,
WatchTree,
Buffer,
Length,
Asynchronous);
}
NTSTATUS NTSTATUS
NTAPI NTAPI
NtInitializeRegistry(IN USHORT Flag) NtInitializeRegistry(IN USHORT Flag)
@ -617,6 +649,23 @@ NtInitializeRegistry(IN USHORT Flag)
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
NTSTATUS
NTAPI
NtCompactKeys(IN ULONG Count,
IN PHANDLE KeyArray)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
NTAPI
NtCompressKey(IN HANDLE Key)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS NTSTATUS
NTAPI NTAPI
NtLockProductActivationKeys(IN PULONG pPrivateVer, NtLockProductActivationKeys(IN PULONG pPrivateVer,
@ -653,33 +702,6 @@ NtNotifyChangeMultipleKeys(IN HANDLE MasterKeyHandle,
return STATUS_NOT_IMPLEMENTED; return STATUS_NOT_IMPLEMENTED;
} }
NTSTATUS
NTAPI
NtNotifyChangeKey(IN HANDLE KeyHandle,
IN HANDLE Event,
IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
IN PVOID ApcContext OPTIONAL,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN ULONG CompletionFilter,
IN BOOLEAN WatchTree,
OUT PVOID Buffer,
IN ULONG Length,
IN BOOLEAN Asynchronous)
{
return NtNotifyChangeMultipleKeys(KeyHandle,
0,
NULL,
Event,
ApcRoutine,
ApcContext,
IoStatusBlock,
CompletionFilter,
WatchTree,
Buffer,
Length,
Asynchronous);
}
NTSTATUS NTSTATUS
NTAPI NTAPI
NtQueryMultipleValueKey(IN HANDLE KeyHandle, NtQueryMultipleValueKey(IN HANDLE KeyHandle,

View file

@ -139,7 +139,6 @@
<file>ntapi.c</file> <file>ntapi.c</file>
</directory> </directory>
<directory name="cm"> <directory name="cm">
<file>ntfunc.c</file>
<file>regobj.c</file> <file>regobj.c</file>
</directory> </directory>
<directory name="dbgk"> <directory name="dbgk">