[v3 06/12] comctl32: TaskDialog - make thread-safe
Fabian Maurer
dark.shadow4 at web.de
Fri Mar 10 12:21:58 CST 2017
v3: Rewrite to implement Nikolay Sivov's suggestions
Signed-off-by: Fabian Maurer <dark.shadow4 at web.de>
---
dlls/comctl32/taskdialog.c | 49 ++++++++++++++++++++++++++++++++++++----------
1 file changed, 39 insertions(+), 10 deletions(-)
diff --git a/dlls/comctl32/taskdialog.c b/dlls/comctl32/taskdialog.c
index 655d75228c..fb179c35c3 100644
--- a/dlls/comctl32/taskdialog.c
+++ b/dlls/comctl32/taskdialog.c
@@ -61,6 +61,21 @@ typedef struct
UINT titleSize; /* Length in bytes including null-terminator */
}dialog_header;
+typedef struct
+{
+ int id;
+ const WCHAR *text;
+ UINT width;
+ UINT x;
+ UINT y;
+}button_info;
+
+typedef struct
+{
+ const TASKDIALOGCONFIG *task_config;
+ HWND hwnd;
+}taskdialog_info;
+
#define MEMCPY_MOVEPTR(target, source, size) memcpy(target, source, size); target += size;
static void* align_pointer(void *ptr, unsigned int boundary)
@@ -184,31 +199,43 @@ static void controls_add(struct list *controls, WORD id, const WCHAR *class, con
list_add_tail(controls, &data->entry);
}
-/* FIXME: Make thread safe */
-static const TASKDIALOGCONFIG *task_config = 0;
-static HRESULT callback(HWND hwnd, UINT uNotification, WPARAM wParam, LPARAM lParam)
+/* DialogProc and helper functions */
+
+static HRESULT callback(taskdialog_info *dialog_info, UINT uNotification, WPARAM wParam, LPARAM lParam)
{
+ const TASKDIALOGCONFIG *task_config = dialog_info->task_config;
+
if(task_config->pfCallback)
- return task_config->pfCallback(hwnd, uNotification, wParam, lParam, task_config->lpCallbackData);
+ return task_config->pfCallback(dialog_info->hwnd, uNotification, wParam, lParam, task_config->lpCallbackData);
return S_OK;
}
static INT_PTR CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
+ static const WCHAR taskdialog_info_propnameW[] = {'T','a','s','k','D','i','a','l','o','g','I','n','f','o',0};
HRESULT ret_callback;
+ taskdialog_info *dialog_info;
+
+ if(uMsg != WM_INITDIALOG && uMsg != WM_NCDESTROY)
+ dialog_info = GetPropW(hwndDlg, taskdialog_info_propnameW);
switch (uMsg)
{
case WM_INITDIALOG:
- callback(hwndDlg, TDN_DIALOG_CONSTRUCTED, 0, 0);
- callback(hwndDlg, TDN_CREATED, 0, 0);
+ dialog_info = (taskdialog_info *)lParam;
+ dialog_info->hwnd = hwndDlg;
+ SetPropW(hwndDlg, taskdialog_info_propnameW, dialog_info);
+
+ callback(dialog_info, TDN_DIALOG_CONSTRUCTED, 0, 0);
+ callback(dialog_info, TDN_CREATED, 0, 0);
+
return TRUE;
case WM_COMMAND:
if(HIWORD(wParam) == BN_CLICKED)
{
WORD command_id = LOWORD(wParam);
- ret_callback = callback(hwndDlg, TDN_BUTTON_CLICKED, command_id, 0);
+ ret_callback = callback(dialog_info, TDN_BUTTON_CLICKED, command_id, 0);
if(ret_callback == S_OK) /* FIXME */
{
EndDialog(hwndDlg, command_id);
@@ -217,7 +244,8 @@ static INT_PTR CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARA
}
break;
case WM_DESTROY:
- callback(hwndDlg, TDN_DESTROYED, 0, 0);
+ callback(dialog_info, TDN_DESTROYED, 0, 0);
+ RemovePropW(hwndDlg, taskdialog_info_propnameW);
break;
}
return FALSE;
@@ -231,6 +259,7 @@ HRESULT WINAPI TaskDialogIndirect(const TASKDIALOGCONFIG *pTaskConfig, int *pnBu
{
static const WCHAR empty_string[] = {0};
static const WCHAR text_ok[] = {'O','K',0};
+ taskdialog_info dialog_info;
RECT desktop;
UINT dialog_width; /* In dialog units */
UINT dialog_height; /* In dialog units */
@@ -243,7 +272,6 @@ HRESULT WINAPI TaskDialogIndirect(const TASKDIALOGCONFIG *pTaskConfig, int *pnBu
if (!pTaskConfig || pTaskConfig->cbSize != sizeof(TASKDIALOGCONFIG))
return E_INVALIDARG;
- task_config = pTaskConfig;
list_init(&controls);
get_desktop_size(&desktop, pTaskConfig->hwndParent);
@@ -278,7 +306,8 @@ HRESULT WINAPI TaskDialogIndirect(const TASKDIALOGCONFIG *pTaskConfig, int *pnBu
/* Turn template information into a dialog template to display it */
template_data = dialog_template_create(header, &controls);
- DialogBoxIndirectParamW(pTaskConfig->hInstance, template_data, pTaskConfig->hwndParent, DialogProc, 0);
+ dialog_info.task_config = pTaskConfig;
+ DialogBoxIndirectParamW(pTaskConfig->hInstance, template_data, pTaskConfig->hwndParent, DialogProc, (LPARAM)&dialog_info);
/* Cleanup */
--
2.12.0
More information about the wine-patches
mailing list