Author: ion Date: Sat May 12 02:51:11 2007 New Revision: 26705
URL: http://svn.reactos.org/svn/reactos?rev=26705&view=rev Log: - 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.
Modified: trunk/reactos/ntoskrnl/cm/cm.h trunk/reactos/ntoskrnl/cm/regfile.c trunk/reactos/ntoskrnl/config/cm.h trunk/reactos/ntoskrnl/config/cmdata.c trunk/reactos/ntoskrnl/config/cminit.c trunk/reactos/ntoskrnl/config/cmsysini.c trunk/reactos/ntoskrnl/config/cmwraprs.c
Modified: trunk/reactos/ntoskrnl/cm/cm.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/cm/cm.h?rev=26705&... ============================================================================== --- trunk/reactos/ntoskrnl/cm/cm.h (original) +++ trunk/reactos/ntoskrnl/cm/cm.h Sat May 12 02:51:11 2007 @@ -496,6 +496,19 @@ 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) {
Modified: trunk/reactos/ntoskrnl/cm/regfile.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/cm/regfile.c?rev=2... ============================================================================== --- trunk/reactos/ntoskrnl/cm/regfile.c (original) +++ trunk/reactos/ntoskrnl/cm/regfile.c Sat May 12 02:51:11 2007 @@ -283,63 +283,6 @@ 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 @@ { BOOLEAN Success; NTSTATUS Status; + ULONG Disposition;
ASSERT(!IsNoFileHive(RegistryHive));
@@ -361,7 +305,16 @@ 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;
Modified: trunk/reactos/ntoskrnl/config/cm.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/config/cm.h?rev=26... ============================================================================== --- trunk/reactos/ntoskrnl/config/cm.h (original) +++ trunk/reactos/ntoskrnl/config/cm.h Sat May 12 02:51:11 2007 @@ -1007,6 +1007,14 @@ // // Wrapper Routines // +NTSTATUS +NTAPI +CmpCreateEvent( + IN EVENT_TYPE EventType, + OUT PHANDLE EventHandle, + OUT PKEVENT *Event +); + PVOID NTAPI CmpAllocate( @@ -1060,6 +1068,8 @@ // 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 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;
//
Modified: trunk/reactos/ntoskrnl/config/cmdata.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/config/cmdata.c?re... ============================================================================== --- trunk/reactos/ntoskrnl/config/cmdata.c (original) +++ trunk/reactos/ntoskrnl/config/cmdata.c Sat May 12 02:51:11 2007 @@ -37,6 +37,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] = {
Modified: trunk/reactos/ntoskrnl/config/cminit.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/config/cminit.c?re... ============================================================================== --- trunk/reactos/ntoskrnl/config/cminit.c (original) +++ trunk/reactos/ntoskrnl/config/cminit.c Sat May 12 02:51:11 2007 @@ -226,3 +226,357 @@ *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; +}
Modified: trunk/reactos/ntoskrnl/config/cmsysini.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/config/cmsysini.c?... ============================================================================== --- trunk/reactos/ntoskrnl/config/cmsysini.c (original) +++ trunk/reactos/ntoskrnl/config/cmsysini.c Sat May 12 02:51:11 2007 @@ -12,25 +12,6 @@ #include "cm.h" #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 *****************************************************************/
Modified: trunk/reactos/ntoskrnl/config/cmwraprs.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/config/cmwraprs.c?... ============================================================================== --- trunk/reactos/ntoskrnl/config/cmwraprs.c (original) +++ trunk/reactos/ntoskrnl/config/cmwraprs.c Sat May 12 02:51:11 2007 @@ -14,6 +14,41 @@ #include "debug.h"
/* 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