Návrháři operačních systémů se dříve či později ocitají před problémem, jakým způsobem a kam ukládat nastavení celého systému, případně konfiguraci jednotlivých aplikací. Tento problém řeší operační systémy založené na Unixu a rodina Windows zcela odlišným postupem, který má své výhody i nevýhody.

Operační systémy založené na Unixu uchovávají nastavení do množství různě umístěných textových souborů, které se nazývají konfigurační soubory. Výhodou takovéhoto přístupu je čitelnost uložených konfigurací lidským okem a snadná manipulace i bez použití speciálních nástrojů. Postačí i jednoduchý textový editor.

Nevýhodou textových konfiguračních souborů je horší čitelnost pro vlastní operační systém. Ten musí nejprve údaje uložené v daném souboru převést z textového do binárního formátu, což vyžaduje určitý čas. My si myslíme, že tato nevýhoda patří v dnešní době mezi ty zanedbatelné.

Windows se postupem času přiklonily k ukládání nastavení do speciálního binárního formátu. Tento formát lze chápat jako rozšíření možností souborů INI, které se používaly dříve a ještě dodnes přežívají u některých aplikací a součástí systému, o stromové uspořádání jednotlivých položek. Binární formát s sebou přináší rychlejší softwarové zpracování, protože informace není třeba konvergovat z textové podoby. Na druhou stranu prohlížení a editace jednotlivých nastavení vyžaduje použití speciálních programů.

Součást Windows, která zajišťuje ukládání, čtení a modifikaci nastavení, se označuje jako registr (Windows Registry). Vytváří iluzi uchovávání všech nastavení v jedné stromové struktuře a umožňuje v ní rychle vyhledávat. Pro práci s touto strukturou zvenčí poskytuje pro potřeby aplikací řadu funkcí rozhraní Windows API a ovladače mohou použít několik nativních funkcí exportovaných hlavním modulem jádra. Pro potřeby uživatele slouží program Editor registru (regedit.exe), který dovoluje číst a měnit jednotlivá nastavení manuálně.

Tato kapitola se věnuje popisu registru hned z několika pohledů. Nejprve se seznámíte s tím, jak tato struktura vypadá a jak se chová z pohledu uživatele a běžných aplikací. Také budou zmíněny funkce Windows API a nativní rutiny, které lze k ovládání této součásti systému využít. Ve svých dalších částech se kapitola věnuje tomu, jak registr zajišťuje kompatibilitu se starými aplikacemi v rámci emulace 32bitových programů na 64bitové platformě. Zbylé dvě části pojednávají o jeho interní struktuře a způsobech, jak mohou ovladače jednotlivé operace nad registrem monitorovat a kontrolovat.

Pohled shora

Struktura registru je analogická k adresářové struktuře souborového systému. Složky se nazývají klíče a nemohou přímo obsahovat žádná data, ale jen další klíče (podklíče) a hodnoty, které lze považovat za ekvivalent k souborům, protože slouží právě k uchovávání dat.

Jelikož registr slouží k trochu jinému účelu než souborový systém (jedná se spíše o databázi), nelze s touto analogií vystačit ve všech případech. Hloubka stromu registru je například omezena na 512 úrovní. Starší verze Windows též limitovaly maximální velikost dat hodnoty na 1 MB. Toto omezení bylo s příchodem Windows Vista zrušeno, maximální velikost hodnoty je však i tak limitována dostupnou pamětí počítače. Registr si klade za úkol uchovávat konfiguraci systému a programů, nikoliv obecná data. Proto předpokládá, že velikost hodnot se bude nejčastěji pohybovat nejvýše okolo stovek bajtů a je v tomto smyslu také optimalizován. Jednotlivé klíče a hodnoty systém rozlišuje pomocí jména, nerozlišuje v nich však malá a velká písmena. Na konkrétní klíče se lze odvolávat cestou relativní ke klíči, v jehož podstromu se nacházejí. Obdobně jako v případě souborového systému, i zde se k oddělení jednotlivých částí cesty (jmen klíčů) používá zpětné lomítko („\“). Cesty v rámci registru ale nemohou používat analogii pseudo adresářů „..“ (o úroveň výš) a „.“ (aktuální adresář). Vždy tedy popisují cestu od určitého klíče směrem do hlubin jeho podstromu.

Z pohledu uživatele a programátora běžných aplikací je registr tvořen dvěma oddělenými stromy. Pod kořenem HKEY_LOCAL_MACHINE (zkráceně HKLM) se nachází informace o aktuálním nastavení počítače, informace o jeho hardware, nainstalovaných aplikacích, o uživatelských účtech a jednotlivých součástech operačního systému. Kořen HKEY_USERS (zkráceně HKU) pod sebe sdružuje osobní nastavení jednotlivých uživatelů – každý z nich v případě přihlášení pod tímto kořenem nalezne svůj podklíč.

Uživatelské rozhraní programu Editor registrů

regedit 1

Pokud si otevřete Editor registru (regedit.exe), naskytne se vám podobný pohled jako na obrázku 1. Zjistíte, že ukazuje více kořenů než dva výše zmíněné. Krom HKLM a HKU však ostatní kořeny plní roli symbolických odkazů – zjednodušují přístup k některým často používaným podstromům obou kořenů. Jejich seznam a význam popisuje tabulka 1.

Tabulka 1. Nadbytečné kořeny registru
Kořen Popis

HKEY_CLASSES_ROOT (HKCR)

Obsahuje podklíče z HKCU\Software\Classes a HKLM\Software\Classes.

HKEY_CURRENT_USER (HKCU)

Odkazuje na klíč HKU\<ID>, kde ID je identifikátor právě přihlášeného uživatele, pod jehož účtem daný proces běží.

HKEY_CURRENT_CONFIG

Alias pro HKLM\SYSTEM\CurrentControlSet\Hardware Profiles\Current.

Každá hodnota může obsahovat data určitého typu. Aplikace tak dokáží rozpoznat, zda její obsah mají interpretovat například jako 32bitové celé číslo, nebo se k nim chovat jako k řetězci. Seznam všech možných typů včetně jejich krátké charakteristiky obsahuje tabulka 2.

Tabulka 2. Možné typy hodnot a jejich význam
Název typu Konstanta Popis

REG_NONE

0

Neznámý typ dat. Registr s takovými hodnotami zachází jako by obsahovaly obecná binární data.

REG_SZ

1

Řetězec. Nemusí být ukončen nulovým znakem.

REG_EXPAND_SZ

2

Řetězec, který v sobě obsahuje proměnné prostředí. Před jeho použitím je třeba tyto proměnné expandovat – dosadit na místa jejich výskytu jejich hodnotu.

REG_BINARY

3

Obecná binární data.

REG_DWORD

4

32bitové celé číslo.

REG_DWORD_LITTLE_ENDIAN

4

32bitové celé číslo ve formátu little endian.

REG_DWORD_BIG_ENDIAN

5

32bitové celé číslo ve formátu big endian.

REG_LINK

6

Obsahuje cíl symbolického odkazu.

REG_MULTI_SZ

7

Víceřetězcová hodnota. Data jsou tvořena polem řetězců, jehož položky jsou odděleny nulovým znakem. Celé pole je zakončeno dvojicí nulových znaků.

REG_RESOURCE_LIST

8

Pole binárních dat. Formát takových hodnot není dokumentovaný.

REG_FULL_RESOURCE_DESCRIPTOR

9

Pole binárních dat. Formát takových hodnot není dokumentovaný.

REG_RESOURCE_REQUIREMENTS_LIST

10

Pole binárních dat. Formát takových hodnot není dokumentovaný.

REG_QWORD

11

64bitové celé číslo ve formátu little endian.

Little endian a big endian

Termíny big endian, little endian, případně middle endian označují způsob ukládání vícebajtových dat v operační paměti. V případě celých čísel se jedná o pořadí jednotlivých bajtů, které obsahují hodnotu daného čísla. V případě little endian jsou jednotlivé bajty dat ukládány v pořadí od nejméně významného po ten nejvýznamnější. Například číslo 0x80543A02 bude ve formátu little endian do operační paměti zaznamenáno v sekvenci bajtů 0x02 0x3A 0x54 0x80. Číslo je tedy v paměti uloženo „obráceně“. Tento formát ukládání dat používají i procesory Intel.

Naproti tomu, formát big endian ukládá data od nejvýznamnějšího bajtu po ten nejméně významný. V tomto případě by číslo 0x80543A02 reprezentovala sekvence bajtů 0x80 0x54 0x3A 0x02. Pořadí bajtů je podobné pořadí cifer psaných na papír. Obdobným pravidlům také podléhá pořadí ukládání jednotlivých bitů v jednom bajtu. V případě little endian každý bajt začíná nejméně významným bitem (obvykle označovaným jako bit 0) a končí tím nejvýznamnějším (například bit 31, nebo bit 63; záleží na velikosti datového typu). Kromě výše zmíněných forem ukládání bajtů dat v pořadí od toho nejvýznamnějšího k nejméně významnému existují i formy, které jednotlivé bajty ukládají ještě v jiném pořadí. Nazývají se middle endian nebo mixed endian.

Operace nad registrem

Windows API obsahuje řadu funkcí, jejichž jména začínají prefixem Reg a které aplikacím umožňují číst a manipulovat jak s jednotlivými klíči a hodnotami, tak i s celými podstromy. Mnoho z nich funguje tak, že pro úspěšné provedení operace požadují cestu k cílovému klíči. Tato cesta je relativní k jinému klíči, ke kterému již aplikace musí vlastnit handle.

Vytváření klíčů a získávání handle

Pro vytvoření nového klíče slouží funkce RegCreateKeyEx, jejíž definici vidíte na výpisu 1 Na rozdíl od funkcí pro tvorbu jiných druhů objektů jádra tato rutina nevrací handle v návratové hodnotě, ale přes výstupní parametr phkResult. V případě funkcí určených pro práci s registry slouží návratová hodnota k předání chybového kódu.

Potřebuje-li aplikace vytvořit v určitém místě stromu registru nový klíč, musí mít přístup k některému z klíčů, které se nacházejí na cestě od kořene stromu k novému objektu. Handle předané v prvním parametru (hKey) spolu s relativní cestou předanou v parametru lpSubKey jednoznačně určuje polohu klíče ve stromu registru. Pokud takový objekt již existuje, funkce se místo vytvoření k němu pokusí získat zadaný přístup. Obdobným způsobem funguje většina rutin sloužících pro vytvoření jiných druhů objektů jádra.

Hodnotou parametru dwOptions může volající nastavit některé specifické vlastnosti nového klíče. Hodnota REG_CONTROL_CREATE_LINK vytvoří klíč plnící roli symbolického odkazu v rámci registru. Data hodnoty s názvem SymbolicLinkValue jsou následně interpretována jako cíl tohoto odkazu. Cílová cesta musí být absolutní.

Další zajímavou možnost skýtá příznak REG_CONTROL_VOLATILE, který jádru systému říká, že nový klíč bude žít pouze v paměti a nebude ukládán do souborů registru na pevný disk, a tedy ani nepřežije restartování systému. Takové klíče se také označují jako volatilní.

Třetí možnou hodnotou parametru dwOptions je REG_CONTROL_BACKUP_RESTORE, kterou lze použít pouze v případě, že první dva parametry volání RegCreateKeyEx odkazují již na existující klíč. Nastavením této hodnoty aplikace jádru sděluje, že bude daný klíč zálohovat či obnovovat. Pokud má k danému úkonu práva, jádro ke klíči vytvoří handle s dostatečným oprávněním, ačkoliv popisovač zabezpečení klíče uživateli, pod kterým aplikace běží, taková oprávnění získat nedovoluje.

Pokud aplikace vytváří nový klíč nebo nechce obsah již existujícího klíče obnovit či zálohovat, určuje hodnotou parametru samDesired, která oprávnění chce přiřadit handle, jež bude v případě úspěchu nový (či již existující) klíč reprezentovat. Oprávnění dovolují klíčem provádět další operace, mezi které patří například vytváření podklíčů nebo čtení a modifikace hodnot. Seznam všech možných oprávnění a jejich význam ukazuje tabulka 3.

Tabulka 3. Přístupová práva, kterými může handle klíče registru disponovat
Oprávnění Hodnota Význam

KEY_ALL_ACCESS

0xF003F

Dovoluje provádět libovolnou operaci.

KEY_CREATE_LINK

0x20

Určeno pro interní použití systému.

KEY_CREATE_SUB_KEY

0x4

Nutné pro vytváření podklíčů.

KEY_ENUMERATE_SUB_KEYS

0x8

Dovoluje zjistit seznam podklíčů

KEY_EXECUTE

0x20019

Ekvivalentní oprávnění KEY_READ.

KEY_NOTIFY

0x10

Dovoluje aplikaci přijímat notifikace o změně obsahu klíče nebo jeho podstromu.

KEY_QUERY_VALUE

0x1

Nutné pro získání seznamu hodnot, jejich typu a obsahu.

KEY_READ

0x20019

Ekvivalentní kombinaci oprávnění KEY_QUERY_VALUE, KEY_ENUMERATE_SUB_KEYS a KEY_NOTIFY.

KEY_SET_VALUE

0x2

Dovoluje vytvářet, měnit či mazat hodnoty.

KEY_WRITE

0x20006

Ekvivalentní kombinaci oprávnění KEY_SET_VALUE a KEY_CREATE_SUB_KEY.

Poslední argument (lpdwDisposition), též výstupní, po dokončení volání funkce určuje, jaká operace byla ve skutečnosti provedena. Může nabývat hodnot REG_CREATED_NEW_KEY (byl vytvořen nový klíč), nebo REG_OPENED_EXISTING_KEY (podařilo se získat handle k již existujícímu klíči).

Zbylé parametry umožňují nastavit název třídy nového klíče a jeho popisovač zabezpečení.

Výpis 1: Rutina RegCreateEx
LONG WINAPI RegCreateKeyEx(
    __in        HKEY hKey,
    __in        LPCTSTR lpSubKey,
    __reserved  DWORD Reserved,
    __in_opt    LPTSTR lpClass,
    __in        DWORD dwOptions,
    __in        REGSAM samDesired,
    __in_opt    LPSECURITY_ATTRIBUTES lpSecurityAttributes,
    __out       PHKEY phkResult,
    __out_opt   LPDWORD lpdwDisposition);

Pokud program ví, že nějaký klíč existuje a potřebuje k němu získat přístup, může použít rutinu RegOpenKeyEx, jejíž definici ukazuje výpis 2. Význam jejích argumentů odpovídá stejně pojmenovaným parametrům funkce RegCreateKeyEx, jen parametr ulOptions může nabývat pouze hodnoty REG_CONTROL_BACKUP_RESTORE, která má význam jako v případě argumentu dwOptions rutiny z 1.

Výpis 2: Funkce RegOpenKeyEx
LONG WINAPI RegOpenKeyEx(
    __in        HKEY hKey,
    __in_opt    LPCTSTR lpSubKey,
    __reserved  DWORD ulOptions,
    __in        REGSAM samDesired,
    __out       PHKEY phkResult);

Pokud již aplikace nepotřebuje pracovat s klíčem, jehož handle získala pomocí užití jedné z výše popsaných funkcí, měla by jej zrušit voláním rutiny RegCloseKey. Její definici ukazuje výpis 3. Rutina jako svůj jediný klíče akceptuje hodnotu handle, které chce aplikace zrušit.

Výpis 3: Rutina RegCloseKey
LONG WINAPI RegCloseKey( __in HKEY hKey );
Možná vás po přečtení jména rutiny pro zrušení handle ke klíči registru napadá otázka, proč tento krok nelze realizovat prostřednictvím funkce CloseHandle, které slouží ke stejnému účelu v případě jiných druhů objektů exekutivy. Důvod této nekonzistence je pravděpodobně nutné hledat v zachovávání zpětné kompatibility a také ve faktu, že význam rutin RegXXX je přetížený – slouží nejen k práci s registrem, ale také ke sběru různých statistik o aktuálním výkonu systému.

Mazání klíčů

Rozhraní Windows API exportuje dvě rutiny určené pro mazání klíče: RegDeleteKey a RegDeleteKeyEx. Jejich definice najdete na výpisu 10.4. Klíč, který má být smazán, musí aplikace jednoznačně určit pomocí handle a relativní cesty předaných v argumentech hKey a lpSubKey. Cílový klíč nesmí obsahovat žádné další podklíče (potomky). Počet a typ jeho hodnot nemá na úspěch operace žádný vliv.

Použití rutiny RegDeleteKeyEx má význam na 64bitové platformě, která pro 32bitové aplikace emuluje prostředí 32bitového operačního systému přesměrováním operací nad některými klíči do úplně jiné oblasti registru. Parametrem samDssired může aplikace ovlivnit, na jaký klíč má být operace mazání aplikována. Volající může specifikovat jednu z následujících hodnot:

  • KEY_WOW64_32KEY – pokud je na cílový klíč v rámci izolace prostředí 32bitových a 64bitových aplikací aplikováno přesměrování, systém se pokusí smazat až cílový objekt tohoto přesměrování.

  • KEY_WOW64_64KEY – systém se pokusí smazat klíč, aniž by aplikoval přesměrování.

Více informací o mechanismech zajišťujících zpětnou kompatibilitu a emulaci prostředí 32bitových aplikací na 64bitové platformě se dočtete v druhé části kapitoly.

Výpis 3: RegDeleteKey a RegDeleteKeyEx
LONG WINAPI RegDeleteKey(
    __in        HKEY hKey,
    __in        LPCTSTR lpSubKey);

LONG WINAPI RegDeleteKeyEx(
    __in        HKEY hKey,
    __in        LPCTSTR lpSubKey,
    __in        REGSAM samDesired,
    __reserved  DWORD Reserved);

Základní práce s hodnotami

Jak již bylo řečeno dříve, každý klíč může obsahovat množství hodnot, do kterých lze ukládat data. Jednotlivé hodnoty se rozlišují jménem. Každý klíč dále může obsahovat i bezejmennou hodnotu, která se nazývá výchozí hodnota (default value).

Na rozdíl od klíčů, jejich hodnoty nepatří mezi objekty exekutivy. Nemají tedy v jádře žádnou speciální oporu. Nelze k nim přímo přistupovat přes handle a nedisponují ani vlastním popisovačem zabezpečení. Jedná se pouze o atributy daného klíče.

Za účelem vytvoření nové, nebo přepsání dat a typu již existující hodnoty, slouží funkce RegSetValueEx, jejíž definici naleznete na výpisu 5. Názvy jednotlivých parametrů jsou většinou samovysvětlující; volající určí pomocí prvního parametru cílový klíč, ve druhém specifikuje název hodnoty, ve čtvrtém její typ a poslední dva vyplní adresou a velikostí bufferu s daty, která má systém pod danou hodnotu uložit.

Výpis 5: Rutina RegSetValueEx
LONG WINAPI RegSetValueEx(
    __in        HKEY hKey,
    __in_opt    LPCTSTR lpValueName,
    __reserved  DWORD Reserved,
    __in        DWORD dwType,
    __in_opt    const BYTE *lpData,
    __in        DWORD cbData);

Pro zjištění informací o určité hodnotě může aplikace zavolat funkci RegQueryValueEx (výpis 6), která ve svých parametrech vrátí její typ a obsah. Obsahuje-li daná hodnota řetězcová data, funkce je nemusí řádně ukončit nulovými znaky. V takovém případě musí volající spoléhat buď na vrácenou délku dat, nebo použít funkci RegGetValue (viz též výpis 6), která nulové znaky v případě potřeby automaticky doplní. Navíc dovoluje přijímat pouze hodnoty určitých typů. Vyskytuje se však až od Windows Server 2003.

Výpis 6: Funkce RegQueryValueEx a GerGetValue
LONG WINAPI RegQueryValueEx(
    __in        HKEY hKey,
    __in_opt    LPCTSTR lpValueName,
    __reserved  LPDWORD lpReserved,
    __out_opt   LPDWORD lpType,
    __out_opt   LPBYTE lpData,
    __inout_opt LPDWORD lpcbData);

LONG WINAPI RegGetValue(
    __in        HKEY hkey,
    __in_opt    LPCTSTR lpSubKey,
    __in_opt    LPCTSTR lpValue,
    __in_opt    DWORD dwFlags,
    __out_opt   LPDWORD pdwType,
    __out_opt   PVOID pvData,
    __inout_opt LPDWORD pcbData);

Za účelem smazání určité hodnoty poskytuje Windows API funkci RegDeleteValue, kterou vidíte na výpisu 7. Volající pouze musí určit klíč a jméno cílové hodnoty.

Výpis 7: Funkce RegDeleteValue
LONG WINAPI RegDeleteValue(
    __in        HKEY hKey,
    __in_opt    LPCTSTR lpValueName);

Získávání seznamu podklíčů a hodnot

Dosud představené funkce rozhraní Windows API buď sloužily primárně k vytváření nových klíčů a hodnot, nebo vyžadovaly zadat jménem klíč (či hodnotu), který již existoval. Aplikace však nemusí ve všech případech znát jméno objektu registru, se kterým potřebuje pracovat. Jako odpověď tomuto požadavku poskytuje Windows API dvě rutiny, jež umožňují zjistit seznam potomků klíče a seznam jeho hodnot. Nazývají se RegEnumKeyEx a RegEnumValue a jejich definice najdete na výpisu 8.

Obě funkce pracují stejným způsobem. Na základně handle klíče a hodnoty dwIndex vrátí informace o jednom podklíči (v případě RegEnumValue o hodnotě) daného klíče. Hodnota argumentu dwIndex přitom označuje pořadí dané položky v seznamu. Pokud tedy program chce zjistit informace o všech podklíčích (resp. hodnotách) určitého klíče, začne voláním jedné z výše uvedených funkcí s hodnotou dwIndex nastavenou na 0. V případě úspěchu zavolá rutinu s hodnotou dwIndex nastavenou na 1, při dalším volání ji zvýší na 2. Volání se zvyšující se hodnotou druhého parametru budou pokračovat, dokud funkce nevrátí chybovou hodnotu ERROR_NO_MORE_ENTRIES, která znamená, že klíč již v aktuálním okamžiku žádné další podklíče (hodnoty) neobsahuje.

O jednotlivých podklíčích se aplikace dozví jejich jméno, název třídy a čas poslední změny. Při zjišťování seznamu hodnot se o každé dozví jméno, typ a obsah.

Výpis 8: RegEnumKeyEx a RegEnumValue
LONG WINAPI RegEnumKeyEx(
    __in        HKEY hKey,
    __in        DWORD dwIndex,
    __out       LPTSTR lpName,
    __inout     LPDWORD lpcName,
    __reserved  LPDWORD lpReserved,
    __inout     LPTSTR lpClass,
    __inout_opt LPDWORD lpcClass,
    __out_opt   PFILETIME lpftLastWriteTime);

LONG WINAPI RegEnumValue(
    __in        HKEY hKey,
    __in        DWORD dwIndex,
    __out       LPTSTR lpValueName,
    __inout     LPDWORD lpcchValueName,
    __reserved  LPDWORD lpReserved,
    __out_opt   LPDWORD lpType,
    __out_opt   LPBYTE lpData,
    __inout_opt LPDWORD lpcbData);

Problém při zjišťování seznamu podklíčů a hodnot může nastat na platformě x64 kvůli již výše zmíněnému přesměrování operací nad některými klíči do jiné oblasti registru. 32bitová aplikace tak může u některých klíčů „vidět“ odlišný seznam podklíčů než aplikace 64bitová. Pokud program chce získat úplný seznam podklíčů či hodnot určitého klíče, měl by k němu získat handle například pomocí rutiny RegOpenKeyEx a k parametru samDesired přidat postupně příznak REG_WOW64_32KEY a REG_WOW64_64KEY. Tím získá seznam položek jak z pohledu 32bitové, tak z pohledu 64bitové aplikace.

Ukládání a načítání

Stromová struktura registru je uložena v několika souborech na pevném disku. Operační systém při svém startu tyto soubory vyhledá a vytvoří z nich stromovou strukturu. Windows API dovoluje převádět jednotlivé podstromy registru do souboru a opačným směrem. K tomuto účelu slouží funkce RegSaveKey, RegLoadKey, RegUnLoadKey, RegReplaceKey a RegRestoreKey.

Rutina RegSaveKey (viz výpis 9) umožňuje uložit část stromu registru do souboru. První parametr udává handle klíče, který bude sloužit jako kořen ukládaného podstromu. Druhým parametrem volající určí název souboru a třetím jeho popisovač zabezpečení.

Formát vzniklého souboru umožňuje ovlivnit rozšíření předchozí rutiny v podobě funkce RegSaveKeyEx. Ta přidává parametr Flags, který svoji hodnotou ovlivňuje formát vzniklého souboru následujícím způsobem:

  • Specifikování hodnoty REG_STANDARD_FORMAT vede k vytvoření souboru ve formátu, se kterým umí pracovat Windows 2000 a vyšší verze operačního systému.

  • Použití hodnoty REG_LATEST_FORMAT způsobí, že systém podstrom uloží ve formátu, který umí číst Windows XP a vyšší verze operačního systému.

  • Příznak REG_NO_COMPRESSION instruuje systém, aby uložil obsah daného podstromu v nekomprimované formě. Tato hodnota může být použita s libovolnou s předchozích pomocí logického součtu. Handle však musí patřit některému z podklíčů kořenů HKLM či HKU.

Výpis 9: Rutiny RegSaveKey a RegSaveKeyEx
---
LONG WINAPI RegSaveKey(
    __in        HKEY hKey,
    __in        LPCTSTR lpFile,
    __in_opt    LPSECURITY_ATTRIBUTES lpSecurityAttributes);

LONG WINAPI RegSaveKeyEx( in HKEY hKey, in LPCTSTR lpFile, in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes, in DWORD Flags); ---

Načíst podstrom ze souboru zpět do registru je možné hned třemi způsoby. Liší se poškozením existujícího stromu, které mohou způsobit.

Nejméně invazivní metoda spočívá v použití rutiny RegLoadKey (výpis 10), která umožní připojit kořen nového podstromu jako nový podklíč kořene HKLM nebo HKU. Ke změnám ostatních částí stromu tedy nedochází. První dva parametry slouží k určení jednoho ze dvou kořenů a názvu podklíče, který bude tvořit kořen nově připojeného podstromu. Třetí argument určuje název souboru, jehož obsah bude interpretován jako strom klíčů s jejich hodnotami.

Protipól k RegLoadKey tvoří funkce RegUnLoadKey, která odstraní ze stromu registru podstrom, jehož kořenem je podklíč některého ze dvou výše zmíněných kořenů HKLM a HKU. Rutinu lze s úspěchem použít pouze na podklíče připojené do registru pomocí jejího dvojčete.

Výpis 10: Definice funkcí RegLoadKey a RegUnLoadKey
LONG WINAPI RegLoadKey(
            __in        HKEY hKey,
            __in_opt    LPCTSTR lpSubKey,
            __in        LPCTSTR lpFile);

LONG WINAPI RegUnLoadKey(
            __in        HKEY hKey,
            __in_opt    LPCTSTR lpSubKey);

Druhá možnost, jak změnit strukturu stromu registru, spočívá v použití funkce RegReplaceKey, kterou vidíte na výpisu 11. Tato rutina nejprve zjistí, v jakém souboru je uložen podstrom, do kterého patří klíč zadaný pomocí prvních dvou parametrů a tento soubor přesune do umístění zadaného čtvrtým parametrem. Následně přejmenuje soubor zadaný ve třetím parametru na jméno původního souboru, čímž je nahrazení podstromu dokončeno. Změna se projeví až po restartování systému.

Výpis 11: Definice funkce RegReplaceKey
LONG WINAPI RegReplaceKey(
            __in        HKEY hKey,
            __in_opt    LPCTSTR lpSubKey,
            __in        LPCTSTR lpNewFile,
            __in        LPCTSTR lpOldFile);

Poslední možnost načtení podstromu ze souboru do registru spočívá v použití funkce RegRestoreKey (viz výpis 12). Tato rutina přepíše podstrom podklíče udaného parametrem hKey a jeho seznam hodnot podstromem načteným ze souboru s názvem uloženým v parametru lpFile.

Třetí parametr blíže specifikuje chování celého procesu. Nastavení příznaku REG_FORCE_RESTORE donutí systém k přepsání podstromu klíče i v případě, že do něho odkazují handle vlastněná některými procesy. Tím budou tato handle zneplatněna.

Aplikace též může specifikovat příznak REG_WHOLE_HIVE_VOLATILE čímž zajistí, že celý načtený podstrom se bude nacházet pouze v paměti a jeho změny nebudou ukládány na pevný disk. Při specifikování tohoto příznaku musí handle klíče odpovídat jednomu z kořenů HKLM nebo HKU.

Výpis 12: Definice rutiny RegRestoreKey
LONG WINAPI RegRestoreKey(
            __in        HKEY    hKey,
            __in        LPCTSTR lpFile,
            __in        DWORD   dwFlags);

Na rozdíl od RegLoadKey rutina RegRestoreKey nepřipojuje zadaný soubor do registru přímo, ale data z něho pouze překopíruje. Důsledkem tohoto chování je, že zadaný soubor s podstromem není po dokončení volání funkce zamčen proti přístupu ze strany aplikací.

Předdefinovaná handle

Jistě jste si všimli, že rutiny pro práci s registrem v některých případech vyžadují handle k cílovému klíči a že získání tohoto handle je podmíněno získáním handle ke klíči, který se nachází na cestě ve stromu registru blíže ke kořeni. Vzniká tak uzavřený kruh, kdy pro získání přístupu k libovolnému klíči je zapotřebí již přístup k nějakému jinému klíči mít.

Tento problém řeší tzv. předdefinovaná handle (predefined keys, predefined key handles). Jak ukazuje tabulka 1 a obrázek 1, Windows API se snaží předstírat, že registr se skládá z několika oddělených stromů klíčů a hodnot. Již jste se dozvěděli, že kromě HKLM a HKU se jedná pouze o jakousi formu symbolických odkazů, a tedy že registr má stromy pouze dva. Jak se dozvíte v části věnované jeho interní struktuře, ani toto tvrzení není pravdivé; v paměti se nachází strom registru pouze jeden.

Důležité pro řešení problému získání handle k nějakému klíči je, že každá aplikace má k těmto kořenům implicitní přístup, protože ke každému z nich implicitně vlastní jedno pseudo handle, které může použít v rámci mnoha funkcí pro práci s registrem. Díky tomu existují klíče, ke kterým není třeba získávat přístup, a je tak možné získat handle i k objektům z jejich podstromu. Protože tato pseudo handle existují implicitně, nazývají se předdefinovaná handle.

Zajímavou funkci v oblasti předdefinovaných handle představuje rutina RegOverridePredefKey, jejíž hlavičku ukazuje výpis 13. Umožňuje přesměrovat některé z předdefinovaných handle na jiný klíč, a tím přesměrovat i všechny operace, ve kterých bylo použito. Protože toto přesměrování probíhá v uživatelském režimu (v režimu jádra se žádná předdefinovaná handle nevyskytují), nehodí se k ochraně určitých částí registru před poškozením škodlivými programy. Adekvátní využití může ale například spočívat v přesměrování registrových operací prováděných instalačním programem, čímž lze snadno zjistit, do kterých míst zapisuje.

Rutina jako první parametr akceptuje předdefinované handle, jehož význam chce volající změnit. Druhý parametr určuje klíč, na který má být přesměrováno. Pokud jeho hodnotu volající nastaví na NULL, příslušné předdefinované handle opět nabude svého původního významu.

Výpis 13: Hlavička funkce RegOverridePredefKey
LONG WINAPI RegOverrodePredefKey(
        __in        HKEY    hKey,
        __in_opt    HKEY    hNewHKey);

Další funkce

Manipulovat s obsahem registru lze pomocí celé řady funkcí, které v předchozím výpisu nebyly zmíněny a ani blíže popisovány nebudou. Jejich přehled najdete v tabulce.

Tabulka 4. Další rutiny Windows API pro práci s registrem
Název funkce Popis

GetSystemRegistryQuota

Zjistí aktuální velikost registru a maximální velikost, do které mu operační systém dovolí narůst.

RegConnectRegistry

Umožňuje připojení do registru jiného počítače.

RegCopyTree

Překopíruje klíče a hodnoty zadaného podstromu.

RegCreateKeyTransacted

Vytvoří nový klíč v rámci transakce.

RegDeleteKeyTransacted

Odstraní klíč v rámci transakce.

RegDeleteTree

Odstraní podstrom se zadaným kořenem.

RegDisableReflectionKey

Vypne pro daný klíč registru vlastnost reflexe (viz druhá část článku).

RegEnableReflectionKey

Zapne vlastnost reflexe pro daný klíč (viz druhá část kapitoly).

RegFlushKey

Zapíše všechny atributy klíče na pevný disk, nejedná-li se o objekt žijící pouze v paměti.

RegGetKeySecurity

Vrátí popisovač zabezpečení zadaného klíče.

RegOpenKeyTransacted

Získá handle ke klíči v rámci transakce.

RegQueryInfoKey

Zjistí různé atributy klíče, jako je počet hodnot, počet podklíčů, velikost dat největší hodnoty či délka jména podklíče s nejdelším názvem.

RegQueryMultipleValues

Vrátí typ a obsah několika hodnot klíče zadaných jejich názvy.

RegQueryReflectionKey

Zjistí, zda má klíč nastavenu vlastnost reflexe. O reflexi a dalších mechanismech se dočtete dále v této kapitole.

RegSetKeySecurity

Nastaví popisovač zabezpečení klíče.

Práce s registry v režimu jádra

Ovladače pro práci s registrem nemohou využít rozhraní Windows API, protože to je dostupné pouze v rámci knihoven určených výhradně pro použití v uživatelském režimu. Proto se musí spolehnout na několik nativních funkcí, které odpovídají jednotlivým systémovým voláním.

Ovladače nemohou využít předdefinovaných handle. Musí pracovat s takovou strukturou registru, jaká doopravdy je. Taková struktura je tvořena jediným stromem, jehož kořen se v jmenném prostoru správce objektů nazývá \REGISTRY a obsahuje jeden podklíč odpovídající pseudo kořeni HKLM s názvem Machine a jeden podklíč pro pseudo kořen HKU s názvem Users. Drobná výhoda může spočívat ve faktu, že ovladače zacházejí s klíči registru stejným způsobem jako s ostatními objekty exekutivy.

Seznam nativních funkcí exportovaných hlavním modulem jádra pro využití v kódu ovladačů najdete v tabulce 5, které krom jejich názvů obsahuje i název rutiny Windows API, které jim odpovídají.

Tabulka 5. Nativní funkce pro práci s registrem určené pro použitív ovladačích jádra
Nativní funkce Rutina Windows API provádějécé obdobnou práci

ZwCreateKey

RegCreateKeyEx

ZwCreateKeyTransacted

RegCreateKeyTransacted

ZwDeleteKey

RegDeleteKey

ZwDeleteValueKey

RegDeleteValue

ZwEnumerateKey

RegEnumKeyEx

ZwEnumerateValueKey

RegEnumValue

ZwOpenKey

RegOpenKey

ZwOpenKeyEx

RegOpenKeyEx

ZwOpenKeyTransacted

 — 

ZwOpenKeyTransactedEx

RegOpenKeyTransacted

ZwQueryKey

RegQueryInfoKey

ZwQueryValueKey

RegQueryValueEx

ZwSetValueKey

RegSetValueEx

Podpora starších 32bitových aplikacá na 64bitových platformách

Příchod Windows Vista s sebou přinesl několik velkých změn, které mohly způsobit, že starší aplikace na nové verzi operačního systému nefungovaly správně. Pro naše povídání o registrech má význam zavedení kontroly uživatelských účtů (User Account Control – UAC) a větší rozšíření 64bitové verze operačního systému.

Zavedení UAC si kladlo za cíl zvýšit bezpečnost zejména ve sféře domácích uživatelů, kteří v drtivé většině na svém počítači pracují celou dobu pod účtem s administrátorskými právy. UAC tento problém řeší tak, že většinu programů spouští s omezeným oprávněním, ačkoliv uživatel pracuje stále jako administrátor. Plných administrátorských práv se dostane pouze těm aplikacím, kterým to uživatel explicitně povolí při jejich spouštění.

Mnohé aplikace však byly napsané způsobem, že s během pod administrátorskými právy implicitně počítaly a prováděly změny, které s omezenými právy dělat nelze. Například zapisovaly do podstromu registru s kořenem HKEY_LOCAL_MACHINE.

Aby i takové programy fungovaly i na Windows Vista a novějších verzích operačního systému, vývojáři zavedli tzv. virtualizaci registru, která přesměrovává operace z některých oblastí stromu HKEY_LOCAL_MACHINE do oblastí specifických pro daného uživatele.

64bitové verze Windows se od těch 32bitových lišily i v umístění některých složek, souborů a klíčů registru. Pro rozšíření systému bylo důležité, aby i na těchto platformách běžely staré 32bitové aplikace, a tak jádro disponuje prostředky, jak jejich běh emulovat. Pro zvýšení autentičnosti této emulace se vývojáři rozhodli, že emulovaná aplikace uvidí prostředí kolem sebe co nejvíc odpovídající opravdovému 32bitovému systému. V oblasti registru to znamenalo zavedení dalších dvou vlastností: přesměrování a reflexe.

Všechny tři nové vlastnosti registru popisuje následující text.

Virtualizace (Registry Virtualization)

Virtualizace registru umožňuje aplikacím nepřipraveným na prostředí Windows Vista a novějších verzí operačního systému zapisovat do některých klíčů registru, i když na provedení této akce nemají dostatečná oprávnění. Zápis se emuluje přesměrováním na klíč ve stromu z uživatelského profilu. Aby vše bylo transparentní, systém přesměrovává i pokusy o čtení.

Virtualizovány jsou jen klíče nacházející se ve stromu HKLM\SOFTWARE, ke kterým má administrátor právo zápisu. Výjimku tvoří větve HKLM\SOFTWARE\Classes, HKLM\SOFTWARE\Microsoft\Windows a HKLM\SOFTWARE\Microsoft\Windows NT.

Virtualizaci podléhají pouze interaktivní 32bitové aplikace, které nemají ve svém souboru manifest specifikován atribut requestedExecutionLevel. Služeb, ovladačů a 64bitových aplikací se virtualizace netýká.

Virtualizace se projevuje pouze při třech operacích: získávání handle ke klíči, čtení a modifikaci.

Pokud se aplikace pokusí získat handle s právem zápisu k virtualizovanému klíči, operace (na rozdíl od pokusu s normálním klíčem) neselže. Jádro vrátí handle s maximálním možným oprávněním, které může aplikace k danému klíči získat. Tuto tichou „úpravu“ volajícímu nijak nesignalizuje. Aplikace ji však může detekovat pomocí funkce NtQueryObject, která umožňuje zjišťovat o určitém handle (či objektu, na který toto handle odkazuje) různé informace včetně oprávnění.

Pokusí-li se aplikace do virtualizovaného klíče zapsat, ať již vytvořením podklíče, nebo nastavením dat nové či existující hodnoty, tato operace je přesměrována na klíč v oblasti HKU\ID_uživatele-Classes\VirtualStore\Machine\Software. Pokusí-li se program pod klíčem HKLM\SOFTWARE\ProgramX vytvořit hodnotu HodnotaY, virtualizace zajistí vytvoření hodnoty s daným jménem v klíči HKU\ID_uživatele\VirtualStore\Machine\Software\ProgramX. Přesměrování se provede i tehdy, obsahuje-li původní klíč ve stromě HKLM hodnotu HodnotaY. Virtualizovaná oblast má přednost před oblastí reálnou.

Třetí případ virtualizace se týká čtení obsahu klíče. Scénář se drží dvou pravidel:

  • Seznam hodnot a podklíčů vzniká sloučením těchto atributů jak u reálného, tak u virtuálního úložiště.

  • Pokud se některé hodnoty či podklíče svými jmény shodují, přednost dostávají entity z virtuálního úložiště.

Přesměrování (Registry Redirector) a reflexe (Registry Reflection)

Na rozdíl od virtualizace, vlastnost přesměrování se zaměřuje na zajištění soužití 32bitových a 64bitových aplikací na jednom operačním systému. Tato vlastnost se tedy projevuje pouze na 64bitových verzích Windows.

Lepší soužití je zajištěno oddělením přístupu 32bitových a 64bitových aplikací k důležitým klíčům registru. Volání rutin pro práci s registry provádí u 64bitových aplikací přesně to, co by každý očekával – pracuje přímo s objekty, o které volající pomocí předaných hodnot parametrů žádá. Operace prováděné 32bitovými aplikacemi jsou však, obdobně jako v případě virtualizace, v případě některých klíčů přesměrovány do podstromu HKLM\SOFTWARE\Wow6432Node. Na některé klíče, které jsou součástí podstromů, jež jsou přesměrovány, přesměrování uplatňováno není a jejich obsah je sdílen oběma druhy aplikací. Takové klíče se označují jako sdílené.

Seznam klíčů, na kterých je uplatňováno přesměrování, se liší v závislosti na verzi operačního systému. Konkrétní údaje najdete v tabulce.

Tabulka 6. Přesměrované klíče registru
Klíč Windows 7 a novější Starší Windows

HKLM

sdílení

sdílení

HKLM\Software

přesměrování

přesměrování

HKLM\Software\Classe

sdílení

reflexe

HKLM\Software\Classes\AppId

sdílení

reflexe *

HKLM\Software\Classes\CLSID

přesměrování

reflexe **

HKLM\Software\Classes\DirectShow

sdílení

reflexe

HKLM\Software\Classes\HCP

sdílení

sdílení

HKLM\Software\Classes\Interface

přesměrování

reflexe

HKLM\Software\Classes\Media Type

přesměrování

reflexe

HKLM\Software\Classes\MediaFoundation

přesměrování

reflexe

HKLM\Software\Clients

sdílení

přesměrování

HKLM\Software\Microsoft\COM3

sdílení

reflexe

HKLM\Software\Microsoft\Cryptography\Calais\Current

sdílení

sdílení

HKLM\Software\Microsoft\Cryptography\Calais\Readers

sdílení

sdílení

HKLM\Software\Microsoft\Cryptography\Calais\Services

sdílení

sdílení

HKLM\Software\Microsoft\Cryptography\Services

sdílení

sdílení

HKLM\Software\Microsoft\CTF\SystemShared

sdílení

sdílení

HKLM\Software\Microsoft\CTF\TIP

sdílení

sdílení

HKLM\Software\Microsoft\DFS

sdílení

sdílení

HKLM\Software\Microsoft\Driver Signing

sdílení

sdílení

HKLM\Software\Microsoft\EnterpriseCertificates

sdílení

sdílení

HKLM\Software\Microsoft\EventSystem

sdílení

reflexe

HKLM\Software\Microsoft\MSMQ

sdílení

sdílení

Microsoft\Non-Driver Signing

sdílení

sdílení

HKLM\Software\Microsoft\Notepad\DefaultFonts

sdílení

sdílení

HKLM\Software\Microsoft\OLE

sdílení

reflexe

HKLM\Software\Microsoft\RAS

sdílení

sdílení

HKLM\Software\Microsoft\RPC

sdílení

reflexe

HKLM\Software\Microsoft\SOFTWARE\Microsoft\Shared Tools\MSInfo

sdílení

reflexe

HKLM\Software\Microsoft\SystemCertificates

sdílení

sdílení

HKLM\Software\Microsoft\TermServLicensing

sdílení

sdílení

HKLM\Software\Microsoft\TransactionServer

sdílení

sdílení

HKLM\Software\Microsoft\Windows\CurrentVersion\App Paths

sdílení

přesměrování

HKLM\Software\Microsoft\Windows\CurrentVersion\Control Panel\Cursors\Schemes

sdílení

sdílení

HKLM\Software\Microsoft\Windows\CurrentVersion\Explorer\AutoplayHandlers

sdílení

přesměrování

HKLM\Software\Microsoft\Windows\CurrentVersion\Explorer\DriveIcons

sdílení

přesměrování

HKLM\Software\Microsoft\Windows\CurrentVersion\Explorer\KindMap

sdílení

přesměrování

HKLM\Software\Microsoft\Windows\CurrentVersion\Group Policy

sdílení

sdílení

HKLM\Software\Microsoft\Windows\CurrentVersion\Policies

sdílení

sdílení

HKLM\Software\Microsoft\Windows\CurrentVersion\PreviewHandlers

sdílení

přesměrování

HKLM\Software\Microsoft\Windows\CurrentVersion\Setup

sdílení

sdílení

HKLM\Software\Microsoft\Windows\CurrentVersion\Telephony\Locations

sdílení

sdílení

HKLM\Software\Microsoft\Windows NT\CurrentVersion\Console

sdílení

přesměrování

HKLM\Software\Microsoft\Windows NT\CurrentVersion\FontDpi

sdílení

sdílení

Microsoft\Windows NT\CurrentVersion\FontLink

sdílení

přesměrování

HKLM\Software\Microsoft\Windows NT\CurrentVersion\FontMapper

sdílení

sdílení

HKLM\Software\Microsoft\Windows NT\CurrentVersion\Fonts

sdílení

sdílení

HKLM\Software\Microsoft\Windows NT\CurrentVersion\FontSubstitute

sdílení

sdílení

HKLM\Software\Microsoft\Windows NT\CurrentVersion\Gre_Initialize

sdílení

přesměrování

HKLM\Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Options

sdílení

přesměrování

HKLM\Software\Microsoft\Windows NT\CurrentVersion\Language Pack

sdílení

přesměrování

HKLM\Software\Microsoft\Windows NT\CurrentVersion\NetworkCards

sdílení

sdílení

HKLM\Software\Microsoft\Windows NT\CurrentVersion\Perflib

sdílení

sdílení

HKLM\Software\Microsoft\Windows NT\CurrentVersion\Ports

sdílení

sdílení

HKLM\Software\Microsoft\Windows NT\CurrentVersion\Print

sdílení

sdílení

HKLM\Software\Microsoft\Windows NT\CurrentVersion\ ProfileList

sdílení

sdílení

HKLM\Software\Microsoft\Windows NT\CurrentVersion\Time Zones

sdílení

sdílení

HKLM\Software\Policies

sdílení

sdílení

HKLM\Software\RegisteredApplications

sdílení

sdílení

HKCU

sdílení

sdílení

HKCU\Software\Classes

sdílení

reflexe

HKCU\Software\Classes\AppId

sdílení

reflexe

HKCU\Software\Classes\CLSID

přesměrování

reflexe

HKCU\Software\Classes\DirectShow

přesměrování

reflexe

HKCU\Software\Classes\Interface

přesměrování

reflexe

HKCU\Software\Classes\Media Type

přesměrování

reflexe

HKCU\Software\Classes\MediaFoundation

přesměrování

reflexe

Systém dává aplikacím při vytváření, získávání handle či mazání klíče na výběr, zda tuto změnu provést v podstromu nativním pro 64bitové, nebo 32bitové aplikace. Pokud program při volání některé z rutin RegCreateKeyEx, RegOpenKeyEx či RegDeleteKeyEx specifikuje příznak KEY_WOW64_32KEY (hodnota 0x0100), operace se provede v části transparentně přístupné 32bitovým aplikacím. Příznak KEY_WOW64_64KEY (hodnota 0x0200) zpřístupňuje i 32bitovým aplikacím nativní oblast pro programy 64bitové.

Přesměrování může způsobit komplikace při zjišťování seznamu podklíčů, protože při nepoužití výše zmíněných příznaků se volající v závislosti na platformě, pro kterou byl přeložen, dozví jenom část seznamu. Pro získání všech podklíčů je zapotřebí získat k jejich rodiči nejprve handle s jedním příznakem a poté i handle s druhým příznakem. Použití obou příznaků najednou není podporováno.

V tabulce se nachází i klíče, na které se uplatňuje třetí výše zmíněná vlastnost registru — reflexe. Projevuje se u některých klíčů a hodnot, jež sice patří do podstromu, na který systém uplatňuje přesměrování, ale jejichž obsah musí být stejný (konzistentní) jak pro 32bitové, tak 64bitové aplikace.

Konzistenci obsahu takových klíčů a hodnot zajišťuje Registr Windows synchronizací zápisů. Jakmile nějaký program změní obsah klíče, na který je uplatňována reflexe, a zruší na něj handle, systém překopíruje nový obsah i do druhé části registru tak, aby následující pokusy o jeho čtení z libovolné aplikace vydaly stejná data.

Z popisu synchronizace při reflexi vyplývá, že pokud více aplikací zapisuje do jednoho klíče s reflexí, projeví se akce pouze té entity, která jako poslední zruší ke klíči handle.

Interní struktura

V předchozí části této kapitoly jste se dozvěděli, jak Registr Windows funguje z pohledu programátora a uživatele. Znáte funkce rozhraní Windows API, které s jeho objekty pracují, a dokážete k tomuto úložišti přistupovat z ovladače běžícího v režimu jádra. Také jste se dozvěděli, jakými mechanismy se Windows snaží zajistit kompatibilitu se staršími aplikacemi a jak se na 64bitových platformách odděluje prostředí nativních a emulovaných (tedy 32bitových) programů.

Nyní nastal čas podívat se o úroveň níže – na fyzickou strukturu registru na pevném disku. Znalost fyzické struktury registru je užitečná zejména v oblasti detekce a odstraňování rootkitů a přístupu k tomuto úložišti konfigurací z jiných operačních systémů, ale umožní získat i představu o rychlosti jednotlivých operací.

Soubory registru (hive)

Stejně jako ostatní data a programy, i celý registr je na pevném disku uložen v jednotlivých souborech. Neexistuje žádný speciální prostor na diskovém oddílu, který by Windows vyhrazovaly pouze pro toto úložiště. Celý strom není nikdy uložen v jednom souboru, ale jeho části jsou rozesety jak v systémovém adresáři, tak v uživatelských profilech. V terminologii se každý soubor obsahující nějaký podstrom registru označuje jako hive.

Umístění jednotlivých souborů na disku a jejich zařazení do stromu registru vidíte v tabulce 7. Na rozdíl od předchozích částí kapitoly, kde se pro většinu podstromů používaly názvy jejich předdefinovaných handle, v tabulce vidíte jejich skutečná jména v rámci jmenného prostoru správce objektů.

Tabulka 7. Zařazení jednotlivých souborů registru do stromové struktury
Název souboru Umístění ve stromu registru

[Rezervovaný oddíl]:\Boot\BCD

\Registry\Machine\BCD00000000

-

\Registry\Machine\HARDWARE

%windir%\system32\config\SAM

\Registry\Machine\SAM

%windir%\system32\config\SECURITY

\Registry\Machine\SECURITY

%windir%\system32\config\SOFTWARE

\Registry\Machine\SOFTWARE

%windir%\system32\config\SYSTEM

\Registry\Machine\SYSTEM

%windir%\system32\config\DEFAULT

\Registry\User\.DEFAULT

%windir%\sytem32\config\systemprofile\ntuser.dat

\Registry\User\S-1-5-18

%windir%\ServiceProfiles\LocalService\ntuser.dat

\Registry\User\S-1-5-19

%windir%\ServiceProfiles\NetworkService\ntuser.dat

\Registry\User\S-1-5-20

%userprofile%\ntuser.dat

\Registry\User\<ID>

%userprofile%\appdata\local\microsoft\windows\usrclass.dat

\Registry\User\<ID>-Classes

Na Windows Vista a Windows 7 je nastavení zavaděče systému uloženo ve formátu stromu registru. Soubor s tímto stromem se ve výchozím natavení nachází na diskovém oddílu předcházejícím systémový. Tento oddíl je rezervován pro potřeby systému a není namapován na žádnou diskovou jednotku. Hive \Registry\Machine\HARDWARE se nachází pouze v paměti a obsahuje informace o aktuálním přidělení prostředků (vektorů přerušení, rozsahů vstupně/výstupních portů) jednotlivým zařízením. Při každém startu systému je znovu vytvořena. Pod klíčem \Registry\User\<ID> je namapován hive s osobními údaji některého z přihlášených uživatelů. Pokud je aplikace pod jeho účtem spuštěna, předdefinované handle HKEY_CURRENT_USER na tento klíč směřuje.

Pro větší přehlednost je celý strom zachycen i na obrázku. Vidíte, že má ve skutečnosti pouze jediný kořen v podobě klíče \Registry , který se však nevyskytuje v žádném ze souborů a systém jej pokaždé vytváří během svého startu. Tento klíč má dva podklíče: Machine a User. Ty se také nacházejí pouze v paměti, ale na rozdíl od jejich rodiče již jsou vidět v Editoru registrů a lze k nim přistupovat přes předdefinované handle HKEY_LOCAL_MACHINE a HKEY_USERS.

Grafické znázornění zařazení jednotlivých hive do stromu registru

hive do registru

Obsah klíče HKLM\SYSTEM\CurrentControlSet\Control\hivelist

win10 registry hivelist

Seznam aktuálně používaných souborů hive a jejich napojení do stromu registru systém ukládá v podobě klíče

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\hivelist

jehož každá hodnota reprezentuje jedno napojení. Její název určuje jméno klíče, který slouží k napojení a data obsahují název souboru hive. Ukázku obsahu tohoto klíče vidíte ve formě snímku Editoru Registru na obrázku. Obsah tohoto klíče se nikdy neukládá na pevný disk.

Každý hive tedy obsahuje údaje o jednom celém stromu klíčů a hodnot. Skládá se z hlavičky, jež se označuje jako základní blok (base block) obsahující různé všeobecné informace o daném stromu, mezi které patří interní jméno a umístění kořenového klíče, a množství datových bloků, v terminologii registru se každý z nich označuje jako hbin, jež obsahují strukturu celého podstromu včetně dat jednotlivých hodnot. Každý hbin se krom krátké hlavičky skládá z buněk (cell) různých typů. Každý typ buňky je určen pro uchovávání určitých dat – například údajů o klíči, o hodnotě či popisovači zabezpečení.

Obecná struktura hive

hive

Základní blok (base block)

Základní blok zabírá vždy první čtyři kilobajty na počátku souboru každé hive. Jeho strukturu vidíte na výpisu 14.

Výpis 14: Struktura základního bloku
typedef struct _HBASE_BLOCK
{
    CHAR Signature [4]; // regf
    DWORD Sequence1;
    DWORD Sequence2;
    FILETIME TimeStamp;
    DWORD MajorVersion;
    DWORD MinorVersion;
    DWORD Type;
    DWORD Format;
    DWORD RootCell;
    DWORD Length;
    DWORD Cluster;
    CHAR FileName [64];
    BYTE Reserved1 [396];
    DWORD CheckSum;
    BYTE Reserved2 [3576];
    DWORD BootType;
    DWORD BootRecover;
} HBASE_BLOCK, *PHBASE_BLOCK;

Začátek bloku (pole Signature ) je označen magickou signaturou regf. V interních datových strukturách registru se podobné signatury používají velmi často.

Úlohou polí Sequence1 a Sequence2 je odrážet stav synchronizace obsahu hive v paměti a na pevném disku. Pokud obě tato pole obsahují stejnou hodnotu, struktura hive v paměti a na pevném disku je konzistentní, tedy obsahuje stejná data. Výjimku tvoří pouze klíče, které byly vytvořeny s příznakem, jež jádru diktuje uchovávat je pouze v paměti (volatilní klíče). Pokud se obsah polí liší, znamená to, že obsah hive v paměti je aktuálnější než data příslušného souboru na pevném disku.

Mezi významné položky patří také RootCell, která udává, kde se nachází buňka s údaji o kořenovém klíči hive. Tato informace je uložena ve formě offsetu počátku buňky od počátku prvního datového bloku (hbin). První datový blok začíná vždy ihned za koncem základního bloku.

Poznámka: Všechny offsety v interních strukturách registru jsou relativní k počátku prvního datového bloku.

Členy MajorVersion a MinorVersion obsahují číslo verze formátu souboru hive. Do doby psaní tohoto textu byly zpozorovány dvě kombinace hodnot. Soubory registru hive ve verzi 1.3 se používají až do Windows 2000. Novější verze operačního systému dávají přednost verzi 1.5, ale umějí pracovat i se starší verzí.

Velikost datové oblasti hive obsahuje položka Length. Jedná se o součet velikostí všech datových bloků. Interní jméno hive je uloženo v poli FileName a může dosáhnout maximálně délky 64 znaků. Integritu celého základního bloku hlídá kontrolní součet uložený v položce CheckSum.

Datový blok (hbin)

Velikost datového bloku se pohybuje v násobcích 4 kilobajtů. Stejně jako v případě bloku základního, i ten datový uvozuje, v tomto případě velmi krátká, hlavička, jejíž definici vidíte na výpisu 15. Pole Signature zde obsahuje magickou hodnotu hbin. Každý datový blok dále zná svoji pozici v rámci hive (FileOffset) a velikost v bajtech (Size).

Výpis 15: Struktura hlavičky datového bloku
typedef struct _HBIN_HEADER
{
    CHAR Signature [4]; // hbin
    DWORD FileOffset;
    DWORD Size;
    LARGE_INTEGER Reserved;
    FILETIME TimeStamp;
    DWORD Spare;
} HBIN_HEADER, *PHBIN_HEADER;

Za hlavičkou datového bloku následuje pole různě velkých buněk. Každá buňka na svém začátku obsahuje informaci o velikosti v podobě 32bitového celého čísla. Bit 31 této hodnoty se do velikosti nepočítá, ale určuje, zda je daná buňka obsazená, nebo volná. Volné buňky tento příznak mají nastavený na nulu. Dále se struktury buněk liší v závislosti na jejich typu.

Žádná buňka nemůže přesáhnout hranici datového bloku.

Buňka (cell)

Každá buňka obsahuje informace jednoho druhu; například uchovává název a atributy klíče, seznam jeho podklíčů či název a typ některé z jeho hodnot. Každý druh dat znamená odlišný interní formát buňky.

Některé z typů buněk lze dobře rozpoznat na základě dvoubajtové signatury, která se nachází ihned za velikostí buňky. Přesně jej lze určit však pouze na základě znalosti kontextu. Například buňka reprezentující seznam podklíčů určitého klíče bude obsahovat pouze offsety na další buňky s informacemi o jménu a dalších vlastnostech klíčů. Signatury mají svůj význam při rozpoznávání konkrétního formátu zakódování určité informace. Například seznam podklíčů může být zapsán buňkami čtyř různých typů, které se z hlediska syntaxe v jednom případě liší právě pouze svojí signaturou.

Seznam signatur používaných pro některé typy buněk ukazuje tabulka 8. Existují však i buňky, jež žádnou signaturu neobsahují.

Tabulka 8. Signatury buněk různých typů
Signatura Typ uložených informací

nk

Jméno a další vlastnosti klíče.

sk

Popisovač zabezpečení (pouze pro klíče).

vk

Jméno, typ a další informace o hodnotě.

db

Data u některých hodnot.

lh

Seznam podklíčů.

lf

Seznam podklíčů.

ri

Seznam podklíčů.

li

Seznam podklíčů.

lk

Vstupní bod hive do stromu registru.

Monitorování a filtrování operací nad registrem