2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "wine/port.h"
30 #include "wine/server.h"
31 #include "wine/unicode.h"
33 #include "user_private.h"
36 #include "wine/debug.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(win);
40 #define NB_USER_HANDLES ((LAST_USER_HANDLE - FIRST_USER_HANDLE + 1) >> 1)
41 #define USER_HANDLE_TO_INDEX(hwnd) ((LOWORD(hwnd) - FIRST_USER_HANDLE) >> 1)
43 static DWORD process_layout;
45 /**********************************************************************/
47 static inline void mirror_rect( const RECT *window_rect, RECT *rect )
49 int width = window_rect->right - window_rect->left;
51 rect->left = width - rect->right;
52 rect->right = width - tmp;
55 /* helper for Get/SetWindowLong */
56 static inline LONG_PTR get_win_data( const void *ptr, UINT size )
58 if (size == sizeof(WORD))
61 memcpy( &ret, ptr, sizeof(ret) );
64 else if (size == sizeof(DWORD))
67 memcpy( &ret, ptr, sizeof(ret) );
73 memcpy( &ret, ptr, sizeof(ret) );
78 /* helper for Get/SetWindowLong */
79 static inline void set_win_data( void *ptr, LONG_PTR val, UINT size )
81 if (size == sizeof(WORD))
84 memcpy( ptr, &newval, sizeof(newval) );
86 else if (size == sizeof(DWORD))
89 memcpy( ptr, &newval, sizeof(newval) );
93 memcpy( ptr, &val, sizeof(val) );
98 static void *user_handles[NB_USER_HANDLES];
100 /***********************************************************************
103 HANDLE alloc_user_handle( struct user_object *ptr, enum user_obj_type type )
107 SERVER_START_REQ( alloc_user_handle )
109 if (!wine_server_call_err( req )) handle = wine_server_ptr_handle( reply->handle );
115 UINT index = USER_HANDLE_TO_INDEX( handle );
117 assert( index < NB_USER_HANDLES );
118 ptr->handle = handle;
120 InterlockedExchangePointer( &user_handles[index], ptr );
126 /***********************************************************************
127 * get_user_handle_ptr
129 void *get_user_handle_ptr( HANDLE handle, enum user_obj_type type )
131 struct user_object *ptr;
132 WORD index = USER_HANDLE_TO_INDEX( handle );
134 if (index >= NB_USER_HANDLES) return NULL;
137 if ((ptr = user_handles[index]))
139 if (ptr->type == type &&
140 ((UINT)(UINT_PTR)ptr->handle == (UINT)(UINT_PTR)handle ||
141 !HIWORD(handle) || HIWORD(handle) == 0xffff))
145 else ptr = OBJ_OTHER_PROCESS;
151 /***********************************************************************
152 * release_user_handle_ptr
154 void release_user_handle_ptr( void *ptr )
156 assert( ptr && ptr != OBJ_OTHER_PROCESS );
161 /***********************************************************************
164 void *free_user_handle( HANDLE handle, enum user_obj_type type )
166 struct user_object *ptr;
167 WORD index = USER_HANDLE_TO_INDEX( handle );
169 if ((ptr = get_user_handle_ptr( handle, type )) && ptr != OBJ_OTHER_PROCESS)
171 SERVER_START_REQ( free_user_handle )
173 req->handle = wine_server_user_handle( handle );
174 if (wine_server_call( req )) ptr = NULL;
175 else InterlockedCompareExchangePointer( &user_handles[index], NULL, ptr );
178 release_user_handle_ptr( ptr );
184 /***********************************************************************
185 * create_window_handle
187 * Create a window handle with the server.
189 static WND *create_window_handle( HWND parent, HWND owner, LPCWSTR name,
190 HINSTANCE instance, BOOL unicode )
194 HWND handle = 0, full_parent = 0, full_owner = 0;
195 struct tagCLASS *class = NULL;
198 SERVER_START_REQ( create_window )
200 req->parent = wine_server_user_handle( parent );
201 req->owner = wine_server_user_handle( owner );
202 req->instance = wine_server_client_ptr( instance );
203 if (!(req->atom = get_int_atom_value( name )) && name)
204 wine_server_add_data( req, name, strlenW(name)*sizeof(WCHAR) );
205 if (!wine_server_call_err( req ))
207 handle = wine_server_ptr_handle( reply->handle );
208 full_parent = wine_server_ptr_handle( reply->parent );
209 full_owner = wine_server_ptr_handle( reply->owner );
210 extra_bytes = reply->extra;
211 class = wine_server_get_ptr( reply->class_ptr );
218 WARN( "error %d creating window\n", GetLastError() );
222 if (!(win = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
223 sizeof(WND) + extra_bytes - sizeof(win->wExtra) )))
225 SERVER_START_REQ( destroy_window )
227 req->handle = wine_server_user_handle( handle );
228 wine_server_call( req );
231 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
235 if (!parent) /* if parent is 0 we don't have a desktop window yet */
237 struct user_thread_info *thread_info = get_user_thread_info();
239 if (name == (LPCWSTR)DESKTOP_CLASS_ATOM)
241 if (!thread_info->top_window) thread_info->top_window = full_parent ? full_parent : handle;
242 else assert( full_parent == thread_info->top_window );
243 if (full_parent && !USER_Driver->pCreateDesktopWindow( thread_info->top_window ))
244 ERR( "failed to create desktop window\n" );
246 else /* HWND_MESSAGE parent */
248 if (!thread_info->msg_window && !full_parent) thread_info->msg_window = handle;
254 index = USER_HANDLE_TO_INDEX(handle);
255 assert( index < NB_USER_HANDLES );
256 win->obj.handle = handle;
257 win->obj.type = USER_WINDOW;
258 win->parent = full_parent;
259 win->owner = full_owner;
261 win->winproc = get_class_winproc( class );
262 win->cbWndExtra = extra_bytes;
263 InterlockedExchangePointer( &user_handles[index], win );
264 if (WINPROC_IsUnicode( win->winproc, unicode )) win->flags |= WIN_ISUNICODE;
269 /***********************************************************************
272 * Free a window handle.
274 static void free_window_handle( HWND hwnd )
276 struct user_object *ptr;
277 WORD index = USER_HANDLE_TO_INDEX(hwnd);
279 if ((ptr = get_user_handle_ptr( hwnd, USER_WINDOW )) && ptr != OBJ_OTHER_PROCESS)
281 SERVER_START_REQ( destroy_window )
283 req->handle = wine_server_user_handle( hwnd );
284 if (wine_server_call_err( req )) ptr = NULL;
285 else InterlockedCompareExchangePointer( &user_handles[index], NULL, ptr );
288 release_user_handle_ptr( ptr );
289 HeapFree( GetProcessHeap(), 0, ptr );
294 /*******************************************************************
295 * list_window_children
297 * Build an array of the children of a given window. The array must be
298 * freed with HeapFree. Returns NULL when no windows are found.
300 static HWND *list_window_children( HDESK desktop, HWND hwnd, LPCWSTR class, DWORD tid )
304 ATOM atom = get_int_atom_value( class );
306 /* empty class is not the same as NULL class */
307 if (!atom && class && !class[0]) return NULL;
313 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
315 SERVER_START_REQ( get_window_children )
317 req->desktop = wine_server_obj_handle( desktop );
318 req->parent = wine_server_user_handle( hwnd );
321 if (!atom && class) wine_server_add_data( req, class, strlenW(class)*sizeof(WCHAR) );
322 wine_server_set_reply( req, list, (size-1) * sizeof(user_handle_t) );
323 if (!wine_server_call( req )) count = reply->count;
326 if (count && count < size)
328 /* start from the end since HWND is potentially larger than user_handle_t */
329 for (i = count - 1; i >= 0; i--)
330 list[i] = wine_server_ptr_handle( ((user_handle_t *)list)[i] );
334 HeapFree( GetProcessHeap(), 0, list );
336 size = count + 1; /* restart with a large enough buffer */
342 /*******************************************************************
343 * list_window_parents
345 * Build an array of all parents of a given window, starting with
346 * the immediate parent. The array must be freed with HeapFree.
348 static HWND *list_window_parents( HWND hwnd )
352 int i, pos = 0, size = 16, count = 0;
354 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
359 if (!(win = WIN_GetPtr( current ))) goto empty;
360 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
361 if (win == WND_DESKTOP)
363 if (!pos) goto empty;
367 list[pos] = current = win->parent;
368 WIN_ReleasePtr( win );
369 if (!current) return list;
370 if (++pos == size - 1)
372 /* need to grow the list */
373 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
374 if (!new_list) goto empty;
380 /* at least one parent belongs to another process, have to query the server */
385 SERVER_START_REQ( get_window_parents )
387 req->handle = wine_server_user_handle( hwnd );
388 wine_server_set_reply( req, list, (size-1) * sizeof(user_handle_t) );
389 if (!wine_server_call( req )) count = reply->count;
392 if (!count) goto empty;
395 /* start from the end since HWND is potentially larger than user_handle_t */
396 for (i = count - 1; i >= 0; i--)
397 list[i] = wine_server_ptr_handle( ((user_handle_t *)list)[i] );
401 HeapFree( GetProcessHeap(), 0, list );
403 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
407 HeapFree( GetProcessHeap(), 0, list );
412 /*******************************************************************
415 static void send_parent_notify( HWND hwnd, UINT msg )
417 if ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_CHILD | WS_POPUP)) == WS_CHILD &&
418 !(GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY))
420 HWND parent = GetParent(hwnd);
421 if (parent && parent != GetDesktopWindow())
422 SendMessageW( parent, WM_PARENTNOTIFY,
423 MAKEWPARAM( msg, GetWindowLongPtrW( hwnd, GWLP_ID )), (LPARAM)hwnd );
428 /*******************************************************************
429 * get_server_window_text
431 * Retrieve the window text from the server.
433 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
437 SERVER_START_REQ( get_window_text )
439 req->handle = wine_server_user_handle( hwnd );
440 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
441 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
444 text[len / sizeof(WCHAR)] = 0;
448 /*******************************************************************
449 * get_hwnd_message_parent
451 * Return the parent for HWND_MESSAGE windows.
453 HWND get_hwnd_message_parent(void)
455 struct user_thread_info *thread_info = get_user_thread_info();
457 if (!thread_info->msg_window) GetDesktopWindow(); /* trigger creation */
458 return thread_info->msg_window;
462 /*******************************************************************
465 * Check if window is the desktop or the HWND_MESSAGE top parent.
467 BOOL is_desktop_window( HWND hwnd )
469 struct user_thread_info *thread_info = get_user_thread_info();
471 if (!hwnd) return FALSE;
472 if (hwnd == thread_info->top_window) return TRUE;
473 if (hwnd == thread_info->msg_window) return TRUE;
475 if (!HIWORD(hwnd) || HIWORD(hwnd) == 0xffff)
477 if (LOWORD(thread_info->top_window) == LOWORD(hwnd)) return TRUE;
478 if (LOWORD(thread_info->msg_window) == LOWORD(hwnd)) return TRUE;
484 /***********************************************************************
487 * Return a pointer to the WND structure if local to the process,
488 * or WND_OTHER_PROCESS if handle may be valid in other process.
489 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
491 WND *WIN_GetPtr( HWND hwnd )
495 if ((ptr = get_user_handle_ptr( hwnd, USER_WINDOW )) == WND_OTHER_PROCESS)
497 if (is_desktop_window( hwnd )) ptr = WND_DESKTOP;
503 /***********************************************************************
504 * WIN_IsCurrentProcess
506 * Check whether a given window belongs to the current process (and return the full handle).
508 HWND WIN_IsCurrentProcess( HWND hwnd )
513 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
514 ret = ptr->obj.handle;
515 WIN_ReleasePtr( ptr );
520 /***********************************************************************
521 * WIN_IsCurrentThread
523 * Check whether a given window belongs to the current thread (and return the full handle).
525 HWND WIN_IsCurrentThread( HWND hwnd )
530 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
531 if (ptr->tid == GetCurrentThreadId()) ret = ptr->obj.handle;
532 WIN_ReleasePtr( ptr );
537 /***********************************************************************
540 * Convert a possibly truncated window handle to a full 32-bit handle.
542 HWND WIN_GetFullHandle( HWND hwnd )
546 if (!hwnd || (ULONG_PTR)hwnd >> 16) return hwnd;
547 if (LOWORD(hwnd) <= 1 || LOWORD(hwnd) == 0xffff) return hwnd;
548 /* do sign extension for -2 and -3 */
549 if (LOWORD(hwnd) >= (WORD)-3) return (HWND)(LONG_PTR)(INT16)LOWORD(hwnd);
551 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
553 if (ptr == WND_DESKTOP)
555 if (LOWORD(hwnd) == LOWORD(GetDesktopWindow())) return GetDesktopWindow();
556 else return get_hwnd_message_parent();
559 if (ptr != WND_OTHER_PROCESS)
561 hwnd = ptr->obj.handle;
562 WIN_ReleasePtr( ptr );
564 else /* may belong to another process */
566 SERVER_START_REQ( get_window_info )
568 req->handle = wine_server_user_handle( hwnd );
569 if (!wine_server_call_err( req )) hwnd = wine_server_ptr_handle( reply->full_handle );
577 /***********************************************************************
580 * Change the owner of a window.
582 HWND WIN_SetOwner( HWND hwnd, HWND owner )
584 WND *win = WIN_GetPtr( hwnd );
587 if (!win || win == WND_DESKTOP) return 0;
588 if (win == WND_OTHER_PROCESS)
590 if (IsWindow(hwnd)) ERR( "cannot set owner %p on other process window %p\n", owner, hwnd );
593 SERVER_START_REQ( set_window_owner )
595 req->handle = wine_server_user_handle( hwnd );
596 req->owner = wine_server_user_handle( owner );
597 if (!wine_server_call( req ))
599 win->owner = wine_server_ptr_handle( reply->full_owner );
600 ret = wine_server_ptr_handle( reply->prev_owner );
604 WIN_ReleasePtr( win );
609 /***********************************************************************
612 * Change the style of a window.
614 ULONG WIN_SetStyle( HWND hwnd, ULONG set_bits, ULONG clear_bits )
618 WND *win = WIN_GetPtr( hwnd );
620 if (!win || win == WND_DESKTOP) return 0;
621 if (win == WND_OTHER_PROCESS)
624 ERR( "cannot set style %x/%x on other process window %p\n",
625 set_bits, clear_bits, hwnd );
628 style.styleOld = win->dwStyle;
629 style.styleNew = (win->dwStyle | set_bits) & ~clear_bits;
630 if (style.styleNew == style.styleOld)
632 WIN_ReleasePtr( win );
633 return style.styleNew;
635 SERVER_START_REQ( set_window_info )
637 req->handle = wine_server_user_handle( hwnd );
638 req->flags = SET_WIN_STYLE;
639 req->style = style.styleNew;
640 req->extra_offset = -1;
641 if ((ok = !wine_server_call( req )))
643 style.styleOld = reply->old_style;
644 win->dwStyle = style.styleNew;
648 WIN_ReleasePtr( win );
651 USER_Driver->pSetWindowStyle( hwnd, GWL_STYLE, &style );
652 if ((style.styleOld ^ style.styleNew) & WS_VISIBLE) invalidate_dce( hwnd, NULL );
654 return style.styleOld;
658 /***********************************************************************
661 * Get the window and client rectangles.
663 BOOL WIN_GetRectangles( HWND hwnd, enum coords_relative relative, RECT *rectWindow, RECT *rectClient )
665 WND *win = WIN_GetPtr( hwnd );
670 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
673 if (win == WND_DESKTOP)
676 rect.left = rect.top = 0;
677 if (hwnd == get_hwnd_message_parent())
684 rect.right = GetSystemMetrics(SM_CXSCREEN);
685 rect.bottom = GetSystemMetrics(SM_CYSCREEN);
687 if (rectWindow) *rectWindow = rect;
688 if (rectClient) *rectClient = rect;
691 if (win != WND_OTHER_PROCESS)
693 RECT window_rect = win->rectWindow, client_rect = win->rectClient;
698 OffsetRect( &window_rect, -win->rectClient.left, -win->rectClient.top );
699 OffsetRect( &client_rect, -win->rectClient.left, -win->rectClient.top );
700 if (win->dwExStyle & WS_EX_LAYOUTRTL)
701 mirror_rect( &win->rectClient, &window_rect );
704 OffsetRect( &window_rect, -win->rectWindow.left, -win->rectWindow.top );
705 OffsetRect( &client_rect, -win->rectWindow.left, -win->rectWindow.top );
706 if (win->dwExStyle & WS_EX_LAYOUTRTL)
707 mirror_rect( &win->rectWindow, &client_rect );
712 WND *parent = WIN_GetPtr( win->parent );
713 if (parent == WND_DESKTOP) break;
714 if (!parent || parent == WND_OTHER_PROCESS)
716 WIN_ReleasePtr( win );
719 if (parent->dwExStyle & WS_EX_LAYOUTRTL)
721 mirror_rect( &parent->rectClient, &window_rect );
722 mirror_rect( &parent->rectClient, &client_rect );
724 WIN_ReleasePtr( parent );
730 WND *parent = WIN_GetPtr( win->parent );
731 if (parent == WND_DESKTOP) break;
732 if (!parent || parent == WND_OTHER_PROCESS)
734 WIN_ReleasePtr( win );
737 WIN_ReleasePtr( win );
739 OffsetRect( &window_rect, win->rectClient.left, win->rectClient.top );
740 OffsetRect( &client_rect, win->rectClient.left, win->rectClient.top );
744 if (rectWindow) *rectWindow = window_rect;
745 if (rectClient) *rectClient = client_rect;
746 WIN_ReleasePtr( win );
751 SERVER_START_REQ( get_window_rectangles )
753 req->handle = wine_server_user_handle( hwnd );
754 req->relative = relative;
755 if ((ret = !wine_server_call_err( req )))
759 rectWindow->left = reply->window.left;
760 rectWindow->top = reply->window.top;
761 rectWindow->right = reply->window.right;
762 rectWindow->bottom = reply->window.bottom;
766 rectClient->left = reply->client.left;
767 rectClient->top = reply->client.top;
768 rectClient->right = reply->client.right;
769 rectClient->bottom = reply->client.bottom;
778 /***********************************************************************
781 * Destroy storage associated to a window. "Internals" p.358
783 LRESULT WIN_DestroyWindow( HWND hwnd )
787 HMENU menu = 0, sys_menu;
790 TRACE("%p\n", hwnd );
792 /* free child windows */
793 if ((list = WIN_ListChildren( hwnd )))
796 for (i = 0; list[i]; i++)
798 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
799 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
801 HeapFree( GetProcessHeap(), 0, list );
804 /* Unlink now so we won't bother with the children later on */
805 SERVER_START_REQ( set_parent )
807 req->handle = wine_server_user_handle( hwnd );
809 wine_server_call( req );
814 * Send the WM_NCDESTROY to the window being destroyed.
816 SendMessageW( hwnd, WM_NCDESTROY, 0, 0 );
818 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
820 /* free resources associated with the window */
822 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
823 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
824 menu = (HMENU)wndPtr->wIDmenu;
825 sys_menu = wndPtr->hSysMenu;
826 free_dce( wndPtr->dce, hwnd );
828 icon_title = wndPtr->icon_title;
829 HeapFree( GetProcessHeap(), 0, wndPtr->text );
831 HeapFree( GetProcessHeap(), 0, wndPtr->pScroll );
832 wndPtr->pScroll = NULL;
833 WIN_ReleasePtr( wndPtr );
835 if (icon_title) DestroyWindow( icon_title );
836 if (menu) DestroyMenu( menu );
837 if (sys_menu) DestroyMenu( sys_menu );
839 USER_Driver->pDestroyWindow( hwnd );
841 free_window_handle( hwnd );
846 /***********************************************************************
847 * destroy_thread_window
849 * Destroy a window upon exit of its thread.
851 static void destroy_thread_window( HWND hwnd )
855 HMENU menu = 0, sys_menu = 0;
858 /* free child windows */
860 if ((list = WIN_ListChildren( hwnd )))
863 for (i = 0; list[i]; i++)
865 if (WIN_IsCurrentThread( list[i] )) destroy_thread_window( list[i] );
866 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
868 HeapFree( GetProcessHeap(), 0, list );
871 /* destroy the client-side storage */
873 index = USER_HANDLE_TO_INDEX(hwnd);
874 if (index >= NB_USER_HANDLES) return;
876 if ((wndPtr = user_handles[index]))
878 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD) menu = (HMENU)wndPtr->wIDmenu;
879 sys_menu = wndPtr->hSysMenu;
880 free_dce( wndPtr->dce, hwnd );
881 InterlockedCompareExchangePointer( &user_handles[index], NULL, wndPtr );
885 HeapFree( GetProcessHeap(), 0, wndPtr );
886 if (menu) DestroyMenu( menu );
887 if (sys_menu) DestroyMenu( sys_menu );
891 /***********************************************************************
892 * destroy_thread_child_windows
894 * Destroy child windows upon exit of its thread.
896 static void destroy_thread_child_windows( HWND hwnd )
901 if (WIN_IsCurrentThread( hwnd ))
903 destroy_thread_window( hwnd );
905 else if ((list = WIN_ListChildren( hwnd )))
907 for (i = 0; list[i]; i++) destroy_thread_child_windows( list[i] );
908 HeapFree( GetProcessHeap(), 0, list );
913 /***********************************************************************
914 * WIN_DestroyThreadWindows
916 * Destroy all children of 'wnd' owned by the current thread.
918 void WIN_DestroyThreadWindows( HWND hwnd )
923 if (!(list = WIN_ListChildren( hwnd ))) return;
925 /* reset owners of top-level windows */
926 for (i = 0; list[i]; i++)
928 if (!WIN_IsCurrentThread( list[i] ))
930 HWND owner = GetWindow( list[i], GW_OWNER );
931 if (owner && WIN_IsCurrentThread( owner )) WIN_SetOwner( list[i], 0 );
935 for (i = 0; list[i]; i++) destroy_thread_child_windows( list[i] );
936 HeapFree( GetProcessHeap(), 0, list );
940 /***********************************************************************
943 * Fix the coordinates - Helper for WIN_CreateWindowEx.
944 * returns default show mode in sw.
946 static void WIN_FixCoordinates( CREATESTRUCTW *cs, INT *sw)
948 #define IS_DEFAULT(x) ((x) == CW_USEDEFAULT || (x) == (SHORT)0x8000)
951 if (cs->dwExStyle & WS_EX_MDICHILD)
955 MDI_CalcDefaultChildPos(cs->hwndParent, -1, pos, 0, &id);
956 if (!(cs->style & WS_POPUP)) cs->hMenu = ULongToHandle(id);
958 TRACE("MDI child id %04x\n", id);
961 if (cs->style & (WS_CHILD | WS_POPUP))
963 if (cs->dwExStyle & WS_EX_MDICHILD)
965 if (IS_DEFAULT(cs->x))
970 if (IS_DEFAULT(cs->cx) || !cs->cx) cs->cx = pos[1].x;
971 if (IS_DEFAULT(cs->cy) || !cs->cy) cs->cy = pos[1].y;
975 if (IS_DEFAULT(cs->x)) cs->x = cs->y = 0;
976 if (IS_DEFAULT(cs->cx)) cs->cx = cs->cy = 0;
979 else /* overlapped window */
982 MONITORINFO mon_info;
985 if (!IS_DEFAULT(cs->x) && !IS_DEFAULT(cs->cx) && !IS_DEFAULT(cs->cy)) return;
987 monitor = MonitorFromWindow( cs->hwndParent, MONITOR_DEFAULTTOPRIMARY );
988 mon_info.cbSize = sizeof(mon_info);
989 GetMonitorInfoW( monitor, &mon_info );
990 GetStartupInfoW( &info );
992 if (IS_DEFAULT(cs->x))
994 if (!IS_DEFAULT(cs->y)) *sw = cs->y;
995 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : mon_info.rcWork.left;
996 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : mon_info.rcWork.top;
999 if (IS_DEFAULT(cs->cx))
1001 if (info.dwFlags & STARTF_USESIZE)
1003 cs->cx = info.dwXSize;
1004 cs->cy = info.dwYSize;
1008 cs->cx = (mon_info.rcWork.right - mon_info.rcWork.left) * 3 / 4 - cs->x;
1009 cs->cy = (mon_info.rcWork.bottom - mon_info.rcWork.top) * 3 / 4 - cs->y;
1012 /* neither x nor cx are default. Check the y values .
1013 * In the trace we see Outlook and Outlook Express using
1014 * cy set to CW_USEDEFAULT when opening the address book.
1016 else if (IS_DEFAULT(cs->cy))
1018 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
1019 cs->cy = (mon_info.rcWork.bottom - mon_info.rcWork.top) * 3 / 4 - cs->y;
1025 /***********************************************************************
1026 * dump_window_styles
1028 static void dump_window_styles( DWORD style, DWORD exstyle )
1031 if(style & WS_POPUP) TRACE(" WS_POPUP");
1032 if(style & WS_CHILD) TRACE(" WS_CHILD");
1033 if(style & WS_MINIMIZE) TRACE(" WS_MINIMIZE");
1034 if(style & WS_VISIBLE) TRACE(" WS_VISIBLE");
1035 if(style & WS_DISABLED) TRACE(" WS_DISABLED");
1036 if(style & WS_CLIPSIBLINGS) TRACE(" WS_CLIPSIBLINGS");
1037 if(style & WS_CLIPCHILDREN) TRACE(" WS_CLIPCHILDREN");
1038 if(style & WS_MAXIMIZE) TRACE(" WS_MAXIMIZE");
1039 if((style & WS_CAPTION) == WS_CAPTION) TRACE(" WS_CAPTION");
1042 if(style & WS_BORDER) TRACE(" WS_BORDER");
1043 if(style & WS_DLGFRAME) TRACE(" WS_DLGFRAME");
1045 if(style & WS_VSCROLL) TRACE(" WS_VSCROLL");
1046 if(style & WS_HSCROLL) TRACE(" WS_HSCROLL");
1047 if(style & WS_SYSMENU) TRACE(" WS_SYSMENU");
1048 if(style & WS_THICKFRAME) TRACE(" WS_THICKFRAME");
1049 if (style & WS_CHILD)
1051 if(style & WS_GROUP) TRACE(" WS_GROUP");
1052 if(style & WS_TABSTOP) TRACE(" WS_TABSTOP");
1056 if(style & WS_MINIMIZEBOX) TRACE(" WS_MINIMIZEBOX");
1057 if(style & WS_MAXIMIZEBOX) TRACE(" WS_MAXIMIZEBOX");
1060 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
1061 #define DUMPED_STYLES \
1081 if(style & ~DUMPED_STYLES) TRACE(" %08lx", style & ~DUMPED_STYLES);
1083 #undef DUMPED_STYLES
1085 TRACE( "exstyle:" );
1086 if(exstyle & WS_EX_DLGMODALFRAME) TRACE(" WS_EX_DLGMODALFRAME");
1087 if(exstyle & WS_EX_DRAGDETECT) TRACE(" WS_EX_DRAGDETECT");
1088 if(exstyle & WS_EX_NOPARENTNOTIFY) TRACE(" WS_EX_NOPARENTNOTIFY");
1089 if(exstyle & WS_EX_TOPMOST) TRACE(" WS_EX_TOPMOST");
1090 if(exstyle & WS_EX_ACCEPTFILES) TRACE(" WS_EX_ACCEPTFILES");
1091 if(exstyle & WS_EX_TRANSPARENT) TRACE(" WS_EX_TRANSPARENT");
1092 if(exstyle & WS_EX_MDICHILD) TRACE(" WS_EX_MDICHILD");
1093 if(exstyle & WS_EX_TOOLWINDOW) TRACE(" WS_EX_TOOLWINDOW");
1094 if(exstyle & WS_EX_WINDOWEDGE) TRACE(" WS_EX_WINDOWEDGE");
1095 if(exstyle & WS_EX_CLIENTEDGE) TRACE(" WS_EX_CLIENTEDGE");
1096 if(exstyle & WS_EX_CONTEXTHELP) TRACE(" WS_EX_CONTEXTHELP");
1097 if(exstyle & WS_EX_RIGHT) TRACE(" WS_EX_RIGHT");
1098 if(exstyle & WS_EX_RTLREADING) TRACE(" WS_EX_RTLREADING");
1099 if(exstyle & WS_EX_LEFTSCROLLBAR) TRACE(" WS_EX_LEFTSCROLLBAR");
1100 if(exstyle & WS_EX_CONTROLPARENT) TRACE(" WS_EX_CONTROLPARENT");
1101 if(exstyle & WS_EX_STATICEDGE) TRACE(" WS_EX_STATICEDGE");
1102 if(exstyle & WS_EX_APPWINDOW) TRACE(" WS_EX_APPWINDOW");
1103 if(exstyle & WS_EX_LAYERED) TRACE(" WS_EX_LAYERED");
1104 if(exstyle & WS_EX_LAYOUTRTL) TRACE(" WS_EX_LAYOUTRTL");
1106 #define DUMPED_EX_STYLES \
1107 (WS_EX_DLGMODALFRAME | \
1108 WS_EX_DRAGDETECT | \
1109 WS_EX_NOPARENTNOTIFY | \
1111 WS_EX_ACCEPTFILES | \
1112 WS_EX_TRANSPARENT | \
1114 WS_EX_TOOLWINDOW | \
1115 WS_EX_WINDOWEDGE | \
1116 WS_EX_CLIENTEDGE | \
1117 WS_EX_CONTEXTHELP | \
1119 WS_EX_RTLREADING | \
1120 WS_EX_LEFTSCROLLBAR | \
1121 WS_EX_CONTROLPARENT | \
1122 WS_EX_STATICEDGE | \
1127 if(exstyle & ~DUMPED_EX_STYLES) TRACE(" %08lx", exstyle & ~DUMPED_EX_STYLES);
1129 #undef DUMPED_EX_STYLES
1133 /***********************************************************************
1134 * WIN_CreateWindowEx
1136 * Implementation of CreateWindowEx().
1138 HWND WIN_CreateWindowEx( CREATESTRUCTW *cs, LPCWSTR className, HINSTANCE module, BOOL unicode )
1140 INT cx, cy, style, sw = SW_SHOW;
1144 HWND hwnd, parent, owner, top_child = 0;
1145 MDICREATESTRUCTW mdi_cs;
1146 CBT_CREATEWNDW cbtc;
1149 TRACE("%s %s ex=%08x style=%08x %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
1150 unicode ? debugstr_w(cs->lpszName) : debugstr_a((LPCSTR)cs->lpszName),
1151 debugstr_w(className),
1152 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
1153 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
1154 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
1156 /* Fix the styles for MDI children */
1157 if (cs->dwExStyle & WS_EX_MDICHILD)
1161 wndPtr = WIN_GetPtr(cs->hwndParent);
1162 if (wndPtr && wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
1164 flags = wndPtr->flags;
1165 WIN_ReleasePtr(wndPtr);
1168 if (!(flags & WIN_ISMDICLIENT))
1170 WARN("WS_EX_MDICHILD, but parent %p is not MDIClient\n", cs->hwndParent);
1174 /* cs->lpCreateParams of WM_[NC]CREATE is different for MDI children.
1175 * MDICREATESTRUCT members have the originally passed values.
1177 * Note: we rely on the fact that MDICREATESTRUCTA and MDICREATESTRUCTW
1178 * have the same layout.
1180 mdi_cs.szClass = cs->lpszClass;
1181 mdi_cs.szTitle = cs->lpszName;
1182 mdi_cs.hOwner = cs->hInstance;
1187 mdi_cs.style = cs->style;
1188 mdi_cs.lParam = (LPARAM)cs->lpCreateParams;
1190 cs->lpCreateParams = &mdi_cs;
1192 if (GetWindowLongW(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
1194 if (cs->style & WS_POPUP)
1196 TRACE("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n");
1199 cs->style |= WS_CHILD | WS_CLIPSIBLINGS;
1203 cs->style &= ~WS_POPUP;
1204 cs->style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
1205 WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
1208 top_child = GetWindow(cs->hwndParent, GW_CHILD);
1212 /* Restore current maximized child */
1213 if((cs->style & WS_VISIBLE) && IsZoomed(top_child))
1215 TRACE("Restoring current maximized child %p\n", top_child);
1216 if (cs->style & WS_MAXIMIZE)
1218 /* if the new window is maximized don't bother repainting */
1219 SendMessageW( top_child, WM_SETREDRAW, FALSE, 0 );
1220 ShowWindow( top_child, SW_SHOWNORMAL );
1221 SendMessageW( top_child, WM_SETREDRAW, TRUE, 0 );
1223 else ShowWindow( top_child, SW_SHOWNORMAL );
1228 /* Find the parent window */
1230 parent = cs->hwndParent;
1233 if (cs->hwndParent == HWND_MESSAGE)
1235 cs->hwndParent = parent = get_hwnd_message_parent();
1237 else if (cs->hwndParent)
1239 if ((cs->style & (WS_CHILD|WS_POPUP)) != WS_CHILD)
1241 parent = GetDesktopWindow();
1242 owner = cs->hwndParent;
1246 DWORD parent_style = GetWindowLongW( parent, GWL_EXSTYLE );
1247 if ((parent_style & WS_EX_LAYOUTRTL) && !(parent_style & WS_EX_NOINHERITLAYOUT))
1248 cs->dwExStyle |= WS_EX_LAYOUTRTL;
1253 static const WCHAR messageW[] = {'M','e','s','s','a','g','e',0};
1255 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1257 WARN("No parent for child window\n" );
1258 SetLastError(ERROR_TLW_WITH_WSCHILD);
1259 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1261 /* are we creating the desktop or HWND_MESSAGE parent itself? */
1262 if (className != (LPCWSTR)DESKTOP_CLASS_ATOM &&
1263 (IS_INTRESOURCE(className) || strcmpiW( className, messageW )))
1265 parent = GetDesktopWindow();
1266 if (process_layout & LAYOUT_RTL) cs->dwExStyle |= WS_EX_LAYOUTRTL;
1270 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
1272 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
1273 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
1274 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
1275 cs->dwExStyle |= WS_EX_WINDOWEDGE;
1277 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
1279 /* Create the window structure */
1281 if (!(wndPtr = create_window_handle( parent, owner, className, module, unicode )))
1283 hwnd = wndPtr->obj.handle;
1285 /* Fill the window structure */
1287 wndPtr->tid = GetCurrentThreadId();
1288 wndPtr->hInstance = cs->hInstance;
1289 wndPtr->text = NULL;
1290 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1291 wndPtr->dwExStyle = cs->dwExStyle;
1292 wndPtr->wIDmenu = 0;
1293 wndPtr->helpContext = 0;
1294 wndPtr->pScroll = NULL;
1295 wndPtr->userdata = 0;
1297 wndPtr->hIconSmall = 0;
1298 wndPtr->hSysMenu = 0;
1300 wndPtr->min_pos.x = wndPtr->min_pos.y = -1;
1301 wndPtr->max_pos.x = wndPtr->max_pos.y = -1;
1303 if (wndPtr->dwStyle & WS_SYSMENU) SetSystemMenu( hwnd, 0 );
1306 * Correct the window styles.
1308 * It affects only the style loaded into the WIN structure.
1311 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
1313 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1314 if (!(wndPtr->dwStyle & WS_POPUP))
1315 wndPtr->dwStyle |= WS_CAPTION;
1319 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1320 * why does the user get to set it?
1323 if ((wndPtr->dwExStyle & WS_EX_DLGMODALFRAME) ||
1324 (wndPtr->dwStyle & (WS_DLGFRAME | WS_THICKFRAME)))
1325 wndPtr->dwExStyle |= WS_EX_WINDOWEDGE;
1327 wndPtr->dwExStyle &= ~WS_EX_WINDOWEDGE;
1329 if (!(wndPtr->dwStyle & (WS_CHILD | WS_POPUP)))
1330 wndPtr->flags |= WIN_NEED_SIZE;
1332 SERVER_START_REQ( set_window_info )
1334 req->handle = wine_server_user_handle( hwnd );
1335 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE | SET_WIN_UNICODE;
1336 req->style = wndPtr->dwStyle;
1337 req->ex_style = wndPtr->dwExStyle;
1338 req->instance = wine_server_client_ptr( wndPtr->hInstance );
1339 req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
1340 req->extra_offset = -1;
1341 wine_server_call( req );
1345 /* Set the window menu */
1347 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
1351 if (!MENU_SetMenu(hwnd, cs->hMenu))
1353 WIN_ReleasePtr( wndPtr );
1354 free_window_handle( hwnd );
1360 LPCWSTR menuName = (LPCWSTR)GetClassLongPtrW( hwnd, GCLP_MENUNAME );
1363 cs->hMenu = LoadMenuW( cs->hInstance, menuName );
1364 if (cs->hMenu) MENU_SetMenu( hwnd, cs->hMenu );
1368 else SetWindowLongPtrW( hwnd, GWLP_ID, (ULONG_PTR)cs->hMenu );
1370 /* call the WH_CBT hook */
1372 /* the window style passed to the hook must be the real window style,
1373 * rather than just the window style that the caller to CreateWindowEx
1374 * passed in, so we have to copy the original CREATESTRUCT and get the
1375 * the real style. */
1377 cbcs.style = wndPtr->dwStyle;
1379 cbtc.hwndInsertAfter = HWND_TOP;
1380 WIN_ReleasePtr( wndPtr );
1381 if (HOOK_CallHooks( WH_CBT, HCBT_CREATEWND, (WPARAM)hwnd, (LPARAM)&cbtc, unicode )) goto failed;
1383 /* send the WM_GETMINMAXINFO message and fix the size if needed */
1387 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
1389 POINT maxSize, maxPos, minTrack, maxTrack;
1390 WINPOS_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack);
1391 if (maxTrack.x < cx) cx = maxTrack.x;
1392 if (maxTrack.y < cy) cy = maxTrack.y;
1393 if (minTrack.x > cx) cx = minTrack.x;
1394 if (minTrack.y > cy) cy = minTrack.y;
1399 SetRect( &rect, cs->x, cs->y, cs->x + cx, cs->y + cy );
1400 /* check for wraparound */
1401 if (cs->x + cx < cs->x) rect.right = 0x7fffffff;
1402 if (cs->y + cy < cs->y) rect.bottom = 0x7fffffff;
1403 if (!set_window_pos( hwnd, 0, SWP_NOZORDER | SWP_NOACTIVATE, &rect, &rect, NULL )) goto failed;
1405 /* send WM_NCCREATE */
1407 TRACE( "hwnd %p cs %d,%d %dx%d\n", hwnd, cs->x, cs->y, cx, cy );
1409 result = SendMessageW( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
1411 result = SendMessageA( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
1414 WARN( "%p: aborted by WM_NCCREATE\n", hwnd );
1418 /* send WM_NCCALCSIZE */
1420 if (WIN_GetRectangles( hwnd, COORDS_PARENT, &rect, NULL ))
1422 /* yes, even if the CBT hook was called with HWND_TOP */
1423 HWND insert_after = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) ? HWND_BOTTOM : HWND_TOP;
1424 RECT client_rect = rect;
1426 /* the rectangle is in screen coords for WM_NCCALCSIZE when wparam is FALSE */
1427 MapWindowPoints( parent, 0, (POINT *)&client_rect, 2 );
1428 SendMessageW( hwnd, WM_NCCALCSIZE, FALSE, (LPARAM)&client_rect );
1429 MapWindowPoints( 0, parent, (POINT *)&client_rect, 2 );
1430 set_window_pos( hwnd, insert_after, SWP_NOACTIVATE, &rect, &client_rect, NULL );
1434 /* send WM_CREATE */
1437 result = SendMessageW( hwnd, WM_CREATE, 0, (LPARAM)cs );
1439 result = SendMessageA( hwnd, WM_CREATE, 0, (LPARAM)cs );
1440 if (result == -1) goto failed;
1442 /* call the driver */
1444 if (!USER_Driver->pCreateWindow( hwnd )) goto failed;
1446 NotifyWinEvent(EVENT_OBJECT_CREATE, hwnd, OBJID_WINDOW, 0);
1448 /* send the size messages */
1450 if (!(wndPtr = WIN_GetPtr( hwnd )) ||
1451 wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return 0;
1452 if (!(wndPtr->flags & WIN_NEED_SIZE))
1454 WIN_ReleasePtr( wndPtr );
1455 WIN_GetRectangles( hwnd, COORDS_PARENT, NULL, &rect );
1456 SendMessageW( hwnd, WM_SIZE, SIZE_RESTORED,
1457 MAKELONG(rect.right-rect.left, rect.bottom-rect.top));
1458 SendMessageW( hwnd, WM_MOVE, 0, MAKELONG( rect.left, rect.top ) );
1460 else WIN_ReleasePtr( wndPtr );
1462 /* Show the window, maximizing or minimizing if needed */
1464 style = WIN_SetStyle( hwnd, 0, WS_MAXIMIZE | WS_MINIMIZE );
1465 if (style & (WS_MINIMIZE | WS_MAXIMIZE))
1468 UINT swFlag = (style & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
1470 swFlag = WINPOS_MinMaximize( hwnd, swFlag, &newPos );
1471 swFlag |= SWP_FRAMECHANGED; /* Frame always gets changed */
1472 if (!(style & WS_VISIBLE) || (style & WS_CHILD) || GetActiveWindow()) swFlag |= SWP_NOACTIVATE;
1473 SetWindowPos( hwnd, 0, newPos.left, newPos.top, newPos.right - newPos.left,
1474 newPos.bottom - newPos.top, swFlag );
1477 /* Notify the parent window only */
1479 send_parent_notify( hwnd, WM_CREATE );
1480 if (!IsWindow( hwnd )) return 0;
1482 if (cs->style & WS_VISIBLE)
1484 if (cs->style & WS_MAXIMIZE)
1486 else if (cs->style & WS_MINIMIZE)
1487 sw = SW_SHOWMINIMIZED;
1489 ShowWindow( hwnd, sw );
1490 if (cs->dwExStyle & WS_EX_MDICHILD)
1492 SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
1493 /* ShowWindow won't activate child windows */
1494 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE );
1498 /* Call WH_SHELL hook */
1500 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1501 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1503 TRACE("created window %p\n", hwnd);
1507 WIN_DestroyWindow( hwnd );
1512 /***********************************************************************
1513 * CreateWindowExA (USER32.@)
1515 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1516 LPCSTR windowName, DWORD style, INT x,
1517 INT y, INT width, INT height,
1518 HWND parent, HMENU menu,
1519 HINSTANCE instance, LPVOID data )
1523 cs.lpCreateParams = data;
1524 cs.hInstance = instance;
1526 cs.hwndParent = parent;
1532 cs.lpszName = windowName;
1533 cs.lpszClass = className;
1534 cs.dwExStyle = exStyle;
1536 if (!IS_INTRESOURCE(className))
1539 if (!MultiByteToWideChar( CP_ACP, 0, className, -1, bufferW, sizeof(bufferW)/sizeof(WCHAR) ))
1541 return wow_handlers.create_window( (CREATESTRUCTW *)&cs, bufferW, instance, FALSE );
1543 /* Note: we rely on the fact that CREATESTRUCTA and */
1544 /* CREATESTRUCTW have the same layout. */
1545 return wow_handlers.create_window( (CREATESTRUCTW *)&cs, (LPCWSTR)className, instance, FALSE );
1549 /***********************************************************************
1550 * CreateWindowExW (USER32.@)
1552 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1553 LPCWSTR windowName, DWORD style, INT x,
1554 INT y, INT width, INT height,
1555 HWND parent, HMENU menu,
1556 HINSTANCE instance, LPVOID data )
1560 cs.lpCreateParams = data;
1561 cs.hInstance = instance;
1563 cs.hwndParent = parent;
1569 cs.lpszName = windowName;
1570 cs.lpszClass = className;
1571 cs.dwExStyle = exStyle;
1573 return wow_handlers.create_window( &cs, className, instance, TRUE );
1577 /***********************************************************************
1578 * WIN_SendDestroyMsg
1580 static void WIN_SendDestroyMsg( HWND hwnd )
1584 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1586 if (hwnd == info.hwndCaret) DestroyCaret();
1587 if (hwnd == info.hwndActive) WINPOS_ActivateOtherWindow( hwnd );
1591 * Send the WM_DESTROY to the window.
1593 SendMessageW( hwnd, WM_DESTROY, 0, 0);
1596 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1597 * make sure that the window still exists when we come back.
1604 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1606 for (i = 0; pWndArray[i]; i++)
1608 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1610 HeapFree( GetProcessHeap(), 0, pWndArray );
1613 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1617 /***********************************************************************
1618 * DestroyWindow (USER32.@)
1620 BOOL WINAPI DestroyWindow( HWND hwnd )
1624 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || is_desktop_window( hwnd ))
1626 SetLastError( ERROR_ACCESS_DENIED );
1630 TRACE("(%p)\n", hwnd);
1634 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1636 if (MENU_IsMenuActive() == hwnd)
1639 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1643 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1644 send_parent_notify( hwnd, WM_DESTROY );
1646 else if (!GetWindow( hwnd, GW_OWNER ))
1648 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1649 /* FIXME: clean up palette - see "Internals" p.352 */
1652 if (!IsWindow(hwnd)) return TRUE;
1654 /* Hide the window */
1655 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)
1657 /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
1659 ShowWindow( hwnd, SW_HIDE );
1661 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1662 SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW );
1665 if (!IsWindow(hwnd)) return TRUE;
1667 /* Recursively destroy owned windows */
1674 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1677 for (i = 0; list[i]; i++)
1679 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1680 if (WIN_IsCurrentThread( list[i] ))
1682 DestroyWindow( list[i] );
1686 WIN_SetOwner( list[i], 0 );
1688 HeapFree( GetProcessHeap(), 0, list );
1690 if (!got_one) break;
1694 /* Send destroy messages */
1696 WIN_SendDestroyMsg( hwnd );
1697 if (!IsWindow( hwnd )) return TRUE;
1699 if (GetClipboardOwner() == hwnd)
1700 CLIPBOARD_ReleaseOwner();
1702 /* Destroy the window storage */
1704 WIN_DestroyWindow( hwnd );
1709 /***********************************************************************
1710 * CloseWindow (USER32.@)
1712 BOOL WINAPI CloseWindow( HWND hwnd )
1714 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1715 ShowWindow( hwnd, SW_MINIMIZE );
1720 /***********************************************************************
1721 * OpenIcon (USER32.@)
1723 BOOL WINAPI OpenIcon( HWND hwnd )
1725 if (!IsIconic( hwnd )) return FALSE;
1726 ShowWindow( hwnd, SW_SHOWNORMAL );
1731 /***********************************************************************
1732 * FindWindowExW (USER32.@)
1734 HWND WINAPI FindWindowExW( HWND parent, HWND child, LPCWSTR className, LPCWSTR title )
1739 WCHAR *buffer = NULL;
1741 if (!parent && child) parent = GetDesktopWindow();
1742 else if (parent == HWND_MESSAGE) parent = get_hwnd_message_parent();
1746 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1747 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1750 if (!(list = list_window_children( 0, parent, className, 0 ))) goto done;
1754 child = WIN_GetFullHandle( child );
1755 while (list[i] && list[i] != child) i++;
1756 if (!list[i]) goto done;
1757 i++; /* start from next window */
1764 if (GetWindowTextW( list[i], buffer, len + 1 ) && !strcmpiW( buffer, title )) break;
1771 HeapFree( GetProcessHeap(), 0, list );
1772 HeapFree( GetProcessHeap(), 0, buffer );
1778 /***********************************************************************
1779 * FindWindowA (USER32.@)
1781 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1783 HWND ret = FindWindowExA( 0, 0, className, title );
1784 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1789 /***********************************************************************
1790 * FindWindowExA (USER32.@)
1792 HWND WINAPI FindWindowExA( HWND parent, HWND child, LPCSTR className, LPCSTR title )
1794 LPWSTR titleW = NULL;
1799 DWORD len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1800 if (!(titleW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1801 MultiByteToWideChar( CP_ACP, 0, title, -1, titleW, len );
1804 if (!IS_INTRESOURCE(className))
1807 if (MultiByteToWideChar( CP_ACP, 0, className, -1, classW, sizeof(classW)/sizeof(WCHAR) ))
1808 hwnd = FindWindowExW( parent, child, classW, titleW );
1812 hwnd = FindWindowExW( parent, child, (LPCWSTR)className, titleW );
1815 HeapFree( GetProcessHeap(), 0, titleW );
1820 /***********************************************************************
1821 * FindWindowW (USER32.@)
1823 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1825 return FindWindowExW( 0, 0, className, title );
1829 /**********************************************************************
1830 * GetDesktopWindow (USER32.@)
1832 HWND WINAPI GetDesktopWindow(void)
1834 struct user_thread_info *thread_info = get_user_thread_info();
1836 if (thread_info->top_window) return thread_info->top_window;
1838 SERVER_START_REQ( get_desktop_window )
1841 if (!wine_server_call( req ))
1843 thread_info->top_window = wine_server_ptr_handle( reply->top_window );
1844 thread_info->msg_window = wine_server_ptr_handle( reply->msg_window );
1849 if (!thread_info->top_window)
1851 USEROBJECTFLAGS flags;
1852 if (!GetUserObjectInformationW( GetProcessWindowStation(), UOI_FLAGS, &flags,
1853 sizeof(flags), NULL ) || (flags.dwFlags & WSF_VISIBLE))
1855 static const WCHAR explorer[] = {'\\','e','x','p','l','o','r','e','r','.','e','x','e',0};
1856 static const WCHAR args[] = {' ','/','d','e','s','k','t','o','p',0};
1858 PROCESS_INFORMATION pi;
1859 WCHAR windir[MAX_PATH];
1860 WCHAR app[MAX_PATH + sizeof(explorer)/sizeof(WCHAR)];
1861 WCHAR cmdline[MAX_PATH + (sizeof(explorer) + sizeof(args))/sizeof(WCHAR)];
1864 memset( &si, 0, sizeof(si) );
1866 si.dwFlags = STARTF_USESTDHANDLES;
1869 si.hStdError = GetStdHandle( STD_ERROR_HANDLE );
1871 GetSystemDirectoryW( windir, MAX_PATH );
1872 strcpyW( app, windir );
1873 strcatW( app, explorer );
1874 strcpyW( cmdline, app );
1875 strcatW( cmdline, args );
1877 Wow64DisableWow64FsRedirection( &redir );
1878 if (CreateProcessW( app, cmdline, NULL, NULL, FALSE, DETACHED_PROCESS,
1879 NULL, windir, &si, &pi ))
1881 TRACE( "started explorer pid %04x tid %04x\n", pi.dwProcessId, pi.dwThreadId );
1882 WaitForInputIdle( pi.hProcess, 10000 );
1883 CloseHandle( pi.hThread );
1884 CloseHandle( pi.hProcess );
1886 else WARN( "failed to start explorer, err %d\n", GetLastError() );
1887 Wow64RevertWow64FsRedirection( redir );
1889 else TRACE( "not starting explorer since winstation is not visible\n" );
1891 SERVER_START_REQ( get_desktop_window )
1894 if (!wine_server_call( req ))
1896 thread_info->top_window = wine_server_ptr_handle( reply->top_window );
1897 thread_info->msg_window = wine_server_ptr_handle( reply->msg_window );
1903 if (!thread_info->top_window || !USER_Driver->pCreateDesktopWindow( thread_info->top_window ))
1904 ERR( "failed to create desktop window\n" );
1906 return thread_info->top_window;
1910 /*******************************************************************
1911 * EnableWindow (USER32.@)
1913 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1918 if (is_broadcast(hwnd))
1920 SetLastError( ERROR_INVALID_PARAMETER );
1924 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1925 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1929 TRACE("( %p, %d )\n", hwnd, enable);
1931 retvalue = !IsWindowEnabled( hwnd );
1933 if (enable && retvalue)
1935 WIN_SetStyle( hwnd, 0, WS_DISABLED );
1936 SendMessageW( hwnd, WM_ENABLE, TRUE, 0 );
1938 else if (!enable && !retvalue)
1942 SendMessageW( hwnd, WM_CANCELMODE, 0, 0);
1944 WIN_SetStyle( hwnd, WS_DISABLED, 0 );
1946 if (hwnd == GetFocus())
1947 SetFocus( 0 ); /* A disabled window can't have the focus */
1949 capture_wnd = GetCapture();
1950 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1951 ReleaseCapture(); /* A disabled window can't capture the mouse */
1953 SendMessageW( hwnd, WM_ENABLE, FALSE, 0 );
1959 /***********************************************************************
1960 * IsWindowEnabled (USER32.@)
1962 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1964 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1968 /***********************************************************************
1969 * IsWindowUnicode (USER32.@)
1971 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1974 BOOL retvalue = FALSE;
1976 if (!(wndPtr = WIN_GetPtr(hwnd))) return FALSE;
1978 if (wndPtr == WND_DESKTOP) return TRUE;
1980 if (wndPtr != WND_OTHER_PROCESS)
1982 retvalue = (wndPtr->flags & WIN_ISUNICODE) != 0;
1983 WIN_ReleasePtr( wndPtr );
1987 SERVER_START_REQ( get_window_info )
1989 req->handle = wine_server_user_handle( hwnd );
1990 if (!wine_server_call_err( req )) retvalue = reply->is_unicode;
1998 /**********************************************************************
2001 * Helper function for GetWindowLong().
2003 static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, UINT size, BOOL unicode )
2005 LONG_PTR retvalue = 0;
2008 if (offset == GWLP_HWNDPARENT)
2010 HWND parent = GetAncestor( hwnd, GA_PARENT );
2011 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
2012 return (ULONG_PTR)parent;
2015 if (!(wndPtr = WIN_GetPtr( hwnd )))
2017 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2021 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
2023 if (offset == GWLP_WNDPROC)
2025 SetLastError( ERROR_ACCESS_DENIED );
2028 SERVER_START_REQ( set_window_info )
2030 req->handle = wine_server_user_handle( hwnd );
2031 req->flags = 0; /* don't set anything, just retrieve */
2032 req->extra_offset = (offset >= 0) ? offset : -1;
2033 req->extra_size = (offset >= 0) ? size : 0;
2034 if (!wine_server_call_err( req ))
2038 case GWL_STYLE: retvalue = reply->old_style; break;
2039 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
2040 case GWLP_ID: retvalue = reply->old_id; break;
2041 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wine_server_get_ptr( reply->old_instance ); break;
2042 case GWLP_USERDATA: retvalue = reply->old_user_data; break;
2044 if (offset >= 0) retvalue = get_win_data( &reply->old_extra_value, size );
2045 else SetLastError( ERROR_INVALID_INDEX );
2054 /* now we have a valid wndPtr */
2058 if (offset > (int)(wndPtr->cbWndExtra - size))
2060 WARN("Invalid offset %d\n", offset );
2061 WIN_ReleasePtr( wndPtr );
2062 SetLastError( ERROR_INVALID_INDEX );
2065 retvalue = get_win_data( (char *)wndPtr->wExtra + offset, size );
2067 /* Special case for dialog window procedure */
2068 if ((offset == DWLP_DLGPROC) && (size == sizeof(LONG_PTR)) && wndPtr->dlgInfo)
2069 retvalue = (LONG_PTR)WINPROC_GetProc( (WNDPROC)retvalue, unicode );
2070 WIN_ReleasePtr( wndPtr );
2076 case GWLP_USERDATA: retvalue = wndPtr->userdata; break;
2077 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
2078 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
2079 case GWLP_ID: retvalue = wndPtr->wIDmenu; break;
2080 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wndPtr->hInstance; break;
2082 /* This looks like a hack only for the edit control (see tests). This makes these controls
2083 * more tolerant to A/W mismatches. The lack of W->A->W conversion for such a mismatch suggests
2084 * that the hack is in GetWindowLongPtr[AW], not in winprocs.
2086 if (wndPtr->winproc == BUILTIN_WINPROC(WINPROC_EDIT) && (!unicode != !(wndPtr->flags & WIN_ISUNICODE)))
2087 retvalue = (ULONG_PTR)wndPtr->winproc;
2089 retvalue = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, unicode );
2092 WARN("Unknown offset %d\n", offset );
2093 SetLastError( ERROR_INVALID_INDEX );
2096 WIN_ReleasePtr(wndPtr);
2101 /**********************************************************************
2104 * Helper function for SetWindowLong().
2106 * 0 is the failure code. However, in the case of failure SetLastError
2107 * must be set to distinguish between a 0 return value and a failure.
2109 LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, UINT size, LONG_PTR newval, BOOL unicode )
2113 LONG_PTR retval = 0;
2116 TRACE( "%p %d %lx %c\n", hwnd, offset, newval, unicode ? 'W' : 'A' );
2118 if (is_broadcast(hwnd))
2120 SetLastError( ERROR_INVALID_PARAMETER );
2124 if (!(wndPtr = WIN_GetPtr( hwnd )))
2126 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2129 if (wndPtr == WND_DESKTOP)
2131 /* can't change anything on the desktop window */
2132 SetLastError( ERROR_ACCESS_DENIED );
2135 if (wndPtr == WND_OTHER_PROCESS)
2137 if (offset == GWLP_WNDPROC)
2139 SetLastError( ERROR_ACCESS_DENIED );
2142 if (offset > 32767 || offset < -32767)
2144 SetLastError( ERROR_INVALID_INDEX );
2147 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, MAKEWPARAM( offset, size ), newval );
2150 /* first some special cases */
2154 style.styleOld = wndPtr->dwStyle;
2155 style.styleNew = newval;
2156 WIN_ReleasePtr( wndPtr );
2157 SendMessageW( hwnd, WM_STYLECHANGING, GWL_STYLE, (LPARAM)&style );
2158 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
2159 newval = style.styleNew;
2160 /* WS_CLIPSIBLINGS can't be reset on top-level windows */
2161 if (wndPtr->parent == GetDesktopWindow()) newval |= WS_CLIPSIBLINGS;
2164 style.styleOld = wndPtr->dwExStyle;
2165 style.styleNew = newval;
2166 WIN_ReleasePtr( wndPtr );
2167 SendMessageW( hwnd, WM_STYLECHANGING, GWL_EXSTYLE, (LPARAM)&style );
2168 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
2169 /* WS_EX_TOPMOST can only be changed through SetWindowPos */
2170 newval = (style.styleNew & ~WS_EX_TOPMOST) | (wndPtr->dwExStyle & WS_EX_TOPMOST);
2171 /* WS_EX_WINDOWEDGE depends on some other styles */
2172 if ((newval & WS_EX_DLGMODALFRAME) || (wndPtr->dwStyle & WS_THICKFRAME))
2173 newval |= WS_EX_WINDOWEDGE;
2174 else if (wndPtr->dwStyle & (WS_CHILD|WS_POPUP))
2175 newval &= ~WS_EX_WINDOWEDGE;
2177 case GWLP_HWNDPARENT:
2178 if (wndPtr->parent == GetDesktopWindow())
2180 WIN_ReleasePtr( wndPtr );
2181 return (ULONG_PTR)WIN_SetOwner( hwnd, (HWND)newval );
2185 WIN_ReleasePtr( wndPtr );
2186 return (ULONG_PTR)SetParent( hwnd, (HWND)newval );
2191 UINT old_flags = wndPtr->flags;
2192 retval = WIN_GetWindowLong( hwnd, offset, size, unicode );
2193 proc = WINPROC_AllocProc( (WNDPROC)newval, unicode );
2194 if (proc) wndPtr->winproc = proc;
2195 if (WINPROC_IsUnicode( proc, unicode )) wndPtr->flags |= WIN_ISUNICODE;
2196 else wndPtr->flags &= ~WIN_ISUNICODE;
2197 if (!((old_flags ^ wndPtr->flags) & WIN_ISUNICODE))
2199 WIN_ReleasePtr( wndPtr );
2202 /* update is_unicode flag on the server side */
2206 case GWLP_HINSTANCE:
2210 if ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
2211 (size == sizeof(LONG_PTR)) && wndPtr->dlgInfo)
2213 WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWLP_DLGPROC);
2214 retval = (ULONG_PTR)WINPROC_GetProc( *ptr, unicode );
2215 *ptr = WINPROC_AllocProc( (WNDPROC)newval, unicode );
2216 WIN_ReleasePtr( wndPtr );
2221 if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - size))
2223 WARN("Invalid offset %d\n", offset );
2224 WIN_ReleasePtr( wndPtr );
2225 SetLastError( ERROR_INVALID_INDEX );
2228 else if (get_win_data( (char *)wndPtr->wExtra + offset, size ) == newval)
2230 /* already set to the same value */
2231 WIN_ReleasePtr( wndPtr );
2237 SERVER_START_REQ( set_window_info )
2239 req->handle = wine_server_user_handle( hwnd );
2240 req->extra_offset = -1;
2244 req->flags = SET_WIN_STYLE;
2245 req->style = newval;
2248 req->flags = SET_WIN_EXSTYLE;
2249 req->ex_style = newval;
2252 req->flags = SET_WIN_ID;
2255 case GWLP_HINSTANCE:
2256 req->flags = SET_WIN_INSTANCE;
2257 req->instance = wine_server_client_ptr( (void *)newval );
2260 req->flags = SET_WIN_UNICODE;
2261 req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
2264 req->flags = SET_WIN_USERDATA;
2265 req->user_data = newval;
2268 req->flags = SET_WIN_EXTRA;
2269 req->extra_offset = offset;
2270 req->extra_size = size;
2271 set_win_data( &req->extra_value, newval, size );
2273 if ((ok = !wine_server_call_err( req )))
2278 wndPtr->dwStyle = newval;
2279 retval = reply->old_style;
2282 wndPtr->dwExStyle = newval;
2283 retval = reply->old_ex_style;
2286 wndPtr->wIDmenu = newval;
2287 retval = reply->old_id;
2289 case GWLP_HINSTANCE:
2290 wndPtr->hInstance = (HINSTANCE)newval;
2291 retval = (ULONG_PTR)wine_server_get_ptr( reply->old_instance );
2296 wndPtr->userdata = newval;
2297 retval = reply->old_user_data;
2300 retval = get_win_data( (char *)wndPtr->wExtra + offset, size );
2301 set_win_data( (char *)wndPtr->wExtra + offset, newval, size );
2307 WIN_ReleasePtr( wndPtr );
2311 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2313 style.styleOld = retval;
2314 style.styleNew = newval;
2315 USER_Driver->pSetWindowStyle( hwnd, offset, &style );
2316 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2323 /**********************************************************************
2324 * GetWindowWord (USER32.@)
2326 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
2331 case GWLP_HINSTANCE:
2332 case GWLP_HWNDPARENT:
2337 WARN("Invalid offset %d\n", offset );
2338 SetLastError( ERROR_INVALID_INDEX );
2343 return WIN_GetWindowLong( hwnd, offset, sizeof(WORD), FALSE );
2347 /**********************************************************************
2348 * GetWindowLongA (USER32.@)
2350 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2352 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), FALSE );
2356 /**********************************************************************
2357 * GetWindowLongW (USER32.@)
2359 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2361 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), TRUE );
2365 /**********************************************************************
2366 * SetWindowWord (USER32.@)
2368 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
2373 case GWLP_HINSTANCE:
2374 case GWLP_HWNDPARENT:
2379 WARN("Invalid offset %d\n", offset );
2380 SetLastError( ERROR_INVALID_INDEX );
2385 return WIN_SetWindowLong( hwnd, offset, sizeof(WORD), newval, FALSE );
2389 /**********************************************************************
2390 * SetWindowLongA (USER32.@)
2392 * See SetWindowLongW.
2394 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2396 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, FALSE );
2400 /**********************************************************************
2401 * SetWindowLongW (USER32.@) Set window attribute
2403 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2404 * value in a window's extra memory.
2406 * The _hwnd_ parameter specifies the window. is the handle to a
2407 * window that has extra memory. The _newval_ parameter contains the
2408 * new attribute or extra memory value. If positive, the _offset_
2409 * parameter is the byte-addressed location in the window's extra
2410 * memory to set. If negative, _offset_ specifies the window
2411 * attribute to set, and should be one of the following values:
2413 * GWL_EXSTYLE The window's extended window style
2415 * GWL_STYLE The window's window style.
2417 * GWLP_WNDPROC Pointer to the window's window procedure.
2419 * GWLP_HINSTANCE The window's pplication instance handle.
2421 * GWLP_ID The window's identifier.
2423 * GWLP_USERDATA The window's user-specified data.
2425 * If the window is a dialog box, the _offset_ parameter can be one of
2426 * the following values:
2428 * DWLP_DLGPROC The address of the window's dialog box procedure.
2430 * DWLP_MSGRESULT The return value of a message
2431 * that the dialog box procedure processed.
2433 * DWLP_USER Application specific information.
2437 * If successful, returns the previous value located at _offset_. Otherwise,
2442 * Extra memory for a window class is specified by a nonzero cbWndExtra
2443 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2444 * time of class creation.
2446 * Using GWL_WNDPROC to set a new window procedure effectively creates
2447 * a window subclass. Use CallWindowProc() in the new windows procedure
2448 * to pass messages to the superclass's window procedure.
2450 * The user data is reserved for use by the application which created
2453 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2454 * instead, call the EnableWindow() function to change the window's
2457 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2458 * SetParent() instead.
2461 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2462 * it sends WM_STYLECHANGING before changing the settings
2463 * and WM_STYLECHANGED afterwards.
2464 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2466 LONG WINAPI SetWindowLongW(
2467 HWND hwnd, /* [in] window to alter */
2468 INT offset, /* [in] offset, in bytes, of location to alter */
2469 LONG newval /* [in] new value of location */
2471 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, TRUE );
2475 /*******************************************************************
2476 * GetWindowTextA (USER32.@)
2478 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2482 if (!lpString) return 0;
2484 if (WIN_IsCurrentProcess( hwnd ))
2485 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2487 /* when window belongs to other process, don't send a message */
2488 if (nMaxCount <= 0) return 0;
2489 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2490 get_server_window_text( hwnd, buffer, nMaxCount );
2491 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2492 lpString[nMaxCount-1] = 0;
2493 HeapFree( GetProcessHeap(), 0, buffer );
2494 return strlen(lpString);
2498 /*******************************************************************
2499 * InternalGetWindowText (USER32.@)
2501 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2505 if (nMaxCount <= 0) return 0;
2506 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2507 if (win == WND_DESKTOP) lpString[0] = 0;
2508 else if (win != WND_OTHER_PROCESS)
2510 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2511 else lpString[0] = 0;
2512 WIN_ReleasePtr( win );
2516 get_server_window_text( hwnd, lpString, nMaxCount );
2518 return strlenW(lpString);
2522 /*******************************************************************
2523 * GetWindowTextW (USER32.@)
2525 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2527 if (!lpString) return 0;
2529 if (WIN_IsCurrentProcess( hwnd ))
2530 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2532 /* when window belongs to other process, don't send a message */
2533 if (nMaxCount <= 0) return 0;
2534 get_server_window_text( hwnd, lpString, nMaxCount );
2535 return strlenW(lpString);
2539 /*******************************************************************
2540 * SetWindowTextA (USER32.@)
2541 * SetWindowText (USER32.@)
2543 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2545 if (is_broadcast(hwnd))
2547 SetLastError( ERROR_INVALID_PARAMETER );
2550 if (!WIN_IsCurrentProcess( hwnd ))
2551 WARN( "setting text %s of other process window %p should not use SendMessage\n",
2552 debugstr_a(lpString), hwnd );
2553 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2557 /*******************************************************************
2558 * SetWindowTextW (USER32.@)
2560 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2562 if (is_broadcast(hwnd))
2564 SetLastError( ERROR_INVALID_PARAMETER );
2567 if (!WIN_IsCurrentProcess( hwnd ))
2568 WARN( "setting text %s of other process window %p should not use SendMessage\n",
2569 debugstr_w(lpString), hwnd );
2570 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2574 /*******************************************************************
2575 * GetWindowTextLengthA (USER32.@)
2577 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2579 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2582 /*******************************************************************
2583 * GetWindowTextLengthW (USER32.@)
2585 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2587 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2591 /*******************************************************************
2592 * IsWindow (USER32.@)
2594 BOOL WINAPI IsWindow( HWND hwnd )
2599 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2600 if (ptr == WND_DESKTOP) return TRUE;
2602 if (ptr != WND_OTHER_PROCESS)
2604 WIN_ReleasePtr( ptr );
2608 /* check other processes */
2609 SERVER_START_REQ( get_window_info )
2611 req->handle = wine_server_user_handle( hwnd );
2612 ret = !wine_server_call_err( req );
2619 /***********************************************************************
2620 * GetWindowThreadProcessId (USER32.@)
2622 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2627 if (!(ptr = WIN_GetPtr( hwnd )))
2629 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2633 if (ptr != WND_OTHER_PROCESS && ptr != WND_DESKTOP)
2635 /* got a valid window */
2637 if (process) *process = GetCurrentProcessId();
2638 WIN_ReleasePtr( ptr );
2642 /* check other processes */
2643 SERVER_START_REQ( get_window_info )
2645 req->handle = wine_server_user_handle( hwnd );
2646 if (!wine_server_call_err( req ))
2648 tid = (DWORD)reply->tid;
2649 if (process) *process = (DWORD)reply->pid;
2657 /*****************************************************************
2658 * GetParent (USER32.@)
2660 HWND WINAPI GetParent( HWND hwnd )
2665 if (!(wndPtr = WIN_GetPtr( hwnd )))
2667 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2670 if (wndPtr == WND_DESKTOP) return 0;
2671 if (wndPtr == WND_OTHER_PROCESS)
2673 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2674 if (style & (WS_POPUP | WS_CHILD))
2676 SERVER_START_REQ( get_window_tree )
2678 req->handle = wine_server_user_handle( hwnd );
2679 if (!wine_server_call_err( req ))
2681 if (style & WS_POPUP) retvalue = wine_server_ptr_handle( reply->owner );
2682 else if (style & WS_CHILD) retvalue = wine_server_ptr_handle( reply->parent );
2690 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2691 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2692 WIN_ReleasePtr( wndPtr );
2698 /*****************************************************************
2699 * GetAncestor (USER32.@)
2701 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2704 HWND *list, ret = 0;
2709 if (!(win = WIN_GetPtr( hwnd )))
2711 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2714 if (win == WND_DESKTOP) return 0;
2715 if (win != WND_OTHER_PROCESS)
2718 WIN_ReleasePtr( win );
2720 else /* need to query the server */
2722 SERVER_START_REQ( get_window_tree )
2724 req->handle = wine_server_user_handle( hwnd );
2725 if (!wine_server_call_err( req )) ret = wine_server_ptr_handle( reply->parent );
2732 if (!(list = list_window_parents( hwnd ))) return 0;
2734 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2738 while (list[count]) count++;
2739 ret = list[count - 2]; /* get the one before the desktop */
2741 HeapFree( GetProcessHeap(), 0, list );
2745 if (is_desktop_window( hwnd )) return 0;
2746 ret = WIN_GetFullHandle( hwnd );
2749 HWND parent = GetParent( ret );
2759 /*****************************************************************
2760 * SetParent (USER32.@)
2762 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2765 HWND old_parent = 0;
2770 if (is_broadcast(hwnd) || is_broadcast(parent))
2772 SetLastError(ERROR_INVALID_PARAMETER);
2776 if (!parent) parent = GetDesktopWindow();
2777 else if (parent == HWND_MESSAGE) parent = get_hwnd_message_parent();
2778 else parent = WIN_GetFullHandle( parent );
2780 if (!IsWindow( parent ))
2782 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2786 /* Some applications try to set a child as a parent */
2787 if (IsChild(hwnd, parent))
2789 SetLastError( ERROR_INVALID_PARAMETER );
2793 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2794 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2796 if (full_handle == parent)
2798 SetLastError( ERROR_INVALID_PARAMETER );
2802 /* Windows hides the window first, then shows it again
2803 * including the WM_SHOWWINDOW messages and all */
2804 was_visible = ShowWindow( hwnd, SW_HIDE );
2806 wndPtr = WIN_GetPtr( hwnd );
2807 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return 0;
2809 SERVER_START_REQ( set_parent )
2811 req->handle = wine_server_user_handle( hwnd );
2812 req->parent = wine_server_user_handle( parent );
2813 if ((ret = !wine_server_call( req )))
2815 old_parent = wine_server_ptr_handle( reply->old_parent );
2816 wndPtr->parent = parent = wine_server_ptr_handle( reply->full_parent );
2821 WIN_ReleasePtr( wndPtr );
2824 USER_Driver->pSetParent( full_handle, parent, old_parent );
2826 /* SetParent additionally needs to make hwnd the topmost window
2827 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2828 WM_WINDOWPOSCHANGED notification messages.
2830 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0,
2831 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2832 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2833 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2839 /*******************************************************************
2840 * IsChild (USER32.@)
2842 BOOL WINAPI IsChild( HWND parent, HWND child )
2844 HWND *list = list_window_parents( child );
2848 if (!list) return FALSE;
2849 parent = WIN_GetFullHandle( parent );
2850 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2851 ret = list[i] && list[i+1];
2852 HeapFree( GetProcessHeap(), 0, list );
2857 /***********************************************************************
2858 * IsWindowVisible (USER32.@)
2860 BOOL WINAPI IsWindowVisible( HWND hwnd )
2866 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2867 if (!(list = list_window_parents( hwnd ))) return TRUE;
2870 for (i = 0; list[i+1]; i++)
2871 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2872 retval = !list[i+1] && (list[i] == GetDesktopWindow()); /* top message window isn't visible */
2874 HeapFree( GetProcessHeap(), 0, list );
2879 /***********************************************************************
2880 * WIN_IsWindowDrawable
2882 * hwnd is drawable when it is visible, all parents are not
2883 * minimized, and it is itself not minimized unless we are
2884 * trying to draw its default class icon.
2886 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2891 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2893 if (!(style & WS_VISIBLE)) return FALSE;
2894 if ((style & WS_MINIMIZE) && icon && GetClassLongPtrW( hwnd, GCLP_HICON )) return FALSE;
2896 if (!(list = list_window_parents( hwnd ))) return TRUE;
2899 for (i = 0; list[i+1]; i++)
2900 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2902 retval = !list[i+1] && (list[i] == GetDesktopWindow()); /* top message window isn't visible */
2904 HeapFree( GetProcessHeap(), 0, list );
2909 /*******************************************************************
2910 * GetTopWindow (USER32.@)
2912 HWND WINAPI GetTopWindow( HWND hwnd )
2914 if (!hwnd) hwnd = GetDesktopWindow();
2915 return GetWindow( hwnd, GW_CHILD );
2919 /*******************************************************************
2920 * GetWindow (USER32.@)
2922 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2926 if (rel == GW_OWNER) /* this one may be available locally */
2928 WND *wndPtr = WIN_GetPtr( hwnd );
2931 SetLastError( ERROR_INVALID_HANDLE );
2934 if (wndPtr == WND_DESKTOP) return 0;
2935 if (wndPtr != WND_OTHER_PROCESS)
2937 retval = wndPtr->owner;
2938 WIN_ReleasePtr( wndPtr );
2941 /* else fall through to server call */
2944 SERVER_START_REQ( get_window_tree )
2946 req->handle = wine_server_user_handle( hwnd );
2947 if (!wine_server_call_err( req ))
2952 retval = wine_server_ptr_handle( reply->first_sibling );
2955 retval = wine_server_ptr_handle( reply->last_sibling );
2958 retval = wine_server_ptr_handle( reply->next_sibling );
2961 retval = wine_server_ptr_handle( reply->prev_sibling );
2964 retval = wine_server_ptr_handle( reply->owner );
2967 retval = wine_server_ptr_handle( reply->first_child );
2977 /*******************************************************************
2978 * ShowOwnedPopups (USER32.@)
2980 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2984 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2986 if (!win_array) return TRUE;
2988 while (win_array[count]) count++;
2989 while (--count >= 0)
2991 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2992 if (!(pWnd = WIN_GetPtr( win_array[count] ))) continue;
2993 if (pWnd == WND_OTHER_PROCESS) continue;
2996 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2998 WIN_ReleasePtr( pWnd );
2999 /* In Windows, ShowOwnedPopups(TRUE) generates
3000 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
3001 * regardless of the state of the owner
3003 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_SHOWNORMAL, SW_PARENTOPENING);
3009 if (pWnd->dwStyle & WS_VISIBLE)
3011 WIN_ReleasePtr( pWnd );
3012 /* In Windows, ShowOwnedPopups(FALSE) generates
3013 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
3014 * regardless of the state of the owner
3016 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
3020 WIN_ReleasePtr( pWnd );
3022 HeapFree( GetProcessHeap(), 0, win_array );
3027 /*******************************************************************
3028 * GetLastActivePopup (USER32.@)
3030 HWND WINAPI GetLastActivePopup( HWND hwnd )
3034 SERVER_START_REQ( get_window_info )
3036 req->handle = wine_server_user_handle( hwnd );
3037 if (!wine_server_call_err( req )) retval = wine_server_ptr_handle( reply->last_active );
3044 /*******************************************************************
3047 * Build an array of the children of a given window. The array must be
3048 * freed with HeapFree. Returns NULL when no windows are found.
3050 HWND *WIN_ListChildren( HWND hwnd )
3054 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
3057 return list_window_children( 0, hwnd, NULL, 0 );
3061 /*******************************************************************
3062 * EnumWindows (USER32.@)
3064 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
3070 USER_CheckNotLock();
3072 /* We have to build a list of all windows first, to avoid */
3073 /* unpleasant side-effects, for instance if the callback */
3074 /* function changes the Z-order of the windows. */
3076 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
3078 /* Now call the callback function for every window */
3080 for (i = 0; list[i]; i++)
3082 /* Make sure that the window still exists */
3083 if (!IsWindow( list[i] )) continue;
3084 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
3086 HeapFree( GetProcessHeap(), 0, list );
3091 /**********************************************************************
3092 * EnumThreadWindows (USER32.@)
3094 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
3100 USER_CheckNotLock();
3102 if (!(list = list_window_children( 0, GetDesktopWindow(), NULL, id ))) return TRUE;
3104 /* Now call the callback function for every window */
3106 for (i = 0; list[i]; i++)
3107 if (!(ret = func( list[i], lParam ))) break;
3108 HeapFree( GetProcessHeap(), 0, list );
3113 /***********************************************************************
3114 * EnumDesktopWindows (USER32.@)
3116 BOOL WINAPI EnumDesktopWindows( HDESK desktop, WNDENUMPROC func, LPARAM lparam )
3121 USER_CheckNotLock();
3123 if (!(list = list_window_children( desktop, 0, NULL, 0 ))) return TRUE;
3125 for (i = 0; list[i]; i++)
3126 if (!func( list[i], lparam )) break;
3127 HeapFree( GetProcessHeap(), 0, list );
3132 /**********************************************************************
3133 * WIN_EnumChildWindows
3135 * Helper function for EnumChildWindows().
3137 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
3142 for ( ; *list; list++)
3144 /* Make sure that the window still exists */
3145 if (!IsWindow( *list )) continue;
3146 /* Build children list first */
3147 childList = WIN_ListChildren( *list );
3149 ret = func( *list, lParam );
3153 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
3154 HeapFree( GetProcessHeap(), 0, childList );
3156 if (!ret) return FALSE;
3162 /**********************************************************************
3163 * EnumChildWindows (USER32.@)
3165 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
3170 USER_CheckNotLock();
3172 if (!(list = WIN_ListChildren( parent ))) return FALSE;
3173 ret = WIN_EnumChildWindows( list, func, lParam );
3174 HeapFree( GetProcessHeap(), 0, list );
3179 /*******************************************************************
3180 * AnyPopup (USER32.@)
3182 BOOL WINAPI AnyPopup(void)
3186 HWND *list = WIN_ListChildren( GetDesktopWindow() );
3188 if (!list) return FALSE;
3189 for (i = 0; list[i]; i++)
3191 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
3193 retvalue = (list[i] != 0);
3194 HeapFree( GetProcessHeap(), 0, list );
3199 /*******************************************************************
3200 * FlashWindow (USER32.@)
3202 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3206 TRACE("%p\n", hWnd);
3208 if (IsIconic( hWnd ))
3210 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3212 wndPtr = WIN_GetPtr(hWnd);
3213 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
3214 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3216 wndPtr->flags |= WIN_NCACTIVATED;
3220 wndPtr->flags &= ~WIN_NCACTIVATED;
3222 WIN_ReleasePtr( wndPtr );
3229 wndPtr = WIN_GetPtr(hWnd);
3230 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
3231 hWnd = wndPtr->obj.handle; /* make it a full handle */
3233 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3234 else wparam = (hWnd == GetForegroundWindow());
3236 WIN_ReleasePtr( wndPtr );
3237 SendMessageW( hWnd, WM_NCACTIVATE, wparam, 0 );
3242 /*******************************************************************
3243 * FlashWindowEx (USER32.@)
3245 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
3247 FIXME("%p\n", pfwi);
3251 /*******************************************************************
3252 * GetWindowContextHelpId (USER32.@)
3254 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3257 WND *wnd = WIN_GetPtr( hwnd );
3258 if (!wnd || wnd == WND_DESKTOP) return 0;
3259 if (wnd == WND_OTHER_PROCESS)
3261 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3264 retval = wnd->helpContext;
3265 WIN_ReleasePtr( wnd );
3270 /*******************************************************************
3271 * SetWindowContextHelpId (USER32.@)
3273 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3275 WND *wnd = WIN_GetPtr( hwnd );
3276 if (!wnd || wnd == WND_DESKTOP) return FALSE;
3277 if (wnd == WND_OTHER_PROCESS)
3279 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3282 wnd->helpContext = id;
3283 WIN_ReleasePtr( wnd );
3288 /*******************************************************************
3289 * DragDetect (USER32.@)
3291 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3295 WORD wDragWidth = GetSystemMetrics(SM_CXDRAG);
3296 WORD wDragHeight= GetSystemMetrics(SM_CYDRAG);
3298 rect.left = pt.x - wDragWidth;
3299 rect.right = pt.x + wDragWidth;
3301 rect.top = pt.y - wDragHeight;
3302 rect.bottom = pt.y + wDragHeight;
3308 while (PeekMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ))
3310 if( msg.message == WM_LBUTTONUP )
3315 if( msg.message == WM_MOUSEMOVE )
3318 tmp.x = (short)LOWORD(msg.lParam);
3319 tmp.y = (short)HIWORD(msg.lParam);
3320 if( !PtInRect( &rect, tmp ))
3332 /******************************************************************************
3333 * GetWindowModuleFileNameA (USER32.@)
3335 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR module, UINT size )
3340 TRACE( "%p, %p, %u\n", hwnd, module, size );
3342 win = WIN_GetPtr( hwnd );
3343 if (!win || win == WND_OTHER_PROCESS || win == WND_DESKTOP)
3345 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
3348 hinst = win->hInstance;
3349 WIN_ReleasePtr( win );
3351 return GetModuleFileNameA( hinst, module, size );
3354 /******************************************************************************
3355 * GetWindowModuleFileNameW (USER32.@)
3357 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR module, UINT size )
3362 TRACE( "%p, %p, %u\n", hwnd, module, size );
3364 win = WIN_GetPtr( hwnd );
3365 if (!win || win == WND_OTHER_PROCESS || win == WND_DESKTOP)
3367 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
3370 hinst = win->hInstance;
3371 WIN_ReleasePtr( win );
3373 return GetModuleFileNameW( hinst, module, size );
3376 /******************************************************************************
3377 * GetWindowInfo (USER32.@)
3379 * Note: tests show that Windows doesn't check cbSize of the structure.
3381 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3383 if (!pwi) return FALSE;
3384 if (!WIN_GetRectangles( hwnd, COORDS_SCREEN, &pwi->rcWindow, &pwi->rcClient )) return FALSE;
3386 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3387 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3388 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3390 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3391 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3393 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3394 pwi->wCreatorVersion = 0x0400;
3399 /******************************************************************************
3400 * SwitchDesktop (USER32.@)
3402 * NOTES: Sets the current input or interactive desktop.
3404 BOOL WINAPI SwitchDesktop( HDESK hDesktop)
3406 FIXME("(hwnd %p) stub!\n", hDesktop);
3410 /*****************************************************************************
3411 * SetLayeredWindowAttributes (USER32.@)
3413 BOOL WINAPI SetLayeredWindowAttributes( HWND hwnd, COLORREF key, BYTE alpha, DWORD flags )
3417 TRACE("(%p,%08x,%d,%x): stub!\n", hwnd, key, alpha, flags);
3419 SERVER_START_REQ( set_window_layered_info )
3421 req->handle = wine_server_user_handle( hwnd );
3422 req->color_key = key;
3425 ret = !wine_server_call_err( req );
3429 if (ret) USER_Driver->pSetLayeredWindowAttributes( hwnd, key, alpha, flags );
3435 /*****************************************************************************
3436 * GetLayeredWindowAttributes (USER32.@)
3438 BOOL WINAPI GetLayeredWindowAttributes( HWND hwnd, COLORREF *key, BYTE *alpha, DWORD *flags )
3442 SERVER_START_REQ( get_window_layered_info )
3444 req->handle = wine_server_user_handle( hwnd );
3445 if ((ret = !wine_server_call_err( req )))
3447 if (key) *key = reply->color_key;
3448 if (alpha) *alpha = reply->alpha;
3449 if (flags) *flags = reply->flags;
3458 /*****************************************************************************
3459 * UpdateLayeredWindowIndirect (USER32.@)
3461 BOOL WINAPI UpdateLayeredWindowIndirect( HWND hwnd, const UPDATELAYEREDWINDOWINFO *info )
3465 if (!(GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_LAYERED) ||
3466 GetLayeredWindowAttributes( hwnd, NULL, NULL, NULL ))
3468 SetLastError( ERROR_INVALID_PARAMETER );
3472 if (!(info->dwFlags & ULW_EX_NORESIZE) && (info->pptDst || info->psize))
3474 int x = 0, y = 0, cx = 0, cy = 0;
3475 DWORD flags = SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW | SWP_NOSENDCHANGING;
3479 x = info->pptDst->x;
3480 y = info->pptDst->y;
3481 flags &= ~SWP_NOMOVE;
3485 cx = info->psize->cx;
3486 cy = info->psize->cy;
3487 flags &= ~SWP_NOSIZE;
3489 TRACE( "moving window %p pos %d,%d %dx%d\n", hwnd, x, y, cx, cy );
3490 SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
3495 HDC hdc = GetWindowDC( hwnd );
3502 GetWindowRect( hwnd, &rect );
3503 OffsetRect( &rect, -rect.left, -rect.top);
3506 x = info->pptSrc->x;
3507 y = info->pptSrc->y;
3510 if (!info->prcDirty || (info->prcDirty && IntersectRect(&rect, &rect, info->prcDirty)))
3512 TRACE( "copying window %p pos %d,%d\n", hwnd, x, y );
3513 BitBlt( hdc, rect.left, rect.top, rect.right, rect.bottom,
3514 info->hdcSrc, rect.left + x, rect.top + y, SRCCOPY );
3516 ReleaseDC( hwnd, hdc );
3520 if (info->pblend && !(info->dwFlags & ULW_OPAQUE)) alpha = info->pblend->SourceConstantAlpha;
3521 TRACE( "setting window %p alpha %u\n", hwnd, alpha );
3522 USER_Driver->pSetLayeredWindowAttributes( hwnd, info->crKey, alpha,
3523 info->dwFlags & (LWA_ALPHA | LWA_COLORKEY) );
3528 /*****************************************************************************
3529 * UpdateLayeredWindow (USER32.@)
3531 BOOL WINAPI UpdateLayeredWindow( HWND hwnd, HDC hdcDst, POINT *pptDst, SIZE *psize,
3532 HDC hdcSrc, POINT *pptSrc, COLORREF crKey, BLENDFUNCTION *pblend,
3535 UPDATELAYEREDWINDOWINFO info;
3537 info.cbSize = sizeof(info);
3538 info.hdcDst = hdcDst;
3539 info.pptDst = pptDst;
3541 info.hdcSrc = hdcSrc;
3542 info.pptSrc = pptSrc;
3544 info.pblend = pblend;
3545 info.dwFlags = dwFlags;
3546 info.prcDirty = NULL;
3547 return UpdateLayeredWindowIndirect( hwnd, &info );
3551 /******************************************************************************
3552 * GetProcessDefaultLayout [USER32.@]
3554 * Gets the default layout for parentless windows.
3556 BOOL WINAPI GetProcessDefaultLayout( DWORD *layout )
3560 SetLastError( ERROR_NOACCESS );
3563 *layout = process_layout;
3568 /******************************************************************************
3569 * SetProcessDefaultLayout [USER32.@]
3571 * Sets the default layout for parentless windows.
3573 BOOL WINAPI SetProcessDefaultLayout( DWORD layout )
3575 process_layout = layout;
3580 /* 64bit versions */
3582 #ifdef GetWindowLongPtrW
3583 #undef GetWindowLongPtrW
3586 #ifdef GetWindowLongPtrA
3587 #undef GetWindowLongPtrA
3590 #ifdef SetWindowLongPtrW
3591 #undef SetWindowLongPtrW
3594 #ifdef SetWindowLongPtrA
3595 #undef SetWindowLongPtrA
3598 /*****************************************************************************
3599 * GetWindowLongPtrW (USER32.@)
3601 LONG_PTR WINAPI GetWindowLongPtrW( HWND hwnd, INT offset )
3603 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), TRUE );
3606 /*****************************************************************************
3607 * GetWindowLongPtrA (USER32.@)
3609 LONG_PTR WINAPI GetWindowLongPtrA( HWND hwnd, INT offset )
3611 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), FALSE );
3614 /*****************************************************************************
3615 * SetWindowLongPtrW (USER32.@)
3617 LONG_PTR WINAPI SetWindowLongPtrW( HWND hwnd, INT offset, LONG_PTR newval )
3619 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, TRUE );
3622 /*****************************************************************************
3623 * SetWindowLongPtrA (USER32.@)
3625 LONG_PTR WINAPI SetWindowLongPtrA( HWND hwnd, INT offset, LONG_PTR newval )
3627 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, FALSE );