]>Реестр Windows

Реестр Windows

Аватар пользователя mabu

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

  1. Историческая справка
  2. Внутреннее устройство
    1. Хранение настроек в реестре
    2. Типы параметров реестра
    3. Ограничения
  3. Функции
    1. RegOpenKeyEx
    2. RegCreateKeyEx
    3. RegCloseKey
    4. RegQueryInfoKey
    5. RegQueryValueEx
    6. RegSetValueEx
    7. RegEnumKeyEx
    8. RegEnumValue
    9. RegNotifyChangeKeyValue

  4. Примеры
    1. Чтение и запись настроек приложения
    2. Перечисление подразделов

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

Сам реестр как древовидная иерархическая база данных впервые появился в 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\». Данные для формирования «реестра» частично берутся из тех самых файлов (Software, System) и частично из информации, собранной ntdetect.com при загрузке Windows. То есть часть данных реестра хранится в файлах, а часть данных формируется в процессе загрузки Windows.

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

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

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

Для простоты их часто указывают в сокращённом обозначении: HKCR, HKCU, HKLM, HKU, HKCC. Также существует раздел HKEY_PERFORMANCE_DATA, где хранится информация о счётчиках производительности Windows, но он не отображается в редакторе реестра.

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

Хранение настроек в реестре

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

Типы параметров реестра

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

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

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

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

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

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

Ограничения

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

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

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

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

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

Функции

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

Чтобы уничтожить объект ядра реестра и освободить занимаемую им память применяется функция RegCloseKey.

Для чтения и записи значений параметров используются функции RegQueryValueEx и RegSetValueEx.

Для получения списка подразделов и параметров созданы функции RegEnumKeyEx и RegEnumValue.

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

RegOpenKeyEx

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

Код FreeBASIC
Declare Function RegOpenKeyEx Alias "RegOpenKeyExW"( _
&t;ByVal hKey As HKEY, _
&t;ByVal lpSubKey As LPCWSTR, _
&t;ByVal ulOptions As DWORD, _
&t;ByVal samDesired As REGSAM, _
&t;ByVal phkResult As PHKEY) _
As LONG

Параметры

hKey
Описатель открываемого раздела, который может быть получен функциями RegCreateKeyEx и RegOpenKey. Также действуют стандартные описатели корневых разделов, перечисленные выше.
lpSubKey
Указатель на строку с подразделом.
ulOptions
Зарезервировано. Должно быть 0.
samDesired
Требуемый доступ к разделу. Может быть комбинацией одного или нескольких значений:
  • KEY_ALL_ACCESS — разрешаются любые действия над разделом;
  • KEY_ENUMERATE_SUB_KEYS — разрешается перечисление подразделов данного раздела;
  • KEY_QUERY_VALUE — разрешается чтение параметров раздела;
  • KEY_NOTIFY — разрешается использовать ключ для уведомлений об изменениях в разделе и подразделах;
  • KEY_READ — разрешается чтение раздела, параметров и подразделов, является комбинацией флагов STANDARD_RIGHTS_READ, KEY_QUERY_VALUE, KEY_ENUMERATE_SUB_KEYS и KEY_NOTIFY;
  • KEY_SET_VALUE — разрешается создание, удаление и изменение параметров в разделе;
  • KEY_CREATE_SUB_KEY — разрешается создание подразделов в текущем разделе;
  • KEY_WRITE — разрешается запись параметров, является комбинацией флагов STANDARD_RIGHTS_WRITE, KEY_SET_VALUE и KEY_CREATE_SUB_KEY.
phkResult
Указатель на переменную, куда будет записан описатель открытого раздела реестра. Открытый раздел необходимо закрывать функцией RegCloseKey, когда он больше не нужен.

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

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

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

Замечания

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

RegCreateKeyEx

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

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

Параметры

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

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

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

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

Замечания

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

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

RegCloseKey

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

Код FreeBASIC
Declare Function RegCloseKey(ByVal hKey As HKEY)As LONG

Параметры

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

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

Если описатель успешно освобождён, то возвращается ERROR_SUCCESS.

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

RegQueryInfoKey

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

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

Параметры

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

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

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

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

RegQueryValueEx

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

Код FreeBASIC
Declare Function RegQueryValueEx Alias "RegQueryValueExW"( _
&t;ByVal hKey As HKEY, _
&t;ByVal lpValueName As LPCWSTR, _
&t;ByVal lpReserved As LPDWORD, _
&t;ByVal lpType As LPDWORD, _
&t;ByVal lpData As LPBYTE, _
&t;ByVal lpcbData As LPDWORD) _
As LONG

Параметры

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

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

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

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

Замечания

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

RegSetValueEx

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

Код FreeBASIC
Declare Function RegSetValueEx Alias "RegSetValueExW"( _
&t;ByVal hKey As HKEY, _
&t;ByVal lpValueName As LPCWSTR, _
&t;ByVal Reserved As DWORD, _
&t;ByVal dwType As DWORD, _
&t;ByVal lpData As Const UBYTE Ptr, _
&t;ByVal cbData As DWORD) _
As LONG

Параметры

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

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

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

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

Замечания

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

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

RegEnumKeyEx

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

Код FreeBASIC
Declare Function RegEnumKeyEx Alias "RegEnumKeyExW"( _
&t;ByVal hKey As HKEY, _
&t;ByVal dwIndex As DWORD, _
&t;ByVal lpName As LPWSTR, _
&t;ByVal lpcchName As LPDWORD, _
&t;ByVal lpReserved As LPDWORD, _
&t;ByVal lpClass As LPWSTR, _
&t;ByVal lpcchClass As LPDWORD, _
&t;ByVal lpftLastWriteTime As PFILETIME) _
As LONG

Параметры

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

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

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

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

Замечания

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

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

RegEnumValue

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

Код FreeBASIC
Declare Function RegEnumValue Alias "RegEnumValueW"( _
&t;ByVal hKey As HKEY, _
&t;ByVal dwIndex As DWORD, _
&t;ByVal lpValueName As LPWSTR, _
&t;ByVal lpcchValueName As LPDWORD, _
&t;ByVal lpReserved As LPDWORD, _
&t;ByVal lpType As LPDWORD, _
&t;ByVal lpData As LPBYTE, _
&t;ByVal lpcbData As LPDWORD) _
As LONG

Параметры

hKey
Описатель открытого раздела. Раздел должен быть открыт с правами KEY_QUERY_VALUE.
dwIndex
Индекс подраздела. При первом вызове этот параметр должен быть равен нулю, при последующих увеличиваться на единицу.
lpValueName
Указатель на строку‐буфер, куда будет записано имя параметра.
lpcchValueName
Указатель на переменную, где хранится длина строки‐буфера имени параметра в символах включая нулевой. Если функция выполнится успешно, то сюда будет записана длина имени параметра без учёта нулевого символа.
lpReserved
Зарезервировано. Должно быть 0.
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

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

Код FreeBASIC
Declare Function RegNotifyChangeKeyValue( _
&t;ByVal hKey As HKEY, _
&t;ByVal bWatchSubtree As WINBOOL, _
&t;ByVal dwNotifyFilter As DWORD, _
&t;ByVal hEvent As HANDLE, _
&t;ByVal fAsynchronous As WINBOOL) _
As LONG

Параметры

hKey
Описатель открытого раздела. Раздел должен быть открыт с правами KEY_NOTIFY.
bWatchSubtree
Если этот параметр равен True, то функция будет следить за изменениями в подразделах, если False то только в текущем разделе.
dwNotifyFilter
Указывает, о каких изменениях следуем уведомлять приложение. Может быть комбинацией из следующи значений:
  • REG_NOTIFY_CHANGE_NAME — уведомление о добавлении или удалении подраздела;
  • REG_NOTIFY_CHANGE_ATTRIBUTES — уведомление об изменении атрибутов раздела, например, дескриптора защиты;
  • REG_NOTIFY_CHANGE_LAST_SET — уведомление об добавлении, удалении, изменении значения параметра;
  • REG_NOTIFY_CHANGE_SECURITY — уведомление об изменении дескриптора защиты.
hEvent
Описатель объекта ядра «событие». Если fAsynchronous установлен в True, то функция возвращает значение немедленно и будет отправлять уведомления через указанное событие. Если fAsynchronous равно False, то hEvent игнорируется.
fAsynchronous
Если установлен в True, то функция возвращает значение немедленно и будет отправлять уведомления через указанное событие, в этом случае hEvent должен быть действительным объектом ядра «событие». Если fAsynchronous равно False, то hEvent игнорируется.

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

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

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

Замечания

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

Примеры

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

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

Код FreeBASIC
#define unicode
#include once "windows.bi"

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

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

&t;' Открыть раздел реестра в профиле текущего пользователя
&t;Dim hr As Long = RegCreateKeyEx(HKEY_CURRENT_USER, @RegSection, 0, 0, 0, KEY_SET_VALUE, NULL, @reg, @lpdwDisposition)

&t;If hr <> ERROR_SUCCESS Then
&t;&t;End(1)
&t;End If

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

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

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

&t;RegCloseKey(reg)
End Scope

' Чтение параметров
Scope
&t;Dim reg As HKEY = Any
&t;Dim lpdwDisposition As DWORD = Any
&t;Dim hr As Long = RegCreateKeyEx(HKEY_CURRENT_USER, @RegSection, 0, 0, 0, KEY_QUERY_VALUE, NULL, @reg, @lpdwDisposition)

&t;If hr <> ERROR_SUCCESS Then
&t;&t;End(1)
&t;End If

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

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

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

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

&t;RegCloseKey(reg)
End Scope

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

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

Код FreeBASIC
#define unicode
#include once "windows.bi"

Const RegSection = "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
&t;End(1)
End If

Dim strClassName As WString * 512 = 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, @ClassNameLength, 0, @SubKeysCount, @MaxSubKeyLength, @MaxClassNameLength, @ValuesCount, @MaxValueNameLength, @MaxValueDataLength, NULL, @LastWriteTime)
If hr <> ERROR_SUCCESS Then
&t;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 WString Ptr = Allocate((SizeOf(WString) + 1) * MaxSubKeyLength)

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

Deallocate(SubKeyName)
RegCloseKey(reg)

Поделись ссылочкой в социальных сетях