#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_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 SAM_REG_FILE L"\\SystemRoot\\System32\\Config\\SAM"
#define SEC_REG_FILE L"\\SystemRoot\\System32\\Config\\SECURITY"
-#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_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_BIN_ID 0x6e696268
#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_BLOCK_ID 0x666c
+#define REG_HASH_TABLE_CELL_ID 0x666c
#define REG_VALUE_CELL_ID 0x6b76
-#define REG_HIVE_ID 0x66676572
+#define REG_SECURITY_CELL_ID 0x6b73
// BLOCK_OFFSET = offset in file after header block
-typedef ULONG BLOCK_OFFSET;
+typedef ULONG BLOCK_OFFSET, *PBLOCK_OFFSET;
+
+#include <pshpack1.h>
/* header for registry hive file : */
typedef struct _HIVE_HEADER
/* When this hive file was last modified */
LARGE_INTEGER DateModified;
- /* Registry format version ? (1?) */
- ULONG Unused3;
+ /* Registry format major version (1) */
+ ULONG MajorVersion;
- /* Registry format version ? (3?) */
- ULONG Unused4;
+ /* Registry format minor version (3)
+ Version 3 added fast indexes, version 5 has large value optimizations */
+ ULONG MinorVersion;
- /* Registry format version ? (0?) */
- ULONG Unused5;
+ /* Registry file type (0 - Primary, 1 - Log) */
+ ULONG Type;
- /* Registry format version ? (1?) */
- ULONG Unused6;
+ /* 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 RootKeyCell;
+ BLOCK_OFFSET RootKeyOffset;
/* Size of each hive block ? */
ULONG BlockSize;
ULONG Unused7;
/* Name of hive file */
- WCHAR FileName[64];
+ WCHAR FileName[48];
- /* ? */
- ULONG Unused8[83];
+ ULONG Reserved[99];
/* Checksum of first 0x200 bytes */
ULONG Checksum;
-} __attribute__((packed)) HIVE_HEADER, *PHIVE_HEADER;
+} HIVE_HEADER, *PHIVE_HEADER;
-typedef struct _HBIN
+typedef struct _BIN_HEADER
{
/* Bin identifier "hbin" (0x6E696268) */
- ULONG BlockId;
+ ULONG HeaderId;
/* Block offset of this bin */
- BLOCK_OFFSET BlockOffset;
+ BLOCK_OFFSET BinOffset;
/* Size in bytes, multiple of the block size (4KB) */
- ULONG BlockSize;
+ ULONG BinSize;
- /* ? */
- ULONG Unused1;
+ ULONG Reserved[2];
/* When this bin was last modified */
LARGE_INTEGER DateModified;
- /* ? */
- ULONG Unused2;
-} __attribute__((packed)) HBIN, *PHBIN;
+ /* ? (In-memory only) */
+ ULONG MemAlloc;
+} HBIN, *PHBIN;
typedef struct _CELL_HEADER
{
/* <0 if used, >0 if free */
LONG CellSize;
-} __attribute__((packed)) CELL_HEADER, *PCELL_HEADER;
+} CELL_HEADER, *PCELL_HEADER;
typedef struct _KEY_CELL
{
ULONG NumberOfValues;
/* Block offset of VALUE_LIST_CELL */
- BLOCK_OFFSET ValuesOffset;
+ BLOCK_OFFSET ValueListOffset;
/* Block offset of security cell */
BLOCK_OFFSET SecurityKeyOffset;
/* Name of key (not zero terminated) */
UCHAR Name[0];
-} __attribute__((packed)) KEY_CELL, *PKEY_CELL;
+} 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 :
+ * HashValue:
* packed name: four letters of value's name
* otherwise: Zero!
*/
{
BLOCK_OFFSET KeyOffset;
ULONG HashValue;
-} __attribute__((packed)) HASH_RECORD, *PHASH_RECORD;
+} HASH_RECORD, *PHASH_RECORD;
typedef struct _HASH_TABLE_CELL
{
USHORT Id;
USHORT HashTableSize;
HASH_RECORD Table[0];
-} __attribute__((packed)) HASH_TABLE_CELL, *PHASH_TABLE_CELL;
+} HASH_TABLE_CELL, *PHASH_TABLE_CELL;
typedef struct _VALUE_LIST_CELL
{
LONG CellSize;
- BLOCK_OFFSET Values[0];
-} __attribute__((packed)) VALUE_LIST_CELL, *PVALUE_LIST_CELL;
+ BLOCK_OFFSET ValueOffset[0];
+} VALUE_LIST_CELL, *PVALUE_LIST_CELL;
typedef struct _VALUE_CELL
{
LONG CellSize;
USHORT Id; // "kv"
USHORT NameSize; // length of Name
- LONG DataSize; // length of datas in the cell 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 */
-} __attribute__((packed)) VALUE_CELL, *PVALUE_CELL;
+} VALUE_CELL, *PVALUE_CELL;
/* VALUE_CELL.Flags constants */
#define REG_VALUE_NAME_PACKED 0x0001
+/* 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 CellSize;
UCHAR Data[0];
-} __attribute__((packed)) DATA_CELL, *PDATA_CELL;
+} DATA_CELL, *PDATA_CELL;
+
+#include <poppack.h>
+
+
+typedef struct _BLOCK_LIST_ENTRY
+{
+ PHBIN Bin;
+ PVOID Block;
+} BLOCK_LIST_ENTRY, *PBLOCK_LIST_ENTRY;
+
typedef struct _REGISTRY_HIVE
{
PHIVE_HEADER HiveHeader;
ULONG UpdateCounter;
ULONG BlockListSize;
- PHBIN *BlockList;
+ PBLOCK_LIST_ENTRY BlockList;
ULONG FreeListSize;
ULONG FreeListMax;
PCELL_HEADER *FreeList;
BLOCK_OFFSET *FreeListOffset;
- ERESOURCE HiveResource;
+
+ PSECURITY_CELL RootSecurityCell;
PULONG BitmapBuffer;
RTL_BITMAP DirtyBitMap;
PREGISTRY_HIVE RegistryHive;
/* Block offset of the key cell this key belongs in */
- BLOCK_OFFSET BlockOffset;
+ BLOCK_OFFSET KeyCellOffset;
/* KEY_CELL this key belong in */
PKEY_CELL KeyCell;
/* 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 */
extern KSPIN_LOCK CmiKeyListLock;
extern LIST_ENTRY CmiHiveListHead;
-extern ERESOURCE CmiHiveListLock;
+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
-CmiVerifyBinCell(PHBIN BinCell);
+CmiVerifyBinHeader(PHBIN BinHeader);
VOID
CmiVerifyKeyCell(PKEY_CELL KeyCell);
VOID
CmiVerifyRegistryHive(PREGISTRY_HIVE RegistryHive);
#ifdef DBG
-#define VERIFY_BIN_CELL CmiVerifyBinCell
+#define VERIFY_BIN_HEADER CmiVerifyBinHeader
#define VERIFY_KEY_CELL CmiVerifyKeyCell
#define VERIFY_ROOT_KEY_CELL CmiVerifyRootKeyCell
#define VERIFY_VALUE_CELL CmiVerifyValueCell
#define VERIFY_KEY_OBJECT CmiVerifyKeyObject
#define VERIFY_REGISTRY_HIVE CmiVerifyRegistryHive
#else
-#define VERIFY_BIN_CELL(x)
+#define VERIFY_BIN_HEADER(x)
#define VERIFY_KEY_CELL(x)
#define VERIFY_ROOT_KEY_CELL(x)
#define VERIFY_VALUE_CELL(x)
#endif
NTSTATUS STDCALL
-CmiObjectParse(IN PVOID ParsedObject,
- OUT PVOID *NextObject,
- IN PUNICODE_STRING FullPath,
- IN OUT PWSTR *Path,
- IN ULONG Attribute);
+CmRegisterCallback(IN PEX_CALLBACK_FUNCTION Function,
+ IN PVOID Context,
+ IN OUT PLARGE_INTEGER Cookie
+ );
+
+NTSTATUS STDCALL
+CmUnRegisterCallback(IN LARGE_INTEGER Cookie);
NTSTATUS STDCALL
-CmiObjectCreate(PVOID ObjectBody,
- PVOID Parent,
- PWSTR RemainingPath,
- POBJECT_ATTRIBUTES ObjectAttributes);
+CmiObjectParse(IN PVOID ParsedObject,
+ OUT PVOID *NextObject,
+ IN PUNICODE_STRING FullPath,
+ IN OUT PWSTR *Path,
+ IN ULONG Attribute);
VOID STDCALL
CmiObjectDelete(PVOID DeletedObject);
SECURITY_OPERATION_CODE OperationCode,
SECURITY_INFORMATION SecurityInformation,
PSECURITY_DESCRIPTOR SecurityDescriptor,
- PULONG BufferLength);
+ PULONG BufferLength,
+ PSECURITY_DESCRIPTOR *OldSecurityDescriptor,
+ POOL_TYPE PoolType,
+ PGENERIC_MAPPING GenericMapping);
NTSTATUS STDCALL
CmiObjectQueryName (PVOID ObjectBody,
NTSTATUS
CmiRemoveKeyFromList(IN PKEY_OBJECT NewKey);
-PKEY_OBJECT
+NTSTATUS
CmiScanKeyList(IN PKEY_OBJECT Parent,
IN PUNICODE_STRING KeyName,
- IN ULONG Attributes);
+ IN ULONG Attributes,
+ PKEY_OBJECT* ReturnedObject);
NTSTATUS
CmiCreateVolatileHive(PREGISTRY_HIVE *RegistryHive);
NTSTATUS
CmiFlushRegistryHive(PREGISTRY_HIVE RegistryHive);
+ULONG
+CmiGetNumberOfSubKeys(PKEY_OBJECT KeyObject);
+
ULONG
CmiGetMaxNameLength(IN PKEY_OBJECT KeyObject);
CmiGetMaxClassLength(IN PKEY_OBJECT KeyObject);
ULONG
-CmiGetMaxValueNameLength(IN PREGISTRY_HIVE RegistryHive,
- IN PKEY_CELL KeyCell);
+CmiGetMaxValueNameLength(IN PREGISTRY_HIVE RegistryHive,
+ IN PKEY_CELL KeyCell);
ULONG
-CmiGetMaxValueDataLength(IN PREGISTRY_HIVE RegistryHive,
- IN PKEY_CELL KeyCell);
+CmiGetMaxValueDataLength(IN PREGISTRY_HIVE RegistryHive,
+ IN PKEY_CELL KeyCell);
NTSTATUS
-CmiScanForSubKey(IN PREGISTRY_HIVE RegistryHive,
- IN PKEY_CELL KeyCell,
- OUT PKEY_CELL *SubKeyCell,
+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 ACCESS_MASK DesiredAccess,
IN ULONG Attributes);
NTSTATUS
-CmiAddSubKey(IN PREGISTRY_HIVE RegistryHive,
- IN PKEY_OBJECT Parent,
+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);
+ IN ULONG TitleIndex,
+ IN PUNICODE_STRING Class,
+ IN ULONG CreateOptions);
NTSTATUS
CmiRemoveSubKey(IN PREGISTRY_HIVE RegistryHive,
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);
+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);
+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 PUNICODE_STRING ValueName,
- OUT PVALUE_CELL *pValueCell,
- OUT BLOCK_OFFSET *pVBOffset);
+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,
+CmiDeleteValueFromKey(IN PREGISTRY_HIVE RegistryHive,
+ IN PKEY_CELL KeyCell,
IN BLOCK_OFFSET KeyCellOffset,
IN PUNICODE_STRING ValueName);
NTSTATUS
-CmiAllocateHashTableBlock(IN PREGISTRY_HIVE RegistryHive,
- OUT PHASH_TABLE_CELL *HashBlock,
- OUT BLOCK_OFFSET *HBOffset,
- IN ULONG HashTableSize);
+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);
+ PHASH_TABLE_CELL HashBlock,
+ ULONG Index);
NTSTATUS
-CmiAddKeyToHashTable(PREGISTRY_HIVE RegistryHive,
- PHASH_TABLE_CELL HashBlock,
- PKEY_CELL NewKeyCell,
- BLOCK_OFFSET NKBOffset);
+CmiAddKeyToHashTable(PREGISTRY_HIVE RegistryHive,
+ PHASH_TABLE_CELL HashCell,
+ BLOCK_OFFSET HashCellOffset,
+ PKEY_CELL NewKeyCell,
+ BLOCK_OFFSET NKBOffset);
NTSTATUS
CmiRemoveKeyFromHashTable(PREGISTRY_HIVE RegistryHive,
BLOCK_OFFSET NKBOffset);
NTSTATUS
-CmiAllocateValueCell(IN PREGISTRY_HIVE RegistryHive,
- OUT PVALUE_CELL *ValueCell,
- OUT BLOCK_OFFSET *VBOffset,
- IN PUNICODE_STRING ValueName);
+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);
+CmiDestroyValueCell(PREGISTRY_HIVE RegistryHive,
+ PVALUE_CELL ValueCell,
+ BLOCK_OFFSET VBOffset);
NTSTATUS
-CmiAllocateBlock(PREGISTRY_HIVE RegistryHive,
- PVOID *Block,
- LONG BlockSize,
- BLOCK_OFFSET * pBlockOffset);
+CmiAllocateCell(PREGISTRY_HIVE RegistryHive,
+ LONG CellSize,
+ PVOID *Cell,
+ BLOCK_OFFSET *CellOffset);
NTSTATUS
-CmiDestroyBlock(PREGISTRY_HIVE RegistryHive,
- PVOID Block,
- BLOCK_OFFSET Offset);
+CmiDestroyCell(PREGISTRY_HIVE RegistryHive,
+ PVOID Cell,
+ BLOCK_OFFSET CellOffset);
+
+PHBIN
+CmiGetBin (PREGISTRY_HIVE RegistryHive,
+ BLOCK_OFFSET CellOffset);
PVOID
-CmiGetBlock(PREGISTRY_HIVE RegistryHive,
- BLOCK_OFFSET BlockOffset,
- OUT PHBIN * ppBin);
+CmiGetCell (PREGISTRY_HIVE RegistryHive,
+ BLOCK_OFFSET CellOffset,
+ OUT PHBIN *Bin);
VOID
CmiMarkBlockDirty(PREGISTRY_HIVE RegistryHive,
BLOCK_OFFSET BinOffset);
NTSTATUS
-CmiAddFree(PREGISTRY_HIVE RegistryHive,
+CmiAddFree(PREGISTRY_HIVE RegistryHive,
PCELL_HEADER FreeBlock,
BLOCK_OFFSET FreeOffset,
BOOLEAN MergeFreeBlocks);
BOOLEAN
CmiComparePackedNames(IN PUNICODE_STRING Name,
- IN PCHAR NameBuffer,
+ IN PUCHAR NameBuffer,
IN USHORT NameBufferSize,
IN BOOLEAN NamePacked);
VOID
CmiCopyPackedName(PWCHAR NameBuffer,
- PCHAR PackedNameBuffer,
+ PUCHAR PackedNameBuffer,
ULONG PackedNameSize);
BOOLEAN