724 lines
17 KiB
C
724 lines
17 KiB
C
|
|
||
|
/*
|
||
|
* Module Name: WSTCAT.C
|
||
|
*
|
||
|
* Program: WSTCAT
|
||
|
*
|
||
|
*
|
||
|
* Description:
|
||
|
*
|
||
|
* Concatenates multiple WSP files, for the same module, into one WSP file.
|
||
|
* Creates a single TMI file from the resulting files.
|
||
|
*
|
||
|
*
|
||
|
* Modification History:
|
||
|
*
|
||
|
* 8-20-92 Created marklea
|
||
|
* 4-24-98, QFE: DerrickG (mdg)
|
||
|
* - new WSP file format for large symbol counts (ULONG vs. USHORT)
|
||
|
* - support for long file names (LFN) of input/output files
|
||
|
* - removed limit on symbol name lengths
|
||
|
*
|
||
|
*
|
||
|
*
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
#include <windows.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
#include <wsdata.h>
|
||
|
#include <..\wsfslib\wserror.h>
|
||
|
#include <..\wsfslib\wsfslib.h>
|
||
|
|
||
|
#include <ntverp.h>
|
||
|
#define MODULE "WSTCAT"
|
||
|
#define VERSION VER_PRODUCTVERSION_STR
|
||
|
|
||
|
/*
|
||
|
* Global variable declaration and initialization.
|
||
|
*/
|
||
|
static ULONG rc = NO_ERROR; // Return code
|
||
|
|
||
|
|
||
|
typedef struct tagTMI{
|
||
|
CHAR *pszFxnName;
|
||
|
ULONG ulAddr;
|
||
|
ULONG ulSize;
|
||
|
ULONG ulIndex;
|
||
|
BOOL fSet;
|
||
|
}TMI;
|
||
|
|
||
|
typedef struct indxMOD{
|
||
|
ULONG ulSetCnt; // mdg 4/98
|
||
|
ULONG ulFxnTot;
|
||
|
ULONG ulOffset;
|
||
|
ULONG ulSnaps;
|
||
|
PULONG pulBitStrings;
|
||
|
FILE *hFileNDX;
|
||
|
TMI *tmi;
|
||
|
}NDXMOD;
|
||
|
|
||
|
|
||
|
typedef struct tagMOD{
|
||
|
ULONG ulSetCnt; // mdg 4/98
|
||
|
UINT uiLeft;
|
||
|
ULONG ulOffset;
|
||
|
ULONG ulSnaps;
|
||
|
FILE *hFileWxx;
|
||
|
PULONG pulAddr;
|
||
|
}WSTMOD;
|
||
|
|
||
|
NDXMOD nmod;
|
||
|
WSTMOD wmod[256];
|
||
|
|
||
|
CHAR *szFileWSP; //WSP file name
|
||
|
CHAR *szFileTMI; //TMI file name
|
||
|
CHAR *szFileWxx; //extra wsp files
|
||
|
CHAR *szFileTxx; //extra tmi files
|
||
|
CHAR *szModName; //Module or DLL name
|
||
|
CHAR *szFileWSPtmp; // Temporary .WSP file name
|
||
|
CHAR *szFileTMItmp; // Temporary .TMI file name
|
||
|
ULONG clVarTot = 0; // Total number of dwords in bitstr
|
||
|
UINT uiModCount;
|
||
|
|
||
|
WSPHDR WspHdr, tmpHdr;
|
||
|
|
||
|
FILE *hFileWSP;
|
||
|
FILE *hFileTmpWSP;
|
||
|
FILE *hFileTMI;
|
||
|
FILE *hFileTmpTMI;
|
||
|
|
||
|
/*
|
||
|
* Function prototypes.
|
||
|
*/
|
||
|
VOID wspCatSetup(VOID);
|
||
|
VOID wspCatUsage(VOID);
|
||
|
VOID wspCat(VOID);
|
||
|
INT wspCatExit(INT, USHORT, UINT, ULONG, LPSTR);
|
||
|
int WspBCompare (ULONG, PULONG);
|
||
|
LONG WspBSearch (ULONG ulAddr, WSTMOD wmod);
|
||
|
|
||
|
|
||
|
/****************************** M A I N **************************************
|
||
|
*
|
||
|
* Function: main (INT argc, CHAR *argv[])
|
||
|
*
|
||
|
*
|
||
|
* Purpose: Parses command line and dumps the WSP and TMI files
|
||
|
*
|
||
|
* Usage: [d:][path]wstcat modulename
|
||
|
*
|
||
|
* where: modulename is the name of the module whose wXX files
|
||
|
* you want to concatenate.
|
||
|
*
|
||
|
* Returns: NONE
|
||
|
*
|
||
|
*****************************************************************************/
|
||
|
|
||
|
|
||
|
|
||
|
VOID __cdecl main (INT argc, CHAR *argv[])
|
||
|
{
|
||
|
|
||
|
ConvertAppToOem( argc, argv );
|
||
|
if (argc != 2) {
|
||
|
wspCatUsage();
|
||
|
exit( -1 );
|
||
|
}
|
||
|
else {
|
||
|
UINT nLen;
|
||
|
char * pDot;
|
||
|
|
||
|
if ((pDot = strrchr( argv[ 1 ], '.' )) != NULL)
|
||
|
*pDot = '\0';
|
||
|
nLen = strlen( argv[1] ) + 1;
|
||
|
|
||
|
szModName = malloc( nLen );
|
||
|
if (szModName)
|
||
|
strcpy(szModName, argv[1]);
|
||
|
else {
|
||
|
exit(1);
|
||
|
}
|
||
|
szFileWSP = malloc( nLen + 4 );
|
||
|
if (szFileWSP)
|
||
|
strcat( strcpy( szFileWSP, szModName ), ".WSP" );
|
||
|
else {
|
||
|
free(szModName);
|
||
|
exit(1);
|
||
|
}
|
||
|
szFileTMI = malloc( nLen + 4 );
|
||
|
if (szFileTMI)
|
||
|
strcat( strcpy( szFileTMI, szModName ), ".TMI" );
|
||
|
else {
|
||
|
free(szFileWSP);
|
||
|
free(szModName);
|
||
|
exit(1);
|
||
|
}
|
||
|
szFileWxx = malloc( nLen + 4 );
|
||
|
if (szFileWxx)
|
||
|
strcat( strcpy( szFileWxx, szModName ), ".Wxx" );
|
||
|
else {
|
||
|
free(szFileTMI);
|
||
|
free(szFileWSP);
|
||
|
free(szModName);
|
||
|
exit(1);
|
||
|
}
|
||
|
szFileTxx = malloc( nLen + 4 );
|
||
|
if (szFileTxx)
|
||
|
strcat( strcpy( szFileTxx, szModName ), ".Txx" );
|
||
|
else {
|
||
|
free(szFileWxx);
|
||
|
free(szFileTMI);
|
||
|
free(szFileWSP);
|
||
|
free(szModName);
|
||
|
exit(1);
|
||
|
}
|
||
|
szFileWSPtmp = malloc( nLen + 4 );
|
||
|
if (szFileWSPtmp)
|
||
|
strcat( strcpy( szFileWSPtmp, szModName ), ".Wzz" );
|
||
|
else {
|
||
|
free(szFileTxx);
|
||
|
free(szFileWxx);
|
||
|
free(szFileTMI);
|
||
|
free(szFileWSP);
|
||
|
free(szModName);
|
||
|
exit(1);
|
||
|
}
|
||
|
szFileTMItmp = malloc( nLen + 4 );
|
||
|
if (szFileTMItmp)
|
||
|
strcat( strcpy( szFileTMItmp, szModName ), ".Tzz" );
|
||
|
else {
|
||
|
free(szFileTMItmp);
|
||
|
free(szFileTxx);
|
||
|
free(szFileWxx);
|
||
|
free(szFileTMI);
|
||
|
free(szFileWSP);
|
||
|
free(szModName);
|
||
|
exit(1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Setup input files for dump processing.
|
||
|
wspCatSetup();
|
||
|
wspCat();
|
||
|
|
||
|
// Free allocated memory
|
||
|
free( szModName );
|
||
|
free( szFileWSP );
|
||
|
free( szFileTMI );
|
||
|
free( szFileWxx );
|
||
|
free( szFileTxx );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
*
|
||
|
***LP wspCatSetup
|
||
|
*
|
||
|
*
|
||
|
* Effects:
|
||
|
*
|
||
|
* Opens the module's WSP and TMI input files, seeks to the start of the
|
||
|
* first function's bitstring data in the WSP file, and allocates memory
|
||
|
* to hold one function's bitstring.
|
||
|
*
|
||
|
* Returns:
|
||
|
*
|
||
|
* Void. If an error is encountered, exits through wspCatExit()
|
||
|
* with ERROR.
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
VOID wspCatSetup(VOID)
|
||
|
{
|
||
|
ULONG ulTmp;
|
||
|
UINT uiExt = 0;
|
||
|
UINT x;
|
||
|
char * pszTmpName;
|
||
|
|
||
|
|
||
|
|
||
|
/* Open input WSP file. Read and validate WSP file header.*/
|
||
|
|
||
|
rc = WsWSPOpen(szFileWSP, &hFileWSP,(PFN)wspCatExit,
|
||
|
(wsphdr_t *)&WspHdr, ERROR, PRINT_MSG );
|
||
|
|
||
|
if(rc){
|
||
|
exit(rc);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Open a temporary tmi file to hold concatenated information.
|
||
|
// This file will be renamed to module.tmi when the cat process
|
||
|
// is complete, and the current module.tmi will be renamed to module.txx.
|
||
|
//
|
||
|
hFileTMI = fopen(szFileTMI, "rt");
|
||
|
if (!hFileTMI) {
|
||
|
wspCatExit(ERROR, PRINT_MSG, MSG_FILE_OPEN, GetLastError(), szFileTMI);
|
||
|
}
|
||
|
hFileTmpTMI = fopen(szFileTMItmp, "wt");
|
||
|
if (!hFileTmpTMI) {
|
||
|
wspCatExit(ERROR, PRINT_MSG, MSG_FILE_OPEN, GetLastError(), szFileTMItmp);
|
||
|
}
|
||
|
pszTmpName = malloc( 128 + 1 );
|
||
|
if (pszTmpName) {
|
||
|
fputs (fgets (pszTmpName, 128, hFileTMI), hFileTmpTMI);
|
||
|
fputs (fgets (pszTmpName, 128, hFileTMI), hFileTmpTMI);
|
||
|
fputs (fgets (pszTmpName, 128, hFileTMI), hFileTmpTMI);
|
||
|
fputs (fgets (pszTmpName, 128, hFileTMI), hFileTmpTMI);
|
||
|
fputs (fgets (pszTmpName, 128, hFileTMI), hFileTmpTMI);
|
||
|
free( pszTmpName );
|
||
|
}
|
||
|
fclose(hFileTMI);
|
||
|
|
||
|
//
|
||
|
// Set key, module specific information
|
||
|
//
|
||
|
clVarTot = WspHdr.ulSnaps;
|
||
|
nmod.ulSnaps = WspHdr.ulSnaps;
|
||
|
nmod.ulSetCnt = WspHdr.ulSetSymbols; // mdg 4/98
|
||
|
nmod.ulOffset = WspHdr.ulOffset;
|
||
|
|
||
|
nmod.ulFxnTot = WsTMIOpen(szFileTMI, &hFileTMI, (PFN) wspCatExit,
|
||
|
0, (PCHAR)0);
|
||
|
//
|
||
|
// Open a temporary wsp file to hold concatenated information.
|
||
|
// This file will be renamed to module.wsp when the cat process
|
||
|
// is complete, and the current module.wsp will be renamed to module.wxx.
|
||
|
// The header is also written.
|
||
|
//
|
||
|
hFileTmpWSP = fopen(szFileWSPtmp, "wb");
|
||
|
if (!hFileTmpWSP) {
|
||
|
wspCatExit(ERROR, PRINT_MSG, MSG_FILE_OPEN, GetLastError(), szFileWSPtmp);
|
||
|
}
|
||
|
WspHdr.ulOffset = sizeof(WSPHDR) + strlen( szModName ); // Set data location correctly
|
||
|
fwrite(&WspHdr, sizeof(WSPHDR), 1, hFileTmpWSP);
|
||
|
fwrite(szModName, strlen(szModName), 1, hFileTmpWSP);
|
||
|
|
||
|
//
|
||
|
// Allocate memory to hold TMI data for each Symbol in the
|
||
|
// main TMI file
|
||
|
//
|
||
|
nmod.tmi = (TMI *)malloc(nmod.ulFxnTot * sizeof(TMI));
|
||
|
if (nmod.tmi == NULL) {
|
||
|
wspCatExit(ERROR, PRINT_MSG, MSG_NO_MEM,
|
||
|
nmod.ulFxnTot * sizeof(TMI), "nmod.tmi[]");
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Read data for each symbol record in the key TMI file
|
||
|
//
|
||
|
for (x = 0; x < nmod.ulFxnTot ; x++ ) {
|
||
|
nmod.tmi[x].ulSize = WsTMIReadRec(&pszTmpName, &(nmod.tmi[x].ulIndex),
|
||
|
&(nmod.tmi[x].ulAddr), hFileTMI,
|
||
|
(PFN)wspCatExit, (PCHAR)0);
|
||
|
nmod.tmi[x].pszFxnName = pszTmpName;
|
||
|
|
||
|
}
|
||
|
|
||
|
fclose(hFileTMI);
|
||
|
|
||
|
//
|
||
|
// Get Txx and Wxx specific information
|
||
|
//
|
||
|
while(rc == NO_ERROR){
|
||
|
|
||
|
//
|
||
|
// Modify the file name to the first wxx and txx file
|
||
|
//
|
||
|
sprintf(szFileWxx, "%s.w%02d", szModName, uiExt+1);
|
||
|
sprintf(szFileTxx, "%s.t%02d", szModName, uiExt+1);
|
||
|
|
||
|
//
|
||
|
// Open file.Wxx and read header information.
|
||
|
//
|
||
|
rc = WsWSPOpen(szFileWxx, &(wmod[uiExt].hFileWxx),(PFN)wspCatExit,
|
||
|
(wsphdr_t *)&tmpHdr, NOEXIT, NO_MSG );
|
||
|
|
||
|
//
|
||
|
// Check for an error from the open command. Could be the last
|
||
|
// file.
|
||
|
//
|
||
|
if(rc == NO_ERROR){
|
||
|
|
||
|
clVarTot += tmpHdr.ulSnaps; //Increment the total number of
|
||
|
//Snapshots by the number from
|
||
|
//each data file.
|
||
|
wmod[uiExt].ulSetCnt = tmpHdr.ulSetSymbols; // mdg 4/98
|
||
|
wmod[uiExt].uiLeft = tmpHdr.ulSetSymbols; // mdg 4/98
|
||
|
wmod[uiExt].ulOffset = tmpHdr.ulOffset;
|
||
|
wmod[uiExt].ulSnaps = tmpHdr.ulSnaps;
|
||
|
wmod[uiExt].pulAddr = (ULONG *)malloc(wmod[uiExt].ulSetCnt * // mdg 4/98
|
||
|
sizeof(ULONG));
|
||
|
//
|
||
|
// Open the TMI file associated with this data file
|
||
|
//
|
||
|
WsTMIOpen(szFileTxx, &hFileTMI,(PFN)wspCatExit,
|
||
|
0, (PCHAR)0);
|
||
|
//
|
||
|
// Read each address from the TMI file.
|
||
|
//
|
||
|
if(rc == NO_ERROR){
|
||
|
for (x = 0; x < wmod[uiExt].ulSetCnt ; x++ ) { // mdg 4/98
|
||
|
WsTMIReadRec(&pszTmpName, &ulTmp, (wmod[uiExt].pulAddr)+x,
|
||
|
hFileTMI, (PFN)wspCatExit, (PCHAR)0);
|
||
|
free( pszTmpName );
|
||
|
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Increment the module index
|
||
|
//
|
||
|
uiExt++;
|
||
|
|
||
|
|
||
|
}
|
||
|
uiModCount = uiExt;
|
||
|
|
||
|
//
|
||
|
// Allocate enough memory to hold all the bit strings for each module
|
||
|
// in a single array.
|
||
|
//
|
||
|
nmod.pulBitStrings = (ULONG *) malloc(clVarTot * sizeof(ULONG));
|
||
|
|
||
|
if (nmod.pulBitStrings == NULL)
|
||
|
wspCatExit(ERROR, PRINT_MSG, MSG_NO_MEM,
|
||
|
clVarTot * sizeof(ULONG), "pulBitStrings[]");
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
*
|
||
|
***LP wspCat
|
||
|
*
|
||
|
*
|
||
|
* Effects:
|
||
|
*
|
||
|
* For each function,
|
||
|
*
|
||
|
* Returns:
|
||
|
*
|
||
|
* Void. If an error is encountered, exits through wspCatExit()
|
||
|
* with ERROR.
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
VOID wspCat(VOID)
|
||
|
{
|
||
|
UINT uiFxn = 0; // Function number.
|
||
|
UINT x = 0;
|
||
|
PULONG pulBitStrings; // Pointer to bitstring data.
|
||
|
ULONG culSnaps = 0; // Cumulative snapshots.
|
||
|
LONG lIndex = 0; // Index to WSP file.
|
||
|
BOOL fSetBits = FALSE;
|
||
|
CHAR szBuffer [256];
|
||
|
ULONG ulNewSetCnt = 0; // mdg 4/98
|
||
|
|
||
|
|
||
|
for (uiFxn = 0; uiFxn < nmod.ulFxnTot; uiFxn++)
|
||
|
{
|
||
|
|
||
|
pulBitStrings = &(nmod.pulBitStrings[0]);
|
||
|
culSnaps = nmod.ulSnaps;
|
||
|
|
||
|
//
|
||
|
// Check to see if any non-zero bit strings remain
|
||
|
//
|
||
|
if(uiFxn < nmod.ulSetCnt){ // mdg 4/98
|
||
|
//
|
||
|
// Seek to function's bitstring in WSP file.
|
||
|
// only for the first function
|
||
|
//
|
||
|
if(!uiFxn){
|
||
|
if ((rc = fseek(hFileWSP,nmod.ulOffset,SEEK_SET))!=NO_ERROR)
|
||
|
wspCatExit(ERROR, PRINT_MSG, MSG_FILE_OFFSET,
|
||
|
rc, szModName);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Read bitstring for NDX api
|
||
|
//
|
||
|
if (fread(pulBitStrings, sizeof(ULONG), nmod.ulSnaps, hFileWSP) != (sizeof(ULONG) * nmod.ulSnaps))
|
||
|
wspCatExit(ERROR, PRINT_MSG, MSG_FILE_OFFSET, 0, szModName);
|
||
|
fSetBits = TRUE;
|
||
|
}
|
||
|
//
|
||
|
// If not, set the bitstring to '0'. This is faster than seeking
|
||
|
// to each bit string when they are zero.
|
||
|
//
|
||
|
else
|
||
|
memset(pulBitStrings, '\0' , (sizeof(ULONG) * nmod.ulSnaps));
|
||
|
|
||
|
//
|
||
|
// Increment the pointer to allow for the addition of the next
|
||
|
// bitstring set
|
||
|
//
|
||
|
pulBitStrings += nmod.ulSnaps;
|
||
|
//
|
||
|
// Now search WSTMOD array for a matching Function address
|
||
|
//
|
||
|
for (x=0; x < uiModCount - 1 ; x++ ) {
|
||
|
culSnaps += wmod[x].ulSnaps;
|
||
|
//
|
||
|
// See if there are any functions that remain
|
||
|
// and if so search for them
|
||
|
//
|
||
|
if(wmod[x].uiLeft){
|
||
|
lIndex = WspBSearch(nmod.tmi[uiFxn].ulAddr, wmod[x]);
|
||
|
//
|
||
|
// If search has found a matching address, get the bitstring
|
||
|
// and append it pulBitStrings
|
||
|
//
|
||
|
if (lIndex >= 0L) {
|
||
|
|
||
|
lIndex = wmod[x].ulOffset +
|
||
|
( lIndex * (wmod[x].ulSnaps * sizeof(ULONG)));
|
||
|
|
||
|
if (rc = fseek(wmod[x].hFileWxx, lIndex, SEEK_SET) != NO_ERROR)
|
||
|
wspCatExit(ERROR, PRINT_MSG, MSG_FILE_OFFSET, rc, szModName);
|
||
|
|
||
|
if (fread(pulBitStrings, sizeof(ULONG), wmod[x].ulSnaps, wmod[x].hFileWxx) !=
|
||
|
(sizeof(ULONG) * wmod[x].ulSnaps))
|
||
|
{
|
||
|
wspCatExit(ERROR, PRINT_MSG, MSG_FILE_OFFSET, 0, szModName);
|
||
|
|
||
|
}
|
||
|
|
||
|
wmod[x].uiLeft--;
|
||
|
fSetBits = TRUE;
|
||
|
}
|
||
|
//
|
||
|
// Otherwise, set all bytes to 0
|
||
|
//
|
||
|
else{
|
||
|
memset(pulBitStrings, '\0' , (sizeof(ULONG) * wmod[x].ulSnaps));
|
||
|
}
|
||
|
}
|
||
|
//
|
||
|
// Otherwise, set all bytes to 0
|
||
|
//
|
||
|
else
|
||
|
memset(pulBitStrings, '\0' , (sizeof(ULONG) * wmod[x].ulSnaps));
|
||
|
|
||
|
//
|
||
|
// Now increment the pointer to allow for appending of additional
|
||
|
// bitstring data.
|
||
|
//
|
||
|
pulBitStrings += wmod[x].ulSnaps;
|
||
|
}
|
||
|
//
|
||
|
// Now we need to write the TMI & WSP file with the concatenated
|
||
|
// bitstring (only if set)
|
||
|
//
|
||
|
nmod.tmi[uiFxn].fSet = fSetBits;
|
||
|
if (fSetBits) {
|
||
|
ulNewSetCnt++; // 4/98
|
||
|
sprintf(szBuffer, "%ld 0000:%08lx 0x%lx %ld ",
|
||
|
(LONG)nmod.tmi[uiFxn].ulIndex, nmod.tmi[uiFxn].ulAddr,
|
||
|
nmod.tmi[uiFxn].ulSize, strlen( nmod.tmi[uiFxn].pszFxnName ));
|
||
|
fwrite(szBuffer, sizeof(char), strlen(szBuffer), hFileTmpTMI);
|
||
|
fputs( nmod.tmi[uiFxn].pszFxnName, hFileTmpTMI );
|
||
|
fputc( '\n', hFileTmpTMI );
|
||
|
fwrite(nmod.pulBitStrings, sizeof(ULONG), culSnaps, hFileTmpWSP);
|
||
|
fSetBits = FALSE;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Now write all the TMI symbols not set to the temporary .tmi file
|
||
|
//
|
||
|
memset(nmod.pulBitStrings, '\0' , (sizeof(ULONG) * culSnaps));
|
||
|
for (uiFxn = 0; uiFxn < nmod.ulFxnTot; uiFxn++) {
|
||
|
if (!nmod.tmi[uiFxn].fSet) {
|
||
|
sprintf(szBuffer, "%ld 0000:%08lx 0x%lx %ld ",
|
||
|
(LONG)nmod.tmi[uiFxn].ulIndex, nmod.tmi[uiFxn].ulAddr,
|
||
|
nmod.tmi[uiFxn].ulSize, strlen( nmod.tmi[uiFxn].pszFxnName ));
|
||
|
fwrite(szBuffer, sizeof(char), strlen(szBuffer), hFileTmpTMI);
|
||
|
fputs( nmod.tmi[uiFxn].pszFxnName, hFileTmpTMI );
|
||
|
fputc( '\n', hFileTmpTMI );
|
||
|
fwrite(nmod.pulBitStrings, sizeof(ULONG), culSnaps, hFileTmpWSP);
|
||
|
}
|
||
|
}
|
||
|
//
|
||
|
// Seek to the beginning of the WSP file and update the snapshot
|
||
|
// count in the header
|
||
|
//
|
||
|
if (!fseek(hFileTmpWSP, 0L, SEEK_SET)) {
|
||
|
WspHdr.ulSnaps = culSnaps;
|
||
|
WspHdr.ulSetSymbols = ulNewSetCnt; // mdg 4/98
|
||
|
fprintf(stdout,"Set symbols: %lu\n", WspHdr.ulSetSymbols); // mdg 4/98
|
||
|
fwrite(&WspHdr, sizeof(WSPHDR), 1, hFileTmpWSP);
|
||
|
}
|
||
|
_fcloseall();
|
||
|
|
||
|
//
|
||
|
// Rename the non-cat'd .wsp file and rename the cat'd temporary .wsp
|
||
|
// to the original .wsp. We might also consider deleting all the
|
||
|
// Wxx and Txx files.
|
||
|
//
|
||
|
sprintf (szFileWxx, "%s.%s", szModName, "WSP");
|
||
|
sprintf (szFileTxx, "%s.%s", szModName, "WXX");
|
||
|
remove(szFileTxx);
|
||
|
if (rename(szFileWxx, szFileTxx) !=0){
|
||
|
printf("Unable to rename file %s to %s\n", szFileWxx, szFileTxx);
|
||
|
}
|
||
|
else{
|
||
|
if (rename(szFileWSPtmp, szFileWSP) !=0){
|
||
|
printf ("Unable to rename %s to %s!\n", szFileWSPtmp, szFileWxx);
|
||
|
}
|
||
|
}
|
||
|
//
|
||
|
// Rename the non-cat'd .tmi file and rename the cat'd temporary .tmi
|
||
|
// to the original .tmi. We might also consider deleting all the
|
||
|
// Wxx and Txx files.
|
||
|
//
|
||
|
sprintf (szFileWxx, "%s.%s", szModName, "TMI");
|
||
|
sprintf (szFileTxx, "%s.%s", szModName, "TXX");
|
||
|
remove(szFileTxx);
|
||
|
if (rename(szFileWxx, szFileTxx) !=0){
|
||
|
printf("Unable to rename file %s to %s\n", szFileWxx, szFileTxx);
|
||
|
}
|
||
|
else{
|
||
|
if (rename(szFileTMItmp, szFileTMI) !=0){
|
||
|
printf ("Unable to rename %s to %s!\n", szFileTMItmp, szFileWxx);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
*
|
||
|
* wspCatUsage
|
||
|
*
|
||
|
*
|
||
|
* Effects:
|
||
|
*
|
||
|
* Prints out usage message, and exits with an error.
|
||
|
*
|
||
|
* Returns:
|
||
|
*
|
||
|
* Exits with ERROR.
|
||
|
*/
|
||
|
|
||
|
VOID wspCatUsage(VOID)
|
||
|
{
|
||
|
printf("\nUsage: %s moduleName[.WSP]\n\n", MODULE);
|
||
|
printf(" \"moduleName\" is the name of the module file to combine.\n\n");
|
||
|
printf("%s %s\n", MODULE, VERSION);
|
||
|
|
||
|
exit(ERROR);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
*
|
||
|
***LP wspCatExit
|
||
|
*
|
||
|
*
|
||
|
***
|
||
|
*
|
||
|
* Effects:
|
||
|
*
|
||
|
* Frees up resources (as necessary). Exits with the specified
|
||
|
* exit code, or returns void if exit code is NOEXIT.
|
||
|
*
|
||
|
***
|
||
|
* Returns:
|
||
|
*
|
||
|
* Void, else exits.
|
||
|
*/
|
||
|
|
||
|
INT wspCatExit(INT iExitCode, USHORT fPrintMsg, UINT uiMsgCode,
|
||
|
ULONG ulParam1, LPSTR pszParam2)
|
||
|
{
|
||
|
/* Print message, if necessary. */
|
||
|
if (fPrintMsg)
|
||
|
{
|
||
|
printf(pchMsg[uiMsgCode], MODULE, VERSION , ulParam1, pszParam2);
|
||
|
}
|
||
|
|
||
|
|
||
|
// Special case: do NOT exit if called with NOEXIT.
|
||
|
if (iExitCode != NOEXIT)
|
||
|
exit(iExitCode);
|
||
|
return(uiMsgCode);
|
||
|
}
|
||
|
|
||
|
/*********************** W s p B S e a r c h *******************************
|
||
|
*
|
||
|
* Function: WspBSearch(ULONG ulAddr, PULONG pulAddr)
|
||
|
*
|
||
|
* Purpose: Binary search function for finding a match in the WST array
|
||
|
*
|
||
|
*
|
||
|
* Parameters:
|
||
|
*
|
||
|
*
|
||
|
*
|
||
|
* Returns: ULONG lIndex;
|
||
|
*
|
||
|
* History: 8-5-92 Marklea - created
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
LONG WspBSearch (ULONG ulAddr, WSTMOD wmod)
|
||
|
{
|
||
|
int i;
|
||
|
// ULONG ulHigh = (ULONG)wmod.usSetCnt;
|
||
|
ULONG ulHigh = (ULONG)wmod.ulSetCnt; // mdg 4/98
|
||
|
ULONG ulLow = 0;
|
||
|
ULONG ulMid;
|
||
|
|
||
|
|
||
|
while(ulLow < ulHigh){
|
||
|
ulMid = ulLow + (ulHigh - ulLow) /2;
|
||
|
if((i = WspBCompare(ulAddr, wmod.pulAddr+ulMid)) < 0) {
|
||
|
ulHigh = ulMid;
|
||
|
}
|
||
|
else if (i > 0) {
|
||
|
ulLow = ulMid + 1;
|
||
|
}
|
||
|
else {
|
||
|
return (ulMid);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
return (-1L);
|
||
|
|
||
|
} /* WspBSearch () */
|
||
|
|
||
|
/*********************** W s p B C o m p a r e ********************************
|
||
|
*
|
||
|
* Function: WspBCompare(ULONG ulAddr, PULONG pulAddr)
|
||
|
*
|
||
|
* Purpose: Compare values for Binary search
|
||
|
*
|
||
|
*
|
||
|
* Parameters:
|
||
|
*
|
||
|
* Returns: -1 if val1 < val2
|
||
|
* 1 if val1 > val2
|
||
|
* 0 if val1 == val2
|
||
|
*
|
||
|
* History: 8-3-92 Marklea - created
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
int WspBCompare(ULONG ulAddr, PULONG pulAddr)
|
||
|
{
|
||
|
return (ulAddr < *pulAddr ? -1:
|
||
|
ulAddr == *pulAddr ? 0:
|
||
|
1);
|
||
|
|
||
|
} /* WspBCompare () */
|
||
|
|