mirror of
				https://github.com/python/cpython.git
				synced 2025-11-04 07:31:38 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			134 lines
		
	
	
	
		
			3.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			134 lines
		
	
	
	
		
			3.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* 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
 | 
						|
  function as "__declspec(dllexport) DllMain%module%" 
 | 
						|
  (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[] = {
 | 
						|
	"pywintypes",
 | 
						|
	"pythoncom",
 | 
						|
	"win32ui",
 | 
						|
	NULL,
 | 
						|
};
 | 
						|
 | 
						|
BOOL CallModuleDllMain(char *modName, DWORD dwReason);
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
  Called by a frozen .EXE only, so that built-in extension
 | 
						|
  modules are initialized correctly
 | 
						|
*/
 | 
						|
void PyWinFreeze_ExeInit(void)
 | 
						|
{
 | 
						|
	char **modName;
 | 
						|
	for (modName = possibleModules;*modName;*modName++) {
 | 
						|
/*		printf("Initialising '%s'\n", *modName); */
 | 
						|
		CallModuleDllMain(*modName, DLL_PROCESS_ATTACH);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
  Called by a frozen .EXE only, so that built-in extension
 | 
						|
  modules are cleaned up 
 | 
						|
*/
 | 
						|
void PyWinFreeze_ExeTerm(void)
 | 
						|
{
 | 
						|
	// Must go backwards
 | 
						|
	char **modName;
 | 
						|
	for (modName = possibleModules+(sizeof(possibleModules) / sizeof(char *))-2;
 | 
						|
	     modName >= possibleModules;
 | 
						|
	     *modName--) {
 | 
						|
/*		printf("Terminating '%s'\n", *modName);*/
 | 
						|
		CallModuleDllMain(*modName, DLL_PROCESS_DETACH);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
 | 
						|
{
 | 
						|
	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;
 | 
						|
			for (modName = possibleModules+(sizeof(possibleModules) / sizeof(char *))-2;
 | 
						|
			     modName >= possibleModules;
 | 
						|
			     *modName--)
 | 
						|
				CallModuleDllMain(*modName, DLL_PROCESS_DETACH);
 | 
						|
			break;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return ret;
 | 
						|
}
 | 
						|
 | 
						|
BOOL CallModuleDllMain(char *modName, DWORD dwReason)
 | 
						|
{
 | 
						|
	BOOL (WINAPI * pfndllmain)(HINSTANCE, DWORD, LPVOID);
 | 
						|
 | 
						|
	char funcName[255];
 | 
						|
	HMODULE hmod = GetModuleHandle(NULL);
 | 
						|
	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);
 | 
						|
}
 | 
						|
 |