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