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"
30 #include "wx/scopeguard.h"
32 #include "wx/msw/private.h"
34 #if wxUSE_ON_FATAL_EXCEPTION
35 #include "wx/datetime.h"
36 #include "wx/msw/crashrpt.h"
41 #endif // wxUSE_ON_FATAL_EXCEPTION
44 // there is no ExitProcess() under CE but exiting the main thread has the
47 #define ExitProcess ExitThread
52 // BC++ has to be special: its run-time expects the DLL entry point to be
53 // named DllEntryPoint instead of the (more) standard DllMain
54 #define DllMain DllEntryPoint
55 #endif // __BORLANDC__
57 #if defined(__WXMICROWIN__)
58 #define HINSTANCE HANDLE
61 // defined in common/init.cpp
62 extern int wxEntryReal(int& argc
, wxChar
**argv
);
64 // ============================================================================
65 // implementation: various entry points
66 // ============================================================================
70 #if wxUSE_ON_FATAL_EXCEPTION && defined(__VISUALC__) && !defined(__WXWINCE__)
71 // VC++ (at least from 4.0 up to version 7.1) is incredibly broken in that
72 // a "catch ( ... )" will *always* catch SEH exceptions in it even though
73 // it should have never been the case... to prevent such catches from
74 // stealing the exceptions from our wxGlobalSEHandler which is only called
75 // if the exception is not handled elsewhere, we have to also call it from
76 // a special SEH translator function which is called by VC CRT when a Win32
79 // this warns that /EHa (async exceptions) should be used when using
80 // _set_se_translator but, in fact, this doesn't seem to change anything
81 // with VC++ up to 7.1 -- to be confirmed with VC++ 8
83 #pragma warning(disable:4535)
86 // note that the SE translator must be called wxSETranslator!
87 #define DisableAutomaticSETranslator() _set_se_translator(wxSETranslator)
89 #define DisableAutomaticSETranslator()
90 #endif // __VISUALC__/!__VISUALC__
92 // ----------------------------------------------------------------------------
93 // wrapper wxEntry catching all Win32 exceptions occurring in a wx program
94 // ----------------------------------------------------------------------------
96 // wrap real wxEntry in a try-except block to be able to call
97 // OnFatalException() if necessary
98 #if wxUSE_ON_FATAL_EXCEPTION
100 // global pointer to exception information, only valid inside OnFatalException,
101 // used by wxStackWalker and wxCrashReport
102 extern EXCEPTION_POINTERS
*wxGlobalSEInformation
= NULL
;
104 // flag telling us whether the application wants to handle exceptions at all
105 static bool gs_handleExceptions
= false;
107 static void wxFatalExit()
109 // use the same exit code as abort()
113 unsigned long wxGlobalSEHandler(EXCEPTION_POINTERS
*pExcPtrs
)
115 if ( gs_handleExceptions
&& wxTheApp
)
117 // store the pointer to exception info
118 wxGlobalSEInformation
= pExcPtrs
;
120 // give the user a chance to do something special about this
123 wxTheApp
->OnFatalException();
125 __except ( EXCEPTION_EXECUTE_HANDLER
)
127 // nothing to do here, just ignore the exception inside the
132 wxGlobalSEInformation
= NULL
;
134 // this will execute our handler and terminate the process
135 return EXCEPTION_EXECUTE_HANDLER
;
138 return EXCEPTION_CONTINUE_SEARCH
;
143 static void wxSETranslator(unsigned int WXUNUSED(code
), EXCEPTION_POINTERS
*ep
)
145 switch ( wxGlobalSEHandler(ep
) )
148 wxFAIL_MSG( _T("unexpected wxGlobalSEHandler() return value") );
151 case EXCEPTION_EXECUTE_HANDLER
:
152 // if wxApp::OnFatalException() had been called we should exit the
153 // application -- but we shouldn't kill our host when we're a DLL
159 case EXCEPTION_CONTINUE_SEARCH
:
160 // we're called for each "catch ( ... )" and if we (re)throw from
161 // here, the catch handler body is not executed, so the effect is
162 // as if had inhibited translation of SE to C++ ones because the
163 // handler will never see any structured exceptions
168 #endif // __VISUALC__
170 bool wxHandleFatalExceptions(bool doit
)
172 // assume this can only be called from the main thread
173 gs_handleExceptions
= doit
;
175 #if wxUSE_CRASHREPORT
178 // try to find a place where we can put out report file later
179 wxChar fullname
[MAX_PATH
];
180 if ( !::GetTempPath(WXSIZEOF(fullname
), fullname
) )
182 wxLogLastError(_T("GetTempPath"));
184 // when all else fails...
185 wxStrcpy(fullname
, _T("c:\\"));
188 // use PID and date to make the report file name more unique
189 wxString name
= wxString::Format
192 wxTheApp
? wxTheApp
->GetAppName().c_str()
194 wxDateTime::Now().Format(_T("%Y%m%dT%H%M%S")).c_str(),
195 ::GetCurrentProcessId()
198 wxStrncat(fullname
, name
, WXSIZEOF(fullname
) - wxStrlen(fullname
) - 1);
200 wxCrashReport::SetFileName(fullname
);
202 #endif // wxUSE_CRASHREPORT
207 int wxEntry(int& argc
, wxChar
**argv
)
209 DisableAutomaticSETranslator();
213 return wxEntryReal(argc
, argv
);
215 __except ( wxGlobalSEHandler(GetExceptionInformation()) )
219 #if !defined(_MSC_VER) || defined(__WXDEBUG__) || (defined(_MSC_VER) && _MSC_VER <= 1200)
220 // this code is unreachable but put it here to suppress warnings in some compilers
221 // and disable for others to supress warnings too
223 #endif // !__VISUALC__ in release build
227 #else // !wxUSE_ON_FATAL_EXCEPTION
229 #if defined(__VISUALC__) && !defined(__WXWINCE__)
232 wxSETranslator(unsigned int WXUNUSED(code
), EXCEPTION_POINTERS
* WXUNUSED(ep
))
234 // see wxSETranslator() version for wxUSE_ON_FATAL_EXCEPTION above
238 #endif // __VISUALC__
240 int wxEntry(int& argc
, wxChar
**argv
)
242 DisableAutomaticSETranslator();
244 return wxEntryReal(argc
, argv
);
247 #endif // wxUSE_ON_FATAL_EXCEPTION/!wxUSE_ON_FATAL_EXCEPTION
251 #if wxUSE_GUI && defined(__WXMSW__)
253 #if wxUSE_UNICODE && !defined(__WXWINCE__)
254 #define NEED_UNICODE_CHECK
257 #ifdef NEED_UNICODE_CHECK
259 // check whether Unicode is available
260 static bool wxIsUnicodeAvailable()
262 static const wchar_t *ERROR_STRING
= L
"wxWidgets Fatal Error";
264 if ( wxGetOsVersion() != wxWINDOWS_NT
)
266 // we need to be built with MSLU support
267 #if !wxUSE_UNICODE_MSLU
268 // note that we can use MessageBoxW() as it's implemented even under
269 // Win9x - OTOH, we can't use wxGetTranslation() because the file APIs
270 // used by wxLocale are not
274 L
"This program uses Unicode and requires Windows NT/2000/XP.\n"
282 #else // wxUSE_UNICODE_MSLU
283 // and the MSLU DLL must also be available
284 HMODULE hmod
= ::LoadLibraryA("unicows.dll");
290 L
"This program uses Unicode and requires unicows.dll to work "
291 L
"under current operating system.\n"
293 L
"Please install unicows.dll and relaunch the program.",
300 // this is not really necessary but be tidy
303 // finally do the last check: has unicows.lib initialized correctly?
304 hmod
= ::LoadLibraryW(L
"unicows.dll");
310 L
"This program uses Unicode but is not using unicows.dll\n"
311 L
"correctly and so cannot work under current operating system.\n"
312 L
"Please contact the program author for an updated version.\n"
323 #endif // !wxUSE_UNICODE_MSLU
329 #endif // NEED_UNICODE_CHECK
331 // ----------------------------------------------------------------------------
332 // Windows-specific wxEntry
333 // ----------------------------------------------------------------------------
335 // helper function used to clean up in wxEntry() just below
337 // notice that argv elements are supposed to be allocated using malloc() while
338 // argv array itself is allocated with new
339 static void wxFreeArgs(int argc
, wxChar
**argv
)
341 for ( int i
= 0; i
< argc
; i
++ )
349 WXDLLEXPORT
int wxEntry(HINSTANCE hInstance
,
350 HINSTANCE
WXUNUSED(hPrevInstance
),
351 wxCmdLineArgType
WXUNUSED(pCmdLine
),
354 // the first thing to do is to check if we're trying to run an Unicode
355 // program under Win9x w/o MSLU emulation layer - if so, abort right now
356 // as it has no chance to work and has all chances to crash
357 #ifdef NEED_UNICODE_CHECK
358 if ( !wxIsUnicodeAvailable() )
360 #endif // NEED_UNICODE_CHECK
363 // remember the parameters Windows gave us
364 wxSetInstance(hInstance
);
365 wxApp::m_nCmdShow
= nCmdShow
;
367 // parse the command line: we can't use pCmdLine in Unicode build so it is
368 // simpler to never use it at all (this also results in a more correct
371 // break the command line in words
374 const wxChar
*cmdLine
= ::GetCommandLine();
377 args
= wxCmdLineParser::ConvertStringToArgs(cmdLine
);
381 // WinCE doesn't insert the program itself, so do it ourselves.
382 args
.Insert(wxGetFullModuleName(), 0);
385 int argc
= args
.GetCount();
387 // +1 here for the terminating NULL
388 wxChar
**argv
= new wxChar
*[argc
+ 1];
389 for ( int i
= 0; i
< argc
; i
++ )
391 argv
[i
] = wxStrdup(args
[i
]);
394 // argv[] must be NULL-terminated
397 wxON_BLOCK_EXIT2(wxFreeArgs
, argc
, argv
);
399 return wxEntry(argc
, argv
);
402 #endif // wxUSE_GUI && __WXMSW__
404 // ----------------------------------------------------------------------------
406 // ----------------------------------------------------------------------------
410 HINSTANCE wxhInstance
= 0;
412 extern "C" HINSTANCE
wxGetInstance()
417 void wxSetInstance(HINSTANCE hInst
)