Author: fireball
Date: Mon Aug 10 15:44:54 2009
New Revision: 42591
URL: 
http://svn.reactos.org/svn/reactos?rev=42591&view=rev
Log:
- Make NtUnloadKey call a newer version of the NTAPI - NtUnloadKey2.
- Implement NtUnloadKey2 as a wrapper around internal CM API - CmUnloadKey.
- Stub CmUnloadKey.
- Fix a typo in ps/process.c comments.
Modified:
    trunk/reactos/ntoskrnl/config/cmapi.c
    trunk/reactos/ntoskrnl/config/ntapi.c
    trunk/reactos/ntoskrnl/ps/process.c
Modified: trunk/reactos/ntoskrnl/config/cmapi.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/config/cmapi.c?re…
==============================================================================
--- trunk/reactos/ntoskrnl/config/cmapi.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/config/cmapi.c [iso-8859-1] Mon Aug 10 15:44:54 2009
@@ -1493,3 +1493,12 @@
     if (KeyHandle) ZwClose(KeyHandle);
     return Status;
 }
+
+NTSTATUS
+NTAPI
+CmUnloadKey(IN PCM_KEY_CONTROL_BLOCK Kcb,
+            IN ULONG Flags)
+{
+    UNIMPLEMENTED;
+    return STATUS_NOT_IMPLEMENTED;
+}
Modified: trunk/reactos/ntoskrnl/config/ntapi.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/config/ntapi.c?re…
==============================================================================
--- trunk/reactos/ntoskrnl/config/ntapi.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/config/ntapi.c [iso-8859-1] Mon Aug 10 15:44:54 2009
@@ -1122,8 +1122,7 @@
 NTAPI
 NtUnloadKey(IN POBJECT_ATTRIBUTES KeyObjectAttributes)
 {
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
+    return NtUnloadKey2(KeyObjectAttributes, 0);
 }
 NTSTATUS
@@ -1131,8 +1130,166 @@
 NtUnloadKey2(IN POBJECT_ATTRIBUTES TargetKey,
              IN ULONG Flags)
 {
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
+    NTSTATUS Status = STATUS_SUCCESS;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    UNICODE_STRING ObjectName;
+    CM_PARSE_CONTEXT ParseContext = {0};
+    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+    PCM_KEY_BODY KeyBody = NULL;
+    ULONG ParentConv = 0, ChildConv = 0;
+    HANDLE Handle;
+    PAGED_CODE();
+
+    /* Validate privilege */
+    if (!SeSinglePrivilegeCheck(SeRestorePrivilege, PreviousMode))
+    {
+        /* Fail */
+        DPRINT1("Restore Privilege missing!\n");
+        return STATUS_PRIVILEGE_NOT_HELD;
+    }
+
+    /* Check for user-mode caller */
+    if (PreviousMode != KernelMode)
+    {
+        /* Prepare to probe parameters */
+        _SEH2_TRY
+        {
+            /* Probe object attributes */
+            ProbeForRead(TargetKey,
+                         sizeof(OBJECT_ATTRIBUTES),
+                         sizeof(ULONG));
+
+            ObjectAttributes = *TargetKey;
+
+            /* Probe the string */
+            ProbeForReadUnicodeString(&TargetKey->ObjectName);
+
+            ObjectName = *TargetKey->ObjectName;
+
+            ProbeForRead(ObjectName.Buffer,
+                         ObjectName.Length,
+                         sizeof(WCHAR));
+
+            ObjectAttributes.ObjectName = &ObjectName;
+        }
+        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+        {
+            /* Get the error code */
+            Status = _SEH2_GetExceptionCode();
+        }
+        _SEH2_END;
+        if(!NT_SUCCESS(Status)) return Status;
+    }
+    else
+    {
+        /* Save the target attributes directly */
+        ObjectAttributes = *TargetKey;
+    }
+
+    /* Setup the parse context */
+    ParseContext.CreateOperation = TRUE;
+    ParseContext.CreateOptions = REG_OPTION_BACKUP_RESTORE;
+
+    /* Do the create */
+    Status = ObOpenObjectByName(&ObjectAttributes,
+                                CmpKeyObjectType,
+                                KernelMode,
+                                NULL,
+                                KEY_WRITE,
+                                &ParseContext,
+                                &Handle);
+
+    /* Return if failure encountered */
+    if (!NT_SUCCESS(Status)) return Status;
+
+    /* Reference it */
+    Status = ObReferenceObjectByHandle(Handle,
+                                       KEY_WRITE,
+                                       CmpKeyObjectType,
+                                       KernelMode,
+                                       (PVOID *)&KeyBody,
+                                       NULL);
+
+    /* Close the handle */
+    ZwClose(Handle);
+
+    /* Return if failure encountered */
+    if (!NT_SUCCESS(Status)) return Status;
+
+    /* Acquire the lock depending on flags */
+    if (Flags == REG_FORCE_UNLOAD)
+    {
+        /* Lock registry exclusively */
+        CmpLockRegistryExclusive();
+    }
+    else
+    {
+        /* Lock registry */
+        CmpLockRegistry();
+
+        /* Acquire the hive loading lock */
+        ExAcquirePushLockExclusive(&CmpLoadHiveLock);
+
+        /* Lock parent and child */
+        if (KeyBody->KeyControlBlock->ParentKcb)
+            ParentConv = KeyBody->KeyControlBlock->ParentKcb->ConvKey;
+        else
+            ParentConv = KeyBody->KeyControlBlock->ConvKey;
+
+        ChildConv = KeyBody->KeyControlBlock->ConvKey;
+
+        CmpAcquireTwoKcbLocksExclusiveByKey(ChildConv, ParentConv);
+    }
+
+    /* Check if it's being deleted already */
+    if (KeyBody->KeyControlBlock->Delete)
+    {
+        /* Return appropriate status */
+        Status = STATUS_KEY_DELETED;
+        goto Quickie;
+    }
+
+    /* Check if it's a readonly key */
+    if (KeyBody->KeyControlBlock->ExtFlags & CM_KCB_READ_ONLY_KEY)
+    {
+        /* Return appropriate status */
+        Status = STATUS_ACCESS_DENIED;
+        goto Quickie;
+    }
+
+    /* Call the internal API */
+    Status = CmUnloadKey(KeyBody->KeyControlBlock,
+                         Flags);
+
+    /* Check if we failed, but really need to succeed */
+    if ((Status == STATUS_CANNOT_DELETE) && (Flags == REG_FORCE_UNLOAD))
+    {
+        /* TODO: We should perform another attempt here */
+        ASSERT(FALSE);
+    }
+
+    /* If CmUnloadKey failed we need to unlock registry ourselves */
+    if (!NT_SUCCESS(Status))
+    {
+        if (Flags != REG_FORCE_UNLOAD)
+        {
+            /* Release the hive loading lock */
+            ExReleasePushLockExclusive(&CmpLoadHiveLock);
+
+            /* Release two KCBs lock */
+            CmpReleaseTwoKcbLockByKey(ChildConv, ParentConv);
+        }
+
+        /* Unlock the registry */
+        CmpUnlockRegistry();
+    }
+
+Quickie:
+    /* Dereference the key */
+    ObDereferenceObject(KeyBody);
+
+    /* Return status */
+    return Status;
 }
 NTSTATUS
Modified: trunk/reactos/ntoskrnl/ps/process.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ps/process.c?rev=…
==============================================================================
--- trunk/reactos/ntoskrnl/ps/process.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ps/process.c [iso-8859-1] Mon Aug 10 15:44:54 2009
@@ -451,7 +451,7 @@
     /* Check if we have a parent */
     if (Parent)
     {
-        /* Ineherit PID and Hard Error Processing */
+        /* Inherit PID and Hard Error Processing */
         Process->InheritedFromUniqueProcessId = Parent->UniqueProcessId;
         Process->DefaultHardErrorProcessing = Parent->
                                               DefaultHardErrorProcessing;