/* * UI Automation tests * * Copyright 2019 Nikolay Sivov for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #define COBJMACROS #include "windows.h" #include "initguid.h" #include "uiautomation.h" #include "wine/test.h" static LRESULT WINAPI test_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { return DefWindowProcA(hwnd, message, wParam, lParam); } static void test_UiaHostProviderFromHwnd(void) { IRawElementProviderSimple *p, *p2; enum ProviderOptions prov_opt; WNDCLASSA cls; HRESULT hr; HWND hwnd; VARIANT v; int i; cls.style = 0; cls.lpfnWndProc = test_wnd_proc; cls.cbClsExtra = 0; cls.cbWndExtra = 0; cls.hInstance = GetModuleHandleA(NULL); cls.hIcon = 0; cls.hCursor = NULL; cls.hbrBackground = NULL; cls.lpszMenuName = NULL; cls.lpszClassName = "HostProviderFromHwnd class"; RegisterClassA(&cls); hwnd = CreateWindowExA(0, "HostProviderFromHwnd class", "Test window 1", WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_VISIBLE, 0, 0, 100, 100, GetDesktopWindow(), NULL, GetModuleHandleA(NULL), NULL); ok(hwnd != NULL, "Failed to create a test window.\n"); p = (void *)0xdeadbeef; hr = UiaHostProviderFromHwnd(NULL, &p); ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); ok(p == NULL, "Unexpected instance.\n"); hr = UiaHostProviderFromHwnd(hwnd, NULL); ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); p = NULL; hr = UiaHostProviderFromHwnd(hwnd, &p); ok(hr == S_OK, "Failed to get host provider, hr %#lx.\n", hr); p2 = NULL; hr = UiaHostProviderFromHwnd(hwnd, &p2); ok(hr == S_OK, "Failed to get host provider, hr %#lx.\n", hr); ok(p != p2, "Unexpected instance.\n"); IRawElementProviderSimple_Release(p2); hr = IRawElementProviderSimple_get_HostRawElementProvider(p, &p2); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(p2 == NULL, "Unexpected instance.\n"); hr = IRawElementProviderSimple_GetPropertyValue(p, UIA_NativeWindowHandlePropertyId, &v); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(V_VT(&v) == VT_I4, "V_VT(&v) = %d\n", V_VT(&v)); ok(V_I4(&v) == HandleToUlong(hwnd), "V_I4(&v) = %#lx, expected %#lx\n", V_I4(&v), HandleToUlong(hwnd)); hr = IRawElementProviderSimple_GetPropertyValue(p, UIA_ProviderDescriptionPropertyId, &v); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(V_VT(&v) == VT_BSTR, "V_VT(&v) = %d\n", V_VT(&v)); VariantClear(&v); /* No patterns are implemented on the HWND Host provider. */ for (i = UIA_InvokePatternId; i < (UIA_CustomNavigationPatternId + 1); i++) { IUnknown *unk; unk = (void *)0xdeadbeef; hr = IRawElementProviderSimple_GetPatternProvider(p, i, &unk); ok(hr == S_OK, "Unexpected hr %#lx, %d.\n", hr, i); ok(!unk, "Pattern %d returned %p\n", i, unk); } hr = IRawElementProviderSimple_get_ProviderOptions(p, &prov_opt); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok((prov_opt == ProviderOptions_ServerSideProvider) || broken(prov_opt == ProviderOptions_ClientSideProvider), /* Windows < 10 1507 */ "Unexpected provider options %#x\n", prov_opt); /* Test behavior post Window destruction. */ DestroyWindow(hwnd); hr = IRawElementProviderSimple_GetPropertyValue(p, UIA_NativeWindowHandlePropertyId, &v); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(V_VT(&v) == VT_I4, "V_VT(&v) = %d\n", V_VT(&v)); ok(V_I4(&v) == HandleToUlong(hwnd), "V_I4(&v) = %#lx, expected %#lx\n", V_I4(&v), HandleToUlong(hwnd)); hr = IRawElementProviderSimple_GetPropertyValue(p, UIA_ProviderDescriptionPropertyId, &v); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(V_VT(&v) == VT_BSTR, "V_VT(&v) = %d\n", V_VT(&v)); VariantClear(&v); hr = IRawElementProviderSimple_get_ProviderOptions(p, &prov_opt); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok((prov_opt == ProviderOptions_ServerSideProvider) || broken(prov_opt == ProviderOptions_ClientSideProvider), /* Windows < 10 1507 */ "Unexpected provider options %#x\n", prov_opt); IRawElementProviderSimple_Release(p); UnregisterClassA("HostProviderFromHwnd class", NULL); } static DWORD WINAPI uia_reserved_val_iface_marshal_thread(LPVOID param) { IStream **stream = param; IUnknown *unk_ns, *unk_ns2, *unk_ma, *unk_ma2; HRESULT hr; CoInitializeEx(NULL, COINIT_MULTITHREADED); hr = CoGetInterfaceAndReleaseStream(stream[0], &IID_IUnknown, (void **)&unk_ns); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = CoGetInterfaceAndReleaseStream(stream[1], &IID_IUnknown, (void **)&unk_ma); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = UiaGetReservedNotSupportedValue(&unk_ns2); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = UiaGetReservedMixedAttributeValue(&unk_ma2); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(unk_ns2 == unk_ns, "UiaGetReservedNotSupported pointer mismatch, unk_ns2 %p, unk_ns %p\n", unk_ns2, unk_ns); ok(unk_ma2 == unk_ma, "UiaGetReservedMixedAttribute pointer mismatch, unk_ma2 %p, unk_ma %p\n", unk_ma2, unk_ma); CoUninitialize(); return 0; } static void test_uia_reserved_value_ifaces(void) { IUnknown *unk_ns, *unk_ns2, *unk_ma, *unk_ma2; IStream *stream[2]; IMarshal *marshal; HANDLE thread; ULONG refcnt; HRESULT hr; /* ReservedNotSupportedValue. */ hr = UiaGetReservedNotSupportedValue(NULL); ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); hr = UiaGetReservedNotSupportedValue(&unk_ns); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(unk_ns != NULL, "UiaGetReservedNotSupportedValue returned NULL interface.\n"); refcnt = IUnknown_AddRef(unk_ns); ok(refcnt == 1, "Expected refcnt %d, got %ld\n", 1, refcnt); refcnt = IUnknown_AddRef(unk_ns); ok(refcnt == 1, "Expected refcnt %d, got %ld\n", 1, refcnt); refcnt = IUnknown_Release(unk_ns); ok(refcnt == 1, "Expected refcnt %d, got %ld\n", 1, refcnt); hr = UiaGetReservedNotSupportedValue(&unk_ns2); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(unk_ns2 != NULL, "UiaGetReservedNotSupportedValue returned NULL interface."); ok(unk_ns2 == unk_ns, "UiaGetReservedNotSupported pointer mismatch, unk_ns2 %p, unk_ns %p\n", unk_ns2, unk_ns); marshal = NULL; hr = IUnknown_QueryInterface(unk_ns, &IID_IMarshal, (void **)&marshal); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(marshal != NULL, "Failed to get IMarshal interface.\n"); refcnt = IMarshal_AddRef(marshal); ok(refcnt == 2, "Expected refcnt %d, got %ld\n", 2, refcnt); refcnt = IMarshal_Release(marshal); ok(refcnt == 1, "Expected refcnt %d, got %ld\n", 1, refcnt); refcnt = IMarshal_Release(marshal); ok(refcnt == 0, "Expected refcnt %d, got %ld\n", 0, refcnt); /* ReservedMixedAttributeValue. */ hr = UiaGetReservedMixedAttributeValue(NULL); ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); hr = UiaGetReservedMixedAttributeValue(&unk_ma); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(unk_ma != NULL, "UiaGetReservedMixedAttributeValue returned NULL interface."); refcnt = IUnknown_AddRef(unk_ma); ok(refcnt == 1, "Expected refcnt %d, got %ld\n", 1, refcnt); refcnt = IUnknown_AddRef(unk_ma); ok(refcnt == 1, "Expected refcnt %d, got %ld\n", 1, refcnt); refcnt = IUnknown_Release(unk_ma); ok(refcnt == 1, "Expected refcnt %d, got %ld\n", 1, refcnt); hr = UiaGetReservedMixedAttributeValue(&unk_ma2); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(unk_ma2 != NULL, "UiaGetReservedMixedAttributeValue returned NULL interface."); ok(unk_ma2 == unk_ma, "UiaGetReservedMixedAttribute pointer mismatch, unk_ma2 %p, unk_ma %p\n", unk_ma2, unk_ma); marshal = NULL; hr = IUnknown_QueryInterface(unk_ma, &IID_IMarshal, (void **)&marshal); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(marshal != NULL, "Failed to get IMarshal interface.\n"); refcnt = IMarshal_AddRef(marshal); ok(refcnt == 2, "Expected refcnt %d, got %ld\n", 2, refcnt); refcnt = IMarshal_Release(marshal); ok(refcnt == 1, "Expected refcnt %d, got %ld\n", 1, refcnt); refcnt = IMarshal_Release(marshal); ok(refcnt == 0, "Expected refcnt %d, got %ld\n", 0, refcnt); /* Test cross-thread marshaling behavior. */ CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); hr = CoMarshalInterThreadInterfaceInStream(&IID_IUnknown, unk_ns, &stream[0]); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = CoMarshalInterThreadInterfaceInStream(&IID_IUnknown, unk_ma, &stream[1]); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); thread = CreateThread(NULL, 0, uia_reserved_val_iface_marshal_thread, (void *)stream, 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); CoUninitialize(); } START_TEST(uiautomation) { test_UiaHostProviderFromHwnd(); test_uia_reserved_value_ifaces(); }