ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

ndr_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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.