When an application opens an existing registry key, the flow of control starts with the application specifying the name of the key in a registry API that invokes the object manager’s name-parsing routine. The object manager, upon encountering the configuration manager’s registry key object in the namespace, hands the path name to the configuration manager. The configuration manager performs a lookup on the key control block hash table. If the related key control block is found there, there’s no need for any further work; otherwise, the lookup provides the configuration manager with the closest key control block to the searched key, and the lookup continues by using the in-memory hive data structures to search through keys and subkeys to find the specified key. If the configuration manager finds the key cell, the configuration manager searches the key control block tree to determine whether the key is open (by the same application or another one). The search routine is optimized to always start from the closest ancestor with a key control block already opened. For example, if an application opens \Registry\Machine\Key1\Subkey2, and \Registry\Machine is already opened, the parse routine uses the key control block of \Registry\Machine as a starting point. If the key is open, the configuration manager increments the existing key control block’s reference count. If the key isn’t open, the configuration manager allocates a new key control block and inserts it into the tree. Then the configuration manager allocates a key object, points the key object at the key control block, and returns control to the object manager, which returns a handle to the application.
When an application creates a new registry key, the configuration manager first finds the key cell for the new key’s parent. The configuration manager then searches the list of free cells for the hive in which the new key will reside to determine whether cells exist that are large enough to hold the new key cell. If there aren’t any free cells large enough, the configuration manager allocates a new bin and uses it for the cell, placing any space at the end of the bin on the free cell list. The new key cell fills with pertinent information—including the key’s name—and the configuration manager adds the key cell to the subkey list of the parent key’s subkey-list cell. Finally, the system stores the cell index of the parent cell in the new subkey’s key cell.
The configuration manager uses a key control block’s reference count to determine when to delete the key control block. When all the handles that refer to a key in a key control block close, the reference count becomes 0, which denotes that the key control block is no longer necessary. If an application that calls an API to delete the key sets the delete flag, the configuration manager can delete the associated key from the key’s hive because it knows that no application is keeping the key open.
EXPERIMENT: Viewing Key Control Blocks
You can use the kernel debugger to list all the key control blocks allocated on a system with the command !reg openkeys command. Alternatively, if you want to view the key control block for a particular open key, use !reg findkcb:kd> !reg findkcb \registry\machine\software\microsoft Found KCB = e1034d40 :: \REGISTRY\MACHINE\SOFTWARE\MICROSOFT
You can then examine a reported key control block with the !reg kcb command:kd> !reg kcb e1034d40 Key : \REGISTRY\MACHINE\SOFTWARE\MICROSOFT RefCount : 1f Flags : CompressedName, Stable ExtFlags : Parent : 0xe1997368 KeyHive : 0xe1c8a768 KeyCell : 0x64e598 [cell index] TotalLevels : 4 DelayedCloseIndex: 2048 MaxNameLen : 0x3c MaxValueNameLen : 0x0 MaxValueDataLen : 0x0 LastWriteTime : 0x 1c42501:0x7eb6d470 KeyBodyListHead : 0xe1034d70 0xe1034d70 SubKeyCount : 137 ValueCache.Count : 0 KCBLock : 0xe1034d40 KeyLock : 0xe1034d40
The
Stable Storage