|
|
#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
|