📄 tmarshal.c
字号:
for (i=0;i<adesc->cDims;i++)
arrsize *= adesc->rgbounds[i].cElements;
return arrsize*_xsize(&adesc->tdescElem);
}
case VT_UI8:
case VT_I8:
return 8;
case VT_UI2:
case VT_I2:
return 2;
case VT_UI1:
case VT_I1:
return 1;
default:
return 4;
}
}
static HRESULT
serialize_param(
ITypeInfo *tinfo,
BOOL writeit,
BOOL debugout,
BOOL dealloc,
TYPEDESC *tdesc,
DWORD *arg,
marshal_state *buf)
{
HRESULT hres = S_OK;
TRACE("(tdesc.vt %s)\n",debugstr_vt(tdesc->vt));
switch (tdesc->vt) {
case VT_EMPTY: /* nothing. empty variant for instance */
return S_OK;
case VT_I8:
case VT_UI8:
case VT_CY:
hres = S_OK;
if (debugout) TRACE_(olerelay)("%lx%lx",arg[0],arg[1]);
if (writeit)
hres = xbuf_add(buf,(LPBYTE)arg,8);
return hres;
case VT_BOOL:
case VT_ERROR:
case VT_INT:
case VT_UINT:
case VT_I4:
case VT_R4:
case VT_UI4:
hres = S_OK;
if (debugout) TRACE_(olerelay)("%lx",*arg);
if (writeit)
hres = xbuf_add(buf,(LPBYTE)arg,sizeof(DWORD));
return hres;
case VT_I2:
case VT_UI2:
hres = S_OK;
if (debugout) TRACE_(olerelay)("%04lx",*arg & 0xffff);
if (writeit)
hres = xbuf_add(buf,(LPBYTE)arg,sizeof(DWORD));
return hres;
case VT_I1:
case VT_UI1:
hres = S_OK;
if (debugout) TRACE_(olerelay)("%02lx",*arg & 0xff);
if (writeit)
hres = xbuf_add(buf,(LPBYTE)arg,sizeof(DWORD));
return hres;
case VT_I4|VT_BYREF:
hres = S_OK;
if (debugout) TRACE_(olerelay)("&0x%lx",*arg);
if (writeit)
hres = xbuf_add(buf,(LPBYTE)(DWORD*)*arg,sizeof(DWORD));
/* do not dealloc at this time */
return hres;
case VT_VARIANT: {
TYPEDESC tdesc2;
VARIANT *vt = (VARIANT*)arg;
DWORD vttype = V_VT(vt);
if (debugout) TRACE_(olerelay)("Vt(%s%s)(",debugstr_vt(vttype),debugstr_vf(vttype));
tdesc2.vt = vttype;
if (writeit) {
hres = xbuf_add(buf,(LPBYTE)&vttype,sizeof(vttype));
if (hres) return hres;
}
/* need to recurse since we need to free the stuff */
hres = serialize_param(tinfo,writeit,debugout,dealloc,&tdesc2,(DWORD*)&(V_I4(vt)),buf);
if (debugout) TRACE_(olerelay)(")");
return hres;
}
case VT_BSTR|VT_BYREF: {
if (debugout) TRACE_(olerelay)("[byref]'%s'", *(BSTR*)*arg ? relaystr(*((BSTR*)*arg)) : "<bstr NULL>");
if (writeit) {
/* ptr to ptr to magic widestring, basically */
BSTR *bstr = (BSTR *) *arg;
DWORD len;
if (!*bstr) {
/* -1 means "null string" which is equivalent to empty string */
len = -1;
hres = xbuf_add(buf, (LPBYTE)&len,sizeof(DWORD));
if (hres) return hres;
} else {
len = *((DWORD*)*bstr-1)/sizeof(WCHAR);
hres = xbuf_add(buf,(LPBYTE)&len,sizeof(DWORD));
if (hres) return hres;
hres = xbuf_add(buf,(LPBYTE)*bstr,len * sizeof(WCHAR));
if (hres) return hres;
}
}
if (dealloc && arg) {
BSTR *str = *((BSTR **)arg);
SysFreeString(*str);
}
return S_OK;
}
case VT_BSTR: {
if (debugout) {
if (*arg)
TRACE_(olerelay)("%s",relaystr((WCHAR*)*arg));
else
TRACE_(olerelay)("<bstr NULL>");
}
if (writeit) {
BSTR bstr = (BSTR)*arg;
DWORD len;
if (!bstr) {
len = -1;
hres = xbuf_add(buf,(LPBYTE)&len,sizeof(DWORD));
if (hres) return hres;
} else {
len = *((DWORD*)bstr-1)/sizeof(WCHAR);
hres = xbuf_add(buf,(LPBYTE)&len,sizeof(DWORD));
if (hres) return hres;
hres = xbuf_add(buf,(LPBYTE)bstr,len * sizeof(WCHAR));
if (hres) return hres;
}
}
if (dealloc && arg)
SysFreeString((BSTR)*arg);
return S_OK;
}
case VT_PTR: {
DWORD cookie;
BOOL derefhere = TRUE;
if (tdesc->u.lptdesc->vt == VT_USERDEFINED) {
ITypeInfo *tinfo2;
TYPEATTR *tattr;
hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.lptdesc->u.hreftype,&tinfo2);
if (hres) {
ERR("Could not get typeinfo of hreftype %lx for VT_USERDEFINED.\n",tdesc->u.lptdesc->u.hreftype);
return hres;
}
ITypeInfo_GetTypeAttr(tinfo2,&tattr);
switch (tattr->typekind) {
case TKIND_ENUM: /* confirmed */
case TKIND_RECORD: /* FIXME: mostly untested */
derefhere=TRUE;
break;
case TKIND_ALIAS: /* FIXME: untested */
case TKIND_DISPATCH: /* will be done in VT_USERDEFINED case */
case TKIND_INTERFACE: /* will be done in VT_USERDEFINED case */
derefhere=FALSE;
break;
default:
FIXME("unhandled switch cases tattr->typekind %d\n", tattr->typekind);
derefhere=FALSE;
break;
}
ITypeInfo_Release(tinfo2);
}
if (debugout) TRACE_(olerelay)("*");
/* 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;
}
hres = serialize_param(tinfo,writeit,debugout,dealloc,tdesc->u.lptdesc,(DWORD*)*arg,buf);
if (derefhere && dealloc) HeapFree(GetProcessHeap(),0,(LPVOID)*arg);
return hres;
}
case VT_UNKNOWN:
if (debugout) TRACE_(olerelay)("unk(0x%lx)",*arg);
if (writeit)
hres = _marshal_interface(buf,&IID_IUnknown,(LPUNKNOWN)*arg);
if (dealloc && *(IUnknown **)arg)
IUnknown_Release((LPUNKNOWN)*arg);
return hres;
case VT_DISPATCH:
if (debugout) TRACE_(olerelay)("idisp(0x%lx)",*arg);
if (writeit)
hres = _marshal_interface(buf,&IID_IDispatch,(LPUNKNOWN)*arg);
if (dealloc && *(IUnknown **)arg)
IUnknown_Release((LPUNKNOWN)*arg);
return hres;
case VT_VOID:
if (debugout) TRACE_(olerelay)("<void>");
return S_OK;
case VT_USERDEFINED: {
ITypeInfo *tinfo2;
TYPEATTR *tattr;
hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);
if (hres) {
ERR("Could not get typeinfo of hreftype %lx for VT_USERDEFINED.\n",tdesc->u.hreftype);
return hres;
}
ITypeInfo_GetTypeAttr(tinfo2,&tattr);
switch (tattr->typekind) {
case TKIND_DISPATCH:
case TKIND_INTERFACE:
if (writeit)
hres=_marshal_interface(buf,&(tattr->guid),(LPUNKNOWN)arg);
if (dealloc)
IUnknown_Release((LPUNKNOWN)arg);
break;
case TKIND_RECORD: {
int i;
if (debugout) TRACE_(olerelay)("{");
for (i=0;i<tattr->cVars;i++) {
VARDESC *vdesc;
ELEMDESC *elem2;
TYPEDESC *tdesc2;
hres = ITypeInfo2_GetVarDesc(tinfo2, i, &vdesc);
if (hres) {
ERR("Could not get vardesc of %d\n",i);
return hres;
}
/* Need them for hack below */
/*
memset(names,0,sizeof(names));
hres = ITypeInfo_GetNames(tinfo2,vdesc->memid,names,sizeof(names)/sizeof(names[0]),&nrofnames);
if (nrofnames > sizeof(names)/sizeof(names[0])) {
ERR("Need more names!\n");
}
if (!hres && debugout)
TRACE_(olerelay)("%s=",relaystr(names[0]));
*/
elem2 = &vdesc->elemdescVar;
tdesc2 = &elem2->tdesc;
hres = serialize_param(
tinfo2,
writeit,
debugout,
dealloc,
tdesc2,
(DWORD*)(((LPBYTE)arg)+vdesc->u.oInst),
buf
);
ITypeInfo_ReleaseVarDesc(tinfo2, vdesc);
if (hres!=S_OK)
return hres;
if (debugout && (i<(tattr->cVars-1)))
TRACE_(olerelay)(",");
}
if (debugout) TRACE_(olerelay)("}");
break;
}
case TKIND_ALIAS:
return serialize_param(tinfo2,writeit,debugout,dealloc,&tattr->tdescAlias,arg,buf);
case TKIND_ENUM:
hres = S_OK;
if (debugout) TRACE_(olerelay)("%lx",*arg);
if (writeit)
hres = xbuf_add(buf,(LPBYTE)arg,sizeof(DWORD));
return hres;
default:
FIXME("Unhandled typekind %d\n",tattr->typekind);
hres = E_FAIL;
break;
}
ITypeInfo_Release(tinfo2);
return hres;
}
case VT_CARRAY: {
ARRAYDESC *adesc = tdesc->u.lpadesc;
int i, arrsize = 1;
if (debugout) TRACE_(olerelay)("carr");
for (i=0;i<adesc->cDims;i++) {
if (debugout) TRACE_(olerelay)("[%ld]",adesc->rgbounds[i].cElements);
arrsize *= adesc->rgbounds[i].cElements;
}
if (debugout) TRACE_(olerelay)("(vt %s)",debugstr_vt(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);
if (hres)
return hres;
if (debugout && (i<arrsize-1)) TRACE_(olerelay)(",");
}
if (debugout) TRACE_(olerelay)("]");
return S_OK;
}
default:
ERR("Unhandled marshal type %d.\n",tdesc->vt);
return S_OK;
}
}
static HRESULT
deserialize_param(
ITypeInfo *tinfo,
BOOL readit,
BOOL debugout,
BOOL alloc,
TYPEDESC *tdesc,
DWORD *arg,
marshal_state *buf)
{
HRESULT hres = S_OK;
TRACE("vt %s at %p\n",debugstr_vt(tdesc->vt),arg);
while (1) {
switch (tdesc->vt) {
case VT_EMPTY:
if (debugout) TRACE_(olerelay)("<empty>");
return S_OK;
case VT_NULL:
if (debugout) TRACE_(olerelay)("<null>");
return S_OK;
case VT_VARIANT: {
VARIANT *vt = (VARIANT*)arg;
if (readit) {
DWORD vttype;
TYPEDESC tdesc2;
hres = xbuf_get(buf,(LPBYTE)&vttype,sizeof(vttype));
if (hres) {
FIXME("vt type not read?\n");
return hres;
}
memset(&tdesc2,0,sizeof(tdesc2));
tdesc2.vt = vttype;
V_VT(vt) = vttype;
if (debugout) TRACE_(olerelay)("Vt(%s%s)(",debugstr_vt(vttype),debugstr_vf(vttype));
hres = deserialize_param(tinfo, readit, debugout, alloc, &tdesc2, (DWORD*)&(V_I4(vt)), buf);
TRACE_(olerelay)(")");
return hres;
} else {
VariantInit(vt);
return S_OK;
}
}
case VT_I8:
case VT_UI8:
case VT_CY:
if (readit) {
hres = xbuf_get(buf,(LPBYTE)arg,8);
if (hres) ERR("Failed to read integer 8 byte\n");
}
if (debugout) TRACE_(olerelay)("%lx%lx",arg[0],arg[1]);
return hres;
case VT_ERROR:
case VT_BOOL:
case VT_I4:
case VT_INT:
case VT_UINT:
case VT_R4:
case VT_UI4:
if (readit) {
hres = xbuf_get(buf,(LPBYTE)arg,sizeof(DWORD));
if (hres) ERR("Failed to read integer 4 byte\n");
}
if (debugout) TRACE_(olerelay)("%lx",*arg);
return hres;
case VT_I2:
case VT_UI2:
if (readit) {
DWORD x;
hres = xbuf_get(buf,(LPBYTE)&x,sizeof(DWORD));
if (hres) ERR("Failed to read integer 4 byte\n");
memcpy(arg,&x,2);
}
if (debugout) TRACE_(olerelay)("%04lx",*arg & 0xffff);
return hres;
case VT_I1:
case VT_UI1:
if (readit) {
DWORD x;
hres = xbuf_get(buf,(LPBYTE)&x,sizeof(DWORD));
if (hres) ERR("Failed to read integer 4 byte\n");
memcpy(arg,&x,1);
}
if (debugout) TRACE_(olerelay)("%02lx",*arg & 0xff);
return hres;
case VT_I4|VT_BYREF:
hres = S_OK;
if (alloc)
*arg = (DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DWORD));
if (readit) {
hres = xbuf_get(buf,(LPBYTE)*arg,sizeof(DWORD));
if (hres) ERR("Failed to read integer 4 byte\n");
}
if (debugout) TRACE_(olerelay)("&0x%lx",*(DWORD*)*arg);
return hres;
case VT_BSTR|VT_BYREF: {
BSTR **bstr = (BSTR **)arg;
WCHAR *str;
DWORD len;
if (readit) {
hres = xbuf_get(buf,(LPBYTE)&len,sizeof(DWORD));
if (hres) {
ERR("failed to read bstr klen\n");
return hres;
}
if (len == -1) {
*bstr = CoTaskMemAlloc(sizeof(BSTR *));
**bstr = NULL;
if (debugout) TRACE_(olerelay)("<bstr NULL>");
} else {
str = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,(len+1)*sizeof(WCHAR));
hres = xbuf_get(buf,(LPBYTE)str,len*sizeof(WCHAR));
if (hres) {
ERR("Failed to read BSTR.\n");
return hres;
}
*bstr = CoTaskMemAlloc(sizeof(BSTR *));
**bstr = SysAllocStringLen(str,len);
if (debugout) TRACE_(olerelay)("%s",relaystr(str));
HeapFree(GetProcessHeap(),0,str);
}
} else {
*bstr = NULL;
}
return S_OK;
}
case VT_BSTR: {
WCHAR *str;
DWORD len;
if (readit) {
hres = xbuf_get(buf,(LPBYTE)&len,sizeof(DWORD));
if (hres) {
ERR("failed to read bstr klen\n");
return hres;
}
if (len == -1) {
*arg = 0;
if (debugout) TRACE_(olerelay)("<bstr NULL>");
} else {
str = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,(len+1)*sizeof(WCHAR));
hres = xbuf_get(buf,(LPBYTE)str,len*sizeof(WCHAR));
if (hres) {
ERR("Failed to read BSTR.\n");
return hres;
}
*arg = (DWORD)SysAllocStringLen(str,len);
if (debugout) TRACE_(olerelay)("%s",relaystr(str));
HeapFree(GetProcessHeap(),0,str);
}
} else {
*arg = 0;
}
return S_OK;
}
case VT_PTR: {
DWORD cookie;
BOOL derefhere = TRUE;
if (tdesc->u.lptdesc->vt == VT_USERDEFINED) {
ITypeInfo *tinfo2;
TYPEATTR *tattr;
hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.lptdesc->u.hreftype,&tinfo2);
if (hres) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -