📄 reg.c
字号:
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;
}
}
else
{
NtClose(KeyHandle);
}
}
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
*
* @implemented
*/
LONG STDCALL
RegCopyTreeW(IN HKEY hKeySrc,
IN LPCWSTR lpSubKey OPTIONAL,
IN HKEY hKeyDest)
{
HANDLE DestKeyHandle, KeyHandle, CurKey, SubKeyHandle = NULL;
NTSTATUS Status;
Status = MapDefaultKey(&KeyHandle,
hKeySrc);
if (!NT_SUCCESS(Status))
{
return RtlNtStatusToDosError(Status);
}
Status = MapDefaultKey(&DestKeyHandle,
hKeyDest);
if (!NT_SUCCESS(Status))
{
goto Cleanup2;
}
if (lpSubKey != NULL)
{
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING SubKeyName;
RtlInitUnicodeString(&SubKeyName,
(LPWSTR)lpSubKey);
InitializeObjectAttributes(&ObjectAttributes,
&SubKeyName,
OBJ_CASE_INSENSITIVE,
KeyHandle,
NULL);
Status = NtOpenKey(&SubKeyHandle,
KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE,
&ObjectAttributes);
if (!NT_SUCCESS(Status))
{
goto Cleanup;
}
CurKey = SubKeyHandle;
}
else
CurKey = KeyHandle;
Status = RegpCopyTree(CurKey,
hKeyDest);
if (SubKeyHandle != NULL)
{
NtClose(SubKeyHandle);
}
Cleanup:
ClosePredefKey(DestKeyHandle);
Cleanup2:
ClosePredefKey(KeyHandle);
if (!NT_SUCCESS(Status))
{
return RtlNtStatusToDosError(Status);
}
return ERROR_SUCCESS;
}
/************************************************************************
* RegCopyTreeA
*
* @implemented
*/
LONG STDCALL
RegCopyTreeA(IN HKEY hKeySrc,
IN LPCSTR lpSubKey OPTIONAL,
IN HKEY hKeyDest)
{
UNICODE_STRING SubKeyName = {0};
LONG Ret;
if (lpSubKey != NULL &&
!RtlCreateUnicodeStringFromAsciiz(&SubKeyName,
(LPSTR)lpSubKey))
{
return ERROR_NOT_ENOUGH_MEMORY;
}
Ret = RegCopyTreeW(hKeySrc,
SubKeyName.Buffer,
hKeyDest);
RtlFreeUnicodeString(&SubKeyName);
return Ret;
}
/************************************************************************
* RegConnectRegistryA
*
* @implemented
*/
LONG STDCALL
RegConnectRegistryA (IN LPCSTR lpMachineName,
IN HKEY hKey,
OUT PHKEY phkResult)
{
UNICODE_STRING MachineName = {0};
LONG Ret;
if (lpMachineName != NULL &&
!RtlCreateUnicodeStringFromAsciiz(&MachineName,
(LPSTR)lpMachineName))
{
return ERROR_NOT_ENOUGH_MEMORY;
}
Ret = RegConnectRegistryW(MachineName.Buffer,
hKey,
phkResult);
RtlFreeUnicodeString(&MachineName);
return Ret;
}
/************************************************************************
* RegConnectRegistryW
*
* @unimplemented
*/
LONG STDCALL
RegConnectRegistryW (LPCWSTR lpMachineName,
HKEY hKey,
PHKEY phkResult)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return ERROR_CALL_NOT_IMPLEMENTED;
}
/************************************************************************
* CreateNestedKey
*
* Create key and all necessary intermediate keys
*/
static NTSTATUS
CreateNestedKey(PHKEY KeyHandle,
POBJECT_ATTRIBUTES ObjectAttributes,
PUNICODE_STRING ClassString,
DWORD dwOptions,
REGSAM samDesired,
DWORD *lpdwDisposition)
{
OBJECT_ATTRIBUTES LocalObjectAttributes;
UNICODE_STRING LocalKeyName;
ULONG Disposition;
NTSTATUS Status;
ULONG FullNameLength;
ULONG Length;
PWCHAR Ptr;
HANDLE LocalKeyHandle;
Status = NtCreateKey((PHANDLE) KeyHandle,
samDesired,
ObjectAttributes,
0,
ClassString,
dwOptions,
(PULONG)lpdwDisposition);
TRACE("NtCreateKey(%wZ) called (Status %lx)\n", ObjectAttributes->ObjectName, Status);
if (Status != STATUS_OBJECT_NAME_NOT_FOUND)
return Status;
/* Copy object attributes */
RtlCopyMemory (&LocalObjectAttributes,
ObjectAttributes,
sizeof(OBJECT_ATTRIBUTES));
RtlCreateUnicodeString (&LocalKeyName,
ObjectAttributes->ObjectName->Buffer);
LocalObjectAttributes.ObjectName = &LocalKeyName;
FullNameLength = LocalKeyName.Length / sizeof(WCHAR);
/* Remove the last part of the key name and try to create the key again. */
while (Status == STATUS_OBJECT_NAME_NOT_FOUND)
{
Ptr = wcsrchr (LocalKeyName.Buffer, '\\');
if (Ptr == NULL || Ptr == LocalKeyName.Buffer)
{
Status = STATUS_UNSUCCESSFUL;
break;
}
*Ptr = (WCHAR)0;
LocalKeyName.Length = wcslen (LocalKeyName.Buffer) * sizeof(WCHAR);
Status = NtCreateKey (&LocalKeyHandle,
KEY_ALL_ACCESS,
&LocalObjectAttributes,
0,
NULL,
0,
&Disposition);
TRACE("NtCreateKey(%wZ) called (Status %lx)\n", &LocalKeyName, Status);
}
if (!NT_SUCCESS(Status))
{
RtlFreeUnicodeString (&LocalKeyName);
return Status;
}
/* Add removed parts of the key name and create them too. */
Length = wcslen (LocalKeyName.Buffer);
while (TRUE)
{
NtClose (LocalKeyHandle);
LocalKeyName.Buffer[Length] = L'\\';
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -