On Sat, Nov 03, 2018 at 06:07:18PM -0500, Zebediah Figura wrote:
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com> --- dlls/rpcrt4/ndr_typelib.c | 256 +++++++++++++++++++++++++++++++++++++- 1 file changed, 255 insertions(+), 1 deletion(-)
diff --git a/dlls/rpcrt4/ndr_typelib.c b/dlls/rpcrt4/ndr_typelib.c index 51e198d711..ee4e551fcb 100644 --- a/dlls/rpcrt4/ndr_typelib.c +++ b/dlls/rpcrt4/ndr_typelib.c @@ -35,6 +35,30 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole);
+static HRESULT get_param_pointer_info(ITypeInfo *typeinfo, TYPEDESC *tdesc, int is_in, + int is_out, unsigned short *server_size, unsigned short *flags, + unsigned char *basetype, TYPEDESC **tfs_tdesc) +{ + ITypeInfo *refinfo; + TYPEATTR *attr; + HRESULT hr; + + switch (tdesc->vt) + { + case VT_UNKNOWN: + case VT_DISPATCH: + *flags |= MustFree; + if (is_in && is_out) + *server_size = sizeof(void *); + break; + case VT_PTR: + *flags |= MustFree; + + if (tdesc->lptdesc->vt == VT_USERDEFINED) + { + 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: + *server_size = sizeof(void *); + } + + ITypeInfo_ReleaseTypeAttr(refinfo, attr); + ITypeInfo_Release(refinfo); + } + else + *server_size = sizeof(void *); + break; + case VT_CARRAY: + *flags |= IsSimpleRef | MustFree; + *server_size = type_memsize(typeinfo, tdesc); + *tfs_tdesc = tdesc; + break; + case VT_USERDEFINED: + ITypeInfo_GetRefTypeInfo(typeinfo, tdesc->hreftype, &refinfo); + ITypeInfo_GetTypeAttr(refinfo, &attr); + + switch (attr->typekind) + { + case TKIND_ENUM: + *flags |= IsSimpleRef | IsBasetype; + if (!is_in && is_out) + *server_size = sizeof(void *); + *basetype = FC_ENUM32; + break; + case TKIND_RECORD: + *flags |= IsSimpleRef | MustFree; + if (!is_in && is_out) + *server_size = attr->cbSizeInstance; + *tfs_tdesc = tdesc; + break; + case TKIND_INTERFACE: + case TKIND_DISPATCH: + case TKIND_COCLASS: + *flags |= MustFree; + break; + case TKIND_ALIAS: + hr = get_param_pointer_info(refinfo, &attr->tdescAlias, is_in, + is_out, server_size, flags, basetype, tfs_tdesc); + if (FAILED(hr)) + return hr;
Leaking refinfo and attr.
+ break; + default: + FIXME("unhandled kind %#x\n", attr->typekind); + return E_NOTIMPL;
And here.
+ } + + ITypeInfo_ReleaseTypeAttr(refinfo, attr); + ITypeInfo_Release(refinfo); + break; + default: + *flags |= IsSimpleRef; + *tfs_tdesc = tdesc; + if (!is_in && is_out) + *server_size = type_memsize(typeinfo, tdesc); + if ((*basetype = get_base_type(tdesc->vt))) + *flags |= IsBasetype; + break; + } + + return S_OK; +} + +static HRESULT get_param_info(ITypeInfo *typeinfo, TYPEDESC *tdesc, int is_in, + int is_out, unsigned short *server_size, unsigned short *flags, + unsigned char *basetype, TYPEDESC **tfs_tdesc) +{ + ITypeInfo *refinfo; + TYPEATTR *attr; + HRESULT hr; + + *server_size = 0; + *flags = MustSize; + *basetype = 0; + *tfs_tdesc = tdesc; + + TRACE("vt %u\n", tdesc->vt); + + switch (tdesc->vt) + { + case VT_VARIANT: +#ifndef __i386__ + *flags |= IsSimpleRef | MustFree; + break; +#endif + /* otherwise fall through */ + case VT_BSTR: + case VT_SAFEARRAY: + case VT_CY: + *flags |= IsByValue | MustFree; + break; + case VT_UNKNOWN: + case VT_DISPATCH: + case VT_CARRAY: + *flags |= MustFree; + break; + case VT_PTR: + return get_param_pointer_info(typeinfo, tdesc->lptdesc, is_in, is_out, + server_size, flags, basetype, tfs_tdesc); + case VT_USERDEFINED: + ITypeInfo_GetRefTypeInfo(typeinfo, tdesc->hreftype, &refinfo); + ITypeInfo_GetTypeAttr(refinfo, &attr); + + switch (attr->typekind) + { + case TKIND_ENUM: + *flags |= IsBasetype; + *basetype = FC_ENUM32; + break; + case TKIND_RECORD: +#ifdef __i386__ + *flags |= IsByValue | MustFree; +#elif defined(__x86_64__) + if (attr->cbSizeInstance <= 8) + *flags |= IsByValue | MustFree; + else + *flags |= IsSimpleRef | MustFree; +#endif + break; + case TKIND_ALIAS: + hr = get_param_info(refinfo, &attr->tdescAlias, is_in, is_out, + server_size, flags, basetype, tfs_tdesc); + if (FAILED(hr)) + return hr;
And here.
+ break; + default: + FIXME("unhandled kind %#x\n", attr->typekind); + return E_NOTIMPL;
And here.
+ } + + ITypeInfo_ReleaseTypeAttr(refinfo, attr); + ITypeInfo_Release(refinfo); + break; + default: + if ((*basetype = get_base_type(tdesc->vt))) + *flags |= IsBasetype; + else + { + FIXME("unhandled type %u\n", tdesc->vt); + return E_NOTIMPL; + } + break; + } + + return S_OK; +} +