Джонсон Харт - Системное программирование в среде Windows
Примечание
Программирование реестра обсуждается в данной главе по той причине, что решаемая при этом задача весьма напоминает обработку файлов, а также потому, что оно играет важную роль в некоторых, хотя и не во всех, приложениях. Соответствующий пример будет получен путем несложного изменения программы lsW. Вместе с тем, данный раздел вполне мог бы стать небольшой отдельной главой. Поэтому читатели, для которых программирование реестра не представляет непосредственного интереса, могут пропустить этот раздел, чтобы вернуться к нему впоследствии, если это окажется необходимым.
В парах "имя-значение" реестра хранится следующая информация:
• Номер версии операционной системы, номер сборки и информация о зарегистрированном пользователе.
• Аналогичная информация обо всех приложения, которые были надлежащим образом установлены в системе.
• Информация о типе процессоров в системе и их количестве, системной памяти и тому подобное.
• Специфическая для каждого отдельного пользователя системы информация, включая данные относительно основного каталога пользователя и предпочтительных пользовательских настройках приложений.
• Информация, необходимая для системы безопасности, включая имена учетных записей пользователей.
• Информация об установленных службах (глава 13).
• Список соответствий между расширениями имен файлов и ассоциированными с ними исполняемыми программами. Именно эти соответствия используются системой после того, как пользователь щелкнет на пиктограмме какого-либо файла. Например, щелчок на файле с расширением .doc может приводить к запуску текстового редактора Microsoft Word.
• Отображения сетевых адресов на имена, используемые локальным компьютером.
В операционной системе UNIX аналогичная информация хранится в каталоге /etc и файлах, находящихся в основном каталоге пользователя. В Windows 3.1 для этих целей использовались .INI-файлы. Реестр обеспечивает единообразное централизованное хранение всей информации подобного рода. Кроме того, используя средства защиты, описанные в главе 15, можно обеспечить безопасность реестра.
API управления реестром описывается ниже, однако подробное рассмотрение содержимого и смысла различных записей, образующих реестр, выходит за рамки данной книги. Тем не менее, общее представление о структуре и содержимом этого хранилища данных можно получить на рис. 3.1, на котором изображен типичный вид окна открытого редактора реестра.
Рис. 3.1. Окно редактора реестра
Справа на этом рисунке можно видеть специфическая информация, относящаяся к установленному на данном локальном компьютере процессору. В нижней левой части рисунка показаны различные разделы, содержащие информацию об установленном в локальной системе программном обеспечении. Обратите внимание, что каждый ключ обязательно имеет значение по умолчанию, которое указывается в списке самым первым, предшествуя любым другим парам "имя-значение".
Рассмотрение принципов реализации реестра, включая организацию хранения и извлечения хранящихся в реестре данных, выходит за рамки данной книги; для более глубокого изучения этих вопросов обратитесь к списку дополнительной литературы, приведенному в конце главы.
Ключи реестра
На рис. 3.1 показана аналогия между разделами реестра и каталогами файловой системы. Каждый раздел может содержать другие разделы или последовательности пар "имя-значение". В то время как доступ к файловой системе реализуется посредством указания путей доступа, доступ к реестру осуществляется через его разделы. Существует несколько предопределенных разделов, которые играют роль точек входа в реестр.
• HKEY_LOCAL_MACHINE. В этом разделе хранится информация об оборудовании локального компьютера и установленном на нем программном обеспечении. Информация об установленном программном обеспечении обычно создается в подразделах (subkeys) в виде: SOFTWAREНазваниеКомпанииНазваниеПродуктаВерсия.
• HKEY_USERS. В этом разделе хранится информация о настройке пользовательских конфигураций.
• HKEY_CURRENT_CONFIG. В этом разделе хранятся текущие настройки таких параметров, как разрешение дисплея или гарнитура шрифта.
• HKEY_CLASSES_ROOT. В этом разделе содержатся подчиненные записи, устанавливающие соответствие между именами файлов и классами, а также приложениями, используемыми оболочкой для доступа к объектам, имена которых имеют определенные расширения. В этот раздел также входят все подразделы, необходимые для функционирования модели компонентных объектов (Component Object Model — СОМ), разработанной компанией Microsoft.
• HKEY_CURRENT_USER. В этом разделе хранится информация, определяемая пользователем, в том числе информация о переменных среды, принтерах и предпочтительных для вошедшего в систему пользователя конфигурационных параметрах приложений.
Управление системным реестром
Функции управления реестром позволяют запрашивать и изменять данные, относящиеся к парам "имя-значение", а также создавать новые подразделы и новые пары "имя-значение". Как для указания существующих разделов, так и для создания новых используются дескрипторы типа HKEY.[17] Нужные значения необходимо вводить; тип значения можно выбрать из нескольких готовых вариантов, соответствующих, например, строкам, двойным словам или расширяемым (expandable) строкам, параметры которых могут быть заменены переменными окружения.
Управление подразделами реестра
Первая из рассматриваемых нами функций, RegOpenKeyEx, предназначена для открытия подразделов системного реестра. Начав с одного из предопределенных зарезервированных дескрипторов, вы можете получить дескриптор любого из его подразделов, совершая обход дерева разделов.
LONG RegOpenKeyEx(HKEY hKey, LPCTSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
ПараметрыhKey — указатель на текущий открытый раздел реестра или значение дескриптора одного из предопределенных зарезервированных разделов. pHkResult — указатель на переменную типа HKEY, получающую значение дескриптора вновь открываемого раздела.
lpSubKey — указатель на строку с именем подраздела. Именем подраздела может быть путь, например: MicrosoftWindowsNTCurrentVersion. Значению NULL соответствует открытие новой копии раздела для hKey. Значение параметра ulOptions должно быть равным 0.
samDesired — маска доступа, описывающая уровень защиты нового раздела. К числу возможных значений относятся значения KEY_ALL_ACCESS, KEY_WRITE, KEY_QUERY_VALUE и KEY_ENUMARATE_SUBKEYS.
В случае успешного завершения функции возвращается значение ERROR_SUCCESS. Возврат любого другого значения указывает на ошибку. Для закрытия дескриптора открытого раздела используется функция RegCloseKey, которая в качестве своего единственного параметра принимает дескриптор.
Для получения имен подразделов любого заданного раздела следует воспользоваться функцией RegEnumKeyEx.
Для получения пар "имя-значение" используются две взаимно дополняющих функции: RegEnumValue и RegQueryValueEx.[18] Функция RegSetValueEx сохраняет данные различного типа в поле значения открытого раздела реестра. Описания перечисленных функций, применение которых будет проиллюстрировано примером, содержатся в этом и следующем разделах книги.
Функция RegEnumKeyEx перечисляет подразделы открытого раздела системного реестра во многом аналогично тому, как функции FindFirstFile и FindNextFile перечисляют содержимое каталогов. Эта функция извлекает имя подраздела, строку с именем класса подраздела, а также дату и время последнего изменения.
LONG RegEnumValue(HKEY hKey, DWORD dwIndex, LPTSTR lpValueName, LPDWORD lpcbValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData)
Значение параметра dwIndex должно устанавливаться равным 0 при первом вызове функции и увеличиваться на единицу при каждом последующем вызове. Название раздела и его размер, а также строка с именем класса и ее размер, возвращаются обычным способом. В случае успешного завершения функция возвращает значение ERROR_SUCCESS, иначе — код ошибки.
Можно также создавать новые разделы, используя для этого функцию RegCreateKeyEx. Разделам системного реестра можно присваивать атрибуты защиты точно так же, как каталогам и файлам (глава 15).
LONG RegCreateKeyEx(HKEY hKey, LPCTSTR lpSubKey, DWORD Reserved, LPTSTR lpClass, DWORD dwOptions, REGSAM samDesired, LPSECURITY_ATTRIBUTES lpSecurityAttributes, PHKEY phkResult, LPDWORD lpdwDisposition)
ПараметрыlpSubKey — указатель на строку, содержащую имя нового подраздела, создаваемого в разделе, на который указывает дескриптор hKey.
lpClass — указатель на строку, содержащую имя класса, или объектный тип, раздела, описывающее данные, представляемые разделом. Одними из многочисленных возможных значений являются REG_SZ (строка, завершающаяся нулевым символом) и REG_DWORD (двойное слово).