[09/18] comctl32: TaskDialog - make thread-safe

Fabian Maurer dark.shadow4 at web.de
Fri Feb 24 14:04:03 CST 2017


Signed-off-by: Fabian Maurer <dark.shadow4 at web.de>
---
 dlls/comctl32/taskdialog.c | 137 ++++++++++++++++++++++++++++++++++-----------
 1 file changed, 105 insertions(+), 32 deletions(-)

diff --git a/dlls/comctl32/taskdialog.c b/dlls/comctl32/taskdialog.c
index 3d6b99000c..63848303f5 100644
--- a/dlls/comctl32/taskdialog.c
+++ b/dlls/comctl32/taskdialog.c
@@ -69,6 +69,26 @@ typedef struct
     UINT y;
 }button_info;
 
+typedef struct
+{
+    struct list entry;
+    const TASKDIALOGCONFIG *task_config;
+    HFONT font_default;
+    HFONT font_main;
+    HWND hwnd;
+}taskdialog_info;
+
+struct list taskdialogs = LIST_INIT(taskdialogs);
+
+static CRITICAL_SECTION taskdialog_section;
+static CRITICAL_SECTION_DEBUG taskdialog_section_debug =
+{
+    0, 0, &taskdialog_section,
+    { &taskdialog_section_debug.ProcessLocksList, &taskdialog_section_debug.ProcessLocksList },
+      0, 0, { (DWORD_PTR)(__FILE__ ": taskdialog_section") }
+};
+static CRITICAL_SECTION taskdialog_section = { &taskdialog_section_debug, -1, 0, 0, 0, 0 };
+
 #define MEMCPY_MOVEPTR(target, source, size) memcpy(target, source, size); target += size;
 
 #define STR_SIZE(str) ((lstrlenW(str) + 1) * sizeof(WCHAR))
@@ -220,6 +240,55 @@ static DLGITEMTEMPLATE* controls_add(struct list *controls, WORD id, const WCHAR
     return &data->template;
 }
 
+/* Functions to control thread safe taskdialog information */
+
+static void taskdialog_info_init(taskdialog_info **taskdialog, const TASKDIALOGCONFIG *pTaskConfig)
+{
+    static const WCHAR font_name[] = {'T','a','h','o','m','a',0};
+    taskdialog_info *dialog;
+
+    dialog = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(taskdialog_info));
+
+    EnterCriticalSection(&taskdialog_section);
+    list_add_tail(&taskdialogs, &dialog->entry);
+    LeaveCriticalSection(&taskdialog_section);
+
+    dialog->task_config = pTaskConfig;
+    dialog->font_default = CreateFontW (16, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE,
+                                DEFAULT_CHARSET, 0, 0, CLEARTYPE_QUALITY,  FF_DONTCARE, font_name);
+    dialog->font_main = CreateFontW (19, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE,
+                                DEFAULT_CHARSET, 0, 0, CLEARTYPE_QUALITY,  FF_DONTCARE, font_name);
+
+    *taskdialog = dialog;
+}
+
+static void taskdialog_info_destroy(taskdialog_info *taskdialog)
+{
+    DeleteObject(taskdialog->font_main);
+    DeleteObject(taskdialog->font_default);
+
+    EnterCriticalSection(&taskdialog_section);
+    list_remove(&taskdialog->entry);
+    HeapFree(GetProcessHeap(), 0, taskdialog);
+    LeaveCriticalSection(&taskdialog_section);
+}
+
+static taskdialog_info* taskdialog_info_get(HWND hwnd)
+{
+    taskdialog_info *ret = NULL;
+    taskdialog_info *dialog;
+
+    EnterCriticalSection(&taskdialog_section);
+    LIST_FOR_EACH_ENTRY(dialog, &taskdialogs, taskdialog_info, entry)
+    {
+        if(dialog->hwnd == hwnd)
+            ret = dialog;
+    }
+    LeaveCriticalSection(&taskdialog_section);
+
+    return ret;
+}
+
 /* used to calculate size for the static controls */
 static RECT text_get_rect(HDC hdc, const WCHAR *text, UINT dialog_width)
 {
@@ -234,39 +303,50 @@ static RECT text_get_rect(HDC hdc, const WCHAR *text, UINT dialog_width)
     return rect;
 }
 
-/* FIXME: Make thread safe? */
-static const TASKDIALOGCONFIG *task_config = 0;
-static HFONT font_default, font_main;
+/* DialogProc and helper functions */
 
-static HRESULT callback(HWND hwnd, UINT uNotification, WPARAM wParam, LPARAM lParam)
+static HRESULT callback(taskdialog_info *dialog, UINT uNotification, WPARAM wParam, LPARAM lParam)
 {
+    const TASKDIALOGCONFIG *task_config = dialog->task_config;
+
     if(task_config->pfCallback)
-        return task_config->pfCallback(hwnd, uNotification, wParam, lParam, task_config->lpCallbackData);
+        return task_config->pfCallback(dialog->hwnd, uNotification, wParam, lParam, task_config->lpCallbackData);
     return S_OK;
 }
 
 static INT_PTR CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
 {
     HRESULT ret_callback;
+    taskdialog_info *dialog;
+    const TASKDIALOGCONFIG *task_config;
+
+    if(uMsg == WM_INITDIALOG)
+    {
+        dialog = (taskdialog_info *)lParam;
+        dialog->hwnd = hwndDlg;
+    }
+    else
+        dialog = taskdialog_info_get(hwndDlg);
+    task_config = dialog->task_config;
 
     switch (uMsg)
     {
         case WM_INITDIALOG:
-            PostMessageW(GetDlgItem(hwndDlg, ID_TEXTMAIN), WM_SETFONT, (WPARAM)font_main, TRUE);
-            PostMessageW(GetDlgItem(hwndDlg, ID_TEXTCONTENT), WM_SETFONT, (WPARAM)font_default, TRUE);
+            PostMessageW(GetDlgItem(hwndDlg, ID_TEXTMAIN), WM_SETFONT, (WPARAM)dialog->font_main, TRUE);
+            PostMessageW(GetDlgItem(hwndDlg, ID_TEXTCONTENT), WM_SETFONT, (WPARAM)dialog->font_default, TRUE);
 
             if(task_config->dwCommonButtons & TDCBF_OK_BUTTON)
-                PostMessageW(GetDlgItem(hwndDlg, IDOK), WM_SETFONT, (WPARAM)font_default, TRUE);
+                PostMessageW(GetDlgItem(hwndDlg, IDOK), WM_SETFONT, (WPARAM)dialog->font_default, TRUE);
             if(task_config->dwCommonButtons & TDCBF_YES_BUTTON)
-                PostMessageW(GetDlgItem(hwndDlg, IDYES), WM_SETFONT, (WPARAM)font_default, TRUE);
+                PostMessageW(GetDlgItem(hwndDlg, IDYES), WM_SETFONT, (WPARAM)dialog->font_default, TRUE);
             if(task_config->dwCommonButtons & TDCBF_NO_BUTTON)
-                PostMessageW(GetDlgItem(hwndDlg, IDNO), WM_SETFONT, (WPARAM)font_default, TRUE);
+                PostMessageW(GetDlgItem(hwndDlg, IDNO), WM_SETFONT, (WPARAM)dialog->font_default, TRUE);
             if(task_config->dwCommonButtons & TDCBF_CANCEL_BUTTON)
-                PostMessageW(GetDlgItem(hwndDlg, IDCANCEL), WM_SETFONT, (WPARAM)font_default, TRUE);
+                PostMessageW(GetDlgItem(hwndDlg, IDCANCEL), WM_SETFONT, (WPARAM)dialog->font_default, TRUE);
             if(task_config->dwCommonButtons & TDCBF_RETRY_BUTTON)
-                PostMessageW(GetDlgItem(hwndDlg, IDRETRY), WM_SETFONT, (WPARAM)font_default, TRUE);
+                PostMessageW(GetDlgItem(hwndDlg, IDRETRY), WM_SETFONT, (WPARAM)dialog->font_default, TRUE);
             if(task_config->dwCommonButtons & TDCBF_CLOSE_BUTTON)
-                PostMessageW(GetDlgItem(hwndDlg, IDCLOSE), WM_SETFONT, (WPARAM)font_default, TRUE);
+                PostMessageW(GetDlgItem(hwndDlg, IDCLOSE), WM_SETFONT, (WPARAM)dialog->font_default, TRUE);
 
             if(task_config->cButtons && task_config->pButtons)
             {
@@ -274,12 +354,12 @@ static INT_PTR CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARA
                 for(i=0; i< task_config->cButtons; i++)
                 {
                     PostMessageW(GetDlgItem(hwndDlg, task_config->pButtons[i].nButtonID),
-                                 WM_SETFONT, (WPARAM)font_default, TRUE);
+                                 WM_SETFONT, (WPARAM)dialog->font_default, TRUE);
                 }
             }
 
-            callback(hwndDlg, TDN_DIALOG_CONSTRUCTED, 0, 0);
-            callback(hwndDlg, TDN_CREATED, 0, 0);
+            callback(dialog, TDN_DIALOG_CONSTRUCTED, 0, 0);
+            callback(dialog, TDN_CREATED, 0, 0);
 
             return TRUE;
         case WM_CTLCOLORSTATIC:
@@ -298,12 +378,12 @@ static INT_PTR CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARA
             {
                 WORD command_id = LOWORD(wParam);
 
-                ret_callback = callback(hwndDlg, TDN_BUTTON_CLICKED, command_id, 0);
+                ret_callback = callback(dialog, TDN_BUTTON_CLICKED, command_id, 0);
                 if(ret_callback == S_OK) /* FIXME */
                 {
                     EndDialog(hwndDlg, command_id);
 
-                    callback(hwndDlg, TDN_DESTROYED, 0, 0);
+                    callback(dialog, TDN_DESTROYED, 0, 0);
                 }
                 return TRUE;
             }
@@ -431,8 +511,8 @@ HRESULT WINAPI TaskDialogIndirect(const TASKDIALOGCONFIG *pTaskConfig, int *pnBu
                                   int *pnRadioButton, BOOL *pfVerificationFlagChecked)
 {
     static const WCHAR empty_string[] = {0};
-    static const WCHAR font_name[] = {'T','a','h','o','m','a',0};
     static const WCHAR class_static[] = {'S','t','a','t','i','c',0};
+    taskdialog_info *dialog;
     RECT desktop;
     UINT dialog_width; /* In dialog units */
     UINT dialog_height; /* In dialog units */
@@ -446,17 +526,11 @@ HRESULT WINAPI TaskDialogIndirect(const TASKDIALOGCONFIG *pTaskConfig, int *pnBu
     if (!pTaskConfig || pTaskConfig->cbSize != sizeof(TASKDIALOGCONFIG))
         return E_INVALIDARG;
 
-    task_config = pTaskConfig;
-
+    taskdialog_info_init(&dialog, pTaskConfig);
     controls_init(&controls);
 
-    font_default = CreateFontW (16, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE,
-                                DEFAULT_CHARSET, 0, 0, CLEARTYPE_QUALITY,  FF_DONTCARE, font_name);
-    font_main = CreateFontW (19, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE,
-                                DEFAULT_CHARSET, 0, 0, CLEARTYPE_QUALITY,  FF_DONTCARE, font_name);
-
     dc_dummy = CreateCompatibleDC(NULL);
-    SelectObject(dc_dummy, font_default);
+    SelectObject(dc_dummy, dialog->font_default);
 
     get_desktop_size(&desktop, pTaskConfig->hwndParent);
     dialog_height = 5;
@@ -475,14 +549,14 @@ HRESULT WINAPI TaskDialogIndirect(const TASKDIALOGCONFIG *pTaskConfig, int *pnBu
     {
         RECT rect;
 
-        SelectObject(dc_dummy, font_main);
+        SelectObject(dc_dummy, dialog->font_main);
         rect = text_get_rect(dc_dummy, pTaskConfig->pszMainInstruction, dialog_width);
 
         controls_add(controls, ID_TEXTMAIN, class_static, pTaskConfig->pszMainInstruction,
                      WS_CHILD | WS_VISIBLE, 5, dialog_height + 5, rect.right, rect.bottom);
 
         dialog_height += rect.bottom + 10;
-        SelectObject(dc_dummy, font_default);
+        SelectObject(dc_dummy, dialog->font_default);
     }
 
     if(!STR_EMPTY(pTaskConfig->pszContent))
@@ -515,15 +589,14 @@ 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);
+    DialogBoxIndirectParamW(pTaskConfig->hInstance, template_data, pTaskConfig->hwndParent, DialogProc, (LPARAM)dialog);
 
     /* Cleanup */
 
     DeleteDC(dc_dummy);
-    DeleteObject(font_main);
-    DeleteObject(font_default);
     dialog_template_destroy(template_data);
     controls_destroy(controls);
+    taskdialog_info_destroy(dialog);
 
     return S_OK;
 }
-- 
2.11.1




More information about the wine-patches mailing list