17db96d56Sopenharmony_ci/* FreezeDLLMain.cpp
27db96d56Sopenharmony_ci
37db96d56Sopenharmony_ciThis is a DLLMain suitable for frozen applications/DLLs on
47db96d56Sopenharmony_cia Windows platform.
57db96d56Sopenharmony_ci
67db96d56Sopenharmony_ciThe general problem is that many Python extension modules may define
77db96d56Sopenharmony_ciDLL main functions, but when statically linked together to form
87db96d56Sopenharmony_cia frozen application, this DLLMain symbol exists multiple times.
97db96d56Sopenharmony_ci
107db96d56Sopenharmony_ciThe solution is:
117db96d56Sopenharmony_ci* Each module checks for a frozen build, and if so, defines its DLLMain
127db96d56Sopenharmony_ci  function as "__declspec(dllexport) DllMain%module%"
137db96d56Sopenharmony_ci  (eg, DllMainpythoncom, or DllMainpywintypes)
147db96d56Sopenharmony_ci
157db96d56Sopenharmony_ci* The frozen .EXE/.DLL links against this module, which provides
167db96d56Sopenharmony_ci  the single DllMain.
177db96d56Sopenharmony_ci
187db96d56Sopenharmony_ci* This DllMain attempts to locate and call the DllMain for each
197db96d56Sopenharmony_ci  of the extension modules.
207db96d56Sopenharmony_ci
217db96d56Sopenharmony_ci* This code also has hooks to "simulate" DllMain when used from
227db96d56Sopenharmony_ci  a frozen .EXE.
237db96d56Sopenharmony_ci
247db96d56Sopenharmony_ciAt this stage, there is a static table of "possibly embedded modules".
257db96d56Sopenharmony_ciThis should change to something better, but it will work OK for now.
267db96d56Sopenharmony_ci
277db96d56Sopenharmony_ciNote that this scheme does not handle dependencies in the order
287db96d56Sopenharmony_ciof DllMain calls - except it does call pywintypes first :-)
297db96d56Sopenharmony_ci
307db96d56Sopenharmony_ciAs an example of how an extension module with a DllMain should be
317db96d56Sopenharmony_cichanged, here is a snippet from the pythoncom extension module.
327db96d56Sopenharmony_ci
337db96d56Sopenharmony_ci  // end of example code from pythoncom's DllMain.cpp
347db96d56Sopenharmony_ci  #ifndef BUILD_FREEZE
357db96d56Sopenharmony_ci  #define DLLMAIN DllMain
367db96d56Sopenharmony_ci  #define DLLMAIN_DECL
377db96d56Sopenharmony_ci  #else
387db96d56Sopenharmony_ci  #define DLLMAIN DllMainpythoncom
397db96d56Sopenharmony_ci  #define DLLMAIN_DECL __declspec(dllexport)
407db96d56Sopenharmony_ci  #endif
417db96d56Sopenharmony_ci
427db96d56Sopenharmony_ci  extern "C" DLLMAIN_DECL
437db96d56Sopenharmony_ci  BOOL WINAPI DLLMAIN(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
447db96d56Sopenharmony_ci  // end of example code from pythoncom's DllMain.cpp
457db96d56Sopenharmony_ci
467db96d56Sopenharmony_ci***************************************************************************/
477db96d56Sopenharmony_ci#include "windows.h"
487db96d56Sopenharmony_ci
497db96d56Sopenharmony_cistatic char *possibleModules[] = {
507db96d56Sopenharmony_ci    "pywintypes",
517db96d56Sopenharmony_ci    "pythoncom",
527db96d56Sopenharmony_ci    "win32ui",
537db96d56Sopenharmony_ci    NULL,
547db96d56Sopenharmony_ci};
557db96d56Sopenharmony_ci
567db96d56Sopenharmony_ciBOOL CallModuleDllMain(char *modName, DWORD dwReason);
577db96d56Sopenharmony_ci
587db96d56Sopenharmony_ci
597db96d56Sopenharmony_ci/*
607db96d56Sopenharmony_ci  Called by a frozen .EXE only, so that built-in extension
617db96d56Sopenharmony_ci  modules are initialized correctly
627db96d56Sopenharmony_ci*/
637db96d56Sopenharmony_civoid PyWinFreeze_ExeInit(void)
647db96d56Sopenharmony_ci{
657db96d56Sopenharmony_ci    char **modName;
667db96d56Sopenharmony_ci    for (modName = possibleModules;*modName;*modName++) {
677db96d56Sopenharmony_ci/*              printf("Initialising '%s'\n", *modName); */
687db96d56Sopenharmony_ci        CallModuleDllMain(*modName, DLL_PROCESS_ATTACH);
697db96d56Sopenharmony_ci    }
707db96d56Sopenharmony_ci}
717db96d56Sopenharmony_ci
727db96d56Sopenharmony_ci/*
737db96d56Sopenharmony_ci  Called by a frozen .EXE only, so that built-in extension
747db96d56Sopenharmony_ci  modules are cleaned up
757db96d56Sopenharmony_ci*/
767db96d56Sopenharmony_civoid PyWinFreeze_ExeTerm(void)
777db96d56Sopenharmony_ci{
787db96d56Sopenharmony_ci    // Must go backwards
797db96d56Sopenharmony_ci    char **modName;
807db96d56Sopenharmony_ci    for (modName = possibleModules+Py_ARRAY_LENGTH(possibleModules)-2;
817db96d56Sopenharmony_ci         modName >= possibleModules;
827db96d56Sopenharmony_ci         *modName--) {
837db96d56Sopenharmony_ci/*              printf("Terminating '%s'\n", *modName);*/
847db96d56Sopenharmony_ci        CallModuleDllMain(*modName, DLL_PROCESS_DETACH);
857db96d56Sopenharmony_ci    }
867db96d56Sopenharmony_ci}
877db96d56Sopenharmony_ci
887db96d56Sopenharmony_ciBOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
897db96d56Sopenharmony_ci{
907db96d56Sopenharmony_ci    BOOL ret = TRUE;
917db96d56Sopenharmony_ci    switch (dwReason) {
927db96d56Sopenharmony_ci        case DLL_PROCESS_ATTACH:
937db96d56Sopenharmony_ci        {
947db96d56Sopenharmony_ci            char **modName;
957db96d56Sopenharmony_ci            for (modName = possibleModules;*modName;*modName++) {
967db96d56Sopenharmony_ci                BOOL ok = CallModuleDllMain(*modName, dwReason);
977db96d56Sopenharmony_ci                if (!ok)
987db96d56Sopenharmony_ci                    ret = FALSE;
997db96d56Sopenharmony_ci            }
1007db96d56Sopenharmony_ci            break;
1017db96d56Sopenharmony_ci        }
1027db96d56Sopenharmony_ci        case DLL_PROCESS_DETACH:
1037db96d56Sopenharmony_ci        {
1047db96d56Sopenharmony_ci            // Must go backwards
1057db96d56Sopenharmony_ci            char **modName;
1067db96d56Sopenharmony_ci            for (modName = possibleModules+Py_ARRAY_LENGTH(possibleModules)-2;
1077db96d56Sopenharmony_ci                 modName >= possibleModules;
1087db96d56Sopenharmony_ci                 *modName--)
1097db96d56Sopenharmony_ci                CallModuleDllMain(*modName, DLL_PROCESS_DETACH);
1107db96d56Sopenharmony_ci            break;
1117db96d56Sopenharmony_ci        }
1127db96d56Sopenharmony_ci    }
1137db96d56Sopenharmony_ci    return ret;
1147db96d56Sopenharmony_ci}
1157db96d56Sopenharmony_ci
1167db96d56Sopenharmony_ciBOOL CallModuleDllMain(char *modName, DWORD dwReason)
1177db96d56Sopenharmony_ci{
1187db96d56Sopenharmony_ci    BOOL (WINAPI * pfndllmain)(HINSTANCE, DWORD, LPVOID);
1197db96d56Sopenharmony_ci
1207db96d56Sopenharmony_ci    char funcName[255];
1217db96d56Sopenharmony_ci    HMODULE hmod = GetModuleHandleW(NULL);
1227db96d56Sopenharmony_ci    strcpy(funcName, "_DllMain");
1237db96d56Sopenharmony_ci    strcat(funcName, modName);
1247db96d56Sopenharmony_ci    strcat(funcName, "@12"); // stdcall convention.
1257db96d56Sopenharmony_ci    pfndllmain = (BOOL (WINAPI *)(HINSTANCE, DWORD, LPVOID))GetProcAddress(hmod, funcName);
1267db96d56Sopenharmony_ci    if (pfndllmain==NULL) {
1277db96d56Sopenharmony_ci        /* No function by that name exported - then that module does
1287db96d56Sopenharmony_ci           not appear in our frozen program - return OK
1297db96d56Sopenharmony_ci        */
1307db96d56Sopenharmony_ci        return TRUE;
1317db96d56Sopenharmony_ci    }
1327db96d56Sopenharmony_ci    return (*pfndllmain)(hmod, dwReason, NULL);
1337db96d56Sopenharmony_ci}
1347db96d56Sopenharmony_ci
135