327 lines
8.5 KiB
C++
327 lines
8.5 KiB
C++
/////////////////////////////////////////////////////////////////////////////
|
|
// Name: src/msw/main.cpp
|
|
// Purpose: WinMain/DllMain
|
|
// Author: Julian Smart
|
|
// Modified by:
|
|
// Created: 04/01/98
|
|
// Copyright: (c) Julian Smart
|
|
// Licence: wxWindows licence
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// ============================================================================
|
|
// declarations
|
|
// ============================================================================
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// headers
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// For compilers that support precompilation, includes "wx.h".
|
|
#include "wx/wxprec.h"
|
|
|
|
|
|
#ifndef WX_PRECOMP
|
|
#include "wx/event.h"
|
|
#include "wx/app.h"
|
|
#include "wx/utils.h"
|
|
#endif //WX_PRECOMP
|
|
|
|
// wxCmdLineParser is only used when we can't use ::CommandLineToArgvW().
|
|
#if !wxUSE_UNICODE
|
|
#include "wx/cmdline.h"
|
|
#endif
|
|
#include "wx/dynlib.h"
|
|
|
|
#include "wx/msw/private.h"
|
|
#include "wx/msw/seh.h"
|
|
|
|
#if wxUSE_ON_FATAL_EXCEPTION
|
|
#include "wx/datetime.h"
|
|
#include "wx/msw/crashrpt.h"
|
|
#endif // wxUSE_ON_FATAL_EXCEPTION
|
|
|
|
// defined in common/init.cpp
|
|
extern int wxEntryReal(int& argc, wxChar **argv);
|
|
extern int wxEntryCleanupReal(int& argc, wxChar **argv);
|
|
|
|
// ============================================================================
|
|
// implementation: various entry points
|
|
// ============================================================================
|
|
|
|
#if wxUSE_BASE
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// wrapper wxEntry catching all Win32 exceptions occurring in a wx program
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// wrap real wxEntry in a try-except block to be able to call
|
|
// OnFatalException() if necessary
|
|
#if wxUSE_ON_FATAL_EXCEPTION
|
|
|
|
// global pointer to exception information, only valid inside OnFatalException,
|
|
// used by wxStackWalker and wxCrashReport
|
|
extern EXCEPTION_POINTERS *wxGlobalSEInformation = NULL;
|
|
|
|
// flag telling us whether the application wants to handle exceptions at all
|
|
static bool gs_handleExceptions = false;
|
|
|
|
static void wxFatalExit()
|
|
{
|
|
// use the same exit code as abort()
|
|
::ExitProcess(3);
|
|
}
|
|
|
|
unsigned long wxGlobalSEHandler(EXCEPTION_POINTERS *pExcPtrs)
|
|
{
|
|
if ( gs_handleExceptions && wxTheApp )
|
|
{
|
|
// store the pointer to exception info
|
|
wxGlobalSEInformation = pExcPtrs;
|
|
|
|
// give the user a chance to do something special about this
|
|
wxSEH_TRY
|
|
{
|
|
wxTheApp->OnFatalException();
|
|
}
|
|
wxSEH_IGNORE // ignore any exceptions inside the exception handler
|
|
|
|
wxGlobalSEInformation = NULL;
|
|
|
|
// this will execute our handler and terminate the process
|
|
return EXCEPTION_EXECUTE_HANDLER;
|
|
}
|
|
|
|
return EXCEPTION_CONTINUE_SEARCH;
|
|
}
|
|
|
|
#ifdef __VISUALC__
|
|
|
|
void wxSETranslator(unsigned int WXUNUSED(code), EXCEPTION_POINTERS *ep)
|
|
{
|
|
switch ( wxGlobalSEHandler(ep) )
|
|
{
|
|
default:
|
|
wxFAIL_MSG( wxT("unexpected wxGlobalSEHandler() return value") );
|
|
// fall through
|
|
|
|
case EXCEPTION_EXECUTE_HANDLER:
|
|
// if wxApp::OnFatalException() had been called we should exit the
|
|
// application -- but we shouldn't kill our host when we're a DLL
|
|
#ifndef WXMAKINGDLL
|
|
wxFatalExit();
|
|
#endif // not a DLL
|
|
break;
|
|
|
|
case EXCEPTION_CONTINUE_SEARCH:
|
|
// we're called for each "catch ( ... )" and if we (re)throw from
|
|
// here, the catch handler body is not executed, so the effect is
|
|
// as if had inhibited translation of SE to C++ ones because the
|
|
// handler will never see any structured exceptions
|
|
throw;
|
|
}
|
|
}
|
|
|
|
#endif // __VISUALC__
|
|
|
|
bool wxHandleFatalExceptions(bool doit)
|
|
{
|
|
// assume this can only be called from the main thread
|
|
gs_handleExceptions = doit;
|
|
|
|
#if wxUSE_CRASHREPORT
|
|
if ( doit )
|
|
{
|
|
// try to find a place where we can put out report file later
|
|
wxChar fullname[MAX_PATH];
|
|
if ( !::GetTempPath(WXSIZEOF(fullname), fullname) )
|
|
{
|
|
wxLogLastError(wxT("GetTempPath"));
|
|
|
|
// when all else fails...
|
|
wxStrcpy(fullname, wxT("c:\\"));
|
|
}
|
|
|
|
// use PID and date to make the report file name more unique
|
|
wxString name = wxString::Format
|
|
(
|
|
#if wxUSE_DATETIME
|
|
wxT("%s_%s_%lu.dmp"),
|
|
#else
|
|
wxT("%s_%lu.dmp"),
|
|
#endif
|
|
wxTheApp ? (const wxChar*)wxTheApp->GetAppDisplayName().c_str()
|
|
: wxT("wxwindows"),
|
|
#if wxUSE_DATETIME
|
|
wxDateTime::Now().Format(wxT("%Y%m%dT%H%M%S")).c_str(),
|
|
#endif
|
|
::GetCurrentProcessId()
|
|
);
|
|
|
|
wxStrncat(fullname, name, WXSIZEOF(fullname) - wxStrlen(fullname) - 1);
|
|
|
|
wxCrashReport::SetFileName(fullname);
|
|
}
|
|
#endif // wxUSE_CRASHREPORT
|
|
|
|
return true;
|
|
}
|
|
|
|
int wxEntry(int& argc, wxChar **argv)
|
|
{
|
|
DisableAutomaticSETranslator();
|
|
|
|
wxSEH_TRY
|
|
{
|
|
return wxEntryReal(argc, argv);
|
|
}
|
|
wxSEH_HANDLE(-1)
|
|
}
|
|
|
|
#else // !wxUSE_ON_FATAL_EXCEPTION
|
|
|
|
int wxEntry(int& argc, wxChar **argv)
|
|
{
|
|
return wxEntryReal(argc, argv);
|
|
}
|
|
|
|
#endif // wxUSE_ON_FATAL_EXCEPTION/!wxUSE_ON_FATAL_EXCEPTION
|
|
|
|
#endif // wxUSE_BASE
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// Windows-specific wxEntry
|
|
// ----------------------------------------------------------------------------
|
|
|
|
struct wxMSWCommandLineArguments
|
|
{
|
|
wxMSWCommandLineArguments() { argc = 0; argv = NULL; }
|
|
|
|
// Initialize this object from the current process command line.
|
|
//
|
|
// In Unicode build prefer to use the standard function for tokenizing the
|
|
// command line, but we can't use it with narrow strings, so use our own
|
|
// approximation instead then.
|
|
#if wxUSE_UNICODE
|
|
void Init()
|
|
{
|
|
argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc);
|
|
}
|
|
|
|
~wxMSWCommandLineArguments()
|
|
{
|
|
if ( argc )
|
|
::LocalFree(argv);
|
|
}
|
|
#else // !wxUSE_UNICODE
|
|
void Init()
|
|
{
|
|
// Get the command line.
|
|
const wxChar* const cmdLine = ::GetCommandLine();
|
|
if ( !cmdLine )
|
|
return;
|
|
|
|
// And tokenize it.
|
|
const wxArrayString args = wxCmdLineParser::ConvertStringToArgs(cmdLine);
|
|
|
|
argc = args.size();
|
|
|
|
// +1 here for the terminating NULL
|
|
argv = new wxChar *[argc + 1];
|
|
for ( int i = 0; i < argc; i++ )
|
|
{
|
|
argv[i] = wxStrdup(args[i].t_str());
|
|
}
|
|
|
|
// argv[] must be NULL-terminated
|
|
argv[argc] = NULL;
|
|
}
|
|
|
|
~wxMSWCommandLineArguments()
|
|
{
|
|
if ( !argc )
|
|
return;
|
|
|
|
for ( int i = 0; i < argc; i++ )
|
|
{
|
|
free(argv[i]);
|
|
}
|
|
|
|
wxDELETEA(argv);
|
|
argc = 0;
|
|
}
|
|
#endif // wxUSE_UNICODE/!wxUSE_UNICODE
|
|
|
|
int argc;
|
|
wxChar **argv;
|
|
};
|
|
|
|
static wxMSWCommandLineArguments wxArgs;
|
|
|
|
#if wxUSE_GUI
|
|
|
|
// common part of wxMSW-specific wxEntryStart() and wxEntry() overloads
|
|
static bool
|
|
wxMSWEntryCommon(HINSTANCE hInstance, int nCmdShow)
|
|
{
|
|
// remember the parameters Windows gave us
|
|
wxSetInstance(hInstance);
|
|
#ifdef __WXMSW__
|
|
wxApp::m_nCmdShow = nCmdShow;
|
|
#endif
|
|
|
|
wxArgs.Init();
|
|
|
|
return true;
|
|
}
|
|
|
|
WXDLLEXPORT bool wxEntryStart(HINSTANCE hInstance,
|
|
HINSTANCE WXUNUSED(hPrevInstance),
|
|
wxCmdLineArgType WXUNUSED(pCmdLine),
|
|
int nCmdShow)
|
|
{
|
|
if ( !wxMSWEntryCommon(hInstance, nCmdShow) )
|
|
return false;
|
|
|
|
return wxEntryStart(wxArgs.argc, wxArgs.argv);
|
|
}
|
|
|
|
WXDLLEXPORT int wxEntry(HINSTANCE hInstance,
|
|
HINSTANCE WXUNUSED(hPrevInstance),
|
|
wxCmdLineArgType WXUNUSED(pCmdLine),
|
|
int nCmdShow)
|
|
{
|
|
if ( !wxMSWEntryCommon(hInstance, nCmdShow) )
|
|
return -1;
|
|
|
|
return wxEntry(wxArgs.argc, wxArgs.argv);
|
|
}
|
|
|
|
#endif // wxUSE_GUI
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// global HINSTANCE
|
|
// ----------------------------------------------------------------------------
|
|
|
|
#if wxUSE_BASE
|
|
|
|
int wxEntry()
|
|
{
|
|
wxArgs.Init();
|
|
|
|
return wxEntry(wxArgs.argc, wxArgs.argv);
|
|
}
|
|
|
|
HINSTANCE wxhInstance = 0;
|
|
|
|
extern "C" HINSTANCE wxGetInstance()
|
|
{
|
|
return wxhInstance;
|
|
}
|
|
|
|
void wxSetInstance(HINSTANCE hInst)
|
|
{
|
|
wxhInstance = hInst;
|
|
}
|
|
|
|
#endif // wxUSE_BASE
|