Fix some registry structures to match the Windows format.
[reactos.git] / reactos / ntoskrnl / cm / cm.h
index bc19c68..fd34016 100644 (file)
-
 #ifndef __INCLUDE_CM_H
 #define __INCLUDE_CM_H
 
-#include <ddk/ntddk.h>
-#include <internal/config.h>
-#include <internal/ob.h>
-#include <limits.h>
-#include <string.h>
-#include <internal/pool.h>
-#include <internal/registry.h>
+#ifdef DBG
+#define CHECKED 1
+#else
+#define CHECKED 0
+#endif
+
+#define  REG_ROOT_KEY_NAME             L"\\Registry"
+#define  REG_MACHINE_KEY_NAME          L"\\Registry\\Machine"
+#define  REG_HARDWARE_KEY_NAME         L"\\Registry\\Machine\\HARDWARE"
+#define  REG_DESCRIPTION_KEY_NAME      L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION"
+#define  REG_DEVICEMAP_KEY_NAME                L"\\Registry\\Machine\\HARDWARE\\DEVICEMAP"
+#define  REG_RESOURCEMAP_KEY_NAME      L"\\Registry\\Machine\\HARDWARE\\RESOURCEMAP"
+#define  REG_CLASSES_KEY_NAME          L"\\Registry\\Machine\\Software\\Classes"
+#define  REG_SYSTEM_KEY_NAME           L"\\Registry\\Machine\\SYSTEM"
+#define  REG_SOFTWARE_KEY_NAME         L"\\Registry\\Machine\\SOFTWARE"
+#define  REG_SAM_KEY_NAME              L"\\Registry\\Machine\\SAM"
+#define  REG_SEC_KEY_NAME              L"\\Registry\\Machine\\SECURITY"
+#define  REG_USER_KEY_NAME             L"\\Registry\\User"
+#define  REG_DEFAULT_USER_KEY_NAME     L"\\Registry\\User\\.Default"
+#define  REG_CURRENT_USER_KEY_NAME     L"\\Registry\\User\\CurrentUser"
+
+#define  SYSTEM_REG_FILE               L"\\SystemRoot\\System32\\Config\\SYSTEM"
+#define  SYSTEM_LOG_FILE               L"\\SystemRoot\\System32\\Config\\SYSTEM.log"
+#define  SOFTWARE_REG_FILE             L"\\SystemRoot\\System32\\Config\\SOFTWARE"
+#define  DEFAULT_USER_REG_FILE         L"\\SystemRoot\\System32\\Config\\DEFAULT"
+#define  SAM_REG_FILE                  L"\\SystemRoot\\System32\\Config\\SAM"
+#define  SEC_REG_FILE                  L"\\SystemRoot\\System32\\Config\\SECURITY"
 
-#define NDEBUG
-#include <internal/debug.h>
+#define  REG_SYSTEM_FILE_NAME          L"\\system"
+#define  REG_SOFTWARE_FILE_NAME                L"\\software"
+#define  REG_DEFAULT_USER_FILE_NAME    L"\\default"
+#define  REG_SAM_FILE_NAME             L"\\sam"
+#define  REG_SEC_FILE_NAME             L"\\security"
+
+#define  REG_BLOCK_SIZE                4096
+#define  REG_HBIN_DATA_OFFSET          32
+#define  REG_INIT_BLOCK_LIST_SIZE      32
+#define  REG_INIT_HASH_TABLE_SIZE      3
+#define  REG_EXTEND_HASH_TABLE_SIZE    4
+#define  REG_VALUE_LIST_CELL_MULTIPLE  4
+
+#define  REG_HIVE_ID                   0x66676572
+#define  REG_BIN_ID                    0x6e696268
+#define  REG_KEY_CELL_ID               0x6b6e
+#define  REG_HASH_TABLE_CELL_ID        0x666c
+#define  REG_VALUE_CELL_ID             0x6b76
+#define  REG_SECURITY_CELL_ID          0x6b73
 
-#define  KO_MARKED_FOR_DELETE  0x00000001
 
 // BLOCK_OFFSET = offset in file after header block
-typedef DWORD  BLOCK_OFFSET;
+typedef ULONG BLOCK_OFFSET, *PBLOCK_OFFSET;
+
+#include <pshpack1.h>
 
 /* header for registry hive file : */
-typedef struct _HEADER_BLOCK
+typedef struct _HIVE_HEADER
 {
-  ULONG  BlockId;              /* ="regf" */
-  ULONG  Version;              /* file version ?*/
-  ULONG  VersionOld;           /* file version ?*/
-  FILETIME  DateModified;      /* please don't replace with LARGE_INTEGER !*/
-  ULONG  Unused3;              /* registry format version ? */
-  ULONG  Unused4;              /* registry format version ? */
-  ULONG  Unused5;              /* registry format version ? */
-  ULONG  Unused6;              /* registry format version ? */
-  BLOCK_OFFSET  RootKeyBlock;
+  /* Hive identifier "regf" (0x66676572) */
+  ULONG  BlockId;
+
+  /* Update counter */
+  ULONG  UpdateCounter1;
+
+  /* Update counter */
+  ULONG  UpdateCounter2;
+
+  /* When this hive file was last modified */
+  LARGE_INTEGER  DateModified;
+
+  /* Registry format major version (1) */
+  ULONG  MajorVersion;
+
+  /* Registry format minor version (3)
+     Version 3 added fast indexes, version 5 has large value optimizations */
+  ULONG  MinorVersion;
+
+  /* Registry file type (0 - Primary, 1 - Log) */
+  ULONG  Type;
+
+  /* Registry format (1 is the only defined value so far) */
+  ULONG  Format;
+
+  /* Offset into file from the byte after the end of the base block.
+     If the hive is volatile, this is the actual pointer to the KEY_CELL */
+  BLOCK_OFFSET  RootKeyOffset;
+
+  /* Size of each hive block ? */
   ULONG  BlockSize;
+
+  /* (1?) */
   ULONG  Unused7;
-  WCHAR  FileName[64];         /* end of file name */
-  ULONG  Unused8[83];
+
+  /* Name of hive file */
+  WCHAR  FileName[48];
+
+  ULONG  Reserved[99];
+
+  /* Checksum of first 0x200 bytes */
   ULONG  Checksum;
-} HEADER_BLOCK, *PHEADER_BLOCK;
+} HIVE_HEADER, *PHIVE_HEADER;
 
-typedef struct _HEAP_BLOCK
+typedef struct _BIN_HEADER
 {
-  ULONG  BlockId;              /* = "hbin" */
-  BLOCK_OFFSET  BlockOffset;   /* block offset of this heap */
-  ULONG  BlockSize;            /* size in bytes, 4k multiple */
-  ULONG  Unused1;
-  FILETIME  DateModified;      /* please don't replace with LARGE_INTEGER !*/
-  ULONG  Unused2;
-} HEAP_BLOCK, *PHEAP_BLOCK;
-
-// each sub_block begin with this struct :
-// in a free subblock, higher bit of SubBlockSize is set
-typedef struct _FREE_SUB_BLOCK
+  /* Bin identifier "hbin" (0x6E696268) */
+  ULONG  HeaderId;
+
+  /* Block offset of this bin */
+  BLOCK_OFFSET  BinOffset;
+
+  /* Size in bytes, multiple of the block size (4KB) */
+  ULONG  BinSize;
+
+  ULONG  Reserved[2];
+
+  /* When this bin was last modified */
+  LARGE_INTEGER  DateModified;
+
+  /* ? (In-memory only) */
+  ULONG  MemAlloc;
+} HBIN, *PHBIN;
+
+typedef struct _CELL_HEADER
 {
-  LONG  SubBlockSize;/* <0 if used, >0 if free */
-} FREE_SUB_BLOCK, *PFREE_SUB_BLOCK;
+  /* <0 if used, >0 if free */
+  LONG  CellSize;
+} CELL_HEADER, *PCELL_HEADER;
 
-typedef struct _KEY_BLOCK
+typedef struct _KEY_CELL
 {
-  LONG  SubBlockSize;
-  USHORT SubBlockId;
-  USHORT Type;
-  FILETIME  LastWriteTime;     /* please don't replace with LARGE_INTEGER !*/
+  /* Size of this cell */
+  LONG  CellSize;
+
+  /* Key cell identifier "kn" (0x6b6e) */
+  USHORT  Id;
+
+  /* Flags */
+  USHORT  Flags;
+
+  /* Time of last flush */
+  LARGE_INTEGER  LastWriteTime;
+
+  /* ? */
   ULONG  UnUsed1;
+
+  /* Block offset of parent key cell */
   BLOCK_OFFSET  ParentKeyOffset;
+
+  /* Count of sub keys for the key in this key cell */
   ULONG  NumberOfSubKeys;
+
+  /* ? */
   ULONG  UnUsed2;
+
+  /* Block offset of has table for FIXME: subkeys/values? */
   BLOCK_OFFSET  HashTableOffset;
+
+  /* ? */
   ULONG  UnUsed3;
+
+  /* Count of values contained in this key cell */
   ULONG  NumberOfValues;
-  BLOCK_OFFSET  ValuesOffset;
+
+  /* Block offset of VALUE_LIST_CELL */
+  BLOCK_OFFSET  ValueListOffset;
+
+  /* Block offset of security cell */
   BLOCK_OFFSET  SecurityKeyOffset;
+
+  /* Block offset of registry key class */
   BLOCK_OFFSET  ClassNameOffset;
+
+  /* ? */
   ULONG  Unused4[5];
+
+  /* Size in bytes of key name */
   USHORT NameSize;
-  USHORT ClassSize; /* size of ClassName in bytes */
-  UCHAR  Name[0]; /* warning : not zero terminated */
-} KEY_BLOCK, *PKEY_BLOCK;
 
-// hash record :
-// HashValue=four letters of value's name
+  /* Size of class name in bytes */
+  USHORT ClassSize;
+
+  /* Name of key (not zero terminated) */
+  UCHAR  Name[0];
+} KEY_CELL, *PKEY_CELL;
+
+/* KEY_CELL.Flags constants */
+#define  REG_KEY_ROOT_CELL                 0x0C
+#define  REG_KEY_LINK_CELL                 0x10
+#define  REG_KEY_NAME_PACKED               0x20
+
+/*
+ * Hash record
+ *
+ * HashValue:
+ *     packed name: four letters of value's name
+ *     otherwise: Zero!
+ */
 typedef struct _HASH_RECORD
 {
   BLOCK_OFFSET  KeyOffset;
   ULONG  HashValue;
 } HASH_RECORD, *PHASH_RECORD;
 
-typedef struct _HASH_TABLE_BLOCK
+typedef struct _HASH_TABLE_CELL
 {
-  LONG  SubBlockSize;
-  USHORT SubBlockId;
-  USHORT HashTableSize;
+  LONG  CellSize;
+  USHORT  Id;
+  USHORT  HashTableSize;
   HASH_RECORD  Table[0];
-} HASH_TABLE_BLOCK, *PHASH_TABLE_BLOCK;
+} HASH_TABLE_CELL, *PHASH_TABLE_CELL;
 
-typedef struct _VALUE_LIST_BLOCK
+
+typedef struct _VALUE_LIST_CELL
 {
-  LONG  SubBlockSize;
-  BLOCK_OFFSET  Values[0];
-} VALUE_LIST_BLOCK, *PVALUE_LIST_BLOCK;
+  LONG  CellSize;
+  BLOCK_OFFSET  ValueOffset[0];
+} VALUE_LIST_CELL, *PVALUE_LIST_CELL;
 
-typedef struct _VALUE_BLOCK
+typedef struct _VALUE_CELL
 {
-  LONG  SubBlockSize;
-  USHORT SubBlockId;   // "kv"
+  LONG  CellSize;
+  USHORT Id;   // "kv"
   USHORT NameSize;     // length of Name
-  LONG  DataSize;      // length of datas in the subblock pointed by DataOffset
+  ULONG  DataSize;     // length of datas in the cell pointed by DataOffset
   BLOCK_OFFSET  DataOffset;// datas are here if high bit of DataSize is set
   ULONG  DataType;
   USHORT Flags;
   USHORT Unused1;
   UCHAR  Name[0]; /* warning : not zero terminated */
-} VALUE_BLOCK, *PVALUE_BLOCK;
+} VALUE_CELL, *PVALUE_CELL;
+
+/* VALUE_CELL.Flags constants */
+#define REG_VALUE_NAME_PACKED             0x0001
 
-typedef struct _DATA_BLOCK
+/* VALUE_CELL.DataSize mask constants */
+#define REG_DATA_SIZE_MASK                 0x7FFFFFFF
+#define REG_DATA_IN_OFFSET                 0x80000000
+
+
+typedef struct _SECURITY_CELL
+{
+  LONG  CellSize;
+  USHORT Id;   // "sk"
+  USHORT Reserved;
+  BLOCK_OFFSET PrevSecurityCell;
+  BLOCK_OFFSET NextSecurityCell;
+  ULONG RefCount;
+  ULONG SdSize;
+  UCHAR Data[0];
+} SECURITY_CELL, *PSECURITY_CELL;
+
+
+typedef struct _DATA_CELL
 {
-  LONG  SubBlockSize;
+  LONG  CellSize;
   UCHAR  Data[0];
-} DATA_BLOCK, *PDATA_BLOCK;
+} DATA_CELL, *PDATA_CELL;
+
+#include <poppack.h>
 
-typedef struct _REGISTRY_FILE
+
+typedef struct _BLOCK_LIST_ENTRY
+{
+  PHBIN Bin;
+  PVOID Block;
+} BLOCK_LIST_ENTRY, *PBLOCK_LIST_ENTRY;
+
+
+typedef struct _REGISTRY_HIVE
 {
-  PWSTR  Filename;
+  LIST_ENTRY  HiveList;
+  ULONG  Flags;
+  UNICODE_STRING  HiveFileName;
+  UNICODE_STRING  LogFileName;
   ULONG  FileSize;
-  PFILE_OBJECT FileObject;
-  PHEADER_BLOCK  HeaderBlock;
-//  ULONG  NumberOfBlocks;
+  PHIVE_HEADER  HiveHeader;
+  ULONG  UpdateCounter;
   ULONG  BlockListSize;
-  PHEAP_BLOCK  *BlockList;
+  PBLOCK_LIST_ENTRY BlockList;
   ULONG  FreeListSize;
   ULONG  FreeListMax;
-  PFREE_SUB_BLOCK *FreeList;
+  PCELL_HEADER *FreeList;
   BLOCK_OFFSET *FreeListOffset;
-//  KSPIN_LOCK  RegLock;
-  KSEMAPHORE RegSem;
-  
 
-//  NTSTATUS  (*Extend)(ULONG NewSize);
-//  PVOID  (*Flush)(VOID);
-} REGISTRY_FILE, *PREGISTRY_FILE;
+  PSECURITY_CELL RootSecurityCell;
+
+  PULONG BitmapBuffer;
+  RTL_BITMAP  DirtyBitMap;
+  BOOLEAN  HiveDirty;
+} REGISTRY_HIVE, *PREGISTRY_HIVE;
 
-/*  Type defining the Object Manager Key Object  */
+/* REGISTRY_HIVE.Flags constants */
+/* When set, the hive uses pointers instead of offsets. */
+#define HIVE_POINTER    0x00000001
+
+/* When set, the hive is not backed by a file.
+   Therefore, it can not be flushed to disk. */
+#define HIVE_NO_FILE    0x00000002
+
+/* When set, a modified (dirty) hive is not synchronized automatically.
+   Explicit synchronization (save/flush) works. */
+#define HIVE_NO_SYNCH   0x00000004
+
+#define IsPointerHive(Hive)  ((Hive)->Flags & HIVE_POINTER)
+#define IsNoFileHive(Hive)  ((Hive)->Flags & HIVE_NO_FILE)
+#define IsNoSynchHive(Hive)  ((Hive)->Flags & HIVE_NO_SYNCH)
+
+
+#define IsFreeCell(Cell)(Cell->CellSize >= 0)
+#define IsUsedCell(Cell)(Cell->CellSize < 0)
+
+
+/* KEY_OBJECT.Flags */
+
+/* When set, the key is scheduled for deletion, and all
+   attempts to access the key must not succeed */
+#define KO_MARKED_FOR_DELETE              0x00000001
+
+
+/* Type defining the Object Manager Key Object */
 typedef struct _KEY_OBJECT
 {
-  CSHORT  Type;
-  CSHORT  Size;
-  
-  ULONG  Flags;
-  USHORT NameSize;     // length of Name
-  UCHAR  *Name;
-  PREGISTRY_FILE  RegistryFile;
-  BLOCK_OFFSET BlockOffset;
-  PKEY_BLOCK  KeyBlock;
-  struct _KEY_OBJECT  *ParentKey;
-  ULONG  NumberOfSubKeys;              /* subkeys loaded in SubKeys */
-  ULONG  SizeOfSubKeys;                        /* space allocated in SubKeys */
-  struct _KEY_OBJECT  **SubKeys;               /* list of subkeys loaded */
+  /* Fields used by the Object Manager */
+  CSHORT Type;
+  CSHORT Size;
+
+  /* Key flags */
+  ULONG Flags;
+
+  /* Key name */
+  UNICODE_STRING Name;
+
+  /* Registry hive the key belongs to */
+  PREGISTRY_HIVE RegistryHive;
+
+  /* Block offset of the key cell this key belongs in */
+  BLOCK_OFFSET KeyCellOffset;
+
+  /* KEY_CELL this key belong in */
+  PKEY_CELL KeyCell;
+
+  /* Link to the parent KEY_OBJECT for this key */
+  struct _KEY_OBJECT *ParentKey;
+
+  /* Subkeys loaded in SubKeys */
+  ULONG NumberOfSubKeys;
+
+  /* Space allocated in SubKeys */
+  ULONG SizeOfSubKeys;
+
+  /* List of subkeys loaded */
+  struct _KEY_OBJECT **SubKeys;
+
+  /* List entry into the global key object list */
+  LIST_ENTRY ListEntry;
+
+  /* Time stamp for the last access by the parse routine */
+  ULONG TimeStamp;
 } KEY_OBJECT, *PKEY_OBJECT;
 
+/* Bits 31-22 (top 10 bits) of the cell index is the directory index */
+#define CmiDirectoryIndex(CellIndex)(CellIndex & 0xffc000000)
+/* Bits 21-12 (middle 10 bits) of the cell index is the table index */
+#define CmiTableIndex(Cellndex)(CellIndex & 0x003ff000)
+/* Bits 11-0 (bottom 12 bits) of the cell index is the byte offset */
+#define CmiByteOffset(Cellndex)(CellIndex & 0x00000fff)
+
+
+extern BOOLEAN CmiDoVerify;
+extern PREGISTRY_HIVE CmiVolatileHive;
+extern POBJECT_TYPE CmiKeyType;
+extern KSPIN_LOCK CmiKeyListLock;
+
+extern LIST_ENTRY CmiHiveListHead;
+
+extern ERESOURCE CmiRegistryLock;
+
+
+/* Registry Callback Function */
+typedef NTSTATUS (STDCALL *PEX_CALLBACK_FUNCTION ) (
+    IN PVOID CallbackContext,
+    IN REG_NOTIFY_CLASS Argument1,
+    IN PVOID Argument2
+    );
+
+typedef struct _REGISTRY_CALLBACK
+{
+    LIST_ENTRY ListEntry;
+    EX_RUNDOWN_REF RundownRef;
+    PEX_CALLBACK_FUNCTION Function;
+    PVOID Context;
+    LARGE_INTEGER Cookie;
+    BOOLEAN PendingDelete;
+} REGISTRY_CALLBACK, *PREGISTRY_CALLBACK;
+
+NTSTATUS
+CmiCallRegisteredCallbacks(IN REG_NOTIFY_CLASS Argument1,
+                           IN PVOID Argument2);
+
+VOID
+CmiVerifyBinHeader(PHBIN BinHeader);
+VOID
+CmiVerifyKeyCell(PKEY_CELL KeyCell);
+VOID
+CmiVerifyRootKeyCell(PKEY_CELL RootKeyCell);
+VOID
+CmiVerifyKeyObject(PKEY_OBJECT KeyObject);
+VOID
+CmiVerifyRegistryHive(PREGISTRY_HIVE RegistryHive);
+
+#ifdef DBG
+#define VERIFY_BIN_HEADER CmiVerifyBinHeader
+#define VERIFY_KEY_CELL CmiVerifyKeyCell
+#define VERIFY_ROOT_KEY_CELL CmiVerifyRootKeyCell
+#define VERIFY_VALUE_CELL CmiVerifyValueCell
+#define VERIFY_VALUE_LIST_CELL CmiVerifyValueListCell
+#define VERIFY_KEY_OBJECT CmiVerifyKeyObject
+#define VERIFY_REGISTRY_HIVE CmiVerifyRegistryHive
+#else
+#define VERIFY_BIN_HEADER(x)
+#define VERIFY_KEY_CELL(x)
+#define VERIFY_ROOT_KEY_CELL(x)
+#define VERIFY_VALUE_CELL(x)
+#define VERIFY_VALUE_LIST_CELL(x)
+#define VERIFY_KEY_OBJECT(x)
+#define VERIFY_REGISTRY_HIVE(x)
+#endif
+
+NTSTATUS STDCALL
+CmRegisterCallback(IN PEX_CALLBACK_FUNCTION Function,
+                   IN PVOID                 Context,
+                   IN OUT PLARGE_INTEGER    Cookie
+                    );
+
+NTSTATUS STDCALL
+CmUnRegisterCallback(IN LARGE_INTEGER    Cookie);
+
+NTSTATUS STDCALL
+CmiObjectParse(IN PVOID ParsedObject,
+              OUT PVOID *NextObject,
+              IN PUNICODE_STRING FullPath,
+              IN OUT PWSTR *Path,
+              IN ULONG Attribute);
+
+VOID STDCALL
+CmiObjectDelete(PVOID  DeletedObject);
+
+NTSTATUS STDCALL
+CmiObjectSecurity(PVOID ObjectBody,
+                 SECURITY_OPERATION_CODE OperationCode,
+                 SECURITY_INFORMATION SecurityInformation,
+                 PSECURITY_DESCRIPTOR SecurityDescriptor,
+                 PULONG BufferLength,
+                 PSECURITY_DESCRIPTOR *OldSecurityDescriptor,
+                 POOL_TYPE PoolType,
+                 PGENERIC_MAPPING GenericMapping);
+
+NTSTATUS STDCALL
+CmiObjectQueryName (PVOID ObjectBody,
+                   POBJECT_NAME_INFORMATION ObjectNameInfo,
+                   ULONG Length,
+                   PULONG ReturnLength);
+
+NTSTATUS
+CmiImportHiveBins(PREGISTRY_HIVE Hive,
+                 PUCHAR ChunkPtr);
+
+VOID
+CmiFreeHiveBins(PREGISTRY_HIVE Hive);
+
+NTSTATUS
+CmiCreateHiveFreeCellList(PREGISTRY_HIVE Hive);
+
+VOID
+CmiFreeHiveFreeCellList(PREGISTRY_HIVE Hive);
+
+NTSTATUS
+CmiCreateHiveBitmap(PREGISTRY_HIVE Hive);
+
+
+VOID
+CmiAddKeyToList(IN PKEY_OBJECT ParentKey,
+               IN PKEY_OBJECT NewKey);
+
+NTSTATUS
+CmiRemoveKeyFromList(IN PKEY_OBJECT NewKey);
+
+NTSTATUS
+CmiScanKeyList(IN PKEY_OBJECT Parent,
+              IN PUNICODE_STRING KeyName,
+              IN ULONG Attributes,
+              PKEY_OBJECT* ReturnedObject);
+
+NTSTATUS
+CmiCreateVolatileHive(PREGISTRY_HIVE *RegistryHive);
+
+NTSTATUS
+CmiLoadHive(POBJECT_ATTRIBUTES KeyObjectAttributes,
+           PUNICODE_STRING FileName,
+           ULONG Flags);
+
+NTSTATUS
+CmiRemoveRegistryHive(PREGISTRY_HIVE RegistryHive);
+
+NTSTATUS
+CmiFlushRegistryHive(PREGISTRY_HIVE RegistryHive);
+
+ULONG
+CmiGetNumberOfSubKeys(PKEY_OBJECT KeyObject);
+
+ULONG
+CmiGetMaxNameLength(IN PKEY_OBJECT KeyObject);
+
+ULONG
+CmiGetMaxClassLength(IN PKEY_OBJECT KeyObject);
+
+ULONG
+CmiGetMaxValueNameLength(IN PREGISTRY_HIVE RegistryHive,
+                        IN PKEY_CELL KeyCell);
+
+ULONG
+CmiGetMaxValueDataLength(IN PREGISTRY_HIVE RegistryHive,
+                        IN PKEY_CELL KeyCell);
+
+NTSTATUS
+CmiScanForSubKey(IN PREGISTRY_HIVE RegistryHive,
+                IN PKEY_CELL KeyCell,
+                OUT PKEY_CELL *SubKeyCell,
+                OUT BLOCK_OFFSET *BlockOffset,
+                IN PUNICODE_STRING KeyName,
+                IN ACCESS_MASK DesiredAccess,
+                IN ULONG Attributes);
+
+NTSTATUS
+CmiAddSubKey(IN PREGISTRY_HIVE RegistryHive,
+            IN PKEY_OBJECT ParentKey,
+            OUT PKEY_OBJECT SubKey,
+            IN PUNICODE_STRING SubKeyName,
+            IN ULONG TitleIndex,
+            IN PUNICODE_STRING Class,
+            IN ULONG CreateOptions);
+
+NTSTATUS
+CmiRemoveSubKey(IN PREGISTRY_HIVE RegistryHive,
+               IN PKEY_OBJECT Parent,
+               IN PKEY_OBJECT SubKey);
+
+NTSTATUS
+CmiScanKeyForValue(IN PREGISTRY_HIVE RegistryHive,
+                  IN PKEY_CELL KeyCell,
+                  IN PUNICODE_STRING ValueName,
+                  OUT PVALUE_CELL *ValueCell,
+                  OUT BLOCK_OFFSET *VBOffset);
+
+NTSTATUS
+CmiGetValueFromKeyByIndex(IN PREGISTRY_HIVE RegistryHive,
+                         IN PKEY_CELL KeyCell,
+                         IN ULONG Index,
+                         OUT PVALUE_CELL *ValueCell);
+
+NTSTATUS
+CmiAddValueToKey(IN PREGISTRY_HIVE RegistryHive,
+                IN PKEY_CELL KeyCell,
+                IN BLOCK_OFFSET KeyCellOffset,
+                IN PUNICODE_STRING ValueName,
+                OUT PVALUE_CELL *pValueCell,
+                OUT BLOCK_OFFSET *pValueCellOffset);
+
+NTSTATUS
+CmiDeleteValueFromKey(IN PREGISTRY_HIVE RegistryHive,
+                     IN PKEY_CELL KeyCell,
+                     IN BLOCK_OFFSET KeyCellOffset,
+                     IN PUNICODE_STRING ValueName);
+
+NTSTATUS
+CmiAllocateHashTableCell(IN PREGISTRY_HIVE RegistryHive,
+                        OUT PHASH_TABLE_CELL *HashBlock,
+                        OUT BLOCK_OFFSET *HBOffset,
+                        IN ULONG HashTableSize);
+
+PKEY_CELL
+CmiGetKeyFromHashByIndex(PREGISTRY_HIVE RegistryHive,
+                        PHASH_TABLE_CELL HashBlock,
+                        ULONG Index);
+
+NTSTATUS
+CmiAddKeyToHashTable(PREGISTRY_HIVE RegistryHive,
+                    PHASH_TABLE_CELL HashCell,
+                    BLOCK_OFFSET HashCellOffset,
+                    PKEY_CELL NewKeyCell,
+                    BLOCK_OFFSET NKBOffset);
+
+NTSTATUS
+CmiRemoveKeyFromHashTable(PREGISTRY_HIVE RegistryHive,
+                         PHASH_TABLE_CELL HashBlock,
+                         BLOCK_OFFSET NKBOffset);
+
+NTSTATUS
+CmiAllocateValueCell(IN PREGISTRY_HIVE RegistryHive,
+                    OUT PVALUE_CELL *ValueCell,
+                    OUT BLOCK_OFFSET *VBOffset,
+                    IN PUNICODE_STRING ValueName);
+
+NTSTATUS
+CmiDestroyValueCell(PREGISTRY_HIVE RegistryHive,
+                   PVALUE_CELL ValueCell,
+                   BLOCK_OFFSET VBOffset);
+
+NTSTATUS
+CmiAllocateCell(PREGISTRY_HIVE RegistryHive,
+               LONG CellSize,
+               PVOID *Cell,
+               BLOCK_OFFSET *CellOffset);
+
+NTSTATUS
+CmiDestroyCell(PREGISTRY_HIVE RegistryHive,
+              PVOID Cell,
+              BLOCK_OFFSET CellOffset);
+
+PHBIN
+CmiGetBin (PREGISTRY_HIVE RegistryHive,
+          BLOCK_OFFSET CellOffset);
+
+PVOID
+CmiGetCell (PREGISTRY_HIVE RegistryHive,
+           BLOCK_OFFSET CellOffset,
+           OUT PHBIN *Bin);
+
+VOID
+CmiMarkBlockDirty(PREGISTRY_HIVE RegistryHive,
+                 BLOCK_OFFSET BlockOffset);
+
+VOID
+CmiMarkBinDirty(PREGISTRY_HIVE RegistryHive,
+               BLOCK_OFFSET BinOffset);
+
+NTSTATUS
+CmiAddFree(PREGISTRY_HIVE RegistryHive,
+          PCELL_HEADER FreeBlock,
+          BLOCK_OFFSET FreeOffset,
+          BOOLEAN MergeFreeBlocks);
+
+NTSTATUS
+CmiConnectHive(POBJECT_ATTRIBUTES KeyObjectAttributes,
+              PREGISTRY_HIVE RegistryHive);
+
+NTSTATUS
+CmiDisconnectHive (POBJECT_ATTRIBUTES KeyObjectAttributes,
+                  PREGISTRY_HIVE *RegistryHive);
+
+NTSTATUS
+CmiInitHives(BOOLEAN SetupBoot);
+
+ULONG
+CmiGetPackedNameLength(IN PUNICODE_STRING Name,
+                      OUT PBOOLEAN Packable);
+
+BOOLEAN
+CmiComparePackedNames(IN PUNICODE_STRING Name,
+                     IN PUCHAR NameBuffer,
+                     IN USHORT NameBufferSize,
+                     IN BOOLEAN NamePacked);
+
+VOID
+CmiCopyPackedName(PWCHAR NameBuffer,
+                 PUCHAR PackedNameBuffer,
+                 ULONG PackedNameSize);
+
+BOOLEAN
+CmiCompareHash(PUNICODE_STRING KeyName,
+              PCHAR HashString);
+
+BOOLEAN
+CmiCompareHashI(PUNICODE_STRING KeyName,
+               PCHAR HashString);
+
+BOOLEAN
+CmiCompareKeyNames(PUNICODE_STRING KeyName,
+                  PKEY_CELL KeyCell);
+
+BOOLEAN
+CmiCompareKeyNamesI(PUNICODE_STRING KeyName,
+                   PKEY_CELL KeyCell);
+
+
+VOID
+CmiSyncHives(VOID);
+
+
+NTSTATUS
+CmiCreateTempHive(PREGISTRY_HIVE *RegistryHive);
+
+NTSTATUS
+CmiCopyKey (PREGISTRY_HIVE DstHive,
+           PKEY_CELL DstKeyCell,
+           PREGISTRY_HIVE SrcHive,
+           PKEY_CELL SrcKeyCell);
 
-NTSTATUS CmiObjectParse(PVOID ParsedObject,
-                    PVOID *NextObject,
-                    PUNICODE_STRING FullPath,
-                    PWSTR *Path,
-                    POBJECT_TYPE ObjectType,
-                    ULONG Attribute);
-                    
-NTSTATUS CmiObjectCreate(PVOID ObjectBody,
-                     PVOID Parent,
-                     PWSTR RemainingPath,
-                     struct _OBJECT_ATTRIBUTES* ObjectAttributes);
-void  CmiObjectDelete(PVOID  DeletedObject);
-
-VOID  CmiAddKeyToList(PKEY_OBJECT ParentKey,PKEY_OBJECT  NewKey);
-NTSTATUS  CmiRemoveKeyFromList(PKEY_OBJECT  NewKey);
-PKEY_OBJECT  CmiScanKeyList(PKEY_OBJECT Parent,
-                                   PCHAR KeyNameBuf,
-                                   ULONG Attributes);
-
-PREGISTRY_FILE  CmiCreateRegistry(PWSTR  Filename);
-
-ULONG  CmiGetMaxNameLength(PREGISTRY_FILE  RegistryFile,
-                                  PKEY_BLOCK  KeyBlock);
-ULONG  CmiGetMaxClassLength(PREGISTRY_FILE  RegistryFile,
-                                   PKEY_BLOCK  KeyBlock);
-ULONG  CmiGetMaxValueNameLength(PREGISTRY_FILE  RegistryFile,
-                                       PKEY_BLOCK  KeyBlock);
-ULONG  CmiGetMaxValueDataLength(PREGISTRY_FILE  RegistryFile,
-                                       PKEY_BLOCK  KeyBlock);
-
-NTSTATUS  CmiScanForSubKey(IN PREGISTRY_FILE  RegistryFile,
-                                  IN PKEY_BLOCK  KeyBlock,
-                                  OUT PKEY_BLOCK  *SubKeyBlock,
-                                  OUT BLOCK_OFFSET *BlockOffset,
-                                  IN PCHAR  KeyName,
-                                  IN ACCESS_MASK  DesiredAccess,
-                                  IN ULONG Attributes);
-NTSTATUS  CmiAddSubKey(IN PREGISTRY_FILE  RegistryFile,
-                              IN PKEY_OBJECT Parent,
-                              OUT PKEY_OBJECT SubKey,
-                              IN PWSTR  NewSubKeyName,
-                              IN USHORT  NewSubKeyNameSize,
-                              IN ULONG  TitleIndex,
-                              IN PUNICODE_STRING  Class,
-                              IN ULONG  CreateOptions);
-
-NTSTATUS  CmiScanKeyForValue(IN PREGISTRY_FILE  RegistryFile,
-                                    IN PKEY_BLOCK  KeyBlock,
-                                    IN PCHAR  ValueName,
-                                    OUT PVALUE_BLOCK  *ValueBlock,
-                                   OUT BLOCK_OFFSET *VBOffset);
-NTSTATUS  CmiGetValueFromKeyByIndex(IN PREGISTRY_FILE  RegistryFile,
-                                           IN PKEY_BLOCK  KeyBlock,
-                                           IN ULONG  Index,
-                                           OUT PVALUE_BLOCK  *ValueBlock);
-NTSTATUS  CmiAddValueToKey(IN PREGISTRY_FILE  RegistryFile,
-                                  IN PKEY_BLOCK  KeyBlock,
-                                  IN PCHAR  ValueNameBuf,
-                                 OUT PVALUE_BLOCK *pValueBlock,
-                                 OUT BLOCK_OFFSET *pVBOffset);
-NTSTATUS  CmiDeleteValueFromKey(IN PREGISTRY_FILE  RegistryFile,
-                                       IN PKEY_BLOCK  KeyBlock,
-                                       IN PCHAR  ValueName);
-
-NTSTATUS  CmiAllocateHashTableBlock(IN PREGISTRY_FILE  RegistryFile,
-                                           OUT PHASH_TABLE_BLOCK  *HashBlock,
-                                           OUT BLOCK_OFFSET  *HBOffset,
-                                           IN ULONG  HashTableSize);
-PKEY_BLOCK  CmiGetKeyFromHashByIndex(PREGISTRY_FILE RegistryFile,
-                                            PHASH_TABLE_BLOCK  HashBlock,
-                                            ULONG  Index);
-NTSTATUS  CmiAddKeyToHashTable(PREGISTRY_FILE  RegistryFile,
-                                      PHASH_TABLE_BLOCK  HashBlock,
-                                      PKEY_BLOCK  NewKeyBlock,
-                                      BLOCK_OFFSET  NKBOffset);
-
-NTSTATUS  CmiAllocateValueBlock(IN PREGISTRY_FILE  RegistryFile,
-                                       OUT PVALUE_BLOCK  *ValueBlock,
-                                       OUT BLOCK_OFFSET  *VBOffset,
-                                       IN PCHAR  ValueNameBuf);
-NTSTATUS  CmiDestroyValueBlock(PREGISTRY_FILE  RegistryFile,
-                     PVALUE_BLOCK  ValueBlock, BLOCK_OFFSET VBOffset);
-
-NTSTATUS  CmiAllocateBlock(PREGISTRY_FILE  RegistryFile,
-                                  PVOID  *Block,
-                                  LONG  BlockSize,
-                                 BLOCK_OFFSET * pBlockOffset);
-NTSTATUS  CmiDestroyBlock(PREGISTRY_FILE  RegistryFile,
-                PVOID  Block,BLOCK_OFFSET Offset);
-PVOID  CmiGetBlock(PREGISTRY_FILE  RegistryFile,
-                          BLOCK_OFFSET  BlockOffset,
-                         OUT PHEAP_BLOCK * ppHeap);
-VOID CmiLockBlock(PREGISTRY_FILE  RegistryFile,
-                         PVOID  Block);
-VOID  CmiReleaseBlock(PREGISTRY_FILE  RegistryFile,
-                             PVOID  Block);
 NTSTATUS
-CmiAddFree(PREGISTRY_FILE  RegistryFile,
-               PFREE_SUB_BLOCK FreeBlock,BLOCK_OFFSET FreeOffset);
+CmiSaveTempHive (PREGISTRY_HIVE Hive,
+                HANDLE FileHandle);
 
-#endif /*__INCLUDE_CM_H*/
\ No newline at end of file
+#endif /*__INCLUDE_CM_H*/