tiny_impdef.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. /* -------------------------------------------------------------- */
  2. /*
  3. * tiny_impdef creates an export definition file (.def) from a dll
  4. * on MS-Windows. Usage: tiny_impdef library.dll [-o outputfile]"
  5. *
  6. * Copyright (c) 2005,2007 grischka
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21. */
  22. #define WIN32_LEAN_AND_MEAN
  23. #include <windows.h>
  24. #include <stdio.h>
  25. /* Offset to PE file signature */
  26. #define NTSIGNATURE(a) ((LPVOID)((BYTE *)a + \
  27. ((PIMAGE_DOS_HEADER)a)->e_lfanew))
  28. /* MS-OS header identifies the NT PEFile signature dword;
  29. the PEFILE header exists just after that dword. */
  30. #define PEFHDROFFSET(a) ((LPVOID)((BYTE *)a + \
  31. ((PIMAGE_DOS_HEADER)a)->e_lfanew + \
  32. SIZE_OF_NT_SIGNATURE))
  33. /* PE optional header is immediately after PEFile header. */
  34. #define OPTHDROFFSET(a) ((LPVOID)((BYTE *)a + \
  35. ((PIMAGE_DOS_HEADER)a)->e_lfanew + \
  36. SIZE_OF_NT_SIGNATURE + \
  37. sizeof (IMAGE_FILE_HEADER)))
  38. /* Section headers are immediately after PE optional header. */
  39. #define SECHDROFFSET(a) ((LPVOID)((BYTE *)a + \
  40. ((PIMAGE_DOS_HEADER)a)->e_lfanew + \
  41. SIZE_OF_NT_SIGNATURE + \
  42. sizeof (IMAGE_FILE_HEADER) + \
  43. sizeof (IMAGE_OPTIONAL_HEADER)))
  44. #define SIZE_OF_NT_SIGNATURE 4
  45. /* -------------------------------------------------------------- */
  46. int WINAPI NumOfSections (
  47. LPVOID lpFile)
  48. {
  49. /* Number of sections is indicated in file header. */
  50. return (int)
  51. ((PIMAGE_FILE_HEADER)
  52. PEFHDROFFSET(lpFile))->NumberOfSections;
  53. }
  54. /* -------------------------------------------------------------- */
  55. LPVOID WINAPI ImageDirectoryOffset (
  56. LPVOID lpFile,
  57. DWORD dwIMAGE_DIRECTORY)
  58. {
  59. PIMAGE_OPTIONAL_HEADER poh;
  60. PIMAGE_SECTION_HEADER psh;
  61. int nSections = NumOfSections (lpFile);
  62. int i = 0;
  63. LPVOID VAImageDir;
  64. /* Retrieve offsets to optional and section headers. */
  65. poh = (PIMAGE_OPTIONAL_HEADER)OPTHDROFFSET (lpFile);
  66. psh = (PIMAGE_SECTION_HEADER)SECHDROFFSET (lpFile);
  67. /* Must be 0 thru (NumberOfRvaAndSizes-1). */
  68. if (dwIMAGE_DIRECTORY >= poh->NumberOfRvaAndSizes)
  69. return NULL;
  70. /* Locate image directory's relative virtual address. */
  71. VAImageDir = (LPVOID)poh->DataDirectory[dwIMAGE_DIRECTORY].VirtualAddress;
  72. /* Locate section containing image directory. */
  73. while (i++<nSections)
  74. {
  75. if (psh->VirtualAddress <= (DWORD)VAImageDir
  76. && psh->VirtualAddress + psh->SizeOfRawData > (DWORD)VAImageDir)
  77. break;
  78. psh++;
  79. }
  80. if (i > nSections)
  81. return NULL;
  82. /* Return image import directory offset. */
  83. return (LPVOID)(((int)lpFile +
  84. (int)VAImageDir - psh->VirtualAddress) +
  85. (int)psh->PointerToRawData);
  86. }
  87. /* -------------------------------------------------------------- */
  88. BOOL WINAPI GetSectionHdrByName (
  89. LPVOID lpFile,
  90. IMAGE_SECTION_HEADER *sh,
  91. char *szSection)
  92. {
  93. PIMAGE_SECTION_HEADER psh;
  94. int nSections = NumOfSections (lpFile);
  95. int i;
  96. if ((psh = (PIMAGE_SECTION_HEADER)SECHDROFFSET (lpFile)) != NULL)
  97. {
  98. /* find the section by name */
  99. for (i=0; i<nSections; i++)
  100. {
  101. if (!strcmp (psh->Name, szSection))
  102. {
  103. /* copy data to header */
  104. memcpy ((LPVOID)sh, (LPVOID)psh, sizeof (IMAGE_SECTION_HEADER));
  105. return TRUE;
  106. }
  107. else
  108. psh++;
  109. }
  110. }
  111. return FALSE;
  112. }
  113. /* -------------------------------------------------------------- */
  114. BOOL WINAPI GetSectionHdrByAddress (
  115. LPVOID lpFile,
  116. IMAGE_SECTION_HEADER *sh,
  117. DWORD addr)
  118. {
  119. PIMAGE_SECTION_HEADER psh;
  120. int nSections = NumOfSections (lpFile);
  121. int i;
  122. if ((psh = (PIMAGE_SECTION_HEADER)SECHDROFFSET (lpFile)) != NULL)
  123. {
  124. /* find the section by name */
  125. for (i=0; i<nSections; i++)
  126. {
  127. if (addr >= psh->VirtualAddress
  128. && addr < psh->VirtualAddress + psh->SizeOfRawData)
  129. {
  130. /* copy data to header */
  131. memcpy ((LPVOID)sh, (LPVOID)psh, sizeof (IMAGE_SECTION_HEADER));
  132. return TRUE;
  133. }
  134. else
  135. psh++;
  136. }
  137. }
  138. return FALSE;
  139. }
  140. /* -------------------------------------------------------------- */
  141. int WINAPI GetExportFunctionNames (
  142. LPVOID lpFile,
  143. HANDLE hHeap,
  144. char **pszFunctions)
  145. {
  146. IMAGE_SECTION_HEADER sh;
  147. PIMAGE_EXPORT_DIRECTORY ped;
  148. int *pNames, *pCnt;
  149. char *pSrc, *pDest;
  150. int i, nCnt;
  151. DWORD VAImageDir;
  152. PIMAGE_OPTIONAL_HEADER poh;
  153. char *pOffset;
  154. /* Get section header and pointer to data directory
  155. for .edata section. */
  156. if (NULL == (ped = (PIMAGE_EXPORT_DIRECTORY)
  157. ImageDirectoryOffset (lpFile, IMAGE_DIRECTORY_ENTRY_EXPORT)))
  158. return 0;
  159. poh = (PIMAGE_OPTIONAL_HEADER)OPTHDROFFSET (lpFile);
  160. VAImageDir = poh->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
  161. if (FALSE == GetSectionHdrByAddress (lpFile, &sh, VAImageDir))
  162. return 0;
  163. pOffset = (char *)lpFile + (sh.PointerToRawData - sh.VirtualAddress);
  164. pNames = (int *)(pOffset + (DWORD)ped->AddressOfNames);
  165. /* Figure out how much memory to allocate for all strings. */
  166. nCnt = 1;
  167. for (i=0, pCnt = pNames; i<(int)ped->NumberOfNames; i++)
  168. {
  169. pSrc = (pOffset + *pCnt++);
  170. if (pSrc)
  171. nCnt += strlen(pSrc)+1;
  172. }
  173. /* Allocate memory off heap for function names. */
  174. pDest = *pszFunctions = HeapAlloc (hHeap, HEAP_ZERO_MEMORY, nCnt);
  175. /* Copy all strings to buffer. */
  176. for (i=0, pCnt = pNames; i<(int)ped->NumberOfNames; i++)
  177. {
  178. pSrc = (pOffset + *pCnt++);
  179. if (pSrc) {
  180. strcpy(pDest, pSrc);
  181. pDest += strlen(pSrc)+1;
  182. }
  183. }
  184. *pDest = 0;
  185. return ped->NumberOfNames;
  186. }
  187. /* -------------------------------------------------------------- */
  188. /* extract the basename of a file */
  189. static char *file_basename(const char *name)
  190. {
  191. const char *p = strchr(name, 0);
  192. while (p > name
  193. && p[-1] != '/'
  194. && p[-1] != '\\'
  195. )
  196. --p;
  197. return (char*)p;
  198. }
  199. /* -------------------------------------------------------------- */
  200. int main(int argc, char **argv)
  201. {
  202. HANDLE hHeap;
  203. HANDLE hFile;
  204. HANDLE hMapObject;
  205. VOID *pMem;
  206. int nCnt, ret, n;
  207. char *pNames;
  208. char infile[MAX_PATH];
  209. char buffer[MAX_PATH];
  210. char outfile[MAX_PATH];
  211. FILE *op;
  212. char *p;
  213. hHeap = NULL;
  214. hFile = NULL;
  215. hMapObject = NULL;
  216. pMem = NULL;
  217. infile[0] = 0;
  218. outfile[0] = 0;
  219. ret = 1;
  220. for (n = 1; n < argc; ++n)
  221. {
  222. const char *a = argv[n];
  223. if ('-' == a[0]) {
  224. if (0 == strcmp(a, "-o")) {
  225. if (++n == argc)
  226. goto usage;
  227. strcpy(outfile, argv[n]);
  228. }
  229. else
  230. goto usage;
  231. } else if (0 == infile[0])
  232. strcpy(infile, a);
  233. else
  234. goto usage;
  235. }
  236. if (0 == infile[0])
  237. {
  238. usage:
  239. fprintf(stderr,
  240. "tiny_impdef creates an export definition file (.def) from a dll\n"
  241. "Usage: tiny_impdef library.dll [-o outputfile]\n"
  242. );
  243. goto the_end;
  244. }
  245. if (SearchPath(NULL, infile, ".dll", sizeof buffer, buffer, NULL))
  246. strcpy(infile, buffer);
  247. if (0 == outfile[0])
  248. {
  249. char *p;
  250. strcpy(outfile, file_basename(infile));
  251. p = strrchr(outfile, '.');
  252. if (NULL == p)
  253. p = strchr(outfile, 0);
  254. strcpy(p, ".def");
  255. }
  256. hFile = CreateFile(
  257. infile,
  258. GENERIC_READ,
  259. FILE_SHARE_READ,
  260. NULL,
  261. OPEN_EXISTING,
  262. 0,
  263. NULL
  264. );
  265. if (hFile == INVALID_HANDLE_VALUE)
  266. {
  267. fprintf(stderr, "No such file: %s\n", infile);
  268. goto the_end;
  269. }
  270. hMapObject = CreateFileMapping(
  271. hFile,
  272. NULL,
  273. PAGE_READONLY,
  274. 0, 0,
  275. NULL
  276. );
  277. if (NULL == hMapObject)
  278. {
  279. fprintf(stderr, "Could not create file mapping: %s\n", infile);
  280. goto the_end;
  281. }
  282. pMem = MapViewOfFile(
  283. hMapObject, // object to map view of
  284. FILE_MAP_READ, // read access
  285. 0, // high offset: map from
  286. 0, // low offset: beginning
  287. 0); // default: map entire file
  288. if (NULL == pMem)
  289. {
  290. fprintf(stderr, "Could not map view of file: %s\n", infile);
  291. goto the_end;
  292. }
  293. if (0 != strncmp(NTSIGNATURE(pMem), "PE", 2))
  294. {
  295. fprintf(stderr, "Not a PE file: %s\n", infile);
  296. goto the_end;
  297. }
  298. hHeap = GetProcessHeap();
  299. nCnt = GetExportFunctionNames(pMem, hHeap, &pNames);
  300. if (0 == nCnt) {
  301. fprintf(stderr, "Could not get exported function names: %s\n", infile);
  302. goto the_end;
  303. }
  304. printf("--> %s\n", infile);
  305. op = fopen(outfile, "w");
  306. if (NULL == op)
  307. {
  308. fprintf(stderr, "Could not create file: %s\n", outfile);
  309. goto the_end;
  310. }
  311. printf("<-- %s\n", outfile);
  312. fprintf(op, "LIBRARY %s\n\nEXPORTS\n", file_basename(infile));
  313. for (n = 0, p = pNames; n < nCnt; ++n)
  314. {
  315. fprintf(op, "%s\n", p);
  316. while (*p++);
  317. }
  318. ret = 0;
  319. the_end:
  320. if (pMem)
  321. UnmapViewOfFile(pMem);
  322. if (hMapObject)
  323. CloseHandle(hMapObject);
  324. if (hFile)
  325. CloseHandle(hFile);
  326. return ret;
  327. }
  328. /* -------------------------------------------------------------- */