Module: wine Branch: master Commit: a97cdeaf20d78e4e49f0c37fc07b5d20514fdbfd URL: https://gitlab.winehq.org/wine/wine/-/commit/a97cdeaf20d78e4e49f0c37fc07b5d2...
Author: Connor McAdams cmcadams@codeweavers.com Date: Thu Mar 23 15:14:30 2023 -0400
uiautomationcore: Implement UiaGetRootNode.
Signed-off-by: Connor McAdams cmcadams@codeweavers.com
---
dlls/uiautomationcore/tests/uiautomation.c | 62 +++++++++++++++++++++++++++++ dlls/uiautomationcore/uia_client.c | 10 +++++ dlls/uiautomationcore/uiautomationcore.spec | 2 +- include/uiautomationcoreapi.h | 1 + 4 files changed, 74 insertions(+), 1 deletion(-)
diff --git a/dlls/uiautomationcore/tests/uiautomation.c b/dlls/uiautomationcore/tests/uiautomation.c index 3ec275a874c..a3153eff7ab 100644 --- a/dlls/uiautomationcore/tests/uiautomation.c +++ b/dlls/uiautomationcore/tests/uiautomation.c @@ -12792,6 +12792,67 @@ static void test_default_clientside_providers(void) CoUninitialize(); }
+static void test_UiaGetRootNode(void) +{ + HUIANODE node; + HRESULT hr; + VARIANT v; + + CoInitializeEx(NULL, COINIT_MULTITHREADED); + UiaRegisterProviderCallback(test_uia_provider_callback); + + /* + * UiaGetRootNode is the same as calling UiaNodeFromHandle with the + * desktop window handle. + */ + initialize_provider(&Provider_hwnd, ProviderOptions_ClientSideProvider, GetDesktopWindow(), TRUE); + initialize_provider(&Provider_nc, ProviderOptions_ClientSideProvider | ProviderOptions_NonClientAreaProvider, + GetDesktopWindow(), TRUE); + initialize_provider(&Provider_proxy, ProviderOptions_ClientSideProvider, GetDesktopWindow(), TRUE); + Provider_proxy.ignore_hwnd_prop = TRUE; + + base_hwnd_prov = &Provider_hwnd.IRawElementProviderSimple_iface; + proxy_prov = &Provider_proxy.IRawElementProviderSimple_iface; + nc_prov = &Provider_nc.IRawElementProviderSimple_iface; + + method_sequences_enabled = FALSE; + SET_EXPECT(prov_callback_base_hwnd); + SET_EXPECT(prov_callback_nonclient); + SET_EXPECT(prov_callback_proxy); + hr = UiaGetRootNode(&node); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!!node, "Node == NULL.\n"); + ok(Provider_proxy.ref == 2, "Unexpected refcnt %ld\n", Provider_proxy.ref); + ok(Provider_hwnd.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd.ref); + ok(Provider_nc.ref == 2, "Unexpected refcnt %ld\n", Provider_nc.ref); + CHECK_CALLED(prov_callback_base_hwnd); + CHECK_CALLED(prov_callback_nonclient); + CHECK_CALLED(prov_callback_proxy); + + hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v); + ok(hr == S_OK, "Unexpected hr %#lx\n", hr); + check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), GetDesktopWindow()); + check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_proxy", TRUE); + check_node_provider_desc(V_BSTR(&v), L"Hwnd", L"Provider_hwnd", FALSE); + check_node_provider_desc(V_BSTR(&v), L"Nonclient", L"Provider_nc", FALSE); + VariantClear(&v); + + ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n"); + ok(Provider_proxy.ref == 1, "Unexpected refcnt %ld\n", Provider_proxy.ref); + ok(Provider_hwnd.ref == 1, "Unexpected refcnt %ld\n", Provider_hwnd.ref); + ok(Provider_nc.ref == 1, "Unexpected refcnt %ld\n", Provider_nc.ref); + + initialize_provider(&Provider_hwnd, ProviderOptions_ClientSideProvider, NULL, TRUE); + initialize_provider(&Provider_nc, ProviderOptions_ClientSideProvider | ProviderOptions_NonClientAreaProvider, NULL, + TRUE); + initialize_provider(&Provider_proxy, ProviderOptions_ClientSideProvider, NULL, TRUE); + base_hwnd_prov = proxy_prov = nc_prov = NULL; + + method_sequences_enabled = TRUE; + UiaRegisterProviderCallback(NULL); + CoUninitialize(); +} + /* * Once a process returns a UI Automation provider with * UiaReturnRawElementProvider it ends up in an implicit MTA until exit. This @@ -12860,6 +12921,7 @@ START_TEST(uiautomation) test_UiaFind(); test_CUIAutomation(); test_default_clientside_providers(); + test_UiaGetRootNode(); if (uia_dll) { pUiaProviderFromIAccessible = (void *)GetProcAddress(uia_dll, "UiaProviderFromIAccessible"); diff --git a/dlls/uiautomationcore/uia_client.c b/dlls/uiautomationcore/uia_client.c index e3eb5cd0561..4ec12423533 100644 --- a/dlls/uiautomationcore/uia_client.c +++ b/dlls/uiautomationcore/uia_client.c @@ -2368,6 +2368,16 @@ HRESULT WINAPI UiaNodeFromHandle(HWND hwnd, HUIANODE *huianode) return S_OK; }
+/*********************************************************************** + * UiaGetRootNode (uiautomationcore.@) + */ +HRESULT WINAPI UiaGetRootNode(HUIANODE *huianode) +{ + TRACE("(%p)\n", huianode); + + return UiaNodeFromHandle(GetDesktopWindow(), huianode); +} + /*********************************************************************** * UiaNodeRelease (uiautomationcore.@) */ diff --git a/dlls/uiautomationcore/uiautomationcore.spec b/dlls/uiautomationcore/uiautomationcore.spec index 7168135487b..34856be6b36 100644 --- a/dlls/uiautomationcore/uiautomationcore.spec +++ b/dlls/uiautomationcore/uiautomationcore.spec @@ -65,7 +65,7 @@ @ stdcall UiaGetPropertyValue(ptr long ptr) @ stdcall UiaGetReservedMixedAttributeValue(ptr) @ stdcall UiaGetReservedNotSupportedValue(ptr) -@ stub UiaGetRootNode +@ stdcall UiaGetRootNode(ptr) @ stdcall UiaGetRuntimeId(ptr ptr) @ stdcall UiaGetUpdatedCache(ptr ptr long ptr ptr ptr) @ stub UiaHPatternObjectFromVariant diff --git a/include/uiautomationcoreapi.h b/include/uiautomationcoreapi.h index 1d78113e1fd..320bb814b9c 100644 --- a/include/uiautomationcoreapi.h +++ b/include/uiautomationcoreapi.h @@ -544,6 +544,7 @@ BOOL WINAPI UiaNodeRelease(HUIANODE huianode); HRESULT WINAPI UiaGetRuntimeId(HUIANODE huianode, SAFEARRAY **runtime_id); HRESULT WINAPI UiaHUiaNodeFromVariant(VARIANT *in_val, HUIANODE *huianode); HRESULT WINAPI UiaNodeFromHandle(HWND hwnd, HUIANODE *huianode); +HRESULT WINAPI UiaGetRootNode(HUIANODE *huianode); HRESULT WINAPI UiaDisconnectProvider(IRawElementProviderSimple *elprov); HRESULT WINAPI UiaGetUpdatedCache(HUIANODE huianode, struct UiaCacheRequest *cache_req, enum NormalizeState normalize_state, struct UiaCondition *normalize_cond, SAFEARRAY **out_req, BSTR *tree_struct);