Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenndr_ole.c
Go to the documentation of this file.
00001 /* 00002 * OLE32 callouts, COM interface marshalling 00003 * 00004 * Copyright 2001 Ove Kåven, TransGaming Technologies 00005 * 00006 * This library is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2.1 of the License, or (at your option) any later version. 00010 * 00011 * This library is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with this library; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00019 * 00020 * TODO: 00021 * - fix the wire-protocol to match MS/RPC 00022 * - finish RpcStream_Vtbl 00023 */ 00024 00025 #include <stdarg.h> 00026 #include <stdio.h> 00027 #include <string.h> 00028 00029 #define COBJMACROS 00030 #define NONAMELESSUNION 00031 #define NONAMELESSSTRUCT 00032 00033 #include "windef.h" 00034 #include "winbase.h" 00035 #include "winerror.h" 00036 00037 #include "objbase.h" 00038 00039 #include "ndr_misc.h" 00040 #include "rpcndr.h" 00041 #include "rpcproxy.h" 00042 #include "wine/rpcfc.h" 00043 #include "cpsf.h" 00044 00045 #include "wine/debug.h" 00046 00047 WINE_DEFAULT_DEBUG_CHANNEL(ole); 00048 00049 static HMODULE hOLE; 00050 00051 static HRESULT (WINAPI *COM_GetMarshalSizeMax)(ULONG *,REFIID,LPUNKNOWN,DWORD,LPVOID,DWORD); 00052 static HRESULT (WINAPI *COM_MarshalInterface)(LPSTREAM,REFIID,LPUNKNOWN,DWORD,LPVOID,DWORD); 00053 static HRESULT (WINAPI *COM_UnmarshalInterface)(LPSTREAM,REFIID,LPVOID*); 00054 static HRESULT (WINAPI *COM_ReleaseMarshalData)(LPSTREAM); 00055 static HRESULT (WINAPI *COM_GetClassObject)(REFCLSID,DWORD,COSERVERINFO *,REFIID,LPVOID *); 00056 static HRESULT (WINAPI *COM_GetPSClsid)(REFIID,CLSID *); 00057 static LPVOID (WINAPI *COM_MemAlloc)(ULONG); 00058 static void (WINAPI *COM_MemFree)(LPVOID); 00059 00060 static HMODULE LoadCOM(void) 00061 { 00062 if (hOLE) return hOLE; 00063 hOLE = LoadLibraryA("OLE32.DLL"); 00064 if (!hOLE) return 0; 00065 COM_GetMarshalSizeMax = (LPVOID)GetProcAddress(hOLE, "CoGetMarshalSizeMax"); 00066 COM_MarshalInterface = (LPVOID)GetProcAddress(hOLE, "CoMarshalInterface"); 00067 COM_UnmarshalInterface = (LPVOID)GetProcAddress(hOLE, "CoUnmarshalInterface"); 00068 COM_ReleaseMarshalData = (LPVOID)GetProcAddress(hOLE, "CoReleaseMarshalData"); 00069 COM_GetClassObject = (LPVOID)GetProcAddress(hOLE, "CoGetClassObject"); 00070 COM_GetPSClsid = (LPVOID)GetProcAddress(hOLE, "CoGetPSClsid"); 00071 COM_MemAlloc = (LPVOID)GetProcAddress(hOLE, "CoTaskMemAlloc"); 00072 COM_MemFree = (LPVOID)GetProcAddress(hOLE, "CoTaskMemFree"); 00073 return hOLE; 00074 } 00075 00076 /* CoMarshalInterface/CoUnmarshalInterface works on streams, 00077 * so implement a simple stream on top of the RPC buffer 00078 * (which also implements the MInterfacePointer structure) */ 00079 typedef struct RpcStreamImpl 00080 { 00081 IStream IStream_iface; 00082 LONG RefCount; 00083 PMIDL_STUB_MESSAGE pMsg; 00084 LPDWORD size; 00085 unsigned char *data; 00086 DWORD pos; 00087 } RpcStreamImpl; 00088 00089 static inline RpcStreamImpl *impl_from_IStream(IStream *iface) 00090 { 00091 return CONTAINING_RECORD(iface, RpcStreamImpl, IStream_iface); 00092 } 00093 00094 static HRESULT WINAPI RpcStream_QueryInterface(LPSTREAM iface, 00095 REFIID riid, 00096 LPVOID *obj) 00097 { 00098 RpcStreamImpl *This = impl_from_IStream(iface); 00099 if (IsEqualGUID(&IID_IUnknown, riid) || 00100 IsEqualGUID(&IID_ISequentialStream, riid) || 00101 IsEqualGUID(&IID_IStream, riid)) { 00102 *obj = This; 00103 InterlockedIncrement( &This->RefCount ); 00104 return S_OK; 00105 } 00106 return E_NOINTERFACE; 00107 } 00108 00109 static ULONG WINAPI RpcStream_AddRef(LPSTREAM iface) 00110 { 00111 RpcStreamImpl *This = impl_from_IStream(iface); 00112 return InterlockedIncrement( &This->RefCount ); 00113 } 00114 00115 static ULONG WINAPI RpcStream_Release(LPSTREAM iface) 00116 { 00117 RpcStreamImpl *This = impl_from_IStream(iface); 00118 ULONG ref = InterlockedDecrement( &This->RefCount ); 00119 if (!ref) { 00120 TRACE("size=%d\n", *This->size); 00121 This->pMsg->Buffer = This->data + *This->size; 00122 HeapFree(GetProcessHeap(),0,This); 00123 return 0; 00124 } 00125 return ref; 00126 } 00127 00128 static HRESULT WINAPI RpcStream_Read(LPSTREAM iface, 00129 void *pv, 00130 ULONG cb, 00131 ULONG *pcbRead) 00132 { 00133 RpcStreamImpl *This = impl_from_IStream(iface); 00134 HRESULT hr = S_OK; 00135 if (This->pos + cb > *This->size) 00136 { 00137 cb = *This->size - This->pos; 00138 hr = S_FALSE; 00139 } 00140 if (cb) { 00141 memcpy(pv, This->data + This->pos, cb); 00142 This->pos += cb; 00143 } 00144 if (pcbRead) *pcbRead = cb; 00145 return hr; 00146 } 00147 00148 static HRESULT WINAPI RpcStream_Write(LPSTREAM iface, 00149 const void *pv, 00150 ULONG cb, 00151 ULONG *pcbWritten) 00152 { 00153 RpcStreamImpl *This = impl_from_IStream(iface); 00154 if (This->data + cb > (unsigned char *)This->pMsg->RpcMsg->Buffer + This->pMsg->BufferLength) 00155 return STG_E_MEDIUMFULL; 00156 memcpy(This->data + This->pos, pv, cb); 00157 This->pos += cb; 00158 if (This->pos > *This->size) *This->size = This->pos; 00159 if (pcbWritten) *pcbWritten = cb; 00160 return S_OK; 00161 } 00162 00163 static HRESULT WINAPI RpcStream_Seek(LPSTREAM iface, 00164 LARGE_INTEGER move, 00165 DWORD origin, 00166 ULARGE_INTEGER *newPos) 00167 { 00168 RpcStreamImpl *This = impl_from_IStream(iface); 00169 switch (origin) { 00170 case STREAM_SEEK_SET: 00171 This->pos = move.u.LowPart; 00172 break; 00173 case STREAM_SEEK_CUR: 00174 This->pos = This->pos + move.u.LowPart; 00175 break; 00176 case STREAM_SEEK_END: 00177 This->pos = *This->size + move.u.LowPart; 00178 break; 00179 default: 00180 return STG_E_INVALIDFUNCTION; 00181 } 00182 if (newPos) { 00183 newPos->u.LowPart = This->pos; 00184 newPos->u.HighPart = 0; 00185 } 00186 return S_OK; 00187 } 00188 00189 static HRESULT WINAPI RpcStream_SetSize(LPSTREAM iface, 00190 ULARGE_INTEGER newSize) 00191 { 00192 RpcStreamImpl *This = impl_from_IStream(iface); 00193 *This->size = newSize.u.LowPart; 00194 return S_OK; 00195 } 00196 00197 static const IStreamVtbl RpcStream_Vtbl = 00198 { 00199 RpcStream_QueryInterface, 00200 RpcStream_AddRef, 00201 RpcStream_Release, 00202 RpcStream_Read, 00203 RpcStream_Write, 00204 RpcStream_Seek, 00205 RpcStream_SetSize, 00206 NULL, /* CopyTo */ 00207 NULL, /* Commit */ 00208 NULL, /* Revert */ 00209 NULL, /* LockRegion */ 00210 NULL, /* UnlockRegion */ 00211 NULL, /* Stat */ 00212 NULL /* Clone */ 00213 }; 00214 00215 static LPSTREAM RpcStream_Create(PMIDL_STUB_MESSAGE pStubMsg, BOOL init) 00216 { 00217 RpcStreamImpl *This; 00218 This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(RpcStreamImpl)); 00219 if (!This) return NULL; 00220 This->IStream_iface.lpVtbl = &RpcStream_Vtbl; 00221 This->RefCount = 1; 00222 This->pMsg = pStubMsg; 00223 This->size = (LPDWORD)pStubMsg->Buffer; 00224 This->data = (unsigned char*)(This->size + 1); 00225 This->pos = 0; 00226 if (init) *This->size = 0; 00227 TRACE("init size=%d\n", *This->size); 00228 return (LPSTREAM)This; 00229 } 00230 00231 static const IID* get_ip_iid(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat) 00232 { 00233 const IID *riid; 00234 if (!pFormat) return &IID_IUnknown; 00235 TRACE("format=%02x %02x\n", pFormat[0], pFormat[1]); 00236 if (pFormat[0] != RPC_FC_IP) FIXME("format=%d\n", pFormat[0]); 00237 if (pFormat[1] == RPC_FC_CONSTANT_IID) { 00238 riid = (const IID *)&pFormat[2]; 00239 } else { 00240 ComputeConformance(pStubMsg, pMemory, pFormat+2, 0); 00241 riid = (const IID *)pStubMsg->MaxCount; 00242 } 00243 if (!riid) riid = &IID_IUnknown; 00244 TRACE("got %s\n", debugstr_guid(riid)); 00245 return riid; 00246 } 00247 00248 /*********************************************************************** 00249 * NdrInterfacePointerMarshall [RPCRT4.@] 00250 */ 00251 unsigned char * WINAPI NdrInterfacePointerMarshall(PMIDL_STUB_MESSAGE pStubMsg, 00252 unsigned char *pMemory, 00253 PFORMAT_STRING pFormat) 00254 { 00255 const IID *riid = get_ip_iid(pStubMsg, pMemory, pFormat); 00256 LPSTREAM stream; 00257 HRESULT hr; 00258 00259 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); 00260 pStubMsg->MaxCount = 0; 00261 if (!LoadCOM()) return NULL; 00262 if (pStubMsg->Buffer + sizeof(DWORD) <= (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) { 00263 stream = RpcStream_Create(pStubMsg, TRUE); 00264 if (stream) { 00265 if (pMemory) 00266 hr = COM_MarshalInterface(stream, riid, (LPUNKNOWN)pMemory, 00267 pStubMsg->dwDestContext, pStubMsg->pvDestContext, 00268 MSHLFLAGS_NORMAL); 00269 else 00270 hr = S_OK; 00271 00272 IStream_Release(stream); 00273 if (FAILED(hr)) 00274 RpcRaiseException(hr); 00275 } 00276 } 00277 return NULL; 00278 } 00279 00280 /*********************************************************************** 00281 * NdrInterfacePointerUnmarshall [RPCRT4.@] 00282 */ 00283 unsigned char * WINAPI NdrInterfacePointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, 00284 unsigned char **ppMemory, 00285 PFORMAT_STRING pFormat, 00286 unsigned char fMustAlloc) 00287 { 00288 LPSTREAM stream; 00289 HRESULT hr; 00290 00291 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); 00292 if (!LoadCOM()) return NULL; 00293 *(LPVOID*)ppMemory = NULL; 00294 if (pStubMsg->Buffer + sizeof(DWORD) < (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) { 00295 stream = RpcStream_Create(pStubMsg, FALSE); 00296 if (!stream) RpcRaiseException(E_OUTOFMEMORY); 00297 if (*((RpcStreamImpl *)stream)->size != 0) 00298 hr = COM_UnmarshalInterface(stream, &IID_NULL, (LPVOID*)ppMemory); 00299 else 00300 hr = S_OK; 00301 IStream_Release(stream); 00302 if (FAILED(hr)) 00303 RpcRaiseException(hr); 00304 } 00305 return NULL; 00306 } 00307 00308 /*********************************************************************** 00309 * NdrInterfacePointerBufferSize [RPCRT4.@] 00310 */ 00311 void WINAPI NdrInterfacePointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg, 00312 unsigned char *pMemory, 00313 PFORMAT_STRING pFormat) 00314 { 00315 const IID *riid = get_ip_iid(pStubMsg, pMemory, pFormat); 00316 ULONG size = 0; 00317 00318 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); 00319 if (!LoadCOM()) return; 00320 COM_GetMarshalSizeMax(&size, riid, (LPUNKNOWN)pMemory, 00321 pStubMsg->dwDestContext, pStubMsg->pvDestContext, 00322 MSHLFLAGS_NORMAL); 00323 TRACE("size=%d\n", size); 00324 pStubMsg->BufferLength += sizeof(DWORD) + size; 00325 } 00326 00327 /*********************************************************************** 00328 * NdrInterfacePointerMemorySize [RPCRT4.@] 00329 */ 00330 ULONG WINAPI NdrInterfacePointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg, 00331 PFORMAT_STRING pFormat) 00332 { 00333 ULONG size; 00334 00335 TRACE("(%p,%p)\n", pStubMsg, pFormat); 00336 00337 size = *(ULONG *)pStubMsg->Buffer; 00338 pStubMsg->Buffer += 4; 00339 pStubMsg->MemorySize += 4; 00340 00341 pStubMsg->Buffer += size; 00342 00343 return pStubMsg->MemorySize; 00344 } 00345 00346 /*********************************************************************** 00347 * NdrInterfacePointerFree [RPCRT4.@] 00348 */ 00349 void WINAPI NdrInterfacePointerFree(PMIDL_STUB_MESSAGE pStubMsg, 00350 unsigned char *pMemory, 00351 PFORMAT_STRING pFormat) 00352 { 00353 LPUNKNOWN pUnk = (LPUNKNOWN)pMemory; 00354 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); 00355 if (pUnk) IUnknown_Release(pUnk); 00356 } 00357 00358 /*********************************************************************** 00359 * NdrOleAllocate [RPCRT4.@] 00360 */ 00361 void * WINAPI NdrOleAllocate(SIZE_T Size) 00362 { 00363 if (!LoadCOM()) return NULL; 00364 return COM_MemAlloc(Size); 00365 } 00366 00367 /*********************************************************************** 00368 * NdrOleFree [RPCRT4.@] 00369 */ 00370 void WINAPI NdrOleFree(void *NodeToFree) 00371 { 00372 if (!LoadCOM()) return; 00373 COM_MemFree(NodeToFree); 00374 } 00375 00376 /*********************************************************************** 00377 * Helper function to create a proxy. 00378 * Probably similar to NdrpCreateProxy. 00379 */ 00380 HRESULT create_proxy(REFIID iid, IUnknown *pUnkOuter, IRpcProxyBuffer **pproxy, void **ppv) 00381 { 00382 CLSID clsid; 00383 IPSFactoryBuffer *psfac; 00384 HRESULT r; 00385 00386 if(!LoadCOM()) return E_FAIL; 00387 00388 r = COM_GetPSClsid( iid, &clsid ); 00389 if(FAILED(r)) return r; 00390 00391 r = COM_GetClassObject( &clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IPSFactoryBuffer, (void**)&psfac ); 00392 if(FAILED(r)) return r; 00393 00394 r = IPSFactoryBuffer_CreateProxy(psfac, pUnkOuter, iid, pproxy, ppv); 00395 00396 IPSFactoryBuffer_Release(psfac); 00397 return r; 00398 } 00399 00400 /*********************************************************************** 00401 * Helper function to create a stub. 00402 * This probably looks very much like NdrpCreateStub. 00403 */ 00404 HRESULT create_stub(REFIID iid, IUnknown *pUnk, IRpcStubBuffer **ppstub) 00405 { 00406 CLSID clsid; 00407 IPSFactoryBuffer *psfac; 00408 HRESULT r; 00409 00410 if(!LoadCOM()) return E_FAIL; 00411 00412 r = COM_GetPSClsid( iid, &clsid ); 00413 if(FAILED(r)) return r; 00414 00415 r = COM_GetClassObject( &clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IPSFactoryBuffer, (void**)&psfac ); 00416 if(FAILED(r)) return r; 00417 00418 r = IPSFactoryBuffer_CreateStub(psfac, iid, pUnk, ppstub); 00419 00420 IPSFactoryBuffer_Release(psfac); 00421 return r; 00422 } Generated on Sun May 27 2012 04:26:03 for ReactOS by
1.7.6.1
|