mirror of
https://github.com/reactos/reactos.git
synced 2024-12-27 09:34:43 +00:00
implemented RegCopyTreeW() (untested!)
svn path=/trunk/; revision=18026
This commit is contained in:
parent
5681e54736
commit
5f8c990b41
1 changed files with 289 additions and 5 deletions
|
@ -319,10 +319,294 @@ RegCloseKey (HKEY hKey)
|
|||
}
|
||||
|
||||
|
||||
static NTSTATUS
|
||||
RegpCopyTree(IN HKEY hKeySrc,
|
||||
IN HKEY hKeyDest)
|
||||
{
|
||||
typedef struct
|
||||
{
|
||||
LIST_ENTRY ListEntry;
|
||||
HANDLE hKeySrc;
|
||||
HANDLE hKeyDest;
|
||||
} REGP_COPY_KEYS, *PREGP_COPY_KEYS;
|
||||
|
||||
LIST_ENTRY copyQueueHead;
|
||||
PREGP_COPY_KEYS copyKeys, newCopyKeys;
|
||||
union
|
||||
{
|
||||
KEY_VALUE_FULL_INFORMATION *KeyValue;
|
||||
KEY_NODE_INFORMATION *KeyNode;
|
||||
PVOID Buffer;
|
||||
} Info;
|
||||
ULONG Index, BufferSizeRequired, BufferSize = 0x200;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
NTSTATUS Status2 = STATUS_SUCCESS;
|
||||
|
||||
InitializeListHead(©QueueHead);
|
||||
|
||||
Info.Buffer = RtlAllocateHeap(ProcessHeap,
|
||||
0,
|
||||
BufferSize);
|
||||
if (Info.Buffer == NULL)
|
||||
{
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
copyKeys = RtlAllocateHeap(ProcessHeap,
|
||||
0,
|
||||
sizeof(REGP_COPY_KEYS));
|
||||
if (copyKeys != NULL)
|
||||
{
|
||||
copyKeys->hKeySrc = hKeySrc;
|
||||
copyKeys->hKeyDest = hKeyDest;
|
||||
InsertHeadList(©QueueHead,
|
||||
©Keys->ListEntry);
|
||||
|
||||
/* FIXME - copy security from hKeySrc to hKeyDest or just for the subkeys? */
|
||||
|
||||
do
|
||||
{
|
||||
copyKeys = CONTAINING_RECORD(copyQueueHead.Flink,
|
||||
REGP_COPY_KEYS,
|
||||
ListEntry);
|
||||
|
||||
/* enumerate all values and copy them */
|
||||
Index = 0;
|
||||
for (;;)
|
||||
{
|
||||
Status2 = NtEnumerateValueKey(copyKeys->hKeySrc,
|
||||
Index,
|
||||
KeyValueFullInformation,
|
||||
Info.KeyValue,
|
||||
BufferSize,
|
||||
&BufferSizeRequired);
|
||||
if (NT_SUCCESS(Status2))
|
||||
{
|
||||
UNICODE_STRING ValueName;
|
||||
PVOID Data;
|
||||
|
||||
/* don't use RtlInitUnicodeString as the string is not NULL-terminated! */
|
||||
ValueName.Length = Info.KeyValue->NameLength;
|
||||
ValueName.MaximumLength = ValueName.Length;
|
||||
ValueName.Buffer = Info.KeyValue->Name;
|
||||
|
||||
Data = (PVOID)((ULONG_PTR)Info.KeyValue + Info.KeyValue->DataOffset);
|
||||
|
||||
Status2 = NtSetValueKey(copyKeys->hKeyDest,
|
||||
&ValueName,
|
||||
Info.KeyValue->TitleIndex,
|
||||
Info.KeyValue->Type,
|
||||
Data,
|
||||
Info.KeyValue->DataLength);
|
||||
|
||||
/* don't break, let's try to copy as many values as possible */
|
||||
if (!NT_SUCCESS(Status2) && NT_SUCCESS(Status))
|
||||
{
|
||||
Status = Status2;
|
||||
}
|
||||
|
||||
Index++;
|
||||
}
|
||||
else if (Status2 == STATUS_BUFFER_OVERFLOW)
|
||||
{
|
||||
PVOID Buffer;
|
||||
|
||||
ASSERT(BufferSize < BufferSizeRequired);
|
||||
|
||||
Buffer = RtlReAllocateHeap(ProcessHeap,
|
||||
0,
|
||||
Info.Buffer,
|
||||
BufferSizeRequired);
|
||||
if (Buffer != NULL)
|
||||
{
|
||||
Info.Buffer = Buffer;
|
||||
/* try again */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* don't break, let's try to copy as many values as possible */
|
||||
Status2 = STATUS_INSUFFICIENT_RESOURCES;
|
||||
Index++;
|
||||
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
Status = Status2;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* break to avoid an infinite loop in case of denied access or
|
||||
other errors! */
|
||||
if (Status2 != STATUS_NO_MORE_ENTRIES && NT_SUCCESS(Status))
|
||||
{
|
||||
Status = Status2;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* enumerate all subkeys and open and enqueue them */
|
||||
Index = 0;
|
||||
for (;;)
|
||||
{
|
||||
Status2 = NtEnumerateKey(copyKeys->hKeySrc,
|
||||
Index,
|
||||
KeyNodeInformation,
|
||||
Info.KeyNode,
|
||||
BufferSize,
|
||||
&BufferSizeRequired);
|
||||
if (NT_SUCCESS(Status2))
|
||||
{
|
||||
HANDLE KeyHandle, NewKeyHandle;
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
UNICODE_STRING SubKeyName, ClassName;
|
||||
|
||||
/* don't use RtlInitUnicodeString as the string is not NULL-terminated! */
|
||||
SubKeyName.Length = Info.KeyNode->NameLength;
|
||||
SubKeyName.MaximumLength = SubKeyName.Length;
|
||||
SubKeyName.Buffer = Info.KeyNode->Name;
|
||||
ClassName.Length = Info.KeyNode->ClassLength;
|
||||
ClassName.MaximumLength = ClassName.Length;
|
||||
ClassName.Buffer = (PWSTR)((ULONG_PTR)Info.KeyNode + Info.KeyNode->ClassOffset);
|
||||
|
||||
/* open the subkey with sufficient rights */
|
||||
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&SubKeyName,
|
||||
OBJ_CASE_INSENSITIVE,
|
||||
copyKeys->hKeySrc,
|
||||
NULL);
|
||||
|
||||
Status2 = NtOpenKey(&KeyHandle,
|
||||
KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE,
|
||||
&ObjectAttributes);
|
||||
if (NT_SUCCESS(Status2))
|
||||
{
|
||||
/* FIXME - attempt to query the security information */
|
||||
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&SubKeyName,
|
||||
OBJ_CASE_INSENSITIVE,
|
||||
copyKeys->hKeyDest,
|
||||
NULL);
|
||||
|
||||
Status2 = NtCreateKey(&NewKeyHandle,
|
||||
KEY_ALL_ACCESS,
|
||||
&ObjectAttributes,
|
||||
Info.KeyNode->TitleIndex,
|
||||
&ClassName,
|
||||
0,
|
||||
NULL);
|
||||
if (NT_SUCCESS(Status2))
|
||||
{
|
||||
newCopyKeys = RtlAllocateHeap(ProcessHeap,
|
||||
0,
|
||||
sizeof(REGP_COPY_KEYS));
|
||||
if (newCopyKeys != NULL)
|
||||
{
|
||||
/* save the handles and enqueue the subkey */
|
||||
newCopyKeys->hKeySrc = KeyHandle;
|
||||
newCopyKeys->hKeyDest = NewKeyHandle;
|
||||
InsertTailList(©QueueHead,
|
||||
&newCopyKeys->ListEntry);
|
||||
}
|
||||
else
|
||||
{
|
||||
NtClose(KeyHandle);
|
||||
NtClose(NewKeyHandle);
|
||||
|
||||
Status2 = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto GoNextKey;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NtClose(KeyHandle);
|
||||
}
|
||||
}
|
||||
|
||||
GoNextKey:
|
||||
if (!NT_SUCCESS(Status2) && NT_SUCCESS(Status))
|
||||
{
|
||||
Status = Status2;
|
||||
}
|
||||
|
||||
Index++;
|
||||
}
|
||||
else if (Status2 == STATUS_BUFFER_OVERFLOW)
|
||||
{
|
||||
PVOID Buffer;
|
||||
|
||||
ASSERT(BufferSize < BufferSizeRequired);
|
||||
|
||||
Buffer = RtlReAllocateHeap(ProcessHeap,
|
||||
0,
|
||||
Info.Buffer,
|
||||
BufferSizeRequired);
|
||||
if (Buffer != NULL)
|
||||
{
|
||||
Info.Buffer = Buffer;
|
||||
/* try again */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* don't break, let's try to copy as many keys as possible */
|
||||
Status2 = STATUS_INSUFFICIENT_RESOURCES;
|
||||
Index++;
|
||||
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
Status = Status2;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* break to avoid an infinite loop in case of denied access or
|
||||
other errors! */
|
||||
if (Status2 != STATUS_NO_MORE_ENTRIES && NT_SUCCESS(Status))
|
||||
{
|
||||
Status = Status2;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* close the handles and remove the entry from the list */
|
||||
if (copyKeys->hKeySrc != hKeySrc)
|
||||
{
|
||||
NtClose(copyKeys->hKeySrc);
|
||||
}
|
||||
if (copyKeys->hKeyDest != hKeyDest)
|
||||
{
|
||||
NtClose(copyKeys->hKeyDest);
|
||||
}
|
||||
|
||||
RemoveEntryList(©Keys->ListEntry);
|
||||
|
||||
RtlFreeHeap(ProcessHeap,
|
||||
0,
|
||||
copyKeys);
|
||||
} while (!IsListEmpty(©QueueHead));
|
||||
}
|
||||
else
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
RtlFreeHeap(ProcessHeap,
|
||||
0,
|
||||
Info.Buffer);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************
|
||||
* RegCopyTreeW
|
||||
*
|
||||
* @unimplemented
|
||||
* @implemented
|
||||
*/
|
||||
LONG STDCALL
|
||||
RegCopyTreeW(IN HKEY hKeySrc,
|
||||
|
@ -361,7 +645,7 @@ RegCopyTreeW(IN HKEY hKeySrc,
|
|||
NULL);
|
||||
|
||||
Status = NtOpenKey(&SubKeyHandle,
|
||||
KEY_READ,
|
||||
KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE,
|
||||
&ObjectAttributes);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
|
@ -373,8 +657,8 @@ RegCopyTreeW(IN HKEY hKeySrc,
|
|||
else
|
||||
CurKey = KeyHandle;
|
||||
|
||||
/* FIXME - copy all keys and values recursively */
|
||||
Status = STATUS_NOT_IMPLEMENTED;
|
||||
Status = RegpCopyTree(CurKey,
|
||||
hKeyDest);
|
||||
|
||||
if (SubKeyHandle != NULL)
|
||||
{
|
||||
|
@ -1135,7 +1419,7 @@ SubKeyFailureNoFree:
|
|||
NtClose(delKeys->KeyHandle);
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* don't break, let's try to delete as many keys as possible */
|
||||
Status = Status2;
|
||||
|
|
Loading…
Reference in a new issue