PATCH: serialize / deserialize IDispatch::GetIDsOfNames
Marcus Meissner
meissner at suse.de
Sat Mar 26 06:56:59 CST 2005
Hi,
IDispatch::GetIDsOfNames() cannot be correctly serialized / deserialized
using just the typelib information since it contains variable sized
arrays.
So special case this method and add its own serializer/deserializer.
results in ishield example:
trace:olerelay:xCall ->IDispatch:GetIDsOfNames(5)(riid={00000000-0000-0000-0000-000000000000},cNames=1,rgszNames=[DefaultPalette,],lcid=0400)
trace:olerelay:xCall = 00000000 (dispid=[00000002,]))
I had to reformat a bit and this includes and replaces the earlier VT_PTR / NULL
marshalling patch since the changes overlap.
Ciao, Marcus
Changelog:
Added IDispatch::GetIDsOfNames() special case serializing.
Handle VT_PTR / NULL marshalling correctly.
Index: dlls/oleaut32/tmarshal.c
===================================================================
RCS file: /home/wine/wine/dlls/oleaut32/tmarshal.c,v
retrieving revision 1.45
diff -u -r1.45 tmarshal.c
--- dlls/oleaut32/tmarshal.c 25 Mar 2005 16:38:37 -0000 1.45
+++ dlls/oleaut32/tmarshal.c 26 Mar 2005 12:52:09 -0000
@@ -48,6 +48,8 @@
static const WCHAR riidW[5] = {'r','i','i','d',0};
static const WCHAR pdispparamsW[] = {'p','d','i','s','p','p','a','r','a','m','s',0};
static const WCHAR ppvObjectW[] = {'p','p','v','O','b','j','e','c','t',0};
+static const WCHAR IDispatchW[] = { 'I','D','i','s','p','a','t','c','h',0};
+static const WCHAR GetIDsOfNamesW[] = { 'G','e','t','I','D','s','O','f','N','a','m','e','s',0};
WINE_DEFAULT_DEBUG_CHANNEL(ole);
WINE_DECLARE_DEBUG_CHANNEL(olerelay);
@@ -583,12 +595,12 @@
DWORD cookie;
if (debugout) TRACE_(olerelay)("*");
- if (writeit) {
- cookie = *arg ? 0x42424242 : 0;
- hres = xbuf_add(buf,(LPBYTE)&cookie,sizeof(cookie));
- if (hres)
- return hres;
- }
+ /* Write always, so the other side knows when it gets a NULL pointer.
+ */
+ cookie = *arg ? 0x42424242 : 0;
+ hres = xbuf_add(buf,(LPBYTE)&cookie,sizeof(cookie));
+ if (hres)
+ return hres;
if (!*arg) {
if (debugout) TRACE_(olerelay)("NULL");
return S_OK;
@@ -687,6 +699,7 @@
if (debugout) TRACE_(olerelay)("[%ld]",adesc->rgbounds[i].cElements);
arrsize *= adesc->rgbounds[i].cElements;
}
+ if (debugout) TRACE_(olerelay)("(vt %d)",adesc->tdescElem.vt);
if (debugout) TRACE_(olerelay)("[");
for (i=0;i<arrsize;i++) {
hres = serialize_param(tinfo, writeit, debugout, dealloc, &adesc->tdescElem, (DWORD*)((LPBYTE)arg+i*_xsize(&adesc->tdescElem)), buf);
@@ -703,6 +716,168 @@
}
}
+/* IDL desc:
+ * HRESULT GetIDsOfNames(
+ * [in] REFIID riid, args[1]
+ * [in, size_is(cNames)] LPOLESTR *rgszNames, args[2]
+ * [in] UINT cNames, args[3]
+ * [in] LCID lcid, args[4]
+ * [out, size_is(cNames)] DISPID *rgDispId); args[5]
+ *
+ * line format:
+ * IID iid;
+ * DWORD cNames;
+ * LPOLESTR rgszNames[cNames];
+ * DWORD bytestrlen (incl 0)
+ * BYTE data[bytestrlen] (incl 0)
+ * LCID
+ */
+static HRESULT
+serialize_IDispatch_GetIDsOfNames(
+ BOOL inputparams,
+ BOOL debugout,
+ DWORD *args,
+ marshal_state *buf)
+{
+ HRESULT hres;
+ DWORD cNames = args[2];
+ LPOLESTR *rgszNames = (LPOLESTR*)args[1];
+ int i;
+
+ if (inputparams) {
+ if (debugout) TRACE_(olerelay)("riid=%s,",debugstr_guid((REFIID)args[0]));
+ hres = xbuf_add(buf, (LPBYTE)args[0], sizeof(IID));
+ if (hres) {
+ FIXME("serialize of IID failed.\n");
+ return hres;
+ }
+ if (debugout) TRACE_(olerelay)("cNames=%ld,",cNames);
+ hres = xbuf_add(buf, (LPBYTE)&cNames, sizeof(DWORD));
+ if (hres) {
+ FIXME("serialize of cNames failed.\n");
+ return hres;
+ }
+ if (debugout) TRACE_(olerelay)("rgszNames=[");
+ for (i=0;i<cNames;i++) {
+ DWORD len = 2*(lstrlenW(rgszNames[i])+1);
+
+ if (debugout) TRACE_(olerelay)("%s,",relaystr(rgszNames[i]));
+ hres = xbuf_add(buf, (LPBYTE)&len, sizeof(DWORD));
+ if (hres) {
+ FIXME("serialize of len failed.\n");
+ return hres;
+ }
+ hres = xbuf_add(buf, (LPBYTE)rgszNames[i], len);
+ if (hres) {
+ FIXME("serialize of rgszNames[i] failed.\n");
+ return hres;
+ }
+ }
+ if (debugout) TRACE_(olerelay)("],lcid=%04lx)",args[3]);
+ hres = xbuf_add(buf, (LPBYTE)&args[3], sizeof(DWORD));
+ if (hres) {
+ FIXME("serialize of lcid failed.\n");
+ return hres;
+ }
+ } else {
+ DISPID *rgDispId = (DISPID*)args[4];
+
+ hres = xbuf_add(buf, (LPBYTE)rgDispId, sizeof(DISPID) * cNames);
+ if (hres) {
+ FIXME("serialize of rgDispId failed.\n");
+ return hres;
+ }
+ if (debugout) {
+ TRACE_(olerelay)("riid=[in],rgszNames=[in],cNames=[in],rgDispId=[");
+ for (i=0;i<cNames;i++)
+ TRACE_(olerelay)("%08lx,",rgDispId[i]);
+ TRACE_(olerelay)("])");
+ }
+ HeapFree(GetProcessHeap(),0,(IID*)args[0]);
+ rgszNames = (LPOLESTR*)args[1];
+ for (i=0;i<cNames;i++) HeapFree(GetProcessHeap(),0,rgszNames[i]);
+ HeapFree(GetProcessHeap(),0,rgszNames);
+ HeapFree(GetProcessHeap(),0,rgDispId);
+ }
+ return S_OK;
+}
+
+static HRESULT
+deserialize_IDispatch_GetIDsOfNames(
+ BOOL inputparams,
+ BOOL debugout,
+ DWORD *args,
+ marshal_state *buf)
+{
+ HRESULT hres;
+ DWORD cNames;
+ LPOLESTR *rgszNames;
+ int i;
+
+ if (inputparams) {
+ args[0] = (DWORD)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IID));
+ if (!args[0]) return E_FAIL;
+ hres = xbuf_get(buf, (LPBYTE)args[0], sizeof(IID));
+ if (hres) {
+ FIXME("deserialize of IID failed.\n");
+ return hres;
+ }
+ if (debugout) TRACE_(olerelay)("riid=%s,",debugstr_guid((REFIID)args[0]));
+
+ hres = xbuf_get(buf, (LPBYTE)&cNames, sizeof(DWORD));
+ if (hres) {
+ FIXME("deserialize of cNames failed.\n");
+ return hres;
+ }
+ args[2] = cNames;
+ if (debugout) TRACE_(olerelay)("cNames=%ld,",cNames);
+ if (debugout) TRACE_(olerelay)("rgszNames=[");
+ rgszNames = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(LPOLESTR) * cNames);
+ if (!rgszNames) return E_FAIL;
+ args[1] = (DWORD)rgszNames;
+ for (i=0;i<cNames;i++) {
+ DWORD len;
+
+ hres = xbuf_get(buf, (LPBYTE)&len, sizeof(DWORD));
+ if (hres) {
+ FIXME("serialize of len failed.\n");
+ return hres;
+ }
+ rgszNames[i] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
+ if (!rgszNames[i]) {
+ FIXME("heapalloc of %ld bytes failed\n", len);
+ return E_FAIL;
+ }
+ hres = xbuf_get(buf, (LPBYTE)rgszNames[i], len);
+ if (hres) {
+ FIXME("serialize of rgszNames[i] failed.\n");
+ return hres;
+ }
+ if (debugout) TRACE_(olerelay)("%s,",relaystr(rgszNames[i]));
+ }
+ hres = xbuf_get(buf, (LPBYTE)&args[3], sizeof(DWORD));
+ if (hres) {
+ FIXME("deserialize of lcid failed.\n");
+ return hres;
+ }
+ if (debugout) TRACE_(olerelay)("],lcid=%04lx,rgDispId=[out])",args[3]);
+ args[4] = (DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DISPID) * cNames);
+ } else {
+ hres = xbuf_get(buf, (LPBYTE)args[4], sizeof(DISPID) * args[2]);
+ if (hres) {
+ FIXME("serialize of rgDispId failed.\n");
+ return hres;
+ }
+ if (debugout) {
+ TRACE_(olerelay)("dispid=[");
+ for (i=0;i<args[2];i++)
+ TRACE_(olerelay)("%08lx,",((DISPID*)args[4])[i]);
+ TRACE_(olerelay)("])");
+ }
+ }
+ return S_OK;
+}
+
static HRESULT
serialize_LPVOID_ptr(
ITypeInfo *tinfo,
@@ -953,24 +1146,26 @@
}
case VT_PTR: {
DWORD cookie;
- BOOL derefhere = 0;
+ BOOL derefhere = 0;
derefhere = (tdesc->u.lptdesc->vt != VT_USERDEFINED);
-
- if (readit) {
- hres = xbuf_get(buf,(LPBYTE)&cookie,sizeof(cookie));
- if (hres) {
- ERR("Failed to load pointer cookie.\n");
- return hres;
- }
- if (cookie != 0x42424242) {
- if (debugout) TRACE_(olerelay)("NULL");
- *arg = 0;
- return S_OK;
- }
- if (debugout) TRACE_(olerelay)("*");
+ /* read it in all cases, we need to know if we have
+ * NULL pointer or not.
+ */
+ hres = xbuf_get(buf,(LPBYTE)&cookie,sizeof(cookie));
+ if (hres) {
+ ERR("Failed to load pointer cookie.\n");
+ return hres;
+ }
+ if (cookie != 0x42424242) {
+ /* we read a NULL ptr from the remote side */
+ if (debugout) TRACE_(olerelay)("NULL");
+ *arg = 0;
+ return S_OK;
}
+ if (debugout) TRACE_(olerelay)("*");
if (alloc) {
+ /* Allocate space for the referenced struct */
if (derefhere)
*arg=(DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,_xsize(tdesc->u.lptdesc));
}
@@ -1121,8 +1316,10 @@
}
if (readit) {
hres = _unmarshal_interface(buf,&buf->iid,(LPUNKNOWN*)*arg);
- if (hres)
+ if (hres) {
+ FIXME("_unmarshal_interface of %s , %p failed with %lx\n", debugstr_guid(&buf->iid), (LPUNKNOWN*)*arg, hres);
return hres;
+ }
}
if (debugout) TRACE_(olerelay)("ppv(%p)",(LPVOID)*arg);
return S_OK;
@@ -1274,6 +1471,7 @@
BSTR fname,iname;
BSTR names[10];
int nrofnames;
+ int is_idispatch_getidsofnames = 0;
EnterCriticalSection(&tpinfo->crit);
@@ -1300,9 +1498,35 @@
else
TRACE_(olerelay)("%d",method);
TRACE_(olerelay)("(");
- if (iname) SysFreeString(iname);
- if (fname) SysFreeString(fname);
}
+ if (iname && fname && !lstrcmpW(iname,IDispatchW) && !lstrcmpW(fname,GetIDsOfNamesW))
+ is_idispatch_getidsofnames = 1;
+
+ if (iname) SysFreeString(iname);
+ if (fname) SysFreeString(fname);
+
+ memset(&buf,0,sizeof(buf));
+ buf.iid = IID_IUnknown;
+
+ /* Special IDispatch::GetIDsOfNames() serializer */
+ if (is_idispatch_getidsofnames) {
+ hres = serialize_IDispatch_GetIDsOfNames(TRUE,relaydeb,args,&buf);
+ if (hres != S_OK) {
+ FIXME("serialize of IDispatch::GetIDsOfNames failed!\n");
+ return hres;
+ }
+ goto afterserialize;
+ }
+
+ /* special QueryInterface serialize */
+ if (method == 0) {
+ xbuf_add(&buf,(LPBYTE)args[0],sizeof(IID));
+ if (relaydeb) TRACE_(olerelay)("riid=%s,[out])",debugstr_guid((REFIID)args[0]));
+ goto afterserialize;
+ }
+
+ /* normal typelib driven serializing */
+
/* Need them for hack below */
memset(names,0,sizeof(names));
if (ITypeInfo_GetNames(tpinfo->tinfo,fdesc->memid,names,sizeof(names)/sizeof(names[0]),&nrofnames))
@@ -1310,62 +1534,42 @@
if (nrofnames > sizeof(names)/sizeof(names[0]))
ERR("Need more names!\n");
- memset(&buf,0,sizeof(buf));
- buf.iid = IID_IUnknown;
- if (method == 0) {
- xbuf_add(&buf,(LPBYTE)args[0],sizeof(IID));
- if (relaydeb) TRACE_(olerelay)("riid=%s,[out]",debugstr_guid((REFIID)args[0]));
- } else {
- xargs = args;
- for (i=0;i<fdesc->cParams;i++) {
- ELEMDESC *elem = fdesc->lprgelemdescParam+i;
- BOOL isserialized = FALSE;
- if (relaydeb) {
- if (i) TRACE_(olerelay)(",");
- if (i+1<nrofnames && names[i+1])
- TRACE_(olerelay)("%s=",relaystr(names[i+1]));
- }
- /* No need to marshal other data than FIN */
- if (!(elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN)) {
- xargs+=_argsize(elem->tdesc.vt);
- if (relaydeb) TRACE_(olerelay)("[out]");
- continue;
- }
- if (((i+1)<nrofnames) && !IsBadStringPtrW(names[i+1],1)) {
- /* If the parameter is 'riid', we use it as interface IID
- * for a later ppvObject serialization.
- */
- buf.thisisiid = !lstrcmpW(names[i+1],riidW);
-
- /* DISPPARAMS* needs special serializer */
- if (!lstrcmpW(names[i+1],pdispparamsW)) {
- hres = serialize_DISPPARAM_ptr(
- tpinfo->tinfo,
- elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN,
- relaydeb,
- FALSE,
- &elem->tdesc,
- xargs,
- &buf
- );
- isserialized = TRUE;
- }
- if (!lstrcmpW(names[i+1],ppvObjectW)) {
- hres = serialize_LPVOID_ptr(
- tpinfo->tinfo,
- elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN,
- relaydeb,
- FALSE,
- &elem->tdesc,
- xargs,
- &buf
- );
- if (hres == S_OK)
- isserialized = TRUE;
- }
+ xargs = args;
+ for (i=0;i<fdesc->cParams;i++) {
+ ELEMDESC *elem = fdesc->lprgelemdescParam+i;
+ BOOL isserialized = FALSE;
+ if (relaydeb) {
+ if (i) TRACE_(olerelay)(",");
+ if (i+1<nrofnames && names[i+1])
+ TRACE_(olerelay)("%s=",relaystr(names[i+1]));
+ }
+ /* No need to marshal other data than FIN and any VT_PTR. */
+ if (!(elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN) && (elem->tdesc.vt != VT_PTR)) {
+ xargs+=_argsize(elem->tdesc.vt);
+ if (relaydeb) TRACE_(olerelay)("[out]");
+ continue;
+ }
+ if (((i+1)<nrofnames) && !IsBadStringPtrW(names[i+1],1)) {
+ /* If the parameter is 'riid', we use it as interface IID
+ * for a later ppvObject serialization.
+ */
+ buf.thisisiid = !lstrcmpW(names[i+1],riidW);
+
+ /* DISPPARAMS* needs special serializer */
+ if (!lstrcmpW(names[i+1],pdispparamsW)) {
+ hres = serialize_DISPPARAM_ptr(
+ tpinfo->tinfo,
+ elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN,
+ relaydeb,
+ FALSE,
+ &elem->tdesc,
+ xargs,
+ &buf
+ );
+ isserialized = TRUE;
}
- if (!isserialized)
- hres = serialize_param(
+ if (!lstrcmpW(names[i+1],ppvObjectW)) {
+ hres = serialize_LPVOID_ptr(
tpinfo->tinfo,
elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN,
relaydeb,
@@ -1374,15 +1578,30 @@
xargs,
&buf
);
-
- if (hres) {
- ERR("Failed to serialize param, hres %lx\n",hres);
- break;
+ if (hres == S_OK)
+ isserialized = TRUE;
}
- xargs+=_argsize(elem->tdesc.vt);
}
+ if (!isserialized)
+ hres = serialize_param(
+ tpinfo->tinfo,
+ elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN,
+ relaydeb,
+ FALSE,
+ &elem->tdesc,
+ xargs,
+ &buf
+ );
+
+ if (hres) {
+ ERR("Failed to serialize param, hres %lx\n",hres);
+ break;
+ }
+ xargs+=_argsize(elem->tdesc.vt);
}
if (relaydeb) TRACE_(olerelay)(")");
+
+afterserialize:
memset(&msg,0,sizeof(msg));
msg.cbBuffer = buf.curoff;
msg.iMethod = method;
@@ -1409,80 +1628,94 @@
buf.size = msg.cbBuffer;
memcpy(buf.base,msg.Buffer,buf.size);
buf.curoff = 0;
+
+ /* Special IDispatch::GetIDsOfNames() deserializer */
+ if (is_idispatch_getidsofnames) {
+ hres = deserialize_IDispatch_GetIDsOfNames(FALSE,relaydeb,args,&buf);
+ if (hres != S_OK) {
+ FIXME("deserialize of IDispatch::GetIDsOfNames failed!\n");
+ return hres;
+ }
+ goto after_deserialize;
+ }
+ /* Special QueryInterface deserializer */
if (method == 0) {
_unmarshal_interface(&buf,(REFIID)args[0],(LPUNKNOWN*)args[1]);
if (relaydeb) TRACE_(olerelay)("[in],%p",*((DWORD**)args[1]));
- } else {
- xargs = args;
- for (i=0;i<fdesc->cParams;i++) {
- ELEMDESC *elem = fdesc->lprgelemdescParam+i;
- BOOL isdeserialized = FALSE;
-
- if (relaydeb) {
- if (i) TRACE_(olerelay)(",");
- if (i+1<nrofnames && names[i+1]) TRACE_(olerelay)("%s=",relaystr(names[i+1]));
- }
- /* No need to marshal other data than FOUT I think */
- if (!(elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT)) {
- xargs += _argsize(elem->tdesc.vt);
- if (relaydeb) TRACE_(olerelay)("[in]");
- continue;
- }
- if (((i+1)<nrofnames) && !IsBadStringPtrW(names[i+1],1)) {
- /* If the parameter is 'riid', we use it as interface IID
- * for a later ppvObject serialization.
- */
- buf.thisisiid = !lstrcmpW(names[i+1],riidW);
-
- /* deserialize DISPPARAM */
- if (!lstrcmpW(names[i+1],pdispparamsW)) {
- hres = deserialize_DISPPARAM_ptr(
- tpinfo->tinfo,
- elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT,
- relaydeb,
- FALSE,
- &(elem->tdesc),
- xargs,
- &buf
- );
- if (hres) {
- ERR("Failed to deserialize DISPPARAM*, hres %lx\n",hres);
- break;
- }
- isdeserialized = TRUE;
- }
- if (!lstrcmpW(names[i+1],ppvObjectW)) {
- hres = deserialize_LPVOID_ptr(
- tpinfo->tinfo,
- elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT,
- relaydeb,
- FALSE,
- &elem->tdesc,
- xargs,
- &buf
- );
- if (hres == S_OK)
- isdeserialized = TRUE;
+ goto after_deserialize;
+ }
+
+ /* generic deserializer using typelib description */
+ xargs = args;
+ for (i=0;i<fdesc->cParams;i++) {
+ ELEMDESC *elem = fdesc->lprgelemdescParam+i;
+ BOOL isdeserialized = FALSE;
+
+ if (relaydeb) {
+ if (i) TRACE_(olerelay)(",");
+ if (i+1<nrofnames && names[i+1]) TRACE_(olerelay)("%s=",relaystr(names[i+1]));
+ }
+ /* No need to marshal other data than FOUT and any VT_PTR */
+ if (!(elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT) && (elem->tdesc.vt != VT_PTR)) {
+ xargs += _argsize(elem->tdesc.vt);
+ if (relaydeb) TRACE_(olerelay)("[in]");
+ continue;
+ }
+ if (((i+1)<nrofnames) && !IsBadStringPtrW(names[i+1],1)) {
+ /* If the parameter is 'riid', we use it as interface IID
+ * for a later ppvObject serialization.
+ */
+ buf.thisisiid = !lstrcmpW(names[i+1],riidW);
+
+ /* deserialize DISPPARAM */
+ if (!lstrcmpW(names[i+1],pdispparamsW)) {
+ hres = deserialize_DISPPARAM_ptr(
+ tpinfo->tinfo,
+ elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT,
+ relaydeb,
+ FALSE,
+ &(elem->tdesc),
+ xargs,
+ &buf
+ );
+ if (hres) {
+ ERR("Failed to deserialize DISPPARAM*, hres %lx\n",hres);
+ break;
}
+ isdeserialized = TRUE;
}
- if (!isdeserialized)
- hres = deserialize_param(
+ if (!lstrcmpW(names[i+1],ppvObjectW)) {
+ hres = deserialize_LPVOID_ptr(
tpinfo->tinfo,
elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT,
relaydeb,
FALSE,
- &(elem->tdesc),
+ &elem->tdesc,
xargs,
&buf
);
- if (hres) {
- ERR("Failed to unmarshall param, hres %lx\n",hres);
- status = hres;
- break;
+ if (hres == S_OK)
+ isdeserialized = TRUE;
}
- xargs += _argsize(elem->tdesc.vt);
}
+ if (!isdeserialized)
+ hres = deserialize_param(
+ tpinfo->tinfo,
+ elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT,
+ relaydeb,
+ FALSE,
+ &(elem->tdesc),
+ xargs,
+ &buf
+ );
+ if (hres) {
+ ERR("Failed to unmarshall param, hres %lx\n",hres);
+ status = hres;
+ break;
+ }
+ xargs += _argsize(elem->tdesc.vt);
}
+after_deserialize:
if (relaydeb) TRACE_(olerelay)(")\n");
HeapFree(GetProcessHeap(),0,buf.base);
@@ -1711,6 +1944,8 @@
marshal_state buf;
int nrofnames;
BSTR names[10];
+ BSTR fname = NULL,iname = NULL;
+ BOOL is_idispatch_getidsofnames = 0;
memset(&buf,0,sizeof(buf));
buf.size = xmsg->cbBuffer;
@@ -1730,11 +1965,18 @@
xmsg->cbBuffer = buf.size;
return hres;
}
- hres = _get_funcdesc(This->tinfo,xmsg->iMethod,&fdesc,NULL,NULL);
+ hres = _get_funcdesc(This->tinfo,xmsg->iMethod,&fdesc,&iname,&fname);
if (hres) {
ERR("GetFuncDesc on method %ld failed with %lx\n",xmsg->iMethod,hres);
return hres;
}
+
+ if (iname && fname && !lstrcmpW(iname, IDispatchW) && !lstrcmpW(fname, GetIDsOfNamesW))
+ is_idispatch_getidsofnames = 1;
+
+ if (iname) SysFreeString (iname);
+ if (fname) SysFreeString (fname);
+
/* Need them for hack below */
memset(names,0,sizeof(names));
ITypeInfo_GetNames(This->tinfo,fdesc->memid,names,sizeof(names)/sizeof(names[0]),&nrofnames);
@@ -1749,6 +1991,16 @@
args = HeapAlloc(GetProcessHeap(),0,(nrofargs+1)*sizeof(DWORD));
if (!args) return E_OUTOFMEMORY;
+ if (is_idispatch_getidsofnames) {
+ hres = deserialize_IDispatch_GetIDsOfNames(TRUE,FALSE,args+1,&buf);
+ if (hres != S_OK) {
+ FIXME("deserialize_IDispatch_GetIDsOfNames failed!\n");
+ return hres;
+ }
+ xargs = args+1+5;
+ goto afterdeserialize;
+ }
+
/* Allocate all stuff used by call. */
xargs = args+1;
for (i=0;i<fdesc->cParams;i++) {
@@ -1808,19 +2060,30 @@
break;
}
}
+afterdeserialize:
hres = IUnknown_QueryInterface(This->pUnk,&(This->iid),(LPVOID*)&(args[0]));
if (hres) {
- ERR("Does not support iface %s\n",debugstr_guid(&(This->iid)));
+ ERR("Does not support iface %s, returning %lx\n",debugstr_guid(&(This->iid)), hres);
return hres;
}
res = _invoke(
- (*((FARPROC**)args[0]))[fdesc->oVft/4],
- fdesc->callconv,
- (xargs-args),
- args
+ (*((FARPROC**)args[0]))[fdesc->oVft/4],
+ fdesc->callconv,
+ (xargs-args),
+ args
);
IUnknown_Release((LPUNKNOWN)args[0]);
buf.curoff = 0;
+
+ /* special IDispatch::GetIDsOfNames serializer */
+ if (is_idispatch_getidsofnames) {
+ hres = serialize_IDispatch_GetIDsOfNames(FALSE,FALSE,args+1,&buf);
+ if (hres != S_OK) {
+ FIXME("serialize of IDispatch::GetIDsOfNames failed!\n");
+ return hres;
+ }
+ goto afterserialize;
+ }
xargs = args+1;
for (i=0;i<fdesc->cParams;i++) {
ELEMDESC *elem = fdesc->lprgelemdescParam+i;
@@ -1875,6 +2138,7 @@
break;
}
}
+afterserialize:
/* might need to use IRpcChannelBuffer_GetBuffer ? */
xmsg->cbBuffer = buf.curoff;
xmsg->Buffer = buf.base;
More information about the wine-patches
mailing list