windows-nt/Source/XPSP1/NT/base/win32/fusion/inc/sxsexceptionhandling.h
2020-09-26 16:20:57 +08:00

215 lines
4.7 KiB
C++

#if !defined(_FUSION_INC_SXSEXCEPTIONHANDLING_H_INCLUDED_)
#define _FUSION_INC_SXSEXCEPTIONHANDLING_H_INCLUDED_
/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
SxsExceptionHandling.h
Abstract:
Author:
Jay Krell (a-JayK) October 2000
Revision History:
--*/
#pragma once
#include "nt.h"
#include "ntrtl.h"
#include "nturtl.h"
#include "windows.h"
#include "fusionlastwin32error.h"
#include "fusionntdll.h"
#include "fusiontrace.h"
#include "csxspreservelasterror.h" // Most destructors should use this.
#include "fusionheap.h"
/*-----------------------------------------------------------------------------
Instead of:
__except(EXECEPTION_EXECUTE_HANDLER)
say:
__except(SXSP_EXCEPTION_FILTER())
This way all exceptions will be logged with DbgPrint,
and probably hit a breakpoint if under a debugger, and any other behavior we
want.
If your exception filter is other than (EXECEPTION_EXECUTE_HANDLER), then
you are on your own.
-----------------------------------------------------------------------------*/
INT
SxspExceptionFilter(
PEXCEPTION_POINTERS ExceptionPointers,
PCSTR Function
);
#define SXSP_EXCEPTION_FILTER() (::SxspExceptionFilter(GetExceptionInformation(), __FUNCTION__))
#define SXS_REPORT_SEH_EXCEPTION(string) \
__try \
{ \
if (::FusionpReportConditionAndBreak(NULL, "SXS.DLL: " __FUNCTION__ " - Unhandled exception caught: 0x%08lx", GetExceptionCode())) \
FUSION_DEBUG_BREAK(); \
} \
__except(EXCEPTION_EXECUTE_HANDLER) { }
class CCriticalSectionNoConstructor : public CRITICAL_SECTION
{
void operator=(const CCriticalSectionNoConstructor&); // deliberately not implemented
//CCriticalSectionNoConstructor(const CCriticalSectionNoConstructor&); // deliberately not implemented
public:
BOOL Construct();
BOOL ConstructWithSEH(PCSTR Function = "");
BOOL Destruct();
};
inline BOOL
CCriticalSectionNoConstructor::Construct()
{
::InitializeCriticalSection(this);
return TRUE;
}
inline BOOL
CCriticalSectionNoConstructor::Destruct()
{
::DeleteCriticalSection(this);
return TRUE;
}
inline BOOL
CCriticalSectionNoConstructor::ConstructWithSEH(
PCSTR /* Function */)
{
BOOL Result = FALSE;
DWORD dwWin32Error;
__try
{
if (!this->Construct())
goto Exit;
}
__except(SXSP_EXCEPTION_FILTER())
{
SXS_REPORT_SEH_EXCEPTION("");
#if FUSION_STATIC_NTDLL
dwWin32Error = ::RtlNtStatusToDosErrorNoTeb(GetExceptionCode());
#else
dwWin32Error = ERROR_OUTOFMEMORY;
#endif
::FusionpSetLastWin32Error(dwWin32Error);
goto Exit;
}
Result = TRUE;
Exit:
return Result;
}
class CSxsLockCriticalSection
{
public:
CSxsLockCriticalSection(CRITICAL_SECTION &rcs) : m_rcs(rcs), m_fIsLocked(false) { }
BOOL Lock();
BOOL TryLock();
BOOL LockWithSEH();
~CSxsLockCriticalSection() { if (m_fIsLocked) { CSxsPreserveLastError ple; ::LeaveCriticalSection(&m_rcs); ple.Restore(); } }
BOOL Unlock();
protected:
CRITICAL_SECTION &m_rcs;
bool m_fIsLocked;
private:
void operator=(const CSxsLockCriticalSection&);
CSxsLockCriticalSection(const CSxsLockCriticalSection&);
};
inline
BOOL
CSxsLockCriticalSection::Lock()
{
BOOL fSuccess = FALSE;
FN_TRACE_WIN32(fSuccess);
INTERNAL_ERROR_CHECK(!m_fIsLocked);
::EnterCriticalSection(&m_rcs);
m_fIsLocked = true;
fSuccess = TRUE;
Exit:
return fSuccess;
}
inline
BOOL
CSxsLockCriticalSection::LockWithSEH()
{
BOOL fSuccess = FALSE;
DWORD dwWin32Error;
// We can't use the spiffy macros in the same frame as a __try block.
ASSERT_NTC(!m_fIsLocked);
if (m_fIsLocked)
{
::FusionpSetLastWin32Error(ERROR_INTERNAL_ERROR);
goto Exit;
}
__try
{
if (!this->Lock())
goto Exit;
m_fIsLocked = true;
}
__except(SXSP_EXCEPTION_FILTER())
{
SXS_REPORT_SEH_EXCEPTION("");
#if FUSION_STATIC_NTDLL
dwWin32Error = ::RtlNtStatusToDosErrorNoTeb(GetExceptionCode());
#else
dwWin32Error = ERROR_OUTOFMEMORY;
#endif
::FusionpSetLastWin32Error(dwWin32Error);
goto Exit;
}
fSuccess = TRUE;
Exit:
return fSuccess;
}
inline
BOOL
CSxsLockCriticalSection::TryLock()
{
BOOL fSuccess = FALSE;
FN_TRACE_WIN32(fSuccess);
IFW32FALSE_ORIGINATE_AND_EXIT(::TryEnterCriticalSection(&m_rcs));
m_fIsLocked = true;
fSuccess = TRUE;
Exit:
return fSuccess;
}
inline
BOOL
CSxsLockCriticalSection::Unlock()
{
BOOL fSuccess = FALSE;
FN_TRACE_WIN32(fSuccess);
INTERNAL_ERROR_CHECK(m_fIsLocked);
::LeaveCriticalSection(&m_rcs);
m_fIsLocked = false;
fSuccess = TRUE;
Exit:
return fSuccess;
}
#endif // !defined(_FUSION_INC_SXSEXCEPTIONHANDLING_H_INCLUDED_)