ExceptionAttacher.cpp. #1

  • //
  • guest/
  • YourUncleBob/
  • p4win/
  • main/
  • common/
  • ExceptionAttacher.cpp.
  • View
  • Commits
  • Open Download .zip Download (5 KB)
// ExceptionAttacher.cpp
//
// This module contains the code that you need to add to any
// MFC app in order to wrap the main thread in an exception handler.
// The original version of this by Hans Dietrich replaced AfxWinMain, 
// but that fails to link properly, for unknown reasons, when UNICODE is 
// defined.
// The code in this source file consists of two parts.
//
// The first part replaces code found in appmodul.cpp in the MFC
// library.  This is a verbatim copy with the exception of commenting
// out the #pragma init_seg.  The only reason for this code being here
// is to fix the link problem; the MFC provided version of _tWinMain
// won't call the replacement AfxWinMain because for mysterious reasons
// it has a different decorated name when UNICODE is defined.
//
// The second part is a replacement for AfxWinMain.  This is a direct copy
// from winmain.cpp, modified by inserting the __try/__except.  There is a
// small difference here from the way it was done by Hans Deitrich: the call
// to AfxWinTerm is moved outside the __try/__except.  The reason for this
// is that AfxWinTerm calls CToolTipCtrl::DestroyToolTipCtrl.  If it's not
// done now, it will be done later by ExitProcess, but it's too late then
// and will result in a secondary exception.
//
// Warning: Any time MFC is updated, this file may need to be updated as well.
//
///////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "ExceptionHandler.h"

#ifdef UNICODE

// When UNICODE is defined, the compiler thinks the AfxWinMain is not a 
// replacement for the one in winmain.cpp.  Fortunately, it accepts our
// replacement for wWinMain, which ends up correctly calling our version
// of AfxWinMain.

// the following section is a copy from appmodul.cpp

/////////////////////////////////////////////////////////////////////////////
// export WinMain to force linkage to this module
extern int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
	LPTSTR lpCmdLine, int nCmdShow);

extern "C" int WINAPI
_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
	LPTSTR lpCmdLine, int nCmdShow)
{
	// call shared/exported WinMain
	return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
}

/////////////////////////////////////////////////////////////////////////////
// initialize app state such that it points to this module's core state

BOOL AFXAPI AfxInitialize(BOOL bDLL, DWORD dwVersion)
{
	AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
	pModuleState->m_bDLL = (BYTE)bDLL;
	ASSERT(dwVersion <= _MFC_VER);
	UNUSED(dwVersion);  // not used in release build
#ifdef _AFXDLL
	pModuleState->m_dwVersion = dwVersion;
#endif
#ifdef _MBCS
	// set correct multi-byte code-page for Win32 apps
	if (!bDLL)
		_setmbcp(_MB_CP_ANSI);
#endif //_MBCS
	return TRUE;
}

// force initialization early
#pragma warning(disable: 4074)
//#pragma init_seg(lib)

#ifndef _AFXDLL
void AFX_CDECL _AfxTermAppState()
{
	// terminate local data and critical sections
	AfxTermLocalData(NULL, TRUE);
	AfxCriticalTerm();

	// release the reference to thread local storage data
	AfxTlsRelease();
}
#endif

#ifndef _AFXDLL
char _afxInitAppState = (char)(AfxInitialize(FALSE, _MFC_VER), atexit(&_AfxTermAppState));
#else
char _afxInitAppState = (char)(AfxInitialize(FALSE, _MFC_VER));
#endif

/////////////////////////////////////////////////////////////////////////////
#endif //UNICODE

// the following section is a modified version of AfxWinMain from winmain.cpp:

/////////////////////////////////////////////////////////////////////////////
// Standard WinMain implementation
//  Can be replaced as long as 'AfxWinInit' is called first

int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
	LPTSTR lpCmdLine, int nCmdShow)
{
	ASSERT(hPrevInstance == NULL);

	int nReturnCode = -1;
	__try
	{
	CWinThread* pThread = AfxGetThread();
	CWinApp* pApp = AfxGetApp();

	// AFX internal initialization
	if (!AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow))
		goto InitFailure;

	// App global initializations (rare)
	if (pApp != NULL && !pApp->InitApplication())
		goto InitFailure;

	// Perform specific initializations
	if (!pThread->InitInstance())
	{
		if (pThread->m_pMainWnd != NULL)
		{
			TRACE(traceAppMsg, 0, "Warning: Destroying non-NULL m_pMainWnd\n");
			pThread->m_pMainWnd->DestroyWindow();
		}
		nReturnCode = pThread->ExitInstance();
		goto InitFailure;
	}
	nReturnCode = pThread->Run();

InitFailure:
#ifdef _DEBUG
	// Check for missing AfxLockTempMap calls
	if (AfxGetModuleThreadState()->m_nTempMapLock != 0)
	{
		TRACE(traceAppMsg, 0, "Warning: Temp map lock count non-zero (%ld).\n",
			AfxGetModuleThreadState()->m_nTempMapLock);
	}
	AfxLockTempMaps();
	AfxUnlockTempMaps(-1);
#else
	;
#endif
	}
	__except(RecordExceptionInfo(GetExceptionInformation()))
	{
	}

	// must call AfxWinTerm after handling exception or we'll crash
	// again trying to destroy the tooltip window

	AfxWinTerm();

	return nReturnCode;
}
# Change User Description Committed
#1 19924 YourUncleBob Populate -o //guest/perforce_software/p4win/...
//guest/YourUncleBob/p4win/.....
//guest/perforce_software/p4win/main/common/ExceptionAttacher.cpp
#1 16169 perforce_software Move files to follow new path scheme for branches.
//guest/perforce_software/p4win/common/ExceptionAttacher.cpp
#1 8562 Matt Attaway These feet never stop running.

Initial commit of the P4Win source code.  To the best of our knowledge this
compiles and runs using the 2013.3 P4 API and VS 2010. Expect a few changes
as we refine the build process. Please post any build issues to the forums.