Configuration Manangment

Burt Rosenberg
4:05 PM 5/21/99

What we know as the registry is in kernel-speak the configuration manager. The Hungarian prefix for the configuration manager is CM, the code is found under ntos/config.

The configuration manager has an involved data structure arranged around (in-core) hives and cells in the hives. The CM defines it's own NT-Object type, Object-Key, which interfaces the hive to the operating system. Outside of the kernel, the registry looks like a network of Key's. However, Key's are only pointers into the hive. A symptom of this is that a key opened twice will yield two distinct Key-Objects.

The root of the registry is represented by the \REGISTRY Key-Object. It points to the Master Hive, the original hive created by cmsysini.c. The Master Hive never exists outside of core, it has no backing store. Hives have a choice of of backing-store disciplines. For instance the System Hive is backed by the %SYSTEMROOT%\Config\System file, also known as a hive.

The whole hive deal is a very sophisticated, object oriented system, where hive operations are supported by function pointers in the hive header. The hive structure is hidden behind accessor functions pointed to by header slots. The allocate function for the hive enforces a quota so that allocated hive memory does not exceed a system-defined value. This value is manipulated through Control Panel->System->Virtual Memory.

Looking at a registry through KD.

First, find the pointer to the root directory object. This is at ObpRootDirectoryObject+0x60:

kd> dd ObpRootDirectoryObject
80156c70  00000096 00087f51 0000008c 00000000
80156c80  6943624f 00000030 80109ba4 8010a43a
80156c90  80156c30 80154120 00087ec2 00000096
80156ca0  00000000 00000000 00000000 00000000
80156cb0  806e8970 806e8850 00000000 00000000  <---
80156cc0  806e7360 80156d00 00000000 00000000
80156cd0  00000000 00000000 00000000 00000000
80156ce0  00000000 00000000 00000000 00000000

kd> !object 806e8970
Object: 806e8970  Type: (8070dd60) Directory
    ObjectHeader: 806e8958
    HandleCount: 0  PointerCount: 39
    Directory Object: 00000000  Name: \
    59 symbolic links snapped through this directory
    HashBucket[ 00 ]: 806e64b0 Directory 'ArcName'
                      806bfd30 Device 'Ntfs'
    HashBucket[ 01 ]: e1273f60 Port 'SeLsaCommandPort'
    HashBucket[ 03 ]: e1004d30 Key '\REGISTRY'
    HashBucket[ 06 ]: e12ba620 Port 'XactSrvLpcPort'
    HashBucket[ 07 ]: e1217280 Port 'DbgUiApiPort'
    HashBucket[ 09 ]: 80654400 Directory 'NLS'
    HashBucket[ 10 ]: 806e8710 SymbolicLink 'DosDevices'
    HashBucket[ 12 ]: 806828b0 Directory 'WinStations'
    HashBucket[ 13 ]: 80641f50 Event 'SC_AutoStartComplete'
                      e1220d20 Port 'SeRmCommandPort'
    HashBucket[ 14 ]: 805f5d10 Device 'Dfs'
                      e12763c0 Port 'LsaAuthenticationPort'
                      805f8490 Event 'LanmanServerAnnounceEvent'
    HashBucket[ 16 ]: e12f3360 Port 'CtxMsgSvcQualifier'
                      806dad50 Directory 'Driver'
    HashBucket[ 17 ]: e11d65a0 Port 'DbgSsApiPort'
    HashBucket[ 19 ]: 806e63d0 Directory 'Device'
    HashBucket[ 20 ]: 80661030 Directory 'Windows'
    HashBucket[ 21 ]: 8063a970 Event 'SAM_SERVICE_STARTED'
    HashBucket[ 22 ]: 80661f50 Directory 'RPC Control'
                      e1223dc0 Port 'SmApiPort'
                      806367b0 Device 'Fat'
    HashBucket[ 23 ]: 806557d0 Directory 'BaseNamedObjects'
    HashBucket[ 24 ]: 806e8770 Directory '??'
                      806dac70 Directory 'FileSystem'
    HashBucket[ 26 ]: e12ed040 Port 'SmSsWinStationApiPort'
                      80656350 Process 'WindowsSS'
                      806e8850 Directory 'ObjectTypes'
    HashBucket[ 27 ]: 806e8070 Directory 'Security'
                      805f29f0 Event 'NETLOGON_SERVICE_STARTED'
                      e1278d80 Port 'ErrorLogPort'
    HashBucket[ 29 ]: e12df680 Port 'NtLmSecuritySupportProviderPort'
    HashBucket[ 31 ]: 80663f50 SymbolicLink 'SystemRoot'
                      8064f2f0 Device 'Cdfs'
    HashBucket[ 33 ]: 806693d0 Event 'SeLsaInitEvent'
    HashBucket[ 35 ]: 80661e70 Directory 'KnownDlls'

The REGISTRY Key-Object

Then look at the \REGISTRY object. It's body has the folling structure:
typedef struct _CM_KEY_BODY {
    ULONG                   Type;
    PCM_KEY_CONTROL_BLOCK   KeyControlBlock;
    PCM_NOTIFY_BLOCK        NotifyBlock;
} CM_KEY_BODY, *PCM_KEY_BODY;

kd> !object  e1004d30
Object: e1004d30  Type: (806e5500) Key
    ObjectHeader: e1004d18
    HandleCount: 1  PointerCount: 3
    Directory Object: 00000000  Name: \REGISTRY
kd> dd  e1004d18
e1004d18  00000003 00000001 806e5500 00000010
e1004d28  00000001 00000000 6b793032 e1005ca8  <---
e1004d38  00000000 00000000 01021102 6944624f
e1004d48  00000000 806e5500 00000000 00000000
e1004d58  00000000 00000000 08021101 74536d4d
e1004d68  00000000 00000024 00024000 00000000
e1004d78  00000024 00000000 806e5608 00000000
e1004d88  00000000 00000000 00000000 00000000
chasing the CONTROL_BLOCK pointer, we confirm our location by db'ing the NameBuffer.
typedef struct _CM_KEY_CONTROL_BLOCK {
    BOOLEAN                     Delete;
    SHORT                       RefCount;
    PHHIVE                      KeyHive;        // Hive containing CM_KEY_NODE
    HCELL_INDEX                 KeyCell;        // Cell containing CM_KEY_NODE
    struct _CM_KEY_NODE         *KeyNode;       // pointer to CM_KEY_NODE

    struct _CM_KEY_CONTROL_BLOCK    *Parent;    // parent in binary tree
    struct _CM_KEY_CONTROL_BLOCK    *Left;      // left child
    struct _CM_KEY_CONTROL_BLOCK    *Right;     // right child

    UNICODE_STRING  FullName;           // p->canonical name of key
    WCHAR           NameBuffer[1];      // Variable length array, holds
                                        // body of actual name. MUST BE LAST
} CM_KEY_CONTROL_BLOCK, *PCM_KEY_CONTROL_BLOCK;

kd> dd e1005ca8
e1005ca8  00010000 e1005ce8 00000020 e1008024
e1005cb8  00000000 e1004628 e120ca48 00120012
e1005cc8  e1005ccc 0052005c 00470045 00530049
e1005cd8  00520054 00000059 0d022202 20204d43
e1005ce8  bee0bee0 801b7802 801b8c04 801b8c82
e1005cf8  801b6dca 801b8d6c 801b8cda 801b8e06
e1005d08  e1006000 00000000 00000000 00000000
e1005d18  00000000 00000001 00000000 00000001
kd> db e1005cc8
e1005cc8  cc 5c 00 e1 5c 00 52 00-45 00 47 00 49 00 53 00  .\..\.R.E.G.I.S.
e1005cd8  54 00 52 00 59 00 00 00-02 22 02 0d 43 4d 20 20  T.R.Y...."..CM
e1005ce8  e0 be e0 be 02 78 1b 80-04 8c 1b 80 82 8c 1b 80  .....x..........
e1005cf8  ca 6d 1b 80 6c 8d 1b 80-da 8c 1b 80 06 8e 1b 80  .m..l...........
e1005d08  00 60 00 e1 00 00 00 00-00 00 00 00 00 00 00 00  .`..............
kd> du  e1005ccc
e1005ccc   "\REGISTRY"
kd>
So we can investigate the parent and children pointers. Left child:
kd> dd  e1004628
e1004628  00010000 e1005a28 800001f0 e114f1f4
e1004638  e1005ca8 e1005548 00000000 00800080
e1004648  e100464c 0052005c 00470045 00530049
e1004658  00520054 005c0059 0061004d 00680063
e1004668  006e0069 005c0065 00790053 00740073
e1004678  006d0065 0043005c 006e006f 00720074
e1004688  006c006f 00650053 00300074 00310030
e1004698  0048005c 00720061 00770064 00720061
kd> du  e100464c
e100464c   "\REGISTRY\Machine\System\Control"
e100468c   "Set001\Hardware Profiles\Current"
e10046cc   " "
Right Child:
kd> dd  e120ca48
e120ca48  00010000 e122a428 00043f80 e1443f84
e120ca58  e1005ca8 e1124fa8 e12e18c8 008c008c
e120ca68  e120ca6c 0052005c 00470045 00530049
e120ca78  00520054 005c0059 0041004d 00480043
e120ca88  004e0049 005c0045 004f0053 00540046
e120ca98  00410057 00450052 004d005c 00430049
e120caa8  004f0052 004f0053 00540046 0057005c
e120cab8  004e0049 004f0044 00530057 004e0020
kd> du  e120ca6c
e120ca6c   "\REGISTRY\MACHINE\SOFTWARE\MICRO"
e120caac   "SOFT\WINDOWS NT\CURRENTVERSION\P"
e120caec   "ERFLIB"
kd>

A Hive

typedef struct _HHIVE {
    ULONG                   Signature;

    PGET_CELL_ROUTINE       GetCellRoutine;

    PALLOCATE_ROUTINE       Allocate;
    PFREE_ROUTINE           Free;

    PFILE_SET_SIZE_ROUTINE  FileSetSize;
    PFILE_WRITE_ROUTINE     FileWrite;
    PFILE_READ_ROUTINE      FileRead;
    PFILE_FLUSH_ROUTINE     FileFlush;

    struct _HBASE_BLOCK     *BaseBlock;

    RTL_BITMAP              DirtyVector;    // only for Stable bins
    ULONG                   DirtyCount;
    ULONG                   DirtyAlloc;     // allocated bytges for dirty vect
    ULONG                   Cluster;        // Usually 1 512 byte sector.
                                            // Set up force writes to be
                                            // done in larger units on
                                            // machines with larger sectors.
                                            // Is number of logical 512 sectors.

    BOOLEAN                 Flat;               // TRUE if FLAT
    BOOLEAN                 ReadOnly;           // TRUE if READONLY

    BOOLEAN                 Log;
    BOOLEAN                 Alternate;

    ULONG                   HiveFlags;

    ULONG                   LogSize;

    ULONG                   RefreshCount;       // debugging aid


    ULONG                   StorageTypeCount;   // 1 > Number of largest valid
                                                // type. (1 for Stable only,
                                                // 2 for stable & volatile)

    ULONG                   Version;            // hive version, to allow supporting multiple
                                                // formats simultaneously.

    struct _DUAL {
        ULONG               Length;
        PHMAP_DIRECTORY     Map;
        PHMAP_TABLE         SmallDir;
        ULONG               Guard;          // Always == -1

        HCELL_INDEX         FreeDisplay[HHIVE_FREE_DISPLAY_SIZE];
        ULONG               FreeSummary;
        LIST_ENTRY          FreeBins;           // list of freed HBINs (FREE_HBIN)

    }                       Storage[ HTYPE_COUNT ];

    //
    // Caller defined data goes here
    //

} HHIVE, *PHHIVE;


kd> dd e1005ce8
e1005ce8  bee0bee0 801b7802 801b8c04 801b8c82
e1005cf8  801b6dca 801b8d6c 801b8cda 801b8e06
e1005d08  e1006000 00000000 00000000 00000000
e1005d18  00000000 00000001 00000000 00000001
e1005d28  00000000 00000000 00000002 00000003
e1005d38  00001000 e1005d40 e1009000 ffffffff
e1005d48  ffffffff 000001f0 ffffffff ffffffff
e1005d58  ffffffff ffffffff ffffffff ffffffff
kd> dd
e1005d68  ffffffff ffffffff ffffffff ffffffff
e1005d78  ffffffff 000002c8 ffffffff ffffffff
e1005d88  ffffffff ffffffff ffffffff ffffffff
e1005d98  ffffffff ffffffff ffffffff 000005d8
e1005da8  00802002 e1005dac e1005dac 00000000
e1005db8  00000000 00000000 ffffffff ffffffff
e1005dc8  ffffffff ffffffff ffffffff ffffffff
e1005dd8  ffffffff ffffffff ffffffff ffffffff
kd> dd
e1005de8  ffffffff ffffffff ffffffff ffffffff
e1005df8  ffffffff ffffffff ffffffff ffffffff
e1005e08  ffffffff ffffffff ffffffff ffffffff
e1005e18  ffffffff ffffffff ffffffff 00000000
e1005e28  e1005e28 e1005e28 00000000 00000000
e1005e38  00000000 00000000 e12fbf08 00000000
e1005e48  00000003 801cb3d0 e1005b8c 00000001
e1005e58  00000000 00000000 00040001 00000000
kd> dd
e1005e68  e1005e68 e1005e68 00000000 00000000
e1005e78  00000000 00000000 0102220d 6d4e624f
e1005e88  0065004b 00000079 00000000 00000000
e1005e98  00000000 00000000 08022201 74536d4d
e1005ea8  00000000 00000020 00020000 00000000
e1005eb8  00000020 00000000 806460c8 00000000
e1005ec8  00000000 00000000 00000000 00000000
e1005ed8  00000000 00000000 00000000 00000000