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