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
30 #define NONAMELESSUNION
31 #define NONAMELESSSTRUCT
41 #include "wine/debug.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
47 static HRESULT
WINAPI (*COM_GetMarshalSizeMax
)(ULONG
*,REFIID
,LPUNKNOWN
,DWORD
,LPVOID
,DWORD
);
48 static HRESULT
WINAPI (*COM_MarshalInterface
)(LPSTREAM
,REFIID
,LPUNKNOWN
,DWORD
,LPVOID
,DWORD
);
49 static HRESULT
WINAPI (*COM_UnmarshalInterface
)(LPSTREAM
,REFIID
,LPVOID
*);
50 static HRESULT
WINAPI (*COM_ReleaseMarshalData
)(LPSTREAM
);
51 static HRESULT
WINAPI (*COM_GetClassObject
)(REFCLSID
,DWORD
,COSERVERINFO
*,REFIID
,LPVOID
*);
52 static HRESULT
WINAPI (*COM_GetPSClsid
)(REFIID
,CLSID
*);
53 static LPVOID
WINAPI (*COM_MemAlloc
)(ULONG
);
54 static void WINAPI (*COM_MemFree
)(LPVOID
);
56 static HMODULE
LoadCOM(void)
58 if (hOLE
) return hOLE
;
59 hOLE
= LoadLibraryA("OLE32.DLL");
61 COM_GetMarshalSizeMax
= (LPVOID
)GetProcAddress(hOLE
, "CoGetMarshalSizeMax");
62 COM_MarshalInterface
= (LPVOID
)GetProcAddress(hOLE
, "CoMarshalInterface");
63 COM_UnmarshalInterface
= (LPVOID
)GetProcAddress(hOLE
, "CoUnmarshalInterface");
64 COM_ReleaseMarshalData
= (LPVOID
)GetProcAddress(hOLE
, "CoReleaseMarshalData");
65 COM_GetClassObject
= (LPVOID
)GetProcAddress(hOLE
, "CoGetClassObject");
66 COM_GetPSClsid
= (LPVOID
)GetProcAddress(hOLE
, "CoGetPSClsid");
67 COM_MemAlloc
= (LPVOID
)GetProcAddress(hOLE
, "CoTaskMemAlloc");
68 COM_MemFree
= (LPVOID
)GetProcAddress(hOLE
, "CoTaskMemFree");
72 /* CoMarshalInterface/CoUnmarshalInterface works on streams,
73 * so implement a simple stream on top of the RPC buffer
74 * (which also implements the MInterfacePointer structure) */
75 typedef struct RpcStreamImpl
79 PMIDL_STUB_MESSAGE pMsg
;
85 static HRESULT WINAPI
RpcStream_QueryInterface(LPSTREAM iface
,
89 ICOM_THIS(RpcStreamImpl
, iface
);
90 if (IsEqualGUID(&IID_IUnknown
, riid
) ||
91 IsEqualGUID(&IID_ISequentialStream
, riid
) ||
92 IsEqualGUID(&IID_IStream
, riid
)) {
100 static ULONG WINAPI
RpcStream_AddRef(LPSTREAM iface
)
102 ICOM_THIS(RpcStreamImpl
, iface
);
103 return ++(This
->RefCount
);
106 static ULONG WINAPI
RpcStream_Release(LPSTREAM iface
)
108 ICOM_THIS(RpcStreamImpl
, iface
);
109 if (!--(This
->RefCount
)) {
110 TRACE("size=%ld\n", *This
->size
);
111 This
->pMsg
->Buffer
= This
->data
+ *This
->size
;
112 HeapFree(GetProcessHeap(),0,This
);
115 return This
->RefCount
;
118 static HRESULT WINAPI
RpcStream_Read(LPSTREAM iface
,
123 ICOM_THIS(RpcStreamImpl
, iface
);
124 if (This
->pos
+ cb
> *This
->size
) cb
= *This
->size
- This
->pos
;
126 memcpy(pv
, This
->data
+ This
->pos
, cb
);
129 if (pcbRead
) *pcbRead
= cb
;
133 static HRESULT WINAPI
RpcStream_Write(LPSTREAM iface
,
138 ICOM_THIS(RpcStreamImpl
, iface
);
139 memcpy(This
->data
+ This
->pos
, pv
, cb
);
141 if (This
->pos
> *This
->size
) *This
->size
= This
->pos
;
142 if (pcbWritten
) *pcbWritten
= cb
;
146 static HRESULT WINAPI
RpcStream_Seek(LPSTREAM iface
,
149 ULARGE_INTEGER
*newPos
)
151 ICOM_THIS(RpcStreamImpl
, iface
);
153 case STREAM_SEEK_SET
:
154 This
->pos
= move
.s
.LowPart
;
156 case STREAM_SEEK_CUR
:
157 This
->pos
= This
->pos
+ move
.s
.LowPart
;
159 case STREAM_SEEK_END
:
160 This
->pos
= *This
->size
+ move
.s
.LowPart
;
163 return STG_E_INVALIDFUNCTION
;
166 newPos
->s
.LowPart
= This
->pos
;
167 newPos
->s
.HighPart
= 0;
172 static HRESULT WINAPI
RpcStream_SetSize(LPSTREAM iface
,
173 ULARGE_INTEGER newSize
)
175 ICOM_THIS(RpcStreamImpl
, iface
);
176 *This
->size
= newSize
.s
.LowPart
;
180 static ICOM_VTABLE(IStream
) RpcStream_Vtbl
=
182 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
183 RpcStream_QueryInterface
,
193 NULL
, /* LockRegion */
194 NULL
, /* UnlockRegion */
199 static LPSTREAM
RpcStream_Create(PMIDL_STUB_MESSAGE pStubMsg
, BOOL init
)
202 This
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(RpcStreamImpl
));
203 if (!This
) return NULL
;
204 This
->lpVtbl
= &RpcStream_Vtbl
;
206 This
->pMsg
= pStubMsg
;
207 This
->size
= (LPDWORD
)pStubMsg
->Buffer
;
208 This
->data
= (char*)(This
->size
+ 1);
210 if (init
) *This
->size
= 0;
211 TRACE("init size=%ld\n", *This
->size
);
212 return (LPSTREAM
)This
;
215 /***********************************************************************
216 * NdrInterfacePointerMarshall [RPCRT4.@]
218 unsigned char * WINAPI
NdrInterfacePointerMarshall(PMIDL_STUB_MESSAGE pStubMsg
,
219 unsigned char *pMemory
,
220 PFORMAT_STRING pFormat
)
222 const IID
*riid
= (const IID
*)pStubMsg
->MaxCount
;
226 TRACE("(%p,%p,%p)\n", pStubMsg
, pMemory
, pFormat
);
227 if (!riid
) riid
= &IID_IUnknown
;
228 pStubMsg
->MaxCount
= 0;
229 if (!LoadCOM()) return NULL
;
230 stream
= RpcStream_Create(pStubMsg
, TRUE
);
231 hr
= COM_MarshalInterface(stream
, riid
, (LPUNKNOWN
)pMemory
,
232 pStubMsg
->dwDestContext
, pStubMsg
->pvDestContext
,
234 IStream_Release(stream
);
238 /***********************************************************************
239 * NdrInterfacePointerUnmarshall [RPCRT4.@]
241 unsigned char * WINAPI
NdrInterfacePointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg
,
242 unsigned char **ppMemory
,
243 PFORMAT_STRING pFormat
,
244 unsigned char fMustAlloc
)
249 TRACE("(%p,%p,%p,%d)\n", pStubMsg
, ppMemory
, pFormat
, fMustAlloc
);
250 if (!LoadCOM()) return NULL
;
251 *(LPVOID
*)ppMemory
= NULL
;
252 stream
= RpcStream_Create(pStubMsg
, FALSE
);
253 hr
= COM_UnmarshalInterface(stream
, &IID_NULL
, (LPVOID
*)ppMemory
);
254 IStream_Release(stream
);
258 /***********************************************************************
259 * NdrInterfacePointerBufferSize [RPCRT4.@]
261 void WINAPI
NdrInterfacePointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg
,
262 unsigned char *pMemory
,
263 PFORMAT_STRING pFormat
)
265 const IID
*riid
= (const IID
*)pStubMsg
->MaxCount
;
269 TRACE("(%p,%p,%p)\n", pStubMsg
, pMemory
, pFormat
);
270 if (!riid
) riid
= &IID_IUnknown
;
271 if (!LoadCOM()) return;
272 hr
= COM_GetMarshalSizeMax(&size
, riid
, (LPUNKNOWN
)pMemory
,
273 pStubMsg
->dwDestContext
, pStubMsg
->pvDestContext
,
275 TRACE("size=%ld\n", size
);
276 pStubMsg
->BufferLength
+= sizeof(DWORD
) + size
;
279 /***********************************************************************
280 * NdrInterfacePointerMemorySize [RPCRT4.@]
282 unsigned long WINAPI
NdrInterfacePointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg
,
283 PFORMAT_STRING pFormat
)
285 FIXME("(%p,%p): stub\n", pStubMsg
, pFormat
);
289 /***********************************************************************
290 * NdrInterfacePointerFree [RPCRT4.@]
292 void WINAPI
NdrInterfacePointerFree(PMIDL_STUB_MESSAGE pStubMsg
,
293 unsigned char *pMemory
,
294 PFORMAT_STRING pFormat
)
296 LPUNKNOWN pUnk
= (LPUNKNOWN
)pMemory
;
297 TRACE("(%p,%p,%p)\n", pStubMsg
, pMemory
, pFormat
);
298 if (pUnk
) IUnknown_Release(pUnk
);
301 /***********************************************************************
302 * NdrOleAllocate [RPCRT4.@]
304 void * WINAPI
NdrOleAllocate(size_t Size
)
306 if (!LoadCOM()) return NULL
;
307 return COM_MemAlloc(Size
);
310 /***********************************************************************
311 * NdrOleFree [RPCRT4.@]
313 void WINAPI
NdrOleFree(void *NodeToFree
)
315 if (!LoadCOM()) return;
316 COM_MemFree(NodeToFree
);
320 HRESULT
RPCRT4_GetPSFactory(REFIID riid
, LPPSFACTORYBUFFER
*pPS
)
325 if (!LoadCOM()) return RPC_E_UNEXPECTED
;
326 hr
= COM_GetPSClsid(riid
, &clsid
);
327 if (FAILED(hr
)) return hr
;
328 hr
= COM_GetClassObject(&clsid
, CLSCTX_INPROC_SERVER
, NULL
,
329 &IID_IPSFactoryBuffer
, (LPVOID
*)pPS
);