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 = ExGetPreviousMode();
+
+ 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);
+ DPRINT1("ObpCaptureObjectAttributes() failed (Status %lx)\n", Status);
return Status;
}
Status = CmiCallRegisteredCallbacks(RegNtPreCreateKey, &PreCreateKeyInfo);
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);
if (!NT_SUCCESS(Status))
{
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);
+
+ DPRINT1("CmpFindObject failed, Status: 0x%x\n", 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);
+
+ DPRINT1("Object marked for delete!\n");
+ Status = STATUS_UNSUCCESSFUL;
+ goto Cleanup;
}
- if (Disposition)
- *Disposition = REG_OPENED_EXISTING_KEY;
+ Status = ObpCreateHandle(Object,
+ DesiredAccess,
+ ObjectCreateInfo.Attributes,
+ &hKey);
- Status = ObpCreateHandle(PsGetCurrentProcess(),
- Object,
- DesiredAccess,
- TRUE,
- KeyHandle);
+ if (!NT_SUCCESS(Status))
+ DPRINT1("ObpCreateHandle failed Status 0x%x\n", Status);
- 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))
{
- DPRINT("CmiAddSubKey() failed (Status %lx)\n", Status);
+ DPRINT1("CmiAddSubKey() failed (Status %lx)\n", Status);
/* Release hive lock */
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:
+ ObpReleaseCapturedAttributes(&ObjectCreateInfo);
+ if (Class != NULL)
+ {
+ ReleaseCapturedUnicodeString(&CapturedClass,
+ PreviousMode);
+ }
+ if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
+ if (FreeRemainingPath) RtlFreeUnicodeString(&RemainingPath);
+ if (Object != NULL) ObDereferenceObject(Object);
return Status;
}
Status = ObReferenceObjectByHandle(KeyHandle,
KEY_QUERY_VALUE,
CmiKeyType,
- UserMode,
+ ExGetPreviousMode(),
(PVOID *) &KeyObject,
NULL);
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;
}
UNICODE_STRING RemainingPath;
KPROCESSOR_MODE PreviousMode;
PVOID Object = NULL;
- HANDLE hKey;
+ HANDLE hKey = NULL;
NTSTATUS Status = STATUS_SUCCESS;
UNICODE_STRING ObjectName;
OBJECT_CREATE_INFORMATION ObjectCreateInfo;
(PVOID*)&Object,
&RemainingPath,
CmiKeyType);
- ObpReleaseCapturedAttributes(&ObjectCreateInfo);
if (!NT_SUCCESS(Status))
{
DPRINT("CmpFindObject() returned 0x%08lx\n", Status);
- Status = STATUS_INVALID_HANDLE; /* Because CmpFindObject returns STATUS_UNSUCCESSFUL */
- hKey = *KeyHandle; /* Preserve hkResult value */
+ Status = STATUS_INVALID_HANDLE; /* Because ObFindObject returns STATUS_UNSUCCESSFUL */
goto openkey_cleanup;
}
{
RtlFreeUnicodeString(&RemainingPath);
Status = STATUS_OBJECT_NAME_NOT_FOUND;
- hKey = NULL;
goto openkey_cleanup;
}
if (((PKEY_OBJECT)Object)->Flags & KO_MARKED_FOR_DELETE)
{
Status = STATUS_UNSUCCESSFUL;
- hKey = NULL;
goto openkey_cleanup;
}
- Status = ObpCreateHandle(PsGetCurrentProcess(),
- Object,
- DesiredAccess,
- TRUE,
- &hKey);
-
- if (!NT_SUCCESS(Status))
- hKey = NULL;
+ Status = ObpCreateHandle(Object,
+ DesiredAccess,
+ ObjectCreateInfo.Attributes,
+ &hKey);
openkey_cleanup:
+ ObpReleaseCapturedAttributes(&ObjectCreateInfo);
PostOpenKeyInfo.Object = NT_SUCCESS(Status) ? (PVOID)Object : NULL;
PostOpenKeyInfo.Status = Status;
CmiCallRegisteredCallbacks (RegNtPostOpenKey, &PostOpenKeyInfo);
ObDereferenceObject(Object);
}
- _SEH_TRY
- {
- *KeyHandle = hKey;
- }
- _SEH_HANDLE
+ if (NT_SUCCESS(Status))
{
- Status = _SEH_GetExceptionCode();
+ _SEH_TRY
+ {
+ *KeyHandle = hKey;
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
}
- _SEH_END;
return Status;
}
Status = ObReferenceObjectByHandle(KeyHandle,
(KeyInformationClass != KeyNameInformation ? KEY_QUERY_VALUE : 0),
CmiKeyType,
- UserMode,
+ ExGetPreviousMode(),
(PVOID *) &KeyObject,
NULL);
if (!NT_SUCCESS(Status))
Status = ObReferenceObjectByHandle(KeyHandle,
KEY_QUERY_VALUE,
CmiKeyType,
- UserMode,
+ ExGetPreviousMode(),
(PVOID *)&KeyObject,
NULL);
BLOCK_OFFSET ValueCellOffset;
PDATA_CELL DataCell;
PDATA_CELL NewDataCell;
- PHBIN pBin;
ULONG DesiredAccess;
REG_SET_VALUE_KEY_INFORMATION SetValueKeyInfo;
REG_POST_OPERATION_INFORMATION PostOperationInfo;
+ ULONG DataCellSize;
PAGED_CODE();
DPRINT("ValueCell %p\n", ValueCell);
DPRINT("ValueCell->DataSize %lu\n", ValueCell->DataSize);
+ if (!(ValueCell->DataSize & REG_DATA_IN_OFFSET) &&
+ (ValueCell->DataSize & REG_DATA_SIZE_MASK) != 0)
+ {
+ DataCell = CmiGetCell (RegistryHive, ValueCell->DataOffset, NULL);
+ DataCellSize = (DataCell->CellSize < 0 ? -DataCell->CellSize : DataCell->CellSize) - sizeof(CELL_HEADER);
+ }
+ else
+ {
+ DataCell = NULL;
+ DataCellSize = 0;
+ }
+
+
if (DataSize <= sizeof(BLOCK_OFFSET))
{
/* If data size <= sizeof(BLOCK_OFFSET) then store data in the data offset */
DPRINT("ValueCell->DataSize %lu\n", ValueCell->DataSize);
- if (!(ValueCell->DataSize & REG_DATA_IN_OFFSET) &&
- (ValueCell->DataSize & REG_DATA_SIZE_MASK) != 0)
+ if (DataCell)
{
- DataCell = CmiGetCell (RegistryHive, ValueCell->DataOffset, NULL);
CmiDestroyCell(RegistryHive, DataCell, ValueCell->DataOffset);
}
RtlCopyMemory(&ValueCell->DataOffset, Data, DataSize);
ValueCell->DataSize = DataSize | REG_DATA_IN_OFFSET;
ValueCell->DataType = Type;
- RtlMoveMemory(&ValueCell->DataOffset, Data, DataSize);
CmiMarkBlockDirty(RegistryHive, ValueCellOffset);
}
- else if (!(ValueCell->DataSize & REG_DATA_IN_OFFSET) &&
- (DataSize <= (ValueCell->DataSize & REG_DATA_SIZE_MASK)))
+ else
{
- /* If new data size is <= current then overwrite current data */
- DataCell = CmiGetCell (RegistryHive, ValueCell->DataOffset,&pBin);
- RtlZeroMemory(DataCell->Data, ValueCell->DataSize);
- RtlCopyMemory(DataCell->Data, Data, DataSize);
- ValueCell->DataSize = DataSize;
- ValueCell->DataType = Type;
- }
- else
- {
- /*
- * New data size is larger than the current, destroy current
- * data block and allocate a new one.
- */
- BLOCK_OFFSET NewOffset;
+ if (DataSize > DataCellSize)
+ {
+ /*
+ * New data size is larger than the current, destroy current
+ * data block and allocate a new one.
+ */
+ BLOCK_OFFSET NewOffset;
+
+ DPRINT("ValueCell->DataSize %lu\n", ValueCell->DataSize);
+
+ Status = CmiAllocateCell (RegistryHive,
+ sizeof(CELL_HEADER) + DataSize,
+ (PVOID *)&NewDataCell,
+ &NewOffset);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("CmiAllocateBlock() failed (Status %lx)\n", Status);
- DPRINT("ValueCell->DataSize %lu\n", ValueCell->DataSize);
+ ExReleaseResourceLite(&CmiRegistryLock);
+ KeLeaveCriticalRegion();
+ PostOperationInfo.Status = Status;
+ CmiCallRegisteredCallbacks(RegNtPostSetValueKey, &PostOperationInfo);
+ ObDereferenceObject(KeyObject);
- if (!(ValueCell->DataSize & REG_DATA_IN_OFFSET) &&
- (ValueCell->DataSize & REG_DATA_SIZE_MASK) != 0)
- {
- DataCell = CmiGetCell (RegistryHive, ValueCell->DataOffset, NULL);
- CmiDestroyCell(RegistryHive, DataCell, ValueCell->DataOffset);
- ValueCell->DataSize = 0;
- ValueCell->DataType = 0;
- ValueCell->DataOffset = (BLOCK_OFFSET)-1;
- }
-
- Status = CmiAllocateCell (RegistryHive,
- sizeof(CELL_HEADER) + DataSize,
- (PVOID *)&NewDataCell,
- &NewOffset);
- if (!NT_SUCCESS(Status))
- {
- DPRINT("CmiAllocateBlock() failed (Status %lx)\n", Status);
+ return Status;
+ }
- ExReleaseResourceLite(&CmiRegistryLock);
- KeLeaveCriticalRegion();
- PostOperationInfo.Status = Status;
- CmiCallRegisteredCallbacks(RegNtPostSetValueKey, &PostOperationInfo);
- ObDereferenceObject(KeyObject);
+ if (DataCell)
+ {
+ CmiDestroyCell(RegistryHive, DataCell, ValueCell->DataOffset);
+ }
- return Status;
- }
+ ValueCell->DataOffset = NewOffset;
+ DataCell = NewDataCell;
+ }
- RtlCopyMemory(&NewDataCell->Data[0], Data, DataSize);
+ RtlCopyMemory(DataCell->Data, Data, DataSize);
ValueCell->DataSize = DataSize & REG_DATA_SIZE_MASK;
ValueCell->DataType = Type;
- ValueCell->DataOffset = NewOffset;
CmiMarkBlockDirty(RegistryHive, ValueCell->DataOffset);
CmiMarkBlockDirty(RegistryHive, ValueCellOffset);
}
PAGED_CODE();
- PreviousMode = KeGetPreviousMode();
+ PreviousMode = ExGetPreviousMode();
/* Verify that the handle is valid and is a registry key */
Status = ObReferenceObjectByHandle(KeyHandle,
DPRINT ("NtLoadKey2() called\n");
#if 0
- if (!SeSinglePrivilegeCheck (SeRestorePrivilege, KeGetPreviousMode ()))
+ if (!SeSinglePrivilegeCheck (SeRestorePrivilege, ExGetPreviousMode ()))
return STATUS_PRIVILEGE_NOT_HELD;
#endif
Status = ObReferenceObjectByHandle(KeyHandle,
KEY_QUERY_VALUE,
CmiKeyType,
- UserMode,
+ ExGetPreviousMode(),
(PVOID *) &KeyObject,
NULL);
if (!NT_SUCCESS(Status))
DPRINT ("NtSaveKey() called\n");
#if 0
- if (!SeSinglePrivilegeCheck (SeBackupPrivilege, KeGetPreviousMode ()))
+ if (!SeSinglePrivilegeCheck (SeBackupPrivilege, ExGetPreviousMode ()))
return STATUS_PRIVILEGE_NOT_HELD;
#endif
Status = ObReferenceObjectByHandle (KeyHandle,
0,
CmiKeyType,
- KeGetPreviousMode(),
+ ExGetPreviousMode(),
(PVOID *)&KeyObject,
NULL);
if (!NT_SUCCESS(Status))
Status = ObReferenceObjectByHandle (KeyHandle,
KEY_SET_VALUE,
CmiKeyType,
- UserMode,
+ ExGetPreviousMode(),
(PVOID *)&KeyObject,
NULL);
if (!NT_SUCCESS (Status))
DPRINT ("NtUnloadKey() called\n");
#if 0
- if (!SeSinglePrivilegeCheck (SeRestorePrivilege, KeGetPreviousMode ()))
+ if (!SeSinglePrivilegeCheck (SeRestorePrivilege, ExGetPreviousMode ()))
return STATUS_PRIVILEGE_NOT_HELD;
#endif