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