]> git.saurik.com Git - wxWidgets.git/blame - src/msw/main.cpp
Unicode build fix
[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
6f2df739
VZ
256#if wxUSE_UNICODE && !defined(__WXWINCE__)
257 #define NEED_UNICODE_CHECK
258#endif
94826170 259
6f2df739
VZ
260#ifdef NEED_UNICODE_CHECK
261
262// check whether Unicode is available
263static bool wxIsUnicodeAvailable()
94826170 264{
6f2df739
VZ
265 static const wchar_t *ERROR_STRING = L"wxWidgets Fatal Error";
266
bd866271
VZ
267 if ( wxGetOsVersion() != wxWINDOWS_NT )
268 {
69c54afe
VZ
269 // we need to be built with MSLU support
270#if !wxUSE_UNICODE_MSLU
bd866271
VZ
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,
6f2df739
VZ
277 L"This program uses Unicode and requires Windows NT/2000/XP.\n"
278 L"\n"
279 L"Program aborted.",
280 ERROR_STRING,
bd866271
VZ
281 MB_ICONERROR | MB_OK
282 );
283
6f2df739 284 return false;
774960ce 285#else // wxUSE_UNICODE_MSLU
69c54afe
VZ
286 // and the MSLU DLL must also be available
287 HMODULE hmod = ::LoadLibraryA("unicows.dll");
288 if ( !hmod )
289 {
290 ::MessageBox
291 (
292 NULL,
6f2df739
VZ
293 L"This program uses Unicode and requires unicows.dll to work "
294 L"under current operating system.\n"
295 L"\n"
296 L"Please install unicows.dll and relaunch the program.",
297 ERROR_STRING,
69c54afe
VZ
298 MB_ICONERROR | MB_OK
299 );
6f2df739 300 return false;
69c54afe
VZ
301 }
302
303 // this is not really necessary but be tidy
304 ::FreeLibrary(hmod);
6f2df739
VZ
305
306 // finally do the last check: has unicows.lib initialized correctly?
307 hmod = ::LoadLibraryW(L"unicows.dll");
308 if ( !hmod )
309 {
310 ::MessageBox
311 (
312 NULL,
313 L"This program uses Unicode but is not using unicows.dll\n"
314 L"correctly and so cannot work under current operating system.\n"
315 L"Please contact the program author for an updated version.\n"
316 L"\n"
317 L"Program aborted.",
318 ERROR_STRING,
319 MB_ICONERROR | MB_OK
320 );
321
322 return false;
323 }
324
325 ::FreeLibrary(hmod);
774960ce 326#endif // !wxUSE_UNICODE_MSLU
bd866271 327 }
6f2df739
VZ
328
329 return true;
330}
331
332#endif // NEED_UNICODE_CHECK
333
334// ----------------------------------------------------------------------------
335// Windows-specific wxEntry
336// ----------------------------------------------------------------------------
337
338WXDLLEXPORT int wxEntry(HINSTANCE hInstance,
339 HINSTANCE WXUNUSED(hPrevInstance),
340 wxCmdLineArgType WXUNUSED(pCmdLine),
341 int nCmdShow)
342{
343 // the first thing to do is to check if we're trying to run an Unicode
344 // program under Win9x w/o MSLU emulation layer - if so, abort right now
345 // as it has no chance to work and has all chances to crash
346#ifdef NEED_UNICODE_CHECK
347 if ( !wxIsUnicodeAvailable() )
348 return -1;
349#endif // NEED_UNICODE_CHECK
bd866271
VZ
350
351
94826170 352 // remember the parameters Windows gave us
13bdd545 353 wxSetInstance(hInstance);
94826170
VZ
354 wxApp::m_nCmdShow = nCmdShow;
355
b2b1371c
VZ
356 // parse the command line: we can't use pCmdLine in Unicode build so it is
357 // simpler to never use it at all (this also results in a more correct
358 // argv[0])
359
360 // break the command line in words
361 wxArrayString args;
13a5a49f 362
b2b1371c
VZ
363 const wxChar *cmdLine = ::GetCommandLine();
364 if ( cmdLine )
365 {
366 args = wxCmdLineParser::ConvertStringToArgs(cmdLine);
367 }
368
13a5a49f 369#ifdef __WXWINCE__
77d8d6cd
VZ
370 // WinCE doesn't insert the program itself, so do it ourselves.
371 args.Insert(wxGetFullModuleName(), 0);
13a5a49f
JS
372#endif
373
b2b1371c
VZ
374 int argc = args.GetCount();
375
376 // +1 here for the terminating NULL
377 wxChar **argv = new wxChar *[argc + 1];
378 for ( int i = 0; i < argc; i++ )
379 {
380 argv[i] = wxStrdup(args[i]);
381 }
382
383 // argv[] must be NULL-terminated
384 argv[argc] = NULL;
94826170
VZ
385
386 return wxEntry(argc, argv);
387}
388
2bda0e17 389// May wish not to have a DllMain or WinMain, e.g. if we're programming
b568d04f 390// a Netscape plugin or if we're writing a console application
94826170 391#if !defined(NOMAIN)
2bda0e17 392
e2478fde
VZ
393extern "C"
394{
2bda0e17 395
e2478fde 396// ----------------------------------------------------------------------------
2bda0e17 397// WinMain
e2478fde
VZ
398// ----------------------------------------------------------------------------
399
2bda0e17 400// Note that WinMain is also defined in dummy.obj, which is linked to
77ffb593 401// an application that is using the DLL version of wxWidgets.
2bda0e17 402
ac9a3c61 403#if defined(_WINDLL)
2bda0e17
KB
404
405// DLL entry point
406
e2478fde 407BOOL WINAPI
7adf0b4d 408DllMain(HINSTANCE hModule, DWORD fdwReason, LPVOID WXUNUSED(lpReserved))
2bda0e17 409{
e2478fde 410 // Only call wxEntry if the application itself is part of the DLL.
77ffb593 411 // If only the wxWidgets library is in the DLL, then the
e2478fde
VZ
412 // initialisation will be called when the application implicitly
413 // calls WinMain.
beed393c 414#ifndef WXMAKINGDLL
2bda0e17 415 switch (fdwReason)
b568d04f
VZ
416 {
417 case DLL_PROCESS_ATTACH:
13bdd545 418 return wxEntry(hModule);
2bda0e17 419
b568d04f 420 case DLL_PROCESS_DETACH:
94826170
VZ
421 wxEntryCleanup();
422 break;
b568d04f 423 }
33ac7e6f 424#else
598ddd96
WS
425 (void)hModule;
426 (void)fdwReason;
beed393c 427#endif // !WXMAKINGDLL
e2478fde 428
b568d04f 429 return TRUE;
2bda0e17
KB
430}
431
ac9a3c61 432#endif // _WINDLL
e2478fde
VZ
433
434} // extern "C"
2bda0e17 435
b568d04f
VZ
436#endif // !NOMAIN
437
532d575b 438#endif // wxUSE_GUI && __WXMSW__
94826170 439
b568d04f 440// ----------------------------------------------------------------------------
e2478fde 441// global HINSTANCE
b568d04f
VZ
442// ----------------------------------------------------------------------------
443
ec67cff1 444#if wxUSE_BASE
e2478fde
VZ
445
446HINSTANCE wxhInstance = 0;
447
028e7716 448extern "C" HINSTANCE wxGetInstance()
b568d04f
VZ
449{
450 return wxhInstance;
451}
452
453void wxSetInstance(HINSTANCE hInst)
454{
455 wxhInstance = hInst;
456}
2bda0e17 457
ec67cff1 458#endif // wxUSE_BASE
e2478fde 459