Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- include/uiautomationclient.idl | 43 ++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+)
diff --git a/include/uiautomationclient.idl b/include/uiautomationclient.idl index a353a63816b..917d3456ebf 100644 --- a/include/uiautomationclient.idl +++ b/include/uiautomationclient.idl @@ -27,6 +27,49 @@ import "uiautomationcore.idl"; library UIAutomationClient { importlib ("stdole2.tlb");
+ /* FIXME: Uncomment when properly supported in widl + [dllname("<no entry points>")] + module UIA_PatternIds + { + */ + const long UIA_InvokePatternId = 10000; + const long UIA_SelectionPatternId = 10001; + const long UIA_ValuePatternId = 10002; + const long UIA_RangeValuePatternId = 10003; + const long UIA_ScrollPatternId = 10004; + const long UIA_ExpandCollapsePatternId = 10005; + const long UIA_GridPatternId = 10006; + const long UIA_GridItemPatternId = 10007; + const long UIA_MultipleViewPatternId = 10008; + const long UIA_WindowPatternId = 10009; + const long UIA_SelectionItemPatternId = 10010; + const long UIA_DockPatternId = 10011; + const long UIA_TablePatternId = 10012; + const long UIA_TableItemPatternId = 10013; + const long UIA_TextPatternId = 10014; + const long UIA_TogglePatternId = 10015; + const long UIA_TransformPatternId = 10016; + const long UIA_ScrollItemPatternId = 10017; + const long UIA_LegacyIAccessiblePatternId = 10018; + const long UIA_ItemContainerPatternId = 10019; + const long UIA_VirtualizedItemPatternId = 10020; + const long UIA_SynchronizedInputPatternId = 10021; + const long UIA_ObjectModelPatternId = 10022; + const long UIA_AnnotationPatternId = 10023; + const long UIA_TextPattern2Id = 10024; + const long UIA_StylesPatternId = 10025; + const long UIA_SpreadsheetPatternId = 10026; + const long UIA_SpreadsheetItemPatternId = 10027; + const long UIA_TransformPattern2Id = 10028; + const long UIA_TextChildPatternId = 10029; + const long UIA_DragPatternId = 10030; + const long UIA_DropTargetPatternId = 10031; + const long UIA_TextEditPatternId = 10032; + const long UIA_CustomNavigationPatternId = 10033; + /* + } + */ + /* FIXME: Uncomment when properly supported in widl [dllname("<no entry points>")] module UIA_PropertyIds
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/uiautomationcore/Makefile.in | 2 +- dlls/uiautomationcore/tests/uiautomation.c | 7 +- dlls/uiautomationcore/uia_main.c | 134 ++++++++++++++++++++- 3 files changed, 134 insertions(+), 9 deletions(-)
diff --git a/dlls/uiautomationcore/Makefile.in b/dlls/uiautomationcore/Makefile.in index 5a72ea144c4..f0973fdec4c 100644 --- a/dlls/uiautomationcore/Makefile.in +++ b/dlls/uiautomationcore/Makefile.in @@ -1,6 +1,6 @@ MODULE = uiautomationcore.dll IMPORTLIB = uiautomationcore -IMPORTS = uuid ole32 +IMPORTS = uuid ole32 oleaut32 user32
EXTRADLLFLAGS = -Wb,--prefer-native
diff --git a/dlls/uiautomationcore/tests/uiautomation.c b/dlls/uiautomationcore/tests/uiautomation.c index 52a6648dad2..76d2e06e07e 100644 --- a/dlls/uiautomationcore/tests/uiautomation.c +++ b/dlls/uiautomationcore/tests/uiautomation.c @@ -58,17 +58,13 @@ static void test_UiaHostProviderFromHwnd(void)
p = (void *)0xdeadbeef; hr = UiaHostProviderFromHwnd(NULL, &p); -todo_wine { ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr); ok(p == NULL, "Unexpected instance.\n"); -} + p = NULL; hr = UiaHostProviderFromHwnd(hwnd, &p); -todo_wine ok(hr == S_OK, "Failed to get host provider, hr %#x.\n", hr);
-if (hr == S_OK) -{ p2 = NULL; hr = UiaHostProviderFromHwnd(hwnd, &p2); ok(hr == S_OK, "Failed to get host provider, hr %#x.\n", hr); @@ -80,7 +76,6 @@ if (hr == S_OK) ok(p2 == NULL, "Unexpected instance.\n");
IRawElementProviderSimple_Release(p); -}
DestroyWindow(hwnd); UnregisterClassA("HostProviderFromHwnd class", NULL); diff --git a/dlls/uiautomationcore/uia_main.c b/dlls/uiautomationcore/uia_main.c index 174e4756920..44fd42742d9 100644 --- a/dlls/uiautomationcore/uia_main.c +++ b/dlls/uiautomationcore/uia_main.c @@ -18,6 +18,7 @@
#define COBJMACROS
+#include "initguid.h" #include "uiautomation.h"
#include "wine/debug.h" @@ -145,6 +146,117 @@ static const IUnknownVtbl uia_reserved_obj_vtbl = { static IUnknown uia_reserved_ns_iface = {&uia_reserved_obj_vtbl}; static IUnknown uia_reserved_ma_iface = {&uia_reserved_obj_vtbl};
+/* + * UiaHostProviderFromHwnd IRawElementProviderSimple interface. + */ +struct hwnd_host_provider { + IRawElementProviderSimple IRawElementProviderSimple_iface; + LONG refcount; + + HWND hwnd; +}; + +static inline struct hwnd_host_provider *impl_from_hwnd_host_provider(IRawElementProviderSimple *iface) +{ + return CONTAINING_RECORD(iface, struct hwnd_host_provider, IRawElementProviderSimple_iface); +} + +HRESULT WINAPI hwnd_host_provider_QueryInterface(IRawElementProviderSimple *iface, REFIID riid, void **ppv) +{ + *ppv = NULL; + if (IsEqualIID(riid, &IID_IRawElementProviderSimple) || IsEqualIID(riid, &IID_IUnknown)) + *ppv = iface; + else + return E_NOINTERFACE; + + IRawElementProviderSimple_AddRef(iface); + return S_OK; +} + +ULONG WINAPI hwnd_host_provider_AddRef(IRawElementProviderSimple *iface) +{ + struct hwnd_host_provider *host_prov = impl_from_hwnd_host_provider(iface); + ULONG refcount = InterlockedIncrement(&host_prov->refcount); + + TRACE("%p, refcount %d\n", iface, refcount); + + return refcount; +} + +ULONG WINAPI hwnd_host_provider_Release(IRawElementProviderSimple *iface) +{ + struct hwnd_host_provider *host_prov = impl_from_hwnd_host_provider(iface); + ULONG refcount = InterlockedDecrement(&host_prov->refcount); + + TRACE("%p, refcount %d\n", iface, refcount); + + if (!refcount) + heap_free(host_prov); + + return refcount; +} + +HRESULT WINAPI hwnd_host_provider_get_ProviderOptions(IRawElementProviderSimple *iface, + enum ProviderOptions *ret_val) +{ + TRACE("%p, %p\n", iface, ret_val); + *ret_val = ProviderOptions_ServerSideProvider; + return S_OK; +} + +HRESULT WINAPI hwnd_host_provider_GetPatternProvider(IRawElementProviderSimple *iface, + PATTERNID pattern_id, IUnknown **ret_val) +{ + TRACE("%p, %d, %p\n", iface, pattern_id, ret_val); + *ret_val = NULL; + return S_OK; +} + +HRESULT WINAPI hwnd_host_provider_GetPropertyValue(IRawElementProviderSimple *iface, + PROPERTYID prop_id, VARIANT *ret_val) +{ + struct hwnd_host_provider *host_prov = impl_from_hwnd_host_provider(iface); + + TRACE("%p, %d, %p\n", iface, prop_id, ret_val); + + VariantInit(ret_val); + switch (prop_id) + { + case UIA_NativeWindowHandlePropertyId: + V_VT(ret_val) = VT_I4; + V_I4(ret_val) = HandleToUlong(host_prov->hwnd); + break; + + case UIA_ProviderDescriptionPropertyId: + V_VT(ret_val) = VT_BSTR; + V_BSTR(ret_val) = SysAllocString(L"Wine: HWND Provider Proxy"); + break; + + default: + break; + } + + return S_OK; +} + +HRESULT WINAPI hwnd_host_provider_get_HostRawElementProvider(IRawElementProviderSimple *iface, + IRawElementProviderSimple **ret_val) +{ + TRACE("%p, %p\n", iface, ret_val); + *ret_val = NULL; + return S_OK; +} + +IRawElementProviderSimpleVtbl hwnd_host_provider_vtbl = { + hwnd_host_provider_QueryInterface, + hwnd_host_provider_AddRef, + hwnd_host_provider_Release, + hwnd_host_provider_get_ProviderOptions, + hwnd_host_provider_GetPatternProvider, + hwnd_host_provider_GetPropertyValue, + hwnd_host_provider_get_HostRawElementProvider, +}; + /*********************************************************************** * UiaClientsAreListening (uiautomationcore.@) */ @@ -219,8 +331,26 @@ void WINAPI UiaRegisterProviderCallback(UiaProviderCallback *callback)
HRESULT WINAPI UiaHostProviderFromHwnd(HWND hwnd, IRawElementProviderSimple **provider) { - FIXME("(%p, %p): stub\n", hwnd, provider); - return E_NOTIMPL; + struct hwnd_host_provider *host_prov; + + TRACE("(%p, %p)\n", hwnd, provider); + + if (provider) + *provider = NULL; + + if (!IsWindow(hwnd) || !provider) + return E_INVALIDARG; + + host_prov = heap_alloc(sizeof(*host_prov)); + if (!host_prov) + return E_OUTOFMEMORY; + + host_prov->IRawElementProviderSimple_iface.lpVtbl = &hwnd_host_provider_vtbl; + host_prov->refcount = 1; + host_prov->hwnd = hwnd; + *provider = &host_prov->IRawElementProviderSimple_iface; + + return S_OK; }
HRESULT WINAPI UiaDisconnectProvider(IRawElementProviderSimple *provider)
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/uiautomationcore/tests/Makefile.in | 2 +- dlls/uiautomationcore/tests/uiautomation.c | 53 +++++++++++++++++++++- 2 files changed, 53 insertions(+), 2 deletions(-)
diff --git a/dlls/uiautomationcore/tests/Makefile.in b/dlls/uiautomationcore/tests/Makefile.in index 1d08e19093f..fbd53507fbe 100644 --- a/dlls/uiautomationcore/tests/Makefile.in +++ b/dlls/uiautomationcore/tests/Makefile.in @@ -1,5 +1,5 @@ TESTDLL = uiautomationcore.dll -IMPORTS = uiautomationcore user32 ole32 +IMPORTS = uiautomationcore user32 ole32 oleaut32
C_SRCS = \ uiautomation.c diff --git a/dlls/uiautomationcore/tests/uiautomation.c b/dlls/uiautomationcore/tests/uiautomation.c index 76d2e06e07e..e5fa12535be 100644 --- a/dlls/uiautomationcore/tests/uiautomation.c +++ b/dlls/uiautomationcore/tests/uiautomation.c @@ -34,9 +34,12 @@ static LRESULT WINAPI test_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPAR static void test_UiaHostProviderFromHwnd(void) { IRawElementProviderSimple *p, *p2; + enum ProviderOptions prov_opt; WNDCLASSA cls; HRESULT hr; HWND hwnd; + VARIANT v; + int i;
cls.style = 0; cls.lpfnWndProc = test_wnd_proc; @@ -61,6 +64,9 @@ static void test_UiaHostProviderFromHwnd(void) ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr); ok(p == NULL, "Unexpected instance.\n");
+ hr = UiaHostProviderFromHwnd(hwnd, NULL); + ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr); + p = NULL; hr = UiaHostProviderFromHwnd(hwnd, &p); ok(hr == S_OK, "Failed to get host provider, hr %#x.\n", hr); @@ -75,9 +81,54 @@ static void test_UiaHostProviderFromHwnd(void) ok(hr == S_OK, "Unexpected hr %#x.\n", hr); ok(p2 == NULL, "Unexpected instance.\n");
- IRawElementProviderSimple_Release(p); + hr = IRawElementProviderSimple_GetPropertyValue(p, UIA_NativeWindowHandlePropertyId, &v); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(V_VT(&v) == VT_I4, "V_VT(&v) = %d\n", V_VT(&v)); + ok(V_I4(&v) == HandleToUlong(hwnd), "V_I4(&v) = %#x, expected %#x\n", V_I4(&v), HandleToUlong(hwnd)); + + hr = IRawElementProviderSimple_GetPropertyValue(p, UIA_ProviderDescriptionPropertyId, &v); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(V_VT(&v) == VT_BSTR, "V_VT(&v) = %d\n", V_VT(&v)); + VariantClear(&v);
+ /* No patterns are implemented on the HWND Host provider. */ + for (i = UIA_InvokePatternId; i < (UIA_CustomNavigationPatternId + 1); i++) + { + IUnknown *unk; + + unk = (void *)0xdeadbeef; + hr = IRawElementProviderSimple_GetPatternProvider(p, i, &unk); + ok(hr == S_OK, "Unexpected hr %#x, %d.\n", hr, i); + ok(!unk, "Pattern %d returned %p\n", i, unk); + } + + hr = IRawElementProviderSimple_get_ProviderOptions(p, &prov_opt); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok((prov_opt == ProviderOptions_ServerSideProvider) || + broken(prov_opt == ProviderOptions_ClientSideProvider), /* Windows < 10 1507 */ + "Unexpected provider options %#x\n", prov_opt); + + /* Test behavior post Window destruction. */ DestroyWindow(hwnd); + + hr = IRawElementProviderSimple_GetPropertyValue(p, UIA_NativeWindowHandlePropertyId, &v); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(V_VT(&v) == VT_I4, "V_VT(&v) = %d\n", V_VT(&v)); + ok(V_I4(&v) == HandleToUlong(hwnd), "V_I4(&v) = %#x, expected %#x\n", V_I4(&v), HandleToUlong(hwnd)); + + hr = IRawElementProviderSimple_GetPropertyValue(p, UIA_ProviderDescriptionPropertyId, &v); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(V_VT(&v) == VT_BSTR, "V_VT(&v) = %d\n", V_VT(&v)); + VariantClear(&v); + + hr = IRawElementProviderSimple_get_ProviderOptions(p, &prov_opt); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok((prov_opt == ProviderOptions_ServerSideProvider) || + broken(prov_opt == ProviderOptions_ClientSideProvider), /* Windows < 10 1507 */ + "Unexpected provider options %#x\n", prov_opt); + + IRawElementProviderSimple_Release(p); + UnregisterClassA("HostProviderFromHwnd class", NULL); }
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com