Files
wxWidgets/src/msw/main.cpp
Vadim Zeitlin c9a458bfe8 Use Win32 ::CommandLineToArgvW() to tokenize command line
Use the standard function in Unicode build instead of our own emulation, it
should give better results and is marginally more efficient as it does fewer
heap allocations than our own wxCmdLineParser::ConvertStringToArgs().
2017-03-11 03:41:25 +01:00

338 lines
8.8 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"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#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
#ifdef __BORLANDC__
// BC++ has to be special: its run-time expects the DLL entry point to be
// named DllEntryPoint instead of the (more) standard DllMain
#define DllMain DllEntryPoint
#endif // __BORLANDC__
// 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);
}
#else // !wxUSE_GUI
int wxEntry()
{
wxArgs.Init();
return wxEntry(wxArgs.argc, wxArgs.argv);
}
#endif // wxUSE_GUI/!wxUSE_GUI
// ----------------------------------------------------------------------------
// global HINSTANCE
// ----------------------------------------------------------------------------
#if wxUSE_BASE
HINSTANCE wxhInstance = 0;
extern "C" HINSTANCE wxGetInstance()
{
return wxhInstance;
}
void wxSetInstance(HINSTANCE hInst)
{
wxhInstance = hInst;
}
#endif // wxUSE_BASE