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