Files
libreoffice/bridges/source/cpp_uno/msvc_win32_x86-64/except.cxx
2011-09-09 17:46:39 +02:00

840 lines
26 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright 2000, 2010 Oracle and/or its affiliates.
*
* OpenOffice.org - a multi-platform office productivity suite
*
* This file is part of OpenOffice.org.
*
* OpenOffice.org is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3
* only, as published by the Free Software Foundation.
*
* OpenOffice.org is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License version 3 for more details
* (a copy is included in the LICENSE file that accompanied this code).
*
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with OpenOffice.org. If not, see
* <http://www.openoffice.org/license.html>
* for a copy of the LGPLv3 License.
*
************************************************************************/
// Interesting info can be found in:
// MSDN, obviously
// http://www.osronline.com/article.cfm?article=469
// ONTL, "Open NT Native Template Library", a C++ STL-like library
// that can be used even when writing Windows drivers. This is some
// quite badass code. The author has done impressive heavy spelunking
// of MSVCR structures. http://code.google.com/p/ontl/
// Geoff Chappell's pages:
// http://members.ozemail.com.au/~geoffch/samples/programming/msvc/language/index.html
// The below is from ONTL's ntl/nt/exception.hxx, cleaned up to keep just the _M_X64 parts:
#if 0
/* This information until the corresponding '#endif // 0' is covered
* by ONTL's license, which is said to be the "zlib/libgng license"
* below, which as far as I see is permissive enough to allow this
* information to be included here in this source file. Note that no
* actual code from ONTL below gets compiled into the object file.
*/
/*
* Copyright (c) 2011 <copyright holders> (The ONTL main
* developer(s) don't tell their real name(s) on the ONTL site.)
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*
*/
typedef uint32_t rva_t;
///\note the calling convention should not matter since this has no arguments
typedef void generic_function_t();
struct ptrtomember // _PMD
{
typedef __w64 int32_t mdiff_t;
mdiff_t member_offset;
mdiff_t vbtable_offset; // -1 if not a virtual base
mdiff_t vdisp_offset; // offset to the displacement value inside the vbtable
template<typename T>
T * operator()(T * const thisptr) const
{
uintptr_t tp = reinterpret_cast<uintptr_t>(thisptr);
uintptr_t ptr = tp + member_offset;
if ( vbtable_offset != -1 ) // !(vbtable_offset < 0)
{
ptr += *reinterpret_cast<mdiff_t*>( static_cast<intptr_t>(vdisp_offset + *reinterpret_cast<mdiff_t*>(tp + vbtable_offset)) )
+ vbtable_offset;
}
return reinterpret_cast<T*>(ptr);
}
};
struct eobject
{
typedef void (* dtor_ptr )(eobject*);
typedef void (* ctor_ptr )(eobject*, eobject*);
typedef void (* ctor_ptr2)(eobject*, eobject*, int);
};
struct catchabletype
{
/** is simple type */
uint32_t memmoveable : 1;
/** catchable as reference only */
uint32_t refonly : 1;
/** class with virtual base */
uint32_t hasvirtbase : 1;
/** offset to the type descriptor */
rva_t typeinfo;
/** catch type instance location within a thrown object */
ptrtomember thiscast;
/** size of the simple type or offset into buffer of \c this pointer for catch object */
uint32_t object_size;
union
{
rva_t copyctor;
rva_t copyctor2;
};
};
#pragma pack(push, 4)
struct catchabletypearray
{
uint32_t size;
rva_t type[1];
};
#pragma pack(pop)
#pragma pack(push, 4)
struct throwinfo
{
typedef exception_disposition __cdecl forwardcompathandler_t(...);
/* 0x00 */ uint32_t econst : 1;
/* 0x00 */ uint32_t evolatile : 1;
/* 0x00 */ uint32_t : 1;
/* 0x00 */ uint32_t e8 : 1;
/* 0x04 */ rva_t exception_dtor;
/* 0x08 */ rva_t forwardcompathandler;
/* 0x0C */ rva_t catchabletypearray; ///< types able to catch the exception.
};
#pragma pack(pop)
/// This type represents the catch clause
struct ehandler
{
// union { uint32_t adjectives; void * ptr; };
uint32_t isconst : 1;
uint32_t isvolatile : 1;
uint32_t isunaligned : 1;// guess it is not used on x86
uint32_t isreference : 1;
uint32_t :27;
uint32_t ishz : 1;
/** offset to the type descriptor of this catch object */
/*0x04*/ rva_t typeinfo; // dispType
/*0x08*/ int eobject_bpoffset; // dispCatchObj
/** offset to the catch clause funclet */
/*0x0C*/ rva_t handler; // dispOfHandler
/*0x10*/ uint32_t frame; // dispFrame
}
// ___BuildCatchObject
/// 15.3/16 When the exception-declaration specifies a class type, a copy
/// constructor is used to initialize either the object declared
/// in the exception-declaration or,
/// if the exception-declaration does not specify a name,
/// a temporary object of that type.
///\note This is the question may we optimize out the last case.
///\warning If the copy constructor throws an exception, std::unexpected would be called
void
constructcatchobject(
cxxregistration * cxxreg,
const ehandler * const catchblock,
catchabletype * const convertable,
const dispatcher_context* const dispatch
)
const
{
_EH_TRACE_ENTER();
// build helper
__try {
struct typeinfo_t { void* vtbl; void* spare; char name[1]; };
enum catchable_info { cidefault, cicomplex, civirtual } cinfo = cidefault;
const typeinfo_t* ti = catchblock->typeinfo ? dispatch->va<typeinfo_t*>(catchblock->typeinfo) : NULL;
if(ti && *ti->name && (catchblock->eobject_bpoffset || catchblock->ishz)){
eobject** objplace = catchblock->ishz
? reinterpret_cast<eobject**>(cxxreg)
: reinterpret_cast<eobject**>(catchblock->eobject_bpoffset + cxxreg->fp.FramePointers);
if(catchblock->isreference){
// just ref/pointer
*objplace = adjust_pointer(get_object(), convertable);
}else if(convertable->memmoveable){
// POD
std::memcpy(objplace, get_object(), convertable->object_size);
if(convertable->object_size == sizeof(void*) && *objplace)
*objplace = adjust_pointer((void*)*objplace, convertable);
}else{
// if copy ctor exists, call it; binary copy otherwise
if(convertable->copyctor){
cinfo = convertable->hasvirtbase ? civirtual : cicomplex;
}else{
std::memcpy(objplace, (const void*)adjust_pointer(get_object(), convertable), convertable->object_size);
}
}
}
// end of build helper
if(cinfo != cidefault){
eobject* objthis = catchblock->ishz
? reinterpret_cast<eobject*>(cxxreg)
: reinterpret_cast<eobject*>(catchblock->eobject_bpoffset + cxxreg->fp.FramePointers);
void* copyctor = thrown_va(convertable->copyctor);
eobject* copyarg = adjust_pointer(get_object(), convertable);
if(cinfo == cicomplex)
(eobject::ctor_ptr (copyctor))(objthis, copyarg);
else
(eobject::ctor_ptr2(copyctor))(objthis, copyarg, 1);
}
}
__except(cxxregistration::unwindfilter(static_cast<nt::ntstatus>(_exception_code())))
{
nt::exception::inconsistency();
}
_EH_TRACE_LEAVE();
}
#endif // 0
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_bridges.hxx"
#pragma warning( disable : 4237 )
#include <boost/unordered_map.hpp>
#include <sal/config.h>
#include <malloc.h>
#include <new.h>
#include <typeinfo.h>
#include <signal.h>
#include "rtl/alloc.h"
#include <rtl/instance.hxx>
#include "rtl/strbuf.hxx"
#include "rtl/ustrbuf.hxx"
#include "com/sun/star/uno/Any.hxx"
#include "mscx.hxx"
#pragma pack(push, 8)
using namespace ::com::sun::star::uno;
using namespace ::std;
using namespace ::osl;
using namespace ::rtl;
namespace CPPU_CURRENT_NAMESPACE
{
static inline OUString toUNOname(
OUString const & rRTTIname )
throw ()
{
OUStringBuffer aRet( 64 );
OUString aStr( rRTTIname.copy( 4, rRTTIname.getLength()-4-2 ) ); // filter .?AUzzz@yyy@xxx@@
sal_Int32 nPos = aStr.getLength();
while (nPos > 0)
{
sal_Int32 n = aStr.lastIndexOf( '@', nPos );
aRet.append( aStr.copy( n +1, nPos -n -1 ) );
if (n >= 0)
{
aRet.append( (sal_Unicode)'.' );
}
nPos = n;
}
return aRet.makeStringAndClear();
}
static inline OUString toRTTIname(
OUString const & rUNOname )
throw ()
{
OUStringBuffer aRet( 64 );
aRet.appendAscii( RTL_CONSTASCII_STRINGPARAM(".?AV") ); // class ".?AV"; struct ".?AU"
sal_Int32 nPos = rUNOname.getLength();
while (nPos > 0)
{
sal_Int32 n = rUNOname.lastIndexOf( '.', nPos );
aRet.append( rUNOname.copy( n +1, nPos -n -1 ) );
aRet.append( (sal_Unicode)'@' );
nPos = n;
}
aRet.append( (sal_Unicode)'@' );
return aRet.makeStringAndClear();
}
//RTTI simulation
typedef boost::unordered_map< OUString, void *, OUStringHash, equal_to< OUString > > t_string2PtrMap;
class RTTInfos
{
Mutex _aMutex;
t_string2PtrMap _allRTTI;
static OUString toRawName( OUString const & rUNOname ) throw ();
public:
type_info * getRTTI( OUString const & rUNOname ) throw ();
RTTInfos();
~RTTInfos();
};
class __type_info
{
friend type_info * RTTInfos::getRTTI( OUString const & ) throw ();
friend int mscx_filterCppException(
LPEXCEPTION_POINTERS, uno_Any *, uno_Mapping * );
public:
virtual ~__type_info() throw ();
inline __type_info( void * m_data, const char * m_d_name ) throw ()
: _m_data( m_data )
{ ::strcpy( _m_d_name, m_d_name ); } // #100211# - checked
private:
void * _m_data;
char _m_d_name[1];
};
__type_info::~__type_info() throw ()
{
}
type_info * RTTInfos::getRTTI( OUString const & rUNOname ) throw ()
{
// a must be
OSL_ENSURE( sizeof(__type_info) == sizeof(type_info), "### type info structure size differ!" );
MutexGuard aGuard( _aMutex );
t_string2PtrMap::const_iterator const iFind( _allRTTI.find( rUNOname ) );
// check if type is already available
if (iFind == _allRTTI.end())
{
// insert new type_info
OString aRawName( OUStringToOString( toRTTIname( rUNOname ), RTL_TEXTENCODING_ASCII_US ) );
__type_info * pRTTI = new( ::rtl_allocateMemory( sizeof(__type_info) + aRawName.getLength() ) )
__type_info( NULL, aRawName.getStr() );
// put into map
pair< t_string2PtrMap::iterator, bool > insertion(
_allRTTI.insert( t_string2PtrMap::value_type( rUNOname, pRTTI ) ) );
OSL_ENSURE( insertion.second, "### rtti insertion failed?!" );
return (type_info *)pRTTI;
}
else
{
return (type_info *)iFind->second;
}
}
RTTInfos::RTTInfos() throw ()
{
}
RTTInfos::~RTTInfos() throw ()
{
#if OSL_DEBUG_LEVEL > 1
OSL_TRACE( "> freeing generated RTTI infos... <\n" );
#endif
MutexGuard aGuard( _aMutex );
for ( t_string2PtrMap::const_iterator iPos( _allRTTI.begin() );
iPos != _allRTTI.end(); ++iPos )
{
__type_info * pType = (__type_info *)iPos->second;
pType->~__type_info(); // obsolete, but good style...
::rtl_freeMemory( pType );
}
}
void * __cdecl copyConstruct(
void * pExcThis,
void * pSource,
typelib_TypeDescription * pTD ) throw ()
{
::uno_copyData( pExcThis, pSource, pTD, cpp_acquire );
return pExcThis;
}
void * __cdecl destruct(
void * pExcThis,
typelib_TypeDescription * pTD ) throw ()
{
::uno_destructData( pExcThis, pTD, cpp_release );
return pExcThis;
}
const int codeSnippetSize = 40;
void GenerateConstructorTrampoline(
unsigned char * code,
typelib_TypeDescription * pTD ) throw ()
{
unsigned char *p = code;
// mov r8, pTD
*p++ = 0x49; *p++ = 0xB8;
*((void **)p) = pTD; p += 8;
// mov r11, copyConstruct
*p++ = 0x49; *p++ = 0xBB;
*((void **)p) = &copyConstruct; p += 8;
// jmp r11
*p++ = 0x41; *p++ = 0xFF; *p++ = 0xE3;
OSL_ASSERT( p < code + codeSnippetSize );
}
void GenerateDestructorTrampoline(
unsigned char * code,
typelib_TypeDescription * pTD ) throw ()
{
unsigned char *p = code;
// mov rdx, pTD
*p++ = 0x48; *p++ = 0xBA;
*((void **)p) = pTD; p += 8;
// mov r11, destruct
*p++ = 0x49; *p++ = 0xBB;
*((void **)p) = &destruct; p += 8;
// jmp r11
*p++ = 0x41; *p++ = 0xFF; *p++ = 0xE3;
OSL_ASSERT( p < code + codeSnippetSize );
}
// This looks like it is the struct catchabletype above
struct ExceptionType
{
sal_Int32 _n0; // flags
sal_uInt32 _pTypeInfo; // typeinfo
sal_Int32 _n1, _n2, _n3; // thiscast
sal_Int32 _n4; // object_size
sal_uInt32 _pCopyCtor; // copyctor
inline ExceptionType(
sal_uChar * pCode,
sal_uInt64 pCodeBase,
typelib_TypeDescription * pTD ) throw ()
: _n0( 0 )
, _n1( 0 )
, _n2( -1 )
, _n3( 0 )
, _n4( pTD->nSize )
{
// As _n0 is always initialized to zero, that means the
// hasvirtbase flag (see the ONTL catchabletype struct) is
// off, and thus the copyctor is of the ctor_ptr kind.
_pTypeInfo = (sal_uInt32) ((sal_uInt64) mscx_getRTTI( pTD->pTypeName ) - pCodeBase);
GenerateConstructorTrampoline( pCode, pTD );
_pCopyCtor = (sal_uInt32) ((sal_uInt64) pCode - pCodeBase);
}
inline ~ExceptionType() throw ()
{
}
};
struct RaiseInfo;
class ExceptionInfos
{
Mutex _aMutex;
t_string2PtrMap _allRaiseInfos;
public:
static RaiseInfo * getRaiseInfo( typelib_TypeDescription * pTD ) throw ();
static DWORD allocationGranularity;
ExceptionInfos() throw ();
~ExceptionInfos() throw ();
};
DWORD ExceptionInfos::allocationGranularity = 0;
// This corresponds to the struct throwinfo described above.
struct RaiseInfo
{
sal_Int32 _n0;
sal_uInt32 _pDtor;
sal_Int32 _n2;
sal_uInt32 _types;
// Additional fields
typelib_TypeDescription * _pTD;
sal_uChar * _code;
sal_uInt64 _codeBase;
RaiseInfo( typelib_TypeDescription * pTD ) throw ();
~RaiseInfo() throw ();
};
RaiseInfo::RaiseInfo( typelib_TypeDescription * pTD )throw ()
: _n0( 0 )
, _n2( 0 )
, _pTD( pTD )
{
typelib_CompoundTypeDescription * pCompTD;
// Count how many trampolines we need
int codeSize = codeSnippetSize;
// Info count
int nLen = 0;
for ( pCompTD = (typelib_CompoundTypeDescription*)pTD;
pCompTD; pCompTD = pCompTD->pBaseTypeDescription )
{
++nLen;
codeSize += codeSnippetSize;
}
sal_uChar * pCode = _code = (sal_uChar *)::rtl_allocateMemory( codeSize );
_codeBase = (sal_uInt64)pCode & ~(ExceptionInfos::allocationGranularity-1);
DWORD old_protect;
#if OSL_DEBUG_LEVEL > 0
BOOL success =
#endif
VirtualProtect( pCode, codeSize, PAGE_EXECUTE_READWRITE, &old_protect );
OSL_ENSURE( success, "VirtualProtect() failed!" );
::typelib_typedescription_acquire( pTD );
GenerateDestructorTrampoline( pCode, pTD );
_pDtor = (sal_Int32)((sal_uInt64)pCode - _codeBase);
pCode += codeSnippetSize;
// Info count accompanied by type info ptrs: type, base type, base base type, ...
_types = (sal_Int32)((sal_uInt64)::rtl_allocateMemory( 4 + 4* nLen) - _codeBase);
*(sal_Int32 *)_types = nLen;
ExceptionType ** ppTypes = (ExceptionType **)((sal_Int32 *)_types + 1);
int nPos = 0;
for ( pCompTD = (typelib_CompoundTypeDescription*)pTD;
pCompTD; pCompTD = pCompTD->pBaseTypeDescription )
{
ppTypes[nPos++] =
new ExceptionType( pCode, _codeBase,
(typelib_TypeDescription *)pCompTD );
pCode += codeSnippetSize;
}
}
RaiseInfo::~RaiseInfo() throw ()
{
sal_uInt32 * pTypes =
(sal_uInt32 *)(_codeBase + _types) + 1;
for ( int nTypes = *(sal_uInt32 *)(_codeBase + _types); nTypes--; )
{
delete (ExceptionType *) (_codeBase + pTypes[nTypes]);
}
::rtl_freeMemory( (void*)(_codeBase +_types) );
::rtl_freeMemory( _code );
::typelib_typedescription_release( _pTD );
}
ExceptionInfos::ExceptionInfos() throw ()
{
}
ExceptionInfos::~ExceptionInfos() throw ()
{
#if OSL_DEBUG_LEVEL > 1
OSL_TRACE( "> freeing exception infos... <\n" );
#endif
MutexGuard aGuard( _aMutex );
for ( t_string2PtrMap::const_iterator iPos( _allRaiseInfos.begin() );
iPos != _allRaiseInfos.end(); ++iPos )
{
delete (RaiseInfo *)iPos->second;
}
}
RaiseInfo * ExceptionInfos::getRaiseInfo( typelib_TypeDescription * pTD ) throw ()
{
static ExceptionInfos * s_pInfos = 0;
if (! s_pInfos)
{
MutexGuard aGuard( Mutex::getGlobalMutex() );
if (! s_pInfos)
{
SYSTEM_INFO systemInfo;
GetSystemInfo( &systemInfo );
allocationGranularity = systemInfo.dwAllocationGranularity;
#ifdef LEAK_STATIC_DATA
s_pInfos = new ExceptionInfos();
#else
static ExceptionInfos s_allExceptionInfos;
s_pInfos = &s_allExceptionInfos;
#endif
}
}
OSL_ASSERT( pTD &&
(pTD->eTypeClass == typelib_TypeClass_STRUCT ||
pTD->eTypeClass == typelib_TypeClass_EXCEPTION) );
RaiseInfo * pRaiseInfo;
OUString const & rTypeName = *reinterpret_cast< OUString * >( &pTD->pTypeName );
MutexGuard aGuard( s_pInfos->_aMutex );
t_string2PtrMap::const_iterator const iFind(
s_pInfos->_allRaiseInfos.find( rTypeName ) );
if (iFind == s_pInfos->_allRaiseInfos.end())
{
pRaiseInfo = new RaiseInfo( pTD );
// Put into map
pair< t_string2PtrMap::iterator, bool > insertion(
s_pInfos->_allRaiseInfos.insert( t_string2PtrMap::value_type( rTypeName, (void *)pRaiseInfo ) ) );
OSL_ENSURE( insertion.second, "### raise info insertion failed?!" );
}
else
{
// Reuse existing info
pRaiseInfo = (RaiseInfo *)iFind->second;
}
return pRaiseInfo;
}
struct RTTISingleton: public rtl::Static< RTTInfos, RTTISingleton > {};
type_info * mscx_getRTTI(
OUString const & rUNOname )
{
return RTTISingleton::get().getRTTI( rUNOname );
}
void mscx_raiseException(
uno_Any * pUnoExc,
uno_Mapping * pUno2Cpp )
{
// no ctor/dtor in here: this leads to dtors called twice upon RaiseException()!
// thus this obj file will be compiled without opt, so no inlining of
// ExceptionInfos::getRaiseInfo()
// construct cpp exception object
typelib_TypeDescription * pTD = NULL;
TYPELIB_DANGER_GET( &pTD, pUnoExc->pType );
void * pCppExc = alloca( pTD->nSize );
::uno_copyAndConvertData( pCppExc, pUnoExc->pData, pTD, pUno2Cpp );
ULONG_PTR arFilterArgs[4];
arFilterArgs[0] = MSVC_magic_number;
arFilterArgs[1] = (ULONG_PTR)pCppExc;
arFilterArgs[2] = (ULONG_PTR)ExceptionInfos::getRaiseInfo( pTD );
arFilterArgs[3] = ((RaiseInfo *)arFilterArgs[2])->_codeBase;
// Destruct uno exception
::uno_any_destruct( pUnoExc, 0 );
TYPELIB_DANGER_RELEASE( pTD );
// last point to release anything not affected by stack unwinding
RaiseException( MSVC_ExceptionCode, EXCEPTION_NONCONTINUABLE, 3, arFilterArgs );
}
int mscx_filterCppException(
EXCEPTION_POINTERS * pPointers,
uno_Any * pUnoExc,
uno_Mapping * pCpp2Uno )
{
if (pPointers == 0)
return EXCEPTION_CONTINUE_SEARCH;
EXCEPTION_RECORD * pRecord = pPointers->ExceptionRecord;
// Handle only C++ exceptions:
if (pRecord == 0 || pRecord->ExceptionCode != MSVC_ExceptionCode)
return EXCEPTION_CONTINUE_SEARCH;
bool rethrow = __CxxDetectRethrow( &pRecord );
OSL_ASSERT( pRecord == pPointers->ExceptionRecord );
if (rethrow && pRecord == pPointers->ExceptionRecord)
{
// Hack to get msvcrt internal _curexception field:
pRecord = *reinterpret_cast< EXCEPTION_RECORD ** >(
reinterpret_cast< char * >( __pxcptinfoptrs() ) +
// As long as we don't demand MSVCR source as build prerequisite,
// we have to code those offsets here.
//
// MSVS9/crt/src/mtdll.h:
// offsetof (_tiddata, _curexception) -
// offsetof (_tiddata, _tpxcptinfoptrs):
#if _MSC_VER < 1500
error, this compiler version is not supported
#elif _MSC_VER < 1600
0x48 // msvcr90.dll
#else
error, please find value for this compiler version
#endif
);
}
// Rethrow: handle only C++ exceptions:
if (pRecord == 0 || pRecord->ExceptionCode != MSVC_ExceptionCode)
return EXCEPTION_CONTINUE_SEARCH;
if (pRecord->NumberParameters == 4 &&
pRecord->ExceptionInformation[0] == MSVC_magic_number &&
pRecord->ExceptionInformation[1] != 0 &&
pRecord->ExceptionInformation[2] != 0 &&
pRecord->ExceptionInformation[3] != 0)
{
// ExceptionInformation[1] is the address of the thrown object
// (or the address of a pointer to it, in most cases when it
// is a C++ class, obviously).
// [2] is the throwinfo pointer
// [3] is the image base address which is added the 32-bit
// rva_t fields in throwinfo to get actual 64-bit addresses
void * types =
(void *) (pRecord->ExceptionInformation[3] +
((RaiseInfo *)pRecord->ExceptionInformation[2])->_types);
if (types != 0 && *(DWORD *)types > 0)
{
DWORD pType = *((DWORD *)types + 1);
if (pType != 0 &&
((ExceptionType *)(pRecord->ExceptionInformation[3]+pType))->_pTypeInfo != 0)
{
OUString aRTTIname(
OStringToOUString(
reinterpret_cast< __type_info * >(
((ExceptionType *)(pRecord->ExceptionInformation[3]+pType))->_pTypeInfo )->_m_d_name,
RTL_TEXTENCODING_ASCII_US ) );
OUString aUNOname( toUNOname( aRTTIname ) );
typelib_TypeDescription * pExcTD = 0;
typelib_typedescription_getByName(
&pExcTD, aUNOname.pData );
if (pExcTD == NULL)
{
OUStringBuffer buf;
buf.appendAscii(
RTL_CONSTASCII_STRINGPARAM(
"[mscx_uno bridge error] UNO type of "
"C++ exception unknown: \"") );
buf.append( aUNOname );
buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(
"\", RTTI-name=\"") );
buf.append( aRTTIname );
buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\"!") );
RuntimeException exc(
buf.makeStringAndClear(), Reference< XInterface >() );
uno_type_any_constructAndConvert(
pUnoExc, &exc,
::getCppuType( &exc ).getTypeLibType(), pCpp2Uno );
#if _MSC_VER < 1400 // msvcr80.dll cleans up, different from former msvcrs
// if (! rethrow):
// though this unknown exception leaks now, no user-defined
// exception is ever thrown thru the binary C-UNO dispatcher
// call stack.
#endif
}
else
{
// construct uno exception any
uno_any_constructAndConvert(
pUnoExc, (void *) pRecord->ExceptionInformation[1],
pExcTD, pCpp2Uno );
#if _MSC_VER < 1400 // msvcr80.dll cleans up, different from former msvcrs
if (! rethrow)
{
uno_destructData(
(void *) pRecord->ExceptionInformation[1],
pExcTD, cpp_release );
}
#endif
typelib_typedescription_release( pExcTD );
}
return EXCEPTION_EXECUTE_HANDLER;
}
}
}
// though this unknown exception leaks now, no user-defined exception
// is ever thrown thru the binary C-UNO dispatcher call stack.
RuntimeException exc(
OUString( RTL_CONSTASCII_USTRINGPARAM(
"[mscx_uno bridge error] unexpected "
"C++ exception occurred!") ),
Reference< XInterface >() );
uno_type_any_constructAndConvert(
pUnoExc, &exc, ::getCppuType( &exc ).getTypeLibType(), pCpp2Uno );
return EXCEPTION_EXECUTE_HANDLER;
}
}
#pragma pack(pop)
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */