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