From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/uiautomationcore/uia_client.c | 67 +++++++++++++++++++++++++++++ dlls/uiautomationcore/uia_event.c | 10 +++-- dlls/uiautomationcore/uia_private.h | 1 + 3 files changed, 75 insertions(+), 3 deletions(-)
diff --git a/dlls/uiautomationcore/uia_client.c b/dlls/uiautomationcore/uia_client.c index 492ca0e52de..5fe3078bec1 100644 --- a/dlls/uiautomationcore/uia_client.c +++ b/dlls/uiautomationcore/uia_client.c @@ -673,6 +673,73 @@ static HRESULT prepare_uia_node(struct uia_node *node) return S_OK; }
+static HRESULT create_wine_uia_provider(struct uia_node *node, IRawElementProviderSimple *elprov, int prov_type); +HRESULT clone_uia_node(HUIANODE in_node, HUIANODE *out_node) +{ + struct uia_node *in_node_data = impl_from_IWineUiaNode((IWineUiaNode *)in_node); + struct uia_node *node; + HRESULT hr = S_OK; + int i; + + *out_node = NULL; + if (in_node_data->nested_node) + { + FIXME("Cloning of nested nodes currently unimplemented\n"); + return E_NOTIMPL; + } + + for (i = 0; i < PROV_TYPE_COUNT; i++) + { + if (in_node_data->prov[i] && is_nested_node_provider(in_node_data->prov[i])) + { + FIXME("Cloning of nested node providers currently unimplemented\n"); + return E_NOTIMPL; + } + } + + if (!(node = heap_alloc_zero(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; + node->hwnd = in_node_data->hwnd; + + for (i = 0; i < PROV_TYPE_COUNT; i++) + { + struct uia_provider *in_prov_data; + + if (!in_node_data->prov[i]) + continue; + + in_prov_data = impl_from_IWineUiaProvider(in_node_data->prov[i]); + hr = create_wine_uia_provider(node, in_prov_data->elprov, i); + if (FAILED(hr)) + goto exit; + + if (in_node_data->git_cookie[i]) + { + hr = register_interface_in_git((IUnknown *)node->prov[i], &IID_IWineUiaProvider, &node->git_cookie[i]); + if (FAILED(hr)) + goto exit; + } + } + + node->parent_link_idx = in_node_data->parent_link_idx; + node->creator_prov_idx = in_node_data->creator_prov_idx; + node->creator_prov_type = in_node_data->creator_prov_type; + + *out_node = (void *)&node->IWineUiaNode_iface; + TRACE("Created clone node %p from node %p\n", *out_node, in_node); + +exit: + if (FAILED(hr)) + IWineUiaNode_Release(&node->IWineUiaNode_iface); + + return hr; +} + static BOOL node_creator_is_parent_link(struct uia_node *node) { if (node->creator_prov_idx == node->parent_link_idx) diff --git a/dlls/uiautomationcore/uia_event.c b/dlls/uiautomationcore/uia_event.c index 4f5483d4c74..44f184cda7d 100644 --- a/dlls/uiautomationcore/uia_event.c +++ b/dlls/uiautomationcore/uia_event.c @@ -1171,13 +1171,17 @@ static HRESULT uia_event_invoke(HUIANODE node, struct uia_event_args *args, stru } else { + HUIANODE node2; VARIANT v;
- get_variant_for_node(node, &v); - IWineUiaNode_AddRef((IWineUiaNode *)node); + hr = clone_uia_node(node, &node2); + if (FAILED(hr)) + return hr; + + get_variant_for_node(node2, &v); hr = uia_event_queue_post_event(event, v, args); if (FAILED(hr)) - UiaNodeRelease(node); + UiaNodeRelease(node2); }
return hr; diff --git a/dlls/uiautomationcore/uia_private.h b/dlls/uiautomationcore/uia_private.h index 325206c6d90..727c0be6894 100644 --- a/dlls/uiautomationcore/uia_private.h +++ b/dlls/uiautomationcore/uia_private.h @@ -192,6 +192,7 @@ static inline BOOL uia_array_reserve(void **elements, SIZE_T *capacity, SIZE_T c /* uia_client.c */ int get_node_provider_type_at_idx(struct uia_node *node, int idx) DECLSPEC_HIDDEN; HRESULT attach_event_to_uia_node(HUIANODE node, struct uia_event *event) DECLSPEC_HIDDEN; +HRESULT clone_uia_node(HUIANODE in_node, HUIANODE *out_node) DECLSPEC_HIDDEN; HRESULT navigate_uia_node(struct uia_node *node, int nav_dir, HUIANODE *out_node) DECLSPEC_HIDDEN; HRESULT create_uia_node_from_elprov(IRawElementProviderSimple *elprov, HUIANODE *out_node, BOOL get_hwnd_providers) DECLSPEC_HIDDEN;