Update the address of the Free Software Foundation.
[wine/testsucceed.git] / dlls / ole32 / oleproxy.c
blob169dc4f7e4e5fe8e6afced10193024a030219a57
1 /*
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
27 * (COM Proxy)
28 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/com/htm/comext_1q0p.asp
30 * (COM Stub)
31 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/com/htm/comext_1lia.asp
33 * (Marshal)
34 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/com/htm/comext_1gfn.asp
38 #include "config.h"
40 #include <stdlib.h>
41 #include <stdarg.h>
42 #include <stdio.h>
43 #include <string.h>
45 #define COBJMACROS
46 #define NONAMELESSUNION
47 #define NONAMELESSSTRUCT
49 #include "windef.h"
50 #include "winbase.h"
51 #include "winuser.h"
52 #include "objbase.h"
53 #include "ole2.h"
54 #include "rpc.h"
55 #include "winerror.h"
56 #include "winreg.h"
57 #include "wtypes.h"
59 #include "compobj_private.h"
60 #include "moniker.h"
62 #include "wine/debug.h"
64 WINE_DEFAULT_DEBUG_CHANNEL(ole);
66 const CLSID CLSID_DfMarshal = { 0x0000030b, 0, 0, {0xc0, 0, 0, 0, 0, 0, 0, 0x46} };
67 const CLSID CLSID_PSFactoryBuffer = { 0x00000320, 0, 0, {0xc0, 0, 0, 0, 0, 0, 0, 0x46} };
69 static ULONG WINAPI RURpcProxyBufferImpl_Release(LPRPCPROXYBUFFER iface);
71 /* From: http://msdn.microsoft.com/library/en-us/com/cmi_m_4lda.asp
73 * The first time a client requests a pointer to an interface on a
74 * particular object, COM loads an IClassFactory stub in the server
75 * process and uses it to marshal the first pointer back to the
76 * client. In the client process, COM loads the generic proxy for the
77 * class factory object and calls its implementation of IMarshal to
78 * unmarshal that first pointer. COM then creates the first interface
79 * proxy and hands it a pointer to the RPC channel. Finally, COM returns
80 * the IClassFactory pointer to the client, which uses it to call
81 * IClassFactory::CreateInstance, passing it a reference to the interface.
83 * Back in the server process, COM now creates a new instance of the
84 * object, along with a stub for the requested interface. This stub marshals
85 * the interface pointer back to the client process, where another object
86 * proxy is created, this time for the object itself. Also created is a
87 * proxy for the requested interface, a pointer to which is returned to
88 * the client. With subsequent calls to other interfaces on the object,
89 * COM will load the appropriate interface stubs and proxies as needed.
91 typedef struct _CFStub {
92 const IRpcStubBufferVtbl *lpvtbl;
93 LONG ref;
95 LPUNKNOWN pUnkServer;
96 } CFStub;
98 static HRESULT WINAPI
99 CFStub_QueryInterface(LPRPCSTUBBUFFER iface, REFIID riid, LPVOID *ppv) {
100 if (IsEqualIID(&IID_IUnknown,riid)||IsEqualIID(&IID_IRpcStubBuffer,riid)) {
101 *ppv = (LPVOID)iface;
102 IUnknown_AddRef(iface);
103 return S_OK;
105 FIXME("(%s), interface not supported.\n",debugstr_guid(riid));
106 return E_NOINTERFACE;
109 static ULONG WINAPI
110 CFStub_AddRef(LPRPCSTUBBUFFER iface) {
111 CFStub *This = (CFStub *)iface;
112 return InterlockedIncrement(&This->ref);
115 static ULONG WINAPI
116 CFStub_Release(LPRPCSTUBBUFFER iface) {
117 CFStub *This = (CFStub *)iface;
118 ULONG ref;
120 ref = InterlockedDecrement(&This->ref);
121 if (!ref) {
122 IRpcStubBuffer_Disconnect(iface);
123 HeapFree(GetProcessHeap(),0,This);
125 return ref;
128 static HRESULT WINAPI
129 CFStub_Connect(LPRPCSTUBBUFFER iface, IUnknown *pUnkServer) {
130 CFStub *This = (CFStub *)iface;
132 This->pUnkServer = pUnkServer;
133 IUnknown_AddRef(pUnkServer);
134 return S_OK;
137 static void WINAPI
138 CFStub_Disconnect(LPRPCSTUBBUFFER iface) {
139 CFStub *This = (CFStub *)iface;
141 if (This->pUnkServer) {
142 IUnknown_Release(This->pUnkServer);
143 This->pUnkServer = NULL;
147 static HRESULT WINAPI
148 CFStub_Invoke(
149 LPRPCSTUBBUFFER iface,RPCOLEMESSAGE* msg,IRpcChannelBuffer* chanbuf
151 CFStub *This = (CFStub *)iface;
152 HRESULT hres;
154 if (msg->iMethod == 3) { /* CreateInstance */
155 IID iid;
156 IClassFactory *classfac;
157 IUnknown *ppv;
158 IStream *pStm;
159 STATSTG ststg;
160 ULARGE_INTEGER newpos;
161 LARGE_INTEGER seekto;
162 ULONG res;
164 if (msg->cbBuffer < sizeof(IID)) {
165 FIXME("Not enough bytes in buffer (%ld instead of %d)?\n",msg->cbBuffer,sizeof(IID));
166 return E_FAIL;
168 memcpy(&iid,msg->Buffer,sizeof(iid));
169 TRACE("->CreateInstance(%s)\n",debugstr_guid(&iid));
170 hres = IUnknown_QueryInterface(This->pUnkServer,&IID_IClassFactory,(LPVOID*)&classfac);
171 if (hres) {
172 FIXME("Ole server does not provide an IClassFactory?\n");
173 return hres;
175 hres = IClassFactory_CreateInstance(classfac,NULL,&iid,(LPVOID*)&ppv);
176 IClassFactory_Release(classfac);
177 if (hres) {
178 msg->cbBuffer = 0;
179 FIXME("Failed to create an instance of %s\n",debugstr_guid(&iid));
180 return hres;
182 hres = CreateStreamOnHGlobal(0,TRUE,&pStm);
183 if (hres) {
184 FIXME("Failed to create stream on hglobal\n");
185 return hres;
187 hres = CoMarshalInterface(pStm,&iid,ppv,0,NULL,0);
188 IUnknown_Release((IUnknown*)ppv);
189 if (hres) {
190 FIXME("CoMarshalInterface failed, %lx!\n",hres);
191 msg->cbBuffer = 0;
192 return hres;
194 hres = IStream_Stat(pStm,&ststg,0);
195 if (hres) {
196 FIXME("Stat failed.\n");
197 return hres;
200 msg->cbBuffer = ststg.cbSize.u.LowPart;
202 I_RpcGetBuffer((RPC_MESSAGE *)msg);
203 if (hres) return hres;
205 seekto.u.LowPart = 0;seekto.u.HighPart = 0;
206 hres = IStream_Seek(pStm,seekto,SEEK_SET,&newpos);
207 if (hres) {
208 FIXME("IStream_Seek failed, %lx\n",hres);
209 return hres;
211 hres = IStream_Read(pStm,msg->Buffer,msg->cbBuffer,&res);
212 if (hres) {
213 FIXME("Stream Read failed, %lx\n",hres);
214 return hres;
216 IStream_Release(pStm);
217 return S_OK;
219 FIXME("(%p,%p), stub!\n",msg,chanbuf);
220 FIXME("iMethod is %ld\n",msg->iMethod);
221 FIXME("cbBuffer is %ld\n",msg->cbBuffer);
222 return E_FAIL;
225 static LPRPCSTUBBUFFER WINAPI
226 CFStub_IsIIDSupported(LPRPCSTUBBUFFER iface,REFIID riid) {
227 FIXME("(%s), stub!\n",debugstr_guid(riid));
228 return NULL;
231 static ULONG WINAPI
232 CFStub_CountRefs(LPRPCSTUBBUFFER iface) {
233 FIXME("(), stub!\n");
234 return 1;
237 static HRESULT WINAPI
238 CFStub_DebugServerQueryInterface(LPRPCSTUBBUFFER iface,void** ppv) {
239 FIXME("(%p), stub!\n",ppv);
240 return E_FAIL;
242 static void WINAPI
243 CFStub_DebugServerRelease(LPRPCSTUBBUFFER iface,void *pv) {
244 FIXME("(%p), stub!\n",pv);
247 static const IRpcStubBufferVtbl cfstubvt = {
248 CFStub_QueryInterface,
249 CFStub_AddRef,
250 CFStub_Release,
251 CFStub_Connect,
252 CFStub_Disconnect,
253 CFStub_Invoke,
254 CFStub_IsIIDSupported,
255 CFStub_CountRefs,
256 CFStub_DebugServerQueryInterface,
257 CFStub_DebugServerRelease
260 static HRESULT
261 CFStub_Construct(LPRPCSTUBBUFFER *ppv) {
262 CFStub *cfstub;
263 cfstub = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(CFStub));
264 if (!cfstub)
265 return E_OUTOFMEMORY;
266 *ppv = (LPRPCSTUBBUFFER)cfstub;
267 cfstub->lpvtbl = &cfstubvt;
268 cfstub->ref = 1;
269 return S_OK;
272 /* Since we create proxy buffers and classfactory in a pair, there is
273 * no need for 2 separate structs. Just put them in one, but remember
274 * the refcount.
276 typedef struct _CFProxy {
277 const IClassFactoryVtbl *lpvtbl_cf;
278 const IRpcProxyBufferVtbl *lpvtbl_proxy;
279 LONG ref;
281 IRpcChannelBuffer *chanbuf;
282 IUnknown *outer_unknown;
283 } CFProxy;
285 static HRESULT WINAPI IRpcProxyBufferImpl_QueryInterface(LPRPCPROXYBUFFER iface,REFIID riid,LPVOID *ppv) {
286 *ppv = NULL;
287 if (IsEqualIID(riid,&IID_IRpcProxyBuffer)||IsEqualIID(riid,&IID_IUnknown)) {
288 IRpcProxyBuffer_AddRef(iface);
289 *ppv = (LPVOID)iface;
290 return S_OK;
292 FIXME("(%s), no interface.\n",debugstr_guid(riid));
293 return E_NOINTERFACE;
296 static ULONG WINAPI IRpcProxyBufferImpl_AddRef(LPRPCPROXYBUFFER iface) {
297 ICOM_THIS_MULTI(CFProxy,lpvtbl_proxy,iface);
298 return InterlockedIncrement(&This->ref);
301 static ULONG WINAPI IRpcProxyBufferImpl_Release(LPRPCPROXYBUFFER iface) {
302 ICOM_THIS_MULTI(CFProxy,lpvtbl_proxy,iface);
303 ULONG ref = InterlockedDecrement(&This->ref);
305 if (!ref) {
306 IRpcProxyBuffer_Disconnect(iface);
307 HeapFree(GetProcessHeap(),0,This);
309 return ref;
312 static HRESULT WINAPI IRpcProxyBufferImpl_Connect(LPRPCPROXYBUFFER iface,IRpcChannelBuffer* pRpcChannelBuffer) {
313 ICOM_THIS_MULTI(CFProxy,lpvtbl_proxy,iface);
315 This->chanbuf = pRpcChannelBuffer;
316 IRpcChannelBuffer_AddRef(This->chanbuf);
317 return S_OK;
319 static void WINAPI IRpcProxyBufferImpl_Disconnect(LPRPCPROXYBUFFER iface) {
320 ICOM_THIS_MULTI(CFProxy,lpvtbl_proxy,iface);
321 if (This->chanbuf) {
322 IRpcChannelBuffer_Release(This->chanbuf);
323 This->chanbuf = NULL;
327 static HRESULT WINAPI
328 CFProxy_QueryInterface(LPCLASSFACTORY iface,REFIID riid, LPVOID *ppv) {
329 ICOM_THIS_MULTI(CFProxy,lpvtbl_cf,iface);
330 if (This->outer_unknown) return IUnknown_QueryInterface(This->outer_unknown, riid, ppv);
331 *ppv = NULL;
332 if (IsEqualIID(&IID_IClassFactory,riid) || IsEqualIID(&IID_IUnknown,riid)) {
333 *ppv = (LPVOID)iface;
334 IClassFactory_AddRef(iface);
335 return S_OK;
337 if (IsEqualIID(riid,&IID_IMarshal)) /* just to avoid debug output */
338 return E_NOINTERFACE;
339 FIXME("Unhandled interface: %s\n",debugstr_guid(riid));
340 return E_NOINTERFACE;
343 static ULONG WINAPI CFProxy_AddRef(LPCLASSFACTORY iface) {
344 ICOM_THIS_MULTI(CFProxy,lpvtbl_cf,iface);
345 if (This->outer_unknown) return IUnknown_AddRef(This->outer_unknown);
346 return InterlockedIncrement(&This->ref);
349 static ULONG WINAPI CFProxy_Release(LPCLASSFACTORY iface) {
350 ICOM_THIS_MULTI(CFProxy,lpvtbl_cf,iface);
351 if (This->outer_unknown)
352 return IUnknown_Release(This->outer_unknown);
353 else
354 return IRpcProxyBufferImpl_Release((IRpcProxyBuffer *)&This->lpvtbl_proxy);
357 static HRESULT WINAPI CFProxy_CreateInstance(
358 LPCLASSFACTORY iface,
359 LPUNKNOWN pUnkOuter,/* [in] */
360 REFIID riid, /* [in] */
361 LPVOID *ppv /* [out] */
363 ICOM_THIS_MULTI(CFProxy,lpvtbl_cf,iface);
364 HRESULT hres;
365 LPSTREAM pStream;
366 HGLOBAL hGlobal;
367 ULONG srstatus;
368 RPCOLEMESSAGE msg;
370 TRACE("(%p,%s,%p)\n",pUnkOuter,debugstr_guid(riid),ppv);
372 /* Send CreateInstance to the remote classfactory.
374 * Data: Only the 'IID'.
376 msg.iMethod = 3;
377 msg.cbBuffer = sizeof(*riid);
378 msg.Buffer = NULL;
379 hres = IRpcChannelBuffer_GetBuffer(This->chanbuf,&msg,&IID_IClassFactory);
380 if (hres) {
381 FIXME("IRpcChannelBuffer_GetBuffer failed with %lx?\n",hres);
382 return hres;
384 memcpy(msg.Buffer,riid,sizeof(*riid));
385 hres = IRpcChannelBuffer_SendReceive(This->chanbuf,&msg,&srstatus);
386 if (hres) {
387 FIXME("IRpcChannelBuffer_SendReceive failed with %lx?\n",hres);
388 return hres;
391 if (!msg.cbBuffer) /* interface not found on remote */
392 return srstatus;
394 /* We got back: [Marshalled Interface data] */
395 TRACE("got %ld bytes data.\n",msg.cbBuffer);
396 hGlobal = GlobalAlloc(GMEM_MOVEABLE|GMEM_NODISCARD|GMEM_SHARE,msg.cbBuffer);
397 memcpy(GlobalLock(hGlobal),msg.Buffer,msg.cbBuffer);
398 hres = CreateStreamOnHGlobal(hGlobal,TRUE,&pStream);
399 if (hres) {
400 FIXME("CreateStreamOnHGlobal failed with %lx\n",hres);
401 return hres;
403 hres = CoUnmarshalInterface(
404 pStream,
405 riid,
408 IStream_Release(pStream); /* Does GlobalFree hGlobal too. */
409 if (hres) {
410 FIXME("CoMarshalInterface failed, %lx\n",hres);
411 return hres;
413 return S_OK;
416 static HRESULT WINAPI CFProxy_LockServer(LPCLASSFACTORY iface,BOOL fLock) {
417 /*ICOM_THIS_MULTI(CFProxy,lpvtbl_cf,iface);*/
418 FIXME("(%d), stub!\n",fLock);
419 /* basically: write BOOL, read empty */
420 return S_OK;
423 static const IRpcProxyBufferVtbl pspbvtbl = {
424 IRpcProxyBufferImpl_QueryInterface,
425 IRpcProxyBufferImpl_AddRef,
426 IRpcProxyBufferImpl_Release,
427 IRpcProxyBufferImpl_Connect,
428 IRpcProxyBufferImpl_Disconnect
430 static const IClassFactoryVtbl cfproxyvt = {
431 CFProxy_QueryInterface,
432 CFProxy_AddRef,
433 CFProxy_Release,
434 CFProxy_CreateInstance,
435 CFProxy_LockServer
438 static HRESULT
439 CFProxy_Construct(IUnknown *pUnkOuter, LPVOID *ppv,LPVOID *ppProxy) {
440 CFProxy *cf;
442 cf = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(CFProxy));
443 if (!cf)
444 return E_OUTOFMEMORY;
446 cf->lpvtbl_cf = &cfproxyvt;
447 cf->lpvtbl_proxy = &pspbvtbl;
448 /* one reference for the proxy buffer */
449 cf->ref = 1;
450 cf->outer_unknown = pUnkOuter;
451 *ppv = &(cf->lpvtbl_cf);
452 *ppProxy = &(cf->lpvtbl_proxy);
453 /* and one reference for the object */
454 IUnknown_AddRef((IUnknown *)*ppv);
455 return S_OK;
459 /********************* IRemUnknown Proxy/Stub ********************************/
461 typedef struct
463 const IRpcStubBufferVtbl *lpVtbl;
464 LONG refs;
465 IRemUnknown *iface;
466 } RemUnkStub;
468 static HRESULT WINAPI RemUnkStub_QueryInterface(LPRPCSTUBBUFFER iface,
469 REFIID riid,
470 LPVOID *obj)
472 RemUnkStub *This = (RemUnkStub *)iface;
473 TRACE("(%p)->QueryInterface(%s,%p)\n",This,debugstr_guid(riid),obj);
474 if (IsEqualGUID(&IID_IUnknown,riid) ||
475 IsEqualGUID(&IID_IRpcStubBuffer,riid)) {
476 *obj = This;
477 return S_OK;
479 return E_NOINTERFACE;
482 static ULONG WINAPI RemUnkStub_AddRef(LPRPCSTUBBUFFER iface)
484 RemUnkStub *This = (RemUnkStub *)iface;
485 TRACE("(%p)->AddRef()\n",This);
486 return InterlockedIncrement(&This->refs);
489 static ULONG WINAPI RemUnkStub_Release(LPRPCSTUBBUFFER iface)
491 RemUnkStub *This = (RemUnkStub *)iface;
492 ULONG refs;
493 TRACE("(%p)->Release()\n",This);
494 refs = InterlockedDecrement(&This->refs);
495 if (!refs)
496 HeapFree(GetProcessHeap(), 0, This);
497 return refs;
500 static HRESULT WINAPI RemUnkStub_Connect(LPRPCSTUBBUFFER iface,
501 LPUNKNOWN lpUnkServer)
503 RemUnkStub *This = (RemUnkStub *)iface;
504 TRACE("(%p)->Connect(%p)\n",This,lpUnkServer);
505 This->iface = (IRemUnknown*)lpUnkServer;
506 IRemUnknown_AddRef(This->iface);
507 return S_OK;
510 static void WINAPI RemUnkStub_Disconnect(LPRPCSTUBBUFFER iface)
512 RemUnkStub *This = (RemUnkStub *)iface;
513 TRACE("(%p)->Disconnect()\n",This);
514 IUnknown_Release(This->iface);
515 This->iface = NULL;
518 static HRESULT WINAPI RemUnkStub_Invoke(LPRPCSTUBBUFFER iface,
519 PRPCOLEMESSAGE pMsg,
520 LPRPCCHANNELBUFFER pChannel)
522 RemUnkStub *This = (RemUnkStub *)iface;
523 ULONG iMethod = pMsg->iMethod;
524 LPBYTE buf = pMsg->Buffer;
525 HRESULT hr = RPC_E_INVALIDMETHOD;
527 TRACE("(%p)->Invoke(%p,%p) method %ld\n", This, pMsg, pChannel, iMethod);
528 switch (iMethod)
530 case 3: /* RemQueryInterface */
532 IPID ipid;
533 ULONG cRefs;
534 USHORT cIids;
535 IID *iids;
536 REMQIRESULT *pQIResults = NULL;
538 /* in */
539 memcpy(&ipid, buf, sizeof(ipid));
540 buf += sizeof(ipid);
541 memcpy(&cRefs, buf, sizeof(cRefs));
542 buf += sizeof(cRefs);
543 memcpy(&cIids, buf, sizeof(cIids));
544 buf += sizeof(cIids);
545 iids = (IID *)buf;
547 hr = IRemUnknown_RemQueryInterface(This->iface, &ipid, cRefs, cIids, iids, &pQIResults);
549 /* out */
550 pMsg->cbBuffer = cIids * sizeof(REMQIRESULT) + sizeof(HRESULT);
552 I_RpcGetBuffer((RPC_MESSAGE *)pMsg);
554 buf = pMsg->Buffer;
555 *(HRESULT *)buf = hr;
556 buf += sizeof(HRESULT);
558 if (hr) return hr;
559 /* FIXME: pQIResults is a unique pointer so pQIResults can be NULL! */
560 memcpy(buf, pQIResults, cIids * sizeof(REMQIRESULT));
562 break;
564 case 4: /* RemAddRef */
566 USHORT cIids;
567 REMINTERFACEREF *ir;
568 HRESULT *pResults;
570 /* in */
571 memcpy(&cIids, buf, sizeof(USHORT));
572 buf += sizeof(USHORT);
573 ir = (REMINTERFACEREF*)buf;
574 pResults = CoTaskMemAlloc(cIids * sizeof(HRESULT));
575 if (!pResults) return E_OUTOFMEMORY;
577 hr = IRemUnknown_RemAddRef(This->iface, cIids, ir, pResults);
579 /* out */
580 pMsg->cbBuffer = cIids * sizeof(HRESULT);
582 I_RpcGetBuffer((RPC_MESSAGE *)pMsg);
583 if (!hr)
585 buf = pMsg->Buffer;
586 memcpy(buf, pResults, cIids * sizeof(HRESULT));
589 CoTaskMemFree(pResults);
591 break;
593 case 5: /* RemRelease */
595 USHORT cIids;
596 REMINTERFACEREF *ir;
598 /* in */
599 memcpy(&cIids, buf, sizeof(USHORT));
600 buf += sizeof(USHORT);
601 ir = (REMINTERFACEREF*)buf;
603 hr = IRemUnknown_RemRelease(This->iface, cIids, ir);
605 /* out */
606 pMsg->cbBuffer = 0;
607 break;
610 return hr;
613 static LPRPCSTUBBUFFER WINAPI RemUnkStub_IsIIDSupported(LPRPCSTUBBUFFER iface,
614 REFIID riid)
616 RemUnkStub *This = (RemUnkStub *)iface;
617 TRACE("(%p)->IsIIDSupported(%s)\n", This, debugstr_guid(riid));
618 return IsEqualGUID(&IID_IRemUnknown, riid) ? iface : NULL;
621 static ULONG WINAPI RemUnkStub_CountRefs(LPRPCSTUBBUFFER iface)
623 RemUnkStub *This = (RemUnkStub *)iface;
624 FIXME("(%p)->CountRefs()\n", This);
625 return 1;
628 static HRESULT WINAPI RemUnkStub_DebugServerQueryInterface(LPRPCSTUBBUFFER iface,
629 LPVOID *ppv)
631 RemUnkStub *This = (RemUnkStub *)iface;
632 FIXME("(%p)->DebugServerQueryInterface(%p)\n",This,ppv);
633 return E_NOINTERFACE;
636 static void WINAPI RemUnkStub_DebugServerRelease(LPRPCSTUBBUFFER iface,
637 LPVOID pv)
639 RemUnkStub *This = (RemUnkStub *)iface;
640 FIXME("(%p)->DebugServerRelease(%p)\n", This, pv);
643 static const IRpcStubBufferVtbl RemUnkStub_VTable =
645 RemUnkStub_QueryInterface,
646 RemUnkStub_AddRef,
647 RemUnkStub_Release,
648 RemUnkStub_Connect,
649 RemUnkStub_Disconnect,
650 RemUnkStub_Invoke,
651 RemUnkStub_IsIIDSupported,
652 RemUnkStub_CountRefs,
653 RemUnkStub_DebugServerQueryInterface,
654 RemUnkStub_DebugServerRelease
657 static HRESULT RemUnkStub_Construct(IRpcStubBuffer **ppStub)
659 RemUnkStub *This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
660 if (!This) return E_OUTOFMEMORY;
661 This->lpVtbl = &RemUnkStub_VTable;
662 This->refs = 1;
663 This->iface = NULL;
664 *ppStub = (IRpcStubBuffer*)This;
665 return S_OK;
669 typedef struct _RemUnkProxy {
670 const IRemUnknownVtbl *lpvtbl_remunk;
671 const IRpcProxyBufferVtbl *lpvtbl_proxy;
672 LONG refs;
674 IRpcChannelBuffer *chan;
675 IUnknown *outer_unknown;
676 } RemUnkProxy;
678 static HRESULT WINAPI RemUnkProxy_QueryInterface(LPREMUNKNOWN iface, REFIID riid, void **ppv)
680 RemUnkProxy *This = (RemUnkProxy *)iface;
681 if (This->outer_unknown)
682 return IUnknown_QueryInterface(This->outer_unknown, riid, ppv);
683 if (IsEqualIID(riid, &IID_IUnknown) ||
684 IsEqualIID(riid, &IID_IRemUnknown))
686 IRemUnknown_AddRef(iface);
687 *ppv = (LPVOID)iface;
688 return S_OK;
690 return E_NOINTERFACE;
693 static ULONG WINAPI RemUnkProxy_AddRef(LPREMUNKNOWN iface)
695 RemUnkProxy *This = (RemUnkProxy *)iface;
696 ULONG refs;
698 TRACE("(%p)->AddRef()\n",This);
700 if (This->outer_unknown)
701 refs = IUnknown_AddRef(This->outer_unknown);
702 else
703 refs = InterlockedIncrement(&This->refs);
704 return refs;
707 static ULONG WINAPI RemUnkProxy_Release(LPREMUNKNOWN iface)
709 RemUnkProxy *This = (RemUnkProxy *)iface;
711 TRACE("(%p)->Release()\n",This);
712 if (This->outer_unknown)
713 return IUnknown_Release(This->outer_unknown);
714 else
715 return IRpcProxyBufferImpl_Release((IRpcProxyBuffer *)&This->lpvtbl_proxy);
718 static HRESULT WINAPI RemUnkProxy_RemQueryInterface(LPREMUNKNOWN iface,
719 REFIPID ripid,
720 ULONG cRefs,
721 USHORT cIids,
722 IID* iids,
723 REMQIRESULT** ppQIResults)
725 RemUnkProxy *This = (RemUnkProxy *)iface;
726 RPCOLEMESSAGE msg;
727 HRESULT hr = S_OK;
728 ULONG status;
730 TRACE("(%p)->(%s,%ld,%d,%p,%p)\n",This,
731 debugstr_guid(ripid),cRefs,cIids,iids,ppQIResults);
733 *ppQIResults = NULL;
734 memset(&msg, 0, sizeof(msg));
735 msg.iMethod = 3;
736 msg.cbBuffer = sizeof(IPID) + sizeof(ULONG) +
737 sizeof(USHORT) + cIids*sizeof(IID);
738 hr = IRpcChannelBuffer_GetBuffer(This->chan, &msg, &IID_IRemUnknown);
739 if (SUCCEEDED(hr)) {
740 LPBYTE buf = msg.Buffer;
741 memcpy(buf, ripid, sizeof(IPID));
742 buf += sizeof(IPID);
743 memcpy(buf, &cRefs, sizeof(ULONG));
744 buf += sizeof(ULONG);
745 memcpy(buf, &cIids, sizeof(USHORT));
746 buf += sizeof(USHORT);
747 memcpy(buf, iids, cIids*sizeof(IID));
749 hr = IRpcChannelBuffer_SendReceive(This->chan, &msg, &status);
751 buf = msg.Buffer;
753 if (SUCCEEDED(hr)) {
754 hr = *(HRESULT *)buf;
755 buf += sizeof(HRESULT);
758 if (SUCCEEDED(hr)) {
759 *ppQIResults = CoTaskMemAlloc(cIids*sizeof(REMQIRESULT));
760 memcpy(*ppQIResults, buf, cIids*sizeof(REMQIRESULT));
763 IRpcChannelBuffer_FreeBuffer(This->chan, &msg);
766 return hr;
769 static HRESULT WINAPI RemUnkProxy_RemAddRef(LPREMUNKNOWN iface,
770 USHORT cInterfaceRefs,
771 REMINTERFACEREF* InterfaceRefs,
772 HRESULT* pResults)
774 RemUnkProxy *This = (RemUnkProxy *)iface;
775 RPCOLEMESSAGE msg;
776 HRESULT hr = S_OK;
777 ULONG status;
779 TRACE("(%p)->(%d,%p,%p)\n",This,
780 cInterfaceRefs,InterfaceRefs,pResults);
782 memset(&msg, 0, sizeof(msg));
783 msg.iMethod = 4;
784 msg.cbBuffer = sizeof(USHORT) + cInterfaceRefs*sizeof(REMINTERFACEREF);
785 hr = IRpcChannelBuffer_GetBuffer(This->chan, &msg, &IID_IRemUnknown);
786 if (SUCCEEDED(hr)) {
787 LPBYTE buf = msg.Buffer;
788 memcpy(buf, &cInterfaceRefs, sizeof(USHORT));
789 buf += sizeof(USHORT);
790 memcpy(buf, InterfaceRefs, cInterfaceRefs*sizeof(REMINTERFACEREF));
792 hr = IRpcChannelBuffer_SendReceive(This->chan, &msg, &status);
794 if (SUCCEEDED(hr)) {
795 buf = msg.Buffer;
796 memcpy(pResults, buf, cInterfaceRefs*sizeof(HRESULT));
799 IRpcChannelBuffer_FreeBuffer(This->chan, &msg);
802 return hr;
805 static HRESULT WINAPI RemUnkProxy_RemRelease(LPREMUNKNOWN iface,
806 USHORT cInterfaceRefs,
807 REMINTERFACEREF* InterfaceRefs)
809 RemUnkProxy *This = (RemUnkProxy *)iface;
810 RPCOLEMESSAGE msg;
811 HRESULT hr = S_OK;
812 ULONG status;
814 TRACE("(%p)->(%d,%p)\n",This,
815 cInterfaceRefs,InterfaceRefs);
817 memset(&msg, 0, sizeof(msg));
818 msg.iMethod = 5;
819 msg.cbBuffer = sizeof(USHORT) + cInterfaceRefs*sizeof(REMINTERFACEREF);
820 hr = IRpcChannelBuffer_GetBuffer(This->chan, &msg, &IID_IRemUnknown);
821 if (SUCCEEDED(hr)) {
822 LPBYTE buf = msg.Buffer;
823 memcpy(buf, &cInterfaceRefs, sizeof(USHORT));
824 buf += sizeof(USHORT);
825 memcpy(buf, InterfaceRefs, cInterfaceRefs*sizeof(REMINTERFACEREF));
827 hr = IRpcChannelBuffer_SendReceive(This->chan, &msg, &status);
829 IRpcChannelBuffer_FreeBuffer(This->chan, &msg);
832 return hr;
835 static const IRemUnknownVtbl RemUnkProxy_VTable =
837 RemUnkProxy_QueryInterface,
838 RemUnkProxy_AddRef,
839 RemUnkProxy_Release,
840 RemUnkProxy_RemQueryInterface,
841 RemUnkProxy_RemAddRef,
842 RemUnkProxy_RemRelease
846 static HRESULT WINAPI RURpcProxyBufferImpl_QueryInterface(LPRPCPROXYBUFFER iface,REFIID riid,LPVOID *ppv) {
847 *ppv = NULL;
848 if (IsEqualIID(riid,&IID_IRpcProxyBuffer)||IsEqualIID(riid,&IID_IUnknown)) {
849 IRpcProxyBuffer_AddRef(iface);
850 *ppv = (LPVOID)iface;
851 return S_OK;
853 FIXME("(%s), no interface.\n",debugstr_guid(riid));
854 return E_NOINTERFACE;
857 static ULONG WINAPI RURpcProxyBufferImpl_AddRef(LPRPCPROXYBUFFER iface) {
858 ICOM_THIS_MULTI(RemUnkProxy,lpvtbl_proxy,iface);
859 TRACE("%p, %ld\n", iface, This->refs + 1);
860 return InterlockedIncrement(&This->refs);
863 static ULONG WINAPI RURpcProxyBufferImpl_Release(LPRPCPROXYBUFFER iface) {
864 ICOM_THIS_MULTI(RemUnkProxy,lpvtbl_proxy,iface);
865 ULONG ref = InterlockedDecrement(&This->refs);
866 TRACE("%p, %ld\n", iface, ref);
867 if (!ref) {
868 IRpcProxyBuffer_Disconnect(iface);
869 HeapFree(GetProcessHeap(),0,This);
871 return ref;
874 static HRESULT WINAPI RURpcProxyBufferImpl_Connect(LPRPCPROXYBUFFER iface,IRpcChannelBuffer* pRpcChannelBuffer) {
875 ICOM_THIS_MULTI(RemUnkProxy,lpvtbl_proxy,iface);
877 TRACE("%p, %p\n", iface, pRpcChannelBuffer);
878 This->chan = pRpcChannelBuffer;
879 IRpcChannelBuffer_AddRef(This->chan);
880 return S_OK;
882 static void WINAPI RURpcProxyBufferImpl_Disconnect(LPRPCPROXYBUFFER iface) {
883 ICOM_THIS_MULTI(RemUnkProxy,lpvtbl_proxy,iface);
884 TRACE("%p, %p\n", iface, This->chan);
885 if (This->chan) {
886 IRpcChannelBuffer_Release(This->chan);
887 This->chan = NULL;
892 static const IRpcProxyBufferVtbl RURpcProxyBuffer_VTable = {
893 RURpcProxyBufferImpl_QueryInterface,
894 RURpcProxyBufferImpl_AddRef,
895 RURpcProxyBufferImpl_Release,
896 RURpcProxyBufferImpl_Connect,
897 RURpcProxyBufferImpl_Disconnect
900 static HRESULT
901 RemUnkProxy_Construct(IUnknown *pUnkOuter, LPVOID *ppv,LPVOID *ppProxy) {
902 RemUnkProxy *This;
904 This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*This));
905 if (!This)
906 return E_OUTOFMEMORY;
908 This->lpvtbl_remunk = &RemUnkProxy_VTable;
909 This->lpvtbl_proxy = &RURpcProxyBuffer_VTable;
910 /* only one reference for the proxy buffer */
911 This->refs = 1;
912 This->outer_unknown = pUnkOuter;
913 *ppv = &(This->lpvtbl_remunk);
914 *ppProxy = &(This->lpvtbl_proxy);
915 /* and one reference for the object */
916 IUnknown_AddRef((IUnknown *)*ppv);
917 return S_OK;
921 /********************* OLE Proxy/Stub Factory ********************************/
922 static HRESULT WINAPI
923 PSFacBuf_QueryInterface(LPPSFACTORYBUFFER iface, REFIID iid, LPVOID *ppv) {
924 if (IsEqualIID(iid,&IID_IPSFactoryBuffer)||IsEqualIID(iid,&IID_IUnknown)) {
925 *ppv = (LPVOID)iface;
926 /* No ref counting, static class */
927 return S_OK;
929 FIXME("(%s) unknown IID?\n",debugstr_guid(iid));
930 return E_NOINTERFACE;
933 static ULONG WINAPI PSFacBuf_AddRef(LPPSFACTORYBUFFER iface) { return 2; }
934 static ULONG WINAPI PSFacBuf_Release(LPPSFACTORYBUFFER iface) { return 1; }
936 static HRESULT WINAPI
937 PSFacBuf_CreateProxy(
938 LPPSFACTORYBUFFER iface, IUnknown* pUnkOuter, REFIID riid,
939 IRpcProxyBuffer **ppProxy, LPVOID *ppv
941 if (IsEqualIID(&IID_IClassFactory,riid))
942 return CFProxy_Construct(pUnkOuter, ppv,(LPVOID*)ppProxy);
943 else if (IsEqualIID(&IID_IRemUnknown,riid))
944 return RemUnkProxy_Construct(pUnkOuter, ppv,(LPVOID*)ppProxy);
945 FIXME("proxying not implemented for (%s) yet!\n",debugstr_guid(riid));
946 return E_FAIL;
949 static HRESULT WINAPI
950 PSFacBuf_CreateStub(
951 LPPSFACTORYBUFFER iface, REFIID riid,IUnknown *pUnkServer,
952 IRpcStubBuffer** ppStub
954 HRESULT hres;
956 TRACE("(%s,%p,%p)\n",debugstr_guid(riid),pUnkServer,ppStub);
958 if (IsEqualIID(&IID_IClassFactory, riid) ||
959 IsEqualIID(&IID_IUnknown, riid) /* FIXME: fixup stub manager and remove this*/) {
960 hres = CFStub_Construct(ppStub);
961 if (!hres)
962 IRpcStubBuffer_Connect((*ppStub),pUnkServer);
963 return hres;
964 } else if (IsEqualIID(&IID_IRemUnknown,riid)) {
965 hres = RemUnkStub_Construct(ppStub);
966 if (!hres)
967 IRpcStubBuffer_Connect((*ppStub),pUnkServer);
968 return hres;
970 FIXME("stubbing not implemented for (%s) yet!\n",debugstr_guid(riid));
971 return E_FAIL;
974 static const IPSFactoryBufferVtbl psfacbufvtbl = {
975 PSFacBuf_QueryInterface,
976 PSFacBuf_AddRef,
977 PSFacBuf_Release,
978 PSFacBuf_CreateProxy,
979 PSFacBuf_CreateStub
982 /* This is the whole PSFactoryBuffer object, just the vtableptr */
983 static const IPSFactoryBufferVtbl *lppsfac = &psfacbufvtbl;
985 /***********************************************************************
986 * DllGetClassObject [OLE32.@]
988 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID iid,LPVOID *ppv)
990 *ppv = NULL;
991 if (IsEqualIID(rclsid, &CLSID_PSFactoryBuffer))
992 return IPSFactoryBuffer_QueryInterface((IPSFactoryBuffer *)&lppsfac, iid, ppv);
993 if (IsEqualIID(rclsid,&CLSID_DfMarshal)&&(
994 IsEqualIID(iid,&IID_IClassFactory) ||
995 IsEqualIID(iid,&IID_IUnknown)
998 return MARSHAL_GetStandardMarshalCF(ppv);
999 if (IsEqualIID(rclsid,&CLSID_StdGlobalInterfaceTable) && (IsEqualIID(iid,&IID_IClassFactory) || IsEqualIID(iid,&IID_IUnknown)))
1000 return StdGlobalInterfaceTable_GetFactory(ppv);
1001 if (IsEqualCLSID(rclsid, &CLSID_FileMoniker))
1002 return FileMonikerCF_Create(iid, ppv);
1003 if (IsEqualCLSID(rclsid, &CLSID_ItemMoniker))
1004 return ItemMonikerCF_Create(iid, ppv);
1005 if (IsEqualCLSID(rclsid, &CLSID_AntiMoniker))
1006 return AntiMonikerCF_Create(iid, ppv);
1007 if (IsEqualCLSID(rclsid, &CLSID_CompositeMoniker))
1008 return CompositeMonikerCF_Create(iid, ppv);
1009 if (IsEqualCLSID(rclsid, &CLSID_ClassMoniker))
1010 return ClassMonikerCF_Create(iid, ppv);
1012 FIXME("\n\tCLSID:\t%s,\n\tIID:\t%s\n",debugstr_guid(rclsid),debugstr_guid(iid));
1013 return CLASS_E_CLASSNOTAVAILABLE;