mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
implemented RegDeleteTree() (untested!)
svn path=/trunk/; revision=17572
This commit is contained in:
parent
ff8b08beb4
commit
4270d01108
1 changed files with 174 additions and 3 deletions
|
@ -970,10 +970,182 @@ RegDeleteKeyValueA(IN HKEY hKey,
|
|||
}
|
||||
|
||||
|
||||
static NTSTATUS
|
||||
RegpDeleteTree(IN HKEY hKey)
|
||||
{
|
||||
typedef struct
|
||||
{
|
||||
LIST_ENTRY ListEntry;
|
||||
HANDLE KeyHandle;
|
||||
} REGP_DEL_KEYS, *PREG_DEL_KEYS;
|
||||
|
||||
LIST_ENTRY delQueueHead;
|
||||
PREG_DEL_KEYS delKeys = NULL, newDelKeys;
|
||||
HANDLE ProcessHeap;
|
||||
ULONG BufferSize;
|
||||
PKEY_BASIC_INFORMATION BasicInfo;
|
||||
PREG_DEL_KEYS KeyDelRoot;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
NTSTATUS Status2 = STATUS_SUCCESS;
|
||||
|
||||
InitializeListHead(&delQueueHead);
|
||||
|
||||
ProcessHeap = RtlGetProcessHeap();
|
||||
|
||||
/* NOTE: no need to allocate enough memory for an additional KEY_BASIC_INFORMATION
|
||||
structure for the root key, we only do that for subkeys as we need to
|
||||
allocate REGP_DEL_KEYS structures anyway! */
|
||||
KeyDelRoot = RtlAllocateHeap(ProcessHeap,
|
||||
0,
|
||||
sizeof(REGP_DEL_KEYS));
|
||||
if (KeyDelRoot != NULL)
|
||||
{
|
||||
KeyDelRoot->KeyHandle = hKey;
|
||||
InsertTailList(&delQueueHead,
|
||||
&KeyDelRoot->ListEntry);
|
||||
|
||||
do
|
||||
{
|
||||
delKeys = CONTAINING_RECORD(delQueueHead.Flink,
|
||||
REGP_DEL_KEYS,
|
||||
ListEntry);
|
||||
|
||||
BufferSize = 0;
|
||||
BasicInfo = NULL;
|
||||
newDelKeys = NULL;
|
||||
|
||||
ReadFirstSubKey:
|
||||
/* check if this key contains subkeys and delete them first by queuing
|
||||
them at the head of the list */
|
||||
Status2 = NtEnumerateKey(delKeys->KeyHandle,
|
||||
0,
|
||||
KeyBasicInformation,
|
||||
BasicInfo,
|
||||
BufferSize,
|
||||
&BufferSize);
|
||||
|
||||
if (NT_SUCCESS(Status2))
|
||||
{
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
UNICODE_STRING SubKeyName;
|
||||
|
||||
ASSERT(newDelKeys != NULL);
|
||||
ASSERT(BasicInfo != NULL);
|
||||
|
||||
/* don't use RtlInitUnicodeString as the string is not NULL-terminated! */
|
||||
SubKeyName.Length = BasicInfo->NameLength;
|
||||
SubKeyName.MaximumLength = BasicInfo->NameLength;
|
||||
SubKeyName.Buffer = BasicInfo->Name;
|
||||
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&SubKeyName,
|
||||
OBJ_CASE_INSENSITIVE,
|
||||
delKeys->KeyHandle,
|
||||
NULL);
|
||||
|
||||
/* open the subkey */
|
||||
Status2 = NtOpenKey(&newDelKeys->KeyHandle,
|
||||
DELETE | KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE,
|
||||
&ObjectAttributes);
|
||||
if (!NT_SUCCESS(Status2))
|
||||
{
|
||||
goto SubKeyFailure;
|
||||
}
|
||||
|
||||
/* enqueue this key to the head of the deletion queue */
|
||||
InsertHeadList(&delQueueHead,
|
||||
&newDelKeys->ListEntry);
|
||||
|
||||
/* try again from the head of the list */
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Status2 == STATUS_BUFFER_TOO_SMALL)
|
||||
{
|
||||
newDelKeys = RtlAllocateHeap(ProcessHeap,
|
||||
0,
|
||||
BufferSize + sizeof(REGP_DEL_KEYS));
|
||||
if (newDelKeys != NULL)
|
||||
{
|
||||
BasicInfo = (PKEY_BASIC_INFORMATION)(newDelKeys + 1);
|
||||
|
||||
/* try again */
|
||||
goto ReadFirstSubKey;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* don't break, let's try to delete as many keys as possible */
|
||||
Status2 = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto SubKeyFailureNoFree;
|
||||
}
|
||||
}
|
||||
else if (Status2 == STATUS_BUFFER_OVERFLOW)
|
||||
{
|
||||
PREG_DEL_KEYS newDelKeys2;
|
||||
|
||||
ASSERT(newDelKeys != NULL);
|
||||
|
||||
/* we need more memory to query the key name */
|
||||
newDelKeys2 = RtlReAllocateHeap(ProcessHeap,
|
||||
0,
|
||||
newDelKeys,
|
||||
BufferSize + sizeof(REGP_DEL_KEYS));
|
||||
if (newDelKeys2 != NULL)
|
||||
{
|
||||
newDelKeys = newDelKeys2;
|
||||
BasicInfo = (PKEY_BASIC_INFORMATION)(newDelKeys + 1);
|
||||
|
||||
/* try again */
|
||||
goto ReadFirstSubKey;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* don't break, let's try to delete as many keys as possible */
|
||||
Status2 = STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
}
|
||||
SubKeyFailure:
|
||||
RtlFreeHeap(ProcessHeap,
|
||||
0,
|
||||
newDelKeys);
|
||||
SubKeyFailureNoFree:
|
||||
/* don't break, let's try to delete as many keys as possible */
|
||||
if (Status2 != STATUS_NO_MORE_ENTRIES && NT_SUCCESS(Status))
|
||||
{
|
||||
Status = Status2;
|
||||
}
|
||||
}
|
||||
|
||||
Status2 = NtDeleteKey(delKeys->KeyHandle);
|
||||
|
||||
/* NOTE: do NOT close the handle anymore, it's invalid already! */
|
||||
|
||||
if (!NT_SUCCESS(Status2) && NT_SUCCESS(Status))
|
||||
{
|
||||
/* don't break, let's try to delete as many keys as possible */
|
||||
Status = Status2;
|
||||
}
|
||||
|
||||
/* remove the entry from the list */
|
||||
RemoveEntryList(&delKeys->ListEntry);
|
||||
|
||||
RtlFreeHeap(ProcessHeap,
|
||||
0,
|
||||
delKeys);
|
||||
} while (!IsListEmpty(&delQueueHead));
|
||||
}
|
||||
else
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************
|
||||
* RegDeleteTreeW
|
||||
*
|
||||
* @unimplemented
|
||||
* @implemented
|
||||
*/
|
||||
LONG STDCALL
|
||||
RegDeleteTreeW(IN HKEY hKey,
|
||||
|
@ -1016,8 +1188,7 @@ RegDeleteTreeW(IN HKEY hKey,
|
|||
else
|
||||
CurKey = KeyHandle;
|
||||
|
||||
/* FIXME - delete all keys recursively */
|
||||
Status = STATUS_NOT_IMPLEMENTED;
|
||||
Status = RegpDeleteTree(CurKey);
|
||||
|
||||
if (SubKeyHandle != NULL)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue