/* -------------------------------------------------------------- */ /* "tiny_impdef creates a .def file from a dll" "Usage: tiny_impdef [-p] [-o outputfile]" "Options:" " -p print to stdout" */ #include #include /* Offset to PE file signature */ #define NTSIGNATURE(a) ((LPVOID)((BYTE *)a + \ ((PIMAGE_DOS_HEADER)a)->e_lfanew)) /* MS-OS header identifies the NT PEFile signature dword; the PEFILE header exists just after that dword. */ #define PEFHDROFFSET(a) ((LPVOID)((BYTE *)a + \ ((PIMAGE_DOS_HEADER)a)->e_lfanew + \ SIZE_OF_NT_SIGNATURE)) /* PE optional header is immediately after PEFile header. */ #define OPTHDROFFSET(a) ((LPVOID)((BYTE *)a + \ ((PIMAGE_DOS_HEADER)a)->e_lfanew + \ SIZE_OF_NT_SIGNATURE + \ sizeof (IMAGE_FILE_HEADER))) /* Section headers are immediately after PE optional header. */ #define SECHDROFFSET(a) ((LPVOID)((BYTE *)a + \ ((PIMAGE_DOS_HEADER)a)->e_lfanew + \ SIZE_OF_NT_SIGNATURE + \ sizeof (IMAGE_FILE_HEADER) + \ sizeof (IMAGE_OPTIONAL_HEADER))) #define SIZE_OF_NT_SIGNATURE 4 /* -------------------------------------------------------------- */ int WINAPI NumOfSections ( LPVOID lpFile) { /* Number of sections is indicated in file header. */ return (int) ((PIMAGE_FILE_HEADER) PEFHDROFFSET(lpFile))->NumberOfSections; } /* -------------------------------------------------------------- */ LPVOID WINAPI ImageDirectoryOffset ( LPVOID lpFile, DWORD dwIMAGE_DIRECTORY) { PIMAGE_OPTIONAL_HEADER poh; PIMAGE_SECTION_HEADER psh; int nSections = NumOfSections (lpFile); int i = 0; LPVOID VAImageDir; /* 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). */ if (dwIMAGE_DIRECTORY >= poh->NumberOfRvaAndSizes) return NULL; /* Locate image directory's relative virtual address. */ VAImageDir = (LPVOID)poh->DataDirectory [dwIMAGE_DIRECTORY].VirtualAddress; /* Locate section containing image directory. */ while (i++VirtualAddress <= (DWORD)VAImageDir && psh->VirtualAddress + psh->SizeOfRawData > (DWORD)VAImageDir) break; psh++; } if (i > nSections) return NULL; /* Return image import directory offset. */ return (LPVOID)(((int)lpFile + (int)VAImageDir - psh->VirtualAddress) + (int)psh->PointerToRawData); } /* -------------------------------------------------------------- */ BOOL WINAPI GetSectionHdrByName ( LPVOID lpFile, IMAGE_SECTION_HEADER *sh, char *szSection) { PIMAGE_SECTION_HEADER psh; int nSections = NumOfSections (lpFile); int i; if ((psh = (PIMAGE_SECTION_HEADER)SECHDROFFSET (lpFile)) != NULL) { /* find the section by name */ for (i=0; iName, szSection)) { /* copy data to header */ memcpy ((LPVOID)sh, (LPVOID)psh, sizeof (IMAGE_SECTION_HEADER)); return TRUE; } else psh++; } } return FALSE; } /* -------------------------------------------------------------- */ BOOL WINAPI GetSectionHdrByAddress ( LPVOID lpFile, IMAGE_SECTION_HEADER *sh, DWORD addr) { PIMAGE_SECTION_HEADER psh; int nSections = NumOfSections (lpFile); int i; if ((psh = (PIMAGE_SECTION_HEADER)SECHDROFFSET (lpFile)) != NULL) { /* find the section by name */ for (i=0; i= psh->VirtualAddress && addr < psh->VirtualAddress + psh->SizeOfRawData) { /* copy data to header */ memcpy ((LPVOID)sh, (LPVOID)psh, sizeof (IMAGE_SECTION_HEADER)); return TRUE; } else psh++; } } return FALSE; } /* -------------------------------------------------------------- */ int WINAPI GetExportFunctionNames ( LPVOID lpFile, HANDLE hHeap, char **pszFunctions) { IMAGE_SECTION_HEADER sh; PIMAGE_EXPORT_DIRECTORY ped; int *pNames, *pCnt; char *pSrc, *pDest; int i, nCnt; DWORD VAImageDir; PIMAGE_OPTIONAL_HEADER poh; char *pOffset; /* Get section header and pointer to data directory for .edata section. */ if ((ped = (PIMAGE_EXPORT_DIRECTORY)ImageDirectoryOffset (lpFile, IMAGE_DIRECTORY_ENTRY_EXPORT)) == NULL) return 0; poh = (PIMAGE_OPTIONAL_HEADER)OPTHDROFFSET (lpFile); VAImageDir = poh->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; if (FALSE == GetSectionHdrByAddress (lpFile, &sh, VAImageDir)) return 0; pOffset = (char *)lpFile + (sh.PointerToRawData - sh.VirtualAddress); pNames = (int *)(pOffset + (DWORD)ped->AddressOfNames); /* Figure out how much memory to allocate for all strings. */ nCnt = 1; for (i=0, pCnt = pNames; i<(int)ped->NumberOfNames; i++) { pSrc = (pOffset + *pCnt++); if (pSrc) nCnt += strlen(pSrc)+1; } /* Allocate memory off heap for function names. */ pDest = *pszFunctions = HeapAlloc (hHeap, HEAP_ZERO_MEMORY, nCnt); /* Copy all strings to buffer. */ for (i=0, pCnt = pNames; i<(int)ped->NumberOfNames; i++) { pSrc = (pOffset + *pCnt++); if (pSrc) { strcpy(pDest, pSrc); pDest += strlen(pSrc)+1; } } *pDest = 0; return ped->NumberOfNames; } /* -------------------------------------------------------------- */ int main(int argc, char **argv) { HANDLE hHeap; HANDLE hFile; HANDLE hMapObject; VOID *pMem; int nCnt, ret, argind, std; char *pNames; char infile[MAX_PATH]; char buffer[MAX_PATH]; char outfile[MAX_PATH]; char libname[80]; hHeap = NULL; hFile = NULL; hMapObject = NULL; pMem = NULL; infile[0] = 0; outfile[0] = 0; ret = 0; std = 0; for (argind = 1; argind < argc; ++argind) { const char *a = argv[argind]; if ('-' == a[0]) { if (0 == strcmp(a, "-p")) std = 1; else if (0 == strcmp(a, "-o")) { if (++argind == argc) goto usage; strcpy(outfile, argv[argind]); } else goto usage; } else if (0 == infile[0]) strcpy(infile, a); else goto usage; } if (0 == infile[0]) { usage: fprintf(stderr, "tiny_impdef creates a .def file from a dll\n" "Usage: tiny_impdef [-p] [-o outputfile]\n" "Options:\n" " -p print to stdout\n" ); error: ret = 1; goto the_end; } if (SearchPath(NULL, infile, ".dll", sizeof buffer, buffer, NULL)) strcpy(infile, buffer); if (0 == outfile[0]) { char *p; p = strrchr(strcpy(outfile, infile), '\\'); if (NULL == p) p = strrchr(outfile, '/'); if (p) strcpy(outfile, p+1); p = strrchr(outfile, '.'); if (NULL == p) p = strchr(outfile, 0); strcpy(p, ".def"); } hFile=CreateFile( infile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL ); if (hFile == INVALID_HANDLE_VALUE) { fprintf(stderr, "file not found: %s\n", infile); goto error; } if (!std) printf("--> %s\n", infile); hMapObject = CreateFileMapping( hFile, NULL, PAGE_READONLY, 0, 0, NULL ); if (NULL == hMapObject) { fprintf(stderr, "could not create file mapping.\n"); goto error; } pMem = MapViewOfFile( hMapObject, // object to map view of FILE_MAP_READ, // read access 0, // high offset: map from 0, // low offset: beginning 0); // default: map entire file if (NULL == pMem) { fprintf(stderr, "could not map view of file.\n"); goto error; } hHeap = GetProcessHeap(); nCnt = GetExportFunctionNames(pMem, hHeap, &pNames); { FILE *op; char *p; int n; if (!std) printf("<-- %s\n", outfile); if (std) op = stdout; else op = fopen(outfile, "wt"); if (NULL == op) { fprintf(stderr, "could not create file: %s\n", outfile); goto error; } p = strrchr(infile, '\\'); if (NULL == p) p = strrchr(infile, '/'); if (NULL == p) p = infile; else ++p; fprintf(op, "LIBRARY %s\n\nEXPORTS", p); if (std) fprintf(op, " (%d)", nCnt); fprintf(op, "\n"); for (n = 0, p = pNames; n < nCnt; ++n) { fprintf(op, "%s\n", p); while (*p++); } if (!std) fclose(op); } the_end: if (pMem) UnmapViewOfFile(pMem); if (hMapObject) CloseHandle(hMapObject); if (hFile) CloseHandle(hFile); return ret; } /* -------------------------------------------------------------- */