[PATCH 06/11] winemac: Use unixlib interface for macdrv_app_quit_request.

Jacek Caban wine at gitlab.winehq.org
Thu Jun 2 19:51:21 CDT 2022


From: Jacek Caban <jacek at codeweavers.com>

Signed-off-by: Jacek Caban <jacek at codeweavers.com>
---
 dlls/winemac.drv/dllmain.c     | 174 +++++++++++++++++++++++++++++++++
 dlls/winemac.drv/macdrv_main.c |   9 ++
 dlls/winemac.drv/unixlib.h     |  16 ++-
 dlls/winemac.drv/window.c      | 168 +------------------------------
 4 files changed, 202 insertions(+), 165 deletions(-)

diff --git a/dlls/winemac.drv/dllmain.c b/dlls/winemac.drv/dllmain.c
index 4bedb2aaf61..675820b28cd 100644
--- a/dlls/winemac.drv/dllmain.c
+++ b/dlls/winemac.drv/dllmain.c
@@ -22,13 +22,187 @@
 #include <stdarg.h>
 #include "macdrv.h"
 #include "shellapi.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(macdrv);
 
 
 HMODULE macdrv_module = 0;
 
+struct quit_info {
+    HWND               *wins;
+    UINT                capacity;
+    UINT                count;
+    UINT                done;
+    DWORD               flags;
+    BOOL                result;
+    BOOL                replied;
+};
+
+
+static BOOL CALLBACK get_process_windows(HWND hwnd, LPARAM lp)
+{
+    struct quit_info *qi = (struct quit_info*)lp;
+    DWORD pid;
+
+    NtUserGetWindowThread(hwnd, &pid);
+    if (pid == GetCurrentProcessId())
+    {
+        if (qi->count >= qi->capacity)
+        {
+            UINT new_cap = qi->capacity * 2;
+            HWND *new_wins = HeapReAlloc(GetProcessHeap(), 0, qi->wins, new_cap * sizeof(*qi->wins));
+            if (!new_wins) return FALSE;
+            qi->wins = new_wins;
+            qi->capacity = new_cap;
+        }
+
+        qi->wins[qi->count++] = hwnd;
+    }
+
+    return TRUE;
+}
+
+static void quit_reply(int reply)
+{
+    struct quit_result_params params = { .result = reply };
+    MACDRV_CALL(quit_result, &params);
+}
+
+
+static void CALLBACK quit_callback(HWND hwnd, UINT msg, ULONG_PTR data, LRESULT result)
+{
+    struct quit_info *qi = (struct quit_info*)data;
+
+    qi->done++;
+
+    if (msg == WM_QUERYENDSESSION)
+    {
+        TRACE("got WM_QUERYENDSESSION result %ld from win %p (%u of %u done)\n", result,
+              hwnd, qi->done, qi->count);
+
+        if (!result && !IsWindow(hwnd))
+        {
+            TRACE("win %p no longer exists; ignoring apparent refusal\n", hwnd);
+            result = TRUE;
+        }
+
+        if (!result && qi->result)
+        {
+            qi->result = FALSE;
+
+            /* On the first FALSE from WM_QUERYENDSESSION, we already know the
+               ultimate reply.  Might as well tell Cocoa now. */
+            if (!qi->replied)
+            {
+                qi->replied = TRUE;
+                TRACE("giving quit reply %d\n", qi->result);
+                quit_reply(qi->result);
+            }
+        }
+
+        if (qi->done >= qi->count)
+        {
+            UINT i;
+
+            qi->done = 0;
+            for (i = 0; i < qi->count; i++)
+            {
+                TRACE("sending WM_ENDSESSION to win %p result %d flags 0x%08x\n", qi->wins[i],
+                      qi->result, qi->flags);
+                if (!SendMessageCallbackW(qi->wins[i], WM_ENDSESSION, qi->result, qi->flags,
+                                          quit_callback, (ULONG_PTR)qi))
+                {
+                    WARN("failed to send WM_ENDSESSION to win %p; error 0x%08x\n",
+                         qi->wins[i], GetLastError());
+                    quit_callback(qi->wins[i], WM_ENDSESSION, (ULONG_PTR)qi, 0);
+                }
+            }
+        }
+    }
+    else /* WM_ENDSESSION */
+    {
+        TRACE("finished WM_ENDSESSION for win %p (%u of %u done)\n", hwnd, qi->done, qi->count);
+
+        if (qi->done >= qi->count)
+        {
+            if (!qi->replied)
+            {
+                TRACE("giving quit reply %d\n", qi->result);
+                quit_reply(qi->result);
+            }
+
+            TRACE("%sterminating process\n", qi->result ? "" : "not ");
+            if (qi->result)
+                TerminateProcess(GetCurrentProcess(), 0);
+
+            HeapFree(GetProcessHeap(), 0, qi->wins);
+            HeapFree(GetProcessHeap(), 0, qi);
+        }
+    }
+}
+
+
+/***********************************************************************
+ *              macdrv_app_quit_request
+ */
+NTSTATUS WINAPI macdrv_app_quit_request(void *arg, ULONG size)
+{
+    struct app_quit_request_params *params = arg;
+    struct quit_info *qi;
+    UINT i;
+
+    qi = HeapAlloc(GetProcessHeap(), 0, sizeof(*qi));
+    if (!qi)
+        goto fail;
+
+    qi->capacity = 32;
+    qi->wins = HeapAlloc(GetProcessHeap(), 0, qi->capacity * sizeof(*qi->wins));
+    qi->count = qi->done = 0;
+
+    if (!qi->wins || !EnumWindows(get_process_windows, (LPARAM)qi))
+        goto fail;
+
+    qi->flags = params->flags;
+    qi->result = TRUE;
+    qi->replied = FALSE;
+
+    for (i = 0; i < qi->count; i++)
+    {
+        TRACE("sending WM_QUERYENDSESSION to win %p\n", qi->wins[i]);
+        if (!SendMessageCallbackW(qi->wins[i], WM_QUERYENDSESSION, 0, qi->flags,
+                                  quit_callback, (ULONG_PTR)qi))
+        {
+            DWORD error = GetLastError();
+            BOOL invalid = (error == ERROR_INVALID_WINDOW_HANDLE);
+            if (invalid)
+                TRACE("failed to send WM_QUERYENDSESSION to win %p because it's invalid; assuming success\n",
+                     qi->wins[i]);
+            else
+                WARN("failed to send WM_QUERYENDSESSION to win %p; error 0x%08x; assuming refusal\n",
+                     qi->wins[i], error);
+            quit_callback(qi->wins[i], WM_QUERYENDSESSION, (ULONG_PTR)qi, invalid);
+        }
+    }
+
+    /* quit_callback() will clean up qi */
+    return 0;
+
+fail:
+    WARN("failed to allocate window list\n");
+    if (qi)
+    {
+        HeapFree(GetProcessHeap(), 0, qi->wins);
+        HeapFree(GetProcessHeap(), 0, qi);
+    }
+    quit_reply(FALSE);
+    return 0;
+}
+
 typedef NTSTATUS (WINAPI *kernel_callback)(void *params, ULONG size);
 static const kernel_callback kernel_callbacks[] =
 {
+    macdrv_app_quit_request,
     macdrv_dnd_query_drag,
     macdrv_dnd_query_drop,
     macdrv_dnd_query_exited,
diff --git a/dlls/winemac.drv/macdrv_main.c b/dlls/winemac.drv/macdrv_main.c
index 61195d408c8..ddd4f03fd31 100644
--- a/dlls/winemac.drv/macdrv_main.c
+++ b/dlls/winemac.drv/macdrv_main.c
@@ -628,6 +628,14 @@ static NTSTATUS macdrv_ime_using_input_method(void *arg)
 }
 
 
+static NTSTATUS macdrv_quit_result(void *arg)
+{
+    struct quit_result_params *params = arg;
+    macdrv_quit_reply(params->result);
+    return 0;
+}
+
+
 const unixlib_entry_t __wine_unix_call_funcs[] =
 {
     macdrv_dnd_get_data,
@@ -640,6 +648,7 @@ const unixlib_entry_t __wine_unix_call_funcs[] =
     macdrv_ime_using_input_method,
     macdrv_init,
     macdrv_notify_icon,
+    macdrv_quit_result,
 };
 
 C_ASSERT( ARRAYSIZE(__wine_unix_call_funcs) == unix_funcs_count );
diff --git a/dlls/winemac.drv/unixlib.h b/dlls/winemac.drv/unixlib.h
index 0bfc61321d0..894ab699c13 100644
--- a/dlls/winemac.drv/unixlib.h
+++ b/dlls/winemac.drv/unixlib.h
@@ -31,6 +31,7 @@ enum macdrv_funcs
     unix_ime_using_input_method,
     unix_init,
     unix_notify_icon,
+    unix_quit_result,
     unix_funcs_count
 };
 
@@ -92,10 +93,17 @@ struct notify_icon_params
     struct _NOTIFYICONDATAW *data;
 };
 
+/* macdrv_quit_result params */
+struct quit_result_params
+{
+    int result;
+};
+
 /* driver client callbacks exposed with KernelCallbackTable interface */
 enum macdrv_client_funcs
 {
-    client_func_dnd_query_drag = NtUserDriverCallbackFirst,
+    client_func_app_quit_request = NtUserDriverCallbackFirst,
+    client_func_dnd_query_drag,
     client_func_dnd_query_drop,
     client_func_dnd_query_exited,
     client_func_ime_query_char_rect,
@@ -103,6 +111,12 @@ enum macdrv_client_funcs
     client_func_last
 };
 
+/* macdrv_app_quit_request params */
+struct app_quit_request_params
+{
+    UINT flags;
+};
+
 /* macdrv_dnd_query_drag params */
 struct dnd_query_drag_params
 {
diff --git a/dlls/winemac.drv/window.c b/dlls/winemac.drv/window.c
index 2f473730b2f..072bdf606d4 100644
--- a/dlls/winemac.drv/window.c
+++ b/dlls/winemac.drv/window.c
@@ -2653,114 +2653,6 @@ void macdrv_reassert_window_position(HWND hwnd)
 }
 
 
-struct quit_info {
-    HWND               *wins;
-    UINT                capacity;
-    UINT                count;
-    UINT                done;
-    DWORD               flags;
-    BOOL                result;
-    BOOL                replied;
-};
-
-
-static BOOL CALLBACK get_process_windows(HWND hwnd, LPARAM lp)
-{
-    struct quit_info *qi = (struct quit_info*)lp;
-    DWORD pid;
-
-    NtUserGetWindowThread(hwnd, &pid);
-    if (pid == GetCurrentProcessId())
-    {
-        if (qi->count >= qi->capacity)
-        {
-            UINT new_cap = qi->capacity * 2;
-            HWND *new_wins = realloc(qi->wins, new_cap * sizeof(*qi->wins));
-            if (!new_wins) return FALSE;
-            qi->wins = new_wins;
-            qi->capacity = new_cap;
-        }
-
-        qi->wins[qi->count++] = hwnd;
-    }
-
-    return TRUE;
-}
-
-
-static void CALLBACK quit_callback(HWND hwnd, UINT msg, ULONG_PTR data, LRESULT result)
-{
-    struct quit_info *qi = (struct quit_info*)data;
-
-    qi->done++;
-
-    if (msg == WM_QUERYENDSESSION)
-    {
-        TRACE("got WM_QUERYENDSESSION result %ld from win %p (%u of %u done)\n", result,
-              hwnd, qi->done, qi->count);
-
-        if (!result && !IsWindow(hwnd))
-        {
-            TRACE("win %p no longer exists; ignoring apparent refusal\n", hwnd);
-            result = TRUE;
-        }
-
-        if (!result && qi->result)
-        {
-            qi->result = FALSE;
-
-            /* On the first FALSE from WM_QUERYENDSESSION, we already know the
-               ultimate reply.  Might as well tell Cocoa now. */
-            if (!qi->replied)
-            {
-                qi->replied = TRUE;
-                TRACE("giving quit reply %d\n", qi->result);
-                macdrv_quit_reply(qi->result);
-            }
-        }
-
-        if (qi->done >= qi->count)
-        {
-            UINT i;
-
-            qi->done = 0;
-            for (i = 0; i < qi->count; i++)
-            {
-                TRACE("sending WM_ENDSESSION to win %p result %d flags 0x%08x\n", qi->wins[i],
-                      qi->result, qi->flags);
-                if (!SendMessageCallbackW(qi->wins[i], WM_ENDSESSION, qi->result, qi->flags,
-                                          quit_callback, (ULONG_PTR)qi))
-                {
-                    WARN("failed to send WM_ENDSESSION to win %p; error 0x%08x\n",
-                         qi->wins[i], GetLastError());
-                    quit_callback(qi->wins[i], WM_ENDSESSION, (ULONG_PTR)qi, 0);
-                }
-            }
-        }
-    }
-    else /* WM_ENDSESSION */
-    {
-        TRACE("finished WM_ENDSESSION for win %p (%u of %u done)\n", hwnd, qi->done, qi->count);
-
-        if (qi->done >= qi->count)
-        {
-            if (!qi->replied)
-            {
-                TRACE("giving quit reply %d\n", qi->result);
-                macdrv_quit_reply(qi->result);
-            }
-
-            TRACE("%sterminating process\n", qi->result ? "" : "not ");
-            if (qi->result)
-                TerminateProcess(GetCurrentProcess(), 0);
-
-            free(qi->wins);
-            free(qi);
-        }
-    }
-}
-
-
 /***********************************************************************
  *              macdrv_app_quit_requested
  *
@@ -2768,66 +2660,14 @@ static void CALLBACK quit_callback(HWND hwnd, UINT msg, ULONG_PTR data, LRESULT
  */
 void macdrv_app_quit_requested(const macdrv_event *event)
 {
-    struct quit_info *qi;
-    UINT i;
+    struct app_quit_request_params params = { .flags = 0 };
 
     TRACE("reason %d\n", event->app_quit_requested.reason);
 
-    qi = malloc(sizeof(*qi));
-    if (!qi)
-        goto fail;
-
-    qi->capacity = 32;
-    qi->wins = malloc(qi->capacity * sizeof(*qi->wins));
-    qi->count = qi->done = 0;
-
-    if (!qi->wins || !EnumWindows(get_process_windows, (LPARAM)qi))
-        goto fail;
+    if (event->app_quit_requested.reason == QUIT_REASON_LOGOUT)
+        params.flags = ENDSESSION_LOGOFF;
 
-    switch (event->app_quit_requested.reason)
-    {
-        case QUIT_REASON_LOGOUT:
-        default:
-            qi->flags = ENDSESSION_LOGOFF;
-            break;
-        case QUIT_REASON_RESTART:
-        case QUIT_REASON_SHUTDOWN:
-            qi->flags = 0;
-            break;
-    }
-
-    qi->result = TRUE;
-    qi->replied = FALSE;
-
-    for (i = 0; i < qi->count; i++)
-    {
-        TRACE("sending WM_QUERYENDSESSION to win %p\n", qi->wins[i]);
-        if (!SendMessageCallbackW(qi->wins[i], WM_QUERYENDSESSION, 0, qi->flags,
-                                  quit_callback, (ULONG_PTR)qi))
-        {
-            DWORD error = GetLastError();
-            BOOL invalid = (error == ERROR_INVALID_WINDOW_HANDLE);
-            if (invalid)
-                TRACE("failed to send WM_QUERYENDSESSION to win %p because it's invalid; assuming success\n",
-                     qi->wins[i]);
-            else
-                WARN("failed to send WM_QUERYENDSESSION to win %p; error 0x%08x; assuming refusal\n",
-                     qi->wins[i], error);
-            quit_callback(qi->wins[i], WM_QUERYENDSESSION, (ULONG_PTR)qi, invalid);
-        }
-    }
-
-    /* quit_callback() will clean up qi */
-    return;
-
-fail:
-    WARN("failed to allocate window list\n");
-    if (qi)
-    {
-        free(qi->wins);
-        free(qi);
-    }
-    macdrv_quit_reply(FALSE);
+    macdrv_client_func(client_func_app_quit_request, &params, sizeof(params));
 }
 
 
-- 
GitLab


https://gitlab.winehq.org/wine/wine/-/merge_requests/177



More information about the wine-devel mailing list