xref: /trunk/main/bridges/source/cpp_uno/msvc_win32_intel/except.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_bridges.hxx"
26 
27 #pragma warning( disable : 4237 )
28 #include <hash_map>
29 #include <sal/config.h>
30 #include <malloc.h>
31 // <typeinfo.h> was a Microsoft compatibility header, removed in VS2015+.
32 // The standard spelling works on VC9 too, so this needs no guard.
33 #include <typeinfo>
34 #include <signal.h>
35 
36 #include "rtl/alloc.h"
37 #include "rtl/strbuf.hxx"
38 #include "rtl/ustrbuf.hxx"
39 
40 #include "com/sun/star/uno/Any.hxx"
41 
42 #include "msci.hxx"
43 
44 #if defined _MSC_VER && _MSC_VER >= 1900
45 // The UCRT's own accessor for the field the hack below reaches into by offset.
46 // vcruntime exports it and no public header declares it; the CRT's internal
47 // ehdata.h spells _pCurrentException as exactly this dereference.
48 extern "C" void ** __cdecl __current_exception();
49 #endif
50 
51 
52 #pragma pack(push, 8)
53 
54 using namespace ::com::sun::star::uno;
55 using namespace ::std;
56 using namespace ::osl;
57 using namespace ::rtl;
58 
59 namespace CPPU_CURRENT_NAMESPACE
60 {
61 
62 //==================================================================================================
toUNOname(OUString const & rRTTIname)63 static inline OUString toUNOname( OUString const & rRTTIname ) throw ()
64 {
65     OUStringBuffer aRet( 64 );
66     OUString aStr( rRTTIname.copy( 4, rRTTIname.getLength()-4-2 ) ); // filter .?AUzzz@yyy@xxx@@
67     sal_Int32 nPos = aStr.getLength();
68     while (nPos > 0)
69     {
70         sal_Int32 n = aStr.lastIndexOf( '@', nPos );
71         aRet.append( aStr.copy( n +1, nPos -n -1 ) );
72         if (n >= 0)
73         {
74             aRet.append( (sal_Unicode)'.' );
75         }
76         nPos = n;
77     }
78     return aRet.makeStringAndClear();
79 }
80 //==================================================================================================
toRTTIname(OUString const & rUNOname)81 static inline OUString toRTTIname( OUString const & rUNOname ) throw ()
82 {
83     OUStringBuffer aRet( 64 );
84     aRet.appendAscii( RTL_CONSTASCII_STRINGPARAM(".?AV") ); // class ".?AV"; struct ".?AU"
85     sal_Int32 nPos = rUNOname.getLength();
86     while (nPos > 0)
87     {
88         sal_Int32 n = rUNOname.lastIndexOf( '.', nPos );
89         aRet.append( rUNOname.copy( n +1, nPos -n -1 ) );
90         aRet.append( (sal_Unicode)'@' );
91         nPos = n;
92     }
93     aRet.append( (sal_Unicode)'@' );
94     return aRet.makeStringAndClear();
95 }
96 
97 
98 //##################################################################################################
99 //#### RTTI simulation #############################################################################
100 //##################################################################################################
101 
102 
103 typedef hash_map< OUString, void *, OUStringHash, equal_to< OUString > > t_string2PtrMap;
104 
105 //==================================================================================================
106 class RTTInfos
107 {
108     Mutex               _aMutex;
109     t_string2PtrMap     _allRTTI;
110 
111     static OUString toRawName( OUString const & rUNOname ) throw ();
112 public:
113     type_info * getRTTI( OUString const & rUNOname ) throw ();
114 
115     RTTInfos();
116     ~RTTInfos();
117 };
118 
119 //==================================================================================================
120 class __type_info
121 {
122     friend type_info * RTTInfos::getRTTI( OUString const & ) throw ();
123     friend int msci_filterCppException(
124         LPEXCEPTION_POINTERS, uno_Any *, uno_Mapping * );
125 
126 public:
127     virtual ~__type_info() throw ();
128 
__type_info(void * m_data,const char * m_d_name)129     inline __type_info( void * m_data, const char * m_d_name ) throw ()
130         : _m_data( m_data )
131         { ::strcpy( _m_d_name, m_d_name ); } // #100211# - checked
132 
133 private:
134     void * _m_data;
135     char _m_d_name[1];
136 };
137 //__________________________________________________________________________________________________
~__type_info()138 __type_info::~__type_info() throw ()
139 {
140 }
141 //__________________________________________________________________________________________________
getRTTI(OUString const & rUNOname)142 type_info * RTTInfos::getRTTI( OUString const & rUNOname ) throw ()
143 {
144     // a must be
145     OSL_ENSURE( sizeof(__type_info) == sizeof(type_info), "### type info structure size differ!" );
146 
147     MutexGuard aGuard( _aMutex );
148     t_string2PtrMap::const_iterator const iFind( _allRTTI.find( rUNOname ) );
149 
150     // check if type is already available
151     if (iFind == _allRTTI.end())
152     {
153         // insert new type_info
154         OString aRawName( OUStringToOString( toRTTIname( rUNOname ), RTL_TEXTENCODING_ASCII_US ) );
155         __type_info * pRTTI = new( ::rtl_allocateMemory( sizeof(__type_info) + aRawName.getLength() ) )
156             __type_info( NULL, aRawName.getStr() );
157 
158         // put into map
159         pair< t_string2PtrMap::iterator, bool > insertion(
160             _allRTTI.insert( t_string2PtrMap::value_type( rUNOname, pRTTI ) ) );
161         OSL_ENSURE( insertion.second, "### rtti insertion failed?!" );
162 
163         return (type_info *)pRTTI;
164     }
165     else
166     {
167         return (type_info *)iFind->second;
168     }
169 }
170 //__________________________________________________________________________________________________
RTTInfos()171 RTTInfos::RTTInfos() throw ()
172 {
173 }
174 //__________________________________________________________________________________________________
~RTTInfos()175 RTTInfos::~RTTInfos() throw ()
176 {
177 #if OSL_DEBUG_LEVEL > 1
178     OSL_TRACE( "> freeing generated RTTI infos... <\n" );
179 #endif
180 
181     MutexGuard aGuard( _aMutex );
182     for ( t_string2PtrMap::const_iterator iPos( _allRTTI.begin() );
183           iPos != _allRTTI.end(); ++iPos )
184     {
185         __type_info * pType = (__type_info *)iPos->second;
186         pType->~__type_info(); // obsolete, but good style...
187         ::rtl_freeMemory( pType );
188     }
189 }
190 
191 
192 //##################################################################################################
193 //#### Exception raising ###########################################################################
194 //##################################################################################################
195 
196 
197 //==================================================================================================
198 struct ObjectFunction
199 {
200     char somecode[12];
201     typelib_TypeDescription * _pTypeDescr; // type of object
202 
203     inline static void * operator new ( size_t nSize );
204     inline static void operator delete ( void * pMem );
205 
206     ObjectFunction( typelib_TypeDescription * pTypeDescr, void * fpFunc ) throw ();
207     ~ObjectFunction() throw ();
208 };
209 
operator new(size_t nSize)210 inline void * ObjectFunction::operator new ( size_t nSize )
211 {
212     void * pMem = rtl_allocateMemory( nSize );
213     if (pMem != 0)
214     {
215         DWORD old_protect;
216 #if OSL_DEBUG_LEVEL > 0
217         BOOL success =
218 #endif
219         VirtualProtect( pMem, nSize, PAGE_EXECUTE_READWRITE, &old_protect );
220         OSL_ENSURE( success, "VirtualProtect() failed!" );
221     }
222     return pMem;
223 }
224 
operator delete(void * pMem)225 inline void ObjectFunction::operator delete ( void * pMem )
226 {
227     rtl_freeMemory( pMem );
228 }
229 
230 //__________________________________________________________________________________________________
ObjectFunction(typelib_TypeDescription * pTypeDescr,void * fpFunc)231 ObjectFunction::ObjectFunction( typelib_TypeDescription * pTypeDescr, void * fpFunc ) throw ()
232     : _pTypeDescr( pTypeDescr )
233 {
234     ::typelib_typedescription_acquire( _pTypeDescr );
235 
236     unsigned char * pCode = (unsigned char *)somecode;
237     // a must be!
238     OSL_ENSURE( (void *)this == (void *)pCode, "### unexpected!" );
239 
240     // push ObjectFunction this
241     *pCode++ = 0x68;
242     *(void **)pCode = this;
243     pCode += sizeof(void *);
244     // jmp rel32 fpFunc
245     *pCode++ = 0xe9;
246     *(sal_Int32 *)pCode = ((unsigned char *)fpFunc) - pCode - sizeof(sal_Int32);
247 }
248 //__________________________________________________________________________________________________
~ObjectFunction()249 ObjectFunction::~ObjectFunction() throw ()
250 {
251     ::typelib_typedescription_release( _pTypeDescr );
252 }
253 
254 //==================================================================================================
__copyConstruct(void * pExcThis,void * pSource,ObjectFunction * pThis)255 static void * __cdecl __copyConstruct( void * pExcThis, void * pSource, ObjectFunction * pThis )
256     throw ()
257 {
258     ::uno_copyData( pExcThis, pSource, pThis->_pTypeDescr, cpp_acquire );
259     return pExcThis;
260 }
261 //==================================================================================================
__destruct(void * pExcThis,ObjectFunction * pThis)262 static void * __cdecl __destruct( void * pExcThis, ObjectFunction * pThis )
263     throw ()
264 {
265     ::uno_destructData( pExcThis, pThis->_pTypeDescr, cpp_release );
266     return pExcThis;
267 }
268 
269 // these are non virtual object methods; there is no this ptr on stack => ecx supplies _this_ ptr
270 
271 //==================================================================================================
copyConstruct()272 static __declspec(naked) void copyConstruct() throw ()
273 {
274     __asm
275     {
276         // ObjectFunction this already on stack
277         push [esp+8]  // source exc object this
278         push ecx      // exc object
279         call __copyConstruct
280         add  esp, 12  // + ObjectFunction this
281         ret  4
282     }
283 }
284 //==================================================================================================
destruct()285 static __declspec(naked) void destruct() throw ()
286 {
287     __asm
288     {
289         // ObjectFunction this already on stack
290         push ecx    // exc object
291         call __destruct
292         add  esp, 8 // + ObjectFunction this
293         ret
294     }
295 }
296 
297 //==================================================================================================
298 struct ExceptionType
299 {
300     sal_Int32           _n0;
301     type_info *         _pTypeInfo;
302     sal_Int32           _n1, _n2, _n3, _n4;
303     ObjectFunction *    _pCopyCtor;
304     sal_Int32           _n5;
305 
ExceptionTypeCPPU_CURRENT_NAMESPACE::ExceptionType306     inline ExceptionType( typelib_TypeDescription * pTypeDescr ) throw ()
307         : _n0( 0 )
308         , _n1( 0 )
309         , _n2( -1 )
310         , _n3( 0 )
311         , _n4( pTypeDescr->nSize )
312         , _pCopyCtor( new ObjectFunction( pTypeDescr, copyConstruct ) )
313         , _n5( 0 )
314         { _pTypeInfo = msci_getRTTI( pTypeDescr->pTypeName ); }
~ExceptionTypeCPPU_CURRENT_NAMESPACE::ExceptionType315     inline ~ExceptionType() throw ()
316         { delete _pCopyCtor; }
317 };
318 //==================================================================================================
319 struct RaiseInfo
320 {
321     sal_Int32           _n0;
322     ObjectFunction *    _pDtor;
323     sal_Int32           _n2;
324     void *              _types;
325     sal_Int32           _n3, _n4;
326 
327     RaiseInfo( typelib_TypeDescription * pTypeDescr ) throw ();
328     ~RaiseInfo() throw ();
329 };
330 //__________________________________________________________________________________________________
RaiseInfo(typelib_TypeDescription * pTypeDescr)331 RaiseInfo::RaiseInfo( typelib_TypeDescription * pTypeDescr ) throw ()
332     : _n0( 0 )
333     , _pDtor( new ObjectFunction( pTypeDescr, destruct ) )
334     , _n2( 0 )
335     , _n3( 0 )
336     , _n4( 0 )
337 {
338     // a must be
339     OSL_ENSURE( sizeof(sal_Int32) == sizeof(ExceptionType *), "### pointer size differs from sal_Int32!" );
340 
341     typelib_CompoundTypeDescription * pCompTypeDescr;
342 
343     // info count
344     sal_Int32 nLen = 0;
345     for ( pCompTypeDescr = (typelib_CompoundTypeDescription*)pTypeDescr;
346           pCompTypeDescr; pCompTypeDescr = pCompTypeDescr->pBaseTypeDescription )
347     {
348         ++nLen;
349     }
350 
351     // info count accompanied by type info ptrs: type, base type, base base type, ...
352     _types = ::rtl_allocateMemory( sizeof(sal_Int32) + (sizeof(ExceptionType *) * nLen) );
353     *(sal_Int32 *)_types = nLen;
354 
355     ExceptionType ** ppTypes = (ExceptionType **)((sal_Int32 *)_types + 1);
356 
357     sal_Int32 nPos = 0;
358     for ( pCompTypeDescr = (typelib_CompoundTypeDescription*)pTypeDescr;
359           pCompTypeDescr; pCompTypeDescr = pCompTypeDescr->pBaseTypeDescription )
360     {
361         ppTypes[nPos++] = new ExceptionType( (typelib_TypeDescription *)pCompTypeDescr );
362     }
363 }
364 //__________________________________________________________________________________________________
~RaiseInfo()365 RaiseInfo::~RaiseInfo() throw ()
366 {
367     ExceptionType ** ppTypes = (ExceptionType **)((sal_Int32 *)_types + 1);
368     for ( sal_Int32 nTypes = *(sal_Int32 *)_types; nTypes--; )
369     {
370         delete ppTypes[nTypes];
371     }
372     ::rtl_freeMemory( _types );
373 
374     delete _pDtor;
375 }
376 
377 //==================================================================================================
378 class ExceptionInfos
379 {
380     Mutex           _aMutex;
381     t_string2PtrMap _allRaiseInfos;
382 
383 public:
384     static void * getRaiseInfo( typelib_TypeDescription * pTypeDescr ) throw ();
385 
386     ExceptionInfos() throw ();
387     ~ExceptionInfos() throw ();
388 };
389 //__________________________________________________________________________________________________
ExceptionInfos()390 ExceptionInfos::ExceptionInfos() throw ()
391 {
392 }
393 //__________________________________________________________________________________________________
~ExceptionInfos()394 ExceptionInfos::~ExceptionInfos() throw ()
395 {
396 #if OSL_DEBUG_LEVEL > 1
397     OSL_TRACE( "> freeing exception infos... <\n" );
398 #endif
399 
400     MutexGuard aGuard( _aMutex );
401     for ( t_string2PtrMap::const_iterator iPos( _allRaiseInfos.begin() );
402           iPos != _allRaiseInfos.end(); ++iPos )
403     {
404         delete (RaiseInfo *)iPos->second;
405     }
406 }
407 //__________________________________________________________________________________________________
getRaiseInfo(typelib_TypeDescription * pTypeDescr)408 void * ExceptionInfos::getRaiseInfo( typelib_TypeDescription * pTypeDescr ) throw ()
409 {
410     static ExceptionInfos * s_pInfos = 0;
411     if (! s_pInfos)
412     {
413         MutexGuard aGuard( Mutex::getGlobalMutex() );
414         if (! s_pInfos)
415         {
416 #ifdef LEAK_STATIC_DATA
417             s_pInfos = new ExceptionInfos();
418 #else
419             static ExceptionInfos s_allExceptionInfos;
420             s_pInfos = &s_allExceptionInfos;
421 #endif
422         }
423     }
424 
425     OSL_ASSERT( pTypeDescr &&
426                 (pTypeDescr->eTypeClass == typelib_TypeClass_STRUCT ||
427                  pTypeDescr->eTypeClass == typelib_TypeClass_EXCEPTION) );
428 
429     void * pRaiseInfo;
430 
431     OUString const & rTypeName = *reinterpret_cast< OUString * >( &pTypeDescr->pTypeName );
432     MutexGuard aGuard( s_pInfos->_aMutex );
433     t_string2PtrMap::const_iterator const iFind(
434         s_pInfos->_allRaiseInfos.find( rTypeName ) );
435     if (iFind == s_pInfos->_allRaiseInfos.end())
436     {
437         pRaiseInfo = new RaiseInfo( pTypeDescr );
438         // put into map
439         pair< t_string2PtrMap::iterator, bool > insertion(
440             s_pInfos->_allRaiseInfos.insert( t_string2PtrMap::value_type( rTypeName, pRaiseInfo ) ) );
441         OSL_ENSURE( insertion.second, "### raise info insertion failed?!" );
442     }
443     else
444     {
445         // reuse existing info
446         pRaiseInfo = iFind->second;
447     }
448 
449     return pRaiseInfo;
450 }
451 
452 
453 //##################################################################################################
454 //#### exported ####################################################################################
455 //##################################################################################################
456 
457 
458 //##################################################################################################
msci_getRTTI(OUString const & rUNOname)459 type_info * msci_getRTTI( OUString const & rUNOname )
460 {
461     static RTTInfos * s_pRTTIs = 0;
462     if (! s_pRTTIs)
463     {
464         MutexGuard aGuard( Mutex::getGlobalMutex() );
465         if (! s_pRTTIs)
466         {
467 #ifdef LEAK_STATIC_DATA
468             s_pRTTIs = new RTTInfos();
469 #else
470             static RTTInfos s_aRTTIs;
471             s_pRTTIs = &s_aRTTIs;
472 #endif
473         }
474     }
475     return s_pRTTIs->getRTTI( rUNOname );
476 }
477 
478 //##################################################################################################
msci_raiseException(uno_Any * pUnoExc,uno_Mapping * pUno2Cpp)479 void msci_raiseException( uno_Any * pUnoExc, uno_Mapping * pUno2Cpp )
480 {
481     // no ctor/dtor in here: this leads to dtors called twice upon RaiseException()!
482     // thus this obj file will be compiled without opt, so no inling of
483     // ExceptionInfos::getRaiseInfo()
484 
485     // construct cpp exception object
486     typelib_TypeDescription * pTypeDescr = 0;
487     TYPELIB_DANGER_GET( &pTypeDescr, pUnoExc->pType );
488 
489     void * pCppExc = alloca( pTypeDescr->nSize );
490     ::uno_copyAndConvertData( pCppExc, pUnoExc->pData, pTypeDescr, pUno2Cpp );
491 
492     // a must be
493     OSL_ENSURE(
494         sizeof(sal_Int32) == sizeof(void *),
495         "### pointer size differs from sal_Int32!" );
496     DWORD arFilterArgs[3];
497     arFilterArgs[0] = MSVC_magic_number;
498     arFilterArgs[1] = (DWORD)pCppExc;
499     arFilterArgs[2] = (DWORD)ExceptionInfos::getRaiseInfo( pTypeDescr );
500 
501     // destruct uno exception
502     ::uno_any_destruct( pUnoExc, 0 );
503     TYPELIB_DANGER_RELEASE( pTypeDescr );
504 
505     // last point to release anything not affected by stack unwinding
506     RaiseException( MSVC_ExceptionCode, EXCEPTION_NONCONTINUABLE, 3, arFilterArgs );
507 }
508 
509 //##############################################################################
msci_filterCppException(EXCEPTION_POINTERS * pPointers,uno_Any * pUnoExc,uno_Mapping * pCpp2Uno)510 int msci_filterCppException(
511     EXCEPTION_POINTERS * pPointers, uno_Any * pUnoExc, uno_Mapping * pCpp2Uno )
512 {
513     if (pPointers == 0)
514         return EXCEPTION_CONTINUE_SEARCH;
515     EXCEPTION_RECORD * pRecord = pPointers->ExceptionRecord;
516     // handle only C++ exceptions:
517     if (pRecord == 0 || pRecord->ExceptionCode != MSVC_ExceptionCode)
518         return EXCEPTION_CONTINUE_SEARCH;
519 
520 #if _MSC_VER < 1300 // MSVC -6
521     bool rethrow = (pRecord->NumberParameters < 3 ||
522                     pRecord->ExceptionInformation[ 2 ] == 0);
523 #else
524     bool rethrow = __CxxDetectRethrow( &pRecord );
525     OSL_ASSERT( pRecord == pPointers->ExceptionRecord );
526 #endif
527     if (rethrow && pRecord == pPointers->ExceptionRecord)
528     {
529 #if defined _MSC_VER && _MSC_VER >= 1900
530         // Ask the CRT, rather than guessing where it keeps the answer.
531         //
532         // The #else below hard-codes a byte offset into _tiddata, the CRT's
533         // private per-thread block, and the last offset anybody measured was
534         // msvcr80's.  VC9 happens to match it; the UCRT does not, so on a
535         // modern CRT that arithmetic lands in the middle of some unrelated
536         // member and pRecord comes back pointing at nothing in particular.
537         //
538         // The symptom is not a crash.  The bogus record fails the checks just
539         // below, filtering stops, and the caller gets a C++ exception where it
540         // expected a UNO one:
541         //
542         //     getCaughtException() failed!
543         //
544         // __current_exception() is the accessor the CRT uses for this itself.
545         pRecord = *reinterpret_cast< EXCEPTION_RECORD ** >(
546             __current_exception() );
547 #else
548         // hack to get msvcrt internal _curexception field:
549         pRecord = *reinterpret_cast< EXCEPTION_RECORD ** >(
550             reinterpret_cast< char * >( __pxcptinfoptrs() ) +
551             // as long as we don't demand msvcr source as build prerequisite
552             // (->platform sdk), we have to code those offsets here.
553             //
554             // crt\src\mtdll.h:
555             // offsetof (_tiddata, _curexception) -
556             // offsetof (_tiddata, _tpxcptinfoptrs):
557 #if _MSC_VER < 1300
558             0x18 // msvcrt,dll
559 #elif _MSC_VER < 1310
560             0x20 // msvcr70.dll
561 #elif _MSC_VER < 1400
562             0x24 // msvcr71.dll
563 #else
564             0x28 // msvcr80.dll
565 #endif
566             );
567 #endif
568     }
569     // rethrow: handle only C++ exceptions:
570     if (pRecord == 0 || pRecord->ExceptionCode != MSVC_ExceptionCode)
571         return EXCEPTION_CONTINUE_SEARCH;
572 
573     if (pRecord->NumberParameters == 3 &&
574 //          pRecord->ExceptionInformation[ 0 ] == MSVC_magic_number &&
575         pRecord->ExceptionInformation[ 1 ] != 0 &&
576         pRecord->ExceptionInformation[ 2 ] != 0)
577     {
578         void * types = reinterpret_cast< RaiseInfo * >(
579             pRecord->ExceptionInformation[ 2 ] )->_types;
580         if (types != 0 && *reinterpret_cast< DWORD * >( types ) > 0) // count
581         {
582             ExceptionType * pType = *reinterpret_cast< ExceptionType ** >(
583                 reinterpret_cast< DWORD * >( types ) + 1 );
584             if (pType != 0 && pType->_pTypeInfo != 0)
585             {
586                 OUString aRTTIname(
587                     OStringToOUString(
588                         reinterpret_cast< __type_info * >(
589                             pType->_pTypeInfo )->_m_d_name,
590                         RTL_TEXTENCODING_ASCII_US ) );
591                 OUString aUNOname( toUNOname( aRTTIname ) );
592 
593                 typelib_TypeDescription * pExcTypeDescr = 0;
594                 typelib_typedescription_getByName(
595                     &pExcTypeDescr, aUNOname.pData );
596                 if (pExcTypeDescr == 0)
597                 {
598                     OUStringBuffer buf;
599                     buf.appendAscii(
600                         RTL_CONSTASCII_STRINGPARAM(
601                             "[msci_uno bridge error] UNO type of "
602                             "C++ exception unknown: \"") );
603                     buf.append( aUNOname );
604                     buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(
605                                          "\", RTTI-name=\"") );
606                     buf.append( aRTTIname );
607                     buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\"!") );
608                     RuntimeException exc(
609                         buf.makeStringAndClear(), Reference< XInterface >() );
610                     uno_type_any_constructAndConvert(
611                         pUnoExc, &exc,
612                         ::getCppuType( &exc ).getTypeLibType(), pCpp2Uno );
613 #if _MSC_VER < 1400 // msvcr80.dll cleans up, different from former msvcrs
614                     // if (! rethrow):
615                     // though this unknown exception leaks now, no user-defined
616                     // exception is ever thrown through the binary C-UNO dispatcher
617                     // call stack.
618 #endif
619                 }
620                 else
621                 {
622                     // construct uno exception any
623                     uno_any_constructAndConvert(
624                         pUnoExc, (void *) pRecord->ExceptionInformation[1],
625                         pExcTypeDescr, pCpp2Uno );
626 #if _MSC_VER < 1400 // msvcr80.dll cleans up, different from former msvcrs
627                     if (! rethrow)
628                     {
629                         uno_destructData(
630                             (void *) pRecord->ExceptionInformation[1],
631                             pExcTypeDescr, cpp_release );
632                     }
633 #endif
634                     typelib_typedescription_release( pExcTypeDescr );
635                 }
636 
637                 return EXCEPTION_EXECUTE_HANDLER;
638             }
639         }
640     }
641     // though this unknown exception leaks now, no user-defined exception
642     // is ever thrown through the binary C-UNO dispatcher call stack.
643     RuntimeException exc(
644         OUString( RTL_CONSTASCII_USTRINGPARAM(
645                       "[msci_uno bridge error] unexpected "
646                       "C++ exception occurred!") ),
647         Reference< XInterface >() );
648     uno_type_any_constructAndConvert(
649         pUnoExc, &exc, ::getCppuType( &exc ).getTypeLibType(), pCpp2Uno );
650     return EXCEPTION_EXECUTE_HANDLER;
651 }
652 
653 }
654 
655 #pragma pack(pop)
656