CM_PARSE_CONTEXT ParseContext = {0};
HANDLE Handle;
PAGED_CODE();
- DPRINT("NtCreateKey(OB name %wZ)\n", ObjectAttributes->ObjectName);
+
+ DPRINT("NtCreateKey(Path: %wZ, Root %x, Access: %x, CreateOptions %x)\n",
+ ObjectAttributes->ObjectName, ObjectAttributes->RootDirectory,
+ DesiredAccess, CreateOptions);
/* Check for user-mode caller */
if (PreviousMode != KernelMode)
sizeof(OBJECT_ATTRIBUTES),
sizeof(ULONG));
- if (Disposition) ProbeForWriteUlong(Disposition);
+ if (Disposition)
+ ProbeForWriteUlong(Disposition);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
}
_SEH2_END;
+ DPRINT("Returning handle %x, Status %x.\n", Handle, Status);
+
/* Return status */
return Status;
}
NTSTATUS Status;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
PAGED_CODE();
- DPRINT("NtOpenKey(OB 0x%wZ)\n", ObjectAttributes->ObjectName);
+ DPRINT("NtOpenKey(Path: %wZ, Root %x, Access: %x)\n",
+ ObjectAttributes->ObjectName, ObjectAttributes->RootDirectory, DesiredAccess);
/* Check for user-mode caller */
if (PreviousMode != KernelMode)
_SEH2_END;
}
+ DPRINT("Returning handle %x, Status %x.\n", Handle, Status);
+
/* Return status */
return Status;
}
REG_ENUMERATE_KEY_INFORMATION EnumerateKeyInfo;
REG_POST_OPERATION_INFORMATION PostOperationInfo;
PAGED_CODE();
- DPRINT("NtEnumerateKey() KH 0x%x, Index 0x%x, KIC %d, Length %d\n",
+ DPRINT("NtEnumerateKey() KH 0x%p, Index 0x%x, KIC %d, Length %lu\n",
KeyHandle, Index, KeyInformationClass, Length);
/* Reject classes we don't know about */
/* Dereference and return status */
ObDereferenceObject(KeyObject);
+ DPRINT("Returning status %x.\n", Status);
return Status;
}
REG_ENUMERATE_VALUE_KEY_INFORMATION EnumerateValueKeyInfo;
REG_POST_OPERATION_INFORMATION PostOperationInfo;
PAGED_CODE();
- DPRINT("NtEnumerateValueKey() KH 0x%x, Index 0x%x, KVIC %d, Length %d\n",
+ DPRINT("NtEnumerateValueKey() KH 0x%p, Index 0x%x, KVIC %d, Length %lu\n",
KeyHandle, Index, KeyValueInformationClass, Length);
/* Reject classes we don't know about */
REG_POST_OPERATION_INFORMATION PostOperationInfo;
OBJECT_HANDLE_INFORMATION HandleInfo;
PAGED_CODE();
- DPRINT("NtQueryKey() KH 0x%x, KIC %d, Length %d\n",
+ DPRINT("NtQueryKey() KH 0x%p, KIC %d, Length %lu\n",
KeyHandle, KeyInformationClass, Length);
/* Reject invalid classes */
REG_POST_OPERATION_INFORMATION PostOperationInfo;
UNICODE_STRING ValueNameCopy = *ValueName;
PAGED_CODE();
- DPRINT("NtQueryValueKey() KH 0x%x, VN '%wZ', KVIC %d, Length %d\n",
+ DPRINT("NtQueryValueKey() KH 0x%p, VN '%wZ', KVIC %d, Length %lu\n",
KeyHandle, ValueName, KeyValueInformationClass, Length);
/* Verify that the handle is valid and is a registry key */
IN PVOID Data,
IN ULONG DataSize)
{
- NTSTATUS Status;
- PCM_KEY_BODY KeyObject;
+ NTSTATUS Status = STATUS_SUCCESS;
+ PCM_KEY_BODY KeyObject = NULL;
REG_SET_VALUE_KEY_INFORMATION SetValueKeyInfo;
REG_POST_OPERATION_INFORMATION PostOperationInfo;
- UNICODE_STRING ValueNameCopy = *ValueName;
+ UNICODE_STRING ValueNameCopy;
+ KPROCESSOR_MODE PreviousMode;
+
PAGED_CODE();
- DPRINT("NtSetValueKey() KH 0x%x, VN '%wZ', TI %x, T %d, DS %d\n",
- KeyHandle, ValueName, TitleIndex, Type, DataSize);
+
+ PreviousMode = ExGetPreviousMode();
+
+ if (!DataSize)
+ Data = NULL;
+
+ /* Probe and copy the data */
+ if ((PreviousMode != KernelMode) && Data)
+ {
+ PVOID DataCopy = ExAllocatePoolWithTag(PagedPool, DataSize, TAG_CM);
+ if (!DataCopy)
+ return STATUS_NO_MEMORY;
+ _SEH2_TRY
+ {
+ ProbeForRead(Data, DataSize, 1);
+ RtlCopyMemory(DataCopy, Data, DataSize);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+
+ if (!NT_SUCCESS(Status))
+ {
+ ExFreePoolWithTag(DataCopy, TAG_CM);
+ return Status;
+ }
+ Data = DataCopy;
+ }
+
+ /* Capture the string */
+ Status = ProbeAndCaptureUnicodeString(&ValueNameCopy, PreviousMode, ValueName);
+ if (!NT_SUCCESS(Status))
+ goto end;
+
+ DPRINT("NtSetValueKey() KH 0x%p, VN '%wZ', TI %x, T %lu, DS %lu\n",
+ KeyHandle, &ValueNameCopy, TitleIndex, Type, DataSize);
/* Verify that the handle is valid and is a registry key */
Status = ObReferenceObjectByHandle(KeyHandle,
ExGetPreviousMode(),
(PVOID*)&KeyObject,
NULL);
- if (!NT_SUCCESS(Status)) return Status;
+ if (!NT_SUCCESS(Status))
+ goto end;
/* Make sure the name is aligned, not too long, and the data under 4GB */
if ( (ValueNameCopy.Length > 32767) ||
(DataSize > 0x80000000))
{
/* Fail */
- ObDereferenceObject(KeyObject);
- return STATUS_INVALID_PARAMETER;
+ Status = STATUS_INVALID_PARAMETER;
+ goto end;
}
/* Ignore any null characters at the end */
if (KeyObject->KeyControlBlock->ExtFlags & CM_KCB_READ_ONLY_KEY)
{
/* Fail */
- ObDereferenceObject(KeyObject);
- return STATUS_ACCESS_DENIED;
+ Status = STATUS_ACCESS_DENIED;
+ goto end;
}
/* Setup callback */
PostOperationInfo.Object = (PVOID)KeyObject;
SetValueKeyInfo.Object = (PVOID)KeyObject;
- SetValueKeyInfo.ValueName = ValueName;
+ SetValueKeyInfo.ValueName = &ValueNameCopy;
SetValueKeyInfo.TitleIndex = TitleIndex;
SetValueKeyInfo.Type = Type;
SetValueKeyInfo.Data = Data;
PostOperationInfo.Status = Status;
CmiCallRegisteredCallbacks(RegNtPostSetValueKey, &PostOperationInfo);
+end:
/* Dereference and return status */
- ObDereferenceObject(KeyObject);
+ if (KeyObject)
+ ObDereferenceObject(KeyObject);
+ ReleaseCapturedUnicodeString(&ValueNameCopy, PreviousMode);
+ if ((PreviousMode != KernelMode) && Data)
+ ExFreePoolWithTag(Data, TAG_CM);
return Status;
}
NtSaveKey(IN HANDLE KeyHandle,
IN HANDLE FileHandle)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ /* Call the extended API */
+ return NtSaveKeyEx(KeyHandle, FileHandle, REG_STANDARD_FORMAT);
}
NTSTATUS
IN HANDLE FileHandle,
IN ULONG Flags)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ NTSTATUS Status;
+ PCM_KEY_BODY KeyObject;
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+
+ PAGED_CODE();
+
+ DPRINT("NtSaveKeyEx(0x%08X, 0x%08X, %lu)\n", KeyHandle, FileHandle, Flags);
+
+ /* Verify the flags */
+ if ((Flags != REG_STANDARD_FORMAT)
+ && (Flags != REG_LATEST_FORMAT)
+ && (Flags != REG_NO_COMPRESSION))
+ {
+ /* Only one of these values can be specified */
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ /* Check for the SeBackupPrivilege */
+ if (!SeSinglePrivilegeCheck(SeBackupPrivilege, PreviousMode))
+ {
+ return STATUS_PRIVILEGE_NOT_HELD;
+ }
+
+ /* Verify that the handle is valid and is a registry key */
+ Status = ObReferenceObjectByHandle(KeyHandle,
+ KEY_READ,
+ CmpKeyObjectType,
+ PreviousMode,
+ (PVOID*)&KeyObject,
+ NULL);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ /* Call the internal API */
+ Status = CmSaveKey(KeyObject->KeyControlBlock, FileHandle, Flags);
+
+ ObDereferenceObject(KeyObject);
+ return Status;
}
NTSTATUS