]> git.saurik.com Git - wxWidgets.git/blame - src/msw/main.cpp
Make public headers compatible with Objective-C++ with ARC.
[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
6c9a19aa 7// Copyright: (c) Julian Smart
65571936 8// Licence: wxWindows licence
2bda0e17
KB
9/////////////////////////////////////////////////////////////////////////////
10
b568d04f
VZ
11// ============================================================================
12// declarations
13// ============================================================================
14
15// ----------------------------------------------------------------------------
16// headers
17// ----------------------------------------------------------------------------
18
2bda0e17
KB
19// For compilers that support precompilation, includes "wx.h".
20#include "wx/wxprec.h"
21
22#ifdef __BORLANDC__
b568d04f 23 #pragma hdrstop
2bda0e17
KB
24#endif
25
d5da0ce7
WS
26#ifndef WX_PRECOMP
27 #include "wx/event.h"
670f9935 28 #include "wx/app.h"
c43507b0 29 #include "wx/utils.h"
d5da0ce7
WS
30#endif //WX_PRECOMP
31
94826170 32#include "wx/cmdline.h"
605ff820 33#include "wx/dynlib.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
26cdd42d 204#if wxUSE_GUI
8c125d13 205
605ff820
VS
206namespace
207{
208
6f2df739
VZ
209#if wxUSE_UNICODE && !defined(__WXWINCE__)
210 #define NEED_UNICODE_CHECK
211#endif
94826170 212
6f2df739
VZ
213#ifdef NEED_UNICODE_CHECK
214
215// check whether Unicode is available
605ff820 216bool wxIsUnicodeAvailable()
94826170 217{
6f2df739
VZ
218 static const wchar_t *ERROR_STRING = L"wxWidgets Fatal Error";
219
406d283a 220 if ( wxGetOsVersion() != wxOS_WINDOWS_NT )
bd866271 221 {
69c54afe 222 // we need to be built with MSLU support
d5da0ce7 223#if !wxUSE_UNICODE_MSLU
bd866271
VZ
224 // note that we can use MessageBoxW() as it's implemented even under
225 // Win9x - OTOH, we can't use wxGetTranslation() because the file APIs
226 // used by wxLocale are not
227 ::MessageBox
228 (
229 NULL,
6f2df739
VZ
230 L"This program uses Unicode and requires Windows NT/2000/XP.\n"
231 L"\n"
232 L"Program aborted.",
233 ERROR_STRING,
bd866271
VZ
234 MB_ICONERROR | MB_OK
235 );
236
6f2df739 237 return false;
774960ce 238#else // wxUSE_UNICODE_MSLU
69c54afe
VZ
239 // and the MSLU DLL must also be available
240 HMODULE hmod = ::LoadLibraryA("unicows.dll");
241 if ( !hmod )
242 {
243 ::MessageBox
244 (
245 NULL,
6f2df739
VZ
246 L"This program uses Unicode and requires unicows.dll to work "
247 L"under current operating system.\n"
248 L"\n"
249 L"Please install unicows.dll and relaunch the program.",
250 ERROR_STRING,
69c54afe
VZ
251 MB_ICONERROR | MB_OK
252 );
6f2df739 253 return false;
69c54afe
VZ
254 }
255
256 // this is not really necessary but be tidy
257 ::FreeLibrary(hmod);
6f2df739
VZ
258
259 // finally do the last check: has unicows.lib initialized correctly?
260 hmod = ::LoadLibraryW(L"unicows.dll");
261 if ( !hmod )
262 {
263 ::MessageBox
264 (
265 NULL,
266 L"This program uses Unicode but is not using unicows.dll\n"
267 L"correctly and so cannot work under current operating system.\n"
268 L"Please contact the program author for an updated version.\n"
269 L"\n"
270 L"Program aborted.",
271 ERROR_STRING,
272 MB_ICONERROR | MB_OK
273 );
274
275 return false;
276 }
277
278 ::FreeLibrary(hmod);
774960ce 279#endif // !wxUSE_UNICODE_MSLU
bd866271 280 }
6f2df739
VZ
281
282 return true;
283}
284
285#endif // NEED_UNICODE_CHECK
286
605ff820
VS
287void wxSetProcessDPIAware()
288{
289#if wxUSE_DYNLIB_CLASS
290 typedef BOOL (WINAPI *SetProcessDPIAware_t)(void);
291 wxDynamicLibrary dllUser32(wxT("user32.dll"));
292 SetProcessDPIAware_t pfnSetProcessDPIAware =
293 (SetProcessDPIAware_t)dllUser32.RawGetSymbol(wxT("SetProcessDPIAware"));
294
295 if ( pfnSetProcessDPIAware )
296 pfnSetProcessDPIAware();
297#endif // wxUSE_DYNLIB_CLASS
298}
299
300} //anonymous namespace
301
6f2df739
VZ
302// ----------------------------------------------------------------------------
303// Windows-specific wxEntry
304// ----------------------------------------------------------------------------
305
d76a558d 306struct wxMSWCommandLineArguments
48733d47 307{
d76a558d
VZ
308 wxMSWCommandLineArguments() { argc = 0; argv = NULL; }
309
310 void Init(const wxArrayString& args)
48733d47 311 {
d76a558d
VZ
312 argc = args.size();
313
314 // +1 here for the terminating NULL
315 argv = new wxChar *[argc + 1];
316 for ( int i = 0; i < argc; i++ )
317 {
017dc06b 318 argv[i] = wxStrdup(args[i].t_str());
d76a558d
VZ
319 }
320
321 // argv[] must be NULL-terminated
322 argv[argc] = NULL;
48733d47
VZ
323 }
324
d76a558d
VZ
325 void Free()
326 {
327 if ( !argc )
328 return;
48733d47 329
d76a558d
VZ
330 for ( int i = 0; i < argc; i++ )
331 {
332 free(argv[i]);
333 }
334
5276b0a5 335 wxDELETEA(argv);
d76a558d
VZ
336 argc = 0;
337 }
338
339 int argc;
340 wxChar **argv;
341};
342
343static wxMSWCommandLineArguments wxArgs;
344
345// common part of wxMSW-specific wxEntryStart() and wxEntry() overloads
346static bool
347wxMSWEntryCommon(HINSTANCE hInstance, int nCmdShow)
6f2df739
VZ
348{
349 // the first thing to do is to check if we're trying to run an Unicode
350 // program under Win9x w/o MSLU emulation layer - if so, abort right now
351 // as it has no chance to work and has all chances to crash
352#ifdef NEED_UNICODE_CHECK
353 if ( !wxIsUnicodeAvailable() )
d76a558d 354 return false;
6f2df739 355#endif // NEED_UNICODE_CHECK
bd866271
VZ
356
357
94826170 358 // remember the parameters Windows gave us
13bdd545 359 wxSetInstance(hInstance);
26cdd42d 360#ifdef __WXMSW__
94826170 361 wxApp::m_nCmdShow = nCmdShow;
26cdd42d 362#endif
94826170 363
b2b1371c
VZ
364 // parse the command line: we can't use pCmdLine in Unicode build so it is
365 // simpler to never use it at all (this also results in a more correct
366 // argv[0])
367
368 // break the command line in words
369 wxArrayString args;
13a5a49f 370
b2b1371c
VZ
371 const wxChar *cmdLine = ::GetCommandLine();
372 if ( cmdLine )
373 {
374 args = wxCmdLineParser::ConvertStringToArgs(cmdLine);
375 }
376
13a5a49f 377#ifdef __WXWINCE__
77d8d6cd
VZ
378 // WinCE doesn't insert the program itself, so do it ourselves.
379 args.Insert(wxGetFullModuleName(), 0);
13a5a49f
JS
380#endif
381
d76a558d 382 wxArgs.Init(args);
b2b1371c 383
d76a558d
VZ
384 return true;
385}
386
387WXDLLEXPORT bool wxEntryStart(HINSTANCE hInstance,
388 HINSTANCE WXUNUSED(hPrevInstance),
389 wxCmdLineArgType WXUNUSED(pCmdLine),
390 int nCmdShow)
391{
392 if ( !wxMSWEntryCommon(hInstance, nCmdShow) )
393 return false;
b2b1371c 394
d76a558d
VZ
395 return wxEntryStart(wxArgs.argc, wxArgs.argv);
396}
397
398WXDLLEXPORT int wxEntry(HINSTANCE hInstance,
399 HINSTANCE WXUNUSED(hPrevInstance),
400 wxCmdLineArgType WXUNUSED(pCmdLine),
401 int nCmdShow)
402{
605ff820
VS
403 // wxWidgets library doesn't have problems with non-default DPI settings,
404 // so we can mark the app as "DPI aware" for Vista/Win7 (see
405 // http://msdn.microsoft.com/en-us/library/dd464659%28VS.85%29.aspx).
406 // Note that we intentionally do it here and not in wxApp, so that it
407 // doesn't happen if wx code is hosted in another app (e.g. a plugin).
408 wxSetProcessDPIAware();
409
d76a558d
VZ
410 if ( !wxMSWEntryCommon(hInstance, nCmdShow) )
411 return -1;
94826170 412
d76a558d 413 wxON_BLOCK_EXIT_OBJ0(wxArgs, wxMSWCommandLineArguments::Free);
48733d47 414
d76a558d 415 return wxEntry(wxArgs.argc, wxArgs.argv);
94826170
VZ
416}
417
26cdd42d 418#endif // wxUSE_GUI
94826170 419
b568d04f 420// ----------------------------------------------------------------------------
e2478fde 421// global HINSTANCE
b568d04f
VZ
422// ----------------------------------------------------------------------------
423
ec67cff1 424#if wxUSE_BASE
e2478fde
VZ
425
426HINSTANCE wxhInstance = 0;
427
028e7716 428extern "C" HINSTANCE wxGetInstance()
b568d04f
VZ
429{
430 return wxhInstance;
431}
432
433void wxSetInstance(HINSTANCE hInst)
434{
435 wxhInstance = hInst;
436}
2bda0e17 437
ec67cff1 438#endif // wxUSE_BASE