windows-nt/Source/XPSP1/NT/sdktools/link16/impexp.c
2020-09-26 16:20:57 +08:00

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);
}