Bump for 3.6-28
[LibreOffice.git] / bridges / source / cpp_uno / msvc_win32_x86-64 / except.cxx
blobe7ce54915fd052707cb20756c59512ccc66e1c39
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 // Interesting info can be found in:
31 // MSDN, obviously
33 // http://www.osronline.com/article.cfm?article=469
35 // ONTL, "Open NT Native Template Library", a C++ STL-like library
36 // that can be used even when writing Windows drivers. This is some
37 // quite badass code. The author has done impressive heavy spelunking
38 // of MSVCR structures. http://code.google.com/p/ontl/
40 // Geoff Chappell's pages:
41 // http://www.geoffchappell.com/studies/msvc/language/index.htm
43 // The below is from ONTL's ntl/nt/exception.hxx, cleaned up to keep just the _M_X64 parts:
45 #if 0
47 /* This information until the corresponding '#endif // 0' is covered
48 * by ONTL's license, which is said to be the "zlib/libgng license"
49 * below, which as far as I see is permissive enough to allow this
50 * information to be included here in this source file. Note that no
51 * actual code from ONTL below gets compiled into the object file.
55 * Copyright (c) 2011 <copyright holders> (The ONTL main
56 * developer(s) don't tell their real name(s) on the ONTL site.)
58 * This software is provided 'as-is', without any express or implied
59 * warranty. In no event will the authors be held liable for any damages
60 * arising from the use of this software.
62 * Permission is granted to anyone to use this software for any purpose,
63 * including commercial applications, and to alter it and redistribute it
64 * freely, subject to the following restrictions:
66 * 1. The origin of this software must not be misrepresented; you must not
67 * claim that you wrote the original software. If you use this software
68 * in a product, an acknowledgment in the product documentation would be
69 * appreciated but is not required.
71 * 2. Altered source versions must be plainly marked as such, and must not be
72 * misrepresented as being the original software.
74 * 3. This notice may not be removed or altered from any source
75 * distribution.
79 typedef uint32_t rva_t;
81 ///\note the calling convention should not matter since this has no arguments
82 typedef void generic_function_t();
84 struct ptrtomember // _PMD
86 typedef __w64 int32_t mdiff_t;
87 mdiff_t member_offset;
88 mdiff_t vbtable_offset; // -1 if not a virtual base
89 mdiff_t vdisp_offset; // offset to the displacement value inside the vbtable
91 template<typename T>
92 T * operator()(T * const thisptr) const
94 uintptr_t tp = reinterpret_cast<uintptr_t>(thisptr);
95 uintptr_t ptr = tp + member_offset;
96 if ( vbtable_offset != -1 ) // !(vbtable_offset < 0)
98 ptr += *reinterpret_cast<mdiff_t*>( static_cast<intptr_t>(vdisp_offset + *reinterpret_cast<mdiff_t*>(tp + vbtable_offset)) )
99 + vbtable_offset;
101 return reinterpret_cast<T*>(ptr);
105 struct eobject
107 typedef void (* dtor_ptr )(eobject*);
108 typedef void (* ctor_ptr )(eobject*, eobject*);
109 typedef void (* ctor_ptr2)(eobject*, eobject*, int);
112 struct catchabletype
114 /** is simple type */
115 uint32_t memmoveable : 1;
116 /** catchable as reference only */
117 uint32_t refonly : 1;
118 /** class with virtual base */
119 uint32_t hasvirtbase : 1;
120 /** offset to the type descriptor */
121 rva_t typeinfo;
123 /** catch type instance location within a thrown object */
124 ptrtomember thiscast;
125 /** size of the simple type or offset into buffer of \c this pointer for catch object */
126 uint32_t object_size;
128 union
130 rva_t copyctor;
131 rva_t copyctor2;
135 #pragma pack(push, 4)
136 struct catchabletypearray
138 uint32_t size;
139 rva_t type[1];
141 #pragma pack(pop)
143 #pragma pack(push, 4)
144 struct throwinfo
146 typedef exception_disposition __cdecl forwardcompathandler_t(...);
148 /* 0x00 */ uint32_t econst : 1;
149 /* 0x00 */ uint32_t evolatile : 1;
150 /* 0x00 */ uint32_t : 1;
151 /* 0x00 */ uint32_t e8 : 1;
152 /* 0x04 */ rva_t exception_dtor;
153 /* 0x08 */ rva_t forwardcompathandler;
154 /* 0x0C */ rva_t catchabletypearray; ///< types able to catch the exception.
156 #pragma pack(pop)
158 /// This type represents the catch clause
159 struct ehandler
161 // union { uint32_t adjectives; void * ptr; };
162 uint32_t isconst : 1;
163 uint32_t isvolatile : 1;
164 uint32_t isunaligned : 1;// guess it is not used on x86
165 uint32_t isreference : 1;
167 uint32_t :27;
168 uint32_t ishz : 1;
170 /** offset to the type descriptor of this catch object */
171 /*0x04*/ rva_t typeinfo; // dispType
172 /*0x08*/ int eobject_bpoffset; // dispCatchObj
173 /** offset to the catch clause funclet */
174 /*0x0C*/ rva_t handler; // dispOfHandler
175 /*0x10*/ uint32_t frame; // dispFrame
178 // ___BuildCatchObject
179 /// 15.3/16 When the exception-declaration specifies a class type, a copy
180 /// constructor is used to initialize either the object declared
181 /// in the exception-declaration or,
182 /// if the exception-declaration does not specify a name,
183 /// a temporary object of that type.
184 ///\note This is the question may we optimize out the last case.
185 ///\warning If the copy constructor throws an exception, std::unexpected would be called
186 void
187 constructcatchobject(
188 cxxregistration * cxxreg,
189 const ehandler * const catchblock,
190 catchabletype * const convertable,
191 const dispatcher_context* const dispatch
193 const
195 _EH_TRACE_ENTER();
196 // build helper
197 __try {
198 struct typeinfo_t { void* vtbl; void* spare; char name[1]; };
199 enum catchable_info { cidefault, cicomplex, civirtual } cinfo = cidefault;
201 const typeinfo_t* ti = catchblock->typeinfo ? dispatch->va<typeinfo_t*>(catchblock->typeinfo) : NULL;
202 if(ti && *ti->name && (catchblock->eobject_bpoffset || catchblock->ishz)){
203 eobject** objplace = catchblock->ishz
204 ? reinterpret_cast<eobject**>(cxxreg)
205 : reinterpret_cast<eobject**>(catchblock->eobject_bpoffset + cxxreg->fp.FramePointers);
206 if(catchblock->isreference){
207 // just ref/pointer
208 *objplace = adjust_pointer(get_object(), convertable);
209 }else if(convertable->memmoveable){
210 // POD
211 std::memcpy(objplace, get_object(), convertable->object_size);
212 if(convertable->object_size == sizeof(void*) && *objplace)
213 *objplace = adjust_pointer((void*)*objplace, convertable);
214 }else{
215 // if copy ctor exists, call it; binary copy otherwise
216 if(convertable->copyctor){
217 cinfo = convertable->hasvirtbase ? civirtual : cicomplex;
218 }else{
219 std::memcpy(objplace, (const void*)adjust_pointer(get_object(), convertable), convertable->object_size);
223 // end of build helper
224 if(cinfo != cidefault){
225 eobject* objthis = catchblock->ishz
226 ? reinterpret_cast<eobject*>(cxxreg)
227 : reinterpret_cast<eobject*>(catchblock->eobject_bpoffset + cxxreg->fp.FramePointers);
228 void* copyctor = thrown_va(convertable->copyctor);
229 eobject* copyarg = adjust_pointer(get_object(), convertable);
230 if(cinfo == cicomplex)
231 (eobject::ctor_ptr (copyctor))(objthis, copyarg);
232 else
233 (eobject::ctor_ptr2(copyctor))(objthis, copyarg, 1);
236 __except(cxxregistration::unwindfilter(static_cast<nt::ntstatus>(_exception_code())))
238 nt::exception::inconsistency();
240 _EH_TRACE_LEAVE();
243 #endif // 0
246 #pragma warning( disable : 4237 )
247 #include <boost/unordered_map.hpp>
248 #include <sal/config.h>
249 #include <malloc.h>
250 #include <new.h>
251 #include <typeinfo.h>
252 #include <signal.h>
254 #include "rtl/alloc.h"
255 #include <rtl/instance.hxx>
256 #include "rtl/strbuf.hxx"
257 #include "rtl/ustrbuf.hxx"
259 #include "com/sun/star/uno/Any.hxx"
261 #include "mscx.hxx"
263 #pragma pack(push, 8)
265 using namespace ::com::sun::star::uno;
266 using namespace ::std;
267 using namespace ::osl;
268 using namespace ::rtl;
270 namespace CPPU_CURRENT_NAMESPACE
273 static inline OUString toUNOname(
274 OUString const & rRTTIname )
275 throw ()
277 OUStringBuffer aRet( 64 );
278 OUString aStr( rRTTIname.copy( 4, rRTTIname.getLength()-4-2 ) ); // filter .?AUzzz@yyy@xxx@@
279 sal_Int32 nPos = aStr.getLength();
280 while (nPos > 0)
282 sal_Int32 n = aStr.lastIndexOf( '@', nPos );
283 aRet.append( aStr.copy( n +1, nPos -n -1 ) );
284 if (n >= 0)
286 aRet.append( (sal_Unicode)'.' );
288 nPos = n;
290 return aRet.makeStringAndClear();
293 static inline OUString toRTTIname(
294 OUString const & rUNOname )
295 throw ()
297 OUStringBuffer aRet( 64 );
298 aRet.appendAscii( RTL_CONSTASCII_STRINGPARAM(".?AV") ); // class ".?AV"; struct ".?AU"
299 sal_Int32 nPos = rUNOname.getLength();
300 while (nPos > 0)
302 sal_Int32 n = rUNOname.lastIndexOf( '.', nPos );
303 aRet.append( rUNOname.copy( n +1, nPos -n -1 ) );
304 aRet.append( (sal_Unicode)'@' );
305 nPos = n;
307 aRet.append( (sal_Unicode)'@' );
308 return aRet.makeStringAndClear();
311 //RTTI simulation
313 typedef boost::unordered_map< OUString, void *, OUStringHash, equal_to< OUString > > t_string2PtrMap;
315 class RTTInfos
317 Mutex _aMutex;
318 t_string2PtrMap _allRTTI;
320 static OUString toRawName( OUString const & rUNOname ) throw ();
321 public:
322 type_info * getRTTI( OUString const & rUNOname ) throw ();
324 RTTInfos();
325 ~RTTInfos();
328 class __type_info
330 friend type_info * RTTInfos::getRTTI( OUString const & ) throw ();
331 friend int mscx_filterCppException(
332 LPEXCEPTION_POINTERS, uno_Any *, uno_Mapping * );
334 public:
335 virtual ~__type_info() throw ();
337 inline __type_info( void * m_data, const char * m_d_name ) throw ()
338 : _m_data( m_data )
339 { ::strcpy( _m_d_name, m_d_name ); } // #100211# - checked
341 private:
342 void * _m_data;
343 char _m_d_name[1];
346 __type_info::~__type_info() throw ()
350 type_info * RTTInfos::getRTTI( OUString const & rUNOname ) throw ()
352 // a must be
353 OSL_ENSURE( sizeof(__type_info) == sizeof(type_info), "### type info structure size differ!" );
355 MutexGuard aGuard( _aMutex );
356 t_string2PtrMap::const_iterator const iFind( _allRTTI.find( rUNOname ) );
358 // check if type is already available
359 if (iFind == _allRTTI.end())
361 // insert new type_info
362 OString aRawName( OUStringToOString( toRTTIname( rUNOname ), RTL_TEXTENCODING_ASCII_US ) );
363 __type_info * pRTTI = new( ::rtl_allocateMemory( sizeof(__type_info) + aRawName.getLength() ) )
364 __type_info( NULL, aRawName.getStr() );
366 // put into map
367 pair< t_string2PtrMap::iterator, bool > insertion(
368 _allRTTI.insert( t_string2PtrMap::value_type( rUNOname, pRTTI ) ) );
369 OSL_ENSURE( insertion.second, "### rtti insertion failed?!" );
371 return (type_info *)pRTTI;
373 else
375 return (type_info *)iFind->second;
379 RTTInfos::RTTInfos() throw ()
383 RTTInfos::~RTTInfos() throw ()
385 #if OSL_DEBUG_LEVEL > 1
386 OSL_TRACE( "> freeing generated RTTI infos... <" );
387 #endif
389 MutexGuard aGuard( _aMutex );
390 for ( t_string2PtrMap::const_iterator iPos( _allRTTI.begin() );
391 iPos != _allRTTI.end(); ++iPos )
393 __type_info * pType = (__type_info *)iPos->second;
394 pType->~__type_info(); // obsolete, but good style...
395 ::rtl_freeMemory( pType );
399 void * __cdecl copyConstruct(
400 void * pExcThis,
401 void * pSource,
402 typelib_TypeDescription * pTD ) throw ()
404 ::uno_copyData( pExcThis, pSource, pTD, cpp_acquire );
405 return pExcThis;
408 void * __cdecl destruct(
409 void * pExcThis,
410 typelib_TypeDescription * pTD ) throw ()
412 ::uno_destructData( pExcThis, pTD, cpp_release );
413 return pExcThis;
416 const int codeSnippetSize = 40;
418 void GenerateConstructorTrampoline(
419 unsigned char * code,
420 typelib_TypeDescription * pTD ) throw ()
422 unsigned char *p = code;
424 // mov r8, pTD
425 *p++ = 0x49; *p++ = 0xB8;
426 *((void **)p) = pTD; p += 8;
428 // mov r11, copyConstruct
429 *p++ = 0x49; *p++ = 0xBB;
430 *((void **)p) = &copyConstruct; p += 8;
432 // jmp r11
433 *p++ = 0x41; *p++ = 0xFF; *p++ = 0xE3;
435 OSL_ASSERT( p < code + codeSnippetSize );
438 void GenerateDestructorTrampoline(
439 unsigned char * code,
440 typelib_TypeDescription * pTD ) throw ()
442 unsigned char *p = code;
444 // mov rdx, pTD
445 *p++ = 0x48; *p++ = 0xBA;
446 *((void **)p) = pTD; p += 8;
448 // mov r11, destruct
449 *p++ = 0x49; *p++ = 0xBB;
450 *((void **)p) = &destruct; p += 8;
452 // jmp r11
453 *p++ = 0x41; *p++ = 0xFF; *p++ = 0xE3;
455 OSL_ASSERT( p < code + codeSnippetSize );
458 // This looks like it is the struct catchabletype above
460 struct ExceptionType
462 sal_Int32 _n0; // flags
463 sal_uInt32 _pTypeInfo; // typeinfo
464 sal_Int32 _n1, _n2, _n3; // thiscast
465 sal_Int32 _n4; // object_size
466 sal_uInt32 _pCopyCtor; // copyctor
468 inline ExceptionType(
469 sal_uChar * pCode,
470 sal_uInt64 pCodeBase,
471 typelib_TypeDescription * pTD ) throw ()
472 : _n0( 0 )
473 , _n1( 0 )
474 , _n2( -1 )
475 , _n3( 0 )
476 , _n4( pTD->nSize )
478 // As _n0 is always initialized to zero, that means the
479 // hasvirtbase flag (see the ONTL catchabletype struct) is
480 // off, and thus the copyctor is of the ctor_ptr kind.
481 _pTypeInfo = (sal_uInt32) ((sal_uInt64) mscx_getRTTI( pTD->pTypeName ) - pCodeBase);
482 GenerateConstructorTrampoline( pCode, pTD );
483 _pCopyCtor = (sal_uInt32) ((sal_uInt64) pCode - pCodeBase);
485 inline ~ExceptionType() throw ()
490 struct RaiseInfo;
492 class ExceptionInfos
494 Mutex _aMutex;
495 t_string2PtrMap _allRaiseInfos;
497 public:
498 static RaiseInfo * getRaiseInfo( typelib_TypeDescription * pTD ) throw ();
500 static DWORD allocationGranularity;
502 ExceptionInfos() throw ();
503 ~ExceptionInfos() throw ();
506 DWORD ExceptionInfos::allocationGranularity = 0;
508 // This corresponds to the struct throwinfo described above.
510 struct RaiseInfo
512 sal_Int32 _n0;
513 sal_uInt32 _pDtor;
514 sal_Int32 _n2;
515 sal_uInt32 _types;
517 // Additional fields
518 typelib_TypeDescription * _pTD;
519 sal_uChar * _code;
520 sal_uInt64 _codeBase;
522 RaiseInfo( typelib_TypeDescription * pTD ) throw ();
524 ~RaiseInfo() throw ();
527 RaiseInfo::RaiseInfo( typelib_TypeDescription * pTD )throw ()
528 : _n0( 0 )
529 , _n2( 0 )
530 , _pTD( pTD )
532 typelib_CompoundTypeDescription * pCompTD;
534 // Count how many trampolines we need
535 int codeSize = codeSnippetSize;
537 // Info count
538 int nLen = 0;
539 for ( pCompTD = (typelib_CompoundTypeDescription*)pTD;
540 pCompTD; pCompTD = pCompTD->pBaseTypeDescription )
542 ++nLen;
543 codeSize += codeSnippetSize;
546 sal_uChar * pCode = _code = (sal_uChar *)::rtl_allocateMemory( codeSize );
548 _codeBase = (sal_uInt64)pCode & ~(ExceptionInfos::allocationGranularity-1);
550 DWORD old_protect;
551 #if OSL_DEBUG_LEVEL > 0
552 BOOL success =
553 #endif
554 VirtualProtect( pCode, codeSize, PAGE_EXECUTE_READWRITE, &old_protect );
555 OSL_ENSURE( success, "VirtualProtect() failed!" );
557 ::typelib_typedescription_acquire( pTD );
559 GenerateDestructorTrampoline( pCode, pTD );
560 _pDtor = (sal_Int32)((sal_uInt64)pCode - _codeBase);
561 pCode += codeSnippetSize;
563 // Info count accompanied by type info ptrs: type, base type, base base type, ...
564 _types = (sal_Int32)((sal_uInt64)::rtl_allocateMemory( 4 + 4* nLen) - _codeBase);
565 *(sal_Int32 *)_types = nLen;
567 ExceptionType ** ppTypes = (ExceptionType **)((sal_Int32 *)_types + 1);
569 int nPos = 0;
570 for ( pCompTD = (typelib_CompoundTypeDescription*)pTD;
571 pCompTD; pCompTD = pCompTD->pBaseTypeDescription )
573 ppTypes[nPos++] =
574 new ExceptionType( pCode, _codeBase,
575 (typelib_TypeDescription *)pCompTD );
576 pCode += codeSnippetSize;
580 RaiseInfo::~RaiseInfo() throw ()
582 sal_uInt32 * pTypes =
583 (sal_uInt32 *)(_codeBase + _types) + 1;
585 for ( int nTypes = *(sal_uInt32 *)(_codeBase + _types); nTypes--; )
587 delete (ExceptionType *) (_codeBase + pTypes[nTypes]);
589 ::rtl_freeMemory( (void*)(_codeBase +_types) );
590 ::rtl_freeMemory( _code );
592 ::typelib_typedescription_release( _pTD );
595 ExceptionInfos::ExceptionInfos() throw ()
599 ExceptionInfos::~ExceptionInfos() throw ()
601 #if OSL_DEBUG_LEVEL > 1
602 OSL_TRACE( "> freeing exception infos... <" );
603 #endif
605 MutexGuard aGuard( _aMutex );
606 for ( t_string2PtrMap::const_iterator iPos( _allRaiseInfos.begin() );
607 iPos != _allRaiseInfos.end(); ++iPos )
609 delete (RaiseInfo *)iPos->second;
613 RaiseInfo * ExceptionInfos::getRaiseInfo( typelib_TypeDescription * pTD ) throw ()
615 static ExceptionInfos * s_pInfos = 0;
616 if (! s_pInfos)
618 MutexGuard aGuard( Mutex::getGlobalMutex() );
619 if (! s_pInfos)
621 SYSTEM_INFO systemInfo;
622 GetSystemInfo( &systemInfo );
623 allocationGranularity = systemInfo.dwAllocationGranularity;
625 #ifdef LEAK_STATIC_DATA
626 s_pInfos = new ExceptionInfos();
627 #else
628 static ExceptionInfos s_allExceptionInfos;
629 s_pInfos = &s_allExceptionInfos;
630 #endif
634 OSL_ASSERT( pTD &&
635 (pTD->eTypeClass == typelib_TypeClass_STRUCT ||
636 pTD->eTypeClass == typelib_TypeClass_EXCEPTION) );
638 RaiseInfo * pRaiseInfo;
640 OUString const & rTypeName = *reinterpret_cast< OUString * >( &pTD->pTypeName );
641 MutexGuard aGuard( s_pInfos->_aMutex );
642 t_string2PtrMap::const_iterator const iFind(
643 s_pInfos->_allRaiseInfos.find( rTypeName ) );
644 if (iFind == s_pInfos->_allRaiseInfos.end())
646 pRaiseInfo = new RaiseInfo( pTD );
648 // Put into map
649 pair< t_string2PtrMap::iterator, bool > insertion(
650 s_pInfos->_allRaiseInfos.insert( t_string2PtrMap::value_type( rTypeName, (void *)pRaiseInfo ) ) );
651 OSL_ENSURE( insertion.second, "### raise info insertion failed?!" );
653 else
655 // Reuse existing info
656 pRaiseInfo = (RaiseInfo *)iFind->second;
659 return pRaiseInfo;
662 struct RTTISingleton: public rtl::Static< RTTInfos, RTTISingleton > {};
664 type_info * mscx_getRTTI(
665 OUString const & rUNOname )
667 return RTTISingleton::get().getRTTI( rUNOname );
670 void mscx_raiseException(
671 uno_Any * pUnoExc,
672 uno_Mapping * pUno2Cpp )
674 // no ctor/dtor in here: this leads to dtors called twice upon RaiseException()!
675 // thus this obj file will be compiled without opt, so no inlining of
676 // ExceptionInfos::getRaiseInfo()
678 // construct cpp exception object
679 typelib_TypeDescription * pTD = NULL;
680 TYPELIB_DANGER_GET( &pTD, pUnoExc->pType );
682 void * pCppExc = alloca( pTD->nSize );
683 ::uno_copyAndConvertData( pCppExc, pUnoExc->pData, pTD, pUno2Cpp );
685 ULONG_PTR arFilterArgs[4];
686 arFilterArgs[0] = MSVC_magic_number;
687 arFilterArgs[1] = (ULONG_PTR)pCppExc;
688 arFilterArgs[2] = (ULONG_PTR)ExceptionInfos::getRaiseInfo( pTD );
689 arFilterArgs[3] = ((RaiseInfo *)arFilterArgs[2])->_codeBase;
691 // Destruct uno exception
692 ::uno_any_destruct( pUnoExc, 0 );
693 TYPELIB_DANGER_RELEASE( pTD );
695 // last point to release anything not affected by stack unwinding
696 RaiseException( MSVC_ExceptionCode, EXCEPTION_NONCONTINUABLE, 3, arFilterArgs );
699 int mscx_filterCppException(
700 EXCEPTION_POINTERS * pPointers,
701 uno_Any * pUnoExc,
702 uno_Mapping * pCpp2Uno )
704 if (pPointers == 0)
705 return EXCEPTION_CONTINUE_SEARCH;
707 EXCEPTION_RECORD * pRecord = pPointers->ExceptionRecord;
709 // Handle only C++ exceptions:
710 if (pRecord == 0 || pRecord->ExceptionCode != MSVC_ExceptionCode)
711 return EXCEPTION_CONTINUE_SEARCH;
713 bool rethrow = __CxxDetectRethrow( &pRecord );
714 OSL_ASSERT( pRecord == pPointers->ExceptionRecord );
716 if (rethrow && pRecord == pPointers->ExceptionRecord)
718 // Hack to get msvcrt internal _curexception field:
719 pRecord = *reinterpret_cast< EXCEPTION_RECORD ** >(
720 reinterpret_cast< char * >( __pxcptinfoptrs() ) +
721 // As long as we don't demand MSVCR source as build prerequisite,
722 // we have to code those offsets here.
724 // MSVS9/crt/src/mtdll.h:
725 // offsetof (_tiddata, _curexception) -
726 // offsetof (_tiddata, _tpxcptinfoptrs):
727 #if _MSC_VER < 1500
728 error, this compiler version is not supported
729 #elif _MSC_VER < 1600
730 0x48 // msvcr90.dll
731 #else
732 error, please find value for this compiler version
733 #endif
737 // Rethrow: handle only C++ exceptions:
738 if (pRecord == 0 || pRecord->ExceptionCode != MSVC_ExceptionCode)
739 return EXCEPTION_CONTINUE_SEARCH;
741 if (pRecord->NumberParameters == 4 &&
742 pRecord->ExceptionInformation[0] == MSVC_magic_number &&
743 pRecord->ExceptionInformation[1] != 0 &&
744 pRecord->ExceptionInformation[2] != 0 &&
745 pRecord->ExceptionInformation[3] != 0)
747 // ExceptionInformation[1] is the address of the thrown object
748 // (or the address of a pointer to it, in most cases when it
749 // is a C++ class, obviously).
751 // [2] is the throwinfo pointer
753 // [3] is the image base address which is added the 32-bit
754 // rva_t fields in throwinfo to get actual 64-bit addresses
756 void * types =
757 (void *) (pRecord->ExceptionInformation[3] +
758 ((RaiseInfo *)pRecord->ExceptionInformation[2])->_types);
760 if (types != 0 && *(DWORD *)types > 0)
762 DWORD pType = *((DWORD *)types + 1);
763 if (pType != 0 &&
764 ((ExceptionType *)(pRecord->ExceptionInformation[3]+pType))->_pTypeInfo != 0)
766 OUString aRTTIname(
767 OStringToOUString(
768 reinterpret_cast< __type_info * >(
769 ((ExceptionType *)(pRecord->ExceptionInformation[3]+pType))->_pTypeInfo )->_m_d_name,
770 RTL_TEXTENCODING_ASCII_US ) );
771 OUString aUNOname( toUNOname( aRTTIname ) );
773 typelib_TypeDescription * pExcTD = 0;
774 typelib_typedescription_getByName(
775 &pExcTD, aUNOname.pData );
776 if (pExcTD == NULL)
778 OUStringBuffer buf;
779 buf.appendAscii(
780 RTL_CONSTASCII_STRINGPARAM(
781 "[mscx_uno bridge error] UNO type of "
782 "C++ exception unknown: \"") );
783 buf.append( aUNOname );
784 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(
785 "\", RTTI-name=\"") );
786 buf.append( aRTTIname );
787 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\"!") );
788 RuntimeException exc(
789 buf.makeStringAndClear(), Reference< XInterface >() );
790 uno_type_any_constructAndConvert(
791 pUnoExc, &exc,
792 ::getCppuType( &exc ).getTypeLibType(), pCpp2Uno );
793 #if _MSC_VER < 1400 // msvcr80.dll cleans up, different from former msvcrs
794 // if (! rethrow):
795 // though this unknown exception leaks now, no user-defined
796 // exception is ever thrown thru the binary C-UNO dispatcher
797 // call stack.
798 #endif
800 else
802 // construct uno exception any
803 uno_any_constructAndConvert(
804 pUnoExc, (void *) pRecord->ExceptionInformation[1],
805 pExcTD, pCpp2Uno );
806 #if _MSC_VER < 1400 // msvcr80.dll cleans up, different from former msvcrs
807 if (! rethrow)
809 uno_destructData(
810 (void *) pRecord->ExceptionInformation[1],
811 pExcTD, cpp_release );
813 #endif
814 typelib_typedescription_release( pExcTD );
817 return EXCEPTION_EXECUTE_HANDLER;
821 // though this unknown exception leaks now, no user-defined exception
822 // is ever thrown thru the binary C-UNO dispatcher call stack.
823 RuntimeException exc(
824 OUString( RTL_CONSTASCII_USTRINGPARAM(
825 "[mscx_uno bridge error] unexpected "
826 "C++ exception occurred!") ),
827 Reference< XInterface >() );
828 uno_type_any_constructAndConvert(
829 pUnoExc, &exc, ::getCppuType( &exc ).getTypeLibType(), pCpp2Uno );
830 return EXCEPTION_EXECUTE_HANDLER;
835 #pragma pack(pop)
837 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */