1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: WinMain/DllMain
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
29 #include "wx/cmdline.h"
31 #include "wx/msw/private.h"
33 #if wxUSE_ON_FATAL_EXCEPTION
34 #include "wx/datetime.h"
35 #include "wx/msw/crashrpt.h"
40 #endif // wxUSE_ON_FATAL_EXCEPTION
43 // there is no ExitProcess() under CE but exiting the main thread has the
46 #define ExitProcess ExitThread
51 // BC++ has to be special: its run-time expects the DLL entry point to be
52 // named DllEntryPoint instead of the (more) standard DllMain
53 #define DllMain DllEntryPoint
54 #endif // __BORLANDC__
56 #if defined(__WXMICROWIN__)
57 #define HINSTANCE HANDLE
60 // defined in common/init.cpp
61 extern int wxEntryReal(int& argc
, wxChar
**argv
);
63 // ============================================================================
64 // implementation: various entry points
65 // ============================================================================
69 #if wxUSE_ON_FATAL_EXCEPTION && defined(__VISUALC__) && !defined(__WXWINCE__)
70 // VC++ (at least from 4.0 up to version 7.1) is incredibly broken in that
71 // a "catch ( ... )" will *always* catch SEH exceptions in it even though
72 // it should have never been the case... to prevent such catches from
73 // stealing the exceptions from our wxGlobalSEHandler which is only called
74 // if the exception is not handled elsewhere, we have to also call it from
75 // a special SEH translator function which is called by VC CRT when a Win32
78 // this warns that /EHa (async exceptions) should be used when using
79 // _set_se_translator but, in fact, this doesn't seem to change anything
80 // with VC++ up to 7.1 -- to be confirmed with VC++ 8
82 #pragma warning(disable:4535)
85 // note that the SE translator must be called wxSETranslator!
86 #define DisableAutomaticSETranslator() _set_se_translator(wxSETranslator)
88 #define DisableAutomaticSETranslator()
89 #endif // __VISUALC__/!__VISUALC__
91 // ----------------------------------------------------------------------------
92 // wrapper wxEntry catching all Win32 exceptions occurring in a wx program
93 // ----------------------------------------------------------------------------
95 // wrap real wxEntry in a try-except block to be able to call
96 // OnFatalException() if necessary
97 #if wxUSE_ON_FATAL_EXCEPTION
99 // global pointer to exception information, only valid inside OnFatalException,
100 // used by wxStackWalker and wxCrashReport
101 extern EXCEPTION_POINTERS
*wxGlobalSEInformation
= NULL
;
103 // flag telling us whether the application wants to handle exceptions at all
104 static bool gs_handleExceptions
= false;
106 static void wxFatalExit()
108 // use the same exit code as abort()
112 unsigned long wxGlobalSEHandler(EXCEPTION_POINTERS
*pExcPtrs
)
114 if ( gs_handleExceptions
&& wxTheApp
)
116 // store the pointer to exception info
117 wxGlobalSEInformation
= pExcPtrs
;
119 // give the user a chance to do something special about this
122 wxTheApp
->OnFatalException();
124 __except ( EXCEPTION_EXECUTE_HANDLER
)
126 // nothing to do here, just ignore the exception inside the
131 wxGlobalSEInformation
= NULL
;
133 // this will execute our handler and terminate the process
134 return EXCEPTION_EXECUTE_HANDLER
;
137 return EXCEPTION_CONTINUE_SEARCH
;
142 static void wxSETranslator(unsigned int WXUNUSED(code
), EXCEPTION_POINTERS
*ep
)
144 switch ( wxGlobalSEHandler(ep
) )
147 wxFAIL_MSG( _T("unexpected wxGlobalSEHandler() return value") );
150 case EXCEPTION_EXECUTE_HANDLER
:
151 // if wxApp::OnFatalException() had been called we should exit the
152 // application -- but we shouldn't kill our host when we're a DLL
158 case EXCEPTION_CONTINUE_SEARCH
:
159 // we're called for each "catch ( ... )" and if we (re)throw from
160 // here, the catch handler body is not executed, so the effect is
161 // as if had inhibited translation of SE to C++ ones because the
162 // handler will never see any structured exceptions
167 #endif // __VISUALC__
169 bool wxHandleFatalExceptions(bool doit
)
171 // assume this can only be called from the main thread
172 gs_handleExceptions
= doit
;
174 #if wxUSE_CRASHREPORT
177 // try to find a place where we can put out report file later
178 wxChar fullname
[MAX_PATH
];
179 if ( !::GetTempPath(WXSIZEOF(fullname
), fullname
) )
181 wxLogLastError(_T("GetTempPath"));
183 // when all else fails...
184 wxStrcpy(fullname
, _T("c:\\"));
187 // use PID and date to make the report file name more unique
188 wxString name
= wxString::Format
191 wxTheApp
? wxTheApp
->GetAppName().c_str()
193 wxDateTime::Now().Format(_T("%Y%m%dT%H%M%S")).c_str(),
194 ::GetCurrentProcessId()
197 wxStrncat(fullname
, name
, WXSIZEOF(fullname
) - wxStrlen(fullname
) - 1);
199 wxCrashReport::SetFileName(fullname
);
201 #endif // wxUSE_CRASHREPORT
206 int wxEntry(int& argc
, wxChar
**argv
)
208 DisableAutomaticSETranslator();
212 return wxEntryReal(argc
, argv
);
214 __except ( wxGlobalSEHandler(GetExceptionInformation()) )
218 #if !defined(_MSC_VER) || defined(__WXDEBUG__) || (defined(_MSC_VER) && _MSC_VER <= 1200)
219 // this code is unreachable but put it here to suppress warnings in some compilers
220 // and disable for others to supress warnings too
222 #endif // !__VISUALC__ in release build
226 #else // !wxUSE_ON_FATAL_EXCEPTION
228 #if defined(__VISUALC__) && !defined(__WXWINCE__)
231 wxSETranslator(unsigned int WXUNUSED(code
), EXCEPTION_POINTERS
* WXUNUSED(ep
))
233 // see wxSETranslator() version for wxUSE_ON_FATAL_EXCEPTION above
237 #endif // __VISUALC__
239 int wxEntry(int& argc
, wxChar
**argv
)
241 DisableAutomaticSETranslator();
243 return wxEntryReal(argc
, argv
);
246 #endif // wxUSE_ON_FATAL_EXCEPTION/!wxUSE_ON_FATAL_EXCEPTION
250 #if wxUSE_GUI && defined(__WXMSW__)
252 #if wxUSE_UNICODE && !defined(__WXWINCE__)
253 #define NEED_UNICODE_CHECK
256 #ifdef NEED_UNICODE_CHECK
258 // check whether Unicode is available
259 static bool wxIsUnicodeAvailable()
261 static const wchar_t *ERROR_STRING
= L
"wxWidgets Fatal Error";
263 if ( wxGetOsVersion() != wxWINDOWS_NT
)
265 // we need to be built with MSLU support
266 #if !wxUSE_UNICODE_MSLU
267 // note that we can use MessageBoxW() as it's implemented even under
268 // Win9x - OTOH, we can't use wxGetTranslation() because the file APIs
269 // used by wxLocale are not
273 L
"This program uses Unicode and requires Windows NT/2000/XP.\n"
281 #else // wxUSE_UNICODE_MSLU
282 // and the MSLU DLL must also be available
283 HMODULE hmod
= ::LoadLibraryA("unicows.dll");
289 L
"This program uses Unicode and requires unicows.dll to work "
290 L
"under current operating system.\n"
292 L
"Please install unicows.dll and relaunch the program.",
299 // this is not really necessary but be tidy
302 // finally do the last check: has unicows.lib initialized correctly?
303 hmod
= ::LoadLibraryW(L
"unicows.dll");
309 L
"This program uses Unicode but is not using unicows.dll\n"
310 L
"correctly and so cannot work under current operating system.\n"
311 L
"Please contact the program author for an updated version.\n"
322 #endif // !wxUSE_UNICODE_MSLU
328 #endif // NEED_UNICODE_CHECK
330 // ----------------------------------------------------------------------------
331 // Windows-specific wxEntry
332 // ----------------------------------------------------------------------------
334 WXDLLEXPORT
int wxEntry(HINSTANCE hInstance
,
335 HINSTANCE
WXUNUSED(hPrevInstance
),
336 wxCmdLineArgType
WXUNUSED(pCmdLine
),
339 // the first thing to do is to check if we're trying to run an Unicode
340 // program under Win9x w/o MSLU emulation layer - if so, abort right now
341 // as it has no chance to work and has all chances to crash
342 #ifdef NEED_UNICODE_CHECK
343 if ( !wxIsUnicodeAvailable() )
345 #endif // NEED_UNICODE_CHECK
348 // remember the parameters Windows gave us
349 wxSetInstance(hInstance
);
350 wxApp::m_nCmdShow
= nCmdShow
;
352 // parse the command line: we can't use pCmdLine in Unicode build so it is
353 // simpler to never use it at all (this also results in a more correct
356 // break the command line in words
359 const wxChar
*cmdLine
= ::GetCommandLine();
362 args
= wxCmdLineParser::ConvertStringToArgs(cmdLine
);
366 // WinCE doesn't insert the program itself, so do it ourselves.
367 args
.Insert(wxGetFullModuleName(), 0);
370 int argc
= args
.GetCount();
372 // +1 here for the terminating NULL
373 wxChar
**argv
= new wxChar
*[argc
+ 1];
374 for ( int i
= 0; i
< argc
; i
++ )
376 argv
[i
] = wxStrdup(args
[i
]);
379 // argv[] must be NULL-terminated
382 return wxEntry(argc
, argv
);
385 // May wish not to have a DllMain or WinMain, e.g. if we're programming
386 // a Netscape plugin or if we're writing a console application
392 // ----------------------------------------------------------------------------
394 // ----------------------------------------------------------------------------
396 // Note that WinMain is also defined in dummy.obj, which is linked to
397 // an application that is using the DLL version of wxWidgets.
404 DllMain(HINSTANCE hModule
, DWORD fdwReason
, LPVOID
WXUNUSED(lpReserved
))
406 // Only call wxEntry if the application itself is part of the DLL.
407 // If only the wxWidgets library is in the DLL, then the
408 // initialisation will be called when the application implicitly
413 case DLL_PROCESS_ATTACH
:
414 return wxEntry(hModule
);
416 case DLL_PROCESS_DETACH
:
423 #endif // !WXMAKINGDLL
434 #endif // wxUSE_GUI && __WXMSW__
436 // ----------------------------------------------------------------------------
438 // ----------------------------------------------------------------------------
442 HINSTANCE wxhInstance
= 0;
444 extern "C" HINSTANCE
wxGetInstance()
449 void wxSetInstance(HINSTANCE hInst
)