Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Welcome Guest | Log In | Register | Benefits
Channels ▼
RSS

Packing DLLs in your EXE


HexWeb HTML

Listing 1: DLLpack.cpp
Run-time extraction of DLLs from applications

/* DLLPACK.CPP  - Run-time extraction of DLLs from applications */

#include <windows.h>
#include "dllpack.h"

#if !defined DLLPACK_NO_UNLOAD
    #include <string.h>         /* for strupr() */
    #include <map>
    #include <string>
    static std::map<std::basic_string<char>,HANDLE> DLLfiles;
#endif


static BOOL IsWindowsNT(void)
{
    OSVERSIONINFO VerInfo;
    VerInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
    GetVersionEx(&VerInfo);
    return VerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT;
}


HINSTANCE dpExtractDLL(LPCSTR FileName)
{
    HRSRC     hRsrc;
    HGLOBAL   hResource;
    DWORD     dwResourceSize, dwWritten;
    LPVOID    lpfResource;
    char      TmpPath[MAX_PATH];
    char      BaseName[MAX_PATH];
    char      TmpName[MAX_PATH];
    char      *Ext;
    HANDLE    hFile;
    HINSTANCE hinstApp, hinstDLL;

    strcpy(BaseName, FileName);
    if ((Ext=strchr(BaseName,'.'))!=NULL)
        *Ext = '\0';                    /* erase extension */

    GetTempPath(sizeof TmpPath, TmpPath);
    GetTempFileName(TmpPath, BaseName, 0, TmpName);

    hinstApp = GetModuleHandle(NULL);
    hRsrc = FindResource(hinstApp, BaseName, "BINDATA");
    if (hRsrc == NULL)
        return NULL;
    hResource = LoadResource(hinstApp, hRsrc);
    if (hResource == NULL)
        return NULL;
    dwResourceSize = SizeofResource(hinstApp, hRsrc);
    lpfResource = LockResource(hResource);

    hFile = CreateFile(TmpName, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
    if (hFile == INVALID_HANDLE_VALUE)
        return NULL;
    WriteFile(hFile, lpfResource, dwResourceSize, &dwWritten, NULL);
    CloseHandle(hFile);
    if (dwResourceSize != dwWritten) {
        DeleteFile(FileName);
        return NULL;
    } /* if */

    if (!IsWindowsNT())
        FreeResource(hResource);        /* required only for Win95 etc. */

    /* open the file again, now with the DELETE_ON_CLOSE flag */
    hFile = CreateFile(TmpName, GENERIC_READ, FILE_SHARE_READ, NULL,
                       OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, NULL);
    if (hFile == INVALID_HANDLE_VALUE)
        return NULL;

    hinstDLL = LoadLibrary(TmpName);
    if (hinstDLL == NULL) {
        CloseHandle(hFile);             /* this also deletes the file */
        return NULL;
    } /* if */

    #if !defined DLLPACK_NO_UNLOAD
        /* save the file name/handle pair, to be able to unload the DLL */
        DLLfiles.insert(std::pair<std::basic_string<char>,HANDLE>
                        (FileName, hFile));
    #endif

    return hinstDLL;
}


FARPROC WINAPI dpDelayLoadHook(unsigned dliNotify, PDelayLoadInfo pdli)
{
    FARPROC fp = NULL;

    switch (dliNotify) {
    case dliStartProcessing:
        break;

    case dliNotePreLoadLibrary:
        #if !defined DLLPACK_NO_UNLOAD
            strupr((char *)pdli->szDll);
        #endif
        fp = (FARPROC)dpExtractDLL(pdli->szDll);
        break;

    case dliNotePreGetProcAddress:
        break;

    case dliNoteEndProcessing:
        break;

    case dliFailLoadLib: {
        char ErrorMsg[256];
        wsprintf(ErrorMsg, "Fatal error: the application extension %s "
                 "could not be launched. Possible causes: insufficient "
                 "free disk space or a corrupted application file.",
                 pdli->szDll);
        MessageBox(GetFocus(), ErrorMsg, NULL, MB_ICONHAND | MB_SYSTEMMODAL);
        TerminateProcess(GetCurrentProcess(),2);
        break;
        } /* case */

    case dliFailGetProc: {
        char ErrorMsg[256], OrdStr[20];
        const char *FuncName;
        if (pdli->dlp.fImportByName) {
            FuncName = pdli->dlp.szProcName;
        } else {
            wsprintf(OrdStr, "ord:%u", pdli->dlp.dwOrdinal);
            FuncName = OrdStr;
        } /* if */
        wsprintf(ErrorMsg, "Fatal error: the application extension %s "
                 "does not provide the required function %s. Possible "
                 "cause: version conflict.", pdli->szDll, FuncName);
        MessageBox(GetFocus(), ErrorMsg, NULL, MB_ICONHAND | MB_SYSTEMMODAL);
        TerminateProcess(GetCurrentProcess(),2);
        break;
        } /* case */

    } /* switch */

    return fp;
}


#if !defined DLLPACK_NO_UNLOAD

BOOL dpUnloadDLL(LPCSTR FileName)
{
    BOOL result;
    std::map<std::basic_string<char>,HANDLE>::iterator p;

    result = __FUnloadDelayLoadedDLL(FileName);

    if (FileName) {
        /* remove specific DLL */
        p = DLLfiles.find(FileName);
        if (p != DLLfiles.end()) {
            CloseHandle(p->second);
            DLLfiles.erase(p);
        } /* if */
    } else {
        /* remove all DLLs */
        while ((p = DLLfiles.begin()) != DLLfiles.end()) {
            CloseHandle(p->second);
            DLLfiles.erase(p);
        } /* if */
    } /* if */

    return result;
}

#endif


Related Reading


More Insights