xref: /trunk/main/bridges/source/cpp_uno/msvc_win64_x86-64/except.cxx (revision 8e44b893f976561605ef2d78f346a63374d4be89) !
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 "mscx.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 //==================================================================================================
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 //==================================================================================================
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 mscx_filterCppException(
115         LPEXCEPTION_POINTERS, uno_Any *, uno_Mapping * );
116 
117 public:
118     virtual ~__type_info() throw ();
119 
120     inline __type_info( void * m_vtable, const char * m_d_name ) throw ()
121         : _m_vtable( m_vtable )
122         , _m_name( NULL )
123         { ::strcpy( _m_d_name, m_d_name ); } // #100211# - checked
124 
125     size_t length() const
126     {
127         return sizeof(__type_info) + strlen(_m_d_name);
128     }
129 
130 private:
131     void * _m_vtable;
132     char * _m_name;     // cached copy of unmangled name, NULL initially
133     char _m_d_name[1];  // mangled name
134 };
135 //__________________________________________________________________________________________________
136 __type_info::~__type_info() throw ()
137 {
138 }
139 //__________________________________________________________________________________________________
140 type_info * RTTInfos::getRTTI( OUString const & rUNOname ) throw ()
141 {
142     // a must be
143     OSL_ENSURE( sizeof(__type_info) == sizeof(type_info), "### type info structure size differ!" );
144 
145     MutexGuard aGuard( _aMutex );
146     t_string2PtrMap::const_iterator const iFind( _allRTTI.find( rUNOname ) );
147 
148     // check if type is already available
149     if (iFind == _allRTTI.end())
150     {
151         // insert new type_info
152         OString aRawName( OUStringToOString( toRTTIname( rUNOname ), RTL_TEXTENCODING_ASCII_US ) );
153         __type_info * pRTTI = new( ::rtl_allocateMemory( sizeof(__type_info) + aRawName.getLength() ) )
154             __type_info( NULL, aRawName.getStr() );
155 
156         // put into map
157         pair< t_string2PtrMap::iterator, bool > insertion(
158             _allRTTI.insert( t_string2PtrMap::value_type( rUNOname, pRTTI ) ) );
159         OSL_ENSURE( insertion.second, "### rtti insertion failed?!" );
160 
161         return (type_info *)pRTTI;
162     }
163     else
164     {
165         return (type_info *)iFind->second;
166     }
167 }
168 //__________________________________________________________________________________________________
169 RTTInfos::RTTInfos() throw ()
170 {
171 }
172 //__________________________________________________________________________________________________
173 RTTInfos::~RTTInfos() throw ()
174 {
175 #if OSL_DEBUG_LEVEL > 1
176     OSL_TRACE( "> freeing generated RTTI infos... <\n" );
177 #endif
178 
179     MutexGuard aGuard( _aMutex );
180     for ( t_string2PtrMap::const_iterator iPos( _allRTTI.begin() );
181           iPos != _allRTTI.end(); ++iPos )
182     {
183         __type_info * pType = (__type_info *)iPos->second;
184         pType->~__type_info(); // obsolete, but good style...
185         ::rtl_freeMemory( pType );
186     }
187 }
188 
189 
190 //##################################################################################################
191 //#### Exception raising ###########################################################################
192 //##################################################################################################
193 
194 
195 //==================================================================================================
196 static void * __copyConstruct( void * pExcThis, void * pSource, typelib_TypeDescription *pTypeDescr )
197     throw ()
198 {
199     ::uno_copyData( pExcThis, pSource, pTypeDescr, cpp_acquire );
200     return pExcThis;
201 }
202 //==================================================================================================
203 static void * __destruct( void * pExcThis, typelib_TypeDescription *pTypeDescr )
204     throw ()
205 {
206     ::uno_destructData( pExcThis, pTypeDescr, cpp_release );
207     return pExcThis;
208 }
209 
210 //==================================================================================================
211 
212 int const codeSnippetSize = 32;
213 
214 void copyConstructCodeSnippet( unsigned char * code, typelib_TypeDescription * pTypeDescr )
215     throw ()
216 {
217     unsigned char * p = code;
218 
219     // mov r8, pTypeDescr
220     *p++ = 0x49;
221     *p++ = 0xb8;
222     *p++ = ((sal_uIntPtr)(pTypeDescr)) & 0xff;
223     *p++ = (((sal_uIntPtr)(pTypeDescr)) >> 8) & 0xff;
224     *p++ = (((sal_uIntPtr)(pTypeDescr)) >> 16) & 0xff;
225     *p++ = (((sal_uIntPtr)(pTypeDescr)) >> 24) & 0xff;
226     *p++ = (((sal_uIntPtr)(pTypeDescr)) >> 32) & 0xff;
227     *p++ = (((sal_uIntPtr)(pTypeDescr)) >> 40) & 0xff;
228     *p++ = (((sal_uIntPtr)(pTypeDescr)) >> 48) & 0xff;
229     *p++ = (((sal_uIntPtr)(pTypeDescr)) >> 56) & 0xff;
230 
231     // mov r9, __copyConstruct
232     *p++ = 0x49;
233     *p++ = 0xb9;
234     *p++ = ((sal_uIntPtr)(&__copyConstruct)) & 0xff;
235     *p++ = (((sal_uIntPtr)(&__copyConstruct)) >> 8) & 0xff;
236     *p++ = (((sal_uIntPtr)(&__copyConstruct)) >> 16) & 0xff;
237     *p++ = (((sal_uIntPtr)(&__copyConstruct)) >> 24) & 0xff;
238     *p++ = (((sal_uIntPtr)(&__copyConstruct)) >> 32) & 0xff;
239     *p++ = (((sal_uIntPtr)(&__copyConstruct)) >> 40) & 0xff;
240     *p++ = (((sal_uIntPtr)(&__copyConstruct)) >> 48) & 0xff;
241     *p++ = (((sal_uIntPtr)(&__copyConstruct)) >> 56) & 0xff;
242 
243     // jmp r9
244     *p++ = 0x41;
245     *p++ = 0xff;
246     *p++ = 0xe1;
247 
248     OSL_ASSERT(p - code <= codeSnippetSize);
249 }
250 
251 //==================================================================================================
252 void destructCodeSnippet( unsigned char * code, typelib_TypeDescription * pTypeDescr )
253     throw ()
254 {
255     unsigned char * p = code;
256 
257     // mov rdx, pTypeDescr
258     *p++ = 0x48;
259     *p++ = 0xba;
260     *p++ = ((sal_uIntPtr)(pTypeDescr)) & 0xff;
261     *p++ = (((sal_uIntPtr)(pTypeDescr)) >> 8) & 0xff;
262     *p++ = (((sal_uIntPtr)(pTypeDescr)) >> 16) & 0xff;
263     *p++ = (((sal_uIntPtr)(pTypeDescr)) >> 24) & 0xff;
264     *p++ = (((sal_uIntPtr)(pTypeDescr)) >> 32) & 0xff;
265     *p++ = (((sal_uIntPtr)(pTypeDescr)) >> 40) & 0xff;
266     *p++ = (((sal_uIntPtr)(pTypeDescr)) >> 48) & 0xff;
267     *p++ = (((sal_uIntPtr)(pTypeDescr)) >> 56) & 0xff;
268 
269     // mov r9, __destruct
270     *p++ = 0x49;
271     *p++ = 0xb9;
272     *p++ = ((sal_uIntPtr)(&__destruct)) & 0xff;
273     *p++ = (((sal_uIntPtr)(&__destruct)) >> 8) & 0xff;
274     *p++ = (((sal_uIntPtr)(&__destruct)) >> 16) & 0xff;
275     *p++ = (((sal_uIntPtr)(&__destruct)) >> 24) & 0xff;
276     *p++ = (((sal_uIntPtr)(&__destruct)) >> 32) & 0xff;
277     *p++ = (((sal_uIntPtr)(&__destruct)) >> 40) & 0xff;
278     *p++ = (((sal_uIntPtr)(&__destruct)) >> 48) & 0xff;
279     *p++ = (((sal_uIntPtr)(&__destruct)) >> 56) & 0xff;
280 
281     // jmp r9
282     *p++ = 0x41;
283     *p++ = 0xff;
284     *p++ = 0xe1;
285 
286     OSL_ASSERT(p - code <= codeSnippetSize);
287 }
288 
289 //==================================================================================================
290 static size_t align16(size_t size)
291 {
292     return ((size + 15) >> 4) << 4;
293 }
294 
295 //==================================================================================================
296 // Known as "catchabletype" in https://github.com/icestudent/ontl/blob/master/ntl/nt/exception.hxx
297 struct ExceptionType
298 {
299     sal_Int32           _n0;
300     sal_uInt32          _pTypeInfo;    // type_info *, RVA on Win64
301     sal_Int32           _n1, _n2, _n3; // pointer to member descriptor, 12 bytes.
302     sal_uInt32          _n4;
303     sal_uInt32          _pCopyCtor;    // RVA on Win64
304     sal_Int32           _n5;
305 
306     static void initialize( unsigned char *p, sal_uInt32 typeInfoRVA, typelib_TypeDescription * pTypeDescr, sal_uInt32 copyConstructorRVA ) throw ()
307     {
308         ExceptionType *e = (ExceptionType*)p;
309         e->_n0 = 0;
310         e->_pTypeInfo = typeInfoRVA;
311         e->_n1 = 0;
312         e->_n2 = -1;
313         e->_n3 = 0;
314         e->_n4 = pTypeDescr->nSize;
315         e->_pCopyCtor = copyConstructorRVA;
316         e->_n5 = 0;
317     }
318 };
319 
320 //==================================================================================================
321 // Known as "throwinfo" in https://github.com/icestudent/ontl/blob/master/ntl/nt/exception.hxx
322 struct RaiseInfo
323 {
324     // Microsoft's fields:
325     sal_uInt32          _n0;
326     sal_uInt32          _pDtor; // RVA on Win64
327     sal_uInt32          _n2;
328     sal_uInt32          _types; // void *, RVA on Win64
329 
330     // Our additional fields:
331     typelib_TypeDescription * pTypeDescr;
332     unsigned char       *baseAddress; // The RVAs are relative to this field
333 
334     RaiseInfo( typelib_TypeDescription * pTypeDescr ) throw ();
335     ~RaiseInfo() throw ();
336 };
337 //__________________________________________________________________________________________________
338 RaiseInfo::RaiseInfo( typelib_TypeDescription * pTypeDescr ) throw ()
339     : _n0( 0 )
340     , _n2( 0 )
341 {
342     // a must be
343     OSL_ENSURE( sizeof(sal_Int32) == sizeof(ExceptionType *), "### pointer size differs from sal_Int32!" );
344 
345     ::typelib_typedescription_acquire( pTypeDescr );
346     this->pTypeDescr = pTypeDescr;
347 
348     typelib_CompoundTypeDescription * pCompTypeDescr;
349 
350     size_t bytesNeeded = codeSnippetSize; // destructCodeSnippet for _pDtor
351     sal_uInt32 typeCount = 0;
352     for ( pCompTypeDescr = (typelib_CompoundTypeDescription*)pTypeDescr;
353           pCompTypeDescr; pCompTypeDescr = pCompTypeDescr->pBaseTypeDescription )
354     {
355         ++typeCount;
356         bytesNeeded += align16( sizeof( ExceptionType ) );
357         __type_info *typeInfo = (__type_info*) mscx_getRTTI( ((typelib_TypeDescription *)pCompTypeDescr)->pTypeName );
358         bytesNeeded += align16( typeInfo->length() );
359         bytesNeeded += codeSnippetSize; // copyConstructCodeSnippet for its _pCopyCtor
360     }
361     // type info count accompanied by RVAs of type info ptrs: type, base type, base base type, ...
362     bytesNeeded += align16( sizeof( sal_uInt32 ) + (typeCount * sizeof( sal_uInt32 )) );
363 
364     unsigned char *p = (unsigned char*) ::rtl_allocateMemory( bytesNeeded );
365     DWORD old_protect;
366 #if OSL_DEBUG_LEVEL > 0
367     BOOL success =
368 #endif
369     VirtualProtect( p, bytesNeeded, PAGE_EXECUTE_READWRITE, &old_protect );
370     OSL_ENSURE( success, "VirtualProtect() failed!" );
371     baseAddress = p;
372 
373     destructCodeSnippet( p, pTypeDescr );
374     _pDtor = (sal_uInt32)(p - baseAddress);
375     p += codeSnippetSize;
376 
377     sal_uInt32 *types = (sal_uInt32*)p;
378     _types = (sal_uInt32)(p - baseAddress);
379     p += align16( sizeof( sal_uInt32 ) + (typeCount * sizeof( sal_uInt32 )) );
380     types[0] = typeCount;
381     int next = 1;
382     for ( pCompTypeDescr = (typelib_CompoundTypeDescription*)pTypeDescr;
383           pCompTypeDescr; pCompTypeDescr = pCompTypeDescr->pBaseTypeDescription )
384     {
385         __type_info *typeInfo = (__type_info*) mscx_getRTTI( ((typelib_TypeDescription *)pCompTypeDescr)->pTypeName );
386         memcpy(p, typeInfo, typeInfo->length() );
387         sal_uInt32 typeInfoRVA = (sal_uInt32)(p - baseAddress);
388         p += align16( typeInfo->length() );
389 
390         copyConstructCodeSnippet( p, (typelib_TypeDescription *)pCompTypeDescr );
391         sal_uInt32 copyConstructorRVA = (sal_uInt32)(p - baseAddress);
392         p += codeSnippetSize;
393 
394         ExceptionType::initialize( p, typeInfoRVA, (typelib_TypeDescription *)pCompTypeDescr, copyConstructorRVA );
395         types[next++] = (sal_uInt32)(p - baseAddress);
396         p += align16( sizeof(ExceptionType) );
397     }
398 
399     OSL_ASSERT(p - baseAddress <= bytesNeeded);
400 }
401 //__________________________________________________________________________________________________
402 RaiseInfo::~RaiseInfo() throw ()
403 {
404     ::rtl_freeMemory( baseAddress );
405     ::typelib_typedescription_release( pTypeDescr );
406 }
407 
408 //==================================================================================================
409 class ExceptionInfos
410 {
411     Mutex           _aMutex;
412     t_string2PtrMap _allRaiseInfos;
413 
414 public:
415     static RaiseInfo * getRaiseInfo( typelib_TypeDescription * pTypeDescr ) throw ();
416 
417     ExceptionInfos() throw ();
418     ~ExceptionInfos() throw ();
419 };
420 //__________________________________________________________________________________________________
421 ExceptionInfos::ExceptionInfos() throw ()
422 {
423 }
424 //__________________________________________________________________________________________________
425 ExceptionInfos::~ExceptionInfos() throw ()
426 {
427 #if OSL_DEBUG_LEVEL > 1
428     OSL_TRACE( "> freeing exception infos... <\n" );
429 #endif
430 
431     MutexGuard aGuard( _aMutex );
432     for ( t_string2PtrMap::const_iterator iPos( _allRaiseInfos.begin() );
433           iPos != _allRaiseInfos.end(); ++iPos )
434     {
435         delete (RaiseInfo *)iPos->second;
436     }
437 }
438 //__________________________________________________________________________________________________
439 RaiseInfo * ExceptionInfos::getRaiseInfo( typelib_TypeDescription * pTypeDescr ) throw ()
440 {
441     static ExceptionInfos * s_pInfos = 0;
442     if (! s_pInfos)
443     {
444         MutexGuard aGuard( Mutex::getGlobalMutex() );
445         if (! s_pInfos)
446         {
447 #ifdef LEAK_STATIC_DATA
448             s_pInfos = new ExceptionInfos();
449 #else
450             static ExceptionInfos s_allExceptionInfos;
451             s_pInfos = &s_allExceptionInfos;
452 #endif
453         }
454     }
455 
456     OSL_ASSERT( pTypeDescr &&
457                 (pTypeDescr->eTypeClass == typelib_TypeClass_STRUCT ||
458                  pTypeDescr->eTypeClass == typelib_TypeClass_EXCEPTION) );
459 
460     void * pRaiseInfo;
461 
462     OUString const & rTypeName = *reinterpret_cast< OUString * >( &pTypeDescr->pTypeName );
463     MutexGuard aGuard( s_pInfos->_aMutex );
464     t_string2PtrMap::const_iterator const iFind(
465         s_pInfos->_allRaiseInfos.find( rTypeName ) );
466     if (iFind == s_pInfos->_allRaiseInfos.end())
467     {
468         pRaiseInfo = new RaiseInfo( pTypeDescr );
469         // put into map
470         pair< t_string2PtrMap::iterator, bool > insertion(
471             s_pInfos->_allRaiseInfos.insert( t_string2PtrMap::value_type( rTypeName, pRaiseInfo ) ) );
472         OSL_ENSURE( insertion.second, "### raise info insertion failed?!" );
473     }
474     else
475     {
476         // reuse existing info
477         pRaiseInfo = iFind->second;
478     }
479 
480     return (RaiseInfo*) pRaiseInfo;
481 }
482 
483 
484 //##################################################################################################
485 //#### exported ####################################################################################
486 //##################################################################################################
487 
488 
489 //##################################################################################################
490 type_info * mscx_getRTTI( OUString const & rUNOname )
491 {
492     static RTTInfos * s_pRTTIs = 0;
493     if (! s_pRTTIs)
494     {
495         MutexGuard aGuard( Mutex::getGlobalMutex() );
496         if (! s_pRTTIs)
497         {
498 #ifdef LEAK_STATIC_DATA
499             s_pRTTIs = new RTTInfos();
500 #else
501             static RTTInfos s_aRTTIs;
502             s_pRTTIs = &s_aRTTIs;
503 #endif
504         }
505     }
506     return s_pRTTIs->getRTTI( rUNOname );
507 }
508 
509 //##################################################################################################
510 void mscx_raiseException( uno_Any * pUnoExc, uno_Mapping * pUno2Cpp )
511 {
512     // no ctor/dtor in here: this leads to dtors called twice upon RaiseException()!
513     // thus this obj file will be compiled without opt, so no inling of
514     // ExceptionInfos::getRaiseInfo()
515 
516     // construct cpp exception object
517     typelib_TypeDescription * pTypeDescr = 0;
518     TYPELIB_DANGER_GET( &pTypeDescr, pUnoExc->pType );
519 
520     void * pCppExc = alloca( pTypeDescr->nSize );
521     ::uno_copyAndConvertData( pCppExc, pUnoExc->pData, pTypeDescr, pUno2Cpp );
522 
523     // a must be
524     OSL_ENSURE(
525         sizeof(sal_Int32) == sizeof(void *),
526         "### pointer size differs from sal_Int32!" );
527     RaiseInfo *raiseInfo = ExceptionInfos::getRaiseInfo( pTypeDescr );
528     ULONG_PTR arFilterArgs[4];
529     arFilterArgs[0] = MSVC_magic_number;
530     arFilterArgs[1] = (ULONG_PTR)pCppExc;
531     arFilterArgs[2] = (ULONG_PTR)raiseInfo;
532     arFilterArgs[3] = (ULONG_PTR)raiseInfo->baseAddress;
533 
534     // destruct uno exception
535     ::uno_any_destruct( pUnoExc, 0 );
536     TYPELIB_DANGER_RELEASE( pTypeDescr );
537 
538     // last point to release anything not affected by stack unwinding
539     RaiseException( MSVC_ExceptionCode, EXCEPTION_NONCONTINUABLE, 4, arFilterArgs );
540 }
541 
542 //##############################################################################
543 int mscx_filterCppException(
544     EXCEPTION_POINTERS * pPointers, uno_Any * pUnoExc, uno_Mapping * pCpp2Uno )
545 {
546     if (pPointers == 0)
547         return EXCEPTION_CONTINUE_SEARCH;
548     EXCEPTION_RECORD * pRecord = pPointers->ExceptionRecord;
549     // handle only C++ exceptions:
550     if (pRecord == 0 || pRecord->ExceptionCode != MSVC_ExceptionCode)
551         return EXCEPTION_CONTINUE_SEARCH;
552 
553 #if _MSC_VER < 1300 // MSVC -6
554     bool rethrow = (pRecord->NumberParameters < 3 ||
555                     pRecord->ExceptionInformation[ 2 ] == 0);
556 #else
557     bool rethrow = __CxxDetectRethrow( &pRecord );
558     OSL_ASSERT( pRecord == pPointers->ExceptionRecord );
559 #endif
560     if (rethrow && pRecord == pPointers->ExceptionRecord)
561     {
562         // hack to get msvcrt internal _curexception field:
563         pRecord = *reinterpret_cast< EXCEPTION_RECORD ** >(
564             reinterpret_cast< char * >( __pxcptinfoptrs() ) +
565             // as long as we don't demand msvcr source as build prerequisite
566             // (->platform sdk), we have to code those offsets here.
567             //
568             // crt\src\mtdll.h:
569             // offsetof (_tiddata, _curexception) -
570             // offsetof (_tiddata, _tpxcptinfoptrs):
571             48
572             );
573     }
574     // rethrow: handle only C++ exceptions:
575     if (pRecord == 0 || pRecord->ExceptionCode != MSVC_ExceptionCode)
576         return EXCEPTION_CONTINUE_SEARCH;
577 
578     if (pRecord->NumberParameters == 4 &&
579 //          pRecord->ExceptionInformation[ 0 ] == MSVC_magic_number &&
580         pRecord->ExceptionInformation[ 1 ] != 0 &&
581         pRecord->ExceptionInformation[ 2 ] != 0 &&
582         pRecord->ExceptionInformation[ 3 ] != 0)
583     {
584         unsigned char *baseAddress = (unsigned char*) pRecord->ExceptionInformation[ 3 ];
585         sal_uInt32 * types = (sal_uInt32*)(baseAddress + reinterpret_cast< RaiseInfo * >(
586             pRecord->ExceptionInformation[ 2 ] )->_types );
587         if (types != 0 && (sal_uInt32)(types[0]) > 0) // count
588         {
589             ExceptionType * pType = reinterpret_cast< ExceptionType * >(
590                 baseAddress + types[ 1 ] );
591             if (pType != 0 && pType->_pTypeInfo != 0)
592             {
593                 OUString aRTTIname(
594                     OStringToOUString(
595                         reinterpret_cast< __type_info * >(
596                             baseAddress + pType->_pTypeInfo )->_m_d_name,
597                         RTL_TEXTENCODING_ASCII_US ) );
598                 OUString aUNOname( toUNOname( aRTTIname ) );
599 
600                 typelib_TypeDescription * pExcTypeDescr = 0;
601                 typelib_typedescription_getByName(
602                     &pExcTypeDescr, aUNOname.pData );
603                 if (pExcTypeDescr == 0)
604                 {
605                     OUStringBuffer buf;
606                     buf.appendAscii(
607                         RTL_CONSTASCII_STRINGPARAM(
608                             "[mscx_uno bridge error] UNO type of "
609                             "C++ exception unknown: \"") );
610                     buf.append( aUNOname );
611                     buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(
612                                          "\", RTTI-name=\"") );
613                     buf.append( aRTTIname );
614                     buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\"!") );
615                     RuntimeException exc(
616                         buf.makeStringAndClear(), Reference< XInterface >() );
617                     uno_type_any_constructAndConvert(
618                         pUnoExc, &exc,
619                         ::getCppuType( &exc ).getTypeLibType(), pCpp2Uno );
620 #if _MSC_VER < 1400 // msvcr80.dll cleans up, different from former msvcrs
621                     // if (! rethrow):
622                     // though this unknown exception leaks now, no user-defined
623                     // exception is ever thrown through the binary C-UNO dispatcher
624                     // call stack.
625 #endif
626                 }
627                 else
628                 {
629                     // construct uno exception any
630                     uno_any_constructAndConvert(
631                         pUnoExc, (void *) pRecord->ExceptionInformation[1],
632                         pExcTypeDescr, pCpp2Uno );
633 #if _MSC_VER < 1400 // msvcr80.dll cleans up, different from former msvcrs
634                     if (! rethrow)
635                     {
636                         uno_destructData(
637                             (void *) pRecord->ExceptionInformation[1],
638                             pExcTypeDescr, cpp_release );
639                     }
640 #endif
641                     typelib_typedescription_release( pExcTypeDescr );
642                 }
643 
644                 return EXCEPTION_EXECUTE_HANDLER;
645             }
646         }
647     }
648     // though this unknown exception leaks now, no user-defined exception
649     // is ever thrown through the binary C-UNO dispatcher call stack.
650     RuntimeException exc(
651         OUString( RTL_CONSTASCII_USTRINGPARAM(
652                       "[mscx_uno bridge error] unexpected "
653                       "C++ exception occurred!") ),
654         Reference< XInterface >() );
655     uno_type_any_constructAndConvert(
656         pUnoExc, &exc, ::getCppuType( &exc ).getTypeLibType(), pCpp2Uno );
657     return EXCEPTION_EXECUTE_HANDLER;
658 }
659 
660 }
661 
662 #pragma pack(pop)
663 
664