]> git.saurik.com Git - wxWidgets.git/blame - src/msw/main.cpp
Call SymCleanup() in wxStackWalker to fix problem with next call to it.
[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
b97d1013
VZ
72// ----------------------------------------------------------------------------
73// wrapper wxEntry catching all Win32 exceptions occurring in a wx program
74// ----------------------------------------------------------------------------
75
76// wrap real wxEntry in a try-except block to be able to call
77// OnFatalException() if necessary
78#if wxUSE_ON_FATAL_EXCEPTION
79
8c125d13
VZ
80// global pointer to exception information, only valid inside OnFatalException,
81// used by wxStackWalker and wxCrashReport
82extern EXCEPTION_POINTERS *wxGlobalSEInformation = NULL;
83
84// flag telling us whether the application wants to handle exceptions at all
85static bool gs_handleExceptions = false;
86
226c11c0
VZ
87static void wxFatalExit()
88{
89 // use the same exit code as abort()
90 ::ExitProcess(3);
91}
92
8c125d13
VZ
93unsigned long wxGlobalSEHandler(EXCEPTION_POINTERS *pExcPtrs)
94{
95 if ( gs_handleExceptions && wxTheApp )
96 {
97 // store the pointer to exception info
98 wxGlobalSEInformation = pExcPtrs;
99
100 // give the user a chance to do something special about this
39ea2103 101 wxSEH_TRY
8c125d13
VZ
102 {
103 wxTheApp->OnFatalException();
104 }
39ea2103 105 wxSEH_IGNORE // ignore any exceptions inside the exception handler
8c125d13
VZ
106
107 wxGlobalSEInformation = NULL;
108
109 // this will execute our handler and terminate the process
110 return EXCEPTION_EXECUTE_HANDLER;
111 }
112
113 return EXCEPTION_CONTINUE_SEARCH;
114}
115
116#ifdef __VISUALC__
117
39ea2103 118void wxSETranslator(unsigned int WXUNUSED(code), EXCEPTION_POINTERS *ep)
8c125d13 119{
226c11c0
VZ
120 switch ( wxGlobalSEHandler(ep) )
121 {
122 default:
9a83f860 123 wxFAIL_MSG( wxT("unexpected wxGlobalSEHandler() return value") );
226c11c0
VZ
124 // fall through
125
126 case EXCEPTION_EXECUTE_HANDLER:
127 // if wxApp::OnFatalException() had been called we should exit the
128 // application -- but we shouldn't kill our host when we're a DLL
129#ifndef WXMAKINGDLL
130 wxFatalExit();
131#endif // not a DLL
132 break;
133
134 case EXCEPTION_CONTINUE_SEARCH:
135 // we're called for each "catch ( ... )" and if we (re)throw from
136 // here, the catch handler body is not executed, so the effect is
137 // as if had inhibited translation of SE to C++ ones because the
138 // handler will never see any structured exceptions
139 throw;
140 }
8c125d13
VZ
141}
142
143#endif // __VISUALC__
144
145bool wxHandleFatalExceptions(bool doit)
146{
147 // assume this can only be called from the main thread
148 gs_handleExceptions = doit;
149
8c125d13
VZ
150#if wxUSE_CRASHREPORT
151 if ( doit )
152 {
153 // try to find a place where we can put out report file later
154 wxChar fullname[MAX_PATH];
155 if ( !::GetTempPath(WXSIZEOF(fullname), fullname) )
156 {
9a83f860 157 wxLogLastError(wxT("GetTempPath"));
8c125d13
VZ
158
159 // when all else fails...
9a83f860 160 wxStrcpy(fullname, wxT("c:\\"));
8c125d13
VZ
161 }
162
163 // use PID and date to make the report file name more unique
164 wxString name = wxString::Format
165 (
9a83f860 166 wxT("%s_%s_%lu.dmp"),
9cf3d218 167 wxTheApp ? (const wxChar*)wxTheApp->GetAppDisplayName().c_str()
9a83f860
VZ
168 : wxT("wxwindows"),
169 wxDateTime::Now().Format(wxT("%Y%m%dT%H%M%S")).c_str(),
8c125d13
VZ
170 ::GetCurrentProcessId()
171 );
172
173 wxStrncat(fullname, name, WXSIZEOF(fullname) - wxStrlen(fullname) - 1);
174
175 wxCrashReport::SetFileName(fullname);
176 }
177#endif // wxUSE_CRASHREPORT
178
179 return true;
180}
181
182int wxEntry(int& argc, wxChar **argv)
183{
226c11c0
VZ
184 DisableAutomaticSETranslator();
185
39ea2103 186 wxSEH_TRY
8c125d13 187 {
8c125d13
VZ
188 return wxEntryReal(argc, argv);
189 }
39ea2103 190 wxSEH_HANDLE(-1)
8c125d13
VZ
191}
192
226c11c0
VZ
193#else // !wxUSE_ON_FATAL_EXCEPTION
194
226c11c0
VZ
195int wxEntry(int& argc, wxChar **argv)
196{
226c11c0
VZ
197 return wxEntryReal(argc, argv);
198}
199
200#endif // wxUSE_ON_FATAL_EXCEPTION/!wxUSE_ON_FATAL_EXCEPTION
201
202#endif // wxUSE_BASE
8c125d13 203
532d575b 204#if wxUSE_GUI && defined(__WXMSW__)
8c125d13 205
6f2df739
VZ
206#if wxUSE_UNICODE && !defined(__WXWINCE__)
207 #define NEED_UNICODE_CHECK
208#endif
94826170 209
6f2df739
VZ
210#ifdef NEED_UNICODE_CHECK
211
212// check whether Unicode is available
213static bool wxIsUnicodeAvailable()
94826170 214{
6f2df739
VZ
215 static const wchar_t *ERROR_STRING = L"wxWidgets Fatal Error";
216
406d283a 217 if ( wxGetOsVersion() != wxOS_WINDOWS_NT )
bd866271 218 {
69c54afe 219 // we need to be built with MSLU support
d5da0ce7 220#if !wxUSE_UNICODE_MSLU
bd866271
VZ
221 // note that we can use MessageBoxW() as it's implemented even under
222 // Win9x - OTOH, we can't use wxGetTranslation() because the file APIs
223 // used by wxLocale are not
224 ::MessageBox
225 (
226 NULL,
6f2df739
VZ
227 L"This program uses Unicode and requires Windows NT/2000/XP.\n"
228 L"\n"
229 L"Program aborted.",
230 ERROR_STRING,
bd866271
VZ
231 MB_ICONERROR | MB_OK
232 );
233
6f2df739 234 return false;
774960ce 235#else // wxUSE_UNICODE_MSLU
69c54afe
VZ
236 // and the MSLU DLL must also be available
237 HMODULE hmod = ::LoadLibraryA("unicows.dll");
238 if ( !hmod )
239 {
240 ::MessageBox
241 (
242 NULL,
6f2df739
VZ
243 L"This program uses Unicode and requires unicows.dll to work "
244 L"under current operating system.\n"
245 L"\n"
246 L"Please install unicows.dll and relaunch the program.",
247 ERROR_STRING,
69c54afe
VZ
248 MB_ICONERROR | MB_OK
249 );
6f2df739 250 return false;
69c54afe
VZ
251 }
252
253 // this is not really necessary but be tidy
254 ::FreeLibrary(hmod);
6f2df739
VZ
255
256 // finally do the last check: has unicows.lib initialized correctly?
257 hmod = ::LoadLibraryW(L"unicows.dll");
258 if ( !hmod )
259 {
260 ::MessageBox
261 (
262 NULL,
263 L"This program uses Unicode but is not using unicows.dll\n"
264 L"correctly and so cannot work under current operating system.\n"
265 L"Please contact the program author for an updated version.\n"
266 L"\n"
267 L"Program aborted.",
268 ERROR_STRING,
269 MB_ICONERROR | MB_OK
270 );
271
272 return false;
273 }
274
275 ::FreeLibrary(hmod);
774960ce 276#endif // !wxUSE_UNICODE_MSLU
bd866271 277 }
6f2df739
VZ
278
279 return true;
280}
281
282#endif // NEED_UNICODE_CHECK
283
284// ----------------------------------------------------------------------------
285// Windows-specific wxEntry
286// ----------------------------------------------------------------------------
287
d76a558d 288struct wxMSWCommandLineArguments
48733d47 289{
d76a558d
VZ
290 wxMSWCommandLineArguments() { argc = 0; argv = NULL; }
291
292 void Init(const wxArrayString& args)
48733d47 293 {
d76a558d
VZ
294 argc = args.size();
295
296 // +1 here for the terminating NULL
297 argv = new wxChar *[argc + 1];
298 for ( int i = 0; i < argc; i++ )
299 {
52de37c7 300 argv[i] = wxStrdup(args[i].wx_str());
d76a558d
VZ
301 }
302
303 // argv[] must be NULL-terminated
304 argv[argc] = NULL;
48733d47
VZ
305 }
306
d76a558d
VZ
307 void Free()
308 {
309 if ( !argc )
310 return;
48733d47 311
d76a558d
VZ
312 for ( int i = 0; i < argc; i++ )
313 {
314 free(argv[i]);
315 }
316
317 delete [] argv;
318 argv = NULL;
319 argc = 0;
320 }
321
322 int argc;
323 wxChar **argv;
324};
325
326static wxMSWCommandLineArguments wxArgs;
327
328// common part of wxMSW-specific wxEntryStart() and wxEntry() overloads
329static bool
330wxMSWEntryCommon(HINSTANCE hInstance, int nCmdShow)
6f2df739
VZ
331{
332 // the first thing to do is to check if we're trying to run an Unicode
333 // program under Win9x w/o MSLU emulation layer - if so, abort right now
334 // as it has no chance to work and has all chances to crash
335#ifdef NEED_UNICODE_CHECK
336 if ( !wxIsUnicodeAvailable() )
d76a558d 337 return false;
6f2df739 338#endif // NEED_UNICODE_CHECK
bd866271
VZ
339
340
94826170 341 // remember the parameters Windows gave us
13bdd545 342 wxSetInstance(hInstance);
94826170
VZ
343 wxApp::m_nCmdShow = nCmdShow;
344
b2b1371c
VZ
345 // parse the command line: we can't use pCmdLine in Unicode build so it is
346 // simpler to never use it at all (this also results in a more correct
347 // argv[0])
348
349 // break the command line in words
350 wxArrayString args;
13a5a49f 351
b2b1371c
VZ
352 const wxChar *cmdLine = ::GetCommandLine();
353 if ( cmdLine )
354 {
355 args = wxCmdLineParser::ConvertStringToArgs(cmdLine);
356 }
357
13a5a49f 358#ifdef __WXWINCE__
77d8d6cd
VZ
359 // WinCE doesn't insert the program itself, so do it ourselves.
360 args.Insert(wxGetFullModuleName(), 0);
13a5a49f
JS
361#endif
362
d76a558d 363 wxArgs.Init(args);
b2b1371c 364
d76a558d
VZ
365 return true;
366}
367
368WXDLLEXPORT bool wxEntryStart(HINSTANCE hInstance,
369 HINSTANCE WXUNUSED(hPrevInstance),
370 wxCmdLineArgType WXUNUSED(pCmdLine),
371 int nCmdShow)
372{
373 if ( !wxMSWEntryCommon(hInstance, nCmdShow) )
374 return false;
b2b1371c 375
d76a558d
VZ
376 return wxEntryStart(wxArgs.argc, wxArgs.argv);
377}
378
379WXDLLEXPORT int wxEntry(HINSTANCE hInstance,
380 HINSTANCE WXUNUSED(hPrevInstance),
381 wxCmdLineArgType WXUNUSED(pCmdLine),
382 int nCmdShow)
383{
384 if ( !wxMSWEntryCommon(hInstance, nCmdShow) )
385 return -1;
94826170 386
d76a558d 387 wxON_BLOCK_EXIT_OBJ0(wxArgs, wxMSWCommandLineArguments::Free);
48733d47 388
d76a558d 389 return wxEntry(wxArgs.argc, wxArgs.argv);
94826170
VZ
390}
391
532d575b 392#endif // wxUSE_GUI && __WXMSW__
94826170 393
b568d04f 394// ----------------------------------------------------------------------------
e2478fde 395// global HINSTANCE
b568d04f
VZ
396// ----------------------------------------------------------------------------
397
ec67cff1 398#if wxUSE_BASE
e2478fde
VZ
399
400HINSTANCE wxhInstance = 0;
401
028e7716 402extern "C" HINSTANCE wxGetInstance()
b568d04f
VZ
403{
404 return wxhInstance;
405}
406
407void wxSetInstance(HINSTANCE hInst)
408{
409 wxhInstance = hInst;
410}
2bda0e17 411
ec67cff1 412#endif // wxUSE_BASE