ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

cminit.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.