]> git.saurik.com Git - wxWidgets.git/blame - src/msw/main.cpp
Better fix
[wxWidgets.git] / src / msw / main.cpp
CommitLineData
2bda0e17 1/////////////////////////////////////////////////////////////////////////////
d5da0ce7 2// Name: src/msw/main.cpp
e2478fde 3// Purpose: WinMain/DllMain
2bda0e17
KB
4// Author: Julian Smart
5// Modified by:
6// Created: 04/01/98
7// RCS-ID: $Id$
6c9a19aa 8// Copyright: (c) Julian Smart
65571936 9// Licence: wxWindows licence
2bda0e17
KB
10/////////////////////////////////////////////////////////////////////////////
11
b568d04f
VZ
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
2bda0e17
KB
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
b568d04f 24 #pragma hdrstop
2bda0e17
KB
25#endif
26
d5da0ce7
WS
27#ifndef WX_PRECOMP
28 #include "wx/event.h"
670f9935 29 #include "wx/app.h"
c43507b0 30 #include "wx/utils.h"
d5da0ce7
WS
31#endif //WX_PRECOMP
32
94826170 33#include "wx/cmdline.h"
48733d47 34#include "wx/scopeguard.h"
b568d04f
VZ
35
36#include "wx/msw/private.h"
39ea2103 37#include "wx/msw/seh.h"
b568d04f 38
8c125d13
VZ
39#if wxUSE_ON_FATAL_EXCEPTION
40 #include "wx/datetime.h"
41 #include "wx/msw/crashrpt.h"
8c125d13
VZ
42#endif // wxUSE_ON_FATAL_EXCEPTION
43
44#ifdef __WXWINCE__
45 // there is no ExitProcess() under CE but exiting the main thread has the
46 // same effect
226c11c0
VZ
47 #ifndef ExitProcess
48 #define ExitProcess ExitThread
49 #endif
50#endif // __WXWINCE__
8c125d13 51
e2478fde
VZ
52#ifdef __BORLANDC__
53 // BC++ has to be special: its run-time expects the DLL entry point to be
54 // named DllEntryPoint instead of the (more) standard DllMain
55 #define DllMain DllEntryPoint
226c11c0 56#endif // __BORLANDC__
e2478fde
VZ
57
58#if defined(__WXMICROWIN__)
59 #define HINSTANCE HANDLE
60#endif
beed393c 61
1ac4716d
VZ
62// defined in common/init.cpp
63extern int wxEntryReal(int& argc, wxChar **argv);
d76a558d 64extern int wxEntryCleanupReal(int& argc, wxChar **argv);
1ac4716d 65
b568d04f 66// ============================================================================
e2478fde 67// implementation: various entry points
b568d04f
VZ
68// ============================================================================
69
226c11c0
VZ
70#if wxUSE_BASE
71
84bdb0d8 72#if wxUSE_ON_FATAL_EXCEPTION && defined(__VISUALC__) && !defined(__WXWINCE__)
226c11c0
VZ
73 // VC++ (at least from 4.0 up to version 7.1) is incredibly broken in that
74 // a "catch ( ... )" will *always* catch SEH exceptions in it even though
75 // it should have never been the case... to prevent such catches from
76 // stealing the exceptions from our wxGlobalSEHandler which is only called
77 // if the exception is not handled elsewhere, we have to also call it from
78 // a special SEH translator function which is called by VC CRT when a Win32
79 // exception occurs
80
81 // this warns that /EHa (async exceptions) should be used when using
82 // _set_se_translator but, in fact, this doesn't seem to change anything
23c06cde
VZ
83 // with VC++ up to 8.0
84 #if _MSC_VER <= 1400
226c11c0
VZ
85 #pragma warning(disable:4535)
86 #endif
87
88 // note that the SE translator must be called wxSETranslator!
89 #define DisableAutomaticSETranslator() _set_se_translator(wxSETranslator)
90#else // !__VISUALC__
91 #define DisableAutomaticSETranslator()
92#endif // __VISUALC__/!__VISUALC__
93
8c125d13 94// ----------------------------------------------------------------------------
3103e8a9 95// wrapper wxEntry catching all Win32 exceptions occurring in a wx program
8c125d13
VZ
96// ----------------------------------------------------------------------------
97
98// wrap real wxEntry in a try-except block to be able to call
99// OnFatalException() if necessary
226c11c0
VZ
100#if wxUSE_ON_FATAL_EXCEPTION
101
8c125d13
VZ
102// global pointer to exception information, only valid inside OnFatalException,
103// used by wxStackWalker and wxCrashReport
104extern EXCEPTION_POINTERS *wxGlobalSEInformation = NULL;
105
106// flag telling us whether the application wants to handle exceptions at all
107static bool gs_handleExceptions = false;
108
226c11c0
VZ
109static void wxFatalExit()
110{
111 // use the same exit code as abort()
112 ::ExitProcess(3);
113}
114
8c125d13
VZ
115unsigned long wxGlobalSEHandler(EXCEPTION_POINTERS *pExcPtrs)
116{
117 if ( gs_handleExceptions && wxTheApp )
118 {
119 // store the pointer to exception info
120 wxGlobalSEInformation = pExcPtrs;
121
122 // give the user a chance to do something special about this
39ea2103 123 wxSEH_TRY
8c125d13
VZ
124 {
125 wxTheApp->OnFatalException();
126 }
39ea2103 127 wxSEH_IGNORE // ignore any exceptions inside the exception handler
8c125d13
VZ
128
129 wxGlobalSEInformation = NULL;
130
131 // this will execute our handler and terminate the process
132 return EXCEPTION_EXECUTE_HANDLER;
133 }
134
135 return EXCEPTION_CONTINUE_SEARCH;
136}
137
138#ifdef __VISUALC__
139
39ea2103 140void wxSETranslator(unsigned int WXUNUSED(code), EXCEPTION_POINTERS *ep)
8c125d13 141{
226c11c0
VZ
142 switch ( wxGlobalSEHandler(ep) )
143 {
144 default:
145 wxFAIL_MSG( _T("unexpected wxGlobalSEHandler() return value") );
146 // fall through
147
148 case EXCEPTION_EXECUTE_HANDLER:
149 // if wxApp::OnFatalException() had been called we should exit the
150 // application -- but we shouldn't kill our host when we're a DLL
151#ifndef WXMAKINGDLL
152 wxFatalExit();
153#endif // not a DLL
154 break;
155
156 case EXCEPTION_CONTINUE_SEARCH:
157 // we're called for each "catch ( ... )" and if we (re)throw from
158 // here, the catch handler body is not executed, so the effect is
159 // as if had inhibited translation of SE to C++ ones because the
160 // handler will never see any structured exceptions
161 throw;
162 }
8c125d13
VZ
163}
164
165#endif // __VISUALC__
166
167bool wxHandleFatalExceptions(bool doit)
168{
169 // assume this can only be called from the main thread
170 gs_handleExceptions = doit;
171
8c125d13
VZ
172#if wxUSE_CRASHREPORT
173 if ( doit )
174 {
175 // try to find a place where we can put out report file later
176 wxChar fullname[MAX_PATH];
177 if ( !::GetTempPath(WXSIZEOF(fullname), fullname) )
178 {
179 wxLogLastError(_T("GetTempPath"));
180
181 // when all else fails...
182 wxStrcpy(fullname, _T("c:\\"));
183 }
184
185 // use PID and date to make the report file name more unique
186 wxString name = wxString::Format
187 (
188 _T("%s_%s_%lu.dmp"),
9cf3d218 189 wxTheApp ? (const wxChar*)wxTheApp->GetAppDisplayName().c_str()
8c125d13
VZ
190 : _T("wxwindows"),
191 wxDateTime::Now().Format(_T("%Y%m%dT%H%M%S")).c_str(),
192 ::GetCurrentProcessId()
193 );
194
195 wxStrncat(fullname, name, WXSIZEOF(fullname) - wxStrlen(fullname) - 1);
196
197 wxCrashReport::SetFileName(fullname);
198 }
199#endif // wxUSE_CRASHREPORT
200
201 return true;
202}
203
204int wxEntry(int& argc, wxChar **argv)
205{
226c11c0
VZ
206 DisableAutomaticSETranslator();
207
39ea2103 208 wxSEH_TRY
8c125d13 209 {
8c125d13
VZ
210 return wxEntryReal(argc, argv);
211 }
39ea2103 212 wxSEH_HANDLE(-1)
8c125d13
VZ
213}
214
226c11c0
VZ
215#else // !wxUSE_ON_FATAL_EXCEPTION
216
b734b2ca 217#if defined(__VISUALC__) && !defined(__WXWINCE__)
1ac4716d 218
226c11c0
VZ
219static void
220wxSETranslator(unsigned int WXUNUSED(code), EXCEPTION_POINTERS * WXUNUSED(ep))
221{
222 // see wxSETranslator() version for wxUSE_ON_FATAL_EXCEPTION above
223 throw;
224}
225
1ac4716d
VZ
226#endif // __VISUALC__
227
226c11c0
VZ
228int wxEntry(int& argc, wxChar **argv)
229{
230 DisableAutomaticSETranslator();
231
232 return wxEntryReal(argc, argv);
233}
234
235#endif // wxUSE_ON_FATAL_EXCEPTION/!wxUSE_ON_FATAL_EXCEPTION
236
237#endif // wxUSE_BASE
8c125d13 238
532d575b 239#if wxUSE_GUI && defined(__WXMSW__)
8c125d13 240
6f2df739
VZ
241#if wxUSE_UNICODE && !defined(__WXWINCE__)
242 #define NEED_UNICODE_CHECK
243#endif
94826170 244
6f2df739
VZ
245#ifdef NEED_UNICODE_CHECK
246
247// check whether Unicode is available
248static bool wxIsUnicodeAvailable()
94826170 249{
6f2df739
VZ
250 static const wchar_t *ERROR_STRING = L"wxWidgets Fatal Error";
251
406d283a 252 if ( wxGetOsVersion() != wxOS_WINDOWS_NT )
bd866271 253 {
69c54afe 254 // we need to be built with MSLU support
d5da0ce7 255#if !wxUSE_UNICODE_MSLU
bd866271
VZ
256 // note that we can use MessageBoxW() as it's implemented even under
257 // Win9x - OTOH, we can't use wxGetTranslation() because the file APIs
258 // used by wxLocale are not
259 ::MessageBox
260 (
261 NULL,
6f2df739
VZ
262 L"This program uses Unicode and requires Windows NT/2000/XP.\n"
263 L"\n"
264 L"Program aborted.",
265 ERROR_STRING,
bd866271
VZ
266 MB_ICONERROR | MB_OK
267 );
268
6f2df739 269 return false;
774960ce 270#else // wxUSE_UNICODE_MSLU
69c54afe
VZ
271 // and the MSLU DLL must also be available
272 HMODULE hmod = ::LoadLibraryA("unicows.dll");
273 if ( !hmod )
274 {
275 ::MessageBox
276 (
277 NULL,
6f2df739
VZ
278 L"This program uses Unicode and requires unicows.dll to work "
279 L"under current operating system.\n"
280 L"\n"
281 L"Please install unicows.dll and relaunch the program.",
282 ERROR_STRING,
69c54afe
VZ
283 MB_ICONERROR | MB_OK
284 );
6f2df739 285 return false;
69c54afe
VZ
286 }
287
288 // this is not really necessary but be tidy
289 ::FreeLibrary(hmod);
6f2df739
VZ
290
291 // finally do the last check: has unicows.lib initialized correctly?
292 hmod = ::LoadLibraryW(L"unicows.dll");
293 if ( !hmod )
294 {
295 ::MessageBox
296 (
297 NULL,
298 L"This program uses Unicode but is not using unicows.dll\n"
299 L"correctly and so cannot work under current operating system.\n"
300 L"Please contact the program author for an updated version.\n"
301 L"\n"
302 L"Program aborted.",
303 ERROR_STRING,
304 MB_ICONERROR | MB_OK
305 );
306
307 return false;
308 }
309
310 ::FreeLibrary(hmod);
774960ce 311#endif // !wxUSE_UNICODE_MSLU
bd866271 312 }
6f2df739
VZ
313
314 return true;
315}
316
317#endif // NEED_UNICODE_CHECK
318
319// ----------------------------------------------------------------------------
320// Windows-specific wxEntry
321// ----------------------------------------------------------------------------
322
d76a558d 323struct wxMSWCommandLineArguments
48733d47 324{
d76a558d
VZ
325 wxMSWCommandLineArguments() { argc = 0; argv = NULL; }
326
327 void Init(const wxArrayString& args)
48733d47 328 {
d76a558d
VZ
329 argc = args.size();
330
331 // +1 here for the terminating NULL
332 argv = new wxChar *[argc + 1];
333 for ( int i = 0; i < argc; i++ )
334 {
52de37c7 335 argv[i] = wxStrdup(args[i].wx_str());
d76a558d
VZ
336 }
337
338 // argv[] must be NULL-terminated
339 argv[argc] = NULL;
48733d47
VZ
340 }
341
d76a558d
VZ
342 void Free()
343 {
344 if ( !argc )
345 return;
48733d47 346
d76a558d
VZ
347 for ( int i = 0; i < argc; i++ )
348 {
349 free(argv[i]);
350 }
351
352 delete [] argv;
353 argv = NULL;
354 argc = 0;
355 }
356
357 int argc;
358 wxChar **argv;
359};
360
361static wxMSWCommandLineArguments wxArgs;
362
363// common part of wxMSW-specific wxEntryStart() and wxEntry() overloads
364static bool
365wxMSWEntryCommon(HINSTANCE hInstance, int nCmdShow)
6f2df739
VZ
366{
367 // the first thing to do is to check if we're trying to run an Unicode
368 // program under Win9x w/o MSLU emulation layer - if so, abort right now
369 // as it has no chance to work and has all chances to crash
370#ifdef NEED_UNICODE_CHECK
371 if ( !wxIsUnicodeAvailable() )
d76a558d 372 return false;
6f2df739 373#endif // NEED_UNICODE_CHECK
bd866271
VZ
374
375
94826170 376 // remember the parameters Windows gave us
13bdd545 377 wxSetInstance(hInstance);
94826170
VZ
378 wxApp::m_nCmdShow = nCmdShow;
379
b2b1371c
VZ
380 // parse the command line: we can't use pCmdLine in Unicode build so it is
381 // simpler to never use it at all (this also results in a more correct
382 // argv[0])
383
384 // break the command line in words
385 wxArrayString args;
13a5a49f 386
b2b1371c
VZ
387 const wxChar *cmdLine = ::GetCommandLine();
388 if ( cmdLine )
389 {
390 args = wxCmdLineParser::ConvertStringToArgs(cmdLine);
391 }
392
13a5a49f 393#ifdef __WXWINCE__
77d8d6cd
VZ
394 // WinCE doesn't insert the program itself, so do it ourselves.
395 args.Insert(wxGetFullModuleName(), 0);
13a5a49f
JS
396#endif
397
d76a558d 398 wxArgs.Init(args);
b2b1371c 399
d76a558d
VZ
400 return true;
401}
402
403WXDLLEXPORT bool wxEntryStart(HINSTANCE hInstance,
404 HINSTANCE WXUNUSED(hPrevInstance),
405 wxCmdLineArgType WXUNUSED(pCmdLine),
406 int nCmdShow)
407{
408 if ( !wxMSWEntryCommon(hInstance, nCmdShow) )
409 return false;
b2b1371c 410
d76a558d
VZ
411 return wxEntryStart(wxArgs.argc, wxArgs.argv);
412}
413
414WXDLLEXPORT int wxEntry(HINSTANCE hInstance,
415 HINSTANCE WXUNUSED(hPrevInstance),
416 wxCmdLineArgType WXUNUSED(pCmdLine),
417 int nCmdShow)
418{
419 if ( !wxMSWEntryCommon(hInstance, nCmdShow) )
420 return -1;
94826170 421
d76a558d 422 wxON_BLOCK_EXIT_OBJ0(wxArgs, wxMSWCommandLineArguments::Free);
48733d47 423
d76a558d 424 return wxEntry(wxArgs.argc, wxArgs.argv);
94826170
VZ
425}
426
532d575b 427#endif // wxUSE_GUI && __WXMSW__
94826170 428
b568d04f 429// ----------------------------------------------------------------------------
e2478fde 430// global HINSTANCE
b568d04f
VZ
431// ----------------------------------------------------------------------------
432
ec67cff1 433#if wxUSE_BASE
e2478fde
VZ
434
435HINSTANCE wxhInstance = 0;
436
028e7716 437extern "C" HINSTANCE wxGetInstance()
b568d04f
VZ
438{
439 return wxhInstance;
440}
441
442void wxSetInstance(HINSTANCE hInst)
443{
444 wxhInstance = hInst;
445}
2bda0e17 446
ec67cff1 447#endif // wxUSE_BASE