Commit 1122fde4 authored by Connor McAdams's avatar Connor McAdams Committed by Alexandre Julliard

uiautomationcore: Respect ProviderOptions_UseComThreading on advise events interfaces.

parent 68aa92d6
......@@ -13810,7 +13810,7 @@ static DWORD WINAPI uia_add_event_test_thread(LPVOID param)
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
ok(Provider2.ref == 1, "Unexpected refcnt %ld\n", Provider2.ref);
todo_wine ok(Provider2.last_call_tid == data->exp_thread_id ||
ok(Provider2.last_call_tid == data->exp_thread_id ||
broken(Provider2.last_call_tid == GetCurrentThreadId()), "Expected method call on separate thread\n");
ok(Provider2.advise_events_removed_event_id == UIA_AutomationFocusChangedEventId,
"Unexpected advise event removed, event ID %d\n", Provider.advise_events_removed_event_id);
......
......@@ -56,6 +56,16 @@ library UIA_wine_private
[
object,
uuid(9a754e12-e570-49ab-b223-6f6871007d28),
pointer_default(unique),
]
interface IWineUiaEventAdviser : IUnknown
{
HRESULT advise([in]BOOL advise_added, [in]LONG_PTR huiaevent);
}
[
object,
uuid(5e60162c-ab0e-4e22-a61d-3a3acd442aba),
pointer_default(unique),
]
......
......@@ -63,7 +63,7 @@ static ULONG WINAPI uia_event_Release(IWineUiaEvent *iface)
SafeArrayDestroy(event->runtime_id);
for (i = 0; i < event->event_advisers_count; i++)
IRawElementProviderAdviseEvents_Release(event->event_advisers[i]);
IWineUiaEventAdviser_Release(event->event_advisers[i]);
heap_free(event->event_advisers);
heap_free(event);
}
......@@ -81,12 +81,7 @@ static HRESULT WINAPI uia_event_advise_events(IWineUiaEvent *iface, BOOL advise_
for (i = 0; i < event->event_advisers_count; i++)
{
IRawElementProviderAdviseEvents *adviser = event->event_advisers[i];
if (advise_added)
hr = IRawElementProviderAdviseEvents_AdviseEventAdded(adviser, event->event_id, NULL);
else
hr = IRawElementProviderAdviseEvents_AdviseEventRemoved(adviser, event->event_id, NULL);
hr = IWineUiaEventAdviser_advise(event->event_advisers[i], advise_added, (UINT_PTR)event);
if (FAILED(hr))
return hr;
}
......@@ -95,7 +90,7 @@ static HRESULT WINAPI uia_event_advise_events(IWineUiaEvent *iface, BOOL advise_
if (!advise_added)
{
for (i = 0; i < event->event_advisers_count; i++)
IRawElementProviderAdviseEvents_Release(event->event_advisers[i]);
IWineUiaEventAdviser_Release(event->event_advisers[i]);
heap_free(event->event_advisers);
event->event_advisers_count = event->event_advisers_arr_size = 0;
}
......@@ -138,14 +133,148 @@ static HRESULT create_uia_event(struct uia_event **out_event, int event_id, int
return S_OK;
}
/*
* IWineUiaEventAdviser interface.
*/
struct uia_event_adviser {
IWineUiaEventAdviser IWineUiaEventAdviser_iface;
LONG ref;
IRawElementProviderAdviseEvents *advise_events;
DWORD git_cookie;
};
static inline struct uia_event_adviser *impl_from_IWineUiaEventAdviser(IWineUiaEventAdviser *iface)
{
return CONTAINING_RECORD(iface, struct uia_event_adviser, IWineUiaEventAdviser_iface);
}
static HRESULT WINAPI uia_event_adviser_QueryInterface(IWineUiaEventAdviser *iface, REFIID riid, void **ppv)
{
*ppv = NULL;
if (IsEqualIID(riid, &IID_IWineUiaEventAdviser) || IsEqualIID(riid, &IID_IUnknown))
*ppv = iface;
else
return E_NOINTERFACE;
IWineUiaEventAdviser_AddRef(iface);
return S_OK;
}
static ULONG WINAPI uia_event_adviser_AddRef(IWineUiaEventAdviser *iface)
{
struct uia_event_adviser *adv_events = impl_from_IWineUiaEventAdviser(iface);
ULONG ref = InterlockedIncrement(&adv_events->ref);
TRACE("%p, refcount %ld\n", adv_events, ref);
return ref;
}
static ULONG WINAPI uia_event_adviser_Release(IWineUiaEventAdviser *iface)
{
struct uia_event_adviser *adv_events = impl_from_IWineUiaEventAdviser(iface);
ULONG ref = InterlockedDecrement(&adv_events->ref);
TRACE("%p, refcount %ld\n", adv_events, ref);
if (!ref)
{
if (adv_events->git_cookie)
{
if (FAILED(unregister_interface_in_git(adv_events->git_cookie)))
WARN("Failed to revoke advise events interface from GIT\n");
}
IRawElementProviderAdviseEvents_Release(adv_events->advise_events);
heap_free(adv_events);
}
return ref;
}
static HRESULT WINAPI uia_event_adviser_advise(IWineUiaEventAdviser *iface, BOOL advise_added, LONG_PTR huiaevent)
{
struct uia_event_adviser *adv_events = impl_from_IWineUiaEventAdviser(iface);
struct uia_event *event_data = (struct uia_event *)huiaevent;
IRawElementProviderAdviseEvents *advise_events;
HRESULT hr;
TRACE("%p, %d, %#Ix\n", adv_events, advise_added, huiaevent);
if (adv_events->git_cookie)
{
hr = get_interface_in_git(&IID_IRawElementProviderAdviseEvents, adv_events->git_cookie,
(IUnknown **)&advise_events);
if (FAILED(hr))
return hr;
}
else
{
advise_events = adv_events->advise_events;
IRawElementProviderAdviseEvents_AddRef(advise_events);
}
if (advise_added)
hr = IRawElementProviderAdviseEvents_AdviseEventAdded(advise_events, event_data->event_id, NULL);
else
hr = IRawElementProviderAdviseEvents_AdviseEventRemoved(advise_events, event_data->event_id, NULL);
IRawElementProviderAdviseEvents_Release(advise_events);
return hr;
}
static const IWineUiaEventAdviserVtbl uia_event_adviser_vtbl = {
uia_event_adviser_QueryInterface,
uia_event_adviser_AddRef,
uia_event_adviser_Release,
uia_event_adviser_advise,
};
HRESULT uia_event_add_provider_event_adviser(IRawElementProviderAdviseEvents *advise_events, struct uia_event *event)
{
struct uia_event_adviser *adv_events;
IRawElementProviderSimple *elprov;
enum ProviderOptions prov_opts;
HRESULT hr;
hr = IRawElementProviderAdviseEvents_QueryInterface(advise_events, &IID_IRawElementProviderSimple,
(void **)&elprov);
if (FAILED(hr))
{
ERR("Failed to get IRawElementProviderSimple from advise events\n");
return E_FAIL;
}
hr = IRawElementProviderSimple_get_ProviderOptions(elprov, &prov_opts);
IRawElementProviderSimple_Release(elprov);
if (FAILED(hr))
return hr;
if (!(adv_events = heap_alloc_zero(sizeof(*adv_events))))
return E_OUTOFMEMORY;
if (prov_opts & ProviderOptions_UseComThreading)
{
hr = register_interface_in_git((IUnknown *)advise_events, &IID_IRawElementProviderAdviseEvents,
&adv_events->git_cookie);
if (FAILED(hr))
{
heap_free(adv_events);
return hr;
}
}
adv_events->IWineUiaEventAdviser_iface.lpVtbl = &uia_event_adviser_vtbl;
adv_events->ref = 1;
adv_events->advise_events = advise_events;
IRawElementProviderAdviseEvents_AddRef(advise_events);
if (!uia_array_reserve((void **)&event->event_advisers, &event->event_advisers_arr_size,
event->event_advisers_count + 1, sizeof(*event->event_advisers)))
{
IWineUiaEventAdviser_Release(&adv_events->IWineUiaEventAdviser_iface);
return E_OUTOFMEMORY;
}
event->event_advisers[event->event_advisers_count] = advise_events;
IRawElementProviderAdviseEvents_AddRef(advise_events);
event->event_advisers[event->event_advisers_count] = &adv_events->IWineUiaEventAdviser_iface;
event->event_advisers_count++;
return S_OK;
......
......@@ -102,7 +102,7 @@ struct uia_event
int event_id;
int scope;
IRawElementProviderAdviseEvents **event_advisers;
IWineUiaEventAdviser **event_advisers;
int event_advisers_count;
SIZE_T event_advisers_arr_size;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment