From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/uiautomationcore/uia_client.c | 9 +++++++++ dlls/uiautomationcore/uiautomationcore.spec | 2 +- include/uiautomationcoreapi.h | 1 + 3 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/dlls/uiautomationcore/uia_client.c b/dlls/uiautomationcore/uia_client.c index 1bffb571586..85f29c0219c 100644 --- a/dlls/uiautomationcore/uia_client.c +++ b/dlls/uiautomationcore/uia_client.c @@ -2616,6 +2616,15 @@ HRESULT WINAPI UiaGetRootNode(HUIANODE *huianode) return UiaNodeFromHandle(GetDesktopWindow(), huianode); }
+/*********************************************************************** + * UiaHasServerSideProvider (uiautomationcore.@) + */ +BOOL WINAPI UiaHasServerSideProvider(HWND hwnd) +{ + FIXME("(%p): stub\n", hwnd); + return FALSE; +} + static HRESULT get_focused_uia_node(HUIANODE in_node, HUIANODE *out_node) { struct uia_node *node = unsafe_impl_from_IWineUiaNode((IWineUiaNode *)in_node); diff --git a/dlls/uiautomationcore/uiautomationcore.spec b/dlls/uiautomationcore/uiautomationcore.spec index 686594debba..69e1f0ba9f9 100644 --- a/dlls/uiautomationcore/uiautomationcore.spec +++ b/dlls/uiautomationcore/uiautomationcore.spec @@ -71,7 +71,7 @@ @ stub UiaHPatternObjectFromVariant @ stub UiaHTextRangeFromVariant @ stdcall UiaHUiaNodeFromVariant(ptr ptr) -@ stub UiaHasServerSideProvider +@ stdcall UiaHasServerSideProvider(long) @ stdcall UiaHostProviderFromHwnd(long ptr) #@ stub UiaIAccessibleFromProvider @ stdcall UiaLookupId(long ptr) diff --git a/include/uiautomationcoreapi.h b/include/uiautomationcoreapi.h index a9a3c75c13c..0fd942f3f37 100644 --- a/include/uiautomationcoreapi.h +++ b/include/uiautomationcoreapi.h @@ -558,6 +558,7 @@ HRESULT WINAPI UiaAddEvent(HUIANODE huianode, EVENTID event_id, UiaEventCallback HRESULT WINAPI UiaRemoveEvent(HUIAEVENT huiaevent); HRESULT WINAPI UiaEventAddWindow(HUIAEVENT huiaevent, HWND hwnd); HRESULT WINAPI UiaEventRemoveWindow(HUIAEVENT huiaevent, HWND hwnd); +BOOL WINAPI UiaHasServerSideProvider(HWND hwnd);
#ifdef __cplusplus }
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/uiautomationcore/uia_client.c | 58 +++++++++++++++--------------- 1 file changed, 29 insertions(+), 29 deletions(-)
diff --git a/dlls/uiautomationcore/uia_client.c b/dlls/uiautomationcore/uia_client.c index 85f29c0219c..b1a21de3a17 100644 --- a/dlls/uiautomationcore/uia_client.c +++ b/dlls/uiautomationcore/uia_client.c @@ -597,6 +597,23 @@ static struct uia_node *unsafe_impl_from_IWineUiaNode(IWineUiaNode *iface) return CONTAINING_RECORD(iface, struct uia_node, IWineUiaNode_iface); }
+static HRESULT create_uia_node(struct uia_node **out_node) +{ + struct uia_node *node; + + *out_node = NULL; + if (!(node = calloc(1, sizeof(*node)))) + return E_OUTOFMEMORY; + + node->IWineUiaNode_iface.lpVtbl = &uia_node_vtbl; + list_init(&node->prov_thread_list_entry); + list_init(&node->node_map_list_entry); + node->ref = 1; + + *out_node = node; + return S_OK; +} + static BOOL is_nested_node_provider(IWineUiaProvider *iface); static HRESULT prepare_uia_node(struct uia_node *node) { @@ -697,15 +714,11 @@ HRESULT clone_uia_node(HUIANODE in_node, HUIANODE *out_node) } }
- if (!(node = calloc(1, sizeof(*node)))) - return E_OUTOFMEMORY; + hr = create_uia_node(&node); + if (FAILED(hr)) + return hr;
- node->IWineUiaNode_iface.lpVtbl = &uia_node_vtbl; - list_init(&node->prov_thread_list_entry); - list_init(&node->node_map_list_entry); - node->ref = 1; node->hwnd = in_node_data->hwnd; - for (i = 0; i < PROV_TYPE_COUNT; i++) { struct uia_provider *in_prov_data; @@ -1967,15 +1980,11 @@ HRESULT create_uia_node_from_elprov(IRawElementProviderSimple *elprov, HUIANODE else prov_type = PROV_TYPE_MAIN;
- node = calloc(1, sizeof(*node)); - if (!node) - return E_OUTOFMEMORY; + hr = create_uia_node(&node); + if (FAILED(hr)) + return hr;
- node->IWineUiaNode_iface.lpVtbl = &uia_node_vtbl; node->hwnd = get_hwnd_from_provider(elprov); - list_init(&node->prov_thread_list_entry); - list_init(&node->node_map_list_entry); - node->ref = 1;
hr = create_wine_uia_provider(node, elprov, prov_type); if (FAILED(hr)) @@ -2493,14 +2502,10 @@ HRESULT uia_node_from_lresult(LRESULT lr, HUIANODE *huianode) HRESULT hr;
*huianode = NULL; - node = calloc(1, sizeof(*node)); - if (!node) - return E_OUTOFMEMORY;
- node->IWineUiaNode_iface.lpVtbl = &uia_node_vtbl; - list_init(&node->prov_thread_list_entry); - list_init(&node->node_map_list_entry); - node->ref = 1; + hr = create_uia_node(&node); + if (FAILED(hr)) + return hr;
uia_start_client_thread(); hr = create_wine_uia_nested_node_provider(node, lr, FALSE); @@ -2577,16 +2582,11 @@ HRESULT WINAPI UiaNodeFromHandle(HWND hwnd, HUIANODE *huianode) if (!IsWindow(hwnd)) return UIA_E_ELEMENTNOTAVAILABLE;
- node = calloc(1, sizeof(*node)); - if (!node) - return E_OUTOFMEMORY; + hr = create_uia_node(&node); + if (FAILED(hr)) + return hr;
node->hwnd = hwnd; - node->IWineUiaNode_iface.lpVtbl = &uia_node_vtbl; - list_init(&node->prov_thread_list_entry); - list_init(&node->node_map_list_entry); - node->ref = 1; - hr = uia_get_providers_for_hwnd(node); if (FAILED(hr)) {
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/uiautomationcore/tests/uiautomation.c | 59 ++++++++++++++++++++++ dlls/uiautomationcore/uia_client.c | 54 ++++++++++++++------ dlls/uiautomationcore/uia_private.h | 8 +++ 3 files changed, 105 insertions(+), 16 deletions(-)
diff --git a/dlls/uiautomationcore/tests/uiautomation.c b/dlls/uiautomationcore/tests/uiautomation.c index a733e183312..fd1f5d0414b 100644 --- a/dlls/uiautomationcore/tests/uiautomation.c +++ b/dlls/uiautomationcore/tests/uiautomation.c @@ -15302,6 +15302,64 @@ static void test_UiaAddEvent(const char *name) UnregisterClassA("UiaAddEvent test class", NULL); }
+static const struct prov_method_sequence serverside_prov_seq[] = { + NODE_CREATE_SEQ2(&Provider), + /* Windows 10+ calls this. */ + { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, + { 0 } +}; + +static void test_UiaHasServerSideProvider(void) +{ + BOOL ret_val; + HWND hwnd; + + CoInitializeEx(NULL, COINIT_MULTITHREADED); + hwnd = create_test_hwnd("UiaHasServerSideProvider test class"); + + /* NULL hwnd. */ + ret_val = UiaHasServerSideProvider(NULL); + ok(!ret_val, "UiaHasServerSideProvider returned TRUE\n"); + + /* Desktop window has no serverside providers. */ + UiaRegisterProviderCallback(test_uia_provider_callback); + ret_val = UiaHasServerSideProvider(GetDesktopWindow()); + ok(!ret_val, "UiaHasServerSideProvider returned TRUE\n"); + + /* No provider to pass to UiaReturnRawElementProvider, returns FALSE. */ + prov_root = NULL; + SET_EXPECT(winproc_GETOBJECT_UiaRoot); + ret_val = UiaHasServerSideProvider(hwnd); + ok(!ret_val, "UiaHasServerSideProvider returned TRUE\n"); + CHECK_CALLED(winproc_GETOBJECT_UiaRoot); + + /* + * Provider passed to UiaReturnRawElementProvider returns a failure from + * get_ProviderOptions. Returns FALSE. + */ + initialize_provider(&Provider, 0, hwnd, TRUE); + prov_root = &Provider.IRawElementProviderSimple_iface; + SET_EXPECT(winproc_GETOBJECT_UiaRoot); + ret_val = UiaHasServerSideProvider(hwnd); + ok(!ret_val, "UiaHasServerSideProvider returned TRUE\n"); + ok_method_sequence(node_from_hwnd1, NULL); + CHECK_CALLED(winproc_GETOBJECT_UiaRoot); + + /* Successfully return a provider from UiaReturnRawElementProvider. */ + initialize_provider(&Provider, ProviderOptions_ServerSideProvider, hwnd, TRUE); + SET_EXPECT(winproc_GETOBJECT_UiaRoot); + ret_val = UiaHasServerSideProvider(hwnd); + ok(ret_val, "UiaHasServerSideProvider returned FALSE\n"); + ok_method_sequence(serverside_prov_seq, "serverside_prov_seq"); + CHECK_CALLED(winproc_GETOBJECT_UiaRoot); + + UiaRegisterProviderCallback(NULL); + prov_root = NULL; + CoUninitialize(); + DestroyWindow(hwnd); + UnregisterClassA("UiaHasServerSideProvider test class", NULL); +} + /* * Once a process returns a UI Automation provider with * UiaReturnRawElementProvider it ends up in an implicit MTA until exit. This @@ -15375,6 +15433,7 @@ START_TEST(uiautomation) test_UiaGetRootNode(); test_UiaNodeFromFocus(); test_UiaAddEvent(argv[0]); + test_UiaHasServerSideProvider(); if (uia_dll) { pUiaProviderFromIAccessible = (void *)GetProcAddress(uia_dll, "UiaProviderFromIAccessible"); diff --git a/dlls/uiautomationcore/uia_client.c b/dlls/uiautomationcore/uia_client.c index b1a21de3a17..57d1ca812f7 100644 --- a/dlls/uiautomationcore/uia_client.c +++ b/dlls/uiautomationcore/uia_client.c @@ -597,7 +597,7 @@ static struct uia_node *unsafe_impl_from_IWineUiaNode(IWineUiaNode *iface) return CONTAINING_RECORD(iface, struct uia_node, IWineUiaNode_iface); }
-static HRESULT create_uia_node(struct uia_node **out_node) +static HRESULT create_uia_node(struct uia_node **out_node, int node_flags) { struct uia_node *node;
@@ -609,6 +609,10 @@ static HRESULT create_uia_node(struct uia_node **out_node) list_init(&node->prov_thread_list_entry); list_init(&node->node_map_list_entry); node->ref = 1; + if (node_flags & NODE_FLAG_IGNORE_CLIENTSIDE_HWND_PROVS) + node->ignore_clientside_hwnd_provs = TRUE; + if (node_flags & NODE_FLAG_NO_PREPARE) + node->no_prepare = TRUE;
*out_node = node; return S_OK; @@ -620,6 +624,9 @@ static HRESULT prepare_uia_node(struct uia_node *node) int i, prov_idx; HRESULT hr;
+ if (node->no_prepare) + return S_OK; + /* Get the provider index for the provider that created the node. */ for (i = prov_idx = 0; i < PROV_TYPE_COUNT; i++) { @@ -714,7 +721,7 @@ HRESULT clone_uia_node(HUIANODE in_node, HUIANODE *out_node) } }
- hr = create_uia_node(&node); + hr = create_uia_node(&node, 0); if (FAILED(hr)) return hr;
@@ -1980,7 +1987,7 @@ HRESULT create_uia_node_from_elprov(IRawElementProviderSimple *elprov, HUIANODE else prov_type = PROV_TYPE_MAIN;
- hr = create_uia_node(&node); + hr = create_uia_node(&node, 0); if (FAILED(hr)) return hr;
@@ -2503,7 +2510,7 @@ HRESULT uia_node_from_lresult(LRESULT lr, HUIANODE *huianode)
*huianode = NULL;
- hr = create_uia_node(&node); + hr = create_uia_node(&node, 0); if (FAILED(hr)) return hr;
@@ -2564,25 +2571,20 @@ static HRESULT uia_get_provider_from_hwnd(struct uia_node *node) return SendMessageW(client_thread.hwnd, WM_UIA_CLIENT_GET_NODE_PROV, (WPARAM)&args, (LPARAM)node); }
-/*********************************************************************** - * UiaNodeFromHandle (uiautomationcore.@) - */ -HRESULT WINAPI UiaNodeFromHandle(HWND hwnd, HUIANODE *huianode) +static HRESULT create_uia_node_from_hwnd(HWND hwnd, HUIANODE *out_node, int node_flags) { struct uia_node *node; HRESULT hr;
- TRACE("(%p, %p)\n", hwnd, huianode); - - if (!huianode) + if (!out_node) return E_INVALIDARG;
- *huianode = NULL; + *out_node = NULL;
if (!IsWindow(hwnd)) return UIA_E_ELEMENTNOTAVAILABLE;
- hr = create_uia_node(&node); + hr = create_uia_node(&node, node_flags); if (FAILED(hr)) return hr;
@@ -2601,11 +2603,21 @@ HRESULT WINAPI UiaNodeFromHandle(HWND hwnd, HUIANODE *huianode) return hr; }
- *huianode = (void *)&node->IWineUiaNode_iface; + *out_node = (void *)&node->IWineUiaNode_iface;
return S_OK; }
+/*********************************************************************** + * UiaNodeFromHandle (uiautomationcore.@) + */ +HRESULT WINAPI UiaNodeFromHandle(HWND hwnd, HUIANODE *huianode) +{ + TRACE("(%p, %p)\n", hwnd, huianode); + + return create_uia_node_from_hwnd(hwnd, huianode, 0); +} + /*********************************************************************** * UiaGetRootNode (uiautomationcore.@) */ @@ -2621,8 +2633,15 @@ HRESULT WINAPI UiaGetRootNode(HUIANODE *huianode) */ BOOL WINAPI UiaHasServerSideProvider(HWND hwnd) { - FIXME("(%p): stub\n", hwnd); - return FALSE; + HUIANODE node = NULL; + HRESULT hr; + + TRACE("(%p)\n", hwnd); + + hr = create_uia_node_from_hwnd(hwnd, &node, NODE_FLAG_NO_PREPARE | NODE_FLAG_IGNORE_CLIENTSIDE_HWND_PROVS); + UiaNodeRelease(node); + + return SUCCEEDED(hr); }
static HRESULT get_focused_uia_node(HUIANODE in_node, HUIANODE *out_node) @@ -3026,6 +3045,9 @@ static HRESULT uia_get_clientside_provider(struct uia_node *node, int prov_type, VARTYPE vt; HRESULT hr;
+ if (node->ignore_clientside_hwnd_provs) + return S_OK; + if (!(sa = uia_provider_callback(node->hwnd, prov_type))) return S_OK;
diff --git a/dlls/uiautomationcore/uia_private.h b/dlls/uiautomationcore/uia_private.h index 253eacbc4e7..e8bb4845189 100644 --- a/dlls/uiautomationcore/uia_private.h +++ b/dlls/uiautomationcore/uia_private.h @@ -54,6 +54,11 @@ enum uia_node_prov_type { PROV_TYPE_COUNT, };
+enum uia_node_flags { + NODE_FLAG_IGNORE_CLIENTSIDE_HWND_PROVS = 0x01, + NODE_FLAG_NO_PREPARE = 0x02, +}; + struct uia_node { IWineUiaNode IWineUiaNode_iface; LONG ref; @@ -65,9 +70,12 @@ struct uia_node { int creator_prov_idx;
HWND hwnd; + BOOL no_prepare; BOOL nested_node; BOOL disconnected; int creator_prov_type; + BOOL ignore_clientside_hwnd_provs; + struct list prov_thread_list_entry; struct list node_map_list_entry; struct uia_provider_thread_map_entry *map;
This merge request was approved by Esme Povirk.