[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, ¶ms);
+}
+
+
+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, ¶ms, sizeof(params));
}
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/177
More information about the wine-devel
mailing list