diff options
Diffstat (limited to 'bridges')
-rw-r--r-- | bridges/source/cpp_uno/msvc_win32_x86-64/except.cxx | 514 |
1 files changed, 331 insertions, 183 deletions
diff --git a/bridges/source/cpp_uno/msvc_win32_x86-64/except.cxx b/bridges/source/cpp_uno/msvc_win32_x86-64/except.cxx index 03e9dee50ff0..df724232cfaf 100644 --- a/bridges/source/cpp_uno/msvc_win32_x86-64/except.cxx +++ b/bridges/source/cpp_uno/msvc_win32_x86-64/except.cxx @@ -26,6 +26,150 @@ * ************************************************************************/ +// 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 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 + } + +#endif // 0 + // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_bridges.hxx" @@ -181,202 +325,185 @@ RTTInfos::~RTTInfos() throw () } } -struct ObjectFunction -{ - char somecode[12]; - typelib_TypeDescription * _pTypeDescr; // type of object - - inline static void * operator new ( size_t nSize ); - inline static void operator delete ( void * pMem ); - - ObjectFunction( typelib_TypeDescription * pTypeDescr, void * fpFunc ) throw (); - ~ObjectFunction() throw (); -}; - -inline void * ObjectFunction::operator new( - size_t nSize ) -{ - void * pMem = rtl_allocateMemory( nSize ); - if (pMem != 0) - { - DWORD old_protect; -#if OSL_DEBUG_LEVEL > 0 - BOOL success = -#endif - VirtualProtect( pMem, nSize, PAGE_EXECUTE_READWRITE, &old_protect ); - OSL_ENSURE( success, "VirtualProtect() failed!" ); - } - return pMem; -} - -inline void ObjectFunction::operator delete( - void * pMem ) -{ - rtl_freeMemory( pMem ); -} - -ObjectFunction::ObjectFunction( - typelib_TypeDescription * pTypeDescr, - void * fpFunc ) throw () - : _pTypeDescr( pTypeDescr ) -{ - ::typelib_typedescription_acquire( _pTypeDescr ); - - unsigned char * pCode = (unsigned char *)somecode; - // a must be! - OSL_ENSURE( (void *)this == (void *)pCode, "### unexpected!" ); - - // push ObjectFunction this - *pCode++ = 0x68; - *(void **)pCode = this; - pCode += sizeof(void *); - // jmp rel64 fpFunc - *pCode++ = 0xe9; - *(sal_Int64 *)pCode = ((unsigned char *)fpFunc) - pCode - sizeof(sal_Int64); -} - -ObjectFunction::~ObjectFunction() throw () -{ - ::typelib_typedescription_release( _pTypeDescr ); -} - - -void * __cdecl __copyConstruct( +void * __cdecl copyConstruct( void * pExcThis, void * pSource, - ObjectFunction * pThis ) - throw () + typelib_TypeDescription * pTD ) throw () { - ::uno_copyData( pExcThis, pSource, pThis->_pTypeDescr, cpp_acquire ); + ::uno_copyData( pExcThis, pSource, pTD, cpp_acquire ); return pExcThis; } -void * __cdecl __destruct( +void * __cdecl destruct( void * pExcThis, - ObjectFunction * pThis ) - throw () + typelib_TypeDescription * pTD ) throw () { - ::uno_destructData( pExcThis, pThis->_pTypeDescr, cpp_release ); + ::uno_destructData( pExcThis, pTD, cpp_release ); return pExcThis; } -#if 0 - -// These are machine code snippets in asmbits.asm +const int codeSnippetSize = 40; -extern void *copyConstruct; -extern void *destruct; - -#else - -static void whatthefuck_copyctor(sal_Int64 i, ...) +void GenerateConstructorTrampoline( + sal_uChar * pCode, + typelib_TypeDescription * pTD ) throw () { - MessageBoxA (NULL, "Shit!", "whatthefuck_copyctor in except.cxx", MB_OK); + // push typelib_TypeDescription pTD + *pCode++ = 0x68; + *(void **)pCode = pTD; + pCode += sizeof(void *); + // jmp rel64 fpFunc + *pCode++ = 0xe9; + *(sal_Int64 *)pCode = (sal_uChar *)©Construct - pCode - sizeof(sal_Int64); } -static void whatthefuck_dtor(sal_Int64 i, ...) +void GenerateDestructorTrampoline( + sal_uChar * pCode, + typelib_TypeDescription * pTD ) throw () { - MessageBoxA (NULL, "Shit!", "whatthefuck_dtor in except.cxx", MB_OK); + // mov rdx, pTD + *pCode++ = 0x68; + *(void **)pCode = pTD; + pCode += sizeof(void *); + // jmp rel64 fpFunc + *pCode++ = 0xe9; + *(sal_Int64 *)pCode = (sal_uChar *)destruct - pCode - sizeof(sal_Int64); } -#endif +// This looks like it is the struct catchabletype above struct ExceptionType { - sal_Int32 _n0; - type_info * _pTypeInfo; - sal_Int32 _n1, _n2, _n3, _n4; - ObjectFunction * _pCopyCtor; - sal_Int32 _n5; - - inline ExceptionType( typelib_TypeDescription * pTypeDescr ) throw () + 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( pTypeDescr->nSize ) -#if 0 - , _pCopyCtor( new ObjectFunction( pTypeDescr, copyConstruct ) ) -#else - , _pCopyCtor( (ObjectFunction*) whatthefuck_copyctor ) -#endif - , _n5( 0 ) - { _pTypeInfo = mscx_getRTTI( pTypeDescr->pTypeName ); } + , _n4( pTD->nSize ) + { + _pTypeInfo = (sal_uInt32) ((sal_uInt64) mscx_getRTTI( pTD->pTypeName ) - pCodeBase); + GenerateConstructorTrampoline( pCode, pTD ); + _pCopyCtor = (sal_uInt32) ((sal_uInt64) pCode - pCodeBase); + } inline ~ExceptionType() throw () - { delete _pCopyCtor; } + { + } }; +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; - ObjectFunction * _pDtor; + sal_uInt32 _pDtor; sal_Int32 _n2; - void * _types; - sal_Int32 _n3, _n4; + sal_uInt32 _types; + + // Additional fields + typelib_TypeDescription * _pTD; + sal_uChar * _code; + sal_uInt64 _codeBase; + + RaiseInfo( typelib_TypeDescription * pTD ) throw (); - RaiseInfo( typelib_TypeDescription * pTypeDescr ) throw (); ~RaiseInfo() throw (); }; -RaiseInfo::RaiseInfo( typelib_TypeDescription * pTypeDescr ) throw () +RaiseInfo::RaiseInfo( typelib_TypeDescription * pTD )throw () : _n0( 0 ) -#if 0 - , _pDtor( new ObjectFunction( pTypeDescr, destruct ) ) -#else - , _pDtor( (ObjectFunction*) whatthefuck_dtor ) -#endif , _n2( 0 ) - , _n3( 0 ) - , _n4( 0 ) + , _pTD( pTD ) { - typelib_CompoundTypeDescription * pCompTypeDescr; + typelib_CompoundTypeDescription * pCompTD; + + // Count how many trampolines we need + int codeSize = codeSnippetSize; - // info count - sal_Int32 nLen = 0; - for ( pCompTypeDescr = (typelib_CompoundTypeDescription*)pTypeDescr; - pCompTypeDescr; pCompTypeDescr = pCompTypeDescr->pBaseTypeDescription ) + // Info count + int nLen = 0; + for ( pCompTD = (typelib_CompoundTypeDescription*)pTD; + pCompTD; pCompTD = pCompTD->pBaseTypeDescription ) { ++nLen; + codeSize += codeSnippetSize; } - // info count accompanied by type info ptrs: type, base type, base base type, ... - _types = ::rtl_allocateMemory( sizeof(sal_Int64) + (sizeof(ExceptionType *) * nLen) ); - *(sal_Int64 *)_types = nLen; + 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 ); - ExceptionType ** ppTypes = (ExceptionType **)((sal_Int64 *)_types + 1); + GenerateDestructorTrampoline( pCode, pTD ); + _pDtor = (sal_Int32)((sal_uInt64)pCode - _codeBase); + pCode += codeSnippetSize; - sal_Int32 nPos = 0; - for ( pCompTypeDescr = (typelib_CompoundTypeDescription*)pTypeDescr; - pCompTypeDescr; pCompTypeDescr = pCompTypeDescr->pBaseTypeDescription ) + // 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( (typelib_TypeDescription *)pCompTypeDescr ); + ppTypes[nPos++] = + new ExceptionType( pCode, _codeBase, + (typelib_TypeDescription *)pCompTD ); + pCode += codeSnippetSize; } } RaiseInfo::~RaiseInfo() throw () { - ExceptionType ** ppTypes = (ExceptionType **)((sal_Int64 *)_types + 1); - for ( sal_Int32 nTypes = *(sal_Int64 *)_types; nTypes--; ) + sal_uInt32 * pTypes = + (sal_uInt32 *)(_codeBase + _types) + 1; + + for ( int nTypes = *(sal_uInt32 *)(_codeBase + _types); nTypes--; ) { - delete ppTypes[nTypes]; + delete (ExceptionType *) (_codeBase + pTypes[nTypes]); } - ::rtl_freeMemory( _types ); + ::rtl_freeMemory( (void*)(_codeBase +_types) ); + ::rtl_freeMemory( _code ); - delete _pDtor; + ::typelib_typedescription_release( _pTD ); } -class ExceptionInfos -{ - Mutex _aMutex; - t_string2PtrMap _allRaiseInfos; - -public: - static void * getRaiseInfo( typelib_TypeDescription * pTypeDescr ) throw (); - - ExceptionInfos() throw (); - ~ExceptionInfos() throw (); -}; - ExceptionInfos::ExceptionInfos() throw () { } @@ -394,8 +521,8 @@ ExceptionInfos::~ExceptionInfos() throw () delete (RaiseInfo *)iPos->second; } } -void * ExceptionInfos::getRaiseInfo( - typelib_TypeDescription * pTypeDescr ) throw () + +RaiseInfo * ExceptionInfos::getRaiseInfo( typelib_TypeDescription * pTD ) throw () { static ExceptionInfos * s_pInfos = 0; if (! s_pInfos) @@ -403,6 +530,10 @@ void * ExceptionInfos::getRaiseInfo( MutexGuard aGuard( Mutex::getGlobalMutex() ); if (! s_pInfos) { + SYSTEM_INFO systemInfo; + GetSystemInfo( &systemInfo ); + allocationGranularity = systemInfo.dwAllocationGranularity; + #ifdef LEAK_STATIC_DATA s_pInfos = new ExceptionInfos(); #else @@ -412,28 +543,29 @@ void * ExceptionInfos::getRaiseInfo( } } - OSL_ASSERT( pTypeDescr && - (pTypeDescr->eTypeClass == typelib_TypeClass_STRUCT || - pTypeDescr->eTypeClass == typelib_TypeClass_EXCEPTION) ); + OSL_ASSERT( pTD && + (pTD->eTypeClass == typelib_TypeClass_STRUCT || + pTD->eTypeClass == typelib_TypeClass_EXCEPTION) ); - void * pRaiseInfo; + RaiseInfo * pRaiseInfo; - OUString const & rTypeName = *reinterpret_cast< OUString * >( &pTypeDescr->pTypeName ); + 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( pTypeDescr ); - // put into map + pRaiseInfo = new RaiseInfo( pTD ); + + // Put into map pair< t_string2PtrMap::iterator, bool > insertion( - s_pInfos->_allRaiseInfos.insert( t_string2PtrMap::value_type( rTypeName, pRaiseInfo ) ) ); + s_pInfos->_allRaiseInfos.insert( t_string2PtrMap::value_type( rTypeName, (void *)pRaiseInfo ) ) ); OSL_ENSURE( insertion.second, "### raise info insertion failed?!" ); } else { - // reuse existing info - pRaiseInfo = iFind->second; + // Reuse existing info + pRaiseInfo = (RaiseInfo *)iFind->second; } return pRaiseInfo; @@ -464,24 +596,25 @@ void mscx_raiseException( 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 inling of + // thus this obj file will be compiled without opt, so no inlining of // ExceptionInfos::getRaiseInfo() // construct cpp exception object - typelib_TypeDescription * pTypeDescr = 0; - TYPELIB_DANGER_GET( &pTypeDescr, pUnoExc->pType ); + typelib_TypeDescription * pTD = NULL; + TYPELIB_DANGER_GET( &pTD, pUnoExc->pType ); - void * pCppExc = alloca( pTypeDescr->nSize ); - ::uno_copyAndConvertData( pCppExc, pUnoExc->pData, pTypeDescr, pUno2Cpp ); + void * pCppExc = alloca( pTD->nSize ); + ::uno_copyAndConvertData( pCppExc, pUnoExc->pData, pTD, pUno2Cpp ); - ULONG_PTR arFilterArgs[3]; + ULONG_PTR arFilterArgs[4]; arFilterArgs[0] = MSVC_magic_number; arFilterArgs[1] = (ULONG_PTR)pCppExc; - arFilterArgs[2] = (ULONG_PTR)ExceptionInfos::getRaiseInfo( pTypeDescr ); + arFilterArgs[2] = (ULONG_PTR)ExceptionInfos::getRaiseInfo( pTD ); + arFilterArgs[3] = ((RaiseInfo *)arFilterArgs[2])->_codeBase; - // destruct uno exception + // Destruct uno exception ::uno_any_destruct( pUnoExc, 0 ); - TYPELIB_DANGER_RELEASE( pTypeDescr ); + TYPELIB_DANGER_RELEASE( pTD ); // last point to release anything not affected by stack unwinding RaiseException( MSVC_ExceptionCode, EXCEPTION_NONCONTINUABLE, 3, arFilterArgs ); @@ -494,8 +627,10 @@ int mscx_filterCppException( { if (pPointers == 0) return EXCEPTION_CONTINUE_SEARCH; + EXCEPTION_RECORD * pRecord = pPointers->ExceptionRecord; - // handle only C++ exceptions: + + // Handle only C++ exceptions: if (pRecord == 0 || pRecord->ExceptionCode != MSVC_ExceptionCode) return EXCEPTION_CONTINUE_SEARCH; @@ -504,13 +639,13 @@ int mscx_filterCppException( if (rethrow && pRecord == pPointers->ExceptionRecord) { - // hack to get msvcrt internal _curexception field: + // 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 - // (->platform sdk), we have to code those offsets here. + // As long as we don't demand MSVCR source as build prerequisite, + // we have to code those offsets here. // - // crt\src\mtdll.h: + // MSVS9/crt/src/mtdll.h: // offsetof (_tiddata, _curexception) - // offsetof (_tiddata, _tpxcptinfoptrs): #if _MSC_VER < 1500 @@ -522,34 +657,47 @@ int mscx_filterCppException( #endif ); } - // rethrow: handle only C++ exceptions: + + // Rethrow: handle only C++ exceptions: if (pRecord == 0 || pRecord->ExceptionCode != MSVC_ExceptionCode) return EXCEPTION_CONTINUE_SEARCH; - if (pRecord->NumberParameters == 3 && -// pRecord->ExceptionInformation[ 0 ] == MSVC_magic_number && - pRecord->ExceptionInformation[ 1 ] != 0 && - pRecord->ExceptionInformation[ 2 ] != 0) + if (pRecord->NumberParameters == 4 && + pRecord->ExceptionInformation[0] == MSVC_magic_number && + pRecord->ExceptionInformation[1] != 0 && + pRecord->ExceptionInformation[2] != 0 && + pRecord->ExceptionInformation[3] != 0) { - void * types = reinterpret_cast< RaiseInfo * >( - pRecord->ExceptionInformation[ 2 ] )->_types; - if (types != 0 && *reinterpret_cast< DWORD * >( types ) > 0) // count + // 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) { - ExceptionType * pType = *reinterpret_cast< ExceptionType ** >( - reinterpret_cast< DWORD * >( types ) + 1 ); - if (pType != 0 && pType->_pTypeInfo != 0) + DWORD pType = *((DWORD *)types + 1); + if (pType != 0 && + ((ExceptionType *)(pRecord->ExceptionInformation[3]+pType))->_pTypeInfo != 0) { OUString aRTTIname( OStringToOUString( reinterpret_cast< __type_info * >( - pType->_pTypeInfo )->_m_d_name, + ((ExceptionType *)(pRecord->ExceptionInformation[3]+pType))->_pTypeInfo )->_m_d_name, RTL_TEXTENCODING_ASCII_US ) ); OUString aUNOname( toUNOname( aRTTIname ) ); - typelib_TypeDescription * pExcTypeDescr = 0; + typelib_TypeDescription * pExcTD = 0; typelib_typedescription_getByName( - &pExcTypeDescr, aUNOname.pData ); - if (pExcTypeDescr == 0) + &pExcTD, aUNOname.pData ); + if (pExcTD == NULL) { OUStringBuffer buf; buf.appendAscii( @@ -578,16 +726,16 @@ int mscx_filterCppException( // construct uno exception any uno_any_constructAndConvert( pUnoExc, (void *) pRecord->ExceptionInformation[1], - pExcTypeDescr, pCpp2Uno ); + pExcTD, pCpp2Uno ); #if _MSC_VER < 1400 // msvcr80.dll cleans up, different from former msvcrs if (! rethrow) { uno_destructData( (void *) pRecord->ExceptionInformation[1], - pExcTypeDescr, cpp_release ); + pExcTD, cpp_release ); } #endif - typelib_typedescription_release( pExcTypeDescr ); + typelib_typedescription_release( pExcTD ); } return EXCEPTION_EXECUTE_HANDLER; |