1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/msw/main.cpp 
   3 // Purpose:     WinMain/DllMain 
   4 // Author:      Julian Smart 
   8 // Copyright:   (c) Julian Smart 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  20 // For compilers that support precompilation, includes "wx.h". 
  21 #include "wx/wxprec.h" 
  32 #include "wx/cmdline.h" 
  33 #include "wx/scopeguard.h" 
  35 #include "wx/msw/private.h" 
  36 #include "wx/msw/seh.h" 
  38 #if wxUSE_ON_FATAL_EXCEPTION 
  39     #include "wx/datetime.h" 
  40     #include "wx/msw/crashrpt.h" 
  41 #endif // wxUSE_ON_FATAL_EXCEPTION 
  44     // there is no ExitProcess() under CE but exiting the main thread has the 
  47         #define ExitProcess ExitThread 
  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 
  55 #endif // __BORLANDC__ 
  57 #if defined(__WXMICROWIN__) 
  58     #define HINSTANCE HANDLE 
  61 // defined in common/init.cpp 
  62 extern int wxEntryReal(int& argc
, wxChar 
**argv
); 
  64 // ============================================================================ 
  65 // implementation: various entry points 
  66 // ============================================================================ 
  70 #if wxUSE_ON_FATAL_EXCEPTION && defined(__VISUALC__) && !defined(__WXWINCE__) 
  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 
  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 
  83         #pragma warning(disable:4535) 
  86     // note that the SE translator must be called wxSETranslator! 
  87     #define DisableAutomaticSETranslator() _set_se_translator(wxSETranslator) 
  89     #define DisableAutomaticSETranslator() 
  90 #endif // __VISUALC__/!__VISUALC__ 
  92 // ---------------------------------------------------------------------------- 
  93 // wrapper wxEntry catching all Win32 exceptions occurring in a wx program 
  94 // ---------------------------------------------------------------------------- 
  96 // wrap real wxEntry in a try-except block to be able to call 
  97 // OnFatalException() if necessary 
  98 #if wxUSE_ON_FATAL_EXCEPTION 
 100 // global pointer to exception information, only valid inside OnFatalException, 
 101 // used by wxStackWalker and wxCrashReport 
 102 extern EXCEPTION_POINTERS 
*wxGlobalSEInformation 
= NULL
; 
 104 // flag telling us whether the application wants to handle exceptions at all 
 105 static bool gs_handleExceptions 
= false; 
 107 static void wxFatalExit() 
 109     // use the same exit code as abort() 
 113 unsigned long wxGlobalSEHandler(EXCEPTION_POINTERS 
*pExcPtrs
) 
 115     if ( gs_handleExceptions 
&& wxTheApp 
) 
 117         // store the pointer to exception info 
 118         wxGlobalSEInformation 
= pExcPtrs
; 
 120         // give the user a chance to do something special about this 
 123             wxTheApp
->OnFatalException(); 
 125         wxSEH_IGNORE      
// ignore any exceptions inside the exception handler 
 127         wxGlobalSEInformation 
= NULL
; 
 129         // this will execute our handler and terminate the process 
 130         return EXCEPTION_EXECUTE_HANDLER
; 
 133     return EXCEPTION_CONTINUE_SEARCH
; 
 138 void wxSETranslator(unsigned int WXUNUSED(code
), EXCEPTION_POINTERS 
*ep
) 
 140     switch ( wxGlobalSEHandler(ep
) ) 
 143             wxFAIL_MSG( _T("unexpected wxGlobalSEHandler() return value") ); 
 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 
 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 
 163 #endif // __VISUALC__ 
 165 bool wxHandleFatalExceptions(bool doit
) 
 167     // assume this can only be called from the main thread 
 168     gs_handleExceptions 
= doit
; 
 170 #if wxUSE_CRASHREPORT 
 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
) ) 
 177             wxLogLastError(_T("GetTempPath")); 
 179             // when all else fails... 
 180             wxStrcpy(fullname
, _T("c:\\")); 
 183         // use PID and date to make the report file name more unique 
 184         wxString name 
= wxString::Format
 
 187                             wxTheApp 
? wxTheApp
->GetAppName().c_str() 
 189                             wxDateTime::Now().Format(_T("%Y%m%dT%H%M%S")).c_str(), 
 190                             ::GetCurrentProcessId() 
 193         wxStrncat(fullname
, name
, WXSIZEOF(fullname
) - wxStrlen(fullname
) - 1); 
 195         wxCrashReport::SetFileName(fullname
); 
 197 #endif // wxUSE_CRASHREPORT 
 202 int wxEntry(int& argc
, wxChar 
**argv
) 
 204     DisableAutomaticSETranslator(); 
 208         return wxEntryReal(argc
, argv
); 
 213 #else // !wxUSE_ON_FATAL_EXCEPTION 
 215 #if defined(__VISUALC__) && !defined(__WXWINCE__) 
 218 wxSETranslator(unsigned int WXUNUSED(code
), EXCEPTION_POINTERS 
* WXUNUSED(ep
)) 
 220     // see wxSETranslator() version for wxUSE_ON_FATAL_EXCEPTION above 
 224 #endif // __VISUALC__ 
 226 int wxEntry(int& argc
, wxChar 
**argv
) 
 228     DisableAutomaticSETranslator(); 
 230     return wxEntryReal(argc
, argv
); 
 233 #endif // wxUSE_ON_FATAL_EXCEPTION/!wxUSE_ON_FATAL_EXCEPTION 
 237 #if wxUSE_GUI && defined(__WXMSW__) 
 239 #if wxUSE_UNICODE && !defined(__WXWINCE__) 
 240     #define NEED_UNICODE_CHECK 
 243 #ifdef NEED_UNICODE_CHECK 
 245 // check whether Unicode is available 
 246 static bool wxIsUnicodeAvailable() 
 248     static const wchar_t *ERROR_STRING 
= L
"wxWidgets Fatal Error"; 
 250     if ( wxGetOsVersion() != wxWINDOWS_NT 
) 
 252         // we need to be built with MSLU support 
 253 #if !wxUSE_UNICODE_MSLU 
 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 
 260          L
"This program uses Unicode and requires Windows NT/2000/XP.\n" 
 268 #else // wxUSE_UNICODE_MSLU 
 269         // and the MSLU DLL must also be available 
 270         HMODULE hmod 
= ::LoadLibraryA("unicows.dll"); 
 276              L
"This program uses Unicode and requires unicows.dll to work " 
 277              L
"under current operating system.\n" 
 279              L
"Please install unicows.dll and relaunch the program.", 
 286         // this is not really necessary but be tidy 
 289         // finally do the last check: has unicows.lib initialized correctly? 
 290         hmod 
= ::LoadLibraryW(L
"unicows.dll"); 
 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" 
 309 #endif // !wxUSE_UNICODE_MSLU 
 315 #endif // NEED_UNICODE_CHECK 
 317 // ---------------------------------------------------------------------------- 
 318 // Windows-specific wxEntry 
 319 // ---------------------------------------------------------------------------- 
 321 // helper function used to clean up in wxEntry() just below 
 323 // notice that argv elements are supposed to be allocated using malloc() while 
 324 // argv array itself is allocated with new 
 325 static void wxFreeArgs(int argc
, wxChar 
**argv
) 
 327     for ( int i 
= 0; i 
< argc
; i
++ ) 
 335 WXDLLEXPORT 
int wxEntry(HINSTANCE hInstance
, 
 336                         HINSTANCE 
WXUNUSED(hPrevInstance
), 
 337                         wxCmdLineArgType 
WXUNUSED(pCmdLine
), 
 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() ) 
 346 #endif // NEED_UNICODE_CHECK 
 349     // remember the parameters Windows gave us 
 350     wxSetInstance(hInstance
); 
 351     wxApp::m_nCmdShow 
= nCmdShow
; 
 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 
 357     // break the command line in words 
 360     const wxChar 
*cmdLine 
= ::GetCommandLine(); 
 363         args 
= wxCmdLineParser::ConvertStringToArgs(cmdLine
); 
 367     // WinCE doesn't insert the program itself, so do it ourselves. 
 368     args
.Insert(wxGetFullModuleName(), 0); 
 371     int argc 
= args
.GetCount(); 
 373     // +1 here for the terminating NULL 
 374     wxChar 
**argv 
= new wxChar 
*[argc 
+ 1]; 
 375     for ( int i 
= 0; i 
< argc
; i
++ ) 
 377         argv
[i
] = wxStrdup(args
[i
]); 
 380     // argv[] must be NULL-terminated 
 383     wxON_BLOCK_EXIT2(wxFreeArgs
, argc
, argv
); 
 385     return wxEntry(argc
, argv
); 
 388 #endif // wxUSE_GUI && __WXMSW__ 
 390 // ---------------------------------------------------------------------------- 
 392 // ---------------------------------------------------------------------------- 
 396 HINSTANCE wxhInstance 
= 0; 
 398 extern "C" HINSTANCE 
wxGetInstance() 
 403 void wxSetInstance(HINSTANCE hInst
)