[PATCH 5/6] user32/tests: Add tests for window cloaking.

Gabriel Ivăncescu gabrielopcode at gmail.com
Fri Nov 6 10:03:34 CST 2020


Signed-off-by: Gabriel Ivăncescu <gabrielopcode at gmail.com>
---
 dlls/user32/tests/win.c | 595 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 595 insertions(+)

diff --git a/dlls/user32/tests/win.c b/dlls/user32/tests/win.c
index 843da89..2bfde85 100644
--- a/dlls/user32/tests/win.c
+++ b/dlls/user32/tests/win.c
@@ -31,6 +31,7 @@
 #include "wingdi.h"
 #include "winuser.h"
 #include "winreg.h"
+#include "dwmapi.h"
 
 #include "wine/test.h"
 
@@ -45,10 +46,51 @@
 #define LONG_PTR INT_PTR
 #define ULONG_PTR UINT_PTR
 
+/* Undocumented structure for (Get|Set)WindowCompositionAttribute */
+struct WINCOMPATTRDATA
+{
+    DWORD attribute;
+    void *pData;
+    ULONG dataSize;
+};
+enum
+{
+    WCA_UNDEFINED = 0,
+    WCA_NCRENDERING_ENABLED = 1,
+    WCA_NCRENDERING_POLICY = 2,
+    WCA_TRANSITIONS_FORCEDISABLED = 3,
+    WCA_ALLOW_NCPAINT = 4,
+    WCA_CAPTION_BUTTON_BOUNDS = 5,
+    WCA_NONCLIENT_RTL_LAYOUT = 6,
+    WCA_FORCE_ICONIC_REPRESENTATION = 7,
+    WCA_EXTENDED_FRAME_BOUNDS = 8,
+    WCA_HAS_ICONIC_BITMAP = 9,
+    WCA_THEME_ATTRIBUTES = 10,
+    WCA_NCRENDERING_EXILED = 11,
+    WCA_NCADORNMENTINFO = 12,
+    WCA_EXCLUDED_FROM_LIVEPREVIEW = 13,
+    WCA_VIDEO_OVERLAY_ACTIVE = 14,
+    WCA_FORCE_ACTIVEWINDOW_APPEARANCE = 15,
+    WCA_DISALLOW_PEEK = 16,
+    WCA_CLOAK = 17,
+    WCA_CLOAKED = 18,
+    WCA_ACCENT_POLICY = 19,
+    WCA_FREEZE_REPRESENTATION = 20,
+    WCA_EVER_UNCLOAKED = 21,
+    WCA_VISUAL_OWNER = 22,
+    WCA_HOLOGRAPHIC = 23,
+    WCA_EXCLUDED_FROM_DDA = 24,
+    WCA_PASSIVEUPDATEMODE = 25,
+    WCA_USEDARKMODECOLORS = 26,
+    WCA_LAST
+};
+
 void dump_region(HRGN hrgn);
 
 static BOOL (WINAPI *pGetWindowInfo)(HWND,WINDOWINFO*);
 static UINT (WINAPI *pGetWindowModuleFileNameA)(HWND,LPSTR,UINT);
+static BOOL (WINAPI *pGetWindowCompositionAttribute)(HWND, struct WINCOMPATTRDATA*);
+static BOOL (WINAPI *pSetWindowCompositionAttribute)(HWND, struct WINCOMPATTRDATA*);
 static BOOL (WINAPI *pGetLayeredWindowAttributes)(HWND,COLORREF*,BYTE*,DWORD*);
 static BOOL (WINAPI *pSetLayeredWindowAttributes)(HWND,COLORREF,BYTE,DWORD);
 static BOOL (WINAPI *pUpdateLayeredWindow)(HWND,HDC,POINT*,SIZE*,HDC,POINT*,COLORREF,BLENDFUNCTION*,DWORD);
@@ -8269,6 +8311,551 @@ static void test_layered_window(void)
     DeleteObject( hbm );
 }
 
+static void cloaked_attribute_proc(HWND hwndOtherProc)
+{
+    HWND hwnd;
+    MSG msg;
+
+    hwnd = CreateWindowExA(0, "static", "static", WS_OVERLAPPED | WS_VISIBLE,
+                           0, 0, 100, 100, hwndOtherProc, 0, NULL, NULL);
+    ok(hwnd != 0, "CreateWindowEx failed\n");
+
+    if (!PostMessageA(hwndOtherProc, WM_APP, 0, (LPARAM)hwnd))
+    {
+        ok(0, "PostMessage failed, error %u\n", GetLastError());
+        DestroyWindow(hwnd);
+        return;
+    }
+
+    while (GetMessageA(&msg, NULL, 0, 0) > 0 && (msg.hwnd != hwnd || msg.message != WM_APP))
+        DispatchMessageA(&msg);
+    ok(msg.hwnd == hwnd && msg.message == WM_APP, "didn't get WM_APP message\n");
+    SetWindowLongPtrA(hwnd, GWLP_HWNDPARENT, 0);
+    ok(PostMessageA(hwndOtherProc, WM_APP, 0, 0), "PostMessage failed, error %u\n", GetLastError());
+
+    while (GetMessageA(&msg, NULL, 0, 0) > 0 && (msg.hwnd != hwnd || msg.message != WM_APP))
+        DispatchMessageW(&msg);
+    DestroyWindow(hwnd);
+    ok(PostMessageA(hwndOtherProc, WM_APP, 0, 0), "PostMessage failed, error %u\n", GetLastError());
+}
+
+static void test_cloaked_attribute(const char *argv0)
+{
+    struct WINCOMPATTRDATA data, set_data;
+    HWND hwnd, hwnd2, hwndOwner;
+    PROCESS_INFORMATION info;
+    BOOL ret, cloak = FALSE;
+    DWORD cloaked, version;
+    STARTUPINFOA startup;
+    char cmd[MAX_PATH];
+    RECT rect;
+    POINT pt;
+    MSG msg;
+
+    if (!pGetWindowCompositionAttribute || !pSetWindowCompositionAttribute)
+    {
+        win_skip("window composition APIs not supported\n");
+        return;
+    }
+
+    version = GetVersion();
+    if (broken(LOBYTE(LOWORD(version)) < 6 || (LOBYTE(LOWORD(version)) == 6 && HIBYTE(LOWORD(version)) < 2)))
+    {
+        win_skip("cloak attribute is not supported\n");
+        return;
+    }
+
+    hwnd = CreateWindowA("MainWindowClass", NULL, WS_OVERLAPPED | WS_VISIBLE,
+                         200, 200, 200, 200, 0, 0, 0, NULL);
+    assert(hwnd);
+
+    SetLastError(0xdeadbeef);
+    ret = pGetWindowCompositionAttribute(hwnd, NULL);
+    ok(!ret, "GetWindowCompositionAttribute should fail with NULL pointer\n");
+    ok(GetLastError() == ERROR_NOACCESS, "expected ERROR_NOACCESS, got %u\n", GetLastError());
+    SetLastError(0xdeadbeef);
+    ret = pSetWindowCompositionAttribute(hwnd, NULL);
+    ok(!ret, "SetWindowCompositionAttribute should fail with NULL pointer\n");
+    ok(GetLastError() == ERROR_NOACCESS, "expected ERROR_NOACCESS, got %u\n", GetLastError());
+
+    data.attribute = WCA_CLOAKED;
+    data.pData = NULL;
+    data.dataSize = sizeof(cloaked);
+    SetLastError(0xdeadbeef);
+    ret = pGetWindowCompositionAttribute(hwnd, &data);
+    ok(!ret, "GetWindowCompositionAttribute should fail with NULL pData\n");
+    ok(GetLastError() == ERROR_NOACCESS, "expected ERROR_NOACCESS, got %u\n", GetLastError());
+    set_data.attribute = WCA_CLOAK;
+    set_data.pData = NULL;
+    set_data.dataSize = sizeof(cloak);
+    SetLastError(0xdeadbeef);
+    ret = pSetWindowCompositionAttribute(hwnd, &set_data);
+    ok(!ret, "SetWindowCompositionAttribute should fail with NULL pData\n");
+    ok(GetLastError() == ERROR_NOACCESS, "expected ERROR_NOACCESS, got %u\n", GetLastError());
+
+    data.pData = &cloaked;
+    data.dataSize = sizeof(cloaked) - 1;
+    SetLastError(0xdeadbeef);
+    ret = pGetWindowCompositionAttribute(hwnd, &data);
+    ok(!ret, "GetWindowCompositionAttribute should have failed\n");
+    ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
+    set_data.pData = &cloak;
+    set_data.dataSize = sizeof(cloak) - 1;
+    SetLastError(0xdeadbeef);
+    ret = pSetWindowCompositionAttribute(hwnd, &set_data);
+    ok(!ret, "SetWindowCompositionAttribute should have failed\n");
+    ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
+
+    data.dataSize = sizeof(cloaked);
+    SetLastError(0xdeadbeef);
+    ret = pGetWindowCompositionAttribute(NULL, &data);
+    ok(!ret, "GetWindowCompositionAttribute should have failed with NULL hwnd\n");
+    ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %u\n", GetLastError());
+    set_data.dataSize = sizeof(cloak);
+    SetLastError(0xdeadbeef);
+    ret = pSetWindowCompositionAttribute(NULL, &set_data);
+    ok(!ret, "SetWindowCompositionAttribute should have failed with NULL hwnd\n");
+    ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %u\n", GetLastError());
+
+    SetLastError(0xdeadbeef);
+    ret = pGetWindowCompositionAttribute(HWND_BROADCAST, &data);
+    ok(!ret, "GetWindowCompositionAttribute should have failed with broadcast hwnd\n");
+    ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %u\n", GetLastError());
+    SetLastError(0xdeadbeef);
+    ret = pGetWindowCompositionAttribute(HWND_TOPMOST, &data);
+    ok(!ret, "GetWindowCompositionAttribute should have failed with broadcast hwnd\n");
+    ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %u\n", GetLastError());
+    SetLastError(0xdeadbeef);
+    ret = pSetWindowCompositionAttribute(HWND_BROADCAST, &set_data);
+    ok(!ret, "SetWindowCompositionAttribute should have failed with broadcast hwnd\n");
+    ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %u\n", GetLastError());
+    SetLastError(0xdeadbeef);
+    ret = pSetWindowCompositionAttribute(HWND_TOPMOST, &set_data);
+    ok(!ret, "SetWindowCompositionAttribute should have failed with broadcast hwnd\n");
+    ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %u\n", GetLastError());
+
+    data.dataSize = sizeof(cloaked) + 1;
+    ret = pGetWindowCompositionAttribute(hwnd, &data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ok(!cloaked, "window was not supposed to be cloaked: %u\n", cloaked);
+    data.dataSize = sizeof(cloaked);
+
+    set_data.dataSize = sizeof(cloak) + 1;
+    ret = pSetWindowCompositionAttribute(hwnd, &set_data);
+    ok(ret, "SetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    set_data.dataSize = sizeof(cloak);
+    ret = pGetWindowCompositionAttribute(hwnd, &data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ok(!cloaked, "window was not supposed to be cloaked: %u\n", cloaked);
+
+    /* cloaking and visibility are unrelated */
+    ret = ShowWindow(hwnd, SW_HIDE);
+    ok(ret, "ShowWindow returned %u\n", ret);
+    ok(!(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE), "window has the WS_VISIBLE style\n");
+    ret = pGetWindowCompositionAttribute(hwnd, &data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ok(!cloaked, "window was not supposed to be cloaked: %u\n", cloaked);
+    ok(GetActiveWindow() == hwndMain, "wrong active window\n");
+
+    cloak = TRUE;
+    ret = pSetWindowCompositionAttribute(hwnd, &set_data);
+    ok(ret, "SetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ret = pGetWindowCompositionAttribute(hwnd, &data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ok(cloaked == DWM_CLOAKED_APP, "window was not cloaked as DWM_CLOAKED_APP, got %u\n", cloaked);
+    ok(GetActiveWindow() == hwndMain, "wrong active window\n");
+
+    ret = ShowWindow(hwnd, SW_SHOW);
+    ok(!ret, "ShowWindow returned %u\n", ret);
+    ok(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE, "window does not have the WS_VISIBLE style\n");
+    ok(GetActiveWindow() == hwnd, "wrong active window\n");
+    ret = pGetWindowCompositionAttribute(hwnd, &data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ok(cloaked == DWM_CLOAKED_APP, "window was not cloaked as DWM_CLOAKED_APP, got %u\n", cloaked);
+
+    /* cloaking and minimization are unrelated */
+    ret = ShowWindow(hwnd, SW_MINIMIZE);
+    ok(ret, "ShowWindow returned %u\n", ret);
+    ok(GetWindowLongA(hwnd, GWL_STYLE) & WS_MINIMIZE, "window does not have the WS_MINIMIZE style\n");
+    ret = pGetWindowCompositionAttribute(hwnd, &data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ok(cloaked == DWM_CLOAKED_APP, "window was not cloaked as DWM_CLOAKED_APP, got %u\n", cloaked);
+
+    cloak = FALSE;
+    ret = pSetWindowCompositionAttribute(hwnd, &set_data);
+    ok(ret, "SetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ret = pGetWindowCompositionAttribute(hwnd, &data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ok(!cloaked, "window was not supposed to be cloaked: %u\n", cloaked);
+    ok(GetWindowLongA(hwnd, GWL_STYLE) & WS_MINIMIZE, "window does not have the WS_MINIMIZE style\n");
+
+    cloak = TRUE;
+    ret = pSetWindowCompositionAttribute(hwnd, &set_data);
+    ok(ret, "SetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ret = pGetWindowCompositionAttribute(hwnd, &data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ok(cloaked == DWM_CLOAKED_APP, "window was not cloaked as DWM_CLOAKED_APP, got %u\n", cloaked);
+    ok(GetWindowLongA(hwnd, GWL_STYLE) & WS_MINIMIZE, "window does not have the WS_MINIMIZE style\n");
+
+    ret = ShowWindow(hwnd, SW_RESTORE);
+    ok(ret, "ShowWindow returned %u\n", ret);
+    ok(!(GetWindowLongA(hwnd, GWL_STYLE) & WS_MINIMIZE), "window has the WS_MINIMIZE style\n");
+    ret = pGetWindowCompositionAttribute(hwnd, &data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ok(cloaked == DWM_CLOAKED_APP, "window was not cloaked as DWM_CLOAKED_APP, got %u\n", cloaked);
+
+    /* cloaked windows can be activated and have valid rects */
+    GetWindowRect(hwnd, &rect);
+    ok(rect.left == 200 && rect.top == 200 && rect.right == 400 && rect.bottom == 400,
+       "wrong window rect %s\n", wine_dbgstr_rect(&rect));
+    ok(SetForegroundWindow(hwndMain), "SetForegroundWindow failed\n");
+    ok(GetActiveWindow() == hwndMain, "wrong active window\n");
+    ok(SetForegroundWindow(hwnd), "SetForegroundWindow failed\n");
+    ok(GetActiveWindow() == hwnd, "wrong active window\n");
+
+    /* cloaked windows can't be retrieved via WindowFromPoint */
+    pt.x = pt.y = 350;
+    hwnd2 = WindowFromPoint(pt);
+    ok(hwnd2 != hwnd, "cloaked window returned from WindowFromPoint\n");
+    pt.x = pt.y = 250;
+    hwnd2 = WindowFromPoint(pt);
+    ok(hwnd2 == hwndMain, "unexpected window returned %p (expected %p)\n", hwnd2, hwndMain);
+    pt.x = pt.y = 10;
+    hwnd2 = ChildWindowFromPointEx(hwnd, pt, CWP_SKIPDISABLED | CWP_SKIPINVISIBLE | CWP_SKIPTRANSPARENT);
+    ok(hwnd2 == hwnd, "unexpected window returned %p (expected %p)\n", hwnd2, hwnd);
+
+    cloak = FALSE;
+    ret = pSetWindowCompositionAttribute(hwnd, &set_data);
+    ok(ret, "SetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    pt.x = pt.y = 350;
+    hwnd2 = WindowFromPoint(pt);
+    ok(hwnd2 == hwnd, "unexpected window returned %p (expected %p)\n", hwnd2, hwnd);
+
+    /* child windows can't be cloaked, but remember their cloaked status */
+    cloak = TRUE;
+    ret = pSetWindowCompositionAttribute(hwnd, &set_data);
+    ok(ret, "SetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ret = pGetWindowCompositionAttribute(hwnd, &data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ok(cloaked == DWM_CLOAKED_APP, "window was not cloaked as DWM_CLOAKED_APP, got %u\n", cloaked);
+
+    hwndOwner = CreateWindowA("MainWindowClass", NULL, WS_OVERLAPPED | WS_VISIBLE,
+                              100, 100, 300, 300, 0, 0, 0, NULL);
+    assert(hwndOwner);
+
+    ok(SetParent(hwnd, hwndOwner) == GetDesktopWindow(), "SetParent failed, error %u\n", GetLastError());
+    ok(GetAncestor(hwnd, GA_PARENT) == hwndOwner, "unexpected parent window\n");
+    ret = pGetWindowCompositionAttribute(hwnd, &data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ok(!cloaked, "window was not supposed to be cloaked: %u\n", cloaked);
+
+    ok(SetParent(hwnd, NULL) == hwndOwner, "SetParent failed, error %u\n", GetLastError());
+    ok(GetAncestor(hwnd, GA_PARENT) == GetDesktopWindow(), "unexpected parent window\n");
+    ret = pGetWindowCompositionAttribute(hwnd, &data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ok(cloaked == DWM_CLOAKED_APP, "window was not cloaked as DWM_CLOAKED_APP, got %u\n", cloaked);
+
+    cloak = FALSE;
+    ret = pSetWindowCompositionAttribute(hwnd, &set_data);
+    ok(ret, "SetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ret = pGetWindowCompositionAttribute(hwnd, &data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ok(!cloaked, "window was not supposed to be cloaked: %u\n", cloaked);
+
+    ok(SetParent(hwnd, hwndOwner) == GetDesktopWindow(), "SetParent failed, error %u\n", GetLastError());
+    ok(GetAncestor(hwnd, GA_PARENT) == hwndOwner, "unexpected parent window\n");
+    cloak = TRUE;
+    SetLastError(0xdeadbeef);
+    ret = pSetWindowCompositionAttribute(hwnd, &set_data);
+    ok(!ret, "SetWindowCompositionAttribute should have failed on a child window\n");
+    ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %u\n", GetLastError());
+    ret = pGetWindowCompositionAttribute(hwnd, &data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ok(!cloaked, "window was not supposed to be cloaked: %u\n", cloaked);
+    ok(SetParent(hwnd, NULL) == hwndOwner, "SetParent failed, error %u\n", GetLastError());
+    ok(GetAncestor(hwnd, GA_PARENT) == GetDesktopWindow(), "unexpected parent window\n");
+
+    cloak = TRUE;
+    ret = pSetWindowCompositionAttribute(hwndOwner, &set_data);
+    ok(ret, "SetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ret = pGetWindowCompositionAttribute(hwndOwner, &data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ok(cloaked == DWM_CLOAKED_APP, "window was not cloaked as DWM_CLOAKED_APP, got %u\n", cloaked);
+
+    ok(SetParent(hwnd, hwndOwner) == GetDesktopWindow(), "SetParent failed, error %u\n", GetLastError());
+    ok(GetAncestor(hwnd, GA_PARENT) == hwndOwner, "unexpected parent window\n");
+    ret = pGetWindowCompositionAttribute(hwnd, &data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ok(cloaked == (DWM_CLOAKED_APP | DWM_CLOAKED_INHERITED),
+        "window was not cloaked as DWM_CLOAKED_APP | DWM_CLOAKED_INHERITED, got %u\n", cloaked);
+    pt.x = pt.y = 205;
+    hwnd2 = ChildWindowFromPointEx(hwndOwner, pt, CWP_SKIPDISABLED | CWP_SKIPINVISIBLE | CWP_SKIPTRANSPARENT);
+    ok(hwnd2 == hwnd, "unexpected window returned %p (expected %p)\n", hwnd2, hwnd);
+
+    cloak = FALSE;
+    ret = pSetWindowCompositionAttribute(hwndOwner, &set_data);
+    ok(ret, "SetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ret = pGetWindowCompositionAttribute(hwndOwner, &data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ok(!cloaked, "window was not supposed to be cloaked: %u\n", cloaked);
+    ret = pGetWindowCompositionAttribute(hwnd, &data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ok(!cloaked, "window was not supposed to be cloaked: %u\n", cloaked);
+
+    ok(SetParent(hwnd, NULL) == hwndOwner, "SetParent failed, error %u\n", GetLastError());
+    ok(GetAncestor(hwnd, GA_PARENT) == GetDesktopWindow(), "unexpected parent window\n");
+
+    /* owned windows inherit the cloaked status from the owner */
+    SetWindowLongPtrA(hwnd, GWLP_HWNDPARENT, (LONG_PTR)hwndOwner);
+    ok(GetWindow(hwnd, GW_OWNER) == hwndOwner, "unexpected owner window\n");
+
+    cloak = TRUE;
+    ret = pSetWindowCompositionAttribute(hwndOwner, &set_data);
+    ok(ret, "SetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ret = pGetWindowCompositionAttribute(hwndOwner, &data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ok(cloaked == DWM_CLOAKED_APP, "window was not cloaked as DWM_CLOAKED_APP, got %u\n", cloaked);
+    ret = pGetWindowCompositionAttribute(hwnd, &data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ok(cloaked == DWM_CLOAKED_APP, "window was not cloaked as DWM_CLOAKED_APP, got %u\n", cloaked);
+
+    cloak = FALSE;
+    ret = pSetWindowCompositionAttribute(hwndOwner, &set_data);
+    ok(ret, "SetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ret = pGetWindowCompositionAttribute(hwndOwner, &data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ok(!cloaked, "window was not supposed to be cloaked: %u\n", cloaked);
+    ret = pGetWindowCompositionAttribute(hwnd, &data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ok(!cloaked, "window was not supposed to be cloaked: %u\n", cloaked);
+
+    /* owned windows can't be uncloaked if their owner is cloaked, but they can be cloaked */
+    cloak = TRUE;
+    ret = pSetWindowCompositionAttribute(hwndOwner, &set_data);
+    ok(ret, "SetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ret = pGetWindowCompositionAttribute(hwnd, &data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ok(cloaked == DWM_CLOAKED_APP, "window was not cloaked as DWM_CLOAKED_APP, got %u\n", cloaked);
+    cloak = FALSE;
+    SetLastError(0xdeadbeef);
+    ret = pSetWindowCompositionAttribute(hwnd, &set_data);
+    ok(!ret, "SetWindowCompositionAttribute should have failed on an owned window\n");
+    ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
+
+    cloak = FALSE;
+    ret = pSetWindowCompositionAttribute(hwndOwner, &set_data);
+    ok(ret, "SetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ret = pGetWindowCompositionAttribute(hwndOwner, &data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ok(!cloaked, "window was not supposed to be cloaked: %u\n", cloaked);
+    cloak = TRUE;
+    ret = pSetWindowCompositionAttribute(hwnd, &set_data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ret = pGetWindowCompositionAttribute(hwndOwner, &data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ok(!cloaked, "window was not supposed to be cloaked: %u\n", cloaked);
+    ret = pGetWindowCompositionAttribute(hwnd, &data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ok(cloaked == DWM_CLOAKED_APP, "window was not cloaked as DWM_CLOAKED_APP, got %u\n", cloaked);
+
+    cloak = FALSE;
+    ret = pSetWindowCompositionAttribute(hwndOwner, &set_data);
+    ok(ret, "SetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ret = pGetWindowCompositionAttribute(hwnd, &data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ok(!cloaked, "window was not supposed to be cloaked: %u\n", cloaked);
+    ret = pSetWindowCompositionAttribute(hwnd, &set_data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ret = pGetWindowCompositionAttribute(hwndOwner, &data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ok(!cloaked, "window was not supposed to be cloaked: %u\n", cloaked);
+    ret = pGetWindowCompositionAttribute(hwnd, &data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ok(!cloaked, "window was not supposed to be cloaked: %u\n", cloaked);
+
+    /* owned windows remain cloaked after inheriting it, even if they get disowned */
+    cloak = TRUE;
+    ret = pSetWindowCompositionAttribute(hwndOwner, &set_data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ret = pGetWindowCompositionAttribute(hwnd, &data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ok(cloaked == DWM_CLOAKED_APP, "window was not cloaked as DWM_CLOAKED_APP, got %u\n", cloaked);
+
+    SetWindowLongPtrA(hwnd, GWLP_HWNDPARENT, 0);
+    ok(GetWindow(hwnd, GW_OWNER) == 0, "unexpected owner window\n");
+    ret = pGetWindowCompositionAttribute(hwnd, &data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ok(cloaked == DWM_CLOAKED_APP, "window was not cloaked as DWM_CLOAKED_APP, got %u\n", cloaked);
+
+    /* owned windows inherit the cloak attribute when setting new owner */
+    cloak = FALSE;
+    ret = pSetWindowCompositionAttribute(hwnd, &set_data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ret = pGetWindowCompositionAttribute(hwnd, &data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ok(!cloaked, "window was not supposed to be cloaked: %u\n", cloaked);
+
+    SetWindowLongPtrA(hwnd, GWLP_HWNDPARENT, (LONG_PTR)hwndOwner);
+    ok(GetWindow(hwnd, GW_OWNER) == hwndOwner, "unexpected owner window\n");
+    ret = pGetWindowCompositionAttribute(hwnd, &data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ok(cloaked == DWM_CLOAKED_APP, "window was not cloaked as DWM_CLOAKED_APP, got %u\n", cloaked);
+
+    SetWindowLongPtrA(hwnd, GWLP_HWNDPARENT, 0);
+    ok(GetWindow(hwnd, GW_OWNER) == 0, "unexpected owner window\n");
+    ret = pGetWindowCompositionAttribute(hwnd, &data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ok(cloaked == DWM_CLOAKED_APP, "window was not cloaked as DWM_CLOAKED_APP, got %u\n", cloaked);
+
+    /* DWM_CLOAKED_INHERITED is not used even if the window is created as owned */
+    DestroyWindow(hwnd);
+    ret = pGetWindowCompositionAttribute(hwndOwner, &data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ok(cloaked == DWM_CLOAKED_APP, "window was not cloaked as DWM_CLOAKED_APP, got %u\n", cloaked);
+    hwnd = CreateWindowA("MainWindowClass", NULL, WS_POPUP | WS_VISIBLE,
+                         200, 200, 200, 200, hwndOwner, 0, 0, NULL);
+    assert(hwnd);
+    ret = pGetWindowCompositionAttribute(hwnd, &data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ok(cloaked == DWM_CLOAKED_APP, "window was not cloaked as DWM_CLOAKED_APP, got %u\n", cloaked);
+
+    SetWindowLongPtrA(hwnd, GWLP_HWNDPARENT, 0);
+    ok(GetWindow(hwnd, GW_OWNER) == 0, "unexpected owner window\n");
+    DestroyWindow(hwndOwner);
+
+    /* windows belonging to another process can't be cloaked directly */
+    cloak = FALSE;
+    ret = pSetWindowCompositionAttribute(hwnd, &set_data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ret = pGetWindowCompositionAttribute(hwnd, &data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ok(!cloaked, "window was not supposed to be cloaked: %u\n", cloaked);
+
+    sprintf(cmd, "%s win test_cloaked_attribute %p\n", argv0, hwnd);
+    memset(&startup, 0, sizeof(startup));
+    startup.cb = sizeof(startup);
+    ok(CreateProcessA(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL,
+                      &startup, &info), "CreateProcess failed.\n");
+    CloseHandle(info.hThread);
+
+    while (GetMessageA(&msg, NULL, 0, 0) > 0 && (msg.hwnd != hwnd || msg.message != WM_APP))
+        DispatchMessageA(&msg);
+    ok(msg.hwnd == hwnd && msg.message == WM_APP, "didn't get WM_APP message with hwnd\n");
+    hwnd2 = (HWND)msg.lParam;
+    flush_events(TRUE);
+
+    ok(GetWindow(hwnd2, GW_OWNER) == hwnd, "unexpected owner window\n");
+    ret = pGetWindowCompositionAttribute(hwnd2, &data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ok(!cloaked, "window was not supposed to be cloaked: %u\n", cloaked);
+    cloak = TRUE;
+    SetLastError(0xdeadbeef);
+    ret = pSetWindowCompositionAttribute(hwnd2, &set_data);
+    ok(!ret, "SetWindowCompositionAttribute should fail with NULL pData\n");
+    ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %u\n", GetLastError());
+
+    /* but they can be cloaked by inheriting the owner's cloaked status */
+    cloak = TRUE;
+    ret = pSetWindowCompositionAttribute(hwnd, &set_data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ret = pGetWindowCompositionAttribute(hwnd, &data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ok(cloaked == DWM_CLOAKED_APP, "window was not cloaked as DWM_CLOAKED_APP, got %u\n", cloaked);
+    ret = pGetWindowCompositionAttribute(hwnd2, &data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ok(cloaked == DWM_CLOAKED_APP, "window was not cloaked as DWM_CLOAKED_APP, got %u\n", cloaked);
+
+    ok(PostMessageA(hwnd2, WM_APP, 0, 0), "PostMessage failed, error %u\n", GetLastError());
+    while (GetMessageA(&msg, NULL, 0, 0) > 0 && (msg.hwnd != hwnd || msg.message != WM_APP))
+        DispatchMessageA(&msg);
+    ok(msg.hwnd == hwnd && msg.message == WM_APP, "didn't get WM_APP message\n");
+    flush_events(TRUE);
+    ok(GetWindow(hwnd2, GW_OWNER) == 0, "unexpected owner window\n");
+
+    cloak = FALSE;
+    ret = pSetWindowCompositionAttribute(hwnd, &set_data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ret = pGetWindowCompositionAttribute(hwnd, &data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ok(!cloaked, "window was not supposed to be cloaked: %u\n", cloaked);
+    ret = pGetWindowCompositionAttribute(hwnd2, &data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ok(cloaked == DWM_CLOAKED_APP, "window was not cloaked as DWM_CLOAKED_APP, got %u\n", cloaked);
+    SetLastError(0xdeadbeef);
+    ret = pSetWindowCompositionAttribute(hwnd2, &set_data);
+    ok(!ret, "SetWindowCompositionAttribute should fail with NULL pData\n");
+    ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %u\n", GetLastError());
+
+    SetWindowLongPtrA(hwnd, GWLP_HWNDPARENT, (LONG_PTR)hwnd2);
+    ok(GetWindow(hwnd, GW_OWNER) == hwnd2, "unexpected owner window\n");
+    ret = pGetWindowCompositionAttribute(hwnd, &data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ok(cloaked == DWM_CLOAKED_APP, "window was not cloaked as DWM_CLOAKED_APP, got %u\n", cloaked);
+    cloak = FALSE;
+    SetLastError(0xdeadbeef);
+    ret = pSetWindowCompositionAttribute(hwnd, &set_data);
+    ok(!ret, "SetWindowCompositionAttribute should have failed on an owned window\n");
+    ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
+
+    SetWindowLongPtrA(hwnd, GWLP_HWNDPARENT, 0);
+    ok(GetWindow(hwnd, GW_OWNER) == 0, "unexpected owner window\n");
+    ret = pGetWindowCompositionAttribute(hwnd, &data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ok(cloaked == DWM_CLOAKED_APP, "window was not cloaked as DWM_CLOAKED_APP, got %u\n", cloaked);
+
+    /* child windows behave identically whether they're on different process or not */
+    cloak = FALSE;
+    ret = pSetWindowCompositionAttribute(hwnd, &set_data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ret = pGetWindowCompositionAttribute(hwnd, &data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ok(!cloaked, "window was not supposed to be cloaked: %u\n", cloaked);
+    ok(SetParent(hwnd2, hwnd) == GetDesktopWindow(), "SetParent failed, error %u\n", GetLastError());
+    flush_events(TRUE);
+    ok(GetAncestor(hwnd2, GA_PARENT) == hwnd, "unexpected parent window\n");
+    ret = pGetWindowCompositionAttribute(hwnd2, &data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ok(!cloaked, "window was not supposed to be cloaked: %u\n", cloaked);
+
+    cloak = TRUE;
+    ret = pSetWindowCompositionAttribute(hwnd, &set_data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ret = pGetWindowCompositionAttribute(hwnd, &data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ok(cloaked == DWM_CLOAKED_APP, "window was not cloaked as DWM_CLOAKED_APP, got %u\n", cloaked);
+    ret = pGetWindowCompositionAttribute(hwnd2, &data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ok(cloaked == (DWM_CLOAKED_APP | DWM_CLOAKED_INHERITED),
+        "window was not cloaked as DWM_CLOAKED_APP | DWM_CLOAKED_INHERITED, got %u\n", cloaked);
+
+    cloak = FALSE;
+    ret = pSetWindowCompositionAttribute(hwnd, &set_data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ret = pGetWindowCompositionAttribute(hwnd, &data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ok(!cloaked, "window was not supposed to be cloaked: %u\n", cloaked);
+    ret = pGetWindowCompositionAttribute(hwnd2, &data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ok(!cloaked, "window was not supposed to be cloaked: %u\n", cloaked);
+
+    ok(SetParent(hwnd2, NULL) == hwnd, "SetParent failed, error %u\n", GetLastError());
+    flush_events(TRUE);
+    ok(GetAncestor(hwnd, GA_PARENT) == GetDesktopWindow(), "unexpected parent window\n");
+    ret = pGetWindowCompositionAttribute(hwnd2, &data);
+    ok(ret, "GetWindowCompositionAttribute failed, error %u\n", GetLastError());
+    ok(cloaked == DWM_CLOAKED_APP, "window was not cloaked as DWM_CLOAKED_APP, got %u\n", cloaked);
+
+    ok(PostMessageA(hwnd2, WM_APP, 0, 0), "PostMessage failed, error %u\n", GetLastError());
+    while (GetMessageA(&msg, NULL, 0, 0) > 0 && (msg.hwnd != hwnd || msg.message != WM_APP))
+        DispatchMessageA(&msg);
+    ok(msg.hwnd == hwnd && msg.message == WM_APP, "didn't get WM_APP message\n");
+    flush_events(TRUE);
+    wait_child_process(info.hProcess);
+    CloseHandle(info.hProcess);
+
+    DestroyWindow(hwnd);
+}
+
 static MONITORINFO mi;
 
 static LRESULT CALLBACK fullscreen_wnd_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
@@ -11904,6 +12491,8 @@ START_TEST(win)
     HMODULE gdi32 = GetModuleHandleA("gdi32.dll");
     pGetWindowInfo = (void *)GetProcAddress( user32, "GetWindowInfo" );
     pGetWindowModuleFileNameA = (void *)GetProcAddress( user32, "GetWindowModuleFileNameA" );
+    pGetWindowCompositionAttribute = (void *)GetProcAddress( user32, "GetWindowCompositionAttribute" );
+    pSetWindowCompositionAttribute = (void *)GetProcAddress( user32, "SetWindowCompositionAttribute" );
     pGetLayeredWindowAttributes = (void *)GetProcAddress( user32, "GetLayeredWindowAttributes" );
     pSetLayeredWindowAttributes = (void *)GetProcAddress( user32, "SetLayeredWindowAttributes" );
     pUpdateLayeredWindow = (void *)GetProcAddress( user32, "UpdateLayeredWindow" );
@@ -11935,6 +12524,11 @@ START_TEST(win)
             other_process_proc(hwnd);
             return;
         }
+        else if (!strcmp(argv[2], "test_cloaked_attribute"))
+        {
+            cloaked_attribute_proc(hwnd);
+            return;
+        }
     }
 
     if (argc == 3 && !strcmp(argv[2], "winproc_limit"))
@@ -12039,6 +12633,7 @@ START_TEST(win)
     test_GetUpdateRect();
     test_Expose();
     test_layered_window();
+    test_cloaked_attribute(argv[0]);
 
     test_SetForegroundWindow(hwndMain);
     test_handles( hwndMain );
-- 
2.21.0




More information about the wine-devel mailing list