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