From 612c0104312e81c21b0a1216edd181cd46687404 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Wed, 25 Jun 2008 15:30:22 +0200 Subject: [PATCH] user32: Add support for finding HWND_MESSAGE windows in FindWindowEx. --- dlls/user32/tests/win.c | 14 ++++++++- dlls/user32/win.c | 9 +++++- server/window.c | 68 +++++++++++++++++++++++++++++------------ 3 files changed, 69 insertions(+), 22 deletions(-) diff --git a/dlls/user32/tests/win.c b/dlls/user32/tests/win.c index 182a0b66e8c..3a3a1525a5e 100644 --- a/dlls/user32/tests/win.c +++ b/dlls/user32/tests/win.c @@ -4709,7 +4709,7 @@ static void test_GetWindowModuleFileName(void) static void test_hwnd_message(void) { - HWND parent = 0, hwnd; + HWND parent = 0, hwnd, found; RECT rect; hwnd = CreateWindowExA(0, "MainWindowClass", "message window", WS_CAPTION | WS_VISIBLE, @@ -4743,6 +4743,18 @@ static void test_hwnd_message(void) ok( rect.left == 100 && rect.right == 300 && rect.top == 100 && rect.bottom == 300, "wrong window rect %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom ); + /* test FindWindow behavior */ + + found = FindWindowExA( 0, 0, 0, "message window" ); + ok( found == hwnd, "didn't find message window %p/%p\n", found, hwnd ); + found = FindWindowExA( GetDesktopWindow(), 0, 0, "message window" ); + ok( found == 0, "found message window %p/%p\n", found, hwnd ); + if (parent) + { + found = FindWindowExA( parent, 0, 0, "message window" ); + ok( found == hwnd, "didn't find message window %p/%p\n", found, hwnd ); + } + DestroyWindow(hwnd); } diff --git a/dlls/user32/win.c b/dlls/user32/win.c index 3ba4d76aa15..9a2124687fc 100644 --- a/dlls/user32/win.c +++ b/dlls/user32/win.c @@ -1578,7 +1578,9 @@ HWND WINAPI FindWindowExW( HWND parent, HWND child, LPCWSTR className, LPCWSTR t int i = 0, len = 0; WCHAR *buffer = NULL; - if (!parent) parent = GetDesktopWindow(); + if (!parent && child) parent = GetDesktopWindow(); + else if (parent == HWND_MESSAGE) parent = get_hwnd_message_parent(); + if (title) { len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */ @@ -2940,6 +2942,11 @@ HWND WINAPI GetLastActivePopup( HWND hwnd ) */ HWND *WIN_ListChildren( HWND hwnd ) { + if (!hwnd) + { + SetLastError( ERROR_INVALID_WINDOW_HANDLE ); + return NULL; + } return list_window_children( 0, hwnd, NULL, 0 ); } diff --git a/server/window.c b/server/window.c index 53ea59fa4a1..ed8f042154d 100644 --- a/server/window.c +++ b/server/window.c @@ -639,6 +639,29 @@ static inline int is_point_in_window( struct window *win, int x, int y ) return 1; } +/* fill an array with the handles of the children of a specified window */ +static unsigned int get_children_windows( struct window *parent, atom_t atom, thread_id_t tid, + user_handle_t *handles, unsigned int max_count ) +{ + struct window *ptr; + unsigned int count = 0; + + if (!parent) return 0; + + LIST_FOR_EACH_ENTRY( ptr, &parent->children, struct window, entry ) + { + if (atom && get_class_atom(ptr->class) != atom) continue; + if (tid && get_thread_id(ptr->thread) != tid) continue; + if (handles) + { + if (count >= max_count) break; + handles[count] = ptr->handle; + } + count++; + } + return count; +} + /* find child of 'parent' that contains the given point (in parent-relative coords) */ static struct window *child_window_from_point( struct window *parent, int x, int y ) { @@ -1932,46 +1955,51 @@ DECL_HANDLER(get_window_parents) /* get a list of the window children */ DECL_HANDLER(get_window_children) { - struct window *ptr, *parent; - int total = 0; + struct window *parent = NULL; + unsigned int total; user_handle_t *data; data_size_t len; struct unicode_str cls_name; atom_t atom = req->atom; + struct desktop *desktop = NULL; if (req->desktop) { - struct desktop *desktop = get_desktop_obj( current->process, req->desktop, DESKTOP_ENUMERATE ); - if (!desktop) return; + if (!(desktop = get_desktop_obj( current->process, req->desktop, DESKTOP_ENUMERATE ))) return; parent = desktop->top_window; - release_object( desktop ); } - else parent = get_window( req->parent ); - - if (!parent) return; + else + { + if (req->parent && !(parent = get_window( req->parent ))) return; + if (!parent && !(desktop = get_thread_desktop( current, 0 ))) return; + } get_req_unicode_str( &cls_name ); if (cls_name.len && !(atom = find_global_atom( NULL, &cls_name ))) return; - LIST_FOR_EACH_ENTRY( ptr, &parent->children, struct window, entry ) - { - if (atom && get_class_atom(ptr->class) != atom) continue; - if (req->tid && get_thread_id(ptr->thread) != req->tid) continue; - total++; - } + if (parent) + total = get_children_windows( parent, atom, req->tid, NULL, 0 ); + else + total = get_children_windows( desktop->top_window, atom, req->tid, NULL, 0 ) + + get_children_windows( desktop->msg_window, atom, req->tid, NULL, 0 ); + reply->count = total; len = min( get_reply_max_size(), total * sizeof(user_handle_t) ); if (len && ((data = set_reply_data_size( len )))) { - LIST_FOR_EACH_ENTRY( ptr, &parent->children, struct window, entry ) + if (parent) get_children_windows( parent, atom, req->tid, data, len / sizeof(user_handle_t) ); + else { - if (len < sizeof(*data)) break; - if (atom && get_class_atom(ptr->class) != atom) continue; - if (req->tid && get_thread_id(ptr->thread) != req->tid) continue; - *data++ = ptr->handle; - len -= sizeof(*data); + total = get_children_windows( desktop->top_window, atom, req->tid, + data, len / sizeof(user_handle_t) ); + data += total; + len -= total * sizeof(user_handle_t); + if (len >= sizeof(user_handle_t)) + get_children_windows( desktop->msg_window, atom, req->tid, + data, len / sizeof(user_handle_t) ); } } + if (desktop) release_object( desktop ); }