windows-nt/Source/XPSP1/NT/base/fs/utils/reg/save.c
2020-09-26 16:20:57 +08:00

471 lines
12 KiB
C

//-----------------------------------------------------------------------//
//
// 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"
//-----------------------------------------------------------------------//
//
// SaveHive()
//
//-----------------------------------------------------------------------//
LONG SaveHive(PAPPVARS pAppVars, UINT argc, TCHAR *argv[])
{
LONG nResult;
HKEY hKey;
//
// Parse the cmd-line
//
nResult = ParseSaveCmdLine(pAppVars, argc, argv);
if (nResult != ERROR_SUCCESS)
{
return nResult;
}
#ifndef REG_FOR_WIN2000 // ANSI version for Win98
// because RegLoadKey() failed on remote Win98,
// works local only on Win98, cancel SAVE for remote
if(pAppVars->bUseRemoteMachine)
return REG_STATUS_NONREMOTABLE;
#endif
//
// Connect to the Remote Machine - if applicable
//
nResult = RegConnectMachine(pAppVars);
if (nResult != ERROR_SUCCESS)
{
return nResult;
}
//
// Open the key
//
if ((nResult = RegOpenKeyEx(pAppVars->hRootKey,
pAppVars->szSubKey,
0,
KEY_READ,
&hKey)) == ERROR_SUCCESS)
{
//
// Acquire the necessary privilages and call the API
//
nResult = RegAdjustTokenPrivileges(pAppVars->szMachineName,
SE_BACKUP_NAME,
SE_PRIVILEGE_ENABLED);
if (nResult == ERROR_SUCCESS)
{
nResult = RegSaveKey(hKey, pAppVars->szValueName, NULL);
}
RegCloseKey(hKey);
}
#ifndef REG_FOR_WIN2000
// since the newly created file has the hidden attibute on win98,
// remove this hidden attribute (work for local machine only)
if (nResult == ERROR_SUCCESS)
SetFileAttributes(pAppVars->szValueName, FILE_ATTRIBUTE_ARCHIVE);
#endif
return nResult;
}
//-----------------------------------------------------------------------//
//
// RestoreHive()
//
//-----------------------------------------------------------------------//
LONG RestoreHive(PAPPVARS pAppVars, UINT argc, TCHAR *argv[])
{
LONG nResult;
HKEY hKey;
//
// Parse the cmd-line
//
nResult = ParseSaveCmdLine(pAppVars, argc, argv);
if (nResult != ERROR_SUCCESS)
{
return nResult;
}
#ifndef REG_FOR_WIN2000 // ANSI version for Win98
// because RegLoadKey() failed on remote Win98,
// works local only on Win98
if(pAppVars->bUseRemoteMachine)
return REG_STATUS_NONREMOTABLE;
#endif
//
// Connect to the Remote Machine(s) - if applicable
//
nResult = RegConnectMachine(pAppVars);
if (nResult != ERROR_SUCCESS)
{
return nResult;
}
//
// Open the Key
//
if ((nResult = RegOpenKeyEx(pAppVars->hRootKey,
pAppVars->szSubKey,
0,
KEY_ALL_ACCESS,
&hKey)) == ERROR_SUCCESS)
{
#ifdef REG_FOR_WIN2000 // works on Win2000(unicode) only, not Win98(ansi)
// Acquire the necessary privilages and call the API
nResult = RegAdjustTokenPrivileges(pAppVars->szMachineName,
SE_RESTORE_NAME,
SE_PRIVILEGE_ENABLED);
if (nResult == ERROR_SUCCESS)
{
nResult = RegRestoreKey(hKey, pAppVars->szValueName, 0);
}
RegCloseKey(hKey);
#else // works on Win98(ansi) only, not Win2000(unicode)
RegCloseKey(hKey);
nResult = RegRestoreKeyWin98(pAppVars->hRootKey,
pAppVars->szSubKey,
pAppVars->szValueName);
#endif
}
return nResult;
}
//-----------------------------------------------------------------------//
//
// LoadHive()
//
//-----------------------------------------------------------------------//
LONG LoadHive(PAPPVARS pAppVars, UINT argc, TCHAR *argv[])
{
LONG nResult;
//
// Parse the cmd-line
//
nResult = ParseSaveCmdLine(pAppVars, argc, argv);
if (nResult != ERROR_SUCCESS)
{
return nResult;
}
#ifndef REG_FOR_WIN2000 // ANSI version for Win98
// because RegLoadKey() failed on remote Win98,
// works local only on Win98
if(pAppVars->bUseRemoteMachine)
return REG_STATUS_NONREMOTABLE;
#endif
//
// Connect to the Remote Machine(s) - if applicable
//
nResult = RegConnectMachine(pAppVars);
if (nResult != ERROR_SUCCESS)
{
return nResult;
}
//
// Acquire the necessary privilages and call the API
//
nResult = RegAdjustTokenPrivileges(pAppVars->szMachineName,
SE_RESTORE_NAME,
SE_PRIVILEGE_ENABLED);
if (nResult == ERROR_SUCCESS)
{
nResult = RegLoadKey(pAppVars->hRootKey,
pAppVars->szSubKey,
pAppVars->szValueName);
}
return nResult;
}
//-----------------------------------------------------------------------//
//
// UnLoadHive()
//
//-----------------------------------------------------------------------//
LONG UnLoadHive(PAPPVARS pAppVars, UINT argc, TCHAR *argv[])
{
LONG nResult;
//
// Parse the cmd-line
//
nResult = ParseUnLoadCmdLine(pAppVars, argc, argv);
if (nResult != ERROR_SUCCESS)
{
return nResult;
}
#ifndef REG_FOR_WIN2000 // ANSI version for Win98
// because RegUnLoadKey() failed on remote Win98,
// works local only on Win98
if(pAppVars->bUseRemoteMachine)
return REG_STATUS_NONREMOTABLE;
#endif
//
// Connect to the Remote Machine(s) - if applicable
//
nResult = RegConnectMachine(pAppVars);
if (nResult != ERROR_SUCCESS)
{
return nResult;
}
//
// Acquire the necessary privilages and call the API
//
nResult = RegAdjustTokenPrivileges(pAppVars->szMachineName,
SE_RESTORE_NAME,
SE_PRIVILEGE_ENABLED);
if (nResult == ERROR_SUCCESS)
{
nResult = RegUnLoadKey(pAppVars->hRootKey, pAppVars->szSubKey);
}
return nResult;
}
//------------------------------------------------------------------------//
//
// ParseSaveCmdLine()
//
//------------------------------------------------------------------------//
REG_STATUS ParseSaveCmdLine(PAPPVARS pAppVars, UINT argc, TCHAR *argv[])
{
REG_STATUS nResult = ERROR_SUCCESS;
//
// Do we have a *valid* number of cmd-line params
//
if (argc < 4)
{
return REG_STATUS_TOFEWPARAMS;
}
else if (argc > 4)
{
return REG_STATUS_TOMANYPARAMS;
}
// Machine Name and Registry key
//
nResult = BreakDownKeyString(argv[2], pAppVars);
if(nResult != ERROR_SUCCESS)
return nResult;
//
// Get the FileName - using the szValueName string field to hold it
//
pAppVars->szValueName = (TCHAR*) calloc(_tcslen(argv[3]) + 1,
sizeof(TCHAR));
if (!pAppVars->szValueName) {
return ERROR_NOT_ENOUGH_MEMORY;
}
_tcscpy(pAppVars->szValueName, argv[3]);
return nResult;
}
//------------------------------------------------------------------------//
//
// ParseUnLoadCmdLine()
//
//------------------------------------------------------------------------//
REG_STATUS ParseUnLoadCmdLine(PAPPVARS pAppVars, UINT argc, TCHAR *argv[])
{
REG_STATUS nResult = ERROR_SUCCESS;
//
// Do we have a *valid* number of cmd-line params
//
if (argc < 3)
{
return REG_STATUS_TOFEWPARAMS;
}
else if (argc > 3)
{
return REG_STATUS_TOMANYPARAMS;
}
// Machine Name and Registry key
//
nResult = BreakDownKeyString(argv[2], pAppVars);
return nResult;
}
//------------------------------------------------------------------------//
//
// AdjustTokenPrivileges()
//
//------------------------------------------------------------------------//
LONG RegAdjustTokenPrivileges(TCHAR *szMachine,
TCHAR *szPrivilege,
LONG nAttribute)
{
// works on Win2000(unicode) only, not Win98(ansi)
#ifdef REG_FOR_WIN2000
HANDLE hToken;
TOKEN_PRIVILEGES tkp;
if(!OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
&hToken))
{
return GetLastError();
}
if(!LookupPrivilegeValue(szMachine,
szPrivilege,
&tkp.Privileges[0].Luid))
{
return GetLastError();
}
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Attributes = nAttribute;
if(!AdjustTokenPrivileges(hToken,
FALSE,
&tkp,
0,
(PTOKEN_PRIVILEGES) NULL,
NULL))
{
return GetLastError();
}
#endif
return ERROR_SUCCESS;
}
//-----------------------------------------------------------------------//
// RegRestoreKeyWin98() for Win98 only (ANSI version)
// because RegRestoreKey() does not work on Win98
//-----------------------------------------------------------------------//
LONG RegRestoreKeyWin98(HKEY hRootKey, // handle to a root key
TCHAR* szSubKey, // name of subkey
TCHAR* szFile) // hive filename
{
LONG nResult;
HKEY hKey;
HKEY hTempKey;
TCHAR szTempHive[50];
LONG nRetUnload;
// avoid key name conflict, reduce failed possibility
_tcscpy(szTempHive, _T("TEMP_HIVE_FOR_RESTORE_0000"));
if(_tcsicmp(szSubKey, szTempHive) == 0)
_tcscpy(szTempHive, _T("TEMP_HIVE_FOR_RESTORE_1111"));
nResult = RegOpenKeyEx(hRootKey,
szTempHive,
0,
KEY_READ,
&hTempKey);
if(nResult == ERROR_SUCCESS)
{
RegCloseKey(hTempKey);
_tcscpy(szTempHive, _T("TEMP_HIVE_FOR_RESTORE_RETRY_0000"));
}
// load hive file to szTempHive key
nResult = RegLoadKey(hRootKey,
szTempHive,
szFile);
if(nResult != ERROR_SUCCESS)
return nResult;
nResult = RecursiveDeleteKey(hRootKey,
szSubKey);
if(nResult == ERROR_SUCCESS)
{
// Create the Key
nResult = RegCreateKeyEx(hRootKey,
szSubKey,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hKey,
NULL);
if(nResult == ERROR_SUCCESS)
{
// Now open TempHive key
nResult = RegOpenKeyEx(hRootKey,
szTempHive,
0,
KEY_READ,
&hTempKey);
if (nResult == ERROR_SUCCESS)
{
// Recursively copy the entire hive
BOOL bOverWriteAll = TRUE;
nResult = CopyEnumerateKey(hTempKey,
szTempHive,
hKey,
szSubKey,
&bOverWriteAll,
TRUE);
RegCloseKey(hTempKey);
}
RegCloseKey(hKey);
}
}
// unload the temphive key
nRetUnload = RegUnLoadKey(hRootKey, szTempHive);
if(nResult == ERROR_SUCCESS)
nResult = nRetUnload;
return nResult;
}