KnigaRead.com/
KnigaRead.com » Компьютеры и Интернет » Программирование » Джонсон Харт - Системное программирование в среде Windows

Джонсон Харт - Системное программирование в среде Windows

На нашем сайте KnigaRead.com Вы можете абсолютно бесплатно читать книгу онлайн Джонсон Харт, "Системное программирование в среде Windows" бесплатно, без регистрации.
Перейти на страницу:

lpClass — указатель на строку, содержащую имя класса, или объектный тип, раздела, описывающее данные, представляемые разделом. Одними из многочисленных возможных значений являются REG_SZ (строка, завершающаяся нулевым символом) и REG_DWORD (двойное слово).

Параметр dwOptions может иметь значение 0 или одно из двух взаимоисключающих значений — REG_OPTION_VOLATILE или REG_OPTION_NON_VOLATILE. Постоянно хранимая (nonvolatile) информация системного реестра сохраняется в файле на диске и не теряется после перезапуска системы. При этом временные (volatile) разделы системного реестра, хранящиеся в оперативной памяти, не будут восстановлены. 

Параметр samDesired имеет тот же смысл, что и в случае функции RegOpenKeyEx.

Параметр lpSecurityAttributes может принимать значение NULL или указывать атрибуты защиты. Опции прав доступа к разделу могут выбираться из того же набора значений, что и в случае параметра samDesired.

lpdwDisposition — указатель на переменную типа DWORD, значение которой говорит о том, существовал ли раздел ранее (REG_OPENED_EXISTING_KEY) или он только создается (REG_CREATED_NEW_KEY).

Для удаления раздела используется функция RegDeleteKey. Двумя ее параметрами являются дескриптор открытого раздела и имя подраздела.

Управление значениями

Для перечисления значений параметров открытого раздела реестра используется функция RegEnumValue. Значение параметра dwIndex должно устанавливаться равным 0 при первом вызове функции и увеличиваться на единицу при каждом последующем вызове. После возврата из функции вы получаете строку, содержащую имя перечисляемого параметра, а также размер данных. Кроме того, вы получаете значение перечисляемого параметра и его тип. 

LONG RegEnumValue(HKEY hKey, DWORD dwIndex, LPTSTR lpValueName, LPDWORD lpcbValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData) 

Фактическое значение параметра возвращается в буфере, на который указывает указатель lpData. Размер результата содержится в переменной, на которую указывает указатель lpcbData. Тип данных, содержащийся в переменной, на которую указывает указатель lpType, может быть самым различным, включая REG_BINARY, REG_DWORD, REG_SZ (строка) и REG_EXPAND_SZ (расширяемая строка с параметрами, которые заменяются переменными окружения). Полный список типов данных системного реестра можно найти в оперативной справочной системе.

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

Функция RegQueryValueEx ведет себя аналогичным образом, за исключением того, что требует указания имени перечисляемого параметра, а не его индекса. Эту функцию можно использовать в тех случаях, когда известны имена параметров. Если же имена параметров неизвестны, следует использовать функцию RegEnumValueEx.

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

LONG RegSetValueEx(HKEY hKey, LPCTSTR lpValueName, DWORD Reserved, DWORD dwType, CONST BYTE * lpData, CONST cbData) 

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

Пример: вывод списка разделов и содержимого реестра

Программа lsReq (программа 3.4), является видоизменением lsW (программа 3.2, предназначенная для вывода списка файлов и каталогов) и обрабатывает не каталоги и файлы, а разделы и пары "имя-значение" системного реестра.

Программа 3.4. lsReq: вывод списка разделов и содержимого системного реестра

/* Глава 3. lsReg: Команда вывода содержимого реестра. Адаптированная версия программы 3.2. */

/* lsReg [параметры] подраздел */

#include "EvryThng.h"

BOOL TraverseRegistry(HKEY, LPTSTR, LPTSTR, LPBOOL);

BOOL DisplayPair(LPTSTR, DWORD, LPBYTE, DWORD, LPBOOL);

BOOL DisplaySubKey (LPTSTR, LPTSTR, PFILETIME, LPBOOL);


int _tmain(int argc, LPTSTR argv[]) {

 BOOL Flags[2], ok = TRUE;

 TCHAR KeyName[MAX_PATH + 1];

 LPTSTR pScan;

 DWORD i, KeyIndex;

 HKEY hKey, hNextKey;

 /* Таблица предопределенных имен и дескрипторов разделов. */

 LPTSTR PreDefKeyNames[] = {

  _Т("HKEY_LOCAL_MACHINE"), _T("HKEY_CLASSES_ROOT"),

  _Т("HKEY CURRENT USER"), _T ("HKEY CURRENT CONFIG"), NULL

 };

 HKEY PreDefKeys[] = {

  HKEY_LOCAL_MACHINE, HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, HKEY_CURRENT_CONFIG

 };

 KeyIndex = Options(argc, argv, _T("Rl"), &Flags[0], &Flags[1], NULL);

 /* "Разобрать" шаблон поиска на "раздел" и "подраздел". */

 /* Воссоздать раздел. */

 pScan = argv[KeyIndex];

 for (i = 0; *pScan != _T('\') && *pScan != _T(''); pScan++, i++) KeyName [i] = *pScan;

 KeyName[i] = _T('');

 if (*pScan == _T('\')) pScan++;

 /* Преобразовать предопределенное имя раздела в соответствующий HKEY.*/

 for (i = 0; PreDefKeyNames [i] != NULL && _tcscmp(PreDefKeyNames[i], KeyName) != 0; i++);

 hKey = PreDefKeys[i];

 RegOpenKeyEx(hKey, pScan, 0, KEY_READ, &hNextKey);

 hKey = hNextKey;

 ok = TraverseRegistry(hKey, argv[KeyIndex], NULL, Flags);

 return ok ? 0 : 1;

}


BOOL TraverseRegistry(HKEY hKey, LPTSTR FullKeyName, LPTSTR SubKey, LPBOOL Flags)

/*Совершить обход разделов и подразделов реестра, если задан параметр –R.*/

{

 HKEY hSubK;

 BOOL Recursive = Flags[0];

 LONG Result;

 DWORD ValType, Index, NumSubKs, SubKNameLen, ValNameLen, ValLen;

 DWORD MaxSubKLen, NumVals, MaxValNameLen, MaxValLen;

 FILETIME LastWriteTime;

 LPTSTR SubKName, ValName;

 LPBYTE Val;

 TCHAR FullSubKName[MAX_PATH + 1];

 /* Открыть дескриптор раздела. */

 RegOpenKeyEx(hKey, SubKey, 0, KEY_READ, &hSubK);

 /* Определить максимальный размер информации относительно раздела и распределить память. */

 RegQueryInfoKey(hSubK, NULL, NULL, NULL, &NumSubKs, &MaxSubKLen, NULL, &NumVals, &MaxValNameLen, &MaxValLen, NULL, &LastWriteTime);

 SubKName = malloc (MaxSubKLen+1); /* Размер без учета завершающего нулевого символа. */

 ValName = malloc(MaxValNameLen+1); /* Учесть нулевой символ. */

 Val = malloc(MaxValLen); /* Размер в байтах. */

 /* Первый проход: пары "имя-значение". */

 for (Index = 0; Index < NumVals; Index++) {

  ValNameLen = MaxValNameLen + 1; /* Устанавливается каждый раз! */

  ValLen = MaxValLen + 1;

  RegEnumValue(hSubK, Index, ValName, &ValNameLen, NULL, &ValType, Val, &ValLen);

  DisplayPair(ValName, ValType, Val, ValLen, Flags);

 }

 /* Второй проход: подразделы. */

 for (Index = 0; Index < NumSubKs; Index++) {

  SubKNameLen = MaxSubKLen + 1;

  RegEnumKeyEx(hSubK, Index, SubKName, &SubKNameLen, NULL, NULL, NULL, &LastWriteTime);

  DisplaySubKey(FullKName, SubKName, &LastWriteTime, Flags);

  if (Recursive) {

   _stprintf(FullSubKName, _T("%s\%s"), FullKName, SubKName);

   TraverseRegistry(hSubK, FullSubKName, SubKName, Flags);

  }

 }

 _tprintf(_T("n"));

 free(SubKName);

 free(ValName);

 free(Val);

 RegCloseKey(hSubK);

 return TRUE;

}


BOOL DisplayPair(LPTSTR ValueName, DWORD ValueType, LPBYTE Value, DWORD ValueLen, LPBOOL Flags)

/* Функция, отображающая пары "имя-значение". */

{

 LPBYTE pV = Value;

 DWORD i;

 _tprintf(_T("nValue: %s = "), ValueName);

 switch (ValueType) {

 case REG_FULL_RESOURCE_DESCRIPTOR: /* 9: описание оборудования. */

 case REG_BINARY: /* 3: Любые двоичные данные. */

  for (i = 0; i < ValueLen; i++, pV++) _tprintf (_T (" %x"), *pV);

  break;

 case REG_DWORD: /* 4: 32-битовое число. */

  _tprintf(_T ("%x"), (DWORD)*Value);

  break;

 case REG_MULTI SZ: /*7: массив строк, завершающихся нулевым символом.*/

 case REG_SZ: /* 1: строка, завершающаяся нулевым символом. */

  _tprintf(_T("%s"), (LPTSTR)Value);

  break;

 /* … Несколько других типов … */

 }

 return TRUE;

}


BOOL DisplaySubKey(LPTSTR KeyName, LPTSTR SubKeyName, PFILETIME pLastWrite, LPBOOL Flags) {

 BOOL Long = Flags[1];

 SYSTEMTIME SysLastWrite;

 _tprintf(_T("nSubkey: %s"), KeyName);

 if (_tcslen(SubKeyName) > 0) _tprintf (_T ("\%s "), SubKeyName);

 if (Long) {

  FileTimeToSystemTime(pLastWrite, &SysLastWrite);

  _tprintf(_T("%02d/%02d/%04d %02d:%02d:%02d"), SysLastWrite.wMonth, SysLastWrite.wDay, SysLastWrite.wYear, SysLastWrite.wHour, SysLastWrite.wMinute, SysLastWrite.wSecond);

 }

 return TRUE;

}

Резюме

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

В последующих главах будут рассмотрены такие усовершенствованные методы ввода/вывода, как асинхронные операции ввода/вывода и отображение файлов. Этих средств будет достаточно для того, чтобы воспроизвести в Windows почти любой из обычных видов обработки файлов, доступных при использовании UNIX или библиотечных функций С.

Перейти на страницу:
Прокомментировать
Подтвердите что вы не робот:*