//-----------------------------------------------------------------------// // // File: save.cpp // Created: March 1997 // By: Martin Holladay (a-martih) // Purpose: Registry Save Support for REG.CPP // Modification History: // Copied from Copy.cpp and modificd - May 1997 (a-martih) // Aug 1997 - MartinHo // Fixed bug which didn't allow you to specify a ROOT key. // Example REG SAVE HKLM\Software didn't work - but should have // April 1999 Zeyong Xu: re-design, revision -> version 2.0 // //------------------------------------------------------------------------// #include "stdafx.h" #include "reg.h" // // function prototypes // LONG RegAdjustTokenPrivileges( LPCWSTR pwszMachine, LPCWSTR pwszPrivilege, LONG lAttribute ); BOOL ParseSaveCmdLine( DWORD argc, LPCWSTR argv[], LPCWSTR pwszOption, PTREG_PARAMS pParams, BOOL* pbUsage ); BOOL ParseUnLoadCmdLine( DWORD argc, LPCWSTR argv[], PTREG_PARAMS pParams, BOOL* pbUsage ); // // implementation // //-----------------------------------------------------------------------// // // SaveHive() // //-----------------------------------------------------------------------// LONG SaveHive( DWORD argc, LPCWSTR argv[] ) { // local variables LONG lResult = 0; BOOL bResult = TRUE; HKEY hKey = NULL; BOOL bUsage = FALSE; TREG_PARAMS params; LPCWSTR pwszList = NULL; LPCWSTR pwszFormat = NULL; if ( argc == 0 || argv == NULL ) { SetLastError( ERROR_INVALID_PARAMETER ); ShowLastError( stderr ); return 1; } // initialize the global data structure InitGlobalData( REG_SAVE, ¶ms ); // // Parse the cmd-line // bResult = ParseSaveCmdLine( argc, argv, L"SAVE", ¶ms, &bUsage ); if( bResult == FALSE ) { ShowLastErrorEx( stderr, SLE_INTERNAL ); FreeGlobalData( ¶ms ); return 1; } // check whether we need to display the usage if ( bUsage == TRUE ) { Usage( REG_SAVE ); FreeGlobalData( ¶ms ); return 0; } // // Connect to the Remote Machine - if applicable // bResult = RegConnectMachine( ¶ms ); if( bResult == FALSE ) { SaveErrorMessage( -1 ); ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL ); FreeGlobalData( ¶ms ); return 1; } // // Open the key // lResult = RegOpenKeyEx( params.hRootKey, params.pwszSubKey, 0, KEY_READ, &hKey ); if( lResult == ERROR_SUCCESS ) { // // Acquire the necessary privilages and call the API // lResult = RegAdjustTokenPrivileges( params.pwszMachineName, SE_BACKUP_NAME, SE_PRIVILEGE_ENABLED); if( lResult == ERROR_SUCCESS ) { lResult = RegSaveKeyEx( hKey, params.pwszValueName, NULL, REG_NO_COMPRESSION ); if ( lResult == ERROR_ALREADY_EXISTS ) { // load the format strings pwszFormat = GetResString2( IDS_SAVE_OVERWRITE_CONFIRM, 0 ); pwszList = GetResString2( IDS_CONFIRM_CHOICE_LIST, 1 ); // ... do { lResult = Prompt( pwszFormat, params.pwszValueName, pwszList, params.bForce ); } while ( lResult > 2 ); if( lResult != 1 ) { lResult = ERROR_CANCELLED; } else { // since there are chances of getting access problems -- // instead of deleting the existing file, we will try to // save the data using temporary file name and then transfer // the contents to the orignal filename params.pwszValue = params.pwszValueName; params.pwszValueName = GetTemporaryFileName( params.pwszValueName ); if ( params.pwszValueName == NULL ) { lResult = GetLastError(); } else { // try to save lResult = RegSaveKey( hKey, params.pwszValueName, NULL ); // check the result of the operation if ( lResult == ERROR_SUCCESS ) { bResult = CopyFile( params.pwszValueName, params.pwszValue, FALSE ); if ( bResult == FALSE ) { lResult = GetLastError(); } } // ... DeleteFile( params.pwszValueName ); } } } else { switch( lResult ) { case ERROR_INVALID_PARAMETER: { lResult = ERROR_FILENAME_EXCED_RANGE; break; } default: break; } } } SafeCloseKey( &hKey ); } // display the result SaveErrorMessage( lResult ); if ( lResult == ERROR_SUCCESS || lResult == ERROR_CANCELLED ) { lResult = 0; ShowLastErrorEx( stdout, SLE_INTERNAL ); } else { lResult = 1; ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL ); } // return FreeGlobalData( ¶ms ); return lResult; } //-----------------------------------------------------------------------// // // RestoreHive() // //-----------------------------------------------------------------------// LONG RestoreHive( DWORD argc, LPCWSTR argv[] ) { // local variables LONG lResult = 0; BOOL bResult = FALSE; HKEY hKey = NULL; BOOL bUsage = FALSE; TREG_PARAMS params; if ( argc == 0 || argv == NULL ) { SetLastError( ERROR_INVALID_PARAMETER ); ShowLastError( stderr ); return 1; } // initialize the global data structure InitGlobalData( REG_RESTORE, ¶ms ); // // Parse the cmd-line // bResult = ParseSaveCmdLine( argc, argv, L"RESTORE", ¶ms, &bUsage ); if( bResult == FALSE ) { ShowLastErrorEx( stderr, SLE_INTERNAL ); FreeGlobalData( ¶ms ); return 1; } // check whether we need to display the usage if ( bUsage == TRUE ) { Usage( REG_RESTORE ); FreeGlobalData( ¶ms ); return 0; } // // Connect to the Remote Machine - if applicable // bResult = RegConnectMachine( ¶ms ); if( bResult == FALSE ) { SaveErrorMessage( -1 ); ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL ); FreeGlobalData( ¶ms ); return 1; } // // Open the key // lResult = RegOpenKeyEx( params.hRootKey, params.pwszSubKey, 0, KEY_ALL_ACCESS, &hKey ); if( lResult == ERROR_SUCCESS ) { // // Acquire the necessary privilages and call the API // lResult = RegAdjustTokenPrivileges( params.pwszMachineName, SE_RESTORE_NAME, SE_PRIVILEGE_ENABLED ); if( lResult == ERROR_SUCCESS ) { lResult = RegRestoreKey( hKey, params.pwszValueName, REG_FORCE_RESTORE ); // check the return error code switch( lResult ) { case ERROR_INVALID_PARAMETER: { lResult = ERROR_FILENAME_EXCED_RANGE; break; } default: break; } } SafeCloseKey( &hKey ); } // display the result SaveErrorMessage( lResult ); if ( lResult == ERROR_SUCCESS ) { ShowLastErrorEx( stdout, SLE_INTERNAL ); } else { ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL ); } // return FreeGlobalData( ¶ms ); return ((lResult == ERROR_SUCCESS) ? 0 : 1); } //-----------------------------------------------------------------------// // // LoadHive() // //-----------------------------------------------------------------------// LONG LoadHive( DWORD argc, LPCWSTR argv[] ) { // local variables LONG lResult = 0; BOOL bResult = FALSE; BOOL bUsage = FALSE; TREG_PARAMS params; if ( argc == 0 || argv == NULL ) { SetLastError( ERROR_INVALID_PARAMETER ); ShowLastError( stderr ); return 1; } // initialize the global data structure InitGlobalData( REG_LOAD, ¶ms ); // // Parse the cmd-line // bResult = ParseSaveCmdLine( argc, argv, L"LOAD", ¶ms, &bUsage ); if( bResult == FALSE ) { ShowLastErrorEx( stderr, SLE_INTERNAL ); FreeGlobalData( ¶ms ); return 1; } // check whether we need to display the usage if ( bUsage == TRUE ) { Usage( REG_LOAD ); FreeGlobalData( ¶ms ); return 0; } // // Connect to the Remote Machine - if applicable // bResult = RegConnectMachine( ¶ms ); if( bResult == FALSE ) { SaveErrorMessage( -1 ); ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL ); FreeGlobalData( ¶ms ); return 1; } // // Acquire the necessary privilages and call the API // lResult = RegAdjustTokenPrivileges( params.pwszMachineName, SE_RESTORE_NAME, SE_PRIVILEGE_ENABLED ); if( lResult == ERROR_SUCCESS ) { lResult = RegLoadKey( params.hRootKey, params.pwszSubKey, params.pwszValueName ); // check the return error code switch( lResult ) { case ERROR_INVALID_PARAMETER: { lResult = ERROR_FILENAME_EXCED_RANGE; break; } default: break; } } // display the result SaveErrorMessage( lResult ); if ( lResult == ERROR_SUCCESS ) { ShowLastErrorEx( stdout, SLE_INTERNAL ); } else { ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL ); } // return FreeGlobalData( ¶ms ); return ((lResult == ERROR_SUCCESS) ? 0 : 1); } //-----------------------------------------------------------------------// // // UnLoadHive() // //-----------------------------------------------------------------------// LONG UnLoadHive( DWORD argc, LPCWSTR argv[] ) { // local variables LONG lResult = 0; BOOL bResult = FALSE; BOOL bUsage = FALSE; TREG_PARAMS params; if ( argc == 0 || argv == NULL ) { SetLastError( ERROR_INVALID_PARAMETER ); ShowLastError( stderr ); return 1; } // initialize the global data structure InitGlobalData( REG_UNLOAD, ¶ms ); // // Parse the cmd-line // bResult = ParseUnLoadCmdLine( argc, argv, ¶ms, &bUsage ); if( bResult == FALSE ) { ShowLastErrorEx( stderr, SLE_INTERNAL ); FreeGlobalData( ¶ms ); return 1; } // check whether we need to display the usage if ( bUsage == TRUE ) { Usage( REG_UNLOAD ); FreeGlobalData( ¶ms ); return 0; } // // Connect to the Remote Machine(s) - if applicable // bResult = RegConnectMachine( ¶ms ); if( bResult == FALSE ) { SaveErrorMessage( -1 ); ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL ); FreeGlobalData( ¶ms ); return 1; } // // Acquire the necessary privilages and call the API // lResult = RegAdjustTokenPrivileges( params.pwszMachineName, SE_RESTORE_NAME, SE_PRIVILEGE_ENABLED ); if( lResult == ERROR_SUCCESS ) { lResult = RegUnLoadKey( params.hRootKey, params.pwszSubKey ); } // display the result SaveErrorMessage( lResult ); if ( lResult == ERROR_SUCCESS ) { ShowLastErrorEx( stdout, SLE_INTERNAL ); } else { ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL ); } // return FreeGlobalData( ¶ms ); return ((lResult == ERROR_SUCCESS) ? 0 : 1); } //------------------------------------------------------------------------// // // ParseSaveCmdLine() // //------------------------------------------------------------------------// BOOL ParseSaveCmdLine( DWORD argc, LPCWSTR argv[], LPCWSTR pwszOption, PTREG_PARAMS pParams, BOOL* pbUsage ) { // local variables DWORD dwLength = 0; BOOL bResult = FALSE; // check the input if ( argc == 0 || argv == NULL || pwszOption == NULL || pParams == NULL || pbUsage == NULL ) { SaveErrorMessage( ERROR_INVALID_PARAMETER ); return FALSE; } // check whether this function is being called for // valid operation or not if ( pParams->lOperation < 0 || pParams->lOperation >= REG_OPTIONS_COUNT ) { SaveErrorMessage( ERROR_INVALID_PARAMETER ); return FALSE; } // // Do we have a *valid* number of cmd-line params // if ( argc >= 3 && InString( argv[ 2 ], L"-?|/?|-h|/h", TRUE ) == TRUE ) { if ( argc == 3 ) { *pbUsage = TRUE; return TRUE; } else { SetLastError( (DWORD) MK_E_SYNTAX ); SetReason2( 1, ERROR_INVALID_SYNTAX_WITHOPT, g_wszOptions[ pParams->lOperation ] ); return FALSE; } } else if( (pParams->lOperation != REG_SAVE && argc != 4) || (pParams->lOperation == REG_SAVE && (argc < 4 || argc > 5)) ) { SetLastError( (DWORD) MK_E_SYNTAX ); SetReason2( 1, ERROR_INVALID_SYNTAX_WITHOPT, g_wszOptions[ pParams->lOperation ] ); return FALSE; } else if ( StringCompareEx( argv[ 1 ], pwszOption, TRUE, 0 ) != 0 ) { SaveErrorMessage( ERROR_INVALID_PARAMETER ); return FALSE; } // Machine Name and Registry key // bResult = BreakDownKeyString( argv[ 2 ], pParams ); if( bResult == FALSE ) { return FALSE; } // for "LOAD" subkey should be present if ( pParams->lOperation == REG_LOAD ) { if ( pParams->pwszSubKey == NULL || StringLength( pParams->pwszSubKey, 0 ) == 0 ) { SetLastError( (DWORD) MK_E_SYNTAX ); SetReason2( 1, ERROR_INVALID_SYNTAX_WITHOPT, g_wszOptions[ pParams->lOperation ] ); return FALSE; } } // // Get the FileName - using the szValueName string field to hold it // dwLength = StringLength( argv[ 3 ], 0 ) + 1; pParams->pwszValueName = (LPWSTR) AllocateMemory( dwLength * sizeof( WCHAR ) ); if( pParams->pwszValueName == NULL ) { SaveErrorMessage( ERROR_OUTOFMEMORY ); return FALSE; } // ... StringCopy( pParams->pwszValueName, argv[ 3 ], dwLength ); // validate the file name -- it should not be empty TrimString( pParams->pwszValueName, TRIM_ALL ); if ( StringLength( pParams->pwszValueName, 0 ) == 0 ) { SetLastError( (DWORD) MK_E_SYNTAX ); SetReason2( 1, ERROR_INVALID_SYNTAX_WITHOPT, g_wszOptions[ pParams->lOperation ] ); return FALSE; } // check if user specified overwrite flag or not -- this is only for REG SAVE if ( argc == 5 && pParams->lOperation == REG_SAVE ) { pParams->bForce = FALSE; if ( StringCompareEx( argv[ 4 ], L"/y", TRUE, 0 ) == 0 ) { pParams->bForce = TRUE; } else { SetLastError( (DWORD) MK_E_SYNTAX ); SetReason2( 1, ERROR_INVALID_SYNTAX_WITHOPT, g_wszOptions[ pParams->lOperation ] ); return FALSE; } } // return return TRUE; } //------------------------------------------------------------------------// // // ParseUnLoadCmdLine() // //------------------------------------------------------------------------// BOOL ParseUnLoadCmdLine( DWORD argc, LPCWSTR argv[], PTREG_PARAMS pParams, BOOL* pbUsage ) { // local variables BOOL bResult = FALSE; // check the input if ( argc == 0 || argv == NULL || pParams == NULL || pbUsage == NULL ) { SaveErrorMessage( ERROR_INVALID_PARAMETER ); return FALSE; } // check whether this function is being called for // valid operation or not if ( pParams->lOperation < 0 || pParams->lOperation >= REG_OPTIONS_COUNT ) { SaveErrorMessage( ERROR_INVALID_PARAMETER ); return FALSE; } // // Do we have a *valid* number of cmd-line params // if( argc != 3 ) { SetLastError( (DWORD) MK_E_SYNTAX ); SetReason2( 1, ERROR_INVALID_SYNTAX_WITHOPT, g_wszOptions[ REG_UNLOAD ] ); return FALSE; } else if ( InString( argv[ 2 ], L"-?|/?|-h|/h", TRUE ) == TRUE ) { *pbUsage = TRUE; return TRUE; } else if ( StringCompareEx( argv[ 1 ], L"UNLOAD", TRUE, 0 ) != 0 ) { SaveErrorMessage( ERROR_INVALID_PARAMETER ); return FALSE; } // Machine Name and Registry key // bResult = BreakDownKeyString( argv[ 2 ], pParams ); if( bResult == FALSE ) { return FALSE; } if ( pParams->pwszSubKey == NULL || StringLength( pParams->pwszSubKey, 0 ) == 0 ) { SetLastError( (DWORD) MK_E_SYNTAX ); SetReason2( 1, ERROR_INVALID_SYNTAX_WITHOPT, g_wszOptions[ REG_UNLOAD ] ); return FALSE; } // return return TRUE; } //------------------------------------------------------------------------// // // AdjustTokenPrivileges() // //------------------------------------------------------------------------// LONG RegAdjustTokenPrivileges( LPCWSTR pwszMachine, LPCWSTR pwszPrivilege, LONG lAttribute ) { // local variables BOOL bResult = FALSE; HANDLE hToken = NULL; TOKEN_PRIVILEGES tkp; bResult = OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken ); if( bResult == FALSE ) { return GetLastError(); } bResult = LookupPrivilegeValue( pwszMachine, pwszPrivilege, &tkp.Privileges[0].Luid ); if( bResult == FALSE ) { return GetLastError(); } tkp.PrivilegeCount = 1; tkp.Privileges[0].Attributes = lAttribute; bResult = AdjustTokenPrivileges( hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES) NULL, NULL ); if( bResult == FALSE ) { return GetLastError(); } return ERROR_SUCCESS; }