ReactOS  0.4.14-dev-49-gfb4591c
taskdialog.c
Go to the documentation of this file.
1 /* Unit tests for the task dialog control.
2  *
3  * Copyright 2017 Fabian Maurer for the Wine project
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 <stdarg.h>
21 
22 #include "windef.h"
23 #include "winbase.h"
24 #include "winuser.h"
25 #include "commctrl.h"
26 
27 #include "wine/heap.h"
28 #include "wine/test.h"
29 #include "v6util.h"
30 #include "msg.h"
31 
32 #ifdef __REACTOS__
33 #define WM_KEYF1 0x004d
34 #endif
35 
36 #define WM_TD_CALLBACK (WM_APP) /* Custom dummy message to wrap callback notifications */
37 
38 #define NUM_MSG_SEQUENCES 1
39 #define TASKDIALOG_SEQ_INDEX 0
40 
41 #define TEST_NUM_BUTTONS 10 /* Number of custom buttons to test with */
42 #define TEST_NUM_RADIO_BUTTONS 3
43 
44 #define ID_START 20 /* Lower IDs might be used by the system */
45 #define ID_START_BUTTON (ID_START + 0)
46 #define ID_START_RADIO_BUTTON (ID_START + 20)
47 
48 static HRESULT (WINAPI *pTaskDialogIndirect)(const TASKDIALOGCONFIG *, int *, int *, BOOL *);
49 static HRESULT (WINAPI *pTaskDialog)(HWND, HINSTANCE, const WCHAR *, const WCHAR *, const WCHAR *,
50  TASKDIALOG_COMMON_BUTTON_FLAGS, const WCHAR *, int *);
51 
53 
55 {
59 
61  const struct message_info *send; /* Message to send to trigger the next callback message */
62 };
63 
64 static const struct message_info *current_message_info;
65 
66 /* Messages to send */
67 static const struct message_info msg_send_return[] =
68 {
69  { WM_KEYDOWN, VK_RETURN, 0 },
70  { 0 }
71 };
72 
73 /* Messages to test against */
74 static const struct message_info msg_return_press_ok[] =
75 {
76  { TDN_CREATED, 0, 0, S_OK, msg_send_return },
77  { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
78  { 0 }
79 };
80 
81 static const struct message_info msg_return_press_yes[] =
82 {
83  { TDN_CREATED, 0, 0, S_OK, msg_send_return },
85  { 0 }
86 };
87 
88 static const struct message_info msg_return_press_no[] =
89 {
90  { TDN_CREATED, 0, 0, S_OK, msg_send_return },
91  { TDN_BUTTON_CLICKED, IDNO, 0, S_OK, NULL },
92  { 0 }
93 };
94 
95 static const struct message_info msg_return_press_cancel[] =
96 {
97  { TDN_CREATED, 0, 0, S_OK, msg_send_return },
99  { 0 }
100 };
101 
102 static const struct message_info msg_return_press_retry[] =
103 {
104  { TDN_CREATED, 0, 0, S_OK, msg_send_return },
106  { 0 }
107 };
108 
109 static const struct message_info msg_return_press_custom1[] =
110 {
111  { TDN_CREATED, 0, 0, S_OK, msg_send_return },
113  { 0 }
114 };
115 
116 static const struct message_info msg_return_press_custom4[] =
117 {
118  { TDN_CREATED, 0, 0, S_OK, msg_send_return },
120  { 0 }
121 };
122 
124 {
125  { TDN_CREATED, 0, 0, S_OK, msg_send_return },
126  { TDN_BUTTON_CLICKED, -1, 0, S_OK, NULL },
127  { 0 }
128 };
129 
130 static const struct message_info msg_send_click_ok[] =
131 {
132  { TDM_CLICK_BUTTON, IDOK, 0 },
133  { 0 }
134 };
135 
136 static const struct message_info msg_send_f1[] =
137 {
138  { WM_KEYF1, 0, 0, 0},
139  { 0 }
140 };
141 
142 static const struct message_info msg_got_tdn_help[] =
143 {
144  { TDN_CREATED, 0, 0, S_OK, msg_send_f1 },
145  { TDN_HELP, 0, 0, S_OK, msg_send_click_ok },
146  { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
147  { 0 }
148 };
149 
150 /* Three radio buttons */
152 {
153  { TDN_CREATED, 0, 0, S_OK, NULL },
155  { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
156  { 0 }
157 };
158 
160 {
161  { TDN_CREATED, 0, 0, S_OK, NULL },
163  { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
164  { 0 }
165 };
166 
168 {
169  { TDN_CREATED, 0, 0, S_OK, NULL },
171  { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
172  { 0 }
173 };
174 
176 {
178  { 0 }
179 };
180 
182 {
183  { TDN_CREATED, 0, 0, S_OK, NULL },
186  { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
187  { 0 }
188 };
189 
191 {
194  { TDM_CLICK_BUTTON, IDOK, 0 },
195  { 0 }
196 };
197 
199 {
200  { TDN_CREATED, 0, 0, S_OK, NULL },
203  { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
204  { 0 }
205 };
206 
208 {
209  { TDN_CREATED, 0, 0, S_OK, msg_send_click_ok },
211  { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
212  { 0 }
213 };
214 
216 {
217  { TDN_CREATED, 0, 0, S_OK, msg_send_click_ok },
218  { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
219  { 0 }
220 };
221 
223 {
224  { TDM_CLICK_RADIO_BUTTON, -2, 0 },
225  { 0 }
226 };
227 
229 {
232  { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
233  { 0 }
234 };
235 
237 {
238  { TDM_CLICK_BUTTON, IDOK, 0 },
239  { TDM_CLICK_BUTTON, IDYES, 0 },
240  { TDM_CLICK_BUTTON, IDNO, 0 },
241  { TDM_CLICK_BUTTON, IDCANCEL, 0 },
242  { TDM_CLICK_BUTTON, IDRETRY, 0 },
243  { TDM_CLICK_BUTTON, IDCLOSE, 0 },
244  { TDM_CLICK_BUTTON, ID_START_BUTTON + 99, 0 },
245  { 0 }
246 };
247 
249 {
256  { TDN_BUTTON_CLICKED, IDCLOSE, 0, S_FALSE, NULL },
258  { 0 }
259 };
260 
262 {
268  { WM_COMMAND, MAKEWORD(IDCLOSE, BN_CLICKED), 0 },
271  { 0 }
272 };
273 
275 {
279  { 0 }
280 };
281 
283 {
285  { TDM_CLICK_BUTTON, IDOK, 0 },
286  { 0 }
287 };
288 
290 {
292  { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
293  { 0 }
294 };
295 
297 {
298  { TDN_CREATED, 0, 0, S_OK, msg_send_click_ok },
299  { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
300  { 0 }
301 };
302 
304 {
305  { TDN_CREATED, 0, 0, S_OK, msg_send_click_ok },
306  { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
307  { 0 }
308 };
309 
310 static const struct message_info msg_uncheck_verification[] =
311 {
313  { 0 }
314 };
315 
317 {
320  { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
321  { 0 }
322 };
323 
324 static const struct message_info msg_check_verification[] =
325 {
327  { 0 }
328 };
329 
331 {
334  { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
335  { 0 }
336 };
337 
339 
340 static const struct message_info msg_send_navigate[] =
341 {
343  { 0 }
344 };
345 
347 {
348  { TDN_CREATED, 0, 0, S_OK, NULL },
350  { TDN_DIALOG_CONSTRUCTED, 0, 0, S_OK, NULL },
353  { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
354  { 0 }
355 };
356 
357 static const struct message_info msg_send_close[] =
358 {
359  { WM_CLOSE, 0, 0, 0},
360  { 0 }
361 };
362 
363 static const struct message_info msg_handle_wm_close[] =
364 {
365  { TDN_CREATED, 0, 0, S_OK, msg_send_close },
368  { 0 }
369 };
370 
371 static const struct message_info msg_send_close_then_ok[] =
372 {
373  { WM_CLOSE, 0, 0, 0},
374  { TDM_CLICK_BUTTON, IDOK, 0 },
375  { 0 }
376 };
377 
379 {
381  { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
382  { 0 }
383 };
384 
386 {
387  msg->message = WM_TD_CALLBACK;
388  msg->flags = sent|wparam|lparam|id;
389  msg->wParam = wParam;
390  msg->lParam = lParam;
391  msg->id = message;
392  msg->stage = 0;
393 }
394 
395 #define run_test(info, expect_button, expect_radio_button, verification_checked, seq, context) \
396  run_test_(info, expect_button, expect_radio_button, verification_checked, seq, context, \
397  ARRAY_SIZE(seq) - 1, __FILE__, __LINE__)
398 
399 static void run_test_(TASKDIALOGCONFIG *info, int expect_button, int expect_radio_button, BOOL verification_checked,
400  const struct message_info *test_messages, const char *context, int test_messages_len,
401  const char *file, int line)
402 {
403  struct message *msg, *msg_start;
404  int ret_button = 0;
405  int ret_radio = 0;
406  BOOL ret_verification = FALSE;
407  HRESULT hr;
408  int i;
409 
410  /* Allocate messages to test against, plus 2 implicit and 1 empty */
411  msg_start = msg = heap_alloc_zero(sizeof(*msg) * (test_messages_len + 3));
412 
413  /* Always needed, thus made implicit */
415  for (i = 0; i < test_messages_len; i++)
417  /* Always needed, thus made implicit */
419 
422 
423  hr = pTaskDialogIndirect(info, &ret_button, &ret_radio, &ret_verification);
424  ok_(file, line)(hr == S_OK, "TaskDialogIndirect() failed, got %#x.\n", hr);
425 
427  ok_(file, line)(ret_button == expect_button,
428  "Wrong button. Expected %d, got %d\n", expect_button, ret_button);
429  ok_(file, line)(ret_radio == expect_radio_button,
430  "Wrong radio button. Expected %d, got %d\n", expect_radio_button, ret_radio);
431 
432  heap_free(msg_start);
433 }
434 
435 static const LONG_PTR test_ref_data = 123456;
436 
438  WPARAM wParam, LPARAM lParam, LONG_PTR ref_data)
439 {
440  int msg_pos = sequences[TASKDIALOG_SEQ_INDEX]->count - 1; /* Skip implicit message */
441  const struct message_info *msg_send;
442  struct message msg;
443 
444  ok(test_ref_data == ref_data, "Unexpected ref data %lu.\n", ref_data);
445 
448 
449  if (notification == TDN_DIALOG_CONSTRUCTED || notification == TDN_DESTROYED) /* Skip implicit messages */
450  return S_OK;
451 
452  msg_send = current_message_info[msg_pos].send;
453  for(; msg_send && msg_send->message; msg_send++)
454  PostMessageW(hwnd, msg_send->message, msg_send->wparam, msg_send->lparam);
455 
456  return current_message_info[msg_pos].callback_retval;
457 }
458 
459 static void test_invalid_parameters(void)
460 {
461  TASKDIALOGCONFIG info = { 0 };
462  HRESULT hr;
463 
464  hr = pTaskDialogIndirect(NULL, NULL, NULL, NULL);
465  ok(hr == E_INVALIDARG, "Unexpected return value %#x.\n", hr);
466 
467  info.cbSize = 0;
468  hr = pTaskDialogIndirect(&info, NULL, NULL, NULL);
469  ok(hr == E_INVALIDARG, "Unexpected return value %#x.\n", hr);
470 
471  info.cbSize = sizeof(TASKDIALOGCONFIG) - 1;
472  hr = pTaskDialogIndirect(&info, NULL, NULL, NULL);
473  ok(hr == E_INVALIDARG, "Unexpected return value %#x.\n", hr);
474 
475  info.cbSize = sizeof(TASKDIALOGCONFIG) + 1;
476  hr = pTaskDialogIndirect(&info, NULL, NULL, NULL);
477  ok(hr == E_INVALIDARG, "Unexpected return value %#x.\n", hr);
478 }
479 
480 static void test_callback(void)
481 {
482  TASKDIALOGCONFIG info = {0};
483 
484  info.cbSize = sizeof(TASKDIALOGCONFIG);
485  info.pfCallback = taskdialog_callback_proc;
486  info.lpCallbackData = test_ref_data;
487 
488  run_test(&info, IDOK, 0, FALSE, msg_return_press_ok, "Press VK_RETURN.");
489 }
490 
491 static void test_buttons(void)
492 {
493  TASKDIALOGCONFIG info = {0};
494  static const DWORD command_link_flags[] = {0, TDF_USE_COMMAND_LINKS, TDF_USE_COMMAND_LINKS_NO_ICON};
495  TASKDIALOG_BUTTON custom_buttons[TEST_NUM_BUTTONS], radio_buttons[TEST_NUM_RADIO_BUTTONS];
496  const WCHAR button_format[] = {'%','0','2','d',0};
497  /* Each button has two digits as title, plus null-terminator */
498  WCHAR button_titles[TEST_NUM_BUTTONS * 3], radio_button_titles[TEST_NUM_BUTTONS * 3];
499  int i;
500 
501  info.cbSize = sizeof(TASKDIALOGCONFIG);
502  info.pfCallback = taskdialog_callback_proc;
503  info.lpCallbackData = test_ref_data;
504 
505  /* Init custom buttons */
506  for (i = 0; i < TEST_NUM_BUTTONS; i++)
507  {
508  WCHAR *text = &button_titles[i * 3];
509  wsprintfW(text, button_format, i);
510 
511  custom_buttons[i].pszButtonText = text;
512  custom_buttons[i].nButtonID = ID_START_BUTTON + i;
513  }
514  custom_buttons[TEST_NUM_BUTTONS - 1].nButtonID = -1;
515 
516  /* Init radio buttons */
517  for (i = 0; i < TEST_NUM_RADIO_BUTTONS; i++)
518  {
519  WCHAR *text = &radio_button_titles[i * 3];
520  wsprintfW(text, button_format, i);
521 
522  radio_buttons[i].pszButtonText = text;
523  radio_buttons[i].nButtonID = ID_START_RADIO_BUTTON + i;
524  }
525  radio_buttons[TEST_NUM_RADIO_BUTTONS - 1].nButtonID = -2;
526 
527  /* Test nDefaultButton */
528 
529  /* Test common buttons with invalid default ID */
530  info.nDefaultButton = 0; /* Should default to first created button */
533  run_test(&info, IDOK, 0, FALSE, msg_return_press_ok, "default button: unset default");
534  info.dwCommonButtons = TDCBF_YES_BUTTON | TDCBF_NO_BUTTON
536  run_test(&info, IDYES, 0, FALSE, msg_return_press_yes, "default button: unset default");
538  run_test(&info, IDNO, 0, FALSE, msg_return_press_no, "default button: unset default");
540  run_test(&info, IDRETRY, 0, FALSE, msg_return_press_retry, "default button: unset default");
541  info.dwCommonButtons = TDCBF_CANCEL_BUTTON | TDCBF_CLOSE_BUTTON;
542  run_test(&info, IDCANCEL, 0, FALSE, msg_return_press_cancel, "default button: unset default");
543 
544  /* Custom buttons could be command links */
545  for (i = 0; i < ARRAY_SIZE(command_link_flags); i++)
546  {
547  info.dwFlags = command_link_flags[i];
548 
549  /* Test with all common and custom buttons and invalid default ID */
550  info.nDefaultButton = 0xff; /* Random ID, should also default to first created button */
551  info.cButtons = TEST_NUM_BUTTONS;
552  info.pButtons = custom_buttons;
554  "default button: invalid default, with common buttons - 1");
555 
556  info.nDefaultButton = -1; /* Should work despite button ID -1 */
557  run_test(&info, -1, 0, FALSE, msg_return_press_custom10, "default button: invalid default, with common buttons - 2");
558 
559  info.nDefaultButton = -2; /* Should also default to first created button */
561  "default button: invalid default, with common buttons - 3");
562 
563  /* Test with only custom buttons and invalid default ID */
564  info.dwCommonButtons = 0;
566  "default button: invalid default, no common buttons");
567 
568  /* Test with common and custom buttons and valid default ID */
571  info.nDefaultButton = IDRETRY;
572  run_test(&info, IDRETRY, 0, FALSE, msg_return_press_retry, "default button: valid default - 1");
573 
574  /* Test with common and custom buttons and valid default ID */
575  info.nDefaultButton = ID_START_BUTTON + 3;
576  run_test(&info, ID_START_BUTTON + 3, 0, FALSE, msg_return_press_custom4, "default button: valid default - 2");
577  }
578 
579  /* Test radio buttons */
580  info.nDefaultButton = 0;
581  info.cButtons = 0;
582  info.pButtons = 0;
583  info.dwCommonButtons = TDCBF_OK_BUTTON;
584  info.cRadioButtons = TEST_NUM_RADIO_BUTTONS;
585  info.pRadioButtons = radio_buttons;
586 
587  /* Test default first radio button */
589  "default radio button: default first radio button");
590 
591  /* Test default radio button */
592  info.nDefaultRadioButton = ID_START_RADIO_BUTTON + 1;
594  "default radio button: default radio button");
595 
596  /* Test default radio button with -2 */
597  info.nDefaultRadioButton = -2;
599  "default radio button: default radio button with id -2");
600 
601  /* Test default radio button after clicking the first, messages still work even radio button is disabled */
602  info.nDefaultRadioButton = ID_START_RADIO_BUTTON + 1;
604  "default radio button: radio button after clicking");
605 
606  /* Test radio button after disabling and clicking the first */
607  info.nDefaultRadioButton = ID_START_RADIO_BUTTON + 1;
609  "default radio button: disable radio button before clicking");
610 
611  /* Test no default radio button, TDF_NO_DEFAULT_RADIO_BUTTON is set, TDN_RADIO_BUTTON_CLICKED will still be received, just radio button not selected */
612  info.nDefaultRadioButton = ID_START_RADIO_BUTTON;
615  "default radio button: no default radio flag");
616 
617  /* Test no default radio button, TDF_NO_DEFAULT_RADIO_BUTTON is set and nDefaultRadioButton is 0.
618  * TDN_RADIO_BUTTON_CLICKED will not be sent, and just radio button not selected */
619  info.nDefaultRadioButton = 0;
622  "default radio button: no default radio id and flag");
623 
624  /* Test no default radio button, TDF_NO_DEFAULT_RADIO_BUTTON is set and nDefaultRadioButton is invalid.
625  * TDN_RADIO_BUTTON_CLICKED will not be sent, and just radio button not selected */
626  info.nDefaultRadioButton = 0xff;
629  "default radio button: no default flag, invalid id");
630 
631  info.nDefaultRadioButton = 0;
634  "radio button: manually click radio button with negative id");
635 
636  /* Test sending clicks to non-existent buttons. Notification of non-existent buttons will be sent */
637  info.cButtons = TEST_NUM_BUTTONS;
638  info.pButtons = custom_buttons;
639  info.cRadioButtons = TEST_NUM_RADIO_BUTTONS;
640  info.pRadioButtons = radio_buttons;
641  info.dwCommonButtons = 0;
643  run_test(&info, ID_START_BUTTON + 99, 0, FALSE, msg_press_nonexistent_buttons, "sends click to non-existent buttons");
644 
645  /* Non-existent button clicks sent by WM_COMMAND won't generate TDN_BUTTON_CLICKED except IDOK.
646  * And will get the first existent button identifier instead of IDOK */
648  "sends click to non-existent buttons with WM_COMMAND");
649 
650  /* Non-existent radio button won't get notifications */
651  run_test(&info, IDOK, 0, FALSE, msg_press_nonexistent_radio_button, "sends click to non-existent radio buttons");
652 }
653 
654 static void test_help(void)
655 {
656  TASKDIALOGCONFIG info = {0};
657 
658  info.cbSize = sizeof(TASKDIALOGCONFIG);
659  info.pfCallback = taskdialog_callback_proc;
660  info.lpCallbackData = test_ref_data;
661  info.dwCommonButtons = TDCBF_OK_BUTTON;
662 
663  run_test(&info, IDOK, 0, FALSE, msg_got_tdn_help, "send f1");
664 }
665 
667 {
670 };
671 
673  WPARAM wParam, LPARAM lParam, LONG_PTR ref_data)
674 {
675  struct timer_notification_data *data = (struct timer_notification_data *)ref_data;
676 
677  if (notification == TDN_TIMER)
678  {
679  DWORD elapsed_ms;
680  int delta;
681 
682  elapsed_ms = (DWORD)wParam;
683 
684  if (data->num_fired == 3)
685  ok(data->last_elapsed_ms > elapsed_ms, "Expected reference time update.\n");
686  else
687  {
688  delta = elapsed_ms - data->last_elapsed_ms;
689  ok(delta > 0, "Expected positive time tick difference.\n");
690  }
691  data->last_elapsed_ms = elapsed_ms;
692 
693  if (data->num_fired == 3)
695 
696  ++data->num_fired;
697  return data->num_fired == 3 ? S_FALSE : S_OK;
698  }
699 
700  return S_OK;
701 }
702 
703 static void test_timer(void)
704 {
705  struct timer_notification_data data = { 0 };
706  TASKDIALOGCONFIG info = { 0 };
707 
708  info.cbSize = sizeof(TASKDIALOGCONFIG);
710  info.lpCallbackData = (LONG_PTR)&data;
711  info.dwFlags = TDF_CALLBACK_TIMER;
712  info.dwCommonButtons = TDCBF_OK_BUTTON;
713 
714  pTaskDialogIndirect(&info, NULL, NULL, NULL);
715 }
716 
718  LPARAM lParam, LONG_PTR ref_data)
719 {
720  unsigned long ret;
721  LONG flags = (LONG)ref_data;
722  if (notification == TDN_CREATED)
723  {
724  /* TDM_SET_PROGRESS_BAR_STATE */
725  ret = SendMessageW(hwnd, TDM_SET_PROGRESS_BAR_STATE, PBST_NORMAL, 0);
726  ok(ret == PBST_NORMAL, "Expect state: %d got state: %lx\n", PBST_NORMAL, ret);
727  ret = SendMessageW(hwnd, TDM_SET_PROGRESS_BAR_STATE, PBST_PAUSED, 0);
728  ok(ret == PBST_NORMAL, "Expect state: %d got state: %lx\n", PBST_NORMAL, ret);
729  ret = SendMessageW(hwnd, TDM_SET_PROGRESS_BAR_STATE, PBST_ERROR, 0);
730  /* Progress bar has fixme on handling PBM_SETSTATE message */
731  todo_wine ok(ret == PBST_PAUSED, "Expect state: %d got state: %lx\n", PBST_PAUSED, ret);
732  ret = SendMessageW(hwnd, TDM_SET_PROGRESS_BAR_STATE, PBST_NORMAL, 0);
733  todo_wine ok(ret == PBST_ERROR, "Expect state: %d got state: %lx\n", PBST_ERROR, ret);
734 
735  /* TDM_SET_PROGRESS_BAR_RANGE */
737  ok(ret == MAKELONG(0, 100), "Expect range:%x got:%lx\n", MAKELONG(0, 100), ret);
739  ok(ret == MAKELONG(0, 200), "Expect range:%x got:%lx\n", MAKELONG(0, 200), ret);
740 
741  /* TDM_SET_PROGRESS_BAR_POS */
743  {
745  ok(ret == 0, "Expect position:%x got:%lx\n", 0, ret);
747  ok(ret == 0, "Expect position:%x got:%lx\n", 0, ret);
748  }
749  else
750  {
752  ok(ret == 0, "Expect position:%x got:%lx\n", 0, ret);
754  ok(ret == 1, "Expect position:%x got:%lx\n", 1, ret);
755  }
756 
758  }
759 
760  return S_OK;
761 }
762 
763 static void test_progress_bar(void)
764 {
765  TASKDIALOGCONFIG info = {0};
766 
767  info.cbSize = sizeof(TASKDIALOGCONFIG);
768  info.dwFlags = TDF_SHOW_PROGRESS_BAR;
770  info.lpCallbackData = (LONG_PTR)info.dwFlags;
771  info.dwCommonButtons = TDCBF_OK_BUTTON;
772  pTaskDialogIndirect(&info, NULL, NULL, NULL);
773 
775  info.lpCallbackData = (LONG_PTR)info.dwFlags;
776  pTaskDialogIndirect(&info, NULL, NULL, NULL);
777 
779  info.lpCallbackData = (LONG_PTR)info.dwFlags;
780  pTaskDialogIndirect(&info, NULL, NULL, NULL);
781 }
782 
783 static void test_verification_box(void)
784 {
785  TASKDIALOGCONFIG info = {0};
786  WCHAR textW[] = {'t', 'e', 'x', 't', 0};
787 
788  info.cbSize = sizeof(TASKDIALOGCONFIG);
789  info.pfCallback = taskdialog_callback_proc;
790  info.lpCallbackData = test_ref_data;
791  info.dwCommonButtons = TDCBF_OK_BUTTON;
792 
793  /* TDF_VERIFICATION_FLAG_CHECKED works even if pszVerificationText is not set */
794  run_test(&info, IDOK, 0, FALSE, msg_return_default_verification_unchecked, "default verification box: unchecked");
795 
797  run_test(&info, IDOK, 0, FALSE, msg_return_default_verification_checked, "default verification box: checked");
798 
799  info.pszVerificationText = textW;
800  run_test(&info, IDOK, 0, FALSE, msg_return_default_verification_unchecked, "default verification box: unchecked");
801 
803  run_test(&info, IDOK, 0, FALSE, msg_return_default_verification_checked, "default verification box: checked");
804 
806  "default verification box: default checked and then unchecked");
807 
808  info.dwFlags = 0;
810  "default verification box: default unchecked and then checked");
811 }
812 
813 static void test_navigate_page(void)
814 {
815  TASKDIALOGCONFIG info = {0};
816  static const WCHAR textW[] = {'t', 'e', 'x', 't', 0};
817  static const WCHAR button_format[] = {'%', '0', '2', 'd', 0};
819  WCHAR radio_button_titles[TEST_NUM_BUTTONS * 3];
820  int i;
821 
822  /* Init radio buttons */
823  for (i = 0; i < TEST_NUM_RADIO_BUTTONS; i++)
824  {
825  WCHAR *text = &radio_button_titles[i * 3];
826  wsprintfW(text, button_format, i);
827 
828  radio_buttons[i].pszButtonText = text;
829  radio_buttons[i].nButtonID = ID_START_RADIO_BUTTON + i;
830  }
831 
832  info.cbSize = sizeof(TASKDIALOGCONFIG);
833  info.pfCallback = taskdialog_callback_proc;
834  info.lpCallbackData = test_ref_data;
835  info.dwCommonButtons = TDCBF_OK_BUTTON;
836  info.cRadioButtons = TEST_NUM_RADIO_BUTTONS;
837  info.pRadioButtons = radio_buttons;
838 
842 
843  run_test(&info, IDOK, ID_START_RADIO_BUTTON, TRUE, msg_return_navigated_page, "navigate page: default");
844 
845  /* TDM_NAVIGATE_PAGE doesn't check cbSize.
846  * And null taskconfig pointer crash applicatioin, thus doesn't check pointer either */
848  run_test(&info, IDOK, ID_START_RADIO_BUTTON, TRUE, msg_return_navigated_page, "navigate page: invalid taskconfig cbSize");
849 }
850 
851 static void test_wm_close(void)
852 {
853  TASKDIALOGCONFIG info = {0};
854 
855  info.cbSize = sizeof(TASKDIALOGCONFIG);
856  info.pfCallback = taskdialog_callback_proc;
857  info.lpCallbackData = test_ref_data;
858 
859  /* WM_CLOSE can end the dialog only when a cancel button is present or dwFlags has TDF_ALLOW_DIALOG_CANCELLATION */
860  info.dwCommonButtons = TDCBF_OK_BUTTON;
861  run_test(&info, IDOK, 0, FALSE, msg_handle_wm_close_without_cancel_button, "send WM_CLOSE without cancel button");
862 
864  run_test(&info, IDCANCEL, 0, FALSE, msg_handle_wm_close, "send WM_CLOSE with TDF_ALLOW_DIALOG_CANCELLATION");
865 
866  info.dwFlags = 0;
867  info.dwCommonButtons = TDCBF_CANCEL_BUTTON;
868  run_test(&info, IDCANCEL, 0, FALSE, msg_handle_wm_close, "send WM_CLOSE with a cancel button");
869 }
870 
871 START_TEST(taskdialog)
872 {
873  ULONG_PTR ctx_cookie;
874  void *ptr_ordinal;
876  HANDLE hCtx;
877 
878  if (!load_v6_module(&ctx_cookie, &hCtx))
879  return;
880 
881  /* Check if task dialogs are available */
882  hinst = LoadLibraryA("comctl32.dll");
883 
884  pTaskDialogIndirect = (void *)GetProcAddress(hinst, "TaskDialogIndirect");
885  if (!pTaskDialogIndirect)
886  {
887  win_skip("TaskDialogIndirect not exported by name\n");
888  unload_v6_module(ctx_cookie, hCtx);
889  return;
890  }
891 
892  pTaskDialog = (void *)GetProcAddress(hinst, "TaskDialog");
893 
894  ptr_ordinal = GetProcAddress(hinst, (const char *)344);
895  ok(pTaskDialog == ptr_ordinal, "got wrong pointer for ordinal 344, %p expected %p\n",
896  ptr_ordinal, pTaskDialog);
897 
898  ptr_ordinal = GetProcAddress(hinst, (const char *)345);
899  ok(pTaskDialogIndirect == ptr_ordinal, "got wrong pointer for ordinal 345, %p expected %p\n",
900  ptr_ordinal, pTaskDialogIndirect);
901 
903 
905  test_callback();
906  test_buttons();
907  test_help();
908  test_timer();
912  test_wm_close();
913 
914  unload_v6_module(ctx_cookie, hCtx);
915 }
int WINAPIV wsprintfW(_Out_ LPWSTR, _In_ _Printf_format_string_ LPCWSTR,...)
static const struct message_info msg_return_default_radio_button_2[]
Definition: taskdialog.c:159
static const LONG_PTR test_ref_data
Definition: taskdialog.c:435
static const struct message_info msg_send_close[]
Definition: taskdialog.c:357
static const struct message_info msg_check_verification[]
Definition: taskdialog.c:324
#define WM_TD_CALLBACK
Definition: taskdialog.c:36
const DOCKBAR PVOID HWND HWND * hwnd
Definition: tooldock.h:22
#define LONG_PTR
Definition: treelist.c:79
static const struct message_info msg_return_press_custom4[]
Definition: taskdialog.c:116
Definition: tftpd.h:59
static const struct message_info msg_select_first_disabled_radio_button_and_press_ok[]
Definition: taskdialog.c:190
#define TRUE
Definition: types.h:120
static const struct message_info msg_return_press_cancel[]
Definition: taskdialog.c:95
#define IDOK
Definition: winuser.h:824
static HRESULT(WINAPI *pTaskDialogIndirect)(const TASKDIALOGCONFIG *
static void test_callback(void)
Definition: taskdialog.c:480
HRESULT hr
Definition: shlfolder.c:183
#define IDYES
Definition: winuser.h:829
static const struct message_info msg_press_nonexistent_buttons[]
Definition: taskdialog.c:248
static const struct message_info msg_send_all_common_button_click_with_command[]
Definition: taskdialog.c:261
HRESULT callback_retval
Definition: taskdialog.c:60
Definition: http.c:6587
#define MAKEWORD(a, b)
Definition: typedefs.h:247
static const struct message_info msg_return_press_custom10[]
Definition: taskdialog.c:123
const WCHAR * text
Definition: package.c:1827
#define MAKELPARAM(l, h)
Definition: winuser.h:3947
static const struct message_info msg_handle_wm_close_without_cancel_button[]
Definition: taskdialog.c:378
static void run_test_(TASKDIALOGCONFIG *info, int expect_button, int expect_radio_button, BOOL verification_checked, const struct message_info *test_messages, const char *context, int test_messages_len, const char *file, int line)
Definition: taskdialog.c:399
GLenum GLuint GLenum GLsizei const GLchar * message
Definition: glext.h:5579
#define CALLBACK
Definition: compat.h:27
#define NUM_MSG_SEQUENCES
Definition: taskdialog.c:38
static const struct message_info msg_send_nonexistent_radio_button_click[]
Definition: taskdialog.c:282
HANDLE HWND
Definition: compat.h:13
static void unload_v6_module(ULONG_PTR cookie, HANDLE hCtx)
Definition: v6util.h:63
static const struct message_info msg_send_click_ok[]
Definition: taskdialog.c:130
UINT_PTR WPARAM
Definition: windef.h:207
static void test_timer(void)
Definition: taskdialog.c:703
#define TEST_NUM_RADIO_BUTTONS
Definition: taskdialog.c:42
PCWSTR pszButtonText
Definition: commctrl.h:5157
static const struct message_info msg_return_verification_checked[]
Definition: taskdialog.c:330
static const struct message_info msg_return_press_yes[]
Definition: taskdialog.c:81
#define DWORD
Definition: nt_native.h:44
#define VK_RETURN
Definition: winuser.h:2176
WPARAM wParam
Definition: combotst.c:138
static const struct message_info msg_handle_wm_close[]
Definition: taskdialog.c:363
static const struct message_info msg_return_press_negative_id_radio_button[]
Definition: taskdialog.c:228
struct _test_info info[]
Definition: SetCursorPos.c:19
uint32_t ULONG_PTR
Definition: typedefs.h:63
static const struct message_info msg_return_default_radio_button_3[]
Definition: taskdialog.c:167
static TASKDIALOGCONFIG navigated_info
Definition: taskdialog.c:338
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
static const struct message_info msg_send_close_then_ok[]
Definition: taskdialog.c:371
static BOOL load_v6_module(ULONG_PTR *pcookie, HANDLE *hCtx)
Definition: v6util.h:71
unsigned int BOOL
Definition: ntddk_ex.h:94
static const struct message_info msg_send_f1[]
Definition: taskdialog.c:136
long LONG
Definition: pedump.c:60
static const struct message_info msg_return_default_radio_button_1[]
Definition: taskdialog.c:151
static UINT WPARAM LPARAM lparam
Definition: combo.c:716
HINSTANCE WINAPI DECLSPEC_HOTPATCH LoadLibraryA(LPCSTR lpLibFileName)
Definition: loader.c:111
static void init_msg_sequences(struct msg_sequence **seq, int n)
Definition: msg.h:391
#define S_FALSE
Definition: winerror.h:2357
WPARAM wparam
Definition: taskdialog.c:57
#define E_INVALIDARG
Definition: ddrawi.h:101
#define MAKELONG(a, b)
Definition: typedefs.h:248
static int int BOOL *static const WCHAR const WCHAR const WCHAR const WCHAR int *static struct msg_sequence * sequences[NUM_MSG_SEQUENCES]
Definition: taskdialog.c:52
smooth NULL
Definition: ftsmooth.c:416
static const struct message_info msg_return_no_default_radio_button_flag[]
Definition: taskdialog.c:207
START_TEST(taskdialog)
Definition: taskdialog.c:871
#define WM_KEYDOWN
Definition: winuser.h:1697
#define run_test(info, expect_button, expect_radio_button, verification_checked, seq, context)
Definition: taskdialog.c:395
LONG_PTR LPARAM
Definition: windef.h:208
Definition: parser.c:48
static void test_progress_bar(void)
Definition: taskdialog.c:763
UINT message
Definition: taskdialog.c:56
static void test_navigate_page(void)
Definition: taskdialog.c:813
#define ID_START_BUTTON
Definition: taskdialog.c:45
static const struct message_info msg_return_default_verification_unchecked[]
Definition: taskdialog.c:296
static const struct message_info msg_return_default_radio_button_clicking_disabled[]
Definition: taskdialog.c:198
static const struct message_info msg_select_negative_id_radio_button[]
Definition: taskdialog.c:222
static int int BOOL *static const WCHAR const WCHAR const WCHAR TASKDIALOG_COMMON_BUTTON_FLAGS
Definition: taskdialog.c:49
static void ok_sequence_(struct msg_sequence **seq, int sequence_index, const struct message *expected_list, const char *context, BOOL todo, const char *file, int line)
Definition: msg.h:167
static const struct message_info msg_send_navigate[]
Definition: taskdialog.c:340
__wchar_t WCHAR
Definition: xmlstorage.h:180
LONG HRESULT
Definition: typedefs.h:77
static const struct message_info msg_return_no_default_radio_button_id_and_flag[]
Definition: taskdialog.c:215
#define WM_CLOSE
Definition: winuser.h:1603
#define WINAPI
Definition: msvc.h:8
#define TEST_NUM_BUTTONS
Definition: taskdialog.c:41
#define BN_CLICKED
Definition: winuser.h:1907
unsigned long DWORD
Definition: ntddk_ex.h:95
static const struct message_info msg_return_verification_unchecked[]
Definition: taskdialog.c:316
static const struct message_info msg_return_press_custom1[]
Definition: taskdialog.c:109
#define IDRETRY
Definition: winuser.h:827
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
static const struct message_info msg_return_press_no[]
Definition: taskdialog.c:88
GLbitfield flags
Definition: glext.h:7161
static const struct message_info msg_return_navigated_page[]
Definition: taskdialog.c:346
static void init_test_message(UINT message, WPARAM wParam, LPARAM lParam, struct message *msg)
Definition: taskdialog.c:385
int ret
Definition: msg.h:34
#define todo_wine
Definition: test.h:154
static const struct message_info msg_got_tdn_help[]
Definition: taskdialog.c:142
static const struct message_info msg_send_return[]
Definition: taskdialog.c:67
static void test_wm_close(void)
Definition: taskdialog.c:851
static const struct message_info msg_return_default_verification_checked[]
Definition: taskdialog.c:303
#define WM_COMMAND
Definition: winuser.h:1722
static const struct message_info msg_return_press_ok[]
Definition: taskdialog.c:74
static const WCHAR textW[]
Definition: itemdlg.c:1559
static void test_help(void)
Definition: taskdialog.c:654
static const struct message_info msg_press_nonexistent_buttons_with_command[]
Definition: taskdialog.c:274
static void test_buttons(void)
Definition: taskdialog.c:491
static int int BOOL *static HINSTANCE
Definition: taskdialog.c:49
#define S_OK
Definition: intsafe.h:59
TASKDIALOG_FLAGS dwFlags
Definition: commctrl.h:5173
#define TASKDIALOG_SEQ_INDEX
Definition: taskdialog.c:39
#define add_message(msg)
Definition: msg.c:2142
#define ARRAY_SIZE(a)
Definition: main.h:24
const struct message_info * send
Definition: taskdialog.c:61
LRESULT WINAPI SendMessageW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
#define ok(value,...)
Definition: atltest.h:57
static void flush_sequences(struct msg_sequence **seq, int n)
Definition: msg.h:97
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
static const struct message_info msg_send_all_common_button_click[]
Definition: taskdialog.c:236
unsigned int UINT
Definition: ndis.h:50
static HRESULT CALLBACK taskdialog_callback_proc_progress_bar(HWND hwnd, UINT notification, WPARAM wParam, LPARAM lParam, LONG_PTR ref_data)
Definition: taskdialog.c:717
static const struct message_info msg_select_first_radio_button[]
Definition: taskdialog.c:175
#define msg(x)
Definition: auth_time.c:54
LPARAM lparam
Definition: taskdialog.c:58
PCWSTR pszVerificationText
Definition: commctrl.h:5189
BOOL WINAPI PostMessageW(_In_opt_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
GLenum GLuint id
Definition: glext.h:5579
static HINSTANCE hinst
Definition: edit.c:551
#define GetProcAddress(x, y)
Definition: compat.h:410
static const struct message_info * current_message_info
Definition: taskdialog.c:64
static void test_messages(void)
Definition: propsheet.c:790
#define IDNO
Definition: winuser.h:830
#define IDCANCEL
Definition: winuser.h:825
static const struct message_info msg_press_nonexistent_radio_button[]
Definition: taskdialog.c:289
static const struct message_info msg_uncheck_verification[]
Definition: taskdialog.c:310
#define win_skip
Definition: test.h:141
LPARAM lParam
Definition: combotst.c:139
static HRESULT CALLBACK taskdialog_callback_proc(HWND hwnd, UINT notification, WPARAM wParam, LPARAM lParam, LONG_PTR ref_data)
Definition: taskdialog.c:437
static void test_invalid_parameters(void)
Definition: taskdialog.c:459
struct _TASKDIALOGCONFIG TASKDIALOGCONFIG
#define WM_KEYF1
Definition: msg.c:52
#define ID_START_RADIO_BUTTON
Definition: taskdialog.c:46
static const struct message_info msg_return_first_radio_button[]
Definition: taskdialog.c:181
static UINT WPARAM wparam
Definition: combo.c:716
#define ok_(x1, x2)
Definition: atltest.h:61
static BOOL heap_free(void *mem)
Definition: appwiz.h:75
static const struct message_info msg_return_press_retry[]
Definition: taskdialog.c:102
static void test_verification_box(void)
Definition: taskdialog.c:783
static HRESULT CALLBACK taskdialog_callback_proc_timer(HWND hwnd, UINT notification, WPARAM wParam, LPARAM lParam, LONG_PTR ref_data)
Definition: taskdialog.c:672
Definition: fci.c:126