438 lines
14 KiB
C
438 lines
14 KiB
C
#include "setupp.h"
|
||
#pragma hdrstop
|
||
|
||
|
||
#define SYSTEM_HIVE (LPWSTR)L"system"
|
||
#define SOFTWARE_HIVE (LPWSTR)L"software"
|
||
#define SECURITY_HIVE (LPWSTR)L"security"
|
||
#define SAM_HIVE (LPWSTR)L"sam"
|
||
#define DEFAULT_USER_HIVE (LPWSTR)L".default"
|
||
#define DEFAULT_USER_HIVE_FILE (LPWSTR)L"default"
|
||
#define NTUSER_HIVE_FILE (LPWSTR)L"ntuser.dat"
|
||
#define REPAIR_DIRECTORY (LPWSTR)L"\\repair"
|
||
#define SETUP_LOG_FILE (LPWSTR)L"setup.log"
|
||
|
||
#define NTUSER_COMPRESSED_FILE_NAME ( LPWSTR )L"ntuser.da_"
|
||
#define AUTOEXEC_NT_FILE_NAME ( LPWSTR )L"autoexec.nt"
|
||
#define CONFIG_NT_FILE_NAME ( LPWSTR )L"config.nt"
|
||
|
||
//
|
||
// Relative costs to perform various actions,
|
||
// to help make the gas gauge mean something.
|
||
//
|
||
#define COST_SAVE_HIVE 3
|
||
#define COST_COMPRESS_HIVE 20
|
||
#define COST_SAVE_VDM_FILE 1
|
||
|
||
|
||
//
|
||
// Structure used in the array of hives to be saved.
|
||
// This structure contains the predefined key that contains the hive
|
||
// to be saved, and the name of the hive root, and the name of the file
|
||
// where the hive should be saved.
|
||
//
|
||
|
||
typedef struct _HIVE_INFO {
|
||
HKEY PredefinedKey;
|
||
PWSTR HiveName;
|
||
PWSTR FileName;
|
||
} HIVE_INFO, *PHIVE_INFO;
|
||
|
||
|
||
//
|
||
// The array below contains the location and name of all hives that
|
||
// we need to save. When the utility is operating on the silent mode,
|
||
// (invoked from setup), then all hives will be saved. Otherwise, only
|
||
// system and software will be saved.
|
||
// For this reason, do not change the order of the hives in the array
|
||
// below. System and software must be the first elements of
|
||
// the array.
|
||
//
|
||
static
|
||
HIVE_INFO HiveList[] = {
|
||
{ HKEY_LOCAL_MACHINE, SYSTEM_HIVE, SYSTEM_HIVE },
|
||
{ HKEY_LOCAL_MACHINE, SOFTWARE_HIVE, SOFTWARE_HIVE },
|
||
{ HKEY_USERS, DEFAULT_USER_HIVE, DEFAULT_USER_HIVE_FILE },
|
||
{ HKEY_LOCAL_MACHINE, SECURITY_HIVE, SECURITY_HIVE },
|
||
{ HKEY_LOCAL_MACHINE, SAM_HIVE, SAM_HIVE }
|
||
};
|
||
|
||
static
|
||
PWSTR VdmFiles[] = {
|
||
AUTOEXEC_NT_FILE_NAME,
|
||
CONFIG_NT_FILE_NAME
|
||
};
|
||
|
||
|
||
DWORD
|
||
SaveOneHive(
|
||
IN LPWSTR DirectoryName,
|
||
IN LPWSTR HiveName,
|
||
IN HKEY hkey,
|
||
IN HWND hWnd,
|
||
IN OUT PDWORD GaugePosition,
|
||
IN DWORD GaugeDeltaUnit
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Save one registry hive. The way we will do this is to do a RegSaveKey
|
||
of the hive into a temporary localtion, and then call the LZ apis to
|
||
compress the file from that temporary location to the floppy.
|
||
|
||
LZ must have already been initialized via InitGloablBuffersEx()
|
||
BEFORE calling this routine.
|
||
|
||
Arguments:
|
||
|
||
DirectoryName - Full path of the directory where the hive will be saved.
|
||
|
||
HiveName - base name of the hive file to save. The file will end up
|
||
compressed on disk with the name <HiveName>._.
|
||
|
||
hkey - supplies handle to open key of root of hive to save.
|
||
|
||
GaugePosition - in input, supplies current position of the gas gauge.
|
||
On output, supplies new position of gas gauge.
|
||
|
||
GaugeDeltaUnit - supplies cost of one unit of activity.
|
||
|
||
Return Value:
|
||
|
||
DWORD - Return ERROR_SUCCESS if the hive was saved. Otherwise, it returns
|
||
an error code.
|
||
|
||
--*/
|
||
|
||
{
|
||
DWORD Status;
|
||
WCHAR SaveFilename[ MAX_PATH + 1 ];
|
||
WCHAR CompressPath[ MAX_PATH + 1 ];
|
||
CHAR SaveFilenameAnsi[ MAX_PATH + 1 ];
|
||
CHAR CompressPathAnsi[ MAX_PATH + 1 ];
|
||
LPWSTR TempName = ( LPWSTR )L"\\$$hive$$.tmp";
|
||
|
||
//
|
||
// Create the name of the file into which we will save the
|
||
// uncompressed hive.
|
||
//
|
||
|
||
wsprintf(SaveFilename,L"%ls\\%ls.",DirectoryName,HiveName);
|
||
wsprintfA(SaveFilenameAnsi,"%ls\\%ls.",DirectoryName,HiveName);
|
||
|
||
//
|
||
// Delete the file just in case, because RegSaveKey will fail if the file
|
||
// already exists.
|
||
//
|
||
SetFileAttributes(SaveFilename,FILE_ATTRIBUTE_NORMAL);
|
||
DeleteFile(SaveFilename);
|
||
|
||
//
|
||
// Save the registry hive into the temporary file.
|
||
//
|
||
Status = RegSaveKey(hkey,SaveFilename,NULL);
|
||
|
||
//
|
||
// Update the gas gauge.
|
||
//
|
||
*GaugePosition += GaugeDeltaUnit * COST_SAVE_HIVE;
|
||
SendMessage(
|
||
hWnd,
|
||
PBM_SETPOS,
|
||
*GaugePosition,
|
||
0L
|
||
);
|
||
|
||
//
|
||
// If the hive was saved successfully, then delete the old compressed
|
||
// one if it happens to be there.
|
||
//
|
||
|
||
if(Status == ERROR_SUCCESS) {
|
||
//
|
||
// Form the name of the file into which the saved hive file is
|
||
// to be compressed.
|
||
//
|
||
wsprintf(CompressPath,L"%ls\\%ls._",DirectoryName,HiveName);
|
||
wsprintfA(CompressPathAnsi,"%ls\\%ls._",DirectoryName,HiveName );
|
||
|
||
//
|
||
// Delete the destination file just in case.
|
||
//
|
||
SetFileAttributes(CompressPath,FILE_ATTRIBUTE_NORMAL);
|
||
DeleteFile(CompressPath);
|
||
}
|
||
|
||
return(Status);
|
||
}
|
||
|
||
VOID
|
||
SaveRepairInfo(
|
||
IN HWND hWnd,
|
||
IN ULONG StartAtPercent,
|
||
IN ULONG StopAtPercent
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine implements the thread that saves all system configuration
|
||
files into the repair directory. It first saves and compresses the
|
||
registry hives, and then it save the VDM configuration files (autoexec.nt
|
||
and config.nt).
|
||
If the application is running in the SilentMode (invoked by setup),
|
||
then system, software, default, security and sam hives will be saved
|
||
and compressed.
|
||
If the application was invoked by the user, then only system, software
|
||
and default will be saved.
|
||
|
||
This thread will send messages to the gas gauge dialog prcedure, so that
|
||
the gas gauge gets updated after each configuration file is saved.
|
||
This thread will also inform the user about errors that might have
|
||
occurred during the process of saving the configuration files.
|
||
|
||
Arguments:
|
||
|
||
hWnd - handle to progress gauge
|
||
|
||
StartAtPercent - Position where the progress window should start (0% to 100%).
|
||
|
||
StopAtPercent - Maximum position where the progress window can be moved to (0% to 100%).
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
However, the this routine will send a message to the dialog procedure
|
||
that created the thread, informing the outcome the operation.
|
||
|
||
--*/
|
||
|
||
{
|
||
DWORD i;
|
||
HKEY hkey;
|
||
BOOL ErrorOccurred;
|
||
CHAR SourceUserHivePathAnsi[ MAX_PATH + 1 ];
|
||
CHAR UncompressedUserHivePathAnsi[ MAX_PATH + 1 ];
|
||
CHAR CompressedUserHivePathAnsi[ MAX_PATH + 1 ];
|
||
WCHAR ProfilesDirectory[ MAX_PATH + 1 ];
|
||
WCHAR RepairDirectory[ MAX_PATH + 1 ];
|
||
WCHAR SystemDirectory[ MAX_PATH + 1 ];
|
||
WCHAR Source[ MAX_PATH + 1 ];
|
||
WCHAR Target[ MAX_PATH + 1 ];
|
||
DWORD GaugeDeltaUnit;
|
||
DWORD GaugeTotalCost;
|
||
DWORD GaugeRange;
|
||
DWORD GaugePosition;
|
||
DWORD NumberOfHivesToSave;
|
||
DWORD NumberOfUserHivesToSave;
|
||
DWORD NumberOfVdmFiles;
|
||
DWORD dwSize;
|
||
DWORD Error;
|
||
DWORD Status;
|
||
HANDLE Token;
|
||
BOOL b;
|
||
TOKEN_PRIVILEGES NewPrivileges;
|
||
LUID Luid;
|
||
|
||
|
||
Error = ERROR_SUCCESS;
|
||
|
||
ErrorOccurred = FALSE;
|
||
//
|
||
// Compute the cost of saving the hives and vdm files.
|
||
// For every hive we save, we have to save a key into a file and then
|
||
// compress the file. After each of these tasks is completed, we upgrade
|
||
// the gas gauge by the amount dicated by the COST_xxx values.
|
||
// The cost of saving the hives depends on the mode that the utility is
|
||
// running.
|
||
//
|
||
NumberOfHivesToSave = sizeof( HiveList ) / sizeof( HIVE_INFO );
|
||
|
||
NumberOfUserHivesToSave = 1;
|
||
NumberOfVdmFiles = sizeof( VdmFiles ) / sizeof( PWSTR );
|
||
|
||
GaugeTotalCost = (COST_SAVE_HIVE * NumberOfHivesToSave)
|
||
+ (COST_SAVE_VDM_FILE * NumberOfVdmFiles);
|
||
|
||
GaugeRange = (GaugeTotalCost*100/(StopAtPercent-StartAtPercent));
|
||
GaugeDeltaUnit = 1;
|
||
GaugePosition = GaugeRange*StartAtPercent/100;
|
||
SendMessage(hWnd, WMX_PROGRESSTICKS, GaugeTotalCost, 0);
|
||
SendMessage(hWnd,PBM_SETRANGE,0,MAKELPARAM(0,GaugeRange));
|
||
SendMessage(hWnd,PBM_SETPOS,GaugePosition,0);
|
||
|
||
//
|
||
// Enable BACKUP privilege
|
||
//
|
||
if(OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES,&Token)) {
|
||
|
||
if(LookupPrivilegeValue(NULL,SE_BACKUP_NAME,&Luid)) {
|
||
|
||
NewPrivileges.PrivilegeCount = 1;
|
||
NewPrivileges.Privileges[0].Luid = Luid;
|
||
NewPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
||
|
||
AdjustTokenPrivileges(Token,FALSE,&NewPrivileges,0,NULL,NULL);
|
||
}
|
||
}
|
||
|
||
Status = GetWindowsDirectory( RepairDirectory, sizeof( RepairDirectory ) / sizeof( WCHAR ) );
|
||
if( Status == 0) {
|
||
MYASSERT(FALSE);
|
||
return;
|
||
}
|
||
lstrcat( RepairDirectory, REPAIR_DIRECTORY );
|
||
|
||
dwSize = MAX_PATH + 1;
|
||
GetDefaultUserProfileDirectoryW (ProfilesDirectory, &dwSize);
|
||
|
||
GetSystemDirectory( SystemDirectory, sizeof( SystemDirectory ) / sizeof( WCHAR ) );
|
||
|
||
//
|
||
// Make sure that the repair directory already exists.
|
||
// If it doesn't exist, then create one.
|
||
//
|
||
if( CreateDirectory( RepairDirectory, NULL ) ||
|
||
( ( Error = GetLastError() ) == ERROR_ALREADY_EXISTS ) ||
|
||
( Error == ERROR_ACCESS_DENIED )
|
||
) {
|
||
//
|
||
// If the repair directory didn't exist and we were able to create it,
|
||
// or if the repair directory already exists, then save and compress
|
||
// the hives.
|
||
//
|
||
|
||
Error = ERROR_SUCCESS;
|
||
for( i=0; i < NumberOfHivesToSave; i++ ) {
|
||
//
|
||
// First open the root of the hive to be saved
|
||
//
|
||
Status = RegOpenKeyEx( HiveList[i].PredefinedKey,
|
||
HiveList[i].HiveName,
|
||
REG_OPTION_RESERVED,
|
||
READ_CONTROL,
|
||
&hkey );
|
||
|
||
//
|
||
// If unable to open the key, update the gas gauge to reflect
|
||
// that the operation on this hive was completed.
|
||
// Otherwise, save the hive. Note that Save hive will update
|
||
// the gas gauge, as it saves and compresses the hive.
|
||
//
|
||
if(Status != ERROR_SUCCESS) {
|
||
//
|
||
// If this is the first error while saving the hives,
|
||
// then save the error code, so that we can display the
|
||
// correct error message to the user.
|
||
//
|
||
if( Error == ERROR_SUCCESS ) {
|
||
Error = Status;
|
||
}
|
||
|
||
//
|
||
// Update the gas gauge
|
||
//
|
||
GaugePosition += GaugeDeltaUnit * (COST_SAVE_HIVE + COST_COMPRESS_HIVE);
|
||
SendMessage( hWnd,
|
||
PBM_SETPOS,
|
||
GaugePosition,
|
||
0L );
|
||
|
||
} else {
|
||
//
|
||
// Save and compress the hive.
|
||
// Note that the gas gauge will up be updated by SaveOneHive
|
||
// Note also that when we save the default user hive, we skip
|
||
// the first character of the
|
||
//
|
||
|
||
Status = SaveOneHive(RepairDirectory,
|
||
HiveList[i].FileName,
|
||
hkey,
|
||
hWnd,
|
||
&GaugePosition,
|
||
GaugeDeltaUnit );
|
||
//
|
||
// If this is the first error while saving the hives,
|
||
// then save the error code, so that we can display the
|
||
// correct error message to the user.
|
||
//
|
||
|
||
if( Error == ERROR_SUCCESS ) {
|
||
Error = Status;
|
||
}
|
||
|
||
RegCloseKey(hkey);
|
||
}
|
||
}
|
||
|
||
//
|
||
// Save the hive for the Default User
|
||
//
|
||
|
||
wsprintfA(SourceUserHivePathAnsi,"%ls\\%ls",ProfilesDirectory,NTUSER_HIVE_FILE);
|
||
wsprintfA(UncompressedUserHivePathAnsi,"%ls\\%ls",RepairDirectory,NTUSER_HIVE_FILE);
|
||
wsprintfA(CompressedUserHivePathAnsi, "%ls\\%ls",RepairDirectory,NTUSER_COMPRESSED_FILE_NAME);
|
||
|
||
|
||
Status = CopyFileA (
|
||
SourceUserHivePathAnsi,
|
||
UncompressedUserHivePathAnsi,
|
||
FALSE);
|
||
|
||
if(Status) {
|
||
//
|
||
// Delete the destination file just in case.
|
||
//
|
||
SetFileAttributesA(CompressedUserHivePathAnsi,FILE_ATTRIBUTE_NORMAL);
|
||
DeleteFileA(CompressedUserHivePathAnsi);
|
||
} else if(Error == ERROR_SUCCESS) {
|
||
//
|
||
// If this is the first error, remember it.
|
||
//
|
||
Error = GetLastError();
|
||
}
|
||
|
||
//
|
||
// Now that the hives are saved, save the vdm files
|
||
//
|
||
|
||
for( i = 0; i < NumberOfVdmFiles; i++ ) {
|
||
wsprintf(Source,L"%ls\\%ls",SystemDirectory,VdmFiles[i]);
|
||
wsprintf(Target,L"%ls\\%ls",RepairDirectory,VdmFiles[i]);
|
||
if( !CopyFile( Source, Target, FALSE ) ) {
|
||
Status = GetLastError();
|
||
if( Error != ERROR_SUCCESS ) {
|
||
Error = Status;
|
||
}
|
||
}
|
||
GaugePosition += GaugeDeltaUnit * COST_SAVE_VDM_FILE;
|
||
SendMessage( ( HWND )hWnd,
|
||
PBM_SETPOS,
|
||
GaugePosition,
|
||
0L );
|
||
|
||
}
|
||
}
|
||
|
||
if( Error != ERROR_SUCCESS ) {
|
||
SetupDebugPrint1( L"SETUP: SaveRepairInfo() failed. Error = %d", Error );
|
||
}
|
||
|
||
//
|
||
// Set security on all the files.
|
||
//
|
||
ApplySecurityToRepairInfo();
|
||
|
||
//
|
||
// At this point, the operation was completed (successfully, or not).
|
||
// So update the gas gauge to 100%
|
||
//
|
||
GaugePosition = GaugeRange*StopAtPercent/100;
|
||
SendMessage(hWnd,PBM_SETPOS,GaugePosition,0L);
|
||
}
|
||
|