2 * OLE32 proxy/stub handler
4 * Copyright 2002 Marcus Meissner
5 * Copyright 2001 Ove Kåven, TransGaming Technologies
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
22 /* Documentation on MSDN:
24 * (Top level COM documentation)
25 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnanchor/html/componentdevelopmentank.asp
28 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/com/htm/comext_1q0p.asp
31 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/com/htm/comext_1lia.asp
34 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/com/htm/comext_1gfn.asp
46 #define NONAMELESSUNION
47 #define NONAMELESSSTRUCT
59 #include "compobj_private.h"
62 #include "comcat.h" /* FOR HACK BELOW */
64 #include "wine/debug.h"
66 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
70 static ULONG WINAPI
RURpcProxyBufferImpl_Release(LPRPCPROXYBUFFER iface
);
72 /* From: http://msdn.microsoft.com/library/en-us/com/cmi_m_4lda.asp
74 * The first time a client requests a pointer to an interface on a
75 * particular object, COM loads an IClassFactory stub in the server
76 * process and uses it to marshal the first pointer back to the
77 * client. In the client process, COM loads the generic proxy for the
78 * class factory object and calls its implementation of IMarshal to
79 * unmarshal that first pointer. COM then creates the first interface
80 * proxy and hands it a pointer to the RPC channel. Finally, COM returns
81 * the IClassFactory pointer to the client, which uses it to call
82 * IClassFactory::CreateInstance, passing it a reference to the interface.
84 * Back in the server process, COM now creates a new instance of the
85 * object, along with a stub for the requested interface. This stub marshals
86 * the interface pointer back to the client process, where another object
87 * proxy is created, this time for the object itself. Also created is a
88 * proxy for the requested interface, a pointer to which is returned to
89 * the client. With subsequent calls to other interfaces on the object,
90 * COM will load the appropriate interface stubs and proxies as needed.
92 typedef struct _CFStub
{
93 const IRpcStubBufferVtbl
*lpvtbl
;
100 CFStub_QueryInterface(LPRPCSTUBBUFFER iface
, REFIID riid
, LPVOID
*ppv
) {
101 if (IsEqualIID(&IID_IUnknown
,riid
)||IsEqualIID(&IID_IRpcStubBuffer
,riid
)) {
102 *ppv
= (LPVOID
)iface
;
103 IUnknown_AddRef(iface
);
106 FIXME("(%s), interface not supported.\n",debugstr_guid(riid
));
107 return E_NOINTERFACE
;
111 CFStub_AddRef(LPRPCSTUBBUFFER iface
) {
112 CFStub
*This
= (CFStub
*)iface
;
113 return InterlockedIncrement(&This
->ref
);
117 CFStub_Release(LPRPCSTUBBUFFER iface
) {
118 CFStub
*This
= (CFStub
*)iface
;
121 ref
= InterlockedDecrement(&This
->ref
);
123 IRpcStubBuffer_Disconnect(iface
);
124 HeapFree(GetProcessHeap(),0,This
);
129 static HRESULT WINAPI
130 CFStub_Connect(LPRPCSTUBBUFFER iface
, IUnknown
*pUnkServer
) {
131 CFStub
*This
= (CFStub
*)iface
;
133 This
->pUnkServer
= pUnkServer
;
134 IUnknown_AddRef(pUnkServer
);
139 CFStub_Disconnect(LPRPCSTUBBUFFER iface
) {
140 CFStub
*This
= (CFStub
*)iface
;
142 if (This
->pUnkServer
) {
143 IUnknown_Release(This
->pUnkServer
);
144 This
->pUnkServer
= NULL
;
148 static HRESULT WINAPI
150 LPRPCSTUBBUFFER iface
,RPCOLEMESSAGE
* msg
,IRpcChannelBuffer
* chanbuf
152 CFStub
*This
= (CFStub
*)iface
;
155 if (msg
->iMethod
== 3) { /* CreateInstance */
157 IClassFactory
*classfac
;
161 ULARGE_INTEGER newpos
;
162 LARGE_INTEGER seekto
;
165 if (msg
->cbBuffer
< sizeof(IID
)) {
166 FIXME("Not enough bytes in buffer (%d)?\n",msg
->cbBuffer
);
169 memcpy(&iid
,msg
->Buffer
,sizeof(iid
));
170 TRACE("->CreateInstance(%s)\n",debugstr_guid(&iid
));
171 hres
= IUnknown_QueryInterface(This
->pUnkServer
,&IID_IClassFactory
,(LPVOID
*)&classfac
);
173 FIXME("Ole server does not provide an IClassFactory?\n");
176 hres
= IClassFactory_CreateInstance(classfac
,NULL
,&iid
,(LPVOID
*)&ppv
);
177 IClassFactory_Release(classfac
);
180 FIXME("Failed to create an instance of %s\n",debugstr_guid(&iid
));
183 hres
= CreateStreamOnHGlobal(0,TRUE
,&pStm
);
185 FIXME("Failed to create stream on hglobal\n");
188 hres
= IStream_Write(pStm
, &ppv
, sizeof(ppv
), NULL
);
190 ERR("IStream_Write failed, 0x%08x\n", hres
);
194 hres
= CoMarshalInterface(pStm
,&iid
,ppv
,0,NULL
,0);
195 IUnknown_Release(ppv
);
197 FIXME("CoMarshalInterface failed, %x!\n",hres
);
201 hres
= IStream_Stat(pStm
,&ststg
,0);
203 FIXME("Stat failed.\n");
207 msg
->cbBuffer
= ststg
.cbSize
.u
.LowPart
;
210 IRpcChannelBuffer_GetBuffer(chanbuf
, msg
, &IID_IClassFactory
);
211 if (hres
) return hres
;
213 seekto
.u
.LowPart
= 0;seekto
.u
.HighPart
= 0;
214 hres
= IStream_Seek(pStm
,seekto
,SEEK_SET
,&newpos
);
216 FIXME("IStream_Seek failed, %x\n",hres
);
219 hres
= IStream_Read(pStm
,msg
->Buffer
,msg
->cbBuffer
,&res
);
221 FIXME("Stream Read failed, %x\n",hres
);
224 IStream_Release(pStm
);
227 FIXME("(%p,%p), stub!\n",msg
,chanbuf
);
228 FIXME("iMethod is %d\n",msg
->iMethod
);
229 FIXME("cbBuffer is %d\n",msg
->cbBuffer
);
233 static LPRPCSTUBBUFFER WINAPI
234 CFStub_IsIIDSupported(LPRPCSTUBBUFFER iface
,REFIID riid
) {
235 FIXME("(%s), stub!\n",debugstr_guid(riid
));
240 CFStub_CountRefs(LPRPCSTUBBUFFER iface
) {
241 FIXME("(), stub!\n");
245 static HRESULT WINAPI
246 CFStub_DebugServerQueryInterface(LPRPCSTUBBUFFER iface
,void** ppv
) {
247 FIXME("(%p), stub!\n",ppv
);
251 CFStub_DebugServerRelease(LPRPCSTUBBUFFER iface
,void *pv
) {
252 FIXME("(%p), stub!\n",pv
);
255 static const IRpcStubBufferVtbl cfstubvt
= {
256 CFStub_QueryInterface
,
262 CFStub_IsIIDSupported
,
264 CFStub_DebugServerQueryInterface
,
265 CFStub_DebugServerRelease
269 CFStub_Construct(LPRPCSTUBBUFFER
*ppv
) {
271 cfstub
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(CFStub
));
273 return E_OUTOFMEMORY
;
274 *ppv
= (LPRPCSTUBBUFFER
)cfstub
;
275 cfstub
->lpvtbl
= &cfstubvt
;
280 /* Since we create proxy buffers and classfactory in a pair, there is
281 * no need for 2 separate structs. Just put them in one, but remember
284 typedef struct _CFProxy
{
285 const IClassFactoryVtbl
*lpvtbl_cf
;
286 const IRpcProxyBufferVtbl
*lpvtbl_proxy
;
289 IRpcChannelBuffer
*chanbuf
;
290 IUnknown
*outer_unknown
;
293 static HRESULT WINAPI
IRpcProxyBufferImpl_QueryInterface(LPRPCPROXYBUFFER iface
,REFIID riid
,LPVOID
*ppv
) {
295 if (IsEqualIID(riid
,&IID_IRpcProxyBuffer
)||IsEqualIID(riid
,&IID_IUnknown
)) {
296 IRpcProxyBuffer_AddRef(iface
);
297 *ppv
= (LPVOID
)iface
;
300 FIXME("(%s), no interface.\n",debugstr_guid(riid
));
301 return E_NOINTERFACE
;
304 static ULONG WINAPI
IRpcProxyBufferImpl_AddRef(LPRPCPROXYBUFFER iface
) {
305 ICOM_THIS_MULTI(CFProxy
,lpvtbl_proxy
,iface
);
306 return InterlockedIncrement(&This
->ref
);
309 static ULONG WINAPI
IRpcProxyBufferImpl_Release(LPRPCPROXYBUFFER iface
) {
310 ICOM_THIS_MULTI(CFProxy
,lpvtbl_proxy
,iface
);
311 ULONG ref
= InterlockedDecrement(&This
->ref
);
314 IRpcProxyBuffer_Disconnect(iface
);
315 HeapFree(GetProcessHeap(),0,This
);
320 static HRESULT WINAPI
IRpcProxyBufferImpl_Connect(LPRPCPROXYBUFFER iface
,IRpcChannelBuffer
* pRpcChannelBuffer
) {
321 ICOM_THIS_MULTI(CFProxy
,lpvtbl_proxy
,iface
);
323 This
->chanbuf
= pRpcChannelBuffer
;
324 IRpcChannelBuffer_AddRef(This
->chanbuf
);
327 static void WINAPI
IRpcProxyBufferImpl_Disconnect(LPRPCPROXYBUFFER iface
) {
328 ICOM_THIS_MULTI(CFProxy
,lpvtbl_proxy
,iface
);
330 IRpcChannelBuffer_Release(This
->chanbuf
);
331 This
->chanbuf
= NULL
;
335 static HRESULT WINAPI
336 CFProxy_QueryInterface(LPCLASSFACTORY iface
,REFIID riid
, LPVOID
*ppv
) {
337 ICOM_THIS_MULTI(CFProxy
,lpvtbl_cf
,iface
);
338 if (This
->outer_unknown
) return IUnknown_QueryInterface(This
->outer_unknown
, riid
, ppv
);
340 if (IsEqualIID(&IID_IClassFactory
,riid
) || IsEqualIID(&IID_IUnknown
,riid
)) {
341 *ppv
= (LPVOID
)iface
;
342 IClassFactory_AddRef(iface
);
345 if (IsEqualIID(riid
,&IID_IMarshal
)) /* just to avoid debug output */
346 return E_NOINTERFACE
;
347 FIXME("Unhandled interface: %s\n",debugstr_guid(riid
));
348 return E_NOINTERFACE
;
351 static ULONG WINAPI
CFProxy_AddRef(LPCLASSFACTORY iface
) {
352 ICOM_THIS_MULTI(CFProxy
,lpvtbl_cf
,iface
);
353 if (This
->outer_unknown
) return IUnknown_AddRef(This
->outer_unknown
);
354 return InterlockedIncrement(&This
->ref
);
357 static ULONG WINAPI
CFProxy_Release(LPCLASSFACTORY iface
) {
358 ICOM_THIS_MULTI(CFProxy
,lpvtbl_cf
,iface
);
359 if (This
->outer_unknown
)
360 return IUnknown_Release(This
->outer_unknown
);
362 return IRpcProxyBufferImpl_Release((IRpcProxyBuffer
*)&This
->lpvtbl_proxy
);
365 static HRESULT WINAPI
CFProxy_CreateInstance(
366 LPCLASSFACTORY iface
,
367 LPUNKNOWN pUnkOuter
,/* [in] */
368 REFIID riid
, /* [in] */
369 LPVOID
*ppv
/* [out] */
371 ICOM_THIS_MULTI(CFProxy
,lpvtbl_cf
,iface
);
378 TRACE("(%p,%s,%p)\n",pUnkOuter
,debugstr_guid(riid
),ppv
);
380 /* Send CreateInstance to the remote classfactory.
382 * Data: Only the 'IID'.
385 msg
.cbBuffer
= sizeof(*riid
);
387 hres
= IRpcChannelBuffer_GetBuffer(This
->chanbuf
,&msg
,&IID_IClassFactory
);
389 FIXME("IRpcChannelBuffer_GetBuffer failed with %x?\n",hres
);
392 memcpy(msg
.Buffer
,riid
,sizeof(*riid
));
393 hres
= IRpcChannelBuffer_SendReceive(This
->chanbuf
,&msg
,&srstatus
);
395 FIXME("IRpcChannelBuffer_SendReceive failed with %x?\n",hres
);
396 IRpcChannelBuffer_FreeBuffer(This
->chanbuf
,&msg
);
400 if (!msg
.cbBuffer
) { /* interface not found on remote */
401 IRpcChannelBuffer_FreeBuffer(This
->chanbuf
,&msg
);
405 /* We got back: [Marshalled Interface data] */
406 TRACE("got %d bytes data.\n",msg
.cbBuffer
);
407 hGlobal
= GlobalAlloc(GMEM_MOVEABLE
|GMEM_NODISCARD
|GMEM_SHARE
,msg
.cbBuffer
);
408 memcpy(GlobalLock(hGlobal
),msg
.Buffer
,msg
.cbBuffer
);
409 hres
= CreateStreamOnHGlobal(hGlobal
,TRUE
,&pStream
);
411 FIXME("CreateStreamOnHGlobal failed with %x\n",hres
);
412 IRpcChannelBuffer_FreeBuffer(This
->chanbuf
,&msg
);
415 hres
= IStream_Read(pStream
, ppv
, sizeof(*ppv
), NULL
);
419 hres
= CoUnmarshalInterface(
425 IStream_Release(pStream
); /* Does GlobalFree hGlobal too. */
427 IRpcChannelBuffer_FreeBuffer(This
->chanbuf
,&msg
);
430 FIXME("CoMarshalInterface failed, %x\n",hres
);
436 static HRESULT WINAPI
CFProxy_LockServer(LPCLASSFACTORY iface
,BOOL fLock
) {
437 /*ICOM_THIS_MULTI(CFProxy,lpvtbl_cf,iface);*/
438 FIXME("(%d), stub!\n",fLock
);
439 /* basically: write BOOL, read empty */
443 static const IRpcProxyBufferVtbl pspbvtbl
= {
444 IRpcProxyBufferImpl_QueryInterface
,
445 IRpcProxyBufferImpl_AddRef
,
446 IRpcProxyBufferImpl_Release
,
447 IRpcProxyBufferImpl_Connect
,
448 IRpcProxyBufferImpl_Disconnect
450 static const IClassFactoryVtbl cfproxyvt
= {
451 CFProxy_QueryInterface
,
454 CFProxy_CreateInstance
,
459 CFProxy_Construct(IUnknown
*pUnkOuter
, LPVOID
*ppv
,LPVOID
*ppProxy
) {
462 cf
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(CFProxy
));
464 return E_OUTOFMEMORY
;
466 cf
->lpvtbl_cf
= &cfproxyvt
;
467 cf
->lpvtbl_proxy
= &pspbvtbl
;
468 /* one reference for the proxy buffer */
470 cf
->outer_unknown
= pUnkOuter
;
471 *ppv
= &(cf
->lpvtbl_cf
);
472 *ppProxy
= &(cf
->lpvtbl_proxy
);
473 /* and one reference for the object */
474 IUnknown_AddRef((IUnknown
*)*ppv
);
479 /********************* IRemUnknown Proxy/Stub ********************************/
483 const IRpcStubBufferVtbl
*lpVtbl
;
488 static HRESULT WINAPI
RemUnkStub_QueryInterface(LPRPCSTUBBUFFER iface
,
492 RemUnkStub
*This
= (RemUnkStub
*)iface
;
493 TRACE("(%p)->QueryInterface(%s,%p)\n",This
,debugstr_guid(riid
),obj
);
494 if (IsEqualGUID(&IID_IUnknown
,riid
) ||
495 IsEqualGUID(&IID_IRpcStubBuffer
,riid
)) {
499 return E_NOINTERFACE
;
502 static ULONG WINAPI
RemUnkStub_AddRef(LPRPCSTUBBUFFER iface
)
504 RemUnkStub
*This
= (RemUnkStub
*)iface
;
505 TRACE("(%p)->AddRef()\n",This
);
506 return InterlockedIncrement(&This
->refs
);
509 static ULONG WINAPI
RemUnkStub_Release(LPRPCSTUBBUFFER iface
)
511 RemUnkStub
*This
= (RemUnkStub
*)iface
;
513 TRACE("(%p)->Release()\n",This
);
514 refs
= InterlockedDecrement(&This
->refs
);
516 HeapFree(GetProcessHeap(), 0, This
);
520 static HRESULT WINAPI
RemUnkStub_Connect(LPRPCSTUBBUFFER iface
,
521 LPUNKNOWN lpUnkServer
)
523 RemUnkStub
*This
= (RemUnkStub
*)iface
;
524 TRACE("(%p)->Connect(%p)\n",This
,lpUnkServer
);
525 This
->iface
= (IRemUnknown
*)lpUnkServer
;
526 IRemUnknown_AddRef(This
->iface
);
530 static void WINAPI
RemUnkStub_Disconnect(LPRPCSTUBBUFFER iface
)
532 RemUnkStub
*This
= (RemUnkStub
*)iface
;
533 TRACE("(%p)->Disconnect()\n",This
);
534 IUnknown_Release(This
->iface
);
538 static HRESULT WINAPI
RemUnkStub_Invoke(LPRPCSTUBBUFFER iface
,
540 LPRPCCHANNELBUFFER pChannel
)
542 RemUnkStub
*This
= (RemUnkStub
*)iface
;
543 ULONG iMethod
= pMsg
->iMethod
;
544 LPBYTE buf
= pMsg
->Buffer
;
545 HRESULT hr
= RPC_E_INVALIDMETHOD
;
547 TRACE("(%p)->Invoke(%p,%p) method %d\n", This
, pMsg
, pChannel
, iMethod
);
550 case 3: /* RemQueryInterface */
556 REMQIRESULT
*pQIResults
= NULL
;
559 memcpy(&ipid
, buf
, sizeof(ipid
));
561 memcpy(&cRefs
, buf
, sizeof(cRefs
));
562 buf
+= sizeof(cRefs
);
563 memcpy(&cIids
, buf
, sizeof(cIids
));
564 buf
+= sizeof(cIids
);
567 hr
= IRemUnknown_RemQueryInterface(This
->iface
, &ipid
, cRefs
, cIids
, iids
, &pQIResults
);
570 pMsg
->cbBuffer
= cIids
* sizeof(REMQIRESULT
) + sizeof(HRESULT
);
572 IRpcChannelBuffer_GetBuffer(pChannel
, pMsg
, &IID_IRemUnknown
);
575 *(HRESULT
*)buf
= hr
;
576 buf
+= sizeof(HRESULT
);
579 /* FIXME: pQIResults is a unique pointer so pQIResults can be NULL! */
580 memcpy(buf
, pQIResults
, cIids
* sizeof(REMQIRESULT
));
584 case 4: /* RemAddRef */
591 memcpy(&cIids
, buf
, sizeof(USHORT
));
592 buf
+= sizeof(USHORT
);
593 ir
= (REMINTERFACEREF
*)buf
;
594 pResults
= CoTaskMemAlloc(cIids
* sizeof(HRESULT
));
595 if (!pResults
) return E_OUTOFMEMORY
;
597 hr
= IRemUnknown_RemAddRef(This
->iface
, cIids
, ir
, pResults
);
600 pMsg
->cbBuffer
= cIids
* sizeof(HRESULT
);
602 IRpcChannelBuffer_GetBuffer(pChannel
, pMsg
, &IID_IRemUnknown
);
606 memcpy(buf
, pResults
, cIids
* sizeof(HRESULT
));
609 CoTaskMemFree(pResults
);
613 case 5: /* RemRelease */
619 memcpy(&cIids
, buf
, sizeof(USHORT
));
620 buf
+= sizeof(USHORT
);
621 ir
= (REMINTERFACEREF
*)buf
;
623 hr
= IRemUnknown_RemRelease(This
->iface
, cIids
, ir
);
627 IRpcChannelBuffer_GetBuffer(pChannel
, pMsg
, &IID_IRemUnknown
);
634 static LPRPCSTUBBUFFER WINAPI
RemUnkStub_IsIIDSupported(LPRPCSTUBBUFFER iface
,
637 RemUnkStub
*This
= (RemUnkStub
*)iface
;
638 TRACE("(%p)->IsIIDSupported(%s)\n", This
, debugstr_guid(riid
));
639 return IsEqualGUID(&IID_IRemUnknown
, riid
) ? iface
: NULL
;
642 static ULONG WINAPI
RemUnkStub_CountRefs(LPRPCSTUBBUFFER iface
)
644 RemUnkStub
*This
= (RemUnkStub
*)iface
;
645 FIXME("(%p)->CountRefs()\n", This
);
649 static HRESULT WINAPI
RemUnkStub_DebugServerQueryInterface(LPRPCSTUBBUFFER iface
,
652 RemUnkStub
*This
= (RemUnkStub
*)iface
;
653 FIXME("(%p)->DebugServerQueryInterface(%p)\n",This
,ppv
);
654 return E_NOINTERFACE
;
657 static void WINAPI
RemUnkStub_DebugServerRelease(LPRPCSTUBBUFFER iface
,
660 RemUnkStub
*This
= (RemUnkStub
*)iface
;
661 FIXME("(%p)->DebugServerRelease(%p)\n", This
, pv
);
664 static const IRpcStubBufferVtbl RemUnkStub_VTable
=
666 RemUnkStub_QueryInterface
,
670 RemUnkStub_Disconnect
,
672 RemUnkStub_IsIIDSupported
,
673 RemUnkStub_CountRefs
,
674 RemUnkStub_DebugServerQueryInterface
,
675 RemUnkStub_DebugServerRelease
678 static HRESULT
RemUnkStub_Construct(IRpcStubBuffer
**ppStub
)
680 RemUnkStub
*This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
681 if (!This
) return E_OUTOFMEMORY
;
682 This
->lpVtbl
= &RemUnkStub_VTable
;
685 *ppStub
= (IRpcStubBuffer
*)This
;
690 typedef struct _RemUnkProxy
{
691 const IRemUnknownVtbl
*lpvtbl_remunk
;
692 const IRpcProxyBufferVtbl
*lpvtbl_proxy
;
695 IRpcChannelBuffer
*chan
;
696 IUnknown
*outer_unknown
;
699 static HRESULT WINAPI
RemUnkProxy_QueryInterface(LPREMUNKNOWN iface
, REFIID riid
, void **ppv
)
701 RemUnkProxy
*This
= (RemUnkProxy
*)iface
;
702 if (This
->outer_unknown
)
703 return IUnknown_QueryInterface(This
->outer_unknown
, riid
, ppv
);
704 if (IsEqualIID(riid
, &IID_IUnknown
) ||
705 IsEqualIID(riid
, &IID_IRemUnknown
))
707 IRemUnknown_AddRef(iface
);
708 *ppv
= (LPVOID
)iface
;
711 return E_NOINTERFACE
;
714 static ULONG WINAPI
RemUnkProxy_AddRef(LPREMUNKNOWN iface
)
716 RemUnkProxy
*This
= (RemUnkProxy
*)iface
;
719 TRACE("(%p)->AddRef()\n",This
);
721 if (This
->outer_unknown
)
722 refs
= IUnknown_AddRef(This
->outer_unknown
);
724 refs
= InterlockedIncrement(&This
->refs
);
728 static ULONG WINAPI
RemUnkProxy_Release(LPREMUNKNOWN iface
)
730 RemUnkProxy
*This
= (RemUnkProxy
*)iface
;
732 TRACE("(%p)->Release()\n",This
);
733 if (This
->outer_unknown
)
734 return IUnknown_Release(This
->outer_unknown
);
736 return IRpcProxyBufferImpl_Release((IRpcProxyBuffer
*)&This
->lpvtbl_proxy
);
739 static HRESULT WINAPI
RemUnkProxy_RemQueryInterface(LPREMUNKNOWN iface
,
744 REMQIRESULT
** ppQIResults
)
746 RemUnkProxy
*This
= (RemUnkProxy
*)iface
;
751 TRACE("(%p)->(%s,%d,%d,%p,%p)\n",This
,
752 debugstr_guid(ripid
),cRefs
,cIids
,iids
,ppQIResults
);
755 memset(&msg
, 0, sizeof(msg
));
757 msg
.cbBuffer
= sizeof(IPID
) + sizeof(ULONG
) +
758 sizeof(USHORT
) + cIids
*sizeof(IID
);
759 hr
= IRpcChannelBuffer_GetBuffer(This
->chan
, &msg
, &IID_IRemUnknown
);
761 LPBYTE buf
= msg
.Buffer
;
762 memcpy(buf
, ripid
, sizeof(IPID
));
764 memcpy(buf
, &cRefs
, sizeof(ULONG
));
765 buf
+= sizeof(ULONG
);
766 memcpy(buf
, &cIids
, sizeof(USHORT
));
767 buf
+= sizeof(USHORT
);
768 memcpy(buf
, iids
, cIids
*sizeof(IID
));
770 hr
= IRpcChannelBuffer_SendReceive(This
->chan
, &msg
, &status
);
775 hr
= *(HRESULT
*)buf
;
776 buf
+= sizeof(HRESULT
);
780 *ppQIResults
= CoTaskMemAlloc(cIids
*sizeof(REMQIRESULT
));
781 memcpy(*ppQIResults
, buf
, cIids
*sizeof(REMQIRESULT
));
784 IRpcChannelBuffer_FreeBuffer(This
->chan
, &msg
);
790 static HRESULT WINAPI
RemUnkProxy_RemAddRef(LPREMUNKNOWN iface
,
791 USHORT cInterfaceRefs
,
792 REMINTERFACEREF
* InterfaceRefs
,
795 RemUnkProxy
*This
= (RemUnkProxy
*)iface
;
800 TRACE("(%p)->(%d,%p,%p)\n",This
,
801 cInterfaceRefs
,InterfaceRefs
,pResults
);
803 memset(&msg
, 0, sizeof(msg
));
805 msg
.cbBuffer
= sizeof(USHORT
) + cInterfaceRefs
*sizeof(REMINTERFACEREF
);
806 hr
= IRpcChannelBuffer_GetBuffer(This
->chan
, &msg
, &IID_IRemUnknown
);
808 LPBYTE buf
= msg
.Buffer
;
809 memcpy(buf
, &cInterfaceRefs
, sizeof(USHORT
));
810 buf
+= sizeof(USHORT
);
811 memcpy(buf
, InterfaceRefs
, cInterfaceRefs
*sizeof(REMINTERFACEREF
));
813 hr
= IRpcChannelBuffer_SendReceive(This
->chan
, &msg
, &status
);
817 memcpy(pResults
, buf
, cInterfaceRefs
*sizeof(HRESULT
));
820 IRpcChannelBuffer_FreeBuffer(This
->chan
, &msg
);
826 static HRESULT WINAPI
RemUnkProxy_RemRelease(LPREMUNKNOWN iface
,
827 USHORT cInterfaceRefs
,
828 REMINTERFACEREF
* InterfaceRefs
)
830 RemUnkProxy
*This
= (RemUnkProxy
*)iface
;
835 TRACE("(%p)->(%d,%p)\n",This
,
836 cInterfaceRefs
,InterfaceRefs
);
838 memset(&msg
, 0, sizeof(msg
));
840 msg
.cbBuffer
= sizeof(USHORT
) + cInterfaceRefs
*sizeof(REMINTERFACEREF
);
841 hr
= IRpcChannelBuffer_GetBuffer(This
->chan
, &msg
, &IID_IRemUnknown
);
843 LPBYTE buf
= msg
.Buffer
;
844 memcpy(buf
, &cInterfaceRefs
, sizeof(USHORT
));
845 buf
+= sizeof(USHORT
);
846 memcpy(buf
, InterfaceRefs
, cInterfaceRefs
*sizeof(REMINTERFACEREF
));
848 hr
= IRpcChannelBuffer_SendReceive(This
->chan
, &msg
, &status
);
850 IRpcChannelBuffer_FreeBuffer(This
->chan
, &msg
);
856 static const IRemUnknownVtbl RemUnkProxy_VTable
=
858 RemUnkProxy_QueryInterface
,
861 RemUnkProxy_RemQueryInterface
,
862 RemUnkProxy_RemAddRef
,
863 RemUnkProxy_RemRelease
867 static HRESULT WINAPI
RURpcProxyBufferImpl_QueryInterface(LPRPCPROXYBUFFER iface
,REFIID riid
,LPVOID
*ppv
) {
869 if (IsEqualIID(riid
,&IID_IRpcProxyBuffer
)||IsEqualIID(riid
,&IID_IUnknown
)) {
870 IRpcProxyBuffer_AddRef(iface
);
871 *ppv
= (LPVOID
)iface
;
874 FIXME("(%s), no interface.\n",debugstr_guid(riid
));
875 return E_NOINTERFACE
;
878 static ULONG WINAPI
RURpcProxyBufferImpl_AddRef(LPRPCPROXYBUFFER iface
) {
879 ICOM_THIS_MULTI(RemUnkProxy
,lpvtbl_proxy
,iface
);
880 TRACE("%p, %d\n", iface
, This
->refs
+ 1);
881 return InterlockedIncrement(&This
->refs
);
884 static ULONG WINAPI
RURpcProxyBufferImpl_Release(LPRPCPROXYBUFFER iface
) {
885 ICOM_THIS_MULTI(RemUnkProxy
,lpvtbl_proxy
,iface
);
886 ULONG ref
= InterlockedDecrement(&This
->refs
);
887 TRACE("%p, %d\n", iface
, ref
);
889 IRpcProxyBuffer_Disconnect(iface
);
890 HeapFree(GetProcessHeap(),0,This
);
895 static HRESULT WINAPI
RURpcProxyBufferImpl_Connect(LPRPCPROXYBUFFER iface
,IRpcChannelBuffer
* pRpcChannelBuffer
) {
896 ICOM_THIS_MULTI(RemUnkProxy
,lpvtbl_proxy
,iface
);
898 TRACE("%p, %p\n", iface
, pRpcChannelBuffer
);
899 This
->chan
= pRpcChannelBuffer
;
900 IRpcChannelBuffer_AddRef(This
->chan
);
903 static void WINAPI
RURpcProxyBufferImpl_Disconnect(LPRPCPROXYBUFFER iface
) {
904 ICOM_THIS_MULTI(RemUnkProxy
,lpvtbl_proxy
,iface
);
905 TRACE("%p, %p\n", iface
, This
->chan
);
907 IRpcChannelBuffer_Release(This
->chan
);
913 static const IRpcProxyBufferVtbl RURpcProxyBuffer_VTable
= {
914 RURpcProxyBufferImpl_QueryInterface
,
915 RURpcProxyBufferImpl_AddRef
,
916 RURpcProxyBufferImpl_Release
,
917 RURpcProxyBufferImpl_Connect
,
918 RURpcProxyBufferImpl_Disconnect
922 RemUnkProxy_Construct(IUnknown
*pUnkOuter
, LPVOID
*ppv
,LPVOID
*ppProxy
) {
925 This
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(*This
));
927 return E_OUTOFMEMORY
;
929 This
->lpvtbl_remunk
= &RemUnkProxy_VTable
;
930 This
->lpvtbl_proxy
= &RURpcProxyBuffer_VTable
;
931 /* only one reference for the proxy buffer */
933 This
->outer_unknown
= pUnkOuter
;
934 *ppv
= &(This
->lpvtbl_remunk
);
935 *ppProxy
= &(This
->lpvtbl_proxy
);
936 /* and one reference for the object */
937 IUnknown_AddRef((IUnknown
*)*ppv
);
942 /********************* OLE Proxy/Stub Factory ********************************/
943 static HRESULT WINAPI
944 PSFacBuf_QueryInterface(LPPSFACTORYBUFFER iface
, REFIID iid
, LPVOID
*ppv
) {
945 if (IsEqualIID(iid
,&IID_IPSFactoryBuffer
)||IsEqualIID(iid
,&IID_IUnknown
)) {
946 *ppv
= (LPVOID
)iface
;
947 /* No ref counting, static class */
950 FIXME("(%s) unknown IID?\n",debugstr_guid(iid
));
951 return E_NOINTERFACE
;
954 static ULONG WINAPI
PSFacBuf_AddRef(LPPSFACTORYBUFFER iface
) { return 2; }
955 static ULONG WINAPI
PSFacBuf_Release(LPPSFACTORYBUFFER iface
) { return 1; }
957 static HRESULT WINAPI
958 PSFacBuf_CreateProxy(
959 LPPSFACTORYBUFFER iface
, IUnknown
* pUnkOuter
, REFIID riid
,
960 IRpcProxyBuffer
**ppProxy
, LPVOID
*ppv
962 if (IsEqualIID(&IID_IClassFactory
,riid
))
963 return CFProxy_Construct(pUnkOuter
, ppv
,(LPVOID
*)ppProxy
);
964 else if (IsEqualIID(&IID_IRemUnknown
,riid
))
965 return RemUnkProxy_Construct(pUnkOuter
, ppv
,(LPVOID
*)ppProxy
);
966 FIXME("proxying not implemented for (%s) yet!\n",debugstr_guid(riid
));
970 static HRESULT WINAPI
972 LPPSFACTORYBUFFER iface
, REFIID riid
,IUnknown
*pUnkServer
,
973 IRpcStubBuffer
** ppStub
977 TRACE("(%s,%p,%p)\n",debugstr_guid(riid
),pUnkServer
,ppStub
);
979 if (IsEqualIID(&IID_IClassFactory
, riid
) ||
980 IsEqualIID(&IID_IUnknown
, riid
) /* FIXME: fixup stub manager and remove this*/) {
981 hres
= CFStub_Construct(ppStub
);
983 IRpcStubBuffer_Connect((*ppStub
),pUnkServer
);
985 } else if (IsEqualIID(&IID_IRemUnknown
,riid
)) {
986 hres
= RemUnkStub_Construct(ppStub
);
988 IRpcStubBuffer_Connect((*ppStub
),pUnkServer
);
991 FIXME("stubbing not implemented for (%s) yet!\n",debugstr_guid(riid
));
995 static const IPSFactoryBufferVtbl psfacbufvtbl
= {
996 PSFacBuf_QueryInterface
,
999 PSFacBuf_CreateProxy
,
1003 /* This is the whole PSFactoryBuffer object, just the vtableptr */
1004 static const IPSFactoryBufferVtbl
*lppsfac
= &psfacbufvtbl
;
1007 #include "rpcproxy.h"
1009 static CStdPSFactoryBuffer PSFactoryBuffer
;
1011 CSTDSTUBBUFFERRELEASE(&PSFactoryBuffer
)
1013 extern const ExtendedProxyFileInfo dcom_ProxyFileInfo
;
1014 extern const ExtendedProxyFileInfo objidl_ProxyFileInfo
;
1015 extern const ExtendedProxyFileInfo oleidl_ProxyFileInfo
;
1016 extern const ExtendedProxyFileInfo unknwn_ProxyFileInfo
;
1018 const ProxyFileInfo
* aProxyFileList
[] =
1020 &dcom_ProxyFileInfo
,
1021 &objidl_ProxyFileInfo
,
1022 &oleidl_ProxyFileInfo
,
1023 &unknwn_ProxyFileInfo
,
1027 /***********************************************************************
1028 * DllGetClassObject [OLE32.@]
1030 HRESULT WINAPI
DllGetClassObject(REFCLSID rclsid
, REFIID iid
,LPVOID
*ppv
)
1033 if (IsEqualIID(rclsid
, &CLSID_PSFactoryBuffer
))
1034 return NdrDllGetClassObject(rclsid
, iid
, ppv
, aProxyFileList
,
1035 &CLSID_PSFactoryBuffer
, &PSFactoryBuffer
);
1036 if (IsEqualIID(rclsid
,&CLSID_DfMarshal
)&&(
1037 IsEqualIID(iid
,&IID_IClassFactory
) ||
1038 IsEqualIID(iid
,&IID_IUnknown
)
1041 return MARSHAL_GetStandardMarshalCF(ppv
);
1042 if (IsEqualIID(rclsid
,&CLSID_StdGlobalInterfaceTable
) && (IsEqualIID(iid
,&IID_IClassFactory
) || IsEqualIID(iid
,&IID_IUnknown
)))
1043 return StdGlobalInterfaceTable_GetFactory(ppv
);
1044 if (IsEqualCLSID(rclsid
, &CLSID_FileMoniker
))
1045 return FileMonikerCF_Create(iid
, ppv
);
1046 if (IsEqualCLSID(rclsid
, &CLSID_ItemMoniker
))
1047 return ItemMonikerCF_Create(iid
, ppv
);
1048 if (IsEqualCLSID(rclsid
, &CLSID_AntiMoniker
))
1049 return AntiMonikerCF_Create(iid
, ppv
);
1050 if (IsEqualCLSID(rclsid
, &CLSID_CompositeMoniker
))
1051 return CompositeMonikerCF_Create(iid
, ppv
);
1052 if (IsEqualCLSID(rclsid
, &CLSID_ClassMoniker
))
1053 return ClassMonikerCF_Create(iid
, ppv
);
1055 /* CODEWEAVERS HACK: Fix up native implementing Component Categories
1056 * Manager in ole32 and us in comcat - we should remove this hack when
1057 * we get around to moving our comcat implementation to ole32 */
1058 if (IsEqualCLSID(rclsid
, &CLSID_StdComponentCategoriesMgr
))
1060 HMODULE hComCat
= LoadLibraryA("comcat");
1061 typedef HRESULT (CALLBACK
*DllGetClassObjectFunc
)(REFCLSID clsid
, REFIID iid
, LPVOID
*ppv
);
1062 DllGetClassObjectFunc DllGetClassObject
=
1063 (DllGetClassObjectFunc
)GetProcAddress(hComCat
, "DllGetClassObject");
1064 if (DllGetClassObject
) return DllGetClassObject(rclsid
, iid
, ppv
);
1067 FIXME("\n\tCLSID:\t%s,\n\tIID:\t%s\n",debugstr_guid(rclsid
),debugstr_guid(iid
));
1068 return CLASS_E_CLASSNOTAVAILABLE
;