Module: wine Branch: master Commit: 68aa92d6b038d1ee8f6dcd3cda5ba90d27eadb98 URL: https://gitlab.winehq.org/wine/wine/-/commit/68aa92d6b038d1ee8f6dcd3cda5ba90...
Author: Connor McAdams cmcadams@codeweavers.com Date: Fri Mar 17 15:31:16 2023 -0400
uiautomationcore: Add global interface table helper functions.
Signed-off-by: Connor McAdams cmcadams@codeweavers.com
---
dlls/uiautomationcore/uia_client.c | 65 ++++--------------------------- dlls/uiautomationcore/uia_private.h | 3 ++ dlls/uiautomationcore/uia_utils.c | 76 +++++++++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+), 57 deletions(-)
diff --git a/dlls/uiautomationcore/uia_client.c b/dlls/uiautomationcore/uia_client.c index 9ea66e27d61..32f16c0731d 100644 --- a/dlls/uiautomationcore/uia_client.c +++ b/dlls/uiautomationcore/uia_client.c @@ -169,18 +169,6 @@ exit: } }
-static HRESULT get_global_interface_table(IGlobalInterfaceTable **git) -{ - HRESULT hr; - - hr = CoCreateInstance(&CLSID_StdGlobalInterfaceTable, NULL, - CLSCTX_INPROC_SERVER, &IID_IGlobalInterfaceTable, (void **)git); - if (FAILED(hr)) - WARN("Failed to get GlobalInterfaceTable, hr %#lx\n", hr); - - return hr; -} - static HWND get_hwnd_from_provider(IRawElementProviderSimple *elprov) { IRawElementProviderSimple *host_prov; @@ -428,16 +416,8 @@ static ULONG WINAPI uia_node_Release(IWineUiaNode *iface) { if (node->git_cookie[i]) { - IGlobalInterfaceTable *git; - HRESULT hr; - - hr = get_global_interface_table(&git); - if (SUCCEEDED(hr)) - { - hr = IGlobalInterfaceTable_RevokeInterfaceFromGlobal(git, node->git_cookie[i]); - if (FAILED(hr)) - WARN("Failed to get revoke provider interface from Global Interface Table, hr %#lx\n", hr); - } + if (FAILED(unregister_interface_in_git(node->git_cookie[i]))) + WARN("Failed to get revoke provider interface from GIT\n"); }
if (node->prov[i]) @@ -472,21 +452,13 @@ static HRESULT WINAPI uia_node_get_provider(IWineUiaNode *iface, int idx, IWineU prov_type = get_node_provider_type_at_idx(node, idx); if (node->git_cookie[prov_type]) { - IGlobalInterfaceTable *git; IWineUiaProvider *prov; HRESULT hr;
- hr = get_global_interface_table(&git); + hr = get_interface_in_git(&IID_IWineUiaProvider, node->git_cookie[prov_type], (IUnknown **)&prov); if (FAILED(hr)) return hr;
- hr = IGlobalInterfaceTable_GetInterfaceFromGlobal(git, node->git_cookie[prov_type], - &IID_IWineUiaProvider, (void **)&prov); - if (FAILED(hr)) - { - ERR("Failed to get provider interface from GlobalInterfaceTable, hr %#lx\n", hr); - return hr; - } *out_prov = prov; } else @@ -542,16 +514,8 @@ static HRESULT WINAPI uia_node_disconnect(IWineUiaNode *iface) prov_type = get_node_provider_type_at_idx(node, 0); if (node->git_cookie[prov_type]) { - IGlobalInterfaceTable *git; - HRESULT hr; - - hr = get_global_interface_table(&git); - if (SUCCEEDED(hr)) - { - hr = IGlobalInterfaceTable_RevokeInterfaceFromGlobal(git, node->git_cookie[prov_type]); - if (FAILED(hr)) - WARN("Failed to get revoke provider interface from Global Interface Table, hr %#lx\n", hr); - } + if (FAILED(unregister_interface_in_git(node->git_cookie[prov_type]))) + WARN("Failed to get revoke provider interface from GIT\n"); node->git_cookie[prov_type] = 0; }
@@ -639,7 +603,6 @@ static HRESULT prepare_uia_node(struct uia_node *node) for (i = 0; i < PROV_TYPE_COUNT; i++) { enum ProviderOptions prov_opts; - IGlobalInterfaceTable *git; struct uia_provider *prov; HRESULT hr;
@@ -660,12 +623,8 @@ static HRESULT prepare_uia_node(struct uia_node *node) */ if (prov_opts & ProviderOptions_UseComThreading) { - hr = get_global_interface_table(&git); - if (FAILED(hr)) - return hr; - - hr = IGlobalInterfaceTable_RegisterInterfaceInGlobal(git, (IUnknown *)&prov->IWineUiaProvider_iface, - &IID_IWineUiaProvider, &node->git_cookie[i]); + hr = register_interface_in_git((IUnknown *)&prov->IWineUiaProvider_iface, &IID_IWineUiaProvider, + &node->git_cookie[i]); if (FAILED(hr)) return hr; } @@ -2260,7 +2219,6 @@ static HRESULT create_wine_uia_nested_node_provider(struct uia_node *node, LRESU { IWineUiaProvider *provider_iface = NULL; struct uia_nested_node_provider *prov; - IGlobalInterfaceTable *git; IWineUiaNode *nested_node; int prov_opts, prov_type; DWORD git_cookie; @@ -2339,14 +2297,7 @@ static HRESULT create_wine_uia_nested_node_provider(struct uia_node *node, LRESU * We need to use the GIT on all nested node providers so that our * IWineUiaNode proxy is used in the correct apartment. */ - hr = get_global_interface_table(&git); - if (FAILED(hr)) - { - IWineUiaProvider_Release(&prov->IWineUiaProvider_iface); - return hr; - } - - hr = IGlobalInterfaceTable_RegisterInterfaceInGlobal(git, (IUnknown *)&prov->IWineUiaProvider_iface, + hr = register_interface_in_git((IUnknown *)(IUnknown *)&prov->IWineUiaProvider_iface, &IID_IWineUiaProvider, &git_cookie); if (FAILED(hr)) { diff --git a/dlls/uiautomationcore/uia_private.h b/dlls/uiautomationcore/uia_private.h index 5d3a64cb776..faec42f5d0e 100644 --- a/dlls/uiautomationcore/uia_private.h +++ b/dlls/uiautomationcore/uia_private.h @@ -179,6 +179,9 @@ HRESULT create_msaa_provider(IAccessible *acc, long child_id, HWND hwnd, BOOL kn IRawElementProviderSimple **elprov) DECLSPEC_HIDDEN;
/* uia_utils.c */ +HRESULT register_interface_in_git(IUnknown *iface, REFIID riid, DWORD *ret_cookie) DECLSPEC_HIDDEN; +HRESULT unregister_interface_in_git(DWORD git_cookie) DECLSPEC_HIDDEN; +HRESULT get_interface_in_git(REFIID riid, DWORD git_cookie, IUnknown **ret_iface) DECLSPEC_HIDDEN; HRESULT get_safearray_dim_bounds(SAFEARRAY *sa, UINT dim, LONG *lbound, LONG *elems) DECLSPEC_HIDDEN; HRESULT get_safearray_bounds(SAFEARRAY *sa, LONG *lbound, LONG *elems) DECLSPEC_HIDDEN; int uia_compare_safearrays(SAFEARRAY *sa1, SAFEARRAY *sa2, int prop_type) DECLSPEC_HIDDEN; diff --git a/dlls/uiautomationcore/uia_utils.c b/dlls/uiautomationcore/uia_utils.c index 67c01eed8c3..ef7cf5ff9d2 100644 --- a/dlls/uiautomationcore/uia_utils.c +++ b/dlls/uiautomationcore/uia_utils.c @@ -22,6 +22,82 @@
WINE_DEFAULT_DEBUG_CHANNEL(uiautomation);
+/* + * Global interface table helper functions. + */ +static HRESULT get_global_interface_table(IGlobalInterfaceTable **git) +{ + HRESULT hr; + + hr = CoCreateInstance(&CLSID_StdGlobalInterfaceTable, NULL, + CLSCTX_INPROC_SERVER, &IID_IGlobalInterfaceTable, (void **)git); + if (FAILED(hr)) + WARN("Failed to get GlobalInterfaceTable, hr %#lx\n", hr); + + return hr; +} + +HRESULT register_interface_in_git(IUnknown *iface, REFIID riid, DWORD *ret_cookie) +{ + IGlobalInterfaceTable *git; + DWORD git_cookie; + HRESULT hr; + + *ret_cookie = 0; + hr = get_global_interface_table(&git); + if (FAILED(hr)) + return hr; + + hr = IGlobalInterfaceTable_RegisterInterfaceInGlobal(git, iface, riid, &git_cookie); + if (FAILED(hr)) + { + WARN("Failed to register interface in GlobalInterfaceTable, hr %#lx\n", hr); + return hr; + } + + *ret_cookie = git_cookie; + + return S_OK; +} + +HRESULT unregister_interface_in_git(DWORD git_cookie) +{ + IGlobalInterfaceTable *git; + HRESULT hr; + + hr = get_global_interface_table(&git); + if (FAILED(hr)) + return hr; + + hr = IGlobalInterfaceTable_RevokeInterfaceFromGlobal(git, git_cookie); + if (FAILED(hr)) + WARN("Failed to revoke interface from GlobalInterfaceTable, hr %#lx\n", hr); + + return hr; +} + +HRESULT get_interface_in_git(REFIID riid, DWORD git_cookie, IUnknown **ret_iface) +{ + IGlobalInterfaceTable *git; + IUnknown *iface; + HRESULT hr; + + hr = get_global_interface_table(&git); + if (FAILED(hr)) + return hr; + + hr = IGlobalInterfaceTable_GetInterfaceFromGlobal(git, git_cookie, riid, (void **)&iface); + if (FAILED(hr)) + { + ERR("Failed to get interface from Global Interface Table, hr %#lx\n", hr); + return hr; + } + + *ret_iface = iface; + + return S_OK; +} + HRESULT get_safearray_dim_bounds(SAFEARRAY *sa, UINT dim, LONG *lbound, LONG *elems) { LONG ubound;