832 lines
28 KiB
C
832 lines
28 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1992 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
undoinst.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
This program undoes the actions described by an Installation Modification Log file
|
||
|
created by the INSTALER program
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Steve Wood (stevewo) 15-Jan-1996
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include <nt.h>
|
||
|
#include <ntrtl.h>
|
||
|
#include <nturtl.h>
|
||
|
|
||
|
#include "instutil.h"
|
||
|
#include "iml.h"
|
||
|
|
||
|
BOOLEAN RedoScript;
|
||
|
BOOLEAN VerboseOutput;
|
||
|
|
||
|
int
|
||
|
ProcessUndoIml(
|
||
|
PINSTALLATION_MODIFICATION_LOGFILE pImlUndo,
|
||
|
PINSTALLATION_MODIFICATION_LOGFILE pImlRedo
|
||
|
);
|
||
|
|
||
|
int
|
||
|
__cdecl
|
||
|
main(
|
||
|
int argc,
|
||
|
char *argv[]
|
||
|
)
|
||
|
{
|
||
|
int Result;
|
||
|
char *s;
|
||
|
PINSTALLATION_MODIFICATION_LOGFILE pImlUndo;
|
||
|
PINSTALLATION_MODIFICATION_LOGFILE pImlRedo;
|
||
|
USHORT RedoScriptId;
|
||
|
|
||
|
InitCommonCode( "UNDOINST",
|
||
|
"[-r] [-v]",
|
||
|
"-r replace contents of input .IML file with redo script to undo the undo\n"
|
||
|
"-v verbose output\n"
|
||
|
);
|
||
|
RedoScript = FALSE;
|
||
|
VerboseOutput = FALSE;
|
||
|
while (--argc) {
|
||
|
s = *++argv;
|
||
|
if (*s == '-' || *s == '/') {
|
||
|
while (*++s) {
|
||
|
switch( tolower( *s ) ) {
|
||
|
case 'r':
|
||
|
RedoScript = TRUE;
|
||
|
break;
|
||
|
case 'v':
|
||
|
VerboseOutput = TRUE;
|
||
|
break;
|
||
|
default:
|
||
|
CommonSwitchProcessing( &argc, &argv, *s );
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
if (!CommonArgProcessing( &argc, &argv )) {
|
||
|
Usage( "Arguments not supported - '%s'", (ULONG)s );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (ImlPath == NULL) {
|
||
|
Usage( "Must specify an installation name as first argument", 0 );
|
||
|
}
|
||
|
|
||
|
if (!SetCurrentDirectory( InstalerDirectory )) {
|
||
|
FatalError( "Unable to change to '%ws' directory (%u)",
|
||
|
(ULONG)InstalerDirectory,
|
||
|
GetLastError()
|
||
|
);
|
||
|
}
|
||
|
|
||
|
pImlUndo = LoadIml( ImlPath );
|
||
|
if (pImlUndo == NULL) {
|
||
|
FatalError( "Unable to open '%ws' (%u)",
|
||
|
(ULONG)ImlPath,
|
||
|
GetLastError()
|
||
|
);
|
||
|
}
|
||
|
if (RedoScript) {
|
||
|
RedoScriptId = 0;
|
||
|
if (CreateBackupFileName( &RedoScriptId ) == NULL) {
|
||
|
FatalError( "Unable to create temporary file for redo script (%u)\n",
|
||
|
GetLastError(),
|
||
|
0
|
||
|
);
|
||
|
}
|
||
|
|
||
|
pImlRedo = CreateIml( FormatTempFileName( InstalerDirectory, &RedoScriptId ), TRUE );
|
||
|
if (pImlRedo == NULL) {
|
||
|
FatalError( "Unable to create redo script '%ws' (%u)\n",
|
||
|
(ULONG)FormatTempFileName( InstalerDirectory, &RedoScriptId ),
|
||
|
GetLastError()
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
pImlRedo = NULL;
|
||
|
}
|
||
|
|
||
|
Result = ProcessUndoIml( pImlUndo, pImlRedo );
|
||
|
|
||
|
CloseIml( pImlUndo );
|
||
|
if (pImlRedo != NULL) {
|
||
|
CloseIml( pImlRedo );
|
||
|
if (!MoveFileEx( FormatTempFileName( InstalerDirectory, &RedoScriptId ),
|
||
|
ImlPath,
|
||
|
MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED
|
||
|
)
|
||
|
) {
|
||
|
FatalError( "Unable to rename redo script '%ws' (%u)\n",
|
||
|
(ULONG)FormatTempFileName( InstalerDirectory, &RedoScriptId ),
|
||
|
GetLastError()
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
exit( Result );
|
||
|
return Result;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
DeleteFileOrDirectory(
|
||
|
PWSTR Name
|
||
|
)
|
||
|
{
|
||
|
DWORD FileAttributes;
|
||
|
|
||
|
FileAttributes = GetFileAttributes( Name );
|
||
|
if (FileAttributes == 0xFFFFFFFF) {
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
if (FileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
||
|
return RemoveDirectory( Name );
|
||
|
}
|
||
|
else {
|
||
|
return DeleteFile( Name );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
BOOLEAN
|
||
|
ProcessUndoFileIml(
|
||
|
PINSTALLATION_MODIFICATION_LOGFILE pImlUndo,
|
||
|
PIML_FILE_RECORD pFile
|
||
|
)
|
||
|
{
|
||
|
PIML_FILE_RECORD_CONTENTS pOldFile;
|
||
|
PIML_FILE_RECORD_CONTENTS pNewFile;
|
||
|
USHORT UniqueId = 0;
|
||
|
HANDLE FileHandle;
|
||
|
PWSTR BackupFileName;
|
||
|
DWORD FileAttributes;
|
||
|
DWORD BytesWritten;
|
||
|
|
||
|
pOldFile = MP( PIML_FILE_RECORD_CONTENTS, pImlUndo, pFile->OldFile );
|
||
|
pNewFile = MP( PIML_FILE_RECORD_CONTENTS, pImlUndo, pFile->NewFile );
|
||
|
printf( " %ws - ", MP( PWSTR, pImlUndo, pFile->Name ) );
|
||
|
switch( pFile->Action ) {
|
||
|
case CreateNewFile:
|
||
|
printf( "deleting" );
|
||
|
SetFileAttributes( MP( PWSTR, pImlUndo, pFile->Name ),
|
||
|
FILE_ATTRIBUTE_NORMAL
|
||
|
);
|
||
|
if (!DeleteFileOrDirectory( MP( PWSTR, pImlUndo, pFile->Name ) )) {
|
||
|
printf( " - error (%u)", GetLastError() );
|
||
|
}
|
||
|
printf( "\n" );
|
||
|
break;
|
||
|
|
||
|
case ModifyOldFile:
|
||
|
case DeleteOldFile:
|
||
|
FileAttributes = GetFileAttributes( MP( PWSTR, pImlUndo, pFile->Name ) );
|
||
|
printf( "restoring old file" );
|
||
|
if (FileAttributes != 0xFFFFFFFF) {
|
||
|
SetFileAttributes( MP( PWSTR, pImlUndo, pFile->Name ),
|
||
|
FILE_ATTRIBUTE_NORMAL
|
||
|
);
|
||
|
BackupFileName = CreateBackupFileName( &UniqueId );
|
||
|
if (BackupFileName == NULL) {
|
||
|
printf( " - unable to find temporary name for restore\n" );
|
||
|
break;
|
||
|
}
|
||
|
else
|
||
|
if (!MoveFile( MP( PWSTR, pImlUndo, pFile->Name ),
|
||
|
BackupFileName
|
||
|
)
|
||
|
) {
|
||
|
printf( " - unable to rename existing to temporary name (%u)\n",
|
||
|
GetLastError()
|
||
|
);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
BackupFileName = NULL;
|
||
|
}
|
||
|
|
||
|
if (pOldFile != NULL) {
|
||
|
if (pOldFile->FileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
||
|
if (!CreateDirectory( MP( PWSTR, pImlUndo, pFile->Name ), NULL )) {
|
||
|
printf( " - unable to create directory (%u)",
|
||
|
GetLastError()
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
FileHandle = CreateFile( MP( PWSTR, pImlUndo, pFile->Name ),
|
||
|
GENERIC_WRITE,
|
||
|
FILE_SHARE_READ,
|
||
|
NULL,
|
||
|
CREATE_NEW,
|
||
|
0,
|
||
|
NULL
|
||
|
);
|
||
|
if (FileHandle != INVALID_HANDLE_VALUE) {
|
||
|
if (WriteFile( FileHandle,
|
||
|
MP( PVOID, pImlUndo, pOldFile->Contents ),
|
||
|
pOldFile->FileSize,
|
||
|
&BytesWritten,
|
||
|
NULL
|
||
|
) &&
|
||
|
BytesWritten == pOldFile->FileSize
|
||
|
) {
|
||
|
if (!SetFileAttributes( MP( PWSTR, pImlUndo, pFile->Name ),
|
||
|
pOldFile->FileAttributes
|
||
|
)
|
||
|
) {
|
||
|
printf( " - unable to restore attributes (%u)",
|
||
|
GetLastError()
|
||
|
);
|
||
|
}
|
||
|
else
|
||
|
if (!SetFileTime( FileHandle,
|
||
|
&pOldFile->LastWriteTime,
|
||
|
&pOldFile->LastWriteTime,
|
||
|
&pOldFile->LastWriteTime
|
||
|
)
|
||
|
) {
|
||
|
printf( " - unable to restore last write time (%u)",
|
||
|
GetLastError()
|
||
|
);
|
||
|
}
|
||
|
else
|
||
|
if (BackupFileName != NULL) {
|
||
|
DeleteFile( BackupFileName );
|
||
|
BackupFileName = NULL;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
printf( " - unable to restore contents (%u)",
|
||
|
GetLastError()
|
||
|
);
|
||
|
}
|
||
|
|
||
|
CloseHandle( FileHandle );
|
||
|
}
|
||
|
else {
|
||
|
printf( " - unable to create file (%u)",
|
||
|
GetLastError()
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
printf( " - old contents missing from .IML file" );
|
||
|
}
|
||
|
|
||
|
if (BackupFileName != NULL) {
|
||
|
DeleteFile( MP( PWSTR, pImlUndo, pFile->Name ) );
|
||
|
MoveFile( BackupFileName, MP( PWSTR, pImlUndo, pFile->Name ) );
|
||
|
}
|
||
|
printf( "\n" );
|
||
|
break;
|
||
|
|
||
|
case ModifyFileDateTime:
|
||
|
printf( "restoring date/time\n" );
|
||
|
FileHandle = CreateFile( MP( PWSTR, pImlUndo, pFile->Name ),
|
||
|
FILE_WRITE_ATTRIBUTES,
|
||
|
FILE_SHARE_READ,
|
||
|
NULL,
|
||
|
OPEN_EXISTING,
|
||
|
0,
|
||
|
NULL
|
||
|
);
|
||
|
if (FileHandle != INVALID_HANDLE_VALUE) {
|
||
|
if (!SetFileTime( FileHandle,
|
||
|
&pOldFile->LastWriteTime,
|
||
|
&pOldFile->LastWriteTime,
|
||
|
&pOldFile->LastWriteTime
|
||
|
)
|
||
|
) {
|
||
|
printf( " - unable to restore last write time (%u)",
|
||
|
GetLastError()
|
||
|
);
|
||
|
}
|
||
|
|
||
|
CloseHandle( FileHandle );
|
||
|
}
|
||
|
else {
|
||
|
printf( " - unable to open file (%u)",
|
||
|
GetLastError()
|
||
|
);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case ModifyFileAttributes:
|
||
|
printf( "restoring attributes" );
|
||
|
if (!SetFileAttributes( MP( PWSTR, pImlUndo, pFile->Name ),
|
||
|
pOldFile->FileAttributes
|
||
|
)
|
||
|
) {
|
||
|
printf( " - unable to restore attributes (%u)",
|
||
|
GetLastError()
|
||
|
);
|
||
|
}
|
||
|
printf( "\n" );
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOLEAN
|
||
|
ProcessRedoFileIml(
|
||
|
PINSTALLATION_MODIFICATION_LOGFILE pImlUndo,
|
||
|
PIML_FILE_RECORD pFile,
|
||
|
PINSTALLATION_MODIFICATION_LOGFILE pImlRedo
|
||
|
)
|
||
|
{
|
||
|
HANDLE FindHandle;
|
||
|
WIN32_FIND_DATA FindFileData;
|
||
|
|
||
|
if (pFile->Action == CreateNewFile) {
|
||
|
//
|
||
|
// Created a new file. So do the same in the redo
|
||
|
// script, with the existing contents of the new file
|
||
|
//
|
||
|
ImlAddFileRecord( pImlRedo,
|
||
|
CreateNewFile,
|
||
|
MP( PWSTR, pImlUndo, pFile->Name ),
|
||
|
NULL,
|
||
|
NULL,
|
||
|
0
|
||
|
);
|
||
|
}
|
||
|
else
|
||
|
if (pFile->Action == ModifyOldFile) {
|
||
|
//
|
||
|
// Modified an existing file. Create a similar record
|
||
|
// in the redo script that will hold the new contents
|
||
|
//
|
||
|
ImlAddFileRecord( pImlRedo,
|
||
|
ModifyOldFile,
|
||
|
MP( PWSTR, pImlUndo, pFile->Name ),
|
||
|
NULL,
|
||
|
NULL,
|
||
|
0
|
||
|
);
|
||
|
}
|
||
|
else {
|
||
|
//
|
||
|
// Modified the file attributes and/or date and time. Get the current
|
||
|
// values and save them in the redo script
|
||
|
//
|
||
|
FindHandle = FindFirstFile( MP( PWSTR, pImlUndo, pFile->Name ),
|
||
|
&FindFileData
|
||
|
);
|
||
|
if (FindHandle != INVALID_HANDLE_VALUE) {
|
||
|
ImlAddFileRecord( pImlRedo,
|
||
|
ModifyFileDateTime,
|
||
|
MP( PWSTR, pImlUndo, pFile->Name ),
|
||
|
NULL,
|
||
|
&FindFileData.ftLastWriteTime,
|
||
|
FindFileData.dwFileAttributes
|
||
|
);
|
||
|
FindClose( FindHandle );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOLEAN
|
||
|
ProcessUndoKeyIml(
|
||
|
PINSTALLATION_MODIFICATION_LOGFILE pImlUndo,
|
||
|
PIML_KEY_RECORD pKey
|
||
|
)
|
||
|
{
|
||
|
PIML_VALUE_RECORD pValue;
|
||
|
PIML_VALUE_RECORD_CONTENTS pOldValue;
|
||
|
PIML_VALUE_RECORD_CONTENTS pNewValue;
|
||
|
NTSTATUS Status;
|
||
|
UNICODE_STRING KeyName;
|
||
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||
|
HANDLE KeyHandle;
|
||
|
UNICODE_STRING ValueName;
|
||
|
|
||
|
KeyHandle = NULL;
|
||
|
if (pKey->Values != 0 || pKey->Action == CreateNewKey) {
|
||
|
printf( " %ws - ", MP( PWSTR, pImlUndo, pKey->Name ) );
|
||
|
RtlInitUnicodeString( &KeyName, MP( PWSTR, pImlUndo, pKey->Name ) );
|
||
|
InitializeObjectAttributes( &ObjectAttributes,
|
||
|
&KeyName,
|
||
|
OBJ_CASE_INSENSITIVE,
|
||
|
NULL,
|
||
|
NULL
|
||
|
);
|
||
|
if (pKey->Action != DeleteOldKey) {
|
||
|
if (pKey->Action == CreateNewKey) {
|
||
|
printf( "deleting" );
|
||
|
}
|
||
|
else {
|
||
|
printf( "modifying" );
|
||
|
}
|
||
|
Status = NtOpenKey( &KeyHandle, DELETE | GENERIC_WRITE, &ObjectAttributes );
|
||
|
}
|
||
|
else {
|
||
|
printf( "creating" );
|
||
|
Status = NtCreateKey( &KeyHandle,
|
||
|
GENERIC_WRITE,
|
||
|
&ObjectAttributes,
|
||
|
0,
|
||
|
NULL,
|
||
|
0,
|
||
|
NULL
|
||
|
);
|
||
|
}
|
||
|
|
||
|
if (!NT_SUCCESS( Status )) {
|
||
|
KeyHandle = NULL;
|
||
|
printf( " - failed (0x%08x)", Status );
|
||
|
}
|
||
|
printf( "\n" );
|
||
|
|
||
|
if (KeyHandle != NULL) {
|
||
|
pValue = MP( PIML_VALUE_RECORD, pImlUndo, pKey->Values );
|
||
|
while (pValue != NULL) {
|
||
|
pOldValue = MP( PIML_VALUE_RECORD_CONTENTS, pImlUndo, pValue->OldValue );
|
||
|
pNewValue = MP( PIML_VALUE_RECORD_CONTENTS, pImlUndo, pValue->NewValue );
|
||
|
printf( " %ws - ", MP( PWSTR, pImlUndo, pValue->Name ) );
|
||
|
RtlInitUnicodeString( &ValueName,
|
||
|
MP( PWSTR, pImlUndo, pValue->Name )
|
||
|
);
|
||
|
if (pValue->Action == CreateNewValue) {
|
||
|
printf( "deleting" );
|
||
|
Status = NtDeleteValueKey( KeyHandle, &ValueName );
|
||
|
}
|
||
|
else {
|
||
|
if (pValue->Action == DeleteOldValue) {
|
||
|
printf( "creating" );
|
||
|
}
|
||
|
else {
|
||
|
printf( "restoring" );
|
||
|
}
|
||
|
|
||
|
Status = NtSetValueKey( KeyHandle,
|
||
|
&ValueName,
|
||
|
0,
|
||
|
pOldValue->Type,
|
||
|
MP( PWSTR, pImlUndo, pOldValue->Data ),
|
||
|
pOldValue->Length
|
||
|
);
|
||
|
}
|
||
|
|
||
|
if (!NT_SUCCESS( Status )) {
|
||
|
printf( " - failed (0x%08x)", Status );
|
||
|
}
|
||
|
printf( "\n" );
|
||
|
|
||
|
pValue = MP( PIML_VALUE_RECORD, pImlUndo, pValue->Next );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (KeyHandle != NULL) {
|
||
|
if (pKey->Action == CreateNewKey) {
|
||
|
Status = NtDeleteKey( KeyHandle );
|
||
|
if (!NT_SUCCESS( Status )) {
|
||
|
printf( " *** delete of above key failed (0x%08x)", Status );
|
||
|
}
|
||
|
}
|
||
|
NtClose( KeyHandle );
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOLEAN
|
||
|
ProcessRedoKeyIml(
|
||
|
PINSTALLATION_MODIFICATION_LOGFILE pImlUndo,
|
||
|
PIML_KEY_RECORD pKey,
|
||
|
PINSTALLATION_MODIFICATION_LOGFILE pImlRedo
|
||
|
)
|
||
|
{
|
||
|
PIML_VALUE_RECORD pValue;
|
||
|
PIML_VALUE_RECORD_CONTENTS pOldValue;
|
||
|
PIML_VALUE_RECORD_CONTENTS pNewValue;
|
||
|
POFFSET Values;
|
||
|
|
||
|
Values = 0;
|
||
|
if ((pKey->Values != 0 || pKey->Action == CreateNewKey) &&
|
||
|
pKey->Action != DeleteOldKey
|
||
|
) {
|
||
|
//
|
||
|
// Created or modified an existing key and/or values.
|
||
|
//
|
||
|
pValue = MP( PIML_VALUE_RECORD, pImlUndo, pKey->Values );
|
||
|
while (pValue != NULL) {
|
||
|
pOldValue = MP( PIML_VALUE_RECORD_CONTENTS, pImlUndo, pValue->OldValue );
|
||
|
pNewValue = MP( PIML_VALUE_RECORD_CONTENTS, pImlUndo, pValue->NewValue );
|
||
|
if (pValue->Action == CreateNewValue) {
|
||
|
if (pNewValue != NULL) {
|
||
|
ImlAddValueRecord( pImlRedo,
|
||
|
pValue->Action,
|
||
|
MP( PWSTR, pImlUndo, pValue->Name ),
|
||
|
pNewValue->Type,
|
||
|
pNewValue->Length,
|
||
|
MP( PWSTR, pImlUndo, pNewValue->Data ),
|
||
|
0,
|
||
|
0,
|
||
|
NULL,
|
||
|
&Values
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
if (pValue->Action == ModifyOldValue) {
|
||
|
if (pOldValue != NULL && pNewValue != NULL) {
|
||
|
ImlAddValueRecord( pImlRedo,
|
||
|
pValue->Action,
|
||
|
MP( PWSTR, pImlUndo, pValue->Name ),
|
||
|
pNewValue->Type,
|
||
|
pNewValue->Length,
|
||
|
MP( PWSTR, pImlUndo, pNewValue->Data ),
|
||
|
pOldValue->Type,
|
||
|
pOldValue->Length,
|
||
|
MP( PWSTR, pImlUndo, pOldValue->Data ),
|
||
|
&Values
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
if (pValue->Action == DeleteOldValue) {
|
||
|
if (pOldValue != NULL) {
|
||
|
ImlAddValueRecord( pImlRedo,
|
||
|
pValue->Action,
|
||
|
MP( PWSTR, pImlUndo, pValue->Name ),
|
||
|
0,
|
||
|
0,
|
||
|
NULL,
|
||
|
pOldValue->Type,
|
||
|
pOldValue->Length,
|
||
|
MP( PWSTR, pImlUndo, pOldValue->Data ),
|
||
|
&Values
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pValue = MP( PIML_VALUE_RECORD, pImlUndo, pValue->Next );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ImlAddKeyRecord( pImlRedo,
|
||
|
pKey->Action,
|
||
|
MP( PWSTR, pImlUndo, pKey->Name ),
|
||
|
Values
|
||
|
);
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
BOOLEAN
|
||
|
ProcessUndoIniIml(
|
||
|
PINSTALLATION_MODIFICATION_LOGFILE pImlUndo,
|
||
|
PIML_INI_RECORD pIni
|
||
|
)
|
||
|
{
|
||
|
PIML_INISECTION_RECORD pSection;
|
||
|
PIML_INIVARIABLE_RECORD pVariable;
|
||
|
HANDLE FileHandle;
|
||
|
BOOLEAN FileNameShown;
|
||
|
BOOLEAN SectionNameShown;
|
||
|
|
||
|
FileNameShown = FALSE;
|
||
|
pSection = MP( PIML_INISECTION_RECORD, pImlUndo, pIni->Sections );
|
||
|
while (pSection != NULL) {
|
||
|
SectionNameShown = FALSE;
|
||
|
pVariable = MP( PIML_INIVARIABLE_RECORD, pImlUndo, pSection->Variables );
|
||
|
while (pVariable != NULL) {
|
||
|
if (!FileNameShown) {
|
||
|
printf( "%ws\n", MP( PWSTR, pImlUndo, pIni->Name ) );
|
||
|
FileNameShown = TRUE;
|
||
|
}
|
||
|
|
||
|
if (!SectionNameShown) {
|
||
|
printf( " [%ws]", MP( PWSTR, pImlUndo, pSection->Name ) );
|
||
|
if (pSection->Action == DeleteOldSection) {
|
||
|
printf( " - deleting" );
|
||
|
}
|
||
|
printf( "\n" );
|
||
|
SectionNameShown = TRUE;
|
||
|
}
|
||
|
|
||
|
printf( " %ws = ", MP( PWSTR, pImlUndo, pVariable->Name ) );
|
||
|
if (pVariable->Action == CreateNewVariable) {
|
||
|
printf( "deleting" );
|
||
|
if (!WritePrivateProfileString( MP( PWSTR, pImlUndo, pSection->Name ),
|
||
|
MP( PWSTR, pImlUndo, pVariable->Name ),
|
||
|
NULL,
|
||
|
MP( PWSTR, pImlUndo, pIni->Name )
|
||
|
)
|
||
|
) {
|
||
|
printf( " - failed (%u)", GetLastError() );
|
||
|
}
|
||
|
printf( "\n" );
|
||
|
}
|
||
|
else {
|
||
|
printf( "restoring" );
|
||
|
if (!WritePrivateProfileString( MP( PWSTR, pImlUndo, pSection->Name ),
|
||
|
MP( PWSTR, pImlUndo, pVariable->Name ),
|
||
|
MP( PWSTR, pImlUndo, pVariable->OldValue ),
|
||
|
MP( PWSTR, pImlUndo, pIni->Name )
|
||
|
)
|
||
|
) {
|
||
|
printf( " - failed (%u)", GetLastError() );
|
||
|
}
|
||
|
printf( "\n" );
|
||
|
}
|
||
|
|
||
|
pVariable = MP( PIML_INIVARIABLE_RECORD, pImlUndo, pVariable->Next );
|
||
|
}
|
||
|
|
||
|
if (pSection->Action == CreateNewSection) {
|
||
|
if (!FileNameShown) {
|
||
|
printf( "%ws\n", MP( PWSTR, pImlUndo, pIni->Name ) );
|
||
|
FileNameShown = TRUE;
|
||
|
}
|
||
|
|
||
|
if (!SectionNameShown) {
|
||
|
printf( " [%ws]", MP( PWSTR, pImlUndo, pSection->Name ) );
|
||
|
if (pSection->Action == CreateNewSection) {
|
||
|
printf( " - deleting" );
|
||
|
}
|
||
|
SectionNameShown = TRUE;
|
||
|
printf( "\n" );
|
||
|
}
|
||
|
|
||
|
if (!WritePrivateProfileSection( MP( PWSTR, pImlUndo, pSection->Name ),
|
||
|
NULL,
|
||
|
MP( PWSTR, pImlUndo, pIni->Name )
|
||
|
)
|
||
|
) {
|
||
|
printf( " *** delete of above section name failed (%u)\n",
|
||
|
GetLastError()
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pSection = MP( PIML_INISECTION_RECORD, pImlUndo, pSection->Next );
|
||
|
}
|
||
|
|
||
|
if (pIni->Action == CreateNewIniFile) {
|
||
|
printf( "%ws - deleting", MP( PWSTR, pImlUndo, pIni->Name ) );
|
||
|
if (!DeleteFile( MP( PWSTR, pImlUndo, pIni->Name ) )) {
|
||
|
printf( " - failed (%u)", GetLastError() );
|
||
|
}
|
||
|
printf( "\n" );
|
||
|
FileNameShown = TRUE;
|
||
|
}
|
||
|
else {
|
||
|
FileHandle = CreateFile( MP( PWSTR, pImlUndo, pIni->Name ),
|
||
|
FILE_WRITE_ATTRIBUTES,
|
||
|
FILE_SHARE_READ,
|
||
|
NULL,
|
||
|
OPEN_EXISTING,
|
||
|
0,
|
||
|
NULL
|
||
|
);
|
||
|
if (FileHandle != INVALID_HANDLE_VALUE) {
|
||
|
SetFileTime( FileHandle,
|
||
|
&pIni->LastWriteTime,
|
||
|
&pIni->LastWriteTime,
|
||
|
&pIni->LastWriteTime
|
||
|
);
|
||
|
CloseHandle( FileHandle );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (FileNameShown) {
|
||
|
printf( "\n" );
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOLEAN
|
||
|
ProcessRedoIniIml(
|
||
|
PINSTALLATION_MODIFICATION_LOGFILE pImlUndo,
|
||
|
PIML_INI_RECORD pIni,
|
||
|
PINSTALLATION_MODIFICATION_LOGFILE pImlRedo
|
||
|
)
|
||
|
{
|
||
|
PIML_INISECTION_RECORD pSection;
|
||
|
PIML_INIVARIABLE_RECORD pVariable;
|
||
|
POFFSET Variables, Sections;
|
||
|
|
||
|
pSection = MP( PIML_INISECTION_RECORD, pImlUndo, pIni->Sections );
|
||
|
Sections = 0;
|
||
|
while (pSection != NULL) {
|
||
|
pVariable = MP( PIML_INIVARIABLE_RECORD, pImlUndo, pSection->Variables );
|
||
|
Variables = 0;
|
||
|
while (pVariable != NULL) {
|
||
|
ImlAddIniVariableRecord( pImlRedo,
|
||
|
pVariable->Action,
|
||
|
MP( PWSTR, pImlUndo, pVariable->Name ),
|
||
|
MP( PWSTR, pImlUndo, pVariable->OldValue ),
|
||
|
MP( PWSTR, pImlUndo, pVariable->NewValue ),
|
||
|
&Variables
|
||
|
);
|
||
|
|
||
|
pVariable = MP( PIML_INIVARIABLE_RECORD, pImlUndo, pVariable->Next );
|
||
|
}
|
||
|
|
||
|
if (Variables != 0) {
|
||
|
ImlAddIniSectionRecord( pImlRedo,
|
||
|
pSection->Action,
|
||
|
MP( PWSTR, pImlUndo, pSection->Name ),
|
||
|
Variables,
|
||
|
&Sections
|
||
|
);
|
||
|
}
|
||
|
|
||
|
pSection = MP( PIML_INISECTION_RECORD, pImlUndo, pSection->Next );
|
||
|
}
|
||
|
|
||
|
if (Sections != 0) {
|
||
|
ImlAddIniRecord( pImlRedo,
|
||
|
pIni->Action,
|
||
|
MP( PWSTR, pImlUndo, pIni->Name ),
|
||
|
&pIni->LastWriteTime,
|
||
|
Sections
|
||
|
);
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
int
|
||
|
ProcessUndoIml(
|
||
|
PINSTALLATION_MODIFICATION_LOGFILE pImlUndo,
|
||
|
PINSTALLATION_MODIFICATION_LOGFILE pImlRedo
|
||
|
)
|
||
|
{
|
||
|
PIML_FILE_RECORD pFile;
|
||
|
PIML_KEY_RECORD pKey;
|
||
|
PIML_INI_RECORD pIni;
|
||
|
|
||
|
if (pImlUndo->NumberOfFileRecords > 0) {
|
||
|
printf( "Undoing File Modifications:\n" );
|
||
|
pFile = MP( PIML_FILE_RECORD, pImlUndo, pImlUndo->FileRecords );
|
||
|
while (pFile != NULL) {
|
||
|
if (pFile->Name != 0) {
|
||
|
if (pImlRedo != NULL) {
|
||
|
ProcessRedoFileIml( pImlUndo, pFile, pImlRedo );
|
||
|
}
|
||
|
|
||
|
ProcessUndoFileIml( pImlUndo, pFile );
|
||
|
}
|
||
|
|
||
|
pFile = MP( PIML_FILE_RECORD, pImlUndo, pFile->Next );
|
||
|
}
|
||
|
|
||
|
printf( "\n" );
|
||
|
}
|
||
|
|
||
|
if (pImlUndo->NumberOfKeyRecords > 0) {
|
||
|
printf( "Undoing Registry Modifications:\n" );
|
||
|
pKey = MP( PIML_KEY_RECORD, pImlUndo, pImlUndo->KeyRecords );
|
||
|
while (pKey != NULL) {
|
||
|
if (pImlRedo != NULL) {
|
||
|
ProcessRedoKeyIml( pImlUndo, pKey, pImlRedo );
|
||
|
}
|
||
|
|
||
|
ProcessUndoKeyIml( pImlUndo, pKey );
|
||
|
|
||
|
pKey = MP( PIML_KEY_RECORD, pImlUndo, pKey->Next );
|
||
|
}
|
||
|
|
||
|
printf( "\n" );
|
||
|
}
|
||
|
|
||
|
if (pImlUndo->NumberOfIniRecords > 0) {
|
||
|
printf( "Undoing .INI File modifications:\n" );
|
||
|
pIni = MP( PIML_INI_RECORD, pImlUndo, pImlUndo->IniRecords );
|
||
|
while (pIni != NULL) {
|
||
|
if (pImlRedo != NULL) {
|
||
|
ProcessRedoIniIml( pImlUndo, pIni, pImlRedo );
|
||
|
}
|
||
|
|
||
|
ProcessUndoIniIml( pImlUndo, pIni);
|
||
|
|
||
|
pIni = MP( PIML_INI_RECORD, pImlUndo, pIni->Next );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|