1 /* -------------------------------------------------------------- */
3 * tiny_impdef creates an export definition file (.def) from a dll
4 * on MS-Windows. Usage: tiny_impdef library.dll [-o outputfile]"
6 * Copyright (c) 2005,2007 grischka
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.
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.
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.
23 #define WIN32_LEAN_AND_MEAN
27 /* Offset to PE file signature */
28 #define NTSIGNATURE(a) ((LPVOID)((BYTE *)a + \
29 ((PIMAGE_DOS_HEADER)a)->e_lfanew))
31 /* MS-OS header identifies the NT PEFile signature dword;
32 the PEFILE header exists just after that dword. */
33 #define PEFHDROFFSET(a) ((LPVOID)((BYTE *)a + \
34 ((PIMAGE_DOS_HEADER)a)->e_lfanew + \
35 SIZE_OF_NT_SIGNATURE))
37 /* PE optional header is immediately after PEFile header. */
38 #define OPTHDROFFSET(a) ((LPVOID)((BYTE *)a + \
39 ((PIMAGE_DOS_HEADER)a)->e_lfanew + \
40 SIZE_OF_NT_SIGNATURE + \
41 sizeof (IMAGE_FILE_HEADER)))
43 /* Section headers are immediately after PE optional header. */
44 #define SECHDROFFSET(a) ((LPVOID)((BYTE *)a + \
45 ((PIMAGE_DOS_HEADER)a)->e_lfanew + \
46 SIZE_OF_NT_SIGNATURE + \
47 sizeof (IMAGE_FILE_HEADER) + \
48 sizeof (IMAGE_OPTIONAL_HEADER)))
51 #define SIZE_OF_NT_SIGNATURE 4
53 /* -------------------------------------------------------------- */
55 int WINAPI
NumOfSections (
58 /* Number of sections is indicated in file header. */
61 PEFHDROFFSET(lpFile
))->NumberOfSections
;
65 /* -------------------------------------------------------------- */
67 LPVOID WINAPI
ImageDirectoryOffset (
69 DWORD dwIMAGE_DIRECTORY
)
71 PIMAGE_OPTIONAL_HEADER poh
;
72 PIMAGE_SECTION_HEADER psh
;
73 int nSections
= NumOfSections (lpFile
);
77 /* Retrieve offsets to optional and section headers. */
78 poh
= (PIMAGE_OPTIONAL_HEADER
)OPTHDROFFSET (lpFile
);
79 psh
= (PIMAGE_SECTION_HEADER
)SECHDROFFSET (lpFile
);
81 /* Must be 0 thru (NumberOfRvaAndSizes-1). */
82 if (dwIMAGE_DIRECTORY
>= poh
->NumberOfRvaAndSizes
)
85 /* Locate image directory's relative virtual address. */
86 VAImageDir
= (LPVOID
)poh
->DataDirectory
[dwIMAGE_DIRECTORY
].VirtualAddress
;
88 /* Locate section containing image directory. */
91 if (psh
->VirtualAddress
<= (DWORD
)VAImageDir
92 && psh
->VirtualAddress
+ psh
->SizeOfRawData
> (DWORD
)VAImageDir
)
100 /* Return image import directory offset. */
101 return (LPVOID
)(((int)lpFile
+
102 (int)VAImageDir
- psh
->VirtualAddress
) +
103 (int)psh
->PointerToRawData
);
106 /* -------------------------------------------------------------- */
108 BOOL WINAPI
GetSectionHdrByName (
110 IMAGE_SECTION_HEADER
*sh
,
113 PIMAGE_SECTION_HEADER psh
;
114 int nSections
= NumOfSections (lpFile
);
117 if ((psh
= (PIMAGE_SECTION_HEADER
)SECHDROFFSET (lpFile
)) != NULL
)
119 /* find the section by name */
120 for (i
=0; i
<nSections
; i
++)
122 if (!strcmp (psh
->Name
, szSection
))
124 /* copy data to header */
125 memcpy ((LPVOID
)sh
, (LPVOID
)psh
, sizeof (IMAGE_SECTION_HEADER
));
135 /* -------------------------------------------------------------- */
137 BOOL WINAPI
GetSectionHdrByAddress (
139 IMAGE_SECTION_HEADER
*sh
,
142 PIMAGE_SECTION_HEADER psh
;
143 int nSections
= NumOfSections (lpFile
);
146 if ((psh
= (PIMAGE_SECTION_HEADER
)SECHDROFFSET (lpFile
)) != NULL
)
148 /* find the section by name */
149 for (i
=0; i
<nSections
; i
++)
151 if (addr
>= psh
->VirtualAddress
152 && addr
< psh
->VirtualAddress
+ psh
->SizeOfRawData
)
154 /* copy data to header */
155 memcpy ((LPVOID
)sh
, (LPVOID
)psh
, sizeof (IMAGE_SECTION_HEADER
));
165 /* -------------------------------------------------------------- */
167 int WINAPI
GetExportFunctionNames (
172 IMAGE_SECTION_HEADER sh
;
173 PIMAGE_EXPORT_DIRECTORY ped
;
178 PIMAGE_OPTIONAL_HEADER poh
;
181 /* Get section header and pointer to data directory
182 for .edata section. */
183 if (NULL
== (ped
= (PIMAGE_EXPORT_DIRECTORY
)
184 ImageDirectoryOffset (lpFile
, IMAGE_DIRECTORY_ENTRY_EXPORT
)))
187 poh
= (PIMAGE_OPTIONAL_HEADER
)OPTHDROFFSET (lpFile
);
188 VAImageDir
= poh
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
;
190 if (FALSE
== GetSectionHdrByAddress (lpFile
, &sh
, VAImageDir
))
193 pOffset
= (char *)lpFile
+ (sh
.PointerToRawData
- sh
.VirtualAddress
);
195 pNames
= (int *)(pOffset
+ (DWORD
)ped
->AddressOfNames
);
197 /* Figure out how much memory to allocate for all strings. */
199 for (i
=0, pCnt
= pNames
; i
<(int)ped
->NumberOfNames
; i
++)
201 pSrc
= (pOffset
+ *pCnt
++);
203 nCnt
+= strlen(pSrc
)+1;
206 /* Allocate memory off heap for function names. */
207 pDest
= *pszFunctions
= HeapAlloc (hHeap
, HEAP_ZERO_MEMORY
, nCnt
);
209 /* Copy all strings to buffer. */
210 for (i
=0, pCnt
= pNames
; i
<(int)ped
->NumberOfNames
; i
++)
212 pSrc
= (pOffset
+ *pCnt
++);
215 pDest
+= strlen(pSrc
)+1;
220 return ped
->NumberOfNames
;
223 /* -------------------------------------------------------------- */
224 /* extract the basename of a file */
226 static char *file_basename(const char *name
)
228 const char *p
= strchr(name
, 0);
237 /* -------------------------------------------------------------- */
239 int main(int argc
, char **argv
)
248 char infile
[MAX_PATH
];
249 char buffer
[MAX_PATH
];
250 char outfile
[MAX_PATH
];
262 for (n
= 1; n
< argc
; ++n
)
264 const char *a
= argv
[n
];
266 if (0 == strcmp(a
, "-o")) {
269 strcpy(outfile
, argv
[n
]);
274 } else if (0 == infile
[0])
284 "tiny_impdef creates an export definition file (.def) from a dll\n"
285 "Usage: tiny_impdef library.dll [-o outputfile]\n"
290 if (SearchPath(NULL
, infile
, ".dll", sizeof buffer
, buffer
, NULL
))
291 strcpy(infile
, buffer
);
296 strcpy(outfile
, file_basename(infile
));
297 p
= strrchr(outfile
, '.');
299 p
= strchr(outfile
, 0);
313 if (hFile
== INVALID_HANDLE_VALUE
)
315 fprintf(stderr
, "No such file: %s\n", infile
);
320 hMapObject
= CreateFileMapping(
328 if (NULL
== hMapObject
)
330 fprintf(stderr
, "Could not create file mapping: %s\n", infile
);
334 pMem
= MapViewOfFile(
335 hMapObject
, // object to map view of
336 FILE_MAP_READ
, // read access
337 0, // high offset: map from
338 0, // low offset: beginning
339 0); // default: map entire file
343 fprintf(stderr
, "Could not map view of file: %s\n", infile
);
347 if (0 != strncmp(NTSIGNATURE(pMem
), "PE", 2))
349 fprintf(stderr
, "Not a PE file: %s\n", infile
);
354 hHeap
= GetProcessHeap();
355 nCnt
= GetExportFunctionNames(pMem
, hHeap
, &pNames
);
357 fprintf(stderr
, "Could not get exported function names: %s\n", infile
);
361 printf("--> %s\n", infile
);
363 op
= fopen(outfile
, "w");
366 fprintf(stderr
, "Could not create file: %s\n", outfile
);
370 printf("<-- %s\n", outfile
);
372 fprintf(op
, "LIBRARY %s\n\nEXPORTS\n", file_basename(infile
));
373 for (n
= 0, p
= pNames
; n
< nCnt
; ++n
)
375 fprintf(op
, "%s\n", p
);
382 UnmapViewOfFile(pMem
);
385 CloseHandle(hMapObject
);
393 /* -------------------------------------------------------------- */