| 
									
										
										
										
											1998-03-20 17:34:26 +00:00
										 |  |  | /* FreezeDLLMain.cpp
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This is a DLLMain suitable for frozen applications/DLLs on | 
					
						
							|  |  |  | a Windows platform. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The general problem is that many Python extension modules may define | 
					
						
							|  |  |  | DLL main functions, but when statically linked together to form | 
					
						
							|  |  |  | a frozen application, this DLLMain symbol exists multiple times. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The solution is: | 
					
						
							|  |  |  | * Each module checks for a frozen build, and if so, defines its DLLMain | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |   function as "__declspec(dllexport) DllMain%module%" | 
					
						
							| 
									
										
										
										
											1998-03-20 17:34:26 +00:00
										 |  |  |   (eg, DllMainpythoncom, or DllMainpywintypes) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | * The frozen .EXE/.DLL links against this module, which provides | 
					
						
							|  |  |  |   the single DllMain. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | * This DllMain attempts to locate and call the DllMain for each | 
					
						
							|  |  |  |   of the extension modules. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | * This code also has hooks to "simulate" DllMain when used from | 
					
						
							|  |  |  |   a frozen .EXE. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | At this stage, there is a static table of "possibly embedded modules". | 
					
						
							|  |  |  | This should change to something better, but it will work OK for now. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Note that this scheme does not handle dependencies in the order | 
					
						
							|  |  |  | of DllMain calls - except it does call pywintypes first :-) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | As an example of how an extension module with a DllMain should be | 
					
						
							|  |  |  | changed, here is a snippet from the pythoncom extension module. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // end of example code from pythoncom's DllMain.cpp
 | 
					
						
							|  |  |  |   #ifndef BUILD_FREEZE
 | 
					
						
							|  |  |  |   #define DLLMAIN DllMain
 | 
					
						
							|  |  |  |   #define DLLMAIN_DECL
 | 
					
						
							|  |  |  |   #else
 | 
					
						
							|  |  |  |   #define DLLMAIN DllMainpythoncom
 | 
					
						
							|  |  |  |   #define DLLMAIN_DECL __declspec(dllexport)
 | 
					
						
							|  |  |  |   #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   extern "C" DLLMAIN_DECL | 
					
						
							|  |  |  |   BOOL WINAPI DLLMAIN(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) | 
					
						
							|  |  |  |   // end of example code from pythoncom's DllMain.cpp
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ***************************************************************************/ | 
					
						
							|  |  |  | #include "windows.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static char *possibleModules[] = { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     "pywintypes", | 
					
						
							|  |  |  |     "pythoncom", | 
					
						
							|  |  |  |     "win32ui", | 
					
						
							|  |  |  |     NULL, | 
					
						
							| 
									
										
										
										
											1998-03-20 17:34:26 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | BOOL CallModuleDllMain(char *modName, DWORD dwReason); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |   Called by a frozen .EXE only, so that built-in extension | 
					
						
							|  |  |  |   modules are initialized correctly | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											2000-07-22 19:25:51 +00:00
										 |  |  | void PyWinFreeze_ExeInit(void) | 
					
						
							| 
									
										
										
										
											1998-03-20 17:34:26 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     char **modName; | 
					
						
							|  |  |  |     for (modName = possibleModules;*modName;*modName++) { | 
					
						
							|  |  |  | /*              printf("Initialising '%s'\n", *modName); */ | 
					
						
							|  |  |  |         CallModuleDllMain(*modName, DLL_PROCESS_ATTACH); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											1998-03-20 17:34:26 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |   Called by a frozen .EXE only, so that built-in extension | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |   modules are cleaned up | 
					
						
							| 
									
										
										
										
											1998-03-20 17:34:26 +00:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2000-07-22 19:25:51 +00:00
										 |  |  | void PyWinFreeze_ExeTerm(void) | 
					
						
							| 
									
										
										
										
											1998-03-20 17:34:26 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     // Must go backwards
 | 
					
						
							|  |  |  |     char **modName; | 
					
						
							| 
									
										
										
										
											2011-09-29 00:42:28 +02:00
										 |  |  |     for (modName = possibleModules+Py_ARRAY_LENGTH(possibleModules)-2; | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |          modName >= possibleModules; | 
					
						
							|  |  |  |          *modName--) { | 
					
						
							|  |  |  | /*              printf("Terminating '%s'\n", *modName);*/ | 
					
						
							|  |  |  |         CallModuleDllMain(*modName, DLL_PROCESS_DETACH); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											1998-03-20 17:34:26 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     BOOL ret = TRUE; | 
					
						
							|  |  |  |     switch (dwReason) { | 
					
						
							|  |  |  |         case DLL_PROCESS_ATTACH: | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             char **modName; | 
					
						
							|  |  |  |             for (modName = possibleModules;*modName;*modName++) { | 
					
						
							|  |  |  |                 BOOL ok = CallModuleDllMain(*modName, dwReason); | 
					
						
							|  |  |  |                 if (!ok) | 
					
						
							|  |  |  |                     ret = FALSE; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         case DLL_PROCESS_DETACH: | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             // Must go backwards
 | 
					
						
							|  |  |  |             char **modName; | 
					
						
							| 
									
										
										
										
											2011-09-29 00:42:28 +02:00
										 |  |  |             for (modName = possibleModules+Py_ARRAY_LENGTH(possibleModules)-2; | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |                  modName >= possibleModules; | 
					
						
							|  |  |  |                  *modName--) | 
					
						
							|  |  |  |                 CallModuleDllMain(*modName, DLL_PROCESS_DETACH); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return ret; | 
					
						
							| 
									
										
										
										
											1998-03-20 17:34:26 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | BOOL CallModuleDllMain(char *modName, DWORD dwReason) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     BOOL (WINAPI * pfndllmain)(HINSTANCE, DWORD, LPVOID); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     char funcName[255]; | 
					
						
							| 
									
										
										
										
											2012-01-14 17:54:09 +01:00
										 |  |  |     HMODULE hmod = GetModuleHandleW(NULL); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     strcpy(funcName, "_DllMain"); | 
					
						
							|  |  |  |     strcat(funcName, modName); | 
					
						
							|  |  |  |     strcat(funcName, "@12"); // stdcall convention.
 | 
					
						
							|  |  |  |     pfndllmain = (BOOL (WINAPI *)(HINSTANCE, DWORD, LPVOID))GetProcAddress(hmod, funcName); | 
					
						
							|  |  |  |     if (pfndllmain==NULL) { | 
					
						
							|  |  |  |         /* No function by that name exported - then that module does
 | 
					
						
							|  |  |  |            not appear in our frozen program - return OK | 
					
						
							|  |  |  |         */ | 
					
						
							|  |  |  |         return TRUE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return (*pfndllmain)(hmod, dwReason, NULL); | 
					
						
							| 
									
										
										
										
											1998-03-20 17:34:26 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 |