Program 3-2 (lsW, the file and directory listing program); it processes registry keys and name/value pairs rather than directories and files.
/* Chapter 3. lsReg: Registry list command. Adapted from Prog. 3-2. */ /* lsReg [options] SubKey */ #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; /* Tables of predefined key names and keys. */ LPTSTR PreDefKeyNames [] = { _T ("HKEY_LOCAL_MACHINE"), _T ("HKEY_CLASSES_ROOT"), _T ("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); /* "Parse" the search pattern into "key" and "subkey". */ /* Build the key. */ pScan = argv [KeyIndex]; for (i = 0; *pScan != _T ('\\') && *pScan != _T ('\0'); pScan++, i++) KeyName [i] = *pScan; KeyName [i] = _T ('\0'); if (*pScan == _T ('\\')) pScan++; /* Translate predefined key name to an 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) /* Traverse registry key and subkeys if the -R option is set. */ { 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]; /* Open up the key handle. */ RegOpenKeyEx (hKey, SubKey, 0, KEY_READ, &hSubK); /* Find max size info regarding the key and allocate storage. */ RegQueryInfoKey (hSubK, NULL, NULL, NULL, &NumSubKs, &MaxSubKLen, NULL, &NumVals, &MaxValNameLen, &MaxValLen, NULL, &LastWriteTime); SubKName = malloc (MaxSubKLen+1); /* Size w/o null. */ ValName = malloc (MaxValNameLen+1); /* Allow for null. */ Val = malloc (MaxValLen); /* Size in bytes. */ /* First pass for name/value pairs. */ for (Index = 0; Index < NumVals; Index++) { ValNameLen = MaxValNameLen + 1; /* Set each time! */ ValLen = MaxValLen + 1; RegEnumValue (hSubK, Index, ValName, &ValNameLen, NULL, &ValType, Val, &ValLen); DisplayPair (ValName, ValType, Val, ValLen, Flags); } /* Second pass for subkeys. */ 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) /* Function to display name/value pairs. */ { LPBYTE pV = Value; DWORD i; _tprintf (_T ("\nValue: %s = "), ValueName); switch (ValueType) { case REG_FULL_RESOURCE_DESCRIPTOR: /* 9: hardware description. */ case REG_BINARY: /* 3: Binary data in any form. */ for (i = 0; i < ValueLen; i++, pV++) _tprintf (_T (" %x"), *pV); break; case REG_DWORD: /* 4: A 32-bit number. */ _tprintf (_T ("%x"), (DWORD)*Value); break; case REG_MULTI_SZ: /* 7: Array of null-terminated strings. */ case REG_SZ: /* 1: A null-terminated string. */ _tprintf (_T ("%s"), (LPTSTR) Value); break; /* ... Several other types ... */ } 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; }