wined3d: Use a separate STATE_VDECL state handler in the GLSL pipeline.
[wine/multimedia.git] / dlls / rpcrt4 / ndr_ole.c
blob0f0b7e7df206a4a8ed703512679cdeb2b13705f4
1 /*
2 * OLE32 callouts, COM interface marshalling
4 * Copyright 2001 Ove Kåven, TransGaming Technologies
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 * TODO:
21 * - fix the wire-protocol to match MS/RPC
24 #include <stdarg.h>
25 #include <stdio.h>
26 #include <string.h>
28 #define COBJMACROS
29 #define NONAMELESSUNION
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winerror.h"
35 #include "objbase.h"
37 #include "ndr_misc.h"
38 #include "rpcndr.h"
39 #include "rpcproxy.h"
40 #include "wine/rpcfc.h"
41 #include "cpsf.h"
43 #include "wine/debug.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(ole);
47 static HMODULE hOLE;
49 static HRESULT (WINAPI *COM_GetMarshalSizeMax)(ULONG *,REFIID,LPUNKNOWN,DWORD,LPVOID,DWORD);
50 static HRESULT (WINAPI *COM_MarshalInterface)(LPSTREAM,REFIID,LPUNKNOWN,DWORD,LPVOID,DWORD);
51 static HRESULT (WINAPI *COM_UnmarshalInterface)(LPSTREAM,REFIID,LPVOID*);
52 static HRESULT (WINAPI *COM_ReleaseMarshalData)(LPSTREAM);
53 static HRESULT (WINAPI *COM_GetClassObject)(REFCLSID,DWORD,COSERVERINFO *,REFIID,LPVOID *);
54 static HRESULT (WINAPI *COM_GetPSClsid)(REFIID,CLSID *);
55 static LPVOID (WINAPI *COM_MemAlloc)(ULONG);
56 static void (WINAPI *COM_MemFree)(LPVOID);
58 static HMODULE LoadCOM(void)
60 if (hOLE) return hOLE;
61 hOLE = LoadLibraryA("OLE32.DLL");
62 if (!hOLE) return 0;
63 COM_GetMarshalSizeMax = (LPVOID)GetProcAddress(hOLE, "CoGetMarshalSizeMax");
64 COM_MarshalInterface = (LPVOID)GetProcAddress(hOLE, "CoMarshalInterface");
65 COM_UnmarshalInterface = (LPVOID)GetProcAddress(hOLE, "CoUnmarshalInterface");
66 COM_ReleaseMarshalData = (LPVOID)GetProcAddress(hOLE, "CoReleaseMarshalData");
67 COM_GetClassObject = (LPVOID)GetProcAddress(hOLE, "CoGetClassObject");
68 COM_GetPSClsid = (LPVOID)GetProcAddress(hOLE, "CoGetPSClsid");
69 COM_MemAlloc = (LPVOID)GetProcAddress(hOLE, "CoTaskMemAlloc");
70 COM_MemFree = (LPVOID)GetProcAddress(hOLE, "CoTaskMemFree");
71 return hOLE;
74 /* CoMarshalInterface/CoUnmarshalInterface works on streams,
75 * so implement a simple stream on top of the RPC buffer
76 * (which also implements the MInterfacePointer structure) */
77 typedef struct RpcStreamImpl
79 IStream IStream_iface;
80 LONG RefCount;
81 PMIDL_STUB_MESSAGE pMsg;
82 LPDWORD size;
83 unsigned char *data;
84 DWORD pos;
85 } RpcStreamImpl;
87 static inline RpcStreamImpl *impl_from_IStream(IStream *iface)
89 return CONTAINING_RECORD(iface, RpcStreamImpl, IStream_iface);
92 static HRESULT WINAPI RpcStream_QueryInterface(LPSTREAM iface,
93 REFIID riid,
94 LPVOID *obj)
96 if (IsEqualGUID(&IID_IUnknown, riid) ||
97 IsEqualGUID(&IID_ISequentialStream, riid) ||
98 IsEqualGUID(&IID_IStream, riid)) {
99 *obj = iface;
100 IStream_AddRef(iface);
101 return S_OK;
104 *obj = NULL;
105 return E_NOINTERFACE;
108 static ULONG WINAPI RpcStream_AddRef(LPSTREAM iface)
110 RpcStreamImpl *This = impl_from_IStream(iface);
111 return InterlockedIncrement( &This->RefCount );
114 static ULONG WINAPI RpcStream_Release(LPSTREAM iface)
116 RpcStreamImpl *This = impl_from_IStream(iface);
117 ULONG ref = InterlockedDecrement( &This->RefCount );
118 if (!ref) {
119 TRACE("size=%d\n", *This->size);
120 This->pMsg->Buffer = This->data + *This->size;
121 HeapFree(GetProcessHeap(),0,This);
123 return ref;
126 static HRESULT WINAPI RpcStream_Read(LPSTREAM iface,
127 void *pv,
128 ULONG cb,
129 ULONG *pcbRead)
131 RpcStreamImpl *This = impl_from_IStream(iface);
132 HRESULT hr = S_OK;
133 if (This->pos + cb > *This->size)
135 cb = *This->size - This->pos;
136 hr = S_FALSE;
138 if (cb) {
139 memcpy(pv, This->data + This->pos, cb);
140 This->pos += cb;
142 if (pcbRead) *pcbRead = cb;
143 return hr;
146 static HRESULT WINAPI RpcStream_Write(LPSTREAM iface,
147 const void *pv,
148 ULONG cb,
149 ULONG *pcbWritten)
151 RpcStreamImpl *This = impl_from_IStream(iface);
152 if (This->data + cb > (unsigned char *)This->pMsg->RpcMsg->Buffer + This->pMsg->BufferLength)
153 return STG_E_MEDIUMFULL;
154 memcpy(This->data + This->pos, pv, cb);
155 This->pos += cb;
156 if (This->pos > *This->size) *This->size = This->pos;
157 if (pcbWritten) *pcbWritten = cb;
158 return S_OK;
161 static HRESULT WINAPI RpcStream_Seek(LPSTREAM iface,
162 LARGE_INTEGER move,
163 DWORD origin,
164 ULARGE_INTEGER *newPos)
166 RpcStreamImpl *This = impl_from_IStream(iface);
167 switch (origin) {
168 case STREAM_SEEK_SET:
169 This->pos = move.u.LowPart;
170 break;
171 case STREAM_SEEK_CUR:
172 This->pos = This->pos + move.u.LowPart;
173 break;
174 case STREAM_SEEK_END:
175 This->pos = *This->size + move.u.LowPart;
176 break;
177 default:
178 return STG_E_INVALIDFUNCTION;
180 if (newPos) {
181 newPos->u.LowPart = This->pos;
182 newPos->u.HighPart = 0;
184 return S_OK;
187 static HRESULT WINAPI RpcStream_SetSize(LPSTREAM iface,
188 ULARGE_INTEGER newSize)
190 RpcStreamImpl *This = impl_from_IStream(iface);
191 *This->size = newSize.u.LowPart;
192 return S_OK;
195 static HRESULT WINAPI RpcStream_CopyTo(IStream *iface, IStream *dest,
196 ULARGE_INTEGER len, ULARGE_INTEGER *read, ULARGE_INTEGER *written)
198 RpcStreamImpl *This = impl_from_IStream(iface);
199 FIXME("(%p): stub\n", This);
200 return E_NOTIMPL;
203 static HRESULT WINAPI RpcStream_Commit(IStream *iface, DWORD flags)
205 RpcStreamImpl *This = impl_from_IStream(iface);
206 FIXME("(%p)->(0x%08x): stub\n", This, flags);
207 return E_NOTIMPL;
210 static HRESULT WINAPI RpcStream_Revert(IStream *iface)
212 RpcStreamImpl *This = impl_from_IStream(iface);
213 FIXME("(%p): stub\n", This);
214 return E_NOTIMPL;
217 static HRESULT WINAPI RpcStream_LockRegion(IStream *iface,
218 ULARGE_INTEGER offset, ULARGE_INTEGER len, DWORD locktype)
220 RpcStreamImpl *This = impl_from_IStream(iface);
221 FIXME("(%p): stub\n", This);
222 return E_NOTIMPL;
225 static HRESULT WINAPI RpcStream_UnlockRegion(IStream *iface,
226 ULARGE_INTEGER offset, ULARGE_INTEGER len, DWORD locktype)
228 RpcStreamImpl *This = impl_from_IStream(iface);
229 FIXME("(%p): stub\n", This);
230 return E_NOTIMPL;
233 static HRESULT WINAPI RpcStream_Stat(IStream *iface, STATSTG *stat, DWORD flag)
235 RpcStreamImpl *This = impl_from_IStream(iface);
236 FIXME("(%p): stub\n", This);
237 return E_NOTIMPL;
240 static HRESULT WINAPI RpcStream_Clone(IStream *iface, IStream **cloned)
242 RpcStreamImpl *This = impl_from_IStream(iface);
243 FIXME("(%p): stub\n", This);
244 return E_NOTIMPL;
247 static const IStreamVtbl RpcStream_Vtbl =
249 RpcStream_QueryInterface,
250 RpcStream_AddRef,
251 RpcStream_Release,
252 RpcStream_Read,
253 RpcStream_Write,
254 RpcStream_Seek,
255 RpcStream_SetSize,
256 RpcStream_CopyTo,
257 RpcStream_Commit,
258 RpcStream_Revert,
259 RpcStream_LockRegion,
260 RpcStream_UnlockRegion,
261 RpcStream_Stat,
262 RpcStream_Clone
265 static HRESULT RpcStream_Create(PMIDL_STUB_MESSAGE pStubMsg, BOOL init, ULONG *size, IStream **stream)
267 RpcStreamImpl *This;
269 *stream = NULL;
270 This = HeapAlloc(GetProcessHeap(), 0, sizeof(RpcStreamImpl));
271 if (!This) return E_OUTOFMEMORY;
272 This->IStream_iface.lpVtbl = &RpcStream_Vtbl;
273 This->RefCount = 1;
274 This->pMsg = pStubMsg;
275 This->size = (LPDWORD)pStubMsg->Buffer;
276 This->data = pStubMsg->Buffer + sizeof(DWORD);
277 This->pos = 0;
278 if (init) *This->size = 0;
279 TRACE("init size=%d\n", *This->size);
281 if (size) *size = *This->size;
282 *stream = &This->IStream_iface;
283 return S_OK;
286 static const IID* get_ip_iid(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat)
288 const IID *riid;
289 if (!pFormat) return &IID_IUnknown;
290 TRACE("format=%02x %02x\n", pFormat[0], pFormat[1]);
291 if (pFormat[0] != RPC_FC_IP) FIXME("format=%d\n", pFormat[0]);
292 if (pFormat[1] == RPC_FC_CONSTANT_IID) {
293 riid = (const IID *)&pFormat[2];
294 } else {
295 ComputeConformance(pStubMsg, pMemory, pFormat+2, 0);
296 riid = (const IID *)pStubMsg->MaxCount;
298 if (!riid) riid = &IID_IUnknown;
299 TRACE("got %s\n", debugstr_guid(riid));
300 return riid;
303 /***********************************************************************
304 * NdrInterfacePointerMarshall [RPCRT4.@]
306 unsigned char * WINAPI NdrInterfacePointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
307 unsigned char *pMemory,
308 PFORMAT_STRING pFormat)
310 const IID *riid = get_ip_iid(pStubMsg, pMemory, pFormat);
311 LPSTREAM stream;
312 HRESULT hr;
314 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
315 pStubMsg->MaxCount = 0;
316 if (!LoadCOM()) return NULL;
317 if (pStubMsg->Buffer + sizeof(DWORD) <= (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) {
318 hr = RpcStream_Create(pStubMsg, TRUE, NULL, &stream);
319 if (hr == S_OK) {
320 if (pMemory)
321 hr = COM_MarshalInterface(stream, riid, (LPUNKNOWN)pMemory,
322 pStubMsg->dwDestContext, pStubMsg->pvDestContext,
323 MSHLFLAGS_NORMAL);
324 IStream_Release(stream);
327 if (FAILED(hr))
328 RpcRaiseException(hr);
330 return NULL;
333 /***********************************************************************
334 * NdrInterfacePointerUnmarshall [RPCRT4.@]
336 unsigned char * WINAPI NdrInterfacePointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
337 unsigned char **ppMemory,
338 PFORMAT_STRING pFormat,
339 unsigned char fMustAlloc)
341 LPSTREAM stream;
342 HRESULT hr;
344 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
345 if (!LoadCOM()) return NULL;
346 *(LPVOID*)ppMemory = NULL;
347 if (pStubMsg->Buffer + sizeof(DWORD) < (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) {
348 ULONG size;
350 hr = RpcStream_Create(pStubMsg, FALSE, &size, &stream);
351 if (hr == S_OK) {
352 if (size != 0)
353 hr = COM_UnmarshalInterface(stream, &IID_NULL, (LPVOID*)ppMemory);
355 IStream_Release(stream);
358 if (FAILED(hr))
359 RpcRaiseException(hr);
361 return NULL;
364 /***********************************************************************
365 * NdrInterfacePointerBufferSize [RPCRT4.@]
367 void WINAPI NdrInterfacePointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
368 unsigned char *pMemory,
369 PFORMAT_STRING pFormat)
371 const IID *riid = get_ip_iid(pStubMsg, pMemory, pFormat);
372 ULONG size = 0;
374 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
375 if (!LoadCOM()) return;
376 COM_GetMarshalSizeMax(&size, riid, (LPUNKNOWN)pMemory,
377 pStubMsg->dwDestContext, pStubMsg->pvDestContext,
378 MSHLFLAGS_NORMAL);
379 TRACE("size=%d\n", size);
380 pStubMsg->BufferLength += sizeof(DWORD) + size;
383 /***********************************************************************
384 * NdrInterfacePointerMemorySize [RPCRT4.@]
386 ULONG WINAPI NdrInterfacePointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
387 PFORMAT_STRING pFormat)
389 ULONG size;
391 TRACE("(%p,%p)\n", pStubMsg, pFormat);
393 size = *(ULONG *)pStubMsg->Buffer;
394 pStubMsg->Buffer += 4;
395 pStubMsg->MemorySize += 4;
397 pStubMsg->Buffer += size;
399 return pStubMsg->MemorySize;
402 /***********************************************************************
403 * NdrInterfacePointerFree [RPCRT4.@]
405 void WINAPI NdrInterfacePointerFree(PMIDL_STUB_MESSAGE pStubMsg,
406 unsigned char *pMemory,
407 PFORMAT_STRING pFormat)
409 LPUNKNOWN pUnk = (LPUNKNOWN)pMemory;
410 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
411 if (pUnk) IUnknown_Release(pUnk);
414 /***********************************************************************
415 * NdrOleAllocate [RPCRT4.@]
417 void * WINAPI NdrOleAllocate(SIZE_T Size)
419 if (!LoadCOM()) return NULL;
420 return COM_MemAlloc(Size);
423 /***********************************************************************
424 * NdrOleFree [RPCRT4.@]
426 void WINAPI NdrOleFree(void *NodeToFree)
428 if (!LoadCOM()) return;
429 COM_MemFree(NodeToFree);
432 /***********************************************************************
433 * Helper function to create a proxy.
434 * Probably similar to NdrpCreateProxy.
436 HRESULT create_proxy(REFIID iid, IUnknown *pUnkOuter, IRpcProxyBuffer **pproxy, void **ppv)
438 CLSID clsid;
439 IPSFactoryBuffer *psfac;
440 HRESULT r;
442 if(!LoadCOM()) return E_FAIL;
444 r = COM_GetPSClsid( iid, &clsid );
445 if(FAILED(r)) return r;
447 r = COM_GetClassObject( &clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IPSFactoryBuffer, (void**)&psfac );
448 if(FAILED(r)) return r;
450 r = IPSFactoryBuffer_CreateProxy(psfac, pUnkOuter, iid, pproxy, ppv);
452 IPSFactoryBuffer_Release(psfac);
453 return r;
456 /***********************************************************************
457 * Helper function to create a stub.
458 * This probably looks very much like NdrpCreateStub.
460 HRESULT create_stub(REFIID iid, IUnknown *pUnk, IRpcStubBuffer **ppstub)
462 CLSID clsid;
463 IPSFactoryBuffer *psfac;
464 HRESULT r;
466 if(!LoadCOM()) return E_FAIL;
468 r = COM_GetPSClsid( iid, &clsid );
469 if(FAILED(r)) return r;
471 r = COM_GetClassObject( &clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IPSFactoryBuffer, (void**)&psfac );
472 if(FAILED(r)) return r;
474 r = IPSFactoryBuffer_CreateStub(psfac, iid, pUnk, ppstub);
476 IPSFactoryBuffer_Release(psfac);
477 return r;