uiautomationcore: Use the free threaded marshaler to marshal IUIAutomationElement interfaces.

Signed-off-by: Connor McAdams <cmcadams@codeweavers.com>
This commit is contained in:
Connor McAdams 2023-05-24 10:57:02 -04:00 committed by Alexandre Julliard
parent cfc50b2887
commit 7844a544af
2 changed files with 92 additions and 0 deletions

View file

@ -10620,6 +10620,79 @@ static void test_UiaFind(void)
CoUninitialize();
}
struct marshal_thread_data {
IUnknown *iface;
const GUID *iface_iid;
BOOL expect_proxy;
const char *file;
int line;
IStream *marshal_stream;
};
static DWORD WINAPI interface_marshal_proxy_thread(LPVOID param)
{
struct marshal_thread_data *data = (struct marshal_thread_data *)param;
IUnknown *proxy_iface, *unk, *unk2;
HRESULT hr;
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
proxy_iface = unk = unk2 = NULL;
hr = CoGetInterfaceAndReleaseStream(data->marshal_stream, data->iface_iid, (void **)&proxy_iface);
ok_(data->file, data->line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = IUnknown_QueryInterface(data->iface, &IID_IUnknown, (void **)&unk);
ok_(data->file, data->line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
ok_(data->file, data->line)(!!unk, "unk == NULL\n");
hr = IUnknown_QueryInterface(proxy_iface, &IID_IUnknown, (void **)&unk2);
ok_(data->file, data->line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
ok_(data->file, data->line)(!!unk2, "unk2 == NULL\n");
if (data->expect_proxy)
ok_(data->file, data->line)(unk != unk2, "unk == unk2\n");
else
ok_(data->file, data->line)(unk == unk2, "unk != unk2\n");
IUnknown_Release(proxy_iface);
IUnknown_Release(unk);
IUnknown_Release(unk2);
CoUninitialize();
return 0;
}
#define check_interface_marshal_proxy_creation( iface, iid, expect_proxy ) \
check_interface_marshal_proxy_creation_( (iface), (iid), (expect_proxy), __FILE__, __LINE__)
static void check_interface_marshal_proxy_creation_(IUnknown *iface, REFIID iid, BOOL expect_proxy, const char *file,
int line)
{
struct marshal_thread_data data = { NULL, iid, expect_proxy, file, line };
HANDLE thread;
HRESULT hr;
hr = IUnknown_QueryInterface(iface, data.iface_iid, (void **)&data.iface);
ok_(file, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = CoMarshalInterThreadInterfaceInStream(data.iface_iid, data.iface, &data.marshal_stream);
ok_(file, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
thread = CreateThread(NULL, 0, interface_marshal_proxy_thread, (void *)&data, 0, NULL);
while (MsgWaitForMultipleObjects(1, &thread, FALSE, INFINITE, QS_ALLINPUT) != WAIT_OBJECT_0)
{
MSG msg;
while(PeekMessageW(&msg, 0, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
}
CloseHandle(thread);
IUnknown_Release(data.iface);
}
static HWND create_test_hwnd(const char *class_name)
{
WNDCLASSA cls = { 0 };
@ -10717,6 +10790,12 @@ static void test_ElementFromHandle(IUIAutomation *uia_iface, BOOL is_cui8)
else
ok(hr == E_NOINTERFACE, "Unexpected hr %#lx.\n", hr);
/*
* The IUIAutomationElement interface uses the free threaded marshaler, so
* no actual proxy interface will be created.
*/
check_interface_marshal_proxy_creation((IUnknown *)element, &IID_IUIAutomationElement, FALSE);
IUIAutomationElement_Release(element);
ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);

View file

@ -1186,6 +1186,8 @@ struct uia_element {
struct uia_cache_property *cached_props;
int cached_props_count;
IUnknown *marshal;
};
static inline struct uia_element *impl_from_IUIAutomationElement9(IUIAutomationElement9 *iface)
@ -1203,6 +1205,8 @@ static HRESULT WINAPI uia_element_QueryInterface(IUIAutomationElement9 *iface, R
IsEqualIID(riid, &IID_IUIAutomationElement6) || IsEqualIID(riid, &IID_IUIAutomationElement7) ||
IsEqualIID(riid, &IID_IUIAutomationElement8) || IsEqualIID(riid, &IID_IUIAutomationElement9))))
*ppv = iface;
else if (IsEqualIID(riid, &IID_IMarshal))
return IUnknown_QueryInterface(element->marshal, riid, ppv);
else
return E_NOINTERFACE;
@ -1235,6 +1239,7 @@ static ULONG WINAPI uia_element_Release(IUIAutomationElement9 *iface)
VariantClear(&element->cached_props[i].prop_val);
}
IUnknown_Release(element->marshal);
heap_free(element->cached_props);
UiaNodeRelease(element->node);
heap_free(element);
@ -2484,6 +2489,7 @@ static const IUIAutomationElement9Vtbl uia_element_vtbl = {
static HRESULT create_uia_element(IUIAutomationElement **iface, BOOL from_cui8, HUIANODE node)
{
struct uia_element *element = heap_alloc_zero(sizeof(*element));
HRESULT hr;
*iface = NULL;
if (!element)
@ -2494,6 +2500,13 @@ static HRESULT create_uia_element(IUIAutomationElement **iface, BOOL from_cui8,
element->from_cui8 = from_cui8;
element->node = node;
hr = CoCreateFreeThreadedMarshaler((IUnknown *)&element->IUIAutomationElement9_iface, &element->marshal);
if (FAILED(hr))
{
heap_free(element);
return hr;
}
*iface = (IUIAutomationElement *)&element->IUIAutomationElement9_iface;
return S_OK;
}