https://git.reactos.org/?p=reactos.git;a=commitdiff;h=d91a47826e64e6766aae0…
commit d91a47826e64e6766aae069773d4a5470576fe59
Author: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
AuthorDate: Sun Oct 14 15:31:12 2018 +0200
Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
CommitDate: Sun Oct 14 15:59:57 2018 +0200
[MKHIVE] Implement RegDeleteKeyW() and RegDeleteValueW().
---
sdk/tools/mkhive/registry.c | 197 +++++++++++++++++++++++++++++++++++++++++---
1 file changed, 186 insertions(+), 11 deletions(-)
diff --git a/sdk/tools/mkhive/registry.c b/sdk/tools/mkhive/registry.c
index a3cc712184..8fbc7d5b15 100644
--- a/sdk/tools/mkhive/registry.c
+++ b/sdk/tools/mkhive/registry.c
@@ -25,14 +25,12 @@
* Hermès Bélusca-Maïto
*/
-/*
- * TODO:
- * - Implement RegDeleteKeyW() and RegDeleteValueW()
- */
-
#define NDEBUG
#include "mkhive.h"
+#define STATUS_NO_LOG_SPACE ((NTSTATUS)0xC000017D)
+#define STATUS_CANNOT_DELETE ((NTSTATUS)0xC0000121)
+
static CMHIVE RootHive;
static PMEMKEY RootKey;
@@ -533,9 +531,87 @@ RegDeleteKeyW(
IN HKEY hKey,
IN LPCWSTR lpSubKey)
{
- DPRINT1("RegDeleteKeyW(0x%p, '%S') is UNIMPLEMENTED!\n",
- hKey, (lpSubKey ? lpSubKey : L""));
- return ERROR_SUCCESS;
+ LONG rc;
+ HKEY hTargetKey;
+ PMEMKEY Key; // ParentKey
+ PHHIVE Hive;
+ PCM_KEY_NODE KeyNode; // ParentNode
+ PCM_KEY_NODE Parent;
+ HCELL_INDEX ParentCell;
+
+ NTSTATUS Status;
+
+ if (lpSubKey)
+ {
+ rc = RegOpenKeyW(hKey, lpSubKey, &hTargetKey);
+ if (rc != ERROR_SUCCESS)
+ return rc;
+ }
+ else
+ {
+ hTargetKey = hKey;
+ }
+
+ /* Don't allow deleting the root */
+ if (hTargetKey == RootKey)
+ {
+ /* Fail */
+ Status = STATUS_CANNOT_DELETE;
+ goto Quit;
+ }
+
+ /* Get the hive and node */
+ Key = HKEY_TO_MEMKEY(hTargetKey);
+ Hive = &Key->RegistryHive->Hive;
+
+ /* Get the key node */
+ KeyNode = (PCM_KEY_NODE)HvGetCell(Hive, Key->KeyCellOffset);
+ if (!KeyNode)
+ {
+ Status = ERROR_UNSUCCESSFUL;
+ goto Quit;
+ }
+
+ ASSERT(KeyNode->Signature == CM_KEY_NODE_SIGNATURE);
+
+ /* Check if we don't have any children */
+ if (!(KeyNode->SubKeyCounts[Stable] + KeyNode->SubKeyCounts[Volatile])
&&
+ !(KeyNode->Flags & KEY_NO_DELETE))
+ {
+ /* Get the parent and free the cell */
+ ParentCell = KeyNode->Parent;
+ Status = CmpFreeKeyByCell(Hive, Key->KeyCellOffset, TRUE);
+ if (NT_SUCCESS(Status))
+ {
+ /* Get the parent node */
+ Parent = (PCM_KEY_NODE)HvGetCell(Hive, ParentCell);
+ if (Parent)
+ {
+ /* Make sure we're dirty */
+ ASSERT(HvIsCellDirty(Hive, ParentCell));
+
+ /* Update the write time */
+ KeQuerySystemTime(&Parent->LastWriteTime);
+
+ /* Release the cell */
+ HvReleaseCell(Hive, ParentCell);
+ }
+ }
+ }
+ else
+ {
+ /* Fail */
+ Status = STATUS_CANNOT_DELETE;
+ }
+
+ /* Release the cell */
+ HvReleaseCell(Hive, Key->KeyCellOffset);
+
+Quit:
+ if (lpSubKey)
+ RegCloseKey(hTargetKey);
+
+ return Status;
}
LONG WINAPI
@@ -798,9 +874,108 @@ RegDeleteValueW(
IN HKEY hKey,
IN LPCWSTR lpValueName OPTIONAL)
{
- DPRINT1("RegDeleteValueW(0x%p, '%S') is UNIMPLEMENTED!\n",
- hKey, (lpValueName ? lpValueName : L""));
- return ERROR_UNSUCCESSFUL;
+ PMEMKEY Key = HKEY_TO_MEMKEY(hKey); // ParentKey
+ PHHIVE Hive = &Key->RegistryHive->Hive;
+ PCM_KEY_NODE KeyNode; // ParentNode
+ PCM_KEY_VALUE ValueCell;
+ HCELL_INDEX CellIndex;
+ ULONG ChildIndex;
+ UNICODE_STRING ValueNameString;
+
+ NTSTATUS Status;
+
+ KeyNode = (PCM_KEY_NODE)HvGetCell(Hive, Key->KeyCellOffset);
+ if (!KeyNode)
+ return ERROR_UNSUCCESSFUL;
+
+ ASSERT(KeyNode->Signature == CM_KEY_NODE_SIGNATURE);
+
+ /* Initialize value name string */
+ RtlInitUnicodeString(&ValueNameString, lpValueName);
+ if (!CmpFindNameInList(Hive,
+ &KeyNode->ValueList,
+ &ValueNameString,
+ &ChildIndex,
+ &CellIndex))
+ {
+ /* Sanity check */
+ ASSERT(CellIndex == HCELL_NIL);
+ }
+ if (CellIndex == HCELL_NIL)
+ {
+ Status = ERROR_FILE_NOT_FOUND; // STATUS_OBJECT_NAME_NOT_FOUND;
+ goto Quit;
+ }
+
+ /* We found the value, mark all relevant cells dirty */
+ HvMarkCellDirty(Hive, Key->KeyCellOffset, FALSE);
+ HvMarkCellDirty(Hive, KeyNode->ValueList.List, FALSE);
+ HvMarkCellDirty(Hive, CellIndex, FALSE);
+
+ /* Get the key value */
+ ValueCell = (PCM_KEY_VALUE)HvGetCell(Hive, CellIndex);
+ ASSERT(ValueCell);
+
+ /* Mark it and all related data as dirty */
+ if (!CmpMarkValueDataDirty(Hive, ValueCell))
+ {
+ /* Not enough log space, fail */
+ Status = STATUS_NO_LOG_SPACE;
+ goto Quit;
+ }
+
+ /* Sanity checks */
+ ASSERT(HvIsCellDirty(Hive, KeyNode->ValueList.List));
+ ASSERT(HvIsCellDirty(Hive, CellIndex));
+
+ /* Remove the value from the child list */
+ Status = CmpRemoveValueFromList(Hive, ChildIndex, &KeyNode->ValueList);
+ if (!NT_SUCCESS(Status))
+ {
+ /* Set known error */
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto Quit;
+ }
+
+ /* Remove the value and its data itself */
+ if (!CmpFreeValue(Hive, CellIndex))
+ {
+ /* Failed to free the value, fail */
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto Quit;
+ }
+
+ /* Set the last write time */
+ KeQuerySystemTime(&KeyNode->LastWriteTime);
+
+ /* Sanity check */
+ ASSERT(HvIsCellDirty(Hive, Key->KeyCellOffset));
+
+ /* Check if the value list is empty now */
+ if (!KeyNode->ValueList.Count)
+ {
+ /* Then clear key node data */
+ KeyNode->MaxValueNameLen = 0;
+ KeyNode->MaxValueDataLen = 0;
+ }
+
+ /* Change default Status to success */
+ Status = STATUS_SUCCESS;
+
+Quit:
+ /* Check if we had a value */
+ if (ValueCell)
+ {
+ /* Release the child cell */
+ ASSERT(CellIndex != HCELL_NIL);
+ HvReleaseCell(Hive, CellIndex);
+ }
+
+ /* Release the parent cell, if any */
+ if (KeyNode)
+ HvReleaseCell(Hive, Key->KeyCellOffset);
+
+ return Status;
}