/*\r
* TYPELIB Marshaler\r
*\r
- * Copyright 2002 Marcus Meissner\r
+ * Copyright 2002,2005 Marcus Meissner\r
*\r
* The olerelay debug channel allows you to see calls marshalled by\r
* the typelib marshaller. It is not a generic COM relaying system.\r
static const WCHAR riidW[5] = {'r','i','i','d',0};\r
static const WCHAR pdispparamsW[] = {'p','d','i','s','p','p','a','r','a','m','s',0};\r
static const WCHAR ppvObjectW[] = {'p','p','v','O','b','j','e','c','t',0};\r
+static const WCHAR IDispatchW[] = { 'I','D','i','s','p','a','t','c','h',0};\r
+static const WCHAR GetIDsOfNamesW[] = { 'G','e','t','I','D','s','O','f','N','a','m','e','s',0};\r
\r
WINE_DEFAULT_DEBUG_CHANNEL(ole);\r
WINE_DECLARE_DEBUG_CHANNEL(olerelay);\r
DWORD xsize;\r
HRESULT hres;\r
\r
- hres = E_FAIL;\r
if (!pUnk) {\r
+ /* this is valid, if for instance we serialize\r
+ * a VT_DISPATCH with NULL ptr which apparently\r
+ * can happen. S_OK to make sure we continue\r
+ * serializing.\r
+ */\r
ERR("pUnk is NULL?\n");\r
- goto fail;\r
+ xsize = 0;\r
+ return xbuf_add(buf,(LPBYTE)&xsize,sizeof(xsize));\r
}\r
\r
+ hres = E_FAIL;\r
+\r
TRACE("...%s...\n",debugstr_guid(riid));\r
hres = IUnknown_QueryInterface(pUnk,riid,(LPVOID*)&newiface);\r
if (hres) {\r
IRpcChannelBuffer* chanbuf;\r
IID iid;\r
CRITICAL_SECTION crit;\r
+ IUnknown *outerunknown;\r
} TMProxyImpl;\r
\r
static HRESULT WINAPI\r
return S_OK;\r
case VT_BOOL:\r
case VT_ERROR:\r
- case VT_UI4:\r
case VT_UINT:\r
case VT_I4:\r
case VT_R4:\r
+ case VT_UI4:\r
+ hres = S_OK;\r
+ if (debugout) TRACE_(olerelay)("%lx",*arg);\r
+ if (writeit)\r
+ hres = xbuf_add(buf,(LPBYTE)arg,sizeof(DWORD));\r
+ return hres;\r
+ case VT_I2:\r
case VT_UI2:\r
+ hres = S_OK;\r
+ if (debugout) TRACE_(olerelay)("%04lx",*arg & 0xffff);\r
+ if (writeit)\r
+ hres = xbuf_add(buf,(LPBYTE)arg,sizeof(DWORD));\r
+ return hres;\r
+ case VT_I1:\r
case VT_UI1:\r
hres = S_OK;\r
- if (debugout) TRACE_(olerelay)("%lx",*arg);\r
+ if (debugout) TRACE_(olerelay)("%02lx",*arg & 0xff);\r
if (writeit)\r
hres = xbuf_add(buf,(LPBYTE)arg,sizeof(DWORD));\r
return hres;\r
+ case VT_I4|VT_BYREF:\r
+ hres = S_OK;\r
+ if (debugout) TRACE_(olerelay)("&0x%lx",*arg);\r
+ if (writeit)\r
+ hres = xbuf_add(buf,(LPBYTE)(DWORD*)*arg,sizeof(DWORD));\r
+ /* do not dealloc at this time */\r
+ return hres;\r
case VT_VARIANT: {\r
TYPEDESC tdesc2;\r
VARIANT *vt = (VARIANT*)arg;\r
if (debugout) TRACE_(olerelay)(")");\r
return hres;\r
}\r
+ case VT_BSTR|VT_BYREF: {\r
+ if (debugout) TRACE_(olerelay)("[byref]'%s'", *(BSTR*)*arg ? relaystr(*((BSTR*)*arg)) : "<bstr NULL>");\r
+ if (writeit) {\r
+ /* ptr to ptr to magic widestring, basically */\r
+ BSTR *bstr = (BSTR *) *arg;\r
+ if (!*bstr) {\r
+ /* -1 means "null string" which is equivalent to empty string */\r
+ DWORD fakelen = -1; \r
+ xbuf_add(buf, (LPBYTE)&fakelen,4);\r
+ } else {\r
+ /* BSTRs store the length behind the first character */\r
+ DWORD *len = ((DWORD *)(*bstr))-1;\r
+ hres = xbuf_add(buf, (LPBYTE) len, *len + 4);\r
+ if (hres) return hres;\r
+ }\r
+ }\r
+\r
+ if (dealloc && arg) {\r
+ BSTR *str = *((BSTR **)arg);\r
+ SysFreeString(*str);\r
+ }\r
+ return S_OK;\r
+ }\r
+ \r
case VT_BSTR: {\r
if (debugout) {\r
- if (arg)\r
- TRACE_(olerelay)("%s",relaystr((BSTR)*arg));\r
+ if (*arg)\r
+ TRACE_(olerelay)("%s",relaystr((WCHAR*)*arg));\r
else\r
TRACE_(olerelay)("<bstr NULL>");\r
}\r
DWORD cookie;\r
\r
if (debugout) TRACE_(olerelay)("*");\r
- if (writeit) {\r
- cookie = *arg ? 0x42424242 : 0;\r
- hres = xbuf_add(buf,(LPBYTE)&cookie,sizeof(cookie));\r
- if (hres)\r
- return hres;\r
- }\r
+ /* Write always, so the other side knows when it gets a NULL pointer.\r
+ */\r
+ cookie = *arg ? 0x42424242 : 0;\r
+ hres = xbuf_add(buf,(LPBYTE)&cookie,sizeof(cookie));\r
+ if (hres)\r
+ return hres;\r
if (!*arg) {\r
if (debugout) TRACE_(olerelay)("NULL");\r
return S_OK;\r
if (debugout) TRACE_(olerelay)("[%ld]",adesc->rgbounds[i].cElements);\r
arrsize *= adesc->rgbounds[i].cElements;\r
}\r
+ if (debugout) TRACE_(olerelay)("(vt %d)",adesc->tdescElem.vt);\r
if (debugout) TRACE_(olerelay)("[");\r
for (i=0;i<arrsize;i++) {\r
hres = serialize_param(tinfo, writeit, debugout, dealloc, &adesc->tdescElem, (DWORD*)((LPBYTE)arg+i*_xsize(&adesc->tdescElem)), buf);\r
}\r
}\r
\r
+/* IDL desc:\r
+ * HRESULT GetIDsOfNames(\r
+ * [in] REFIID riid, args[1]\r
+ * [in, size_is(cNames)] LPOLESTR *rgszNames, args[2]\r
+ * [in] UINT cNames, args[3]\r
+ * [in] LCID lcid, args[4]\r
+ * [out, size_is(cNames)] DISPID *rgDispId); args[5]\r
+ *\r
+ * line format:\r
+ * IID iid;\r
+ * DWORD cNames;\r
+ * LPOLESTR rgszNames[cNames];\r
+ * DWORD bytestrlen (incl 0)\r
+ * BYTE data[bytestrlen] (incl 0)\r
+ * LCID\r
+ */\r
+static HRESULT\r
+serialize_IDispatch_GetIDsOfNames(\r
+ BOOL inputparams,\r
+ BOOL debugout,\r
+ DWORD *args,\r
+ marshal_state *buf)\r
+{\r
+ HRESULT hres;\r
+ DWORD cNames = args[2];\r
+ LPOLESTR *rgszNames = (LPOLESTR*)args[1];\r
+ int i;\r
+\r
+ if (inputparams) {\r
+ if (debugout) TRACE_(olerelay)("riid=%s,",debugstr_guid((REFIID)args[0]));\r
+ hres = xbuf_add(buf, (LPBYTE)args[0], sizeof(IID));\r
+ if (hres) {\r
+ FIXME("serialize of IID failed.\n");\r
+ return hres;\r
+ }\r
+ if (debugout) TRACE_(olerelay)("cNames=%ld,",cNames);\r
+ hres = xbuf_add(buf, (LPBYTE)&cNames, sizeof(DWORD));\r
+ if (hres) {\r
+ FIXME("serialize of cNames failed.\n");\r
+ return hres;\r
+ }\r
+ if (debugout) TRACE_(olerelay)("rgszNames=[");\r
+ for (i=0;i<cNames;i++) {\r
+ DWORD len = 2*(lstrlenW(rgszNames[i])+1);\r
+\r
+ if (debugout) TRACE_(olerelay)("%s,",relaystr(rgszNames[i]));\r
+ hres = xbuf_add(buf, (LPBYTE)&len, sizeof(DWORD));\r
+ if (hres) {\r
+ FIXME("serialize of len failed.\n");\r
+ return hres;\r
+ }\r
+ hres = xbuf_add(buf, (LPBYTE)rgszNames[i], len);\r
+ if (hres) {\r
+ FIXME("serialize of rgszNames[i] failed.\n");\r
+ return hres;\r
+ }\r
+ }\r
+ if (debugout) TRACE_(olerelay)("],lcid=%04lx)",args[3]);\r
+ hres = xbuf_add(buf, (LPBYTE)&args[3], sizeof(DWORD));\r
+ if (hres) {\r
+ FIXME("serialize of lcid failed.\n");\r
+ return hres;\r
+ }\r
+ } else {\r
+ DISPID *rgDispId = (DISPID*)args[4];\r
+\r
+ hres = xbuf_add(buf, (LPBYTE)rgDispId, sizeof(DISPID) * cNames);\r
+ if (hres) {\r
+ FIXME("serialize of rgDispId failed.\n");\r
+ return hres;\r
+ }\r
+ if (debugout) {\r
+ TRACE_(olerelay)("riid=[in],rgszNames=[in],cNames=[in],rgDispId=[");\r
+ for (i=0;i<cNames;i++)\r
+ TRACE_(olerelay)("%08lx,",rgDispId[i]);\r
+ TRACE_(olerelay)("])");\r
+ }\r
+ HeapFree(GetProcessHeap(),0,(IID*)args[0]);\r
+ rgszNames = (LPOLESTR*)args[1];\r
+ for (i=0;i<cNames;i++) HeapFree(GetProcessHeap(),0,rgszNames[i]);\r
+ HeapFree(GetProcessHeap(),0,rgszNames);\r
+ HeapFree(GetProcessHeap(),0,rgDispId);\r
+ }\r
+ return S_OK;\r
+}\r
+\r
+static HRESULT\r
+deserialize_IDispatch_GetIDsOfNames(\r
+ BOOL inputparams,\r
+ BOOL debugout,\r
+ DWORD *args,\r
+ marshal_state *buf)\r
+{\r
+ HRESULT hres;\r
+ DWORD cNames;\r
+ LPOLESTR *rgszNames;\r
+ int i;\r
+\r
+ if (inputparams) {\r
+ args[0] = (DWORD)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IID));\r
+ if (!args[0]) return E_FAIL;\r
+ hres = xbuf_get(buf, (LPBYTE)args[0], sizeof(IID));\r
+ if (hres) {\r
+ FIXME("deserialize of IID failed.\n");\r
+ return hres;\r
+ }\r
+ if (debugout) TRACE_(olerelay)("riid=%s,",debugstr_guid((REFIID)args[0]));\r
+\r
+ hres = xbuf_get(buf, (LPBYTE)&cNames, sizeof(DWORD));\r
+ if (hres) {\r
+ FIXME("deserialize of cNames failed.\n");\r
+ return hres;\r
+ }\r
+ args[2] = cNames;\r
+ if (debugout) TRACE_(olerelay)("cNames=%ld,",cNames);\r
+ if (debugout) TRACE_(olerelay)("rgszNames=[");\r
+ rgszNames = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(LPOLESTR) * cNames);\r
+ if (!rgszNames) return E_FAIL;\r
+ args[1] = (DWORD)rgszNames;\r
+ for (i=0;i<cNames;i++) {\r
+ DWORD len;\r
+\r
+ hres = xbuf_get(buf, (LPBYTE)&len, sizeof(DWORD));\r
+ if (hres) {\r
+ FIXME("serialize of len failed.\n");\r
+ return hres;\r
+ }\r
+ rgszNames[i] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);\r
+ if (!rgszNames[i]) {\r
+ FIXME("heapalloc of %ld bytes failed\n", len);\r
+ return E_FAIL;\r
+ }\r
+ hres = xbuf_get(buf, (LPBYTE)rgszNames[i], len);\r
+ if (hres) {\r
+ FIXME("serialize of rgszNames[i] failed.\n");\r
+ return hres;\r
+ }\r
+ if (debugout) TRACE_(olerelay)("%s,",relaystr(rgszNames[i]));\r
+ }\r
+ hres = xbuf_get(buf, (LPBYTE)&args[3], sizeof(DWORD));\r
+ if (hres) {\r
+ FIXME("deserialize of lcid failed.\n");\r
+ return hres;\r
+ }\r
+ if (debugout) TRACE_(olerelay)("],lcid=%04lx,rgDispId=[out])",args[3]);\r
+ args[4] = (DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DISPID) * cNames);\r
+ } else {\r
+ hres = xbuf_get(buf, (LPBYTE)args[4], sizeof(DISPID) * args[2]);\r
+ if (hres) {\r
+ FIXME("serialize of rgDispId failed.\n");\r
+ return hres;\r
+ }\r
+ if (debugout) {\r
+ TRACE_(olerelay)("dispid=[");\r
+ for (i=0;i<args[2];i++)\r
+ TRACE_(olerelay)("%08lx,",((DISPID*)args[4])[i]);\r
+ TRACE_(olerelay)("])");\r
+ }\r
+ }\r
+ return S_OK;\r
+}\r
+\r
static HRESULT\r
serialize_LPVOID_ptr(\r
ITypeInfo *tinfo,\r
FIXME("ppvObject not expressed as VT_PTR -> VT_PTR -> VT_VOID?\n");\r
return E_FAIL;\r
}\r
- cookie = (*arg) ? 0x42424242: 0x0;\r
+ cookie = (*(DWORD*)*arg) ? 0x42424242: 0x0;\r
if (writeit) {\r
hres = xbuf_add(buf, (LPVOID)&cookie, sizeof(cookie));\r
if (hres)\r
return hres;\r
}\r
- if (!*arg) {\r
+ if (!*(DWORD*)*arg) {\r
if (debugout) TRACE_(olerelay)("<lpvoid NULL>");\r
return S_OK;\r
}\r
}\r
}\r
case VT_ERROR:\r
- case VT_BOOL: case VT_I4: case VT_UI4: case VT_UINT: case VT_R4:\r
- case VT_UI2:\r
- case VT_UI1:\r
+ case VT_BOOL:\r
+ case VT_I4:\r
+ case VT_UINT:\r
+ case VT_R4:\r
+ case VT_UI4:\r
if (readit) {\r
hres = xbuf_get(buf,(LPBYTE)arg,sizeof(DWORD));\r
if (hres) ERR("Failed to read integer 4 byte\n");\r
}\r
if (debugout) TRACE_(olerelay)("%lx",*arg);\r
return hres;\r
+ case VT_I2:\r
+ case VT_UI2:\r
+ if (readit) {\r
+ DWORD x;\r
+ hres = xbuf_get(buf,(LPBYTE)&x,sizeof(DWORD));\r
+ if (hres) ERR("Failed to read integer 4 byte\n");\r
+ memcpy(arg,&x,2);\r
+ }\r
+ if (debugout) TRACE_(olerelay)("%04lx",*arg & 0xffff);\r
+ return hres;\r
+ case VT_I1:\r
+ case VT_UI1:\r
+ if (readit) {\r
+ DWORD x;\r
+ hres = xbuf_get(buf,(LPBYTE)&x,sizeof(DWORD));\r
+ if (hres) ERR("Failed to read integer 4 byte\n");\r
+ memcpy(arg,&x,1);\r
+ }\r
+ if (debugout) TRACE_(olerelay)("%02lx",*arg & 0xff);\r
+ return hres;\r
+ case VT_I4|VT_BYREF:\r
+ hres = S_OK;\r
+ if (alloc)\r
+ *arg = (DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DWORD));\r
+ if (readit) {\r
+ hres = xbuf_get(buf,(LPBYTE)*arg,sizeof(DWORD));\r
+ if (hres) ERR("Failed to read integer 4 byte\n");\r
+ }\r
+ if (debugout) TRACE_(olerelay)("&0x%lx",*(DWORD*)*arg);\r
+ return hres;\r
+ case VT_BSTR|VT_BYREF: {\r
+ BSTR **bstr = (BSTR **)arg;\r
+ WCHAR *str;\r
+ DWORD len;\r
+\r
+ if (readit) {\r
+ hres = xbuf_get(buf,(LPBYTE)&len,sizeof(DWORD));\r
+ if (hres) {\r
+ ERR("failed to read bstr klen\n");\r
+ return hres;\r
+ }\r
+ if (len == -1) {\r
+ *bstr = CoTaskMemAlloc(sizeof(BSTR *));\r
+ **bstr = NULL;\r
+ if (debugout) TRACE_(olerelay)("<bstr NULL>");\r
+ } else {\r
+ str = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,len+sizeof(WCHAR));\r
+ hres = xbuf_get(buf,(LPBYTE)str,len);\r
+ if (hres) {\r
+ ERR("Failed to read BSTR.\n");\r
+ return hres;\r
+ }\r
+ *bstr = CoTaskMemAlloc(sizeof(BSTR *));\r
+ **bstr = SysAllocStringLen(str,len);\r
+ if (debugout) TRACE_(olerelay)("%s",relaystr(str));\r
+ HeapFree(GetProcessHeap(),0,str);\r
+ }\r
+ } else {\r
+ *bstr = NULL;\r
+ }\r
+ return S_OK;\r
+ }\r
case VT_BSTR: {\r
WCHAR *str;\r
DWORD len;\r
}\r
case VT_PTR: {\r
DWORD cookie;\r
- BOOL derefhere = 0;\r
+ BOOL derefhere = 0;\r
\r
derefhere = (tdesc->u.lptdesc->vt != VT_USERDEFINED);\r
-\r
- if (readit) {\r
- hres = xbuf_get(buf,(LPBYTE)&cookie,sizeof(cookie));\r
- if (hres) {\r
- ERR("Failed to load pointer cookie.\n");\r
- return hres;\r
- }\r
- if (cookie != 0x42424242) {\r
- if (debugout) TRACE_(olerelay)("NULL");\r
- *arg = 0;\r
- return S_OK;\r
- }\r
- if (debugout) TRACE_(olerelay)("*");\r
+ /* read it in all cases, we need to know if we have \r
+ * NULL pointer or not.\r
+ */\r
+ hres = xbuf_get(buf,(LPBYTE)&cookie,sizeof(cookie));\r
+ if (hres) {\r
+ ERR("Failed to load pointer cookie.\n");\r
+ return hres;\r
+ }\r
+ if (cookie != 0x42424242) {\r
+ /* we read a NULL ptr from the remote side */\r
+ if (debugout) TRACE_(olerelay)("NULL");\r
+ *arg = 0;\r
+ return S_OK;\r
}\r
+ if (debugout) TRACE_(olerelay)("*");\r
if (alloc) {\r
+ /* Allocate space for the referenced struct */\r
if (derefhere)\r
*arg=(DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,_xsize(tdesc->u.lptdesc));\r
}\r
if (hres) {\r
ERR("Could not get typeattr in VT_USERDEFINED.\n");\r
} else {\r
- if (alloc)\r
- *arg = (DWORD)HeapAlloc(GetProcessHeap(),0,tattr->cbSizeInstance);\r
switch (tattr->typekind) {\r
case TKIND_DISPATCH:\r
case TKIND_INTERFACE:\r
case TKIND_RECORD: {\r
int i;\r
\r
+ if (alloc)\r
+ *arg = (DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,tattr->cbSizeInstance);\r
+\r
if (debugout) TRACE_(olerelay)("{");\r
for (i=0;i<tattr->cVars;i++) {\r
VARDESC *vdesc;\r
}\r
if (readit) {\r
hres = _unmarshal_interface(buf,&buf->iid,(LPUNKNOWN*)*arg);\r
- if (hres)\r
+ if (hres) {\r
+ FIXME("_unmarshal_interface of %s , %p failed with %lx\n", debugstr_guid(&buf->iid), (LPUNKNOWN*)*arg, hres);\r
return hres;\r
+ }\r
}\r
if (debugout) TRACE_(olerelay)("ppv(%p)",(LPVOID)*arg);\r
return S_OK;\r
BSTR fname,iname;\r
BSTR names[10];\r
int nrofnames;\r
+ int is_idispatch_getidsofnames = 0;\r
+ DWORD remoteresult = 0;\r
\r
EnterCriticalSection(&tpinfo->crit);\r
\r
else\r
TRACE_(olerelay)("%d",method);\r
TRACE_(olerelay)("(");\r
- if (iname) SysFreeString(iname);\r
- if (fname) SysFreeString(fname);\r
}\r
+ if (iname && fname && !lstrcmpW(iname,IDispatchW) && !lstrcmpW(fname,GetIDsOfNamesW))\r
+ is_idispatch_getidsofnames = 1;\r
+\r
+ if (iname) SysFreeString(iname);\r
+ if (fname) SysFreeString(fname);\r
+\r
+ memset(&buf,0,sizeof(buf));\r
+ buf.iid = IID_IUnknown;\r
+\r
+ /* Special IDispatch::GetIDsOfNames() serializer */\r
+ if (is_idispatch_getidsofnames) {\r
+ hres = serialize_IDispatch_GetIDsOfNames(TRUE,relaydeb,args,&buf);\r
+ if (hres != S_OK) {\r
+ FIXME("serialize of IDispatch::GetIDsOfNames failed!\n");\r
+ return hres;\r
+ }\r
+ goto afterserialize;\r
+ }\r
+\r
+ /* special QueryInterface serialize */\r
+ if (method == 0) {\r
+ xbuf_add(&buf,(LPBYTE)args[0],sizeof(IID));\r
+ if (relaydeb) TRACE_(olerelay)("riid=%s,[out])",debugstr_guid((REFIID)args[0]));\r
+ goto afterserialize;\r
+ }\r
+\r
+ /* normal typelib driven serializing */\r
+\r
/* Need them for hack below */\r
memset(names,0,sizeof(names));\r
if (ITypeInfo_GetNames(tpinfo->tinfo,fdesc->memid,names,sizeof(names)/sizeof(names[0]),&nrofnames))\r
if (nrofnames > sizeof(names)/sizeof(names[0]))\r
ERR("Need more names!\n");\r
\r
- memset(&buf,0,sizeof(buf));\r
- buf.iid = IID_IUnknown;\r
- if (method == 0) {\r
- xbuf_add(&buf,(LPBYTE)args[0],sizeof(IID));\r
- if (relaydeb) TRACE_(olerelay)("riid=%s,[out]",debugstr_guid((REFIID)args[0]));\r
- } else {\r
- xargs = args;\r
- for (i=0;i<fdesc->cParams;i++) {\r
- ELEMDESC *elem = fdesc->lprgelemdescParam+i;\r
- BOOL isserialized = FALSE;\r
- if (relaydeb) {\r
- if (i) TRACE_(olerelay)(",");\r
- if (i+1<nrofnames && names[i+1])\r
- TRACE_(olerelay)("%s=",relaystr(names[i+1]));\r
- }\r
- /* No need to marshal other data than FIN */\r
- if (!(elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN)) {\r
- xargs+=_argsize(elem->tdesc.vt);\r
- if (relaydeb) TRACE_(olerelay)("[out]");\r
- continue;\r
- }\r
- if (((i+1)<nrofnames) && !IsBadStringPtrW(names[i+1],1)) {\r
- /* If the parameter is 'riid', we use it as interface IID\r
- * for a later ppvObject serialization.\r
- */\r
- buf.thisisiid = !lstrcmpW(names[i+1],riidW);\r
-\r
- /* DISPPARAMS* needs special serializer */\r
- if (!lstrcmpW(names[i+1],pdispparamsW)) {\r
- hres = serialize_DISPPARAM_ptr(\r
- tpinfo->tinfo,\r
- elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN,\r
- relaydeb,\r
- FALSE,\r
- &elem->tdesc,\r
- xargs,\r
- &buf\r
- );\r
- isserialized = TRUE;\r
- }\r
- if (!lstrcmpW(names[i+1],ppvObjectW)) {\r
- hres = serialize_LPVOID_ptr(\r
- tpinfo->tinfo,\r
- elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN,\r
- relaydeb,\r
- FALSE,\r
- &elem->tdesc,\r
- xargs,\r
- &buf\r
- );\r
- if (hres == S_OK)\r
- isserialized = TRUE;\r
- }\r
+ xargs = args;\r
+ for (i=0;i<fdesc->cParams;i++) {\r
+ ELEMDESC *elem = fdesc->lprgelemdescParam+i;\r
+ BOOL isserialized = FALSE;\r
+ if (relaydeb) {\r
+ if (i) TRACE_(olerelay)(",");\r
+ if (i+1<nrofnames && names[i+1])\r
+ TRACE_(olerelay)("%s=",relaystr(names[i+1]));\r
+ }\r
+ /* No need to marshal other data than FIN and any VT_PTR. */\r
+ if (!(elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN) && (elem->tdesc.vt != VT_PTR)) {\r
+ xargs+=_argsize(elem->tdesc.vt);\r
+ if (relaydeb) TRACE_(olerelay)("[out]");\r
+ continue;\r
+ }\r
+ if (((i+1)<nrofnames) && !IsBadStringPtrW(names[i+1],1)) {\r
+ /* If the parameter is 'riid', we use it as interface IID\r
+ * for a later ppvObject serialization.\r
+ */\r
+ buf.thisisiid = !lstrcmpW(names[i+1],riidW);\r
+\r
+ /* DISPPARAMS* needs special serializer */\r
+ if (!lstrcmpW(names[i+1],pdispparamsW)) {\r
+ hres = serialize_DISPPARAM_ptr(\r
+ tpinfo->tinfo,\r
+ elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN,\r
+ relaydeb,\r
+ FALSE,\r
+ &elem->tdesc,\r
+ xargs,\r
+ &buf\r
+ );\r
+ isserialized = TRUE;\r
}\r
- if (!isserialized)\r
- hres = serialize_param(\r
+ if (!lstrcmpW(names[i+1],ppvObjectW)) {\r
+ hres = serialize_LPVOID_ptr(\r
tpinfo->tinfo,\r
elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN,\r
relaydeb,\r
xargs,\r
&buf\r
);\r
-\r
- if (hres) {\r
- ERR("Failed to serialize param, hres %lx\n",hres);\r
- break;\r
+ if (hres == S_OK)\r
+ isserialized = TRUE;\r
}\r
- xargs+=_argsize(elem->tdesc.vt);\r
}\r
+ if (!isserialized)\r
+ hres = serialize_param(\r
+ tpinfo->tinfo,\r
+ elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN,\r
+ relaydeb,\r
+ FALSE,\r
+ &elem->tdesc,\r
+ xargs,\r
+ &buf\r
+ );\r
+\r
+ if (hres) {\r
+ ERR("Failed to serialize param, hres %lx\n",hres);\r
+ break;\r
+ }\r
+ xargs+=_argsize(elem->tdesc.vt);\r
}\r
if (relaydeb) TRACE_(olerelay)(")");\r
+\r
+afterserialize:\r
memset(&msg,0,sizeof(msg));\r
msg.cbBuffer = buf.curoff;\r
msg.iMethod = method;\r
return hres;\r
}\r
\r
- if (relaydeb) TRACE_(olerelay)(" = %08lx (",status);\r
+ if (relaydeb) TRACE_(olerelay)(" status = %08lx (",status);\r
if (buf.base)\r
buf.base = HeapReAlloc(GetProcessHeap(),0,buf.base,msg.cbBuffer);\r
else\r
buf.size = msg.cbBuffer;\r
memcpy(buf.base,msg.Buffer,buf.size);\r
buf.curoff = 0;\r
+\r
+ /* Special IDispatch::GetIDsOfNames() deserializer */\r
+ if (is_idispatch_getidsofnames) {\r
+ hres = deserialize_IDispatch_GetIDsOfNames(FALSE,relaydeb,args,&buf);\r
+ if (hres != S_OK) {\r
+ FIXME("deserialize of IDispatch::GetIDsOfNames failed!\n");\r
+ return hres;\r
+ }\r
+ goto after_deserialize;\r
+ }\r
+ /* Special QueryInterface deserializer */\r
if (method == 0) {\r
_unmarshal_interface(&buf,(REFIID)args[0],(LPUNKNOWN*)args[1]);\r
if (relaydeb) TRACE_(olerelay)("[in],%p",*((DWORD**)args[1]));\r
- } else {\r
- xargs = args;\r
- for (i=0;i<fdesc->cParams;i++) {\r
- ELEMDESC *elem = fdesc->lprgelemdescParam+i;\r
- BOOL isdeserialized = FALSE;\r
-\r
- if (relaydeb) {\r
- if (i) TRACE_(olerelay)(",");\r
- if (i+1<nrofnames && names[i+1]) TRACE_(olerelay)("%s=",relaystr(names[i+1]));\r
- }\r
- /* No need to marshal other data than FOUT I think */\r
- if (!(elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT)) {\r
- xargs += _argsize(elem->tdesc.vt);\r
- if (relaydeb) TRACE_(olerelay)("[in]");\r
- continue;\r
- }\r
- if (((i+1)<nrofnames) && !IsBadStringPtrW(names[i+1],1)) {\r
- /* If the parameter is 'riid', we use it as interface IID\r
- * for a later ppvObject serialization.\r
- */\r
- buf.thisisiid = !lstrcmpW(names[i+1],riidW);\r
-\r
- /* deserialize DISPPARAM */\r
- if (!lstrcmpW(names[i+1],pdispparamsW)) {\r
- hres = deserialize_DISPPARAM_ptr(\r
- tpinfo->tinfo,\r
- elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT,\r
- relaydeb,\r
- FALSE,\r
- &(elem->tdesc),\r
- xargs,\r
- &buf\r
- );\r
- if (hres) {\r
- ERR("Failed to deserialize DISPPARAM*, hres %lx\n",hres);\r
- break;\r
- }\r
- isdeserialized = TRUE;\r
- }\r
- if (!lstrcmpW(names[i+1],ppvObjectW)) {\r
- hres = deserialize_LPVOID_ptr(\r
- tpinfo->tinfo,\r
- elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT,\r
- relaydeb,\r
- FALSE,\r
- &elem->tdesc,\r
- xargs,\r
- &buf\r
- );\r
- if (hres == S_OK)\r
- isdeserialized = TRUE;\r
+ goto after_deserialize;\r
+ }\r
+\r
+ /* generic deserializer using typelib description */\r
+ xargs = args;\r
+ status = S_OK;\r
+ for (i=0;i<fdesc->cParams;i++) {\r
+ ELEMDESC *elem = fdesc->lprgelemdescParam+i;\r
+ BOOL isdeserialized = FALSE;\r
+\r
+ if (relaydeb) {\r
+ if (i) TRACE_(olerelay)(",");\r
+ if (i+1<nrofnames && names[i+1]) TRACE_(olerelay)("%s=",relaystr(names[i+1]));\r
+ }\r
+ /* No need to marshal other data than FOUT and any VT_PTR */\r
+ if (!(elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT) && (elem->tdesc.vt != VT_PTR)) {\r
+ xargs += _argsize(elem->tdesc.vt);\r
+ if (relaydeb) TRACE_(olerelay)("[in]");\r
+ continue;\r
+ }\r
+ if (((i+1)<nrofnames) && !IsBadStringPtrW(names[i+1],1)) {\r
+ /* If the parameter is 'riid', we use it as interface IID\r
+ * for a later ppvObject serialization.\r
+ */\r
+ buf.thisisiid = !lstrcmpW(names[i+1],riidW);\r
+\r
+ /* deserialize DISPPARAM */\r
+ if (!lstrcmpW(names[i+1],pdispparamsW)) {\r
+ hres = deserialize_DISPPARAM_ptr(\r
+ tpinfo->tinfo,\r
+ elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT,\r
+ relaydeb,\r
+ FALSE,\r
+ &(elem->tdesc),\r
+ xargs,\r
+ &buf\r
+ );\r
+ if (hres) {\r
+ ERR("Failed to deserialize DISPPARAM*, hres %lx\n",hres);\r
+ break;\r
}\r
+ isdeserialized = TRUE;\r
}\r
- if (!isdeserialized)\r
- hres = deserialize_param(\r
+ if (!lstrcmpW(names[i+1],ppvObjectW)) {\r
+ hres = deserialize_LPVOID_ptr(\r
tpinfo->tinfo,\r
elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT,\r
relaydeb,\r
FALSE,\r
- &(elem->tdesc),\r
+ &elem->tdesc,\r
xargs,\r
&buf\r
);\r
- if (hres) {\r
- ERR("Failed to unmarshall param, hres %lx\n",hres);\r
- status = hres;\r
- break;\r
+ if (hres == S_OK)\r
+ isdeserialized = TRUE;\r
}\r
- xargs += _argsize(elem->tdesc.vt);\r
}\r
+ if (!isdeserialized)\r
+ hres = deserialize_param(\r
+ tpinfo->tinfo,\r
+ elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT,\r
+ relaydeb,\r
+ FALSE,\r
+ &(elem->tdesc),\r
+ xargs,\r
+ &buf\r
+ );\r
+ if (hres) {\r
+ ERR("Failed to unmarshall param, hres %lx\n",hres);\r
+ status = hres;\r
+ break;\r
+ }\r
+ xargs += _argsize(elem->tdesc.vt);\r
}\r
- if (relaydeb) TRACE_(olerelay)(")\n");\r
- HeapFree(GetProcessHeap(),0,buf.base);\r
+after_deserialize:\r
+ hres = xbuf_get(&buf, (LPBYTE)&remoteresult, sizeof(DWORD));\r
+ if (hres != S_OK)\r
+ return hres;\r
+ if (relaydeb) TRACE_(olerelay)(") = %08lx\n", remoteresult);\r
\r
+ if (status != S_OK) /* OLE/COM internal error */\r
+ return status;\r
+\r
+ HeapFree(GetProcessHeap(),0,buf.base);\r
LeaveCriticalSection(&tpinfo->crit);\r
+ return remoteresult;\r
+}\r
+\r
+HRESULT WINAPI ProxyIUnknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)\r
+{\r
+ TMProxyImpl *proxy = (TMProxyImpl *)iface;\r
+\r
+ TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);\r
\r
- return status;\r
+ if (proxy->outerunknown)\r
+ return IUnknown_QueryInterface(proxy->outerunknown, riid, ppv);\r
+\r
+ FIXME("No interface\n");\r
+ return E_NOINTERFACE;\r
+}\r
+\r
+ULONG WINAPI ProxyIUnknown_AddRef(IUnknown *iface)\r
+{\r
+ TMProxyImpl *proxy = (TMProxyImpl *)iface;\r
+\r
+ TRACE("\n");\r
+\r
+ if (proxy->outerunknown)\r
+ return IUnknown_AddRef(proxy->outerunknown);\r
+\r
+ return 2; /* FIXME */\r
+}\r
+\r
+ULONG WINAPI ProxyIUnknown_Release(IUnknown *iface)\r
+{\r
+ TMProxyImpl *proxy = (TMProxyImpl *)iface;\r
+\r
+ TRACE("\n");\r
+\r
+ if (proxy->outerunknown)\r
+ return IUnknown_Release(proxy->outerunknown);\r
+\r
+ return 1; /* FIXME */\r
}\r
\r
static HRESULT WINAPI\r
\r
assert(sizeof(TMAsmProxy) == 12);\r
\r
+ proxy->outerunknown = pUnkOuter;\r
proxy->asmstubs = VirtualAlloc(NULL, sizeof(TMAsmProxy) * nroffuncs, MEM_COMMIT, PAGE_EXECUTE_READWRITE);\r
if (!proxy->asmstubs) {\r
ERR("Could not commit pages for proxy thunks\n");\r
\r
proxy->lpvtbl = HeapAlloc(GetProcessHeap(),0,sizeof(LPBYTE)*nroffuncs);\r
for (i=0;i<nroffuncs;i++) {\r
- int nrofargs;\r
TMAsmProxy *xasm = proxy->asmstubs+i;\r
\r
- /* nrofargs without This */\r
switch (i) {\r
- case 0: nrofargs = 2;\r
+ case 0:\r
+ proxy->lpvtbl[i] = ProxyIUnknown_QueryInterface;\r
+ break;\r
+ case 1:\r
+ proxy->lpvtbl[i] = ProxyIUnknown_AddRef;\r
break;\r
- case 1: case 2: nrofargs = 0;\r
+ case 2:\r
+ proxy->lpvtbl[i] = ProxyIUnknown_Release;\r
break;\r
default: {\r
int j;\r
+ /* nrofargs without This */\r
+ int nrofargs;\r
hres = _get_funcdesc(tinfo,i,&fdesc,NULL,NULL);\r
if (hres) {\r
ERR("GetFuncDesc %lx should not fail here.\n",hres);\r
ERR("calling convention is not stdcall????\n");\r
return E_FAIL;\r
}\r
- break;\r
- }\r
- }\r
/* popl %eax - return ptr\r
* pushl <nr>\r
* pushl %eax\r
*\r
* arg3 arg2 arg1 <method> <returnptr>\r
*/\r
- xasm->popleax = 0x58;\r
- xasm->pushlval = 0x6a;\r
- xasm->nr = i;\r
- xasm->pushleax = 0x50;\r
- xasm->lcall = 0xe8; /* relative jump */\r
- xasm->xcall = (DWORD)xCall;\r
- xasm->xcall -= (DWORD)&(xasm->lret);\r
- xasm->lret = 0xc2;\r
- xasm->bytestopop= (nrofargs+2)*4; /* pop args, This, iMethod */\r
- proxy->lpvtbl[i] = xasm;\r
+ xasm->popleax = 0x58;\r
+ xasm->pushlval = 0x6a;\r
+ xasm->nr = i;\r
+ xasm->pushleax = 0x50;\r
+ xasm->lcall = 0xe8; /* relative jump */\r
+ xasm->xcall = (DWORD)xCall;\r
+ xasm->xcall -= (DWORD)&(xasm->lret);\r
+ xasm->lret = 0xc2;\r
+ xasm->bytestopop= (nrofargs+2)*4; /* pop args, This, iMethod */\r
+ proxy->lpvtbl[i] = xasm;\r
+ break;\r
+ }\r
+ }\r
}\r
proxy->lpvtbl2 = &tmproxyvtable;\r
/* 1 reference for the proxy and 1 for the object */\r
marshal_state buf;\r
int nrofnames;\r
BSTR names[10];\r
+ BSTR fname = NULL,iname = NULL;\r
+ BOOL is_idispatch_getidsofnames = 0;\r
\r
memset(&buf,0,sizeof(buf));\r
buf.size = xmsg->cbBuffer;\r
xmsg->cbBuffer = buf.size;\r
return hres;\r
}\r
- hres = _get_funcdesc(This->tinfo,xmsg->iMethod,&fdesc,NULL,NULL);\r
+ hres = _get_funcdesc(This->tinfo,xmsg->iMethod,&fdesc,&iname,&fname);\r
if (hres) {\r
ERR("GetFuncDesc on method %ld failed with %lx\n",xmsg->iMethod,hres);\r
return hres;\r
}\r
+\r
+ if (iname && fname && !lstrcmpW(iname, IDispatchW) && !lstrcmpW(fname, GetIDsOfNamesW))\r
+ is_idispatch_getidsofnames = 1;\r
+\r
+ if (iname) SysFreeString (iname);\r
+ if (fname) SysFreeString (fname);\r
+\r
/* Need them for hack below */\r
memset(names,0,sizeof(names));\r
ITypeInfo_GetNames(This->tinfo,fdesc->memid,names,sizeof(names)/sizeof(names[0]),&nrofnames);\r
args = HeapAlloc(GetProcessHeap(),0,(nrofargs+1)*sizeof(DWORD));\r
if (!args) return E_OUTOFMEMORY;\r
\r
+ if (is_idispatch_getidsofnames) {\r
+ hres = deserialize_IDispatch_GetIDsOfNames(TRUE,FALSE,args+1,&buf);\r
+ if (hres != S_OK) {\r
+ FIXME("deserialize_IDispatch_GetIDsOfNames failed!\n");\r
+ return hres;\r
+ }\r
+ xargs = args+1+5;\r
+ goto afterdeserialize;\r
+ }\r
+\r
/* Allocate all stuff used by call. */\r
xargs = args+1;\r
for (i=0;i<fdesc->cParams;i++) {\r
if (!lstrcmpW(names[i+1],ppvObjectW)) {\r
hres = deserialize_LPVOID_ptr(\r
This->tinfo,\r
- elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT,\r
+ elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN,\r
FALSE,\r
TRUE,\r
&elem->tdesc,\r
break;\r
}\r
}\r
+afterdeserialize:\r
hres = IUnknown_QueryInterface(This->pUnk,&(This->iid),(LPVOID*)&(args[0]));\r
if (hres) {\r
- ERR("Does not support iface %s\n",debugstr_guid(&(This->iid)));\r
+ ERR("Does not support iface %s, returning %lx\n",debugstr_guid(&(This->iid)), hres);\r
return hres;\r
}\r
res = _invoke(\r
- (*((FARPROC**)args[0]))[fdesc->oVft/4],\r
- fdesc->callconv,\r
- (xargs-args),\r
- args\r
+ (*((FARPROC**)args[0]))[fdesc->oVft/4],\r
+ fdesc->callconv,\r
+ (xargs-args),\r
+ args\r
);\r
IUnknown_Release((LPUNKNOWN)args[0]);\r
buf.curoff = 0;\r
+\r
+ /* special IDispatch::GetIDsOfNames serializer */\r
+ if (is_idispatch_getidsofnames) {\r
+ hres = serialize_IDispatch_GetIDsOfNames(FALSE,FALSE,args+1,&buf);\r
+ if (hres != S_OK) {\r
+ FIXME("serialize of IDispatch::GetIDsOfNames failed!\n");\r
+ return hres;\r
+ }\r
+ goto afterserialize;\r
+ }\r
xargs = args+1;\r
for (i=0;i<fdesc->cParams;i++) {\r
ELEMDESC *elem = fdesc->lprgelemdescParam+i;\r
break;\r
}\r
}\r
+afterserialize:\r
+ hres = xbuf_add (&buf, (LPBYTE)&res, sizeof(DWORD));\r
+ if (hres != S_OK)\r
+ return hres;\r
+ \r
/* might need to use IRpcChannelBuffer_GetBuffer ? */\r
xmsg->cbBuffer = buf.curoff;\r
xmsg->Buffer = buf.base;\r
HeapFree(GetProcessHeap(),0,args);\r
- return res;\r
+ return S_OK;\r
}\r
\r
static LPRPCSTUBBUFFER WINAPI\r