Пример #1
0
VOID CMAPI
HvpFreeHiveBins(
   PHHIVE Hive)
{
   ULONG i;
   PHBIN Bin;
   ULONG Storage;

   for (Storage = Stable; Storage < HTYPE_COUNT; Storage++)
   {
      Bin = NULL;
      for (i = 0; i < Hive->Storage[Storage].Length; i++)
      {
         if (Hive->Storage[Storage].BlockList[i].BinAddress == (ULONG_PTR)NULL)
            continue;
         if (Hive->Storage[Storage].BlockList[i].BinAddress != (ULONG_PTR)Bin)
         {
            Bin = (PHBIN)Hive->Storage[Storage].BlockList[i].BinAddress;
            Hive->Free((PHBIN)Hive->Storage[Storage].BlockList[i].BinAddress, 0);
         }
         Hive->Storage[Storage].BlockList[i].BinAddress = (ULONG_PTR)NULL;
         Hive->Storage[Storage].BlockList[i].BlockAddress = (ULONG_PTR)NULL;
      }

      if (Hive->Storage[Storage].Length)
         Hive->Free(Hive->Storage[Storage].BlockList, 0);
   }
}
Пример #2
0
NTSTATUS CMAPI
HvpCreateHive(
   PHHIVE RegistryHive,
   PCUNICODE_STRING FileName OPTIONAL)
{
   PHBASE_BLOCK BaseBlock;
   ULONG Index;

   BaseBlock = RegistryHive->Allocate(sizeof(HBASE_BLOCK), FALSE, TAG_CM);
   if (BaseBlock == NULL)
      return STATUS_NO_MEMORY;

   RtlZeroMemory(BaseBlock, sizeof(HBASE_BLOCK));

   BaseBlock->Signature = HV_SIGNATURE;
   BaseBlock->Major = HSYS_MAJOR;
   BaseBlock->Minor = HSYS_MINOR;
   BaseBlock->Type = HFILE_TYPE_PRIMARY;
   BaseBlock->Format = HBASE_FORMAT_MEMORY;
   BaseBlock->Cluster = 1;
   BaseBlock->RootCell = HCELL_NIL;
   BaseBlock->Length = 0;
   BaseBlock->Sequence1 = 1;
   BaseBlock->Sequence2 = 1;

   /* Copy the 31 last characters of the hive file name if any */
   if (FileName)
   {
      if (FileName->Length / sizeof(WCHAR) <= HIVE_FILENAME_MAXLEN)
      {
         RtlCopyMemory(BaseBlock->FileName,
                       FileName->Buffer,
                       FileName->Length);
      }
      else
      {
         RtlCopyMemory(BaseBlock->FileName,
                       FileName->Buffer +
                       FileName->Length / sizeof(WCHAR) - HIVE_FILENAME_MAXLEN,
                       HIVE_FILENAME_MAXLEN * sizeof(WCHAR));
      }

      /* NULL-terminate */
      BaseBlock->FileName[HIVE_FILENAME_MAXLEN] = L'\0';
   }

   BaseBlock->CheckSum = HvpHiveHeaderChecksum(BaseBlock);

   RegistryHive->BaseBlock = BaseBlock;
   for (Index = 0; Index < 24; Index++)
   {
      RegistryHive->Storage[Stable].FreeDisplay[Index] = HCELL_NIL;
      RegistryHive->Storage[Volatile].FreeDisplay[Index] = HCELL_NIL;
   }

   return STATUS_SUCCESS;
}
Пример #3
0
VOID CMAPI
HvFree(
   PHHIVE RegistryHive)
{
   if (!RegistryHive->ReadOnly)
   {
      /* Release hive bitmap */
      if (RegistryHive->DirtyVector.Buffer)
      {
         RegistryHive->Free(RegistryHive->DirtyVector.Buffer, 0);
      }

      HvpFreeHiveBins(RegistryHive);

      /* Free the BaseBlock */
      if (RegistryHive->BaseBlock)
      {
         RegistryHive->Free(RegistryHive->BaseBlock, 0);
         RegistryHive->BaseBlock = NULL;
      }
   }
}
Пример #4
0
static BOOLEAN CMAPI
HvpWriteHive(
   PHHIVE RegistryHive,
   BOOLEAN OnlyDirty)
{
   ULONG FileOffset;
   ULONG BlockIndex;
   ULONG LastIndex;
   PVOID BlockPtr;
   BOOLEAN Success;

   ASSERT(RegistryHive->ReadOnly == FALSE);
   ASSERT(RegistryHive->BaseBlock->Length ==
          RegistryHive->Storage[Stable].Length * HV_BLOCK_SIZE);

   DPRINT("HvpWriteHive called\n");

   if (RegistryHive->BaseBlock->Sequence1 !=
       RegistryHive->BaseBlock->Sequence2)
   {
      return FALSE;
   }

   /* Update first update counter and CheckSum */
   RegistryHive->BaseBlock->Type = HFILE_TYPE_PRIMARY;
   RegistryHive->BaseBlock->Sequence1++;
   RegistryHive->BaseBlock->CheckSum =
   HvpHiveHeaderChecksum(RegistryHive->BaseBlock);

   /* Write hive block */
   FileOffset = 0;
   Success = RegistryHive->FileWrite(RegistryHive, HFILE_TYPE_PRIMARY,
                                     &FileOffset, RegistryHive->BaseBlock,
                                     sizeof(HBASE_BLOCK));
   if (!Success)
   {
      return FALSE;
   }

   BlockIndex = 0;
   while (BlockIndex < RegistryHive->Storage[Stable].Length)
   {
      if (OnlyDirty)
      {
         LastIndex = BlockIndex;
         BlockIndex = RtlFindSetBits(&RegistryHive->DirtyVector, 1, BlockIndex);
         if (BlockIndex == ~0U || BlockIndex < LastIndex)
         {
            break;
         }
      }

      BlockPtr = (PVOID)RegistryHive->Storage[Stable].BlockList[BlockIndex].BlockAddress;
      FileOffset = (BlockIndex + 1) * HV_BLOCK_SIZE;

      /* Write hive block */
      Success = RegistryHive->FileWrite(RegistryHive, HFILE_TYPE_PRIMARY,
                                        &FileOffset, BlockPtr,
                                        HV_BLOCK_SIZE);
      if (!Success)
      {
         return FALSE;
      }

      BlockIndex++;
   }

   Success = RegistryHive->FileFlush(RegistryHive, HFILE_TYPE_PRIMARY, NULL, 0);
   if (!Success)
   {
      DPRINT("FileFlush failed\n");
   }

   /* Update second update counter and CheckSum */
   RegistryHive->BaseBlock->Sequence2++;
   RegistryHive->BaseBlock->CheckSum =
      HvpHiveHeaderChecksum(RegistryHive->BaseBlock);

   /* Write hive block */
   FileOffset = 0;
   Success = RegistryHive->FileWrite(RegistryHive, HFILE_TYPE_PRIMARY,
                                     &FileOffset, RegistryHive->BaseBlock,
                                     sizeof(HBASE_BLOCK));
   if (!Success)
   {
      return FALSE;
   }

   Success = RegistryHive->FileFlush(RegistryHive, HFILE_TYPE_PRIMARY, NULL, 0);
   if (!Success)
   {
      DPRINT("FileFlush failed\n");
   }

   return TRUE;
}
Пример #5
0
static BOOLEAN CMAPI
HvpWriteLog(
   PHHIVE RegistryHive)
{
   ULONG FileOffset;
   ULONG BufferSize;
   ULONG BitmapSize;
   PUCHAR Buffer;
   PUCHAR Ptr;
   ULONG BlockIndex;
   ULONG LastIndex;
   PVOID BlockPtr;
   BOOLEAN Success;

   UNIMPLEMENTED;
   return TRUE;

   ASSERT(RegistryHive->ReadOnly == FALSE);
   ASSERT(RegistryHive->BaseBlock->Length ==
          RegistryHive->Storage[Stable].Length * HV_BLOCK_SIZE);

   DPRINT("HvpWriteLog called\n");

   if (RegistryHive->BaseBlock->Sequence1 !=
       RegistryHive->BaseBlock->Sequence2)
   {
      return FALSE;
   }

   BitmapSize = RegistryHive->DirtyVector.SizeOfBitMap;
   BufferSize = HV_LOG_HEADER_SIZE + sizeof(ULONG) + BitmapSize;
   BufferSize = ROUND_UP(BufferSize, HV_BLOCK_SIZE);

   DPRINT("Bitmap size %lu  buffer size: %lu\n", BitmapSize, BufferSize);

   Buffer = RegistryHive->Allocate(BufferSize, TRUE, TAG_CM);
   if (Buffer == NULL)
   {
      return FALSE;
   }

   /* Update first update counter and CheckSum */
   RegistryHive->BaseBlock->Type = HFILE_TYPE_LOG;
   RegistryHive->BaseBlock->Sequence1++;
   RegistryHive->BaseBlock->CheckSum =
      HvpHiveHeaderChecksum(RegistryHive->BaseBlock);

   /* Copy hive header */
   RtlCopyMemory(Buffer, RegistryHive->BaseBlock, HV_LOG_HEADER_SIZE);
   Ptr = Buffer + HV_LOG_HEADER_SIZE;
   RtlCopyMemory(Ptr, "DIRT", 4);
   Ptr += 4;
   RtlCopyMemory(Ptr, RegistryHive->DirtyVector.Buffer, BitmapSize);

   /* Write hive block and block bitmap */
   FileOffset = 0;
   Success = RegistryHive->FileWrite(RegistryHive, HFILE_TYPE_LOG,
                                     &FileOffset, Buffer, BufferSize);
   RegistryHive->Free(Buffer, 0);

   if (!Success)
   {
      return FALSE;
   }

   /* Write dirty blocks */
   FileOffset = BufferSize;
   BlockIndex = 0;
   while (BlockIndex < RegistryHive->Storage[Stable].Length)
   {
      LastIndex = BlockIndex;
      BlockIndex = RtlFindSetBits(&RegistryHive->DirtyVector, 1, BlockIndex);
      if (BlockIndex == ~0U || BlockIndex < LastIndex)
      {
         break;
      }

      BlockPtr = (PVOID)RegistryHive->Storage[Stable].BlockList[BlockIndex].BlockAddress;

      /* Write hive block */
      Success = RegistryHive->FileWrite(RegistryHive, HFILE_TYPE_LOG,
                                        &FileOffset, BlockPtr,
                                        HV_BLOCK_SIZE);
      if (!Success)
      {
         return FALSE;
      }

      BlockIndex++;
      FileOffset += HV_BLOCK_SIZE;
    }

   Success = RegistryHive->FileSetSize(RegistryHive, HFILE_TYPE_LOG, FileOffset, FileOffset);
   if (!Success)
   {
      DPRINT("FileSetSize failed\n");
      return FALSE;
    }

   /* Flush the log file */
   Success = RegistryHive->FileFlush(RegistryHive, HFILE_TYPE_LOG, NULL, 0);
   if (!Success)
   {
      DPRINT("FileFlush failed\n");
   }

   /* Update second update counter and CheckSum. */
   RegistryHive->BaseBlock->Sequence2++;
   RegistryHive->BaseBlock->CheckSum =
      HvpHiveHeaderChecksum(RegistryHive->BaseBlock);

   /* Write hive header again with updated sequence counter. */
   FileOffset = 0;
   Success = RegistryHive->FileWrite(RegistryHive, HFILE_TYPE_LOG,
                                     &FileOffset, RegistryHive->BaseBlock,
                                     HV_LOG_HEADER_SIZE);
   if (!Success)
   {
      return FALSE;
   }

   /* Flush the log file */
   Success = RegistryHive->FileFlush(RegistryHive, HFILE_TYPE_LOG, NULL, 0);
   if (!Success)
   {
      DPRINT("FileFlush failed\n");
   }

   return TRUE;
}
Пример #6
0
NTSTATUS CMAPI
HvpInitializeMemoryHive(
   PHHIVE Hive,
   PVOID ChunkBase)
{
   SIZE_T BlockIndex;
   PHBIN Bin, NewBin;
   ULONG i;
   ULONG BitmapSize;
   PULONG BitmapBuffer;
   SIZE_T ChunkSize;

   ChunkSize = ((PHBASE_BLOCK)ChunkBase)->Length;
   DPRINT("ChunkSize: %lx\n", ChunkSize);

   if (ChunkSize < sizeof(HBASE_BLOCK) ||
       !HvpVerifyHiveHeader((PHBASE_BLOCK)ChunkBase))
   {
      DPRINT1("Registry is corrupt: ChunkSize %lu < sizeof(HBASE_BLOCK) %lu, "
          "or HvpVerifyHiveHeader() failed\n", ChunkSize, (SIZE_T)sizeof(HBASE_BLOCK));
      return STATUS_REGISTRY_CORRUPT;
   }

   Hive->BaseBlock = Hive->Allocate(sizeof(HBASE_BLOCK), FALSE, TAG_CM);
   if (Hive->BaseBlock == NULL)
   {
      return STATUS_NO_MEMORY;
   }
   RtlCopyMemory(Hive->BaseBlock, ChunkBase, sizeof(HBASE_BLOCK));

   /*
    * Build a block list from the in-memory chunk and copy the data as
    * we go.
    */

   Hive->Storage[Stable].Length = (ULONG)(ChunkSize / HV_BLOCK_SIZE);
   Hive->Storage[Stable].BlockList =
      Hive->Allocate(Hive->Storage[Stable].Length *
                     sizeof(HMAP_ENTRY), FALSE, TAG_CM);
   if (Hive->Storage[Stable].BlockList == NULL)
   {
      DPRINT1("Allocating block list failed\n");
      Hive->Free(Hive->BaseBlock, 0);
      return STATUS_NO_MEMORY;
   }

   for (BlockIndex = 0; BlockIndex < Hive->Storage[Stable].Length; )
   {
      Bin = (PHBIN)((ULONG_PTR)ChunkBase + (BlockIndex + 1) * HV_BLOCK_SIZE);
      if (Bin->Signature != HV_BIN_SIGNATURE ||
          (Bin->Size % HV_BLOCK_SIZE) != 0)
      {
         DPRINT1("Invalid bin at BlockIndex %lu, Signature 0x%x, Size 0x%x\n",
                 (unsigned long)BlockIndex, (unsigned)Bin->Signature, (unsigned)Bin->Size);
         Hive->Free(Hive->BaseBlock, 0);
         Hive->Free(Hive->Storage[Stable].BlockList, 0);
         return STATUS_REGISTRY_CORRUPT;
      }

      NewBin = Hive->Allocate(Bin->Size, TRUE, TAG_CM);
      if (NewBin == NULL)
      {
         Hive->Free(Hive->BaseBlock, 0);
         Hive->Free(Hive->Storage[Stable].BlockList, 0);
         return STATUS_NO_MEMORY;
      }

      Hive->Storage[Stable].BlockList[BlockIndex].BinAddress = (ULONG_PTR)NewBin;
      Hive->Storage[Stable].BlockList[BlockIndex].BlockAddress = (ULONG_PTR)NewBin;

      RtlCopyMemory(NewBin, Bin, Bin->Size);

      if (Bin->Size > HV_BLOCK_SIZE)
      {
         for (i = 1; i < Bin->Size / HV_BLOCK_SIZE; i++)
         {
            Hive->Storage[Stable].BlockList[BlockIndex + i].BinAddress = (ULONG_PTR)NewBin;
            Hive->Storage[Stable].BlockList[BlockIndex + i].BlockAddress =
               ((ULONG_PTR)NewBin + (i * HV_BLOCK_SIZE));
         }
      }

      BlockIndex += Bin->Size / HV_BLOCK_SIZE;
   }

   if (HvpCreateHiveFreeCellList(Hive))
   {
      HvpFreeHiveBins(Hive);
      Hive->Free(Hive->BaseBlock, 0);
      return STATUS_NO_MEMORY;
   }

   BitmapSize = ROUND_UP(Hive->Storage[Stable].Length,
                         sizeof(ULONG) * 8) / 8;
   BitmapBuffer = (PULONG)Hive->Allocate(BitmapSize, TRUE, TAG_CM);
   if (BitmapBuffer == NULL)
   {
      HvpFreeHiveBins(Hive);
      Hive->Free(Hive->BaseBlock, 0);
      return STATUS_NO_MEMORY;
   }

   RtlInitializeBitMap(&Hive->DirtyVector, BitmapBuffer, BitmapSize * 8);
   RtlClearAllBits(&Hive->DirtyVector);

   return STATUS_SUCCESS;
}