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 или библиотечных функций С.
В приложении Б приведены сравнительные таблицы функций Windows, UNIX и библиотеки С, в которых наглядно показано, в чем указанные группы функций соответствуют друг другу, а в чем заметно отличаются.
Глава 4 рассказывает о том, как упростить обработку ошибок и исключений, и распространяет применение функции ReportError на случаи обработки любых исключительных ситуаций.
Дополнительная литература
Для получения более подробной информации относительно программирования и использования системного реестра Windows, обратитесь к книге [17].
3.1. Используя функции GetDiskFreeSpace и GetDiskFreeSpaceEx, определите, насколько разреженным оказывается файловое пространство, распределяемое различными версиями операционной системы Windows. Например, создайте новый файл, установите для указателя файла большое значение, задайте размер файла и исследуйте наличие свободного пространства на жестком диске при помощи функции GetDiskFreeSpace. Эту же функцию Windows можно использовать для определения того, чтобы определить, каким образом сконфигурирован диск в терминах секторов и кластеров. Определите, инициализируется ли выделенное для вновь созданного файла дисковое пространство. Решение в виде исходного текста функции FreeSpace.с доступно на Web-сайте книги. Сравните результаты, полученные для столь различных систем, как Windows NT и Windows 9x. Представляет интерес также исследование вопроса о том, как сделать файл разреженным.
Читать дальше