Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygencminit.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS Kernel 00003 * LICENSE: GPL - See COPYING in the top level directory 00004 * FILE: ntoskrnl/config/cminit.c 00005 * PURPOSE: Configuration Manager - Hive Initialization 00006 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 00007 */ 00008 00009 /* INCLUDES ******************************************************************/ 00010 00011 #include "ntoskrnl.h" 00012 #define NDEBUG 00013 #include "debug.h" 00014 00015 /* FUNCTIONS *****************************************************************/ 00016 00017 NTSTATUS 00018 NTAPI 00019 CmpInitializeHive(OUT PCMHIVE *RegistryHive, 00020 IN ULONG OperationType, 00021 IN ULONG HiveFlags, 00022 IN ULONG FileType, 00023 IN PVOID HiveData OPTIONAL, 00024 IN HANDLE Primary, 00025 IN HANDLE Log, 00026 IN HANDLE External, 00027 IN PCUNICODE_STRING FileName OPTIONAL, 00028 IN ULONG CheckFlags) 00029 { 00030 PCMHIVE Hive; 00031 FILE_STANDARD_INFORMATION FileInformation; 00032 IO_STATUS_BLOCK IoStatusBlock; 00033 FILE_FS_SIZE_INFORMATION FileSizeInformation; 00034 NTSTATUS Status; 00035 ULONG Cluster; 00036 00037 /* Assume failure */ 00038 *RegistryHive = NULL; 00039 00040 /* 00041 * The following are invalid: 00042 * An external hive that is also internal. 00043 * A log hive that's not a primary hive too. 00044 * A volatile hive that's linked to permanent storage. 00045 * An in-memory initialization without hive data. 00046 * A log hive that's not linked to a correct file type. 00047 */ 00048 if (((External) && ((Primary) || (Log))) || 00049 ((Log) && !(Primary)) || 00050 ((HiveFlags & HIVE_VOLATILE) && ((Primary) || (External) || (Log))) || 00051 ((OperationType == HINIT_MEMORY) && (!HiveData)) || 00052 ((Log) && (FileType != HFILE_TYPE_LOG))) 00053 { 00054 /* Fail the request */ 00055 return STATUS_INVALID_PARAMETER; 00056 } 00057 00058 /* Check if this is a primary hive */ 00059 if (Primary) 00060 { 00061 /* Get the cluster size */ 00062 Status = ZwQueryVolumeInformationFile(Primary, 00063 &IoStatusBlock, 00064 &FileSizeInformation, 00065 sizeof(FILE_FS_SIZE_INFORMATION), 00066 FileFsSizeInformation); 00067 if (!NT_SUCCESS(Status)) return Status; 00068 00069 /* Make sure it's not larger then the block size */ 00070 if (FileSizeInformation.BytesPerSector > HBLOCK_SIZE) 00071 { 00072 /* Fail */ 00073 return STATUS_REGISTRY_IO_FAILED; 00074 } 00075 00076 /* Otherwise, calculate the cluster */ 00077 Cluster = FileSizeInformation.BytesPerSector / HSECTOR_SIZE; 00078 Cluster = max(1, Cluster); 00079 } 00080 else 00081 { 00082 /* Otherwise use cluster 1 */ 00083 Cluster = 1; 00084 } 00085 00086 /* Allocate the hive */ 00087 Hive = ExAllocatePoolWithTag(NonPagedPool, sizeof(CMHIVE), TAG_CM); 00088 if (!Hive) return STATUS_INSUFFICIENT_RESOURCES; 00089 00090 /* Setup null fields */ 00091 Hive->UnloadEvent = NULL; 00092 Hive->RootKcb = NULL; 00093 Hive->Frozen = FALSE; 00094 Hive->UnloadWorkItem = NULL; 00095 Hive->GrowOnlyMode = FALSE; 00096 Hive->GrowOffset = 0; 00097 Hive->CellRemapArray = NULL; 00098 Hive->UseCountLog.Next = 0; 00099 Hive->LockHiveLog.Next = 0; 00100 Hive->FileObject = NULL; 00101 Hive->NotifyList.Flink = NULL; 00102 Hive->NotifyList.Blink = NULL; 00103 00104 /* Set loading flag */ 00105 Hive->HiveIsLoading = TRUE; 00106 00107 /* Set the current thread as creator */ 00108 Hive->CreatorOwner = KeGetCurrentThread(); 00109 00110 /* Initialize lists */ 00111 InitializeListHead(&Hive->KcbConvertListHead); 00112 InitializeListHead(&Hive->KnodeConvertListHead); 00113 InitializeListHead(&Hive->TrustClassEntry); 00114 00115 /* Allocate the view log */ 00116 Hive->ViewLock = ExAllocatePoolWithTag(NonPagedPool, 00117 sizeof(KGUARDED_MUTEX), 00118 TAG_CM); 00119 if (!Hive->ViewLock) return STATUS_INSUFFICIENT_RESOURCES; 00120 00121 /* Allocate the flush lock */ 00122 Hive->FlusherLock = ExAllocatePoolWithTag(NonPagedPool, 00123 sizeof(ERESOURCE), 00124 TAG_CM); 00125 if (!Hive->FlusherLock) return STATUS_INSUFFICIENT_RESOURCES; 00126 00127 /* Setup the handles */ 00128 Hive->FileHandles[HFILE_TYPE_PRIMARY] = Primary; 00129 Hive->FileHandles[HFILE_TYPE_LOG] = Log; 00130 Hive->FileHandles[HFILE_TYPE_EXTERNAL] = External; 00131 00132 /* Initailize the guarded mutex */ 00133 KeInitializeGuardedMutex(Hive->ViewLock); 00134 Hive->ViewLockOwner = NULL; 00135 00136 /* Initialize the flush lock */ 00137 ExInitializeResourceLite(Hive->FlusherLock); 00138 00139 /* Setup hive locks */ 00140 ExInitializePushLock(&Hive->HiveLock); 00141 Hive->HiveLockOwner = NULL; 00142 ExInitializePushLock(&Hive->WriterLock); 00143 Hive->WriterLockOwner = NULL; 00144 ExInitializePushLock(&Hive->SecurityLock); 00145 Hive->HiveSecurityLockOwner = NULL; 00146 00147 /* Clear file names */ 00148 RtlInitEmptyUnicodeString(&Hive->FileUserName, NULL, 0); 00149 RtlInitEmptyUnicodeString(&Hive->FileFullPath, NULL, 0); 00150 00151 /* Initialize the view list */ 00152 CmpInitHiveViewList(Hive); 00153 00154 /* Initailize the security cache */ 00155 CmpInitSecurityCache(Hive); 00156 00157 /* Setup flags */ 00158 Hive->Flags = 0; 00159 Hive->FlushCount = 0; 00160 00161 /* Set flags */ 00162 Hive->Flags = HiveFlags; 00163 00164 /* Check if this is a primary */ 00165 if (Primary) 00166 { 00167 /* Check how large the file is */ 00168 ZwQueryInformationFile(Primary, 00169 &IoStatusBlock, 00170 &FileInformation, 00171 sizeof(FileInformation), 00172 FileStandardInformation); 00173 Cluster = FileInformation.EndOfFile.LowPart; 00174 } 00175 00176 /* Initialize it */ 00177 Status = HvInitialize(&Hive->Hive, 00178 OperationType, 00179 FileType, 00180 HiveFlags, 00181 HiveData, 00182 CmpAllocate, 00183 CmpFree, 00184 CmpFileSetSize, 00185 CmpFileWrite, 00186 CmpFileRead, 00187 CmpFileFlush, 00188 Cluster, 00189 (PUNICODE_STRING)FileName); 00190 if (!NT_SUCCESS(Status)) 00191 { 00192 /* Clear allocations and fail */ 00193 ExFreePool(Hive->ViewLock); 00194 ExFreePool(Hive->FlusherLock); 00195 ExFreePool(Hive); 00196 return Status; 00197 } 00198 00199 /* Check if we should verify the registry */ 00200 if ((OperationType == HINIT_FILE) || 00201 (OperationType == HINIT_MEMORY) || 00202 (OperationType == HINIT_MEMORY_INPLACE) || 00203 (OperationType == HINIT_MAPFILE)) 00204 { 00205 /* Verify integrity */ 00206 if (CmCheckRegistry((PCMHIVE)Hive, TRUE)) 00207 { 00208 /* Free all alocations */ 00209 ExFreePool(Hive->ViewLock); 00210 ExFreePool(Hive->FlusherLock); 00211 ExFreePool(Hive); 00212 return STATUS_REGISTRY_CORRUPT; 00213 } 00214 } 00215 00216 /* Lock the hive list */ 00217 ExAcquirePushLockExclusive(&CmpHiveListHeadLock); 00218 00219 /* Insert this hive */ 00220 InsertHeadList(&CmpHiveListHead, &Hive->HiveList); 00221 00222 /* Release the lock */ 00223 ExReleasePushLock(&CmpHiveListHeadLock); 00224 00225 /* Return the hive and success */ 00226 *RegistryHive = (PCMHIVE)Hive; 00227 return STATUS_SUCCESS; 00228 } 00229 00230 NTSTATUS 00231 NTAPI 00232 CmpOpenHiveFiles(IN PCUNICODE_STRING BaseName, 00233 IN PCWSTR Extension OPTIONAL, 00234 IN PHANDLE Primary, 00235 IN PHANDLE Log, 00236 IN PULONG PrimaryDisposition, 00237 IN PULONG LogDisposition, 00238 IN BOOLEAN CreateAllowed, 00239 IN BOOLEAN MarkAsSystemHive, 00240 IN BOOLEAN NoBuffering, 00241 OUT PULONG ClusterSize OPTIONAL) 00242 { 00243 HANDLE EventHandle; 00244 PKEVENT Event; 00245 NTSTATUS Status; 00246 UNICODE_STRING FullName, ExtensionName; 00247 PWCHAR NameBuffer; 00248 USHORT Length; 00249 OBJECT_ATTRIBUTES ObjectAttributes; 00250 IO_STATUS_BLOCK IoStatusBlock; 00251 ULONG AttributeFlags, ShareMode, DesiredAccess, CreateDisposition, IoFlags; 00252 USHORT CompressionState; 00253 FILE_STANDARD_INFORMATION FileInformation; 00254 FILE_FS_SIZE_INFORMATION FsSizeInformation; 00255 00256 /* Create event */ 00257 Status = CmpCreateEvent(NotificationEvent, &EventHandle, &Event); 00258 if (!NT_SUCCESS(Status)) return Status; 00259 00260 /* Initialize the full name */ 00261 RtlInitEmptyUnicodeString(&FullName, NULL, 0); 00262 Length = BaseName->Length; 00263 00264 /* Check if we have an extension */ 00265 if (Extension) 00266 { 00267 /* Update the name length */ 00268 Length += (USHORT)wcslen(Extension) * sizeof(WCHAR) + sizeof(UNICODE_NULL); 00269 00270 /* Allocate the buffer for the full name */ 00271 NameBuffer = ExAllocatePoolWithTag(PagedPool, Length, TAG_CM); 00272 if (!NameBuffer) 00273 { 00274 /* Fail */ 00275 ObDereferenceObject(Event); 00276 ZwClose(EventHandle); 00277 return STATUS_NO_MEMORY; 00278 } 00279 00280 /* Build the full name */ 00281 FullName.Buffer = NameBuffer; 00282 FullName.MaximumLength = Length; 00283 RtlAppendUnicodeStringToString(&FullName, BaseName); 00284 } 00285 else 00286 { 00287 /* The base name is the full name */ 00288 FullName = *BaseName; 00289 NameBuffer = NULL; 00290 } 00291 00292 /* Initialize the attributes */ 00293 InitializeObjectAttributes(&ObjectAttributes, 00294 &FullName, 00295 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 00296 NULL, 00297 NULL); 00298 00299 /* Check if we can create the hive */ 00300 if ((CreateAllowed) && !(CmpShareSystemHives)) 00301 { 00302 /* Open only or create */ 00303 CreateDisposition = FILE_OPEN_IF; 00304 } 00305 else 00306 { 00307 /* Open only */ 00308 CreateDisposition = FILE_OPEN; 00309 } 00310 00311 /* Setup the flags */ 00312 // FIXME : FILE_OPEN_FOR_BACKUP_INTENT is unimplemented and breaks 3rd stage boot 00313 IoFlags = //FILE_OPEN_FOR_BACKUP_INTENT | 00314 FILE_NO_COMPRESSION | 00315 FILE_RANDOM_ACCESS | 00316 (NoBuffering ? FILE_NO_INTERMEDIATE_BUFFERING : 0); 00317 00318 /* Set share and access modes */ 00319 if ((CmpMiniNTBoot) && (CmpShareSystemHives)) 00320 { 00321 /* We're on Live CD or otherwise sharing */ 00322 DesiredAccess = FILE_READ_DATA; 00323 ShareMode = FILE_SHARE_READ; 00324 } 00325 else 00326 { 00327 /* We want to write exclusively */ 00328 ShareMode = 0; 00329 DesiredAccess = FILE_READ_DATA | FILE_WRITE_DATA; 00330 } 00331 00332 /* Default attributes */ 00333 AttributeFlags = FILE_ATTRIBUTE_NORMAL; 00334 00335 /* Now create the file */ 00336 Status = ZwCreateFile(Primary, 00337 DesiredAccess | SYNCHRONIZE, 00338 &ObjectAttributes, 00339 &IoStatusBlock, 00340 NULL, 00341 AttributeFlags, 00342 ShareMode, 00343 CreateDisposition, 00344 FILE_SYNCHRONOUS_IO_NONALERT | IoFlags, 00345 NULL, 00346 0); 00347 /* Check if anything failed until now */ 00348 if (!NT_SUCCESS(Status)) 00349 { 00350 /* Close handles and free buffers */ 00351 if (NameBuffer) ExFreePool(NameBuffer); 00352 ObDereferenceObject(Event); 00353 ZwClose(EventHandle); 00354 DPRINT1("ZwCreateFile failed : %lx.\n", Status); 00355 *Primary = NULL; 00356 return Status; 00357 } 00358 00359 if (MarkAsSystemHive) 00360 { 00361 /* We opened it, mark it as a system hive */ 00362 Status = ZwFsControlFile(*Primary, 00363 EventHandle, 00364 NULL, 00365 NULL, 00366 &IoStatusBlock, 00367 FSCTL_MARK_AS_SYSTEM_HIVE, 00368 NULL, 00369 0, 00370 NULL, 00371 0); 00372 if (Status == STATUS_PENDING) 00373 { 00374 /* Wait for completion */ 00375 KeWaitForSingleObject(Event, 00376 Executive, 00377 KernelMode, 00378 FALSE, 00379 NULL); 00380 Status = IoStatusBlock.Status; 00381 } 00382 00383 /* If we don't support it, ignore the failure */ 00384 if (Status == STATUS_INVALID_DEVICE_REQUEST) Status = STATUS_SUCCESS; 00385 00386 if (!NT_SUCCESS(Status)) 00387 { 00388 /* Close handles and free buffers */ 00389 if (NameBuffer) ExFreePool(NameBuffer); 00390 ObDereferenceObject(Event); 00391 ZwClose(EventHandle); 00392 ZwClose(*Primary); 00393 *Primary = NULL; 00394 return Status; 00395 } 00396 } 00397 00398 /* Disable compression */ 00399 CompressionState = 0; 00400 Status = ZwFsControlFile(*Primary, 00401 EventHandle, 00402 NULL, 00403 NULL, 00404 &IoStatusBlock, 00405 FSCTL_SET_COMPRESSION, 00406 &CompressionState, 00407 sizeof(CompressionState), 00408 NULL, 00409 0); 00410 if (Status == STATUS_PENDING) 00411 { 00412 /* Wait for completion */ 00413 KeWaitForSingleObject(Event, 00414 Executive, 00415 KernelMode, 00416 FALSE, 00417 NULL); 00418 } 00419 00420 /* Get the disposition */ 00421 *PrimaryDisposition = (ULONG)IoStatusBlock.Information; 00422 if (IoStatusBlock.Information != FILE_CREATED) 00423 { 00424 /* Check how large the file is */ 00425 Status = ZwQueryInformationFile(*Primary, 00426 &IoStatusBlock, 00427 &FileInformation, 00428 sizeof(FileInformation), 00429 FileStandardInformation); 00430 if (NT_SUCCESS(Status)) 00431 { 00432 /* Check if it's 0 bytes */ 00433 if (!FileInformation.EndOfFile.QuadPart) 00434 { 00435 /* Assume it's a new file */ 00436 *PrimaryDisposition = FILE_CREATED; 00437 } 00438 } 00439 } 00440 00441 /* Check if the caller wants cluster size returned */ 00442 if (ClusterSize) 00443 { 00444 /* Query it */ 00445 Status = ZwQueryVolumeInformationFile(*Primary, 00446 &IoStatusBlock, 00447 &FsSizeInformation, 00448 sizeof(FsSizeInformation), 00449 FileFsSizeInformation); 00450 if (!NT_SUCCESS(Status)) 00451 { 00452 /* Close handles and free buffers */ 00453 if (NameBuffer) ExFreePool(NameBuffer); 00454 ObDereferenceObject(Event); 00455 ZwClose(EventHandle); 00456 return Status; 00457 } 00458 00459 /* Check if the sector size is invalid */ 00460 if (FsSizeInformation.BytesPerSector > HBLOCK_SIZE) 00461 { 00462 /* Close handles and free buffers */ 00463 if (NameBuffer) ExFreePool(NameBuffer); 00464 ObDereferenceObject(Event); 00465 ZwClose(EventHandle); 00466 return STATUS_CANNOT_LOAD_REGISTRY_FILE; 00467 } 00468 00469 /* Return cluster size */ 00470 *ClusterSize = max(1, FsSizeInformation.BytesPerSector / HSECTOR_SIZE); 00471 } 00472 00473 /* Check if we don't need to create a log file */ 00474 if (!Extension) 00475 { 00476 /* We're done, close handles */ 00477 ObDereferenceObject(Event); 00478 ZwClose(EventHandle); 00479 return STATUS_SUCCESS; 00480 } 00481 00482 /* Check if we can create the hive */ 00483 CreateDisposition = CmpShareSystemHives ? FILE_OPEN : FILE_OPEN_IF; 00484 if (*PrimaryDisposition == FILE_CREATED) 00485 { 00486 /* Over-write the existing log file, since this is a new hive */ 00487 CreateDisposition = FILE_SUPERSEDE; 00488 } 00489 00490 /* Setup the name */ 00491 RtlInitUnicodeString(&ExtensionName, Extension); 00492 RtlAppendUnicodeStringToString(&FullName, &ExtensionName); 00493 00494 /* Initialize the attributes */ 00495 InitializeObjectAttributes(&ObjectAttributes, 00496 &FullName, 00497 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 00498 NULL, 00499 NULL); 00500 00501 /* Setup the flags */ 00502 IoFlags = FILE_NO_COMPRESSION | FILE_NO_INTERMEDIATE_BUFFERING; 00503 00504 /* Check if this is a log file */ 00505 if (!_wcsnicmp(Extension, L".log", 4)) 00506 { 00507 /* Hide log files */ 00508 AttributeFlags |= FILE_ATTRIBUTE_HIDDEN; 00509 } 00510 00511 /* Now create the file */ 00512 Status = ZwCreateFile(Log, 00513 DesiredAccess, 00514 &ObjectAttributes, 00515 &IoStatusBlock, 00516 NULL, 00517 AttributeFlags, 00518 ShareMode, 00519 CreateDisposition, 00520 IoFlags, 00521 NULL, 00522 0); 00523 if ((NT_SUCCESS(Status)) && (MarkAsSystemHive)) 00524 { 00525 /* We opened it, mark it as a system hive */ 00526 Status = ZwFsControlFile(*Log, 00527 EventHandle, 00528 NULL, 00529 NULL, 00530 &IoStatusBlock, 00531 FSCTL_MARK_AS_SYSTEM_HIVE, 00532 NULL, 00533 0, 00534 NULL, 00535 0); 00536 if (Status == STATUS_PENDING) 00537 { 00538 /* Wait for completion */ 00539 KeWaitForSingleObject(Event, 00540 Executive, 00541 KernelMode, 00542 FALSE, 00543 NULL); 00544 Status = IoStatusBlock.Status; 00545 } 00546 00547 /* If we don't support it, ignore the failure */ 00548 if (Status == STATUS_INVALID_DEVICE_REQUEST) Status = STATUS_SUCCESS; 00549 00550 /* If we failed, close the handle */ 00551 if (!NT_SUCCESS(Status)) ZwClose(*Log); 00552 } 00553 00554 /* Check if anything failed until now */ 00555 if (!NT_SUCCESS(Status)) 00556 { 00557 /* Clear the handle */ 00558 *Log = NULL; 00559 } 00560 else 00561 { 00562 /* Disable compression */ 00563 Status = ZwFsControlFile(*Log, 00564 EventHandle, 00565 NULL, 00566 NULL, 00567 &IoStatusBlock, 00568 FSCTL_SET_COMPRESSION, 00569 &CompressionState, 00570 sizeof(CompressionState), 00571 NULL, 00572 0); 00573 if (Status == STATUS_PENDING) 00574 { 00575 /* Wait for completion */ 00576 KeWaitForSingleObject(Event, 00577 Executive, 00578 KernelMode, 00579 FALSE, 00580 NULL); 00581 } 00582 00583 /* Return the disposition */ 00584 *LogDisposition = (ULONG)IoStatusBlock.Information; 00585 } 00586 00587 /* We're done, close handles and free buffers */ 00588 if (NameBuffer) ExFreePool(NameBuffer); 00589 ObDereferenceObject(Event); 00590 ZwClose(EventHandle); 00591 return STATUS_SUCCESS; 00592 } Generated on Sun May 27 2012 04:35:56 for ReactOS by
1.7.6.1
|