Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/rpcrt4/ndr_typelib.c | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-)
diff --git a/dlls/rpcrt4/ndr_typelib.c b/dlls/rpcrt4/ndr_typelib.c index 8a08ad9918..d8c429ba11 100644 --- a/dlls/rpcrt4/ndr_typelib.c +++ b/dlls/rpcrt4/ndr_typelib.c @@ -106,9 +106,13 @@ static unsigned short write_oleaut_tfs(VARTYPE vt) return 0; }
-static unsigned char get_base_type(VARTYPE vt) +static unsigned char get_basetype(ITypeInfo *typeinfo, TYPEDESC *desc) { - switch (vt) + ITypeInfo *refinfo; + unsigned char ret; + TYPEATTR *attr; + + switch (desc->vt) { case VT_I1: return FC_SMALL; case VT_BOOL: @@ -126,6 +130,18 @@ static unsigned char get_base_type(VARTYPE vt) case VT_R4: return FC_FLOAT; case VT_DATE: case VT_R8: return FC_DOUBLE; + case VT_USERDEFINED: + ITypeInfo_GetRefTypeInfo(typeinfo, desc->hreftype, &refinfo); + ITypeInfo_GetTypeAttr(refinfo, &attr); + if (attr->typekind == TKIND_ENUM) + ret = FC_ENUM32; + else if (attr->typekind == TKIND_ALIAS) + ret = get_basetype(refinfo, &attr->tdescAlias); + else + ret = 0; + ITypeInfo_ReleaseTypeAttr(refinfo, attr); + ITypeInfo_Release(refinfo); + return ret; default: return 0; } } @@ -210,7 +226,7 @@ static unsigned char get_struct_fc(ITypeInfo *typeinfo, TYPEATTR *attr) fc = FC_BOGUS_STRUCT; break; default: - if (!get_base_type(vt)) + if (!get_basetype(typeinfo, &desc->elemdescVar.tdesc)) { FIXME("unhandled type %u\n", vt); fc = FC_BOGUS_STRUCT; @@ -226,7 +242,7 @@ static unsigned char get_struct_fc(ITypeInfo *typeinfo, TYPEATTR *attr)
static unsigned char get_array_fc(ITypeInfo *typeinfo, TYPEDESC *desc) { - if (get_base_type(desc->vt)) + if (get_basetype(typeinfo, desc)) return FC_LGFARRAY; else if (desc->vt == VT_USERDEFINED) { @@ -283,7 +299,7 @@ static size_t write_array_tfs(ITypeInfo *typeinfo, unsigned char *str, if (fc != FC_LGFARRAY) FIXME("complex arrays not implemented\n");
- if (!(basetype = get_base_type(desc->tdescElem.vt))) + if (!(basetype = get_basetype(typeinfo, &desc->tdescElem))) ref = write_type_tfs(typeinfo, str, len, &desc->tdescElem, FALSE, FALSE);
/* In theory arrays should be nested, but there's no reason not to marshal @@ -401,7 +417,7 @@ static size_t write_pointer_tfs(ITypeInfo *typeinfo, unsigned char *str, ITypeInfo_ReleaseTypeAttr(refinfo, attr); ITypeInfo_Release(refinfo); } - else if ((basetype = get_base_type(desc->vt))) + else if ((basetype = get_basetype(typeinfo, desc))) { assert(!toplevel); /* toplevel base-type pointers should use IsSimpleRef */ WRITE_CHAR(str, *len, FC_UP); @@ -466,7 +482,7 @@ static size_t write_type_tfs(ITypeInfo *typeinfo, unsigned char *str, break; default: /* base types are always embedded directly */ - assert(!get_base_type(desc->vt)); + assert(!get_basetype(typeinfo, desc)); FIXME("unhandled type %u\n", desc->vt); off = *len; WRITE_SHORT(str, *len, 0); @@ -584,7 +600,7 @@ static HRESULT get_param_pointer_info(ITypeInfo *typeinfo, TYPEDESC *tdesc, int *tfs_tdesc = tdesc; if (!is_in && is_out) *server_size = type_memsize(typeinfo, tdesc); - if ((*basetype = get_base_type(tdesc->vt))) + if ((*basetype = get_basetype(typeinfo, tdesc))) *flags |= IsBasetype; break; } @@ -662,7 +678,7 @@ static HRESULT get_param_info(ITypeInfo *typeinfo, TYPEDESC *tdesc, int is_in, ITypeInfo_Release(refinfo); break; default: - if ((*basetype = get_base_type(tdesc->vt))) + if ((*basetype = get_basetype(typeinfo, tdesc))) *flags |= IsBasetype; else { @@ -749,7 +765,7 @@ static void write_proc_func_header(ITypeInfo *typeinfo, FUNCDESC *desc, WRITE_SHORT(proc, *proclen, 0); /* NotifyIndex */ for (param_idx = 0; param_idx < desc->cParams && param_idx < 3; param_idx++) { - basetype = get_base_type(desc->lprgelemdescParam[param_idx].tdesc.vt); + basetype = get_basetype(typeinfo, &desc->lprgelemdescParam[param_idx].tdesc); if (basetype == FC_FLOAT) float_mask |= (1 << ((param_idx + 1) * 2)); else if (basetype == FC_DOUBLE)
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/rpcrt4/ndr_typelib.c | 43 +++++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 18 deletions(-)
diff --git a/dlls/rpcrt4/ndr_typelib.c b/dlls/rpcrt4/ndr_typelib.c index d8c429ba11..f182f1a95c 100644 --- a/dlls/rpcrt4/ndr_typelib.c +++ b/dlls/rpcrt4/ndr_typelib.c @@ -205,6 +205,29 @@ static unsigned int type_memsize(ITypeInfo *typeinfo, TYPEDESC *desc) } }
+static BOOL type_pointer_is_iface(ITypeInfo *typeinfo, TYPEDESC *tdesc) +{ + ITypeInfo *refinfo; + BOOL ret = FALSE; + TYPEATTR *attr; + + if (tdesc->vt == VT_USERDEFINED) + { + ITypeInfo_GetRefTypeInfo(typeinfo, tdesc->hreftype, &refinfo); + ITypeInfo_GetTypeAttr(refinfo, &attr); + + if (attr->typekind == TKIND_INTERFACE + || attr->typekind == TKIND_DISPATCH + || attr->typekind == TKIND_COCLASS) + ret = TRUE; + + ITypeInfo_ReleaseTypeAttr(refinfo, attr); + ITypeInfo_Release(refinfo); + } + + return ret; +} + static unsigned char get_array_fc(ITypeInfo *typeinfo, TYPEDESC *desc);
static unsigned char get_struct_fc(ITypeInfo *typeinfo, TYPEATTR *attr) @@ -530,26 +553,10 @@ static HRESULT get_param_pointer_info(ITypeInfo *typeinfo, TYPEDESC *tdesc, int break; case VT_PTR: *flags |= MustFree; - - if (tdesc->lptdesc->vt == VT_USERDEFINED) + if (type_pointer_is_iface(typeinfo, tdesc->lptdesc)) { - ITypeInfo_GetRefTypeInfo(typeinfo, tdesc->lptdesc->hreftype, &refinfo); - ITypeInfo_GetTypeAttr(refinfo, &attr); - - switch (attr->typekind) - { - case TKIND_INTERFACE: - case TKIND_DISPATCH: - case TKIND_COCLASS: - if (is_in && is_out) - *server_size = sizeof(void *); - break; - default: + if (is_in && is_out) *server_size = sizeof(void *); - } - - ITypeInfo_ReleaseTypeAttr(refinfo, attr); - ITypeInfo_Release(refinfo); } else *server_size = sizeof(void *);
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/rpcrt4/ndr_typelib.c | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/dlls/rpcrt4/ndr_typelib.c b/dlls/rpcrt4/ndr_typelib.c index f182f1a95c..963a119ce8 100644 --- a/dlls/rpcrt4/ndr_typelib.c +++ b/dlls/rpcrt4/ndr_typelib.c @@ -220,6 +220,8 @@ static BOOL type_pointer_is_iface(ITypeInfo *typeinfo, TYPEDESC *tdesc) || attr->typekind == TKIND_DISPATCH || attr->typekind == TKIND_COCLASS) ret = TRUE; + else if (attr->typekind == TKIND_ALIAS) + ret = type_pointer_is_iface(refinfo, &attr->tdescAlias);
ITypeInfo_ReleaseTypeAttr(refinfo, attr); ITypeInfo_Release(refinfo); @@ -280,6 +282,8 @@ static unsigned char get_array_fc(ITypeInfo *typeinfo, TYPEDESC *desc) fc = FC_LGFARRAY; else if (attr->typekind == TKIND_RECORD && get_struct_fc(refinfo, attr) == FC_STRUCT) fc = FC_LGFARRAY; + else if (attr->typekind == TKIND_ALIAS) + fc = get_array_fc(refinfo, &attr->tdescAlias); else fc = FC_BOGUS_ARRAY;
@@ -493,6 +497,9 @@ static size_t write_type_tfs(ITypeInfo *typeinfo, unsigned char *str, case TKIND_RECORD: off = write_struct_tfs(refinfo, str, len, attr); break; + case TKIND_ALIAS: + off = write_type_tfs(refinfo, str, len, &attr->tdescAlias, toplevel, onstack); + break; default: FIXME("unhandled kind %u\n", attr->typekind); off = *len;
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/rpcrt4/ndr_typelib.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/dlls/rpcrt4/ndr_typelib.c b/dlls/rpcrt4/ndr_typelib.c index 963a119ce8..c756682e46 100644 --- a/dlls/rpcrt4/ndr_typelib.c +++ b/dlls/rpcrt4/ndr_typelib.c @@ -497,6 +497,11 @@ static size_t write_type_tfs(ITypeInfo *typeinfo, unsigned char *str, case TKIND_RECORD: off = write_struct_tfs(refinfo, str, len, attr); break; + case TKIND_INTERFACE: + case TKIND_DISPATCH: + case TKIND_COCLASS: + assert(0); + break; case TKIND_ALIAS: off = write_type_tfs(refinfo, str, len, &attr->tdescAlias, toplevel, onstack); break;
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/rpcrt4/ndr_typelib.c | 92 +++++++++++++++++++++++++++++++-------- 1 file changed, 75 insertions(+), 17 deletions(-)
diff --git a/dlls/rpcrt4/ndr_typelib.c b/dlls/rpcrt4/ndr_typelib.c index c756682e46..8f87693a6b 100644 --- a/dlls/rpcrt4/ndr_typelib.c +++ b/dlls/rpcrt4/ndr_typelib.c @@ -231,34 +231,92 @@ static BOOL type_pointer_is_iface(ITypeInfo *typeinfo, TYPEDESC *tdesc) }
static unsigned char get_array_fc(ITypeInfo *typeinfo, TYPEDESC *desc); +static unsigned char get_struct_fc(ITypeInfo *typeinfo, TYPEATTR *attr);
-static unsigned char get_struct_fc(ITypeInfo *typeinfo, TYPEATTR *attr) +static unsigned char get_struct_member_fc(ITypeInfo *typeinfo, TYPEDESC *tdesc) { - unsigned char fc = FC_STRUCT; - VARDESC *desc; - VARTYPE vt; - WORD i; + unsigned char fc; + ITypeInfo *refinfo; + TYPEATTR *attr;
- for (i = 0; i < attr->cVars; i++) + switch (tdesc->vt) { - ITypeInfo_GetVarDesc(typeinfo, i, &desc); - vt = desc->elemdescVar.tdesc.vt; + case VT_BSTR: + case VT_SAFEARRAY: + return (sizeof(void *) == 4) ? FC_PSTRUCT : FC_BOGUS_STRUCT; + case VT_CY: + return FC_STRUCT; + case VT_UNKNOWN: + case VT_DISPATCH: + return FC_BOGUS_STRUCT; + case VT_CARRAY: + if (get_array_fc(typeinfo, &tdesc->lpadesc->tdescElem) == FC_BOGUS_ARRAY) + return FC_BOGUS_STRUCT; + return FC_STRUCT; + case VT_PTR: + if (type_pointer_is_iface(typeinfo, tdesc)) + fc = FC_BOGUS_STRUCT; + else + fc = (sizeof(void *) == 4) ? FC_PSTRUCT : FC_BOGUS_STRUCT; + break; + case VT_USERDEFINED: + ITypeInfo_GetRefTypeInfo(typeinfo, tdesc->hreftype, &refinfo); + ITypeInfo_GetTypeAttr(refinfo, &attr);
- switch (vt) + switch (attr->typekind) { - case VT_CARRAY: - if (get_array_fc(typeinfo, &desc->elemdescVar.tdesc.lpadesc->tdescElem) == FC_BOGUS_ARRAY) - fc = FC_BOGUS_STRUCT; + case TKIND_ENUM: + fc = FC_STRUCT; + break; + case TKIND_RECORD: + fc = get_struct_fc(refinfo, attr); + break; + case TKIND_INTERFACE: + case TKIND_DISPATCH: + case TKIND_COCLASS: + fc = FC_BOGUS_STRUCT; + break; + case TKIND_ALIAS: + fc = get_struct_member_fc(refinfo, &attr->tdescAlias); break; default: - if (!get_basetype(typeinfo, &desc->elemdescVar.tdesc)) - { - FIXME("unhandled type %u\n", vt); - fc = FC_BOGUS_STRUCT; - } + FIXME("Unhandled kind %#x.\n", attr->typekind); + fc = FC_BOGUS_STRUCT; break; }
+ ITypeInfo_ReleaseTypeAttr(refinfo, attr); + ITypeInfo_Release(refinfo); + break; + default: + if (get_basetype(typeinfo, tdesc)) + return FC_STRUCT; + else + { + FIXME("Unhandled type %u.\n", tdesc->vt); + return FC_BOGUS_STRUCT; + } + } + + return fc; +} + +static unsigned char get_struct_fc(ITypeInfo *typeinfo, TYPEATTR *attr) +{ + unsigned char fc = FC_STRUCT, member_fc; + VARDESC *desc; + WORD i; + + for (i = 0; i < attr->cVars; i++) + { + ITypeInfo_GetVarDesc(typeinfo, i, &desc); + + member_fc = get_struct_member_fc(typeinfo, &desc->elemdescVar.tdesc); + if (member_fc == FC_BOGUS_STRUCT) + fc = FC_BOGUS_STRUCT; + else if (member_fc == FC_PSTRUCT && fc != FC_BOGUS_STRUCT) + fc = FC_PSTRUCT; + ITypeInfo_ReleaseVarDesc(typeinfo, desc); }
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/rpcrt4/ndr_typelib.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-)
diff --git a/dlls/rpcrt4/ndr_typelib.c b/dlls/rpcrt4/ndr_typelib.c index 8f87693a6b..3d3d42b97a 100644 --- a/dlls/rpcrt4/ndr_typelib.c +++ b/dlls/rpcrt4/ndr_typelib.c @@ -246,6 +246,7 @@ static unsigned char get_struct_member_fc(ITypeInfo *typeinfo, TYPEDESC *tdesc) return (sizeof(void *) == 4) ? FC_PSTRUCT : FC_BOGUS_STRUCT; case VT_CY: return FC_STRUCT; + case VT_VARIANT: case VT_UNKNOWN: case VT_DISPATCH: return FC_BOGUS_STRUCT; @@ -358,7 +359,12 @@ static size_t write_struct_tfs(ITypeInfo *typeinfo, unsigned char *str, size_t *len, TYPEATTR *attr) { unsigned char fc = get_struct_fc(typeinfo, attr); + unsigned int struct_offset = 0; + unsigned char basetype; size_t off = *len; + TYPEDESC *tdesc; + VARDESC *desc; + WORD i;
if (fc != FC_STRUCT) FIXME("fc %02x not implemented\n", fc); @@ -366,7 +372,30 @@ static size_t write_struct_tfs(ITypeInfo *typeinfo, unsigned char *str, WRITE_CHAR (str, *len, FC_STRUCT); WRITE_CHAR (str, *len, attr->cbAlignment - 1); WRITE_SHORT(str, *len, attr->cbSizeInstance); - WRITE_CHAR (str, *len, FC_PAD); + + for (i = 0; i < attr->cVars; i++) + { + ITypeInfo_GetVarDesc(typeinfo, i, &desc); + tdesc = &desc->elemdescVar.tdesc; + + /* This may not match the intended alignment, but we don't have enough + * information to determine that. This should always give the correct + * layout. */ + if ((struct_offset & 7) && !(desc->oInst & 7)) + WRITE_CHAR(str, *len, FC_ALIGNM8); + else if ((struct_offset & 3) && !(desc->oInst & 3)) + WRITE_CHAR(str, *len, FC_ALIGNM4); + else if ((struct_offset & 1) && !(desc->oInst & 1)) + WRITE_CHAR(str, *len, FC_ALIGNM2); + struct_offset = desc->oInst + type_memsize(typeinfo, tdesc); + + if ((basetype = get_basetype(typeinfo, tdesc))) + WRITE_CHAR(str, *len, basetype); + + ITypeInfo_ReleaseVarDesc(typeinfo, desc); + } + if (!(*len & 1)) + WRITE_CHAR (str, *len, FC_PAD); WRITE_CHAR (str, *len, FC_END);
return off;
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=46378 Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/rpcrt4/ndr_typelib.c | 231 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 221 insertions(+), 10 deletions(-)
diff --git a/dlls/rpcrt4/ndr_typelib.c b/dlls/rpcrt4/ndr_typelib.c index 3d3d42b97a..5a4de51dd1 100644 --- a/dlls/rpcrt4/ndr_typelib.c +++ b/dlls/rpcrt4/ndr_typelib.c @@ -355,24 +355,42 @@ static unsigned char get_array_fc(ITypeInfo *typeinfo, TYPEDESC *desc) return FC_BOGUS_ARRAY; }
-static size_t write_struct_tfs(ITypeInfo *typeinfo, unsigned char *str, +static BOOL type_is_non_iface_pointer(ITypeInfo *typeinfo, TYPEDESC *desc) +{ + if (desc->vt == VT_PTR) + return !type_pointer_is_iface(typeinfo, desc->lptdesc); + else if (desc->vt == VT_USERDEFINED) + { + ITypeInfo *refinfo; + TYPEATTR *attr; + BOOL ret; + + ITypeInfo_GetRefTypeInfo(typeinfo, desc->hreftype, &refinfo); + ITypeInfo_GetTypeAttr(refinfo, &attr); + + if (attr->typekind == TKIND_ALIAS) + ret = type_is_non_iface_pointer(refinfo, &attr->tdescAlias); + else + ret = FALSE; + + ITypeInfo_ReleaseTypeAttr(refinfo, attr); + ITypeInfo_Release(refinfo); + + return ret; + } + else + return FALSE; +} + +static void write_struct_members(ITypeInfo *typeinfo, unsigned char *str, size_t *len, TYPEATTR *attr) { - unsigned char fc = get_struct_fc(typeinfo, attr); unsigned int struct_offset = 0; unsigned char basetype; - size_t off = *len; TYPEDESC *tdesc; VARDESC *desc; WORD i;
- if (fc != FC_STRUCT) - FIXME("fc %02x not implemented\n", fc); - - WRITE_CHAR (str, *len, FC_STRUCT); - WRITE_CHAR (str, *len, attr->cbAlignment - 1); - WRITE_SHORT(str, *len, attr->cbSizeInstance); - for (i = 0; i < attr->cVars; i++) { ITypeInfo_GetVarDesc(typeinfo, i, &desc); @@ -391,12 +409,205 @@ static size_t write_struct_tfs(ITypeInfo *typeinfo, unsigned char *str,
if ((basetype = get_basetype(typeinfo, tdesc))) WRITE_CHAR(str, *len, basetype); + else if (type_is_non_iface_pointer(typeinfo, tdesc)) + WRITE_CHAR(str, *len, FC_POINTER); + else + { + WRITE_CHAR(str, *len, FC_EMBEDDED_COMPLEX); + WRITE_CHAR(str, *len, 0); + WRITE_SHORT(str, *len, 0); + }
ITypeInfo_ReleaseVarDesc(typeinfo, desc); } if (!(*len & 1)) WRITE_CHAR (str, *len, FC_PAD); WRITE_CHAR (str, *len, FC_END); +} + +static void write_simple_struct_tfs(ITypeInfo *typeinfo, unsigned char *str, + size_t *len, TYPEATTR *attr) +{ + write_struct_members(typeinfo, str, len, attr); +} + +static BOOL type_needs_pointer_deref(ITypeInfo *typeinfo, TYPEDESC *desc) +{ + if (desc->vt == VT_PTR || desc->vt == VT_UNKNOWN || desc->vt == VT_DISPATCH) + return TRUE; + else if (desc->vt == VT_USERDEFINED) + { + ITypeInfo *refinfo; + BOOL ret = FALSE; + TYPEATTR *attr; + + ITypeInfo_GetRefTypeInfo(typeinfo, desc->hreftype, &refinfo); + ITypeInfo_GetTypeAttr(refinfo, &attr); + + if (attr->typekind == TKIND_ALIAS) + ret = type_needs_pointer_deref(refinfo, &attr->tdescAlias); + + ITypeInfo_ReleaseTypeAttr(refinfo, attr); + ITypeInfo_Release(refinfo); + + return ret; + } + else + return FALSE; +} + +static void write_complex_struct_pointer_layout(ITypeInfo *typeinfo, + TYPEDESC *desc, unsigned char *str, size_t *len) +{ + unsigned char basetype; + + if (desc->vt == VT_PTR && !type_pointer_is_iface(typeinfo, desc->lptdesc)) + { + WRITE_CHAR(str, *len, FC_UP); + if ((basetype = get_basetype(typeinfo, desc->lptdesc))) + { + WRITE_CHAR(str, *len, FC_SIMPLE_POINTER); + WRITE_CHAR(str, *len, basetype); + WRITE_CHAR(str, *len, FC_PAD); + } + else + { + if (type_needs_pointer_deref(typeinfo, desc->lptdesc)) + WRITE_CHAR(str, *len, FC_POINTER_DEREF); + else + WRITE_CHAR(str, *len, 0); + WRITE_SHORT(str, *len, 0); + } + } + else if (desc->vt == VT_USERDEFINED) + { + ITypeInfo *refinfo; + TYPEATTR *attr; + + ITypeInfo_GetRefTypeInfo(typeinfo, desc->hreftype, &refinfo); + ITypeInfo_GetTypeAttr(refinfo, &attr); + + if (attr->typekind == TKIND_ALIAS) + write_complex_struct_pointer_layout(refinfo, &attr->tdescAlias, str, len); + + ITypeInfo_ReleaseTypeAttr(refinfo, attr); + ITypeInfo_Release(refinfo); + } +} + +static size_t write_complex_struct_pointer_ref(ITypeInfo *typeinfo, + TYPEDESC *desc, unsigned char *str, size_t *len) +{ + if (desc->vt == VT_PTR && !type_pointer_is_iface(typeinfo, desc->lptdesc) + && !get_basetype(typeinfo, desc->lptdesc)) + { + return write_type_tfs(typeinfo, str, len, desc->lptdesc, FALSE, FALSE); + } + else if (desc->vt == VT_USERDEFINED) + { + ITypeInfo *refinfo; + TYPEATTR *attr; + size_t ret = 0; + + ITypeInfo_GetRefTypeInfo(typeinfo, desc->hreftype, &refinfo); + ITypeInfo_GetTypeAttr(refinfo, &attr); + + if (attr->typekind == TKIND_ALIAS) + ret = write_complex_struct_pointer_ref(refinfo, &attr->tdescAlias, str, len); + + ITypeInfo_ReleaseTypeAttr(refinfo, attr); + ITypeInfo_Release(refinfo); + + return ret; + } + + return 0; +} + +static void write_complex_struct_tfs(ITypeInfo *typeinfo, unsigned char *str, + size_t *len, TYPEATTR *attr) +{ + size_t pointer_layout_offset, pointer_layout, member_layout, ref; + unsigned int struct_offset = 0; + TYPEDESC *tdesc; + VARDESC *desc; + WORD i; + + WRITE_SHORT(str, *len, 0); /* conformant array description */ + pointer_layout_offset = *len; + WRITE_SHORT(str, *len, 0); /* pointer layout; will be filled in later */ + member_layout = *len; + + /* First pass: write the struct members and pointer layout, but do not yet + * write the offsets for embedded complexes and pointer refs. These must be + * handled after we write the whole struct description, since it must be + * contiguous. */ + + write_struct_members(typeinfo, str, len, attr); + + pointer_layout = *len; + if (str) *((short *)(str + pointer_layout_offset)) = pointer_layout - pointer_layout_offset; + + for (i = 0; i < attr->cVars; i++) + { + ITypeInfo_GetVarDesc(typeinfo, i, &desc); + write_complex_struct_pointer_layout(typeinfo, &desc->elemdescVar.tdesc, str, len); + ITypeInfo_ReleaseVarDesc(typeinfo, desc); + } + + /* Second pass: write types for embedded complexes and non-simple pointers. */ + + struct_offset = 0; + + for (i = 0; i < attr->cVars; i++) + { + ITypeInfo_GetVarDesc(typeinfo, i, &desc); + tdesc = &desc->elemdescVar.tdesc; + + if (struct_offset != desc->oInst) + member_layout++; /* alignment directive */ + struct_offset = desc->oInst + type_memsize(typeinfo, tdesc); + + if (get_basetype(typeinfo, tdesc)) + member_layout++; + else if (type_is_non_iface_pointer(typeinfo, tdesc)) + { + member_layout++; + if ((ref = write_complex_struct_pointer_ref(typeinfo, tdesc, str, len))) + { + if (str) *((short *)(str + pointer_layout + 2)) = ref - (pointer_layout + 2); + } + pointer_layout += 4; + } + else + { + ref = write_type_tfs(typeinfo, str, len, tdesc, FALSE, FALSE); + if (str) *((short *)(str + member_layout + 2)) = ref - (member_layout + 2); + member_layout += 4; + } + + ITypeInfo_ReleaseVarDesc(typeinfo, desc); + } +} + +static size_t write_struct_tfs(ITypeInfo *typeinfo, unsigned char *str, + size_t *len, TYPEATTR *attr) +{ + unsigned char fc = get_struct_fc(typeinfo, attr); + size_t off = *len; + + /* For the sake of simplicity, write pointer structs as complex structs. */ + if (fc == FC_PSTRUCT) + fc = FC_BOGUS_STRUCT; + + WRITE_CHAR (str, *len, fc); + WRITE_CHAR (str, *len, attr->cbAlignment - 1); + WRITE_SHORT(str, *len, attr->cbSizeInstance); + + if (fc == FC_STRUCT) + write_simple_struct_tfs(typeinfo, str, len, attr); + else if (fc == FC_BOGUS_STRUCT) + write_complex_struct_tfs(typeinfo, str, len, attr);
return off; }
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/oleaut32/tests/tmarshal.c | 45 ++++++++++++++++++++++++++++++++ dlls/oleaut32/tests/tmarshal.idl | 21 ++++++++++++++- 2 files changed, 65 insertions(+), 1 deletion(-)
diff --git a/dlls/oleaut32/tests/tmarshal.c b/dlls/oleaut32/tests/tmarshal.c index 9a7d995ca8..4f84442baf 100644 --- a/dlls/oleaut32/tests/tmarshal.c +++ b/dlls/oleaut32/tests/tmarshal.c @@ -1441,6 +1441,28 @@ static HRESULT WINAPI Widget_rect(IWidget *iface, RECT in, RECT *out, RECT *in_p return S_OK; }
+static HRESULT WINAPI Widget_complex_struct(IWidget *iface, struct complex in) +{ + HRESULT hr; + + ok(in.c == 98, "Got char %d.\n", in.c); + ok(in.i == 76543, "Got int %d.\n", in.i); + ok(*in.pi == 2, "Got int pointer %d.\n", *in.pi); + ok(**in.ppi == 10, "Got int double pointer %d.\n", **in.ppi); + hr = ISomethingFromDispatch_anotherfn(in.iface); + ok(hr == 0x01234567, "Got wrong hr %#x.\n", hr); + hr = ISomethingFromDispatch_anotherfn(*in.iface_ptr); + ok(hr == 0x01234567, "Got wrong hr %#x.\n", hr); + ok(!lstrcmpW(in.bstr, test_bstr2), "Got string %s.\n", wine_dbgstr_w(in.bstr)); + ok(V_VT(&in.var) == VT_I4, "Got wrong type %u.\n", V_VT(&in.var)); + ok(V_I4(&in.var) == 123, "Got wrong value %d.\n", V_I4(&in.var)); + ok(!memcmp(&in.mystruct, &test_mystruct1, sizeof(MYSTRUCT)), "Structs didn't match.\n"); + ok(!memcmp(in.arr, test_array1, sizeof(array_t)), "Arrays didn't match.\n"); + ok(in.myint == 456, "Got int %d.\n", in.myint); + + return S_OK; +} + static HRESULT WINAPI Widget_array(IWidget *iface, array_t in, array_t out, array_t in_out) { static const array_t empty = {0}; @@ -1600,6 +1622,7 @@ static const struct IWidgetVtbl Widget_VTable = Widget_mystruct_ptr_ptr, Widget_thin_struct, Widget_rect, + Widget_complex_struct, Widget_array, Widget_variant_array, Widget_mystruct_array, @@ -2500,6 +2523,9 @@ static void test_marshal_struct(IWidget *widget, IDispatch *disp) { MYSTRUCT out, in_ptr, in_out, *in_ptr_ptr; RECT rect_out, rect_in_ptr, rect_in_out; + ISomethingFromDispatch *sfd; + struct complex complex; + int i, i2, *pi = &i2; HRESULT hr;
memcpy(&out, &test_mystruct2, sizeof(MYSTRUCT)); @@ -2531,6 +2557,25 @@ static void test_marshal_struct(IWidget *widget, IDispatch *disp) ok(EqualRect(&rect_out, &test_rect5), "Rects didn't match.\n"); ok(EqualRect(&rect_in_ptr, &test_rect3), "Rects didn't match.\n"); ok(EqualRect(&rect_in_out, &test_rect7), "Rects didn't match.\n"); + + /* Test complex structs. */ + complex.c = 98; + complex.i = 76543; + i = 2; + complex.pi = &i; + i2 = 10; + complex.ppi = π + complex.iface = create_disp_obj(); + sfd = create_disp_obj(); + complex.iface_ptr = &sfd; + complex.bstr = SysAllocString(test_bstr2); + V_VT(&complex.var) = VT_I4; + V_I4(&complex.var) = 123; + memcpy(&complex.mystruct, &test_mystruct1, sizeof(MYSTRUCT)); + memcpy(complex.arr, test_array1, sizeof(array_t)); + complex.myint = 456; + hr = IWidget_complex_struct(widget, complex); + ok(hr == S_OK, "Got hr %#x.\n", hr); }
static void test_marshal_array(IWidget *widget, IDispatch *disp) diff --git a/dlls/oleaut32/tests/tmarshal.idl b/dlls/oleaut32/tests/tmarshal.idl index cdc7dc14d3..14b80c4eec 100644 --- a/dlls/oleaut32/tests/tmarshal.idl +++ b/dlls/oleaut32/tests/tmarshal.idl @@ -65,6 +65,7 @@ enum IWidget_dispids DISPID_TM_STRUCT_PTR_PTR, DISPID_TM_THIN_STRUCT, DISPID_TM_RECT, + DISPID_TM_COMPLEX_STRUCT, DISPID_TM_ARRAY, DISPID_TM_VARIANT_ARRAY, DISPID_TM_STRUCT_ARRAY, @@ -105,6 +106,8 @@ library TestTypelib
typedef [public] int myint_t;
+ typedef int array_t[4]; + coclass ApplicationObject2;
[ @@ -335,7 +338,23 @@ library TestTypelib [id(DISPID_TM_RECT)] HRESULT rect([in] RECT in, [out] RECT *out, [in] RECT *in_ptr, [in, out] RECT *in_out);
- typedef int array_t[4]; + struct complex + { + char c; + int i; + int *pi; + int **ppi; + ISomethingFromDispatch *iface; + ISomethingFromDispatch **iface_ptr; + BSTR bstr; + VARIANT var; + MYSTRUCT mystruct; + array_t arr; + myint_t myint; + }; + + [id(DISPID_TM_COMPLEX_STRUCT)] + HRESULT complex_struct([in] struct complex in);
[id(DISPID_TM_ARRAY)] HRESULT array([in] array_t in, [out] array_t out, [in, out] array_t in_out);