oleaut32: Implement ITypeLibComp::BindType.
[wine] / dlls / comctl32 / tests / datetime.c
1 /* Unit test suite for datetime control.
2 *
3 * Copyright 2007 Kanit Therdsteerasukdi
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 */
19
20 #include <windows.h>
21 #include <commctrl.h>
22
23 #include "wine/test.h"
24 #include "msg.h"
25
26 #define expect(EXPECTED, GOT) ok((GOT)==(EXPECTED), "Expected %d, got %ld\n", (EXPECTED), (GOT))
27
28 #define expect_unsuccess(EXPECTED, GOT) ok((GOT)==(EXPECTED), "Expected %d(unsuccessful), got %ld(successful)\n", (EXPECTED), (GOT))
29
30 #define NUM_MSG_SEQUENCES   1
31 #define DATETIME_SEQ_INDEX    0
32
33 static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
34
35 static const struct message test_dtm_set_format_seq[] = {
36     { DTM_SETFORMATA, sent|wparam|lparam, 0x00000000, 0x00000000 },
37     { DTM_SETFORMATA, sent|wparam, 0x00000000 },
38     { 0 }
39 };
40
41 static const struct message test_dtm_set_and_get_mccolor_seq[] = {
42     { DTM_SETMCCOLOR, sent|wparam|lparam, 0x00000000, 0x00000000 },
43     { DTM_SETMCCOLOR, sent|wparam|lparam, 0x00000000, 0x00ffffff },
44     { DTM_SETMCCOLOR, sent|wparam|lparam, 0x00000000, 0x00dcb464 },
45     { DTM_GETMCCOLOR, sent|wparam|lparam, 0x00000000, 0x00000000 },
46     { DTM_SETMCCOLOR, sent|wparam|lparam, 0x00000004, 0x00000000 },
47     { DTM_SETMCCOLOR, sent|wparam|lparam, 0x00000004, 0x00ffffff },
48     { DTM_SETMCCOLOR, sent|wparam|lparam, 0x00000004, 0x00dcb464 },
49     { DTM_GETMCCOLOR, sent|wparam|lparam, 0x00000004, 0x00000000 },
50     { DTM_SETMCCOLOR, sent|wparam|lparam, 0x00000001, 0x00000000 },
51     { DTM_SETMCCOLOR, sent|wparam|lparam, 0x00000001, 0x00ffffff },
52     { DTM_SETMCCOLOR, sent|wparam|lparam, 0x00000001, 0x00dcb464 },
53     { DTM_GETMCCOLOR, sent|wparam|lparam, 0x00000001, 0x00000000 },
54     { DTM_SETMCCOLOR, sent|wparam|lparam, 0x00000002, 0x00000000 },
55     { DTM_SETMCCOLOR, sent|wparam|lparam, 0x00000002, 0x00ffffff },
56     { DTM_SETMCCOLOR, sent|wparam|lparam, 0x00000002, 0x00dcb464 },
57     { DTM_GETMCCOLOR, sent|wparam|lparam, 0x00000002, 0x00000000 },
58     { DTM_SETMCCOLOR, sent|wparam|lparam, 0x00000003, 0x00000000 },
59     { DTM_SETMCCOLOR, sent|wparam|lparam, 0x00000003, 0x00ffffff },
60     { DTM_SETMCCOLOR, sent|wparam|lparam, 0x00000003, 0x00dcb464 },
61     { DTM_GETMCCOLOR, sent|wparam|lparam, 0x00000003, 0x00000000 },
62     { DTM_SETMCCOLOR, sent|wparam|lparam, 0x00000005, 0x00000000 },
63     { DTM_SETMCCOLOR, sent|wparam|lparam, 0x00000005, 0x00ffffff },
64     { DTM_SETMCCOLOR, sent|wparam|lparam, 0x00000005, 0x00dcb464 },
65     { DTM_GETMCCOLOR, sent|wparam|lparam, 0x00000005, 0x00000000 },
66     { 0 }
67 };
68
69 static const struct message test_dtm_set_and_get_mcfont_seq[] = {
70     { DTM_SETMCFONT, sent|lparam, 0, 0x00000001 },
71     { DTM_GETMCFONT, sent|wparam|lparam, 0x00000000, 0x00000000 },
72     { 0 }
73 };
74
75 static const struct message test_dtm_get_monthcal_seq[] = {
76     { DTM_GETMONTHCAL, sent|wparam|lparam, 0x00000000, 0x00000000 },
77     { 0 }
78 };
79
80 static const struct message test_dtm_set_and_get_range_seq[] = {
81     { DTM_SETRANGE, sent|wparam, 0x00000001 },
82     { DTM_GETRANGE, sent|wparam, 0x00000000 },
83     { DTM_SETRANGE, sent|wparam, 0x00000002 },
84     { DTM_SETRANGE, sent|wparam, 0x00000002 },
85     { DTM_GETRANGE, sent|wparam, 0x00000000},
86     { DTM_SETRANGE, sent|wparam, 0x00000001 },
87     { DTM_SETRANGE, sent|wparam, 0x00000003 },
88     { DTM_SETRANGE, sent|wparam, 0x00000003 },
89     { DTM_GETRANGE, sent|wparam, 0x00000000 },
90     { DTM_SETRANGE, sent|wparam, 0x00000003 },
91     { DTM_GETRANGE, sent|wparam, 0x00000000 },
92     { DTM_SETRANGE, sent|wparam, 0x00000003 },
93     { DTM_GETRANGE, sent|wparam, 0x00000000 },
94     { 0 }
95 };
96
97 static const struct message test_dtm_set_range_swap_min_max_seq[] = {
98     { DTM_SETSYSTEMTIME, sent|wparam, 0x00000000 },
99     { DTM_GETSYSTEMTIME, sent|wparam, 0x00000000 },
100     { DTM_SETRANGE, sent|wparam, 0x00000003 },
101     { DTM_GETRANGE, sent|wparam, 0x00000000 },
102     { DTM_SETSYSTEMTIME, sent|wparam, 0x00000000 },
103     { DTM_GETSYSTEMTIME, sent|wparam, 0x00000000 },
104     { DTM_SETRANGE, sent|wparam, 0x00000003 },
105     { DTM_GETRANGE, sent|wparam, 0x00000000 },
106     { DTM_SETRANGE, sent|wparam, 0x00000003 },
107     { DTM_GETRANGE, sent|wparam, 0x00000000 },
108     { DTM_SETRANGE, sent|wparam, 0x00000003 },
109     { DTM_GETRANGE, sent|wparam, 0x00000000 },
110     { 0 }
111 };
112
113 static const struct message test_dtm_set_and_get_system_time_seq[] = {
114     { DTM_SETSYSTEMTIME, sent|wparam, 0x00000001 },
115     { 0x0090, sent|optional }, /* Vista */
116     { WM_DESTROY, sent|wparam|lparam, 0x00000000, 0x00000000 },
117     { WM_NCDESTROY, sent|wparam|lparam, 0x00000000, 0x00000000 },
118     { DTM_SETSYSTEMTIME, sent|wparam, 0x00000001 },
119     { DTM_GETSYSTEMTIME, sent|wparam, 0x00000000 },
120     { DTM_SETSYSTEMTIME, sent|wparam, 0x00000000 },
121     { DTM_SETSYSTEMTIME, sent|wparam, 0x00000000 },
122     { DTM_SETSYSTEMTIME, sent|wparam, 0x00000000 },
123     { DTM_GETSYSTEMTIME, sent|wparam, 0x00000000 },
124     { DTM_SETSYSTEMTIME, sent|wparam, 0x00000000 },
125     { 0 }
126 };
127
128 static const struct message destroy_window_seq[] = {
129     { 0x0090, sent|optional }, /* Vista */
130     { WM_DESTROY, sent|wparam|lparam, 0x00000000, 0x00000000 },
131     { WM_NCDESTROY, sent|wparam|lparam, 0x00000000, 0x00000000 },
132     { 0 }
133 };
134
135 struct subclass_info
136 {
137     WNDPROC oldproc;
138 };
139
140 static LRESULT WINAPI datetime_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
141 {
142     struct subclass_info *info = (struct subclass_info *)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
143     static LONG defwndproc_counter = 0;
144     LRESULT ret;
145     struct message msg;
146
147     trace("datetime: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
148
149     msg.message = message;
150     msg.flags = sent|wparam|lparam;
151     if (defwndproc_counter) msg.flags |= defwinproc;
152     msg.wParam = wParam;
153     msg.lParam = lParam;
154     add_message(sequences, DATETIME_SEQ_INDEX, &msg);
155
156     defwndproc_counter++;
157     ret = CallWindowProcA(info->oldproc, hwnd, message, wParam, lParam);
158     defwndproc_counter--;
159
160     return ret;
161 }
162
163 static HWND create_datetime_control(DWORD style, DWORD exstyle)
164 {
165     struct subclass_info *info;
166     HWND hWndDateTime = NULL;
167
168     info = HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info));
169     if (!info)
170         return NULL;
171
172     hWndDateTime = CreateWindowEx(0,
173         DATETIMEPICK_CLASS,
174         NULL,
175         style,
176         0,50,300,120,
177         NULL,
178         NULL,
179         NULL,
180         NULL);
181
182     if (!hWndDateTime) {
183         HeapFree(GetProcessHeap(), 0, info);
184         return NULL;
185     }
186
187     info->oldproc = (WNDPROC)SetWindowLongPtrA(hWndDateTime, GWLP_WNDPROC,
188                                             (LONG_PTR)datetime_subclass_proc);
189     SetWindowLongPtrA(hWndDateTime, GWLP_USERDATA, (LONG_PTR)info);
190
191     return hWndDateTime;
192 }
193
194 static void test_dtm_set_format(HWND hWndDateTime)
195 {
196     CHAR txt[256];
197     SYSTEMTIME systime;
198     LRESULT r;
199
200     r = SendMessage(hWndDateTime, DTM_SETFORMAT, 0, 0);
201     expect(1, r);
202
203     r = SendMessage(hWndDateTime, DTM_SETFORMAT, 0,
204                     (LPARAM)"'Today is: 'hh':'m':'s dddd MMM dd', 'yyyy");
205     expect(1, r);
206
207     ok_sequence(sequences, DATETIME_SEQ_INDEX, test_dtm_set_format_seq, "test_dtm_set_format", FALSE);
208
209     r = SendMessage(hWndDateTime, DTM_SETFORMAT, 0,
210                     (LPARAM)"'hh' hh");
211     expect(1, r);
212     ZeroMemory(&systime, sizeof(systime));
213     systime.wYear = 2000;
214     systime.wMonth = systime.wDay = 1;
215     r = SendMessage(hWndDateTime, DTM_SETSYSTEMTIME, 0, (LPARAM)&systime);
216     expect(1, r);
217     GetWindowText(hWndDateTime, txt, 256);
218     todo_wine ok(strcmp(txt, "hh 12") == 0, "String mismatch (\"%s\" vs \"hh 12\")\n", txt);
219     flush_sequences(sequences, NUM_MSG_SEQUENCES);
220 }
221
222 static void test_mccolor_types(HWND hWndDateTime, int mccolor_type, const char* mccolor_name)
223 {
224     LRESULT r;
225     COLORREF theColor, prevColor;
226
227     theColor=RGB(0,0,0);
228     r = SendMessage(hWndDateTime, DTM_SETMCCOLOR, mccolor_type, theColor);
229     ok(r != -1, "%s: Set RGB(0,0,0): Expected COLORREF of previous value, got %ld\n", mccolor_name, r);
230     prevColor=theColor;
231     theColor=RGB(255,255,255);
232     r = SendMessage(hWndDateTime, DTM_SETMCCOLOR, mccolor_type, theColor);
233     ok(r==prevColor, "%s: Set RGB(255,255,255): Expected COLORREF of previous value, got %ld\n", mccolor_name, r);
234     prevColor=theColor;
235     theColor=RGB(100,180,220);
236     r = SendMessage(hWndDateTime, DTM_SETMCCOLOR, mccolor_type, theColor);
237     ok(r==prevColor, "%s: Set RGB(100,180,220): Expected COLORREF of previous value, got %ld\n", mccolor_name, r);
238     r = SendMessage(hWndDateTime, DTM_GETMCCOLOR, mccolor_type, 0);
239     ok(r==theColor, "%s: GETMCCOLOR: Expected %d, got %ld\n", mccolor_name, theColor, r);
240 }
241
242 static void test_dtm_set_and_get_mccolor(HWND hWndDateTime)
243 {
244     test_mccolor_types(hWndDateTime, MCSC_BACKGROUND, "MCSC_BACKGROUND");
245     test_mccolor_types(hWndDateTime, MCSC_MONTHBK, "MCSC_MONTHBK");
246     test_mccolor_types(hWndDateTime, MCSC_TEXT, "MCSC_TEXT");
247     test_mccolor_types(hWndDateTime, MCSC_TITLEBK, "MCSC_TITLEBK");
248     test_mccolor_types(hWndDateTime, MCSC_TITLETEXT, "MCSC_TITLETEXT");
249     test_mccolor_types(hWndDateTime, MCSC_TRAILINGTEXT, "MCSC_TRAILINGTEXT");
250
251     ok_sequence(sequences, DATETIME_SEQ_INDEX, test_dtm_set_and_get_mccolor_seq, "test_dtm_set_and_get_mccolor", FALSE);
252     flush_sequences(sequences, NUM_MSG_SEQUENCES);
253 }
254
255 static void test_dtm_set_and_get_mcfont(HWND hWndDateTime)
256 {
257     HFONT hFontOrig, hFontNew;
258
259     hFontOrig = GetStockObject(DEFAULT_GUI_FONT);
260     SendMessage(hWndDateTime, DTM_SETMCFONT, (WPARAM)hFontOrig, TRUE);
261     hFontNew = (HFONT)SendMessage(hWndDateTime, DTM_GETMCFONT, 0, 0);
262     ok(hFontOrig == hFontNew, "Expected hFontOrig==hFontNew, hFontOrig=%p, hFontNew=%p\n", hFontOrig, hFontNew);
263
264     ok_sequence(sequences, DATETIME_SEQ_INDEX, test_dtm_set_and_get_mcfont_seq, "test_dtm_set_and_get_mcfont", FALSE);
265     flush_sequences(sequences, NUM_MSG_SEQUENCES);
266 }
267
268 static void test_dtm_get_monthcal(HWND hWndDateTime)
269 {
270     LRESULT r;
271
272     todo_wine {
273         r = SendMessage(hWndDateTime, DTM_GETMONTHCAL, 0, 0);
274         ok(r == 0, "Expected NULL(no child month calendar control), got %ld\n", r);
275     }
276
277     ok_sequence(sequences, DATETIME_SEQ_INDEX, test_dtm_get_monthcal_seq, "test_dtm_get_monthcal", FALSE);
278     flush_sequences(sequences, NUM_MSG_SEQUENCES);
279 }
280
281 static void fill_systime_struct(SYSTEMTIME *st, int year, int month, int dayofweek, int day, int hour, int minute, int second, int milliseconds)
282 {
283     st->wYear = year;
284     st->wMonth = month;
285     st->wDayOfWeek = dayofweek;
286     st->wDay = day;
287     st->wHour = hour;
288     st->wMinute = minute;
289     st->wSecond = second;
290     st->wMilliseconds = milliseconds;
291 }
292
293 static LPARAM compare_systime_date(SYSTEMTIME *st1, SYSTEMTIME *st2)
294 {
295     return (st1->wYear == st2->wYear)
296             && (st1->wMonth == st2->wMonth)
297             && (st1->wDayOfWeek == st2->wDayOfWeek)
298             && (st1->wDay == st2->wDay);
299 }
300
301 static LPARAM compare_systime_time(SYSTEMTIME *st1, SYSTEMTIME *st2)
302 {
303     return (st1->wHour == st2->wHour)
304             && (st1->wMinute == st2->wMinute)
305             && (st1->wSecond == st2->wSecond)
306             && (st1->wMilliseconds == st2->wMilliseconds);
307 }
308
309 static LPARAM compare_systime(SYSTEMTIME *st1, SYSTEMTIME *st2)
310 {
311     if(!compare_systime_date(st1, st2))
312         return 0;
313
314     return compare_systime_time(st1, st2);
315 }
316
317 #define expect_systime(ST1, ST2) ok(compare_systime((ST1), (ST2))==1, "ST1 != ST2\n")
318 #define expect_systime_date(ST1, ST2) ok(compare_systime_date((ST1), (ST2))==1, "ST1.date != ST2.date\n")
319 #define expect_systime_time(ST1, ST2) ok(compare_systime_time((ST1), (ST2))==1, "ST1.time != ST2.time\n")
320
321 static void test_dtm_set_and_get_range(HWND hWndDateTime)
322 {
323     LRESULT r;
324     SYSTEMTIME st[2];
325     SYSTEMTIME getSt[2];
326
327     /* initialize st[0] to lowest possible value */
328     fill_systime_struct(&st[0], 1601, 1, 0, 1, 0, 0, 0, 0);
329     /* initialize st[1] to all invalid numbers */
330     fill_systime_struct(&st[1], 0, 0, 7, 0, 24, 60, 60, 1000);
331
332     r = SendMessage(hWndDateTime, DTM_SETRANGE, GDTR_MIN, (LPARAM)st);
333     expect(1, r);
334     r = SendMessage(hWndDateTime, DTM_GETRANGE, 0, (LPARAM)getSt);
335     ok(r == GDTR_MIN, "Expected %x, not %x(GDTR_MAX) or %x(GDTR_MIN | GDTR_MAX), got %lx\n", GDTR_MIN, GDTR_MAX, GDTR_MIN | GDTR_MAX, r);
336     expect_systime(&st[0], &getSt[0]);
337
338     r = SendMessage(hWndDateTime, DTM_SETRANGE, GDTR_MAX, (LPARAM)st);
339     expect_unsuccess(0, r);
340
341     /* set st[0] to all invalid numbers */
342     fill_systime_struct(&st[0], 0, 0, 7, 0, 24, 60, 60, 1000);
343     /* set st[1] to highest possible value */
344     fill_systime_struct(&st[1], 30827, 12, 6, 31, 23, 59, 59, 999);
345
346     r = SendMessage(hWndDateTime, DTM_SETRANGE, GDTR_MAX, (LPARAM)st);
347     expect(1, r);
348     r = SendMessage(hWndDateTime, DTM_GETRANGE, 0, (LPARAM)getSt);
349     todo_wine {
350         ok(r == GDTR_MAX, "Expected %x, not %x(GDTR_MIN) or %x(GDTR_MIN | GDTR_MAX), got %lx\n", GDTR_MAX, GDTR_MIN, GDTR_MIN | GDTR_MAX, r);
351     }
352     expect_systime(&st[1], &getSt[1]);
353
354     r = SendMessage(hWndDateTime, DTM_SETRANGE, GDTR_MIN, (LPARAM)st);
355     expect_unsuccess(0, r);
356     r = SendMessage(hWndDateTime, DTM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st);
357     expect_unsuccess(0, r);
358
359     /* set st[0] to highest possible value */
360     fill_systime_struct(&st[0], 30827, 12, 6, 31, 23, 59, 59, 999);
361
362     r = SendMessage(hWndDateTime, DTM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st);
363     expect(1, r);
364     r = SendMessage(hWndDateTime, DTM_GETRANGE, 0, (LPARAM)getSt);
365     ok(r == (GDTR_MIN | GDTR_MAX), "Expected %x, not %x(GDTR_MIN) or %x(GDTR_MAX), got %lx\n", (GDTR_MIN | GDTR_MAX), GDTR_MIN, GDTR_MAX, r);
366     expect_systime(&st[0], &getSt[0]);
367     expect_systime(&st[1], &getSt[1]);
368
369     /* initialize st[0] to lowest possible value */
370     fill_systime_struct(&st[0], 1601, 1, 0, 1, 0, 0, 0, 0);
371     /* set st[1] to highest possible value */
372     fill_systime_struct(&st[1], 30827, 12, 6, 31, 23, 59, 59, 999);
373
374     r = SendMessage(hWndDateTime, DTM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st);
375     expect(1, r);
376     r = SendMessage(hWndDateTime, DTM_GETRANGE, 0, (LPARAM)getSt);
377     ok(r == (GDTR_MIN | GDTR_MAX), "Expected %x, not %x(GDTR_MIN) or %x(GDTR_MAX), got %lx\n", (GDTR_MIN | GDTR_MAX), GDTR_MIN, GDTR_MAX, r);
378     expect_systime(&st[0], &getSt[0]);
379     expect_systime(&st[1], &getSt[1]);
380
381     /* set st[0] to value higher than minimum */
382     fill_systime_struct(&st[0], 1980, 1, 3, 23, 14, 34, 37, 465);
383     /* set st[1] to value lower than maximum */
384     fill_systime_struct(&st[1], 2007, 3, 2, 31, 23, 59, 59, 999);
385
386     r = SendMessage(hWndDateTime, DTM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st);
387     expect(1, r);
388     r = SendMessage(hWndDateTime, DTM_GETRANGE, 0, (LPARAM)getSt);
389     ok(r == (GDTR_MIN | GDTR_MAX), "Expected %x, not %x(GDTR_MIN) or %x(GDTR_MAX), got %lx\n", (GDTR_MIN | GDTR_MAX), GDTR_MIN, GDTR_MAX, r);
390     expect_systime(&st[0], &getSt[0]);
391     expect_systime(&st[1], &getSt[1]);
392
393     ok_sequence(sequences, DATETIME_SEQ_INDEX, test_dtm_set_and_get_range_seq, "test_dtm_set_and_get_range", FALSE);
394     flush_sequences(sequences, NUM_MSG_SEQUENCES);
395 }
396
397 /* when max<min for DTM_SETRANGE, Windows seems to swap the min and max values,
398 although that's undocumented.  However, it doesn't seem to be implemented
399 correctly, causing some strange side effects */
400 static void test_dtm_set_range_swap_min_max(HWND hWndDateTime)
401 {
402     LRESULT r;
403     SYSTEMTIME st[2];
404     SYSTEMTIME getSt[2];
405     SYSTEMTIME origSt;
406
407     fill_systime_struct(&st[0], 2007, 2, 4, 15, 2, 2, 2, 2);
408
409     r = SendMessage(hWndDateTime, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&st[0]);
410     expect(1, r);
411     r = SendMessage(hWndDateTime, DTM_GETSYSTEMTIME, 0, (LPARAM)&origSt);
412     ok(r == GDT_VALID, "Expected %d, not %d(GDT_NONE) or %d(GDT_ERROR), got %ld\n", GDT_VALID, GDT_NONE, GDT_ERROR, r);
413     expect_systime(&st[0], &origSt);
414
415     /* set st[0] to value higher than st[1] */
416     fill_systime_struct(&st[0], 2007, 3, 2, 31, 23, 59, 59, 999);
417     fill_systime_struct(&st[1], 1980, 1, 3, 23, 14, 34, 37, 465);
418
419     /* since min>max, min and max values should be swapped by DTM_SETRANGE
420     automatically */
421     r = SendMessage(hWndDateTime, DTM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st);
422     expect(1, r);
423     r = SendMessage(hWndDateTime, DTM_GETRANGE, 0, (LPARAM)getSt);
424     ok(r == (GDTR_MIN | GDTR_MAX), "Expected %x, not %x(GDTR_MIN) or %x(GDTR_MAX), got %lx\n", (GDTR_MIN | GDTR_MAX), GDTR_MIN, GDTR_MAX, r);
425     todo_wine {
426         ok(compare_systime(&st[0], &getSt[0]) == 1 ||
427            broken(compare_systime(&st[0], &getSt[1]) == 1), /* comctl32 version  <= 5.80 */
428            "ST1 != ST2\n");
429
430         ok(compare_systime(&st[1], &getSt[1]) == 1 ||
431            broken(compare_systime(&st[1], &getSt[0]) == 1), /* comctl32 version  <= 5.80 */
432            "ST1 != ST2\n");
433     }
434
435     fill_systime_struct(&st[0], 1980, 1, 3, 23, 14, 34, 37, 465);
436
437     r = SendMessage(hWndDateTime, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&st[0]);
438     expect(1, r);
439     r = SendMessage(hWndDateTime, DTM_GETSYSTEMTIME, 0, (LPARAM)&getSt[0]);
440     ok(r == GDT_VALID, "Expected %d, not %d(GDT_NONE) or %d(GDT_ERROR), got %ld\n", GDT_VALID, GDT_NONE, GDT_ERROR, r);
441     /* the time part seems to not change after swapping the min and max values
442     and doing DTM_SETSYSTEMTIME */
443     expect_systime_date(&st[0], &getSt[0]);
444     todo_wine {
445         ok(compare_systime_time(&origSt, &getSt[0]) == 1 ||
446            broken(compare_systime_time(&st[0], &getSt[0]) == 1), /* comctl32 version  <= 5.80 */
447            "ST1.time != ST2.time\n");
448     }
449
450     /* set st[0] to value higher than minimum */
451     fill_systime_struct(&st[0], 1980, 1, 3, 23, 14, 34, 37, 465);
452     /* set st[1] to value lower than maximum */
453     fill_systime_struct(&st[1], 2007, 3, 2, 31, 23, 59, 59, 999);
454
455     r = SendMessage(hWndDateTime, DTM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st);
456     expect(1, r);
457     /* for some reason after we swapped the min and max values before,
458     whenever we do a DTM_SETRANGE, the DTM_GETRANGE will return the values
459     swapped*/
460     r = SendMessage(hWndDateTime, DTM_GETRANGE, 0, (LPARAM)getSt);
461     ok(r == (GDTR_MIN | GDTR_MAX), "Expected %x, not %x(GDTR_MIN) or %x(GDTR_MAX), got %lx\n", (GDTR_MIN | GDTR_MAX), GDTR_MIN, GDTR_MAX, r);
462     todo_wine {
463         ok(compare_systime(&st[0], &getSt[1]) == 1 ||
464            broken(compare_systime(&st[0], &getSt[0]) == 1), /* comctl32 version  <= 5.80 */
465            "ST1 != ST2\n");
466
467         ok(compare_systime(&st[1], &getSt[0]) == 1 ||
468            broken(compare_systime(&st[1], &getSt[1]) == 1), /* comctl32 version <= 5.80 */
469            "ST1 != ST2\n");
470     }
471
472     /* set st[0] to value higher than st[1] */
473     fill_systime_struct(&st[0], 2007, 3, 2, 31, 23, 59, 59, 999);
474     fill_systime_struct(&st[1], 1980, 1, 3, 23, 14, 34, 37, 465);
475
476     /* set min>max again, so that the return values of DTM_GETRANGE are no
477     longer swapped the next time we do a DTM SETRANGE and DTM_GETRANGE*/
478     r = SendMessage(hWndDateTime, DTM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st);
479     expect(1, r);
480     r = SendMessage(hWndDateTime, DTM_GETRANGE, 0, (LPARAM)getSt);
481     ok(r == (GDTR_MIN | GDTR_MAX), "Expected %x, not %x(GDTR_MIN) or %x(GDTR_MAX), got %lx\n", (GDTR_MIN | GDTR_MAX), GDTR_MIN, GDTR_MAX, r);
482     expect_systime(&st[0], &getSt[1]);
483     expect_systime(&st[1], &getSt[0]);
484
485     /* initialize st[0] to lowest possible value */
486     fill_systime_struct(&st[0], 1601, 1, 0, 1, 0, 0, 0, 0);
487     /* set st[1] to highest possible value */
488     fill_systime_struct(&st[1], 30827, 12, 6, 31, 23, 59, 59, 999);
489
490     r = SendMessage(hWndDateTime, DTM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st);
491     expect(1, r);
492     r = SendMessage(hWndDateTime, DTM_GETRANGE, 0, (LPARAM)getSt);
493     ok(r == (GDTR_MIN | GDTR_MAX), "Expected %x, not %x(GDTR_MIN) or %x(GDTR_MAX), got %lx\n", (GDTR_MIN | GDTR_MAX), GDTR_MIN, GDTR_MAX, r);
494     expect_systime(&st[0], &getSt[0]);
495     expect_systime(&st[1], &getSt[1]);
496
497     ok_sequence(sequences, DATETIME_SEQ_INDEX, test_dtm_set_range_swap_min_max_seq, "test_dtm_set_range_swap_min_max", FALSE);
498     flush_sequences(sequences, NUM_MSG_SEQUENCES);
499 }
500
501 static void test_dtm_set_and_get_system_time(HWND hWndDateTime)
502 {
503     LRESULT r;
504     SYSTEMTIME st;
505     SYSTEMTIME getSt;
506     HWND hWndDateTime_test_gdt_none;
507
508     hWndDateTime_test_gdt_none = create_datetime_control(0, 0);
509
510     ok(hWndDateTime_test_gdt_none!=NULL, "Expected non NULL, got %p\n", hWndDateTime_test_gdt_none);
511     if(hWndDateTime_test_gdt_none) {
512         r = SendMessage(hWndDateTime_test_gdt_none, DTM_SETSYSTEMTIME, GDT_NONE, (LPARAM)&st);
513         expect(0, r);
514     }
515     else {
516         skip("hWndDateTime_test_gdt_none is NULL\n");
517         flush_sequences(sequences, NUM_MSG_SEQUENCES);
518
519         return;
520     }
521
522     DestroyWindow(hWndDateTime_test_gdt_none);
523
524     r = SendMessage(hWndDateTime, DTM_SETSYSTEMTIME, GDT_NONE, (LPARAM)&st);
525     expect(1, r);
526     r = SendMessage(hWndDateTime, DTM_GETSYSTEMTIME, 0, (LPARAM)&getSt);
527     ok(r == GDT_NONE, "Expected %d, not %d(GDT_VALID) or %d(GDT_ERROR), got %ld\n", GDT_NONE, GDT_VALID, GDT_ERROR, r);
528
529     /* set st to lowest possible value */
530     fill_systime_struct(&st, 1601, 1, 0, 1, 0, 0, 0, 0);
531
532     r = SendMessage(hWndDateTime, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&st);
533     expect(1, r);
534
535     /* set st to highest possible value */
536     fill_systime_struct(&st, 30827, 12, 6, 31, 23, 59, 59, 999);
537
538     r = SendMessage(hWndDateTime, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&st);
539     expect(1, r);
540
541     /* set st to value between min and max */
542     fill_systime_struct(&st, 1980, 1, 3, 23, 14, 34, 37, 465);
543
544     r = SendMessage(hWndDateTime, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&st);
545     expect(1, r);
546     r = SendMessage(hWndDateTime, DTM_GETSYSTEMTIME, 0, (LPARAM)&getSt);
547     ok(r == GDT_VALID, "Expected %d, not %d(GDT_NONE) or %d(GDT_ERROR), got %ld\n", GDT_VALID, GDT_NONE, GDT_ERROR, r);
548     expect_systime(&st, &getSt);
549
550     /* set st to invalid value */
551     fill_systime_struct(&st, 0, 0, 7, 0, 24, 60, 60, 1000);
552
553     r = SendMessage(hWndDateTime, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&st);
554     expect_unsuccess(0, r);
555
556     ok_sequence(sequences, DATETIME_SEQ_INDEX, test_dtm_set_and_get_system_time_seq, "test_dtm_set_and_get_system_time", FALSE);
557     flush_sequences(sequences, NUM_MSG_SEQUENCES);
558 }
559
560 static void test_datetime_control(void)
561 {
562     HWND hWndDateTime;
563
564     hWndDateTime = create_datetime_control(DTS_SHOWNONE, 0);
565
566     ok(hWndDateTime != NULL, "Expected non NULL, got %p\n", hWndDateTime);
567     if(hWndDateTime!=NULL) {
568         test_dtm_set_format(hWndDateTime);
569         test_dtm_set_and_get_mccolor(hWndDateTime);
570         test_dtm_set_and_get_mcfont(hWndDateTime);
571         test_dtm_get_monthcal(hWndDateTime);
572         test_dtm_set_and_get_range(hWndDateTime);
573         test_dtm_set_range_swap_min_max(hWndDateTime);
574         test_dtm_set_and_get_system_time(hWndDateTime);
575     }
576     else {
577         skip("hWndDateTime is NULL\n");
578     }
579
580     DestroyWindow(hWndDateTime);
581     ok_sequence(sequences, DATETIME_SEQ_INDEX, destroy_window_seq, "test_dtm_set_and_get_system_time", TRUE);
582 }
583
584 START_TEST(datetime)
585 {
586     HMODULE hComctl32;
587     BOOL (WINAPI *pInitCommonControlsEx)(const INITCOMMONCONTROLSEX*);
588     INITCOMMONCONTROLSEX iccex;
589
590     hComctl32 = GetModuleHandleA("comctl32.dll");
591     pInitCommonControlsEx = (void*)GetProcAddress(hComctl32, "InitCommonControlsEx");
592     if (!pInitCommonControlsEx)
593     {
594         skip("InitCommonControlsEx() is missing. Skipping the tests\n");
595         return;
596     }
597     iccex.dwSize = sizeof(iccex);
598     iccex.dwICC  = ICC_DATE_CLASSES;
599     pInitCommonControlsEx(&iccex);
600
601     init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
602
603     test_datetime_control();
604 }