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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * - figure out whether we *really* got this right
22 * - check for errors and throw exceptions
23 * - what are the marshalling functions supposed to return?
24 * - finish RpcStream_Vtbl
32 #define NONAMELESSUNION
33 #define NONAMELESSSTRUCT
44 #include "wine/rpcfc.h"
46 #include "wine/debug.h"
48 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
52 static HRESULT (WINAPI
*COM_GetMarshalSizeMax
)(ULONG
*,REFIID
,LPUNKNOWN
,DWORD
,LPVOID
,DWORD
);
53 static HRESULT (WINAPI
*COM_MarshalInterface
)(LPSTREAM
,REFIID
,LPUNKNOWN
,DWORD
,LPVOID
,DWORD
);
54 static HRESULT (WINAPI
*COM_UnmarshalInterface
)(LPSTREAM
,REFIID
,LPVOID
*);
55 static HRESULT (WINAPI
*COM_ReleaseMarshalData
)(LPSTREAM
);
56 static HRESULT (WINAPI
*COM_GetClassObject
)(REFCLSID
,DWORD
,COSERVERINFO
*,REFIID
,LPVOID
*);
57 static HRESULT (WINAPI
*COM_GetPSClsid
)(REFIID
,CLSID
*);
58 static LPVOID (WINAPI
*COM_MemAlloc
)(ULONG
);
59 static void (WINAPI
*COM_MemFree
)(LPVOID
);
61 static HMODULE
LoadCOM(void)
63 if (hOLE
) return hOLE
;
64 hOLE
= LoadLibraryA("OLE32.DLL");
66 COM_GetMarshalSizeMax
= (LPVOID
)GetProcAddress(hOLE
, "CoGetMarshalSizeMax");
67 COM_MarshalInterface
= (LPVOID
)GetProcAddress(hOLE
, "CoMarshalInterface");
68 COM_UnmarshalInterface
= (LPVOID
)GetProcAddress(hOLE
, "CoUnmarshalInterface");
69 COM_ReleaseMarshalData
= (LPVOID
)GetProcAddress(hOLE
, "CoReleaseMarshalData");
70 COM_GetClassObject
= (LPVOID
)GetProcAddress(hOLE
, "CoGetClassObject");
71 COM_GetPSClsid
= (LPVOID
)GetProcAddress(hOLE
, "CoGetPSClsid");
72 COM_MemAlloc
= (LPVOID
)GetProcAddress(hOLE
, "CoTaskMemAlloc");
73 COM_MemFree
= (LPVOID
)GetProcAddress(hOLE
, "CoTaskMemFree");
77 /* CoMarshalInterface/CoUnmarshalInterface works on streams,
78 * so implement a simple stream on top of the RPC buffer
79 * (which also implements the MInterfacePointer structure) */
80 typedef struct RpcStreamImpl
82 const IStreamVtbl
*lpVtbl
;
84 PMIDL_STUB_MESSAGE pMsg
;
90 static HRESULT WINAPI
RpcStream_QueryInterface(LPSTREAM iface
,
94 RpcStreamImpl
*This
= (RpcStreamImpl
*)iface
;
95 if (IsEqualGUID(&IID_IUnknown
, riid
) ||
96 IsEqualGUID(&IID_ISequentialStream
, riid
) ||
97 IsEqualGUID(&IID_IStream
, riid
)) {
102 return E_NOINTERFACE
;
105 static ULONG WINAPI
RpcStream_AddRef(LPSTREAM iface
)
107 RpcStreamImpl
*This
= (RpcStreamImpl
*)iface
;
108 return ++(This
->RefCount
);
111 static ULONG WINAPI
RpcStream_Release(LPSTREAM iface
)
113 RpcStreamImpl
*This
= (RpcStreamImpl
*)iface
;
114 if (!--(This
->RefCount
)) {
115 TRACE("size=%ld\n", *This
->size
);
116 This
->pMsg
->Buffer
= This
->data
+ *This
->size
;
117 HeapFree(GetProcessHeap(),0,This
);
120 return This
->RefCount
;
123 static HRESULT WINAPI
RpcStream_Read(LPSTREAM iface
,
128 RpcStreamImpl
*This
= (RpcStreamImpl
*)iface
;
130 if (This
->pos
+ cb
> *This
->size
)
132 cb
= *This
->size
- This
->pos
;
136 memcpy(pv
, This
->data
+ This
->pos
, cb
);
139 if (pcbRead
) *pcbRead
= cb
;
143 static HRESULT WINAPI
RpcStream_Write(LPSTREAM iface
,
148 RpcStreamImpl
*This
= (RpcStreamImpl
*)iface
;
149 if (This
->data
+ cb
> (char *)This
->pMsg
->BufferEnd
)
150 return STG_E_MEDIUMFULL
;
151 memcpy(This
->data
+ This
->pos
, pv
, cb
);
153 if (This
->pos
> *This
->size
) *This
->size
= This
->pos
;
154 if (pcbWritten
) *pcbWritten
= cb
;
158 static HRESULT WINAPI
RpcStream_Seek(LPSTREAM iface
,
161 ULARGE_INTEGER
*newPos
)
163 RpcStreamImpl
*This
= (RpcStreamImpl
*)iface
;
165 case STREAM_SEEK_SET
:
166 This
->pos
= move
.u
.LowPart
;
168 case STREAM_SEEK_CUR
:
169 This
->pos
= This
->pos
+ move
.u
.LowPart
;
171 case STREAM_SEEK_END
:
172 This
->pos
= *This
->size
+ move
.u
.LowPart
;
175 return STG_E_INVALIDFUNCTION
;
178 newPos
->u
.LowPart
= This
->pos
;
179 newPos
->u
.HighPart
= 0;
184 static HRESULT WINAPI
RpcStream_SetSize(LPSTREAM iface
,
185 ULARGE_INTEGER newSize
)
187 RpcStreamImpl
*This
= (RpcStreamImpl
*)iface
;
188 *This
->size
= newSize
.u
.LowPart
;
192 static const IStreamVtbl RpcStream_Vtbl
=
194 RpcStream_QueryInterface
,
204 NULL
, /* LockRegion */
205 NULL
, /* UnlockRegion */
210 static LPSTREAM
RpcStream_Create(PMIDL_STUB_MESSAGE pStubMsg
, BOOL init
)
213 This
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(RpcStreamImpl
));
214 if (!This
) return NULL
;
215 This
->lpVtbl
= &RpcStream_Vtbl
;
217 This
->pMsg
= pStubMsg
;
218 This
->size
= (LPDWORD
)pStubMsg
->Buffer
;
219 This
->data
= (char*)(This
->size
+ 1);
221 if (init
) *This
->size
= 0;
222 TRACE("init size=%ld\n", *This
->size
);
223 return (LPSTREAM
)This
;
226 static const IID
* get_ip_iid(PMIDL_STUB_MESSAGE pStubMsg
, unsigned char *pMemory
, PFORMAT_STRING pFormat
)
229 if (!pFormat
) return &IID_IUnknown
;
230 TRACE("format=%02x %02x\n", pFormat
[0], pFormat
[1]);
231 if (pFormat
[0] != RPC_FC_IP
) FIXME("format=%d\n", pFormat
[0]);
232 if (pFormat
[1] == RPC_FC_CONSTANT_IID
) {
233 riid
= (const IID
*)&pFormat
[2];
235 ComputeConformance(pStubMsg
, pMemory
, pFormat
+2, 0);
236 riid
= (const IID
*)pStubMsg
->MaxCount
;
238 if (!riid
) riid
= &IID_IUnknown
;
239 TRACE("got %s\n", debugstr_guid(riid
));
243 /***********************************************************************
244 * NdrInterfacePointerMarshall [RPCRT4.@]
246 unsigned char * WINAPI
NdrInterfacePointerMarshall(PMIDL_STUB_MESSAGE pStubMsg
,
247 unsigned char *pMemory
,
248 PFORMAT_STRING pFormat
)
250 const IID
*riid
= get_ip_iid(pStubMsg
, pMemory
, pFormat
);
254 TRACE("(%p,%p,%p)\n", pStubMsg
, pMemory
, pFormat
);
255 pStubMsg
->MaxCount
= 0;
256 if (!LoadCOM()) return NULL
;
257 if (pStubMsg
->Buffer
+ sizeof(DWORD
) < pStubMsg
->BufferEnd
) {
258 stream
= RpcStream_Create(pStubMsg
, TRUE
);
260 hr
= COM_MarshalInterface(stream
, riid
, (LPUNKNOWN
)pMemory
,
261 pStubMsg
->dwDestContext
, pStubMsg
->pvDestContext
,
263 IStream_Release(stream
);
269 /***********************************************************************
270 * NdrInterfacePointerUnmarshall [RPCRT4.@]
272 unsigned char * WINAPI
NdrInterfacePointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg
,
273 unsigned char **ppMemory
,
274 PFORMAT_STRING pFormat
,
275 unsigned char fMustAlloc
)
280 TRACE("(%p,%p,%p,%d)\n", pStubMsg
, ppMemory
, pFormat
, fMustAlloc
);
281 if (!LoadCOM()) return NULL
;
282 *(LPVOID
*)ppMemory
= NULL
;
283 if (pStubMsg
->Buffer
+ sizeof(DWORD
) < pStubMsg
->BufferEnd
) {
284 stream
= RpcStream_Create(pStubMsg
, FALSE
);
286 hr
= COM_UnmarshalInterface(stream
, &IID_NULL
, (LPVOID
*)ppMemory
);
287 IStream_Release(stream
);
293 /***********************************************************************
294 * NdrInterfacePointerBufferSize [RPCRT4.@]
296 void WINAPI
NdrInterfacePointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg
,
297 unsigned char *pMemory
,
298 PFORMAT_STRING pFormat
)
300 const IID
*riid
= get_ip_iid(pStubMsg
, pMemory
, pFormat
);
304 TRACE("(%p,%p,%p)\n", pStubMsg
, pMemory
, pFormat
);
305 if (!LoadCOM()) return;
306 hr
= COM_GetMarshalSizeMax(&size
, riid
, (LPUNKNOWN
)pMemory
,
307 pStubMsg
->dwDestContext
, pStubMsg
->pvDestContext
,
309 TRACE("size=%ld\n", size
);
310 if (size
) pStubMsg
->BufferLength
+= sizeof(DWORD
) + size
;
313 /***********************************************************************
314 * NdrInterfacePointerMemorySize [RPCRT4.@]
316 unsigned long WINAPI
NdrInterfacePointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg
,
317 PFORMAT_STRING pFormat
)
319 FIXME("(%p,%p): stub\n", pStubMsg
, pFormat
);
323 /***********************************************************************
324 * NdrInterfacePointerFree [RPCRT4.@]
326 void WINAPI
NdrInterfacePointerFree(PMIDL_STUB_MESSAGE pStubMsg
,
327 unsigned char *pMemory
,
328 PFORMAT_STRING pFormat
)
330 LPUNKNOWN pUnk
= (LPUNKNOWN
)pMemory
;
331 TRACE("(%p,%p,%p)\n", pStubMsg
, pMemory
, pFormat
);
332 if (pUnk
) IUnknown_Release(pUnk
);
335 /***********************************************************************
336 * NdrOleAllocate [RPCRT4.@]
338 void * WINAPI
NdrOleAllocate(size_t Size
)
340 if (!LoadCOM()) return NULL
;
341 return COM_MemAlloc(Size
);
344 /***********************************************************************
345 * NdrOleFree [RPCRT4.@]
347 void WINAPI
NdrOleFree(void *NodeToFree
)
349 if (!LoadCOM()) return;
350 COM_MemFree(NodeToFree
);
354 HRESULT
RPCRT4_GetPSFactory(REFIID riid
, LPPSFACTORYBUFFER
*pPS
)
359 if (!LoadCOM()) return RPC_E_UNEXPECTED
;
360 hr
= COM_GetPSClsid(riid
, &clsid
);
361 if (FAILED(hr
)) return hr
;
362 hr
= COM_GetClassObject(&clsid
, CLSCTX_INPROC_SERVER
, NULL
,
363 &IID_IPSFactoryBuffer
, (LPVOID
*)pPS
);