258 lines
6.9 KiB
C
258 lines
6.9 KiB
C
|
/*** impexp.c - Import/Export module - implementation
|
||
|
*
|
||
|
* Copyright <C> 1992, Microsoft Corporation
|
||
|
*
|
||
|
* This module contains proprietary information of Microsoft
|
||
|
* Corporation and should be treated as confidential.
|
||
|
*
|
||
|
* Purpose:
|
||
|
* Build and write segmented-executable import/export tables
|
||
|
*
|
||
|
* Revision History:
|
||
|
*
|
||
|
* 29-May-1992 Wieslaw Kalkus Created
|
||
|
*
|
||
|
*************************************************************************/
|
||
|
|
||
|
#include <minlit.h>
|
||
|
#include <bndtrn.h>
|
||
|
#include <bndrel.h>
|
||
|
#include <lnkio.h>
|
||
|
#include <newexe.h>
|
||
|
#include <lnkmsg.h>
|
||
|
#include <extern.h>
|
||
|
#include <string.h>
|
||
|
#include <impexp.h>
|
||
|
|
||
|
//
|
||
|
// Functions operating on dynamic byte arrays
|
||
|
//
|
||
|
|
||
|
void InitByteArray(DYNBYTEARRAY *pArray)
|
||
|
{
|
||
|
pArray->byteMac = 0;
|
||
|
pArray->byteMax = DEF_BYTE_ARR_SIZE;
|
||
|
pArray->rgByte = GetMem(DEF_BYTE_ARR_SIZE);
|
||
|
}
|
||
|
|
||
|
void FreeByteArray(DYNBYTEARRAY *pArray)
|
||
|
{
|
||
|
FFREE(pArray->rgByte);
|
||
|
pArray->byteMac = 0;
|
||
|
pArray->byteMax = 0;
|
||
|
}
|
||
|
|
||
|
WORD ByteArrayPut(DYNBYTEARRAY *pArray, WORD size, BYTE *pBuf)
|
||
|
{
|
||
|
BYTE FAR *pTmp;
|
||
|
WORD idx;
|
||
|
|
||
|
if ((DWORD)(pArray->byteMac) + size > 0xFFFE)
|
||
|
Fatal(ER_memovf);
|
||
|
|
||
|
if ((WORD) (pArray->byteMac + size) >= pArray->byteMax)
|
||
|
{
|
||
|
// Realloc array
|
||
|
if(pArray->byteMax < 0xffff/2)
|
||
|
pArray->byteMax <<= 1;
|
||
|
else
|
||
|
while (pArray->byteMac + size >= pArray->byteMax)
|
||
|
pArray->byteMax += (0x10000 - pArray->byteMax) / 2;
|
||
|
pArray->rgByte = REALLOC(pArray->rgByte,pArray->byteMax);
|
||
|
if(!pArray->rgByte)
|
||
|
Fatal(ER_memovf);
|
||
|
ASSERT (pArray->byteMax > pArray->byteMac + size);
|
||
|
}
|
||
|
idx = pArray->byteMac;
|
||
|
pTmp = &(pArray->rgByte[idx]);
|
||
|
FMEMCPY(pTmp, pBuf, size);
|
||
|
pArray->byteMac += size;
|
||
|
return(idx);
|
||
|
}
|
||
|
|
||
|
void WriteByteArray(DYNBYTEARRAY *pArray)
|
||
|
{
|
||
|
WriteExe(pArray->rgByte, pArray->byteMac);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Functions operating on dynamic word arrays
|
||
|
//
|
||
|
|
||
|
void InitWordArray(DYNWORDARRAY *pArray)
|
||
|
{
|
||
|
pArray->wordMac = 0;
|
||
|
pArray->wordMax = DEF_WORD_ARR_SIZE;
|
||
|
pArray->rgWord = (WORD FAR *) GetMem(DEF_WORD_ARR_SIZE * sizeof(WORD));
|
||
|
}
|
||
|
|
||
|
void FreeWordArray(DYNWORDARRAY *pArray)
|
||
|
{
|
||
|
FFREE(pArray->rgWord);
|
||
|
pArray->wordMac = 0;
|
||
|
pArray->wordMax = 0;
|
||
|
}
|
||
|
|
||
|
WORD WordArrayPut(DYNWORDARRAY *pArray, WORD val)
|
||
|
{
|
||
|
WORD FAR *pTmp;
|
||
|
WORD idx;
|
||
|
|
||
|
if ((WORD) (pArray->wordMac + 1) >= pArray->wordMax)
|
||
|
{
|
||
|
// Realloc array
|
||
|
|
||
|
pTmp = (WORD FAR *) GetMem((pArray->wordMax << 1) * sizeof(WORD));
|
||
|
FMEMCPY(pTmp, pArray->rgWord, pArray->wordMac * sizeof(WORD));
|
||
|
FFREE(pArray->rgWord);
|
||
|
pArray->rgWord = pTmp;
|
||
|
pArray->wordMax <<= 1;
|
||
|
}
|
||
|
idx = pArray->wordMac;
|
||
|
pArray->rgWord[idx] = val;
|
||
|
pArray->wordMac++;
|
||
|
return(idx);
|
||
|
}
|
||
|
|
||
|
void WriteWordArray(DYNWORDARRAY *pArray)
|
||
|
{
|
||
|
WriteExe(pArray->rgWord, pArray->wordMac*sizeof(WORD));
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// IMPORT/EXPORT tables
|
||
|
//
|
||
|
|
||
|
DYNBYTEARRAY ResidentName;
|
||
|
DYNBYTEARRAY NonResidentName;
|
||
|
DYNBYTEARRAY ImportedName;
|
||
|
DYNWORDARRAY ModuleRefTable;
|
||
|
DYNBYTEARRAY EntryTable;
|
||
|
|
||
|
//
|
||
|
// Functions adding names to tables
|
||
|
//
|
||
|
|
||
|
void AddName(DYNBYTEARRAY *pTable, BYTE *sbName, WORD ord)
|
||
|
{
|
||
|
WORD cb;
|
||
|
|
||
|
cb = sbName[0] + 1 + sizeof(WORD);
|
||
|
if ((WORD)(0xFFFE - pTable->byteMac) < cb)
|
||
|
{
|
||
|
if (pTable == &ResidentName)
|
||
|
Fatal(ER_resovf);
|
||
|
else
|
||
|
Fatal(ER_nresovf);
|
||
|
}
|
||
|
ByteArrayPut(pTable, (WORD) (sbName[0] + 1), sbName);
|
||
|
ByteArrayPut(pTable, sizeof(WORD), (BYTE *) &ord);
|
||
|
}
|
||
|
|
||
|
|
||
|
WORD AddImportedName(BYTE *sbName)
|
||
|
{
|
||
|
if ((WORD) (0xfffe - ImportedName.byteMac) < (WORD) (sbName[0] + 1))
|
||
|
Fatal(ER_inamovf);
|
||
|
return(ByteArrayPut(&ImportedName, (WORD) (sbName[0] + 1), sbName));
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Function adding entries to the Entry Table
|
||
|
//
|
||
|
|
||
|
WORD AddEntry(BYTE *entry, WORD size)
|
||
|
{
|
||
|
if ((WORD)(EntryTable.byteMax + size) < EntryTable.byteMax)
|
||
|
Fatal(ER_etovf);
|
||
|
return (ByteArrayPut(&EntryTable, size, entry));
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* This function writes either the resident or nonresident names table
|
||
|
* to a file f. If targeting Windows it also converts the names
|
||
|
* to upper case.
|
||
|
*/
|
||
|
|
||
|
void WriteNTable(DYNBYTEARRAY *pArray, FILE *f)
|
||
|
{
|
||
|
BYTE *p;
|
||
|
WORD *pOrd; // points to the ordinal
|
||
|
WORD Ord; // ordinal value
|
||
|
int i;
|
||
|
p = pArray->rgByte;
|
||
|
#if DEBUG_EXP
|
||
|
for( i = 0; i<pArray->byteMac; i++)
|
||
|
{
|
||
|
fprintf(stdout, "\r\n%d : %d(%c) ", i, *(p+i), *(p+i));
|
||
|
fflush(stdout);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
while(p[0]) // Until names left
|
||
|
{
|
||
|
if(f) // If writing to a file
|
||
|
{
|
||
|
pOrd = (WORD*)(p+p[0]+1);
|
||
|
Ord = *pOrd;
|
||
|
#if DEBUG_EXP
|
||
|
fprintf(stdout, "\r\np[0]=%d, p[1]=%d Ord = %d", p[0], p[1], Ord);
|
||
|
#endif
|
||
|
if(Ord) // Don't output module name/description
|
||
|
{
|
||
|
*pOrd = 0;
|
||
|
fprintf(f, "\r\n %s @%d", p+1, Ord);
|
||
|
*pOrd = Ord;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Windows loader requires both res-and nonresident name tables in uppercase
|
||
|
// If fIgnoreCase is TRUE, the names are already converted by SavExp2
|
||
|
|
||
|
if(!fIgnoreCase && TargetOs == NE_WINDOWS)
|
||
|
SbUcase(p); // Make upper case
|
||
|
p += p[0] + sizeof(WORD) + 1; // Advance to the next name
|
||
|
}
|
||
|
}
|
||
|
/*
|
||
|
* This function converts the res- and nonresident name symbols
|
||
|
* to uppercase (when targeting Windows). On user request it also
|
||
|
* writes all the names to a text file, that can later be included
|
||
|
* in the user's .def file. This frees the user from the need of
|
||
|
* manually copying the decorated names from the .map file.
|
||
|
*/
|
||
|
|
||
|
void ProcesNTables( char *pName)
|
||
|
{
|
||
|
FILE *f = NULL;
|
||
|
int i;
|
||
|
#if DEBUG_EXP
|
||
|
fprintf(stdout, "\r\nOutput file name : %s ", psbRun);
|
||
|
#endif
|
||
|
if(pName[0]) // user requested export file
|
||
|
{
|
||
|
if(pName[0] == '.') // use the default name
|
||
|
{
|
||
|
for(i=0; i< _MAX_PATH; i++)
|
||
|
{
|
||
|
if((pName[i] = psbRun[i]) == '.')
|
||
|
{
|
||
|
pName[i+1] = '\0';
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
strcat(pName, "EXP"); // the default name is 'DLLNAME'.EXP
|
||
|
}
|
||
|
#if DEBUG_EXP
|
||
|
fprintf(stdout, "\r\nEXPORT FILE : %s ", pName+1);
|
||
|
#endif
|
||
|
if((f = fopen(pName+1, WRBIN)) == NULL)
|
||
|
OutError(ER_openw, pName);
|
||
|
}
|
||
|
|
||
|
WriteNTable(&ResidentName, f);
|
||
|
WriteNTable(&NonResidentName, f);
|
||
|
|
||
|
fclose(f);
|
||
|
}
|