1*54c06456SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*54c06456SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*54c06456SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*54c06456SAndrew Rist  * distributed with this work for additional information
6*54c06456SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*54c06456SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*54c06456SAndrew Rist  * "License"); you may not use this file except in compliance
9*54c06456SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*54c06456SAndrew Rist  *
11*54c06456SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*54c06456SAndrew Rist  *
13*54c06456SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*54c06456SAndrew Rist  * software distributed under the License is distributed on an
15*54c06456SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*54c06456SAndrew Rist  * KIND, either express or implied.  See the License for the
17*54c06456SAndrew Rist  * specific language governing permissions and limitations
18*54c06456SAndrew Rist  * under the License.
19*54c06456SAndrew Rist  *
20*54c06456SAndrew Rist  *************************************************************/
21*54c06456SAndrew Rist 
22*54c06456SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_cli_ure.hxx"
26cdf0e10cSrcweir #include "typelib/typedescription.h"
27cdf0e10cSrcweir #include "rtl/ustrbuf.hxx"
28cdf0e10cSrcweir #include "com/sun/star/uno/RuntimeException.hpp"
29cdf0e10cSrcweir #include "osl/mutex.hxx"
30cdf0e10cSrcweir #include "cli_proxy.h"
31cdf0e10cSrcweir #include "cli_base.h"
32cdf0e10cSrcweir #include "cli_bridge.h"
33cdf0e10cSrcweir 
34cdf0e10cSrcweir #using <mscorlib.dll>
35cdf0e10cSrcweir #using <cli_ure.dll>
36cdf0e10cSrcweir #using <cli_uretypes.dll>
37cdf0e10cSrcweir 
38cdf0e10cSrcweir namespace sr = System::Reflection;
39cdf0e10cSrcweir namespace st = System::Text;
40cdf0e10cSrcweir namespace sre = System::Reflection::Emit;
41cdf0e10cSrcweir namespace sc = System::Collections;
42cdf0e10cSrcweir namespace srrm = System::Runtime::Remoting::Messaging;
43cdf0e10cSrcweir namespace srr = System::Runtime::Remoting;
44cdf0e10cSrcweir namespace srrp = System::Runtime::Remoting::Proxies;
45cdf0e10cSrcweir namespace sri = System::Runtime::InteropServices;
46cdf0e10cSrcweir namespace sd = System::Diagnostics;
47cdf0e10cSrcweir namespace css = com::sun::star;
48cdf0e10cSrcweir namespace ucss = unoidl::com::sun::star;
49cdf0e10cSrcweir 
50cdf0e10cSrcweir using namespace cli_uno;
51cdf0e10cSrcweir using namespace rtl;
52cdf0e10cSrcweir extern "C"
53cdf0e10cSrcweir {
54cdf0e10cSrcweir //------------------------------------------------------------------------------
55cdf0e10cSrcweir void SAL_CALL cli_proxy_free( uno_ExtEnvironment * env, void * proxy )
56cdf0e10cSrcweir     SAL_THROW_EXTERN_C();
57cdf0e10cSrcweir //------------------------------------------------------------------------------
58cdf0e10cSrcweir void SAL_CALL cli_proxy_acquire( uno_Interface * pUnoI )
59cdf0e10cSrcweir     SAL_THROW_EXTERN_C();
60cdf0e10cSrcweir //------------------------------------------------------------------------------
61cdf0e10cSrcweir void SAL_CALL cli_proxy_release( uno_Interface * pUnoI )
62cdf0e10cSrcweir     SAL_THROW_EXTERN_C();
63cdf0e10cSrcweir //------------------------------------------------------------------------------
64cdf0e10cSrcweir void SAL_CALL cli_proxy_dispatch(
65cdf0e10cSrcweir     uno_Interface * pUnoI, typelib_TypeDescription const * member_td,
66cdf0e10cSrcweir     void * uno_ret, void * uno_args[], uno_Any ** uno_exc )
67cdf0e10cSrcweir     SAL_THROW_EXTERN_C();
68cdf0e10cSrcweir 
69cdf0e10cSrcweir 
70cdf0e10cSrcweir }
71cdf0e10cSrcweir 
72cdf0e10cSrcweir namespace cli_uno
73cdf0e10cSrcweir {
74cdf0e10cSrcweir 
75cdf0e10cSrcweir UnoInterfaceInfo::UnoInterfaceInfo(Bridge const * bridge, uno_Interface* unoI,
76cdf0e10cSrcweir                                    typelib_InterfaceTypeDescription* td):
77cdf0e10cSrcweir 
78cdf0e10cSrcweir     m_unoI(unoI),
79cdf0e10cSrcweir     m_typeDesc(td),
80cdf0e10cSrcweir     m_bridge(bridge)
81cdf0e10cSrcweir {
82cdf0e10cSrcweir     m_bridge->acquire();
83cdf0e10cSrcweir     m_type = mapUnoType(reinterpret_cast<typelib_TypeDescription*>(td));
84cdf0e10cSrcweir     m_unoI->acquire(m_unoI);
85cdf0e10cSrcweir     typelib_typedescription_acquire(&m_typeDesc->aBase);
86cdf0e10cSrcweir    	if ( ! m_typeDesc->aBase.bComplete)
87cdf0e10cSrcweir     {
88cdf0e10cSrcweir         typelib_TypeDescription* _pt = &m_typeDesc->aBase;
89cdf0e10cSrcweir 		sal_Bool bComplete = ::typelib_typedescription_complete( & _pt);
90cdf0e10cSrcweir         if( ! bComplete)
91cdf0e10cSrcweir         {
92cdf0e10cSrcweir             OUStringBuffer buf( 128 );
93cdf0e10cSrcweir             buf.appendAscii(RTL_CONSTASCII_STRINGPARAM(
94cdf0e10cSrcweir                                  "cannot make type complete: ") );
95cdf0e10cSrcweir             buf.append( *reinterpret_cast< OUString const * >(
96cdf0e10cSrcweir                             & m_typeDesc->aBase.pTypeName));
97cdf0e10cSrcweir             throw BridgeRuntimeError(buf.makeStringAndClear());
98cdf0e10cSrcweir         }
99cdf0e10cSrcweir     }
100cdf0e10cSrcweir }
101cdf0e10cSrcweir UnoInterfaceInfo::~UnoInterfaceInfo()
102cdf0e10cSrcweir {
103cdf0e10cSrcweir     //accessing unmanaged objects is ok.
104cdf0e10cSrcweir    m_bridge->m_uno_env->revokeInterface(
105cdf0e10cSrcweir             m_bridge->m_uno_env, m_unoI );
106cdf0e10cSrcweir    m_bridge->release();
107cdf0e10cSrcweir 
108cdf0e10cSrcweir     m_unoI->release(m_unoI);
109cdf0e10cSrcweir     typelib_typedescription_release(
110cdf0e10cSrcweir         reinterpret_cast<typelib_TypeDescription*>(m_typeDesc));
111cdf0e10cSrcweir }
112cdf0e10cSrcweir 
113cdf0e10cSrcweir UnoInterfaceProxy::UnoInterfaceProxy(
114cdf0e10cSrcweir     Bridge * bridge,
115cdf0e10cSrcweir     uno_Interface * pUnoI,
116cdf0e10cSrcweir     typelib_InterfaceTypeDescription* pTD,
117cdf0e10cSrcweir     const OUString& oid )
118cdf0e10cSrcweir     :RealProxy(__typeof(MarshalByRefObject)),
119cdf0e10cSrcweir      m_bridge(bridge),
120cdf0e10cSrcweir      m_oid(mapUnoString(oid.pData)),
121cdf0e10cSrcweir      m_sTypeName(m_system_Object_String)
122cdf0e10cSrcweir {
123cdf0e10cSrcweir     m_bridge->acquire();
124cdf0e10cSrcweir     // create the list that holds all UnoInterfaceInfos
125cdf0e10cSrcweir     m_listIfaces = new ArrayList(10);
126cdf0e10cSrcweir     m_numUnoIfaces = 0;
127cdf0e10cSrcweir     m_listAdditionalProxies = new ArrayList();
128cdf0e10cSrcweir     m_nlistAdditionalProxies = 0;
129cdf0e10cSrcweir     //put the information of the first UNO interface into the arraylist
130cdf0e10cSrcweir #if OSL_DEBUG_LEVEL >= 2
131cdf0e10cSrcweir     _numInterfaces = 0;
132cdf0e10cSrcweir     _sInterfaces = NULL;
133cdf0e10cSrcweir #endif
134cdf0e10cSrcweir     addUnoInterface(pUnoI, pTD);
135cdf0e10cSrcweir 
136cdf0e10cSrcweir }
137cdf0e10cSrcweir 
138cdf0e10cSrcweir UnoInterfaceProxy::~UnoInterfaceProxy()
139cdf0e10cSrcweir {
140cdf0e10cSrcweir #if OSL_DEBUG_LEVEL >= 2
141cdf0e10cSrcweir     sd::Trace::WriteLine(System::String::Format(
142cdf0e10cSrcweir                new System::String(S"cli uno bridge: Destroying proxy "
143cdf0e10cSrcweir                S"for UNO object, OID: \n\t{0} \n\twith uno interfaces: "),
144cdf0e10cSrcweir                m_oid));
145cdf0e10cSrcweir 
146cdf0e10cSrcweir     sd::Trace::WriteLine( mapUnoString(_sInterfaces));
147cdf0e10cSrcweir     rtl_uString_release(_sInterfaces);
148cdf0e10cSrcweir #endif
149cdf0e10cSrcweir     //m_bridge is unmanaged, therefore we can access it in this finalizer
150cdf0e10cSrcweir 	CliEnvHolder::g_cli_env->revokeInterface(m_oid);
151cdf0e10cSrcweir     m_bridge->release();
152cdf0e10cSrcweir }
153cdf0e10cSrcweir 
154cdf0e10cSrcweir 
155cdf0e10cSrcweir System::Object* UnoInterfaceProxy::create(
156cdf0e10cSrcweir     Bridge * bridge,
157cdf0e10cSrcweir     uno_Interface * pUnoI,
158cdf0e10cSrcweir     typelib_InterfaceTypeDescription* pTD,
159cdf0e10cSrcweir     const OUString& oid)
160cdf0e10cSrcweir {
161cdf0e10cSrcweir     UnoInterfaceProxy* proxyHandler=
162cdf0e10cSrcweir         new UnoInterfaceProxy(bridge, pUnoI, pTD, oid);
163cdf0e10cSrcweir     System::Object* proxy= proxyHandler->GetTransparentProxy();
164cdf0e10cSrcweir 	CliEnvHolder::g_cli_env->registerInterface(proxy, mapUnoString(oid.pData));
165cdf0e10cSrcweir     return proxy;
166cdf0e10cSrcweir }
167cdf0e10cSrcweir 
168cdf0e10cSrcweir 
169cdf0e10cSrcweir void UnoInterfaceProxy::addUnoInterface(uno_Interface* pUnoI,
170cdf0e10cSrcweir                                         typelib_InterfaceTypeDescription* pTd)
171cdf0e10cSrcweir {
172cdf0e10cSrcweir     sc::IEnumerator* enumInfos = m_listIfaces->GetEnumerator();
173cdf0e10cSrcweir     System::Threading::Monitor::Enter(this);
174cdf0e10cSrcweir     try
175cdf0e10cSrcweir     {
176cdf0e10cSrcweir         while (enumInfos->MoveNext())
177cdf0e10cSrcweir         {
178cdf0e10cSrcweir             UnoInterfaceInfo* info = static_cast<UnoInterfaceInfo*>(
179cdf0e10cSrcweir                 enumInfos->Current);
180cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
181cdf0e10cSrcweir             System::Type * t1;
182cdf0e10cSrcweir             System::Type * t2;
183cdf0e10cSrcweir             t1 = mapUnoType(
184cdf0e10cSrcweir                 reinterpret_cast<typelib_TypeDescription*>(info->m_typeDesc) );
185cdf0e10cSrcweir             t2 = mapUnoType(
186cdf0e10cSrcweir                 reinterpret_cast<typelib_TypeDescription*>(pTd) );
187cdf0e10cSrcweir #endif
188cdf0e10cSrcweir             if (typelib_typedescription_equals(
189cdf0e10cSrcweir                reinterpret_cast<typelib_TypeDescription*>(info->m_typeDesc),
190cdf0e10cSrcweir                reinterpret_cast<typelib_TypeDescription*>(pTd)))
191cdf0e10cSrcweir             {
192cdf0e10cSrcweir                 return;
193cdf0e10cSrcweir             }
194cdf0e10cSrcweir         }
195cdf0e10cSrcweir         OUString oid(mapCliString(m_oid));
196cdf0e10cSrcweir         (*m_bridge->m_uno_env->registerInterface)(
197cdf0e10cSrcweir             m_bridge->m_uno_env, reinterpret_cast< void ** >( &pUnoI ),
198cdf0e10cSrcweir             oid.pData, pTd);
199cdf0e10cSrcweir         //This proxy does not contain the uno_Interface. Add it.
200cdf0e10cSrcweir         m_listIfaces->Add(new UnoInterfaceInfo(m_bridge, pUnoI, pTd));
201cdf0e10cSrcweir         m_numUnoIfaces = m_listIfaces->Count;
202cdf0e10cSrcweir #if OSL_DEBUG_LEVEL >= 2
203cdf0e10cSrcweir         System::String * sInterfaceName = static_cast<UnoInterfaceInfo*>(
204cdf0e10cSrcweir             m_listIfaces->get_Item(m_numUnoIfaces - 1))->m_type->FullName;
205cdf0e10cSrcweir         sd::Trace::WriteLine(System::String::Format(
206cdf0e10cSrcweir              new System::String(S"cli uno bridge: Creating proxy for uno object, "
207cdf0e10cSrcweir                  S"id:\n\t{0}\n\t{1}"), m_oid, sInterfaceName));
208cdf0e10cSrcweir         // add to the string that contains all interface names
209cdf0e10cSrcweir          _numInterfaces ++;
210cdf0e10cSrcweir          OUStringBuffer buf(512);
211cdf0e10cSrcweir         buf.appendAscii("\t");
212cdf0e10cSrcweir         buf.append( OUString::valueOf((sal_Int32)_numInterfaces));
213cdf0e10cSrcweir         buf.appendAscii(". ");
214cdf0e10cSrcweir         buf.append(mapCliString(sInterfaceName));
215cdf0e10cSrcweir         buf.appendAscii("\n");
216cdf0e10cSrcweir         OUString _sNewInterface = buf.makeStringAndClear();
217cdf0e10cSrcweir         rtl_uString * __pin * pp_sInterfaces = & _sInterfaces;
218cdf0e10cSrcweir         rtl_uString_newConcat( pp_sInterfaces, * pp_sInterfaces,
219cdf0e10cSrcweir                                _sNewInterface.pData);
220cdf0e10cSrcweir #endif
221cdf0e10cSrcweir     }
222cdf0e10cSrcweir     __finally {
223cdf0e10cSrcweir         System::Threading::Monitor::Exit(this);
224cdf0e10cSrcweir     }
225cdf0e10cSrcweir }
226cdf0e10cSrcweir 
227cdf0e10cSrcweir 
228cdf0e10cSrcweir // IRemotingTypeInfo
229cdf0e10cSrcweir bool UnoInterfaceProxy::CanCastTo(System::Type* fromType,
230cdf0e10cSrcweir                                   System::Object*)
231cdf0e10cSrcweir {
232cdf0e10cSrcweir     if (fromType == __typeof(System::Object)) // trivial case
233cdf0e10cSrcweir         return true;
234cdf0e10cSrcweir 
235cdf0e10cSrcweir     System::Threading::Monitor::Enter(this);
236cdf0e10cSrcweir     try
237cdf0e10cSrcweir     {
238cdf0e10cSrcweir         if (0 != findInfo( fromType )) // proxy supports demanded interface
239cdf0e10cSrcweir             return true;
240cdf0e10cSrcweir 
241cdf0e10cSrcweir         //query an uno interface for the required type
242cdf0e10cSrcweir 
243cdf0e10cSrcweir         // we use the first interface in the list (m_listIfaces) to make
244cdf0e10cSrcweir         // the queryInterface call
245cdf0e10cSrcweir         UnoInterfaceInfo* info =
246cdf0e10cSrcweir             static_cast<UnoInterfaceInfo*>(m_listIfaces->get_Item(0));
247cdf0e10cSrcweir         css::uno::TypeDescription membertd(
248cdf0e10cSrcweir             reinterpret_cast<typelib_InterfaceTypeDescription*>(
249cdf0e10cSrcweir                 info->m_typeDesc)->ppAllMembers[0]);
250cdf0e10cSrcweir         System::Object *args[] = new System::Object*[1];
251cdf0e10cSrcweir 
252cdf0e10cSrcweir         args[0] = fromType;
253cdf0e10cSrcweir         __box uno::Any  * pAny;
254cdf0e10cSrcweir         System::Object* pException = NULL;
255cdf0e10cSrcweir 
256cdf0e10cSrcweir         pAny= static_cast<__box uno::Any *>(
257cdf0e10cSrcweir             m_bridge->call_uno(
258cdf0e10cSrcweir                 info->m_unoI,
259cdf0e10cSrcweir                 membertd.get(),
260cdf0e10cSrcweir                 ((typelib_InterfaceMethodTypeDescription*)
261cdf0e10cSrcweir                  membertd.get())->pReturnTypeRef,
262cdf0e10cSrcweir                 1,
263cdf0e10cSrcweir                 ((typelib_InterfaceMethodTypeDescription*)
264cdf0e10cSrcweir                  membertd.get())->pParams,
265cdf0e10cSrcweir                 args, NULL, &pException) );
266cdf0e10cSrcweir 
267cdf0e10cSrcweir         // handle regular exception from target
268cdf0e10cSrcweir         OSL_ENSURE(
269cdf0e10cSrcweir             0 == pException,
270cdf0e10cSrcweir             OUStringToOString(
271cdf0e10cSrcweir                 mapCliString( pException->ToString()),
272cdf0e10cSrcweir                 RTL_TEXTENCODING_UTF8 ).getStr() );
273cdf0e10cSrcweir 
274cdf0e10cSrcweir         if (pAny->Type != __typeof (void)) // has value?
275cdf0e10cSrcweir         {
276cdf0e10cSrcweir             if (0 != findInfo( fromType ))
277cdf0e10cSrcweir             {
278cdf0e10cSrcweir                 // proxy now supports demanded interface
279cdf0e10cSrcweir                 return true;
280cdf0e10cSrcweir             }
281cdf0e10cSrcweir 
282cdf0e10cSrcweir             // via aggregation: it is possible that queryInterface() returns
283cdf0e10cSrcweir             //                  and interface with a different oid.
284cdf0e10cSrcweir             //                  That way, this type is supported for the CLI
285cdf0e10cSrcweir             //                  interpreter (CanCastTo() returns true)
286cdf0e10cSrcweir             ::System::Object * obj = pAny->Value;
287cdf0e10cSrcweir             OSL_ASSERT( srr::RemotingServices::IsTransparentProxy( obj ) );
288cdf0e10cSrcweir             if (srr::RemotingServices::IsTransparentProxy( obj ))
289cdf0e10cSrcweir             {
290cdf0e10cSrcweir                 UnoInterfaceProxy * proxy =
291cdf0e10cSrcweir                     static_cast< UnoInterfaceProxy * >(
292cdf0e10cSrcweir                         srr::RemotingServices::GetRealProxy( obj ) );
293cdf0e10cSrcweir                 OSL_ASSERT( 0 != proxy->findInfo( fromType ) );
294cdf0e10cSrcweir                 m_listAdditionalProxies->Add( proxy );
295cdf0e10cSrcweir                 m_nlistAdditionalProxies = m_listAdditionalProxies->Count;
296cdf0e10cSrcweir                 OSL_ASSERT( 0 != findInfo( fromType ) );
297cdf0e10cSrcweir                 return true;
298cdf0e10cSrcweir             }
299cdf0e10cSrcweir         }
300cdf0e10cSrcweir     }
301cdf0e10cSrcweir     catch (BridgeRuntimeError& e)
302cdf0e10cSrcweir     {
303cdf0e10cSrcweir         (void) e; // avoid warning
304cdf0e10cSrcweir         OSL_ENSURE(
305cdf0e10cSrcweir             0, OUStringToOString(
306cdf0e10cSrcweir                 e.m_message, RTL_TEXTENCODING_UTF8 ).getStr() );
307cdf0e10cSrcweir     }
308cdf0e10cSrcweir     catch (System::Exception* e)
309cdf0e10cSrcweir     {
310cdf0e10cSrcweir         System::String* msg= new System::String(
311cdf0e10cSrcweir             S"An unexpected CLI exception occurred in "
312cdf0e10cSrcweir             S"UnoInterfaceProxy::CanCastTo().  Original"
313cdf0e10cSrcweir             S"message: \n");
314cdf0e10cSrcweir         msg= System::String::Concat(msg, e->get_Message());
315cdf0e10cSrcweir         OSL_ENSURE(
316cdf0e10cSrcweir             0, OUStringToOString(
317cdf0e10cSrcweir                 mapCliString(msg), RTL_TEXTENCODING_UTF8 ).getStr() );
318cdf0e10cSrcweir     }
319cdf0e10cSrcweir     catch (...)
320cdf0e10cSrcweir     {
321cdf0e10cSrcweir         OSL_ENSURE(
322cdf0e10cSrcweir             0, "An unexpected native C++ exception occurred in "
323cdf0e10cSrcweir             "UnoInterfaceProxy::CanCastTo()" );
324cdf0e10cSrcweir     }
325cdf0e10cSrcweir     __finally
326cdf0e10cSrcweir     {
327cdf0e10cSrcweir         System::Threading::Monitor::Exit(this);
328cdf0e10cSrcweir     }
329cdf0e10cSrcweir     return false;
330cdf0e10cSrcweir }
331cdf0e10cSrcweir 
332cdf0e10cSrcweir srrm::IMessage* UnoInterfaceProxy::invokeObject(
333cdf0e10cSrcweir     sc::IDictionary* props,
334cdf0e10cSrcweir     srrm::LogicalCallContext* context,
335cdf0e10cSrcweir     srrm::IMethodCallMessage* mcm)
336cdf0e10cSrcweir {
337cdf0e10cSrcweir     System::Object* retMethod = 0;
338cdf0e10cSrcweir     System::String* sMethod = static_cast<System::String*>
339cdf0e10cSrcweir         (props->get_Item(m_methodNameString));
340cdf0e10cSrcweir     System::Object* args[] = static_cast<System::Object*[]>(
341cdf0e10cSrcweir         props->get_Item(m_ArgsString));
342cdf0e10cSrcweir     if (m_Equals_String->Equals(sMethod))
343cdf0e10cSrcweir     {
344cdf0e10cSrcweir         // Object.Equals
345cdf0e10cSrcweir         OSL_ASSERT(args->get_Length() == 1);
346cdf0e10cSrcweir         srrp::RealProxy* rProxy = srr::RemotingServices::GetRealProxy(args[0]);
347cdf0e10cSrcweir         bool bDone = false;
348cdf0e10cSrcweir         if (rProxy)
349cdf0e10cSrcweir         {
350cdf0e10cSrcweir             UnoInterfaceProxy* unoProxy =
351cdf0e10cSrcweir                 dynamic_cast<UnoInterfaceProxy*>(rProxy);
352cdf0e10cSrcweir             if (unoProxy)
353cdf0e10cSrcweir             {
354cdf0e10cSrcweir                 bool b = m_oid->Equals(unoProxy->getOid());
355cdf0e10cSrcweir                 retMethod = __box(b);
356cdf0e10cSrcweir                 bDone = true;
357cdf0e10cSrcweir             }
358cdf0e10cSrcweir         }
359cdf0e10cSrcweir         if (bDone == false)
360cdf0e10cSrcweir         {
361cdf0e10cSrcweir             //no proxy or not our proxy, therefore Equals must be false
362cdf0e10cSrcweir             retMethod = __box(false);
363cdf0e10cSrcweir         }
364cdf0e10cSrcweir     }
365cdf0e10cSrcweir     else if (m_GetHashCode_String->Equals(sMethod))
366cdf0e10cSrcweir     {
367cdf0e10cSrcweir         // Object.GetHashCode
368cdf0e10cSrcweir         int nHash = m_oid->GetHashCode();
369cdf0e10cSrcweir         retMethod = __box(nHash);
370cdf0e10cSrcweir     }
371cdf0e10cSrcweir     else if (m_GetType_String->Equals(sMethod))
372cdf0e10cSrcweir     {
373cdf0e10cSrcweir         // Object.GetType
374cdf0e10cSrcweir         retMethod = __typeof(System::Object);
375cdf0e10cSrcweir     }
376cdf0e10cSrcweir     else if (m_ToString_String->Equals(sMethod))
377cdf0e10cSrcweir     {
378cdf0e10cSrcweir         // Object.ToString
379cdf0e10cSrcweir         st::StringBuilder* sb = new st::StringBuilder(256);
380cdf0e10cSrcweir // 				sb->AppendFormat(S"Uno object proxy. Implemented interface: {0}"
381cdf0e10cSrcweir // 					S". OID: {1}", m_type->ToString(), m_oid);
382cdf0e10cSrcweir         sb->AppendFormat(S"Uno object proxy. OID: {0}", m_oid);
383cdf0e10cSrcweir         retMethod = sb->ToString();
384cdf0e10cSrcweir     }
385cdf0e10cSrcweir     else
386cdf0e10cSrcweir     {
387cdf0e10cSrcweir         //Either Object has new functions or a protected method was called
388cdf0e10cSrcweir         //which should not be possible
389cdf0e10cSrcweir         OSL_ASSERT(0);
390cdf0e10cSrcweir     }
391cdf0e10cSrcweir     srrm::IMessage* retVal= new srrm::ReturnMessage(
392cdf0e10cSrcweir         retMethod, new System::Object*[0], 0, context, mcm);
393cdf0e10cSrcweir     return retVal;
394cdf0e10cSrcweir }
395cdf0e10cSrcweir 
396cdf0e10cSrcweir UnoInterfaceInfo * UnoInterfaceProxy::findInfo( ::System::Type * type )
397cdf0e10cSrcweir {
398cdf0e10cSrcweir     for (int i = 0; i < m_numUnoIfaces; i++)
399cdf0e10cSrcweir     {
400cdf0e10cSrcweir         UnoInterfaceInfo* tmpInfo = static_cast<UnoInterfaceInfo*>(
401cdf0e10cSrcweir             m_listIfaces->get_Item(i));
402cdf0e10cSrcweir         if (type->IsAssignableFrom(tmpInfo->m_type))
403cdf0e10cSrcweir             return tmpInfo;
404cdf0e10cSrcweir     }
405cdf0e10cSrcweir     for ( int i = 0; i < m_nlistAdditionalProxies; ++i )
406cdf0e10cSrcweir     {
407cdf0e10cSrcweir         UnoInterfaceProxy * proxy =
408cdf0e10cSrcweir             static_cast< UnoInterfaceProxy * >(
409cdf0e10cSrcweir                 m_listAdditionalProxies->get_Item( i ) );
410cdf0e10cSrcweir         UnoInterfaceInfo * info = proxy->findInfo( type );
411cdf0e10cSrcweir         if (0 != info)
412cdf0e10cSrcweir             return info;
413cdf0e10cSrcweir     }
414cdf0e10cSrcweir     return 0;
415cdf0e10cSrcweir }
416cdf0e10cSrcweir 
417cdf0e10cSrcweir srrm::IMessage* UnoInterfaceProxy::Invoke(srrm::IMessage* callmsg)
418cdf0e10cSrcweir {
419cdf0e10cSrcweir     try
420cdf0e10cSrcweir     {
421cdf0e10cSrcweir         sc::IDictionary* props= callmsg->Properties;
422cdf0e10cSrcweir         srrm::LogicalCallContext* context=
423cdf0e10cSrcweir             static_cast<srrm::LogicalCallContext*>(
424cdf0e10cSrcweir                 props->get_Item(m_CallContextString));
425cdf0e10cSrcweir         srrm::IMethodCallMessage* mcm=
426cdf0e10cSrcweir             static_cast<srrm::IMethodCallMessage*>(callmsg);
427cdf0e10cSrcweir 
428cdf0e10cSrcweir         //Find out which UNO interface is being called
429cdf0e10cSrcweir         System::String* sTypeName = static_cast<System::String*>(
430cdf0e10cSrcweir             props->get_Item(m_typeNameString));
431cdf0e10cSrcweir         sTypeName = sTypeName->Substring(0, sTypeName->IndexOf(','));
432cdf0e10cSrcweir 
433cdf0e10cSrcweir 		// Special Handling for System.Object methods
434cdf0e10cSrcweir         if(sTypeName->IndexOf(m_system_Object_String) != -1)
435cdf0e10cSrcweir         {
436cdf0e10cSrcweir             return invokeObject(props, context, mcm);
437cdf0e10cSrcweir         }
438cdf0e10cSrcweir 
439cdf0e10cSrcweir         System::Type* typeBeingCalled = loadCliType(sTypeName);
440cdf0e10cSrcweir         UnoInterfaceInfo* info = findInfo( typeBeingCalled );
441cdf0e10cSrcweir         OSL_ASSERT( 0 != info );
442cdf0e10cSrcweir 
443cdf0e10cSrcweir         // ToDo do without string conversion, a OUString is not needed here
444cdf0e10cSrcweir         // get the type description of the call
445cdf0e10cSrcweir         OUString usMethodName(mapCliString(static_cast<System::String*>(
446cdf0e10cSrcweir                  props->get_Item(m_methodNameString))));
447cdf0e10cSrcweir         typelib_TypeDescriptionReference ** ppAllMembers =
448cdf0e10cSrcweir             info->m_typeDesc->ppAllMembers;
449cdf0e10cSrcweir         sal_Int32 numberMembers = info->m_typeDesc->nAllMembers;
450cdf0e10cSrcweir         for ( sal_Int32 nPos = numberMembers; nPos--; )
451cdf0e10cSrcweir         {
452cdf0e10cSrcweir             typelib_TypeDescriptionReference * member_type = ppAllMembers[nPos];
453cdf0e10cSrcweir 
454cdf0e10cSrcweir             // check usMethodName against fully qualified usTypeName
455cdf0e10cSrcweir             // of member_type; usTypeName is of the form
456cdf0e10cSrcweir             //  <name> "::" <usMethodName> *(":@" <idx> "," <idx> ":" <name>)
457cdf0e10cSrcweir             OUString const & usTypeName =
458cdf0e10cSrcweir                 OUString::unacquired( & member_type->pTypeName );
459cdf0e10cSrcweir 
460cdf0e10cSrcweir #if OSL_DEBUG_LEVEL >= 2
461cdf0e10cSrcweir 		System::String * pTypeName;
462cdf0e10cSrcweir         pTypeName = mapUnoString(usTypeName.pData);
463cdf0e10cSrcweir #endif
464cdf0e10cSrcweir 			sal_Int32 offset = usTypeName.indexOf( ':' ) + 2;
465cdf0e10cSrcweir             OSL_ASSERT(
466cdf0e10cSrcweir                 offset >= 2 && offset < usTypeName.getLength()
467cdf0e10cSrcweir                 && usTypeName[offset - 1] == ':' );
468cdf0e10cSrcweir             sal_Int32 remainder = usTypeName.getLength() - offset;
469cdf0e10cSrcweir 
470cdf0e10cSrcweir             if (typelib_TypeClass_INTERFACE_METHOD == member_type->eTypeClass)
471cdf0e10cSrcweir             {
472cdf0e10cSrcweir                 if ((usMethodName.getLength() == remainder
473cdf0e10cSrcweir                      || (usMethodName.getLength() < remainder
474cdf0e10cSrcweir                          && usTypeName[offset + usMethodName.getLength()] == ':'))
475cdf0e10cSrcweir                     && usTypeName.match(usMethodName, offset))
476cdf0e10cSrcweir                  {
477cdf0e10cSrcweir                     TypeDescr member_td( member_type );
478cdf0e10cSrcweir                     typelib_InterfaceMethodTypeDescription * method_td =
479cdf0e10cSrcweir                         (typelib_InterfaceMethodTypeDescription *)
480cdf0e10cSrcweir                         member_td.get();
481cdf0e10cSrcweir 
482cdf0e10cSrcweir                     System::Object* args[] = static_cast<System::Object*[]>(
483cdf0e10cSrcweir                         props->get_Item(m_ArgsString));
484cdf0e10cSrcweir                     System::Type* argTypes[] = static_cast<System::Type*[]>(
485cdf0e10cSrcweir                         props->get_Item(m_methodSignatureString));
486cdf0e10cSrcweir                     System::Object* pExc = NULL;
487cdf0e10cSrcweir                     System::Object * cli_ret = m_bridge->call_uno(
488cdf0e10cSrcweir                         info->m_unoI, member_td.get(),
489cdf0e10cSrcweir                         method_td->pReturnTypeRef, method_td->nParams,
490cdf0e10cSrcweir                         method_td->pParams, args, argTypes, &pExc);
491cdf0e10cSrcweir                     return constructReturnMessage(cli_ret, args, method_td,
492cdf0e10cSrcweir                                                   callmsg, pExc);
493cdf0e10cSrcweir                     break;
494cdf0e10cSrcweir                 }
495cdf0e10cSrcweir             }
496cdf0e10cSrcweir             else
497cdf0e10cSrcweir             {
498cdf0e10cSrcweir                 OSL_ASSERT( typelib_TypeClass_INTERFACE_ATTRIBUTE ==
499cdf0e10cSrcweir                             member_type->eTypeClass );
500cdf0e10cSrcweir                 if (usMethodName.getLength() > 4
501cdf0e10cSrcweir                     && (usMethodName.getLength() - 4 == remainder
502cdf0e10cSrcweir                         || (usMethodName.getLength() - 4 < remainder
503cdf0e10cSrcweir                             && usTypeName[
504cdf0e10cSrcweir                                 offset + (usMethodName.getLength() - 4)] == ':'))
505cdf0e10cSrcweir                     && usMethodName[1] == 'e' && usMethodName[2] == 't'
506cdf0e10cSrcweir                     && rtl_ustr_compare_WithLength(
507cdf0e10cSrcweir                         usTypeName.getStr() + offset,
508cdf0e10cSrcweir                         usMethodName.getLength() - 4,
509cdf0e10cSrcweir                         usMethodName.getStr() + 4,
510cdf0e10cSrcweir                         usMethodName.getLength() - 4) == 0)
511cdf0e10cSrcweir                  {
512cdf0e10cSrcweir                     if ('g' == usMethodName[0])
513cdf0e10cSrcweir                     {
514cdf0e10cSrcweir                         TypeDescr member_td( member_type );
515cdf0e10cSrcweir                         typelib_InterfaceAttributeTypeDescription * attribute_td =
516cdf0e10cSrcweir                             (typelib_InterfaceAttributeTypeDescription*)
517cdf0e10cSrcweir                             member_td.get();
518cdf0e10cSrcweir 
519cdf0e10cSrcweir                         System::Object* pExc = NULL;
520cdf0e10cSrcweir                         System::Object* cli_ret= m_bridge->call_uno(
521cdf0e10cSrcweir                             info->m_unoI, member_td.get(),
522cdf0e10cSrcweir                             attribute_td->pAttributeTypeRef,
523cdf0e10cSrcweir                             0, 0,
524cdf0e10cSrcweir                             NULL, NULL, &pExc);
525cdf0e10cSrcweir                         return constructReturnMessage(cli_ret, NULL, NULL,
526cdf0e10cSrcweir                                                       callmsg, pExc);
527cdf0e10cSrcweir                     }
528cdf0e10cSrcweir                     else if ('s' == usMethodName[0])
529cdf0e10cSrcweir                     {
530cdf0e10cSrcweir                         TypeDescr member_td( member_type );
531cdf0e10cSrcweir                         typelib_InterfaceAttributeTypeDescription * attribute_td =
532cdf0e10cSrcweir                             (typelib_InterfaceAttributeTypeDescription *)
533cdf0e10cSrcweir                             member_td.get();
534cdf0e10cSrcweir                         if (! attribute_td->bReadOnly)
535cdf0e10cSrcweir                         {
536cdf0e10cSrcweir                             typelib_MethodParameter param;
537cdf0e10cSrcweir                             param.pTypeRef = attribute_td->pAttributeTypeRef;
538cdf0e10cSrcweir                             param.bIn = sal_True;
539cdf0e10cSrcweir                             param.bOut = sal_False;
540cdf0e10cSrcweir 
541cdf0e10cSrcweir                             System::Object* args[] =
542cdf0e10cSrcweir                                 static_cast<System::Object*[]>(
543cdf0e10cSrcweir                                     props->get_Item(m_ArgsString));
544cdf0e10cSrcweir                             System::Object* pExc = NULL;
545cdf0e10cSrcweir                             m_bridge->call_uno(
546cdf0e10cSrcweir                                 info->m_unoI, member_td.get(),
547cdf0e10cSrcweir                                 ::getCppuVoidType().getTypeLibType(),
548cdf0e10cSrcweir                                 1, &param, args, NULL, &pExc);
549cdf0e10cSrcweir                             return constructReturnMessage(NULL, NULL, NULL,
550cdf0e10cSrcweir                                                           callmsg, pExc);
551cdf0e10cSrcweir                         }
552cdf0e10cSrcweir                         else
553cdf0e10cSrcweir                         {
554cdf0e10cSrcweir                             return constructReturnMessage(NULL, NULL, NULL,
555cdf0e10cSrcweir                                                           callmsg, NULL);
556cdf0e10cSrcweir                         }
557cdf0e10cSrcweir                     }
558cdf0e10cSrcweir                     break;
559cdf0e10cSrcweir                 }
560cdf0e10cSrcweir             }
561cdf0e10cSrcweir         }
562cdf0e10cSrcweir         // ToDo check if the message of the exception is not crippled
563cdf0e10cSrcweir         // the thing that should not be... no method info found!
564cdf0e10cSrcweir         OUStringBuffer buf( 64 );
565cdf0e10cSrcweir         buf.appendAscii(RTL_CONSTASCII_STRINGPARAM(
566cdf0e10cSrcweir                         "[cli_uno bridge]calling undeclared function on "
567cdf0e10cSrcweir                         "interface ") );
568cdf0e10cSrcweir         buf.append( *reinterpret_cast< OUString const * >(
569cdf0e10cSrcweir                   & ((typelib_TypeDescription *)info->m_typeDesc)->pTypeName));
570cdf0e10cSrcweir         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(": ") );
571cdf0e10cSrcweir         buf.append( usMethodName );
572cdf0e10cSrcweir         throw BridgeRuntimeError( buf.makeStringAndClear() );
573cdf0e10cSrcweir     }
574cdf0e10cSrcweir     catch (BridgeRuntimeError & err)
575cdf0e10cSrcweir     {
576cdf0e10cSrcweir         srrm::IMethodCallMessage* mcm =
577cdf0e10cSrcweir             static_cast<srrm::IMethodCallMessage*>(callmsg);
578cdf0e10cSrcweir         return new srrm::ReturnMessage(new ucss::uno::RuntimeException(
579cdf0e10cSrcweir                          mapUnoString(err.m_message.pData), NULL), mcm);
580cdf0e10cSrcweir     }
581cdf0e10cSrcweir     catch (System::Exception* e)
582cdf0e10cSrcweir     {
583cdf0e10cSrcweir         st::StringBuilder * sb = new st::StringBuilder(512);
584cdf0e10cSrcweir         sb->Append(new System::String(
585cdf0e10cSrcweir             S"An unexpected CLI exception occurred in "
586cdf0e10cSrcweir             S"UnoInterfaceProxy::Invoke. Original"
587cdf0e10cSrcweir             S"message: \n"));
588cdf0e10cSrcweir         sb->Append(e->get_Message());
589cdf0e10cSrcweir         sb->Append((__wchar_t) '\n');
590cdf0e10cSrcweir         sb->Append(e->get_StackTrace());
591cdf0e10cSrcweir         srrm::IMethodCallMessage* mcm =
592cdf0e10cSrcweir             static_cast<srrm::IMethodCallMessage*>(callmsg);
593cdf0e10cSrcweir         return new srrm::ReturnMessage(new ucss::uno::RuntimeException(
594cdf0e10cSrcweir                                            sb->ToString(), NULL), mcm);
595cdf0e10cSrcweir     }
596cdf0e10cSrcweir     catch (...)
597cdf0e10cSrcweir     {
598cdf0e10cSrcweir         System::String* msg = new System::String(
599cdf0e10cSrcweir             S"An unexpected native C++ exception occurred in "
600cdf0e10cSrcweir             S"UnoInterfaceProxy::Invoke.");
601cdf0e10cSrcweir         srrm::IMethodCallMessage* mcm =
602cdf0e10cSrcweir             static_cast<srrm::IMethodCallMessage*>(callmsg);
603cdf0e10cSrcweir         return new srrm::ReturnMessage(new ucss::uno::RuntimeException(
604cdf0e10cSrcweir                                        msg, NULL), mcm);
605cdf0e10cSrcweir     }
606cdf0e10cSrcweir     return NULL;
607cdf0e10cSrcweir }
608cdf0e10cSrcweir /** If the argument args is NULL then this function is called for an attribute
609cdf0e10cSrcweir     method (either setXXX or getXXX).
610cdf0e10cSrcweir     For attributes the argument mtd is also NULL.
611cdf0e10cSrcweir */
612cdf0e10cSrcweir srrm::IMessage* UnoInterfaceProxy::constructReturnMessage(
613cdf0e10cSrcweir     System::Object* cliReturn,
614cdf0e10cSrcweir     System::Object* args[],
615cdf0e10cSrcweir     typelib_InterfaceMethodTypeDescription* mtd,
616cdf0e10cSrcweir     srrm::IMessage* msg, System::Object* exc)
617cdf0e10cSrcweir {
618cdf0e10cSrcweir     srrm::IMessage * retVal= NULL;
619cdf0e10cSrcweir     srrm::IMethodCallMessage* mcm = static_cast<srrm::IMethodCallMessage*>(msg);
620cdf0e10cSrcweir     if (exc)
621cdf0e10cSrcweir     {
622cdf0e10cSrcweir         retVal = new srrm::ReturnMessage(
623cdf0e10cSrcweir             dynamic_cast<System::Exception*>(exc), mcm);
624cdf0e10cSrcweir     }
625cdf0e10cSrcweir     else
626cdf0e10cSrcweir     {
627cdf0e10cSrcweir         sc::IDictionary* props= msg->get_Properties();
628cdf0e10cSrcweir         srrm::LogicalCallContext* context=
629cdf0e10cSrcweir             static_cast<srrm::LogicalCallContext*>(
630cdf0e10cSrcweir             props->get_Item(m_CallContextString));
631cdf0e10cSrcweir         if (args != NULL)
632cdf0e10cSrcweir         {
633cdf0e10cSrcweir             // Method
634cdf0e10cSrcweir             //build the array of out parameters, allocate max length
635cdf0e10cSrcweir             System::Object* arOut[]= new System::Object*[mtd->nParams];
636cdf0e10cSrcweir 			int nOut = 0;
637cdf0e10cSrcweir             for (int i= 0; i < mtd->nParams; i++)
638cdf0e10cSrcweir             {
639cdf0e10cSrcweir                 if (mtd->pParams[i].bOut)
640cdf0e10cSrcweir 				{
641cdf0e10cSrcweir                     arOut[i]= args[i];
642cdf0e10cSrcweir 					nOut++;
643cdf0e10cSrcweir 				}
644cdf0e10cSrcweir             }
645cdf0e10cSrcweir             retVal= new srrm::ReturnMessage(cliReturn, arOut, nOut,
646cdf0e10cSrcweir                                             context, mcm);
647cdf0e10cSrcweir         }
648cdf0e10cSrcweir         else
649cdf0e10cSrcweir         {
650cdf0e10cSrcweir             // Attribute  (getXXX)
651cdf0e10cSrcweir             retVal= new srrm::ReturnMessage(cliReturn, NULL, 0,
652cdf0e10cSrcweir                                             context, mcm);
653cdf0e10cSrcweir         }
654cdf0e10cSrcweir     }
655cdf0e10cSrcweir     return retVal;
656cdf0e10cSrcweir }
657cdf0e10cSrcweir 
658cdf0e10cSrcweir //################################################################################
659cdf0e10cSrcweir CliProxy::CliProxy(Bridge const* bridge, System::Object* cliI,
660cdf0e10cSrcweir                          typelib_TypeDescription const* td,
661cdf0e10cSrcweir                          const rtl::OUString& usOid):
662cdf0e10cSrcweir     m_ref(1),
663cdf0e10cSrcweir     m_bridge(bridge),
664cdf0e10cSrcweir     m_cliI(cliI),
665cdf0e10cSrcweir     m_unoType(const_cast<typelib_TypeDescription*>(td)),
666cdf0e10cSrcweir     m_usOid(usOid),
667cdf0e10cSrcweir     m_oid(mapUnoString(usOid.pData)),
668cdf0e10cSrcweir     m_nInheritedInterfaces(0)
669cdf0e10cSrcweir {
670cdf0e10cSrcweir     m_bridge->acquire();
671cdf0e10cSrcweir     uno_Interface::acquire = cli_proxy_acquire;
672cdf0e10cSrcweir     uno_Interface::release = cli_proxy_release;
673cdf0e10cSrcweir     uno_Interface::pDispatcher = cli_proxy_dispatch;
674cdf0e10cSrcweir 
675cdf0e10cSrcweir     m_unoType.makeComplete();
676cdf0e10cSrcweir     m_type= mapUnoType(m_unoType.get());
677cdf0e10cSrcweir 
678cdf0e10cSrcweir     makeMethodInfos();
679cdf0e10cSrcweir #if OSL_DEBUG_LEVEL >= 2
680cdf0e10cSrcweir     sd::Trace::WriteLine(System::String::Format(
681cdf0e10cSrcweir       new System::String(S"cli uno bridge: Creating proxy for cli object, "
682cdf0e10cSrcweir                          S"id:\n\t{0}\n\t{1}"), m_oid, m_type));
683cdf0e10cSrcweir #endif
684cdf0e10cSrcweir 
685cdf0e10cSrcweir }
686cdf0e10cSrcweir 
687cdf0e10cSrcweir void CliProxy::makeMethodInfos()
688cdf0e10cSrcweir {
689cdf0e10cSrcweir #if OSL_DEBUG_LEVEL >= 2
690cdf0e10cSrcweir     System::Object* cliI;
691cdf0e10cSrcweir     System::Type* type;
692cdf0e10cSrcweir     cliI = m_cliI;
693cdf0e10cSrcweir     type = m_type;
694cdf0e10cSrcweir #endif
695cdf0e10cSrcweir 
696cdf0e10cSrcweir     if (m_type->get_IsInterface() == false)
697cdf0e10cSrcweir         return;
698cdf0e10cSrcweir 	sr::MethodInfo* arThisMethods[] = m_type->GetMethods();
699cdf0e10cSrcweir     //get the inherited interfaces
700cdf0e10cSrcweir     System::Type* arInheritedIfaces[] = m_type->GetInterfaces();
701cdf0e10cSrcweir     m_nInheritedInterfaces = arInheritedIfaces->get_Length();
702cdf0e10cSrcweir     //array containing the number of methods for the interface and its
703cdf0e10cSrcweir     //inherited interfaces
704cdf0e10cSrcweir     m_arInterfaceMethodCount = new int __gc [m_nInheritedInterfaces + 1];
705cdf0e10cSrcweir     //determine the number of all interface methods, including the inherited
706cdf0e10cSrcweir     //interfaces
707cdf0e10cSrcweir     int numMethods = arThisMethods->get_Length();
708cdf0e10cSrcweir     for (int i= 0; i < m_nInheritedInterfaces; i++)
709cdf0e10cSrcweir     {
710cdf0e10cSrcweir         numMethods += arInheritedIfaces[i]->GetMethods()->get_Length();
711cdf0e10cSrcweir     }
712cdf0e10cSrcweir     //array containing MethodInfos of the cli object
713cdf0e10cSrcweir     m_arMethodInfos = new sr::MethodInfo*[numMethods];
714cdf0e10cSrcweir     //array containing MethodInfos of the interface
715cdf0e10cSrcweir     m_arInterfaceMethodInfos = new sr::MethodInfo*[numMethods];
716cdf0e10cSrcweir     //array containing the mapping of Uno interface pos to pos in
717cdf0e10cSrcweir     //m_arMethodInfos
718cdf0e10cSrcweir     m_arUnoPosToCliPos = new System::Int32[numMethods];
719cdf0e10cSrcweir     // initialize with -1
720cdf0e10cSrcweir     for (int i = 0; i < numMethods; i++)
721cdf0e10cSrcweir         m_arUnoPosToCliPos[i] = -1;
722cdf0e10cSrcweir 
723cdf0e10cSrcweir #if OSL_DEBUG_LEVEL >= 2
724cdf0e10cSrcweir     sr::MethodInfo* arMethodInfosDbg[];
725cdf0e10cSrcweir     sr::MethodInfo* arInterfaceMethodInfosDbg[];
726cdf0e10cSrcweir     System::Int32 arInterfaceMethodCountDbg[];
727cdf0e10cSrcweir     arMethodInfosDbg = m_arMethodInfos;
728cdf0e10cSrcweir     arInterfaceMethodInfosDbg = m_arInterfaceMethodInfos;
729cdf0e10cSrcweir     arInterfaceMethodCountDbg = m_arInterfaceMethodCount;
730cdf0e10cSrcweir #endif
731cdf0e10cSrcweir 
732cdf0e10cSrcweir 
733cdf0e10cSrcweir     //fill m_arMethodInfos with the mappings
734cdf0e10cSrcweir     // !!! InterfaceMapping.TargetMethods should be MethodInfo*[] according
735cdf0e10cSrcweir     // to documentation
736cdf0e10cSrcweir     // but it is Type*[] instead. Bug in the framework?
737cdf0e10cSrcweir     System::Type* objType = m_cliI->GetType();
738cdf0e10cSrcweir     try
739cdf0e10cSrcweir     {
740cdf0e10cSrcweir         int index = 0;
741cdf0e10cSrcweir         // now get the methods from the inherited interface
742cdf0e10cSrcweir         //arInheritedIfaces[0] is the direct base interface
743cdf0e10cSrcweir         //arInheritedIfaces[n] is the furthest inherited interface
744cdf0e10cSrcweir         //Start with the base interface
745cdf0e10cSrcweir         int nArLength = arInheritedIfaces->get_Length();
746cdf0e10cSrcweir         for (;nArLength > 0; nArLength--)
747cdf0e10cSrcweir         {
748cdf0e10cSrcweir             sr::InterfaceMapping mapInherited = objType->GetInterfaceMap(
749cdf0e10cSrcweir                 arInheritedIfaces[nArLength - 1]);
750cdf0e10cSrcweir             int numMethods = mapInherited.TargetMethods->get_Length();
751cdf0e10cSrcweir             m_arInterfaceMethodCount[nArLength - 1] = numMethods;
752cdf0e10cSrcweir             for (int i = 0; i < numMethods; i++, index++)
753cdf0e10cSrcweir             {
754cdf0e10cSrcweir                 m_arMethodInfos[index] = __try_cast<sr::MethodInfo*>(
755cdf0e10cSrcweir                     mapInherited.TargetMethods[i]);
756cdf0e10cSrcweir 
757cdf0e10cSrcweir                 m_arInterfaceMethodInfos[index] = __try_cast<sr::MethodInfo*>(
758cdf0e10cSrcweir                     mapInherited.InterfaceMethods[i]);
759cdf0e10cSrcweir             }
760cdf0e10cSrcweir         }
761cdf0e10cSrcweir         //At last come the methods of the furthest derived interface
762cdf0e10cSrcweir         sr::InterfaceMapping map = objType->GetInterfaceMap(m_type);
763cdf0e10cSrcweir         nArLength = map.TargetMethods->get_Length();
764cdf0e10cSrcweir         m_arInterfaceMethodCount[m_nInheritedInterfaces] = nArLength;
765cdf0e10cSrcweir         for (int i = 0; i < nArLength; i++,index++)
766cdf0e10cSrcweir         {
767cdf0e10cSrcweir             m_arMethodInfos[index]= __try_cast<sr::MethodInfo*>(
768cdf0e10cSrcweir                 map.TargetMethods[i]);
769cdf0e10cSrcweir             m_arInterfaceMethodInfos[index]= __try_cast<sr::MethodInfo*>(
770cdf0e10cSrcweir                 map.InterfaceMethods[i]);
771cdf0e10cSrcweir         }
772cdf0e10cSrcweir     }
773cdf0e10cSrcweir     catch (System::InvalidCastException* )
774cdf0e10cSrcweir     {
775cdf0e10cSrcweir         OUStringBuffer buf( 128 );
776cdf0e10cSrcweir         buf.appendAscii(RTL_CONSTASCII_STRINGPARAM(
777cdf0e10cSrcweir                             "[cli_uno bridge] preparing proxy for "
778cdf0e10cSrcweir                             "cli interface: ") );
779cdf0e10cSrcweir         buf.append(mapCliString(m_type->ToString() ));
780cdf0e10cSrcweir         buf.appendAscii(RTL_CONSTASCII_STRINGPARAM(" \nfailed!"));
781cdf0e10cSrcweir         throw BridgeRuntimeError( buf.makeStringAndClear() );
782cdf0e10cSrcweir     }
783cdf0e10cSrcweir }
784cdf0e10cSrcweir 
785cdf0e10cSrcweir sr::MethodInfo* CliProxy::getMethodInfo(int nUnoFunctionPos,
786cdf0e10cSrcweir                                            const rtl::OUString& usMethodName, MethodKind methodKind)
787cdf0e10cSrcweir {
788cdf0e10cSrcweir     sr::MethodInfo* ret = NULL;
789cdf0e10cSrcweir #if OSL_DEBUG_LEVEL >= 2
790cdf0e10cSrcweir     System::String* sMethodNameDbg;
791cdf0e10cSrcweir     sr::MethodInfo* arMethodInfosDbg[];
792cdf0e10cSrcweir     sr::MethodInfo* arInterfaceMethodInfosDbg[];
793cdf0e10cSrcweir     System::Int32 arInterfaceMethodCountDbg[];
794cdf0e10cSrcweir     System::Int32 arUnoPosToCliPosDbg[];
795cdf0e10cSrcweir     sMethodNameDbg = mapUnoString(usMethodName.pData);
796cdf0e10cSrcweir     arMethodInfosDbg = m_arMethodInfos;
797cdf0e10cSrcweir     arInterfaceMethodInfosDbg = m_arInterfaceMethodInfos;
798cdf0e10cSrcweir     arInterfaceMethodCountDbg = m_arInterfaceMethodCount;
799cdf0e10cSrcweir     arUnoPosToCliPosDbg = m_arUnoPosToCliPos;
800cdf0e10cSrcweir #endif
801cdf0e10cSrcweir     //deduct 3 for XInterface methods
802cdf0e10cSrcweir     nUnoFunctionPos -= 3;
803cdf0e10cSrcweir     System::Threading::Monitor::Enter(m_arUnoPosToCliPos);
804cdf0e10cSrcweir     try
805cdf0e10cSrcweir     {
806cdf0e10cSrcweir         int cliPos = m_arUnoPosToCliPos[nUnoFunctionPos];
807cdf0e10cSrcweir         if (cliPos != -1)
808cdf0e10cSrcweir             return m_arMethodInfos[cliPos];
809cdf0e10cSrcweir 
810cdf0e10cSrcweir         //create the method function name
811cdf0e10cSrcweir         System::String* sMethodName = mapUnoString(usMethodName.pData);
812cdf0e10cSrcweir         switch (methodKind)
813cdf0e10cSrcweir         {
814cdf0e10cSrcweir         case MK_METHOD:
815cdf0e10cSrcweir             break;
816cdf0e10cSrcweir         case MK_SET:
817cdf0e10cSrcweir             sMethodName = System::String::Concat(
818cdf0e10cSrcweir                 const_cast<System::String*>(Constants::sAttributeSet),
819cdf0e10cSrcweir                 sMethodName);
820cdf0e10cSrcweir             break;
821cdf0e10cSrcweir         case MK_GET:
822cdf0e10cSrcweir             sMethodName = System::String::Concat(
823cdf0e10cSrcweir                 const_cast<System::String*>(Constants::sAttributeGet),
824cdf0e10cSrcweir                 sMethodName);
825cdf0e10cSrcweir             break;
826cdf0e10cSrcweir         default:
827cdf0e10cSrcweir             OSL_ASSERT(0);
828cdf0e10cSrcweir         }
829cdf0e10cSrcweir         //Find the cli interface method that corresponds to the Uno method
830cdf0e10cSrcweir //        System::String* sMethodName= mapUnoString(usMethodName.pData);
831cdf0e10cSrcweir         int indexCliMethod = -1;
832cdf0e10cSrcweir         //If the cli interfaces and their methods are in the same order
833cdf0e10cSrcweir         //as they were declared (inheritance chain and within the interface)
834cdf0e10cSrcweir         //then nUnoFunctionPos should lead to the correct method. However,
835cdf0e10cSrcweir         //the documentation does not say that this ordering is given.
836cdf0e10cSrcweir         if (sMethodName->Equals(m_arInterfaceMethodInfos[nUnoFunctionPos]->Name))
837cdf0e10cSrcweir             indexCliMethod = nUnoFunctionPos;
838cdf0e10cSrcweir         else
839cdf0e10cSrcweir         {
840cdf0e10cSrcweir             int cMethods = m_arInterfaceMethodInfos->get_Length();
841cdf0e10cSrcweir             for (int i = 0; i < cMethods; i++)
842cdf0e10cSrcweir             {
843cdf0e10cSrcweir                 System::String* cliMethod = m_arInterfaceMethodInfos[i]->Name;
844cdf0e10cSrcweir                 if (cliMethod->Equals(sMethodName))
845cdf0e10cSrcweir                 {
846cdf0e10cSrcweir                     indexCliMethod = i;
847cdf0e10cSrcweir                     break;
848cdf0e10cSrcweir                 }
849cdf0e10cSrcweir             }
850cdf0e10cSrcweir         }
851cdf0e10cSrcweir         if (indexCliMethod == -1)
852cdf0e10cSrcweir         {
853cdf0e10cSrcweir             OUStringBuffer buf(256);
854cdf0e10cSrcweir             buf.appendAscii(RTL_CONSTASCII_STRINGPARAM(
855cdf0e10cSrcweir                                 "[cli_uno bridge] CliProxy::getMethodInfo():"
856cdf0e10cSrcweir                                 "cli object does not implement interface method: "));
857cdf0e10cSrcweir             buf.append(usMethodName);
858cdf0e10cSrcweir             throw BridgeRuntimeError(buf.makeStringAndClear());
859cdf0e10cSrcweir             return 0;
860cdf0e10cSrcweir         }
861cdf0e10cSrcweir         m_arUnoPosToCliPos[nUnoFunctionPos] = indexCliMethod;
862cdf0e10cSrcweir         ret = m_arMethodInfos[indexCliMethod];
863cdf0e10cSrcweir     }
864cdf0e10cSrcweir     __finally
865cdf0e10cSrcweir     {
866cdf0e10cSrcweir         System::Threading::Monitor::Exit(m_arUnoPosToCliPos);
867cdf0e10cSrcweir     }
868cdf0e10cSrcweir 
869cdf0e10cSrcweir     return ret;
870cdf0e10cSrcweir }
871cdf0e10cSrcweir 
872cdf0e10cSrcweir CliProxy::~CliProxy()
873cdf0e10cSrcweir {
874cdf0e10cSrcweir #if OSL_DEBUG_LEVEL >= 2
875cdf0e10cSrcweir     sd::Trace::WriteLine(System::String::Format(
876cdf0e10cSrcweir                   new System::String(
877cdf0e10cSrcweir                   S"cli uno bridge: Destroying proxy for cli object, "
878cdf0e10cSrcweir                   S"id:\n\t{0}\n\t{1}\n"),
879cdf0e10cSrcweir                   m_oid, m_type));
880cdf0e10cSrcweir #endif
881cdf0e10cSrcweir 	CliEnvHolder::g_cli_env->revokeInterface(m_oid, mapUnoType(m_unoType.get()));
882cdf0e10cSrcweir     m_bridge->release();
883cdf0e10cSrcweir }
884cdf0e10cSrcweir 
885cdf0e10cSrcweir uno_Interface* CliProxy::create(Bridge const * bridge,
886cdf0e10cSrcweir                                  System::Object* cliI,
887cdf0e10cSrcweir                                  typelib_TypeDescription const* pTD,
888cdf0e10cSrcweir                                  const rtl::OUString& ousOid)
889cdf0e10cSrcweir {
890cdf0e10cSrcweir     uno_Interface* proxy= static_cast<uno_Interface*>(
891cdf0e10cSrcweir         new CliProxy(bridge, cliI, pTD, ousOid));
892cdf0e10cSrcweir 
893cdf0e10cSrcweir     //register proxy with target environment (uno)
894cdf0e10cSrcweir     (*bridge->m_uno_env->registerProxyInterface)(
895cdf0e10cSrcweir        bridge->m_uno_env,
896cdf0e10cSrcweir        reinterpret_cast<void**>(&proxy),
897cdf0e10cSrcweir        cli_proxy_free,
898cdf0e10cSrcweir        ousOid.pData, (typelib_InterfaceTypeDescription*) pTD);
899cdf0e10cSrcweir     //register original interface
900cdf0e10cSrcweir 	CliEnvHolder::g_cli_env->registerInterface(cliI, mapUnoString(ousOid.pData),
901cdf0e10cSrcweir                        mapUnoType((pTD)));
902cdf0e10cSrcweir 
903cdf0e10cSrcweir     return proxy;
904cdf0e10cSrcweir }
905cdf0e10cSrcweir 
906cdf0e10cSrcweir 
907cdf0e10cSrcweir 
908cdf0e10cSrcweir void SAL_CALL CliProxy::uno_DispatchMethod(
909cdf0e10cSrcweir         struct _uno_Interface *,
910cdf0e10cSrcweir         const struct _typelib_TypeDescription *,
911cdf0e10cSrcweir         void *,
912cdf0e10cSrcweir         void **,
913cdf0e10cSrcweir         uno_Any ** )
914cdf0e10cSrcweir {
915cdf0e10cSrcweir }
916cdf0e10cSrcweir inline void CliProxy::acquire() const
917cdf0e10cSrcweir {
918cdf0e10cSrcweir     if (1 == osl_incrementInterlockedCount( &m_ref ))
919cdf0e10cSrcweir     {
920cdf0e10cSrcweir         // rebirth of proxy zombie
921cdf0e10cSrcweir         void * that = const_cast< CliProxy * >( this );
922cdf0e10cSrcweir         // register at uno env
923cdf0e10cSrcweir         (*m_bridge->m_uno_env->registerProxyInterface)(
924cdf0e10cSrcweir             m_bridge->m_uno_env, &that,
925cdf0e10cSrcweir             cli_proxy_free, m_usOid.pData,
926cdf0e10cSrcweir             (typelib_InterfaceTypeDescription *)m_unoType.get() );
927cdf0e10cSrcweir #if OSL_DEBUG_LEVEL >= 2
928cdf0e10cSrcweir         OSL_ASSERT( this == (void const * const)that );
929cdf0e10cSrcweir #endif
930cdf0e10cSrcweir     }
931cdf0e10cSrcweir }
932cdf0e10cSrcweir //---------------------------------------------------------------------------
933cdf0e10cSrcweir inline void CliProxy::release() const
934cdf0e10cSrcweir {
935cdf0e10cSrcweir     if (0 == osl_decrementInterlockedCount( &m_ref ))
936cdf0e10cSrcweir     {
937cdf0e10cSrcweir         // revoke from uno env on last release,
938cdf0e10cSrcweir         // The proxy can be resurrected if acquire is called before the uno
939cdf0e10cSrcweir         // environment calls cli_proxy_free. cli_proxy_free will
940cdf0e10cSrcweir         //delete the proxy. The environment does not acquire a registered
941cdf0e10cSrcweir         //proxy.
942cdf0e10cSrcweir         (*m_bridge->m_uno_env->revokeInterface)(
943cdf0e10cSrcweir             m_bridge->m_uno_env, const_cast< CliProxy * >( this ) );
944cdf0e10cSrcweir     }
945cdf0e10cSrcweir }
946cdf0e10cSrcweir }
947cdf0e10cSrcweir 
948cdf0e10cSrcweir 
949cdf0e10cSrcweir 
950cdf0e10cSrcweir 
951cdf0e10cSrcweir extern "C"
952cdf0e10cSrcweir void SAL_CALL cli_proxy_free( uno_ExtEnvironment *, void * proxy )
953cdf0e10cSrcweir     SAL_THROW_EXTERN_C()
954cdf0e10cSrcweir {
955cdf0e10cSrcweir     cli_uno::CliProxy * cliProxy = reinterpret_cast<
956cdf0e10cSrcweir         cli_uno::CliProxy * >( proxy );
957cdf0e10cSrcweir 
958cdf0e10cSrcweir     delete cliProxy;
959cdf0e10cSrcweir }
960cdf0e10cSrcweir 
961cdf0e10cSrcweir extern "C"
962cdf0e10cSrcweir void SAL_CALL cli_proxy_acquire( uno_Interface * pUnoI )
963cdf0e10cSrcweir     SAL_THROW_EXTERN_C()
964cdf0e10cSrcweir {
965cdf0e10cSrcweir     CliProxy const * cliProxy = static_cast< CliProxy const * >( pUnoI );
966cdf0e10cSrcweir     cliProxy->acquire();
967cdf0e10cSrcweir }
968cdf0e10cSrcweir //-----------------------------------------------------------------------------
969cdf0e10cSrcweir extern "C"
970cdf0e10cSrcweir void SAL_CALL cli_proxy_release( uno_Interface * pUnoI )
971cdf0e10cSrcweir     SAL_THROW_EXTERN_C()
972cdf0e10cSrcweir {
973cdf0e10cSrcweir     CliProxy * cliProxy = static_cast< CliProxy * >( pUnoI );
974cdf0e10cSrcweir     cliProxy->release();
975cdf0e10cSrcweir }
976cdf0e10cSrcweir 
977cdf0e10cSrcweir //------------------------------------------------------------------------------
978cdf0e10cSrcweir extern "C"
979cdf0e10cSrcweir 
980cdf0e10cSrcweir void SAL_CALL cli_proxy_dispatch(
981cdf0e10cSrcweir     uno_Interface * pUnoI, typelib_TypeDescription const * member_td,
982cdf0e10cSrcweir     void * uno_ret, void * uno_args [], uno_Any ** uno_exc )
983cdf0e10cSrcweir     SAL_THROW_EXTERN_C()
984cdf0e10cSrcweir {
985cdf0e10cSrcweir     CliProxy * proxy = static_cast< CliProxy* >( pUnoI );
986cdf0e10cSrcweir     try
987cdf0e10cSrcweir     {
988cdf0e10cSrcweir         Bridge const* bridge = proxy->m_bridge;
989cdf0e10cSrcweir 
990cdf0e10cSrcweir         switch (member_td->eTypeClass)
991cdf0e10cSrcweir         {
992cdf0e10cSrcweir         case typelib_TypeClass_INTERFACE_ATTRIBUTE:
993cdf0e10cSrcweir         {
994cdf0e10cSrcweir 
995cdf0e10cSrcweir             sal_Int32 member_pos = ((typelib_InterfaceMemberTypeDescription *)
996cdf0e10cSrcweir                                     member_td)->nPosition;
997cdf0e10cSrcweir             typelib_InterfaceTypeDescription * iface_td =
998cdf0e10cSrcweir                 (typelib_InterfaceTypeDescription *)proxy->m_unoType.get();
999cdf0e10cSrcweir             OSL_ENSURE(
1000cdf0e10cSrcweir                 member_pos < iface_td->nAllMembers,
1001cdf0e10cSrcweir                 "### member pos out of range!" );
1002cdf0e10cSrcweir             sal_Int32 function_pos =
1003cdf0e10cSrcweir                 iface_td->pMapMemberIndexToFunctionIndex[ member_pos ];
1004cdf0e10cSrcweir             OSL_ENSURE(
1005cdf0e10cSrcweir                 function_pos < iface_td->nMapFunctionIndexToMemberIndex,
1006cdf0e10cSrcweir                 "### illegal function index!" );
1007cdf0e10cSrcweir 
1008cdf0e10cSrcweir             if (uno_ret) // is getter method
1009cdf0e10cSrcweir             {
1010cdf0e10cSrcweir                OUString const& usAttrName= *(rtl_uString**)&
1011cdf0e10cSrcweir                    ((typelib_InterfaceMemberTypeDescription*) member_td)
1012cdf0e10cSrcweir                    ->pMemberName;
1013cdf0e10cSrcweir                sr::MethodInfo* info = proxy->getMethodInfo(function_pos,
1014cdf0e10cSrcweir                                              usAttrName, CliProxy::MK_GET);
1015cdf0e10cSrcweir                bridge->call_cli(
1016cdf0e10cSrcweir                     proxy->m_cliI,
1017cdf0e10cSrcweir                     info,
1018cdf0e10cSrcweir                     ((typelib_InterfaceAttributeTypeDescription *)member_td)
1019cdf0e10cSrcweir                     ->pAttributeTypeRef,
1020cdf0e10cSrcweir                     0, 0, // no params
1021cdf0e10cSrcweir                     uno_ret, 0, uno_exc );
1022cdf0e10cSrcweir             }
1023cdf0e10cSrcweir             else // is setter method
1024cdf0e10cSrcweir             {
1025cdf0e10cSrcweir                 OUString const& usAttrName= *(rtl_uString**) &
1026cdf0e10cSrcweir                     ((typelib_InterfaceMemberTypeDescription*) member_td)
1027cdf0e10cSrcweir                     ->pMemberName;
1028cdf0e10cSrcweir                 sr::MethodInfo* info = proxy->getMethodInfo(function_pos + 1,
1029cdf0e10cSrcweir                                               usAttrName, CliProxy::MK_SET);
1030cdf0e10cSrcweir                 typelib_MethodParameter param;
1031cdf0e10cSrcweir                 param.pTypeRef =
1032cdf0e10cSrcweir                     ((typelib_InterfaceAttributeTypeDescription *)member_td)
1033cdf0e10cSrcweir                     ->pAttributeTypeRef;
1034cdf0e10cSrcweir                 param.bIn = sal_True;
1035cdf0e10cSrcweir                 param.bOut = sal_False;
1036cdf0e10cSrcweir 
1037cdf0e10cSrcweir                 bridge->call_cli(
1038cdf0e10cSrcweir                     proxy->m_cliI,
1039cdf0e10cSrcweir                     // set follows get method
1040cdf0e10cSrcweir                     info,
1041cdf0e10cSrcweir                     0 /* indicates void return */, &param, 1,
1042cdf0e10cSrcweir                     0, uno_args, uno_exc );
1043cdf0e10cSrcweir            }
1044cdf0e10cSrcweir             break;
1045cdf0e10cSrcweir         }
1046cdf0e10cSrcweir         case typelib_TypeClass_INTERFACE_METHOD:
1047cdf0e10cSrcweir         {
1048cdf0e10cSrcweir             sal_Int32 member_pos = ((typelib_InterfaceMemberTypeDescription *)
1049cdf0e10cSrcweir                                     member_td)->nPosition;
1050cdf0e10cSrcweir             typelib_InterfaceTypeDescription * iface_td =
1051cdf0e10cSrcweir                 (typelib_InterfaceTypeDescription *)proxy->m_unoType.get();
1052cdf0e10cSrcweir             OSL_ENSURE(
1053cdf0e10cSrcweir                 member_pos < iface_td->nAllMembers,
1054cdf0e10cSrcweir                 "### member pos out of range!" );
1055cdf0e10cSrcweir             sal_Int32 function_pos =
1056cdf0e10cSrcweir                 iface_td->pMapMemberIndexToFunctionIndex[ member_pos ];
1057cdf0e10cSrcweir             OSL_ENSURE(
1058cdf0e10cSrcweir                 function_pos < iface_td->nMapFunctionIndexToMemberIndex,
1059cdf0e10cSrcweir                 "### illegal function index!" );
1060cdf0e10cSrcweir 
1061cdf0e10cSrcweir             switch (function_pos)
1062cdf0e10cSrcweir             {
1063cdf0e10cSrcweir             case 0: // queryInterface()
1064cdf0e10cSrcweir             {
1065cdf0e10cSrcweir                 TypeDescr demanded_td(
1066cdf0e10cSrcweir                     *reinterpret_cast<typelib_TypeDescriptionReference **>(
1067cdf0e10cSrcweir                         uno_args[0]));
1068cdf0e10cSrcweir                 if (typelib_TypeClass_INTERFACE
1069cdf0e10cSrcweir                     != demanded_td.get()->eTypeClass)
1070cdf0e10cSrcweir                 {
1071cdf0e10cSrcweir                     throw BridgeRuntimeError(
1072cdf0e10cSrcweir                     OUSTR("queryInterface() call demands an INTERFACE type!"));
1073cdf0e10cSrcweir                 }
1074cdf0e10cSrcweir 
1075cdf0e10cSrcweir                 uno_Interface * pInterface = 0;
1076cdf0e10cSrcweir                 (*bridge->m_uno_env->getRegisteredInterface)(
1077cdf0e10cSrcweir                     bridge->m_uno_env,
1078cdf0e10cSrcweir                     (void **)&pInterface, proxy->m_usOid.pData,
1079cdf0e10cSrcweir                     (typelib_InterfaceTypeDescription *)demanded_td.get() );
1080cdf0e10cSrcweir 
1081cdf0e10cSrcweir                 if (0 == pInterface)
1082cdf0e10cSrcweir                 {
1083cdf0e10cSrcweir                     System::Type* mgdDemandedType =
1084cdf0e10cSrcweir                         mapUnoType(demanded_td.get());
1085cdf0e10cSrcweir                     if (mgdDemandedType->IsInstanceOfType( proxy->m_cliI ))
1086cdf0e10cSrcweir                     {
1087cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 0
1088cdf0e10cSrcweir                         OUString usOid(
1089cdf0e10cSrcweir                             mapCliString(
1090cdf0e10cSrcweir 							CliEnvHolder::g_cli_env->getObjectIdentifier(
1091cdf0e10cSrcweir                                     proxy->m_cliI )));
1092cdf0e10cSrcweir                         OSL_ENSURE(usOid.equals( proxy->m_usOid ),
1093cdf0e10cSrcweir                                     "### different oids!");
1094cdf0e10cSrcweir #endif
1095cdf0e10cSrcweir                         uno_Interface* pUnoI = bridge->map_cli2uno(
1096cdf0e10cSrcweir                             proxy->m_cliI, demanded_td.get() );
1097cdf0e10cSrcweir                         uno_any_construct(
1098cdf0e10cSrcweir                             (uno_Any *)uno_ret, &pUnoI, demanded_td.get(), 0 );
1099cdf0e10cSrcweir                         (*pUnoI->release)( pUnoI );
1100cdf0e10cSrcweir                     }
1101cdf0e10cSrcweir                     else // object does not support demanded interface
1102cdf0e10cSrcweir                     {
1103cdf0e10cSrcweir                         uno_any_construct( (uno_Any *)uno_ret, 0, 0, 0 );
1104cdf0e10cSrcweir                     }
1105cdf0e10cSrcweir                     // no excetpion occured
1106cdf0e10cSrcweir                     *uno_exc = 0;
1107cdf0e10cSrcweir                 }
1108cdf0e10cSrcweir                 else
1109cdf0e10cSrcweir                 {
1110cdf0e10cSrcweir                     uno_any_construct(
1111cdf0e10cSrcweir                         reinterpret_cast< uno_Any * >( uno_ret ),
1112cdf0e10cSrcweir                         &pInterface, demanded_td.get(), 0 );
1113cdf0e10cSrcweir                     (*pInterface->release)( pInterface );
1114cdf0e10cSrcweir                     *uno_exc = 0;
1115cdf0e10cSrcweir                 }
1116cdf0e10cSrcweir                 break;
1117cdf0e10cSrcweir             }
1118cdf0e10cSrcweir             case 1: // acquire this proxy
1119cdf0e10cSrcweir                 cli_proxy_acquire(proxy);
1120cdf0e10cSrcweir                 *uno_exc = 0;
1121cdf0e10cSrcweir                 break;
1122cdf0e10cSrcweir             case 2: // release this proxy
1123cdf0e10cSrcweir                 cli_proxy_release(proxy);
1124cdf0e10cSrcweir                 *uno_exc = 0;
1125cdf0e10cSrcweir                 break;
1126cdf0e10cSrcweir             default: // arbitrary method call
1127cdf0e10cSrcweir             {
1128cdf0e10cSrcweir                 typelib_InterfaceMethodTypeDescription * method_td =
1129cdf0e10cSrcweir                     (typelib_InterfaceMethodTypeDescription *)member_td;
1130cdf0e10cSrcweir                OUString const& usMethodName= *(rtl_uString**) &
1131cdf0e10cSrcweir                    ((typelib_InterfaceMemberTypeDescription*) member_td)
1132cdf0e10cSrcweir                    ->pMemberName;
1133cdf0e10cSrcweir 
1134cdf0e10cSrcweir                sr::MethodInfo* info = proxy->getMethodInfo(function_pos,
1135cdf0e10cSrcweir                                              usMethodName, CliProxy::MK_METHOD);
1136cdf0e10cSrcweir                bridge->call_cli(
1137cdf0e10cSrcweir                     proxy->m_cliI,
1138cdf0e10cSrcweir                     info,
1139cdf0e10cSrcweir                     method_td->pReturnTypeRef, method_td->pParams,
1140cdf0e10cSrcweir                     method_td->nParams,
1141cdf0e10cSrcweir                     uno_ret, uno_args, uno_exc);
1142cdf0e10cSrcweir                 return;
1143cdf0e10cSrcweir             }
1144cdf0e10cSrcweir             }
1145cdf0e10cSrcweir             break;
1146cdf0e10cSrcweir         }
1147cdf0e10cSrcweir         default:
1148cdf0e10cSrcweir         {
1149cdf0e10cSrcweir             throw BridgeRuntimeError(
1150cdf0e10cSrcweir                 OUSTR("illegal member type description!") );
1151cdf0e10cSrcweir         }
1152cdf0e10cSrcweir         }
1153cdf0e10cSrcweir     }
1154cdf0e10cSrcweir     catch (BridgeRuntimeError & err)
1155cdf0e10cSrcweir     {
1156cdf0e10cSrcweir         // binary identical struct
1157cdf0e10cSrcweir         ::com::sun::star::uno::RuntimeException exc(
1158cdf0e10cSrcweir             OUSTR("[cli_uno bridge error] ") + err.m_message,
1159cdf0e10cSrcweir             ::com::sun::star::uno::Reference<
1160cdf0e10cSrcweir             ::com::sun::star::uno::XInterface >() );
1161cdf0e10cSrcweir         ::com::sun::star::uno::Type const & exc_type = ::getCppuType( & exc);
1162cdf0e10cSrcweir         uno_type_any_construct( *uno_exc, &exc, exc_type.getTypeLibType(), 0);
1163cdf0e10cSrcweir #if OSL_DEBUG_LEVEL >= 1
1164cdf0e10cSrcweir         OString cstr_msg(OUStringToOString(exc.Message,
1165cdf0e10cSrcweir                                              RTL_TEXTENCODING_ASCII_US ) );
1166cdf0e10cSrcweir         OSL_ENSURE(0, cstr_msg.getStr());
1167cdf0e10cSrcweir #endif
1168cdf0e10cSrcweir     }
1169cdf0e10cSrcweir }
1170cdf0e10cSrcweir 
1171cdf0e10cSrcweir 
1172cdf0e10cSrcweir 
1173cdf0e10cSrcweir 
1174cdf0e10cSrcweir 
1175