#ifndef __INCLUDE_CM_H #define __INCLUDE_CM_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_USERS_KEY_NAME L"\\Registry\\User" #define REG_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 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 REG_SYSTEM_FILE_NAME L"\\SYSTEM" #define REG_SOFTWARE_FILE_NAME L"\\SOFTWARE" #define REG_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_KEY_CELL_ID 0x6b6e #define REG_HASH_TABLE_BLOCK_ID 0x666c #define REG_VALUE_CELL_ID 0x6b76 #define REG_HIVE_ID 0x66676572 #define REGISTRY_FILE_MAGIC "REGEDIT4" #define REG_MACHINE_STD_HANDLE_NAME "HKEY_LOCAL_MACHINE" #define REG_CLASSES_STD_HANDLE_NAME "HKEY_CLASSES_ROOT" #define REG_USERS_STD_HANDLE_NAME "HKEY_USERS" #define REG_USER_STD_HANDLE_NAME "HKEY_CURRENT_USER" #define REG_CONFIG_STD_HANDLE_NAME "HKEY_CURRENT_CONFIG" #define REG_DYN_STD_HANDLE_NAME "HKEY_DYN_DATA" #define MAX_REG_STD_HANDLE_NAME 19 // BLOCK_OFFSET = offset in file after header block typedef ULONG BLOCK_OFFSET; /* header for registry hive file : */ typedef struct _HIVE_HEADER { /* Hive identifier "regf" (0x66676572) */ ULONG BlockId; /* Update counter */ ULONG UpdateCounter1; /* Update counter */ ULONG UpdateCounter2; /* When this hive file was last modified */ FILETIME DateModified; /* Registry format version ? (1?) */ ULONG Unused3; /* Registry format version ? (3?) */ ULONG Unused4; /* Registry format version ? (0?) */ ULONG Unused5; /* Registry format version ? (1?) */ ULONG Unused6; /* 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; /* Size of each hive block ? */ ULONG BlockSize; /* (1?) */ ULONG Unused7; /* Name of hive file */ WCHAR FileName[64]; /* ? */ ULONG Unused8[83]; /* Checksum of first 0x200 bytes */ ULONG Checksum; } __attribute__((packed)) HIVE_HEADER, *PHIVE_HEADER; typedef struct _HBIN { /* Bin identifier "hbin" (0x6E696268) */ ULONG BlockId; /* Block offset of this bin */ BLOCK_OFFSET BlockOffset; /* Size in bytes, multiple of the block size (4KB) */ ULONG BlockSize; /* ? */ ULONG Unused1; /* When this bin was last modified */ FILETIME DateModified; /* ? */ ULONG Unused2; } __attribute__((packed)) HBIN, *PHBIN; typedef struct _CELL_HEADER { /* <0 if used, >0 if free */ LONG CellSize; } __attribute__((packed)) CELL_HEADER, *PCELL_HEADER; typedef struct _KEY_CELL { /* Size of this cell */ LONG CellSize; /* Key cell identifier "kn" (0x6b6e) */ USHORT Id; /* ? */ USHORT Type; /* Time of last flush */ FILETIME 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 of VALUE_LIST_CELL */ BLOCK_OFFSET ValuesOffset; /* 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; /* Size of class name in bytes */ USHORT ClassSize; /* Name of key (not zero terminated) */ UCHAR Name[0]; } __attribute__((packed)) KEY_CELL, *PKEY_CELL; /* KEY_CELL.Type constants */ #define REG_LINK_KEY_CELL_TYPE 0x10 #define REG_KEY_CELL_TYPE 0x20 #define REG_ROOT_KEY_CELL_TYPE 0x2c // hash record : // HashValue=four letters of value's name typedef struct _HASH_RECORD { BLOCK_OFFSET KeyOffset; ULONG HashValue; } __attribute__((packed)) HASH_RECORD, *PHASH_RECORD; typedef struct _HASH_TABLE_CELL { LONG CellSize; USHORT Id; USHORT HashTableSize; HASH_RECORD Table[0]; } __attribute__((packed)) 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; 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 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.Flags constants */ #define REG_VALUE_NAME_PACKED 0x0001 typedef struct _DATA_CELL { LONG CellSize; UCHAR Data[0]; } __attribute__((packed)) DATA_CELL, *PDATA_CELL; typedef struct _REGISTRY_HIVE { LIST_ENTRY HiveList; ULONG Flags; UNICODE_STRING HiveFileName; UNICODE_STRING LogFileName; ULONG FileSize; PHIVE_HEADER HiveHeader; ULONG UpdateCounter; ULONG BlockListSize; PHBIN *BlockList; ULONG FreeListSize; ULONG FreeListMax; PCELL_HEADER *FreeList; BLOCK_OFFSET *FreeListOffset; ERESOURCE HiveResource; PULONG BitmapBuffer; RTL_BITMAP DirtyBitMap; BOOLEAN HiveDirty; } REGISTRY_HIVE, *PREGISTRY_HIVE; /* REGISTRY_HIVE.Flags constants */ /* When set, the hive is volatile. It will not be sync'ed to disk. */ #define HIVE_VOLATILE 0x00000001 /* When set, the hive uses pointers instead of offsets. */ #define HIVE_POINTER 0x00000002 /* When set, the hive is temporary. It will not be sync'ed to disk. */ #define HIVE_TEMPORARY 0x00000004 #define IsVolatileHive(Hive)(Hive->Flags & HIVE_VOLATILE) #define IsPointerHive(Hive)(Hive->Flags & HIVE_POINTER) #define IsTemporaryHive(Hive)(Hive->Flags & HIVE_TEMPORARY) #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 { /* Fields used by the Object Manager */ CSHORT Type; CSHORT Size; /* Key flags */ ULONG Flags; /* Length of Name */ USHORT NameSize; /* Name of key */ PCHAR Name; /* Registry hive the key belongs to */ PREGISTRY_HIVE RegistryHive; /* Block offset of the key cell this key belongs in */ BLOCK_OFFSET BlockOffset; /* 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; } 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 CmiHiveListLock; VOID CmiVerifyBinCell(PHBIN BinCell); 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_CELL CmiVerifyBinCell #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_CELL(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 CmiObjectParse(IN PVOID ParsedObject, OUT PVOID *NextObject, IN PUNICODE_STRING FullPath, IN OUT PWSTR *Path, IN ULONG Attribute); NTSTATUS STDCALL CmiObjectCreate(PVOID ObjectBody, PVOID Parent, PWSTR RemainingPath, POBJECT_ATTRIBUTES ObjectAttributes); VOID STDCALL CmiObjectDelete(PVOID DeletedObject); NTSTATUS STDCALL CmiObjectSecurity(PVOID ObjectBody, SECURITY_OPERATION_CODE OperationCode, SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR SecurityDescriptor, PULONG BufferLength); VOID CmiAddKeyToList(PKEY_OBJECT ParentKey, IN PKEY_OBJECT NewKey); NTSTATUS CmiRemoveKeyFromList(IN PKEY_OBJECT NewKey); PKEY_OBJECT CmiScanKeyList(IN PKEY_OBJECT Parent, IN PCHAR KeyNameBuf, IN ULONG Attributes); NTSTATUS CmiCreateRegistryHive(PWSTR Filename, PREGISTRY_HIVE *RegistryHive, BOOLEAN CreateNew); NTSTATUS CmiRemoveRegistryHive(PREGISTRY_HIVE RegistryHive); NTSTATUS CmiFlushRegistryHive(PREGISTRY_HIVE RegistryHive); ULONG CmiGetMaxNameLength(IN PREGISTRY_HIVE RegistryHive, IN PKEY_CELL KeyCell); ULONG CmiGetMaxClassLength(IN PREGISTRY_HIVE RegistryHive, IN PKEY_CELL KeyCell); 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 PCHAR KeyName, IN ACCESS_MASK DesiredAccess, IN ULONG Attributes); NTSTATUS CmiAddSubKey(IN PREGISTRY_HIVE RegistryHive, 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 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 PUNICODE_STRING ValueName, OUT PVALUE_CELL *pValueCell, OUT BLOCK_OFFSET *pVBOffset); NTSTATUS 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); PKEY_CELL CmiGetKeyFromHashByIndex(PREGISTRY_HIVE RegistryHive, PHASH_TABLE_CELL HashBlock, ULONG Index); NTSTATUS CmiAddKeyToHashTable(PREGISTRY_HIVE RegistryHive, PHASH_TABLE_CELL HashBlock, 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 CmiAllocateBlock(PREGISTRY_HIVE RegistryHive, PVOID *Block, LONG BlockSize, BLOCK_OFFSET * pBlockOffset); NTSTATUS CmiDestroyBlock(PREGISTRY_HIVE RegistryHive, PVOID Block, BLOCK_OFFSET Offset); PVOID CmiGetBlock(PREGISTRY_HIVE RegistryHive, BLOCK_OFFSET BlockOffset, OUT PHBIN * ppBin); 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(PREGISTRY_HIVE RegistryHive, PUNICODE_STRING KeyName); NTSTATUS CmiInitHives(BOOLEAN SetupBoot); ULONG CmiGetPackedNameLength(IN PUNICODE_STRING Name, OUT PBOOLEAN Packable); BOOLEAN CmiComparePackedNames(IN PUNICODE_STRING Name, IN PCHAR NameBuffer, IN USHORT NameBufferSize, IN BOOLEAN NamePacked); VOID CmiCopyPackedName(PWCHAR NameBuffer, PCHAR PackedNameBuffer, ULONG PackedNameSize); VOID CmiSyncHives(VOID); #endif /*__INCLUDE_CM_H*/