diff options
Diffstat (limited to 'private/sdktools/instaler/compinst.c')
-rw-r--r-- | private/sdktools/instaler/compinst.c | 899 |
1 files changed, 899 insertions, 0 deletions
diff --git a/private/sdktools/instaler/compinst.c b/private/sdktools/instaler/compinst.c new file mode 100644 index 000000000..9c6df1338 --- /dev/null +++ b/private/sdktools/instaler/compinst.c @@ -0,0 +1,899 @@ +/*++ + +Copyright (c) 1992 Microsoft Corporation + +Module Name: + + showinst.c + +Abstract: + + This program compares the actions described by two Installation Modification Log file + created by the INSTALER program + +Author: + + Steve Wood (stevewo) 15-Jan-1996 + +Revision History: + +--*/ + +#include "instutil.h" +#include "iml.h" + +BOOLEAN VerboseOutput; + +BOOLEAN +CompareIml( + PINSTALLATION_MODIFICATION_LOGFILE pIml1, + PINSTALLATION_MODIFICATION_LOGFILE pIml2 + ); + +int +_CRTAPI1 +main( + int argc, + char *argv[] + ) +{ + char *s; + PWSTR ImlPathAlt = NULL; + PINSTALLATION_MODIFICATION_LOGFILE pIml1 = NULL; + PINSTALLATION_MODIFICATION_LOGFILE pIml2 = NULL; + + InitCommonCode( "COMPINST", + "InstallationName2 [-v]", + "-v verbose output\n" + ); + VerboseOutput = FALSE; + while (--argc) { + s = *++argv; + if (*s == '-' || *s == '/') { + while (*++s) { + switch( tolower( *s ) ) { + case 'v': + VerboseOutput = TRUE; + break; + default: + CommonSwitchProcessing( &argc, &argv, *s ); + break; + } + } + } + else + if (!CommonArgProcessing( &argc, &argv )) { + if (ImlPathAlt != NULL) { + Usage( "Too many installation names specified - '%s'", (ULONG)s ); + } + + ImlPathAlt = FormatImlPath( InstalerDirectory, GetArgAsUnicode( s ) ); + } + } + + if (ImlPath == NULL || ImlPathAlt == NULL) { + Usage( "Must specify two installation names to compare", 0 ); + } + + if (!SetCurrentDirectory( InstalerDirectory )) { + FatalError( "Unable to change to '%ws' directory (%u)", + (ULONG)InstalerDirectory, + GetLastError() + ); + } + + pIml1 = LoadIml( ImlPath ); + if (pIml1 == NULL) { + FatalError( "Unable to load '%ws' (%u)", + (ULONG)ImlPath, + GetLastError() + ); + } + + pIml2 = LoadIml( ImlPathAlt ); + if (pIml2 == NULL) { + FatalError( "Unable to load '%ws' (%u)", + (ULONG)ImlPathAlt, + GetLastError() + ); + } + + printf( "Displaying differences between:\n" ); + printf( " Installation 1: %ws\n", ImlPath ); + printf( " Installation 2: %ws\n", ImlPathAlt ); + exit( CompareIml( pIml1, pIml2 ) == FALSE ); + return 0; +} + +typedef struct _IML_GENERIC_RECORD { + POFFSET Next; // IML_GENERIC_RECORD + ULONG Action; + POFFSET Name; // WCHAR + POFFSET Records; // IML_GENERIC_RECORD +} IML_GENERIC_RECORD, *PIML_GENERIC_RECORD; + + +typedef +VOID +(*PIML_PRINT_RECORD_ROUTINE)( + PINSTALLATION_MODIFICATION_LOGFILE pIml, + PIML_GENERIC_RECORD pGeneric, + PWSTR Parents[], + ULONG Depth, + ULONG i + ); + +typedef +BOOLEAN +(*PIML_COMPARE_CONTENTS_ROUTINE)( + PINSTALLATION_MODIFICATION_LOGFILE pIml1, + PIML_GENERIC_RECORD pGeneric1, + PINSTALLATION_MODIFICATION_LOGFILE pIml2, + PIML_GENERIC_RECORD pGeneric2, + PWSTR Parents[] + ); + + +PINSTALLATION_MODIFICATION_LOGFILE pSortIml; + +int +_CRTAPI1 +CompareGeneric( + const void *Reference1, + const void *Reference2 + ) +{ + PIML_GENERIC_RECORD p1 = *(PIML_GENERIC_RECORD *)Reference1; + PIML_GENERIC_RECORD p2 = *(PIML_GENERIC_RECORD *)Reference2; + + if (p1->Name == 0) { + if (p2->Name == 0) { + return 0; + } + else { + return -1; + } + } + else + if (p2->Name == 0) { + return 1; + } + + return _wcsicmp( MP( PWSTR, pSortIml, p1->Name ), + MP( PWSTR, pSortIml, p2->Name ) + ); +} + + +PIML_GENERIC_RECORD * +GetSortedGenericListAsArray( + PINSTALLATION_MODIFICATION_LOGFILE pIml, + PIML_GENERIC_RECORD pGeneric + ) +{ + PIML_GENERIC_RECORD p, *pp; + ULONG n; + + p = pGeneric; + n = 1; + while (p != NULL) { + n += 1; + p = MP( PIML_GENERIC_RECORD, pIml, p->Next ); + } + + pp = HeapAlloc( GetProcessHeap(), 0, n * sizeof( *pp ) ); + p = pGeneric; + n = 0; + while (p != NULL) { + pp[ n++ ] = p; + p = MP( PIML_GENERIC_RECORD, pIml, p->Next ); + } + pp[ n ] = NULL; + + pSortIml = pIml; + qsort( (void *)pp, n, sizeof( *pp ), CompareGeneric ); + pSortIml = NULL; + return pp; +} + +BOOLEAN +CompareGenericIml( + PINSTALLATION_MODIFICATION_LOGFILE pIml1, + PIML_GENERIC_RECORD pGeneric1, + PINSTALLATION_MODIFICATION_LOGFILE pIml2, + PIML_GENERIC_RECORD pGeneric2, + PWSTR Parents[], + ULONG Depth, + PIML_PRINT_RECORD_ROUTINE PrintRecordRoutine, + PIML_COMPARE_CONTENTS_ROUTINE CompareContentsRoutine + ) +{ + PVOID pBufferToFree1; + PVOID pBufferToFree2; + PIML_GENERIC_RECORD *ppGeneric1; + PIML_GENERIC_RECORD *ppGeneric2; + PIML_GENERIC_RECORD pShow1; + PIML_GENERIC_RECORD pShow2; + BOOLEAN Result = FALSE; + PWSTR s1, s2; + int cmpResult; + + ppGeneric1 = GetSortedGenericListAsArray( pIml1, pGeneric1 ); + if (ppGeneric1 == NULL) { + return FALSE; + } + pBufferToFree1 = ppGeneric1; + + ppGeneric2 = GetSortedGenericListAsArray( pIml2, pGeneric2 ); + if (ppGeneric2 == NULL) { + HeapFree( GetProcessHeap(), 0, pBufferToFree1 ); + return FALSE; + } + pBufferToFree2 = ppGeneric2; + + pGeneric1 = *ppGeneric1++; + pGeneric2 = *ppGeneric2++; + + while (TRUE) { + pShow1 = NULL; + pShow2 = NULL; + if (pGeneric1 == NULL) { + if (pGeneric2 == NULL) { + break; + } + + // + // pGeneric2 is new + // + + pShow2 = pGeneric2; + pGeneric2 = *ppGeneric2++; + Result = FALSE; + } + else + if (pGeneric2 == NULL) { + // + // pGeneric1 is new + // + pShow1 = pGeneric1; + pGeneric1 = *ppGeneric1++; + Result = FALSE; + } + else { + s1 = MP( PWSTR, pIml1, pGeneric1->Name ); + s2 = MP( PWSTR, pIml2, pGeneric2->Name ); + + if (s1 == NULL) { + if (s2 == NULL) { + cmpResult = 0; + } + else { + cmpResult = -1; + } + } + else + if (s2 == NULL) { + cmpResult = 1; + } + else { + cmpResult = _wcsicmp( s1, s2 ); + } + if (cmpResult == 0) { + if (Depth > 1) { + Parents[ Depth - 1 ] = MP( PWSTR, pIml1, pGeneric1->Name ); + Result = CompareGenericIml( pIml1, + MP( PIML_GENERIC_RECORD, pIml1, pGeneric1->Records ), + pIml2, + MP( PIML_GENERIC_RECORD, pIml2, pGeneric2->Records ), + Parents, + Depth - 1, + PrintRecordRoutine, + CompareContentsRoutine + ); + } + else { + Result = (*CompareContentsRoutine)( pIml1, pGeneric1, + pIml2, pGeneric2, + Parents + ); + } + + pGeneric1 = *ppGeneric1++; + pGeneric2 = *ppGeneric2++; + } + else + if (cmpResult > 0) { + pShow2 = pGeneric2; + pGeneric2 = *ppGeneric2++; + } + else { + pShow1 = pGeneric1; + pGeneric1 = *ppGeneric1++; + } + } + + if (pShow1) { + (*PrintRecordRoutine)( pIml1, pShow1, Parents, Depth, 1 ); + } + + if (pShow2) { + (*PrintRecordRoutine)( pIml2, pShow2, Parents, Depth, 2 ); + } + } + + HeapFree( GetProcessHeap(), 0, pBufferToFree1 ); + HeapFree( GetProcessHeap(), 0, pBufferToFree2 ); + return Result; +} + + +char *FileActionStrings[] = { + "CreateNewFile", + "ModifyOldFile", + "DeleteOldFile", + "RenameOldFile", + "ModifyFileDateTime", + "ModifyFileAttributes" +}; + + +PWSTR +FormatFileTime( + LPFILETIME LastWriteTime + ) +{ + FILETIME LocalFileTime; + SYSTEMTIME DateTime; + static WCHAR DateTimeBuffer[ 128 ]; + + FileTimeToLocalFileTime( LastWriteTime, &LocalFileTime ); + FileTimeToSystemTime( &LocalFileTime, &DateTime ); + + _snwprintf( DateTimeBuffer, + 128, + L"%02u/%02u/%04u %02u:%02u:%02u", + (ULONG)DateTime.wMonth, + (ULONG)DateTime.wDay, + (ULONG)DateTime.wYear, + (ULONG)DateTime.wHour, + (ULONG)DateTime.wMinute, + (ULONG)DateTime.wSecond + ); + + return DateTimeBuffer; +} + + +VOID +PrintFileRecordIml( + PINSTALLATION_MODIFICATION_LOGFILE pIml, + PIML_GENERIC_RECORD pGeneric, + PWSTR Parents[], + ULONG Depth, + ULONG i + ) +{ + PIML_FILE_RECORD pFile = (PIML_FILE_RECORD)pGeneric; + + printf( "File: %ws\n %u: %s\n", + MP( PWSTR, pIml, pFile->Name ), + i, FileActionStrings[ pFile->Action ] + ); +} + +BOOLEAN +CompareFileContentsIml( + PINSTALLATION_MODIFICATION_LOGFILE pIml1, + PIML_GENERIC_RECORD pGeneric1, + PINSTALLATION_MODIFICATION_LOGFILE pIml2, + PIML_GENERIC_RECORD pGeneric2, + PWSTR Parents[] + ) +{ + PIML_FILE_RECORD pFile1 = (PIML_FILE_RECORD)pGeneric1; + PIML_FILE_RECORD pFile2 = (PIML_FILE_RECORD)pGeneric2; + PIML_FILE_RECORD_CONTENTS pFileContents1; + PIML_FILE_RECORD_CONTENTS pFileContents2; + BOOLEAN ActionsDiffer = FALSE; + BOOLEAN DatesDiffer = FALSE; + BOOLEAN AttributesDiffer = FALSE; + BOOLEAN SizesDiffer = FALSE; + BOOLEAN ContentsDiffer = FALSE; + BOOLEAN Result = TRUE; + PCHAR s1, s2; + ULONG n; + + pFileContents1 = MP( PIML_FILE_RECORD_CONTENTS, pIml1, pFile1->NewFile ); + pFileContents2 = MP( PIML_FILE_RECORD_CONTENTS, pIml2, pFile2->NewFile ); + + if (pFile1->Action != pFile2->Action) { + ActionsDiffer = TRUE; + Result = FALSE; + } + else + if (pFileContents1 != NULL && pFileContents2 != NULL) { + if (pFile1->Action != CreateNewFile && + ((pFileContents1->LastWriteTime.dwHighDateTime != + pFileContents2->LastWriteTime.dwHighDateTime + ) || + (pFileContents1->LastWriteTime.dwLowDateTime != + pFileContents2->LastWriteTime.dwLowDateTime + ) + ) + ) { + DatesDiffer = TRUE; + Result = FALSE; + } + + if (pFileContents1->FileAttributes != pFileContents2->FileAttributes) { + AttributesDiffer = TRUE; + Result = FALSE; + } + + if (pFileContents1->FileSize != pFileContents2->FileSize) { + SizesDiffer = TRUE; + Result = FALSE; + } + else + if (pFileContents1->Contents == 0 || + pFileContents2->Contents == 0 || + memcmp( MP( PVOID, pIml1, pFileContents1->Contents ), + MP( PVOID, pIml2, pFileContents2->Contents ), + pFileContents1->FileSize + ) != 0 + ) { + s1 = MP( PVOID, pIml1, pFileContents1->Contents ); + s2 = MP( PVOID, pIml2, pFileContents2->Contents ); + if (s1 == NULL || s2 == NULL) { + n = 0; + } + else { + n = pFileContents1->FileSize; + } + while (n) { + if (*s1 != *s2) { + n = pFileContents1->FileSize - n; + break; + } + + n -= 1; + s1 += 1; + s2 += 1; + } + + ContentsDiffer = TRUE; + Result = FALSE; + } + } + + if (!Result) { + printf( "File: %ws\n", MP( PWSTR, pIml1, pFile1->Name ) ); + if (ActionsDiffer) { + printf( " 1: Action - %s\n", FileActionStrings[ pFile1->Action ] ); + printf( " 2: Action - %s\n", FileActionStrings[ pFile2->Action ] ); + } + if (DatesDiffer) { + printf( " 1: LastWriteTime - %ws\n", + FormatFileTime( &pFileContents1->LastWriteTime ) + ); + printf( " 2: LastWriteTime - %ws\n", + FormatFileTime( &pFileContents2->LastWriteTime ) + ); + } + if (AttributesDiffer) { + printf( " 1: Attributes - 0x%08x\n", pFileContents1->FileAttributes ); + printf( " 2: Attributes - 0x%08x\n", pFileContents2->FileAttributes ); + } + if (SizesDiffer) { + printf( " 1: File Size - 0x%08x\n", pFileContents1->FileSize ); + printf( " 2: File Size - 0x%08x\n", pFileContents2->FileSize ); + } + if (ContentsDiffer) { + printf( " 1: Contents Differs\n" ); + printf( " 2: from each other at offset %08x\n", n ); + } + } + + return Result; +} + + +char *KeyActionStrings[] = { + "CreateNewKey", + "DeleteOldKey", + "ModifyKeyValues" +}; + +char *ValueActionStrings[] = { + "CreateNewValue", + "DeleteOldValue", + "ModifyOldValue" +}; + + +char *ValueTypeStrings[] = { + "REG_NONE", + "REG_SZ", + "REG_EXPAND_SZ", + "REG_BINARY", + "REG_DWORD", + "REG_DWORD_BIG_ENDIAN", + "REG_LINK", + "REG_MULTI_SZ", + "REG_RESOURCE_LIST", + "REG_FULL_RESOURCE_DESCRIPTOR", + "REG_RESOURCE_REQUIREMENTS_LIST" +}; + +VOID +PrintKeyValueRecordIml( + PINSTALLATION_MODIFICATION_LOGFILE pIml, + PIML_GENERIC_RECORD pGeneric, + PWSTR Parents[], + ULONG Depth, + ULONG i + ) +{ + PIML_KEY_RECORD pKey = (PIML_KEY_RECORD)pGeneric; + PIML_VALUE_RECORD pValue = (PIML_VALUE_RECORD)pGeneric; + + if (Depth == 2) { + printf( "Key: %ws\n %u: %s\n", + MP( PWSTR, pIml, pKey->Name ), + i, KeyActionStrings[ pKey->Action ] + ); + } + else { + if (Parents[ 1 ] != NULL) { + printf( "Key: %ws\n", Parents[ 1 ] ); + Parents[ 1 ] = NULL; + } + + printf( " Value: %ws\n %u: %s\n", + MP( PWSTR, pIml, pValue->Name ), + i, ValueActionStrings[ pValue->Action ] + ); + } +} + +UCHAR BlanksForPadding[] = + " "; + +VOID +PrintValueContents( + PCHAR PrefixString, + PINSTALLATION_MODIFICATION_LOGFILE pIml, + PIML_VALUE_RECORD_CONTENTS pValueContents + ) +{ + ULONG ValueType; + ULONG ValueLength; + PVOID ValueData; + ULONG cbPrefix, cb, i, j; + PWSTR pw; + PULONG p; + + ValueType = pValueContents->Type; + ValueLength = pValueContents->Length; + ValueData = MP( PVOID, pIml, pValueContents->Data ); + + cbPrefix = printf( "%s", PrefixString ); + cb = cbPrefix + printf( "%s", ValueTypeStrings[ ValueType ] ); + + switch( ValueType ) { + case REG_SZ: + case REG_LINK: + case REG_EXPAND_SZ: + pw = (PWSTR)ValueData; + printf( " (%u) \"%.*ws\"\n", ValueLength, ValueLength/sizeof(WCHAR), pw ); + break; + + case REG_MULTI_SZ: + pw = (PWSTR)ValueData; + i = 0; + if (*pw) + while (i < (ValueLength - 1) / sizeof( WCHAR )) { + if (i > 0) { + printf( " \\\n%.*s", cbPrefix, BlanksForPadding ); + } + printf( "\"%ws\" ", pw+i ); + do { + ++i; + } + while (pw[i] != UNICODE_NULL); + + ++i; + } + printf( "\n" ); + break; + + case REG_DWORD: + case REG_DWORD_BIG_ENDIAN: + printf( " 0x%08x\n", *(PULONG)ValueData ); + break; + + case REG_RESOURCE_LIST: + case REG_FULL_RESOURCE_DESCRIPTOR: + case REG_RESOURCE_REQUIREMENTS_LIST: + case REG_BINARY: + case REG_NONE: + cb = printf( " [0x%08lx]", ValueLength ); + + if (ValueLength != 0) { + p = (PULONG)ValueData; + i = (ValueLength + 3) / sizeof( ULONG ); + for (j=0; j<i; j++) { + if ((cbPrefix + cb + 11) > 78) { + printf( " \\\n%.*s", cbPrefix, BlanksForPadding ); + cb = 0; + } + else { + cb += printf( " " ); + } + + cb += printf( "0x%08lx", *p++ ); + } + } + + printf( "\n" ); + break; + } +} + +BOOLEAN +CompareKeyValueContentsIml( + PINSTALLATION_MODIFICATION_LOGFILE pIml1, + PIML_GENERIC_RECORD pGeneric1, + PINSTALLATION_MODIFICATION_LOGFILE pIml2, + PIML_GENERIC_RECORD pGeneric2, + PWSTR Parents[] + ) +{ + PIML_VALUE_RECORD pValue1 = (PIML_VALUE_RECORD)pGeneric1; + PIML_VALUE_RECORD pValue2 = (PIML_VALUE_RECORD)pGeneric2; + PIML_VALUE_RECORD_CONTENTS pValueContents1; + PIML_VALUE_RECORD_CONTENTS pValueContents2; + BOOLEAN ActionsDiffer = FALSE; + BOOLEAN TypesDiffer = FALSE; + BOOLEAN LengthsDiffer = FALSE; + BOOLEAN ContentsDiffer = FALSE; + BOOLEAN Result = TRUE; + PCHAR s1, s2; + ULONG n; + + pValueContents1 = MP( PIML_VALUE_RECORD_CONTENTS, pIml1, pValue1->NewValue ); + pValueContents2 = MP( PIML_VALUE_RECORD_CONTENTS, pIml2, pValue2->NewValue ); + + if (pValue1->Action != pValue2->Action) { + ActionsDiffer = TRUE; + Result = FALSE; + } + else + if (pValueContents1 != NULL && pValueContents2 != NULL) { + if (pValue1->Action != CreateNewValue && + (pValueContents1->Type != pValueContents2->Type) + ) { + TypesDiffer = TRUE; + Result = FALSE; + } + + if (pValueContents1->Length != pValueContents2->Length) { + LengthsDiffer = TRUE; + Result = FALSE; + } + else + if (pValueContents1->Data == 0 || + pValueContents2->Data == 0 || + memcmp( MP( PVOID, pIml1, pValueContents1->Data ), + MP( PVOID, pIml2, pValueContents2->Data ), + pValueContents1->Length + ) != 0 + ) { + s1 = MP( PVOID, pIml1, pValueContents1->Data ); + s2 = MP( PVOID, pIml2, pValueContents2->Data ); + if (s1 == NULL || s2 == NULL) { + n = 0; + } + else { + n = pValueContents1->Length; + } + while (n) { + if (*s1 != *s2) { + n = pValueContents1->Length - n; + break; + } + + n -= 1; + s1 += 1; + s2 += 1; + } + + ContentsDiffer = TRUE; + Result = FALSE; + } + } + + if (!Result) { + if (Parents[ 2 ] != NULL) { + printf( "Key: %ws\n", Parents[ 2 ] ); + Parents[ 2 ] = NULL; + } + + printf( " Value: %ws\n", MP( PWSTR, pIml1, pValue1->Name ) ); + if (ActionsDiffer) { + printf( " 1: Action - %s\n", ValueActionStrings[ pValue1->Action ] ); + printf( " 2: Action - %s\n", ValueActionStrings[ pValue2->Action ] ); + } + if (TypesDiffer || LengthsDiffer || ContentsDiffer ) { + PrintValueContents( " 1: ", pIml1, pValueContents1 ); + PrintValueContents( " 2: ", pIml2, pValueContents2 ); + } + } + + return Result; +} + + +char *IniActionStrings[] = { + "CreateNewIniFile", + "ModifyOldIniFile" +}; + +char *SectionActionStrings[] = { + "CreateNewSection", + "DeleteOldSection", + "ModifySectionVariables" +}; + +char *VariableActionStrings[] = { + "CreateNewVariable", + "DeleteOldVariable", + "ModifyOldVariable" +}; + +VOID +PrintIniSectionVariableRecordIml( + PINSTALLATION_MODIFICATION_LOGFILE pIml, + PIML_GENERIC_RECORD pGeneric, + PWSTR Parents[], + ULONG Depth, + ULONG i + ) +{ + PIML_INI_RECORD pIni = (PIML_INI_RECORD)pGeneric; + PIML_INISECTION_RECORD pSection = (PIML_INISECTION_RECORD)pGeneric; + PIML_INIVARIABLE_RECORD pVariable = (PIML_INIVARIABLE_RECORD)pGeneric; + + if (Depth == 3) { + printf( "Ini File: %ws\n %u: %s\n", + MP( PWSTR, pIml, pIni->Name ), + i, IniActionStrings[ pIni->Action ] + ); + } + else + if (Depth == 2) { + if (Parents[ 2 ] != NULL) { + printf( "Ini File: %ws\n", Parents[ 2 ] ); + Parents[ 2 ] = NULL; + } + + printf( " Section: %ws\n %u: %s\n", + MP( PWSTR, pIml, pSection->Name ), + i, SectionActionStrings[ pSection->Action ] + ); + } + else { + if (Parents[ 2 ] != NULL) { + printf( "Ini File: %ws\n", Parents[ 2 ] ); + Parents[ 2 ] = NULL; + } + + if (Parents[ 1 ] != NULL) { + printf( " Section: %ws\n", Parents[ 1 ] ); + Parents[ 1 ] = NULL; + } + + printf( " Variable: %ws\n %u: %s\n", + MP( PWSTR, pIml, pVariable->Name ), + i, VariableActionStrings[ pVariable->Action ] + ); + } +} + +BOOLEAN +CompareIniSectionVariableContentsIml( + PINSTALLATION_MODIFICATION_LOGFILE pIml1, + PIML_GENERIC_RECORD pGeneric1, + PINSTALLATION_MODIFICATION_LOGFILE pIml2, + PIML_GENERIC_RECORD pGeneric2, + PWSTR Parents[] + ) +{ + PIML_INIVARIABLE_RECORD pVariable1 = (PIML_INIVARIABLE_RECORD)pGeneric1; + PIML_INIVARIABLE_RECORD pVariable2 = (PIML_INIVARIABLE_RECORD)pGeneric2; + PWSTR pVariableContents1; + PWSTR pVariableContents2; + BOOLEAN ActionsDiffer = FALSE; + BOOLEAN ContentsDiffer = FALSE; + BOOLEAN Result = TRUE; + + pVariableContents1 = MP( PWSTR, pIml1, pVariable1->NewValue ); + pVariableContents2 = MP( PWSTR, pIml2, pVariable2->NewValue ); + + if (pVariable1->Action != pVariable2->Action) { + ActionsDiffer = TRUE; + Result = FALSE; + } + else + if (pVariableContents1 != NULL && pVariableContents2 != NULL) { + if (wcscmp( pVariableContents1, pVariableContents2 ) != 0) { + ContentsDiffer = TRUE; + Result = FALSE; + } + } + + if (!Result) { + if (Parents[ 2 ] != NULL) { + printf( "Ini File: %ws\n", Parents[ 2 ] ); + Parents[ 2 ] = NULL; + } + + if (Parents[ 1 ] != NULL) { + printf( " Section: %ws\n", Parents[ 1 ] ); + Parents[ 1 ] = NULL; + } + + printf( " Variable: %ws\n", MP( PWSTR, pIml1, pVariable1->Name ) ); + if (ActionsDiffer) { + printf( " 1: Action - %s\n", VariableActionStrings[ pVariable1->Action ] ); + printf( " 2: Action - %s\n", VariableActionStrings[ pVariable2->Action ] ); + } + if (ContentsDiffer) { + printf( " 1: '%ws'\n", pVariableContents1 ); + printf( " 2: '%ws'\n", pVariableContents2 ); + } + } + + return Result; +} + + + + +BOOLEAN +CompareIml( + PINSTALLATION_MODIFICATION_LOGFILE pIml1, + PINSTALLATION_MODIFICATION_LOGFILE pIml2 + ) +{ + BOOLEAN Result = TRUE; + PWSTR Parents[ 3 ]; + + Result &= CompareGenericIml( pIml1, MP( PIML_GENERIC_RECORD, pIml1, pIml1->FileRecords ), + pIml2, MP( PIML_GENERIC_RECORD, pIml2, pIml2->FileRecords ), + NULL, + 1, + PrintFileRecordIml, + CompareFileContentsIml + ); + + memset( Parents, 0, sizeof( Parents ) ); + Result &= CompareGenericIml( pIml1, MP( PIML_GENERIC_RECORD, pIml1, pIml1->KeyRecords ), + pIml2, MP( PIML_GENERIC_RECORD, pIml2, pIml2->KeyRecords ), + Parents, + 2, + PrintKeyValueRecordIml, + CompareKeyValueContentsIml + ); + + memset( Parents, 0, sizeof( Parents ) ); + Result &= CompareGenericIml( pIml1, MP( PIML_GENERIC_RECORD, pIml1, pIml1->IniRecords ), + pIml2, MP( PIML_GENERIC_RECORD, pIml2, pIml2->IniRecords ), + Parents, + 3, + PrintIniSectionVariableRecordIml, + CompareIniSectionVariableContentsIml + ); + + return Result; +} |