Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/vbscript/tests/vbscript.c | 4 --- dlls/vbscript/vbdisp.c | 51 ++++++++++++++++++++++++++++++++-- 2 files changed, 49 insertions(+), 6 deletions(-)
diff --git a/dlls/vbscript/tests/vbscript.c b/dlls/vbscript/tests/vbscript.c index 0c3acd0..1d246c5 100644 --- a/dlls/vbscript/tests/vbscript.c +++ b/dlls/vbscript/tests/vbscript.c @@ -1070,16 +1070,12 @@ static void test_script_typeinfo(void) ITypeComp_Release(typecomp2); wcscpy(str, L"not_found"); hr = ITypeComp_Bind(typecomp, NULL, 0, 0, &typeinfo2, &desckind, &bindptr); - todo_wine ok(hr == E_INVALIDARG, "Bind returned: %08x\n", hr); hr = ITypeComp_Bind(typecomp, str, 0, 0, NULL, &desckind, &bindptr); - todo_wine ok(hr == E_INVALIDARG, "Bind returned: %08x\n", hr); hr = ITypeComp_Bind(typecomp, str, 0, 0, &typeinfo2, NULL, &bindptr); - todo_wine ok(hr == E_INVALIDARG, "Bind returned: %08x\n", hr); hr = ITypeComp_Bind(typecomp, str, 0, 0, &typeinfo2, &desckind, NULL); - todo_wine ok(hr == E_INVALIDARG, "Bind returned: %08x\n", hr); ITypeComp_Release(typecomp);
diff --git a/dlls/vbscript/vbdisp.c b/dlls/vbscript/vbdisp.c index 2e59051..0a4f681 100644 --- a/dlls/vbscript/vbdisp.c +++ b/dlls/vbscript/vbdisp.c @@ -932,9 +932,56 @@ static HRESULT WINAPI ScriptTypeComp_Bind(ITypeComp *iface, LPOLESTR szName, ULO ITypeInfo **ppTInfo, DESCKIND *pDescKind, BINDPTR *pBindPtr) { ScriptTypeInfo *This = ScriptTypeInfo_from_ITypeComp(iface); - FIXME("(%p)->(%s %08x %d %p %p %p)\n", This, debugstr_w(szName), lHashVal, + UINT flags = wFlags ? wFlags : ~0; + ITypeInfo *disp_typeinfo; + ITypeComp *disp_typecomp; + HRESULT hr; + UINT i; + + TRACE("(%p)->(%s %08x %d %p %p %p)\n", This, debugstr_w(szName), lHashVal, wFlags, ppTInfo, pDescKind, pBindPtr); - return E_NOTIMPL; + + if (!szName || !ppTInfo || !pDescKind || !pBindPtr) + return E_INVALIDARG; + + for (i = 0; i < This->num_funcs; i++) + { + if (wcsicmp(szName, This->funcs[i].func->name)) continue; + if (!(flags & INVOKE_FUNC)) return TYPE_E_TYPEMISMATCH; + + hr = ITypeInfo_GetFuncDesc(&This->ITypeInfo_iface, i, &pBindPtr->lpfuncdesc); + if (FAILED(hr)) return hr; + + *pDescKind = DESCKIND_FUNCDESC; + *ppTInfo = &This->ITypeInfo_iface; + ITypeInfo_AddRef(*ppTInfo); + return S_OK; + } + + for (i = 0; i < This->num_vars; i++) + { + if (wcsicmp(szName, This->disp->global_vars[i]->name)) continue; + if (!(flags & INVOKE_PROPERTYGET)) return TYPE_E_TYPEMISMATCH; + + hr = ITypeInfo_GetVarDesc(&This->ITypeInfo_iface, i, &pBindPtr->lpvardesc); + if (FAILED(hr)) return hr; + + *pDescKind = DESCKIND_VARDESC; + *ppTInfo = &This->ITypeInfo_iface; + ITypeInfo_AddRef(*ppTInfo); + return S_OK; + } + + /* Look into the inherited IDispatch */ + hr = get_dispatch_typeinfo(&disp_typeinfo); + if (FAILED(hr)) return hr; + + hr = ITypeInfo_GetTypeComp(disp_typeinfo, &disp_typecomp); + if (FAILED(hr)) return hr; + + hr = ITypeComp_Bind(disp_typecomp, szName, lHashVal, wFlags, ppTInfo, pDescKind, pBindPtr); + ITypeComp_Release(disp_typecomp); + return hr; }
static HRESULT WINAPI ScriptTypeComp_BindType(ITypeComp *iface, LPOLESTR szName, ULONG lHashVal,
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/vbscript/vbdisp.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-)
diff --git a/dlls/vbscript/vbdisp.c b/dlls/vbscript/vbdisp.c index 0a4f681..e27ce22 100644 --- a/dlls/vbscript/vbdisp.c +++ b/dlls/vbscript/vbdisp.c @@ -988,8 +988,25 @@ static HRESULT WINAPI ScriptTypeComp_BindType(ITypeComp *iface, LPOLESTR szName, ITypeInfo **ppTInfo, ITypeComp **ppTComp) { ScriptTypeInfo *This = ScriptTypeInfo_from_ITypeComp(iface); - FIXME("(%p)->(%s %08x %p %p)\n", This, debugstr_w(szName), lHashVal, ppTInfo, ppTComp); - return E_NOTIMPL; + ITypeInfo *disp_typeinfo; + ITypeComp *disp_typecomp; + HRESULT hr; + + TRACE("(%p)->(%s %08x %p %p)\n", This, debugstr_w(szName), lHashVal, ppTInfo, ppTComp); + + if (!szName || !ppTInfo || !ppTComp) + return E_INVALIDARG; + + /* Look into the inherited IDispatch */ + hr = get_dispatch_typeinfo(&disp_typeinfo); + if (FAILED(hr)) return hr; + + hr = ITypeInfo_GetTypeComp(disp_typeinfo, &disp_typecomp); + if (FAILED(hr)) return hr; + + hr = ITypeComp_BindType(disp_typecomp, szName, lHashVal, ppTInfo, ppTComp); + ITypeComp_Release(disp_typecomp); + return hr; }
static const ITypeCompVtbl ScriptTypeCompVtbl = {
Signed-off-by: Jacek Caban jacek@codeweavers.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/vbscript/tests/vbscript.c | 59 ++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+)
diff --git a/dlls/vbscript/tests/vbscript.c b/dlls/vbscript/tests/vbscript.c index 1d246c5..ad3ccf3 100644 --- a/dlls/vbscript/tests/vbscript.c +++ b/dlls/vbscript/tests/vbscript.c @@ -1077,6 +1077,65 @@ static void test_script_typeinfo(void) ok(hr == E_INVALIDARG, "Bind returned: %08x\n", hr); hr = ITypeComp_Bind(typecomp, str, 0, 0, &typeinfo2, &desckind, NULL); ok(hr == E_INVALIDARG, "Bind returned: %08x\n", hr); + + hr = ITypeComp_Bind(typecomp, str, 0, 0, &typeinfo2, &desckind, &bindptr); + ok(hr == S_OK, "Bind failed: %08x\n", hr); + ok(desckind == DESCKIND_NONE, "Unexpected desckind %u\n", desckind); + wcscpy(str, L"GLOBAL_VAR"); + hr = ITypeComp_Bind(typecomp, str, 0, INVOKE_FUNC, &typeinfo2, &desckind, &bindptr); + ok(hr == TYPE_E_TYPEMISMATCH, "Bind returned: %08x\n", hr); + ok(!lstrcmpW(str, L"GLOBAL_VAR"), "Unexpected string %s\n", wine_dbgstr_w(str)); + wcscpy(str, L"C"); + hr = ITypeComp_Bind(typecomp, str, 0, 0, &typeinfo2, &desckind, &bindptr); + ok(hr == S_OK, "Bind failed: %08x\n", hr); + ok(desckind == DESCKIND_NONE, "Unexpected desckind %u\n", desckind); + wcscpy(str, L"addRef"); + hr = ITypeComp_Bind(typecomp, str, 0, 0, &typeinfo2, &desckind, &bindptr); + ok(hr == S_OK, "Bind failed: %08x\n", hr); + ok(desckind == DESCKIND_FUNCDESC, "Unexpected desckind %u\n", desckind); + ok(!lstrcmpW(str, L"addRef"), "Unexpected string %s\n", wine_dbgstr_w(str)); + ITypeInfo_ReleaseFuncDesc(typeinfo2, bindptr.lpfuncdesc); + ITypeInfo_Release(typeinfo2); + for (i = 0; i < ARRAY_SIZE(var); i++) + { + wcscpy(str, var[i].name); + hr = ITypeComp_Bind(typecomp, str, 0, INVOKE_PROPERTYGET, &typeinfo2, &desckind, &bindptr); + ok(hr == S_OK, "Bind failed: %08x\n", hr); + ok(desckind == DESCKIND_VARDESC, "Unexpected desckind %u\n", desckind); + ITypeInfo_ReleaseVarDesc(typeinfo2, bindptr.lpvardesc); + ITypeInfo_Release(typeinfo2); + } + for (i = 0; i < ARRAY_SIZE(func); i++) + { + wcscpy(str, func[i].name); + hr = ITypeComp_Bind(typecomp, str, 0, INVOKE_FUNC, &typeinfo2, &desckind, &bindptr); + ok(hr == S_OK, "Bind failed: %08x\n", hr); + ok(desckind == DESCKIND_FUNCDESC, "Unexpected desckind %u\n", desckind); + ITypeInfo_ReleaseFuncDesc(typeinfo2, bindptr.lpfuncdesc); + ITypeInfo_Release(typeinfo2); + } + wcscpy(str, L"VBScriptTypeInfo"); + hr = ITypeComp_BindType(typecomp, NULL, 0, &typeinfo2, &typecomp2); + ok(hr == E_INVALIDARG, "BindType returned: %08x\n", hr); + hr = ITypeComp_BindType(typecomp, str, 0, NULL, &typecomp2); + ok(hr == E_INVALIDARG, "BindType returned: %08x\n", hr); + hr = ITypeComp_BindType(typecomp, str, 0, &typeinfo2, NULL); + ok(hr == E_INVALIDARG, "BindType returned: %08x\n", hr); + hr = ITypeComp_BindType(typecomp, str, 0, &typeinfo2, &typecomp2); + ok(hr == S_OK, "BindType failed: %08x\n", hr); + ok(!typeinfo2, "Unexpected TypeInfo %p (expected null)\n", typeinfo2); + ok(!typecomp2, "Unexpected TypeComp %p (expected null)\n", typecomp2); + wcscpy(str, L"C"); + hr = ITypeComp_BindType(typecomp, str, 0, &typeinfo2, &typecomp2); + ok(hr == S_OK, "BindType failed: %08x\n", hr); + ok(!typeinfo2, "Unexpected TypeInfo %p (expected null)\n", typeinfo2); + ok(!typecomp2, "Unexpected TypeComp %p (expected null)\n", typecomp2); + wcscpy(str, L"IDispatch"); + hr = ITypeComp_BindType(typecomp, str, 0, &typeinfo2, &typecomp2); + ok(hr == S_OK, "BindType failed: %08x\n", hr); + ok(!typeinfo2, "Unexpected TypeInfo %p (expected null)\n", typeinfo2); + ok(!typecomp2, "Unexpected TypeComp %p (expected null)\n", typecomp2); + ITypeComp_Release(typecomp);
/* Updating the script won't update the typeinfo obtained before,
Signed-off-by: Jacek Caban jacek@codeweavers.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com ---
We need to map the member IDs to the variables and functions. Functions can be replaced or skipped (if private) so we have to keep a map for them.
dlls/vbscript/vbdisp.c | 92 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 89 insertions(+), 3 deletions(-)
diff --git a/dlls/vbscript/vbdisp.c b/dlls/vbscript/vbdisp.c index e27ce22..5d43c43 100644 --- a/dlls/vbscript/vbdisp.c +++ b/dlls/vbscript/vbdisp.c @@ -539,6 +539,9 @@ typedef struct { ITypeComp ITypeComp_iface; LONG ref;
+ UINT func_memid_map_cnt; + UINT *func_memid_map; + UINT num_vars; UINT num_funcs; struct typeinfo_func *funcs; @@ -546,6 +549,30 @@ typedef struct { ScriptDisp *disp; } ScriptTypeInfo;
+enum memid_type { + memid_invalid, + memid_inherited, + memid_func, + memid_var +}; + +static inline enum memid_type get_memid_type(const ScriptTypeInfo *typeinfo, MEMBERID memid) +{ + if (memid <= 0) return memid_invalid; + if (memid & DISPID_FUNCTION_MASK) + { + memid &= ~DISPID_FUNCTION_MASK; + if (memid >= typeinfo->func_memid_map_cnt) + return memid_inherited; + if (typeinfo->func_memid_map[memid] == ~0) + return memid_invalid; + return memid_func; + } + if (memid > typeinfo->num_vars) + return memid_inherited; + return memid_var; +} + static inline ScriptTypeInfo *ScriptTypeInfo_from_ITypeInfo(ITypeInfo *iface) { return CONTAINING_RECORD(iface, ScriptTypeInfo, ITypeInfo_iface); @@ -600,6 +627,7 @@ static ULONG WINAPI ScriptTypeInfo_Release(ITypeInfo *iface) release_vbscode(This->funcs[i].func->code_ctx);
IDispatchEx_Release(&This->disp->IDispatchEx_iface); + heap_free(This->func_memid_map); heap_free(This->funcs); heap_free(This); } @@ -707,10 +735,53 @@ static HRESULT WINAPI ScriptTypeInfo_GetNames(ITypeInfo *iface, MEMBERID memid, UINT cMaxNames, UINT *pcNames) { ScriptTypeInfo *This = ScriptTypeInfo_from_ITypeInfo(iface); + enum memid_type memid_type = get_memid_type(This, memid); + ITypeInfo *disp_typeinfo; + HRESULT hr; + UINT i = 0;
- FIXME("(%p)->(%d %p %u %p)\n", This, memid, rgBstrNames, cMaxNames, pcNames); + TRACE("(%p)->(%d %p %u %p)\n", This, memid, rgBstrNames, cMaxNames, pcNames);
- return E_NOTIMPL; + if (!rgBstrNames || !pcNames) return E_INVALIDARG; + if (memid_type == memid_invalid) return TYPE_E_ELEMENTNOTFOUND; + if (memid_type == memid_inherited) + { + hr = get_dispatch_typeinfo(&disp_typeinfo); + if (FAILED(hr)) return hr; + + return ITypeInfo_GetNames(disp_typeinfo, memid, rgBstrNames, cMaxNames, pcNames); + } + + *pcNames = 0; + if (!cMaxNames) return S_OK; + + if (memid_type == memid_func) + { + UINT index = This->func_memid_map[memid & ~DISPID_FUNCTION_MASK]; + UINT num = min(cMaxNames, This->funcs[index].func->arg_cnt + 1); + arg_desc_t *args = This->funcs[index].func->args; + + rgBstrNames[0] = SysAllocString(This->funcs[index].func->name); + if (!rgBstrNames[0]) return E_OUTOFMEMORY; + + for (i = 1; i < num; i++) + { + if (!(rgBstrNames[i] = SysAllocString(args[i - 1].name))) + { + do SysFreeString(rgBstrNames[--i]); while (i); + return E_OUTOFMEMORY; + } + } + } + else + { + rgBstrNames[0] = SysAllocString(This->disp->global_vars[memid - 1]->name); + if (!rgBstrNames[0]) return E_OUTOFMEMORY; + i++; + } + + *pcNames = i; + return S_OK; }
static HRESULT WINAPI ScriptTypeInfo_GetRefTypeOfImplType(ITypeInfo *iface, UINT index, HREFTYPE *pRefType) @@ -1119,21 +1190,36 @@ static HRESULT WINAPI ScriptDisp_GetTypeInfo(IDispatchEx *iface, UINT iTInfo, LC type_info->ref = 1; type_info->num_funcs = num_funcs; type_info->num_vars = This->global_vars_cnt; + type_info->func_memid_map_cnt = This->global_funcs_cnt + 1; type_info->disp = This;
+ type_info->func_memid_map = heap_alloc(sizeof(*type_info->func_memid_map) * type_info->func_memid_map_cnt); + if(!type_info->func_memid_map) + { + heap_free(type_info); + return E_OUTOFMEMORY; + } + type_info->funcs = heap_alloc(sizeof(*type_info->funcs) * num_funcs); if(!type_info->funcs) { + heap_free(type_info->func_memid_map); heap_free(type_info); return E_OUTOFMEMORY; }
+ type_info->func_memid_map[0] = ~0; for(j = 0, i = 0; i < This->global_funcs_cnt; i++) { - if(!This->global_funcs[i]->is_public) continue; + if(!This->global_funcs[i]->is_public) + { + type_info->func_memid_map[i + 1] = ~0; + continue; + }
type_info->funcs[j].memid = i + 1 + DISPID_FUNCTION_MASK; type_info->funcs[j].func = This->global_funcs[i]; + type_info->func_memid_map[i + 1] = j; grab_vbscode(This->global_funcs[i]->code_ctx); j++; }
On 12/9/19 4:29 PM, Gabriel Ivăncescu wrote:
+enum memid_type {
- memid_invalid,
- memid_inherited,
- memid_func,
- memid_var
+};
+static inline enum memid_type get_memid_type(const ScriptTypeInfo *typeinfo, MEMBERID memid) +{
- if (memid <= 0) return memid_invalid;
- if (memid & DISPID_FUNCTION_MASK)
- {
memid &= ~DISPID_FUNCTION_MASK;
if (memid >= typeinfo->func_memid_map_cnt)
return memid_inherited;
if (typeinfo->func_memid_map[memid] == ~0)
return memid_invalid;
return memid_func;
- }
- if (memid > typeinfo->num_vars)
return memid_inherited;
- return memid_var;
+}
It seems that could let default ITypeInfo handle invalid IDs and you could just forward all calls to unknown IDs to it. You don't need a new map for that, you could just use a binary search on funcs.
Thanks,
Jacek
On 12/10/19 5:35 PM, Jacek Caban wrote:
On 12/9/19 4:29 PM, Gabriel Ivăncescu wrote:
+enum memid_type { + memid_invalid, + memid_inherited, + memid_func, + memid_var +};
+static inline enum memid_type get_memid_type(const ScriptTypeInfo *typeinfo, MEMBERID memid) +{ + if (memid <= 0) return memid_invalid; + if (memid & DISPID_FUNCTION_MASK) + { + memid &= ~DISPID_FUNCTION_MASK; + if (memid >= typeinfo->func_memid_map_cnt) + return memid_inherited; + if (typeinfo->func_memid_map[memid] == ~0) + return memid_invalid; + return memid_func; + } + if (memid > typeinfo->num_vars) + return memid_inherited; + return memid_var; +}
It seems that could let default ITypeInfo handle invalid IDs and you could just forward all calls to unknown IDs to it. You don't need a new map for that, you could just use a binary search on funcs.
Thanks,
Jacek
Sure, that sounds like a good approach as well. I'll look into it tomorrow.
I have a question, though, about jscript (similar patch for jscript, not sent yet to mailing list). In jscript, variables and functions can be deleted, and so currently I have a map of memids for both vars and functions (just one map for both).
Should I also use a binary search there (needed for both variables and functions), or rather keep the single map for both, which I think is slightly simpler code?
Currently I identify whether an element in the map is a variable or a function by looking at where it points to: if it points within the bounds of the function array, then it's a function. So no extra fields needed, other than the map itself.
This is all for jscript of course (not vbscript or this patch, but related).
Thanks, Gabriel
Hi Gabriel,
On 12/10/19 6:17 PM, Gabriel Ivăncescu wrote:
On 12/10/19 5:35 PM, Jacek Caban wrote:
On 12/9/19 4:29 PM, Gabriel Ivăncescu wrote:
+enum memid_type { + memid_invalid, + memid_inherited, + memid_func, + memid_var +};
+static inline enum memid_type get_memid_type(const ScriptTypeInfo *typeinfo, MEMBERID memid) +{ + if (memid <= 0) return memid_invalid; + if (memid & DISPID_FUNCTION_MASK) + { + memid &= ~DISPID_FUNCTION_MASK; + if (memid >= typeinfo->func_memid_map_cnt) + return memid_inherited; + if (typeinfo->func_memid_map[memid] == ~0) + return memid_invalid; + return memid_func; + } + if (memid > typeinfo->num_vars) + return memid_inherited; + return memid_var; +}
It seems that could let default ITypeInfo handle invalid IDs and you could just forward all calls to unknown IDs to it. You don't need a new map for that, you could just use a binary search on funcs.
Thanks,
Jacek
Sure, that sounds like a good approach as well. I'll look into it tomorrow.
I have a question, though, about jscript (similar patch for jscript, not sent yet to mailing list). In jscript, variables and functions can be deleted, and so currently I have a map of memids for both vars and functions (just one map for both).
Should I also use a binary search there (needed for both variables and functions), or rather keep the single map for both, which I think is slightly simpler code?
Currently I identify whether an element in the map is a variable or a function by looking at where it points to: if it points within the bounds of the function array, then it's a function. So no extra fields needed, other than the map itself.
This is all for jscript of course (not vbscript or this patch, but related).
I'm not sure without looking at the code, but two binary searches seem fine.
Thanks,
Jacek
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com ---
The return value matches Windows and makes sense for GetRefTypeInfo.
dlls/vbscript/vbdisp.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/dlls/vbscript/vbdisp.c b/dlls/vbscript/vbdisp.c index 5d43c43..d14a2f6 100644 --- a/dlls/vbscript/vbdisp.c +++ b/dlls/vbscript/vbdisp.c @@ -788,9 +788,14 @@ static HRESULT WINAPI ScriptTypeInfo_GetRefTypeOfImplType(ITypeInfo *iface, UINT { ScriptTypeInfo *This = ScriptTypeInfo_from_ITypeInfo(iface);
- FIXME("(%p)->(%u %p)\n", This, index, pRefType); + TRACE("(%p)->(%u %p)\n", This, index, pRefType);
- return E_NOTIMPL; + /* We only inherit from IDispatch */ + if (!pRefType) return E_INVALIDARG; + if (index != 0) return TYPE_E_ELEMENTNOTFOUND; + + *pRefType = 1; + return S_OK; }
static HRESULT WINAPI ScriptTypeInfo_GetImplTypeFlags(ITypeInfo *iface, UINT index, INT *pImplTypeFlags)
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com ---
The hRefType value is taken from wine's oleaut32 source and verified on Windows (and on tests).
dlls/vbscript/vbdisp.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/dlls/vbscript/vbdisp.c b/dlls/vbscript/vbdisp.c index d14a2f6..db94478 100644 --- a/dlls/vbscript/vbdisp.c +++ b/dlls/vbscript/vbdisp.c @@ -892,10 +892,23 @@ static HRESULT WINAPI ScriptTypeInfo_GetDllEntry(ITypeInfo *iface, MEMBERID memi static HRESULT WINAPI ScriptTypeInfo_GetRefTypeInfo(ITypeInfo *iface, HREFTYPE hRefType, ITypeInfo **ppTInfo) { ScriptTypeInfo *This = ScriptTypeInfo_from_ITypeInfo(iface); + HRESULT hr;
- FIXME("(%p)->(%x %p)\n", This, hRefType, ppTInfo); + TRACE("(%p)->(%x %p)\n", This, hRefType, ppTInfo);
- return E_NOTIMPL; + if (!ppTInfo || (INT)hRefType < 0) return E_INVALIDARG; + + if (hRefType & ~3) return E_FAIL; + if (hRefType & 1) + { + hr = get_dispatch_typeinfo(ppTInfo); + if (FAILED(hr)) return hr; + } + else + *ppTInfo = iface; + + ITypeInfo_AddRef(*ppTInfo); + return S_OK; }
static HRESULT WINAPI ScriptTypeInfo_AddressOfMember(ITypeInfo *iface, MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/vbscript/vbdisp.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/dlls/vbscript/vbdisp.c b/dlls/vbscript/vbdisp.c index db94478..a74b0ba 100644 --- a/dlls/vbscript/vbdisp.c +++ b/dlls/vbscript/vbdisp.c @@ -802,9 +802,13 @@ static HRESULT WINAPI ScriptTypeInfo_GetImplTypeFlags(ITypeInfo *iface, UINT ind { ScriptTypeInfo *This = ScriptTypeInfo_from_ITypeInfo(iface);
- FIXME("(%p)->(%u %p)\n", This, index, pImplTypeFlags); + TRACE("(%p)->(%u %p)\n", This, index, pImplTypeFlags);
- return E_NOTIMPL; + if (!pImplTypeFlags) return E_INVALIDARG; + if (index != 0) return TYPE_E_ELEMENTNOTFOUND; + + *pImplTypeFlags = 0; + return S_OK; }
static HRESULT WINAPI ScriptTypeInfo_GetIDsOfNames(ITypeInfo *iface, LPOLESTR *rgszNames, UINT cNames,
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/vbscript/vbdisp.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-)
diff --git a/dlls/vbscript/vbdisp.c b/dlls/vbscript/vbdisp.c index a74b0ba..242010d 100644 --- a/dlls/vbscript/vbdisp.c +++ b/dlls/vbscript/vbdisp.c @@ -866,11 +866,33 @@ static HRESULT WINAPI ScriptTypeInfo_Invoke(ITypeInfo *iface, PVOID pvInstance, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) { ScriptTypeInfo *This = ScriptTypeInfo_from_ITypeInfo(iface); + enum memid_type memid_type = get_memid_type(This, memid); + ITypeInfo *disp_typeinfo; + IDispatch *disp; + HRESULT hr;
- FIXME("(%p)->(%p %d %d %p %p %p %p)\n", This, pvInstance, memid, wFlags, + TRACE("(%p)->(%p %d %d %p %p %p %p)\n", This, pvInstance, memid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
- return E_NOTIMPL; + if (!pvInstance) return E_INVALIDARG; + if (memid_type == memid_invalid) return TYPE_E_ELEMENTNOTFOUND; + if (memid_type == memid_inherited) + { + hr = get_dispatch_typeinfo(&disp_typeinfo); + if (FAILED(hr)) return hr; + + return ITypeInfo_Invoke(disp_typeinfo, pvInstance, memid, wFlags, pDispParams, + pVarResult, pExcepInfo, puArgErr); + } + + hr = IUnknown_QueryInterface((IUnknown*)pvInstance, &IID_IDispatch, (void**)&disp); + if (FAILED(hr)) return hr; + + hr = IDispatch_Invoke(disp, memid, &IID_NULL, LOCALE_USER_DEFAULT, wFlags, + pDispParams, pVarResult, pExcepInfo, puArgErr); + IDispatch_Release(disp); + + return hr; }
static HRESULT WINAPI ScriptTypeInfo_GetDocumentation(ITypeInfo *iface, MEMBERID memid, BSTR *pBstrName,
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com ---
The DocString is not localized because it's not part of the DLL's resources in Windows, either.
dlls/vbscript/vbdisp.c | 45 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-)
diff --git a/dlls/vbscript/vbdisp.c b/dlls/vbscript/vbdisp.c index 242010d..5044115 100644 --- a/dlls/vbscript/vbdisp.c +++ b/dlls/vbscript/vbdisp.c @@ -899,10 +899,51 @@ static HRESULT WINAPI ScriptTypeInfo_GetDocumentation(ITypeInfo *iface, MEMBERID BSTR *pBstrDocString, DWORD *pdwHelpContext, BSTR *pBstrHelpFile) { ScriptTypeInfo *This = ScriptTypeInfo_from_ITypeInfo(iface); + enum memid_type memid_type = get_memid_type(This, memid); + ITypeInfo *disp_typeinfo; + HRESULT hr;
- FIXME("(%p)->(%d %p %p %p %p)\n", This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile); + TRACE("(%p)->(%d %p %p %p %p)\n", This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
- return E_NOTIMPL; + if (pBstrDocString) *pBstrDocString = NULL; + if (pdwHelpContext) *pdwHelpContext = 0; + if (pBstrHelpFile) *pBstrHelpFile = NULL; + + if (memid == MEMBERID_NIL) + { + if (pBstrName && !(*pBstrName = SysAllocString(L"VBScriptTypeInfo"))) + return STG_E_INSUFFICIENTMEMORY; + if (pBstrDocString && + !(*pBstrDocString = SysAllocString(L"Visual Basic Scripting Type Info"))) + { + if (pBstrName) SysFreeString(*pBstrName); + return STG_E_INSUFFICIENTMEMORY; + } + return S_OK; + } + if (memid_type == memid_invalid) return TYPE_E_ELEMENTNOTFOUND; + if (memid_type == memid_inherited) + { + hr = get_dispatch_typeinfo(&disp_typeinfo); + if (FAILED(hr)) return hr; + + return ITypeInfo_GetDocumentation(disp_typeinfo, memid, pBstrName, pBstrDocString, + pdwHelpContext, pBstrHelpFile); + } + + if (pBstrName) + { + const WCHAR *name; + + if (memid_type == memid_func) + name = This->funcs[This->func_memid_map[memid & ~DISPID_FUNCTION_MASK]].func->name; + else + name = This->disp->global_vars[memid - 1]->name; + + *pBstrName = SysAllocString(name); + if (!*pBstrName) return STG_E_INSUFFICIENTMEMORY; + } + return S_OK; }
static HRESULT WINAPI ScriptTypeInfo_GetDllEntry(ITypeInfo *iface, MEMBERID memid, INVOKEKIND invKind,
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/vbscript/vbdisp.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/dlls/vbscript/vbdisp.c b/dlls/vbscript/vbdisp.c index 5044115..9f34f78 100644 --- a/dlls/vbscript/vbdisp.c +++ b/dlls/vbscript/vbdisp.c @@ -950,10 +950,23 @@ static HRESULT WINAPI ScriptTypeInfo_GetDllEntry(ITypeInfo *iface, MEMBERID memi BSTR *pBstrDllName, BSTR *pBstrName, WORD *pwOrdinal) { ScriptTypeInfo *This = ScriptTypeInfo_from_ITypeInfo(iface); + ITypeInfo *disp_typeinfo; + HRESULT hr;
- FIXME("(%p)->(%d %d %p %p %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal); + TRACE("(%p)->(%d %d %p %p %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
- return E_NOTIMPL; + if (pBstrDllName) *pBstrDllName = NULL; + if (pBstrName) *pBstrName = NULL; + if (pwOrdinal) *pwOrdinal = 0; + + if (get_memid_type(This, memid) == memid_inherited) + { + hr = get_dispatch_typeinfo(&disp_typeinfo); + if (FAILED(hr)) return hr; + + return ITypeInfo_GetDllEntry(disp_typeinfo, memid, invKind, pBstrDllName, pBstrName, pwOrdinal); + } + return TYPE_E_BADMODULEKIND; }
static HRESULT WINAPI ScriptTypeInfo_GetRefTypeInfo(ITypeInfo *iface, HREFTYPE hRefType, ITypeInfo **ppTInfo)
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/vbscript/vbdisp.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/dlls/vbscript/vbdisp.c b/dlls/vbscript/vbdisp.c index 9f34f78..447700f 100644 --- a/dlls/vbscript/vbdisp.c +++ b/dlls/vbscript/vbdisp.c @@ -994,10 +994,22 @@ static HRESULT WINAPI ScriptTypeInfo_GetRefTypeInfo(ITypeInfo *iface, HREFTYPE h static HRESULT WINAPI ScriptTypeInfo_AddressOfMember(ITypeInfo *iface, MEMBERID memid, INVOKEKIND invKind, PVOID *ppv) { ScriptTypeInfo *This = ScriptTypeInfo_from_ITypeInfo(iface); + ITypeInfo *disp_typeinfo; + HRESULT hr;
- FIXME("(%p)->(%d %d %p)\n", This, memid, invKind, ppv); + TRACE("(%p)->(%d %d %p)\n", This, memid, invKind, ppv);
- return E_NOTIMPL; + if (!ppv) return E_INVALIDARG; + *ppv = NULL; + + if (get_memid_type(This, memid) == memid_inherited) + { + hr = get_dispatch_typeinfo(&disp_typeinfo); + if (FAILED(hr)) return hr; + + return ITypeInfo_AddressOfMember(disp_typeinfo, memid, invKind, ppv); + } + return TYPE_E_BADMODULEKIND; }
static HRESULT WINAPI ScriptTypeInfo_CreateInstance(ITypeInfo *iface, IUnknown *pUnkOuter, REFIID riid, PVOID *ppvObj)
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/vbscript/vbdisp.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/dlls/vbscript/vbdisp.c b/dlls/vbscript/vbdisp.c index 447700f..0ea785c 100644 --- a/dlls/vbscript/vbdisp.c +++ b/dlls/vbscript/vbdisp.c @@ -1016,9 +1016,12 @@ static HRESULT WINAPI ScriptTypeInfo_CreateInstance(ITypeInfo *iface, IUnknown * { ScriptTypeInfo *This = ScriptTypeInfo_from_ITypeInfo(iface);
- FIXME("(%p)->(%p %s %p)\n", This, pUnkOuter, debugstr_guid(riid), ppvObj); + TRACE("(%p)->(%p %s %p)\n", This, pUnkOuter, debugstr_guid(riid), ppvObj);
- return E_NOTIMPL; + if (!ppvObj) return E_INVALIDARG; + + *ppvObj = NULL; + return TYPE_E_BADMODULEKIND; }
static HRESULT WINAPI ScriptTypeInfo_GetMops(ITypeInfo *iface, MEMBERID memid, BSTR *pBstrMops)
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/vbscript/vbdisp.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/dlls/vbscript/vbdisp.c b/dlls/vbscript/vbdisp.c index 0ea785c..4601ef5 100644 --- a/dlls/vbscript/vbdisp.c +++ b/dlls/vbscript/vbdisp.c @@ -1027,10 +1027,23 @@ static HRESULT WINAPI ScriptTypeInfo_CreateInstance(ITypeInfo *iface, IUnknown * static HRESULT WINAPI ScriptTypeInfo_GetMops(ITypeInfo *iface, MEMBERID memid, BSTR *pBstrMops) { ScriptTypeInfo *This = ScriptTypeInfo_from_ITypeInfo(iface); + ITypeInfo *disp_typeinfo; + HRESULT hr;
- FIXME("(%p)->(%d %p)\n", This, memid, pBstrMops); + TRACE("(%p)->(%d %p)\n", This, memid, pBstrMops);
- return E_NOTIMPL; + if (!pBstrMops) return E_INVALIDARG; + + if (get_memid_type(This, memid) == memid_inherited) + { + hr = get_dispatch_typeinfo(&disp_typeinfo); + if (FAILED(hr)) return hr; + + return ITypeInfo_GetMops(disp_typeinfo, memid, pBstrMops); + } + + *pBstrMops = NULL; + return S_OK; }
static HRESULT WINAPI ScriptTypeInfo_GetContainingTypeLib(ITypeInfo *iface, ITypeLib **ppTLib, UINT *pIndex)
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/vbscript/tests/vbscript.c | 126 ++++++++++++++++++++++++++++++++- 1 file changed, 125 insertions(+), 1 deletion(-)
diff --git a/dlls/vbscript/tests/vbscript.c b/dlls/vbscript/tests/vbscript.c index ad3ccf3..f0b75ad 100644 --- a/dlls/vbscript/tests/vbscript.c +++ b/dlls/vbscript/tests/vbscript.c @@ -893,12 +893,16 @@ static void test_script_typeinfo(void) FUNCDESC *funcdesc; VARDESC *vardesc; DESCKIND desckind; + INT implTypeFlags; + UINT count, index; + HREFTYPE reftype; BINDPTR bindptr; MEMBERID memid; TYPEATTR *attr; - UINT index; HRESULT hr; WCHAR str[64], *names = str; + BSTR bstr, bstrs[5]; + void *obj; int i;
vbscript = create_vbscript(); @@ -961,6 +965,20 @@ static void test_script_typeinfo(void) ok(typeinfo != typeinfo2, "TypeInfo was not supposed to be shared.\n"); ITypeInfo_Release(typeinfo2);
+ obj = (void*)0xdeadbeef; + hr = ITypeInfo_CreateInstance(typeinfo, NULL, NULL, NULL); + ok(hr == E_INVALIDARG, "CreateInstance returned: %08x\n", hr); + hr = ITypeInfo_CreateInstance(typeinfo, NULL, NULL, &obj); + ok(hr == TYPE_E_BADMODULEKIND, "CreateInstance returned: %08x\n", hr); + hr = ITypeInfo_CreateInstance(typeinfo, NULL, &IID_IDispatch, &obj); + ok(hr == TYPE_E_BADMODULEKIND, "CreateInstance returned: %08x\n", hr); + ok(!obj, "Unexpected non-null obj %p.\n", obj); + + hr = ITypeInfo_GetDocumentation(typeinfo, MEMBERID_NIL, &bstr, NULL, NULL, NULL); + ok(hr == S_OK, "GetDocumentation(MEMBERID_NIL) failed: %08x\n", hr); + ok(!lstrcmpW(bstr, L"VBScriptTypeInfo"), "Unexpected TypeInfo name %s\n", wine_dbgstr_w(bstr)); + SysFreeString(bstr); + hr = ITypeInfo_GetTypeAttr(typeinfo, &attr); ok(hr == S_OK, "GetTypeAttr failed: %08x\n", hr); ok(IsEqualGUID(&attr->guid, &IID_IScriptTypeInfo), "Unexpected GUID %s\n", wine_dbgstr_guid(&attr->guid)); @@ -979,6 +997,45 @@ static void test_script_typeinfo(void) ok(attr->idldescType.wIDLFlags == IDLFLAG_NONE, "Unexpected idldescType.wIDLFlags 0x%x\n", attr->idldescType.wIDLFlags); ITypeInfo_ReleaseTypeAttr(typeinfo, attr);
+ /* The type inherits from IDispatch */ + hr = ITypeInfo_GetImplTypeFlags(typeinfo, 0, NULL); + ok(hr == E_INVALIDARG, "GetImplTypeFlags returned: %08x\n", hr); + hr = ITypeInfo_GetImplTypeFlags(typeinfo, 1, &implTypeFlags); + ok(hr == TYPE_E_ELEMENTNOTFOUND, "GetImplTypeFlags returned: %08x\n", hr); + hr = ITypeInfo_GetImplTypeFlags(typeinfo, -1, &implTypeFlags); + ok(hr == TYPE_E_ELEMENTNOTFOUND, "GetImplTypeFlags returned: %08x\n", hr); + hr = ITypeInfo_GetImplTypeFlags(typeinfo, 0, &implTypeFlags); + ok(hr == S_OK, "GetImplTypeFlags failed: %08x\n", hr); + ok(implTypeFlags == 0, "Unexpected implTypeFlags 0x%x\n", implTypeFlags); + + hr = ITypeInfo_GetRefTypeOfImplType(typeinfo, 0, NULL); + ok(hr == E_INVALIDARG, "GetRefTypeOfImplType returned: %08x\n", hr); + hr = ITypeInfo_GetRefTypeOfImplType(typeinfo, 1, &reftype); + ok(hr == TYPE_E_ELEMENTNOTFOUND, "GetRefTypeOfImplType returned: %08x\n", hr); + hr = ITypeInfo_GetRefTypeOfImplType(typeinfo, -1, &reftype); + ok(hr == TYPE_E_ELEMENTNOTFOUND, "GetRefTypeOfImplType failed: %08x\n", hr); + hr = ITypeInfo_GetRefTypeOfImplType(typeinfo, 0, &reftype); + ok(hr == S_OK, "GetRefTypeOfImplType failed: %08x\n", hr); + ok(reftype == 1, "Unexpected reftype %d\n", reftype); + + hr = ITypeInfo_GetRefTypeInfo(typeinfo, reftype, NULL); + ok(hr == E_INVALIDARG, "GetRefTypeInfo returned: %08x\n", hr); + hr = ITypeInfo_GetRefTypeInfo(typeinfo, -1, &typeinfo2); + ok(hr == E_INVALIDARG, "GetRefTypeInfo returned: %08x\n", hr); + hr = ITypeInfo_GetRefTypeInfo(typeinfo, 4, &typeinfo2); + ok(hr == E_FAIL, "GetRefTypeInfo returned: %08x\n", hr); + hr = ITypeInfo_GetRefTypeInfo(typeinfo, 0, &typeinfo2); + ok(hr == S_OK, "GetRefTypeInfo failed: %08x\n", hr); + ok(typeinfo == typeinfo2, "Unexpected TypeInfo %p (expected %p)\n", typeinfo2, typeinfo); + ITypeInfo_Release(typeinfo2); + hr = ITypeInfo_GetRefTypeInfo(typeinfo, reftype, &typeinfo2); + ok(hr == S_OK, "GetRefTypeInfo failed: %08x\n", hr); + hr = ITypeInfo_GetDocumentation(typeinfo2, MEMBERID_NIL, &bstr, NULL, NULL, NULL); + ok(hr == S_OK, "GetDocumentation(MEMBERID_NIL) failed: %08x\n", hr); + ok(!lstrcmpW(bstr, L"IDispatch"), "Unexpected TypeInfo name %s\n", wine_dbgstr_w(bstr)); + ITypeInfo_Release(typeinfo2); + SysFreeString(bstr); + /* GetIDsOfNames looks into the inherited types as well */ wcscpy(str, L"queryinterface"); hr = ITypeInfo_GetIDsOfNames(typeinfo, NULL, 1, &memid); @@ -998,6 +1055,53 @@ static void test_script_typeinfo(void) ok(hr == S_OK, "GetIDsOfNames failed: %08x\n", hr); ok(!lstrcmpW(str, L"SUBtract"), "Unexpected string %s\n", wine_dbgstr_w(str));
+ hr = ITypeInfo_GetNames(typeinfo, memid, NULL, 1, &count); + ok(hr == E_INVALIDARG, "GetNames returned: %08x\n", hr); + hr = ITypeInfo_GetNames(typeinfo, memid, bstrs, 1, NULL); + ok(hr == E_INVALIDARG, "GetNames returned: %08x\n", hr); + hr = ITypeInfo_GetNames(typeinfo, memid, bstrs, 0, &count); + ok(hr == S_OK, "GetNames failed: %08x\n", hr); + ok(count == 0, "Unexpected count %u\n", count); + hr = ITypeInfo_GetNames(typeinfo, memid, bstrs, ARRAY_SIZE(bstrs), &count); + ok(hr == S_OK, "GetNames failed: %08x\n", hr); + ok(count == 3, "Unexpected count %u\n", count); + ok(!lstrcmpW(bstrs[0], L"subtract"), "Unexpected function name %s\n", wine_dbgstr_w(bstrs[0])); + ok(!lstrcmpW(bstrs[1], L"x"), "Unexpected function first param name %s\n", wine_dbgstr_w(bstrs[1])); + ok(!lstrcmpW(bstrs[2], L"y"), "Unexpected function second param name %s\n", wine_dbgstr_w(bstrs[2])); + for (i = 0; i < count; i++) SysFreeString(bstrs[i]); + + hr = ITypeInfo_GetMops(typeinfo, memid, NULL); + ok(hr == E_INVALIDARG, "GetMops returned: %08x\n", hr); + hr = ITypeInfo_GetMops(typeinfo, memid, &bstr); + ok(hr == S_OK, "GetMops failed: %08x\n", hr); + ok(!bstr, "Unexpected non-null string %s\n", wine_dbgstr_w(bstr)); + hr = ITypeInfo_GetMops(typeinfo, MEMBERID_NIL, &bstr); + ok(hr == S_OK, "GetMops failed: %08x\n", hr); + ok(!bstr, "Unexpected non-null string %s\n", wine_dbgstr_w(bstr)); + + /* These always fail */ + obj = (void*)0xdeadbeef; + hr = ITypeInfo_AddressOfMember(typeinfo, memid, INVOKE_FUNC, NULL); + ok(hr == E_INVALIDARG, "AddressOfMember returned: %08x\n", hr); + hr = ITypeInfo_AddressOfMember(typeinfo, memid, INVOKE_FUNC, &obj); + ok(hr == TYPE_E_BADMODULEKIND, "AddressOfMember returned: %08x\n", hr); + ok(!obj, "Unexpected non-null obj %p.\n", obj); + bstr = (BSTR)0xdeadbeef; + hr = ITypeInfo_GetDllEntry(typeinfo, memid, INVOKE_FUNC, &bstr, NULL, NULL); + ok(hr == TYPE_E_BADMODULEKIND, "GetDllEntry returned: %08x\n", hr); + ok(!bstr, "Unexpected non-null str %p.\n", bstr); + wcscpy(str, L"Invoke"); + hr = ITypeInfo_GetIDsOfNames(typeinfo, &names, 1, &memid); + ok(hr == S_OK, "GetIDsOfNames failed: %08x\n", hr); + obj = (void*)0xdeadbeef; + hr = ITypeInfo_AddressOfMember(typeinfo, memid, INVOKE_FUNC, &obj); + ok(hr == TYPE_E_BADMODULEKIND, "AddressOfMember returned: %08x\n", hr); + ok(!obj, "Unexpected non-null obj %p.\n", obj); + bstr = (BSTR)0xdeadbeef; + hr = ITypeInfo_GetDllEntry(typeinfo, memid, INVOKE_FUNC, &bstr, NULL, NULL); + ok(hr == TYPE_E_BADMODULEKIND, "GetDllEntry returned: %08x\n", hr); + ok(!bstr, "Unexpected non-null str %p.\n", bstr); + /* Check variable descriptions */ hr = ITypeInfo_GetVarDesc(typeinfo, 0, NULL); ok(hr == E_INVALIDARG, "GetVarDesc returned: %08x\n", hr); @@ -1007,6 +1111,12 @@ static void test_script_typeinfo(void) { hr = ITypeInfo_GetVarDesc(typeinfo, i, &vardesc); ok(hr == S_OK, "GetVarDesc(%u) failed: %08x\n", i, hr); + hr = ITypeInfo_GetDocumentation(typeinfo, vardesc->memid, &bstr, &bstrs[0], NULL, NULL); + ok(hr == S_OK, "[%u] GetDocumentation failed: %08x\n", i, hr); + ok(!lstrcmpW(bstr, var[i].name), "[%u] Unexpected variable name %s (expected %s)\n", + i, wine_dbgstr_w(bstr), wine_dbgstr_w(var[i].name)); + ok(!bstrs[0], "[%u] Unexpected doc string %s\n", i, wine_dbgstr_w(bstrs[0])); + SysFreeString(bstr); ok(vardesc->lpstrSchema == NULL, "[%u] Unexpected lpstrSchema %p\n", i, vardesc->lpstrSchema); ok(vardesc->oInst == 0, "[%u] Unexpected oInst %u\n", i, vardesc->oInst); ok(vardesc->varkind == VAR_DISPATCH, "[%u] Unexpected varkind %d\n", i, vardesc->varkind); @@ -1029,6 +1139,12 @@ static void test_script_typeinfo(void) { hr = ITypeInfo_GetFuncDesc(typeinfo, i, &funcdesc); ok(hr == S_OK, "GetFuncDesc(%u) failed: %08x\n", i, hr); + hr = ITypeInfo_GetDocumentation(typeinfo, funcdesc->memid, &bstr, &bstrs[0], NULL, NULL); + ok(hr == S_OK, "[%u] GetDocumentation failed: %08x\n", i, hr); + ok(!lstrcmpW(bstr, func[i].name), "[%u] Unexpected function name %s (expected %s)\n", + i, wine_dbgstr_w(bstr), wine_dbgstr_w(func[i].name)); + ok(!bstrs[0], "[%u] Unexpected doc string %s\n", i, wine_dbgstr_w(bstrs[0])); + SysFreeString(bstr); ok(funcdesc->lprgscode == NULL, "[%u] Unexpected lprgscode %p\n", i, funcdesc->lprgscode); ok(func[i].num_args ? (funcdesc->lprgelemdescParam != NULL) : (funcdesc->lprgelemdescParam == NULL), "[%u] Unexpected lprgelemdescParam %p\n", i, funcdesc->lprgelemdescParam); @@ -1159,6 +1275,14 @@ static void test_script_typeinfo(void) ok(attr->cFuncs == ARRAY_SIZE(func) + 1, "Unexpected cFuncs %u\n", attr->cFuncs); ok(attr->cVars == ARRAY_SIZE(var) + 1, "Unexpected cVars %u\n", attr->cVars); ITypeInfo_ReleaseTypeAttr(typeinfo2, attr); + hr = ITypeInfo_GetVarDesc(typeinfo2, ARRAY_SIZE(var), &vardesc); + ok(hr == S_OK, "GetVarDesc failed: %08x\n", hr); + hr = ITypeInfo_GetDocumentation(typeinfo2, vardesc->memid, &bstr, &bstrs[0], NULL, NULL); + ok(hr == S_OK, "GetDocumentation failed: %08x\n", hr); + ok(!lstrcmpW(bstr, L"new_var"), "Unexpected variable name %s\n", wine_dbgstr_w(bstr)); + ok(!bstrs[0], "Unexpected doc string %s\n", wine_dbgstr_w(bstrs[0])); + ITypeInfo_ReleaseVarDesc(typeinfo2, vardesc); + SysFreeString(bstr); hr = ITypeInfo_GetFuncDesc(typeinfo, 0, &funcdesc); ok(hr == S_OK, "GetFuncDesc failed: %08x\n", hr); ok(funcdesc->cParams == 0, "Unexpected cParams %d\n", funcdesc->cParams);