comctl32/listview: Position edit box after notification.
[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         expect_systime(&st[0], &getSt[0]);
427     }
428     todo_wine {
429         expect_systime(&st[1], &getSt[1]);
430     }
431
432     fill_systime_struct(&st[0], 1980, 1, 3, 23, 14, 34, 37, 465);
433
434     r = SendMessage(hWndDateTime, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&st[0]);
435     expect(1, r);
436     r = SendMessage(hWndDateTime, DTM_GETSYSTEMTIME, 0, (LPARAM)&getSt[0]);
437     ok(r == GDT_VALID, "Expected %d, not %d(GDT_NONE) or %d(GDT_ERROR), got %ld\n", GDT_VALID, GDT_NONE, GDT_ERROR, r);
438     /* the time part seems to not change after swapping the min and max values
439     and doing DTM_SETSYSTEMTIME */
440     expect_systime_date(&st[0], &getSt[0]);
441     todo_wine {
442         expect_systime_time(&origSt, &getSt[0]);
443     }
444
445     /* set st[0] to value higher than minimum */
446     fill_systime_struct(&st[0], 1980, 1, 3, 23, 14, 34, 37, 465);
447     /* set st[1] to value lower than maximum */
448     fill_systime_struct(&st[1], 2007, 3, 2, 31, 23, 59, 59, 999);
449
450     r = SendMessage(hWndDateTime, DTM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st);
451     expect(1, r);
452     /* for some reason after we swapped the min and max values before,
453     whenever we do a DTM_SETRANGE, the DTM_GETRANGE will return the values
454     swapped*/
455     r = SendMessage(hWndDateTime, DTM_GETRANGE, 0, (LPARAM)getSt);
456     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);
457     todo_wine {
458         expect_systime(&st[0], &getSt[1]);
459     }
460     todo_wine {
461         expect_systime(&st[1], &getSt[0]);
462     }
463
464     /* set st[0] to value higher than st[1] */
465     fill_systime_struct(&st[0], 2007, 3, 2, 31, 23, 59, 59, 999);
466     fill_systime_struct(&st[1], 1980, 1, 3, 23, 14, 34, 37, 465);
467
468     /* set min>max again, so that the return values of DTM_GETRANGE are no
469     longer swapped the next time we do a DTM SETRANGE and DTM_GETRANGE*/
470     r = SendMessage(hWndDateTime, DTM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st);
471     expect(1, r);
472     r = SendMessage(hWndDateTime, DTM_GETRANGE, 0, (LPARAM)getSt);
473     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);
474     expect_systime(&st[0], &getSt[1]);
475     expect_systime(&st[1], &getSt[0]);
476
477     /* initialize st[0] to lowest possible value */
478     fill_systime_struct(&st[0], 1601, 1, 0, 1, 0, 0, 0, 0);
479     /* set st[1] to highest possible value */
480     fill_systime_struct(&st[1], 30827, 12, 6, 31, 23, 59, 59, 999);
481
482     r = SendMessage(hWndDateTime, DTM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st);
483     expect(1, r);
484     r = SendMessage(hWndDateTime, DTM_GETRANGE, 0, (LPARAM)getSt);
485     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);
486     expect_systime(&st[0], &getSt[0]);
487     expect_systime(&st[1], &getSt[1]);
488
489     ok_sequence(sequences, DATETIME_SEQ_INDEX, test_dtm_set_range_swap_min_max_seq, "test_dtm_set_range_swap_min_max", FALSE);
490     flush_sequences(sequences, NUM_MSG_SEQUENCES);
491 }
492
493 static void test_dtm_set_and_get_system_time(HWND hWndDateTime)
494 {
495     LRESULT r;
496     SYSTEMTIME st;
497     SYSTEMTIME getSt;
498     HWND hWndDateTime_test_gdt_none;
499
500     hWndDateTime_test_gdt_none = create_datetime_control(0, 0);
501
502     ok(hWndDateTime_test_gdt_none!=NULL, "Expected non NULL, got %p\n", hWndDateTime_test_gdt_none);
503     if(hWndDateTime_test_gdt_none) {
504         r = SendMessage(hWndDateTime_test_gdt_none, DTM_SETSYSTEMTIME, GDT_NONE, (LPARAM)&st);
505         expect(0, r);
506     }
507     else {
508         skip("hWndDateTime_test_gdt_none is NULL\n");
509         flush_sequences(sequences, NUM_MSG_SEQUENCES);
510
511         return;
512     }
513
514     DestroyWindow(hWndDateTime_test_gdt_none);
515
516     r = SendMessage(hWndDateTime, DTM_SETSYSTEMTIME, GDT_NONE, (LPARAM)&st);
517     expect(1, r);
518     r = SendMessage(hWndDateTime, DTM_GETSYSTEMTIME, 0, (LPARAM)&getSt);
519     ok(r == GDT_NONE, "Expected %d, not %d(GDT_VALID) or %d(GDT_ERROR), got %ld\n", GDT_NONE, GDT_VALID, GDT_ERROR, r);
520
521     /* set st to lowest possible value */
522     fill_systime_struct(&st, 1601, 1, 0, 1, 0, 0, 0, 0);
523
524     r = SendMessage(hWndDateTime, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&st);
525     expect(1, r);
526
527     /* set st to highest possible value */
528     fill_systime_struct(&st, 30827, 12, 6, 31, 23, 59, 59, 999);
529
530     r = SendMessage(hWndDateTime, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&st);
531     expect(1, r);
532
533     /* set st to value between min and max */
534     fill_systime_struct(&st, 1980, 1, 3, 23, 14, 34, 37, 465);
535
536     r = SendMessage(hWndDateTime, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&st);
537     expect(1, r);
538     r = SendMessage(hWndDateTime, DTM_GETSYSTEMTIME, 0, (LPARAM)&getSt);
539     ok(r == GDT_VALID, "Expected %d, not %d(GDT_NONE) or %d(GDT_ERROR), got %ld\n", GDT_VALID, GDT_NONE, GDT_ERROR, r);
540     expect_systime(&st, &getSt);
541
542     /* set st to invalid value */
543     fill_systime_struct(&st, 0, 0, 7, 0, 24, 60, 60, 1000);
544
545     r = SendMessage(hWndDateTime, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&st);
546     expect_unsuccess(0, r);
547
548     ok_sequence(sequences, DATETIME_SEQ_INDEX, test_dtm_set_and_get_system_time_seq, "test_dtm_set_and_get_system_time", FALSE);
549     flush_sequences(sequences, NUM_MSG_SEQUENCES);
550 }
551
552 static void test_datetime_control(void)
553 {
554     HWND hWndDateTime;
555
556     hWndDateTime = create_datetime_control(DTS_SHOWNONE, 0);
557
558     ok(hWndDateTime != NULL, "Expected non NULL, got %p\n", hWndDateTime);
559     if(hWndDateTime!=NULL) {
560         test_dtm_set_format(hWndDateTime);
561         test_dtm_set_and_get_mccolor(hWndDateTime);
562         test_dtm_set_and_get_mcfont(hWndDateTime);
563         test_dtm_get_monthcal(hWndDateTime);
564         test_dtm_set_and_get_range(hWndDateTime);
565         test_dtm_set_range_swap_min_max(hWndDateTime);
566         test_dtm_set_and_get_system_time(hWndDateTime);
567     }
568     else {
569         skip("hWndDateTime is NULL\n");
570     }
571
572     DestroyWindow(hWndDateTime);
573     ok_sequence(sequences, DATETIME_SEQ_INDEX, destroy_window_seq, "test_dtm_set_and_get_system_time", TRUE);
574 }
575
576 START_TEST(datetime)
577 {
578     HMODULE hComctl32;
579     BOOL (WINAPI *pInitCommonControlsEx)(const INITCOMMONCONTROLSEX*);
580     INITCOMMONCONTROLSEX iccex;
581
582     hComctl32 = GetModuleHandleA("comctl32.dll");
583     pInitCommonControlsEx = (void*)GetProcAddress(hComctl32, "InitCommonControlsEx");
584     if (!pInitCommonControlsEx)
585     {
586         skip("InitCommonControlsEx() is missing. Skipping the tests\n");
587         return;
588     }
589     iccex.dwSize = sizeof(iccex);
590     iccex.dwICC  = ICC_DATE_CLASSES;
591     pInitCommonControlsEx(&iccex);
592
593     init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
594
595     test_datetime_control();
596 }