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 (sizeof(title_hits) / sizeof(title_hits[0]) <= 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 == sizeof(title_hits) / sizeof(title_hits[0]),
1245        "Wrong title layout\n");
1246 
1247     DestroyWindow(hwnd);
1248 }
1249 
1250 static void test_todaylink(void)
1251 {
1252     MCHITTESTINFO mchit;
1253     SYSTEMTIME st_test, st_new;
1254     UINT res;
1255     HWND hwnd;
1256     RECT r;
1257 
1258     memset(&mchit, 0, sizeof(MCHITTESTINFO));
1259 
1260     hwnd = create_monthcal_control(0);
1261 
1262     res = SendMessageA(hwnd, MCM_GETMINREQRECT, 0, (LPARAM)&r);
1263     expect(1, res);
1264     MoveWindow(hwnd, 0, 0, r.right, r.bottom, FALSE);
1265 
1266     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1267 
1268     /* hit active area - today link */
1269     mchit.cbSize = MCHITTESTINFO_V1_SIZE;
1270     mchit.pt.x = r.right / 14;
1271     mchit.pt.y = 18 * r.bottom / 19;
1272     res = SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit);
1273     expect(r.right / 14, mchit.pt.x);
1274     expect(18 * r.bottom / 19, mchit.pt.y);
1275     expect(mchit.uHit, res);
1276     expect(MCHT_TODAYLINK, res);
1277 
1278     st_test.wDay = 1;
1279     st_test.wMonth = 1;
1280     st_test.wYear = 2005;
1281 
1282     res = SendMessageA(hwnd, MCM_SETTODAY, 0, (LPARAM)&st_test);
1283     expect(0, res);
1284 
1285     memset(&st_new, 0, sizeof(st_new));
1286     res = SendMessageA(hwnd, MCM_GETTODAY, 0, (LPARAM)&st_new);
1287     expect(1, res);
1288     expect(1, st_new.wDay);
1289     expect(1, st_new.wMonth);
1290     expect(2005, st_new.wYear);
1291 
1292     res = SendMessageA(hwnd, WM_LBUTTONDOWN, MK_LBUTTON, MAKELONG(mchit.pt.x, mchit.pt.y));
1293     expect(0, res);
1294 
1295     memset(&st_new, 0, sizeof(st_new));
1296     res = SendMessageA(hwnd, MCM_GETCURSEL, 0, (LPARAM)&st_new);
1297     expect(1, res);
1298     expect(1, st_new.wDay);
1299     expect(1, st_new.wMonth);
1300     expect(2005, st_new.wYear);
1301 
1302     ok_sequence(sequences, MONTHCAL_SEQ_INDEX, monthcal_todaylink_seq, "monthcal hit test", TRUE);
1303 
1304     DestroyWindow(hwnd);
1305 }
1306 
1307 static void test_today(void)
1308 {
1309     SYSTEMTIME st_test, st_new;
1310     int res;
1311     HWND hwnd;
1312 
1313     hwnd = create_monthcal_control(0);
1314 
1315     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1316 
1317     /* Setter and Getters for "today" information */
1318 
1319     /* check for overflow, should be ok */
1320     memset(&st_test, 0, sizeof(st_test));
1321     st_test.wDay = 38;
1322     st_test.wMonth = 38;
1323 
1324     st_new.wDay = 27;
1325     st_new.wMonth = 27;
1326 
1327     res = SendMessageA(hwnd, MCM_SETTODAY, 0, (LPARAM)&st_test);
1328     expect(0, res);
1329 
1330     res = SendMessageA(hwnd, MCM_GETTODAY, 0, (LPARAM)&st_new);
1331     expect(1, res);
1332 
1333     /* st_test should not change */
1334     expect(38, st_test.wDay);
1335     expect(38, st_test.wMonth);
1336 
1337     /* st_new should change, overflow does not matter */
1338     expect(38, st_new.wDay);
1339     expect(38, st_new.wMonth);
1340 
1341     /* check for zero, should be ok*/
1342     st_test.wDay = 0;
1343     st_test.wMonth = 0;
1344 
1345     res = SendMessageA(hwnd, MCM_SETTODAY, 0, (LPARAM)&st_test);
1346     expect(0, res);
1347 
1348     res = SendMessageA(hwnd, MCM_GETTODAY, 0, (LPARAM)&st_new);
1349     expect(1, res);
1350 
1351     /* st_test should not change */
1352     expect(0, st_test.wDay);
1353     expect(0, st_test.wMonth);
1354 
1355     /* st_new should change to zero*/
1356     expect(0, st_new.wDay);
1357     expect(0, st_new.wMonth);
1358 
1359     ok_sequence(sequences, MONTHCAL_SEQ_INDEX, monthcal_today_seq, "monthcal today", TRUE);
1360 
1361     DestroyWindow(hwnd);
1362 }
1363 
1364 static void test_scroll(void)
1365 {
1366     int res;
1367     HWND hwnd;
1368 
1369     hwnd = create_monthcal_control(0);
1370 
1371     res = SendMessageA(hwnd, MCM_GETMONTHDELTA, 0, 0);
1372     expect(2, res);
1373 
1374     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1375 
1376     /* Setter and Getters for scroll rate */
1377     res = SendMessageA(hwnd, MCM_SETMONTHDELTA, 2, 0);
1378     expect(0, res);
1379 
1380     res = SendMessageA(hwnd, MCM_SETMONTHDELTA, 3, 0);
1381     expect(2, res);
1382     res = SendMessageA(hwnd, MCM_GETMONTHDELTA, 0, 0);
1383     expect(3, res);
1384 
1385     res = SendMessageA(hwnd, MCM_SETMONTHDELTA, 12, 0);
1386     expect(3, res);
1387     res = SendMessageA(hwnd, MCM_GETMONTHDELTA, 0, 0);
1388     expect(12, res);
1389 
1390     res = SendMessageA(hwnd, MCM_SETMONTHDELTA, 15, 0);
1391     expect(12, res);
1392     res = SendMessageA(hwnd, MCM_GETMONTHDELTA, 0, 0);
1393     expect(15, res);
1394 
1395     res = SendMessageA(hwnd, MCM_SETMONTHDELTA, -5, 0);
1396     expect(15, res);
1397     res = SendMessageA(hwnd, MCM_GETMONTHDELTA, 0, 0);
1398     expect(-5, res);
1399 
1400     ok_sequence(sequences, MONTHCAL_SEQ_INDEX, monthcal_scroll_seq, "monthcal scroll", FALSE);
1401 
1402     DestroyWindow(hwnd);
1403 }
1404 
1405 static void test_monthrange(void)
1406 {
1407     int res;
1408     SYSTEMTIME st_visible[2], st_daystate[2], st;
1409     HWND hwnd;
1410     RECT r;
1411 
1412     hwnd = create_monthcal_control(0);
1413 
1414     memset(&st_visible, 0, sizeof(st_visible));
1415     memset(&st_daystate, 0, sizeof(st_daystate));
1416 
1417     st.wYear = 2000;
1418     st.wMonth = 11;
1419     st.wDay = 28;
1420     st.wHour = 11;
1421     st.wMinute = 59;
1422     st.wSecond = 30;
1423     st.wMilliseconds = 0;
1424     st.wDayOfWeek = 0;
1425 
1426     res = SendMessageA(hwnd, MCM_SETCURSEL, 0, (LPARAM)&st);
1427     expect(1,res);
1428 
1429     /* to be locale independent */
1430     SendMessageA(hwnd, MCM_SETFIRSTDAYOFWEEK, 0, (LPARAM)6);
1431 
1432     res = SendMessageA(hwnd, MCM_GETMINREQRECT, 0, (LPARAM)&r);
1433     expect(TRUE, res);
1434     /* resize control to display two Calendars */
1435     MoveWindow(hwnd, 0, 0, r.right, (5/2)*r.bottom, FALSE);
1436 
1437     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1438 
1439     res = SendMessageA(hwnd, MCM_GETMONTHRANGE, GMR_VISIBLE, (LPARAM)st_visible);
1440     expect(2, res);
1441     expect(2000, st_visible[0].wYear);
1442     expect(11, st_visible[0].wMonth);
1443     expect(1, st_visible[0].wDay);
1444     expect(2000, st_visible[1].wYear);
1445     expect(12, st_visible[1].wMonth);
1446     expect(31, st_visible[1].wDay);
1447 
1448     res = SendMessageA(hwnd, MCM_GETMONTHRANGE, GMR_DAYSTATE, (LPARAM)st_daystate);
1449     expect(4, res);
1450     expect(2000, st_daystate[0].wYear);
1451     expect(10, st_daystate[0].wMonth);
1452     expect(29, st_daystate[0].wDay);
1453     expect(2001, st_daystate[1].wYear);
1454     expect(1, st_daystate[1].wMonth);
1455     expect(6, st_daystate[1].wDay);
1456 
1457     ok_sequence(sequences, MONTHCAL_SEQ_INDEX, monthcal_monthrange_seq, "monthcal monthrange", FALSE);
1458 
1459     /* with null date array parameter */
1460     res = SendMessageA(hwnd, MCM_GETMONTHRANGE, GMR_VISIBLE, 0);
1461     expect(2, res);
1462 
1463     res = SendMessageA(hwnd, MCM_GETMONTHRANGE, GMR_DAYSTATE, 0);
1464     expect(4, res);
1465 
1466     /* resize control to display single Calendar */
1467     MoveWindow(hwnd, 0, 0, r.right, r.bottom, FALSE);
1468 
1469     memset(&st, 0, sizeof(st));
1470     st.wMonth = 9;
1471     st.wYear  = 1752;
1472     st.wDay   = 14;
1473 
1474     res = SendMessageA(hwnd, MCM_SETCURSEL, 0, (LPARAM)&st);
1475     expect(1, res);
1476 
1477     /* September 1752 has 19 days */
1478     res = SendMessageA(hwnd, MCM_GETMONTHRANGE, GMR_VISIBLE, (LPARAM)st_visible);
1479     expect(1, res);
1480 
1481     expect(1752, st_visible[0].wYear);
1482     expect(9, st_visible[0].wMonth);
1483     ok(14 == st_visible[0].wDay ||
1484        broken(1 == st_visible[0].wDay), /* comctl32 <= 4.72 */
1485        "Expected 14, got %d\n", st_visible[0].wDay);
1486 
1487     expect(1752, st_visible[1].wYear);
1488     expect(9, st_visible[1].wMonth);
1489     expect(19, st_visible[1].wDay);
1490 
1491     DestroyWindow(hwnd);
1492 }
1493 
1494 static void test_maxselday(void)
1495 {
1496     int res;
1497     HWND hwnd;
1498     DWORD style;
1499 
1500     hwnd = create_monthcal_control(0);
1501     /* if no style specified default to 1 */
1502     res = SendMessageA(hwnd, MCM_GETMAXSELCOUNT, 0, 0);
1503     expect(1, res);
1504     res = SendMessageA(hwnd, MCM_SETMAXSELCOUNT, 5, 0);
1505     expect(0, res);
1506     res = SendMessageA(hwnd, MCM_GETMAXSELCOUNT, 0, 0);
1507     expect(1, res);
1508 
1509     /* try to set style */
1510     style = GetWindowLongA(hwnd, GWL_STYLE);
1511     SetWindowLongA(hwnd, GWL_STYLE, style | MCS_MULTISELECT);
1512     style = GetWindowLongA(hwnd, GWL_STYLE);
1513     ok(!(style & MCS_MULTISELECT), "Expected MCS_MULTISELECT not to be set\n");
1514     DestroyWindow(hwnd);
1515 
1516     hwnd = create_monthcal_control(MCS_MULTISELECT);
1517     /* try to remove style */
1518     style = GetWindowLongA(hwnd, GWL_STYLE);
1519     SetWindowLongA(hwnd, GWL_STYLE, style & ~MCS_MULTISELECT);
1520     style = GetWindowLongA(hwnd, GWL_STYLE);
1521     ok(style & MCS_MULTISELECT, "Expected MCS_MULTISELECT to be set\n");
1522     DestroyWindow(hwnd);
1523 
1524     hwnd = create_monthcal_control(MCS_MULTISELECT);
1525 
1526     /* default width is a week */
1527     res = SendMessageA(hwnd, MCM_GETMAXSELCOUNT, 0, 0);
1528     expect(7, res);
1529 
1530     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1531 
1532     /* Setter and Getters for max selected days */
1533     res = SendMessageA(hwnd, MCM_SETMAXSELCOUNT, 5, 0);
1534     expect(1, res);
1535     res = SendMessageA(hwnd, MCM_GETMAXSELCOUNT, 0, 0);
1536     expect(5, res);
1537 
1538     res = SendMessageA(hwnd, MCM_SETMAXSELCOUNT, 15, 0);
1539     expect(1, res);
1540     res = SendMessageA(hwnd, MCM_GETMAXSELCOUNT, 0, 0);
1541     expect(15, res);
1542 
1543     /* test invalid value */
1544     res = SendMessageA(hwnd, MCM_SETMAXSELCOUNT, -1, 0);
1545     expect(0, res);
1546     res = SendMessageA(hwnd, MCM_GETMAXSELCOUNT, 0, 0);
1547     expect(15, res);
1548 
1549     ok_sequence(sequences, MONTHCAL_SEQ_INDEX, monthcal_max_sel_day_seq, "monthcal MaxSelDay", FALSE);
1550 
1551     /* zero value is invalid too */
1552     res = SendMessageA(hwnd, MCM_SETMAXSELCOUNT, 0, 0);
1553     expect(0, res);
1554     res = SendMessageA(hwnd, MCM_GETMAXSELCOUNT, 0, 0);
1555     expect(15, res);
1556 
1557     DestroyWindow(hwnd);
1558 }
1559 
1560 static void test_size(void)
1561 {
1562     int res;
1563     RECT r1, r2;
1564     HFONT hFont1, hFont2;
1565     LOGFONTA logfont;
1566     HWND hwnd;
1567 
1568     hwnd = create_monthcal_control(0);
1569 
1570     lstrcpyA(logfont.lfFaceName, "Arial");
1571     memset(&logfont, 0, sizeof(logfont));
1572     logfont.lfHeight = 12;
1573     hFont1 = CreateFontIndirectA(&logfont);
1574 
1575     logfont.lfHeight = 24;
1576     hFont2 = CreateFontIndirectA(&logfont);
1577 
1578     /* initialize to a font we can compare against */
1579     SendMessageA(hwnd, WM_SETFONT, (WPARAM)hFont1, 0);
1580     res = SendMessageA(hwnd, MCM_GETMINREQRECT, 0, (LPARAM)&r1);
1581     ok(res, "SendMessageA(MCM_GETMINREQRECT) failed\n");
1582 
1583     /* check that setting a larger font results in an larger rect */
1584     SendMessageA(hwnd, WM_SETFONT, (WPARAM)hFont2, 0);
1585     res = SendMessageA(hwnd, MCM_GETMINREQRECT, 0, (LPARAM)&r2);
1586     ok(res, "SendMessageA(MCM_GETMINREQRECT) failed\n");
1587 
1588     OffsetRect(&r1, -r1.left, -r1.top);
1589     OffsetRect(&r2, -r2.left, -r2.top);
1590 
1591     ok(r1.bottom < r2.bottom, "Failed to get larger rect with larger font\n");
1592 
1593     DestroyWindow(hwnd);
1594 }
1595 
1596 static void test_create(void)
1597 {
1598     HWND hwnd;
1599 
1600     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1601 
1602     hwnd = create_monthcal_control(0);
1603     ok_sequence(sequences, PARENT_SEQ_INDEX, create_monthcal_control_seq, "create monthcal control", TRUE);
1604 
1605     DestroyWindow(hwnd);
1606 
1607     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1608     hwnd = create_monthcal_control(MCS_MULTISELECT);
1609     ok_sequence(sequences, PARENT_SEQ_INDEX, create_monthcal_multi_sel_style_seq, "create monthcal (multi sel style)", TRUE);
1610     DestroyWindow(hwnd);
1611 }
1612 
1613 static void test_destroy(void)
1614 {
1615     HWND hwnd;
1616 
1617     hwnd = create_monthcal_control(0);
1618     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1619     DestroyWindow(hwnd);
1620     ok_sequence(sequences, PARENT_SEQ_INDEX, destroy_monthcal_parent_msgs_seq, "Destroy monthcal (parent msg)", FALSE);
1621     ok_sequence(sequences, MONTHCAL_SEQ_INDEX, destroy_monthcal_child_msgs_seq, "Destroy monthcal (child msg)", FALSE);
1622 
1623     /* MCS_MULTISELECT */
1624     hwnd = create_monthcal_control(MCS_MULTISELECT);
1625     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1626     DestroyWindow(hwnd);
1627     ok_sequence(sequences, MONTHCAL_SEQ_INDEX, destroy_monthcal_multi_sel_style_seq, "Destroy monthcal (multi sel style)", FALSE);
1628 }
1629 
1630 static void test_selrange(void)
1631 {
1632     HWND hwnd;
1633     SYSTEMTIME st, range[2], range2[2];
1634     BOOL ret, old_comctl32 = FALSE;
1635 
1636     hwnd = create_monthcal_control(MCS_MULTISELECT);
1637 
1638     /* just after creation selection should start and end today */
1639     ret = SendMessageA(hwnd, MCM_GETTODAY, 0, (LPARAM)&st);
1640     expect(TRUE, ret);
1641 
1642     memset(range, 0xcc, sizeof(range));
1643     ret = SendMessageA(hwnd, MCM_GETSELRANGE, 0, (LPARAM)range);
1644     expect(TRUE, ret);
1645     expect(st.wYear,      range[0].wYear);
1646     expect(st.wMonth,     range[0].wMonth);
1647     expect(st.wDay,       range[0].wDay);
1648     if (range[0].wDayOfWeek != st.wDayOfWeek)
1649     {
1650         win_skip("comctl32 <= 4.70 doesn't set some values\n");
1651         old_comctl32 = TRUE;
1652     }
1653     else
1654     {
1655         expect(st.wDayOfWeek, range[0].wDayOfWeek);
1656         expect(st.wHour,      range[0].wHour);
1657         expect(st.wMinute,    range[0].wMinute);
1658         expect(st.wSecond,    range[0].wSecond);
1659         expect(st.wMilliseconds, range[0].wMilliseconds);
1660     }
1661 
1662     expect(st.wYear,      range[1].wYear);
1663     expect(st.wMonth,     range[1].wMonth);
1664     expect(st.wDay,       range[1].wDay);
1665     if (!old_comctl32)
1666     {
1667         expect(st.wDayOfWeek, range[1].wDayOfWeek);
1668         expect(st.wHour,      range[1].wHour);
1669         expect(st.wMinute,    range[1].wMinute);
1670         expect(st.wSecond,    range[1].wSecond);
1671         expect(st.wMilliseconds, range[1].wMilliseconds);
1672     }
1673 
1674     /* bounds are swapped if min > max */
1675     memset(&range[0], 0, sizeof(range[0]));
1676     range[0].wYear  = 2009;
1677     range[0].wMonth = 10;
1678     range[0].wDay   = 5;
1679     range[1] = range[0];
1680     range[1].wDay   = 3;
1681 
1682     ret = SendMessageA(hwnd, MCM_SETSELRANGE, 0, (LPARAM)range);
1683     expect(TRUE, ret);
1684 
1685     ret = SendMessageA(hwnd, MCM_GETSELRANGE, 0, (LPARAM)range2);
1686     expect(TRUE, ret);
1687 
1688     expect(range[1].wYear,      range2[0].wYear);
1689     expect(range[1].wMonth,     range2[0].wMonth);
1690     expect(range[1].wDay,       range2[0].wDay);
1691     expect(6, range2[0].wDayOfWeek);
1692     expect(range[1].wHour,      range2[0].wHour);
1693     expect(range[1].wMinute,    range2[0].wMinute);
1694     expect(range[1].wSecond,    range2[0].wSecond);
1695     expect(range[1].wMilliseconds, range2[0].wMilliseconds);
1696 
1697     expect(range[0].wYear,      range2[1].wYear);
1698     expect(range[0].wMonth,     range2[1].wMonth);
1699     expect(range[0].wDay,       range2[1].wDay);
1700     expect(1, range2[1].wDayOfWeek);
1701     expect(range[0].wHour,      range2[1].wHour);
1702     expect(range[0].wMinute,    range2[1].wMinute);
1703     expect(range[0].wSecond,    range2[1].wSecond);
1704     expect(range[0].wMilliseconds, range2[1].wMilliseconds);
1705 
1706     /* try with range larger than maximum configured */
1707     memset(&range[0], 0, sizeof(range[0]));
1708     range[0].wYear  = 2009;
1709     range[0].wMonth = 10;
1710     range[0].wDay   = 1;
1711     range[1] = range[0];
1712 
1713     ret = SendMessageA(hwnd, MCM_SETSELRANGE, 0, (LPARAM)range);
1714     expect(TRUE, ret);
1715 
1716     range[1] = range[0];
1717     /* default max. range is 7 days */
1718     range[1].wDay = 8;
1719 
1720     ret = SendMessageA(hwnd, MCM_SETSELRANGE, 0, (LPARAM)range);
1721     expect(FALSE, ret);
1722 
1723     ret = SendMessageA(hwnd, MCM_GETSELRANGE, 0, (LPARAM)range2);
1724     expect(TRUE, ret);
1725 
1726     expect(range[0].wYear,  range2[0].wYear);
1727     expect(range[0].wMonth, range2[0].wMonth);
1728     expect(range[0].wDay,   range2[0].wDay);
1729     expect(range[0].wYear,  range2[1].wYear);
1730     expect(range[0].wMonth, range2[1].wMonth);
1731     expect(range[0].wDay,   range2[1].wDay);
1732 
1733     DestroyWindow(hwnd);
1734 }
1735 
1736 static void test_killfocus(void)
1737 {
1738     HWND hwnd;
1739     DWORD style;
1740 
1741     hwnd = create_monthcal_control(0);
1742 
1743     /* make parent invisible */
1744     style = GetWindowLongA(parent_wnd, GWL_STYLE);
1745     SetWindowLongA(parent_wnd, GWL_STYLE, style & ~WS_VISIBLE);
1746 
1747     SendMessageA(hwnd, WM_KILLFOCUS, (WPARAM)GetDesktopWindow(), 0);
1748 
1749     style = GetWindowLongA(hwnd, GWL_STYLE);
1750     ok(style & WS_VISIBLE, "Expected WS_VISIBLE to be set\n");
1751 
1752     style = GetWindowLongA(parent_wnd, GWL_STYLE);
1753     SetWindowLongA(parent_wnd, GWL_STYLE, style | WS_VISIBLE);
1754 
1755     DestroyWindow(hwnd);
1756 }
1757 
1758 static void test_hittest_v6(void)
1759 {
1760     MCHITTESTINFO mchit;
1761     DWORD ret;
1762     HWND hwnd;
1763     RECT r;
1764 
1765     hwnd = create_monthcal_control(0);
1766     SendMessageA(hwnd, MCM_SETCALENDARBORDER, TRUE, 0);
1767 
1768     SendMessageA(hwnd, MCM_GETMINREQRECT, 0, (LPARAM)&r);
1769     /* reserving some area around calendar */
1770     MoveWindow(hwnd, 0, 0, r.right * 3 / 2, r.bottom * 3 / 2, FALSE);
1771     mchit.cbSize = sizeof(MCHITTESTINFO);
1772     mchit.pt.x = mchit.pt.y = 0;
1773     mchit.iOffset = -1;
1774     mchit.iRow = -1;
1775     mchit.iCol = -1;
1776     ret = SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit);
1777     if (ret == ~0u)
1778     {
1779         win_skip("Only MCHITTESTINFO_V1 supported\n");
1780         DestroyWindow(hwnd);
1781         return;
1782     }
1783     todo_wine expect_hex(MCHT_NOWHERE, ret);
1784     expect(-1, mchit.iOffset);
1785     expect(-1, mchit.iRow);
1786     expect(-1, mchit.iCol);
1787 
1788     MoveWindow(hwnd, 0, 0, r.right, r.bottom, FALSE);
1789     mchit.pt.x = r.right / 2;
1790     mchit.pt.y = r.bottom / 2;
1791     mchit.iOffset = -1;
1792     ret = SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit);
1793     expect_hex(MCHT_CALENDARDATE, ret);
1794     expect(0, mchit.iOffset);
1795 
1796     /* over day area */
1797     mchit.pt.x = r.right / (7*2);
1798     mchit.pt.y = r.bottom / 2;
1799     mchit.iOffset = -1;
1800     mchit.iCol = mchit.iRow = -1;
1801     mchit.uHit = 0;
1802     mchit.rc.left = mchit.rc.right = mchit.rc.top = mchit.rc.bottom = -1;
1803     ret = SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit);
1804     expect_hex(MCHT_CALENDARDATE, ret);
1805     expect_hex(MCHT_CALENDARDATE, mchit.uHit);
1806     expect(0, mchit.iOffset);
1807     expect(2, mchit.iRow);
1808     expect(0, mchit.iCol);
1809     /* returned a one day rectangle */
1810     expect_d(r.right / 7, mchit.rc.right - mchit.rc.left);
1811     expect_d(r.bottom / 10, mchit.rc.bottom - mchit.rc.top);
1812 
1813     /* title */
1814     mchit.pt.x = 1;
1815     mchit.pt.y = 1;
1816     mchit.iOffset = -1;
1817     mchit.iCol = mchit.iRow = -1;
1818     mchit.uHit = 0;
1819     mchit.rc.left = mchit.rc.right = mchit.rc.top = mchit.rc.bottom = -1;
1820     ret = SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit);
1821     expect_hex(MCHT_TITLE, ret);
1822     expect_hex(MCHT_TITLE, mchit.uHit);
1823     expect(0, mchit.iOffset);
1824     expect(-1, mchit.iRow);
1825     expect(-1, mchit.iCol);
1826     expect(0, mchit.rc.left);
1827     expect(0, mchit.rc.top);
1828     expect_d(r.right, mchit.rc.right);
1829     ok(mchit.rc.bottom > 0, "got %d\n", mchit.rc.bottom);
1830 
1831     /* between two calendars */
1832     MoveWindow(hwnd, 0, 0, r.right * 5/2, r.bottom, FALSE);
1833     mchit.pt.x = r.right / (5*4);
1834     mchit.pt.y = r.bottom / 2;
1835     mchit.iOffset = -2;
1836     mchit.iCol = mchit.iRow = -2;
1837     mchit.uHit = ~0;
1838     mchit.rc.left = mchit.rc.right = mchit.rc.top = mchit.rc.bottom = -1;
1839     ret = SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit);
1840     todo_wine expect_hex(MCHT_NOWHERE, ret);
1841     todo_wine expect_hex(MCHT_NOWHERE, mchit.uHit);
1842     expect(-2, mchit.iOffset);
1843     expect(-2, mchit.iRow);
1844     expect(-2, mchit.iCol);
1845     todo_wine expect(0, mchit.rc.left);
1846     todo_wine expect(0, mchit.rc.top);
1847     todo_wine expect_d(r.right * 5/2, mchit.rc.right);
1848     todo_wine expect_d(r.bottom, mchit.rc.bottom);
1849 
1850     DestroyWindow(hwnd);
1851 }
1852 
1853 static void test_get_set_border(void)
1854 {
1855     HWND hwnd;
1856     DWORD ret;
1857 
1858     hwnd = create_monthcal_control(0);
1859 
1860     /* a non-default value */
1861     ret = SendMessageA(hwnd, MCM_SETCALENDARBORDER, TRUE, 10);
1862     expect(0, ret);
1863 
1864     ret = SendMessageA(hwnd, MCM_GETCALENDARBORDER, 0, 0);
1865 
1866     if (ret != 10)
1867     {
1868         skip("MCM_GET/SETCALENDARBORDER not supported\n");
1869         DestroyWindow(hwnd);
1870         return;
1871     }
1872 
1873     expect(10, ret);
1874 
1875     DestroyWindow(hwnd);
1876 }
1877 
1878 static void test_MCM_SIZERECTTOMIN(void)
1879 {
1880     HWND hwnd;
1881     DWORD ret;
1882     RECT r, r2;
1883 
1884     hwnd = create_monthcal_control(0);
1885 
1886     ret = SendMessageA(hwnd, MCM_GETMINREQRECT, 0, (LPARAM)&r2);
1887     if (ret == 0)
1888     {
1889         win_skip("Message MCM_GETMINREQRECT unsupported. Skipping.\n");
1890         DestroyWindow(hwnd);
1891         return;
1892     }
1893 
1894     ret = SendMessageA(hwnd, MCM_SIZERECTTOMIN, 0, 0);
1895     ok(ret == 0, "got %d\n", ret);
1896 
1897     SetRectEmpty(&r);
1898     ret = SendMessageA(hwnd, MCM_SIZERECTTOMIN, 0, (LPARAM)&r);
1899     if (ret == 0)
1900     {
1901         skip("Message MCM_SIZERECTTOMIN unsupported. Skipping.\n");
1902         DestroyWindow(hwnd);
1903         return;
1904     }
1905     ok(ret == 1, "got %d\n", ret);
1906     ok(r.left == 0 && r.right > 0, "got %d, %d\n", r.left, r.right);
1907 
1908     r = r2;
1909     ret = SendMessageA(hwnd, MCM_SIZERECTTOMIN, 0, (LPARAM)&r);
1910     ok(ret == 1, "got %d\n", ret);
1911 
1912     r2.right = (r2.right - r2.left) * 3;
1913     r2.bottom = (r2.bottom - r2.top) * 3;
1914     r2.left = r2.top = 0;
1915     ret = SendMessageA(hwnd, MCM_SIZERECTTOMIN, 0, (LPARAM)&r2);
1916     ok(ret == 1, "got %d\n", ret);
1917 
1918     DestroyWindow(hwnd);
1919 }
1920 
1921 static void test_MCM_GETCALENDARCOUNT(void)
1922 {
1923     HWND hwnd;
1924     DWORD ret;
1925 
1926     hwnd = create_monthcal_control(0);
1927 
1928     ret = SendMessageA(hwnd, MCM_GETCALENDARCOUNT, 0, 0);
1929     if (ret == 0)
1930     {
1931         win_skip("Message MCM_GETCALENDARCOUNT unsupported. Skipping.\n");
1932         DestroyWindow(hwnd);
1933         return;
1934     }
1935 
1936     expect(2, ret);
1937 
1938     DestroyWindow(hwnd);
1939 }
1940 
1941 static void test_daystate(void)
1942 {
1943     MONTHDAYSTATE state[4];
1944     DWORD ret, style;
1945     HWND hwnd;
1946     RECT r;
1947 
1948     /* without MCS_DAYSTATE */
1949     hwnd = create_monthcal_control(0);
1950 
1951     ret = SendMessageA(hwnd, MCM_GETMINREQRECT, 0, (LPARAM)&r);
1952     expect(TRUE, ret);
1953 
1954     /* resize control to display two Calendars */
1955     MoveWindow(hwnd, 0, 0, r.right, (5/2)*r.bottom, FALSE);
1956 
1957     ret = SendMessageA(hwnd, MCM_GETMONTHRANGE, GMR_DAYSTATE, 0);
1958     expect(4, ret);
1959 
1960     ret = SendMessageA(hwnd, MCM_SETDAYSTATE, 4, (LPARAM)&state);
1961     expect(0, ret);
1962 
1963     ret = SendMessageA(hwnd, MCM_SETDAYSTATE, 2, (LPARAM)&state);
1964     expect(0, ret);
1965 
1966     ret = SendMessageA(hwnd, MCM_SETDAYSTATE, 0, 0);
1967     expect(0, ret);
1968 
1969     /* try to switch on */
1970     SetWindowLongA(hwnd, GWL_STYLE, GetWindowLongA(hwnd, GWL_STYLE) | MCS_DAYSTATE);
1971     style = GetWindowLongA(hwnd, GWL_STYLE);
1972     ok((style & MCS_DAYSTATE) == 0, "got 0x%08x\n", style);
1973 
1974     DestroyWindow(hwnd);
1975 
1976     /* with MCS_DAYSTATE */
1977     hwnd = create_monthcal_control(MCS_DAYSTATE);
1978 
1979     ret = SendMessageA(hwnd, MCM_GETMONTHRANGE, GMR_DAYSTATE, 0);
1980     expect(4, ret);
1981 
1982     ret = SendMessageA(hwnd, MCM_SETDAYSTATE, 4, (LPARAM)&state);
1983     expect(1, ret);
1984 
1985     ret = SendMessageA(hwnd, MCM_SETDAYSTATE, 2, (LPARAM)&state);
1986     expect(0, ret);
1987 
1988     ret = SendMessageA(hwnd, MCM_SETDAYSTATE, 0, 0);
1989     expect(0, ret);
1990 
1991     /* try to switch off */
1992     SetWindowLongA(hwnd, GWL_STYLE, GetWindowLongA(hwnd, GWL_STYLE) & ~MCS_DAYSTATE);
1993     style = GetWindowLongA(hwnd, GWL_STYLE);
1994     ok((style & MCS_DAYSTATE) == MCS_DAYSTATE, "got 0x%08x\n", style);
1995 
1996     DestroyWindow(hwnd);
1997 }
1998 
1999 static void test_sel_notify(void)
2000 {
2001     typedef struct
2002     {
2003         DWORD       val;
2004         const char* name;
2005     } Monthcal_style;
2006 
2007     HWND hwnd;
2008     RECT rc;
2009     MCHITTESTINFO mchit = {sizeof(MCHITTESTINFO)};
2010     SYSTEMTIME st;
2011     Monthcal_style styles[] = {
2012         {MCS_NOTODAY,                    "MCS_NOTODAY"},
2013         {MCS_NOTODAY | MCS_MULTISELECT,  "MCS_NOTODAY | MCS_MULTISELECT"},
2014         {MCS_DAYSTATE,                   "MCS_DAYSTATE"},
2015         {MCS_DAYSTATE | MCS_MULTISELECT, "MCS_DAYSTATE | MCS_MULTISELECT"}
2016     };
2017     int i;
2018 
2019     for(i = 0; i < sizeof styles / sizeof styles[0]; i++)
2020     {
2021         hwnd = create_monthcal_control(styles[i].val);
2022         SetWindowLongPtrA(hwnd, GWLP_ID, SEL_NOTIFY_TEST_ID);
2023         SendMessageA(hwnd, MCM_GETMINREQRECT, 0, (LPARAM)&rc);
2024         MoveWindow(hwnd, 0, 0, rc.right, rc.bottom, FALSE);
2025         /* Simulate mouse click on some unselected day to generate
2026             MCN_SELECT and MCN_SELCHANGE notifications */
2027         mchit.pt.x = rc.right / 2;
2028         mchit.pt.y = rc.bottom / 2;
2029         SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit);
2030         SendMessageA(hwnd, MCM_GETCURSEL, 0, (LPARAM)&st);
2031         while(st.wDay == mchit.st.wDay) /* Ensure that mchit.pt points to unselected day */
2032         {
2033             mchit.pt.y++;
2034             SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit);
2035         }
2036         SendMessageA(hwnd, WM_LBUTTONDOWN, 0, MAKELPARAM(mchit.pt.x, mchit.pt.y));
2037         SendMessageA(hwnd, WM_LBUTTONUP, 0, MAKELPARAM(mchit.pt.x, mchit.pt.y));
2038         DestroyWindow(hwnd);
2039     }
2040 }
2041 
2042 static void init_functions(void)
2043 {
2044     HMODULE hComCtl32 = LoadLibraryA("comctl32.dll");
2045 
2046 #define X(f) p##f = (void*)GetProcAddress(hComCtl32, #f);
2047     X(InitCommonControlsEx);
2048 #undef X
2049 }
2050 
2051 START_TEST(monthcal)
2052 {
2053     INITCOMMONCONTROLSEX iccex;
2054     ULONG_PTR ctx_cookie;
2055     HANDLE hCtx;
2056 
2057     init_functions();
2058 
2059     iccex.dwSize = sizeof(iccex);
2060     iccex.dwICC  = ICC_DATE_CLASSES;
2061     pInitCommonControlsEx(&iccex);
2062 
2063     test_monthcal();
2064 
2065     init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
2066 
2067     parent_wnd = create_parent_window();
2068 
2069     test_create();
2070     test_destroy();
2071     test_color();
2072     test_currdate();
2073     test_firstDay();
2074     test_unicode();
2075     test_today();
2076     test_scroll();
2077     test_monthrange();
2078     test_hittest();
2079     test_todaylink();
2080     test_size();
2081     test_maxselday();
2082     test_selrange();
2083     test_killfocus();
2084     test_daystate();
2085     test_sel_notify();
2086 
2087     if (!load_v6_module(&ctx_cookie, &hCtx))
2088     {
2089         DestroyWindow(parent_wnd);
2090         return;
2091     }
2092 
2093     test_hittest_v6();
2094     test_get_set_border();
2095     test_MCM_SIZERECTTOMIN();
2096     test_MCM_GETCALENDARCOUNT();
2097 
2098     unload_v6_module(ctx_cookie, hCtx);
2099 
2100     DestroyWindow(parent_wnd);
2101 }
2102