- Copy CmOpenHiveFiles to cminit.c and rename to CmpOpenHiveFiles. Extend the functionality of the routine:

- Allow caller to have full power over handles and filenames being used instead of hard-coding a pointer to the registry hive.
  - Setup proper I/O flags to disable compression and open for random access, backup-intent and allow disabling buffering.
  - Allow proper access mask/share mode when booting off read-only media.
  - Call the FS driver with FSCTL_MARK_AS_SYSTEM_HIVE if instructed.
  - Call with FSCTL_SET_COMPRESSION to make sure compression is off.
  - Allow creating the hive if it doesn't exist already.
  - Consider 0-byte opened hives as new hives.
  - Allow caller to request volume sector size and validate with hive cluster size.
  - Make .log hives hidden.
- Implemement CmpCreateEvent to allowed for overlapped I/O registry operations.
- Move more globals to cmdata.c.

svn path=/trunk/; revision=26705
This commit is contained in:
Alex Ionescu 2007-05-11 22:51:11 +00:00
parent 57ddb7b014
commit 47687d1136
7 changed files with 447 additions and 77 deletions

View file

@ -496,6 +496,19 @@ BOOLEAN
NTAPI
CmpCreateRegistryRoot(VOID);
NTSTATUS
NTAPI
CmpOpenHiveFiles(IN PUNICODE_STRING BaseName,
IN PWCHAR Extension OPTIONAL,
IN PHANDLE Primary,
IN PHANDLE Log,
IN PULONG PrimaryDisposition,
IN PULONG LogDisposition,
IN BOOLEAN CreateAllowed,
IN BOOLEAN MarkAsSystemHive,
IN BOOLEAN NoBuffering,
OUT PULONG ClusterSize OPTIONAL);
#if 0
static __inline PVOID xHvGetCell(char *file, int line, PHHIVE Hive, HCELL_INDEX Cell)
{

View file

@ -283,63 +283,6 @@ CmiRemoveRegistryHive(PEREGISTRY_HIVE RegistryHive)
return STATUS_SUCCESS;
}
NTSTATUS
CmOpenHiveFiles(PEREGISTRY_HIVE RegistryHive)
{
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK IoStatusBlock;
NTSTATUS Status;
InitializeObjectAttributes(&ObjectAttributes,
&RegistryHive->HiveFileName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = ZwCreateFile(&RegistryHive->HiveHandle,
FILE_ALL_ACCESS,
&ObjectAttributes,
&IoStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
0,
FILE_OPEN,
FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0);
if (!NT_SUCCESS(Status))
{
return(Status);
}
InitializeObjectAttributes(&ObjectAttributes,
&RegistryHive->LogFileName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = ZwCreateFile(&RegistryHive->LogHandle,
FILE_ALL_ACCESS,
&ObjectAttributes,
&IoStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
0,
FILE_SUPERSEDE,
FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0);
if (!NT_SUCCESS(Status))
{
ZwClose(RegistryHive->HiveHandle);
return(Status);
}
return STATUS_SUCCESS;
}
VOID
CmCloseHiveFiles(PEREGISTRY_HIVE RegistryHive)
{
@ -353,6 +296,7 @@ CmiFlushRegistryHive(PEREGISTRY_HIVE RegistryHive)
{
BOOLEAN Success;
NTSTATUS Status;
ULONG Disposition;
ASSERT(!IsNoFileHive(RegistryHive));
@ -361,7 +305,16 @@ CmiFlushRegistryHive(PEREGISTRY_HIVE RegistryHive)
return(STATUS_SUCCESS);
}
Status = CmOpenHiveFiles(RegistryHive);
Status = CmpOpenHiveFiles(&RegistryHive->HiveFileName,
L".LOG",
&RegistryHive->HiveHandle,
&RegistryHive->LogHandle,
&Disposition,
&Disposition,
FALSE,
FALSE,
TRUE,
NULL);
if (!NT_SUCCESS(Status))
{
return Status;

View file

@ -1007,6 +1007,14 @@ CmpInitializeRegistryNode(
//
// Wrapper Routines
//
NTSTATUS
NTAPI
CmpCreateEvent(
IN EVENT_TYPE EventType,
OUT PHANDLE EventHandle,
OUT PKEVENT *Event
);
PVOID
NTAPI
CmpAllocate(
@ -1060,6 +1068,8 @@ CmpFileFlush(
//
extern BOOLEAN CmpSpecialBootCondition;
extern BOOLEAN CmpFlushOnLockRelease;
extern BOOLEAN CmpShareSystemHives;
extern BOOLEAN CmpMiniNTBoot;
extern EX_PUSH_LOCK CmpHiveListHeadLock;
extern LIST_ENTRY CmpHiveListHead;
extern POBJECT_TYPE CmpKeyObjectType;
@ -1080,6 +1090,14 @@ extern CM_SYSTEM_CONTROL_VECTOR CmControlVector[];
extern ULONG CmpConfigurationAreaSize;
extern PCM_FULL_RESOURCE_DESCRIPTOR CmpConfigurationData;
extern UNICODE_STRING CmTypeName[];
extern HIVE_LIST_ENTRY CmpMachineHiveList[5];
extern UNICODE_STRING CmSymbolicLinkValueName;
extern UNICODE_STRING CmpSystemStartOptions;
extern UNICODE_STRING CmpLoadOptions;
extern BOOLEAN CmSelfHeal;
extern BOOLEAN CmpSelfHeal;
extern ULONG CmpBootType;
extern HANDLE CmpRegistryRootHandle;
extern BOOLEAN ExpInTextModeSetup;
//

View file

@ -38,6 +38,22 @@ PCM_FULL_RESOURCE_DESCRIPTOR CmpConfigurationData;
EX_PUSH_LOCK CmpHiveListHeadLock;
HIVE_LIST_ENTRY CmpMachineHiveList[5];
UNICODE_STRING CmSymbolicLinkValueName =
RTL_CONSTANT_STRING(L"SymbolicLinkValue");
UNICODE_STRING CmpSystemStartOptions;
UNICODE_STRING CmpLoadOptions;
BOOLEAN CmpShareSystemHives;
BOOLEAN CmSelfHeal = TRUE;
BOOLEAN CmpSelfHeal = TRUE;
BOOLEAN CmpMiniNTBoot;
ULONG CmpBootType;
HANDLE CmpRegistryRootHandle;
UNICODE_STRING CmTypeName[MaximumType + 1] =
{
RTL_CONSTANT_STRING(L"System"),

View file

@ -226,3 +226,357 @@ CmpInitializeHive(OUT PCMHIVE *RegistryHive,
*RegistryHive = (PCMHIVE)Hive;
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
CmpOpenHiveFiles(IN PUNICODE_STRING BaseName,
IN PWCHAR Extension OPTIONAL,
IN PHANDLE Primary,
IN PHANDLE Log,
IN PULONG PrimaryDisposition,
IN PULONG LogDisposition,
IN BOOLEAN CreateAllowed,
IN BOOLEAN MarkAsSystemHive,
IN BOOLEAN NoBuffering,
OUT PULONG ClusterSize OPTIONAL)
{
HANDLE EventHandle;
PKEVENT Event;
NTSTATUS Status;
UNICODE_STRING FullName, ExtensionName;
PWCHAR NameBuffer;
USHORT Length;
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK IoStatusBlock;
ULONG AttributeFlags, ShareMode, DesiredAccess, CreateDisposition, IoFlags;
USHORT CompressionState;
FILE_STANDARD_INFORMATION FileInformation;
FILE_FS_SIZE_INFORMATION FsSizeInformation;
/* Create event */
Status = CmpCreateEvent(NotificationEvent, &EventHandle, &Event);
if (!NT_SUCCESS(Status)) return Status;
/* Initialize the full name */
RtlInitEmptyUnicodeString(&FullName, NULL, 0);
Length = BaseName->Length;
/* Check if we have an extension */
if (Extension)
{
/* Update the name length */
Length += wcslen(Extension) * sizeof(WCHAR) + sizeof(UNICODE_NULL);
/* Allocate the buffer for the full name */
NameBuffer = ExAllocatePoolWithTag(PagedPool, Length, TAG_CM);
if (!NameBuffer)
{
/* Fail */
ObDereferenceObject(Event);
ZwClose(EventHandle);
return STATUS_NO_MEMORY;
}
/* Build the full name */
FullName.Buffer = NameBuffer;
FullName.MaximumLength = Length;
RtlAppendUnicodeStringToString(&FullName, BaseName);
}
else
{
/* The base name is the full name */
FullName = *BaseName;
NameBuffer = NULL;
}
/* Initialize the attributes */
InitializeObjectAttributes(&ObjectAttributes,
&FullName,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL,
NULL);
/* Check if we can create the hive */
if ((CreateAllowed) && !(CmpShareSystemHives))
{
/* Open only or create */
CreateDisposition = FILE_OPEN_IF;
}
else
{
/* Open only */
CreateDisposition = FILE_OPEN;
}
/* Setup the flags */
IoFlags = FILE_OPEN_FOR_BACKUP_INTENT |
FILE_NO_COMPRESSION |
FILE_RANDOM_ACCESS |
(NoBuffering) ? FILE_NO_INTERMEDIATE_BUFFERING : 0;
/* Set share and access modes */
if ((CmpMiniNTBoot) && (CmpShareSystemHives))
{
/* We're on Live CD or otherwise sharing */
DesiredAccess = FILE_READ_DATA;
ShareMode = FILE_SHARE_READ;
}
else
{
/* We want to write exclusively */
ShareMode = 0;
DesiredAccess = FILE_READ_DATA | FILE_WRITE_DATA;
}
/* Default attributes */
AttributeFlags = FILE_ATTRIBUTE_NORMAL;
/* Now create the file */
Status = ZwCreateFile(Primary,
DesiredAccess,
&ObjectAttributes,
&IoStatusBlock,
NULL,
AttributeFlags,
ShareMode,
CreateDisposition,
FILE_SYNCHRONOUS_IO_NONALERT | IoFlags,
NULL,
0);
if ((NT_SUCCESS(Status)) && (MarkAsSystemHive))
{
/* We opened it, mark it as a system hive */
Status = ZwFsControlFile(*Primary,
EventHandle,
NULL,
NULL,
&IoStatusBlock,
FSCTL_MARK_AS_SYSTEM_HIVE,
NULL,
0,
NULL,
0);
if (Status == STATUS_PENDING)
{
/* Wait for completion */
KeWaitForSingleObject(Event,
Executive,
KernelMode,
FALSE,
NULL);
Status = IoStatusBlock.Status;
}
/* If we don't support it, ignore the failure */
if (Status == STATUS_INVALID_DEVICE_REQUEST) Status = STATUS_SUCCESS;
/* If we failed, close the handle */
if (!NT_SUCCESS(Status)) ZwClose(*Primary);
}
/* Check if anything failed until now */
if (!NT_SUCCESS(Status))
{
/* Close handles and free buffers */
if (NameBuffer) ExFreePool(NameBuffer);
ObDereferenceObject(Event);
ZwClose(EventHandle);
return Status;
}
/* Disable compression */
CompressionState = 0;
Status = ZwFsControlFile(*Primary,
EventHandle,
NULL,
NULL,
&IoStatusBlock,
FSCTL_SET_COMPRESSION,
&CompressionState,
sizeof(CompressionState),
NULL,
0);
if (Status == STATUS_PENDING)
{
/* Wait for completion */
KeWaitForSingleObject(Event,
Executive,
KernelMode,
FALSE,
NULL);
}
/* Get the disposition */
*PrimaryDisposition = IoStatusBlock.Information;
if (IoStatusBlock.Information != FILE_CREATED)
{
/* Check how large the file is */
Status = ZwQueryInformationFile(*Primary,
&IoStatusBlock,
&FileInformation,
sizeof(FileInformation),
FileStandardInformation);
if (NT_SUCCESS(Status))
{
/* Check if it's 0 bytes */
if (!FileInformation.EndOfFile.QuadPart)
{
/* Assume it's a new file */
*PrimaryDisposition = FILE_CREATED;
}
}
}
/* Check if the caller wants cluster size returned */
if (ClusterSize)
{
/* Query it */
Status = ZwQueryVolumeInformationFile(*Primary,
&IoStatusBlock,
&FsSizeInformation,
sizeof(FsSizeInformation),
FileFsSizeInformation);
if (!NT_SUCCESS(Status))
{
/* Close handles and free buffers */
if (NameBuffer) ExFreePool(NameBuffer);
ObDereferenceObject(Event);
ZwClose(EventHandle);
return Status;
}
/* Check if the sector size is invalid */
if (FsSizeInformation.BytesPerSector > HBLOCK_SIZE)
{
/* Close handles and free buffers */
if (NameBuffer) ExFreePool(NameBuffer);
ObDereferenceObject(Event);
ZwClose(EventHandle);
return STATUS_CANNOT_LOAD_REGISTRY_FILE;
}
/* Return cluster size */
*ClusterSize = max(1, FsSizeInformation.BytesPerSector / HSECTOR_SIZE);
}
/* Check if we don't need to create a log file */
if (!Extension)
{
/* We're done, close handles and free buffers */
if (NameBuffer) ExFreePool(NameBuffer);
ObDereferenceObject(Event);
ZwClose(EventHandle);
return STATUS_SUCCESS;
}
/* Check if we can create the hive */
CreateDisposition = CmpShareSystemHives ? FILE_OPEN : FILE_OPEN_IF;
if (*PrimaryDisposition == FILE_CREATED)
{
/* Over-write the existing log file, since this is a new hive */
CreateDisposition = FILE_SUPERSEDE;
}
/* Setup the name */
RtlInitUnicodeString(&ExtensionName, Extension);
RtlAppendUnicodeStringToString(&FullName, &ExtensionName);
/* Initialize the attributes */
InitializeObjectAttributes(&ObjectAttributes,
&FullName,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL,
NULL);
/* Setup the flags */
IoFlags = FILE_NO_COMPRESSION | FILE_NO_INTERMEDIATE_BUFFERING;
/* Check if this is a log file */
if (!_wcsnicmp(Extension, L".log", 4))
{
/* Hide log files */
AttributeFlags |= FILE_ATTRIBUTE_HIDDEN;
}
/* Now create the file */
Status = ZwCreateFile(Log,
DesiredAccess,
&ObjectAttributes,
&IoStatusBlock,
NULL,
AttributeFlags,
ShareMode,
CreateDisposition,
IoFlags,
NULL,
0);
if ((NT_SUCCESS(Status)) && (MarkAsSystemHive))
{
/* We opened it, mark it as a system hive */
Status = ZwFsControlFile(*Log,
EventHandle,
NULL,
NULL,
&IoStatusBlock,
FSCTL_MARK_AS_SYSTEM_HIVE,
NULL,
0,
NULL,
0);
if (Status == STATUS_PENDING)
{
/* Wait for completion */
KeWaitForSingleObject(Event,
Executive,
KernelMode,
FALSE,
NULL);
Status = IoStatusBlock.Status;
}
/* If we don't support it, ignore the failure */
if (Status == STATUS_INVALID_DEVICE_REQUEST) Status = STATUS_SUCCESS;
/* If we failed, close the handle */
if (!NT_SUCCESS(Status)) ZwClose(*Log);
}
/* Check if anything failed until now */
if (!NT_SUCCESS(Status))
{
/* Clear the handle */
*Log = NULL;
}
else
{
/* Disable compression */
Status = ZwFsControlFile(*Log,
EventHandle,
NULL,
NULL,
&IoStatusBlock,
FSCTL_SET_COMPRESSION,
&CompressionState,
sizeof(CompressionState),
NULL,
0);
if (Status == STATUS_PENDING)
{
/* Wait for completion */
KeWaitForSingleObject(Event,
Executive,
KernelMode,
FALSE,
NULL);
}
/* Return the disposition */
*LogDisposition = IoStatusBlock.Information;
}
/* We're done, close handles and free buffers */
if (NameBuffer) ExFreePool(NameBuffer);
ObDereferenceObject(Event);
ZwClose(EventHandle);
return STATUS_SUCCESS;
}

View file

@ -13,25 +13,6 @@
#define NDEBUG
#include "debug.h"
/* GLOBALS *******************************************************************/
HIVE_LIST_ENTRY CmpMachineHiveList[5];
UNICODE_STRING CmSymbolicLinkValueName =
RTL_CONSTANT_STRING(L"SymbolicLinkValue");
UNICODE_STRING CmpSystemStartOptions;
UNICODE_STRING CmpLoadOptions;
BOOLEAN CmpShareSystemHives;
BOOLEAN CmSelfHeal = TRUE;
BOOLEAN CmpSelfHeal = TRUE;
ULONG CmpBootType;
HANDLE CmpRegistryRootHandle;
extern BOOLEAN ExpInTextModeSetup;
/* FUNCTIONS *****************************************************************/
NTSTATUS

View file

@ -15,6 +15,41 @@
/* FUNCTIONS *****************************************************************/
NTSTATUS
NTAPI
CmpCreateEvent(IN EVENT_TYPE EventType,
OUT PHANDLE EventHandle,
OUT PKEVENT *Event)
{
NTSTATUS Status;
OBJECT_ATTRIBUTES ObjectAttributes;
/* Create the event */
InitializeObjectAttributes(&ObjectAttributes,
NULL,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL,
NULL);
Status = ZwCreateEvent(EventHandle,
EVENT_ALL_ACCESS,
&ObjectAttributes,
EventType,
FALSE);
if (!NT_SUCCESS(Status)) return Status;
/* Get a pointer to the object itself */
Status = ObReferenceObjectByHandle(*EventHandle,
EVENT_ALL_ACCESS,
NULL,
KernelMode,
(PVOID*)Event,
NULL);
if (!NT_SUCCESS(Status)) ZwClose(*EventHandle);
/* Return status */
return Status;
}
PVOID
NTAPI
CmpAllocate(IN ULONG Size,