1 /*
2  * PROJECT:     ReactOS api tests
3  * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4  * PURPOSE:     Test for v6 property sheet
5  * COPYRIGHT:   Copyright 2019 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
6  */
7 
8 #include "wine/test.h"
9 #include <windows.h>
10 #include <windowsx.h>
11 #include <commctrl.h>
12 #include <prsht.h>
13 
14 #define IDC_APPLY_BUTTON 12321
15 
16 static BOOL s_bNotified;
17 
18 static BOOL OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam)
19 {
20     s_bNotified = FALSE;
21     SetDlgItemTextW(hwnd, edt1, L"text");
22     SetTimer(hwnd, 999, 300, NULL);
23     return TRUE;
24 }
25 
26 static void OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
27 {
28     switch (id)
29     {
30         case IDOK:
31         case IDCANCEL:
32             EndDialog(hwnd, id);
33             break;
34         case edt1:
35             if (codeNotify == EN_CHANGE)
36             {
37                 s_bNotified = TRUE;
38                 PropSheet_Changed(GetParent(hwnd), hwnd);
39             }
40             break;
41     }
42 }
43 
44 static void OnTimer(HWND hwnd, UINT id)
45 {
46     HWND hwndParent, hwndApply;
47 
48     KillTimer(hwnd, id);
49 
50     ok_int(s_bNotified, TRUE);
51 
52     hwndParent = GetParent(hwnd);
53     hwndApply = GetDlgItem(hwndParent, IDC_APPLY_BUTTON);
54     ok_int(IsWindowEnabled(hwndApply), FALSE);
55 
56     PropSheet_Changed(hwndParent, hwnd);
57     ok_int(IsWindowEnabled(hwndApply), TRUE);
58 
59     PropSheet_UnChanged(hwndParent, hwnd);
60     ok_int(IsWindowEnabled(hwndApply), FALSE);
61 
62     PropSheet_PressButton(hwndParent, PSBTN_OK);
63 }
64 
65 static INT_PTR CALLBACK
66 Page1DlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
67 {
68     switch (uMsg)
69     {
70         HANDLE_MSG(hwnd, WM_INITDIALOG, OnInitDialog);
71         HANDLE_MSG(hwnd, WM_COMMAND, OnCommand);
72         HANDLE_MSG(hwnd, WM_TIMER, OnTimer);
73     }
74     return 0;
75 }
76 
77 #ifdef _MSC_VER
78 #define CHECK_STRUCT_SIZE(x, y) C_ASSERT((x) == (y))
79 #else
80 // Can't do this compile time, thanks gcc
81 // 'error: non-nested function with variably modified type'
82 #define CHECK_STRUCT_SIZE(x, y) ok((x) == (y), "Wrong size for %s, got %u, expected %u\n", #x, y, x)
83 #endif
84 
85 // Validate struct sizes
86 static void test_StructSizes()
87 {
88 #ifdef _M_X64
89     CHECK_STRUCT_SIZE(PROPSHEETPAGEA_V1_SIZE, 72);
90     CHECK_STRUCT_SIZE(PROPSHEETPAGEA_V2_SIZE, 88);
91     CHECK_STRUCT_SIZE(PROPSHEETPAGEA_V3_SIZE, 96);
92     CHECK_STRUCT_SIZE(PROPSHEETPAGEA_V4_SIZE, 104);
93     CHECK_STRUCT_SIZE(PROPSHEETHEADERA_V1_SIZE, 72);
94     CHECK_STRUCT_SIZE(PROPSHEETHEADERA_V2_SIZE, 96);
95 
96     CHECK_STRUCT_SIZE(PROPSHEETPAGEW_V1_SIZE, 72);
97     CHECK_STRUCT_SIZE(PROPSHEETPAGEW_V2_SIZE, 88);
98     CHECK_STRUCT_SIZE(PROPSHEETPAGEW_V3_SIZE, 96);
99     CHECK_STRUCT_SIZE(PROPSHEETPAGEW_V4_SIZE, 104);
100     CHECK_STRUCT_SIZE(PROPSHEETHEADERW_V1_SIZE, 72);
101     CHECK_STRUCT_SIZE(PROPSHEETHEADERW_V2_SIZE, 96);
102 #else
103     CHECK_STRUCT_SIZE(PROPSHEETPAGEA_V1_SIZE, 40);
104     CHECK_STRUCT_SIZE(PROPSHEETPAGEA_V2_SIZE, 48);
105     CHECK_STRUCT_SIZE(PROPSHEETPAGEA_V3_SIZE, 52);
106     CHECK_STRUCT_SIZE(PROPSHEETPAGEA_V4_SIZE, 56);
107     CHECK_STRUCT_SIZE(PROPSHEETHEADERA_V1_SIZE, 40);
108     CHECK_STRUCT_SIZE(PROPSHEETHEADERA_V2_SIZE, 52);
109 
110     CHECK_STRUCT_SIZE(PROPSHEETPAGEW_V1_SIZE, 40);
111     CHECK_STRUCT_SIZE(PROPSHEETPAGEW_V2_SIZE, 48);
112     CHECK_STRUCT_SIZE(PROPSHEETPAGEW_V3_SIZE, 52);
113     CHECK_STRUCT_SIZE(PROPSHEETPAGEW_V4_SIZE, 56);
114     CHECK_STRUCT_SIZE(PROPSHEETHEADERW_V1_SIZE, 40);
115     CHECK_STRUCT_SIZE(PROPSHEETHEADERW_V2_SIZE, 52);
116 #endif
117 }
118 
119 typedef HPROPSHEETPAGE (WINAPI *FN_CreatePropertySheetPageW)(LPCPROPSHEETPAGEW);
120 typedef int (WINAPI *FN_PropertySheetW)(LPCPROPSHEETHEADERW);
121 static FN_CreatePropertySheetPageW pCreatePropertySheetPageW;
122 static FN_PropertySheetW pPropertySheetW;
123 
124 // Show that the Apply button is not enabled by default
125 static void test_ApplyButtonDisabled()
126 {
127     PROPSHEETPAGEW psp = {0};
128     PROPSHEETHEADERW header = {0};
129     HPROPSHEETPAGE hpsp[1];
130 
131     psp.dwSize = sizeof(psp);
132     psp.dwFlags = PSP_DEFAULT;
133     psp.hInstance = GetModuleHandleW(NULL);
134     psp.pszTemplate = MAKEINTRESOURCEW(1);
135     psp.pfnDlgProc = Page1DlgProc;
136     hpsp[0] = pCreatePropertySheetPageW(&psp);
137     ok(hpsp[0] != NULL, "hpsp[0] was NULL.\n");
138 
139     header.dwSize = sizeof(header);
140     header.dwFlags = 0;
141     header.hInstance = GetModuleHandleW(NULL);
142     header.hwndParent = NULL;
143     header.nPages = ARRAYSIZE(hpsp);
144     header.phpage = hpsp;
145     header.pszCaption = L"propsheet";
146     ok(pPropertySheetW(&header) > 0, "PropertySheet returned non-positive value.\n");
147 }
148 
149 
150 START_TEST(propsheet)
151 {
152     HMODULE hComCtl32;
153 
154     hComCtl32 = LoadLibraryW(L"comctl32.dll");
155     pCreatePropertySheetPageW = (FN_CreatePropertySheetPageW)GetProcAddress(hComCtl32, "CreatePropertySheetPageW");
156     pPropertySheetW = (FN_PropertySheetW)GetProcAddress(hComCtl32, "PropertySheetW");
157 
158     ok(pCreatePropertySheetPageW != NULL, "pCreatePropertySheetPageW was NULL.\n");
159     ok(pPropertySheetW != NULL, "pPropertySheetW was NULL.\n");
160 
161     if (!pCreatePropertySheetPageW || !pPropertySheetW)
162     {
163         skip("!pCreatePropertySheetPageW || !pPropertySheetW\n");
164         return;
165     }
166 
167     test_StructSizes();
168     test_ApplyButtonDisabled();
169 
170     FreeLibrary(hComCtl32);
171 }
172