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