IN ULONG CreateOptions,
OUT PULONG Disposition)
{
- UNICODE_STRING RemainingPath;
+ UNICODE_STRING RemainingPath = {0};
+ BOOLEAN FreeRemainingPath = TRUE;
+ ULONG LocalDisposition;
PKEY_OBJECT KeyObject;
- NTSTATUS Status;
- PVOID Object;
+ NTSTATUS Status = STATUS_SUCCESS;
+ PVOID Object = NULL;
PWSTR Start;
UNICODE_STRING ObjectName;
OBJECT_CREATE_INFORMATION ObjectCreateInfo;
unsigned i;
REG_PRE_CREATE_KEY_INFORMATION PreCreateKeyInfo;
REG_POST_CREATE_KEY_INFORMATION PostCreateKeyInfo;
+ KPROCESSOR_MODE PreviousMode;
+ UNICODE_STRING CapturedClass = {0};
+ HANDLE hKey;
PAGED_CODE();
- DPRINT("NtCreateKey (Name %wZ KeyHandle 0x%p Root 0x%p)\n",
- ObjectAttributes->ObjectName,
- KeyHandle,
- ObjectAttributes->RootDirectory);
+ PreviousMode = KeGetPreviousMode();
+
+ if (PreviousMode != KernelMode)
+ {
+ _SEH_TRY
+ {
+ ProbeForWriteHandle(KeyHandle);
+ if (Disposition != NULL)
+ {
+ ProbeForWriteUlong(Disposition);
+ }
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+ }
+
+ if (Class != NULL)
+ {
+ Status = ProbeAndCaptureUnicodeString(&CapturedClass,
+ PreviousMode,
+ Class);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+ }
/* Capture all the info */
DPRINT("Capturing Create Info\n");
Status = ObpCaptureObjectAttributes(ObjectAttributes,
- KeGetPreviousMode(),
+ PreviousMode,
CmiKeyType,
&ObjectCreateInfo,
&ObjectName);
if (!NT_SUCCESS(Status))
{
DPRINT("ObpCaptureObjectAttributes() failed (Status %lx)\n", Status);
- return Status;
+ goto Cleanup;
}
PostCreateKeyInfo.CompleteName = &ObjectName;
if (!NT_SUCCESS(Status))
{
ObpReleaseCapturedAttributes(&ObjectCreateInfo);
- if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
- return Status;
+ goto Cleanup;
}
Status = ObFindObject(&ObjectCreateInfo,
&ObjectName,
- (PVOID*)&Object,
+ (PVOID*)&Object,
&RemainingPath,
CmiKeyType);
ObpReleaseCapturedAttributes(&ObjectCreateInfo);
PostCreateKeyInfo.Object = NULL;
PostCreateKeyInfo.Status = Status;
CmiCallRegisteredCallbacks(RegNtPostCreateKey, &PostCreateKeyInfo);
- if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
+
DPRINT("CmpFindObject failed, Status: 0x%x\n", Status);
- return(Status);
+ goto Cleanup;
}
DPRINT("RemainingPath %wZ\n", &RemainingPath);
/* Fail if the key has been deleted */
if (((PKEY_OBJECT) Object)->Flags & KO_MARKED_FOR_DELETE)
{
- ObDereferenceObject(Object);
- RtlFreeUnicodeString(&RemainingPath);
PostCreateKeyInfo.Object = NULL;
PostCreateKeyInfo.Status = STATUS_UNSUCCESSFUL;
CmiCallRegisteredCallbacks(RegNtPostCreateKey, &PostCreateKeyInfo);
- if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
+
DPRINT("Object marked for delete!\n");
- return(STATUS_UNSUCCESSFUL);
+ Status = STATUS_UNSUCCESSFUL;
+ goto Cleanup;
}
- if (Disposition)
- *Disposition = REG_OPENED_EXISTING_KEY;
-
Status = ObpCreateHandle(PsGetCurrentProcess(),
Object,
DesiredAccess,
TRUE,
- KeyHandle);
+ &hKey);
DPRINT("ObpCreateHandle failed Status 0x%x\n", Status);
- ObDereferenceObject(Object);
- RtlFreeUnicodeString(&RemainingPath);
+
PostCreateKeyInfo.Object = NULL;
PostCreateKeyInfo.Status = Status;
CmiCallRegisteredCallbacks(RegNtPostCreateKey, &PostCreateKeyInfo);
- if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
- return Status;
+
+ LocalDisposition = REG_OPENED_EXISTING_KEY;
+ goto SuccessReturn;
}
/* If RemainingPath contains \ we must return error
{
if (L'\\' == RemainingPath.Buffer[i])
{
- ObDereferenceObject(Object);
- DPRINT1("NtCreateKey() doesn't create trees! (found \'\\\' in remaining path: \"%wZ\"!)\n", &RemainingPath);
- RtlFreeUnicodeString(&RemainingPath);
+ DPRINT("NtCreateKey() doesn't create trees! (found \'\\\' in remaining path: \"%wZ\"!)\n", &RemainingPath);
+
PostCreateKeyInfo.Object = NULL;
PostCreateKeyInfo.Status = STATUS_OBJECT_NAME_NOT_FOUND;
CmiCallRegisteredCallbacks(RegNtPostCreateKey, &PostCreateKeyInfo);
- if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
- return STATUS_OBJECT_NAME_NOT_FOUND;
+
+ Status = STATUS_OBJECT_NAME_NOT_FOUND;
+ goto Cleanup;
}
}
DPRINT("RemainingPath %S ParentObject 0x%p\n", RemainingPath.Buffer, Object);
- Status = ObCreateObject(ExGetPreviousMode(),
+ Status = ObCreateObject(PreviousMode,
CmiKeyType,
NULL,
- ExGetPreviousMode(),
+ PreviousMode,
NULL,
sizeof(KEY_OBJECT),
0,
PostCreateKeyInfo.Object = NULL;
PostCreateKeyInfo.Status = Status;
CmiCallRegisteredCallbacks(RegNtPostCreateKey, &PostCreateKeyInfo);
- if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
- return(Status);
+
+ goto Cleanup;
}
Status = ObInsertObject((PVOID)KeyObject,
DesiredAccess,
0,
NULL,
- KeyHandle);
+ &hKey);
if (!NT_SUCCESS(Status))
{
ObDereferenceObject(KeyObject);
- RtlFreeUnicodeString(&RemainingPath);
DPRINT1("ObInsertObject() failed!\n");
+
PostCreateKeyInfo.Object = NULL;
PostCreateKeyInfo.Status = Status;
CmiCallRegisteredCallbacks(RegNtPostCreateKey, &PostCreateKeyInfo);
- if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
- return(Status);
+
+ goto Cleanup;
}
KeyObject->ParentKey = Object;
KeyObject,
&RemainingPath,
TitleIndex,
- Class,
+ &CapturedClass,
CreateOptions);
if (!NT_SUCCESS(Status))
{
ExReleaseResourceLite(&CmiRegistryLock);
KeLeaveCriticalRegion();
ObDereferenceObject(KeyObject);
- ObDereferenceObject(Object);
- RtlFreeUnicodeString(&RemainingPath);
+
PostCreateKeyInfo.Object = NULL;
PostCreateKeyInfo.Status = STATUS_UNSUCCESSFUL;
CmiCallRegisteredCallbacks(RegNtPostCreateKey, &PostCreateKeyInfo);
- if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
- return STATUS_UNSUCCESSFUL;
+
+ Status = STATUS_UNSUCCESSFUL;
+ goto Cleanup;
}
if (Start == RemainingPath.Buffer)
{
KeyObject->Name = RemainingPath;
+ FreeRemainingPath = FALSE;
}
else
{
RtlpCreateUnicodeString(&KeyObject->Name, Start, NonPagedPool);
- RtlFreeUnicodeString(&RemainingPath);
}
if (KeyObject->RegistryHive == KeyObject->ParentKey->RegistryHive)
KeyObject->KeyCell->SecurityKeyOffset = -1;
/* This key must remain in memory unless it is deleted
or file is unloaded */
- ObReferenceObjectByPointer(KeyObject,
- STANDARD_RIGHTS_REQUIRED,
- NULL,
- UserMode);
+ ObReferenceObject(KeyObject);
}
CmiAddKeyToList(KeyObject->ParentKey, KeyObject);
ExReleaseResourceLite(&CmiRegistryLock);
KeLeaveCriticalRegion();
-
- ObDereferenceObject(Object);
-
- if (Disposition)
- *Disposition = REG_CREATED_NEW_KEY;
-
PostCreateKeyInfo.Object = KeyObject;
PostCreateKeyInfo.Status = Status;
CmiCallRegisteredCallbacks(RegNtPostCreateKey, &PostCreateKeyInfo);
- if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
CmiSyncHives();
+
+ LocalDisposition = REG_CREATED_NEW_KEY;
+
+SuccessReturn:
+ _SEH_TRY
+ {
+ *KeyHandle = hKey;
+ if (Disposition != NULL)
+ {
+ *Disposition = LocalDisposition;
+ }
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+Cleanup:
+ if (Class != NULL)
+ {
+ ReleaseCapturedUnicodeString(&CapturedClass,
+ PreviousMode);
+ }
+ if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
+ if (FreeRemainingPath) RtlFreeUnicodeString(&RemainingPath);
+ if (Object != NULL) ObDereferenceObject(Object);
return Status;
}
ROUND_UP(ValueFullInformation->DataOffset, sizeof(PVOID));
ValueFullInformation->DataLength = ValueCell->DataSize & REG_DATA_SIZE_MASK;
- if (Length - FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name[0]) <
- NameSize)
+ if (Length < ValueFullInformation->DataOffset)
{
NameSize = Length - FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name[0]);
DataSize = 0;
Status = STATUS_BUFFER_OVERFLOW;
CHECKPOINT;
}
- else if (ROUND_UP(Length - FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION,
- Name[0]) - NameSize, sizeof(PVOID)) < DataSize)
+ else if (Length - ValueFullInformation->DataOffset < DataSize)
{
- DataSize = ROUND_UP(Length - FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name[0]) - NameSize, sizeof(PVOID));
+ DataSize = Length - ValueFullInformation->DataOffset;
Status = STATUS_BUFFER_OVERFLOW;
CHECKPOINT;
}
if (!NT_SUCCESS(Status))
{
- DPRINT1("ObReferenceObjectByHandle() failed with status %x\n", Status);
+ DPRINT1("ObReferenceObjectByHandle() failed with status %x %p\n", Status, KeyHandle);
return Status;
}
NTSTATUS Status;
REG_DELETE_VALUE_KEY_INFORMATION DeleteValueKeyInfo;
REG_POST_OPERATION_INFORMATION PostOperationInfo;
+ KPROCESSOR_MODE PreviousMode;
+ UNICODE_STRING CapturedValueName;
PAGED_CODE();
+
+ PreviousMode = KeGetPreviousMode();
/* Verify that the handle is valid and is a registry key */
Status = ObReferenceObjectByHandle(KeyHandle,
- KEY_QUERY_VALUE,
+ KEY_SET_VALUE,
CmiKeyType,
- UserMode,
+ PreviousMode,
(PVOID *)&KeyObject,
NULL);
if (!NT_SUCCESS(Status))
{
return Status;
}
-
+
+ Status = ProbeAndCaptureUnicodeString(&CapturedValueName,
+ PreviousMode,
+ ValueName);
+ if (!NT_SUCCESS(Status))
+ {
+ goto Fail;
+ }
DeleteValueKeyInfo.Object = (PVOID)KeyObject;
- DeleteValueKeyInfo.ValueName = ValueName;
+ DeleteValueKeyInfo.ValueName = &CapturedValueName;
+ /* FIXME - check if value exists before calling the callbacks? */
Status = CmiCallRegisteredCallbacks(RegNtPreDeleteValueKey, &DeleteValueKeyInfo);
if (!NT_SUCCESS(Status))
{
+ ReleaseCapturedUnicodeString(&CapturedValueName,
+ PreviousMode);
+Fail:
ObDereferenceObject(KeyObject);
return Status;
}
ExReleaseResourceLite(&CmiRegistryLock);
KeLeaveCriticalRegion();
+ ReleaseCapturedUnicodeString(&CapturedValueName,
+ PreviousMode);
+
PostOperationInfo.Object = (PVOID)KeyObject;
PostOperationInfo.Status = Status;