2 * COM proxy implementation
4 * Copyright 2001 Ove Kåven, TransGaming Technologies
5 * Copyright 2009 Alexandre Julliard
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
35 #include "ndr_stubless.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
41 static const IRpcProxyBufferVtbl StdProxy_Vtbl
;
43 static inline StdProxyImpl
*impl_from_IRpcProxyBuffer(IRpcProxyBuffer
*iface
)
45 return CONTAINING_RECORD(iface
, StdProxyImpl
, IRpcProxyBuffer_iface
);
48 static inline StdProxyImpl
*impl_from_proxy_obj( void *iface
)
50 return CONTAINING_RECORD(iface
, StdProxyImpl
, PVtbl
);
53 extern void ObjectStublessClient3(void);
54 extern void ObjectStublessClient4(void);
56 BOOL
fill_stubless_table( IUnknownVtbl
*vtbl
, DWORD num
)
58 size_t entry_size
= (char *)ObjectStublessClient4
- (char *)ObjectStublessClient3
;
59 const void **entry
= (const void **)(vtbl
+ 1);
62 if (num
>= NB_THUNK_ENTRIES
)
64 FIXME( "%lu methods not supported\n", num
);
67 for (i
= 0; i
< num
- 3; i
++, entry
++)
68 if (*entry
== (void *)-1) *entry
= (char *)ObjectStublessClient3
+ i
* entry_size
;
73 HRESULT
StdProxy_Construct(REFIID riid
,
75 const ProxyFileInfo
*ProxyInfo
,
77 LPPSFACTORYBUFFER pPSFactory
,
78 LPRPCPROXYBUFFER
*ppProxy
,
82 PCInterfaceName name
= ProxyInfo
->pNamesArray
[Index
];
83 CInterfaceProxyVtbl
*vtbl
= ProxyInfo
->pProxyVtblList
[Index
];
85 TRACE("(%p,%p,%p,%p,%p) %s\n", pUnkOuter
, vtbl
, pPSFactory
, ppProxy
, ppvObj
, name
);
87 /* TableVersion = 2 means it is the stubless version of CInterfaceProxyVtbl */
88 if (ProxyInfo
->TableVersion
> 1) {
89 ULONG count
= ProxyInfo
->pStubVtblList
[Index
]->header
.DispatchTableCount
;
90 vtbl
= (CInterfaceProxyVtbl
*)((const void **)vtbl
+ 1);
91 TRACE("stubless vtbl %p: count=%ld\n", vtbl
->Vtbl
, count
);
92 fill_stubless_table( (IUnknownVtbl
*)vtbl
->Vtbl
, count
);
95 if (!IsEqualGUID(vtbl
->header
.piid
, riid
)) {
96 ERR("IID mismatch during proxy creation\n");
97 return RPC_E_UNEXPECTED
;
100 This
= calloc(1, sizeof(StdProxyImpl
));
101 if (!This
) return E_OUTOFMEMORY
;
103 if (!pUnkOuter
) pUnkOuter
= (IUnknown
*)&This
->IRpcProxyBuffer_iface
;
104 This
->IRpcProxyBuffer_iface
.lpVtbl
= &StdProxy_Vtbl
;
105 This
->PVtbl
= vtbl
->Vtbl
;
106 /* one reference for the proxy */
108 This
->piid
= vtbl
->header
.piid
;
109 This
->base_object
= NULL
;
110 This
->base_proxy
= NULL
;
111 This
->pUnkOuter
= pUnkOuter
;
113 This
->pPSFactory
= pPSFactory
;
114 This
->pChannel
= NULL
;
116 if(ProxyInfo
->pDelegatedIIDs
&& ProxyInfo
->pDelegatedIIDs
[Index
])
118 HRESULT r
= create_proxy( ProxyInfo
->pDelegatedIIDs
[Index
], NULL
,
119 &This
->base_proxy
, (void **)&This
->base_object
);
127 *ppProxy
= &This
->IRpcProxyBuffer_iface
;
128 *ppvObj
= &This
->PVtbl
;
129 IUnknown_AddRef((IUnknown
*)*ppvObj
);
130 IPSFactoryBuffer_AddRef(pPSFactory
);
132 TRACE( "iid=%s this %p proxy %p obj %p vtbl %p base proxy %p base obj %p\n",
133 debugstr_guid(riid
), This
, *ppProxy
, *ppvObj
, This
->PVtbl
, This
->base_proxy
, This
->base_object
);
137 HRESULT WINAPI
StdProxy_QueryInterface(IRpcProxyBuffer
*iface
, REFIID riid
, void **obj
)
139 StdProxyImpl
*This
= impl_from_IRpcProxyBuffer(iface
);
140 TRACE("(%p)->QueryInterface(%s,%p)\n",This
,debugstr_guid(riid
),obj
);
142 if (IsEqualGUID(&IID_IUnknown
,riid
) ||
143 IsEqualGUID(This
->piid
,riid
)) {
145 InterlockedIncrement(&This
->RefCount
);
149 if (IsEqualGUID(&IID_IRpcProxyBuffer
,riid
)) {
150 *obj
= &This
->IRpcProxyBuffer_iface
;
151 InterlockedIncrement(&This
->RefCount
);
155 return E_NOINTERFACE
;
158 ULONG WINAPI
StdProxy_AddRef(IRpcProxyBuffer
*iface
)
160 StdProxyImpl
*This
= impl_from_IRpcProxyBuffer(iface
);
161 TRACE("(%p)->AddRef()\n",This
);
163 return InterlockedIncrement(&This
->RefCount
);
166 static ULONG WINAPI
StdProxy_Release(LPRPCPROXYBUFFER iface
)
169 StdProxyImpl
*This
= impl_from_IRpcProxyBuffer(iface
);
170 TRACE("(%p)->Release()\n",This
);
172 refs
= InterlockedDecrement(&This
->RefCount
);
176 IRpcProxyBuffer_Disconnect(&This
->IRpcProxyBuffer_iface
);
178 if (This
->base_object
) IUnknown_Release( This
->base_object
);
179 if (This
->base_proxy
) IRpcProxyBuffer_Release( This
->base_proxy
);
181 IPSFactoryBuffer_Release(This
->pPSFactory
);
188 HRESULT WINAPI
StdProxy_Connect(IRpcProxyBuffer
*iface
, IRpcChannelBuffer
*pChannel
)
190 StdProxyImpl
*This
= impl_from_IRpcProxyBuffer(iface
);
191 TRACE("(%p)->Connect(%p)\n",This
,pChannel
);
193 This
->pChannel
= pChannel
;
194 IRpcChannelBuffer_AddRef(pChannel
);
195 if (This
->base_proxy
) IRpcProxyBuffer_Connect( This
->base_proxy
, pChannel
);
199 void WINAPI
StdProxy_Disconnect(IRpcProxyBuffer
*iface
)
201 StdProxyImpl
*This
= impl_from_IRpcProxyBuffer(iface
);
202 TRACE("(%p)->Disconnect()\n",This
);
204 if (This
->base_proxy
) IRpcProxyBuffer_Disconnect( This
->base_proxy
);
206 IRpcChannelBuffer_Release(This
->pChannel
);
207 This
->pChannel
= NULL
;
210 static const IRpcProxyBufferVtbl StdProxy_Vtbl
=
212 StdProxy_QueryInterface
,
219 static void StdProxy_GetChannel(LPVOID iface
,
220 LPRPCCHANNELBUFFER
*ppChannel
)
222 StdProxyImpl
*This
= impl_from_proxy_obj( iface
);
223 TRACE("(%p)->GetChannel(%p) %s\n",This
,ppChannel
,This
->name
);
226 IRpcChannelBuffer_AddRef(This
->pChannel
);
228 *ppChannel
= This
->pChannel
;
231 static void StdProxy_GetIID(LPVOID iface
,
234 StdProxyImpl
*This
= impl_from_proxy_obj( iface
);
235 TRACE("(%p)->GetIID(%p) %s\n",This
,ppiid
,This
->name
);
240 HRESULT WINAPI
IUnknown_QueryInterface_Proxy(LPUNKNOWN iface
,
244 StdProxyImpl
*This
= impl_from_proxy_obj( iface
);
245 TRACE("(%p)->QueryInterface(%s,%p) %s\n",This
,debugstr_guid(riid
),ppvObj
,This
->name
);
246 return IUnknown_QueryInterface(This
->pUnkOuter
,riid
,ppvObj
);
249 ULONG WINAPI
IUnknown_AddRef_Proxy(LPUNKNOWN iface
)
251 StdProxyImpl
*This
= impl_from_proxy_obj( iface
);
252 TRACE("(%p)->AddRef() %s\n",This
,This
->name
);
253 return IUnknown_AddRef(This
->pUnkOuter
);
256 ULONG WINAPI
IUnknown_Release_Proxy(LPUNKNOWN iface
)
258 StdProxyImpl
*This
= impl_from_proxy_obj( iface
);
259 TRACE("(%p)->Release() %s\n",This
,This
->name
);
260 return IUnknown_Release(This
->pUnkOuter
);
263 /***********************************************************************
264 * NdrProxyInitialize [RPCRT4.@]
266 void WINAPI
NdrProxyInitialize(void *This
,
267 PRPC_MESSAGE pRpcMsg
,
268 PMIDL_STUB_MESSAGE pStubMsg
,
269 PMIDL_STUB_DESC pStubDescriptor
,
270 unsigned int ProcNum
)
272 TRACE("(%p,%p,%p,%p,%d)\n", This
, pRpcMsg
, pStubMsg
, pStubDescriptor
, ProcNum
);
273 NdrClientInitializeNew(pRpcMsg
, pStubMsg
, pStubDescriptor
, ProcNum
);
274 StdProxy_GetChannel(This
, &pStubMsg
->pRpcChannelBuffer
);
275 if (!pStubMsg
->pRpcChannelBuffer
)
276 RpcRaiseException(CO_E_OBJNOTCONNECTED
);
277 IRpcChannelBuffer_GetDestCtx(pStubMsg
->pRpcChannelBuffer
,
278 &pStubMsg
->dwDestContext
,
279 &pStubMsg
->pvDestContext
);
280 TRACE("channel=%p\n", pStubMsg
->pRpcChannelBuffer
);
283 /***********************************************************************
284 * NdrProxyGetBuffer [RPCRT4.@]
286 void WINAPI
NdrProxyGetBuffer(void *This
,
287 PMIDL_STUB_MESSAGE pStubMsg
)
290 const IID
*riid
= NULL
;
292 TRACE("(%p,%p)\n", This
, pStubMsg
);
293 pStubMsg
->RpcMsg
->BufferLength
= pStubMsg
->BufferLength
;
294 pStubMsg
->dwStubPhase
= PROXY_GETBUFFER
;
295 StdProxy_GetIID(This
, &riid
);
296 hr
= IRpcChannelBuffer_GetBuffer(pStubMsg
->pRpcChannelBuffer
,
297 (RPCOLEMESSAGE
*)pStubMsg
->RpcMsg
,
301 RpcRaiseException(hr
);
304 pStubMsg
->fBufferValid
= TRUE
;
305 pStubMsg
->BufferStart
= pStubMsg
->RpcMsg
->Buffer
;
306 pStubMsg
->BufferEnd
= pStubMsg
->BufferStart
+ pStubMsg
->BufferLength
;
307 pStubMsg
->Buffer
= pStubMsg
->BufferStart
;
308 pStubMsg
->dwStubPhase
= PROXY_MARSHAL
;
311 /***********************************************************************
312 * NdrProxySendReceive [RPCRT4.@]
314 void WINAPI
NdrProxySendReceive(void *This
,
315 PMIDL_STUB_MESSAGE pStubMsg
)
320 TRACE("(%p,%p)\n", This
, pStubMsg
);
322 if (!pStubMsg
->pRpcChannelBuffer
)
324 WARN("Trying to use disconnected proxy %p\n", This
);
325 RpcRaiseException(RPC_E_DISCONNECTED
);
328 pStubMsg
->dwStubPhase
= PROXY_SENDRECEIVE
;
329 /* avoid sending uninitialised parts of the buffer on the wire */
330 pStubMsg
->RpcMsg
->BufferLength
= pStubMsg
->Buffer
- (unsigned char *)pStubMsg
->RpcMsg
->Buffer
;
331 hr
= IRpcChannelBuffer_SendReceive(pStubMsg
->pRpcChannelBuffer
,
332 (RPCOLEMESSAGE
*)pStubMsg
->RpcMsg
,
334 pStubMsg
->dwStubPhase
= PROXY_UNMARSHAL
;
335 pStubMsg
->BufferLength
= pStubMsg
->RpcMsg
->BufferLength
;
336 pStubMsg
->BufferStart
= pStubMsg
->RpcMsg
->Buffer
;
337 pStubMsg
->BufferEnd
= pStubMsg
->BufferStart
+ pStubMsg
->BufferLength
;
338 pStubMsg
->Buffer
= pStubMsg
->BufferStart
;
340 /* raise exception if call failed */
341 if (hr
== RPC_S_CALL_FAILED
) RpcRaiseException(*(DWORD
*)pStubMsg
->Buffer
);
342 else if (FAILED(hr
)) RpcRaiseException(hr
);
345 /***********************************************************************
346 * NdrProxyFreeBuffer [RPCRT4.@]
348 void WINAPI
NdrProxyFreeBuffer(void *This
,
349 PMIDL_STUB_MESSAGE pStubMsg
)
351 TRACE("(%p,%p)\n", This
, pStubMsg
);
353 if (pStubMsg
->fBufferValid
)
355 IRpcChannelBuffer_FreeBuffer(pStubMsg
->pRpcChannelBuffer
,
356 (RPCOLEMESSAGE
*)pStubMsg
->RpcMsg
);
357 pStubMsg
->fBufferValid
= FALSE
;
359 IRpcChannelBuffer_Release(pStubMsg
->pRpcChannelBuffer
);
360 pStubMsg
->pRpcChannelBuffer
= NULL
;
363 /***********************************************************************
364 * NdrProxyErrorHandler [RPCRT4.@]
366 HRESULT WINAPI
NdrProxyErrorHandler(DWORD dwExceptionCode
)
368 WARN("(0x%08lx): a proxy call failed\n", dwExceptionCode
);
370 if (FAILED(dwExceptionCode
))
371 return dwExceptionCode
;
373 return HRESULT_FROM_WIN32(dwExceptionCode
);