Reactos
1/*
2 * PROJECT: ReactOS API Tests
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Test for imagelist
5 * COPYRIGHT: Copyright 2024 Whindmar Saksit <whindsaks@proton.me>
6 */
7
8#include "wine/test.h"
9#include <stdio.h>
10#include <windows.h>
11#include <commctrl.h>
12#include <comctl32_undoc.h>
13
14#define WinVerMajor() LOBYTE(GetVersion())
15
16#define ILC_COLORMASK 0xfe
17#define IL_IMGSIZE 16
18
19static BOOL IL_IsValid(HIMAGELIST himl)
20{
21 int w = -42, h;
22 if (!himl || IsBadReadPtr(himl, sizeof(void*)))
23 return FALSE;
24 return ImageList_GetIconSize(himl, &w, &h) && w != -42;
25}
26
27static HRESULT IL_Destroy(HIMAGELIST himl)
28{
29 if (himl && !IL_IsValid(himl))
30 return E_INVALIDARG;
31 return ImageList_Destroy(himl) ? S_OK : S_FALSE;
32}
33
34static inline HIMAGELIST IL_Create(UINT flags)
35{
36 return ImageList_Create(IL_IMGSIZE, IL_IMGSIZE, flags, 1, 0);
37}
38
39static UINT IL_CalculateOtherBpp(UINT ilc)
40{
41 UINT bpp = (ilc & ILC_COLORMASK) == ILC_COLOR32 ? ILC_COLOR16 : ILC_COLOR32;
42 return (ilc & ~ILC_COLORMASK) | bpp;
43}
44
45static BOOL IL_AddImagesForTest(HIMAGELIST himl)
46{
47 int idx = -1;
48 HINSTANCE hInst = LoadLibraryW(L"USER32");
49 if (!hInst)
50 return FALSE;
51 HICON hIco = (HICON)LoadImage(hInst, MAKEINTRESOURCE(100),
52 IMAGE_ICON, IL_IMGSIZE, IL_IMGSIZE, 0);
53 if (hIco)
54 {
55 idx = ImageList_AddIcon(himl, hIco);
56 DestroyIcon(hIco);
57 }
58 FreeLibrary(hInst);
59 return idx != -1;
60}
61
62static void Test_SystemIL(void)
63{
64 const UINT flags = ILC_COLOR16 | ILC_MASK;
65 HIMAGELIST himl;
66
67 himl = IL_Create(flags);
68 ok(IL_Destroy(himl) == S_OK && !IL_IsValid(himl), "Can destroy normal\n");
69
70 /* You can (sometimes) destroy a system imagelist!
71 * On Win9x it destroys it for all processes according to
72 * https://sporks.space/2021/09/18/notes-on-the-system-image-list/ and
73 * https://www.catch22.net/tuts/win32/system-image-list/
74 */
75 himl = IL_Create(flags | ILC_SYSTEM);
76 if (WinVerMajor() >= 6)
77 ok(IL_Destroy(himl) == S_FALSE && IL_IsValid(himl), "Can't destroy system\n");
78 else
79 ok(IL_Destroy(himl) == S_OK && !IL_IsValid(himl), "Can destroy system\n");
80}
81
82static void Test_Flags(void)
83{
84 const UINT flags = ILC_COLOR16 | ILC_MASK;
85 UINT flagsIn, flagsOut;
86 HIMAGELIST himl;
87
88 himl = IL_Create(flagsIn = flags);
89 flagsOut = ImageList_GetFlags(himl);
90 if (himl ? TRUE : (skip("Could not initialize\n"), FALSE))
91 {
92 ok((flagsOut & ILC_COLORMASK) == (flagsIn & ILC_COLORMASK), "ILC_COLOR\n");
93 ok(!(flagsOut & ILC_SYSTEM), "!ILC_SYSTEM\n");
94
95 ok(IL_AddImagesForTest(himl), "Initialize\n");
96 flagsIn = IL_CalculateOtherBpp(flagsIn);
97 ok(ImageList_SetFlags(himl, flagsIn), "Can change BPP\n");
98 ok(ImageList_GetImageCount(himl) == 0, "SetFlags deletes all images\n");
99
100 ok(IL_AddImagesForTest(himl), "Initialize\n");
101 ok(ImageList_SetFlags(himl, ImageList_GetFlags(himl)), "Can set same flags\n");
102 if (WinVerMajor() >= 6)
103 {
104 ok(ImageList_GetImageCount(himl) != 0, "SetFlags does not delete with same flags\n");
105 ok(ImageList_SetFlags(himl, flagsIn ^ ILC_SYSTEM), "Can change ILC_SYSTEM\n");
106 }
107 else
108 {
109 ok(ImageList_GetImageCount(himl) == 0, "SetFlags deletes all images even with same flags\n");
110 ok(!ImageList_SetFlags(himl, flagsIn ^ ILC_SYSTEM), "Can't change ILC_SYSTEM\n");
111 }
112
113 IL_Destroy(himl);
114 }
115
116 himl = IL_Create(flagsIn = flags | ILC_SYSTEM);
117 flagsOut = ImageList_GetFlags(himl);
118 if (himl ? TRUE : (skip("Could not initialize\n"), FALSE))
119 {
120 ok((flagsOut & ILC_SYSTEM), "ILC_SYSTEM\n"); /* Flag is not hidden */
121
122 ok(IL_AddImagesForTest(himl), "Initialize\n");
123
124 flagsIn = IL_CalculateOtherBpp(flagsIn);
125 ok(ImageList_SetFlags(himl, flagsIn), "Can change BPP\n");
126 ok(ImageList_GetImageCount(himl) == 0, "SetFlags deletes all images\n");
127
128 ok(IL_AddImagesForTest(himl), "Initialize\n");
129 ok(ImageList_SetFlags(himl, ImageList_GetFlags(himl)), "Can set same flags\n");
130 if (WinVerMajor() >= 6)
131 {
132 ok(ImageList_SetFlags(himl, flagsIn ^ ILC_SYSTEM), "Can change ILC_SYSTEM\n");
133 }
134 else
135 {
136 ok(!ImageList_SetFlags(himl, flagsIn ^ ILC_SYSTEM), "Can't change ILC_SYSTEM\n");
137 }
138
139 IL_Destroy(himl);
140 }
141}
142
143START_TEST(ImageListApi)
144{
145 InitCommonControls();
146 Test_SystemIL();
147 Test_Flags();
148}