home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
DEF.ZIP
/
DEF.C
< prev
next >
Wrap
C/C++ Source or Header
|
1989-11-24
|
21KB
|
610 lines
/*****************************************************************************
NAME: DEF.C
DESCRIPTION: This module will re-create a module definition file (DEF)
for the indicated EXE file.
Output is sent to STDOUT and may be redirected.
Still To Do:
- go out to the entry table for STACKPARAMS on
IOPL segments
- better error checking
- cleanup
ASSUMPTIONS: 1. Program doesn't import more than 1000 items
2. The program is in a valid format
3. The program was built with at least 1.1 SDK
4. The internal name for a given import is the same
as that used by the exporter.
WARNINGS: This program is fresh out of the oven. I have not done
exhaustive testing with it...
If you find any bugs or know of a better way to do
something, I'd appreciate hearing from you.
My testing consisted of...
FOR %1 in (\os2\*.exe) DO DEF %1
FOR %1 in (\os2\dll*.dll) DO DEF %1
FOR %1 in (\os2\*.sys) DO DEF %1
...none of which generated GP faults anyway.
This program *definitely* needs to be upgraded to 1.2
but this is a four day weekend and the building is locked.
REFERENCES: Advanced OS/2 Programming - Ray Duncan
PCMagnet - Charles Petzold
AUTHOR: Charlie Schmitt
11/24/89
PCMagnet ID 70022, 773
*****************************************************************************/
/*****************************************************************************
I N C L U D E F I L E S
*****************************************************************************/
#define INCL_DOS
#define INCL_WIN
#include <os2.h>
#include <stdio.h>
#include <string.h>
#include "def.h"
#include "dosexprt.h"
/*****************************************************************************
D E F I N I T I O N S
*****************************************************************************/
#define LIBRARY 0x8000
#define IsLibrary() (new_exe.flags & LIBRARY)
/*****************************************************************************
G L O B A L D A T A
*****************************************************************************/
HAB hab;
NEW_EXE new_exe; /* new exe header */
OLD_EXE old_exe; /* old exe header */
ULONG ulFilePtr; /* current file position */
USHORT cbBytes; /* number of bytes moved */
USHORT rc; /* return code */
HFILE hf; /* file handle */
USHORT usAction; /* UNUSED, required for DosOpen */
CHAR *file=__FILE__; /* for use with error_exit() */
SEL selImptab; /* imported names table selector */
CHAR *imptab; /* imported names table ptr */
USHORT imptab_size; /* size of imported names table */
ULONG imptab_offset; /* location of imported names table */
SEL selRestab; /* resident names table selector */
CHAR *restab; /* resident names table ptr */
USHORT restab_size; /* size of resident names table */
ULONG restab_offset; /* location of resident names table */
SEL selSegtab; /* segment table selector */
CHAR *segtab; /* segment table ptr */
USHORT segtab_size; /* size of segment table */
ULONG segtab_offset; /* location of segment table */
SEL selNRestab; /* non-resident names table selector */
CHAR *nrestab; /* non-resident names table ptr */
USHORT nrestab_size; /* size of non-resident names table */
ULONG nrestab_offset; /* loc. of non-resident names table */
SEL selModtab; /* module reference table selector */
USHORT *modtab; /* module reference table ptr */
USHORT modtab_size; /* size of module reference table */
ULONG modtab_offset; /* loc. of module reference table */
SEL selReloctab; /* relocation table selector */
PIMP_ORD reloctab; /* relocation table pointer */
USHORT reloctab_size; /* size of relocation table */
ULONG reloctab_offset; /* loc. of relocation table */
CHAR szName[256]; /* generic name */
CHAR szComment[256]; /* import table comment */
CHAR *p; /* work pointer */
CHAR szTmp[256]; /* work buffer */
CHAR szAtomName[256]; /* atom name string */
USHORT i,j,k,l; /* work var */
PNEW_SEG pseg_entry; /* ptr to a segment table entry */
USHORT flag; /* another work var. */
PUSHORT iptr; /* pointer to an int */
HATOMTBL hAtomTbl; /* atom table handle */
ATOM atom, atomDOS;
/*****************************************************************************
main()
*****************************************************************************/
void main(USHORT argc, CHAR *argv[])
{
USHORT code_segs, data_segs;
USHORT num_relocs;
ULONG ulLong;
USHORT usAppType;
if (argc != 2)
{
fprintf(stderr, "Usage: def <fspec>\n");
DosExit(EXIT_PROCESS, 0);
}
/***** SETCOM40 brought us here !! *****/
if (rc=DosQAppType(argv[1], &usAppType))
error_exit(rc, "DosQAppType", __LINE__, file);
if (usAppType == 32)
{
fprintf(stderr, "Specified file is not valid EXE\n");
DosExit(EXIT_PROCESS, 0);
}
/***** Open the specified executable *****/
if (rc=DosOpen(argv[1], &hf, &usAction, 0L, FILE_READONLY, FILE_OPEN,
OPEN_SHARE_DENYWRITE, 0L))
error_exit(rc, "DosOpen", __LINE__, file);
/***** Read in the old exe header information *****/
if (rc=DosRead(hf, &old_exe, sizeof(old_exe), &cbBytes))
error_exit(rc, "DosRead", __LINE__, file);
/***** Perform some crude validation *****/
if ( (old_exe.magic != 0x5a4d) || (old_exe.lfanew == 0L) )
{
fprintf(stderr, "Specified file is not valid EXE\n");
DosExit(EXIT_PROCESS, 0);
}
/***** Isolate the new exe header information *****/
if (rc=DosChgFilePtr(hf, old_exe.lfanew, FILE_BEGIN, &ulFilePtr))
error_exit(rc, "DosChgFilePtr", __LINE__, file);
/***** Read in the new exe header *****/
if (rc=DosRead(hf, &new_exe, sizeof(new_exe), &cbBytes))
error_exit(rc, "DosRead", __LINE__, file);
/***** Perform some crude validation *****
if (new_exe.magic != 0x454e)
{
fprintf(stderr, "Specified file is not valid EXE\n");
DosExit(EXIT_PROCESS, 0);
}
/***** Allocate and read in the Imported Names Table *****/
CreateTable(hf, imptab_size = new_exe.enttab - new_exe.imptab,
imptab_offset = old_exe.lfanew + (long)new_exe.imptab,
&imptab, &selImptab);
/***** Allocate and read in the Resident Name Table *****/
CreateTable(hf, restab_size = new_exe.modtab - new_exe.restab,
restab_offset = old_exe.lfanew + (long)new_exe.restab,
&restab, &selRestab);
/***** Allocate and read in the Non-Resident Names Table *****/
CreateTable(hf, nrestab_size = new_exe.cbnrestab,
nrestab_offset = new_exe.nrestab,
&nrestab, &selNRestab);
/***** Allocate and read in the Segment Table *****/
CreateTable(hf, segtab_size = new_exe.rsrctab - new_exe.segtab,
segtab_offset = old_exe.lfanew + (long)new_exe.segtab,
&segtab, &selSegtab);
/***** Allocate and read in the Module Reference Table *****/
CreateTable(hf, modtab_size = new_exe.imptab - new_exe.modtab,
modtab_offset = old_exe.lfanew + (long)new_exe.modtab,
(CHAR **)&modtab, &selModtab);
/***** Get the module name *****/
/***** SETCOM40.EXE reports 0 here (?) *****/
if (restab_size)
getstring(restab, 0, szName);
else
strcpy(szName, "NONAME");
printf("; %s.DEF\n\n", szName);
/***** Output appropriate first line *****/
if (IsLibrary())
{
p = (new_exe.flags & 0x0004) ? "INITINSTANCE" : "INITGLOBAL";
printf("%-14s %-14s %s\n", "LIBRARY", szName, p);
}
else
{
p = "UKNOWN";
if (new_exe.flags & 0x0700)
{
i = (new_exe.flags >> 8) & 0x03;
if (i == 3)
p = "WINDOWAPI";
else if (i == 2)
p = "WINDOWCOMPAT";
else
p = "NOTWINDOWCOMPAT";
}
printf("%-14s %-14s %s\n", "NAME", szName, p);
}
/***** Now let's get the Description *****/
if (nrestab_size)
getstring(nrestab, 0, szName);
else
strcpy(szName, "NO DESCRIPTION");
printf("%-14s '%s'\n", "DESCRIPTION", szName);
/***** Output appropriate mode *****/
/***** NOTE: REALMODE really means both... *****/
p = (new_exe.flags & 0x0008) ? "PROTMODE" : "REALMODE";
printf("%s\n", p);
/***** Output DATA *****/
flag = new_exe.flags & 0x0003;
if (flag == 0)
p = "NONE";
else if (flag == 1)
p = "SINGLE";
else if (flag == 2)
p = "MULTIPLE";
printf("%-14s %s\n", "DATA", p);
/***** Output STACKSIZE *****/
printf("%-14s %u\n", "STACKSIZE", new_exe.stack);
/***** Output HEAPSIZE *****/
printf("%-14s %u\n", "HEAPSIZE", new_exe.heap);
/***** Output Operating System Type *****/
if (new_exe.exetyp == 1)
p = "OS2";
else if (new_exe.exetyp == 2)
p = "WINDOWS";
else
p = "MSDOS4";
printf("%-14s %s\n", "EXETYPE", p);
/***** It's time for the Segments *****/
printf("\nSEGMENTS\n");
code_segs = data_segs = 0; /* init counters */
for (i=0; i < (segtab_size / sizeof(NEW_SEG)); i++)
{
pseg_entry = getsegment((PNEW_SEG)segtab, i);
flag = pseg_entry->flags;
if (flag & 0x0001) /* DATA */
{
if (data_segs == 0)
strcpy(szName, "_DATA");
else
sprintf(szName, "_DATA%u", data_segs);
printf("\t%-8s CLASS 'DATA' ", szName);
strcpy(szName, (flag & 0x0010) ? " MOVEABLE" : " FIXED");
strcat(szName, (flag & 0x0020) ? " SHARED" : " NONSHARED");
strcat(szName, (flag & 0x0040) ? " PRELOAD" : " LOADONCALL");
strcat(szName, (flag & 0x0080) ? " READONLY" : " READWRITE");
strcat(szName, !(flag & 0x0800) ? " IOPL" : " NOIOPL");
strcat(szName, (flag & 0x1000) ? " DISCARDABLE" : " NONDISCARDABLE");
data_segs++;
}
else /* CODE */
{
if (code_segs == 0)
strcpy(szName, "_TEXT");
else
sprintf(szName, "_TEXT%u", code_segs);
printf("\t%-8s CLASS 'CODE' ", szName);
strcpy(szName, (flag & 0x0010) ? " MOVEABLE" : " FIXED");
strcat(szName, (flag & 0x0020) ? " PURE" : " IMPURE");
strcat(szName, (flag & 0x0040) ? " PRELOAD" : " LOADONCALL");
strcat(szName, (flag & 0x0080) ? " EXECUTEONLY" : " EXECUTEREAD");
strcat(szName, (flag & 0x0200) ? " CONFORMING" : " NONCONFORMING");
strcat(szName, !(flag & 0x0800) ? " IOPL" : " NOIOPL");
strcat(szName, (flag & 0x1000) ? " DISCARDABLE" : " NONDISCARDABLE");
code_segs++;
}
/***** Kind of a Kludge *****/
if (strlen(szName) > 49)
{
for (j=49; j; j--)
if (szName[j] == ' ')
break;
szName[j] = '\0';
printf("%s\n", szName);
printf("%30s %s\n", " ", &szName[j+1]);
}
else
printf("%s\n", szName);
}
/***** It's time for the Exports *****/
printf("\nEXPORTS\n");
/***** First let's do the Resident Names Table *****/
p = restab;
p += *p + 3; /* bypass the first entry */
while (p < restab + restab_size - 1)
{
getstring(p, 0, szName); /* grab entry name */
p += *p + 1; /* bypass the length */
iptr = (USHORT *)p; /* grab the ordinal */
printf("\t%-30s @%-3u RESIDENTNAME\n", szName, *iptr);
p += 2; /* move on to next table entry */
}
/***** Now the Non-Resident Names Table *****/
p = nrestab;
p += *p + 3; /* bypass the first entry */
while (p < nrestab + nrestab_size - 1)
{
getstring(p, 0, szName); /* grab entry name */
p += *p + 1; /* bypass the length */
iptr = (USHORT *)p; /* grab the ordinal */
printf("\t%-30s @%u\n", szName, *iptr);
p += 2; /* move on to next table entry */
}
/////////////////// NEED STACK PARAMS ///////////////////////////
/***** It's time for the Imports *****/
/***** The atom table will prevent dups *****/
hAtomTbl = WinCreateAtomTable(0, 1000);
if (hAtomTbl == NULL)
error_exit(0, "WinCreateAtomTable", __LINE__, file);
/***** Build string lookup tables *****/
BuildImportedInfoTable();
/***** Add DOSCALLS for DosCallsTbl[] lookup *****/
if (!(atomDOS = WinAddAtom(hAtomTbl, "DOSCALLS")))
error_exit(0, "WinAddAtom", __LINE__, file);
printf("\nIMPORTS\n");
for (i=0; i < (segtab_size / sizeof(NEW_SEG)); i++)
{
pseg_entry = getsegment((PNEW_SEG)segtab, i);
if (pseg_entry->cbseg == 0)
continue; /* nothing to parse */
if (pseg_entry->flags & 0x0001)
continue; /* data */
if (!(pseg_entry->flags & 0x0100))
continue; /* no reloc information */
/***** Isolate the segment's reloc information *****/
ulLong = pseg_entry->sector * (ULONG)(1 << new_exe.calign);
if (rc=DosChgFilePtr(hf, ulLong + pseg_entry->cbseg,
FILE_BEGIN, &ulFilePtr))
error_exit(rc, "DosChgFilePtr", __LINE__, file);
/***** Read in the number of entries in the table *****/
if (rc=DosRead(hf, &num_relocs, sizeof(num_relocs), &cbBytes))
error_exit(rc, "DosRead", __LINE__, file);
if (num_relocs == 0)
continue; /* double check */
if (rc=DosAllocSeg(cbBytes = num_relocs * sizeof(IMP_ORD),
&selReloctab, 0))
error_exit(rc, "DosAllocSeg", __LINE__, file);
reloctab = MAKEP(selReloctab, 0);
if (rc=DosRead(hf, reloctab, cbBytes, &cbBytes))
error_exit(rc, "DosRead", __LINE__, file);
/***** Step down the relocation table *****/
for (j=0; j<num_relocs; j++, reloctab++)
{
if (reloctab->id == 0 || reloctab->id == 4)
continue;
l = reloctab->index;
k = modtab[l-1];
getstring(imptab + k, 0, szName);
/***** Is the DLL DOSCALLS ? *****/
p = "UNKNOWN";
if (atomDOS == WinFindAtom(hAtomTbl, szName))
{
if (reloctab->ordinal <= DOS_TABLE_ENTRIES)
p = DosCallsTbl[reloctab->ordinal].name;
}
else
{
p = TableLookup(szName, reloctab->ordinal);
}
/***** Create the import string *****/
if (reloctab->id == 1 || reloctab->id == 5)
{
sprintf(szAtomName, "%-29s= %s.%u", p, szName, reloctab->ordinal);
}
else
{
getstring(imptab + reloctab->ordinal, 0, szTmp);
sprintf(szAtomName, "%s.%s", szName, szTmp);
}
/***** Only output import if original *****/
if (!WinFindAtom(hAtomTbl, szAtomName))
{
printf("\t%s\n", szAtomName);
if (!WinAddAtom(hAtomTbl, szAtomName))
error_exit(0, "WinAddAtom", __LINE__, file);
}
}
/***** DOne with this buffer, go get another *****/
if (rc=DosFreeSeg(selReloctab))
error_exit(rc, "DosFreeSeg", __LINE__, file);
}
/***** Having a problem with this call *****/
// if (WinDestroyAtomTable(hAtomTbl))
// error_exit(0, "WinDestroyAtomTable", __LINE__, file);
/***** Cleanup *****/
/***** Free string lookup tables *****/
FreeImportedInfoTable();
if (selModtab)
if (rc=DosFreeSeg(selModtab))
error_exit(rc, "DosFreeSeg", __LINE__, file);
if (selSegtab)
if (rc=DosFreeSeg(selSegtab))
error_exit(rc, "DosFreeSeg", __LINE__, file);
if (selNRestab)
if (rc=DosFreeSeg(selNRestab))
error_exit(rc, "DosFreeSeg", __LINE__, file);
if (selRestab)
if (rc=DosFreeSeg(selRestab))
error_exit(rc, "DosFreeSeg", __LINE__, file);
if (selImptab)
if (rc=DosFreeSeg(selImptab))
error_exit(rc, "DosFreeSeg", __LINE__, file);
if (rc=DosClose(hf))
error_exit(rc, "DosClose", __LINE__, file);
/***** Make sure OS/2 1.2 flushs STDOUT properly when redirected ! *****/
fclose(stdout);
DosExit(EXIT_PROCESS, 0);
}
/*****************************************************************************
CreateTable()
*****************************************************************************/
VOID CreateTable(HFILE hf, USHORT size, ULONG offset, CHAR **table, PSEL sel)
{
if (size != 0)
{
if (rc=DosChgFilePtr(hf, offset, FILE_BEGIN, &ulFilePtr))
error_exit(rc, "DosChgFilePtr", __LINE__, file);
if (rc=DosAllocSeg(size, sel, 0))
error_exit(rc, "DosAllocSeg", __LINE__, file);
*table = MAKEP(*sel, 0);
if (rc=DosRead(hf, *table, size, &cbBytes))
error_exit(rc, "DosRead", __LINE__, file);
}
return;
}
/*****************************************************************************
getstring()
*****************************************************************************/
void getstring(CHAR *table, USHORT num, CHAR *buf)
{
USHORT i, len;
/***** Scan thru table of counted strings and return 'num' entry *****/
for (i=0; ; i++)
{
len = *table++; /* get the string's size */
if (i==num) /* out if this is the one we want */
break;
table += len; /* move on to next table entry */
}
strncpy(buf, table, len); /* copy entry to supplied buffer */
*(buf + len) = '\0'; /* make it ASCIIZ */
return;
}
/*****************************************************************************
getsegment()
*****************************************************************************/
PNEW_SEG getsegment(PNEW_SEG table, USHORT num)
{
USHORT i;
/***** Loops thru the segment table till num entry *****/
for (i=0; i < num; i++)
table++;
return(table);
}
/*****************************************************************************
error_exit()
*****************************************************************************/
void error_exit(USHORT err, CHAR *msg, USHORT line, CHAR *file)
{
fprintf(stderr, "FILE: %s LINE: %u - Error %u returned from %s\n",
file, line, err, msg);
DosExit(EXIT_PROCESS, 0);
}
/*****************************************************************************
E N D
*****************************************************************************/