1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     WinMain/DllMain 
   4 // Author:      Julian Smart 
   8 // Copyright:   (c) Julian Smart 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  20 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) 
  21     #pragma implementation 
  24 // For compilers that support precompilation, includes "wx.h". 
  25 #include "wx/wxprec.h" 
  33 #include "wx/cmdline.h" 
  35 #include "wx/msw/private.h" 
  37 #if wxUSE_ON_FATAL_EXCEPTION 
  38     #include "wx/datetime.h" 
  39     #include "wx/msw/crashrpt.h" 
  44 #endif // wxUSE_ON_FATAL_EXCEPTION 
  47     // there is no ExitProcess() under CE but exiting the main thread has the 
  50         #define ExitProcess ExitThread 
  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 // __BORLANDC__ 
  60 #if defined(__WXMICROWIN__) 
  61     #define HINSTANCE HANDLE 
  64 // defined in common/init.cpp 
  65 extern int wxEntryReal(int& argc
, wxChar 
**argv
); 
  67 // ============================================================================ 
  68 // implementation: various entry points 
  69 // ============================================================================ 
  73 #if wxUSE_ON_FATAL_EXCEPTION && defined(__VISUALC__) && !defined(__WXWINCE__) 
  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 
  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 
  86         #pragma warning(disable:4535) 
  89     // note that the SE translator must be called wxSETranslator! 
  90     #define DisableAutomaticSETranslator() _set_se_translator(wxSETranslator) 
  92     #define DisableAutomaticSETranslator() 
  93 #endif // __VISUALC__/!__VISUALC__ 
  95 // ---------------------------------------------------------------------------- 
  96 // wrapper wxEntry catching all Win32 exceptions occurring in a wx program 
  97 // ---------------------------------------------------------------------------- 
  99 // wrap real wxEntry in a try-except block to be able to call 
 100 // OnFatalException() if necessary 
 101 #if wxUSE_ON_FATAL_EXCEPTION 
 103 // global pointer to exception information, only valid inside OnFatalException, 
 104 // used by wxStackWalker and wxCrashReport 
 105 extern EXCEPTION_POINTERS 
*wxGlobalSEInformation 
= NULL
; 
 107 // flag telling us whether the application wants to handle exceptions at all 
 108 static bool gs_handleExceptions 
= false; 
 110 static void wxFatalExit() 
 112     // use the same exit code as abort() 
 116 unsigned long wxGlobalSEHandler(EXCEPTION_POINTERS 
*pExcPtrs
) 
 118     if ( gs_handleExceptions 
&& wxTheApp 
) 
 120         // store the pointer to exception info 
 121         wxGlobalSEInformation 
= pExcPtrs
; 
 123         // give the user a chance to do something special about this 
 126             wxTheApp
->OnFatalException(); 
 128         __except ( EXCEPTION_EXECUTE_HANDLER 
) 
 130             // nothing to do here, just ignore the exception inside the 
 135         wxGlobalSEInformation 
= NULL
; 
 137         // this will execute our handler and terminate the process 
 138         return EXCEPTION_EXECUTE_HANDLER
; 
 141     return EXCEPTION_CONTINUE_SEARCH
; 
 146 static void wxSETranslator(unsigned int WXUNUSED(code
), EXCEPTION_POINTERS 
*ep
) 
 148     switch ( wxGlobalSEHandler(ep
) ) 
 151             wxFAIL_MSG( _T("unexpected wxGlobalSEHandler() return value") ); 
 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 
 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 
 171 #endif // __VISUALC__ 
 173 bool wxHandleFatalExceptions(bool doit
) 
 175     // assume this can only be called from the main thread 
 176     gs_handleExceptions 
= doit
; 
 178 #if wxUSE_CRASHREPORT 
 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
) ) 
 185             wxLogLastError(_T("GetTempPath")); 
 187             // when all else fails... 
 188             wxStrcpy(fullname
, _T("c:\\")); 
 191         // use PID and date to make the report file name more unique 
 192         wxString name 
= wxString::Format
 
 195                             wxTheApp 
? wxTheApp
->GetAppName().c_str() 
 197                             wxDateTime::Now().Format(_T("%Y%m%dT%H%M%S")).c_str(), 
 198                             ::GetCurrentProcessId() 
 201         wxStrncat(fullname
, name
, WXSIZEOF(fullname
) - wxStrlen(fullname
) - 1); 
 203         wxCrashReport::SetFileName(fullname
); 
 205 #endif // wxUSE_CRASHREPORT 
 210 int wxEntry(int& argc
, wxChar 
**argv
) 
 212     DisableAutomaticSETranslator(); 
 216         return wxEntryReal(argc
, argv
); 
 218     __except ( wxGlobalSEHandler(GetExceptionInformation()) ) 
 222 #if !defined(_MSC_VER) || defined(__WXDEBUG__) || (defined(_MSC_VER) && _MSC_VER <= 1200) 
 223         // this code is unreachable but put it here to suppress warnings in some compilers 
 224         // and disable for others to supress warnings too 
 226 #endif // !__VISUALC__ in release build 
 230 #else // !wxUSE_ON_FATAL_EXCEPTION 
 232 #if defined(__VISUALC__) && !defined(__WXWINCE__) 
 235 wxSETranslator(unsigned int WXUNUSED(code
), EXCEPTION_POINTERS 
* WXUNUSED(ep
)) 
 237     // see wxSETranslator() version for wxUSE_ON_FATAL_EXCEPTION above 
 241 #endif // __VISUALC__ 
 243 int wxEntry(int& argc
, wxChar 
**argv
) 
 245     DisableAutomaticSETranslator(); 
 247     return wxEntryReal(argc
, argv
); 
 250 #endif // wxUSE_ON_FATAL_EXCEPTION/!wxUSE_ON_FATAL_EXCEPTION 
 256 // ---------------------------------------------------------------------------- 
 257 // Windows-specific wxEntry 
 258 // ---------------------------------------------------------------------------- 
 260 WXDLLEXPORT 
int wxEntry(HINSTANCE hInstance
, 
 261                         HINSTANCE 
WXUNUSED(hPrevInstance
), 
 262                         wxCmdLineArgType 
WXUNUSED(pCmdLine
), 
 265     // the first thing to do is to check if we're trying to run an Unicode 
 266     // program under Win9x w/o MSLU emulation layer - if so, abort right now 
 267     // as it has no chance to work and has all chances to crash 
 268 #if wxUSE_UNICODE && !wxUSE_UNICODE_MSLU && !defined(__WXWINCE__) 
 269     if ( wxGetOsVersion() != wxWINDOWS_NT 
) 
 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 
 277          _T("This program uses Unicode and requires Windows NT/2000/XP.\nProgram aborted."), 
 278          _T("wxWidgets Fatal Error"), 
 284 #endif // wxUSE_UNICODE && !wxUSE_UNICODE_MSLU 
 287     // remember the parameters Windows gave us 
 288     wxSetInstance(hInstance
); 
 289     wxApp::m_nCmdShow 
= nCmdShow
; 
 291     // parse the command line: we can't use pCmdLine in Unicode build so it is 
 292     // simpler to never use it at all (this also results in a more correct 
 295     // break the command line in words 
 298     const wxChar 
*cmdLine 
= ::GetCommandLine(); 
 301         args 
= wxCmdLineParser::ConvertStringToArgs(cmdLine
); 
 305     // WinCE doesn't insert the program itself, so do it ourselves. 
 306     args
.Insert(wxGetFullModuleName(), 0); 
 309     int argc 
= args
.GetCount(); 
 311     // +1 here for the terminating NULL 
 312     wxChar 
**argv 
= new wxChar 
*[argc 
+ 1]; 
 313     for ( int i 
= 0; i 
< argc
; i
++ ) 
 315         argv
[i
] = wxStrdup(args
[i
]); 
 318     // argv[] must be NULL-terminated 
 321     return wxEntry(argc
, argv
); 
 324 // May wish not to have a DllMain or WinMain, e.g. if we're programming 
 325 // a Netscape plugin or if we're writing a console application 
 331 // ---------------------------------------------------------------------------- 
 333 // ---------------------------------------------------------------------------- 
 335 // Note that WinMain is also defined in dummy.obj, which is linked to 
 336 // an application that is using the DLL version of wxWidgets. 
 343 DllMain(HINSTANCE hModule
, DWORD fdwReason
, LPVOID 
WXUNUSED(lpReserved
)) 
 345     // Only call wxEntry if the application itself is part of the DLL. 
 346     // If only the wxWidgets library is in the DLL, then the 
 347     // initialisation will be called when the application implicitly 
 352         case DLL_PROCESS_ATTACH
: 
 353             return wxEntry(hModule
); 
 355         case DLL_PROCESS_DETACH
: 
 362 #endif // !WXMAKINGDLL 
 375 // ---------------------------------------------------------------------------- 
 377 // ---------------------------------------------------------------------------- 
 381 HINSTANCE wxhInstance 
= 0; 
 383 extern "C" HINSTANCE 
wxGetInstance() 
 388 void wxSetInstance(HINSTANCE hInst
)