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

tmarshal.c
Go to the documentation of this file.
00001 /*
00002  *  TYPELIB Marshaler
00003  *
00004  *  Copyright 2002,2005 Marcus Meissner
00005  *
00006  * The olerelay debug channel allows you to see calls marshalled by
00007  * the typelib marshaller. It is not a generic COM relaying system.
00008  *
00009  * This library is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU Lesser General Public
00011  * License as published by the Free Software Foundation; either
00012  * version 2.1 of the License, or (at your option) any later version.
00013  *
00014  * This library is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017  * Lesser General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU Lesser General Public
00020  * License along with this library; if not, write to the Free Software
00021  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00022  */
00023 
00024 #include "config.h"
00025 #include "wine/port.h"
00026 
00027 #include <assert.h>
00028 #include <stdlib.h>
00029 #include <string.h>
00030 #include <stdarg.h>
00031 #include <stdio.h>
00032 #include <ctype.h>
00033 
00034 #define COBJMACROS
00035 #define NONAMELESSUNION
00036 #define NONAMELESSSTRUCT
00037 
00038 #include "winerror.h"
00039 #include "windef.h"
00040 #include "winbase.h"
00041 #include "winnls.h"
00042 #include "winreg.h"
00043 #include "winuser.h"
00044 
00045 #include "ole2.h"
00046 #include "propidl.h" /* for LPSAFEARRAY_User* functions */
00047 #include "typelib.h"
00048 #include "variant.h"
00049 #include "wine/debug.h"
00050 #include "wine/exception.h"
00051 
00052 static const WCHAR IDispatchW[] = { 'I','D','i','s','p','a','t','c','h',0};
00053 
00054 WINE_DEFAULT_DEBUG_CHANNEL(ole);
00055 WINE_DECLARE_DEBUG_CHANNEL(olerelay);
00056 
00057 #define ICOM_THIS_MULTI(impl,field,iface) impl* const This=(impl*)((char*)(iface) - offsetof(impl,field))
00058 
00059 static HRESULT TMarshalDispatchChannel_Create(
00060     IRpcChannelBuffer *pDelegateChannel, REFIID tmarshal_riid,
00061     IRpcChannelBuffer **ppChannel);
00062 
00063 typedef struct _marshal_state {
00064     LPBYTE  base;
00065     int     size;
00066     int     curoff;
00067 } marshal_state;
00068 
00069 /* used in the olerelay code to avoid having the L"" stuff added by debugstr_w */
00070 static char *relaystr(WCHAR *in) {
00071     char *tmp = (char *)debugstr_w(in);
00072     tmp += 2;
00073     tmp[strlen(tmp)-1] = '\0';
00074     return tmp;
00075 }
00076 
00077 static HRESULT
00078 xbuf_resize(marshal_state *buf, DWORD newsize)
00079 {
00080     if(buf->size >= newsize)
00081         return S_FALSE;
00082 
00083     if(buf->base)
00084     {
00085         buf->base = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, buf->base, newsize);
00086         if(!buf->base)
00087             return E_OUTOFMEMORY;
00088     }
00089     else
00090     {
00091         buf->base = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, newsize);
00092         if(!buf->base)
00093             return E_OUTOFMEMORY;
00094     }
00095     buf->size = newsize;
00096     return S_OK;
00097 }
00098 
00099 static HRESULT
00100 xbuf_add(marshal_state *buf, const BYTE *stuff, DWORD size)
00101 {
00102     HRESULT hr;
00103 
00104     if(buf->size - buf->curoff < size)
00105     {
00106         hr = xbuf_resize(buf, buf->size + size + 100);
00107         if(FAILED(hr)) return hr;
00108     }
00109     memcpy(buf->base+buf->curoff,stuff,size);
00110     buf->curoff += size;
00111     return S_OK;
00112 }
00113 
00114 static HRESULT
00115 xbuf_get(marshal_state *buf, LPBYTE stuff, DWORD size) {
00116     if (buf->size < buf->curoff+size) return E_FAIL;
00117     memcpy(stuff,buf->base+buf->curoff,size);
00118     buf->curoff += size;
00119     return S_OK;
00120 }
00121 
00122 static HRESULT
00123 xbuf_skip(marshal_state *buf, DWORD size) {
00124     if (buf->size < buf->curoff+size) return E_FAIL;
00125     buf->curoff += size;
00126     return S_OK;
00127 }
00128 
00129 static HRESULT
00130 _unmarshal_interface(marshal_state *buf, REFIID riid, LPUNKNOWN *pUnk) {
00131     IStream     *pStm;
00132     ULARGE_INTEGER  newpos;
00133     LARGE_INTEGER   seekto;
00134     ULONG       res;
00135     HRESULT     hres;
00136     DWORD       xsize;
00137 
00138     TRACE("...%s...\n",debugstr_guid(riid));
00139 
00140     *pUnk = NULL;
00141     hres = xbuf_get(buf,(LPBYTE)&xsize,sizeof(xsize));
00142     if (hres) {
00143         ERR("xbuf_get failed\n");
00144         return hres;
00145     }
00146 
00147     if (xsize == 0) return S_OK;
00148 
00149     hres = CreateStreamOnHGlobal(0,TRUE,&pStm);
00150     if (hres) {
00151     ERR("Stream create failed %x\n",hres);
00152     return hres;
00153     }
00154 
00155     hres = IStream_Write(pStm,buf->base+buf->curoff,xsize,&res);
00156     if (hres) {
00157         ERR("stream write %x\n",hres);
00158         return hres;
00159     }
00160 
00161     memset(&seekto,0,sizeof(seekto));
00162     hres = IStream_Seek(pStm,seekto,SEEK_SET,&newpos);
00163     if (hres) {
00164         ERR("Failed Seek %x\n",hres);
00165         return hres;
00166     }
00167 
00168     hres = CoUnmarshalInterface(pStm,riid,(LPVOID*)pUnk);
00169     if (hres) {
00170     ERR("Unmarshalling interface %s failed with %x\n",debugstr_guid(riid),hres);
00171     return hres;
00172     }
00173 
00174     IStream_Release(pStm);
00175     return xbuf_skip(buf,xsize);
00176 }
00177 
00178 static HRESULT
00179 _marshal_interface(marshal_state *buf, REFIID riid, LPUNKNOWN pUnk) {
00180     LPBYTE      tempbuf = NULL;
00181     IStream     *pStm = NULL;
00182     STATSTG     ststg;
00183     ULARGE_INTEGER  newpos;
00184     LARGE_INTEGER   seekto;
00185     ULONG       res;
00186     DWORD       xsize;
00187     HRESULT     hres;
00188 
00189     if (!pUnk) {
00190     /* this is valid, if for instance we serialize
00191      * a VT_DISPATCH with NULL ptr which apparently
00192      * can happen. S_OK to make sure we continue
00193      * serializing.
00194      */
00195         WARN("pUnk is NULL\n");
00196         xsize = 0;
00197         return xbuf_add(buf,(LPBYTE)&xsize,sizeof(xsize));
00198     }
00199 
00200     hres = E_FAIL;
00201 
00202     TRACE("...%s...\n",debugstr_guid(riid));
00203 
00204     hres = CreateStreamOnHGlobal(0,TRUE,&pStm);
00205     if (hres) {
00206     ERR("Stream create failed %x\n",hres);
00207     goto fail;
00208     }
00209 
00210     hres = CoMarshalInterface(pStm,riid,pUnk,0,NULL,0);
00211     if (hres) {
00212     ERR("Marshalling interface %s failed with %x\n", debugstr_guid(riid), hres);
00213     goto fail;
00214     }
00215 
00216     hres = IStream_Stat(pStm,&ststg,STATFLAG_NONAME);
00217     if (hres) {
00218         ERR("Stream stat failed\n");
00219         goto fail;
00220     }
00221 
00222     tempbuf = HeapAlloc(GetProcessHeap(), 0, ststg.cbSize.u.LowPart);
00223     memset(&seekto,0,sizeof(seekto));
00224     hres = IStream_Seek(pStm,seekto,SEEK_SET,&newpos);
00225     if (hres) {
00226         ERR("Failed Seek %x\n",hres);
00227         goto fail;
00228     }
00229 
00230     hres = IStream_Read(pStm,tempbuf,ststg.cbSize.u.LowPart,&res);
00231     if (hres) {
00232         ERR("Failed Read %x\n",hres);
00233         goto fail;
00234     }
00235 
00236     xsize = ststg.cbSize.u.LowPart;
00237     xbuf_add(buf,(LPBYTE)&xsize,sizeof(xsize));
00238     hres = xbuf_add(buf,tempbuf,ststg.cbSize.u.LowPart);
00239 
00240     HeapFree(GetProcessHeap(),0,tempbuf);
00241     IStream_Release(pStm);
00242 
00243     return hres;
00244 
00245 fail:
00246     xsize = 0;
00247     xbuf_add(buf,(LPBYTE)&xsize,sizeof(xsize));
00248     if (pStm) IUnknown_Release(pStm);
00249     HeapFree(GetProcessHeap(), 0, tempbuf);
00250     return hres;
00251 }
00252 
00253 /********************* OLE Proxy/Stub Factory ********************************/
00254 static HRESULT WINAPI
00255 PSFacBuf_QueryInterface(LPPSFACTORYBUFFER iface, REFIID iid, LPVOID *ppv) {
00256     if (IsEqualIID(iid,&IID_IPSFactoryBuffer)||IsEqualIID(iid,&IID_IUnknown)) {
00257         *ppv = iface;
00258     /* No ref counting, static class */
00259     return S_OK;
00260     }
00261     FIXME("(%s) unknown IID?\n",debugstr_guid(iid));
00262     return E_NOINTERFACE;
00263 }
00264 
00265 static ULONG WINAPI PSFacBuf_AddRef(LPPSFACTORYBUFFER iface) { return 2; }
00266 static ULONG WINAPI PSFacBuf_Release(LPPSFACTORYBUFFER iface) { return 1; }
00267 
00268 static HRESULT
00269 _get_typeinfo_for_iid(REFIID riid, ITypeInfo**ti) {
00270     HRESULT hres;
00271     HKEY    ikey;
00272     char    tlguid[200],typelibkey[300],interfacekey[300],ver[100];
00273     char    tlfn[260];
00274     OLECHAR tlfnW[260];
00275     DWORD   tlguidlen, verlen, type;
00276     LONG    tlfnlen;
00277     ITypeLib    *tl;
00278 
00279     sprintf( interfacekey, "Interface\\{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\Typelib",
00280     riid->Data1, riid->Data2, riid->Data3,
00281     riid->Data4[0], riid->Data4[1], riid->Data4[2], riid->Data4[3],
00282     riid->Data4[4], riid->Data4[5], riid->Data4[6], riid->Data4[7]
00283     );
00284 
00285     if (RegOpenKeyA(HKEY_CLASSES_ROOT,interfacekey,&ikey)) {
00286     ERR("No %s key found.\n",interfacekey);
00287         return E_FAIL;
00288     }
00289     tlguidlen = sizeof(tlguid);
00290     if (RegQueryValueExA(ikey,NULL,NULL,&type,(LPBYTE)tlguid,&tlguidlen)) {
00291     ERR("Getting typelib guid failed.\n");
00292     RegCloseKey(ikey);
00293     return E_FAIL;
00294     }
00295     verlen = sizeof(ver);
00296     if (RegQueryValueExA(ikey,"Version",NULL,&type,(LPBYTE)ver,&verlen)) {
00297     ERR("Could not get version value?\n");
00298     RegCloseKey(ikey);
00299     return E_FAIL;
00300     }
00301     RegCloseKey(ikey);
00302     sprintf(typelibkey,"Typelib\\%s\\%s\\0\\win%u",tlguid,ver,(sizeof(void*) == 8) ? 64 : 32);
00303     tlfnlen = sizeof(tlfn);
00304     if (RegQueryValueA(HKEY_CLASSES_ROOT,typelibkey,tlfn,&tlfnlen)) {
00305     ERR("Could not get typelib fn?\n");
00306     return E_FAIL;
00307     }
00308     MultiByteToWideChar(CP_ACP, 0, tlfn, -1, tlfnW, sizeof(tlfnW) / sizeof(tlfnW[0]));
00309     hres = LoadTypeLib(tlfnW,&tl);
00310     if (hres) {
00311     ERR("Failed to load typelib for %s, but it should be there.\n",debugstr_guid(riid));
00312     return hres;
00313     }
00314     hres = ITypeLib_GetTypeInfoOfGuid(tl,riid,ti);
00315     if (hres) {
00316     ERR("typelib does not contain info for %s?\n",debugstr_guid(riid));
00317     ITypeLib_Release(tl);
00318     return hres;
00319     }
00320     ITypeLib_Release(tl);
00321     return hres;
00322 }
00323 
00324 /*
00325  * Determine the number of functions including all inherited functions.
00326  * Note for non-dual dispinterfaces we simply return the size of IDispatch.
00327  */
00328 static HRESULT num_of_funcs(ITypeInfo *tinfo, unsigned int *num)
00329 {
00330     HRESULT hres;
00331     TYPEATTR *attr;
00332     ITypeInfo *tinfo2;
00333 
00334     *num = 0;
00335     hres = ITypeInfo_GetTypeAttr(tinfo, &attr);
00336     if (hres) {
00337         ERR("GetTypeAttr failed with %x\n",hres);
00338         return hres;
00339     }
00340 
00341     if(attr->typekind == TKIND_DISPATCH && (attr->wTypeFlags & TYPEFLAG_FDUAL))
00342     {
00343         HREFTYPE href;
00344         hres = ITypeInfo_GetRefTypeOfImplType(tinfo, -1, &href);
00345         if(FAILED(hres))
00346         {
00347             ERR("Unable to get interface href from dual dispinterface\n");
00348             goto end;
00349         }
00350         hres = ITypeInfo_GetRefTypeInfo(tinfo, href, &tinfo2);
00351         if(FAILED(hres))
00352         {
00353             ERR("Unable to get interface from dual dispinterface\n");
00354             goto end;
00355         }
00356         hres = num_of_funcs(tinfo2, num);
00357         ITypeInfo_Release(tinfo2);
00358     }
00359     else
00360     {
00361         *num = attr->cbSizeVft / 4;
00362     }
00363 
00364  end:
00365     ITypeInfo_ReleaseTypeAttr(tinfo, attr);
00366     return hres;
00367 }
00368 
00369 #ifdef __i386__
00370 
00371 #include "pshpack1.h"
00372 
00373 typedef struct _TMAsmProxy {
00374     BYTE    popleax;
00375     BYTE    pushlval;
00376     DWORD   nr;
00377     BYTE    pushleax;
00378     BYTE    lcall;
00379     DWORD   xcall;
00380     BYTE    lret;
00381     WORD    bytestopop;
00382     BYTE    nop;
00383 } TMAsmProxy;
00384 
00385 #include "poppack.h"
00386 
00387 #else /* __i386__ */
00388 #ifdef _MSC_VER
00389 #pragma message("You need to implement stubless proxies for your architecture")
00390 #else
00391 # warning You need to implement stubless proxies for your architecture
00392 #endif
00393 typedef struct _TMAsmProxy {
00394     char a;
00395 } TMAsmProxy;
00396 #endif
00397 
00398 typedef struct _TMProxyImpl {
00399     LPVOID                             *lpvtbl;
00400     const IRpcProxyBufferVtbl          *lpvtbl2;
00401     LONG                ref;
00402 
00403     TMAsmProxy              *asmstubs;
00404     ITypeInfo*              tinfo;
00405     IRpcChannelBuffer*          chanbuf;
00406     IID                 iid;
00407     CRITICAL_SECTION    crit;
00408     IUnknown                *outerunknown;
00409     IDispatch               *dispatch;
00410     IRpcProxyBuffer         *dispatch_proxy;
00411 } TMProxyImpl;
00412 
00413 static HRESULT WINAPI
00414 TMProxyImpl_QueryInterface(LPRPCPROXYBUFFER iface, REFIID riid, LPVOID *ppv)
00415 {
00416     TRACE("()\n");
00417     if (IsEqualIID(riid,&IID_IUnknown)||IsEqualIID(riid,&IID_IRpcProxyBuffer)) {
00418         *ppv = iface;
00419         IRpcProxyBuffer_AddRef(iface);
00420         return S_OK;
00421     }
00422     FIXME("no interface for %s\n",debugstr_guid(riid));
00423     return E_NOINTERFACE;
00424 }
00425 
00426 static ULONG WINAPI
00427 TMProxyImpl_AddRef(LPRPCPROXYBUFFER iface)
00428 {
00429     ICOM_THIS_MULTI(TMProxyImpl,lpvtbl2,iface);
00430     ULONG refCount = InterlockedIncrement(&This->ref);
00431 
00432     TRACE("(%p)->(ref before=%u)\n",This, refCount - 1);
00433 
00434     return refCount;
00435 }
00436 
00437 static ULONG WINAPI
00438 TMProxyImpl_Release(LPRPCPROXYBUFFER iface)
00439 {
00440     ICOM_THIS_MULTI(TMProxyImpl,lpvtbl2,iface);
00441     ULONG refCount = InterlockedDecrement(&This->ref);
00442 
00443     TRACE("(%p)->(ref before=%u)\n",This, refCount + 1);
00444 
00445     if (!refCount)
00446     {
00447         if (This->dispatch_proxy) IRpcProxyBuffer_Release(This->dispatch_proxy);
00448         This->crit.DebugInfo->Spare[0] = 0;
00449         DeleteCriticalSection(&This->crit);
00450         if (This->chanbuf) IRpcChannelBuffer_Release(This->chanbuf);
00451         VirtualFree(This->asmstubs, 0, MEM_RELEASE);
00452         HeapFree(GetProcessHeap(), 0, This->lpvtbl);
00453         ITypeInfo_Release(This->tinfo);
00454         CoTaskMemFree(This);
00455     }
00456     return refCount;
00457 }
00458 
00459 static HRESULT WINAPI
00460 TMProxyImpl_Connect(
00461     LPRPCPROXYBUFFER iface,IRpcChannelBuffer* pRpcChannelBuffer)
00462 {
00463     ICOM_THIS_MULTI(TMProxyImpl, lpvtbl2, iface);
00464 
00465     TRACE("(%p)\n", pRpcChannelBuffer);
00466 
00467     EnterCriticalSection(&This->crit);
00468 
00469     IRpcChannelBuffer_AddRef(pRpcChannelBuffer);
00470     This->chanbuf = pRpcChannelBuffer;
00471 
00472     LeaveCriticalSection(&This->crit);
00473 
00474     if (This->dispatch_proxy)
00475     {
00476         IRpcChannelBuffer *pDelegateChannel;
00477         HRESULT hr = TMarshalDispatchChannel_Create(pRpcChannelBuffer, &This->iid, &pDelegateChannel);
00478         if (FAILED(hr))
00479             return hr;
00480         hr = IRpcProxyBuffer_Connect(This->dispatch_proxy, pDelegateChannel);
00481         IRpcChannelBuffer_Release(pDelegateChannel);
00482         return hr;
00483     }
00484 
00485     return S_OK;
00486 }
00487 
00488 static void WINAPI
00489 TMProxyImpl_Disconnect(LPRPCPROXYBUFFER iface)
00490 {
00491     ICOM_THIS_MULTI(TMProxyImpl, lpvtbl2, iface);
00492 
00493     TRACE("()\n");
00494 
00495     EnterCriticalSection(&This->crit);
00496 
00497     IRpcChannelBuffer_Release(This->chanbuf);
00498     This->chanbuf = NULL;
00499 
00500     LeaveCriticalSection(&This->crit);
00501 
00502     if (This->dispatch_proxy)
00503         IRpcProxyBuffer_Disconnect(This->dispatch_proxy);
00504 }
00505 
00506 
00507 static const IRpcProxyBufferVtbl tmproxyvtable = {
00508     TMProxyImpl_QueryInterface,
00509     TMProxyImpl_AddRef,
00510     TMProxyImpl_Release,
00511     TMProxyImpl_Connect,
00512     TMProxyImpl_Disconnect
00513 };
00514 
00515 /* how much space do we use on stack in DWORD steps. */
00516 static int
00517 _argsize(TYPEDESC *tdesc, ITypeInfo *tinfo) {
00518     switch (tdesc->vt) {
00519     case VT_I8:
00520     case VT_UI8:
00521     return 8/sizeof(DWORD);
00522     case VT_R8:
00523         return sizeof(double)/sizeof(DWORD);
00524     case VT_CY:
00525         return sizeof(CY)/sizeof(DWORD);
00526     case VT_DATE:
00527     return sizeof(DATE)/sizeof(DWORD);
00528     case VT_DECIMAL:
00529         return (sizeof(DECIMAL)+3)/sizeof(DWORD);
00530     case VT_VARIANT:
00531     return (sizeof(VARIANT)+3)/sizeof(DWORD);
00532     case VT_USERDEFINED:
00533     {
00534         ITypeInfo *tinfo2;
00535         TYPEATTR *tattr;
00536         HRESULT hres;
00537         DWORD ret;
00538 
00539         hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);
00540         if (FAILED(hres))
00541             return 0; /* should fail critically in serialize_param */
00542         ITypeInfo_GetTypeAttr(tinfo2,&tattr);
00543         ret = (tattr->cbSizeInstance+3)/sizeof(DWORD);
00544         ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
00545         ITypeInfo_Release(tinfo2);
00546         return ret;
00547     }
00548     default:
00549     return 1;
00550     }
00551 }
00552 
00553 /* how much space do we use on the heap (in bytes) */
00554 static int
00555 _xsize(const TYPEDESC *td, ITypeInfo *tinfo) {
00556     switch (td->vt) {
00557     case VT_DATE:
00558     return sizeof(DATE);
00559     case VT_CY:
00560         return sizeof(CY);
00561     /* FIXME: VT_BOOL should return 2? */
00562     case VT_VARIANT:
00563     return sizeof(VARIANT)+3; /* FIXME: why the +3? */
00564     case VT_CARRAY: {
00565     int i, arrsize = 1;
00566     const ARRAYDESC *adesc = td->u.lpadesc;
00567 
00568     for (i=0;i<adesc->cDims;i++)
00569         arrsize *= adesc->rgbounds[i].cElements;
00570     return arrsize*_xsize(&adesc->tdescElem, tinfo);
00571     }
00572     case VT_UI8:
00573     case VT_I8:
00574     case VT_R8:
00575     return 8;
00576     case VT_UI2:
00577     case VT_I2:
00578     return 2;
00579     case VT_UI1:
00580     case VT_I1:
00581     return 1;
00582     case VT_USERDEFINED:
00583     {
00584         ITypeInfo *tinfo2;
00585         TYPEATTR *tattr;
00586         HRESULT hres;
00587         DWORD ret;
00588 
00589         hres = ITypeInfo_GetRefTypeInfo(tinfo,td->u.hreftype,&tinfo2);
00590         if (FAILED(hres))
00591             return 0;
00592         ITypeInfo_GetTypeAttr(tinfo2,&tattr);
00593         ret = tattr->cbSizeInstance;
00594         ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
00595         ITypeInfo_Release(tinfo2);
00596         return ret;
00597     }
00598     default:
00599     return 4;
00600     }
00601 }
00602 
00603 static HRESULT
00604 serialize_param(
00605     ITypeInfo       *tinfo,
00606     BOOL        writeit,
00607     BOOL        debugout,
00608     BOOL        dealloc,
00609     TYPEDESC        *tdesc,
00610     DWORD       *arg,
00611     marshal_state   *buf)
00612 {
00613     HRESULT hres = S_OK;
00614     VARTYPE vartype;
00615 
00616     TRACE("(tdesc.vt %s)\n",debugstr_vt(tdesc->vt));
00617 
00618     vartype = tdesc->vt;
00619     if ((vartype & 0xf000) == VT_ARRAY)
00620         vartype = VT_SAFEARRAY;
00621 
00622     switch (vartype) {
00623     case VT_I8:
00624     case VT_UI8:
00625     case VT_R8:
00626     case VT_CY:
00627     hres = S_OK;
00628     if (debugout) TRACE_(olerelay)("%x%x\n",arg[0],arg[1]);
00629     if (writeit)
00630         hres = xbuf_add(buf,(LPBYTE)arg,8);
00631     return hres;
00632     case VT_BOOL:
00633     case VT_ERROR:
00634     case VT_INT:
00635     case VT_UINT:
00636     case VT_I4:
00637     case VT_R4:
00638     case VT_UI4:
00639     hres = S_OK;
00640     if (debugout) TRACE_(olerelay)("%x\n",*arg);
00641     if (writeit)
00642         hres = xbuf_add(buf,(LPBYTE)arg,sizeof(DWORD));
00643     return hres;
00644     case VT_I2:
00645     case VT_UI2:
00646     hres = S_OK;
00647     if (debugout) TRACE_(olerelay)("%04x\n",*arg & 0xffff);
00648     if (writeit)
00649         hres = xbuf_add(buf,(LPBYTE)arg,sizeof(DWORD));
00650     return hres;
00651     case VT_I1:
00652     case VT_UI1:
00653     hres = S_OK;
00654     if (debugout) TRACE_(olerelay)("%02x\n",*arg & 0xff);
00655     if (writeit)
00656         hres = xbuf_add(buf,(LPBYTE)arg,sizeof(DWORD));
00657     return hres;
00658     case VT_VARIANT: {
00659         if (debugout) TRACE_(olerelay)("Vt(%s%s)(",debugstr_vt(V_VT((VARIANT *)arg)),debugstr_vf(V_VT((VARIANT *)arg)));
00660         if (writeit)
00661         {
00662             ULONG flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
00663             ULONG size = VARIANT_UserSize(&flags, buf->curoff, (VARIANT *)arg);
00664             xbuf_resize(buf, size);
00665             VARIANT_UserMarshal(&flags, buf->base + buf->curoff, (VARIANT *)arg);
00666             buf->curoff = size;
00667         }
00668         if (dealloc)
00669         {
00670             ULONG flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
00671             VARIANT_UserFree(&flags, (VARIANT *)arg);
00672         }
00673         return S_OK;
00674     }
00675     case VT_BSTR: {
00676     if (debugout) {
00677         if (*arg)
00678                    TRACE_(olerelay)("%s",relaystr((WCHAR*)*arg));
00679         else
00680             TRACE_(olerelay)("<bstr NULL>");
00681     }
00682         if (writeit)
00683         {
00684             ULONG flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
00685             ULONG size = BSTR_UserSize(&flags, buf->curoff, (BSTR *)arg);
00686             xbuf_resize(buf, size);
00687             BSTR_UserMarshal(&flags, buf->base + buf->curoff, (BSTR *)arg);
00688             buf->curoff = size;
00689         }
00690         if (dealloc)
00691         {
00692             ULONG flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
00693             BSTR_UserFree(&flags, (BSTR *)arg);
00694         }
00695         return S_OK;
00696     }
00697     case VT_PTR: {
00698     DWORD cookie;
00699     BOOL        derefhere = TRUE;
00700 
00701     if (tdesc->u.lptdesc->vt == VT_USERDEFINED) {
00702         ITypeInfo   *tinfo2;
00703         TYPEATTR    *tattr;
00704 
00705         hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.lptdesc->u.hreftype,&tinfo2);
00706         if (hres) {
00707         ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED.\n",tdesc->u.lptdesc->u.hreftype);
00708         return hres;
00709         }
00710         ITypeInfo_GetTypeAttr(tinfo2,&tattr);
00711         switch (tattr->typekind) {
00712             case TKIND_ALIAS:
00713                 if (tattr->tdescAlias.vt == VT_USERDEFINED)
00714                 {
00715                     DWORD href = tattr->tdescAlias.u.hreftype;
00716                     ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
00717                     ITypeInfo_Release(tinfo2);
00718                     hres = ITypeInfo_GetRefTypeInfo(tinfo,href,&tinfo2);
00719                     if (hres) {
00720                         ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED.\n",tdesc->u.lptdesc->u.hreftype);
00721                         return hres;
00722                     }
00723                     ITypeInfo_GetTypeAttr(tinfo2,&tattr);
00724                     derefhere = (tattr->typekind != TKIND_DISPATCH && tattr->typekind != TKIND_INTERFACE);
00725                 }
00726                 break;
00727         case TKIND_ENUM:    /* confirmed */
00728         case TKIND_RECORD:  /* FIXME: mostly untested */
00729         break;
00730         case TKIND_DISPATCH:    /* will be done in VT_USERDEFINED case */
00731         case TKIND_INTERFACE:   /* will be done in VT_USERDEFINED case */
00732         derefhere=FALSE;
00733         break;
00734         default:
00735         FIXME("unhandled switch cases tattr->typekind %d\n", tattr->typekind);
00736         derefhere=FALSE;
00737         break;
00738         }
00739         ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
00740         ITypeInfo_Release(tinfo2);
00741     }
00742 
00743     if (debugout) TRACE_(olerelay)("*");
00744     /* Write always, so the other side knows when it gets a NULL pointer.
00745      */
00746     cookie = *arg ? 0x42424242 : 0;
00747     hres = xbuf_add(buf,(LPBYTE)&cookie,sizeof(cookie));
00748     if (hres)
00749         return hres;
00750     if (!*arg) {
00751         if (debugout) TRACE_(olerelay)("NULL");
00752         return S_OK;
00753     }
00754     hres = serialize_param(tinfo,writeit,debugout,dealloc,tdesc->u.lptdesc,(DWORD*)*arg,buf);
00755     if (derefhere && dealloc) HeapFree(GetProcessHeap(),0,(LPVOID)*arg);
00756     return hres;
00757     }
00758     case VT_UNKNOWN:
00759     if (debugout) TRACE_(olerelay)("unk(0x%x)",*arg);
00760     if (writeit)
00761         hres = _marshal_interface(buf,&IID_IUnknown,(LPUNKNOWN)*arg);
00762     if (dealloc && *(IUnknown **)arg)
00763         IUnknown_Release((LPUNKNOWN)*arg);
00764     return hres;
00765     case VT_DISPATCH:
00766     if (debugout) TRACE_(olerelay)("idisp(0x%x)",*arg);
00767     if (writeit)
00768         hres = _marshal_interface(buf,&IID_IDispatch,(LPUNKNOWN)*arg);
00769     if (dealloc && *(IUnknown **)arg)
00770         IUnknown_Release((LPUNKNOWN)*arg);
00771     return hres;
00772     case VT_VOID:
00773     if (debugout) TRACE_(olerelay)("<void>");
00774     return S_OK;
00775     case VT_USERDEFINED: {
00776     ITypeInfo   *tinfo2;
00777     TYPEATTR    *tattr;
00778 
00779     hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);
00780     if (hres) {
00781         ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED.\n",tdesc->u.hreftype);
00782         return hres;
00783     }
00784     ITypeInfo_GetTypeAttr(tinfo2,&tattr);
00785     switch (tattr->typekind) {
00786     case TKIND_DISPATCH:
00787     case TKIND_INTERFACE:
00788         if (writeit)
00789            hres=_marshal_interface(buf,&(tattr->guid),(LPUNKNOWN)arg);
00790         if (dealloc)
00791             IUnknown_Release((LPUNKNOWN)arg);
00792         break;
00793     case TKIND_RECORD: {
00794         int i;
00795         if (debugout) TRACE_(olerelay)("{");
00796         for (i=0;i<tattr->cVars;i++) {
00797         VARDESC *vdesc;
00798         ELEMDESC *elem2;
00799         TYPEDESC *tdesc2;
00800 
00801         hres = ITypeInfo2_GetVarDesc(tinfo2, i, &vdesc);
00802         if (hres) {
00803             ERR("Could not get vardesc of %d\n",i);
00804             return hres;
00805         }
00806         elem2 = &vdesc->elemdescVar;
00807         tdesc2 = &elem2->tdesc;
00808         hres = serialize_param(
00809             tinfo2,
00810             writeit,
00811             debugout,
00812             dealloc,
00813             tdesc2,
00814             (DWORD*)(((LPBYTE)arg)+vdesc->u.oInst),
00815             buf
00816         );
00817                 ITypeInfo_ReleaseVarDesc(tinfo2, vdesc);
00818         if (hres!=S_OK)
00819             return hres;
00820         if (debugout && (i<(tattr->cVars-1)))
00821             TRACE_(olerelay)(",");
00822         }
00823         if (debugout) TRACE_(olerelay)("}");
00824         break;
00825     }
00826     case TKIND_ALIAS:
00827         hres = serialize_param(tinfo2,writeit,debugout,dealloc,&tattr->tdescAlias,arg,buf);
00828         break;
00829     case TKIND_ENUM:
00830         hres = S_OK;
00831         if (debugout) TRACE_(olerelay)("%x",*arg);
00832         if (writeit)
00833             hres = xbuf_add(buf,(LPBYTE)arg,sizeof(DWORD));
00834         break;
00835     default:
00836         FIXME("Unhandled typekind %d\n",tattr->typekind);
00837         hres = E_FAIL;
00838         break;
00839     }
00840     ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
00841     ITypeInfo_Release(tinfo2);
00842     return hres;
00843     }
00844     case VT_CARRAY: {
00845     ARRAYDESC *adesc = tdesc->u.lpadesc;
00846     int i, arrsize = 1;
00847 
00848     if (debugout) TRACE_(olerelay)("carr");
00849     for (i=0;i<adesc->cDims;i++) {
00850         if (debugout) TRACE_(olerelay)("[%d]",adesc->rgbounds[i].cElements);
00851         arrsize *= adesc->rgbounds[i].cElements;
00852     }
00853     if (debugout) TRACE_(olerelay)("(vt %s)",debugstr_vt(adesc->tdescElem.vt));
00854     if (debugout) TRACE_(olerelay)("[");
00855     for (i=0;i<arrsize;i++) {
00856         hres = serialize_param(tinfo, writeit, debugout, dealloc, &adesc->tdescElem, (DWORD*)((LPBYTE)(*arg)+i*_xsize(&adesc->tdescElem, tinfo)), buf);
00857         if (hres)
00858         return hres;
00859         if (debugout && (i<arrsize-1)) TRACE_(olerelay)(",");
00860     }
00861     if (debugout) TRACE_(olerelay)("]");
00862     if (dealloc)
00863         HeapFree(GetProcessHeap(), 0, *(void **)arg);
00864     return S_OK;
00865     }
00866     case VT_SAFEARRAY: {
00867         if (writeit)
00868         {
00869             ULONG flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
00870             ULONG size = LPSAFEARRAY_UserSize(&flags, buf->curoff, (LPSAFEARRAY *)arg);
00871             xbuf_resize(buf, size);
00872             LPSAFEARRAY_UserMarshal(&flags, buf->base + buf->curoff, (LPSAFEARRAY *)arg);
00873             buf->curoff = size;
00874         }
00875         if (dealloc)
00876         {
00877             ULONG flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
00878             LPSAFEARRAY_UserFree(&flags, (LPSAFEARRAY *)arg);
00879         }
00880         return S_OK;
00881     }
00882     default:
00883     ERR("Unhandled marshal type %d.\n",tdesc->vt);
00884     return S_OK;
00885     }
00886 }
00887 
00888 static HRESULT
00889 deserialize_param(
00890     ITypeInfo       *tinfo,
00891     BOOL        readit,
00892     BOOL        debugout,
00893     BOOL        alloc,
00894     TYPEDESC        *tdesc,
00895     DWORD       *arg,
00896     marshal_state   *buf)
00897 {
00898     HRESULT hres = S_OK;
00899     VARTYPE vartype;
00900 
00901     TRACE("vt %s at %p\n",debugstr_vt(tdesc->vt),arg);
00902 
00903     vartype = tdesc->vt;
00904     if ((vartype & 0xf000) == VT_ARRAY)
00905         vartype = VT_SAFEARRAY;
00906 
00907     while (1) {
00908     switch (vartype) {
00909     case VT_VARIANT: {
00910         if (readit)
00911         {
00912         ULONG flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
00913         unsigned char *buffer;
00914         buffer = VARIANT_UserUnmarshal(&flags, buf->base + buf->curoff, (VARIANT *)arg);
00915         buf->curoff = buffer - buf->base;
00916         }
00917         return S_OK;
00918     }
00919         case VT_I8:
00920         case VT_UI8:
00921         case VT_R8:
00922         case VT_CY:
00923         if (readit) {
00924         hres = xbuf_get(buf,(LPBYTE)arg,8);
00925         if (hres) ERR("Failed to read integer 8 byte\n");
00926         }
00927         if (debugout) TRACE_(olerelay)("%x%x",arg[0],arg[1]);
00928         return hres;
00929         case VT_ERROR:
00930     case VT_BOOL:
00931         case VT_I4:
00932         case VT_INT:
00933         case VT_UINT:
00934         case VT_R4:
00935         case VT_UI4:
00936         if (readit) {
00937         hres = xbuf_get(buf,(LPBYTE)arg,sizeof(DWORD));
00938         if (hres) ERR("Failed to read integer 4 byte\n");
00939         }
00940         if (debugout) TRACE_(olerelay)("%x",*arg);
00941         return hres;
00942         case VT_I2:
00943         case VT_UI2:
00944         if (readit) {
00945         DWORD x;
00946         hres = xbuf_get(buf,(LPBYTE)&x,sizeof(DWORD));
00947         if (hres) ERR("Failed to read integer 4 byte\n");
00948         memcpy(arg,&x,2);
00949         }
00950         if (debugout) TRACE_(olerelay)("%04x",*arg & 0xffff);
00951         return hres;
00952         case VT_I1:
00953     case VT_UI1:
00954         if (readit) {
00955         DWORD x;
00956         hres = xbuf_get(buf,(LPBYTE)&x,sizeof(DWORD));
00957         if (hres) ERR("Failed to read integer 4 byte\n");
00958         memcpy(arg,&x,1);
00959         }
00960         if (debugout) TRACE_(olerelay)("%02x",*arg & 0xff);
00961         return hres;
00962     case VT_BSTR: {
00963         if (readit)
00964         {
00965         ULONG flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
00966         unsigned char *buffer;
00967         buffer = BSTR_UserUnmarshal(&flags, buf->base + buf->curoff, (BSTR *)arg);
00968         buf->curoff = buffer - buf->base;
00969         if (debugout) TRACE_(olerelay)("%s",debugstr_w(*(BSTR *)arg));
00970         }
00971         return S_OK;
00972     }
00973     case VT_PTR: {
00974         DWORD   cookie;
00975         BOOL        derefhere = TRUE;
00976 
00977         if (tdesc->u.lptdesc->vt == VT_USERDEFINED) {
00978         ITypeInfo   *tinfo2;
00979         TYPEATTR    *tattr;
00980 
00981         hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.lptdesc->u.hreftype,&tinfo2);
00982         if (hres) {
00983             ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED.\n",tdesc->u.lptdesc->u.hreftype);
00984             return hres;
00985         }
00986         ITypeInfo_GetTypeAttr(tinfo2,&tattr);
00987         switch (tattr->typekind) {
00988                 case TKIND_ALIAS:
00989                     if (tattr->tdescAlias.vt == VT_USERDEFINED)
00990                     {
00991                         DWORD href = tattr->tdescAlias.u.hreftype;
00992                         ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
00993                         ITypeInfo_Release(tinfo2);
00994                         hres = ITypeInfo_GetRefTypeInfo(tinfo,href,&tinfo2);
00995                         if (hres) {
00996                             ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED.\n",tdesc->u.lptdesc->u.hreftype);
00997                             return hres;
00998                         }
00999                         ITypeInfo_GetTypeAttr(tinfo2,&tattr);
01000                         derefhere = (tattr->typekind != TKIND_DISPATCH && tattr->typekind != TKIND_INTERFACE);
01001                     }
01002                     break;
01003         case TKIND_ENUM:    /* confirmed */
01004         case TKIND_RECORD:  /* FIXME: mostly untested */
01005             break;
01006         case TKIND_DISPATCH:    /* will be done in VT_USERDEFINED case */
01007         case TKIND_INTERFACE:   /* will be done in VT_USERDEFINED case */
01008             derefhere=FALSE;
01009             break;
01010         default:
01011             FIXME("unhandled switch cases tattr->typekind %d\n", tattr->typekind);
01012             derefhere=FALSE;
01013             break;
01014         }
01015         ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
01016         ITypeInfo_Release(tinfo2);
01017         }
01018         /* read it in all cases, we need to know if we have
01019          * NULL pointer or not.
01020          */
01021         hres = xbuf_get(buf,(LPBYTE)&cookie,sizeof(cookie));
01022         if (hres) {
01023         ERR("Failed to load pointer cookie.\n");
01024         return hres;
01025         }
01026         if (cookie != 0x42424242) {
01027         /* we read a NULL ptr from the remote side */
01028         if (debugout) TRACE_(olerelay)("NULL");
01029         *arg = 0;
01030         return S_OK;
01031         }
01032         if (debugout) TRACE_(olerelay)("*");
01033         if (alloc) {
01034         /* Allocate space for the referenced struct */
01035         if (derefhere)
01036             *arg=(DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,_xsize(tdesc->u.lptdesc, tinfo));
01037         }
01038         if (derefhere)
01039         return deserialize_param(tinfo, readit, debugout, alloc, tdesc->u.lptdesc, (LPDWORD)*arg, buf);
01040         else
01041         return deserialize_param(tinfo, readit, debugout, alloc, tdesc->u.lptdesc, arg, buf);
01042         }
01043     case VT_UNKNOWN:
01044         /* FIXME: UNKNOWN is unknown ..., but allocate 4 byte for it */
01045         if (alloc)
01046             *arg=(DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DWORD));
01047         hres = S_OK;
01048         if (readit)
01049         hres = _unmarshal_interface(buf,&IID_IUnknown,(LPUNKNOWN*)arg);
01050         if (debugout)
01051         TRACE_(olerelay)("unk(%p)",arg);
01052         return hres;
01053     case VT_DISPATCH:
01054         hres = S_OK;
01055         if (readit)
01056         hres = _unmarshal_interface(buf,&IID_IDispatch,(LPUNKNOWN*)arg);
01057         if (debugout)
01058         TRACE_(olerelay)("idisp(%p)",arg);
01059         return hres;
01060     case VT_VOID:
01061         if (debugout) TRACE_(olerelay)("<void>");
01062         return S_OK;
01063     case VT_USERDEFINED: {
01064         ITypeInfo   *tinfo2;
01065         TYPEATTR    *tattr;
01066 
01067         hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);
01068         if (hres) {
01069         ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED.\n",tdesc->u.hreftype);
01070         return hres;
01071         }
01072         hres = ITypeInfo_GetTypeAttr(tinfo2,&tattr);
01073         if (hres) {
01074         ERR("Could not get typeattr in VT_USERDEFINED.\n");
01075         } else {
01076         switch (tattr->typekind) {
01077         case TKIND_DISPATCH:
01078         case TKIND_INTERFACE:
01079             if (readit)
01080             hres = _unmarshal_interface(buf,&(tattr->guid),(LPUNKNOWN*)arg);
01081             break;
01082         case TKIND_RECORD: {
01083             int i;
01084 
01085             if (debugout) TRACE_(olerelay)("{");
01086             for (i=0;i<tattr->cVars;i++) {
01087             VARDESC *vdesc;
01088 
01089             hres = ITypeInfo2_GetVarDesc(tinfo2, i, &vdesc);
01090             if (hres) {
01091                 ERR("Could not get vardesc of %d\n",i);
01092                 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
01093                 ITypeInfo_Release(tinfo2);
01094                 return hres;
01095             }
01096             hres = deserialize_param(
01097                 tinfo2,
01098                 readit,
01099                 debugout,
01100                 alloc,
01101                 &vdesc->elemdescVar.tdesc,
01102                 (DWORD*)(((LPBYTE)arg)+vdesc->u.oInst),
01103                 buf
01104             );
01105                         ITypeInfo2_ReleaseVarDesc(tinfo2, vdesc);
01106                 if (debugout && (i<tattr->cVars-1)) TRACE_(olerelay)(",");
01107             }
01108             if (debugout) TRACE_(olerelay)("}");
01109             break;
01110         }
01111         case TKIND_ALIAS:
01112             hres = deserialize_param(tinfo2,readit,debugout,alloc,&tattr->tdescAlias,arg,buf);
01113             break;
01114         case TKIND_ENUM:
01115             if (readit) {
01116                 hres = xbuf_get(buf,(LPBYTE)arg,sizeof(DWORD));
01117                 if (hres) ERR("Failed to read enum (4 byte)\n");
01118             }
01119             if (debugout) TRACE_(olerelay)("%x",*arg);
01120             break;
01121         default:
01122             ERR("Unhandled typekind %d\n",tattr->typekind);
01123             hres = E_FAIL;
01124             break;
01125         }
01126         ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
01127         }
01128         if (hres)
01129         ERR("failed to stuballoc in TKIND_RECORD.\n");
01130         ITypeInfo_Release(tinfo2);
01131         return hres;
01132     }
01133     case VT_CARRAY: {
01134         /* arg is pointing to the start of the array. */
01135         ARRAYDESC *adesc = tdesc->u.lpadesc;
01136         int     arrsize,i;
01137         arrsize = 1;
01138         if (adesc->cDims > 1) FIXME("cDims > 1 in VT_CARRAY. Does it work?\n");
01139         for (i=0;i<adesc->cDims;i++)
01140         arrsize *= adesc->rgbounds[i].cElements;
01141         *arg=(DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,_xsize(tdesc->u.lptdesc, tinfo) * arrsize);
01142         for (i=0;i<arrsize;i++)
01143         deserialize_param(
01144             tinfo,
01145             readit,
01146             debugout,
01147             alloc,
01148             &adesc->tdescElem,
01149             (DWORD*)((LPBYTE)(*arg)+i*_xsize(&adesc->tdescElem, tinfo)),
01150             buf
01151         );
01152         return S_OK;
01153     }
01154     case VT_SAFEARRAY: {
01155         if (readit)
01156         {
01157         ULONG flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
01158         unsigned char *buffer;
01159         buffer = LPSAFEARRAY_UserUnmarshal(&flags, buf->base + buf->curoff, (LPSAFEARRAY *)arg);
01160         buf->curoff = buffer - buf->base;
01161         }
01162         return S_OK;
01163     }
01164     default:
01165         ERR("No handler for VT type %d!\n",tdesc->vt);
01166         return S_OK;
01167     }
01168     }
01169 }
01170 
01171 /* Retrieves a function's funcdesc, searching back into inherited interfaces. */
01172 static HRESULT get_funcdesc(ITypeInfo *tinfo, int iMethod, ITypeInfo **tactual, const FUNCDESC **fdesc,
01173                             BSTR *iname, BSTR *fname, UINT *num)
01174 {
01175     HRESULT hr;
01176     UINT i, impl_types;
01177     UINT inherited_funcs = 0;
01178     TYPEATTR *attr;
01179 
01180     if (fname) *fname = NULL;
01181     if (iname) *iname = NULL;
01182     if (num) *num = 0;
01183     *tactual = NULL;
01184 
01185     hr = ITypeInfo_GetTypeAttr(tinfo, &attr);
01186     if (FAILED(hr))
01187     {
01188         ERR("GetTypeAttr failed with %x\n",hr);
01189         return hr;
01190     }
01191 
01192     if(attr->typekind == TKIND_DISPATCH)
01193     {
01194         if(attr->wTypeFlags & TYPEFLAG_FDUAL)
01195         {
01196             HREFTYPE href;
01197             ITypeInfo *tinfo2;
01198 
01199             hr = ITypeInfo_GetRefTypeOfImplType(tinfo, -1, &href);
01200             if(FAILED(hr))
01201             {
01202                 ERR("Cannot get interface href from dual dispinterface\n");
01203                 ITypeInfo_ReleaseTypeAttr(tinfo, attr);
01204                 return hr;
01205             }
01206             hr = ITypeInfo_GetRefTypeInfo(tinfo, href, &tinfo2);
01207             if(FAILED(hr))
01208             {
01209                 ERR("Cannot get interface from dual dispinterface\n");
01210                 ITypeInfo_ReleaseTypeAttr(tinfo, attr);
01211                 return hr;
01212             }
01213             hr = get_funcdesc(tinfo2, iMethod, tactual, fdesc, iname, fname, num);
01214             ITypeInfo_Release(tinfo2);
01215             ITypeInfo_ReleaseTypeAttr(tinfo, attr);
01216             return hr;
01217         }
01218         ERR("Shouldn't be called with a non-dual dispinterface\n");
01219         return E_FAIL;
01220     }
01221 
01222     impl_types = attr->cImplTypes;
01223     ITypeInfo_ReleaseTypeAttr(tinfo, attr);
01224 
01225     for (i = 0; i < impl_types; i++)
01226     {
01227         HREFTYPE href;
01228         ITypeInfo *pSubTypeInfo;
01229         UINT sub_funcs;
01230 
01231         hr = ITypeInfo_GetRefTypeOfImplType(tinfo, i, &href);
01232         if (FAILED(hr)) return hr;
01233         hr = ITypeInfo_GetRefTypeInfo(tinfo, href, &pSubTypeInfo);
01234         if (FAILED(hr)) return hr;
01235 
01236         hr = get_funcdesc(pSubTypeInfo, iMethod, tactual, fdesc, iname, fname, &sub_funcs);
01237         inherited_funcs += sub_funcs;
01238         ITypeInfo_Release(pSubTypeInfo);
01239         if(SUCCEEDED(hr)) return hr;
01240     }
01241     if(iMethod < inherited_funcs)
01242     {
01243         ERR("shouldn't be here\n");
01244         return E_INVALIDARG;
01245     }
01246 
01247     for(i = inherited_funcs; i <= iMethod; i++)
01248     {
01249         hr = ITypeInfoImpl_GetInternalFuncDesc(tinfo, i - inherited_funcs, fdesc);
01250         if(FAILED(hr))
01251         {
01252             if(num) *num = i;
01253             return hr;
01254         }
01255     }
01256 
01257     /* found it. We don't care about num so zero it */
01258     if(num) *num = 0;
01259     *tactual = tinfo;
01260     ITypeInfo_AddRef(*tactual);
01261     if (fname) ITypeInfo_GetDocumentation(tinfo,(*fdesc)->memid,fname,NULL,NULL,NULL);
01262     if (iname) ITypeInfo_GetDocumentation(tinfo,-1,iname,NULL,NULL,NULL);
01263     return S_OK;
01264 }
01265 
01266 static inline BOOL is_in_elem(const ELEMDESC *elem)
01267 {
01268     return (elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN || !elem->u.paramdesc.wParamFlags);
01269 }
01270 
01271 static inline BOOL is_out_elem(const ELEMDESC *elem)
01272 {
01273     return (elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT || !elem->u.paramdesc.wParamFlags);
01274 }
01275 
01276 static DWORD
01277 xCall(LPVOID retptr, int method, TMProxyImpl *tpinfo /*, args */)
01278 {
01279     DWORD       *args = ((DWORD*)&tpinfo)+1, *xargs;
01280     const FUNCDESC  *fdesc;
01281     HRESULT     hres;
01282     int         i, relaydeb = TRACE_ON(olerelay);
01283     marshal_state   buf;
01284     RPCOLEMESSAGE   msg;
01285     ULONG       status;
01286     BSTR        fname,iname;
01287     BSTR        names[10];
01288     UINT        nrofnames;
01289     DWORD       remoteresult = 0;
01290     ITypeInfo       *tinfo;
01291     IRpcChannelBuffer *chanbuf;
01292 
01293     EnterCriticalSection(&tpinfo->crit);
01294 
01295     hres = get_funcdesc(tpinfo->tinfo,method,&tinfo,&fdesc,&iname,&fname,NULL);
01296     if (hres) {
01297         ERR("Did not find typeinfo/funcdesc entry for method %d!\n",method);
01298         LeaveCriticalSection(&tpinfo->crit);
01299         return E_FAIL;
01300     }
01301 
01302     if (!tpinfo->chanbuf)
01303     {
01304         WARN("Tried to use disconnected proxy\n");
01305         ITypeInfo_Release(tinfo);
01306         LeaveCriticalSection(&tpinfo->crit);
01307         return RPC_E_DISCONNECTED;
01308     }
01309     chanbuf = tpinfo->chanbuf;
01310     IRpcChannelBuffer_AddRef(chanbuf);
01311 
01312     LeaveCriticalSection(&tpinfo->crit);
01313 
01314     if (relaydeb) {
01315        TRACE_(olerelay)("->");
01316     if (iname)
01317         TRACE_(olerelay)("%s:",relaystr(iname));
01318     if (fname)
01319         TRACE_(olerelay)("%s(%d)",relaystr(fname),method);
01320     else
01321         TRACE_(olerelay)("%d",method);
01322     TRACE_(olerelay)("(");
01323     }
01324 
01325     SysFreeString(iname);
01326     SysFreeString(fname);
01327 
01328     memset(&buf,0,sizeof(buf));
01329 
01330     /* normal typelib driven serializing */
01331 
01332     /* Need them for hack below */
01333     memset(names,0,sizeof(names));
01334     if (ITypeInfo_GetNames(tinfo,fdesc->memid,names,sizeof(names)/sizeof(names[0]),&nrofnames))
01335     nrofnames = 0;
01336     if (nrofnames > sizeof(names)/sizeof(names[0]))
01337     ERR("Need more names!\n");
01338 
01339     xargs = args;
01340     for (i=0;i<fdesc->cParams;i++) {
01341     ELEMDESC    *elem = fdesc->lprgelemdescParam+i;
01342     if (relaydeb) {
01343         if (i) TRACE_(olerelay)(",");
01344         if (i+1<nrofnames && names[i+1])
01345         TRACE_(olerelay)("%s=",relaystr(names[i+1]));
01346     }
01347     /* No need to marshal other data than FIN and any VT_PTR. */
01348     if (!is_in_elem(elem) && (elem->tdesc.vt != VT_PTR)) {
01349         xargs+=_argsize(&elem->tdesc, tinfo);
01350         if (relaydeb) TRACE_(olerelay)("[out]");
01351         continue;
01352     }
01353     hres = serialize_param(
01354         tinfo,
01355         is_in_elem(elem),
01356         relaydeb,
01357         FALSE,
01358         &elem->tdesc,
01359         xargs,
01360         &buf
01361     );
01362 
01363     if (hres) {
01364         ERR("Failed to serialize param, hres %x\n",hres);
01365         break;
01366     }
01367     xargs+=_argsize(&elem->tdesc, tinfo);
01368     }
01369     if (relaydeb) TRACE_(olerelay)(")");
01370 
01371     memset(&msg,0,sizeof(msg));
01372     msg.cbBuffer = buf.curoff;
01373     msg.iMethod  = method;
01374     hres = IRpcChannelBuffer_GetBuffer(chanbuf,&msg,&(tpinfo->iid));
01375     if (hres) {
01376     ERR("RpcChannelBuffer GetBuffer failed, %x\n",hres);
01377     goto exit;
01378     }
01379     memcpy(msg.Buffer,buf.base,buf.curoff);
01380     if (relaydeb) TRACE_(olerelay)("\n");
01381     hres = IRpcChannelBuffer_SendReceive(chanbuf,&msg,&status);
01382     if (hres) {
01383     ERR("RpcChannelBuffer SendReceive failed, %x\n",hres);
01384     goto exit;
01385     }
01386 
01387     if (relaydeb) TRACE_(olerelay)(" status = %08x (",status);
01388     if (buf.base)
01389     buf.base = HeapReAlloc(GetProcessHeap(),0,buf.base,msg.cbBuffer);
01390     else
01391     buf.base = HeapAlloc(GetProcessHeap(),0,msg.cbBuffer);
01392     buf.size = msg.cbBuffer;
01393     memcpy(buf.base,msg.Buffer,buf.size);
01394     buf.curoff = 0;
01395 
01396     /* generic deserializer using typelib description */
01397     xargs = args;
01398     status = S_OK;
01399     for (i=0;i<fdesc->cParams;i++) {
01400     ELEMDESC    *elem = fdesc->lprgelemdescParam+i;
01401 
01402     if (relaydeb) {
01403         if (i) TRACE_(olerelay)(",");
01404         if (i+1<nrofnames && names[i+1]) TRACE_(olerelay)("%s=",relaystr(names[i+1]));
01405     }
01406     /* No need to marshal other data than FOUT and any VT_PTR */
01407     if (!is_out_elem(elem) && (elem->tdesc.vt != VT_PTR)) {
01408         xargs += _argsize(&elem->tdesc, tinfo);
01409         if (relaydeb) TRACE_(olerelay)("[in]");
01410         continue;
01411     }
01412     hres = deserialize_param(
01413         tinfo,
01414         is_out_elem(elem),
01415         relaydeb,
01416         FALSE,
01417         &(elem->tdesc),
01418         xargs,
01419         &buf
01420         );
01421     if (hres) {
01422         ERR("Failed to unmarshall param, hres %x\n",hres);
01423         status = hres;
01424         break;
01425     }
01426     xargs += _argsize(&elem->tdesc, tinfo);
01427     }
01428 
01429     hres = xbuf_get(&buf, (LPBYTE)&remoteresult, sizeof(DWORD));
01430     if (hres != S_OK)
01431         goto exit;
01432     if (relaydeb) TRACE_(olerelay)(") = %08x\n", remoteresult);
01433 
01434     hres = remoteresult;
01435 
01436 exit:
01437     IRpcChannelBuffer_FreeBuffer(chanbuf,&msg);
01438     for (i = 0; i < nrofnames; i++)
01439         SysFreeString(names[i]);
01440     HeapFree(GetProcessHeap(),0,buf.base);
01441     IRpcChannelBuffer_Release(chanbuf);
01442     ITypeInfo_Release(tinfo);
01443     TRACE("-- 0x%08x\n", hres);
01444     return hres;
01445 }
01446 
01447 static HRESULT WINAPI ProxyIUnknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
01448 {
01449     TMProxyImpl *proxy = (TMProxyImpl *)iface;
01450 
01451     TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
01452 
01453     if (proxy->outerunknown)
01454         return IUnknown_QueryInterface(proxy->outerunknown, riid, ppv);
01455 
01456     FIXME("No interface\n");
01457     return E_NOINTERFACE;
01458 }
01459 
01460 static ULONG WINAPI ProxyIUnknown_AddRef(IUnknown *iface)
01461 {
01462     TMProxyImpl *proxy = (TMProxyImpl *)iface;
01463 
01464     TRACE("\n");
01465 
01466     if (proxy->outerunknown)
01467         return IUnknown_AddRef(proxy->outerunknown);
01468 
01469     return 2; /* FIXME */
01470 }
01471 
01472 static ULONG WINAPI ProxyIUnknown_Release(IUnknown *iface)
01473 {
01474     TMProxyImpl *proxy = (TMProxyImpl *)iface;
01475 
01476     TRACE("\n");
01477 
01478     if (proxy->outerunknown)
01479         return IUnknown_Release(proxy->outerunknown);
01480 
01481     return 1; /* FIXME */
01482 }
01483 
01484 static HRESULT WINAPI ProxyIDispatch_GetTypeInfoCount(LPDISPATCH iface, UINT * pctinfo)
01485 {
01486     TMProxyImpl *This = (TMProxyImpl *)iface;
01487 
01488     TRACE("(%p)\n", pctinfo);
01489 
01490     return IDispatch_GetTypeInfoCount(This->dispatch, pctinfo);
01491 }
01492 
01493 static HRESULT WINAPI ProxyIDispatch_GetTypeInfo(LPDISPATCH iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo)
01494 {
01495     TMProxyImpl *This = (TMProxyImpl *)iface;
01496 
01497     TRACE("(%d, %x, %p)\n", iTInfo, lcid, ppTInfo);
01498 
01499     return IDispatch_GetTypeInfo(This->dispatch, iTInfo, lcid, ppTInfo);
01500 }
01501 
01502 static HRESULT WINAPI ProxyIDispatch_GetIDsOfNames(LPDISPATCH iface, REFIID riid, LPOLESTR * rgszNames, UINT cNames, LCID lcid, DISPID * rgDispId)
01503 {
01504     TMProxyImpl *This = (TMProxyImpl *)iface;
01505 
01506     TRACE("(%s, %p, %d, 0x%x, %p)\n", debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
01507 
01508     return IDispatch_GetIDsOfNames(This->dispatch, riid, rgszNames,
01509                                    cNames, lcid, rgDispId);
01510 }
01511 
01512 static HRESULT WINAPI ProxyIDispatch_Invoke(LPDISPATCH iface, DISPID dispIdMember, REFIID riid, LCID lcid,
01513                                             WORD wFlags, DISPPARAMS * pDispParams, VARIANT * pVarResult,
01514                                             EXCEPINFO * pExcepInfo, UINT * puArgErr)
01515 {
01516     TMProxyImpl *This = (TMProxyImpl *)iface;
01517 
01518     TRACE("(%d, %s, 0x%x, 0x%x, %p, %p, %p, %p)\n", dispIdMember,
01519           debugstr_guid(riid), lcid, wFlags, pDispParams, pVarResult,
01520           pExcepInfo, puArgErr);
01521 
01522     return IDispatch_Invoke(This->dispatch, dispIdMember, riid, lcid,
01523                             wFlags, pDispParams, pVarResult, pExcepInfo,
01524                             puArgErr);
01525 }
01526 
01527 typedef struct
01528 {
01529     const IRpcChannelBufferVtbl *lpVtbl;
01530     LONG                  refs;
01531     /* the IDispatch-derived interface we are handling */
01532     IID                   tmarshal_iid;
01533     IRpcChannelBuffer    *pDelegateChannel;
01534 } TMarshalDispatchChannel;
01535 
01536 static HRESULT WINAPI TMarshalDispatchChannel_QueryInterface(LPRPCCHANNELBUFFER iface, REFIID riid, LPVOID *ppv)
01537 {
01538     *ppv = NULL;
01539     if (IsEqualIID(riid,&IID_IRpcChannelBuffer) || IsEqualIID(riid,&IID_IUnknown))
01540     {
01541         *ppv = iface;
01542         IUnknown_AddRef(iface);
01543         return S_OK;
01544     }
01545     return E_NOINTERFACE;
01546 }
01547 
01548 static ULONG WINAPI TMarshalDispatchChannel_AddRef(LPRPCCHANNELBUFFER iface)
01549 {
01550     TMarshalDispatchChannel *This = (TMarshalDispatchChannel *)iface;
01551     return InterlockedIncrement(&This->refs);
01552 }
01553 
01554 static ULONG WINAPI TMarshalDispatchChannel_Release(LPRPCCHANNELBUFFER iface)
01555 {
01556     TMarshalDispatchChannel *This = (TMarshalDispatchChannel *)iface;
01557     ULONG ref;
01558 
01559     ref = InterlockedDecrement(&This->refs);
01560     if (ref)
01561         return ref;
01562 
01563     IRpcChannelBuffer_Release(This->pDelegateChannel);
01564     HeapFree(GetProcessHeap(), 0, This);
01565     return 0;
01566 }
01567 
01568 static HRESULT WINAPI TMarshalDispatchChannel_GetBuffer(LPRPCCHANNELBUFFER iface, RPCOLEMESSAGE* olemsg, REFIID riid)
01569 {
01570     TMarshalDispatchChannel *This = (TMarshalDispatchChannel *)iface;
01571     TRACE("(%p, %s)\n", olemsg, debugstr_guid(riid));
01572     /* Note: we are pretending to invoke a method on the interface identified
01573      * by tmarshal_iid so that we can re-use the IDispatch proxy/stub code
01574      * without the RPC runtime getting confused by not exporting an IDispatch interface */
01575     return IRpcChannelBuffer_GetBuffer(This->pDelegateChannel, olemsg, &This->tmarshal_iid);
01576 }
01577 
01578 static HRESULT WINAPI TMarshalDispatchChannel_SendReceive(LPRPCCHANNELBUFFER iface, RPCOLEMESSAGE *olemsg, ULONG *pstatus)
01579 {
01580     TMarshalDispatchChannel *This = (TMarshalDispatchChannel *)iface;
01581     TRACE("(%p, %p)\n", olemsg, pstatus);
01582     return IRpcChannelBuffer_SendReceive(This->pDelegateChannel, olemsg, pstatus);
01583 }
01584 
01585 static HRESULT WINAPI TMarshalDispatchChannel_FreeBuffer(LPRPCCHANNELBUFFER iface, RPCOLEMESSAGE* olemsg)
01586 {
01587     TMarshalDispatchChannel *This = (TMarshalDispatchChannel *)iface;
01588     TRACE("(%p)\n", olemsg);
01589     return IRpcChannelBuffer_FreeBuffer(This->pDelegateChannel, olemsg);
01590 }
01591 
01592 static HRESULT WINAPI TMarshalDispatchChannel_GetDestCtx(LPRPCCHANNELBUFFER iface, DWORD* pdwDestContext, void** ppvDestContext)
01593 {
01594     TMarshalDispatchChannel *This = (TMarshalDispatchChannel *)iface;
01595     TRACE("(%p,%p)\n", pdwDestContext, ppvDestContext);
01596     return IRpcChannelBuffer_GetDestCtx(This->pDelegateChannel, pdwDestContext, ppvDestContext);
01597 }
01598 
01599 static HRESULT WINAPI TMarshalDispatchChannel_IsConnected(LPRPCCHANNELBUFFER iface)
01600 {
01601     TMarshalDispatchChannel *This = (TMarshalDispatchChannel *)iface;
01602     TRACE("()\n");
01603     return IRpcChannelBuffer_IsConnected(This->pDelegateChannel);
01604 }
01605 
01606 static const IRpcChannelBufferVtbl TMarshalDispatchChannelVtbl =
01607 {
01608     TMarshalDispatchChannel_QueryInterface,
01609     TMarshalDispatchChannel_AddRef,
01610     TMarshalDispatchChannel_Release,
01611     TMarshalDispatchChannel_GetBuffer,
01612     TMarshalDispatchChannel_SendReceive,
01613     TMarshalDispatchChannel_FreeBuffer,
01614     TMarshalDispatchChannel_GetDestCtx,
01615     TMarshalDispatchChannel_IsConnected
01616 };
01617 
01618 static HRESULT TMarshalDispatchChannel_Create(
01619     IRpcChannelBuffer *pDelegateChannel, REFIID tmarshal_riid,
01620     IRpcChannelBuffer **ppChannel)
01621 {
01622     TMarshalDispatchChannel *This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
01623     if (!This)
01624         return E_OUTOFMEMORY;
01625 
01626     This->lpVtbl = &TMarshalDispatchChannelVtbl;
01627     This->refs = 1;
01628     IRpcChannelBuffer_AddRef(pDelegateChannel);
01629     This->pDelegateChannel = pDelegateChannel;
01630     This->tmarshal_iid = *tmarshal_riid;
01631 
01632     *ppChannel = (IRpcChannelBuffer *)&This->lpVtbl;
01633     return S_OK;
01634 }
01635 
01636 
01637 static inline HRESULT get_facbuf_for_iid(REFIID riid, IPSFactoryBuffer **facbuf)
01638 {
01639     HRESULT       hr;
01640     CLSID         clsid;
01641 
01642     if ((hr = CoGetPSClsid(riid, &clsid)))
01643         return hr;
01644     return CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL,
01645                              &IID_IPSFactoryBuffer, (LPVOID*)facbuf);
01646 }
01647 
01648 static HRESULT init_proxy_entry_point(TMProxyImpl *proxy, unsigned int num)
01649 {
01650     int j;
01651     /* nrofargs without This */
01652     int nrofargs;
01653     ITypeInfo *tinfo2;
01654     TMAsmProxy  *xasm = proxy->asmstubs + num;
01655     HRESULT hres;
01656     const FUNCDESC *fdesc;
01657 
01658     hres = get_funcdesc(proxy->tinfo, num, &tinfo2, &fdesc, NULL, NULL, NULL);
01659     if (hres) {
01660         ERR("GetFuncDesc %x should not fail here.\n",hres);
01661         return hres;
01662     }
01663     ITypeInfo_Release(tinfo2);
01664     /* some args take more than 4 byte on the stack */
01665     nrofargs = 0;
01666     for (j=0;j<fdesc->cParams;j++)
01667         nrofargs += _argsize(&fdesc->lprgelemdescParam[j].tdesc, proxy->tinfo);
01668 
01669 #ifdef __i386__
01670     if (fdesc->callconv != CC_STDCALL) {
01671         ERR("calling convention is not stdcall????\n");
01672         return E_FAIL;
01673     }
01674 /* popl %eax    -   return ptr
01675  * pushl <nr>
01676  * pushl %eax
01677  * call xCall
01678  * lret <nr> (+4)
01679  *
01680  *
01681  * arg3 arg2 arg1 <method> <returnptr>
01682  */
01683     xasm->popleax       = 0x58;
01684     xasm->pushlval      = 0x68;
01685     xasm->nr            = num;
01686     xasm->pushleax      = 0x50;
01687     xasm->lcall         = 0xe8; /* relative jump */
01688     xasm->xcall         = (DWORD)xCall;
01689     xasm->xcall        -= (DWORD)&(xasm->lret);
01690     xasm->lret          = 0xc2;
01691     xasm->bytestopop    = (nrofargs+2)*4; /* pop args, This, iMethod */
01692     xasm->nop           = 0x90;
01693     proxy->lpvtbl[num]  = xasm;
01694 #else
01695     FIXME("not implemented on non i386\n");
01696     return E_FAIL;
01697 #endif
01698     return S_OK;
01699 }
01700 
01701 static HRESULT WINAPI
01702 PSFacBuf_CreateProxy(
01703     LPPSFACTORYBUFFER iface, IUnknown* pUnkOuter, REFIID riid,
01704     IRpcProxyBuffer **ppProxy, LPVOID *ppv)
01705 {
01706     HRESULT hres;
01707     ITypeInfo   *tinfo;
01708     unsigned int i, nroffuncs;
01709     TMProxyImpl *proxy;
01710     TYPEATTR    *typeattr;
01711     BOOL        defer_to_dispatch = FALSE;
01712 
01713     TRACE("(...%s...)\n",debugstr_guid(riid));
01714     hres = _get_typeinfo_for_iid(riid,&tinfo);
01715     if (hres) {
01716     ERR("No typeinfo for %s?\n",debugstr_guid(riid));
01717     return hres;
01718     }
01719 
01720     hres = num_of_funcs(tinfo, &nroffuncs);
01721     if (FAILED(hres)) {
01722         ERR("Cannot get number of functions for typeinfo %s\n",debugstr_guid(riid));
01723         ITypeInfo_Release(tinfo);
01724         return hres;
01725     }
01726 
01727     proxy = CoTaskMemAlloc(sizeof(TMProxyImpl));
01728     if (!proxy) return E_OUTOFMEMORY;
01729 
01730     assert(sizeof(TMAsmProxy) == 16);
01731 
01732     proxy->dispatch = NULL;
01733     proxy->dispatch_proxy = NULL;
01734     proxy->outerunknown = pUnkOuter;
01735     proxy->asmstubs = VirtualAlloc(NULL, sizeof(TMAsmProxy) * nroffuncs, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
01736     if (!proxy->asmstubs) {
01737         ERR("Could not commit pages for proxy thunks\n");
01738         CoTaskMemFree(proxy);
01739         return E_OUTOFMEMORY;
01740     }
01741     proxy->lpvtbl2  = &tmproxyvtable;
01742     /* one reference for the proxy */
01743     proxy->ref      = 1;
01744     proxy->tinfo    = tinfo;
01745     proxy->iid      = *riid;
01746     proxy->chanbuf      = 0;
01747 
01748     InitializeCriticalSection(&proxy->crit);
01749     proxy->crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": TMProxyImpl.crit");
01750 
01751     proxy->lpvtbl = HeapAlloc(GetProcessHeap(),0,sizeof(LPBYTE)*nroffuncs);
01752 
01753     /* if we derive from IDispatch then defer to its proxy for its methods */
01754     hres = ITypeInfo_GetTypeAttr(tinfo, &typeattr);
01755     if (hres == S_OK)
01756     {
01757         if (typeattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
01758         {
01759             IPSFactoryBuffer *factory_buffer;
01760             hres = get_facbuf_for_iid(&IID_IDispatch, &factory_buffer);
01761             if (hres == S_OK)
01762             {
01763                 hres = IPSFactoryBuffer_CreateProxy(factory_buffer, NULL,
01764                     &IID_IDispatch, &proxy->dispatch_proxy,
01765                     (void **)&proxy->dispatch);
01766                 IPSFactoryBuffer_Release(factory_buffer);
01767             }
01768             if ((hres == S_OK) && (nroffuncs < 7))
01769             {
01770                 ERR("nroffuncs calculated incorrectly (%d)\n", nroffuncs);
01771                 hres = E_UNEXPECTED;
01772             }
01773             if (hres == S_OK)
01774             {
01775                 defer_to_dispatch = TRUE;
01776             }
01777         }
01778         ITypeInfo_ReleaseTypeAttr(tinfo, typeattr);
01779     }
01780 
01781     for (i=0;i<nroffuncs;i++) {
01782     switch (i) {
01783     case 0:
01784         proxy->lpvtbl[i] = ProxyIUnknown_QueryInterface;
01785         break;
01786     case 1:
01787         proxy->lpvtbl[i] = ProxyIUnknown_AddRef;
01788         break;
01789     case 2:
01790         proxy->lpvtbl[i] = ProxyIUnknown_Release;
01791         break;
01792         case 3:
01793                 if(!defer_to_dispatch)
01794                 {
01795                     hres = init_proxy_entry_point(proxy, i);
01796                     if(FAILED(hres)) return hres;
01797                 }
01798                 else proxy->lpvtbl[3] = ProxyIDispatch_GetTypeInfoCount;
01799                 break;
01800         case 4:
01801                 if(!defer_to_dispatch)
01802                 {
01803                     hres = init_proxy_entry_point(proxy, i);
01804                     if(FAILED(hres)) return hres;
01805                 }
01806                 else proxy->lpvtbl[4] = ProxyIDispatch_GetTypeInfo;
01807                 break;
01808         case 5:
01809                 if(!defer_to_dispatch)
01810                 {
01811                     hres = init_proxy_entry_point(proxy, i);
01812                     if(FAILED(hres)) return hres;
01813                 }
01814                 else proxy->lpvtbl[5] = ProxyIDispatch_GetIDsOfNames;
01815                 break;
01816         case 6:
01817                 if(!defer_to_dispatch)
01818                 {
01819                     hres = init_proxy_entry_point(proxy, i);
01820                     if(FAILED(hres)) return hres;
01821                 }
01822                 else proxy->lpvtbl[6] = ProxyIDispatch_Invoke;
01823                 break;
01824     default:
01825                 hres = init_proxy_entry_point(proxy, i);
01826                 if(FAILED(hres)) return hres;
01827     }
01828     }
01829 
01830     if (hres == S_OK)
01831     {
01832         *ppv = proxy;
01833         *ppProxy = (IRpcProxyBuffer *)&(proxy->lpvtbl2);
01834         IUnknown_AddRef((IUnknown *)*ppv);
01835         return S_OK;
01836     }
01837     else
01838         TMProxyImpl_Release((IRpcProxyBuffer *)&proxy->lpvtbl2);
01839     return hres;
01840 }
01841 
01842 typedef struct _TMStubImpl {
01843     const IRpcStubBufferVtbl   *lpvtbl;
01844     LONG            ref;
01845 
01846     LPUNKNOWN           pUnk;
01847     ITypeInfo           *tinfo;
01848     IID             iid;
01849     IRpcStubBuffer      *dispatch_stub;
01850     BOOL            dispatch_derivative;
01851 } TMStubImpl;
01852 
01853 static HRESULT WINAPI
01854 TMStubImpl_QueryInterface(LPRPCSTUBBUFFER iface, REFIID riid, LPVOID *ppv)
01855 {
01856     if (IsEqualIID(riid,&IID_IRpcStubBuffer)||IsEqualIID(riid,&IID_IUnknown)){
01857         *ppv = iface;
01858     IRpcStubBuffer_AddRef(iface);
01859     return S_OK;
01860     }
01861     FIXME("%s, not supported IID.\n",debugstr_guid(riid));
01862     return E_NOINTERFACE;
01863 }
01864 
01865 static ULONG WINAPI
01866 TMStubImpl_AddRef(LPRPCSTUBBUFFER iface)
01867 {
01868     TMStubImpl *This = (TMStubImpl *)iface;
01869     ULONG refCount = InterlockedIncrement(&This->ref);
01870 
01871     TRACE("(%p)->(ref before=%u)\n", This, refCount - 1);
01872 
01873     return refCount;
01874 }
01875 
01876 static ULONG WINAPI
01877 TMStubImpl_Release(LPRPCSTUBBUFFER iface)
01878 {
01879     TMStubImpl *This = (TMStubImpl *)iface;
01880     ULONG refCount = InterlockedDecrement(&This->ref);
01881 
01882     TRACE("(%p)->(ref before=%u)\n", This, refCount + 1);
01883 
01884     if (!refCount)
01885     {
01886         IRpcStubBuffer_Disconnect(iface);
01887         ITypeInfo_Release(This->tinfo);
01888         if (This->dispatch_stub)
01889             IRpcStubBuffer_Release(This->dispatch_stub);
01890         CoTaskMemFree(This);
01891     }
01892     return refCount;
01893 }
01894 
01895 static HRESULT WINAPI
01896 TMStubImpl_Connect(LPRPCSTUBBUFFER iface, LPUNKNOWN pUnkServer)
01897 {
01898     TMStubImpl *This = (TMStubImpl *)iface;
01899 
01900     TRACE("(%p)->(%p)\n", This, pUnkServer);
01901 
01902     IUnknown_AddRef(pUnkServer);
01903     This->pUnk = pUnkServer;
01904 
01905     if (This->dispatch_stub)
01906         IRpcStubBuffer_Connect(This->dispatch_stub, pUnkServer);
01907 
01908     return S_OK;
01909 }
01910 
01911 static void WINAPI
01912 TMStubImpl_Disconnect(LPRPCSTUBBUFFER iface)
01913 {
01914     TMStubImpl *This = (TMStubImpl *)iface;
01915 
01916     TRACE("(%p)->()\n", This);
01917 
01918     if (This->pUnk)
01919     {
01920         IUnknown_Release(This->pUnk);
01921         This->pUnk = NULL;
01922     }
01923 
01924     if (This->dispatch_stub)
01925         IRpcStubBuffer_Disconnect(This->dispatch_stub);
01926 }
01927 
01928 static HRESULT WINAPI
01929 TMStubImpl_Invoke(
01930     LPRPCSTUBBUFFER iface, RPCOLEMESSAGE* xmsg,IRpcChannelBuffer*rpcchanbuf)
01931 {
01932 #ifdef __i386__
01933     int     i;
01934     const FUNCDESC *fdesc;
01935     TMStubImpl *This = (TMStubImpl *)iface;
01936     HRESULT hres;
01937     DWORD   *args = NULL, res, *xargs, nrofargs;
01938     marshal_state   buf;
01939     UINT    nrofnames = 0;
01940     BSTR    names[10];
01941     BSTR    iname = NULL;
01942     ITypeInfo   *tinfo = NULL;
01943 
01944     TRACE("...\n");
01945 
01946     if (xmsg->iMethod < 3) {
01947         ERR("IUnknown methods cannot be marshaled by the typelib marshaler\n");
01948         return E_UNEXPECTED;
01949     }
01950 
01951     if (This->dispatch_derivative && xmsg->iMethod < sizeof(IDispatchVtbl)/sizeof(void *))
01952     {
01953         IPSFactoryBuffer *factory_buffer;
01954         hres = get_facbuf_for_iid(&IID_IDispatch, &factory_buffer);
01955         if (hres == S_OK)
01956         {
01957             hres = IPSFactoryBuffer_CreateStub(factory_buffer, &IID_IDispatch,
01958                 This->pUnk, &This->dispatch_stub);
01959             IPSFactoryBuffer_Release(factory_buffer);
01960         }
01961         if (hres != S_OK)
01962             return hres;
01963         return IRpcStubBuffer_Invoke(This->dispatch_stub, xmsg, rpcchanbuf);
01964     }
01965 
01966     memset(&buf,0,sizeof(buf));
01967     buf.size    = xmsg->cbBuffer;
01968     buf.base    = HeapAlloc(GetProcessHeap(), 0, xmsg->cbBuffer);
01969     memcpy(buf.base, xmsg->Buffer, xmsg->cbBuffer);
01970     buf.curoff  = 0;
01971 
01972     hres = get_funcdesc(This->tinfo,xmsg->iMethod,&tinfo,&fdesc,&iname,NULL,NULL);
01973     if (hres) {
01974     ERR("GetFuncDesc on method %d failed with %x\n",xmsg->iMethod,hres);
01975     return hres;
01976     }
01977 
01978     if (iname && !lstrcmpW(iname, IDispatchW))
01979     {
01980         ERR("IDispatch cannot be marshaled by the typelib marshaler\n");
01981         hres = E_UNEXPECTED;
01982         SysFreeString (iname);
01983         goto exit;
01984     }
01985 
01986     SysFreeString (iname);
01987 
01988     /* Need them for hack below */
01989     memset(names,0,sizeof(names));
01990     ITypeInfo_GetNames(tinfo,fdesc->memid,names,sizeof(names)/sizeof(names[0]),&nrofnames);
01991     if (nrofnames > sizeof(names)/sizeof(names[0])) {
01992     ERR("Need more names!\n");
01993     }
01994 
01995     /*dump_FUNCDESC(fdesc);*/
01996     nrofargs = 0;
01997     for (i=0;i<fdesc->cParams;i++)
01998     nrofargs += _argsize(&fdesc->lprgelemdescParam[i].tdesc, tinfo);
01999     args = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,(nrofargs+1)*sizeof(DWORD));
02000     if (!args)
02001     {
02002         hres = E_OUTOFMEMORY;
02003         goto exit;
02004     }
02005 
02006     /* Allocate all stuff used by call. */
02007     xargs = args+1;
02008     for (i=0;i<fdesc->cParams;i++) {
02009     ELEMDESC    *elem = fdesc->lprgelemdescParam+i;
02010 
02011     hres = deserialize_param(
02012        tinfo,
02013        is_in_elem(elem),
02014        FALSE,
02015        TRUE,
02016        &(elem->tdesc),
02017        xargs,
02018        &buf
02019     );
02020     xargs += _argsize(&elem->tdesc, tinfo);
02021     if (hres) {
02022         ERR("Failed to deserialize param %s, hres %x\n",relaystr(names[i+1]),hres);
02023         break;
02024     }
02025     }
02026 
02027     args[0] = (DWORD)This->pUnk;
02028 
02029     __TRY
02030     {
02031         res = _invoke(
02032             (*((FARPROC**)args[0]))[fdesc->oVft/4],
02033             fdesc->callconv,
02034             (xargs-args),
02035             args
02036         );
02037     }
02038     __EXCEPT_ALL
02039     {
02040         DWORD dwExceptionCode = GetExceptionCode();
02041         ERR("invoke call failed with exception 0x%08x (%d)\n", dwExceptionCode, dwExceptionCode);
02042         if (FAILED(dwExceptionCode))
02043             hres = dwExceptionCode;
02044         else
02045             hres = HRESULT_FROM_WIN32(dwExceptionCode);
02046     }
02047     __ENDTRY
02048 
02049     if (hres != S_OK)
02050         goto exit;
02051 
02052     buf.curoff = 0;
02053 
02054     xargs = args+1;
02055     for (i=0;i<fdesc->cParams;i++) {
02056     ELEMDESC    *elem = fdesc->lprgelemdescParam+i;
02057     hres = serialize_param(
02058        tinfo,
02059        is_out_elem(elem),
02060        FALSE,
02061        TRUE,
02062        &elem->tdesc,
02063        xargs,
02064        &buf
02065     );
02066     xargs += _argsize(&elem->tdesc, tinfo);
02067     if (hres) {
02068         ERR("Failed to stuballoc param, hres %x\n",hres);
02069         break;
02070     }
02071     }
02072 
02073     hres = xbuf_add (&buf, (LPBYTE)&res, sizeof(DWORD));
02074 
02075     if (hres != S_OK)
02076         goto exit;
02077 
02078     xmsg->cbBuffer  = buf.curoff;
02079     hres = IRpcChannelBuffer_GetBuffer(rpcchanbuf, xmsg, &This->iid);
02080     if (hres != S_OK)
02081         ERR("IRpcChannelBuffer_GetBuffer failed with error 0x%08x\n", hres);
02082 
02083     if (hres == S_OK)
02084         memcpy(xmsg->Buffer, buf.base, buf.curoff);
02085 
02086 exit:
02087     for (i = 0; i < nrofnames; i++)
02088         SysFreeString(names[i]);
02089 
02090     ITypeInfo_Release(tinfo);
02091     HeapFree(GetProcessHeap(), 0, args);
02092 
02093     HeapFree(GetProcessHeap(), 0, buf.base);
02094 
02095     TRACE("returning\n");
02096     return hres;
02097 #else
02098     FIXME( "not implemented on non-i386\n" );
02099     return E_FAIL;
02100 #endif
02101 }
02102 
02103 static LPRPCSTUBBUFFER WINAPI
02104 TMStubImpl_IsIIDSupported(LPRPCSTUBBUFFER iface, REFIID riid) {
02105     FIXME("Huh (%s)?\n",debugstr_guid(riid));
02106     return NULL;
02107 }
02108 
02109 static ULONG WINAPI
02110 TMStubImpl_CountRefs(LPRPCSTUBBUFFER iface) {
02111     TMStubImpl *This = (TMStubImpl *)iface;
02112 
02113     FIXME("()\n");
02114     return This->ref; /*FIXME? */
02115 }
02116 
02117 static HRESULT WINAPI
02118 TMStubImpl_DebugServerQueryInterface(LPRPCSTUBBUFFER iface, LPVOID *ppv) {
02119     return E_NOTIMPL;
02120 }
02121 
02122 static void WINAPI
02123 TMStubImpl_DebugServerRelease(LPRPCSTUBBUFFER iface, LPVOID ppv) {
02124     return;
02125 }
02126 
02127 static const IRpcStubBufferVtbl tmstubvtbl = {
02128     TMStubImpl_QueryInterface,
02129     TMStubImpl_AddRef,
02130     TMStubImpl_Release,
02131     TMStubImpl_Connect,
02132     TMStubImpl_Disconnect,
02133     TMStubImpl_Invoke,
02134     TMStubImpl_IsIIDSupported,
02135     TMStubImpl_CountRefs,
02136     TMStubImpl_DebugServerQueryInterface,
02137     TMStubImpl_DebugServerRelease
02138 };
02139 
02140 static HRESULT WINAPI
02141 PSFacBuf_CreateStub(
02142     LPPSFACTORYBUFFER iface, REFIID riid,IUnknown *pUnkServer,
02143     IRpcStubBuffer** ppStub
02144 ) {
02145     HRESULT hres;
02146     ITypeInfo   *tinfo;
02147     TMStubImpl  *stub;
02148     TYPEATTR *typeattr;
02149 
02150     TRACE("(%s,%p,%p)\n",debugstr_guid(riid),pUnkServer,ppStub);
02151 
02152     hres = _get_typeinfo_for_iid(riid,&tinfo);
02153     if (hres) {
02154     ERR("No typeinfo for %s?\n",debugstr_guid(riid));
02155     return hres;
02156     }
02157 
02158     stub = CoTaskMemAlloc(sizeof(TMStubImpl));
02159     if (!stub)
02160     return E_OUTOFMEMORY;
02161     stub->lpvtbl    = &tmstubvtbl;
02162     stub->ref       = 1;
02163     stub->tinfo     = tinfo;
02164     stub->dispatch_stub = NULL;
02165     stub->dispatch_derivative = FALSE;
02166     stub->iid       = *riid;
02167     hres = IRpcStubBuffer_Connect((LPRPCSTUBBUFFER)stub,pUnkServer);
02168     *ppStub         = (LPRPCSTUBBUFFER)stub;
02169     TRACE("IRpcStubBuffer: %p\n", stub);
02170     if (hres)
02171     ERR("Connect to pUnkServer failed?\n");
02172 
02173     /* if we derive from IDispatch then defer to its stub for some of its methods */
02174     hres = ITypeInfo_GetTypeAttr(tinfo, &typeattr);
02175     if (hres == S_OK)
02176     {
02177         if (typeattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
02178             stub->dispatch_derivative = TRUE;
02179         ITypeInfo_ReleaseTypeAttr(tinfo, typeattr);
02180     }
02181 
02182     return hres;
02183 }
02184 
02185 static const IPSFactoryBufferVtbl psfacbufvtbl = {
02186     PSFacBuf_QueryInterface,
02187     PSFacBuf_AddRef,
02188     PSFacBuf_Release,
02189     PSFacBuf_CreateProxy,
02190     PSFacBuf_CreateStub
02191 };
02192 
02193 /* This is the whole PSFactoryBuffer object, just the vtableptr */
02194 static const IPSFactoryBufferVtbl *lppsfac = &psfacbufvtbl;
02195 
02196 /***********************************************************************
02197  *           TMARSHAL_DllGetClassObject
02198  */
02199 HRESULT TMARSHAL_DllGetClassObject(REFCLSID rclsid, REFIID iid,LPVOID *ppv)
02200 {
02201     if (IsEqualIID(iid,&IID_IPSFactoryBuffer)) {
02202     *ppv = &lppsfac;
02203     return S_OK;
02204     }
02205     return E_NOINTERFACE;
02206 }

Generated on Sat May 26 2012 04:24:17 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.