How to Back Up the Windows NT RegistryLast reviewed: December 16, 1996Article ID: Q128731 |
The information in this article applies to:
SUMMARYThis article shows by example how to back up portions of the Windows NT registry to be restored later.
MORE INFORMATIONThis is normally accomplished by enabling the SeBackupPrivilege and calling RegSaveKey. The operation can fail with ERROR_ACCESS_DENIED if the caller does not have access to portions of the key, such as the registry key HKEY_LOCAL_MACHINE\SECURITY. If you do not have access to the key, but have backup privilege, pass the REG_OPTION_BACKUP_RESTORE flag to RegCreateKeyEx in the dwOptions parameter. This has an effect similar to FILE_FLAG_BACKUP_SEMANTICS with CreateFile, allowing you to open the key for backup. The resultant key handle can be used in a subsequent call to RegSaveKey. To back up the registry from the root, it is necessary to enumerate the subkeys from the root, opening each subkey with RegCreateKeyEx and saving the subkey with RegSaveKey.
Sample CodeThe following sample source code saves the HKEY_LOCAL_MACHINE registry key, with each subkey saved to a filename matching the subkey name. The following function performs the save operation: LONG SaveRegistrySubKey( HKEY hKey, // handle of key to save LPTSTR szSubKey, // pointer to subkey name to save LPTSTR szSaveFileName // pointer to save path/filename )If the function succeeds, the return value is ERROR_SUCCESS. If the function fails, the return value is an error value.
/* Save HKEY_LOCAL_MACHINE registry key, each subkey saved to a file of * name subkey * * this allows us to get around security restrictions which prevent * the use of RegSaveKey() on the root key * * the optional target machine name is specified in argv[1] * * v1.21 * Scott Field (sfield) 01-Apr-1995 */ #define RTN_OK 0 #define RTN_USAGE 1 #define RTN_ERROR 13 #include <windows.h> #include <stdio.h> #include <stdlib.h>LONG SaveRegistrySubKey(HKEY hKey, LPTSTR szSubKey, LPTSTR szSaveFileName); void PERR(LPTSTR szAPI, DWORD dwLastError); int main(int argc, char *argv[]){ TOKEN_PRIVILEGES tp; HANDLE hToken; LUID luid; LONG rc; // contains error value returned by Regxxx() HKEY hKey; // handle to key we are interested in LPTSTR MachineName=NULL; // pointer to machine name DWORD dwSubKeyIndex=0; // index into key char szSubKey[_MAX_FNAME]; // this should be dynamic. // _MAX_FNAME is good because this // is what we happen to save the // subkey as DWORD dwSubKeyLength=_MAX_FNAME; // length of SubKey buffer /* if (argc != 2) // usage { fprintf(stderr,"Usage: %s [<MachineName>]\n", argv[0]); return RTN_USAGE; } */ // set MachineName == argv[1], if appropriate if (argc == 2) MachineName=argv[1]; // // enable backup privilege // if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken )) { PERR("OpenProcessToken", GetLastError() ); return RTN_ERROR; } if(!LookupPrivilegeValue(MachineName, SE_BACKUP_NAME, &luid)) { PERR("LookupPrivilegeValue", GetLastError() ); return RTN_ERROR; } tp.PrivilegeCount = 1; tp.Privileges[0].Luid = luid; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL ); if (GetLastError() != ERROR_SUCCESS) { PERR("AdjustTokenPrivileges", GetLastError() ); return RTN_ERROR; } // only connect if a machine name specified if (MachineName != NULL) { if((rc=RegConnectRegistry(MachineName, HKEY_LOCAL_MACHINE, &hKey)) != ERROR_SUCCESS) { PERR("RegConnectRegistry", rc); return RTN_ERROR; } } else hKey=HKEY_LOCAL_MACHINE; while((rc=RegEnumKeyEx( hKey, dwSubKeyIndex, szSubKey, &dwSubKeyLength, NULL, NULL, NULL, NULL) ) != ERROR_NO_MORE_ITEMS) { // are we done? if(rc == ERROR_SUCCESS) { LONG lRetVal; // return value from SaveRegistrySubKey#ifdef DEBUG fprintf(stdout,"Saving %s\n", szSubKey);#endif
// save registry subkey szSubKey to filename szSubKey if( (lRetVal=SaveRegistrySubKey(hKey, szSubKey, szSubKey) ) != ERROR_SUCCESS) { PERR("SaveRegistrySubKey", lRetVal); } // increment index into the key dwSubKeyIndex++; // reset buffer size dwSubKeyLength=_MAX_FNAME; // Continue the festivities continue; } else { // // note: we need to watch for ERROR_MORE_DATA // this indicates we need a bigger szSubKey buffer // PERR("RegEnumKeyEx", rc); return RTN_ERROR; } } // RegEnumKeyEx // close registry key we have been working with RegCloseKey(hKey); // Revoke all privileges this process holds (including backup) AdjustTokenPrivileges( hToken, TRUE, NULL, 0, NULL, NULL); // close handle to process token CloseHandle(hToken); return RTN_OK;} LONG SaveRegistrySubKey( HKEY hKey, // handle of key to save LPTSTR szSubKey, // pointer to subkey name to save LPTSTR szSaveFileName // pointer to save path/filename ){ HKEY hKeyToSave; // Handle of subkey to save LONG rc; // result code from RegXxx DWORD dwDisposition; if((rc=RegCreateKeyEx(hKey, szSubKey, // Name of subkey to open 0, NULL, REG_OPTION_BACKUP_RESTORE, // in winnt.h KEY_QUERY_VALUE, // minimal access NULL, &hKeyToSave, &dwDisposition) ) == ERROR_SUCCESS) { // Save registry subkey. If the registry is remote, files will // be saved on the remote machine rc=RegSaveKey(hKeyToSave, szSaveFileName, NULL); // close registry key we just tried to save RegCloseKey(hKeyToSave); } // return the last registry result code return rc;}
void PERR( LPTSTR szAPI, // pointer to failed API name DWORD dwLastError // last error value associated with API ){ LPTSTR MessageBuffer; DWORD dwBufferLength; // // TODO get this fprintf out of here! // fprintf(stderr,"%s error! (rc=%lu)\n", szAPI, dwLastError); if(dwBufferLength=FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwLastError, LANG_NEUTRAL, (LPTSTR) &MessageBuffer, 0, NULL)) { DWORD dwBytesWritten; // // Output message string on stderr // WriteFile(GetStdHandle(STD_ERROR_HANDLE), MessageBuffer, dwBufferLength, &dwBytesWritten, NULL); // // free the buffer allocated by the system // LocalFree(MessageBuffer); }}
|
KBCategory: kbprg kbcode
© 1998 Microsoft Corporation. All rights reserved. Terms of Use. |