]> git.saurik.com Git - wxWidgets.git/blob - src/msw/main.cpp
796074690db03368b8014b809f6de374c44320e6
[wxWidgets.git] / src / msw / main.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: msw/main.cpp
3 // Purpose: WinMain/DllMain
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 04/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
21 #pragma implementation
22 #endif
23
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
26
27 #ifdef __BORLANDC__
28 #pragma hdrstop
29 #endif
30
31 #include "wx/event.h"
32 #include "wx/app.h"
33 #include "wx/cmdline.h"
34
35 #include "wx/msw/private.h"
36
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
49 #ifndef ExitProcess
50 #define ExitProcess ExitThread
51 #endif
52 #endif
53
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
58 #endif
59
60 #if defined(__WXMICROWIN__)
61 #define HINSTANCE HANDLE
62 #endif
63
64 // ============================================================================
65 // implementation: various entry points
66 // ============================================================================
67
68 // ----------------------------------------------------------------------------
69 // wrapper wxEntry catching all Win32 exceptions occuring in a wx program
70 // ----------------------------------------------------------------------------
71
72 // wrap real wxEntry in a try-except block to be able to call
73 // OnFatalException() if necessary
74 #if wxUSE_ON_FATAL_EXCEPTION && wxUSE_BASE
75
76 // global pointer to exception information, only valid inside OnFatalException,
77 // used by wxStackWalker and wxCrashReport
78 extern EXCEPTION_POINTERS *wxGlobalSEInformation = NULL;
79
80 // flag telling us whether the application wants to handle exceptions at all
81 static bool gs_handleExceptions = false;
82
83 unsigned long wxGlobalSEHandler(EXCEPTION_POINTERS *pExcPtrs)
84 {
85 if ( gs_handleExceptions && wxTheApp )
86 {
87 // store the pointer to exception info
88 wxGlobalSEInformation = pExcPtrs;
89
90 // give the user a chance to do something special about this
91 __try
92 {
93 wxTheApp->OnFatalException();
94 }
95 __except ( EXCEPTION_EXECUTE_HANDLER )
96 {
97 // nothing to do here, just ignore the exception inside the
98 // exception handler
99 ;
100 }
101
102 wxGlobalSEInformation = NULL;
103
104 // this will execute our handler and terminate the process
105 return EXCEPTION_EXECUTE_HANDLER;
106 }
107
108 return EXCEPTION_CONTINUE_SEARCH;
109 }
110
111 #ifdef __VISUALC__
112
113 static void wxSETranslator(unsigned int WXUNUSED(code), EXCEPTION_POINTERS *ep)
114 {
115 wxGlobalSEHandler(ep);
116 }
117
118 #endif // __VISUALC__
119
120 bool wxHandleFatalExceptions(bool doit)
121 {
122 // assume this can only be called from the main thread
123 gs_handleExceptions = doit;
124
125 #ifdef __VISUALC__
126 // VC++ (at least from 4.0 up to version 7.1) is incredibly broken in that
127 // a "catch ( ... )" will *always* catch SEH exceptions in it even though
128 // it should have never been the case... to prevent such catches from
129 // stealing the exceptions from our wxGlobalSEHandler which is only called
130 // if the exception is not handled elsewhere, we have to also call it from
131 // a special SEH translator function which is called by VC CRT when a Win32
132 // exception occurs
133
134 // this warns that /EHa (async exceptions) should be used when using
135 // _set_se_translator but, in fact, this doesn't seem to change anything
136 // with VC++ up to 7.1 -- to be confirmed with VC++ 8
137 #if _MSC_VER <= 1310
138 #pragma warning(disable:4535)
139 #endif
140
141 _set_se_translator(doit ? wxSETranslator : NULL);
142 #endif
143
144 #if wxUSE_CRASHREPORT
145 if ( doit )
146 {
147 // try to find a place where we can put out report file later
148 wxChar fullname[MAX_PATH];
149 if ( !::GetTempPath(WXSIZEOF(fullname), fullname) )
150 {
151 wxLogLastError(_T("GetTempPath"));
152
153 // when all else fails...
154 wxStrcpy(fullname, _T("c:\\"));
155 }
156
157 // use PID and date to make the report file name more unique
158 wxString name = wxString::Format
159 (
160 _T("%s_%s_%lu.dmp"),
161 wxTheApp ? wxTheApp->GetAppName().c_str()
162 : _T("wxwindows"),
163 wxDateTime::Now().Format(_T("%Y%m%dT%H%M%S")).c_str(),
164 ::GetCurrentProcessId()
165 );
166
167 wxStrncat(fullname, name, WXSIZEOF(fullname) - wxStrlen(fullname) - 1);
168
169 wxCrashReport::SetFileName(fullname);
170 }
171 #endif // wxUSE_CRASHREPORT
172
173 return true;
174 }
175
176 int wxEntry(int& argc, wxChar **argv)
177 {
178 __try
179 {
180 extern int wxEntryReal(int& argc, wxChar **argv);
181
182 return wxEntryReal(argc, argv);
183 }
184 __except ( wxGlobalSEHandler(GetExceptionInformation()) )
185 {
186 ::ExitProcess(3); // the same exit code as abort()
187
188 #if !defined(_MSC_VER) || _MSC_VER < 1300
189 // this code is unreachable but put it here to suppress warnings
190 // from some compilers
191 return -1;
192 #endif
193 }
194 }
195
196 #endif // wxUSE_ON_FATAL_EXCEPTION && wxUSE_BASE
197
198 #if wxUSE_GUI
199
200 // ----------------------------------------------------------------------------
201 // Windows-specific wxEntry
202 // ----------------------------------------------------------------------------
203
204 WXDLLEXPORT int wxEntry(HINSTANCE hInstance,
205 HINSTANCE WXUNUSED(hPrevInstance),
206 wxCmdLineArgType WXUNUSED(pCmdLine),
207 int nCmdShow)
208 {
209 // remember the parameters Windows gave us
210 wxSetInstance(hInstance);
211 wxApp::m_nCmdShow = nCmdShow;
212
213 // parse the command line: we can't use pCmdLine in Unicode build so it is
214 // simpler to never use it at all (this also results in a more correct
215 // argv[0])
216
217 // break the command line in words
218 wxArrayString args;
219
220 const wxChar *cmdLine = ::GetCommandLine();
221 if ( cmdLine )
222 {
223 args = wxCmdLineParser::ConvertStringToArgs(cmdLine);
224 }
225
226 #ifdef __WXWINCE__
227 // WinCE doesn't insert the program itself, so do it ourselves.
228 args.Insert(wxGetFullModuleName(), 0);
229 #endif
230
231 int argc = args.GetCount();
232
233 // +1 here for the terminating NULL
234 wxChar **argv = new wxChar *[argc + 1];
235 for ( int i = 0; i < argc; i++ )
236 {
237 argv[i] = wxStrdup(args[i]);
238 }
239
240 // argv[] must be NULL-terminated
241 argv[argc] = NULL;
242
243 return wxEntry(argc, argv);
244 }
245
246 // May wish not to have a DllMain or WinMain, e.g. if we're programming
247 // a Netscape plugin or if we're writing a console application
248 #if !defined(NOMAIN)
249
250 extern "C"
251 {
252
253 // ----------------------------------------------------------------------------
254 // WinMain
255 // ----------------------------------------------------------------------------
256
257 // Note that WinMain is also defined in dummy.obj, which is linked to
258 // an application that is using the DLL version of wxWidgets.
259
260 #if defined(_WINDLL)
261
262 // DLL entry point
263
264 BOOL WINAPI
265 DllMain(HANDLE hModule, DWORD fdwReason, LPVOID WXUNUSED(lpReserved))
266 {
267 // Only call wxEntry if the application itself is part of the DLL.
268 // If only the wxWidgets library is in the DLL, then the
269 // initialisation will be called when the application implicitly
270 // calls WinMain.
271 #ifndef WXMAKINGDLL
272 switch (fdwReason)
273 {
274 case DLL_PROCESS_ATTACH:
275 return wxEntry(hModule);
276
277 case DLL_PROCESS_DETACH:
278 wxEntryCleanup();
279 break;
280 }
281 #else
282 (void)hModule;
283 (void)fdwReason;
284 #endif // !WXMAKINGDLL
285
286 return TRUE;
287 }
288
289 #endif // _WINDLL
290
291 } // extern "C"
292
293 #endif // !NOMAIN
294
295 #endif // wxUSE_GUI
296
297 // ----------------------------------------------------------------------------
298 // global HINSTANCE
299 // ----------------------------------------------------------------------------
300
301 #if wxUSE_BASE
302
303 HINSTANCE wxhInstance = 0;
304
305 extern "C" HINSTANCE wxGetInstance()
306 {
307 return wxhInstance;
308 }
309
310 void wxSetInstance(HINSTANCE hInst)
311 {
312 wxhInstance = hInst;
313 }
314
315 #endif // wxUSE_BASE
316