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