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