mirror of
https://github.com/reactos/reactos.git
synced 2025-06-04 08:50:27 +00:00
- 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:
parent
f7d91421f8
commit
60fad32ecf
8 changed files with 310 additions and 397 deletions
|
@ -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 */
|
|
@ -875,4 +875,181 @@ CmiGetLinkTarget(PCMHIVE RegistryHive,
|
|||
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 */
|
||||
|
|
|
@ -231,11 +231,14 @@ typedef struct _CM_KEY_CONTROL_BLOCK
|
|||
{
|
||||
USHORT RefCount;
|
||||
USHORT Flags;
|
||||
ULONG ExtFlags:8;
|
||||
ULONG PrivateAlloc:1;
|
||||
ULONG Delete:1;
|
||||
ULONG DelayedCloseIndex:12;
|
||||
ULONG TotalLevels:10;
|
||||
struct
|
||||
{
|
||||
ULONG ExtFlags:8;
|
||||
ULONG PrivateAlloc:1;
|
||||
ULONG Delete:1;
|
||||
ULONG DelayedCloseIndex:12;
|
||||
ULONG TotalLevels:10;
|
||||
};
|
||||
union
|
||||
{
|
||||
CM_KEY_HASH KeyHash;
|
||||
|
@ -251,9 +254,12 @@ typedef struct _CM_KEY_CONTROL_BLOCK
|
|||
PCM_NAME_CONTROL_BLOCK NameBlock;
|
||||
PCM_KEY_SECURITY_CACHE CachedSecurity;
|
||||
CACHED_CHILD_LIST ValueCache;
|
||||
PCM_INDEX_HINT_BLOCK IndexHint;
|
||||
ULONG HashKey;
|
||||
ULONG SubKeyCount;
|
||||
union
|
||||
{
|
||||
PCM_INDEX_HINT_BLOCK IndexHint;
|
||||
ULONG HashKey;
|
||||
ULONG SubKeyCount;
|
||||
};
|
||||
union
|
||||
{
|
||||
LIST_ENTRY KeyBodyListHead;
|
||||
|
|
|
@ -107,6 +107,8 @@ CmpDelayDerefKCBWorker(IN PVOID Context)
|
|||
ASSERT(CmpDelayDerefKCBWorkItemActive);
|
||||
|
||||
/* FIXME: TODO */
|
||||
DPRINT1("CmpDelayDerefKCBWorker has work to do!\n");
|
||||
return;
|
||||
ASSERT(FALSE);
|
||||
}
|
||||
|
||||
|
@ -307,3 +309,4 @@ CmpRemoveFromDelayedClose(IN PCM_KEY_CONTROL_BLOCK Kcb)
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -312,9 +312,10 @@ NTAPI
|
|||
CmpDereferenceNameControlBlockWithLock(IN PCM_NAME_CONTROL_BLOCK Ncb)
|
||||
{
|
||||
PCM_NAME_HASH Current, *Next;
|
||||
ULONG ConvKey = Ncb->ConvKey;
|
||||
|
||||
/* Lock the NCB */
|
||||
CmpAcquireNcbLockExclusive(Ncb);
|
||||
CmpAcquireNcbLockExclusiveByKey(ConvKey);
|
||||
|
||||
/* Decrease the reference count */
|
||||
if (!(--Ncb->RefCount))
|
||||
|
@ -342,7 +343,7 @@ CmpDereferenceNameControlBlockWithLock(IN PCM_NAME_CONTROL_BLOCK Ncb)
|
|||
}
|
||||
|
||||
/* Release the lock */
|
||||
CmpReleaseNcbLock(Ncb);
|
||||
CmpReleaseNcbLockByKey(ConvKey);
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
|
@ -363,13 +364,13 @@ CmpReferenceKeyControlBlock(IN PCM_KEY_CONTROL_BLOCK Kcb)
|
|||
|
||||
/* Increase the reference count while we release the lock */
|
||||
InterlockedIncrement((PLONG)&Kcb->RefCount);
|
||||
|
||||
|
||||
/* Go from shared to exclusive */
|
||||
CmpConvertKcbSharedToExclusive(Kcb);
|
||||
|
||||
/* Decrement the reference count; the lock is now held again */
|
||||
InterlockedDecrement((PLONG)&Kcb->RefCount);
|
||||
|
||||
|
||||
/* Check if we still control the index */
|
||||
if (Kcb->DelayedCloseIndex == 1)
|
||||
{
|
||||
|
@ -387,7 +388,7 @@ CmpReferenceKeyControlBlock(IN PCM_KEY_CONTROL_BLOCK Kcb)
|
|||
}
|
||||
|
||||
/* 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 */
|
||||
InterlockedDecrement((PLONG)&Kcb->RefCount);
|
||||
|
@ -511,9 +512,9 @@ CmpDereferenceKeyControlBlock(IN PCM_KEY_CONTROL_BLOCK Kcb)
|
|||
/* Get the ref count and update it */
|
||||
OldRefCount = *(PLONG)&Kcb->RefCount;
|
||||
NewRefCount = OldRefCount - 1;
|
||||
|
||||
/* Check if we still have refenreces */
|
||||
if( (NewRefCount & 0xffff) > 0)
|
||||
|
||||
/* Check if we still have references */
|
||||
if( (NewRefCount & 0xFFFF) > 0)
|
||||
{
|
||||
/* Do the dereference */
|
||||
if (InterlockedCompareExchange((PLONG)&Kcb->RefCount,
|
||||
|
@ -544,7 +545,7 @@ CmpDereferenceKeyControlBlockWithLock(IN PCM_KEY_CONTROL_BLOCK Kcb,
|
|||
(CmpTestRegistryLockExclusive() == TRUE));
|
||||
|
||||
/* 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 */
|
||||
if (((CmpHoldLazyFlush) &&
|
||||
|
@ -783,7 +784,7 @@ CmpCreateKeyControlBlock(IN PHHIVE Hive,
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Sanity check */
|
||||
ASSERT((!Kcb) || (Kcb->Delete == FALSE));
|
||||
|
||||
|
@ -821,3 +822,4 @@ EnlistKeyBodyWithKCB(IN PCM_KEY_BODY KeyBody,
|
|||
/* FIXME: Implement once we don't link parents to children anymore */
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -782,7 +782,7 @@ CmpCreateLinkNode(IN PHHIVE Hive,
|
|||
/* Release it */
|
||||
HvReleaseCell(Context->ChildHive.KeyHive, ChildCell);
|
||||
|
||||
/* Set the parent adn flags */
|
||||
/* Set the parent and flags */
|
||||
KeyNode->Parent = LinkCell;
|
||||
KeyNode->Flags |= KEY_HIVE_ENTRY | KEY_NO_DELETE;
|
||||
|
||||
|
@ -977,7 +977,6 @@ CmpParseKey2(IN PVOID ParseObject,
|
|||
PULONG LockedKcbs = NULL;
|
||||
BOOLEAN Result, Last;
|
||||
PAGED_CODE();
|
||||
DPRINT1("New style parse routine called: %wZ %wZ!\n", CompleteName, RemainingName);
|
||||
|
||||
/* Loop path separators at the end */
|
||||
while ((RemainingName->Length) &&
|
||||
|
@ -1003,7 +1002,6 @@ CmpParseKey2(IN PVOID ParseObject,
|
|||
|
||||
/* Grab the KCB */
|
||||
Kcb = ((PCM_KEY_BODY)ParseObject)->KeyControlBlock;
|
||||
DPRINT1("KCB Parse: %p\n", Kcb);
|
||||
|
||||
/* Lookup in the cache */
|
||||
Status = CmpBuildHashStackAndLookupCache(ParseObject,
|
||||
|
@ -1019,9 +1017,6 @@ CmpParseKey2(IN PVOID ParseObject,
|
|||
|
||||
/* This is now the parent */
|
||||
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 */
|
||||
if (!TotalRemainingSubkeys) ASSERTMSG("Caching not implemented", FALSE);
|
||||
|
@ -1032,9 +1027,6 @@ CmpParseKey2(IN PVOID ParseObject,
|
|||
/* 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;
|
||||
|
@ -1071,10 +1063,6 @@ CmpParseKey2(IN PVOID ParseObject,
|
|||
/* Couldn't find symlink */
|
||||
Status = STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
}
|
||||
|
||||
/* Not implemented */
|
||||
DPRINT1("Parsing sym link: %lx %wZ %wZ\n", Status,
|
||||
CompleteName, &Current);
|
||||
|
||||
/* We're done */
|
||||
goto Quickie;
|
||||
|
@ -1083,7 +1071,6 @@ CmpParseKey2(IN PVOID ParseObject,
|
|||
/* Get the key node */
|
||||
Node = (PCM_KEY_NODE)HvGetCell(Hive, Cell);
|
||||
if (!Node) return STATUS_INSUFFICIENT_RESOURCES;
|
||||
DPRINT1("Node Parse: %p\n", Node);
|
||||
|
||||
/* Start parsing */
|
||||
Status = STATUS_NOT_IMPLEMENTED;
|
||||
|
@ -1091,7 +1078,6 @@ CmpParseKey2(IN PVOID ParseObject,
|
|||
{
|
||||
/* Get the next component */
|
||||
Result = CmpGetNextName(&Current, &NextName, &Last);
|
||||
DPRINT1("Result Parse: %p\n", Result);
|
||||
if ((Result) && (NextName.Length))
|
||||
{
|
||||
/* See if this is a sym link */
|
||||
|
@ -1099,13 +1085,11 @@ CmpParseKey2(IN PVOID ParseObject,
|
|||
{
|
||||
/* Find the subkey */
|
||||
NextCell = CmpFindSubKeyByName(Hive, Node, &NextName);
|
||||
DPRINT1("NextCell Parse: %lx %wZ\n", NextCell, &NextName);
|
||||
if (NextCell != HCELL_NIL)
|
||||
{
|
||||
/* Get the new node */
|
||||
Cell = NextCell;
|
||||
Node = (PCM_KEY_NODE)HvGetCell(Hive, Cell);
|
||||
DPRINT1("Node Parse: %p\n", Node);
|
||||
if (!Node) ASSERT(FALSE);
|
||||
|
||||
/* Check if this was the last key */
|
||||
|
@ -1115,13 +1099,11 @@ CmpParseKey2(IN PVOID ParseObject,
|
|||
if (Node->Flags & KEY_HIVE_EXIT)
|
||||
{
|
||||
/* Handle it */
|
||||
DPRINT1("Exit node\n");
|
||||
CmpHandleExitNode(&Hive,
|
||||
&Cell,
|
||||
&Node,
|
||||
&HiveToRelease,
|
||||
&CellToRelease);
|
||||
DPRINT1("Node Parse: %p\n", Node);
|
||||
if (!Node) ASSERT(FALSE);
|
||||
}
|
||||
|
||||
|
@ -1139,9 +1121,6 @@ CmpParseKey2(IN PVOID ParseObject,
|
|||
Object);
|
||||
if (Status == STATUS_REPARSE)
|
||||
{
|
||||
DPRINT1("Parsing sym link: %lx %lx\n", Status,
|
||||
CompleteName);
|
||||
|
||||
/* Parse the symlink */
|
||||
if (!CmpGetSymbolicLink(Hive,
|
||||
CompleteName,
|
||||
|
@ -1151,15 +1130,9 @@ CmpParseKey2(IN PVOID ParseObject,
|
|||
/* Symlink parse failed */
|
||||
Status = STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
}
|
||||
|
||||
/* Not implemented */
|
||||
DPRINT1("Parsing sym link: %lx %wZ\n", Status,
|
||||
CompleteName);
|
||||
while (TRUE);
|
||||
}
|
||||
|
||||
/* We are done */
|
||||
DPRINT1("Open of last key\n");
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1167,13 +1140,11 @@ CmpParseKey2(IN PVOID ParseObject,
|
|||
if (Node->Flags & KEY_HIVE_EXIT)
|
||||
{
|
||||
/* Handle it */
|
||||
DPRINT1("Exit node: %lx\n", Node->Flags);
|
||||
CmpHandleExitNode(&Hive,
|
||||
&Cell,
|
||||
&Node,
|
||||
&HiveToRelease,
|
||||
&CellToRelease);
|
||||
DPRINT1("Node Parse: %p\n", Node);
|
||||
if (!Node) ASSERT(FALSE);
|
||||
}
|
||||
|
||||
|
@ -1185,10 +1156,9 @@ CmpParseKey2(IN PVOID ParseObject,
|
|||
0,
|
||||
&NextName);
|
||||
if (!Kcb) ASSERT(FALSE);
|
||||
DPRINT1("Kcb Parse: %p\n", Kcb);
|
||||
|
||||
/* Dereference the parent and set the new one */
|
||||
CmpDereferenceKeyControlBlock(ParentKcb);
|
||||
//CmpDereferenceKeyControlBlock(ParentKcb);
|
||||
ParentKcb = Kcb;
|
||||
}
|
||||
else
|
||||
|
@ -1211,7 +1181,6 @@ CmpParseKey2(IN PVOID ParseObject,
|
|||
ParseContext,
|
||||
ParentKcb,
|
||||
Object);
|
||||
DPRINT1("Link created: %lx\n", Status);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1242,9 +1211,6 @@ CmpParseKey2(IN PVOID ParseObject,
|
|||
}
|
||||
else
|
||||
{
|
||||
DPRINT1("Parsing sym link: %lx %lx\n", Status,
|
||||
CompleteName);
|
||||
|
||||
/* Save the next name */
|
||||
Current.Buffer = NextName.Buffer;
|
||||
|
||||
|
@ -1280,20 +1246,47 @@ CmpParseKey2(IN PVOID ParseObject,
|
|||
/* Couldn't find symlink */
|
||||
Status = STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
}
|
||||
|
||||
/* Not implemented */
|
||||
DPRINT1("Parsing sym link: %lx %wZ %wZ\n", Status,
|
||||
CompleteName, &Current);
|
||||
|
||||
|
||||
/* We're done */
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if ((Result) && (Last))
|
||||
{
|
||||
/* Opening root: unexpected */
|
||||
DPRINT1("Unexpected: Opening root\n");
|
||||
while (TRUE);
|
||||
/* Opening the root. Is this an exit node? */
|
||||
if (Node->Flags & KEY_HIVE_EXIT)
|
||||
{
|
||||
/* 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
|
||||
{
|
||||
|
@ -1305,7 +1298,7 @@ CmpParseKey2(IN PVOID ParseObject,
|
|||
|
||||
/* Dereference the parent if it exists */
|
||||
Quickie:
|
||||
if (ParentKcb) CmpDereferenceKeyControlBlock(ParentKcb);
|
||||
//if (ParentKcb) CmpDereferenceKeyControlBlock(ParentKcb);
|
||||
|
||||
/* Unlock the registry */
|
||||
CmpUnlockRegistry();
|
||||
|
|
|
@ -18,6 +18,25 @@ BOOLEAN CmFirstTime = TRUE;
|
|||
|
||||
/* 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
|
||||
NTAPI
|
||||
NtDeleteKey(IN HANDLE KeyHandle)
|
||||
|
@ -470,28 +489,12 @@ NtFlushKey(IN HANDLE KeyHandle)
|
|||
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
|
||||
NTAPI
|
||||
NtLoadKey(IN POBJECT_ATTRIBUTES KeyObjectAttributes,
|
||||
IN POBJECT_ATTRIBUTES FileObjectAttributes)
|
||||
{
|
||||
/* Call the newer API */
|
||||
return NtLoadKey2(KeyObjectAttributes, FileObjectAttributes, 0);
|
||||
}
|
||||
|
||||
|
@ -501,6 +504,7 @@ NtLoadKey2(IN POBJECT_ATTRIBUTES KeyObjectAttributes,
|
|||
IN POBJECT_ATTRIBUTES FileObjectAttributes,
|
||||
IN ULONG Flags)
|
||||
{
|
||||
/* Call the newer API */
|
||||
return NtLoadKeyEx(KeyObjectAttributes, FileObjectAttributes, Flags, NULL);
|
||||
}
|
||||
|
||||
|
@ -555,6 +559,34 @@ NtLoadKeyEx(IN POBJECT_ATTRIBUTES TargetKey,
|
|||
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
|
||||
NTAPI
|
||||
NtInitializeRegistry(IN USHORT Flag)
|
||||
|
@ -617,6 +649,23 @@ NtInitializeRegistry(IN USHORT Flag)
|
|||
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
|
||||
NTAPI
|
||||
NtLockProductActivationKeys(IN PULONG pPrivateVer,
|
||||
|
@ -653,33 +702,6 @@ NtNotifyChangeMultipleKeys(IN HANDLE MasterKeyHandle,
|
|||
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
|
||||
NTAPI
|
||||
NtQueryMultipleValueKey(IN HANDLE KeyHandle,
|
||||
|
|
|
@ -139,7 +139,6 @@
|
|||
<file>ntapi.c</file>
|
||||
</directory>
|
||||
<directory name="cm">
|
||||
<file>ntfunc.c</file>
|
||||
<file>regobj.c</file>
|
||||
</directory>
|
||||
<directory name="dbgk">
|
||||
|
|
Loading…
Reference in a new issue