mirror of
https://github.com/reactos/reactos.git
synced 2024-12-29 10:35:28 +00:00
0707475f69
For SOME reason comctl32 has been synched manually multiple times to different versions and different pots This PR aims to fix that With the exception of button.c which all in all is a massive fork over wines code entirely. and datetime.c which is at wine 6.0 Comctl32 is now at wine-5.0
916 lines
33 KiB
C
916 lines
33 KiB
C
/* Unit tests for the task dialog control.
|
|
*
|
|
* Copyright 2017 Fabian Maurer for the Wine project
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
*/
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include "windef.h"
|
|
#include "winbase.h"
|
|
#include "winuser.h"
|
|
#include "commctrl.h"
|
|
|
|
#include "wine/heap.h"
|
|
#include "wine/test.h"
|
|
#include "v6util.h"
|
|
#include "msg.h"
|
|
|
|
#ifdef __REACTOS__
|
|
#undef WM_KEYF1
|
|
#define WM_KEYF1 0x004d
|
|
#endif
|
|
|
|
#define WM_TD_CALLBACK (WM_APP) /* Custom dummy message to wrap callback notifications */
|
|
|
|
#define NUM_MSG_SEQUENCES 1
|
|
#define TASKDIALOG_SEQ_INDEX 0
|
|
|
|
#define TEST_NUM_BUTTONS 10 /* Number of custom buttons to test with */
|
|
#define TEST_NUM_RADIO_BUTTONS 3
|
|
|
|
#define ID_START 20 /* Lower IDs might be used by the system */
|
|
#define ID_START_BUTTON (ID_START + 0)
|
|
#define ID_START_RADIO_BUTTON (ID_START + 20)
|
|
|
|
static HRESULT (WINAPI *pTaskDialogIndirect)(const TASKDIALOGCONFIG *, int *, int *, BOOL *);
|
|
static HRESULT (WINAPI *pTaskDialog)(HWND, HINSTANCE, const WCHAR *, const WCHAR *, const WCHAR *,
|
|
TASKDIALOG_COMMON_BUTTON_FLAGS, const WCHAR *, int *);
|
|
|
|
static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
|
|
|
|
struct message_info
|
|
{
|
|
UINT message;
|
|
WPARAM wparam;
|
|
LPARAM lparam;
|
|
|
|
HRESULT callback_retval;
|
|
const struct message_info *send; /* Message to send to trigger the next callback message */
|
|
};
|
|
|
|
static const struct message_info *current_message_info;
|
|
|
|
/* Messages to send */
|
|
static const struct message_info msg_send_return[] =
|
|
{
|
|
{ WM_KEYDOWN, VK_RETURN, 0 },
|
|
{ 0 }
|
|
};
|
|
|
|
/* Messages to test against */
|
|
static const struct message_info msg_return_press_ok[] =
|
|
{
|
|
{ TDN_CREATED, 0, 0, S_OK, msg_send_return },
|
|
{ TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
|
|
{ 0 }
|
|
};
|
|
|
|
static const struct message_info msg_return_press_yes[] =
|
|
{
|
|
{ TDN_CREATED, 0, 0, S_OK, msg_send_return },
|
|
{ TDN_BUTTON_CLICKED, IDYES, 0, S_OK, NULL },
|
|
{ 0 }
|
|
};
|
|
|
|
static const struct message_info msg_return_press_no[] =
|
|
{
|
|
{ TDN_CREATED, 0, 0, S_OK, msg_send_return },
|
|
{ TDN_BUTTON_CLICKED, IDNO, 0, S_OK, NULL },
|
|
{ 0 }
|
|
};
|
|
|
|
static const struct message_info msg_return_press_cancel[] =
|
|
{
|
|
{ TDN_CREATED, 0, 0, S_OK, msg_send_return },
|
|
{ TDN_BUTTON_CLICKED, IDCANCEL, 0, S_OK, NULL },
|
|
{ 0 }
|
|
};
|
|
|
|
static const struct message_info msg_return_press_retry[] =
|
|
{
|
|
{ TDN_CREATED, 0, 0, S_OK, msg_send_return },
|
|
{ TDN_BUTTON_CLICKED, IDRETRY, 0, S_OK, NULL },
|
|
{ 0 }
|
|
};
|
|
|
|
static const struct message_info msg_return_press_custom1[] =
|
|
{
|
|
{ TDN_CREATED, 0, 0, S_OK, msg_send_return },
|
|
{ TDN_BUTTON_CLICKED, ID_START_BUTTON, 0, S_OK, NULL },
|
|
{ 0 }
|
|
};
|
|
|
|
static const struct message_info msg_return_press_custom4[] =
|
|
{
|
|
{ TDN_CREATED, 0, 0, S_OK, msg_send_return },
|
|
{ TDN_BUTTON_CLICKED, ID_START_BUTTON + 3, 0, S_OK, NULL },
|
|
{ 0 }
|
|
};
|
|
|
|
static const struct message_info msg_return_press_custom10[] =
|
|
{
|
|
{ TDN_CREATED, 0, 0, S_OK, msg_send_return },
|
|
{ TDN_BUTTON_CLICKED, -1, 0, S_OK, NULL },
|
|
{ 0 }
|
|
};
|
|
|
|
static const struct message_info msg_send_click_ok[] =
|
|
{
|
|
{ TDM_CLICK_BUTTON, IDOK, 0 },
|
|
{ 0 }
|
|
};
|
|
|
|
static const struct message_info msg_send_f1[] =
|
|
{
|
|
{ WM_KEYF1, 0, 0, 0},
|
|
{ 0 }
|
|
};
|
|
|
|
static const struct message_info msg_got_tdn_help[] =
|
|
{
|
|
{ TDN_CREATED, 0, 0, S_OK, msg_send_f1 },
|
|
{ TDN_HELP, 0, 0, S_OK, msg_send_click_ok },
|
|
{ TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
|
|
{ 0 }
|
|
};
|
|
|
|
/* Three radio buttons */
|
|
static const struct message_info msg_return_default_radio_button_1[] =
|
|
{
|
|
{ TDN_CREATED, 0, 0, S_OK, NULL },
|
|
{ TDN_RADIO_BUTTON_CLICKED, ID_START_RADIO_BUTTON, 0, S_OK, msg_send_click_ok },
|
|
{ TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
|
|
{ 0 }
|
|
};
|
|
|
|
static const struct message_info msg_return_default_radio_button_2[] =
|
|
{
|
|
{ TDN_CREATED, 0, 0, S_OK, NULL },
|
|
{ TDN_RADIO_BUTTON_CLICKED, ID_START_RADIO_BUTTON + 1, 0, S_OK, msg_send_click_ok },
|
|
{ TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
|
|
{ 0 }
|
|
};
|
|
|
|
static const struct message_info msg_return_default_radio_button_3[] =
|
|
{
|
|
{ TDN_CREATED, 0, 0, S_OK, NULL },
|
|
{ TDN_RADIO_BUTTON_CLICKED, -2, 0, S_OK, msg_send_click_ok },
|
|
{ TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
|
|
{ 0 }
|
|
};
|
|
|
|
static const struct message_info msg_select_first_radio_button[] =
|
|
{
|
|
{ TDM_CLICK_RADIO_BUTTON, ID_START_RADIO_BUTTON, 0 },
|
|
{ 0 }
|
|
};
|
|
|
|
static const struct message_info msg_return_first_radio_button[] =
|
|
{
|
|
{ TDN_CREATED, 0, 0, S_OK, NULL },
|
|
{ TDN_RADIO_BUTTON_CLICKED, ID_START_RADIO_BUTTON + 1, 0, S_OK, msg_select_first_radio_button },
|
|
{ TDN_RADIO_BUTTON_CLICKED, ID_START_RADIO_BUTTON, 0, S_OK, msg_send_click_ok },
|
|
{ TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
|
|
{ 0 }
|
|
};
|
|
|
|
static const struct message_info msg_select_first_disabled_radio_button_and_press_ok[] =
|
|
{
|
|
{ TDM_ENABLE_RADIO_BUTTON, ID_START_RADIO_BUTTON, 0 },
|
|
{ TDM_CLICK_RADIO_BUTTON, ID_START_RADIO_BUTTON, 0 },
|
|
{ TDM_CLICK_BUTTON, IDOK, 0 },
|
|
{ 0 }
|
|
};
|
|
|
|
static const struct message_info msg_return_default_radio_button_clicking_disabled[] =
|
|
{
|
|
{ TDN_CREATED, 0, 0, S_OK, NULL },
|
|
{ TDN_RADIO_BUTTON_CLICKED, ID_START_RADIO_BUTTON + 1, 0, S_OK, msg_select_first_disabled_radio_button_and_press_ok },
|
|
{ TDN_RADIO_BUTTON_CLICKED, ID_START_RADIO_BUTTON, 0, S_OK, NULL },
|
|
{ TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
|
|
{ 0 }
|
|
};
|
|
|
|
static const struct message_info msg_return_no_default_radio_button_flag[] =
|
|
{
|
|
{ TDN_CREATED, 0, 0, S_OK, msg_send_click_ok },
|
|
{ TDN_RADIO_BUTTON_CLICKED, ID_START_RADIO_BUTTON, 0, S_OK, NULL },
|
|
{ TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
|
|
{ 0 }
|
|
};
|
|
|
|
static const struct message_info msg_return_no_default_radio_button_id_and_flag[] =
|
|
{
|
|
{ TDN_CREATED, 0, 0, S_OK, msg_send_click_ok },
|
|
{ TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
|
|
{ 0 }
|
|
};
|
|
|
|
static const struct message_info msg_select_negative_id_radio_button[] =
|
|
{
|
|
{ TDM_CLICK_RADIO_BUTTON, -2, 0 },
|
|
{ 0 }
|
|
};
|
|
|
|
static const struct message_info msg_return_press_negative_id_radio_button[] =
|
|
{
|
|
{ TDN_CREATED, 0, 0, S_OK, msg_select_negative_id_radio_button },
|
|
{ TDN_RADIO_BUTTON_CLICKED, -2, 0, S_OK, msg_send_click_ok },
|
|
{ TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
|
|
{ 0 }
|
|
};
|
|
|
|
static const struct message_info msg_send_all_common_button_click[] =
|
|
{
|
|
{ TDM_CLICK_BUTTON, IDOK, 0 },
|
|
{ TDM_CLICK_BUTTON, IDYES, 0 },
|
|
{ TDM_CLICK_BUTTON, IDNO, 0 },
|
|
{ TDM_CLICK_BUTTON, IDCANCEL, 0 },
|
|
{ TDM_CLICK_BUTTON, IDRETRY, 0 },
|
|
{ TDM_CLICK_BUTTON, IDCLOSE, 0 },
|
|
{ TDM_CLICK_BUTTON, ID_START_BUTTON + 99, 0 },
|
|
{ 0 }
|
|
};
|
|
|
|
static const struct message_info msg_press_nonexistent_buttons[] =
|
|
{
|
|
{ TDN_CREATED, 0, 0, S_OK, msg_send_all_common_button_click },
|
|
{ TDN_BUTTON_CLICKED, IDOK, 0, S_FALSE, NULL },
|
|
{ TDN_BUTTON_CLICKED, IDYES, 0, S_FALSE, NULL },
|
|
{ TDN_BUTTON_CLICKED, IDNO, 0, S_FALSE, NULL },
|
|
{ TDN_BUTTON_CLICKED, IDCANCEL, 0, S_FALSE, NULL },
|
|
{ TDN_BUTTON_CLICKED, IDRETRY, 0, S_FALSE, NULL },
|
|
{ TDN_BUTTON_CLICKED, IDCLOSE, 0, S_FALSE, NULL },
|
|
{ TDN_BUTTON_CLICKED, ID_START_BUTTON + 99, 0, S_OK, NULL },
|
|
{ 0 }
|
|
};
|
|
|
|
static const struct message_info msg_send_all_common_button_click_with_command[] =
|
|
{
|
|
{ WM_COMMAND, MAKEWORD(IDOK, BN_CLICKED), 0 },
|
|
{ WM_COMMAND, MAKEWORD(IDYES, BN_CLICKED), 0 },
|
|
{ WM_COMMAND, MAKEWORD(IDNO, BN_CLICKED), 0 },
|
|
{ WM_COMMAND, MAKEWORD(IDCANCEL, BN_CLICKED), 0 },
|
|
{ WM_COMMAND, MAKEWORD(IDRETRY, BN_CLICKED), 0 },
|
|
{ WM_COMMAND, MAKEWORD(IDCLOSE, BN_CLICKED), 0 },
|
|
{ WM_COMMAND, MAKEWORD(ID_START_BUTTON + 99, BN_CLICKED), 0 },
|
|
{ WM_COMMAND, MAKEWORD(IDOK, BN_CLICKED), 0 },
|
|
{ 0 }
|
|
};
|
|
|
|
static const struct message_info msg_press_nonexistent_buttons_with_command[] =
|
|
{
|
|
{ TDN_CREATED, 0, 0, S_OK, msg_send_all_common_button_click_with_command },
|
|
{ TDN_BUTTON_CLICKED, ID_START_BUTTON, 0, S_FALSE, NULL },
|
|
{ TDN_BUTTON_CLICKED, ID_START_BUTTON, 0, S_OK, NULL },
|
|
{ 0 }
|
|
};
|
|
|
|
static const struct message_info msg_send_nonexistent_radio_button_click[] =
|
|
{
|
|
{ TDM_CLICK_RADIO_BUTTON, ID_START_RADIO_BUTTON + 99, 0 },
|
|
{ TDM_CLICK_BUTTON, IDOK, 0 },
|
|
{ 0 }
|
|
};
|
|
|
|
static const struct message_info msg_press_nonexistent_radio_button[] =
|
|
{
|
|
{ TDN_CREATED, 0, 0, S_OK, msg_send_nonexistent_radio_button_click },
|
|
{ TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
|
|
{ 0 }
|
|
};
|
|
|
|
static const struct message_info msg_return_default_verification_unchecked[] =
|
|
{
|
|
{ TDN_CREATED, 0, 0, S_OK, msg_send_click_ok },
|
|
{ TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
|
|
{ 0 }
|
|
};
|
|
|
|
static const struct message_info msg_return_default_verification_checked[] =
|
|
{
|
|
{ TDN_CREATED, 0, 0, S_OK, msg_send_click_ok },
|
|
{ TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
|
|
{ 0 }
|
|
};
|
|
|
|
static const struct message_info msg_uncheck_verification[] =
|
|
{
|
|
{ TDM_CLICK_VERIFICATION, FALSE, 0 },
|
|
{ 0 }
|
|
};
|
|
|
|
static const struct message_info msg_return_verification_unchecked[] =
|
|
{
|
|
{ TDN_CREATED, 0, 0, S_OK, msg_uncheck_verification },
|
|
{ TDN_VERIFICATION_CLICKED, FALSE, 0, S_OK, msg_send_click_ok },
|
|
{ TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
|
|
{ 0 }
|
|
};
|
|
|
|
static const struct message_info msg_check_verification[] =
|
|
{
|
|
{ TDM_CLICK_VERIFICATION, TRUE, 0 },
|
|
{ 0 }
|
|
};
|
|
|
|
static const struct message_info msg_return_verification_checked[] =
|
|
{
|
|
{ TDN_CREATED, 0, 0, S_OK, msg_check_verification },
|
|
{ TDN_VERIFICATION_CLICKED, TRUE, 0, S_OK, msg_send_click_ok },
|
|
{ TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
|
|
{ 0 }
|
|
};
|
|
|
|
static TASKDIALOGCONFIG navigated_info = {0};
|
|
|
|
static const struct message_info msg_send_navigate[] =
|
|
{
|
|
{ TDM_NAVIGATE_PAGE, 0, (LPARAM)&navigated_info, 0},
|
|
{ 0 }
|
|
};
|
|
|
|
static const struct message_info msg_return_navigated_page[] =
|
|
{
|
|
{ TDN_CREATED, 0, 0, S_OK, NULL },
|
|
{ TDN_RADIO_BUTTON_CLICKED, ID_START_RADIO_BUTTON, 0, S_OK, msg_send_navigate },
|
|
{ TDN_DIALOG_CONSTRUCTED, 0, 0, S_OK, NULL },
|
|
{ TDN_RADIO_BUTTON_CLICKED, ID_START_RADIO_BUTTON, 0, S_OK, NULL },
|
|
{ TDN_NAVIGATED, 0, 0, S_OK, msg_send_click_ok },
|
|
{ TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
|
|
{ 0 }
|
|
};
|
|
|
|
static const struct message_info msg_send_close[] =
|
|
{
|
|
{ WM_CLOSE, 0, 0, 0},
|
|
{ 0 }
|
|
};
|
|
|
|
static const struct message_info msg_handle_wm_close[] =
|
|
{
|
|
{ TDN_CREATED, 0, 0, S_OK, msg_send_close },
|
|
{ TDN_BUTTON_CLICKED, IDCANCEL, 0, S_FALSE, msg_send_close },
|
|
{ TDN_BUTTON_CLICKED, IDCANCEL, 0, S_OK, NULL },
|
|
{ 0 }
|
|
};
|
|
|
|
static const struct message_info msg_send_close_then_ok[] =
|
|
{
|
|
{ WM_CLOSE, 0, 0, 0},
|
|
{ TDM_CLICK_BUTTON, IDOK, 0 },
|
|
{ 0 }
|
|
};
|
|
|
|
static const struct message_info msg_handle_wm_close_without_cancel_button[] =
|
|
{
|
|
{ TDN_CREATED, 0, 0, S_OK, msg_send_close_then_ok },
|
|
{ TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
|
|
{ 0 }
|
|
};
|
|
|
|
static void init_test_message(UINT message, WPARAM wParam, LPARAM lParam, struct message *msg)
|
|
{
|
|
msg->message = WM_TD_CALLBACK;
|
|
msg->flags = sent|wparam|lparam|id;
|
|
msg->wParam = wParam;
|
|
msg->lParam = lParam;
|
|
msg->id = message;
|
|
msg->stage = 0;
|
|
}
|
|
|
|
#define run_test(info, expect_button, expect_radio_button, verification_checked, seq, context) \
|
|
run_test_(info, expect_button, expect_radio_button, verification_checked, seq, context, \
|
|
ARRAY_SIZE(seq) - 1, __FILE__, __LINE__)
|
|
|
|
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)
|
|
{
|
|
struct message *msg, *msg_start;
|
|
int ret_button = 0;
|
|
int ret_radio = 0;
|
|
BOOL ret_verification = FALSE;
|
|
HRESULT hr;
|
|
int i;
|
|
|
|
/* Allocate messages to test against, plus 2 implicit and 1 empty */
|
|
msg_start = msg = heap_alloc_zero(sizeof(*msg) * (test_messages_len + 3));
|
|
|
|
/* Always needed, thus made implicit */
|
|
init_test_message(TDN_DIALOG_CONSTRUCTED, 0, 0, msg++);
|
|
for (i = 0; i < test_messages_len; i++)
|
|
init_test_message(test_messages[i].message, test_messages[i].wparam, test_messages[i].lparam, msg++);
|
|
/* Always needed, thus made implicit */
|
|
init_test_message(TDN_DESTROYED, 0, 0, msg++);
|
|
|
|
current_message_info = test_messages;
|
|
flush_sequences(sequences, NUM_MSG_SEQUENCES);
|
|
|
|
hr = pTaskDialogIndirect(info, &ret_button, &ret_radio, &ret_verification);
|
|
ok_(file, line)(hr == S_OK, "TaskDialogIndirect() failed, got %#x.\n", hr);
|
|
|
|
ok_sequence_(sequences, TASKDIALOG_SEQ_INDEX, msg_start, context, FALSE, file, line);
|
|
ok_(file, line)(ret_button == expect_button,
|
|
"Wrong button. Expected %d, got %d\n", expect_button, ret_button);
|
|
ok_(file, line)(ret_radio == expect_radio_button,
|
|
"Wrong radio button. Expected %d, got %d\n", expect_radio_button, ret_radio);
|
|
|
|
heap_free(msg_start);
|
|
}
|
|
|
|
static const LONG_PTR test_ref_data = 123456;
|
|
|
|
static HRESULT CALLBACK taskdialog_callback_proc(HWND hwnd, UINT notification,
|
|
WPARAM wParam, LPARAM lParam, LONG_PTR ref_data)
|
|
{
|
|
int msg_pos = sequences[TASKDIALOG_SEQ_INDEX]->count - 1; /* Skip implicit message */
|
|
const struct message_info *msg_send;
|
|
struct message msg;
|
|
|
|
ok(test_ref_data == ref_data, "Unexpected ref data %lu.\n", ref_data);
|
|
|
|
init_test_message(notification, (short)wParam, lParam, &msg);
|
|
add_message(sequences, TASKDIALOG_SEQ_INDEX, &msg);
|
|
|
|
if (notification == TDN_DIALOG_CONSTRUCTED || notification == TDN_DESTROYED) /* Skip implicit messages */
|
|
return S_OK;
|
|
|
|
msg_send = current_message_info[msg_pos].send;
|
|
for(; msg_send && msg_send->message; msg_send++)
|
|
PostMessageW(hwnd, msg_send->message, msg_send->wparam, msg_send->lparam);
|
|
|
|
return current_message_info[msg_pos].callback_retval;
|
|
}
|
|
|
|
static void test_invalid_parameters(void)
|
|
{
|
|
TASKDIALOGCONFIG info = { 0 };
|
|
HRESULT hr;
|
|
|
|
hr = pTaskDialogIndirect(NULL, NULL, NULL, NULL);
|
|
ok(hr == E_INVALIDARG, "Unexpected return value %#x.\n", hr);
|
|
|
|
info.cbSize = 0;
|
|
hr = pTaskDialogIndirect(&info, NULL, NULL, NULL);
|
|
ok(hr == E_INVALIDARG, "Unexpected return value %#x.\n", hr);
|
|
|
|
info.cbSize = sizeof(TASKDIALOGCONFIG) - 1;
|
|
hr = pTaskDialogIndirect(&info, NULL, NULL, NULL);
|
|
ok(hr == E_INVALIDARG, "Unexpected return value %#x.\n", hr);
|
|
|
|
info.cbSize = sizeof(TASKDIALOGCONFIG) + 1;
|
|
hr = pTaskDialogIndirect(&info, NULL, NULL, NULL);
|
|
ok(hr == E_INVALIDARG, "Unexpected return value %#x.\n", hr);
|
|
}
|
|
|
|
static void test_callback(void)
|
|
{
|
|
TASKDIALOGCONFIG info = {0};
|
|
|
|
info.cbSize = sizeof(TASKDIALOGCONFIG);
|
|
info.pfCallback = taskdialog_callback_proc;
|
|
info.lpCallbackData = test_ref_data;
|
|
|
|
run_test(&info, IDOK, 0, FALSE, msg_return_press_ok, "Press VK_RETURN.");
|
|
}
|
|
|
|
static void test_buttons(void)
|
|
{
|
|
TASKDIALOGCONFIG info = {0};
|
|
static const DWORD command_link_flags[] = {0, TDF_USE_COMMAND_LINKS, TDF_USE_COMMAND_LINKS_NO_ICON};
|
|
TASKDIALOG_BUTTON custom_buttons[TEST_NUM_BUTTONS], radio_buttons[TEST_NUM_RADIO_BUTTONS];
|
|
const WCHAR button_format[] = {'%','0','2','d',0};
|
|
/* Each button has two digits as title, plus null-terminator */
|
|
WCHAR button_titles[TEST_NUM_BUTTONS * 3], radio_button_titles[TEST_NUM_BUTTONS * 3];
|
|
int i;
|
|
|
|
info.cbSize = sizeof(TASKDIALOGCONFIG);
|
|
info.pfCallback = taskdialog_callback_proc;
|
|
info.lpCallbackData = test_ref_data;
|
|
|
|
/* Init custom buttons */
|
|
for (i = 0; i < TEST_NUM_BUTTONS; i++)
|
|
{
|
|
WCHAR *text = &button_titles[i * 3];
|
|
wsprintfW(text, button_format, i);
|
|
|
|
custom_buttons[i].pszButtonText = text;
|
|
custom_buttons[i].nButtonID = ID_START_BUTTON + i;
|
|
}
|
|
custom_buttons[TEST_NUM_BUTTONS - 1].nButtonID = -1;
|
|
|
|
/* Init radio buttons */
|
|
for (i = 0; i < TEST_NUM_RADIO_BUTTONS; i++)
|
|
{
|
|
WCHAR *text = &radio_button_titles[i * 3];
|
|
wsprintfW(text, button_format, i);
|
|
|
|
radio_buttons[i].pszButtonText = text;
|
|
radio_buttons[i].nButtonID = ID_START_RADIO_BUTTON + i;
|
|
}
|
|
radio_buttons[TEST_NUM_RADIO_BUTTONS - 1].nButtonID = -2;
|
|
|
|
/* Test nDefaultButton */
|
|
|
|
/* Test common buttons with invalid default ID */
|
|
info.nDefaultButton = 0; /* Should default to first created button */
|
|
info.dwCommonButtons = TDCBF_OK_BUTTON | TDCBF_YES_BUTTON | TDCBF_NO_BUTTON
|
|
| TDCBF_CANCEL_BUTTON | TDCBF_RETRY_BUTTON | TDCBF_CLOSE_BUTTON;
|
|
run_test(&info, IDOK, 0, FALSE, msg_return_press_ok, "default button: unset default");
|
|
info.dwCommonButtons = TDCBF_YES_BUTTON | TDCBF_NO_BUTTON
|
|
| TDCBF_CANCEL_BUTTON | TDCBF_RETRY_BUTTON | TDCBF_CLOSE_BUTTON;
|
|
run_test(&info, IDYES, 0, FALSE, msg_return_press_yes, "default button: unset default");
|
|
info.dwCommonButtons = TDCBF_NO_BUTTON | TDCBF_CANCEL_BUTTON | TDCBF_RETRY_BUTTON | TDCBF_CLOSE_BUTTON;
|
|
run_test(&info, IDNO, 0, FALSE, msg_return_press_no, "default button: unset default");
|
|
info.dwCommonButtons = TDCBF_CANCEL_BUTTON | TDCBF_RETRY_BUTTON | TDCBF_CLOSE_BUTTON;
|
|
run_test(&info, IDRETRY, 0, FALSE, msg_return_press_retry, "default button: unset default");
|
|
info.dwCommonButtons = TDCBF_CANCEL_BUTTON | TDCBF_CLOSE_BUTTON;
|
|
run_test(&info, IDCANCEL, 0, FALSE, msg_return_press_cancel, "default button: unset default");
|
|
|
|
/* Custom buttons could be command links */
|
|
for (i = 0; i < ARRAY_SIZE(command_link_flags); i++)
|
|
{
|
|
info.dwFlags = command_link_flags[i];
|
|
|
|
/* Test with all common and custom buttons and invalid default ID */
|
|
info.nDefaultButton = 0xff; /* Random ID, should also default to first created button */
|
|
info.cButtons = TEST_NUM_BUTTONS;
|
|
info.pButtons = custom_buttons;
|
|
run_test(&info, ID_START_BUTTON, 0, FALSE, msg_return_press_custom1,
|
|
"default button: invalid default, with common buttons - 1");
|
|
|
|
info.nDefaultButton = -1; /* Should work despite button ID -1 */
|
|
run_test(&info, -1, 0, FALSE, msg_return_press_custom10, "default button: invalid default, with common buttons - 2");
|
|
|
|
info.nDefaultButton = -2; /* Should also default to first created button */
|
|
run_test(&info, ID_START_BUTTON, 0, FALSE, msg_return_press_custom1,
|
|
"default button: invalid default, with common buttons - 3");
|
|
|
|
/* Test with only custom buttons and invalid default ID */
|
|
info.dwCommonButtons = 0;
|
|
run_test(&info, ID_START_BUTTON, 0, FALSE, msg_return_press_custom1,
|
|
"default button: invalid default, no common buttons");
|
|
|
|
/* Test with common and custom buttons and valid default ID */
|
|
info.dwCommonButtons = TDCBF_OK_BUTTON | TDCBF_YES_BUTTON | TDCBF_NO_BUTTON | TDCBF_CANCEL_BUTTON
|
|
| TDCBF_RETRY_BUTTON | TDCBF_CLOSE_BUTTON;
|
|
info.nDefaultButton = IDRETRY;
|
|
run_test(&info, IDRETRY, 0, FALSE, msg_return_press_retry, "default button: valid default - 1");
|
|
|
|
/* Test with common and custom buttons and valid default ID */
|
|
info.nDefaultButton = ID_START_BUTTON + 3;
|
|
run_test(&info, ID_START_BUTTON + 3, 0, FALSE, msg_return_press_custom4, "default button: valid default - 2");
|
|
}
|
|
|
|
/* Test radio buttons */
|
|
info.nDefaultButton = 0;
|
|
info.cButtons = 0;
|
|
info.pButtons = 0;
|
|
info.dwCommonButtons = TDCBF_OK_BUTTON;
|
|
info.cRadioButtons = TEST_NUM_RADIO_BUTTONS;
|
|
info.pRadioButtons = radio_buttons;
|
|
|
|
/* Test default first radio button */
|
|
run_test(&info, IDOK, ID_START_RADIO_BUTTON, FALSE, msg_return_default_radio_button_1,
|
|
"default radio button: default first radio button");
|
|
|
|
/* Test default radio button */
|
|
info.nDefaultRadioButton = ID_START_RADIO_BUTTON + 1;
|
|
run_test(&info, IDOK, info.nDefaultRadioButton, FALSE, msg_return_default_radio_button_2,
|
|
"default radio button: default radio button");
|
|
|
|
/* Test default radio button with -2 */
|
|
info.nDefaultRadioButton = -2;
|
|
run_test(&info, IDOK, info.nDefaultRadioButton, FALSE, msg_return_default_radio_button_3,
|
|
"default radio button: default radio button with id -2");
|
|
|
|
/* Test default radio button after clicking the first, messages still work even radio button is disabled */
|
|
info.nDefaultRadioButton = ID_START_RADIO_BUTTON + 1;
|
|
run_test(&info, IDOK, ID_START_RADIO_BUTTON, FALSE, msg_return_first_radio_button,
|
|
"default radio button: radio button after clicking");
|
|
|
|
/* Test radio button after disabling and clicking the first */
|
|
info.nDefaultRadioButton = ID_START_RADIO_BUTTON + 1;
|
|
run_test(&info, IDOK, ID_START_RADIO_BUTTON, FALSE, msg_return_default_radio_button_clicking_disabled,
|
|
"default radio button: disable radio button before clicking");
|
|
|
|
/* 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 */
|
|
info.nDefaultRadioButton = ID_START_RADIO_BUTTON;
|
|
info.dwFlags = TDF_NO_DEFAULT_RADIO_BUTTON;
|
|
run_test(&info, IDOK, info.nDefaultRadioButton, FALSE, msg_return_no_default_radio_button_flag,
|
|
"default radio button: no default radio flag");
|
|
|
|
/* Test no default radio button, TDF_NO_DEFAULT_RADIO_BUTTON is set and nDefaultRadioButton is 0.
|
|
* TDN_RADIO_BUTTON_CLICKED will not be sent, and just radio button not selected */
|
|
info.nDefaultRadioButton = 0;
|
|
info.dwFlags = TDF_NO_DEFAULT_RADIO_BUTTON;
|
|
run_test(&info, IDOK, 0, FALSE, msg_return_no_default_radio_button_id_and_flag,
|
|
"default radio button: no default radio id and flag");
|
|
|
|
/* Test no default radio button, TDF_NO_DEFAULT_RADIO_BUTTON is set and nDefaultRadioButton is invalid.
|
|
* TDN_RADIO_BUTTON_CLICKED will not be sent, and just radio button not selected */
|
|
info.nDefaultRadioButton = 0xff;
|
|
info.dwFlags = TDF_NO_DEFAULT_RADIO_BUTTON;
|
|
run_test(&info, IDOK, 0, FALSE, msg_return_no_default_radio_button_id_and_flag,
|
|
"default radio button: no default flag, invalid id");
|
|
|
|
info.nDefaultRadioButton = 0;
|
|
info.dwFlags = TDF_NO_DEFAULT_RADIO_BUTTON;
|
|
run_test(&info, IDOK, -2, FALSE, msg_return_press_negative_id_radio_button,
|
|
"radio button: manually click radio button with negative id");
|
|
|
|
/* Test sending clicks to non-existent buttons. Notification of non-existent buttons will be sent */
|
|
info.cButtons = TEST_NUM_BUTTONS;
|
|
info.pButtons = custom_buttons;
|
|
info.cRadioButtons = TEST_NUM_RADIO_BUTTONS;
|
|
info.pRadioButtons = radio_buttons;
|
|
info.dwCommonButtons = 0;
|
|
info.dwFlags = TDF_NO_DEFAULT_RADIO_BUTTON;
|
|
run_test(&info, ID_START_BUTTON + 99, 0, FALSE, msg_press_nonexistent_buttons, "sends click to non-existent buttons");
|
|
|
|
/* Non-existent button clicks sent by WM_COMMAND won't generate TDN_BUTTON_CLICKED except IDOK.
|
|
* And will get the first existent button identifier instead of IDOK */
|
|
run_test(&info, ID_START_BUTTON, 0, FALSE, msg_press_nonexistent_buttons_with_command,
|
|
"sends click to non-existent buttons with WM_COMMAND");
|
|
|
|
/* Non-existent radio button won't get notifications */
|
|
run_test(&info, IDOK, 0, FALSE, msg_press_nonexistent_radio_button, "sends click to non-existent radio buttons");
|
|
}
|
|
|
|
static void test_help(void)
|
|
{
|
|
TASKDIALOGCONFIG info = {0};
|
|
|
|
info.cbSize = sizeof(TASKDIALOGCONFIG);
|
|
info.pfCallback = taskdialog_callback_proc;
|
|
info.lpCallbackData = test_ref_data;
|
|
info.dwCommonButtons = TDCBF_OK_BUTTON;
|
|
|
|
run_test(&info, IDOK, 0, FALSE, msg_got_tdn_help, "send f1");
|
|
}
|
|
|
|
struct timer_notification_data
|
|
{
|
|
DWORD last_elapsed_ms;
|
|
DWORD num_fired;
|
|
};
|
|
|
|
static HRESULT CALLBACK taskdialog_callback_proc_timer(HWND hwnd, UINT notification,
|
|
WPARAM wParam, LPARAM lParam, LONG_PTR ref_data)
|
|
{
|
|
struct timer_notification_data *data = (struct timer_notification_data *)ref_data;
|
|
|
|
if (notification == TDN_TIMER)
|
|
{
|
|
DWORD elapsed_ms;
|
|
int delta;
|
|
|
|
elapsed_ms = (DWORD)wParam;
|
|
|
|
if (data->num_fired == 3)
|
|
ok(data->last_elapsed_ms > elapsed_ms, "Expected reference time update.\n");
|
|
else
|
|
{
|
|
delta = elapsed_ms - data->last_elapsed_ms;
|
|
ok(delta > 0, "Expected positive time tick difference.\n");
|
|
}
|
|
data->last_elapsed_ms = elapsed_ms;
|
|
|
|
if (data->num_fired == 3)
|
|
PostMessageW(hwnd, TDM_CLICK_BUTTON, IDOK, 0);
|
|
|
|
++data->num_fired;
|
|
return data->num_fired == 3 ? S_FALSE : S_OK;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
static void test_timer(void)
|
|
{
|
|
struct timer_notification_data data = { 0 };
|
|
TASKDIALOGCONFIG info = { 0 };
|
|
|
|
info.cbSize = sizeof(TASKDIALOGCONFIG);
|
|
info.pfCallback = taskdialog_callback_proc_timer;
|
|
info.lpCallbackData = (LONG_PTR)&data;
|
|
info.dwFlags = TDF_CALLBACK_TIMER;
|
|
info.dwCommonButtons = TDCBF_OK_BUTTON;
|
|
|
|
pTaskDialogIndirect(&info, NULL, NULL, NULL);
|
|
}
|
|
|
|
static HRESULT CALLBACK taskdialog_callback_proc_progress_bar(HWND hwnd, UINT notification, WPARAM wParam,
|
|
LPARAM lParam, LONG_PTR ref_data)
|
|
{
|
|
unsigned long ret;
|
|
LONG flags = (LONG)ref_data;
|
|
if (notification == TDN_CREATED)
|
|
{
|
|
/* TDM_SET_PROGRESS_BAR_STATE */
|
|
ret = SendMessageW(hwnd, TDM_SET_PROGRESS_BAR_STATE, PBST_NORMAL, 0);
|
|
ok(ret == PBST_NORMAL, "Expect state: %d got state: %lx\n", PBST_NORMAL, ret);
|
|
ret = SendMessageW(hwnd, TDM_SET_PROGRESS_BAR_STATE, PBST_PAUSED, 0);
|
|
ok(ret == PBST_NORMAL, "Expect state: %d got state: %lx\n", PBST_NORMAL, ret);
|
|
ret = SendMessageW(hwnd, TDM_SET_PROGRESS_BAR_STATE, PBST_ERROR, 0);
|
|
/* Progress bar has fixme on handling PBM_SETSTATE message */
|
|
todo_wine ok(ret == PBST_PAUSED, "Expect state: %d got state: %lx\n", PBST_PAUSED, ret);
|
|
ret = SendMessageW(hwnd, TDM_SET_PROGRESS_BAR_STATE, PBST_NORMAL, 0);
|
|
todo_wine ok(ret == PBST_ERROR, "Expect state: %d got state: %lx\n", PBST_ERROR, ret);
|
|
|
|
/* TDM_SET_PROGRESS_BAR_RANGE */
|
|
ret = SendMessageW(hwnd, TDM_SET_PROGRESS_BAR_RANGE, 0, MAKELPARAM(0, 200));
|
|
ok(ret == MAKELONG(0, 100), "Expect range:%x got:%lx\n", MAKELONG(0, 100), ret);
|
|
ret = SendMessageW(hwnd, TDM_SET_PROGRESS_BAR_RANGE, 0, MAKELPARAM(0, 200));
|
|
ok(ret == MAKELONG(0, 200), "Expect range:%x got:%lx\n", MAKELONG(0, 200), ret);
|
|
|
|
/* TDM_SET_PROGRESS_BAR_POS */
|
|
if (flags & TDF_SHOW_MARQUEE_PROGRESS_BAR)
|
|
{
|
|
ret = SendMessageW(hwnd, TDM_SET_PROGRESS_BAR_POS, 1, 0);
|
|
ok(ret == 0, "Expect position:%x got:%lx\n", 0, ret);
|
|
ret = SendMessageW(hwnd, TDM_SET_PROGRESS_BAR_POS, 2, 0);
|
|
ok(ret == 0, "Expect position:%x got:%lx\n", 0, ret);
|
|
}
|
|
else
|
|
{
|
|
ret = SendMessageW(hwnd, TDM_SET_PROGRESS_BAR_POS, 1, 0);
|
|
ok(ret == 0, "Expect position:%x got:%lx\n", 0, ret);
|
|
ret = SendMessageW(hwnd, TDM_SET_PROGRESS_BAR_POS, 2, 0);
|
|
ok(ret == 1, "Expect position:%x got:%lx\n", 1, ret);
|
|
}
|
|
|
|
SendMessageW(hwnd, TDM_CLICK_BUTTON, IDOK, 0);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
static void test_progress_bar(void)
|
|
{
|
|
TASKDIALOGCONFIG info = {0};
|
|
|
|
info.cbSize = sizeof(TASKDIALOGCONFIG);
|
|
info.dwFlags = TDF_SHOW_PROGRESS_BAR;
|
|
info.pfCallback = taskdialog_callback_proc_progress_bar;
|
|
info.lpCallbackData = (LONG_PTR)info.dwFlags;
|
|
info.dwCommonButtons = TDCBF_OK_BUTTON;
|
|
pTaskDialogIndirect(&info, NULL, NULL, NULL);
|
|
|
|
info.dwFlags = TDF_SHOW_MARQUEE_PROGRESS_BAR;
|
|
info.lpCallbackData = (LONG_PTR)info.dwFlags;
|
|
pTaskDialogIndirect(&info, NULL, NULL, NULL);
|
|
|
|
info.dwFlags = TDF_SHOW_PROGRESS_BAR | TDF_SHOW_MARQUEE_PROGRESS_BAR;
|
|
info.lpCallbackData = (LONG_PTR)info.dwFlags;
|
|
pTaskDialogIndirect(&info, NULL, NULL, NULL);
|
|
}
|
|
|
|
static void test_verification_box(void)
|
|
{
|
|
TASKDIALOGCONFIG info = {0};
|
|
WCHAR textW[] = {'t', 'e', 'x', 't', 0};
|
|
|
|
info.cbSize = sizeof(TASKDIALOGCONFIG);
|
|
info.pfCallback = taskdialog_callback_proc;
|
|
info.lpCallbackData = test_ref_data;
|
|
info.dwCommonButtons = TDCBF_OK_BUTTON;
|
|
|
|
/* TDF_VERIFICATION_FLAG_CHECKED works even if pszVerificationText is not set */
|
|
run_test(&info, IDOK, 0, FALSE, msg_return_default_verification_unchecked, "default verification box: unchecked");
|
|
|
|
info.dwFlags = TDF_VERIFICATION_FLAG_CHECKED;
|
|
run_test(&info, IDOK, 0, FALSE, msg_return_default_verification_checked, "default verification box: checked");
|
|
|
|
info.pszVerificationText = textW;
|
|
run_test(&info, IDOK, 0, FALSE, msg_return_default_verification_unchecked, "default verification box: unchecked");
|
|
|
|
info.dwFlags = TDF_VERIFICATION_FLAG_CHECKED;
|
|
run_test(&info, IDOK, 0, FALSE, msg_return_default_verification_checked, "default verification box: checked");
|
|
|
|
run_test(&info, IDOK, 0, FALSE, msg_return_verification_unchecked,
|
|
"default verification box: default checked and then unchecked");
|
|
|
|
info.dwFlags = 0;
|
|
run_test(&info, IDOK, 0, FALSE, msg_return_verification_checked,
|
|
"default verification box: default unchecked and then checked");
|
|
}
|
|
|
|
static void test_navigate_page(void)
|
|
{
|
|
TASKDIALOGCONFIG info = {0};
|
|
static const WCHAR textW[] = {'t', 'e', 'x', 't', 0};
|
|
static const WCHAR button_format[] = {'%', '0', '2', 'd', 0};
|
|
TASKDIALOG_BUTTON radio_buttons[TEST_NUM_RADIO_BUTTONS];
|
|
WCHAR radio_button_titles[TEST_NUM_BUTTONS * 3];
|
|
int i;
|
|
|
|
/* Init radio buttons */
|
|
for (i = 0; i < TEST_NUM_RADIO_BUTTONS; i++)
|
|
{
|
|
WCHAR *text = &radio_button_titles[i * 3];
|
|
wsprintfW(text, button_format, i);
|
|
|
|
radio_buttons[i].pszButtonText = text;
|
|
radio_buttons[i].nButtonID = ID_START_RADIO_BUTTON + i;
|
|
}
|
|
|
|
info.cbSize = sizeof(TASKDIALOGCONFIG);
|
|
info.pfCallback = taskdialog_callback_proc;
|
|
info.lpCallbackData = test_ref_data;
|
|
info.dwCommonButtons = TDCBF_OK_BUTTON;
|
|
info.cRadioButtons = TEST_NUM_RADIO_BUTTONS;
|
|
info.pRadioButtons = radio_buttons;
|
|
|
|
navigated_info = info;
|
|
navigated_info.pszVerificationText = textW;
|
|
navigated_info.dwFlags = TDF_VERIFICATION_FLAG_CHECKED;
|
|
|
|
run_test(&info, IDOK, ID_START_RADIO_BUTTON, TRUE, msg_return_navigated_page, "navigate page: default");
|
|
|
|
/* TDM_NAVIGATE_PAGE doesn't check cbSize.
|
|
* And null taskconfig pointer crash applicatioin, thus doesn't check pointer either */
|
|
navigated_info.cbSize = 0;
|
|
run_test(&info, IDOK, ID_START_RADIO_BUTTON, TRUE, msg_return_navigated_page, "navigate page: invalid taskconfig cbSize");
|
|
}
|
|
|
|
static void test_wm_close(void)
|
|
{
|
|
TASKDIALOGCONFIG info = {0};
|
|
|
|
info.cbSize = sizeof(TASKDIALOGCONFIG);
|
|
info.pfCallback = taskdialog_callback_proc;
|
|
info.lpCallbackData = test_ref_data;
|
|
|
|
/* WM_CLOSE can end the dialog only when a cancel button is present or dwFlags has TDF_ALLOW_DIALOG_CANCELLATION */
|
|
info.dwCommonButtons = TDCBF_OK_BUTTON;
|
|
run_test(&info, IDOK, 0, FALSE, msg_handle_wm_close_without_cancel_button, "send WM_CLOSE without cancel button");
|
|
|
|
info.dwFlags = TDF_ALLOW_DIALOG_CANCELLATION;
|
|
run_test(&info, IDCANCEL, 0, FALSE, msg_handle_wm_close, "send WM_CLOSE with TDF_ALLOW_DIALOG_CANCELLATION");
|
|
|
|
info.dwFlags = 0;
|
|
info.dwCommonButtons = TDCBF_CANCEL_BUTTON;
|
|
run_test(&info, IDCANCEL, 0, FALSE, msg_handle_wm_close, "send WM_CLOSE with a cancel button");
|
|
}
|
|
|
|
START_TEST(taskdialog)
|
|
{
|
|
ULONG_PTR ctx_cookie;
|
|
void *ptr_ordinal;
|
|
HINSTANCE hinst;
|
|
HANDLE hCtx;
|
|
|
|
if (!load_v6_module(&ctx_cookie, &hCtx))
|
|
return;
|
|
|
|
/* Check if task dialogs are available */
|
|
hinst = LoadLibraryA("comctl32.dll");
|
|
|
|
pTaskDialogIndirect = (void *)GetProcAddress(hinst, "TaskDialogIndirect");
|
|
if (!pTaskDialogIndirect)
|
|
{
|
|
win_skip("TaskDialogIndirect not exported by name\n");
|
|
unload_v6_module(ctx_cookie, hCtx);
|
|
return;
|
|
}
|
|
|
|
pTaskDialog = (void *)GetProcAddress(hinst, "TaskDialog");
|
|
|
|
ptr_ordinal = GetProcAddress(hinst, (const char *)344);
|
|
ok(pTaskDialog == ptr_ordinal, "got wrong pointer for ordinal 344, %p expected %p\n",
|
|
ptr_ordinal, pTaskDialog);
|
|
|
|
ptr_ordinal = GetProcAddress(hinst, (const char *)345);
|
|
ok(pTaskDialogIndirect == ptr_ordinal, "got wrong pointer for ordinal 345, %p expected %p\n",
|
|
ptr_ordinal, pTaskDialogIndirect);
|
|
|
|
init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
|
|
|
|
test_invalid_parameters();
|
|
test_callback();
|
|
test_buttons();
|
|
test_help();
|
|
test_timer();
|
|
test_progress_bar();
|
|
test_verification_box();
|
|
test_navigate_page();
|
|
test_wm_close();
|
|
|
|
unload_v6_module(ctx_cookie, hCtx);
|
|
}
|