tiny_impdef.c - converted to LF line-endings (and slight cleanup)

This commit is contained in:
grischka 2007-12-09 18:55:18 +00:00
parent f99d3de221
commit b0d40c12da

View file

@ -1,372 +1,393 @@
/* -------------------------------------------------------------- */ /* -------------------------------------------------------------- */
/* /*
"tiny_impdef creates a .def file from a dll" * tiny_impdef creates an export definition file (.def) from a dll
* on MS-Windows. Usage: tiny_impdef library.dll [-o outputfile]"
"Usage: tiny_impdef [-p] <library.dll> [-o outputfile]" *
"Options:" * Copyright (c) 2005,2007 grischka
" -p print to stdout" *
*/ * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
#include <windows.h> * the Free Software Foundation; either version 2 of the License, or
#include <stdio.h> * (at your option) any later version.
*
/* Offset to PE file signature */ * This program is distributed in the hope that it will be useful,
#define NTSIGNATURE(a) ((LPVOID)((BYTE *)a + \ * but WITHOUT ANY WARRANTY; without even the implied warranty of
((PIMAGE_DOS_HEADER)a)->e_lfanew)) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
/* MS-OS header identifies the NT PEFile signature dword; *
the PEFILE header exists just after that dword. */ * You should have received a copy of the GNU General Public License
#define PEFHDROFFSET(a) ((LPVOID)((BYTE *)a + \ * along with this program; if not, write to the Free Software
((PIMAGE_DOS_HEADER)a)->e_lfanew + \ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
SIZE_OF_NT_SIGNATURE)) */
/* PE optional header is immediately after PEFile header. */ #define WIN32_LEAN_AND_MEAN
#define OPTHDROFFSET(a) ((LPVOID)((BYTE *)a + \ #include <windows.h>
((PIMAGE_DOS_HEADER)a)->e_lfanew + \ #include <stdio.h>
SIZE_OF_NT_SIGNATURE + \
sizeof (IMAGE_FILE_HEADER))) /* Offset to PE file signature */
#define NTSIGNATURE(a) ((LPVOID)((BYTE *)a + \
/* Section headers are immediately after PE optional header. */ ((PIMAGE_DOS_HEADER)a)->e_lfanew))
#define SECHDROFFSET(a) ((LPVOID)((BYTE *)a + \
((PIMAGE_DOS_HEADER)a)->e_lfanew + \ /* MS-OS header identifies the NT PEFile signature dword;
SIZE_OF_NT_SIGNATURE + \ the PEFILE header exists just after that dword. */
sizeof (IMAGE_FILE_HEADER) + \ #define PEFHDROFFSET(a) ((LPVOID)((BYTE *)a + \
sizeof (IMAGE_OPTIONAL_HEADER))) ((PIMAGE_DOS_HEADER)a)->e_lfanew + \
SIZE_OF_NT_SIGNATURE))
#define SIZE_OF_NT_SIGNATURE 4 /* PE optional header is immediately after PEFile header. */
#define OPTHDROFFSET(a) ((LPVOID)((BYTE *)a + \
/* -------------------------------------------------------------- */ ((PIMAGE_DOS_HEADER)a)->e_lfanew + \
SIZE_OF_NT_SIGNATURE + \
int WINAPI NumOfSections ( sizeof (IMAGE_FILE_HEADER)))
LPVOID lpFile)
{ /* Section headers are immediately after PE optional header. */
/* Number of sections is indicated in file header. */ #define SECHDROFFSET(a) ((LPVOID)((BYTE *)a + \
return (int) ((PIMAGE_DOS_HEADER)a)->e_lfanew + \
((PIMAGE_FILE_HEADER) SIZE_OF_NT_SIGNATURE + \
PEFHDROFFSET(lpFile))->NumberOfSections; sizeof (IMAGE_FILE_HEADER) + \
} sizeof (IMAGE_OPTIONAL_HEADER)))
/* -------------------------------------------------------------- */ #define SIZE_OF_NT_SIGNATURE 4
LPVOID WINAPI ImageDirectoryOffset ( /* -------------------------------------------------------------- */
LPVOID lpFile,
DWORD dwIMAGE_DIRECTORY) int WINAPI NumOfSections (
{ LPVOID lpFile)
PIMAGE_OPTIONAL_HEADER poh; {
PIMAGE_SECTION_HEADER psh; /* Number of sections is indicated in file header. */
int nSections = NumOfSections (lpFile); return (int)
int i = 0; ((PIMAGE_FILE_HEADER)
LPVOID VAImageDir; PEFHDROFFSET(lpFile))->NumberOfSections;
}
/* Retrieve offsets to optional and section headers. */
poh = (PIMAGE_OPTIONAL_HEADER)OPTHDROFFSET (lpFile);
psh = (PIMAGE_SECTION_HEADER)SECHDROFFSET (lpFile); /* -------------------------------------------------------------- */
/* Must be 0 thru (NumberOfRvaAndSizes-1). */ LPVOID WINAPI ImageDirectoryOffset (
if (dwIMAGE_DIRECTORY >= poh->NumberOfRvaAndSizes) LPVOID lpFile,
return NULL; DWORD dwIMAGE_DIRECTORY)
{
/* Locate image directory's relative virtual address. */ PIMAGE_OPTIONAL_HEADER poh;
VAImageDir = (LPVOID)poh->DataDirectory PIMAGE_SECTION_HEADER psh;
[dwIMAGE_DIRECTORY].VirtualAddress; int nSections = NumOfSections (lpFile);
int i = 0;
/* Locate section containing image directory. */ LPVOID VAImageDir;
while (i++<nSections)
{ /* Retrieve offsets to optional and section headers. */
if (psh->VirtualAddress <= (DWORD)VAImageDir poh = (PIMAGE_OPTIONAL_HEADER)OPTHDROFFSET (lpFile);
&& psh->VirtualAddress + psh->SizeOfRawData > (DWORD)VAImageDir) psh = (PIMAGE_SECTION_HEADER)SECHDROFFSET (lpFile);
break;
psh++; /* Must be 0 thru (NumberOfRvaAndSizes-1). */
} if (dwIMAGE_DIRECTORY >= poh->NumberOfRvaAndSizes)
return NULL;
if (i > nSections)
return NULL; /* Locate image directory's relative virtual address. */
VAImageDir = (LPVOID)poh->DataDirectory[dwIMAGE_DIRECTORY].VirtualAddress;
/* Return image import directory offset. */
return (LPVOID)(((int)lpFile + /* Locate section containing image directory. */
(int)VAImageDir - psh->VirtualAddress) + while (i++<nSections)
(int)psh->PointerToRawData); {
} if (psh->VirtualAddress <= (DWORD)VAImageDir
&& psh->VirtualAddress + psh->SizeOfRawData > (DWORD)VAImageDir)
/* -------------------------------------------------------------- */ break;
psh++;
BOOL WINAPI GetSectionHdrByName ( }
LPVOID lpFile,
IMAGE_SECTION_HEADER *sh, if (i > nSections)
char *szSection) return NULL;
{
PIMAGE_SECTION_HEADER psh; /* Return image import directory offset. */
int nSections = NumOfSections (lpFile); return (LPVOID)(((int)lpFile +
int i; (int)VAImageDir - psh->VirtualAddress) +
(int)psh->PointerToRawData);
if ((psh = (PIMAGE_SECTION_HEADER)SECHDROFFSET (lpFile)) != }
NULL)
{ /* -------------------------------------------------------------- */
/* find the section by name */
for (i=0; i<nSections; i++) BOOL WINAPI GetSectionHdrByName (
{ LPVOID lpFile,
if (!strcmp (psh->Name, szSection)) IMAGE_SECTION_HEADER *sh,
{ char *szSection)
/* copy data to header */ {
memcpy ((LPVOID)sh, PIMAGE_SECTION_HEADER psh;
(LPVOID)psh, int nSections = NumOfSections (lpFile);
sizeof (IMAGE_SECTION_HEADER)); int i;
return TRUE;
} if ((psh = (PIMAGE_SECTION_HEADER)SECHDROFFSET (lpFile)) != NULL)
else {
psh++; /* find the section by name */
} for (i=0; i<nSections; i++)
} {
if (!strcmp (psh->Name, szSection))
return FALSE; {
} /* copy data to header */
memcpy ((LPVOID)sh, (LPVOID)psh, sizeof (IMAGE_SECTION_HEADER));
/* -------------------------------------------------------------- */ return TRUE;
}
BOOL WINAPI GetSectionHdrByAddress ( else
LPVOID lpFile, psh++;
IMAGE_SECTION_HEADER *sh, }
DWORD addr) }
{ return FALSE;
PIMAGE_SECTION_HEADER psh; }
int nSections = NumOfSections (lpFile);
int i; /* -------------------------------------------------------------- */
if ((psh = (PIMAGE_SECTION_HEADER)SECHDROFFSET (lpFile)) != BOOL WINAPI GetSectionHdrByAddress (
NULL) LPVOID lpFile,
{ IMAGE_SECTION_HEADER *sh,
/* find the section by name */ DWORD addr)
for (i=0; i<nSections; i++) {
{ PIMAGE_SECTION_HEADER psh;
if (addr >= psh->VirtualAddress && addr < psh->VirtualAddress + psh->SizeOfRawData) int nSections = NumOfSections (lpFile);
{ int i;
/* copy data to header */
memcpy ((LPVOID)sh, if ((psh = (PIMAGE_SECTION_HEADER)SECHDROFFSET (lpFile)) != NULL)
(LPVOID)psh, {
sizeof (IMAGE_SECTION_HEADER)); /* find the section by name */
return TRUE; for (i=0; i<nSections; i++)
} {
else if (addr >= psh->VirtualAddress
psh++; && addr < psh->VirtualAddress + psh->SizeOfRawData)
} {
} /* copy data to header */
memcpy ((LPVOID)sh, (LPVOID)psh, sizeof (IMAGE_SECTION_HEADER));
return FALSE; return TRUE;
} }
else
/* -------------------------------------------------------------- */ psh++;
}
int WINAPI GetExportFunctionNames ( }
LPVOID lpFile, return FALSE;
HANDLE hHeap, }
char **pszFunctions)
{ /* -------------------------------------------------------------- */
IMAGE_SECTION_HEADER sh;
PIMAGE_EXPORT_DIRECTORY ped; int WINAPI GetExportFunctionNames (
int *pNames, *pCnt; LPVOID lpFile,
char *pSrc, *pDest; HANDLE hHeap,
int i, nCnt; char **pszFunctions)
DWORD VAImageDir; {
PIMAGE_OPTIONAL_HEADER poh; IMAGE_SECTION_HEADER sh;
char *pOffset; PIMAGE_EXPORT_DIRECTORY ped;
int *pNames, *pCnt;
/* Get section header and pointer to data directory char *pSrc, *pDest;
for .edata section. */ int i, nCnt;
if ((ped = (PIMAGE_EXPORT_DIRECTORY)ImageDirectoryOffset DWORD VAImageDir;
(lpFile, IMAGE_DIRECTORY_ENTRY_EXPORT)) == NULL) PIMAGE_OPTIONAL_HEADER poh;
return 0; char *pOffset;
poh = (PIMAGE_OPTIONAL_HEADER)OPTHDROFFSET (lpFile); /* Get section header and pointer to data directory
VAImageDir = poh->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; for .edata section. */
if (NULL == (ped = (PIMAGE_EXPORT_DIRECTORY)
if (FALSE == GetSectionHdrByAddress (lpFile, &sh, VAImageDir)) return 0; ImageDirectoryOffset (lpFile, IMAGE_DIRECTORY_ENTRY_EXPORT)))
return 0;
pOffset = (char *)lpFile + (sh.PointerToRawData - sh.VirtualAddress);
poh = (PIMAGE_OPTIONAL_HEADER)OPTHDROFFSET (lpFile);
pNames = (int *)(pOffset + (DWORD)ped->AddressOfNames); VAImageDir = poh->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
/* Figure out how much memory to allocate for all strings. */ if (FALSE == GetSectionHdrByAddress (lpFile, &sh, VAImageDir))
nCnt = 1; return 0;
for (i=0, pCnt = pNames; i<(int)ped->NumberOfNames; i++)
{ pOffset = (char *)lpFile + (sh.PointerToRawData - sh.VirtualAddress);
pSrc = (pOffset + *pCnt++);
if (pSrc) nCnt += strlen(pSrc)+1; pNames = (int *)(pOffset + (DWORD)ped->AddressOfNames);
}
/* Figure out how much memory to allocate for all strings. */
/* Allocate memory off heap for function names. */ nCnt = 1;
pDest = *pszFunctions = HeapAlloc (hHeap, HEAP_ZERO_MEMORY, nCnt); for (i=0, pCnt = pNames; i<(int)ped->NumberOfNames; i++)
{
/* Copy all strings to buffer. */ pSrc = (pOffset + *pCnt++);
for (i=0, pCnt = pNames; i<(int)ped->NumberOfNames; i++) if (pSrc)
{ nCnt += strlen(pSrc)+1;
pSrc = (pOffset + *pCnt++); }
if (pSrc) { strcpy(pDest, pSrc); pDest += strlen(pSrc)+1; }
} /* Allocate memory off heap for function names. */
*pDest = 0; pDest = *pszFunctions = HeapAlloc (hHeap, HEAP_ZERO_MEMORY, nCnt);
return ped->NumberOfNames; /* Copy all strings to buffer. */
} for (i=0, pCnt = pNames; i<(int)ped->NumberOfNames; i++)
{
/* -------------------------------------------------------------- */ pSrc = (pOffset + *pCnt++);
if (pSrc) {
int main(int argc, char **argv) strcpy(pDest, pSrc);
{ pDest += strlen(pSrc)+1;
}
HANDLE hHeap; HANDLE hFile; HANDLE hMapObject; VOID *pMem; }
int nCnt, ret, argind, std; *pDest = 0;
char *pNames;
char infile[MAX_PATH]; return ped->NumberOfNames;
char buffer[MAX_PATH]; }
char outfile[MAX_PATH];
char libname[80]; /* -------------------------------------------------------------- */
/* extract the basename of a file */
hHeap = NULL;
hFile = NULL; static char *file_basename(const char *name)
hMapObject = NULL; {
pMem = NULL; const char *p = strchr(name, 0);
infile[0] = 0; while (p > name
outfile[0] = 0; && p[-1] != '/'
ret = 0; && p[-1] != '\\'
std = 0; )
--p;
for (argind = 1; argind < argc; ++argind) return (char*)p;
{ }
const char *a = argv[argind];
if ('-' == a[0]) /* -------------------------------------------------------------- */
{
if (0 == strcmp(a, "-p")) int main(int argc, char **argv)
std = 1; {
else HANDLE hHeap;
if (0 == strcmp(a, "-o")) HANDLE hFile;
{ HANDLE hMapObject;
if (++argind == argc) goto usage; VOID *pMem;
strcpy(outfile, argv[argind]);
} int nCnt, ret, n;
else char *pNames;
goto usage; char infile[MAX_PATH];
} char buffer[MAX_PATH];
else char outfile[MAX_PATH];
if (0 == infile[0]) FILE *op;
strcpy(infile, a); char *p;
else
goto usage; hHeap = NULL;
} hFile = NULL;
hMapObject = NULL;
if (0 == infile[0]) pMem = NULL;
{ infile[0] = 0;
usage: outfile[0] = 0;
fprintf(stderr, ret = 1;
"tiny_impdef creates a .def file from a dll\n"
"Usage: tiny_impdef [-p] <library.dll> [-o outputfile]\n" for (n = 1; n < argc; ++n)
"Options:\n" {
" -p print to stdout\n" const char *a = argv[n];
); if ('-' == a[0]) {
error: if (0 == strcmp(a, "-o")) {
ret = 1; if (++n == argc)
goto the_end; goto usage;
} strcpy(outfile, argv[n]);
}
if (SearchPath(NULL, infile, ".dll", sizeof buffer, buffer, NULL)) else
strcpy(infile, buffer); goto usage;
if (0 == outfile[0]) } else if (0 == infile[0])
{ strcpy(infile, a);
char *p; else
p = strrchr(strcpy(outfile, infile), '\\'); goto usage;
if (NULL == p) }
p = strrchr(outfile, '/');
if (p) strcpy(outfile, p+1); if (0 == infile[0])
{
p = strrchr(outfile, '.'); usage:
if (NULL == p) p = strchr(outfile, 0); fprintf(stderr,
strcpy(p, ".def"); "tiny_impdef creates an export definition file (.def) from a dll\n"
} "Usage: tiny_impdef library.dll [-o outputfile]\n"
);
hFile=CreateFile( goto the_end;
infile, }
GENERIC_READ,
FILE_SHARE_READ, if (SearchPath(NULL, infile, ".dll", sizeof buffer, buffer, NULL))
NULL, strcpy(infile, buffer);
OPEN_EXISTING,
0, if (0 == outfile[0])
NULL {
); char *p;
strcpy(outfile, file_basename(infile));
if (hFile == INVALID_HANDLE_VALUE) p = strrchr(outfile, '.');
{ if (NULL == p)
fprintf(stderr, "file not found: %s\n", infile); p = strchr(outfile, 0);
goto error; strcpy(p, ".def");
} }
if (!std) printf("--> %s\n", infile); hFile = CreateFile(
infile,
hMapObject = CreateFileMapping( GENERIC_READ,
hFile, FILE_SHARE_READ,
NULL, NULL,
PAGE_READONLY, OPEN_EXISTING,
0, 0, 0,
NULL NULL
); );
if (NULL == hMapObject) if (hFile == INVALID_HANDLE_VALUE)
{ {
fprintf(stderr, "could not create file mapping.\n"); fprintf(stderr, "No such file: %s\n", infile);
goto error; goto the_end;
} }
pMem = MapViewOfFile(
hMapObject, // object to map view of hMapObject = CreateFileMapping(
FILE_MAP_READ, // read access hFile,
0, // high offset: map from NULL,
0, // low offset: beginning PAGE_READONLY,
0); // default: map entire file 0, 0,
NULL
if (NULL == pMem) );
{
fprintf(stderr, "could not map view of file.\n"); if (NULL == hMapObject)
goto error; {
} fprintf(stderr, "Could not create file mapping: %s\n", infile);
goto the_end;
hHeap = GetProcessHeap(); }
nCnt = GetExportFunctionNames(pMem, hHeap, &pNames);
{ pMem = MapViewOfFile(
FILE *op; char *p; int n; hMapObject, // object to map view of
if (!std) printf("<-- %s\n", outfile); FILE_MAP_READ, // read access
0, // high offset: map from
if (std) 0, // low offset: beginning
op = stdout; 0); // default: map entire file
else
op = fopen(outfile, "wt"); if (NULL == pMem)
{
if (NULL == op) fprintf(stderr, "Could not map view of file: %s\n", infile);
{ goto the_end;
fprintf(stderr, "could not create file: %s\n", outfile); }
goto error;
} if (0 != strncmp(NTSIGNATURE(pMem), "PE", 2))
{
p = strrchr(infile, '\\'); fprintf(stderr, "Not a PE file: %s\n", infile);
if (NULL == p) goto the_end;
p = strrchr(infile, '/'); }
if (NULL == p) p = infile; else ++p;
fprintf(op, "LIBRARY %s\n\nEXPORTS", p); hHeap = GetProcessHeap();
if (std) fprintf(op, " (%d)", nCnt); nCnt = GetExportFunctionNames(pMem, hHeap, &pNames);
fprintf(op, "\n"); if (0 == nCnt) {
for (n = 0, p = pNames; n < nCnt; ++n) fprintf(stderr, "Could not get exported function names: %s\n", infile);
{ goto the_end;
fprintf(op, "%s\n", p); }
while (*p++);
} printf("--> %s\n", infile);
if (!std) fclose(op);
} op = fopen(outfile, "w");
if (NULL == op)
the_end: {
if (pMem) UnmapViewOfFile(pMem); fprintf(stderr, "Could not create file: %s\n", outfile);
if (hMapObject) CloseHandle(hMapObject); goto the_end;
if (hFile) CloseHandle(hFile); }
return ret;
} printf("<-- %s\n", outfile);
/* -------------------------------------------------------------- */
fprintf(op, "LIBRARY %s\n\nEXPORTS\n", file_basename(infile));
for (n = 0, p = pNames; n < nCnt; ++n)
{
fprintf(op, "%s\n", p);
while (*p++);
}
ret = 0;
the_end:
if (pMem)
UnmapViewOfFile(pMem);
if (hMapObject)
CloseHandle(hMapObject);
if (hFile)
CloseHandle(hFile);
return ret;
}
/* -------------------------------------------------------------- */