IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN ULONG TitleIndex,
- IN PUNICODE_STRING Class,
+ IN PUNICODE_STRING Class OPTIONAL,
IN ULONG CreateOptions,
- OUT PULONG Disposition)
+ OUT PULONG Disposition OPTIONAL)
{
- NTSTATUS Status = STATUS_SUCCESS;
+ NTSTATUS Status;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
CM_PARSE_CONTEXT ParseContext = {0};
HANDLE Handle;
PAGED_CODE();
- DPRINT("NtCreateKey(OB 0x%wZ)\n", ObjectAttributes->ObjectName);
+ DPRINT("NtCreateKey(OB name %wZ)\n", ObjectAttributes->ObjectName);
- /* Prepare to probe parameters */
- _SEH_TRY
+ /* Check for user-mode caller */
+ if (PreviousMode != KernelMode)
{
- /* Check for user-mode caller */
- if (PreviousMode == UserMode)
+ /* Prepare to probe parameters */
+ _SEH2_TRY
{
/* Check if we have a class */
if (Class)
{
/* Probe it */
- ProbeForReadUnicodeString(Class);
+ ParseContext.Class = ProbeForReadUnicodeString(Class);
ProbeForRead(ParseContext.Class.Buffer,
ParseContext.Class.Length,
sizeof(WCHAR));
- ParseContext.Class = *Class;
}
-
+
/* Probe the key handle */
ProbeForWriteHandle(KeyHandle);
*KeyHandle = NULL;
-
+
/* Probe object attributes */
- ProbeForRead(ObjectAttributes, sizeof(OBJECT_ATTRIBUTES), 4);
+ ProbeForRead(ObjectAttributes,
+ sizeof(OBJECT_ATTRIBUTES),
+ sizeof(ULONG));
+
+ if (Disposition) ProbeForWriteUlong(Disposition);
}
- else
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
- /* Save the class directly */
- if (Class) ParseContext.Class = *Class;
+ /* Return the exception code */
+ _SEH2_YIELD(return _SEH2_GetExceptionCode());
}
+ _SEH2_END;
+ }
+ else
+ {
+ /* Save the class directly */
+ if (Class) ParseContext.Class = *Class;
+ }
- /* Setup the parse context */
- ParseContext.CreateOperation = TRUE;
- ParseContext.CreateOptions = CreateOptions;
-
- /* Do the create */
- Status = ObOpenObjectByName(ObjectAttributes,
- CmpKeyObjectType,
- PreviousMode,
- NULL,
- DesiredAccess,
- &ParseContext,
- &Handle);
- if (NT_SUCCESS(Status)) *KeyHandle = Handle;
+ /* Setup the parse context */
+ ParseContext.CreateOperation = TRUE;
+ ParseContext.CreateOptions = CreateOptions;
+
+ /* Do the create */
+ Status = ObOpenObjectByName(ObjectAttributes,
+ CmpKeyObjectType,
+ PreviousMode,
+ NULL,
+ DesiredAccess,
+ &ParseContext,
+ &Handle);
+ _SEH2_TRY
+ {
/* Return data to user */
+ if (NT_SUCCESS(Status)) *KeyHandle = Handle;
if (Disposition) *Disposition = ParseContext.Disposition;
}
- _SEH_HANDLE
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
/* Get the status */
- Status = _SEH_GetExceptionCode();
+ Status = _SEH2_GetExceptionCode();
}
- _SEH_END;
+ _SEH2_END;
/* Return status */
return Status;
{
CM_PARSE_CONTEXT ParseContext = {0};
HANDLE Handle;
- NTSTATUS Status = STATUS_SUCCESS;
+ NTSTATUS Status;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
PAGED_CODE();
DPRINT("NtOpenKey(OB 0x%wZ)\n", ObjectAttributes->ObjectName);
- /* Prepare to probe parameters */
- _SEH_TRY
+ /* Check for user-mode caller */
+ if (PreviousMode != KernelMode)
{
- /* Check for user-mode caller */
- if (PreviousMode == UserMode)
+ /* Prepare to probe parameters */
+ _SEH2_TRY
{
/* Probe the key handle */
ProbeForWriteHandle(KeyHandle);
*KeyHandle = NULL;
/* Probe object attributes */
- ProbeForRead(ObjectAttributes, sizeof(OBJECT_ATTRIBUTES), 4);
+ ProbeForRead(ObjectAttributes,
+ sizeof(OBJECT_ATTRIBUTES),
+ sizeof(ULONG));
}
-
- /* Just let the object manager handle this */
- Status = ObOpenObjectByName(ObjectAttributes,
- CmpKeyObjectType,
- ExGetPreviousMode(),
- NULL,
- DesiredAccess,
- &ParseContext,
- &Handle);
- if (NT_SUCCESS(Status)) *KeyHandle = Handle;
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Return the exception code */
+ _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ }
+ _SEH2_END;
}
- _SEH_HANDLE
+
+ /* Just let the object manager handle this */
+ Status = ObOpenObjectByName(ObjectAttributes,
+ CmpKeyObjectType,
+ ExGetPreviousMode(),
+ NULL,
+ DesiredAccess,
+ &ParseContext,
+ &Handle);
+
+ /* Only do this if we succeeded */
+ if (NT_SUCCESS(Status))
{
- /* Get the status */
- Status = _SEH_GetExceptionCode();
+ _SEH2_TRY
+ {
+ /* Return the handle to caller */
+ *KeyHandle = Handle;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Get the status */
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
}
- _SEH_END;
/* Return status */
return Status;
else
{
/* Call the internal API */
- Status = CmDeleteKey(KeyObject);
+ Status = CmDeleteKey(KeyObject);
}
/* Do post callback */
IN ULONG Length,
OUT PULONG ResultLength)
{
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status;
PCM_KEY_BODY KeyObject;
REG_ENUMERATE_KEY_INFORMATION EnumerateKeyInfo;
NULL);
if (!NT_SUCCESS(Status)) return Status;
+ if (PreviousMode != KernelMode)
+ {
+ _SEH2_TRY
+ {
+ ProbeForWriteUlong(ResultLength);
+ ProbeForWrite(KeyInformation,
+ Length,
+ sizeof(ULONG));
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Dereference and return status */
+ ObDereferenceObject(KeyObject);
+ _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ }
+ _SEH2_END;
+ }
+
/* Setup the callback */
PostOperationInfo.Object = (PVOID)KeyObject;
EnumerateKeyInfo.Object = (PVOID)KeyObject;
IN ULONG Length,
OUT PULONG ResultLength)
{
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status;
PCM_KEY_BODY KeyObject;
REG_ENUMERATE_VALUE_KEY_INFORMATION EnumerateValueKeyInfo;
NULL);
if (!NT_SUCCESS(Status)) return Status;
+ if (PreviousMode != KernelMode)
+ {
+ _SEH2_TRY
+ {
+ ProbeForWriteUlong(ResultLength);
+ ProbeForWrite(KeyValueInformation,
+ Length,
+ sizeof(ULONG));
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Dereference and return status */
+ ObDereferenceObject(KeyObject);
+ _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ }
+ _SEH2_END;
+ }
+
/* Setup the callback */
PostOperationInfo.Object = (PVOID)KeyObject;
EnumerateValueKeyInfo.Object = (PVOID)KeyObject;
IN ULONG Length,
OUT PULONG ResultLength)
{
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status;
PCM_KEY_BODY KeyObject;
REG_QUERY_KEY_INFORMATION QueryKeyInfo;
/* Fail */
return STATUS_INVALID_PARAMETER;
}
-
+
/* Check if just the name is required */
if (KeyInformationClass == KeyNameInformation)
{
(PVOID*)&KeyObject,
NULL);
}
-
+
/* Quit on failure */
if (!NT_SUCCESS(Status)) return Status;
+ if (PreviousMode != KernelMode)
+ {
+ _SEH2_TRY
+ {
+ ProbeForWriteUlong(ResultLength);
+ ProbeForWrite(KeyInformation,
+ Length,
+ sizeof(ULONG));
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Dereference and return status */
+ ObDereferenceObject(KeyObject);
+ _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ }
+ _SEH2_END;
+ }
+
/* Setup the callback */
PostOperationInfo.Object = (PVOID)KeyObject;
QueryKeyInfo.Object = (PVOID)KeyObject;
IN ULONG Length,
OUT PULONG ResultLength)
{
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status;
PCM_KEY_BODY KeyObject;
REG_QUERY_VALUE_KEY_INFORMATION QueryValueKeyInfo;
NULL);
if (!NT_SUCCESS(Status)) return Status;
+ if (PreviousMode != KernelMode)
+ {
+ _SEH2_TRY
+ {
+ ProbeForWriteUlong(ResultLength);
+ ProbeForWrite(KeyValueInformation,
+ Length,
+ sizeof(ULONG));
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Dereference and return status */
+ ObDereferenceObject(KeyObject);
+ _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ }
+ _SEH2_END;
+ }
+
/* Make sure the name is aligned properly */
if ((ValueNameCopy.Length & (sizeof(WCHAR) - 1)))
{
/* Skip it */
ValueNameCopy.Length -= sizeof(WCHAR);
}
-
+
/* Don't touch read-only keys */
if (KeyObject->KeyControlBlock->ExtFlags & CM_KCB_READ_ONLY_KEY)
{
/* Do the callback */
Status = CmiCallRegisteredCallbacks(RegNtPreSetValueKey, &SetValueKeyInfo);
if (NT_SUCCESS(Status))
- {
+ {
/* Call the internal API */
Status = CmSetValueKey(KeyObject->KeyControlBlock,
&ValueNameCopy,
ObDereferenceObject(KeyObject);
return STATUS_ACCESS_DENIED;
}
-
+
/* Make sure the name is aligned properly */
if ((ValueNameCopy.Length & (sizeof(WCHAR) - 1)))
{
NTSTATUS Status;
PCM_KEY_BODY KeyObject;
PAGED_CODE();
-
+
/* Get the key object */
Status = ObReferenceObjectByHandle(KeyHandle,
0,
(PVOID*)&KeyObject,
NULL);
if (!NT_SUCCESS(Status)) return Status;
-
+
/* Lock the registry */
CmpLockRegistry();
-
+
/* Lock the KCB */
CmpAcquireKcbLockShared(KeyObject->KeyControlBlock);
-
+
/* Make sure KCB isn't deleted */
if (KeyObject->KeyControlBlock->Delete)
{
/* Call the internal API */
Status = CmFlushKey(KeyObject->KeyControlBlock, FALSE);
}
-
+
/* Release the locks */
CmpReleaseKcbLock(KeyObject->KeyControlBlock);
CmpUnlockRegistry();
-
+
/* Dereference the object and return status */
ObDereferenceObject(KeyObject);
return Status;
IN POBJECT_ATTRIBUTES FileObjectAttributes)
{
/* Call the newer API */
- return NtLoadKey2(KeyObjectAttributes, FileObjectAttributes, 0);
+ return NtLoadKeyEx(KeyObjectAttributes, FileObjectAttributes, 0, NULL);
}
NTSTATUS
/* Validate flags */
if (Flags & ~REG_NO_LAZY_FLUSH) return STATUS_INVALID_PARAMETER;
-
+
/* Validate privilege */
if (!SeSinglePrivilegeCheck(SeRestorePrivilege, PreviousMode))
{
DPRINT1("Restore Privilege missing!\n");
return STATUS_PRIVILEGE_NOT_HELD;
}
-
+
/* Block APCs */
KeEnterCriticalRegion();
-
+
/* Check if we have a trust class */
if (TrustClassKey)
{
(PVOID *)&KeyBody,
NULL);
}
-
+
/* Call the internal API */
Status = CmLoadKey(TargetKey, SourceFile, Flags, KeyBody);
-
+
/* Dereference the trust key, if any */
if (KeyBody) ObDereferenceObject(KeyBody);
-
+
/* Bring back APCs */
KeLeaveCriticalRegion();
-
+
/* Return status */
return Status;
}
/* Always do this as kernel mode */
if (KeGetPreviousMode() == UserMode) return ZwInitializeRegistry(Flag);
-
+
/* Validate flag */
if (Flag > CM_BOOT_FLAG_MAX) return STATUS_INVALID_PARAMETER;
/* Only allow once */
if (!CmBootAcceptFirstTime) return STATUS_ACCESS_DENIED;
CmBootAcceptFirstTime = FALSE;
-
+
/* Get the control set accepted */
Flag -= CM_BOOT_FLAG_ACCEPTED;
if (Flag)
{
/* FIXME: Save the last known good boot */
//Status = CmpSaveBootControlSet(Flag);
-
+
/* Notify HAL */
HalEndOfBoot();
/* Otherwise, invalid boot */
return STATUS_INVALID_PARAMETER;
}
-
+
/* Check if this was a setup boot */
SetupBoot = (Flag == CM_BOOT_FLAG_SETUP ? TRUE : FALSE);
/* Make sure we're only called once */
if (!CmFirstTime) return STATUS_ACCESS_DENIED;
CmFirstTime = FALSE;
-
+
/* Acquire registry lock */
//CmpLockRegistryExclusive();
NTSTATUS
NTAPI
NtQueryOpenSubKeys(IN POBJECT_ATTRIBUTES TargetKey,
- IN ULONG HandleCount)
+ OUT PULONG HandleCount)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
NTAPI
NtUnloadKey(IN POBJECT_ATTRIBUTES KeyObjectAttributes)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ return NtUnloadKey2(KeyObjectAttributes, 0);
}
NTSTATUS
NtUnloadKey2(IN POBJECT_ATTRIBUTES TargetKey,
IN ULONG Flags)
{
+#if 0
+ NTSTATUS Status;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING ObjectName;
+ CM_PARSE_CONTEXT ParseContext = {0};
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+ PCM_KEY_BODY KeyBody = NULL;
+ ULONG ParentConv = 0, ChildConv = 0;
+ HANDLE Handle;
+ PAGED_CODE();
+
+ /* Validate privilege */
+ if (!SeSinglePrivilegeCheck(SeRestorePrivilege, PreviousMode))
+ {
+ /* Fail */
+ DPRINT1("Restore Privilege missing!\n");
+ return STATUS_PRIVILEGE_NOT_HELD;
+ }
+
+ /* Check for user-mode caller */
+ if (PreviousMode != KernelMode)
+ {
+ /* Prepare to probe parameters */
+ _SEH2_TRY
+ {
+ /* Probe object attributes */
+ ProbeForRead(TargetKey,
+ sizeof(OBJECT_ATTRIBUTES),
+ sizeof(ULONG));
+
+ ObjectAttributes = *TargetKey;
+
+ /* Probe the string */
+ ProbeForReadUnicodeString(&TargetKey->ObjectName);
+
+ ObjectName = *TargetKey->ObjectName;
+
+ ProbeForRead(ObjectName.Buffer,
+ ObjectName.Length,
+ sizeof(WCHAR));
+
+ ObjectAttributes.ObjectName = &ObjectName;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Return the exception code */
+ _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ }
+ _SEH2_END;
+ }
+ else
+ {
+ /* Save the target attributes directly */
+ ObjectAttributes = *TargetKey;
+ }
+
+ /* Setup the parse context */
+ ParseContext.CreateOperation = TRUE;
+ ParseContext.CreateOptions = REG_OPTION_BACKUP_RESTORE;
+
+ /* Do the create */
+ Status = ObOpenObjectByName(&ObjectAttributes,
+ CmpKeyObjectType,
+ KernelMode,
+ NULL,
+ KEY_WRITE,
+ &ParseContext,
+ &Handle);
+
+ /* Return if failure encountered */
+ if (!NT_SUCCESS(Status)) return Status;
+
+ /* Reference it */
+ Status = ObReferenceObjectByHandle(Handle,
+ KEY_WRITE,
+ CmpKeyObjectType,
+ KernelMode,
+ (PVOID *)&KeyBody,
+ NULL);
+
+ /* Close the handle */
+ ZwClose(Handle);
+
+ /* Return if failure encountered */
+ if (!NT_SUCCESS(Status)) return Status;
+
+ /* Acquire the lock depending on flags */
+ if (Flags == REG_FORCE_UNLOAD)
+ {
+ /* Lock registry exclusively */
+ CmpLockRegistryExclusive();
+ }
+ else
+ {
+ /* Lock registry */
+ CmpLockRegistry();
+
+ /* Acquire the hive loading lock */
+ ExAcquirePushLockExclusive(&CmpLoadHiveLock);
+
+ /* Lock parent and child */
+ if (KeyBody->KeyControlBlock->ParentKcb)
+ ParentConv = KeyBody->KeyControlBlock->ParentKcb->ConvKey;
+ else
+ ParentConv = KeyBody->KeyControlBlock->ConvKey;
+
+ ChildConv = KeyBody->KeyControlBlock->ConvKey;
+
+ CmpAcquireTwoKcbLocksExclusiveByKey(ChildConv, ParentConv);
+ }
+
+ /* Check if it's being deleted already */
+ if (KeyBody->KeyControlBlock->Delete)
+ {
+ /* Return appropriate status */
+ Status = STATUS_KEY_DELETED;
+ goto Quickie;
+ }
+
+ /* Check if it's a readonly key */
+ if (KeyBody->KeyControlBlock->ExtFlags & CM_KCB_READ_ONLY_KEY)
+ {
+ /* Return appropriate status */
+ Status = STATUS_ACCESS_DENIED;
+ goto Quickie;
+ }
+
+ /* Call the internal API */
+ Status = CmUnloadKey(KeyBody->KeyControlBlock,
+ Flags);
+
+ /* Check if we failed, but really need to succeed */
+ if ((Status == STATUS_CANNOT_DELETE) && (Flags == REG_FORCE_UNLOAD))
+ {
+ /* TODO: We should perform another attempt here */
+ ASSERT(FALSE);
+ }
+
+ /* If CmUnloadKey failed we need to unlock registry ourselves */
+ if (!NT_SUCCESS(Status))
+ {
+ if (Flags != REG_FORCE_UNLOAD)
+ {
+ /* Release the hive loading lock */
+ ExReleasePushLockExclusive(&CmpLoadHiveLock);
+
+ /* Release two KCBs lock */
+ CmpReleaseTwoKcbLockByKey(ChildConv, ParentConv);
+ }
+
+ /* Unlock the registry */
+ CmpUnlockRegistry();
+ }
+
+Quickie:
+ /* Dereference the key */
+ ObDereferenceObject(KeyBody);
+
+ /* Return status */
+ return Status;
+#else
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
+#endif
}
NTSTATUS