]> git.saurik.com Git - wxWidgets.git/blame - src/msw/main.cpp
added test for wxScopeGuard
[wxWidgets.git] / src / msw / main.cpp
CommitLineData
2bda0e17 1/////////////////////////////////////////////////////////////////////////////
b568d04f 2// Name: 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
14f355c2 20#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
b568d04f 21 #pragma implementation
a3b46648
UU
22#endif
23
2bda0e17
KB
24// For compilers that support precompilation, includes "wx.h".
25#include "wx/wxprec.h"
26
27#ifdef __BORLANDC__
b568d04f 28 #pragma hdrstop
2bda0e17
KB
29#endif
30
2432b92d 31#include "wx/event.h"
2bda0e17 32#include "wx/app.h"
94826170 33#include "wx/cmdline.h"
b568d04f
VZ
34
35#include "wx/msw/private.h"
36
8c125d13
VZ
37#if wxUSE_ON_FATAL_EXCEPTION
38 #include "wx/datetime.h"
39 #include "wx/msw/crashrpt.h"
40
41 #ifdef __VISUALC__
42 #include <eh.h>
43 #endif // __VISUALC__
44#endif // wxUSE_ON_FATAL_EXCEPTION
45
46#ifdef __WXWINCE__
47 // there is no ExitProcess() under CE but exiting the main thread has the
48 // same effect
226c11c0
VZ
49 #ifndef ExitProcess
50 #define ExitProcess ExitThread
51 #endif
52#endif // __WXWINCE__
8c125d13 53
e2478fde
VZ
54#ifdef __BORLANDC__
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
226c11c0 58#endif // __BORLANDC__
e2478fde
VZ
59
60#if defined(__WXMICROWIN__)
61 #define HINSTANCE HANDLE
62#endif
beed393c 63
1ac4716d
VZ
64// defined in common/init.cpp
65extern int wxEntryReal(int& argc, wxChar **argv);
66
b568d04f 67// ============================================================================
e2478fde 68// implementation: various entry points
b568d04f
VZ
69// ============================================================================
70
226c11c0
VZ
71#if wxUSE_BASE
72
84bdb0d8 73#if wxUSE_ON_FATAL_EXCEPTION && defined(__VISUALC__) && !defined(__WXWINCE__)
226c11c0
VZ
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
80 // exception occurs
81
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
85 #if _MSC_VER <= 1310
86 #pragma warning(disable:4535)
87 #endif
88
89 // note that the SE translator must be called wxSETranslator!
90 #define DisableAutomaticSETranslator() _set_se_translator(wxSETranslator)
91#else // !__VISUALC__
92 #define DisableAutomaticSETranslator()
93#endif // __VISUALC__/!__VISUALC__
94
8c125d13 95// ----------------------------------------------------------------------------
3103e8a9 96// wrapper wxEntry catching all Win32 exceptions occurring in a wx program
8c125d13
VZ
97// ----------------------------------------------------------------------------
98
99// wrap real wxEntry in a try-except block to be able to call
100// OnFatalException() if necessary
226c11c0
VZ
101#if wxUSE_ON_FATAL_EXCEPTION
102
8c125d13
VZ
103// global pointer to exception information, only valid inside OnFatalException,
104// used by wxStackWalker and wxCrashReport
105extern EXCEPTION_POINTERS *wxGlobalSEInformation = NULL;
106
107// flag telling us whether the application wants to handle exceptions at all
108static bool gs_handleExceptions = false;
109
226c11c0
VZ
110static void wxFatalExit()
111{
112 // use the same exit code as abort()
113 ::ExitProcess(3);
114}
115
8c125d13
VZ
116unsigned long wxGlobalSEHandler(EXCEPTION_POINTERS *pExcPtrs)
117{
118 if ( gs_handleExceptions && wxTheApp )
119 {
120 // store the pointer to exception info
121 wxGlobalSEInformation = pExcPtrs;
122
123 // give the user a chance to do something special about this
124 __try
125 {
126 wxTheApp->OnFatalException();
127 }
128 __except ( EXCEPTION_EXECUTE_HANDLER )
129 {
130 // nothing to do here, just ignore the exception inside the
131 // exception handler
132 ;
133 }
134
135 wxGlobalSEInformation = NULL;
136
137 // this will execute our handler and terminate the process
138 return EXCEPTION_EXECUTE_HANDLER;
139 }
140
141 return EXCEPTION_CONTINUE_SEARCH;
142}
143
144#ifdef __VISUALC__
145
146static void wxSETranslator(unsigned int WXUNUSED(code), EXCEPTION_POINTERS *ep)
147{
226c11c0
VZ
148 switch ( wxGlobalSEHandler(ep) )
149 {
150 default:
151 wxFAIL_MSG( _T("unexpected wxGlobalSEHandler() return value") );
152 // fall through
153
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
157#ifndef WXMAKINGDLL
158 wxFatalExit();
159#endif // not a DLL
160 break;
161
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
167 throw;
168 }
8c125d13
VZ
169}
170
171#endif // __VISUALC__
172
173bool wxHandleFatalExceptions(bool doit)
174{
175 // assume this can only be called from the main thread
176 gs_handleExceptions = doit;
177
8c125d13
VZ
178#if wxUSE_CRASHREPORT
179 if ( doit )
180 {
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) )
184 {
185 wxLogLastError(_T("GetTempPath"));
186
187 // when all else fails...
188 wxStrcpy(fullname, _T("c:\\"));
189 }
190
191 // use PID and date to make the report file name more unique
192 wxString name = wxString::Format
193 (
194 _T("%s_%s_%lu.dmp"),
195 wxTheApp ? wxTheApp->GetAppName().c_str()
196 : _T("wxwindows"),
197 wxDateTime::Now().Format(_T("%Y%m%dT%H%M%S")).c_str(),
198 ::GetCurrentProcessId()
199 );
200
201 wxStrncat(fullname, name, WXSIZEOF(fullname) - wxStrlen(fullname) - 1);
202
203 wxCrashReport::SetFileName(fullname);
204 }
205#endif // wxUSE_CRASHREPORT
206
207 return true;
208}
209
210int wxEntry(int& argc, wxChar **argv)
211{
226c11c0
VZ
212 DisableAutomaticSETranslator();
213
8c125d13
VZ
214 __try
215 {
8c125d13
VZ
216 return wxEntryReal(argc, argv);
217 }
218 __except ( wxGlobalSEHandler(GetExceptionInformation()) )
219 {
226c11c0 220 wxFatalExit();
8c125d13 221
e5f67955 222#if !defined(_MSC_VER) || defined(__WXDEBUG__) || (defined(_MSC_VER) && _MSC_VER <= 1200)
3d104ec3
WS
223 // this code is unreachable but put it here to suppress warnings in some compilers
224 // and disable for others to supress warnings too
8c125d13 225 return -1;
ad44b2c7 226#endif // !__VISUALC__ in release build
8c125d13
VZ
227 }
228}
229
226c11c0
VZ
230#else // !wxUSE_ON_FATAL_EXCEPTION
231
b734b2ca 232#if defined(__VISUALC__) && !defined(__WXWINCE__)
1ac4716d 233
226c11c0
VZ
234static void
235wxSETranslator(unsigned int WXUNUSED(code), EXCEPTION_POINTERS * WXUNUSED(ep))
236{
237 // see wxSETranslator() version for wxUSE_ON_FATAL_EXCEPTION above
238 throw;
239}
240
1ac4716d
VZ
241#endif // __VISUALC__
242
226c11c0
VZ
243int wxEntry(int& argc, wxChar **argv)
244{
245 DisableAutomaticSETranslator();
246
247 return wxEntryReal(argc, argv);
248}
249
250#endif // wxUSE_ON_FATAL_EXCEPTION/!wxUSE_ON_FATAL_EXCEPTION
251
252#endif // wxUSE_BASE
8c125d13 253
532d575b 254#if wxUSE_GUI && defined(__WXMSW__)
8c125d13 255
94826170
VZ
256// ----------------------------------------------------------------------------
257// Windows-specific wxEntry
258// ----------------------------------------------------------------------------
259
b5fe6924
VS
260WXDLLEXPORT int wxEntry(HINSTANCE hInstance,
261 HINSTANCE WXUNUSED(hPrevInstance),
7c8c7cc2 262 wxCmdLineArgType WXUNUSED(pCmdLine),
b5fe6924 263 int nCmdShow)
94826170 264{
bd866271
VZ
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 && !wxUSE_UNICODE_MSLU && !defined(__WXWINCE__)
269 if ( wxGetOsVersion() != wxWINDOWS_NT )
270 {
271 // note that we can use MessageBoxW() as it's implemented even under
272 // Win9x - OTOH, we can't use wxGetTranslation() because the file APIs
273 // used by wxLocale are not
274 ::MessageBox
275 (
276 NULL,
277 _T("This program uses Unicode and requires Windows NT/2000/XP.\nProgram aborted."),
278 _T("wxWidgets Fatal Error"),
279 MB_ICONERROR | MB_OK
280 );
281
282 return -1;
283 }
284#endif // wxUSE_UNICODE && !wxUSE_UNICODE_MSLU
285
286
94826170 287 // remember the parameters Windows gave us
13bdd545 288 wxSetInstance(hInstance);
94826170
VZ
289 wxApp::m_nCmdShow = nCmdShow;
290
b2b1371c
VZ
291 // parse the command line: we can't use pCmdLine in Unicode build so it is
292 // simpler to never use it at all (this also results in a more correct
293 // argv[0])
294
295 // break the command line in words
296 wxArrayString args;
13a5a49f 297
b2b1371c
VZ
298 const wxChar *cmdLine = ::GetCommandLine();
299 if ( cmdLine )
300 {
301 args = wxCmdLineParser::ConvertStringToArgs(cmdLine);
302 }
303
13a5a49f 304#ifdef __WXWINCE__
77d8d6cd
VZ
305 // WinCE doesn't insert the program itself, so do it ourselves.
306 args.Insert(wxGetFullModuleName(), 0);
13a5a49f
JS
307#endif
308
b2b1371c
VZ
309 int argc = args.GetCount();
310
311 // +1 here for the terminating NULL
312 wxChar **argv = new wxChar *[argc + 1];
313 for ( int i = 0; i < argc; i++ )
314 {
315 argv[i] = wxStrdup(args[i]);
316 }
317
318 // argv[] must be NULL-terminated
319 argv[argc] = NULL;
94826170
VZ
320
321 return wxEntry(argc, argv);
322}
323
2bda0e17 324// May wish not to have a DllMain or WinMain, e.g. if we're programming
b568d04f 325// a Netscape plugin or if we're writing a console application
94826170 326#if !defined(NOMAIN)
2bda0e17 327
e2478fde
VZ
328extern "C"
329{
2bda0e17 330
e2478fde 331// ----------------------------------------------------------------------------
2bda0e17 332// WinMain
e2478fde
VZ
333// ----------------------------------------------------------------------------
334
2bda0e17 335// Note that WinMain is also defined in dummy.obj, which is linked to
77ffb593 336// an application that is using the DLL version of wxWidgets.
2bda0e17 337
ac9a3c61 338#if defined(_WINDLL)
2bda0e17
KB
339
340// DLL entry point
341
e2478fde 342BOOL WINAPI
7adf0b4d 343DllMain(HINSTANCE hModule, DWORD fdwReason, LPVOID WXUNUSED(lpReserved))
2bda0e17 344{
e2478fde 345 // Only call wxEntry if the application itself is part of the DLL.
77ffb593 346 // If only the wxWidgets library is in the DLL, then the
e2478fde
VZ
347 // initialisation will be called when the application implicitly
348 // calls WinMain.
beed393c 349#ifndef WXMAKINGDLL
2bda0e17 350 switch (fdwReason)
b568d04f
VZ
351 {
352 case DLL_PROCESS_ATTACH:
13bdd545 353 return wxEntry(hModule);
2bda0e17 354
b568d04f 355 case DLL_PROCESS_DETACH:
94826170
VZ
356 wxEntryCleanup();
357 break;
b568d04f 358 }
33ac7e6f 359#else
598ddd96
WS
360 (void)hModule;
361 (void)fdwReason;
beed393c 362#endif // !WXMAKINGDLL
e2478fde 363
b568d04f 364 return TRUE;
2bda0e17
KB
365}
366
ac9a3c61 367#endif // _WINDLL
e2478fde
VZ
368
369} // extern "C"
2bda0e17 370
b568d04f
VZ
371#endif // !NOMAIN
372
532d575b 373#endif // wxUSE_GUI && __WXMSW__
94826170 374
b568d04f 375// ----------------------------------------------------------------------------
e2478fde 376// global HINSTANCE
b568d04f
VZ
377// ----------------------------------------------------------------------------
378
ec67cff1 379#if wxUSE_BASE
e2478fde
VZ
380
381HINSTANCE wxhInstance = 0;
382
028e7716 383extern "C" HINSTANCE wxGetInstance()
b568d04f
VZ
384{
385 return wxhInstance;
386}
387
388void wxSetInstance(HINSTANCE hInst)
389{
390 wxhInstance = hInst;
391}
2bda0e17 392
ec67cff1 393#endif // wxUSE_BASE
e2478fde 394