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

hiveinit.c
Go to the documentation of this file.
00001 /*
00002  * PROJECT:   registry manipulation library
00003  * LICENSE:   GPL - See COPYING in the top level directory
00004  * COPYRIGHT: Copyright 2005 Filip Navara <navaraf@reactos.org>
00005  *            Copyright 2001 - 2005 Eric Kohl
00006  */
00007 
00008 #include "cmlib.h"
00009 #define NDEBUG
00010 #include <debug.h>
00011 
00018 BOOLEAN CMAPI
00019 HvpVerifyHiveHeader(
00020    PHBASE_BLOCK BaseBlock)
00021 {
00022    if (BaseBlock->Signature != HV_SIGNATURE ||
00023        BaseBlock->Major != HSYS_MAJOR ||
00024        BaseBlock->Minor < HSYS_MINOR ||
00025        BaseBlock->Type != HFILE_TYPE_PRIMARY ||
00026        BaseBlock->Format != HBASE_FORMAT_MEMORY ||
00027        BaseBlock->Cluster != 1 ||
00028        BaseBlock->Sequence1 != BaseBlock->Sequence2 ||
00029        HvpHiveHeaderChecksum(BaseBlock) != BaseBlock->CheckSum)
00030    {
00031       DPRINT1("Verify Hive Header failed: \n");
00032       DPRINT1("    Signature: 0x%x and not 0x%x, Major: 0x%x and not 0x%x\n",
00033           BaseBlock->Signature, HV_SIGNATURE, BaseBlock->Major, HSYS_MAJOR);
00034       DPRINT1("    Minor: 0x%x is not >= 0x%x, Type: 0x%x and not 0x%x\n",
00035           BaseBlock->Minor, HSYS_MINOR, BaseBlock->Type, HFILE_TYPE_PRIMARY);
00036       DPRINT1("    Format: 0x%x and not 0x%x, Cluster: 0x%x and not 1\n",
00037           BaseBlock->Format, HBASE_FORMAT_MEMORY, BaseBlock->Cluster);
00038       DPRINT1("    Sequence: 0x%x and not 0x%x, Checksum: 0x%x and not 0x%x\n",
00039           BaseBlock->Sequence1, BaseBlock->Sequence2,
00040           HvpHiveHeaderChecksum(BaseBlock), BaseBlock->CheckSum);
00041       return FALSE;
00042    }
00043 
00044    return TRUE;
00045 }
00046 
00054 VOID CMAPI
00055 HvpFreeHiveBins(
00056    PHHIVE Hive)
00057 {
00058    ULONG i;
00059    PHBIN Bin;
00060    ULONG Storage;
00061 
00062    for (Storage = Stable; Storage < HTYPE_COUNT; Storage++)
00063    {
00064       Bin = NULL;
00065       for (i = 0; i < Hive->Storage[Storage].Length; i++)
00066       {
00067          if (Hive->Storage[Storage].BlockList[i].BinAddress == (ULONG_PTR)NULL)
00068             continue;
00069          if (Hive->Storage[Storage].BlockList[i].BinAddress != (ULONG_PTR)Bin)
00070          {
00071             Bin = (PHBIN)Hive->Storage[Storage].BlockList[i].BinAddress;
00072             Hive->Free((PHBIN)Hive->Storage[Storage].BlockList[i].BinAddress, 0);
00073          }
00074          Hive->Storage[Storage].BlockList[i].BinAddress = (ULONG_PTR)NULL;
00075          Hive->Storage[Storage].BlockList[i].BlockAddress = (ULONG_PTR)NULL;
00076       }
00077 
00078       if (Hive->Storage[Storage].Length)
00079          Hive->Free(Hive->Storage[Storage].BlockList, 0);
00080    }
00081 }
00082 
00092 NTSTATUS CMAPI
00093 HvpCreateHive(
00094    PHHIVE RegistryHive)
00095 {
00096    PHBASE_BLOCK BaseBlock;
00097    ULONG Index;
00098 
00099    BaseBlock = RegistryHive->Allocate(sizeof(HBASE_BLOCK), FALSE, TAG_CM);
00100    if (BaseBlock == NULL)
00101       return STATUS_NO_MEMORY;
00102    RtlZeroMemory(BaseBlock, sizeof(HBASE_BLOCK));
00103    BaseBlock->Signature = HV_SIGNATURE;
00104    BaseBlock->Major = HSYS_MAJOR;
00105    BaseBlock->Minor = HSYS_MINOR;
00106    BaseBlock->Type = HFILE_TYPE_PRIMARY;
00107    BaseBlock->Format = HBASE_FORMAT_MEMORY;
00108    BaseBlock->Cluster = 1;
00109    BaseBlock->RootCell = HCELL_NIL;
00110    BaseBlock->Length = HV_BLOCK_SIZE;
00111    BaseBlock->Sequence1 = 1;
00112    BaseBlock->Sequence2 = 1;
00113    /* FIXME: Fill in the file name */
00114    BaseBlock->CheckSum = HvpHiveHeaderChecksum(BaseBlock);
00115 
00116    RegistryHive->BaseBlock = BaseBlock;
00117    for (Index = 0; Index < 24; Index++)
00118    {
00119       RegistryHive->Storage[Stable].FreeDisplay[Index] = HCELL_NIL;
00120       RegistryHive->Storage[Volatile].FreeDisplay[Index] = HCELL_NIL;
00121    }
00122    RtlInitializeBitMap(&RegistryHive->DirtyVector, NULL, 0);
00123 
00124    return STATUS_SUCCESS;
00125 }
00126 
00137 NTSTATUS CMAPI
00138 HvpInitializeMemoryHive(
00139    PHHIVE Hive,
00140    PVOID ChunkBase)
00141 {
00142    SIZE_T BlockIndex;
00143    PHBIN Bin, NewBin;
00144    ULONG i;
00145    ULONG BitmapSize;
00146    PULONG BitmapBuffer;
00147    SIZE_T ChunkSize;
00148 
00149    //
00150    // This hack is similar in magnitude to the US's National Debt
00151    //
00152    ChunkSize = ((PHBASE_BLOCK)ChunkBase)->Length;
00153    ((PHBASE_BLOCK)ChunkBase)->Length = HV_BLOCK_SIZE;
00154    DPRINT("ChunkSize: %lx\n", ChunkSize);
00155 
00156    if (ChunkSize < sizeof(HBASE_BLOCK) ||
00157        !HvpVerifyHiveHeader((PHBASE_BLOCK)ChunkBase))
00158    {
00159       DPRINT1("Registry is corrupt: ChunkSize %lu < sizeof(HBASE_BLOCK) %lu, "
00160           "or HvpVerifyHiveHeader() failed\n", ChunkSize, (SIZE_T)sizeof(HBASE_BLOCK));
00161       return STATUS_REGISTRY_CORRUPT;
00162    }
00163 
00164    Hive->BaseBlock = Hive->Allocate(sizeof(HBASE_BLOCK), FALSE, TAG_CM);
00165    if (Hive->BaseBlock == NULL)
00166    {
00167       return STATUS_NO_MEMORY;
00168    }
00169    RtlCopyMemory(Hive->BaseBlock, ChunkBase, sizeof(HBASE_BLOCK));
00170 
00171    /*
00172     * Build a block list from the in-memory chunk and copy the data as
00173     * we go.
00174     */
00175 
00176    Hive->Storage[Stable].Length = (ULONG)(ChunkSize / HV_BLOCK_SIZE) - 1;
00177    Hive->Storage[Stable].BlockList =
00178       Hive->Allocate(Hive->Storage[Stable].Length *
00179                      sizeof(HMAP_ENTRY), FALSE, TAG_CM);
00180    if (Hive->Storage[Stable].BlockList == NULL)
00181    {
00182       DPRINT1("Allocating block list failed\n");
00183       Hive->Free(Hive->BaseBlock, 0);
00184       return STATUS_NO_MEMORY;
00185    }
00186 
00187    for (BlockIndex = 0; BlockIndex < Hive->Storage[Stable].Length; )
00188    {
00189       Bin = (PHBIN)((ULONG_PTR)ChunkBase + (BlockIndex + 1) * HV_BLOCK_SIZE);
00190       if (Bin->Signature != HV_BIN_SIGNATURE ||
00191           (Bin->Size % HV_BLOCK_SIZE) != 0)
00192       {
00193          Hive->Free(Hive->BaseBlock, 0);
00194          Hive->Free(Hive->Storage[Stable].BlockList, 0);
00195          return STATUS_REGISTRY_CORRUPT;
00196       }
00197 
00198       NewBin = Hive->Allocate(Bin->Size, TRUE, TAG_CM);
00199       if (NewBin == NULL)
00200       {
00201          Hive->Free(Hive->BaseBlock, 0);
00202          Hive->Free(Hive->Storage[Stable].BlockList, 0);
00203          return STATUS_NO_MEMORY;
00204       }
00205 
00206       Hive->Storage[Stable].BlockList[BlockIndex].BinAddress = (ULONG_PTR)NewBin;
00207       Hive->Storage[Stable].BlockList[BlockIndex].BlockAddress = (ULONG_PTR)NewBin;
00208 
00209       RtlCopyMemory(NewBin, Bin, Bin->Size);
00210 
00211       if (Bin->Size > HV_BLOCK_SIZE)
00212       {
00213          for (i = 1; i < Bin->Size / HV_BLOCK_SIZE; i++)
00214          {
00215             Hive->Storage[Stable].BlockList[BlockIndex + i].BinAddress = (ULONG_PTR)NewBin;
00216             Hive->Storage[Stable].BlockList[BlockIndex + i].BlockAddress =
00217                ((ULONG_PTR)NewBin + (i * HV_BLOCK_SIZE));
00218          }
00219       }
00220 
00221       BlockIndex += Bin->Size / HV_BLOCK_SIZE;
00222    }
00223 
00224    if (HvpCreateHiveFreeCellList(Hive))
00225    {
00226       HvpFreeHiveBins(Hive);
00227       Hive->Free(Hive->BaseBlock, 0);
00228       return STATUS_NO_MEMORY;
00229    }
00230 
00231    BitmapSize = ROUND_UP(Hive->Storage[Stable].Length,
00232                          sizeof(ULONG) * 8) / 8;
00233    BitmapBuffer = (PULONG)Hive->Allocate(BitmapSize, TRUE, TAG_CM);
00234    if (BitmapBuffer == NULL)
00235    {
00236       HvpFreeHiveBins(Hive);
00237       Hive->Free(Hive->BaseBlock, 0);
00238       return STATUS_NO_MEMORY;
00239    }
00240 
00241    RtlInitializeBitMap(&Hive->DirtyVector, BitmapBuffer, BitmapSize * 8);
00242    RtlClearAllBits(&Hive->DirtyVector);
00243 
00244    return STATUS_SUCCESS;
00245 }
00246 
00257 NTSTATUS CMAPI
00258 HvpInitializeMemoryInplaceHive(
00259    PHHIVE Hive,
00260    PVOID ChunkBase)
00261 {
00262    if (!HvpVerifyHiveHeader((PHBASE_BLOCK)ChunkBase))
00263    {
00264       return STATUS_REGISTRY_CORRUPT;
00265    }
00266 
00267    Hive->BaseBlock = (PHBASE_BLOCK)ChunkBase;
00268    Hive->ReadOnly = TRUE;
00269    Hive->Flat = TRUE;
00270 
00271    return STATUS_SUCCESS;
00272 }
00273 
00274 typedef enum _RESULT
00275 {
00276     NotHive,
00277     Fail,
00278     NoMemory,
00279     HiveSuccess,
00280     RecoverHeader,
00281     RecoverData,
00282     SelfHeal
00283 } RESULT;
00284 
00285 RESULT CMAPI
00286 HvpGetHiveHeader(IN PHHIVE Hive,
00287                  IN PHBASE_BLOCK *HiveBaseBlock,
00288                  IN PLARGE_INTEGER TimeStamp)
00289 {
00290     PHBASE_BLOCK BaseBlock;
00291     ULONG Alignment;
00292     ULONG Result;
00293     ULONG Offset = 0;
00294     ASSERT(sizeof(HBASE_BLOCK) >= (HV_BLOCK_SIZE * Hive->Cluster));
00295 
00296     /* Assume failure and allocate the buffer */
00297     *HiveBaseBlock = 0;
00298     BaseBlock = Hive->Allocate(sizeof(HBASE_BLOCK), TRUE, TAG_CM);
00299     if (!BaseBlock) return NoMemory;
00300 
00301     /* Check for, and enforce, alignment */
00302     Alignment = Hive->Cluster * HV_BLOCK_SIZE -1;
00303     if ((ULONG_PTR)BaseBlock & Alignment)
00304     {
00305         /* Free the old header */
00306         Hive->Free(BaseBlock, 0);
00307         BaseBlock = Hive->Allocate(PAGE_SIZE, TRUE, TAG_CM);
00308         if (!BaseBlock) return NoMemory;
00309 
00310         //BaseBlock->Length = PAGE_SIZE; ??
00311     }
00312 
00313     /* Clear it */
00314     RtlZeroMemory(BaseBlock, sizeof(HBASE_BLOCK));
00315 
00316     /* Now read it from disk */
00317     Result = Hive->FileRead(Hive,
00318                             HFILE_TYPE_PRIMARY,
00319                             &Offset,
00320                             BaseBlock,
00321                             Hive->Cluster * HV_BLOCK_SIZE);
00322 
00323     /* Couldn't read: assume it's not a hive */
00324     if (!Result) return NotHive;
00325 
00326     /* Do validation */
00327     if (!HvpVerifyHiveHeader(BaseBlock)) return NotHive;
00328 
00329     /* Return information */
00330     *HiveBaseBlock = BaseBlock;
00331     *TimeStamp = BaseBlock->TimeStamp;
00332     return HiveSuccess;
00333 }
00334 
00335 NTSTATUS CMAPI
00336 HvLoadHive(IN PHHIVE Hive,
00337            IN ULONG FileSize)
00338 {
00339     PHBASE_BLOCK BaseBlock = NULL;
00340     ULONG Result;
00341     LARGE_INTEGER TimeStamp;
00342     ULONG Offset = 0;
00343     PVOID HiveData;
00344 
00345     /* Get the hive header */
00346     Result = HvpGetHiveHeader(Hive, &BaseBlock, &TimeStamp);
00347     switch (Result)
00348     {
00349         /* Out of memory */
00350         case NoMemory:
00351 
00352             /* Fail */
00353             return STATUS_INSUFFICIENT_RESOURCES;
00354 
00355         /* Not a hive */
00356         case NotHive:
00357 
00358             /* Fail */
00359             return STATUS_NOT_REGISTRY_FILE;
00360 
00361         /* Has recovery data */
00362         case RecoverData:
00363         case RecoverHeader:
00364 
00365             /* Fail */
00366             return STATUS_REGISTRY_CORRUPT;
00367     }
00368 
00369     /* Set default boot type */
00370     BaseBlock->BootType = 0;
00371 
00372     /* Setup hive data */
00373     Hive->BaseBlock = BaseBlock;
00374     Hive->Version = Hive->BaseBlock->Minor;
00375 
00376     /* Allocate a buffer large enough to hold the hive */
00377     HiveData = Hive->Allocate(FileSize, TRUE, TAG_CM);
00378     if (!HiveData) return STATUS_INSUFFICIENT_RESOURCES;
00379 
00380     /* Now read the whole hive */
00381     Result = Hive->FileRead(Hive,
00382                             HFILE_TYPE_PRIMARY,
00383                             &Offset,
00384                             HiveData,
00385                             FileSize);
00386     if (!Result) return STATUS_NOT_REGISTRY_FILE;
00387 
00388     /* Apply "US National Debt" hack */
00389     ((PHBASE_BLOCK)HiveData)->Length = FileSize;
00390 
00391     /* Free our base block... it's usless in this implementation */
00392     Hive->Free(BaseBlock, 0);
00393 
00394     /* Initialize the hive directly from memory */
00395     return HvpInitializeMemoryHive(Hive, HiveData);
00396 }
00397 
00429 NTSTATUS CMAPI
00430 HvInitialize(
00431    PHHIVE RegistryHive,
00432    ULONG Operation,
00433    ULONG HiveType,
00434    ULONG HiveFlags,
00435    PVOID HiveData OPTIONAL,
00436    PALLOCATE_ROUTINE Allocate,
00437    PFREE_ROUTINE Free,
00438    PFILE_SET_SIZE_ROUTINE FileSetSize,
00439    PFILE_WRITE_ROUTINE FileWrite,
00440    PFILE_READ_ROUTINE FileRead,
00441    PFILE_FLUSH_ROUTINE FileFlush,
00442    ULONG Cluster OPTIONAL,
00443    PUNICODE_STRING FileName)
00444 {
00445    NTSTATUS Status;
00446    PHHIVE Hive = RegistryHive;
00447 
00448    UNREFERENCED_PARAMETER(HiveType);
00449    UNREFERENCED_PARAMETER(FileName);
00450 
00451    /*
00452     * Create a new hive structure that will hold all the maintenance data.
00453     */
00454 
00455    RtlZeroMemory(Hive, sizeof(HHIVE));
00456 
00457    Hive->Allocate = Allocate;
00458    Hive->Free = Free;
00459    Hive->FileRead = FileRead;
00460    Hive->FileWrite = FileWrite;
00461    Hive->FileSetSize = FileSetSize;
00462    Hive->FileFlush = FileFlush;
00463    Hive->StorageTypeCount = HTYPE_COUNT;
00464    Hive->Cluster = 1;
00465    Hive->Version = HSYS_MINOR;
00466    Hive->HiveFlags = HiveFlags &~ HIVE_NOLAZYFLUSH;
00467 
00468    switch (Operation)
00469    {
00470       case HINIT_CREATE:
00471          Status = HvpCreateHive(Hive);
00472          break;
00473 
00474       case HINIT_MEMORY:
00475          Status = HvpInitializeMemoryHive(Hive, HiveData);
00476          break;
00477 
00478       case HINIT_FLAT:
00479          Status = HvpInitializeMemoryInplaceHive(Hive, HiveData);
00480          break;
00481 
00482       case HINIT_FILE:
00483 
00484          /* Hack of doom: Cluster is actually the file size. */
00485          Status = HvLoadHive(Hive, Cluster);
00486          if ((Status != STATUS_SUCCESS) &&
00487              (Status != STATUS_REGISTRY_RECOVERED))
00488          {
00489              /* Unrecoverable failure */
00490              return Status;
00491          }
00492 
00493          /* Check for previous damage */
00494          if (Status == STATUS_REGISTRY_RECOVERED) ASSERT(FALSE);
00495          break;
00496 
00497       default:
00498          /* FIXME: A better return status value is needed */
00499          Status = STATUS_NOT_IMPLEMENTED;
00500          ASSERT(FALSE);
00501    }
00502 
00503    if (!NT_SUCCESS(Status))
00504       return Status;
00505 
00506    if (Operation != HINIT_CREATE) CmPrepareHive(Hive);
00507 
00508    return Status;
00509 }
00510 
00517 VOID CMAPI
00518 HvFree(
00519    PHHIVE RegistryHive)
00520 {
00521    if (!RegistryHive->ReadOnly)
00522    {
00523       /* Release hive bitmap */
00524       if (RegistryHive->DirtyVector.Buffer)
00525       {
00526          RegistryHive->Free(RegistryHive->DirtyVector.Buffer, 0);
00527       }
00528 
00529       HvpFreeHiveBins(RegistryHive);
00530    }
00531 
00532    RegistryHive->Free(RegistryHive, 0);
00533 }
00534 
00535 /* EOF */

Generated on Fri May 25 2012 04:34:28 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.