mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-31 14:24:45 +00:00
uiautomationcore: Use the free threaded marshaler to marshal IUIAutomationElement interfaces.
Signed-off-by: Connor McAdams <cmcadams@codeweavers.com>
This commit is contained in:
parent
cfc50b2887
commit
7844a544af
2 changed files with 92 additions and 0 deletions
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue