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