|
|
/*
regback.c - registry backup program
this program allows the user to back up active registry hives, while the system is running.
basic structure:
DoFullBackup ennumerate entries in HiveList, computes which ones to save and where, and calls DoSpecificBackup for each.
Three argument case of app is just a call to DoSpecificBackup.
*/
#include "regutil.h"
#define MACH_NAME L"machine"
#define USERS_NAME L"users"
BOOLEAN DumpUserHive; PWSTR DirectoryPath; PWSTR UserHiveFileName; PWSTR HivePath; HKEY HiveRoot; PWSTR HiveName;
LONG DoFullBackup( PWSTR DirectoryPath, PWSTR UserHiveFileName );
LONG DoSpecificBackup( PWSTR HivePath, HKEY HiveRoot, PWSTR HiveName );
BOOL CtrlCHandler( IN ULONG CtrlType ) { RTDisconnectFromRegistry( &RegistryContext ); return FALSE; }
int __cdecl main( int argc, char *argv[] ) { char *s; LONG Error; PWSTR w;
if (!RTEnableBackupRestorePrivilege()) { FatalError( "Unable to enable backup/restore priviledge.", 0, 0 ); }
InitCommonCode( CtrlCHandler, "REGBACK", "directoryPath [-u | -U outputFile]", "directoryPath specifies where to save the output files.\n" "\n" "-u specifies to dump the logged on user's profile. Default name is\n" " username.dat User -U with a file name to save it under a different name.\n" "\n" "outputFile specifies the file name to use for the user profile\n" "\n" "If the -m switch is specified to backup the registry of a remote machine\n" " then the directoryPath is relative to that machine.\n" );
DirectoryPath = NULL; UserHiveFileName = NULL; HivePath = NULL; HiveRoot = NULL; HiveName = NULL; while (--argc) { s = *++argv; if (*s == '-' || *s == '/') { while (*++s) { switch( tolower( *s ) ) { case 'u': DumpUserHive = TRUE; if (*s == 'U') { if (!--argc) { Usage( "Missing argument to -U switch", 0 ); }
UserHiveFileName = GetArgAsUnicode( *++argv ); }
break;
default: CommonSwitchProcessing( &argc, &argv, *s ); break; } } } else if (DirectoryPath == NULL) { HivePath = DirectoryPath = GetArgAsUnicode( s ); } else if (HivePath != NULL) { if (HiveRoot == NULL) { w = GetArgAsUnicode( s ); if (!_wcsicmp( w, MACH_NAME )) { HiveRoot = HKEY_LOCAL_MACHINE; } else if (!_wcsicmp( w, USERS_NAME )) { HiveRoot = HKEY_USERS; } else { Usage( "Invalid hive type specified (%ws)", (ULONG_PTR)w ); } } else if (HiveName == NULL) { HiveName = GetArgAsUnicode( s ); } else { Usage( "Too many arguments specified.", 0 ); } } else { Usage( NULL, 0 ); } }
if (DirectoryPath == NULL) { Usage( NULL, 0 ); }
Error = RTConnectToRegistry( MachineName, HiveFileName, HiveRootName, Win95Path, Win95UserPath, NULL, &RegistryContext ); if (Error != NO_ERROR) { FatalError( "Unable to access registry specifed (%u)", Error, 0 ); }
if (HiveRoot == NULL) { Error = DoFullBackup( DirectoryPath, UserHiveFileName ); } else { Error = DoSpecificBackup( HivePath, HiveRoot, HiveName ); }
RTDisconnectFromRegistry( &RegistryContext ); return Error; }
typedef BOOL (*PFNGETPROFILESDIRECTORYW)(LPWSTR lpProfile, LPDWORD dwSize);
LONG DoFullBackup( PWSTR DirectoryPath, PWSTR UserHiveFileName )
/*++
Routine Description:
Scan the hivelist, for each hive which has a file (i.e. not hardware) if the file is in the config dir (e.g. not some remote profile) call DoSpecificBackup to save the hive out.
Arguments:
DirectoryPath - specifies where to write the output files.
UserHiveFileName - optional parameter that specifies the name of the file to use when saving the user profile. If NULL, then username.dat is used.
Return Value:
0 for success, otherwise, non-zero error code.
--*/ { PWSTR w; LONG Error; HKEY HiveListKey; PWSTR KeyName; PWSTR FileName; PWSTR Name; DWORD ValueIndex; DWORD ValueType; DWORD ValueNameLength; DWORD ValueDataLength; WCHAR ConfigPath[ MAX_PATH ]; WCHAR ProfilePath[ MAX_PATH ]; WCHAR MyHiveName[ MAX_PATH ]; WCHAR MyHivePath[ MAX_PATH ]; WCHAR FilePath[ MAX_PATH ]; DWORD dwSize; HANDLE hInstDll; PFNGETPROFILESDIRECTORYW pfnGetProfilesDirectory;
hInstDll = LoadLibrary (TEXT("userenv.dll"));
if (!hInstDll) { return (GetLastError()); }
pfnGetProfilesDirectory = (PFNGETPROFILESDIRECTORYW)GetProcAddress (hInstDll, "GetProfilesDirectoryW");
if (!pfnGetProfilesDirectory) { FreeLibrary (hInstDll); return (GetLastError()); }
dwSize = MAX_PATH; if (!pfnGetProfilesDirectory(ProfilePath, &dwSize)) { FreeLibrary (hInstDll); return (GetLastError()); }
FreeLibrary (hInstDll);
//
// get handle to hivelist key
//
KeyName = L"HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Control\\Hivelist"; Error = RTOpenKey( &RegistryContext, NULL, KeyName, MAXIMUM_ALLOWED, 0, &HiveListKey );
if (Error != NO_ERROR) { FatalError( "Unable to open key '%ws' (%u)\n", (ULONG_PTR)KeyName, (ULONG)Error ); return Error; }
//
// get path data for system hive, which will allow us to compute
// path name to config dir in form that hivelist uses.
// (an NT internal form of path) this is NOT the way the path to
// the config directory should generally be computed.
//
ValueDataLength = sizeof( ConfigPath ); Error = RTQueryValueKey( &RegistryContext, HiveListKey, L"\\Registry\\Machine\\System", &ValueType, &ValueDataLength, ConfigPath ); if (Error != NO_ERROR) { FatalError( "Unable to query 'SYSTEM' hive path.", 0, Error ); } w = wcsrchr( ConfigPath, L'\\' ); if (w) { *w = UNICODE_NULL; }
//
// ennumerate entries in hivelist. for each entry, find it's hive file
// path. if it's file path matches ConfigPath, then save it.
// else, print a message telling the user that it must be saved
// manually, unless the file name is of the form ....\username\ntuser.dat
// in which case save it as username.dat
//
for (ValueIndex = 0; TRUE; ValueIndex++) { ValueType = REG_NONE; ValueNameLength = sizeof( MyHiveName ) / sizeof( WCHAR ); ValueDataLength = sizeof( MyHivePath ); Error = RTEnumerateValueKey( &RegistryContext, HiveListKey, ValueIndex, &ValueType, &ValueNameLength, MyHiveName, &ValueDataLength, MyHivePath ); if (Error == ERROR_NO_MORE_ITEMS) { break; } else if (Error != NO_ERROR) { return Error; }
if (ValueType == REG_SZ && ValueDataLength > sizeof( UNICODE_NULL )) { //
// there's a file, compute it's path, hive branch, etc
//
if (w = wcsrchr( MyHivePath, L'\\' )) { *w++ = UNICODE_NULL; } FileName = w;
if (w = wcsrchr( MyHiveName, L'\\' )) { *w++ = UNICODE_NULL; } Name = w;
HiveRoot = NULL; if (w = wcsrchr( MyHiveName, L'\\' )) { w += 1; if (!_wcsicmp( w, L"MACHINE" )) { HiveRoot = HKEY_LOCAL_MACHINE; } else if (!_wcsicmp( w, L"USER" )) { HiveRoot = HKEY_USERS; } else { Error = ERROR_PATH_NOT_FOUND; } }
if (FileName != NULL && Name != NULL && HiveRoot != NULL) { if (!wcscmp( ConfigPath, MyHivePath )) { //
// hive's file is in config dir, we can back it up
// without fear of collision
//
swprintf( FilePath, L"%s\\%s", DirectoryPath, FileName ); Error = DoSpecificBackup( FilePath, HiveRoot, Name ); } else if (DumpUserHive && !_wcsnicmp( ProfilePath, MyHivePath, wcslen( ProfilePath ) )) { //
// hive's file is in profile dir, we can back it up
// without fear of collision if we use username.dat
// for the file name.
//
if (UserHiveFileName != NULL) { FileName = UserHiveFileName; } else { FileName = wcsrchr(MyHivePath, '\\') + 1; } swprintf( FilePath, L"%s\\%s.dat", DirectoryPath, FileName );
printf( "%ws %ws %ws\n", FilePath, HiveRoot == HKEY_LOCAL_MACHINE ? MACH_NAME : USERS_NAME, Name ); Error = DoSpecificBackup( FilePath, HiveRoot, Name ); } else { printf( "\n***Hive = '%ws'\\'%ws'\nStored in file '%ws'\\'%ws'\n", MyHiveName, Name, MyHivePath, FileName ); printf( "Must be backed up manually\n" ); printf( "regback <filename you choose> %ws %ws\n\n", HiveRoot == HKEY_LOCAL_MACHINE ? MACH_NAME : USERS_NAME, Name ); } } } }
return Error; }
LONG DoSpecificBackup( PWSTR HivePath, HKEY HiveRoot, PWSTR HiveName ) /*
Do backup of one hive to one file. Any valid hive and any valid file will do. RegSaveKey does all the real work.
Arguments: HivePath - file name to pass directly to OS
HiveRoot - HKEY_LOCAL_MACHINE or HKEY_USERS
HiveName - 1st level subkey under machine or users */ { HKEY HiveKey; ULONG Disposition; LONG Error; char *Reason;
//
// print some status
//
printf( "saving %ws to %ws", HiveName, HivePath );
//
// get a handle to the hive. use special create call what will
// use privileges
//
Reason = "accessing"; Error = RTCreateKey( &RegistryContext, HiveRoot, HiveName, KEY_READ, REG_OPTION_BACKUP_RESTORE, NULL, &HiveKey, &Disposition ); if (Error == NO_ERROR) { Reason = "saving"; Error = RegSaveKey( HiveKey, HivePath, NULL ); RTCloseKey( &RegistryContext, HiveKey ); }
if (Error != NO_ERROR) { printf( " - error %s (%u)\n", Reason, Error ); } else { printf( "\n" ); } return Error; }
|