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