windows-nt/Source/XPSP1/NT/base/mspatch/api/samples/apatch/tracing.c
2020-09-26 16:20:57 +08:00

822 lines
21 KiB
C

#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0400
#endif
#ifndef WIN32
#define WIN32 0x0400
#endif
#pragma warning( disable: 4001 4035 4115 4200 4201 4204 4209 4214 4514 4699 )
#include <windows.h>
#pragma warning( disable: 4001 4035 4115 4200 4201 4204 4209 4214 4514 4699 )
#include <stdlib.h>
#include <stdio.h>
#include "patchapi.h"
#ifdef TRACING
#define FILESIZE (3000000)
long g_OldFilePosition;
unsigned long g_cLiterals = 0;
unsigned long g_cMatches = 0;
unsigned long g_cMatchBytes = 0;
#if 0 /* distance.xls */
unsigned long cDistances[6000000] = { 0 };
#endif
#ifdef COMPOSITION /* composition.xls */
#define BUCKET_SIZE (4096)
#define NBUCKETS (FILESIZE / BUCKET_SIZE)
enum { LITERAL, MATCH_OLD, MATCH_NEW, BUCKET_TYPES };
unsigned long cBuckets[NBUCKETS][BUCKET_TYPES] = { { 0,0,0 } };
#endif
#if 0 /* rifts */
#define NO_DISPLACEMENT (333333333)
long iDisplacement[FILESIZE];
#endif
#if 0 /* slots */
#define MAX_SLOTS 500
unsigned long cSlotUsed[MAX_SLOTS];
#endif
typedef struct
{
unsigned long ulRegionOffset;
unsigned long ulRegionSize;
unsigned long ulRegionAddress;
} FILE_REGION;
#define MAX_REGIONS 50
int cRegionsOld = 0;
FILE_REGION RegionsOld[MAX_REGIONS];
int cRegionsNew = 0;
FILE_REGION RegionsNew[MAX_REGIONS];
typedef struct
{
unsigned long ulNewOffset;
unsigned long ulOldOffset;
unsigned long ulMatchLength;
} MATCH_LOG_ENTRY;
#define MAX_MATCH_LOG_ENTRIES (500000)
int cMatchLogEntries = 0;
MATCH_LOG_ENTRY MatchLog[MAX_MATCH_LOG_ENTRIES];
typedef struct _a_POINTER_REMAP
{
struct _a_POINTER_REMAP *pNext;
unsigned long ulNewPointer;
unsigned long ulOldPointer;
unsigned long ulLength;
} POINTER_REMAP;
POINTER_REMAP *pPointerRemapList;
#ifdef RIFTGEN
static char isRelocEntry[FILESIZE] = { '\0' };
#ifdef RIFTGEN2 /* references */
typedef struct _a_reference
{
struct _a_reference *pNext;
long iDisplacement;
} REFERENCE;
static REFERENCE *pReferences[FILESIZE] = { NULL };
#endif
#endif
static int QueryRelocsInRange(unsigned long ulAddress, unsigned long ulLength)
{
int iRegion;
unsigned long ulFileOffset;
int fRelocsFound = FALSE;
for (iRegion = 0; iRegion < cRegionsOld; iRegion++)
{
if ((ulAddress >= RegionsOld[iRegion].ulRegionAddress) &&
(ulAddress < (RegionsOld[iRegion].ulRegionAddress + RegionsOld[iRegion].ulRegionSize)))
{
break;
}
}
if (iRegion != cRegionsOld)
{
ulFileOffset = RegionsOld[iRegion].ulRegionOffset + (ulAddress - RegionsOld[iRegion].ulRegionAddress);
while (ulLength--)
{
if (isRelocEntry[ulFileOffset])
{
fRelocsFound = TRUE;
break;
}
ulFileOffset++;
ulAddress++;
}
}
return(fRelocsFound);
}
static void DisplayMatchLog(void)
{
int iMatchLogEntry;
unsigned long ulNewOffset;
unsigned long ulOldOffset;
int iNewFileRegion;
int iOldFileRegion;
unsigned long ulMatchLength;
unsigned long ulLocalLength;
unsigned long ulNewDisplacement;
unsigned long ulOldDisplacement;
POINTER_REMAP *pRemap;
POINTER_REMAP **ppBacklink;
unsigned long ulNewPointer;
unsigned long ulOldPointer;
long lLastDisplacement;
if (cMatchLogEntries == 0)
{
return;
}
pPointerRemapList = NULL;
for (iMatchLogEntry = 0; iMatchLogEntry < cMatchLogEntries; iMatchLogEntry++)
{
ulNewOffset = MatchLog[iMatchLogEntry].ulNewOffset;
ulOldOffset = MatchLog[iMatchLogEntry].ulOldOffset;
ulMatchLength = MatchLog[iMatchLogEntry].ulMatchLength;
while (ulMatchLength) /* until all is done */
{
ulLocalLength = ulMatchLength; /* might get clipped */
/* locate corresponding new file region to get it's address */
for (iNewFileRegion = 0; iNewFileRegion < cRegionsNew; iNewFileRegion++)
{
if ((ulNewOffset >= RegionsNew[iNewFileRegion].ulRegionOffset) &&
(ulNewOffset < (RegionsNew[iNewFileRegion].ulRegionOffset + RegionsNew[iNewFileRegion].ulRegionSize)))
{
break;
}
}
if (iNewFileRegion == cRegionsNew)
{
goto dontcare;
}
/* clip if match spans beyond this region */
ulNewDisplacement = ulNewOffset - RegionsNew[iNewFileRegion].ulRegionOffset;
ulNewPointer = RegionsNew[iNewFileRegion].ulRegionAddress + ulNewDisplacement;
if (ulLocalLength > (RegionsNew[iNewFileRegion].ulRegionSize - ulNewDisplacement))
{
ulLocalLength = (RegionsNew[iNewFileRegion].ulRegionSize - ulNewDisplacement);
}
/* locate corresponding old file region to get it's address */
for (iOldFileRegion = 0; iOldFileRegion < cRegionsOld; iOldFileRegion++)
{
if ((ulOldOffset >= RegionsOld[iOldFileRegion].ulRegionOffset) &&
(ulOldOffset < (RegionsOld[iOldFileRegion].ulRegionOffset + RegionsOld[iOldFileRegion].ulRegionSize)))
{
break;
}
}
if (iOldFileRegion == cRegionsOld)
{
goto dontcare;
}
/* clip if match spans beyond this region */
ulOldDisplacement = ulOldOffset - RegionsOld[iOldFileRegion].ulRegionOffset;
ulOldPointer = RegionsOld[iOldFileRegion].ulRegionAddress + ulOldDisplacement;
if (ulLocalLength > (RegionsOld[iOldFileRegion].ulRegionSize - ulOldDisplacement))
{
ulLocalLength = (RegionsOld[iOldFileRegion].ulRegionSize - ulOldDisplacement);
}
/* see if any relocs in the range */
if (QueryRelocsInRange(ulOldPointer, ulLocalLength))
{
/* sorted insertion of this new remap into the list */
ppBacklink = &pPointerRemapList;
while (*ppBacklink != NULL)
{
if ((*ppBacklink)->ulOldPointer > ulOldPointer)
{
break;
}
ppBacklink = &((*ppBacklink)->pNext);
}
pRemap = GlobalAlloc( GMEM_FIXED, sizeof(POINTER_REMAP) );
pRemap->ulNewPointer = ulNewPointer;
pRemap->ulOldPointer = ulOldPointer;
pRemap->ulLength = ulLocalLength;
pRemap->pNext = *ppBacklink;
*ppBacklink = pRemap;
}
/* move on to next match or fragment */
ulNewOffset += ulLocalLength;
ulOldOffset += ulLocalLength;
ulMatchLength -= ulLocalLength;
}
dontcare:
NULL; // entertain compiler req: label must have a statement
}
printf("%08X\n", RegionsOld[ 0 ].ulRegionAddress);
lLastDisplacement = 0;
for (pRemap = pPointerRemapList; pRemap != NULL; pRemap = pRemap->pNext)
{
if (lLastDisplacement != (long) (pRemap->ulNewPointer - pRemap->ulOldPointer))
{
lLastDisplacement = pRemap->ulNewPointer - pRemap->ulOldPointer;
printf("%08X %08X\n", pRemap->ulOldPointer, pRemap->ulNewPointer);
}
}
}
#endif
void CopyRight( void ) {
MessageBox(
NULL,
"\n"
"APATCH 0.15 Patch Application Utility\n"
"Copyright (C) Microsoft, 1997\n"
"\n",
"APATCH Copyright",
MB_OK);
}
void Usage( void ) {
MessageBox(NULL,
"Usage: APATCH PatchFile OldFile TargetNewFile\n\n",
"APATCH Usage",
MB_OK);
}
BOOL
CALLBACK
MyProgressCallback(
PVOID CallbackContext,
ULONG CurrentPosition,
ULONG MaximumPosition
)
{
UNREFERENCED_PARAMETER( CallbackContext );
if ( CurrentPosition & 0xFF000000 ) {
CurrentPosition >>= 8;
MaximumPosition >>= 8;
}
if ( MaximumPosition != 0 ) {
// guigauge: printf( "\r%3d%% complete", ( CurrentPosition * 100 ) / MaximumPosition );
}
return TRUE;
}
int StrChr( char *psz, char c )
{
while (*psz)
{
if (*psz++ == c)
{
return(TRUE);
}
}
return(FALSE);
}
int __cdecl main( int argc, char *argv[] ) {
LPSTR OldFileName = NULL;
LPSTR PatchFileName = NULL;
LPSTR NewFileName = NULL;
BOOL Success;
LPSTR arg;
int i;
SetErrorMode( SEM_FAILCRITICALERRORS );
#ifndef DEBUG
SetErrorMode( SEM_NOALIGNMENTFAULTEXCEPT | SEM_FAILCRITICALERRORS );
#endif
// CopyRight();
for ( i = 1; i < argc; i++ ) {
arg = argv[ i ];
if ( StrChr( arg, '?' )) {
Usage();
goto bail;
}
if ( PatchFileName == NULL ) {
PatchFileName = arg;
}
else if ( OldFileName == NULL ) {
OldFileName = arg;
}
else if ( NewFileName == NULL ) {
NewFileName = arg;
}
else {
Usage();
goto bail;
}
}
if (( OldFileName == NULL ) || ( NewFileName == NULL ) || ( PatchFileName == NULL )) {
Usage();
goto bail;
}
DeleteFile( NewFileName );
#ifdef TRACING
#if 0 /* rifts */
{
long filepos;
for (filepos = 0; filepos < FILESIZE; filepos++)
{
iDisplacement[filepos] = NO_DISPLACEMENT;
}
}
#endif
#endif
Success = ApplyPatchToFileEx(
PatchFileName,
OldFileName,
NewFileName,
0,
MyProgressCallback,
NULL
);
if ( ! Success ) {
CHAR ErrorText[ 16 ];
ULONG ErrorCode = GetLastError();
CHAR Message[100];
wsprintf( ErrorText, ( ErrorCode < 0x10000000 ) ? "%d" : "%X", ErrorCode );
wsprintf( Message, "Failed to create file from patch (%s)\n", ErrorText );
MessageBox( NULL, Message, "APATCH Failed", MB_OK );
return( 1 );
}
#ifdef TRACING
{
#ifdef COMPOSITION /* composition.xls */
{
int iBucket;
for (iBucket = 0; iBucket < NBUCKETS; iBucket++)
{
if ((cBuckets[iBucket][LITERAL] || cBuckets[iBucket][MATCH_OLD] || cBuckets[iBucket][MATCH_NEW]))
{
printf("%9lu %9lu %9lu %9lu\n",
iBucket * BUCKET_SIZE,
cBuckets[iBucket][LITERAL],
cBuckets[iBucket][MATCH_OLD],
cBuckets[iBucket][MATCH_NEW]);
}
}
}
#endif
#if 0
printf("%9lu bytes from literals\n", g_cLiterals);
printf("%9lu bytes from %lu matches\n", g_cMatchBytes, g_cMatches);
printf("%9lu bytes total\n", g_cLiterals + g_cMatchBytes);
#endif
#if 0 /* distance.xls */
{
int iDistance;
for (iDistance = 0; iDistance < (sizeof(cDistances)/sizeof(cDistances[0])); iDistance++)
{
if (cDistances[iDistance] != 0)
{
printf("%9ld %9ld\n", iDistance, cDistances[iDistance]);
}
}
}
#endif
#if 0 /* rifts */
{
long filepos;
long iLastDisplacement = NO_DISPLACEMENT;
for (filepos = 0; filepos < FILESIZE; filepos++)
{
if (iDisplacement[filepos] != NO_DISPLACEMENT)
{
if (iLastDisplacement != iDisplacement[filepos])
{
iLastDisplacement = iDisplacement[filepos];
printf("%9lu %9ld\n", filepos, iDisplacement[filepos]);
}
}
}
}
#endif
#if 0 /* slots */
{
int slot;
for (slot = 0; slot < MAX_SLOTS; slot++)
{
if (cSlotUsed[slot])
{
printf("%5d %9ld\n", slot, cSlotUsed[slot]);
}
}
}
#endif
#ifdef RIFTGEN2 /* generating faked references for relrifts file */
{
int index;
REFERENCE *pReference, *pKill;
int iLast = 0;
int cEntries = 0;
int cEntriesHit = 0;
int iBest;
for (index = 0; index < FILESIZE; index++)
{
pReference = pReferences[index];
if (isRelocEntry[index])
{
cEntries++;
}
if (pReference != NULL)
{
if (isRelocEntry[index])
{
cEntriesHit++;
}
if (pReference->pNext != NULL) /* multiple values */
{
/* knowing the number of reloc entries interested could help here */
/* see if the last value is one of the choices */
while (pReference)
{
if (pReference->iDisplacement == iLast)
{
goto found;
}
pReference = pReference->pNext;
}
/* choose the value nearest the last value */
pReference = pReferences[index];
while (pReference != NULL)
{
if (abs(pReference->iDisplacement - iLast) < abs(iBest - iLast))
{
iBest = pReference->iDisplacement;
}
pReference = pReference->pNext;
}
iLast = iBest;
printf("%d %d\n", index, iLast);
found:
/* now free the list */
pReference = pReferences[index];
while (pReference != NULL)
{
pKill = pReference;
pReference = pReference->pNext;
GlobalFree(pKill);
}
}
else
{
if (iLast != pReference->iDisplacement) /* a simple rift */
{
iLast = pReference->iDisplacement;
printf("%d %d\n", index, iLast);
}
GlobalFree(pReference);
}
}
}
//fprintf(stderr, "%d hit of %d total relocation targets\n", cEntriesHit, cEntries);
}
#endif
DisplayMatchLog();
}
#endif
// MessageBox( NULL, "OK\n", "APATCH Done", MB_OK );
bail:
return( 0 );
}
#ifdef TRACING
void TracingSetOldFilePosition(long oldpos)
{
g_OldFilePosition = oldpos;
}
void TracingLiteral(long bufpos, byte c)
{
#ifdef COMPOSITION /* composition.xls */
int iBucket = bufpos / BUCKET_SIZE;
cBuckets[iBucket][LITERAL]++;
#endif
g_cLiterals++;
#ifdef DECO_DETAILS /* trace */
printf("%08lX: %02X\n", bufpos, (byte) c);
#endif
}
void TracingMatch(long bufpos,long srcpos,long window,int length,int slot)
{
static long iLastDisplacement = -1;
g_cMatches++;
g_cMatchBytes += length;
#if 0 /* slots */
if (slot < MAX_SLOTS)
{
cSlotUsed[slot]++;
}
else
{
printf("Slot number out of range (%d)\n", slot);
}
#endif
if (srcpos < g_OldFilePosition)
{
#ifdef COMPOSITION /* composition.xls */
int iBucket = bufpos / BUCKET_SIZE;
int eBucket = (bufpos + length - 1) / BUCKET_SIZE;
if (iBucket == eBucket)
{
cBuckets[iBucket][MATCH_NEW] += length;
}
else
{
long length1 = (eBucket * BUCKET_SIZE) - bufpos;
cBuckets[iBucket][MATCH_NEW] += length1;
cBuckets[eBucket][MATCH_NEW] += (length - length1);
}
#endif
#ifdef DECO_DETAILS /* trace */
{
int iDistance = bufpos - srcpos;
printf("%08lX..%08lX: %08lX..%08lX (%d,%u)\n", /* new file refs no [...] */
bufpos,
bufpos + length - 1,
srcpos,
srcpos + length - 1,
-iDistance,
length);
}
#endif
#if 0
if (iLastDisplacement != (srcpos - bufpos))
{
iLastDisplacement = (srcpos - bufpos);
printf("%9ld %9ld %9ld\n",
bufpos,
srcpos,
srcpos - bufpos);
}
#endif
}
else
{
#ifdef COMPOSITION /* composition.xls */
int iBucket = bufpos / BUCKET_SIZE;
int eBucket = (bufpos + length - 1) / BUCKET_SIZE;
if (iBucket == eBucket)
{
cBuckets[iBucket][MATCH_OLD] += length;
}
else
{
long length1 = (eBucket * BUCKET_SIZE) - bufpos;
cBuckets[iBucket][MATCH_OLD] += length1;
cBuckets[eBucket][MATCH_OLD] += (length - length1);
}
#endif
if ((cMatchLogEntries != 0) &&
((MatchLog[cMatchLogEntries - 1].ulNewOffset + MatchLog[cMatchLogEntries - 1].ulMatchLength) == (unsigned long) bufpos) &&
((MatchLog[cMatchLogEntries - 1].ulOldOffset + MatchLog[cMatchLogEntries - 1].ulMatchLength) == (unsigned long) (srcpos - g_OldFilePosition)))
{
MatchLog[cMatchLogEntries - 1].ulMatchLength += length;
}
else if (cMatchLogEntries < MAX_MATCH_LOG_ENTRIES)
{
MatchLog[cMatchLogEntries].ulNewOffset = bufpos;
MatchLog[cMatchLogEntries].ulOldOffset = srcpos - g_OldFilePosition;
MatchLog[cMatchLogEntries].ulMatchLength = length;
cMatchLogEntries++;
}
#ifdef DECO_DETAILS /* trace */
{
int iDistance = bufpos - srcpos + window;
printf("%08lX..%08lX: [%08lX..%08lX] (%d,%u)\n", /* old file refs in [...] */
bufpos,
bufpos + length - 1,
srcpos - g_OldFilePosition,
srcpos - g_OldFilePosition + length - 1,
-iDistance,
length);
}
#endif
#if 0 /* rifts */
{
int index;
for (index = 0; index < length; index++)
{
iDisplacement[bufpos + index] = bufpos - srcpos + g_OldFilePosition;
}
}
#endif
#if 0
if (iLastDisplacement != (bufpos - srcpos + g_OldFilePosition))
{
iLastDisplacement = (bufpos - srcpos + g_OldFilePosition);
printf("%9ld %9ld %9ld\n",
bufpos,
srcpos - g_OldFilePosition,
bufpos - srcpos + g_OldFilePosition);
}
#endif
#ifdef RIFTGEN2 /* references */
{
int index;
REFERENCE *pReference;
long iOldFilePosition;
for (index = 0; index < length; index++)
{
iOldFilePosition = srcpos - g_OldFilePosition + index;
if (isRelocEntry[iOldFilePosition])
{
pReference = GlobalAlloc(GMEM_FIXED, sizeof(REFERENCE));
pReference->pNext = pReferences[iOldFilePosition];
pReferences[iOldFilePosition] = pReference;
pReference->iDisplacement = bufpos - srcpos + g_OldFilePosition;
}
}
}
#endif
}
#if 0 /* distance.xls */
{
int iDistance = bufpos - srcpos + window;
if ((iDistance < 1) || (iDistance >= (sizeof(cDistances)/sizeof(cDistances[0]))))
{
printf("That's a strange distance.\n");
}
else
{
cDistances[iDistance]++;
}
}
#endif
}
#ifdef RIFTGEN
void TracingSetIsRelocEntry(ULONG OldFileOffset, ULONG Va)
{
// printf("offset 0x%08X is Va 0x%08X\n", OldFileOffset, Va);
// ie, "offset 0x00000DF9 is Va 0x703B17F9" when base=0x703B0000
isRelocEntry[OldFileOffset] = '\1';
}
#endif
void TracingReportAddresses(int FileNumber, ULONG FileOffset, ULONG Size, ULONG Address)
{
if ( FileNumber )
{
RegionsNew[cRegionsNew].ulRegionOffset = FileOffset;
RegionsNew[cRegionsNew].ulRegionSize = Size;
RegionsNew[cRegionsNew].ulRegionAddress = Address;
cRegionsNew++;
}
else
{
RegionsOld[cRegionsOld].ulRegionOffset = FileOffset;
RegionsOld[cRegionsOld].ulRegionSize = Size;
RegionsOld[cRegionsOld].ulRegionAddress = Address;
cRegionsOld++;
}
}
#endif