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 //================================================================================================== 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 //================================================================================================== 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 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 194 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 //__________________________________________________________________________________________________ 204 __type_info::~__type_info() throw () 205 { 206 } 207 //__________________________________________________________________________________________________ 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 //__________________________________________________________________________________________________ 237 RTTInfos::RTTInfos() throw () 238 { 239 } 240 //__________________________________________________________________________________________________ 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 //================================================================================================== 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 //================================================================================================== 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 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 //================================================================================================== 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 //================================================================================================== 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 374 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 //__________________________________________________________________________________________________ 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 //__________________________________________________________________________________________________ 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 //__________________________________________________________________________________________________ 489 ExceptionInfos::ExceptionInfos() throw () 490 { 491 } 492 //__________________________________________________________________________________________________ 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 //__________________________________________________________________________________________________ 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 //################################################################################################## 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 //################################################################################################## 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 //############################################################################## 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