1 /*
2  * comctl32 month calendar unit tests
3  *
4  * Copyright (C) 2006 Vitaliy Margolen
5  * Copyright (C) 2007 Farshad Agah
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21 
22 #include <stdarg.h>
23 
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winuser.h"
27 
28 #include "commctrl.h"
29 
30 #include "wine/test.h"
31 #include "v6util.h"
32 #include <windows.h>
33 #include "msg.h"
34 
35 #define expect(expected, got) ok(expected == got, "Expected %d, got %d\n", expected, got);
36 #define expect_hex(expected, got) ok(expected == got, "Expected %x, got %x\n", expected, got);
37 #define expect_d(expected, got) ok(abs((expected) - (got)) <= 2, "Expected %d, got %d\n", expected, got);
38 
39 #define NUM_MSG_SEQUENCES   2
40 #define PARENT_SEQ_INDEX    0
41 #define MONTHCAL_SEQ_INDEX  1
42 
43 #define SEL_NOTIFY_TEST_ID  100
44 
45 static BOOL (WINAPI *pInitCommonControlsEx)(const INITCOMMONCONTROLSEX*);
46 
47 static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
48 
49 static HWND parent_wnd;
50 
51 static const struct message create_parent_window_seq[] = {
52     { WM_GETMINMAXINFO, sent },
53     { WM_NCCREATE, sent },
54     { WM_NCCALCSIZE, sent|wparam, 0 },
55     { WM_CREATE, sent },
56     { WM_SHOWWINDOW, sent|wparam, 1 },
57     { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
58     { WM_QUERYNEWPALETTE, sent|optional },
59     { WM_WINDOWPOSCHANGING, sent|wparam|optional, 0 },
60     { WM_WINDOWPOSCHANGED, sent|optional },
61     { WM_ACTIVATEAPP, sent|wparam, 1 },
62     { WM_NCACTIVATE, sent },
63     { WM_ACTIVATE, sent|wparam, 1 },
64     { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
65     { WM_IME_NOTIFY, sent|defwinproc|optional },
66     { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
67     /* Win9x adds SWP_NOZORDER below */
68     { WM_WINDOWPOSCHANGED, sent, /*|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ },
69     { WM_NCCALCSIZE, sent|wparam|optional, 1 },
70     { WM_SIZE, sent },
71     { WM_MOVE, sent },
72     { 0 }
73 };
74 
75 static const struct message create_monthcal_control_seq[] = {
76     { WM_NOTIFYFORMAT, sent|lparam, 0, NF_QUERY },
77     { WM_QUERYUISTATE, sent|optional },
78     { WM_GETFONT, sent },
79     { WM_PARENTNOTIFY, sent|wparam, WM_CREATE},
80     { 0 }
81 };
82 
83 static const struct message create_monthcal_multi_sel_style_seq[] = {
84     { WM_NOTIFYFORMAT, sent|lparam, 0, NF_QUERY },
85     { WM_QUERYUISTATE, sent|optional },
86     { WM_GETFONT, sent },
87     { WM_PARENTNOTIFY, sent },
88     { 0 }
89 };
90 
91 static const struct message monthcal_curr_date_seq[] = {
92     { MCM_SETCURSEL, sent|wparam, 0},
93     { WM_PAINT, sent|wparam|lparam|defwinproc, 0, 0},
94     { MCM_SETCURSEL, sent|wparam, 0},
95     { MCM_SETCURSEL, sent|wparam, 0},
96     { MCM_GETCURSEL, sent|wparam, 0},
97     { MCM_GETCURSEL, sent|wparam|lparam, 0, 0},
98     { 0 }
99 };
100 
101 static const struct message monthcal_first_day_seq[] = {
102     { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
103 
104     { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, -5},
105     { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
106 
107     { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, -4},
108     { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
109 
110     { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, -3},
111     { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
112 
113     { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, -2},
114     { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
115 
116     { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, -1},
117     { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
118 
119     { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
120     { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
121 
122     { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 1},
123     { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
124 
125     { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 2},
126     { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
127 
128     { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 3},
129     { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
130 
131     { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 4},
132     { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
133 
134     { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 5},
135     { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
136 
137     { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 6},
138     { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
139 
140     { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 7},
141     { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
142 
143     { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 8},
144     { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
145 
146     { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 9},
147     { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
148 
149     { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 10},
150     { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
151 
152     { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 11},
153     { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
154     { 0 }
155 };
156 
157 static const struct message monthcal_unicode_seq[] = {
158     { MCM_GETUNICODEFORMAT, sent|wparam|lparam, 0, 0},
159     { MCM_SETUNICODEFORMAT, sent|wparam|lparam, 1, 0},
160     { MCM_GETUNICODEFORMAT, sent|wparam|lparam, 0, 0},
161     { MCM_SETUNICODEFORMAT, sent|wparam|lparam, 0, 0},
162     { MCM_GETUNICODEFORMAT, sent|wparam|lparam, 0, 0},
163     { MCM_SETUNICODEFORMAT, sent|wparam|lparam, 1, 0},
164     { 0 }
165 };
166 
167 static const struct message monthcal_hit_test_seq[] = {
168     { MCM_SETCURSEL, sent|wparam, 0},
169     { WM_PAINT, sent|wparam|lparam|defwinproc, 0, 0},
170     { MCM_HITTEST, sent|wparam, 0},
171     { MCM_HITTEST, sent|wparam, 0},
172     { MCM_HITTEST, sent|wparam, 0},
173     { MCM_HITTEST, sent|wparam, 0},
174     { MCM_HITTEST, sent|wparam, 0},
175     { MCM_HITTEST, sent|wparam, 0},
176     { MCM_HITTEST, sent|wparam, 0},
177     { MCM_HITTEST, sent|wparam, 0},
178     { MCM_HITTEST, sent|wparam, 0},
179     { MCM_HITTEST, sent|wparam, 0},
180     { 0 }
181 };
182 
183 static const struct message monthcal_todaylink_seq[] = {
184     { MCM_HITTEST, sent|wparam, 0},
185     { MCM_SETTODAY, sent|wparam, 0},
186     { WM_PAINT, sent|wparam|lparam|defwinproc, 0, 0},
187     { MCM_GETTODAY, sent|wparam, 0},
188     { WM_LBUTTONDOWN, sent|wparam, MK_LBUTTON},
189     { WM_CAPTURECHANGED, sent|wparam|lparam|defwinproc, 0, 0},
190     { WM_PAINT, sent|wparam|lparam|defwinproc, 0, 0},
191     { MCM_GETCURSEL, sent|wparam, 0},
192     { 0 }
193 };
194 
195 static const struct message monthcal_today_seq[] = {
196     { MCM_SETTODAY, sent|wparam, 0},
197     { WM_PAINT, sent|wparam|lparam|defwinproc, 0, 0},
198     { MCM_GETTODAY, sent|wparam, 0},
199     { MCM_SETTODAY, sent|wparam, 0},
200     { WM_PAINT, sent|wparam|lparam|defwinproc, 0, 0},
201     { MCM_GETTODAY, sent|wparam, 0},
202     { 0 }
203 };
204 
205 static const struct message monthcal_scroll_seq[] = {
206     { MCM_SETMONTHDELTA, sent|wparam|lparam, 2, 0},
207     { MCM_SETMONTHDELTA, sent|wparam|lparam, 3, 0},
208     { MCM_GETMONTHDELTA, sent|wparam|lparam, 0, 0},
209     { MCM_SETMONTHDELTA, sent|wparam|lparam, 12, 0},
210     { MCM_GETMONTHDELTA, sent|wparam|lparam, 0, 0},
211     { MCM_SETMONTHDELTA, sent|wparam|lparam, 15, 0},
212     { MCM_GETMONTHDELTA, sent|wparam|lparam, 0, 0},
213     { MCM_SETMONTHDELTA, sent|wparam|lparam, -5, 0},
214     { MCM_GETMONTHDELTA, sent|wparam|lparam, 0, 0},
215     { 0 }
216 };
217 
218 static const struct message monthcal_monthrange_seq[] = {
219     { MCM_GETMONTHRANGE, sent|wparam, GMR_VISIBLE},
220     { MCM_GETMONTHRANGE, sent|wparam, GMR_DAYSTATE},
221     { 0 }
222 };
223 
224 static const struct message monthcal_max_sel_day_seq[] = {
225     { MCM_SETMAXSELCOUNT, sent|wparam|lparam, 5, 0},
226     { MCM_GETMAXSELCOUNT, sent|wparam|lparam, 0, 0},
227     { MCM_SETMAXSELCOUNT, sent|wparam|lparam, 15, 0},
228     { MCM_GETMAXSELCOUNT, sent|wparam|lparam, 0, 0},
229     { MCM_SETMAXSELCOUNT, sent|wparam|lparam, -1, 0},
230     { MCM_GETMAXSELCOUNT, sent|wparam|lparam, 0, 0},
231     { 0 }
232 };
233 
234 /* expected message sequence for parent*/
235 static const struct message destroy_monthcal_parent_msgs_seq[] = {
236     { WM_PARENTNOTIFY, sent|wparam, WM_DESTROY},
237     { 0 }
238 };
239 
240 /* expected message sequence for child*/
241 static const struct message destroy_monthcal_child_msgs_seq[] = {
242     { 0x0090, sent|optional }, /* Vista */
243     { WM_SHOWWINDOW, sent|wparam|lparam, 0, 0},
244     { WM_WINDOWPOSCHANGING, sent|wparam, 0},
245     { WM_WINDOWPOSCHANGED, sent|wparam, 0},
246     { WM_DESTROY, sent|wparam|lparam, 0, 0},
247     { WM_NCDESTROY, sent|wparam|lparam, 0, 0},
248     { 0 }
249 };
250 
251 static const struct message destroy_monthcal_multi_sel_style_seq[] = {
252     { 0x0090, sent|optional }, /* Vista */
253     { WM_SHOWWINDOW, sent|wparam|lparam, 0, 0},
254     { WM_WINDOWPOSCHANGING, sent|wparam, 0},
255     { WM_WINDOWPOSCHANGED, sent|wparam, 0},
256     { WM_DESTROY, sent|wparam|lparam, 0, 0},
257     { WM_NCDESTROY, sent|wparam|lparam, 0, 0},
258     { 0 }
259 };
260 
261 static void test_monthcal(void)
262 {
263     HWND hwnd;
264     SYSTEMTIME st[2], st1[2], today;
265     int res, month_range;
266     DWORD limits;
267     BOOL r;
268 
269     hwnd = CreateWindowA(MONTHCAL_CLASSA, "MonthCal", WS_POPUP | WS_VISIBLE, CW_USEDEFAULT,
270                          0, 300, 300, 0, 0, NULL, NULL);
271     ok(hwnd != NULL, "Failed to create MonthCal\n");
272 
273     /* test range just after creation */
274     memset(&st, 0xcc, sizeof(st));
275     limits = SendMessageA(hwnd, MCM_GETRANGE, 0, (LPARAM)st);
276     ok(limits == 0 ||
277        broken(limits == GDTR_MIN), /* comctl32 <= 4.70 */
278        "No limits should be set (%d)\n", limits);
279     if (limits == GDTR_MIN)
280     {
281         win_skip("comctl32 <= 4.70 is broken\n");
282         DestroyWindow(hwnd);
283         return;
284     }
285 
286     ok(0 == st[0].wYear ||
287        broken(1752 == st[0].wYear), /* comctl32 <= 4.72 */
288        "Expected 0, got %d\n", st[0].wYear);
289     ok(0 == st[0].wMonth ||
290        broken(9 == st[0].wMonth), /* comctl32 <= 4.72 */
291        "Expected 0, got %d\n", st[0].wMonth);
292     ok(0 == st[0].wDay ||
293        broken(14 == st[0].wDay), /* comctl32 <= 4.72 */
294        "Expected 0, got %d\n", st[0].wDay);
295     expect(0, st[0].wDayOfWeek);
296     expect(0, st[0].wHour);
297     expect(0, st[0].wMinute);
298     expect(0, st[0].wSecond);
299     expect(0, st[0].wMilliseconds);
300 
301     expect(0, st[1].wYear);
302     expect(0, st[1].wMonth);
303     expect(0, st[1].wDay);
304     expect(0, st[1].wDayOfWeek);
305     expect(0, st[1].wHour);
306     expect(0, st[1].wMinute);
307     expect(0, st[1].wSecond);
308     expect(0, st[1].wMilliseconds);
309 
310     limits = SendMessageA(hwnd, MCM_GETRANGE, 0, 0);
311     ok(limits == 0, "got %u\n", limits);
312 
313     GetSystemTime(&st[0]);
314     st[1] = st[0];
315 
316     SendMessageA(hwnd, MCM_GETTODAY, 0, (LPARAM)&today);
317 
318     /* Invalid date/time */
319     st[0].wYear  = 2000;
320     /* Time should not matter */
321     st[1].wHour = st[1].wMinute = st[1].wSecond = 70;
322     st[1].wMilliseconds = 1200;
323     ok(SendMessageA(hwnd, MCM_SETRANGE, GDTR_MAX, (LPARAM)st), "Failed to set MAX limit\n");
324     /* invalid timestamp is written back with today data and msecs untouched */
325     expect(today.wHour, st[1].wHour);
326     expect(today.wMinute, st[1].wMinute);
327     expect(today.wSecond, st[1].wSecond);
328     expect(1200, st[1].wMilliseconds);
329 
330     ok(SendMessageA(hwnd, MCM_GETRANGE, 0, (LPARAM)st1) == GDTR_MAX, "No limits should be set\n");
331     ok(st1[0].wYear != 2000, "Lower limit changed\n");
332     /* invalid timestamp should be replaced with today data, except msecs */
333     expect(today.wHour, st1[1].wHour);
334     expect(today.wMinute, st1[1].wMinute);
335     expect(today.wSecond, st1[1].wSecond);
336     expect(1200, st1[1].wMilliseconds);
337 
338     /* Invalid date/time with invalid milliseconds only */
339     GetSystemTime(&st[0]);
340     st[1] = st[0];
341     /* Time should not matter */
342     st[1].wMilliseconds = 1200;
343     ok(SendMessageA(hwnd, MCM_SETRANGE, GDTR_MAX, (LPARAM)st), "Failed to set MAX limit\n");
344     /* invalid milliseconds field doesn't lead to invalid timestamp */
345     expect(st[0].wHour,   st[1].wHour);
346     expect(st[0].wMinute, st[1].wMinute);
347     expect(st[0].wSecond, st[1].wSecond);
348     expect(1200, st[1].wMilliseconds);
349 
350     GetSystemTime(&st[0]);
351 
352     st[1].wMonth = 0;
353     ok(!SendMessageA(hwnd, MCM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st),
354             "Should have failed to set limits\n");
355     ok(SendMessageA(hwnd, MCM_GETRANGE, 0, (LPARAM)st1) == GDTR_MAX, "No limits should be set\n");
356     ok(st1[0].wYear != 2000, "Lower limit changed\n");
357     ok(!SendMessageA(hwnd, MCM_SETRANGE, GDTR_MAX, (LPARAM)st),
358             "Should have failed to set MAX limit\n");
359     ok(SendMessageA(hwnd, MCM_GETRANGE, 0, (LPARAM)st1) == GDTR_MAX, "No limits should be set\n");
360     ok(st1[0].wYear != 2000, "Lower limit changed\n");
361 
362     GetSystemTime(&st[0]);
363     st[0].wDay = 20;
364     st[0].wMonth = 5;
365     st[1] = st[0];
366 
367     month_range = SendMessageA(hwnd, MCM_GETMONTHRANGE, GMR_VISIBLE, (LPARAM)st1);
368     st[1].wMonth--;
369     ok(SendMessageA(hwnd, MCM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st),
370             "Failed to set both min and max limits\n");
371     res = SendMessageA(hwnd, MCM_GETMONTHRANGE, GMR_VISIBLE, (LPARAM)st1);
372     ok(res == month_range, "Invalid month range (%d)\n", res);
373     ok(SendMessageA(hwnd, MCM_GETRANGE, 0, (LPARAM)st1) == (GDTR_MIN|GDTR_MAX),
374             "Limits should be set\n");
375 
376     st[1].wMonth += 2;
377     ok(SendMessageA(hwnd, MCM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st),
378             "Failed to set both min and max limits\n");
379     res = SendMessageA(hwnd, MCM_GETMONTHRANGE, GMR_VISIBLE, (LPARAM)st1);
380     ok(res == month_range, "Invalid month range (%d)\n", res);
381 
382     st[1].wYear --;
383     ok(SendMessageA(hwnd, MCM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st),
384             "Failed to set both min and max limits\n");
385     st[1].wYear += 1;
386     ok(SendMessageA(hwnd, MCM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st),
387             "Failed to set both min and max limits\n");
388 
389     st[1].wMonth -= 3;
390     ok(SendMessageA(hwnd, MCM_SETRANGE, GDTR_MAX, (LPARAM)st), "Failed to set max limit\n");
391     ok(SendMessageA(hwnd, MCM_GETRANGE, 0, (LPARAM)st1) == GDTR_MAX,
392             "Only MAX limit should be set\n");
393     st[1].wMonth += 4;
394     ok(SendMessageA(hwnd, MCM_SETRANGE, GDTR_MAX, (LPARAM)st), "Failed to set max limit\n");
395     st[1].wYear -= 3;
396     ok(SendMessageA(hwnd, MCM_SETRANGE, GDTR_MAX, (LPARAM)st), "Failed to set max limit\n");
397     st[1].wYear += 4;
398     ok(SendMessageA(hwnd, MCM_SETRANGE, GDTR_MAX, (LPARAM)st), "Failed to set max limit\n");
399     ok(SendMessageA(hwnd, MCM_GETRANGE, 0, (LPARAM)st1) == GDTR_MAX,
400             "Only MAX limit should be set\n");
401 
402     /* set both limits, then set max < min */
403     GetSystemTime(&st[0]);
404     st[0].wDay = 25;
405     st[1] = st[0];
406     st[1].wYear++;
407     ok(SendMessageA(hwnd, MCM_SETRANGE, GDTR_MIN|GDTR_MAX, (LPARAM)st), "Failed to set limits\n");
408     ok(SendMessageA(hwnd, MCM_GETRANGE, 0, (LPARAM)st1) == (GDTR_MIN|GDTR_MAX),
409             "Min limit expected\n");
410     st[1].wYear -= 2;
411     ok(SendMessageA(hwnd, MCM_SETRANGE, GDTR_MAX, (LPARAM)st), "Failed to set limits\n");
412     ok(SendMessageA(hwnd, MCM_GETRANGE, 0, (LPARAM)st1) == GDTR_MAX, "Max limit expected\n");
413 
414     expect(0, st1[0].wYear);
415     expect(0, st1[0].wMonth);
416     expect(0, st1[0].wDay);
417     expect(0, st1[0].wDayOfWeek);
418     expect(0, st1[0].wHour);
419     expect(0, st1[0].wMinute);
420     expect(0, st1[0].wSecond);
421     expect(0, st1[0].wMilliseconds);
422 
423     expect(st[1].wYear,      st1[1].wYear);
424     expect(st[1].wMonth,     st1[1].wMonth);
425     expect(st[1].wDay,       st1[1].wDay);
426     expect(st[1].wDayOfWeek, st1[1].wDayOfWeek);
427     expect(st[1].wHour,      st1[1].wHour);
428     expect(st[1].wMinute,    st1[1].wMinute);
429     expect(st[1].wSecond,    st1[1].wSecond);
430     expect(st[1].wMilliseconds, st1[1].wMilliseconds);
431 
432     st[1] = st[0];
433     st[1].wYear++;
434     ok(SendMessageA(hwnd, MCM_SETRANGE, GDTR_MIN|GDTR_MAX, (LPARAM)st), "Failed to set limits\n");
435     ok(SendMessageA(hwnd, MCM_GETRANGE, 0, (LPARAM)st1) == (GDTR_MIN|GDTR_MAX),
436             "Min limit expected\n");
437     st[0].wYear++; /* start == end now */
438     ok(SendMessageA(hwnd, MCM_SETRANGE, GDTR_MIN, (LPARAM)st), "Failed to set limits\n");
439     ok(SendMessageA(hwnd, MCM_GETRANGE, 0, (LPARAM)st1) == GDTR_MIN, "Min limit expected\n");
440 
441     expect(st[0].wYear,      st1[0].wYear);
442     expect(st[0].wMonth,     st1[0].wMonth);
443     expect(st[0].wDay,       st1[0].wDay);
444     expect(st[0].wDayOfWeek, st1[0].wDayOfWeek);
445     expect(st[0].wHour,      st1[0].wHour);
446     expect(st[0].wMinute,    st1[0].wMinute);
447     expect(st[0].wSecond,    st1[0].wSecond);
448     expect(st[0].wMilliseconds, st1[0].wMilliseconds);
449 
450     expect(0, st1[1].wYear);
451     expect(0, st1[1].wMonth);
452     expect(0, st1[1].wDay);
453     expect(0, st1[1].wDayOfWeek);
454     expect(0, st1[1].wHour);
455     expect(0, st1[1].wMinute);
456     expect(0, st1[1].wSecond);
457     expect(0, st1[1].wMilliseconds);
458 
459     /* 0 limit flags */
460     limits = SendMessageA(hwnd, MCM_GETRANGE, 0, (LPARAM)st1);
461     ok(limits == GDTR_MIN, "got 0x%08x\n", limits);
462 
463     GetSystemTime(st);
464     st[1] = st[0];
465     st[1].wYear++;
466     r = SendMessageA(hwnd, MCM_SETRANGE, 0, (LPARAM)st);
467     ok(r, "got %d\n", r);
468 
469     limits = SendMessageA(hwnd, MCM_GETRANGE, 0, (LPARAM)st);
470     ok(limits == 0, "got 0x%08x\n", limits);
471     ok(st[0].wYear == 0 && st[1].wYear == 0, "got %u, %u\n", st[0].wYear, st[1].wYear);
472 
473     /* flags are 0, set min limit */
474     GetSystemTime(st);
475     st[1] = st[0];
476     st[1].wYear++;
477 
478     r = SendMessageA(hwnd, MCM_SETRANGE, GDTR_MIN, (LPARAM)st);
479     ok(r, "got %d\n", r);
480 
481     limits = SendMessageA(hwnd, MCM_GETRANGE, 0, (LPARAM)st1);
482     ok(limits == GDTR_MIN, "got 0x%08x\n", limits);
483     ok(st1[1].wYear == 0, "got %u\n", st1[1].wYear);
484 
485     /* now set max limit, check flags */
486     r = SendMessageA(hwnd, MCM_SETRANGE, GDTR_MAX, (LPARAM)st);
487     ok(r, "got %d\n", r);
488 
489     limits = SendMessageA(hwnd, MCM_GETRANGE, 0, (LPARAM)st1);
490     ok(limits == GDTR_MAX, "got 0x%08x\n", limits);
491     ok(st1[0].wYear == 0, "got %u\n", st1[0].wYear);
492 
493     DestroyWindow(hwnd);
494 }
495 
496 static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
497 {
498     static LONG defwndproc_counter = 0;
499     LRESULT ret;
500     struct message msg;
501 
502     /* log system messages, except for painting */
503     if (message < WM_USER &&
504         message != WM_PAINT &&
505         message != WM_ERASEBKGND &&
506         message != WM_NCPAINT &&
507         message != WM_NCHITTEST &&
508         message != WM_GETTEXT &&
509         message != WM_GETICON &&
510         message != WM_DEVICECHANGE)
511     {
512         msg.message = message;
513         msg.flags = sent|wparam|lparam;
514         if (defwndproc_counter) msg.flags |= defwinproc;
515         msg.wParam = wParam;
516         msg.lParam = lParam;
517         add_message(sequences, PARENT_SEQ_INDEX, &msg);
518     }
519 
520     if (message == WM_NOTIFY)
521     {
522         NMHDR *hdr = (NMHDR*)lParam;
523         switch (hdr->code)
524         {
525           case MCN_GETDAYSTATE:
526           {
527             NMDAYSTATE *nmstate = (NMDAYSTATE*)lParam;
528             static MONTHDAYSTATE months[14] = { 0 };
529 
530             ok(nmstate->cDayState > 0, "got %d\n", nmstate->cDayState);
531             ok(nmstate->cDayState <= 14, "got %d\n", nmstate->cDayState);
532             ok(nmstate->prgDayState != NULL, "got %p\n", nmstate->prgDayState);
533 
534             nmstate->prgDayState = months;
535 
536             return TRUE;
537           }
538           case MCN_SELECT:
539           case MCN_SELCHANGE:
540           {
541             NMSELCHANGE *nmchg = (NMSELCHANGE*)lParam;
542             SYSTEMTIME st[2];
543             BOOL is_multisel = GetWindowLongPtrA(nmchg->nmhdr.hwndFrom, GWL_STYLE) & MCS_MULTISELECT;
544 
545             if(GetWindowLongPtrA(nmchg->nmhdr.hwndFrom, GWLP_ID) != SEL_NOTIFY_TEST_ID)
546               break;
547             SendMessageA(nmchg->nmhdr.hwndFrom, is_multisel ? MCM_GETSELRANGE : MCM_GETCURSEL,
548                     0, (LPARAM)st);
549 
550             expect(st[0].wYear,  nmchg->stSelStart.wYear);
551             expect(st[0].wMonth, nmchg->stSelStart.wMonth);
552             expect(0,            nmchg->stSelStart.wDayOfWeek);
553             expect(st[0].wDay,   nmchg->stSelStart.wDay);
554 
555             if(is_multisel)
556             {
557               expect(st[1].wYear,  nmchg->stSelEnd.wYear);
558               expect(st[1].wMonth, nmchg->stSelEnd.wMonth);
559               expect(0,            nmchg->stSelEnd.wDayOfWeek);
560               expect(st[1].wDay,   nmchg->stSelEnd.wDay);
561             }
562             else
563               ok(!(nmchg->stSelEnd.wYear | nmchg->stSelEnd.wMonth |
564                         nmchg->stSelEnd.wDayOfWeek | nmchg->stSelEnd.wDay |
565                         nmchg->stSelEnd.wHour | nmchg->stSelEnd.wMinute |
566                         nmchg->stSelEnd.wSecond | nmchg->stSelEnd.wMilliseconds),
567                         "Non-zero member in stSelEnd\n");
568             return TRUE;
569           }
570           default:
571             break;
572         }
573     }
574 
575     defwndproc_counter++;
576     ret = DefWindowProcA(hwnd, message, wParam, lParam);
577     defwndproc_counter--;
578 
579     return ret;
580 }
581 
582 static BOOL register_parent_wnd_class(void)
583 {
584     WNDCLASSA cls;
585 
586     cls.style = 0;
587     cls.lpfnWndProc = parent_wnd_proc;
588     cls.cbClsExtra = 0;
589     cls.cbWndExtra = 0;
590     cls.hInstance = GetModuleHandleA(NULL);
591     cls.hIcon = 0;
592     cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
593     cls.hbrBackground = GetStockObject(WHITE_BRUSH);
594     cls.lpszMenuName = NULL;
595     cls.lpszClassName = "Month-Cal test parent class";
596     return RegisterClassA(&cls);
597 }
598 
599 static HWND create_parent_window(void)
600 {
601     HWND hwnd;
602 
603     /* flush message sequences, so we can check the new sequence by the end of function */
604     flush_sequences(sequences, NUM_MSG_SEQUENCES);
605 
606     if (!register_parent_wnd_class())
607         return NULL;
608 
609     hwnd = CreateWindowExA(0, "Month-Cal test parent class", "Month-Cal test parent window",
610             WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_VISIBLE,
611             0, 0, 500, 500, GetDesktopWindow(), NULL, GetModuleHandleA(NULL), NULL);
612     ok(hwnd != NULL, "failed to create parent wnd\n");
613 
614     /* check for message sequences */
615     ok_sequence(sequences, PARENT_SEQ_INDEX, create_parent_window_seq, "create parent window", FALSE);
616 
617     return hwnd;
618 }
619 
620 static LRESULT WINAPI monthcal_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
621 {
622     WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
623     static LONG defwndproc_counter = 0;
624     struct message msg = { 0 };
625     LRESULT ret;
626 
627     msg.message = message;
628     msg.flags = sent|wparam|lparam;
629     if (defwndproc_counter) msg.flags |= defwinproc;
630     msg.wParam = wParam;
631     msg.lParam = lParam;
632     add_message(sequences, MONTHCAL_SEQ_INDEX, &msg);
633 
634     /* some debug output for style changing */
635     if ((message == WM_STYLECHANGING ||
636          message == WM_STYLECHANGED) && lParam)
637     {
638         STYLESTRUCT *style = (STYLESTRUCT*)lParam;
639         trace("\told style: 0x%08x, new style: 0x%08x\n", style->styleOld, style->styleNew);
640     }
641 
642     defwndproc_counter++;
643     ret = CallWindowProcA(oldproc, hwnd, message, wParam, lParam);
644     defwndproc_counter--;
645 
646     return ret;
647 }
648 
649 static HWND create_monthcal_control(DWORD style)
650 {
651     WNDPROC oldproc;
652     RECT rect;
653     HWND hwnd;
654     BOOL ret;
655 
656     hwnd = CreateWindowExA(0, MONTHCAL_CLASSA, "", WS_CHILD | WS_BORDER | WS_VISIBLE | style,
657                     0, 0, 300, 400, parent_wnd, NULL, GetModuleHandleA(NULL), NULL);
658     ok(hwnd != NULL, "failed to create monthcal wnd\n");
659     if (!hwnd) return NULL;
660 
661     oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC,
662                                         (LONG_PTR)monthcal_subclass_proc);
663     SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)oldproc);
664 
665     SendMessageA(hwnd, WM_SETFONT, (WPARAM)GetStockObject(SYSTEM_FONT), 0);
666 
667     /* make sure calendar grid is 2x1 */
668     ret = SendMessageA(hwnd, MCM_GETMINREQRECT, 0, (LPARAM)&rect);
669     ok(ret, "got %d\n", ret);
670 
671     ret = SetWindowPos(hwnd, NULL, 0, 0, rect.right * 5 / 2, rect.bottom * 3 / 2, SWP_NOMOVE);
672     ok(ret, "got %d\n", ret);
673 
674     return hwnd;
675 }
676 
677 
678 /* Setter and Getters Tests */
679 
680 static void test_color(void)
681 {
682     COLORREF color, prev;
683     HWND hwnd;
684 
685     hwnd = create_monthcal_control(0);
686 
687     /* invalid color index */
688     color = SendMessageA(hwnd, MCM_GETCOLOR, MCSC_TRAILINGTEXT + 1, 0);
689     expect(~0u, color);
690     prev = SendMessageA(hwnd, MCM_SETCOLOR, MCSC_TRAILINGTEXT + 1, RGB(255,255,255));
691     expect(~0u, prev);
692 
693     color = SendMessageA(hwnd, MCM_GETCOLOR, MCSC_BACKGROUND, 0);
694     prev = SendMessageA(hwnd, MCM_SETCOLOR, MCSC_BACKGROUND, RGB(0,0,0));
695     expect(color, prev);
696     color = SendMessageA(hwnd, MCM_GETCOLOR, MCSC_BACKGROUND, 0);
697     expect(RGB(0,0,0), color);
698     prev = SendMessageA(hwnd, MCM_SETCOLOR, MCSC_BACKGROUND, RGB(255,255,255));
699     expect(color, prev);
700     color = SendMessageA(hwnd, MCM_GETCOLOR, MCSC_BACKGROUND, 0);
701     expect(RGB(255,255,255), color);
702 
703     color = SendMessageA(hwnd, MCM_GETCOLOR, MCSC_MONTHBK, 0);
704     prev = SendMessageA(hwnd, MCM_SETCOLOR, MCSC_MONTHBK, RGB(0,0,0));
705     expect(color, prev);
706     color = SendMessageA(hwnd, MCM_GETCOLOR, MCSC_MONTHBK, 0);
707     expect(RGB(0,0,0), color);
708     prev = SendMessageA(hwnd, MCM_SETCOLOR, MCSC_MONTHBK, RGB(255,255,255));
709     expect(color, prev);
710     color = SendMessageA(hwnd, MCM_GETCOLOR, MCSC_MONTHBK, 0);
711     expect(RGB(255,255,255), color);
712 
713     color = SendMessageA(hwnd, MCM_GETCOLOR, MCSC_TEXT, 0);
714     prev = SendMessageA(hwnd, MCM_SETCOLOR, MCSC_TEXT, RGB(0,0,0));
715     expect(color, prev);
716     color = SendMessageA(hwnd, MCM_GETCOLOR, MCSC_TEXT, 0);
717     expect(RGB(0,0,0), color);
718     prev = SendMessageA(hwnd, MCM_SETCOLOR, MCSC_TEXT, RGB(255,255,255));
719     expect(color, prev);
720     color = SendMessageA(hwnd, MCM_GETCOLOR, MCSC_TEXT, 0);
721     expect(RGB(255,255,255), color);
722 
723     color = SendMessageA(hwnd, MCM_GETCOLOR, MCSC_TITLEBK, 0);
724     prev = SendMessageA(hwnd, MCM_SETCOLOR, MCSC_TITLEBK, RGB(0,0,0));
725     expect(color, prev);
726     color = SendMessageA(hwnd, MCM_GETCOLOR, MCSC_TITLEBK, 0);
727     expect(RGB(0,0,0), color);
728     prev = SendMessageA(hwnd, MCM_SETCOLOR, MCSC_TITLEBK, RGB(255,255,255));
729     expect(color, prev);
730     color = SendMessageA(hwnd, MCM_GETCOLOR, MCSC_TITLEBK, 0);
731     expect(RGB(255,255,255), color);
732 
733     color = SendMessageA(hwnd, MCM_GETCOLOR, MCSC_TITLETEXT, 0);
734     prev = SendMessageA(hwnd, MCM_SETCOLOR, MCSC_TITLETEXT, RGB(0,0,0));
735     expect(color, prev);
736     color = SendMessageA(hwnd, MCM_GETCOLOR, MCSC_TITLETEXT, 0);
737     expect(RGB(0,0,0), color);
738     prev = SendMessageA(hwnd, MCM_SETCOLOR, MCSC_TITLETEXT, RGB(255,255,255));
739     expect(color, prev);
740     color = SendMessageA(hwnd, MCM_GETCOLOR, MCSC_TITLETEXT, 0);
741     expect(RGB(255,255,255), color);
742 
743     color = SendMessageA(hwnd, MCM_GETCOLOR, MCSC_TRAILINGTEXT, 0);
744     prev = SendMessageA(hwnd, MCM_SETCOLOR, MCSC_TRAILINGTEXT, RGB(0,0,0));
745     expect(color, prev);
746     color = SendMessageA(hwnd, MCM_GETCOLOR, MCSC_TRAILINGTEXT, 0);
747     expect(RGB(0,0,0), color);
748     prev = SendMessageA(hwnd, MCM_SETCOLOR, MCSC_TRAILINGTEXT, RGB(255,255,255));
749     expect(color, prev);
750     color = SendMessageA(hwnd, MCM_GETCOLOR, MCSC_TRAILINGTEXT, 0);
751     expect(RGB(255,255,255), color);
752 
753     DestroyWindow(hwnd);
754 }
755 
756 static void test_currdate(void)
757 {
758     SYSTEMTIME st_original, st_new, st_test;
759     int res;
760     HWND hwnd;
761 
762     hwnd = create_monthcal_control(0);
763 
764     flush_sequences(sequences, NUM_MSG_SEQUENCES);
765 
766     /* Setter and Getters for current date selected */
767     st_original.wYear = 2000;
768     st_original.wMonth = 11;
769     st_original.wDay = 28;
770     st_original.wHour = 11;
771     st_original.wMinute = 59;
772     st_original.wSecond = 30;
773     st_original.wMilliseconds = 0;
774     st_original.wDayOfWeek = 0;
775 
776     st_new = st_test = st_original;
777 
778     /* Should not validate the time */
779     res = SendMessageA(hwnd, MCM_SETCURSEL, 0, (LPARAM)&st_test);
780     expect(1,res);
781 
782     /* Overflow matters, check for wDay */
783     st_test.wDay += 4;
784     res = SendMessageA(hwnd, MCM_SETCURSEL, 0, (LPARAM)&st_test);
785     expect(0,res);
786 
787     /* correct wDay before checking for wMonth */
788     st_test.wDay -= 4;
789     expect(st_original.wDay, st_test.wDay);
790 
791     /* Overflow matters, check for wMonth */
792     st_test.wMonth += 4;
793     res = SendMessageA(hwnd, MCM_SETCURSEL, 0, (LPARAM)&st_test);
794     expect(0,res);
795 
796     /* checking if gets the information right, modify st_new */
797     st_new.wYear += 4;
798     st_new.wMonth += 4;
799     st_new.wDay += 4;
800     st_new.wHour += 4;
801     st_new.wMinute += 4;
802     st_new.wSecond += 4;
803 
804     res = SendMessageA(hwnd, MCM_GETCURSEL, 0, (LPARAM)&st_new);
805     expect(1, res);
806 
807     /* st_new change to st_origin, above settings with overflow */
808     /* should not change the current settings */
809     expect(st_original.wYear, st_new.wYear);
810     expect(st_original.wMonth, st_new.wMonth);
811     expect(st_original.wDay, st_new.wDay);
812     ok(st_original.wHour == st_new.wHour ||
813        broken(0 == st_new.wHour), /* comctl32 <= 4.70 */
814        "Expected %d, got %d\n", st_original.wHour, st_new.wHour);
815     ok(st_original.wMinute == st_new.wMinute ||
816        broken(0 == st_new.wMinute), /* comctl32 <= 4.70 */
817        "Expected %d, got %d\n", st_original.wMinute, st_new.wMinute);
818     ok(st_original.wSecond == st_new.wSecond ||
819        broken(0 == st_new.wSecond), /* comctl32 <= 4.70 */
820        "Expected %d, got %d\n", st_original.wSecond, st_new.wSecond);
821 
822     /* lparam cannot be NULL */
823     res = SendMessageA(hwnd, MCM_GETCURSEL, 0, 0);
824     expect(0, res);
825 
826     ok_sequence(sequences, MONTHCAL_SEQ_INDEX, monthcal_curr_date_seq, "monthcal currDate", TRUE);
827 
828     /* December, 31, 9999 is the maximum allowed date */
829     memset(&st_new, 0, sizeof(st_new));
830     st_new.wYear = 9999;
831     st_new.wMonth = 12;
832     st_new.wDay = 31;
833     res = SendMessageA(hwnd, MCM_SETCURSEL, 0, (LPARAM)&st_new);
834     expect(1, res);
835     memset(&st_test, 0, sizeof(st_test));
836     res = SendMessageA(hwnd, MCM_GETCURSEL, 0, (LPARAM)&st_test);
837     expect(1, res);
838     expect(st_new.wYear, st_test.wYear);
839     expect(st_new.wMonth, st_test.wMonth);
840     expect(st_new.wDay, st_test.wDay);
841     expect(st_new.wHour, st_test.wHour);
842     expect(st_new.wMinute, st_test.wMinute);
843     expect(st_new.wSecond, st_test.wSecond);
844     /* try one day later */
845     st_original = st_new;
846     st_new.wYear = 10000;
847     st_new.wMonth = 1;
848     st_new.wDay = 1;
849     res = SendMessageA(hwnd, MCM_SETCURSEL, 0, (LPARAM)&st_new);
850     ok(0 == res ||
851        broken(1 == res), /* comctl32 <= 4.72 */
852        "Expected 0, got %d\n", res);
853     if (0 == res)
854     {
855         memset(&st_test, 0, sizeof(st_test));
856         res = SendMessageA(hwnd, MCM_GETCURSEL, 0, (LPARAM)&st_test);
857         expect(1, res);
858         expect(st_original.wYear, st_test.wYear);
859         expect(st_original.wMonth, st_test.wMonth);
860         expect(st_original.wDay, st_test.wDay);
861         expect(st_original.wHour, st_test.wHour);
862         expect(st_original.wMinute, st_test.wMinute);
863         expect(st_original.wSecond, st_test.wSecond);
864     }
865 
866     /* setting selection equal to current reports success even if out range */
867     memset(&st_new, 0, sizeof(st_new));
868     st_new.wYear = 2009;
869     st_new.wDay  = 5;
870     st_new.wMonth = 10;
871     res = SendMessageA(hwnd, MCM_SETCURSEL, 0, (LPARAM)&st_new);
872     expect(1, res);
873     memset(&st_test, 0, sizeof(st_test));
874     st_test.wYear = 2009;
875     st_test.wDay  = 6;
876     st_test.wMonth = 10;
877     res = SendMessageA(hwnd, MCM_SETRANGE, GDTR_MIN, (LPARAM)&st_test);
878     expect(1, res);
879     /* set to current again */
880     res = SendMessageA(hwnd, MCM_SETCURSEL, 0, (LPARAM)&st_new);
881     expect(1, res);
882 
883     /* set with invalid day of week */
884     memset(&st_test, 0, sizeof(st_test));
885     st_test.wYear = 2009;
886     st_test.wDay  = 7;
887     st_test.wMonth = 10;
888     st_test.wDayOfWeek = 100;
889     res = SendMessageA(hwnd, MCM_SETCURSEL, 0, (LPARAM)&st_test);
890     expect(1, res);
891 
892     memset(&st_test, 0, sizeof(st_test));
893     res = SendMessageA(hwnd, MCM_GETCURSEL, 0, (LPARAM)&st_test);
894     expect(1, res);
895     expect(2009, st_test.wYear);
896     expect(7, st_test.wDay);
897     expect(10, st_test.wMonth);
898     expect(3, st_test.wDayOfWeek);
899 
900     DestroyWindow(hwnd);
901 }
902 
903 static void test_firstDay(void)
904 {
905     int res, fday, i, prev;
906     CHAR b[128], caltype[3];
907     LCID lcid = LOCALE_USER_DEFAULT;
908     HWND hwnd;
909     LRESULT ret;
910 
911     SetLastError(0xdeadbeef);
912     ret = GetLocaleInfoA(lcid, LOCALE_ICALENDARTYPE, caltype, 3);
913     if (ret == 0) {
914         skip("Must know local calendar type (%x)\n", GetLastError());
915         return;
916     } else if (atoi(caltype) != CAL_GREGORIAN) {
917         skip("MonthCalendar Control only supports Gregorian calendar (type: %s)\n", caltype);
918         return;
919     }
920 
921     hwnd = create_monthcal_control(0);
922 
923     flush_sequences(sequences, NUM_MSG_SEQUENCES);
924 
925     /* Setter and Getters for first day of week */
926     /* check for locale first day */
927     if(GetLocaleInfoA(lcid, LOCALE_IFIRSTDAYOFWEEK, b, 128)){
928         fday = atoi(b);
929         res = SendMessageA(hwnd, MCM_GETFIRSTDAYOFWEEK, 0, 0);
930         expect(fday, res);
931         prev = fday;
932 
933         /* checking for the values that actually will be stored as */
934         /* current first day when we set a new value */
935         for (i = -5; i < 12; i++){
936             res = SendMessageA(hwnd, MCM_SETFIRSTDAYOFWEEK, 0, i);
937             expect(prev, res);
938             res = SendMessageA(hwnd, MCM_GETFIRSTDAYOFWEEK, 0, 0);
939             prev = res;
940 
941             if (i == -1){
942                 expect(MAKELONG(fday, FALSE), res);
943             }else if (i >= 7){
944                 /* out of range sets max first day of week, locale is ignored */
945                 expect(MAKELONG(6, TRUE), res);
946             }else{
947                 expect(MAKELONG(i, TRUE), res);
948             }
949         }
950 
951         ok_sequence(sequences, MONTHCAL_SEQ_INDEX, monthcal_first_day_seq, "monthcal firstDay", FALSE);
952 
953     }else{
954         skip("Cannot retrieve first day of the week\n");
955     }
956 
957     DestroyWindow(hwnd);
958 }
959 
960 static void test_unicode(void)
961 {
962     int res, temp;
963     HWND hwnd;
964 
965     hwnd = create_monthcal_control(0);
966 
967     flush_sequences(sequences, NUM_MSG_SEQUENCES);
968 
969     /* Setter and Getters for Unicode format */
970 
971     /* getting the current settings */
972     temp = SendMessageA(hwnd, MCM_GETUNICODEFORMAT, 0, 0);
973 
974     /* setting to 1, should return previous settings */
975     res = SendMessageA(hwnd, MCM_SETUNICODEFORMAT, 1, 0);
976     expect(temp, res);
977 
978     /* current setting is 1, so, should return 1 */
979     res = SendMessageA(hwnd, MCM_GETUNICODEFORMAT, 0, 0);
980     ok(1 == res ||
981        broken(0 == res), /* comctl32 <= 4.70 */
982        "Expected 1, got %d\n", res);
983 
984     /* setting to 0, should return previous settings */
985     res = SendMessageA(hwnd, MCM_SETUNICODEFORMAT, 0, 0);
986     ok(1 == res ||
987        broken(0 == res), /* comctl32 <= 4.70 */
988        "Expected 1, got %d\n", res);
989 
990     /* current setting is 0, so, it should return 0 */
991     res = SendMessageA(hwnd, MCM_GETUNICODEFORMAT, 0, 0);
992     expect(0, res);
993 
994     /* should return previous settings */
995     res = SendMessageA(hwnd, MCM_SETUNICODEFORMAT, 1, 0);
996     expect(0, res);
997 
998     ok_sequence(sequences, MONTHCAL_SEQ_INDEX, monthcal_unicode_seq, "monthcal unicode", FALSE);
999 
1000     DestroyWindow(hwnd);
1001 }
1002 
1003 static void test_hittest(void)
1004 {
1005     typedef struct hittest_test
1006     {
1007 	UINT ht;
1008         BOOL  todo;
1009     } hittest_test_t;
1010 
1011     static const hittest_test_t title_hits[] = {
1012         /* Start is the same everywhere */
1013         { MCHT_TITLE,        FALSE },
1014         { MCHT_TITLEBTNPREV, FALSE },
1015         /* The middle piece is only tested for presence of items */
1016         /* End is the same everywhere */
1017         { MCHT_TITLEBTNNEXT, FALSE },
1018         { MCHT_TITLE,        FALSE },
1019         { MCHT_NOWHERE,      TRUE }
1020     };
1021 
1022     MCHITTESTINFO mchit;
1023     UINT res, old_res;
1024     SYSTEMTIME st;
1025     LONG x;
1026     UINT title_index;
1027     HWND hwnd;
1028     RECT r;
1029     char yearmonth[80], *locale_month, *locale_year;
1030     int month_count, year_count;
1031     BOOL in_the_middle;
1032 
1033     memset(&mchit, 0, sizeof(MCHITTESTINFO));
1034 
1035     hwnd = create_monthcal_control(0);
1036 
1037     /* test with invalid structure size */
1038     mchit.cbSize = MCHITTESTINFO_V1_SIZE - 1;
1039     mchit.pt.x = 0;
1040     mchit.pt.y = 0;
1041     res = SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit);
1042     expect(0, mchit.pt.x);
1043     expect(0, mchit.pt.y);
1044     expect(~0u, res);
1045     expect(0, mchit.uHit);
1046     /* test with invalid pointer */
1047     res = SendMessageA(hwnd, MCM_HITTEST, 0, 0);
1048     expect(~0u, res);
1049 
1050     /* resize control to display single Calendar */
1051     res = SendMessageA(hwnd, MCM_GETMINREQRECT, 0, (LPARAM)&r);
1052     if (res == 0)
1053     {
1054         win_skip("Message MCM_GETMINREQRECT unsupported. Skipping.\n");
1055         DestroyWindow(hwnd);
1056         return;
1057     }
1058     MoveWindow(hwnd, 0, 0, r.right, r.bottom, FALSE);
1059 
1060     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1061 
1062     st.wYear = 2007;
1063     st.wMonth = 4;
1064     st.wDay = 11;
1065     st.wHour = 1;
1066     st.wMinute = 0;
1067     st.wSecond = 0;
1068     st.wMilliseconds = 0;
1069     st.wDayOfWeek = 0;
1070 
1071     res = SendMessageA(hwnd, MCM_SETCURSEL, 0, (LPARAM)&st);
1072     expect(1,res);
1073 
1074     /* (0, 0) is the top left of the control - title */
1075     mchit.cbSize = MCHITTESTINFO_V1_SIZE;
1076     mchit.pt.x = 0;
1077     mchit.pt.y = 0;
1078     res = SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit);
1079     expect(0, mchit.pt.x);
1080     expect(0, mchit.pt.y);
1081     expect(mchit.uHit, res);
1082     expect_hex(MCHT_TITLE, res);
1083 
1084     /* bottom right of the control and should not be active */
1085     mchit.pt.x = r.right;
1086     mchit.pt.y = r.bottom;
1087     res = SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit);
1088     expect(r.right,  mchit.pt.x);
1089     expect(r.bottom, mchit.pt.y);
1090     expect(mchit.uHit, res);
1091     todo_wine expect_hex(MCHT_NOWHERE, res);
1092 
1093     /* completely out of the control, should not be active */
1094     mchit.pt.x = 2 * r.right;
1095     mchit.pt.y = 2 * r.bottom;
1096     res = SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit);
1097     expect(2 * r.right, mchit.pt.x);
1098     expect(2 * r.bottom, mchit.pt.y);
1099     expect(mchit.uHit, res);
1100     todo_wine expect_hex(MCHT_NOWHERE, res);
1101 
1102     /* in active area - day of the week */
1103     mchit.pt.x = r.right / 2;
1104     mchit.pt.y = r.bottom / 2;
1105     res = SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit);
1106     expect(r.right / 2, mchit.pt.x);
1107     expect(r.bottom / 2, mchit.pt.y);
1108     expect(mchit.uHit, res);
1109     expect_hex(MCHT_CALENDARDATE, res);
1110 
1111     /* in active area - day of the week #2 */
1112     mchit.pt.x = r.right / 14; /* half of first day rect */
1113     mchit.pt.y = r.bottom / 2;
1114     res = SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit);
1115     expect(r.right / 14, mchit.pt.x);
1116     expect(r.bottom / 2, mchit.pt.y);
1117     expect(mchit.uHit, res);
1118     expect_hex(MCHT_CALENDARDATE, res);
1119 
1120     /* in active area - date from prev month */
1121     mchit.pt.x = r.right / 14; /* half of first day rect */
1122     mchit.pt.y = 6 * r.bottom / 19;
1123     res = SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit);
1124     expect(r.right / 14, mchit.pt.x);
1125     expect(6 * r.bottom / 19, mchit.pt.y);
1126     expect(mchit.uHit, res);
1127     expect_hex(MCHT_CALENDARDATEPREV, res);
1128 
1129 if (0)
1130 {
1131     /* (125, 115) is in active area - date from this month */
1132     mchit.pt.x = 125;
1133     mchit.pt.y = 115;
1134     res = SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit);
1135     expect(125, mchit.pt.x);
1136     expect(115, mchit.pt.y);
1137     expect(mchit.uHit, res);
1138     expect(MCHT_CALENDARDATE, res);
1139 }
1140 
1141     /* in active area - date from next month */
1142     mchit.pt.x = 11 * r.right / 14;
1143     mchit.pt.y = 16 * r.bottom / 19;
1144     res = SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit);
1145     expect(11 * r.right / 14, mchit.pt.x);
1146     expect(16 * r.bottom / 19, mchit.pt.y);
1147     expect(mchit.uHit, res);
1148     expect_hex(MCHT_CALENDARDATENEXT, res);
1149 
1150     /* in active area - today link */
1151     mchit.pt.x = r.right / 14;
1152     mchit.pt.y = 18 * r.bottom / 19;
1153     res = SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit);
1154     expect(r.right / 14, mchit.pt.x);
1155     expect(18 * r.bottom / 19, mchit.pt.y);
1156     expect(mchit.uHit, res);
1157     expect_hex(MCHT_TODAYLINK, res);
1158 
1159     /* in active area - today link */
1160     mchit.pt.x = r.right / 2;
1161     mchit.pt.y = 18 * r.bottom / 19;
1162     res = SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit);
1163     expect(r.right / 2, mchit.pt.x);
1164     expect(18 * r.bottom / 19, mchit.pt.y);
1165     expect(mchit.uHit, res);
1166     expect_hex(MCHT_TODAYLINK, res);
1167 
1168     /* in active area - today link */
1169     mchit.pt.x = r.right / 10;
1170     mchit.pt.y = 18 * r.bottom / 19;
1171     res = SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit);
1172     expect(r.right / 10, mchit.pt.x);
1173     expect(18 * r.bottom / 19, mchit.pt.y);
1174     expect(mchit.uHit, res);
1175     expect_hex(MCHT_TODAYLINK, res);
1176 
1177     ok_sequence(sequences, MONTHCAL_SEQ_INDEX, monthcal_hit_test_seq, "monthcal hit test", TRUE);
1178 
1179     /* The horizontal position of title bar elements depends on locale (y pos
1180        is constant), so we sample across a horizontal line and make sure we
1181        find all elements. */
1182 
1183     /* Get the format of the title */
1184     GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SYEARMONTH, yearmonth, 80);
1185     /* Find out if we have a month and/or year */
1186     locale_year = strstr(yearmonth, "y");
1187     locale_month = strstr(yearmonth, "M");
1188 
1189     mchit.pt.x = 0;
1190     mchit.pt.y = (5/2) * r.bottom / 19;
1191     title_index = 0;
1192     old_res = SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit);
1193     expect_hex(title_hits[title_index].ht, old_res);
1194 
1195     in_the_middle = FALSE;
1196     month_count = year_count = 0;
1197     for (x = 0; x < r.right; x++){
1198         mchit.pt.x = x;
1199         res = SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit);
1200         expect(x, mchit.pt.x);
1201         expect((5/2) * r.bottom / 19, mchit.pt.y);
1202         expect(mchit.uHit, res);
1203         if (res != old_res) {
1204 
1205             if (old_res == MCHT_TITLEBTNPREV)
1206                 in_the_middle = TRUE;
1207 
1208             if (res == MCHT_TITLEBTNNEXT)
1209                 in_the_middle = FALSE;
1210 
1211             if (in_the_middle) {
1212                 if (res == MCHT_TITLEMONTH)
1213                     month_count++;
1214                 else if (res == MCHT_TITLEYEAR)
1215                     year_count++;
1216             } else {
1217                 title_index++;
1218 
1219                 if (ARRAY_SIZE(title_hits) <= title_index)
1220                     break;
1221 
1222                 todo_wine_if(title_hits[title_index].todo)
1223                     ok(title_hits[title_index].ht == res, "Expected %x, got %x, pos %d\n",
1224                                                           title_hits[title_index].ht, res, x);
1225             }
1226             old_res = res;
1227         }
1228     }
1229 
1230     /* There are some limits, even if LOCALE_SYEARMONTH contains rubbish
1231      * or no month/year indicators at all */
1232     if (locale_month)
1233         todo_wine ok(month_count == 1, "Expected 1 month item, got %d\n", month_count);
1234     else
1235         ok(month_count <= 1, "Too many month items: %d\n", month_count);
1236 
1237     if (locale_year)
1238         todo_wine ok(year_count == 1, "Expected 1 year item, got %d\n", year_count);
1239     else
1240         ok(year_count <= 1, "Too many year items: %d\n", year_count);
1241 
1242     todo_wine ok(month_count + year_count >= 1, "Not enough month and year items\n");
1243 
1244     ok(r.right <= x && title_index + 1 == ARRAY_SIZE(title_hits), "Wrong title layout\n");
1245 
1246     DestroyWindow(hwnd);
1247 }
1248 
1249 static void test_todaylink(void)
1250 {
1251     MCHITTESTINFO mchit;
1252     SYSTEMTIME st_test, st_new;
1253     UINT res;
1254     HWND hwnd;
1255     RECT r;
1256 
1257     memset(&mchit, 0, sizeof(MCHITTESTINFO));
1258 
1259     hwnd = create_monthcal_control(0);
1260 
1261     res = SendMessageA(hwnd, MCM_GETMINREQRECT, 0, (LPARAM)&r);
1262     expect(1, res);
1263     MoveWindow(hwnd, 0, 0, r.right, r.bottom, FALSE);
1264 
1265     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1266 
1267     /* hit active area - today link */
1268     mchit.cbSize = MCHITTESTINFO_V1_SIZE;
1269     mchit.pt.x = r.right / 14;
1270     mchit.pt.y = 18 * r.bottom / 19;
1271     res = SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit);
1272     expect(r.right / 14, mchit.pt.x);
1273     expect(18 * r.bottom / 19, mchit.pt.y);
1274     expect(mchit.uHit, res);
1275     expect(MCHT_TODAYLINK, res);
1276 
1277     st_test.wDay = 1;
1278     st_test.wMonth = 1;
1279     st_test.wYear = 2005;
1280 
1281     res = SendMessageA(hwnd, MCM_SETTODAY, 0, (LPARAM)&st_test);
1282     expect(0, res);
1283 
1284     memset(&st_new, 0, sizeof(st_new));
1285     res = SendMessageA(hwnd, MCM_GETTODAY, 0, (LPARAM)&st_new);
1286     expect(1, res);
1287     expect(1, st_new.wDay);
1288     expect(1, st_new.wMonth);
1289     expect(2005, st_new.wYear);
1290 
1291     res = SendMessageA(hwnd, WM_LBUTTONDOWN, MK_LBUTTON, MAKELONG(mchit.pt.x, mchit.pt.y));
1292     expect(0, res);
1293 
1294     memset(&st_new, 0, sizeof(st_new));
1295     res = SendMessageA(hwnd, MCM_GETCURSEL, 0, (LPARAM)&st_new);
1296     expect(1, res);
1297     expect(1, st_new.wDay);
1298     expect(1, st_new.wMonth);
1299     expect(2005, st_new.wYear);
1300 
1301     ok_sequence(sequences, MONTHCAL_SEQ_INDEX, monthcal_todaylink_seq, "monthcal hit test", TRUE);
1302 
1303     DestroyWindow(hwnd);
1304 }
1305 
1306 static void test_today(void)
1307 {
1308     SYSTEMTIME st_test, st_new;
1309     int res;
1310     HWND hwnd;
1311 
1312     hwnd = create_monthcal_control(0);
1313 
1314     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1315 
1316     /* Setter and Getters for "today" information */
1317 
1318     /* check for overflow, should be ok */
1319     memset(&st_test, 0, sizeof(st_test));
1320     st_test.wDay = 38;
1321     st_test.wMonth = 38;
1322 
1323     st_new.wDay = 27;
1324     st_new.wMonth = 27;
1325 
1326     res = SendMessageA(hwnd, MCM_SETTODAY, 0, (LPARAM)&st_test);
1327     expect(0, res);
1328 
1329     res = SendMessageA(hwnd, MCM_GETTODAY, 0, (LPARAM)&st_new);
1330     expect(1, res);
1331 
1332     /* st_test should not change */
1333     expect(38, st_test.wDay);
1334     expect(38, st_test.wMonth);
1335 
1336     /* st_new should change, overflow does not matter */
1337     expect(38, st_new.wDay);
1338     expect(38, st_new.wMonth);
1339 
1340     /* check for zero, should be ok*/
1341     st_test.wDay = 0;
1342     st_test.wMonth = 0;
1343 
1344     res = SendMessageA(hwnd, MCM_SETTODAY, 0, (LPARAM)&st_test);
1345     expect(0, res);
1346 
1347     res = SendMessageA(hwnd, MCM_GETTODAY, 0, (LPARAM)&st_new);
1348     expect(1, res);
1349 
1350     /* st_test should not change */
1351     expect(0, st_test.wDay);
1352     expect(0, st_test.wMonth);
1353 
1354     /* st_new should change to zero*/
1355     expect(0, st_new.wDay);
1356     expect(0, st_new.wMonth);
1357 
1358     ok_sequence(sequences, MONTHCAL_SEQ_INDEX, monthcal_today_seq, "monthcal today", TRUE);
1359 
1360     DestroyWindow(hwnd);
1361 }
1362 
1363 static void test_scroll(void)
1364 {
1365     int res;
1366     HWND hwnd;
1367 
1368     hwnd = create_monthcal_control(0);
1369 
1370     res = SendMessageA(hwnd, MCM_GETMONTHDELTA, 0, 0);
1371     expect(2, res);
1372 
1373     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1374 
1375     /* Setter and Getters for scroll rate */
1376     res = SendMessageA(hwnd, MCM_SETMONTHDELTA, 2, 0);
1377     expect(0, res);
1378 
1379     res = SendMessageA(hwnd, MCM_SETMONTHDELTA, 3, 0);
1380     expect(2, res);
1381     res = SendMessageA(hwnd, MCM_GETMONTHDELTA, 0, 0);
1382     expect(3, res);
1383 
1384     res = SendMessageA(hwnd, MCM_SETMONTHDELTA, 12, 0);
1385     expect(3, res);
1386     res = SendMessageA(hwnd, MCM_GETMONTHDELTA, 0, 0);
1387     expect(12, res);
1388 
1389     res = SendMessageA(hwnd, MCM_SETMONTHDELTA, 15, 0);
1390     expect(12, res);
1391     res = SendMessageA(hwnd, MCM_GETMONTHDELTA, 0, 0);
1392     expect(15, res);
1393 
1394     res = SendMessageA(hwnd, MCM_SETMONTHDELTA, -5, 0);
1395     expect(15, res);
1396     res = SendMessageA(hwnd, MCM_GETMONTHDELTA, 0, 0);
1397     expect(-5, res);
1398 
1399     ok_sequence(sequences, MONTHCAL_SEQ_INDEX, monthcal_scroll_seq, "monthcal scroll", FALSE);
1400 
1401     DestroyWindow(hwnd);
1402 }
1403 
1404 static void test_monthrange(void)
1405 {
1406     int res;
1407     SYSTEMTIME st_visible[2], st_daystate[2], st;
1408     HWND hwnd;
1409     RECT r;
1410 
1411     hwnd = create_monthcal_control(0);
1412 
1413     memset(&st_visible, 0, sizeof(st_visible));
1414     memset(&st_daystate, 0, sizeof(st_daystate));
1415 
1416     st.wYear = 2000;
1417     st.wMonth = 11;
1418     st.wDay = 28;
1419     st.wHour = 11;
1420     st.wMinute = 59;
1421     st.wSecond = 30;
1422     st.wMilliseconds = 0;
1423     st.wDayOfWeek = 0;
1424 
1425     res = SendMessageA(hwnd, MCM_SETCURSEL, 0, (LPARAM)&st);
1426     expect(1,res);
1427 
1428     /* to be locale independent */
1429     SendMessageA(hwnd, MCM_SETFIRSTDAYOFWEEK, 0, (LPARAM)6);
1430 
1431     res = SendMessageA(hwnd, MCM_GETMINREQRECT, 0, (LPARAM)&r);
1432     expect(TRUE, res);
1433     /* resize control to display two Calendars */
1434     MoveWindow(hwnd, 0, 0, r.right, (5/2)*r.bottom, FALSE);
1435 
1436     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1437 
1438     res = SendMessageA(hwnd, MCM_GETMONTHRANGE, GMR_VISIBLE, (LPARAM)st_visible);
1439     expect(2, res);
1440     expect(2000, st_visible[0].wYear);
1441     expect(11, st_visible[0].wMonth);
1442     expect(1, st_visible[0].wDay);
1443     expect(2000, st_visible[1].wYear);
1444     expect(12, st_visible[1].wMonth);
1445     expect(31, st_visible[1].wDay);
1446 
1447     res = SendMessageA(hwnd, MCM_GETMONTHRANGE, GMR_DAYSTATE, (LPARAM)st_daystate);
1448     expect(4, res);
1449     expect(2000, st_daystate[0].wYear);
1450     expect(10, st_daystate[0].wMonth);
1451     expect(29, st_daystate[0].wDay);
1452     expect(2001, st_daystate[1].wYear);
1453     expect(1, st_daystate[1].wMonth);
1454     expect(6, st_daystate[1].wDay);
1455 
1456     ok_sequence(sequences, MONTHCAL_SEQ_INDEX, monthcal_monthrange_seq, "monthcal monthrange", FALSE);
1457 
1458     /* with null date array parameter */
1459     res = SendMessageA(hwnd, MCM_GETMONTHRANGE, GMR_VISIBLE, 0);
1460     expect(2, res);
1461 
1462     res = SendMessageA(hwnd, MCM_GETMONTHRANGE, GMR_DAYSTATE, 0);
1463     expect(4, res);
1464 
1465     /* resize control to display single Calendar */
1466     MoveWindow(hwnd, 0, 0, r.right, r.bottom, FALSE);
1467 
1468     memset(&st, 0, sizeof(st));
1469     st.wMonth = 9;
1470     st.wYear  = 1752;
1471     st.wDay   = 14;
1472 
1473     res = SendMessageA(hwnd, MCM_SETCURSEL, 0, (LPARAM)&st);
1474     expect(1, res);
1475 
1476     /* September 1752 has 19 days */
1477     res = SendMessageA(hwnd, MCM_GETMONTHRANGE, GMR_VISIBLE, (LPARAM)st_visible);
1478     expect(1, res);
1479 
1480     expect(1752, st_visible[0].wYear);
1481     expect(9, st_visible[0].wMonth);
1482     ok(14 == st_visible[0].wDay ||
1483        broken(1 == st_visible[0].wDay), /* comctl32 <= 4.72 */
1484        "Expected 14, got %d\n", st_visible[0].wDay);
1485 
1486     expect(1752, st_visible[1].wYear);
1487     expect(9, st_visible[1].wMonth);
1488     expect(19, st_visible[1].wDay);
1489 
1490     DestroyWindow(hwnd);
1491 }
1492 
1493 static void test_maxselday(void)
1494 {
1495     int res;
1496     HWND hwnd;
1497     DWORD style;
1498 
1499     hwnd = create_monthcal_control(0);
1500     /* if no style specified default to 1 */
1501     res = SendMessageA(hwnd, MCM_GETMAXSELCOUNT, 0, 0);
1502     expect(1, res);
1503     res = SendMessageA(hwnd, MCM_SETMAXSELCOUNT, 5, 0);
1504     expect(0, res);
1505     res = SendMessageA(hwnd, MCM_GETMAXSELCOUNT, 0, 0);
1506     expect(1, res);
1507 
1508     /* try to set style */
1509     style = GetWindowLongA(hwnd, GWL_STYLE);
1510     SetWindowLongA(hwnd, GWL_STYLE, style | MCS_MULTISELECT);
1511     style = GetWindowLongA(hwnd, GWL_STYLE);
1512     ok(!(style & MCS_MULTISELECT), "Expected MCS_MULTISELECT not to be set\n");
1513     DestroyWindow(hwnd);
1514 
1515     hwnd = create_monthcal_control(MCS_MULTISELECT);
1516     /* try to remove style */
1517     style = GetWindowLongA(hwnd, GWL_STYLE);
1518     SetWindowLongA(hwnd, GWL_STYLE, style & ~MCS_MULTISELECT);
1519     style = GetWindowLongA(hwnd, GWL_STYLE);
1520     ok(style & MCS_MULTISELECT, "Expected MCS_MULTISELECT to be set\n");
1521     DestroyWindow(hwnd);
1522 
1523     hwnd = create_monthcal_control(MCS_MULTISELECT);
1524 
1525     /* default width is a week */
1526     res = SendMessageA(hwnd, MCM_GETMAXSELCOUNT, 0, 0);
1527     expect(7, res);
1528 
1529     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1530 
1531     /* Setter and Getters for max selected days */
1532     res = SendMessageA(hwnd, MCM_SETMAXSELCOUNT, 5, 0);
1533     expect(1, res);
1534     res = SendMessageA(hwnd, MCM_GETMAXSELCOUNT, 0, 0);
1535     expect(5, res);
1536 
1537     res = SendMessageA(hwnd, MCM_SETMAXSELCOUNT, 15, 0);
1538     expect(1, res);
1539     res = SendMessageA(hwnd, MCM_GETMAXSELCOUNT, 0, 0);
1540     expect(15, res);
1541 
1542     /* test invalid value */
1543     res = SendMessageA(hwnd, MCM_SETMAXSELCOUNT, -1, 0);
1544     expect(0, res);
1545     res = SendMessageA(hwnd, MCM_GETMAXSELCOUNT, 0, 0);
1546     expect(15, res);
1547 
1548     ok_sequence(sequences, MONTHCAL_SEQ_INDEX, monthcal_max_sel_day_seq, "monthcal MaxSelDay", FALSE);
1549 
1550     /* zero value is invalid too */
1551     res = SendMessageA(hwnd, MCM_SETMAXSELCOUNT, 0, 0);
1552     expect(0, res);
1553     res = SendMessageA(hwnd, MCM_GETMAXSELCOUNT, 0, 0);
1554     expect(15, res);
1555 
1556     DestroyWindow(hwnd);
1557 }
1558 
1559 static void test_size(void)
1560 {
1561     int res;
1562     RECT r1, r2;
1563     HFONT hFont1, hFont2;
1564     LOGFONTA logfont;
1565     HWND hwnd;
1566 
1567     hwnd = create_monthcal_control(0);
1568 
1569     lstrcpyA(logfont.lfFaceName, "Arial");
1570     memset(&logfont, 0, sizeof(logfont));
1571     logfont.lfHeight = 12;
1572     hFont1 = CreateFontIndirectA(&logfont);
1573 
1574     logfont.lfHeight = 24;
1575     hFont2 = CreateFontIndirectA(&logfont);
1576 
1577     /* initialize to a font we can compare against */
1578     SendMessageA(hwnd, WM_SETFONT, (WPARAM)hFont1, 0);
1579     res = SendMessageA(hwnd, MCM_GETMINREQRECT, 0, (LPARAM)&r1);
1580     ok(res, "SendMessageA(MCM_GETMINREQRECT) failed\n");
1581 
1582     /* check that setting a larger font results in an larger rect */
1583     SendMessageA(hwnd, WM_SETFONT, (WPARAM)hFont2, 0);
1584     res = SendMessageA(hwnd, MCM_GETMINREQRECT, 0, (LPARAM)&r2);
1585     ok(res, "SendMessageA(MCM_GETMINREQRECT) failed\n");
1586 
1587     OffsetRect(&r1, -r1.left, -r1.top);
1588     OffsetRect(&r2, -r2.left, -r2.top);
1589 
1590     ok(r1.bottom < r2.bottom, "Failed to get larger rect with larger font\n");
1591 
1592     DestroyWindow(hwnd);
1593 }
1594 
1595 static void test_create(void)
1596 {
1597     HWND hwnd;
1598 
1599     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1600 
1601     hwnd = create_monthcal_control(0);
1602     ok_sequence(sequences, PARENT_SEQ_INDEX, create_monthcal_control_seq, "create monthcal control", TRUE);
1603 
1604     DestroyWindow(hwnd);
1605 
1606     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1607     hwnd = create_monthcal_control(MCS_MULTISELECT);
1608     ok_sequence(sequences, PARENT_SEQ_INDEX, create_monthcal_multi_sel_style_seq, "create monthcal (multi sel style)", TRUE);
1609     DestroyWindow(hwnd);
1610 }
1611 
1612 static void test_destroy(void)
1613 {
1614     HWND hwnd;
1615 
1616     hwnd = create_monthcal_control(0);
1617     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1618     DestroyWindow(hwnd);
1619     ok_sequence(sequences, PARENT_SEQ_INDEX, destroy_monthcal_parent_msgs_seq, "Destroy monthcal (parent msg)", FALSE);
1620     ok_sequence(sequences, MONTHCAL_SEQ_INDEX, destroy_monthcal_child_msgs_seq, "Destroy monthcal (child msg)", FALSE);
1621 
1622     /* MCS_MULTISELECT */
1623     hwnd = create_monthcal_control(MCS_MULTISELECT);
1624     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1625     DestroyWindow(hwnd);
1626     ok_sequence(sequences, MONTHCAL_SEQ_INDEX, destroy_monthcal_multi_sel_style_seq, "Destroy monthcal (multi sel style)", FALSE);
1627 }
1628 
1629 static void test_selrange(void)
1630 {
1631     HWND hwnd;
1632     SYSTEMTIME st, range[2], range2[2];
1633     BOOL ret, old_comctl32 = FALSE;
1634 
1635     hwnd = create_monthcal_control(MCS_MULTISELECT);
1636 
1637     /* just after creation selection should start and end today */
1638     ret = SendMessageA(hwnd, MCM_GETTODAY, 0, (LPARAM)&st);
1639     expect(TRUE, ret);
1640 
1641     memset(range, 0xcc, sizeof(range));
1642     ret = SendMessageA(hwnd, MCM_GETSELRANGE, 0, (LPARAM)range);
1643     expect(TRUE, ret);
1644     expect(st.wYear,      range[0].wYear);
1645     expect(st.wMonth,     range[0].wMonth);
1646     expect(st.wDay,       range[0].wDay);
1647     if (range[0].wDayOfWeek != st.wDayOfWeek)
1648     {
1649         win_skip("comctl32 <= 4.70 doesn't set some values\n");
1650         old_comctl32 = TRUE;
1651     }
1652     else
1653     {
1654         expect(st.wDayOfWeek, range[0].wDayOfWeek);
1655         expect(st.wHour,      range[0].wHour);
1656         expect(st.wMinute,    range[0].wMinute);
1657         expect(st.wSecond,    range[0].wSecond);
1658         expect(st.wMilliseconds, range[0].wMilliseconds);
1659     }
1660 
1661     expect(st.wYear,      range[1].wYear);
1662     expect(st.wMonth,     range[1].wMonth);
1663     expect(st.wDay,       range[1].wDay);
1664     if (!old_comctl32)
1665     {
1666         expect(st.wDayOfWeek, range[1].wDayOfWeek);
1667         expect(st.wHour,      range[1].wHour);
1668         expect(st.wMinute,    range[1].wMinute);
1669         expect(st.wSecond,    range[1].wSecond);
1670         expect(st.wMilliseconds, range[1].wMilliseconds);
1671     }
1672 
1673     /* bounds are swapped if min > max */
1674     memset(&range[0], 0, sizeof(range[0]));
1675     range[0].wYear  = 2009;
1676     range[0].wMonth = 10;
1677     range[0].wDay   = 5;
1678     range[1] = range[0];
1679     range[1].wDay   = 3;
1680 
1681     ret = SendMessageA(hwnd, MCM_SETSELRANGE, 0, (LPARAM)range);
1682     expect(TRUE, ret);
1683 
1684     ret = SendMessageA(hwnd, MCM_GETSELRANGE, 0, (LPARAM)range2);
1685     expect(TRUE, ret);
1686 
1687     expect(range[1].wYear,      range2[0].wYear);
1688     expect(range[1].wMonth,     range2[0].wMonth);
1689     expect(range[1].wDay,       range2[0].wDay);
1690     expect(6, range2[0].wDayOfWeek);
1691     expect(range[1].wHour,      range2[0].wHour);
1692     expect(range[1].wMinute,    range2[0].wMinute);
1693     expect(range[1].wSecond,    range2[0].wSecond);
1694     expect(range[1].wMilliseconds, range2[0].wMilliseconds);
1695 
1696     expect(range[0].wYear,      range2[1].wYear);
1697     expect(range[0].wMonth,     range2[1].wMonth);
1698     expect(range[0].wDay,       range2[1].wDay);
1699     expect(1, range2[1].wDayOfWeek);
1700     expect(range[0].wHour,      range2[1].wHour);
1701     expect(range[0].wMinute,    range2[1].wMinute);
1702     expect(range[0].wSecond,    range2[1].wSecond);
1703     expect(range[0].wMilliseconds, range2[1].wMilliseconds);
1704 
1705     /* try with range larger than maximum configured */
1706     memset(&range[0], 0, sizeof(range[0]));
1707     range[0].wYear  = 2009;
1708     range[0].wMonth = 10;
1709     range[0].wDay   = 1;
1710     range[1] = range[0];
1711 
1712     ret = SendMessageA(hwnd, MCM_SETSELRANGE, 0, (LPARAM)range);
1713     expect(TRUE, ret);
1714 
1715     range[1] = range[0];
1716     /* default max. range is 7 days */
1717     range[1].wDay = 8;
1718 
1719     ret = SendMessageA(hwnd, MCM_SETSELRANGE, 0, (LPARAM)range);
1720     expect(FALSE, ret);
1721 
1722     ret = SendMessageA(hwnd, MCM_GETSELRANGE, 0, (LPARAM)range2);
1723     expect(TRUE, ret);
1724 
1725     expect(range[0].wYear,  range2[0].wYear);
1726     expect(range[0].wMonth, range2[0].wMonth);
1727     expect(range[0].wDay,   range2[0].wDay);
1728     expect(range[0].wYear,  range2[1].wYear);
1729     expect(range[0].wMonth, range2[1].wMonth);
1730     expect(range[0].wDay,   range2[1].wDay);
1731 
1732     DestroyWindow(hwnd);
1733 }
1734 
1735 static void test_killfocus(void)
1736 {
1737     HWND hwnd;
1738     DWORD style;
1739 
1740     hwnd = create_monthcal_control(0);
1741 
1742     /* make parent invisible */
1743     style = GetWindowLongA(parent_wnd, GWL_STYLE);
1744     SetWindowLongA(parent_wnd, GWL_STYLE, style & ~WS_VISIBLE);
1745 
1746     SendMessageA(hwnd, WM_KILLFOCUS, (WPARAM)GetDesktopWindow(), 0);
1747 
1748     style = GetWindowLongA(hwnd, GWL_STYLE);
1749     ok(style & WS_VISIBLE, "Expected WS_VISIBLE to be set\n");
1750 
1751     style = GetWindowLongA(parent_wnd, GWL_STYLE);
1752     SetWindowLongA(parent_wnd, GWL_STYLE, style | WS_VISIBLE);
1753 
1754     DestroyWindow(hwnd);
1755 }
1756 
1757 static void test_hittest_v6(void)
1758 {
1759     MCHITTESTINFO mchit;
1760     DWORD ret;
1761     HWND hwnd;
1762     RECT r;
1763 
1764     hwnd = create_monthcal_control(0);
1765     SendMessageA(hwnd, MCM_SETCALENDARBORDER, TRUE, 0);
1766 
1767     SendMessageA(hwnd, MCM_GETMINREQRECT, 0, (LPARAM)&r);
1768     /* reserving some area around calendar */
1769     MoveWindow(hwnd, 0, 0, r.right * 3 / 2, r.bottom * 3 / 2, FALSE);
1770     mchit.cbSize = sizeof(MCHITTESTINFO);
1771     mchit.pt.x = mchit.pt.y = 0;
1772     mchit.iOffset = -1;
1773     mchit.iRow = -1;
1774     mchit.iCol = -1;
1775     ret = SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit);
1776     if (ret == ~0u)
1777     {
1778         win_skip("Only MCHITTESTINFO_V1 supported\n");
1779         DestroyWindow(hwnd);
1780         return;
1781     }
1782     todo_wine expect_hex(MCHT_NOWHERE, ret);
1783     expect(-1, mchit.iOffset);
1784     expect(-1, mchit.iRow);
1785     expect(-1, mchit.iCol);
1786 
1787     MoveWindow(hwnd, 0, 0, r.right, r.bottom, FALSE);
1788     mchit.pt.x = r.right / 2;
1789     mchit.pt.y = r.bottom / 2;
1790     mchit.iOffset = -1;
1791     ret = SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit);
1792     expect_hex(MCHT_CALENDARDATE, ret);
1793     expect(0, mchit.iOffset);
1794 
1795     /* over day area */
1796     mchit.pt.x = r.right / (7*2);
1797     mchit.pt.y = r.bottom / 2;
1798     mchit.iOffset = -1;
1799     mchit.iCol = mchit.iRow = -1;
1800     mchit.uHit = 0;
1801     SetRect(&mchit.rc, -1, -1, -1, -1);
1802     ret = SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit);
1803     expect_hex(MCHT_CALENDARDATE, ret);
1804     expect_hex(MCHT_CALENDARDATE, mchit.uHit);
1805     expect(0, mchit.iOffset);
1806     expect(2, mchit.iRow);
1807     expect(0, mchit.iCol);
1808     /* returned a one day rectangle */
1809     expect_d(r.right / 7, mchit.rc.right - mchit.rc.left);
1810     expect_d(r.bottom / 10, mchit.rc.bottom - mchit.rc.top);
1811 
1812     /* title */
1813     mchit.pt.x = 1;
1814     mchit.pt.y = 1;
1815     mchit.iOffset = -1;
1816     mchit.iCol = mchit.iRow = -1;
1817     mchit.uHit = 0;
1818     SetRect(&mchit.rc, -1, -1, -1, -1);
1819     ret = SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit);
1820     expect_hex(MCHT_TITLE, ret);
1821     expect_hex(MCHT_TITLE, mchit.uHit);
1822     expect(0, mchit.iOffset);
1823     expect(-1, mchit.iRow);
1824     expect(-1, mchit.iCol);
1825     expect(0, mchit.rc.left);
1826     expect(0, mchit.rc.top);
1827     expect_d(r.right, mchit.rc.right);
1828     ok(mchit.rc.bottom > 0, "got %d\n", mchit.rc.bottom);
1829 
1830     /* between two calendars */
1831     MoveWindow(hwnd, 0, 0, r.right * 5/2, r.bottom, FALSE);
1832     mchit.pt.x = r.right / (5*4);
1833     mchit.pt.y = r.bottom / 2;
1834     mchit.iOffset = -2;
1835     mchit.iCol = mchit.iRow = -2;
1836     mchit.uHit = ~0;
1837     SetRect(&mchit.rc, -1, -1, -1, -1);
1838     ret = SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit);
1839     todo_wine expect_hex(MCHT_NOWHERE, ret);
1840     todo_wine expect_hex(MCHT_NOWHERE, mchit.uHit);
1841     expect(-2, mchit.iOffset);
1842     expect(-2, mchit.iRow);
1843     expect(-2, mchit.iCol);
1844     todo_wine expect(0, mchit.rc.left);
1845     todo_wine expect(0, mchit.rc.top);
1846     todo_wine expect_d(r.right * 5/2, mchit.rc.right);
1847     todo_wine expect_d(r.bottom, mchit.rc.bottom);
1848 
1849     DestroyWindow(hwnd);
1850 }
1851 
1852 static void test_get_set_border(void)
1853 {
1854     HWND hwnd;
1855     DWORD ret;
1856 
1857     hwnd = create_monthcal_control(0);
1858 
1859     /* a non-default value */
1860     ret = SendMessageA(hwnd, MCM_SETCALENDARBORDER, TRUE, 10);
1861     expect(0, ret);
1862 
1863     ret = SendMessageA(hwnd, MCM_GETCALENDARBORDER, 0, 0);
1864 
1865     if (ret != 10)
1866     {
1867         skip("MCM_GET/SETCALENDARBORDER not supported\n");
1868         DestroyWindow(hwnd);
1869         return;
1870     }
1871 
1872     expect(10, ret);
1873 
1874     DestroyWindow(hwnd);
1875 }
1876 
1877 static void test_MCM_SIZERECTTOMIN(void)
1878 {
1879     HWND hwnd;
1880     DWORD ret;
1881     RECT r, r2;
1882 
1883     hwnd = create_monthcal_control(0);
1884 
1885     ret = SendMessageA(hwnd, MCM_GETMINREQRECT, 0, (LPARAM)&r2);
1886     if (ret == 0)
1887     {
1888         win_skip("Message MCM_GETMINREQRECT unsupported. Skipping.\n");
1889         DestroyWindow(hwnd);
1890         return;
1891     }
1892 
1893     ret = SendMessageA(hwnd, MCM_SIZERECTTOMIN, 0, 0);
1894     ok(ret == 0, "got %d\n", ret);
1895 
1896     SetRectEmpty(&r);
1897     ret = SendMessageA(hwnd, MCM_SIZERECTTOMIN, 0, (LPARAM)&r);
1898     if (ret == 0)
1899     {
1900         skip("Message MCM_SIZERECTTOMIN unsupported. Skipping.\n");
1901         DestroyWindow(hwnd);
1902         return;
1903     }
1904     ok(ret == 1, "got %d\n", ret);
1905     ok(r.left == 0 && r.right > 0, "got %d, %d\n", r.left, r.right);
1906 
1907     r = r2;
1908     ret = SendMessageA(hwnd, MCM_SIZERECTTOMIN, 0, (LPARAM)&r);
1909     ok(ret == 1, "got %d\n", ret);
1910 
1911     r2.right = (r2.right - r2.left) * 3;
1912     r2.bottom = (r2.bottom - r2.top) * 3;
1913     r2.left = r2.top = 0;
1914     ret = SendMessageA(hwnd, MCM_SIZERECTTOMIN, 0, (LPARAM)&r2);
1915     ok(ret == 1, "got %d\n", ret);
1916 
1917     DestroyWindow(hwnd);
1918 }
1919 
1920 static void test_MCM_GETCALENDARCOUNT(void)
1921 {
1922     HWND hwnd;
1923     DWORD ret;
1924 
1925     hwnd = create_monthcal_control(0);
1926 
1927     ret = SendMessageA(hwnd, MCM_GETCALENDARCOUNT, 0, 0);
1928     if (ret == 0)
1929     {
1930         win_skip("Message MCM_GETCALENDARCOUNT unsupported. Skipping.\n");
1931         DestroyWindow(hwnd);
1932         return;
1933     }
1934 
1935     expect(2, ret);
1936 
1937     DestroyWindow(hwnd);
1938 }
1939 
1940 static void test_daystate(void)
1941 {
1942     MONTHDAYSTATE state[4];
1943     DWORD ret, style;
1944     HWND hwnd;
1945     RECT r;
1946 
1947     /* without MCS_DAYSTATE */
1948     hwnd = create_monthcal_control(0);
1949 
1950     ret = SendMessageA(hwnd, MCM_GETMINREQRECT, 0, (LPARAM)&r);
1951     expect(TRUE, ret);
1952 
1953     /* resize control to display two Calendars */
1954     MoveWindow(hwnd, 0, 0, r.right, (5/2)*r.bottom, FALSE);
1955 
1956     ret = SendMessageA(hwnd, MCM_GETMONTHRANGE, GMR_DAYSTATE, 0);
1957     expect(4, ret);
1958 
1959     ret = SendMessageA(hwnd, MCM_SETDAYSTATE, 4, (LPARAM)&state);
1960     expect(0, ret);
1961 
1962     ret = SendMessageA(hwnd, MCM_SETDAYSTATE, 2, (LPARAM)&state);
1963     expect(0, ret);
1964 
1965     ret = SendMessageA(hwnd, MCM_SETDAYSTATE, 0, 0);
1966     expect(0, ret);
1967 
1968     /* try to switch on */
1969     SetWindowLongA(hwnd, GWL_STYLE, GetWindowLongA(hwnd, GWL_STYLE) | MCS_DAYSTATE);
1970     style = GetWindowLongA(hwnd, GWL_STYLE);
1971     ok((style & MCS_DAYSTATE) == 0, "got 0x%08x\n", style);
1972 
1973     DestroyWindow(hwnd);
1974 
1975     /* with MCS_DAYSTATE */
1976     hwnd = create_monthcal_control(MCS_DAYSTATE);
1977 
1978     ret = SendMessageA(hwnd, MCM_GETMONTHRANGE, GMR_DAYSTATE, 0);
1979     expect(4, ret);
1980 
1981     ret = SendMessageA(hwnd, MCM_SETDAYSTATE, 4, (LPARAM)&state);
1982     expect(1, ret);
1983 
1984     ret = SendMessageA(hwnd, MCM_SETDAYSTATE, 2, (LPARAM)&state);
1985     expect(0, ret);
1986 
1987     ret = SendMessageA(hwnd, MCM_SETDAYSTATE, 0, 0);
1988     expect(0, ret);
1989 
1990     /* try to switch off */
1991     SetWindowLongA(hwnd, GWL_STYLE, GetWindowLongA(hwnd, GWL_STYLE) & ~MCS_DAYSTATE);
1992     style = GetWindowLongA(hwnd, GWL_STYLE);
1993     ok((style & MCS_DAYSTATE) == MCS_DAYSTATE, "got 0x%08x\n", style);
1994 
1995     DestroyWindow(hwnd);
1996 }
1997 
1998 static void test_sel_notify(void)
1999 {
2000     typedef struct
2001     {
2002         DWORD       val;
2003         const char* name;
2004     } Monthcal_style;
2005 
2006     HWND hwnd;
2007     RECT rc;
2008     MCHITTESTINFO mchit = {sizeof(MCHITTESTINFO)};
2009     SYSTEMTIME st;
2010     Monthcal_style styles[] = {
2011         {MCS_NOTODAY,                    "MCS_NOTODAY"},
2012         {MCS_NOTODAY | MCS_MULTISELECT,  "MCS_NOTODAY | MCS_MULTISELECT"},
2013         {MCS_DAYSTATE,                   "MCS_DAYSTATE"},
2014         {MCS_DAYSTATE | MCS_MULTISELECT, "MCS_DAYSTATE | MCS_MULTISELECT"}
2015     };
2016     int i;
2017 
2018     for(i = 0; i < ARRAY_SIZE(styles); i++)
2019     {
2020         hwnd = create_monthcal_control(styles[i].val);
2021         SetWindowLongPtrA(hwnd, GWLP_ID, SEL_NOTIFY_TEST_ID);
2022         SendMessageA(hwnd, MCM_GETMINREQRECT, 0, (LPARAM)&rc);
2023         MoveWindow(hwnd, 0, 0, rc.right, rc.bottom, FALSE);
2024         /* Simulate mouse click on some unselected day to generate
2025             MCN_SELECT and MCN_SELCHANGE notifications */
2026         mchit.pt.x = rc.right / 2;
2027         mchit.pt.y = rc.bottom / 2;
2028         SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit);
2029         SendMessageA(hwnd, MCM_GETCURSEL, 0, (LPARAM)&st);
2030         while(st.wDay == mchit.st.wDay) /* Ensure that mchit.pt points to unselected day */
2031         {
2032             mchit.pt.y++;
2033             SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit);
2034         }
2035         SendMessageA(hwnd, WM_LBUTTONDOWN, 0, MAKELPARAM(mchit.pt.x, mchit.pt.y));
2036         SendMessageA(hwnd, WM_LBUTTONUP, 0, MAKELPARAM(mchit.pt.x, mchit.pt.y));
2037         DestroyWindow(hwnd);
2038     }
2039 }
2040 
2041 static void init_functions(void)
2042 {
2043     HMODULE hComCtl32 = LoadLibraryA("comctl32.dll");
2044 
2045 #define X(f) p##f = (void*)GetProcAddress(hComCtl32, #f);
2046     X(InitCommonControlsEx);
2047 #undef X
2048 }
2049 
2050 START_TEST(monthcal)
2051 {
2052     INITCOMMONCONTROLSEX iccex;
2053     ULONG_PTR ctx_cookie;
2054     HANDLE hCtx;
2055 
2056     init_functions();
2057 
2058     iccex.dwSize = sizeof(iccex);
2059     iccex.dwICC  = ICC_DATE_CLASSES;
2060     pInitCommonControlsEx(&iccex);
2061 
2062     test_monthcal();
2063 
2064     init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
2065 
2066     parent_wnd = create_parent_window();
2067 
2068     test_create();
2069     test_destroy();
2070     test_color();
2071     test_currdate();
2072     test_firstDay();
2073     test_unicode();
2074     test_today();
2075     test_scroll();
2076     test_monthrange();
2077     test_hittest();
2078     test_todaylink();
2079     test_size();
2080     test_maxselday();
2081     test_selrange();
2082     test_killfocus();
2083     test_daystate();
2084     test_sel_notify();
2085 
2086     if (!load_v6_module(&ctx_cookie, &hCtx))
2087     {
2088         DestroyWindow(parent_wnd);
2089         return;
2090     }
2091 
2092     test_hittest_v6();
2093     test_get_set_border();
2094     test_MCM_SIZERECTTOMIN();
2095     test_MCM_GETCALENDARCOUNT();
2096 
2097     unload_v6_module(ctx_cookie, hCtx);
2098 
2099     DestroyWindow(parent_wnd);
2100 }
2101