+// we must ensure that DLLs are unloaded before the static objects cleanup time
+// because we may hit the notorious DllMain() dead lock in this case if wx is
+// used as a DLL (attempting to unload another DLL from inside DllMain() hangs
+// under Windows because it tries to reacquire the same lock)
+class wxGDIDLLsCleanupModule : public wxModule
+{
+public:
+ virtual bool OnInit() { return true; }
+ virtual void OnExit() { wxMSIMG32DLL.Unload(); }
+
+private:
+ DECLARE_DYNAMIC_CLASS(wxGDIDLLsCleanupModule)
+};
+
+IMPLEMENT_DYNAMIC_CLASS(wxGDIDLLsCleanupModule, wxModule)
+
+namespace
+{
+
+#if wxUSE_DC_TRANSFORM_MATRIX
+
+// Class used to dynamically load world transform related API functions.
+class GdiWorldTransformFuncs
+{
+public:
+ static bool IsOk()
+ {
+ if ( !ms_worldTransformSymbolsLoaded )
+ LoadWorldTransformSymbols();
+
+ return ms_pfnSetGraphicsMode &&
+ ms_pfnSetWorldTransform &&
+ ms_pfnGetWorldTransform &&
+ ms_pfnModifyWorldTransform;
+ }
+
+ typedef int (WINAPI *SetGraphicsMode_t)(HDC, int);
+ static SetGraphicsMode_t SetGraphicsMode()
+ {
+ if ( !ms_worldTransformSymbolsLoaded )
+ LoadWorldTransformSymbols();
+
+ return ms_pfnSetGraphicsMode;
+ }
+
+ typedef BOOL (WINAPI *SetWorldTransform_t)(HDC, const XFORM *);
+ static SetWorldTransform_t SetWorldTransform()
+ {
+ if ( !ms_worldTransformSymbolsLoaded )
+ LoadWorldTransformSymbols();
+
+ return ms_pfnSetWorldTransform;
+ }
+
+ typedef BOOL (WINAPI *GetWorldTransform_t)(HDC, LPXFORM);
+ static GetWorldTransform_t GetWorldTransform()
+ {
+ if ( !ms_worldTransformSymbolsLoaded )
+ LoadWorldTransformSymbols();
+
+ return ms_pfnGetWorldTransform;
+ }
+
+ typedef BOOL (WINAPI *ModifyWorldTransform_t)(HDC, const XFORM *, DWORD);
+ static ModifyWorldTransform_t ModifyWorldTransform()
+ {
+ if ( !ms_worldTransformSymbolsLoaded )
+ LoadWorldTransformSymbols();
+
+ return ms_pfnModifyWorldTransform;
+ }
+
+private:
+ static void LoadWorldTransformSymbols()
+ {
+ wxDynamicLibrary dll(wxT("gdi32.dll"));
+
+ wxDL_INIT_FUNC(ms_pfn, SetGraphicsMode, dll);
+ wxDL_INIT_FUNC(ms_pfn, SetWorldTransform, dll);
+ wxDL_INIT_FUNC(ms_pfn, GetWorldTransform, dll);
+ wxDL_INIT_FUNC(ms_pfn, ModifyWorldTransform, dll);
+
+ ms_worldTransformSymbolsLoaded = true;
+ }
+
+ static SetGraphicsMode_t ms_pfnSetGraphicsMode;
+ static SetWorldTransform_t ms_pfnSetWorldTransform;
+ static GetWorldTransform_t ms_pfnGetWorldTransform;
+ static ModifyWorldTransform_t ms_pfnModifyWorldTransform;
+
+ static bool ms_worldTransformSymbolsLoaded;
+};
+
+GdiWorldTransformFuncs::SetGraphicsMode_t
+ GdiWorldTransformFuncs::ms_pfnSetGraphicsMode = NULL;
+GdiWorldTransformFuncs::SetWorldTransform_t
+ GdiWorldTransformFuncs::ms_pfnSetWorldTransform = NULL;
+GdiWorldTransformFuncs::GetWorldTransform_t
+ GdiWorldTransformFuncs::ms_pfnGetWorldTransform = NULL;
+GdiWorldTransformFuncs::ModifyWorldTransform_t
+ GdiWorldTransformFuncs::ms_pfnModifyWorldTransform = NULL;
+
+bool GdiWorldTransformFuncs::ms_worldTransformSymbolsLoaded = false;
+
+#endif // wxUSE_DC_TRANSFORM_MATRIX
+
+} // anonymous namespace
+
+#endif // wxUSE_DYNLIB_CLASS