/* FreezeDLLMain.cpp12This is a DLLMain suitable for frozen applications/DLLs on3a Windows platform.45The general problem is that many Python extension modules may define6DLL main functions, but when statically linked together to form7a frozen application, this DLLMain symbol exists multiple times.89The solution is:10* Each module checks for a frozen build, and if so, defines its DLLMain11function as "__declspec(dllexport) DllMain%module%"12(eg, DllMainpythoncom, or DllMainpywintypes)1314* The frozen .EXE/.DLL links against this module, which provides15the single DllMain.1617* This DllMain attempts to locate and call the DllMain for each18of the extension modules.1920* This code also has hooks to "simulate" DllMain when used from21a frozen .EXE.2223At this stage, there is a static table of "possibly embedded modules".24This should change to something better, but it will work OK for now.2526Note that this scheme does not handle dependencies in the order27of DllMain calls - except it does call pywintypes first :-)2829As an example of how an extension module with a DllMain should be30changed, here is a snippet from the pythoncom extension module.3132// end of example code from pythoncom's DllMain.cpp33#ifndef BUILD_FREEZE34#define DLLMAIN DllMain35#define DLLMAIN_DECL36#else37#define DLLMAIN DllMainpythoncom38#define DLLMAIN_DECL __declspec(dllexport)39#endif4041extern "C" DLLMAIN_DECL42BOOL WINAPI DLLMAIN(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)43// end of example code from pythoncom's DllMain.cpp4445***************************************************************************/46#include "windows.h"4748static char *possibleModules[] = {49"pywintypes",50"pythoncom",51"win32ui",52NULL,53};5455BOOL CallModuleDllMain(char *modName, DWORD dwReason);565758/*59Called by a frozen .EXE only, so that built-in extension60modules are initialized correctly61*/62void PyWinFreeze_ExeInit(void)63{64char **modName;65for (modName = possibleModules;*modName;*modName++) {66/* printf("Initialising '%s'\n", *modName); */67CallModuleDllMain(*modName, DLL_PROCESS_ATTACH);68}69}7071/*72Called by a frozen .EXE only, so that built-in extension73modules are cleaned up74*/75void PyWinFreeze_ExeTerm(void)76{77// Must go backwards78char **modName;79for (modName = possibleModules+Py_ARRAY_LENGTH(possibleModules)-2;80modName >= possibleModules;81*modName--) {82/* printf("Terminating '%s'\n", *modName);*/83CallModuleDllMain(*modName, DLL_PROCESS_DETACH);84}85}8687BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)88{89BOOL ret = TRUE;90switch (dwReason) {91case DLL_PROCESS_ATTACH:92{93char **modName;94for (modName = possibleModules;*modName;*modName++) {95BOOL ok = CallModuleDllMain(*modName, dwReason);96if (!ok)97ret = FALSE;98}99break;100}101case DLL_PROCESS_DETACH:102{103// Must go backwards104char **modName;105for (modName = possibleModules+Py_ARRAY_LENGTH(possibleModules)-2;106modName >= possibleModules;107*modName--)108CallModuleDllMain(*modName, DLL_PROCESS_DETACH);109break;110}111}112return ret;113}114115BOOL CallModuleDllMain(char *modName, DWORD dwReason)116{117BOOL (WINAPI * pfndllmain)(HINSTANCE, DWORD, LPVOID);118119char funcName[255];120HMODULE hmod = GetModuleHandleW(NULL);121strcpy(funcName, "_DllMain");122strcat(funcName, modName);123strcat(funcName, "@12"); // stdcall convention.124pfndllmain = (BOOL (WINAPI *)(HINSTANCE, DWORD, LPVOID))GetProcAddress(hmod, funcName);125if (pfndllmain==NULL) {126/* No function by that name exported - then that module does127not appear in our frozen program - return OK128*/129return TRUE;130}131return (*pfndllmain)(hmod, dwReason, NULL);132}133134135136