1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: WinMain/DllMain
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
21 #pragma implementation
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
33 #include "wx/cmdline.h"
35 #include "wx/msw/private.h"
37 #if wxUSE_ON_FATAL_EXCEPTION
38 #include "wx/datetime.h"
39 #include "wx/msw/crashrpt.h"
44 #endif // wxUSE_ON_FATAL_EXCEPTION
47 // there is no ExitProcess() under CE but exiting the main thread has the
50 #define ExitProcess ExitThread
55 // BC++ has to be special: its run-time expects the DLL entry point to be
56 // named DllEntryPoint instead of the (more) standard DllMain
57 #define DllMain DllEntryPoint
58 #endif // __BORLANDC__
60 #if defined(__WXMICROWIN__)
61 #define HINSTANCE HANDLE
64 // defined in common/init.cpp
65 extern int wxEntryReal(int& argc
, wxChar
**argv
);
67 // ============================================================================
68 // implementation: various entry points
69 // ============================================================================
73 #if wxUSE_ON_FATAL_EXCEPTION && defined(__VISUALC__) && !defined(__WXWINCE__)
74 // VC++ (at least from 4.0 up to version 7.1) is incredibly broken in that
75 // a "catch ( ... )" will *always* catch SEH exceptions in it even though
76 // it should have never been the case... to prevent such catches from
77 // stealing the exceptions from our wxGlobalSEHandler which is only called
78 // if the exception is not handled elsewhere, we have to also call it from
79 // a special SEH translator function which is called by VC CRT when a Win32
82 // this warns that /EHa (async exceptions) should be used when using
83 // _set_se_translator but, in fact, this doesn't seem to change anything
84 // with VC++ up to 7.1 -- to be confirmed with VC++ 8
86 #pragma warning(disable:4535)
89 // note that the SE translator must be called wxSETranslator!
90 #define DisableAutomaticSETranslator() _set_se_translator(wxSETranslator)
92 #define DisableAutomaticSETranslator()
93 #endif // __VISUALC__/!__VISUALC__
95 // ----------------------------------------------------------------------------
96 // wrapper wxEntry catching all Win32 exceptions occurring in a wx program
97 // ----------------------------------------------------------------------------
99 // wrap real wxEntry in a try-except block to be able to call
100 // OnFatalException() if necessary
101 #if wxUSE_ON_FATAL_EXCEPTION
103 // global pointer to exception information, only valid inside OnFatalException,
104 // used by wxStackWalker and wxCrashReport
105 extern EXCEPTION_POINTERS
*wxGlobalSEInformation
= NULL
;
107 // flag telling us whether the application wants to handle exceptions at all
108 static bool gs_handleExceptions
= false;
110 static void wxFatalExit()
112 // use the same exit code as abort()
116 unsigned long wxGlobalSEHandler(EXCEPTION_POINTERS
*pExcPtrs
)
118 if ( gs_handleExceptions
&& wxTheApp
)
120 // store the pointer to exception info
121 wxGlobalSEInformation
= pExcPtrs
;
123 // give the user a chance to do something special about this
126 wxTheApp
->OnFatalException();
128 __except ( EXCEPTION_EXECUTE_HANDLER
)
130 // nothing to do here, just ignore the exception inside the
135 wxGlobalSEInformation
= NULL
;
137 // this will execute our handler and terminate the process
138 return EXCEPTION_EXECUTE_HANDLER
;
141 return EXCEPTION_CONTINUE_SEARCH
;
146 static void wxSETranslator(unsigned int WXUNUSED(code
), EXCEPTION_POINTERS
*ep
)
148 switch ( wxGlobalSEHandler(ep
) )
151 wxFAIL_MSG( _T("unexpected wxGlobalSEHandler() return value") );
154 case EXCEPTION_EXECUTE_HANDLER
:
155 // if wxApp::OnFatalException() had been called we should exit the
156 // application -- but we shouldn't kill our host when we're a DLL
162 case EXCEPTION_CONTINUE_SEARCH
:
163 // we're called for each "catch ( ... )" and if we (re)throw from
164 // here, the catch handler body is not executed, so the effect is
165 // as if had inhibited translation of SE to C++ ones because the
166 // handler will never see any structured exceptions
171 #endif // __VISUALC__
173 bool wxHandleFatalExceptions(bool doit
)
175 // assume this can only be called from the main thread
176 gs_handleExceptions
= doit
;
178 #if wxUSE_CRASHREPORT
181 // try to find a place where we can put out report file later
182 wxChar fullname
[MAX_PATH
];
183 if ( !::GetTempPath(WXSIZEOF(fullname
), fullname
) )
185 wxLogLastError(_T("GetTempPath"));
187 // when all else fails...
188 wxStrcpy(fullname
, _T("c:\\"));
191 // use PID and date to make the report file name more unique
192 wxString name
= wxString::Format
195 wxTheApp
? wxTheApp
->GetAppName().c_str()
197 wxDateTime::Now().Format(_T("%Y%m%dT%H%M%S")).c_str(),
198 ::GetCurrentProcessId()
201 wxStrncat(fullname
, name
, WXSIZEOF(fullname
) - wxStrlen(fullname
) - 1);
203 wxCrashReport::SetFileName(fullname
);
205 #endif // wxUSE_CRASHREPORT
210 int wxEntry(int& argc
, wxChar
**argv
)
212 DisableAutomaticSETranslator();
216 return wxEntryReal(argc
, argv
);
218 __except ( wxGlobalSEHandler(GetExceptionInformation()) )
222 #if !defined(_MSC_VER) || defined(__WXDEBUG__) || (defined(_MSC_VER) && _MSC_VER <= 1200)
223 // this code is unreachable but put it here to suppress warnings in some compilers
224 // and disable for others to supress warnings too
226 #endif // !__VISUALC__ in release build
230 #else // !wxUSE_ON_FATAL_EXCEPTION
232 #if defined(__VISUALC__) && !defined(__WXWINCE__)
235 wxSETranslator(unsigned int WXUNUSED(code
), EXCEPTION_POINTERS
* WXUNUSED(ep
))
237 // see wxSETranslator() version for wxUSE_ON_FATAL_EXCEPTION above
241 #endif // __VISUALC__
243 int wxEntry(int& argc
, wxChar
**argv
)
245 DisableAutomaticSETranslator();
247 return wxEntryReal(argc
, argv
);
250 #endif // wxUSE_ON_FATAL_EXCEPTION/!wxUSE_ON_FATAL_EXCEPTION
254 #if wxUSE_GUI && defined(__WXMSW__)
256 // ----------------------------------------------------------------------------
257 // Windows-specific wxEntry
258 // ----------------------------------------------------------------------------
260 WXDLLEXPORT
int wxEntry(HINSTANCE hInstance
,
261 HINSTANCE
WXUNUSED(hPrevInstance
),
262 wxCmdLineArgType
WXUNUSED(pCmdLine
),
265 // the first thing to do is to check if we're trying to run an Unicode
266 // program under Win9x w/o MSLU emulation layer - if so, abort right now
267 // as it has no chance to work and has all chances to crash
268 #if wxUSE_UNICODE && !defined(__WXWINCE__)
269 if ( wxGetOsVersion() != wxWINDOWS_NT
)
271 // we need to be built with MSLU support
272 #if !wxUSE_UNICODE_MSLU
273 // note that we can use MessageBoxW() as it's implemented even under
274 // Win9x - OTOH, we can't use wxGetTranslation() because the file APIs
275 // used by wxLocale are not
279 _T("This program uses Unicode and requires Windows NT/2000/XP.\n\nProgram aborted."),
280 _T("wxWidgets Fatal Error"),
285 #endif // !wxUSE_UNICODE_MSLU
287 // and the MSLU DLL must also be available
288 HMODULE hmod
= ::LoadLibraryA("unicows.dll");
294 _T("This program uses Unicode and requires unicows.dll to work under current operating system.\n\nPlease install unicows.dll and relaunch the program."),
295 _T("wxWidgets Fatal Error"),
301 // this is not really necessary but be tidy
304 #endif // wxUSE_UNICODE && !wxUSE_UNICODE_MSLU
307 // remember the parameters Windows gave us
308 wxSetInstance(hInstance
);
309 wxApp::m_nCmdShow
= nCmdShow
;
311 // parse the command line: we can't use pCmdLine in Unicode build so it is
312 // simpler to never use it at all (this also results in a more correct
315 // break the command line in words
318 const wxChar
*cmdLine
= ::GetCommandLine();
321 args
= wxCmdLineParser::ConvertStringToArgs(cmdLine
);
325 // WinCE doesn't insert the program itself, so do it ourselves.
326 args
.Insert(wxGetFullModuleName(), 0);
329 int argc
= args
.GetCount();
331 // +1 here for the terminating NULL
332 wxChar
**argv
= new wxChar
*[argc
+ 1];
333 for ( int i
= 0; i
< argc
; i
++ )
335 argv
[i
] = wxStrdup(args
[i
]);
338 // argv[] must be NULL-terminated
341 return wxEntry(argc
, argv
);
344 // May wish not to have a DllMain or WinMain, e.g. if we're programming
345 // a Netscape plugin or if we're writing a console application
351 // ----------------------------------------------------------------------------
353 // ----------------------------------------------------------------------------
355 // Note that WinMain is also defined in dummy.obj, which is linked to
356 // an application that is using the DLL version of wxWidgets.
363 DllMain(HINSTANCE hModule
, DWORD fdwReason
, LPVOID
WXUNUSED(lpReserved
))
365 // Only call wxEntry if the application itself is part of the DLL.
366 // If only the wxWidgets library is in the DLL, then the
367 // initialisation will be called when the application implicitly
372 case DLL_PROCESS_ATTACH
:
373 return wxEntry(hModule
);
375 case DLL_PROCESS_DETACH
:
382 #endif // !WXMAKINGDLL
393 #endif // wxUSE_GUI && __WXMSW__
395 // ----------------------------------------------------------------------------
397 // ----------------------------------------------------------------------------
401 HINSTANCE wxhInstance
= 0;
403 extern "C" HINSTANCE
wxGetInstance()
408 void wxSetInstance(HINSTANCE hInst
)