Автор: mabu (Корпорация «Пакетные файлы»)

Опубликовано:

Исправлено:

Версия документа: 1

Реестр Windows

Реестр Windows или системный реестр — иерархическая база данных параметров и настроек в большинстве операционных систем Microsoft Windows. Реестр содержит информацию и настройки для аппаратного обеспечения, программного обеспечения, профилей пользователей, предустановки. Большинство изменений в Панели управления, ассоциации файлов, системные политики, список установленных программ фиксируются в реестре. Реестр Windows был введён для упорядочения информации, хранившейся до этого во множестве INI‐файлов, обеспечения единого механизма чтения‐записи настроек, избавления от проблем коротких имён файлов, отсутствия разграничения прав доступа и медленного доступа к INI‐файлам.

Историческая справка

Сам реестр как древовидная иерархическая база данных впервые появился в Windows 3.1 (апрель 1992). Это был всего один двоичный файл, который назывался REG.DAT и хранился в каталоге C:\Windows\. Реестр Windows 3.1 имел только одну ветку HKEY_CLASSES_ROOT. Он служил для связи DDE, а позднее и OLE-объектов. Одновременно c появлением реестра в Windows 3.1 появилась программа REGEDIT.EXE для просмотра и редактирования реестра.

Следующий шаг был сделан в Windows NT 3.1 (июль 1993). Произошёл отказ от INI‐файлов как основных файлов конфигурации. На «регистрационную базу» (реестр) была переведена вся конфигурация системы, и основой стал реестр. Он имел 4 корневых раздела: HKEY_LOCAL_MACHINE, HKEY_CURRENT_USER, HKEY_CLASSES_ROOT и HKEY_USERS. Реестр стал «сборным»: на диске он хранился в файлах: DEFAULT, SOFTWARE, SYSTEM, и при запуске системы из этих файлов собиралась единая база данных.

Реестр в том виде, как его использует Windows и как видит его пользователь в процессе использования программ работы с реестром, формируется из различных источников. Впервые, в процессе установки и настройки Windows, на диске формируются файлы, в которых хранится часть данных относительно конфигурации системы. Затем, в процессе каждой загрузки системы, входа и выхода пользователя, формируется некая виртуальная сущность, называемая «реестром» — объект ядра «REGISTRY».

Поставщиками данных для формирования базы реестра могут быть:

Внутреннее устройство

В реестре очень легко разобраться, если представлять его структуру в виде файловой системы. Реестр состоит разделов, подразделов, параметров и значений. Аналог директорий и каталогов в проводнике — это разделы и подразделы реестра, файлы — параметры, содержимое файлов — значения параметров.

Компьютер
│
├───HKEY_CLASSES_ROOT
│   │
│   ├───Раздел — Параметр по умолчанию
│   │   └───Именованный параметр — Значение
│   │
│   └───Раздел
│       ├───Именованный параметр — Значение
│       ├───Именованный параметр — Значение
│       └───Именованный параметр — Значение
│
├───HKEY_CURRENT_USER
│   │
│   ├───Раздел
│   │   ├───Именованный параметр — Значение
│   │   │
│   │   └───Подраздел — Параметр по умолчанию
│   │       └───Именованный параметр — Значение
│   │
│   └───Раздел — Параметр по умолчанию
│       ├───Именованный параметр — Значение
│       ├───Именованный параметр — Значение
│       └───Именованный параметр — Значение
│
├───HKEY_LOCAL_MACHINE
│   │
│   └───…
│
├───HKEY_USERS
│   │
│   └───…
│
└───HKEY_CURRENT_CONFIG
    │
    └───…

Назначения корневых разделов

Если открыть редактор реестра regedit, то можно увидеть пять стандартных корневых разделов реестра:

Только три раздела реестра являются «настоящими» корневыми, остальные являются ссылками на подразделы из HKEY_LOCAL_MACHINE.

HKEY_CLASSES_ROOT

Предназначается для хранения зарегистрированных типов файлов и классов. Это не настоящий корневой раздел, а всего лишь ссылка на HKEY_LOCAL_MACHINE\Software\Classes.

HKEY_CURRENT_USER

Здесь лежат настройки текущего активного пользователя: пути к папкам пользователя, различные персональные настройки и параметры панели управления. Эти сведения напрямую взаимодействуют с профилем пользователя. Данная ветка состоит из нескольких подразделов, которые содержат пути звуковых файлов, используемых для озвучивания системных событий; различные данные, которые могут быть изменены в панели управления, например, упорядочение значков; информацию о текущей раскладке клавиатуры, пользовательские настройки приложений и тому подобное.

Не является настоящим разделом, это ссылка на один из подразделов из HKEY_USERS.

HKEY_LOCAL_MACHINE

Здесь хранятся настройки операционной системы и программ для всех пользователей.

HKEY_USERS

Эта ветка содержит информацию о профилях всех пользователей данного компьютера: имя пользователя, настройки рабочего стола и так далее. Также этот раздел хранит настройки по умолчанию для для пользователей — они нужны в тех случаях, когда новый пользователь входит в систему в первый раз, в этот момент настройки по умолчанию копируются в его профиль.

HKEY_CURRENT_CONFIG

Раздел отвечает за устройства Plug&Play и содержит информацию о текущей конфигурации компьютера с переменным составом устройств, вроде флеш-карт, принтеров, факсов, внешних накопителей. Также данный раздел содержит сведения о текущем профиле оборудования, который используется компьютером при запуске системы.

Является ссылкой на HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Hardware Profiles.

HKEY_PERFORMANCE_DATA

Информация о счётчиках производительности системы, предоставляемая либо самим ядром системы, либо запущенными драйверами, программами и службами, которые предоставляют данные о производительности. Данные счётчиков не хранятся непосредственно в реестре, функции реестра заставляют систему собирать данные воедино из множества источников, в том числе из удалённых систем.

HKEY_CURRENT_USER_LOCAL_SETTINGS

Здесь хранятся настройки текущего пользователя для локального компьютера. Настройки содержат неперемещаемые данные профиля пользователя.

Этот ключ поддерживается начиная с Windows 7 и Server 2008.

HKEY_DYN_DATA

Данный раздел имеется только в реестре систем семейства Windows 9x/ME. Содержит динамически изменяемые данные о компьютере, загрузка процессора, размер файла подкачки и прочее.

Основные типы данных реестра

Параметры реестра могут хранить данные в различных форматах. При создании параметра его тип сохраняется в реестре и затем используется в функциях чтения значений.

REG_BINARY:
Любые двоичные данные.
REG_DWORD:
DWORD, 32‐битное беззнаковое число.
REG_QWORD:
QWORD, 64‐битное беззнаковое число.
REG_SZ:
Строка с нулевым символом на конце.
REG_EXPAND_SZ:
Строка с нулевым символом на конце, в которой могут использоваться переменные среды, такие как %PATH%.
REG_MULTI_SZ:
Список строк, каждая с нулевым символом, пустая строка означает конец списка.

Для строковых типов данных REG_SZ, REG_EXPAND_SZ или REG_MULTI_SZ возможна ситуация, когда строка была сохранена без конечного нулевого символа. При чтении строки из реестра не следует полагаться на наличие нулевого символа, необходимо устанавливать его самостоятельно, иначе при работе с такой строкой может произойти выход за границы буфера.

Типы данных являются больше подсказывающими, чем настоящими: функции чтения и записи работают массивом байт, а не с DWORD или строкой. Поэтому, записывая и читая данные, функции требуют указания количества байт.

Cтроки необходимо записывать вместе с конечным нулевым символом. Общей ошибкой является использование функции Len (strlen в Си, lstrlen в WinAPI) для определения количества записываемых байт, так как функция Len возвращает количество символов в строке и не включает завершающий нулевой символ. Количество байт должно быть рассчитано как произведение размера символа и увеличенной на единицу длины строки:

' Для строк типа String и неюникодных строк
BufferLength = SizeOf(ZString) * (Len(строка) + 1)

' Для юникодных строк
BufferLength = SizeOf(WString) * (Len(строка) + 1)

' Обобщённый вариант в WinAPI
BufferLength = SizeOf(TCHAR) * (Len(строка) + 1)

Пустая строка (строка нулевой длины) в REG_MULTI_SZ означает конец списка, таким образом в списке нельзя сохранить пустую строку.

Кроме этих типов данных существуют и другие, но используются они либо крайне редко (типы данных с указанием подярка байт), либо для внутренних целей самого реестра (ссылки).

Безопасность раздела реестра и права доступа

В следующей таблице перечислены конкретные права доступа для объектов раздела реестра.

ФлагОписание
KEY_ALL_ACCESSЛюбые действия над разделом: чтение, запись, перечисление подразделов. Является комбинацией флагов STANDARD_RIGHTS_REQUIRED, KEY_QUERY_VALUE, KEY_SET_VALUE, KEY_CREATE_SUB_KEY, KEY_ENUMERATE_SUB_KEYS, KEY_NOTIFY и KEY_CREATE_LINK
KEY_READЧтение раздела, параметров и подразделов, является комбинацией флагов STANDARD_RIGHTS_READ, KEY_QUERY_VALUE, KEY_ENUMERATE_SUB_KEYS и KEY_NOTIFY
KEY_QUERY_VALUEЧтение параметров раздела
KEY_ENUMERATE_SUB_KEYSПеречисление подразделов данного раздела
KEY_WRITEЗапись параметров, является комбинацией флагов STANDARD_RIGHTS_WRITE, KEY_SET_VALUE и KEY_CREATE_SUB_KEY
KEY_SET_VALUEСоздание, удаление и изменение параметров в разделе
KEY_CREATE_SUB_KEYСоздание подразделов в текущем разделе
KEY_NOTIFYРазрешается использовать ключ для уведомлений об изменениях в разделе и подразделах
KEY_EXECUTEТо же, что и KEY_READ
KEY_CREATE_LINKЗарезервировано для системы
KEY_WOW64_32KEY64‐битное приложение должно открыть 32‐битную версию реестра
KEY_WOW64_64KEY64‐битное приложение должно открыть 64‐битную версию реестра

Система проверяет запрошенные права доступа. Если пользователь не имеет правильного доступа к разделу реестра, операция открытия завершается неудачей.

Ограничения реестра

Имена разделов, подразделов и параметров не чувствительны к регистру символов.

Имя раздела не должно превышать 255 символов.

Длина имени параметра раздела не должна превышать 16383 юникодных символа включая нулевой.

Значение параметра может занимать всю доступную память, но рекомендуется использовать не более 2048 байт.

Подразделы не должны превышать 512 уровней вложенности. Одновременно можно создать не более 32 уровней вложенности.

Стратегия хранения настроек и параметров в реестре

Программы обычно применяют следующую стратегию когда хранят настройки в реестре.

Настройки для всех пользователей

Используется раздел HKEY_LOCAL_MACHINE:

HKEY_LOCAL_MACHINE\Software\Имя организации\Название программы\[Версия]

Программа должна корректно работать при отсутствии этой ветки или какого‐либо параметра в ней, используя значения по умолчанию. Запись в ветку HKEY_LOCAL_MACHINE и её подразделы обычно разрешена только администраторам, поэтому многие программы обходятся без этого пункта.

Настройки для текущего пользователя

Используется раздел HKEY_CURRENT_USER:

HKEY_CURRENT_USER\Software\Имя организации\Название программы\[Версия]

Если какие‐либо параметры отсутствуют в HKEY_CURRENT_USER, то берутся параметры из HKEY_LOCAL_MACHINE, а если и там нет, то берутся параметры по умолчанию.

Если какие‐либо параметры существуют как в ветке HKEY_LOCAL_MACHINE, так и в ветке HKEY_CURRENT_USER, то HKEY_CURRENT_USER имеют приоритет.

Раздел HKEY_CURRENT_USER хранится в файле NTUSER.DAT в профиле пользователя, что делает настройки перемещаемыми между пользователями домена. Запись в HKEY_CURRENT_USER разрешена текущему пользователю.

Функции

Как и для любого объекта ядра, для обращения к разделу реестра нужно получить его описатель и указать действия, которые необходимо с ним выполнять. Описатель раздела реестра можно получить открывая или создавая раздел.

ФункцииОписание
RegOpenKeyExОткрывает существующий раздел реестра.
RegCreateKeyExСоздаёт указанный раздел реестра. Если ключ уже существует, функция открывает его.
RegCloseKeyЗакрывает открытый раздел реестра.
RegQueryInfoKeyПолучает информацию о разделе.
RegQueryValueExЧитает значение параметра.
RegSetValueExЗаписывает значение параметра.
RegEnumKeyExПолучает список подразделов.
RegEnumValueПолучает список параметров.
RegNotifyChangeKeyValueУведомляет приложение об изменениях в подразделе.

RegOpenKeyEx

Открывает существующий раздел реестра и возвращает описатель раздела.

Declare Function RegOpenKeyEx Alias "RegOpenKeyExW"( _
    ByVal hKey As HKEY, _
    ByVal lpSubKey As LPCWSTR, _
    ByVal ulOptions As DWORD, _
    ByVal samDesired As REGSAM, _
    ByVal phkResult As PHKEY _
)As LONG

Параметры

hKey:
Описатель открываемого раздела, который может быть стандартным корневым разделом или получен функциями RegCreateKeyEx и RegOpenKey.
lpSubKey:
Указатель на строку с подразделом.
ulOptions:
Дополнительные опции. Установи этот параметр в 0 или REG_OPTION_OPEN_LINK для открывания символической ссылки. Символические ссылки используются только в крайней необходимости.
samDesired:
Требуемый доступ к разделу, в соответствии с таблицей.
phkResult:
Указатель на переменную, куда будет записан дескриптор открытого ключа. Если ключ не является одним из предопределённых разделов реестра, то следует вызвать RegCloseKey после завершения использования дескриптора.

Возвращаемое значение

При успешном выполнении функция возвращает ERROR_SUCCESS.

Если функция завершается неудачно, возвращаемое значение представляет собой ненулевой код ошибки, определённый в winerror.bi.

RegCreateKeyEx

Создаёт подраздел в реестре. Если подраздел уже существует, то функция открывает его.

Declare Function RegCreateKeyEx Alias "RegCreateKeyExW"( _
    ByVal hKey As HKEY, _
    ByVal lpSubKey As LPCWSTR, _
    ByVal Reserved As DWORD, _
    ByVal lpClass As LPWSTR, _
    ByVal dwOptions As DWORD, _
    ByVal samDesired As REGSAM, _
    ByVal lpSecurityAttributes As LPSECURITY_ATTRIBUTES, _
    ByVal phkResult As PHKEY, _
    ByVal lpdwDisposition As LPDWORD _
)As LONG

Параметры

hKey:
Описатель открываемого раздела, который может быть стандартным корневым разделом или получен функциями RegCreateKeyEx и RegOpenKey.
lpSubKey:
Указатель на строку с подразделом.
Reserved:
Зарезервировано. Следует устанавливать в 0.
lpClass:
Указатель на строку, которая содержит класс этого раздела. Может быть проигнорирован и равен NULL. Используется для подключения к удаленному реестру.
dwOptions:
Опции открытия раздела. Может принимать одну из следующих констант:
samDesired:
Требуемый доступ к разделу, в соответствии с таблицей.
lpSecurityAttributes:
Указатель на структуру SECURITY_ATTRIBUTES, которая определяет, может ли возвращаемый дескриптор быть унаследован дочерними процессами. Если lpSecurityAttributes имеет значение NULL, дескриптор не может быть унаследован.
phkResult:
Указатель на переменную, куда будет записан дескриптор открытого ключа. Если ключ не является одним из предопределённых разделов реестра, то следует вызвать RegCloseKey после завершения использования дескриптора.
lpdwDisposition:
Указатель на переменную, куда будет функция запишет результат открытия или создания подраздела реестра. Если раздел ранее существовал, то функция запишет сюда константу REG_OPENED_EXISTING_KEY, если раздел был создан, то функция запишет REG_CREATED_NEW_KEY. Этот параметр может быть NULL.

Возвращаемое значение

При успешном выполнении функция возвращает ERROR_SUCCESS.

Если функция завершается неудачно, возвращаемое значение представляет собой ненулевой код ошибки, определённый в winerror.bi.

Замечания

Функция RegCreateKeyEx создаёт разделы без параметров. Можно воспользоваться функцией RegSetValueEx для создания параметров.

Функция создаёт все подразделы в пути, если они не существовали. Пример: приложение может создать подраздел глубиной в четыре уровня одновременно с тремя предыдущими подразделами, отправив в lpSubKey такую строку:

subkey1\subkey2\subkey3\subkey4

Это поведение может привести к созданию нежелательных ключей, когда существующий ключ в пути будет написан неправильно.

Приложение не может создать ключ, который является прямым потомком HKEY_USERS или HKEY_LOCAL_MACHINE. Приложение может создавать подразделы на более низких уровнях деревьев HKEY_USERS или HKEY_LOCAL_MACHINE.

Если твоя служба или приложение олицетворяют разных пользователей, не используй эту функцию с HKEY_CURRENT_USER. Вместо этого вызови функцию RegOpenCurrentUser.

RegCloseKey

Закрывает описатель реестра, уничтожает объект ядра и освобождает память.

Declare Function RegCloseKey( _
	ByVal hKey As HKEY _
)As LONG

Параметры

hKey:
Описатель открытого раздела, который больше не нужен.

Возвращаемое значение

При успешном выполнении функция возвращает ERROR_SUCCESS.

Если функция завершается неудачно, возвращаемое значение представляет собой ненулевой код ошибки, определённый в winerror.bi.

Замечания

После закрытия описатель для указанного ключа становится недействительным и больше не должен использоваться. Описатели для ключей не следует оставлять открытыми дольше, чем это необходимо.

Функция RegCloseKey не обязательно записывает информацию на жёсткий диск перед возвратом; для сброса данных на диск может потребоваться до некоторое время. Если приложение должно явно записать информацию реестра на жёсткий диск, оно может использовать функцию RegFlushKey. RegFlushKey, однако, использует системные ресурсы и должна вызываться только в случае крайней необходимости.

RegQueryInfoKey

Получает информацию о разделе реестра: имя класса, поличество подразделов и параметров, дату последней модификации.

Declare Function RegQueryInfoKey Alias "RegQueryInfoKeyW"( _
    ByVal hKey As HKEY, _
    ByVal lpClass As LPWSTR, _
    ByVal lpcchClass As LPDWORD, _
    ByVal lpReserved As LPDWORD, _
    ByVal lpcSubKeys As LPDWORD, _
    ByVal lpcbMaxSubKeyLen As LPDWORD, _
    ByVal lpcbMaxClassLen As LPDWORD, _
    ByVal lpcValues As LPDWORD, _
    ByVal lpcbMaxValueNameLen As LPDWORD, _
    ByVal lpcbMaxValueLen As LPDWORD, _
    ByVal lpcbSecurityDescriptor As LPDWORD, _
    ByVal lpftLastWriteTime As PFILETIME _
)As LONG

Параметры

hKey:
Описатель открываемого раздела, который может быть стандартным корневым разделом, HKEY_PERFORMANCE_DATA или получен функциями RegCreateKeyEx и RegOpenKey. Раздел должен быть открыт с правами KEY_QUERY_VALUE.
lpClass:
Указатель на строку, куда будет записано имя класса раздела. Может быть NULL.
lpcchClass:
Указатель на переменную, определяющую размер буфера, на который указывает параметр lpClass, в символах. Размер должен включать завершающий нулевой символ. Функция записывает сюда длину строки класса, хранящейся в буфере без учёта завершающего нулевого символа. Если буфер недостаточно велик, функция возвращает ERROR_MORE_DATA, а переменная содержит размер строки в символах, не считая завершающего нулевого символа. Если lpClass установлен в NULL, то lpcchClass может быть NULL. Если параметр lpClass не NULL, а параметр lpcchClass равен NULL, то функция возвращает ERROR_INVALID_PARAMETER.
lpReserved:
Зарезервировано. Должно быть NULL.
lpcSubKeys:
Указатель на переменную, куда будет записано количество подразделов в текущем разделе. Может быть NULL.
lpcbMaxSubKeyLen:
Указатель на переменную, куда будет записана длина самого длинного имени подраздела без учёта нулевого символа. Может быть NULL.
lpcbMaxClassLen:
Указатель на переменную, куда будет записана длина самого длинного имени класса подраздела без учёта нулевого символа. Может быть NULL.
lpcValues:
Указатель на переменную, куда будет записано количество параметров в разделе. Может быть NULL.
lpcbMaxValueNameLen:
Указатель на переменную, куда будет записана длина самого длинного имени параметра в разделе. Может быть NULL.
lpcbMaxValueLen:
Указатель на переменную, куда будет записана длина самого большого значения параметра в разделе, в байтах. Может быть NULL.
lpcbSecurityDescriptor:
Указатель на переменную, куда будет записана длина дескриптора защиты раздела, в байтах. Может быть NULL.
lpftLastWriteTime:
Указатель на структуру FILETIME, куда будет записана дата последней модификации раздела или его параметров. Может быть NULL.

Возвращаемое значение

При успешном выполнении функция возвращает ERROR_SUCCESS.

Если функция завершается неудачно, возвращаемое значение представляет собой ненулевой код ошибки, определённый в winerror.bi.

RegQueryValueEx

Получает значение параметра раздела реестра.

Declare Function RegQueryValueEx Alias "RegQueryValueExW"( _
    ByVal hKey As HKEY, _
    ByVal lpValueName As LPCWSTR, _
    ByVal lpReserved As LPDWORD, _
    ByVal lpType As LPDWORD, _
    ByVal lpData As LPBYTE, _
    ByVal lpcbData As LPDWORD _
)As LONG

Параметры

hKey:
Описатель открываемого раздела, который может быть стандартным корневым разделом, HKEY_PERFORMANCE_DATA или получен функциями RegCreateKeyEx и RegOpenKey. Раздел должен быть открыт с правами KEY_QUERY_VALUE.
lpValueName:
Указатель на строку, содержащую название параметра. Если равно NULL или пустой строке "", то возвращается значение «по умолчанию». Если параметр с таким именем не существует, то функция вернёт ERROR_FILE_NOT_FOUND.
lpReserved:
Зарезервировано. Должно быть NULL.
lpType:
Указатель на переменную, куда будет записан тип данных параметра. Может быть NULL, если тип данных не требуется.
lpData:
Указатель на буфер, куда будет записано значение параметра. Может быть NULL, в этом случае значение параметра не возвращается, такой метод используется для вычисления размера требуемого буфера.
lpcbData:
Указатель на переменную с размером буфера под значение параметра в байтах. Функция запишет сюда размер данных, скопированных в буфер, в байтах. Если данные носят текстовый характер, то в это число включается и нулевой символ. Если размер буфера недостаточен для сохранения данных, функция запишет требуемый размер буфера, вернёт ERROR_MORE_DATA, а содержимое lpData оставит неопределённым.

Если hKey указывает на HKEY_PERFORMANCE_DATA и буфер lpData недостаточно велик, чтобы содержать все возвращаемые данные, RegQueryValueEx возвращает ERROR_MORE_DATA, и значение, возвращаемое через параметр lpcbData, не определено. Это связано с тем, что размер данных производительности может изменяться от одного вызова к другому. В этом случае необходимо увеличить размер буфера и снова вызвать RegQueryValueEx, передав обновлённый размер буфера в параметре lpcbData. Повторяй это до тех пор, пока функция не завершится успешно. Тебе нужно поддерживать отдельную переменную, чтобы отслеживать размер буфера, потому что значение, возвращаемое lpcbData, непредсказуемо.

Возвращаемое значение

При успешном выполнении функция возвращает ERROR_SUCCESS.

Если функция завершилась ошибкой, то возвращается код ошибки.

Если буфер lpData слишком мал, функция возвращает ERROR_MORE_DATA.

Если параметра lpValueName не существует, функция возвращает ERROR_FILE_NOT_FOUND.

Замечания

Функция предоставляет возможность вначале проверить каков размер данных в параметре, отправив NULL в lpData. Это позволяет выделять память под значение параметра динамически, по ходу выполнения программы.

Если данные имеют тип REG_SZ, REG_MULTI_SZ или REG_EXPAND_SZ, то строка, возможно, была сохранена без завершающего нулевого символа. Поэтому, даже если функция возвращает ERROR_SUCCESS, приложение должно убедиться, что строка правильно завершена перед её использованием; в противном случае может произойти выход за границы буфера.

RegSetValueEx

Устанавливает значение параметра реестра. Если такого параметра не существовало в подразделе, то он будет создан.

Declare Function RegSetValueEx Alias "RegSetValueExW"( _
    ByVal hKey As HKEY, _
    ByVal lpValueName As LPCWSTR, _
    ByVal Reserved As DWORD, _
    ByVal dwType As DWORD, _
    ByVal lpData As Const UBYTE Ptr, _
    ByVal cbData As DWORD _
)As LONG

Параметры

hKey:
Описатель открываемого раздела, который может быть получен функциями RegCreateKeyEx и RegOpenKey. Раздел должен быть открыт с правами KEY_SET_VALUE. Также действуют стандартные описатели корневых разделов.
lpValueName:
Указатель на строку, содержащую название параметра. Если равно NULL, то устанавливается значение «по умолчанию». Если параметр с таким именем не существует, то он будет создан.
lpReserved:
Зарезервировано. Должно быть NULL.
dwType:
Тип данных параметра.
lpData:
Указатель на буфер, содержащий значение параметра. Строковые данные должны заканчиваться завершающим нулевым символом.
cbData:
Размер буфера под параметр в байтах. Для числовых данных достаточно указать SizeOf(REG_DWORD) или SizeOf(REG_QWORD), для строк необходимо учитывать все нулевые символы, например, так: ((Длина строки + 1) * SizeOf(WString)).

Возвращаемое значение

При успешном выполнении функция возвращает ERROR_SUCCESS.

Если функция завершается неудачно, возвращаемое значение представляет собой ненулевой код ошибки, определённый в winerror.bi.

Замечания

Хотя значения параметров реестра ограничены только размером доступной памяти, всё же сохранение очень больших данных сильно сказывается на производительности. Данные больше чем 2048 байт следует сохранять в файлах, а не в реестре, сохраняя в реестре только пути к файлам.

Такие данные как значки, точечные рисунки, исполняемые файлы необходимо сохранять на диске.

RegEnumKeyEx

Перечисляет подразделы раздела реестра.

Declare Function RegEnumKeyEx Alias "RegEnumKeyExW"( _
    ByVal hKey As HKEY, _
    ByVal dwIndex As DWORD, _
    ByVal lpName As LPWSTR, _
    ByVal lpcchName As LPDWORD, _
    ByVal lpReserved As LPDWORD, _
    ByVal lpClass As LPWSTR, _
    ByVal lpcchClass As LPDWORD, _
    ByVal lpftLastWriteTime As PFILETIME _
)As LONG

Параметры

hKey:
Описатель открываемого раздела, который может быть получен функциями RegCreateKeyEx и RegOpenKey. Раздел должен быть открыт с правами KEY_ENUMERATE_SUB_KEYS. К стандартным описателям корневых разделов добавляется ключ HKEY_PERFORMANCE_DATA.
dwIndex:
Индекс подраздела. При первом вызове этот параметр должен быть равен нулю, при последующих — увеличиваться на единицу. Подразделы не упорядочены, функция может возвращать подразделы в любом порядке.
lpName:
Указатель на строку‐буфер, куда будет записано имя подраздела.
lpcchName:
Указатель на переменную, где хранится длина строки‐буфера имени подраздела в символах включая нулевой. Если функция выполнится успешно, то сюда будет записана длина имени подраздела без учёта нулевого символа.
lpReserved:
Зарезервировано. Должно быть NULL.
lpClass:
Указатель на строку‐буфер, куда будет записано имя класса раздела. Может быть NULL.
lpcchClass:
Указатель на переменную, где хранится длина строки‐буфера имени класса подраздела в символах, включая нулевой. Если функция выполнится успешно, то сюда будет записана длина имени класса подраздела без учёта нулевого символа. Может быть NULL если строка‐буфер для имени класса подраздела равна NULL.
lpftLastWriteTime:
Указатель на структуру FILETIME, куда будет записана дата последней модификации подраздела. Может быть NULL.

Возвращаемое значение

При успешном выполнении функция возвращает ERROR_SUCCESS.

Если функция завершилась ошибкой, то возвращается код ошибки. Приложение, вызывающее эту функцию, должно увеличивать параметр dwIndex до тех пор, пока функция не возвратит ERROR_NO_MORE_ITEMS.

Замечания

Для перечисления подразделов приложение должно вызвать функцию RegEnumKeyEx с параметром dwIndex равным нулю. Затем каждый раз увеличивать dwIndex на единицу и вызывать функцию снова, до тех пор, пока не будут перечислены все подразделы: в этом случае функция вернёт ERROR_NO_MORE_ITEMS или ошибку.

Приложение также может установить dwIndex в индекс последнего подраздела при первом вызове функции и уменьшать индекс до тех пор, пока не будет перечислен подраздел с индексом 0. Чтобы получить индекс последнего подраздела, используй функцию RegQueryInfoKey.

RegEnumValue

Перечисляет параметры раздела реестра.

Declare Function RegEnumValue Alias "RegEnumValueW"( _
    ByVal hKey As HKEY, _
    ByVal dwIndex As DWORD, _
    ByVal lpValueName As LPWSTR, _
    ByVal lpcchValueName As LPDWORD, _
    ByVal lpReserved As LPDWORD, _
    ByVal lpType As LPDWORD, _
    ByVal lpData As LPBYTE, _
    ByVal lpcbData As LPDWORD _
)As LONG

Параметры

hKey:
Описатель открываемого раздела, который может быть получен функциями RegCreateKeyEx и RegOpenKey. Раздел должен быть открыт с правами KEY_QUERY_VALUE. К стандартным описателям корневых разделов добавляется ключ HKEY_PERFORMANCE_DATA.
dwIndex:
Индекс параметра. При первом вызове этот параметр должен быть равен нулю, при последующих — увеличиваться на единицу. Параметры не упорядочены, функция может возвращать параметры в любом порядке.
lpValueName:
Указатель на строку‐буфер, куда будет записано имя параметра.
lpcchValueName:
Указатель на переменную, где хранится длина строки‐буфера имени параметра в символах включая нулевой. Если функция выполнится успешно, то сюда будет записана длина имени параметра без учёта нулевого символа.
lpReserved:
Зарезервировано. Должно быть NULL.
lpType:
Указатель на переменную, куда будет записан тип данных параметра. Может быть NULL.
lpData:
Указатель на буфер, куда будет записано значение параметра. Если указать NULL, то функция заполнит lpcbData требуемой длиной буфера.
lpcbData:
Указатель на переменную с размером буфера под значение параметра в байтах. Функция запишет сюда размер данных, скопированных в буфер. Может быть NULL, только если lpData равно NULL.

Возвращаемое значение

При успешном выполнении функция возвращает ERROR_SUCCESS.

Если буфер, размер буфера, указанный в lpcbData недостаточен для сохранения данных, то функция вернёт ERROR_MORE_DATA и запишет требуемый размер буфера в lpcbData.

Если функция завершилась ошибкой, то возвращается код ошибки. Приложение, вызывающее эту функцию, должно увеличивать параметр dwIndex до тех пор, пока функция не возвратит ERROR_NO_MORE_ITEMS.

Замечания

Для перечисления параметров подраздела реестра приложение должно вызвать функцию RegEnumValue с параметром dwIndex равным нулю. Затем каждый раз увеличивать этот параметр на единицу и вызывать функцию снова, до тех пор, пока не будут перечислены все параметры, в этом случае функция вернёт ERROR_NO_MORE_ITEMS или ошибку.

Также можно перечислять параметры в обратном порядке, установив параметр dwIndex равным максимальному индексу параметра, возвращённому функцией ReqQueryValue, и уменьшая его на единицу при каждом вызове функции до нуля.

Функция возвращает параметры подраздела без всякой сортировки.

RegNotifyChangeKeyValue

Уведомляет приложение об изменении в разделе реестра.

Declare Function RegNotifyChangeKeyValue( _
    ByVal hKey As HKEY, _
    ByVal bWatchSubtree As WINBOOL, _
    ByVal dwNotifyFilter As DWORD, _
    ByVal hEvent As HANDLE, _
    ByVal fAsynchronous As WINBOOL _
)As LONG

Параметры

hKey:
Описатель открываемого раздела, который может быть получен функциями RegCreateKeyEx и RegOpenKey. Раздел должен быть открыт с правами KEY_NOTIFY. Также действуют стандартные описатели корневых разделов.
bWatchSubtree:
Если этот параметр равен TRUE, то функция будет следить за изменениями в подразделах, если FALSE то только в текущем разделе.
dwNotifyFilter:
Указывает, о каких изменениях следуем уведомлять приложение. Может быть комбинацией из следующих значений:
hEvent:
Описатель объекта ядра «событие». Если fAsynchronous установлен в TRUE, то функция возвращает значение немедленно и будет отправлять уведомления через указанное событие. Если fAsynchronous равно FALSE, то hEvent игнорируется.
fAsynchronous:
Если установлен в TRUE, то функция возвращает значение немедленно и будет отправлять уведомления через указанное событие, в этом случае hEvent должен быть действительным объектом ядра «событие». Если fAsynchronous равно FALSE, то hEvent игнорируется.

Возвращаемое значение

При успешном выполнении функция возвращает ERROR_SUCCESS.

Если функция завершается неудачно, возвращаемое значение представляет собой ненулевой код ошибки.

Замечания

Функция уведомляет об одном изменении. Чтобы получить уведомление о следующем, необходимо вызвать её снова.

Примеры

Чтение и запись настроек приложения

В этом примере сохраним и считаем из реестра имя пользователя и размеры окна приложения «Офис» вымышленной корпорации «Большие программы» в профиле пользователя.

#include "windows.bi"

Const RegSection = __TEXT("Software\Большие программы\Офис\1.0.0.0")
Const UserNameKey = __TEXT("Пользователь")
Const WidthKey = __TEXT("Width")
Const HeightKey = __TEXT("Height")

' Запись параметров
Scope
    Dim reg As HKEY = Any
    Dim lpdwDisposition As DWORD = Any

    ' Открыть раздел реестра в профиле текущего пользователя
    Dim hr As Long = RegCreateKeyEx(HKEY_CURRENT_USER, @RegSection, 0, 0, 0, KEY_SET_VALUE, NULL, @reg, @lpdwDisposition)
    If hr <> ERROR_SUCCESS Then
        End(1)
    End If

    ' Записать ширину окна
    Dim WindowWidth As DWORD = 640
    hr = RegSetValueEx(reg, @WidthKey, 0, REG_DWORD, CPtr(Byte Ptr, @WindowWidth), SizeOf(DWORD))

    ' Записать высоту окна
    Dim WindowHeight As DWORD = 480
    hr = RegSetValueEx(reg, @HeightKey, 0, REG_DWORD, CPtr(Byte Ptr, @WindowHeight), SizeOf(DWORD))

    ' Записать имя пользователя
    Dim UserName As LPTSTR = @__TEXT("Алексей")
    hr = RegSetValueEx(reg, @UserNameKey, 0, REG_SZ, CPtr(Byte Ptr, UserName), (Len(UserName) + 1) * SizeOf(TCHAR))

    RegCloseKey(reg)
End Scope

' Чтение параметров
Scope
    Dim reg As HKEY = Any
    Dim lpdwDisposition As DWORD = Any
    Dim hr As Long = RegCreateKeyEx(HKEY_CURRENT_USER, @RegSection, 0, 0, 0, KEY_QUERY_VALUE, NULL, @reg, @lpdwDisposition)
    If hr <> ERROR_SUCCESS Then
        End(1)
    End If

    Scope
        Dim WindowWidth As DWORD = Any
        Dim BufferLength As DWORD = SizeOf(DWORD)
        hr = RegQueryValueEx(reg, @WidthKey, 0, NULL, CPtr(Byte Ptr, @WindowWidth), @BufferLength)
        Print "Ширина окна", WindowWidth
    End Scope

    Scope
        Dim WindowHeight As DWORD = Any
        Dim BufferLength As DWORD = SizeOf(DWORD)
        hr = RegQueryValueEx(reg, @HeightKey, 0, NULL, CPtr(Byte Ptr, @WindowHeight), @BufferLength)
        Print "Высота окна", WindowHeight
    End Scope

    Scope
        ' Определить размер требуемого буфера для имени пользователя
        Dim BufferLength As DWORD = Any
        hr = RegQueryValueEx(reg, @UserNameKey, 0, NULL, NULL, @BufferLength)
        Print "Размер буфера под имя пользователя в байтах", BufferLength

        Dim pUserName As LPTSTR = Allocate(BufferLength)
        hr = RegQueryValueEx(reg, @UserNameKey, 0, NULL, CPtr(Byte Ptr, pUserName), @BufferLength)
        Print "Имя пользователя", *pUserName
        Deallocate(pUserName)
    End Scope

    RegCloseKey(reg)
End Scope

Перечисление подразделов

В этом примере перечислим все подразделы в разделе «Software» для всех пользователей.

#include "windows.bi"

Const RegSection = __TEXT("Software")

' Получить список подразделов

Dim reg As HKEY = Any
Dim lpdwDisposition As DWORD = Any

' Открыть раздел реестра общий для всех пользователей
Dim hr As Long = RegCreateKeyEx(HKEY_LOCAL_MACHINE, @RegSection, 0, 0, 0, KEY_QUERY_VALUE + KEY_ENUMERATE_SUB_KEYS, NULL, @reg, @lpdwDisposition)
If hr <> ERROR_SUCCESS Then
    End(1)
End If

Dim strClassName(511) As TCHAR = Any
Dim ClassNameLength As DWORD = 511

Dim SubKeysCount As DWORD = Any
Dim MaxSubKeyLength As DWORD = Any
Dim MaxClassNameLength As DWORD = Any

Dim ValuesCount As DWORD = Any
Dim MaxValueDataLength As DWORD = Any
Dim MaxValueNameLength As DWORD = Any

Dim LastWriteTime As FILETIME = Any

' Информация о разделе реестра
hr = RegQueryInfoKey(reg, @strClassName(0), @ClassNameLength, 0, @SubKeysCount, @MaxSubKeyLength, @MaxClassNameLength, @ValuesCount, @MaxValueNameLength, @MaxValueDataLength, NULL, @LastWriteTime)
If hr <> ERROR_SUCCESS Then
    End(1)
End If

Print "ClassNameLength", ClassNameLength
Print "SubKeysCount", SubKeysCount
Print "MaxSubKeyLength", MaxSubKeyLength
Print "MaxClassNameLength", MaxClassNameLength
Print "ValuesCount", ValuesCount
Print "MaxValueNameLength", MaxValueNameLength
Print "MaxValueDataLength", MaxValueDataLength

Dim SubKeyName As LPTSTR = Allocate((SizeOf(TCHAR) + 1) * MaxSubKeyLength)

' Перечисление подразделов в обратном порядке
For i As DWORD = SubKeysCount - 1 To 0 Step -1
    Dim MaxSubKeyLength1 As DWORD = MaxSubKeyLength + 1
    hr = RegEnumKeyEx(reg, i, SubKeyName, @MaxSubKeyLength1, 0, NULL, 0, @LastWriteTime)
    If hr <> ERROR_SUCCESS Then
        Print "Ошибка перечисления", hr
        Exit For
    End If
    Print *SubKeyName
Next

Deallocate(SubKeyName)
RegCloseKey(reg)