summary refs log tree commit diff stats
path: root/tinyc/win32/tools/tiny_impdef.c
diff options
context:
space:
mode:
Diffstat (limited to 'tinyc/win32/tools/tiny_impdef.c')
-rwxr-xr-xtinyc/win32/tools/tiny_impdef.c393
1 files changed, 393 insertions, 0 deletions
diff --git a/tinyc/win32/tools/tiny_impdef.c b/tinyc/win32/tools/tiny_impdef.c
new file mode 100755
index 000000000..040c53acc
--- /dev/null
+++ b/tinyc/win32/tools/tiny_impdef.c
@@ -0,0 +1,393 @@
+/* -------------------------------------------------------------- */
+/*
+ * tiny_impdef creates an export definition file (.def) from a dll
+ * on MS-Windows. Usage: tiny_impdef library.dll [-o outputfile]"
+ * 
+ *  Copyright (c) 2005,2007 grischka
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <stdio.h>
+
+/* 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++<nSections)
+    {
+        if (psh->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; i<nSections; i++)
+        {
+            if (!strcmp (psh->Name, 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<nSections; i++)
+        {
+            if (addr >= 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 (NULL == (ped = (PIMAGE_EXPORT_DIRECTORY)
+        ImageDirectoryOffset (lpFile, IMAGE_DIRECTORY_ENTRY_EXPORT)))
+        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;
+}
+
+/* -------------------------------------------------------------- */
+/* extract the basename of a file */
+
+static char *file_basename(const char *name)
+{
+    const char *p = strchr(name, 0);
+    while (p > name
+        && p[-1] != '/'
+        && p[-1] != '\\'
+        )
+        --p;
+    return (char*)p;
+}
+
+/* -------------------------------------------------------------- */
+
+int main(int argc, char **argv)
+{
+    HANDLE hHeap;
+    HANDLE hFile;
+    HANDLE hMapObject;
+    VOID *pMem;
+
+    int nCnt, ret, n;
+    char *pNames;
+    char infile[MAX_PATH];
+    char buffer[MAX_PATH];
+    char outfile[MAX_PATH];
+    FILE *op;
+    char *p;
+
+    hHeap = NULL;
+    hFile = NULL;
+    hMapObject = NULL;
+    pMem = NULL;
+    infile[0] = 0;
+    outfile[0] = 0;
+    ret = 1;
+
+    for (n = 1; n < argc; ++n)
+    {
+        const char *a = argv[n];
+        if ('-' == a[0]) {
+            if (0 == strcmp(a, "-o")) {
+                if (++n == argc)
+                    goto usage;
+                strcpy(outfile, argv[n]);
+            }
+            else
+                goto usage;
+
+        } else if (0 == infile[0])
+            strcpy(infile, a);
+        else
+            goto usage;
+    }
+
+    if (0 == infile[0])
+    {
+usage:
+        fprintf(stderr,
+            "tiny_impdef creates an export definition file (.def) from a dll\n"
+            "Usage: tiny_impdef library.dll [-o outputfile]\n"
+            );
+        goto the_end;
+    }
+
+    if (SearchPath(NULL, infile, ".dll", sizeof buffer, buffer, NULL))
+        strcpy(infile, buffer);
+
+    if (0 == outfile[0])
+    {
+        char *p;
+        strcpy(outfile, file_basename(infile));
+        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, "No such file: %s\n", infile);
+        goto the_end;
+    }
+
+
+    hMapObject = CreateFileMapping(
+        hFile,
+        NULL,
+        PAGE_READONLY,
+        0, 0,
+        NULL
+        );
+
+    if (NULL == hMapObject)
+    {
+        fprintf(stderr, "Could not create file mapping: %s\n", infile);
+        goto the_end;
+    }
+
+    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: %s\n", infile);
+        goto the_end;
+    }
+
+    if (0 != strncmp(NTSIGNATURE(pMem), "PE", 2))
+    {
+        fprintf(stderr, "Not a PE file: %s\n", infile);
+        goto the_end;
+    }
+
+
+    hHeap = GetProcessHeap();
+    nCnt = GetExportFunctionNames(pMem, hHeap, &pNames);
+    if (0 == nCnt) {
+        fprintf(stderr, "Could not get exported function names: %s\n", infile);
+        goto the_end;
+    }
+
+    printf("--> %s\n", infile);
+
+    op = fopen(outfile, "w");
+    if (NULL == op)
+    {
+        fprintf(stderr, "Could not create file: %s\n", outfile);
+        goto the_end;
+    }
+
+    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;
+}
+
+/* -------------------------------------------------------------- */