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/winbase16.h"
31 #include "wine/winuser16.h"
33 #include "wine/server.h"
34 #include "wine/unicode.h"
36 #include "user_private.h"
39 #include "wine/debug.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(win);
43 #define NB_USER_HANDLES ((LAST_USER_HANDLE - FIRST_USER_HANDLE + 1) >> 1)
44 #define USER_HANDLE_TO_INDEX(hwnd) ((LOWORD(hwnd) - FIRST_USER_HANDLE) >> 1)
46 /**********************************************************************/
48 /* helper for Get/SetWindowLong */
49 static inline LONG_PTR get_win_data( const void *ptr, UINT size )
51 if (size == sizeof(WORD))
54 memcpy( &ret, ptr, sizeof(ret) );
57 else if (size == sizeof(DWORD))
60 memcpy( &ret, ptr, sizeof(ret) );
66 memcpy( &ret, ptr, sizeof(ret) );
71 /* helper for Get/SetWindowLong */
72 static inline void set_win_data( void *ptr, LONG_PTR val, UINT size )
74 if (size == sizeof(WORD))
77 memcpy( ptr, &newval, sizeof(newval) );
79 else if (size == sizeof(DWORD))
82 memcpy( ptr, &newval, sizeof(newval) );
86 memcpy( ptr, &val, sizeof(val) );
91 static void *user_handles[NB_USER_HANDLES];
93 /***********************************************************************
94 * create_window_handle
96 * Create a window handle with the server.
98 static WND *create_window_handle( HWND parent, HWND owner, LPCWSTR name,
99 HINSTANCE instance, BOOL unicode )
103 HWND handle = 0, full_parent = 0, full_owner = 0;
104 struct tagCLASS *class = NULL;
107 /* if 16-bit instance, map to module handle */
108 if (instance && !HIWORD(instance))
109 instance = HINSTANCE_32(GetExePtr(HINSTANCE_16(instance)));
111 SERVER_START_REQ( create_window )
113 req->parent = wine_server_user_handle( parent );
114 req->owner = wine_server_user_handle( owner );
115 req->instance = wine_server_client_ptr( instance );
116 if (!(req->atom = get_int_atom_value( name )) && name)
117 wine_server_add_data( req, name, strlenW(name)*sizeof(WCHAR) );
118 if (!wine_server_call_err( req ))
120 handle = wine_server_ptr_handle( reply->handle );
121 full_parent = wine_server_ptr_handle( reply->parent );
122 full_owner = wine_server_ptr_handle( reply->owner );
123 extra_bytes = reply->extra;
124 class = wine_server_get_ptr( reply->class_ptr );
131 WARN( "error %d creating window\n", GetLastError() );
135 if (!(win = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
136 sizeof(WND) + extra_bytes - sizeof(win->wExtra) )))
138 SERVER_START_REQ( destroy_window )
140 req->handle = wine_server_user_handle( handle );
141 wine_server_call( req );
144 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
148 if (!parent) /* if parent is 0 we don't have a desktop window yet */
150 struct user_thread_info *thread_info = get_user_thread_info();
152 if (name == (LPCWSTR)DESKTOP_CLASS_ATOM)
154 if (!thread_info->top_window) thread_info->top_window = full_parent ? full_parent : handle;
155 else assert( full_parent == thread_info->top_window );
156 if (full_parent && !USER_Driver->pCreateDesktopWindow( thread_info->top_window ))
157 ERR( "failed to create desktop window\n" );
159 else /* HWND_MESSAGE parent */
161 if (!thread_info->msg_window && !full_parent) thread_info->msg_window = handle;
167 index = USER_HANDLE_TO_INDEX(handle);
168 assert( index < NB_USER_HANDLES );
169 user_handles[index] = win;
170 win->hwndSelf = handle;
171 win->parent = full_parent;
172 win->owner = full_owner;
174 win->winproc = get_class_winproc( class );
175 win->dwMagic = WND_MAGIC;
176 win->cbWndExtra = extra_bytes;
177 if (WINPROC_IsUnicode( win->winproc, unicode )) win->flags |= WIN_ISUNICODE;
182 /***********************************************************************
185 * Free a window handle.
187 static WND *free_window_handle( HWND hwnd )
190 WORD index = USER_HANDLE_TO_INDEX(hwnd);
192 if (index >= NB_USER_HANDLES) return NULL;
194 if ((ptr = user_handles[index]))
196 SERVER_START_REQ( destroy_window )
198 req->handle = wine_server_user_handle( hwnd );
199 if (!wine_server_call_err( req ))
201 user_handles[index] = NULL;
210 HeapFree( GetProcessHeap(), 0, ptr );
215 /*******************************************************************
216 * list_window_children
218 * Build an array of the children of a given window. The array must be
219 * freed with HeapFree. Returns NULL when no windows are found.
221 static HWND *list_window_children( HDESK desktop, HWND hwnd, LPCWSTR class, DWORD tid )
225 ATOM atom = get_int_atom_value( class );
227 /* empty class is not the same as NULL class */
228 if (!atom && class && !class[0]) return NULL;
234 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
236 SERVER_START_REQ( get_window_children )
238 req->desktop = wine_server_obj_handle( desktop );
239 req->parent = wine_server_user_handle( hwnd );
242 if (!atom && class) wine_server_add_data( req, class, strlenW(class)*sizeof(WCHAR) );
243 wine_server_set_reply( req, list, (size-1) * sizeof(user_handle_t) );
244 if (!wine_server_call( req )) count = reply->count;
247 if (count && count < size)
249 /* start from the end since HWND is potentially larger than user_handle_t */
250 for (i = count - 1; i >= 0; i--)
251 list[i] = wine_server_ptr_handle( ((user_handle_t *)list)[i] );
255 HeapFree( GetProcessHeap(), 0, list );
257 size = count + 1; /* restart with a large enough buffer */
263 /*******************************************************************
264 * list_window_parents
266 * Build an array of all parents of a given window, starting with
267 * the immediate parent. The array must be freed with HeapFree.
269 static HWND *list_window_parents( HWND hwnd )
273 int i, pos = 0, size = 16, count = 0;
275 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
280 if (!(win = WIN_GetPtr( current ))) goto empty;
281 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
282 if (win == WND_DESKTOP)
284 if (!pos) goto empty;
288 list[pos] = current = win->parent;
289 WIN_ReleasePtr( win );
290 if (!current) return list;
291 if (++pos == size - 1)
293 /* need to grow the list */
294 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
295 if (!new_list) goto empty;
301 /* at least one parent belongs to another process, have to query the server */
306 SERVER_START_REQ( get_window_parents )
308 req->handle = wine_server_user_handle( hwnd );
309 wine_server_set_reply( req, list, (size-1) * sizeof(user_handle_t) );
310 if (!wine_server_call( req )) count = reply->count;
313 if (!count) goto empty;
316 /* start from the end since HWND is potentially larger than user_handle_t */
317 for (i = count - 1; i >= 0; i--)
318 list[i] = wine_server_ptr_handle( ((user_handle_t *)list)[i] );
322 HeapFree( GetProcessHeap(), 0, list );
324 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
328 HeapFree( GetProcessHeap(), 0, list );
333 /*******************************************************************
336 static void send_parent_notify( HWND hwnd, UINT msg )
338 if ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_CHILD | WS_POPUP)) == WS_CHILD &&
339 !(GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY))
341 HWND parent = GetParent(hwnd);
342 if (parent && parent != GetDesktopWindow())
343 SendMessageW( parent, WM_PARENTNOTIFY,
344 MAKEWPARAM( msg, GetWindowLongPtrW( hwnd, GWLP_ID )), (LPARAM)hwnd );
349 /*******************************************************************
350 * get_server_window_text
352 * Retrieve the window text from the server.
354 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
358 SERVER_START_REQ( get_window_text )
360 req->handle = wine_server_user_handle( hwnd );
361 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
362 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
365 text[len / sizeof(WCHAR)] = 0;
369 /*******************************************************************
370 * get_hwnd_message_parent
372 * Return the parent for HWND_MESSAGE windows.
374 HWND get_hwnd_message_parent(void)
376 struct user_thread_info *thread_info = get_user_thread_info();
378 if (!thread_info->msg_window) GetDesktopWindow(); /* trigger creation */
379 return thread_info->msg_window;
383 /*******************************************************************
386 * Check if window is the desktop or the HWND_MESSAGE top parent.
388 BOOL is_desktop_window( HWND hwnd )
390 struct user_thread_info *thread_info = get_user_thread_info();
392 if (!hwnd) return FALSE;
393 if (hwnd == thread_info->top_window) return TRUE;
394 if (hwnd == thread_info->msg_window) return TRUE;
396 if (!HIWORD(hwnd) || HIWORD(hwnd) == 0xffff)
398 if (LOWORD(thread_info->top_window) == LOWORD(hwnd)) return TRUE;
399 if (LOWORD(thread_info->msg_window) == LOWORD(hwnd)) return TRUE;
405 /***********************************************************************
408 * Return a pointer to the WND structure if local to the process,
409 * or WND_OTHER_PROCESS if handle may be valid in other process.
410 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
412 WND *WIN_GetPtr( HWND hwnd )
415 WORD index = USER_HANDLE_TO_INDEX(hwnd);
417 if (index >= NB_USER_HANDLES) return NULL;
420 if ((ptr = user_handles[index]))
422 if (ptr->dwMagic == WND_MAGIC &&
423 (hwnd == ptr->hwndSelf || !HIWORD(hwnd) || HIWORD(hwnd) == 0xffff))
427 else if (is_desktop_window( hwnd )) ptr = WND_DESKTOP;
428 else ptr = WND_OTHER_PROCESS;
434 /***********************************************************************
435 * WIN_IsCurrentProcess
437 * Check whether a given window belongs to the current process (and return the full handle).
439 HWND WIN_IsCurrentProcess( HWND hwnd )
444 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
446 WIN_ReleasePtr( ptr );
451 /***********************************************************************
452 * WIN_IsCurrentThread
454 * Check whether a given window belongs to the current thread (and return the full handle).
456 HWND WIN_IsCurrentThread( HWND hwnd )
461 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
462 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
463 WIN_ReleasePtr( ptr );
468 /***********************************************************************
471 * Convert a 16-bit window handle to a full 32-bit handle.
473 HWND WIN_Handle32( HWND16 hwnd16 )
476 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
478 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
479 /* do sign extension for -2 and -3 */
480 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
482 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
484 if (ptr == WND_DESKTOP)
486 if (LOWORD(hwnd) == LOWORD(GetDesktopWindow())) return GetDesktopWindow();
487 else return get_hwnd_message_parent();
490 if (ptr != WND_OTHER_PROCESS)
492 hwnd = ptr->hwndSelf;
493 WIN_ReleasePtr( ptr );
495 else /* may belong to another process */
497 SERVER_START_REQ( get_window_info )
499 req->handle = wine_server_user_handle( hwnd );
500 if (!wine_server_call_err( req )) hwnd = wine_server_ptr_handle( reply->full_handle );
508 /***********************************************************************
511 * Change the owner of a window.
513 HWND WIN_SetOwner( HWND hwnd, HWND owner )
515 WND *win = WIN_GetPtr( hwnd );
518 if (!win || win == WND_DESKTOP) return 0;
519 if (win == WND_OTHER_PROCESS)
521 if (IsWindow(hwnd)) ERR( "cannot set owner %p on other process window %p\n", owner, hwnd );
524 SERVER_START_REQ( set_window_owner )
526 req->handle = wine_server_user_handle( hwnd );
527 req->owner = wine_server_user_handle( owner );
528 if (!wine_server_call( req ))
530 win->owner = wine_server_ptr_handle( reply->full_owner );
531 ret = wine_server_ptr_handle( reply->prev_owner );
535 WIN_ReleasePtr( win );
540 /***********************************************************************
543 * Change the style of a window.
545 ULONG WIN_SetStyle( HWND hwnd, ULONG set_bits, ULONG clear_bits )
549 WND *win = WIN_GetPtr( hwnd );
551 if (!win || win == WND_DESKTOP) return 0;
552 if (win == WND_OTHER_PROCESS)
555 ERR( "cannot set style %x/%x on other process window %p\n",
556 set_bits, clear_bits, hwnd );
559 style.styleOld = win->dwStyle;
560 style.styleNew = (win->dwStyle | set_bits) & ~clear_bits;
561 if (style.styleNew == style.styleOld)
563 WIN_ReleasePtr( win );
564 return style.styleNew;
566 SERVER_START_REQ( set_window_info )
568 req->handle = wine_server_user_handle( hwnd );
569 req->flags = SET_WIN_STYLE;
570 req->style = style.styleNew;
571 req->extra_offset = -1;
572 if ((ok = !wine_server_call( req )))
574 style.styleOld = reply->old_style;
575 win->dwStyle = style.styleNew;
579 WIN_ReleasePtr( win );
582 USER_Driver->pSetWindowStyle( hwnd, GWL_STYLE, &style );
583 if ((style.styleOld ^ style.styleNew) & WS_VISIBLE) invalidate_dce( hwnd, NULL );
585 return style.styleOld;
589 /***********************************************************************
592 * Get the window and client rectangles.
594 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
596 WND *win = WIN_GetPtr( hwnd );
599 if (!win) return FALSE;
600 if (win == WND_DESKTOP)
603 rect.left = rect.top = 0;
604 if (hwnd == get_hwnd_message_parent())
611 rect.right = GetSystemMetrics(SM_CXSCREEN);
612 rect.bottom = GetSystemMetrics(SM_CYSCREEN);
614 if (rectWindow) *rectWindow = rect;
615 if (rectClient) *rectClient = rect;
617 else if (win == WND_OTHER_PROCESS)
619 SERVER_START_REQ( get_window_rectangles )
621 req->handle = wine_server_user_handle( hwnd );
622 if ((ret = !wine_server_call( req )))
626 rectWindow->left = reply->window.left;
627 rectWindow->top = reply->window.top;
628 rectWindow->right = reply->window.right;
629 rectWindow->bottom = reply->window.bottom;
633 rectClient->left = reply->client.left;
634 rectClient->top = reply->client.top;
635 rectClient->right = reply->client.right;
636 rectClient->bottom = reply->client.bottom;
644 if (rectWindow) *rectWindow = win->rectWindow;
645 if (rectClient) *rectClient = win->rectClient;
646 WIN_ReleasePtr( win );
652 /***********************************************************************
655 * Destroy storage associated to a window. "Internals" p.358
657 LRESULT WIN_DestroyWindow( HWND hwnd )
661 HMENU menu = 0, sys_menu;
664 TRACE("%p\n", hwnd );
666 /* free child windows */
667 if ((list = WIN_ListChildren( hwnd )))
670 for (i = 0; list[i]; i++)
672 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
673 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
675 HeapFree( GetProcessHeap(), 0, list );
678 /* Unlink now so we won't bother with the children later on */
679 SERVER_START_REQ( set_parent )
681 req->handle = wine_server_user_handle( hwnd );
683 wine_server_call( req );
688 * Send the WM_NCDESTROY to the window being destroyed.
690 SendMessageW( hwnd, WM_NCDESTROY, 0, 0 );
692 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
694 /* free resources associated with the window */
696 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
697 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
698 menu = (HMENU)wndPtr->wIDmenu;
699 sys_menu = wndPtr->hSysMenu;
700 free_dce( wndPtr->dce, hwnd );
702 icon_title = wndPtr->icon_title;
703 WIN_ReleasePtr( wndPtr );
705 if (icon_title) DestroyWindow( icon_title );
706 if (menu) DestroyMenu( menu );
707 if (sys_menu) DestroyMenu( sys_menu );
709 USER_Driver->pDestroyWindow( hwnd );
711 free_window_handle( hwnd );
716 /***********************************************************************
717 * destroy_thread_window
719 * Destroy a window upon exit of its thread.
721 static void destroy_thread_window( HWND hwnd )
725 HMENU menu = 0, sys_menu = 0;
728 /* free child windows */
730 if ((list = WIN_ListChildren( hwnd )))
733 for (i = 0; list[i]; i++)
735 if (WIN_IsCurrentThread( list[i] )) destroy_thread_window( list[i] );
736 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
738 HeapFree( GetProcessHeap(), 0, list );
741 /* destroy the client-side storage */
743 index = USER_HANDLE_TO_INDEX(hwnd);
744 if (index >= NB_USER_HANDLES) return;
746 if ((wndPtr = user_handles[index]))
748 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD) menu = (HMENU)wndPtr->wIDmenu;
749 sys_menu = wndPtr->hSysMenu;
750 free_dce( wndPtr->dce, hwnd );
751 user_handles[index] = NULL;
756 HeapFree( GetProcessHeap(), 0, wndPtr );
757 if (menu) DestroyMenu( menu );
758 if (sys_menu) DestroyMenu( sys_menu );
762 /***********************************************************************
763 * destroy_thread_child_windows
765 * Destroy child windows upon exit of its thread.
767 static void destroy_thread_child_windows( HWND hwnd )
772 if (WIN_IsCurrentThread( hwnd ))
774 destroy_thread_window( hwnd );
776 else if ((list = WIN_ListChildren( hwnd )))
778 for (i = 0; list[i]; i++) destroy_thread_child_windows( list[i] );
779 HeapFree( GetProcessHeap(), 0, list );
784 /***********************************************************************
785 * WIN_DestroyThreadWindows
787 * Destroy all children of 'wnd' owned by the current thread.
789 void WIN_DestroyThreadWindows( HWND hwnd )
794 if (!(list = WIN_ListChildren( hwnd ))) return;
796 /* reset owners of top-level windows */
797 for (i = 0; list[i]; i++)
799 if (!WIN_IsCurrentThread( list[i] ))
801 HWND owner = GetWindow( list[i], GW_OWNER );
802 if (owner && WIN_IsCurrentThread( owner )) WIN_SetOwner( list[i], 0 );
806 for (i = 0; list[i]; i++) destroy_thread_child_windows( list[i] );
807 HeapFree( GetProcessHeap(), 0, list );
811 /***********************************************************************
814 * Fix the coordinates - Helper for WIN_CreateWindowEx.
815 * returns default show mode in sw.
817 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
819 #define IS_DEFAULT(x) ((x) == CW_USEDEFAULT || (x) == CW_USEDEFAULT16)
822 if (cs->dwExStyle & WS_EX_MDICHILD)
826 MDI_CalcDefaultChildPos(cs->hwndParent, -1, pos, 0, &id);
827 if (!(cs->style & WS_POPUP)) cs->hMenu = ULongToHandle(id);
829 TRACE("MDI child id %04x\n", id);
832 if (cs->style & (WS_CHILD | WS_POPUP))
834 if (cs->dwExStyle & WS_EX_MDICHILD)
836 if (IS_DEFAULT(cs->x))
841 if (IS_DEFAULT(cs->cx) || !cs->cx) cs->cx = pos[1].x;
842 if (IS_DEFAULT(cs->cy) || !cs->cy) cs->cy = pos[1].y;
846 if (IS_DEFAULT(cs->x)) cs->x = cs->y = 0;
847 if (IS_DEFAULT(cs->cx)) cs->cx = cs->cy = 0;
850 else /* overlapped window */
853 MONITORINFO mon_info;
856 if (!IS_DEFAULT(cs->x) && !IS_DEFAULT(cs->cx) && !IS_DEFAULT(cs->cy)) return;
858 monitor = MonitorFromWindow( cs->hwndParent, MONITOR_DEFAULTTOPRIMARY );
859 mon_info.cbSize = sizeof(mon_info);
860 GetMonitorInfoW( monitor, &mon_info );
861 GetStartupInfoW( &info );
863 if (IS_DEFAULT(cs->x))
865 if (!IS_DEFAULT(cs->y)) *sw = cs->y;
866 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : mon_info.rcWork.left;
867 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : mon_info.rcWork.top;
870 if (IS_DEFAULT(cs->cx))
872 if (info.dwFlags & STARTF_USESIZE)
874 cs->cx = info.dwXSize;
875 cs->cy = info.dwYSize;
879 cs->cx = (mon_info.rcWork.right - mon_info.rcWork.left) * 3 / 4 - cs->x;
880 cs->cy = (mon_info.rcWork.bottom - mon_info.rcWork.top) * 3 / 4 - cs->y;
883 /* neither x nor cx are default. Check the y values .
884 * In the trace we see Outlook and Outlook Express using
885 * cy set to CW_USEDEFAULT when opening the address book.
887 else if (IS_DEFAULT(cs->cy))
889 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
890 cs->cy = (mon_info.rcWork.bottom - mon_info.rcWork.top) * 3 / 4 - cs->y;
896 /***********************************************************************
899 static void dump_window_styles( DWORD style, DWORD exstyle )
902 if(style & WS_POPUP) TRACE(" WS_POPUP");
903 if(style & WS_CHILD) TRACE(" WS_CHILD");
904 if(style & WS_MINIMIZE) TRACE(" WS_MINIMIZE");
905 if(style & WS_VISIBLE) TRACE(" WS_VISIBLE");
906 if(style & WS_DISABLED) TRACE(" WS_DISABLED");
907 if(style & WS_CLIPSIBLINGS) TRACE(" WS_CLIPSIBLINGS");
908 if(style & WS_CLIPCHILDREN) TRACE(" WS_CLIPCHILDREN");
909 if(style & WS_MAXIMIZE) TRACE(" WS_MAXIMIZE");
910 if((style & WS_CAPTION) == WS_CAPTION) TRACE(" WS_CAPTION");
913 if(style & WS_BORDER) TRACE(" WS_BORDER");
914 if(style & WS_DLGFRAME) TRACE(" WS_DLGFRAME");
916 if(style & WS_VSCROLL) TRACE(" WS_VSCROLL");
917 if(style & WS_HSCROLL) TRACE(" WS_HSCROLL");
918 if(style & WS_SYSMENU) TRACE(" WS_SYSMENU");
919 if(style & WS_THICKFRAME) TRACE(" WS_THICKFRAME");
920 if (style & WS_CHILD)
922 if(style & WS_GROUP) TRACE(" WS_GROUP");
923 if(style & WS_TABSTOP) TRACE(" WS_TABSTOP");
927 if(style & WS_MINIMIZEBOX) TRACE(" WS_MINIMIZEBOX");
928 if(style & WS_MAXIMIZEBOX) TRACE(" WS_MAXIMIZEBOX");
931 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
932 #define DUMPED_STYLES \
952 if(style & ~DUMPED_STYLES) TRACE(" %08lx", style & ~DUMPED_STYLES);
957 if(exstyle & WS_EX_DLGMODALFRAME) TRACE(" WS_EX_DLGMODALFRAME");
958 if(exstyle & WS_EX_DRAGDETECT) TRACE(" WS_EX_DRAGDETECT");
959 if(exstyle & WS_EX_NOPARENTNOTIFY) TRACE(" WS_EX_NOPARENTNOTIFY");
960 if(exstyle & WS_EX_TOPMOST) TRACE(" WS_EX_TOPMOST");
961 if(exstyle & WS_EX_ACCEPTFILES) TRACE(" WS_EX_ACCEPTFILES");
962 if(exstyle & WS_EX_TRANSPARENT) TRACE(" WS_EX_TRANSPARENT");
963 if(exstyle & WS_EX_MDICHILD) TRACE(" WS_EX_MDICHILD");
964 if(exstyle & WS_EX_TOOLWINDOW) TRACE(" WS_EX_TOOLWINDOW");
965 if(exstyle & WS_EX_WINDOWEDGE) TRACE(" WS_EX_WINDOWEDGE");
966 if(exstyle & WS_EX_CLIENTEDGE) TRACE(" WS_EX_CLIENTEDGE");
967 if(exstyle & WS_EX_CONTEXTHELP) TRACE(" WS_EX_CONTEXTHELP");
968 if(exstyle & WS_EX_RIGHT) TRACE(" WS_EX_RIGHT");
969 if(exstyle & WS_EX_RTLREADING) TRACE(" WS_EX_RTLREADING");
970 if(exstyle & WS_EX_LEFTSCROLLBAR) TRACE(" WS_EX_LEFTSCROLLBAR");
971 if(exstyle & WS_EX_CONTROLPARENT) TRACE(" WS_EX_CONTROLPARENT");
972 if(exstyle & WS_EX_STATICEDGE) TRACE(" WS_EX_STATICEDGE");
973 if(exstyle & WS_EX_APPWINDOW) TRACE(" WS_EX_APPWINDOW");
974 if(exstyle & WS_EX_LAYERED) TRACE(" WS_EX_LAYERED");
976 #define DUMPED_EX_STYLES \
977 (WS_EX_DLGMODALFRAME | \
979 WS_EX_NOPARENTNOTIFY | \
981 WS_EX_ACCEPTFILES | \
982 WS_EX_TRANSPARENT | \
987 WS_EX_CONTEXTHELP | \
990 WS_EX_LEFTSCROLLBAR | \
991 WS_EX_CONTROLPARENT | \
996 if(exstyle & ~DUMPED_EX_STYLES) TRACE(" %08lx", exstyle & ~DUMPED_EX_STYLES);
998 #undef DUMPED_EX_STYLES
1002 /***********************************************************************
1003 * WIN_CreateWindowEx
1005 * Implementation of CreateWindowEx().
1007 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, LPCWSTR className, UINT flags )
1009 INT cx, cy, style, sw = SW_SHOW;
1013 HWND hwnd, parent, owner, top_child = 0;
1014 BOOL unicode = (flags & WIN_ISUNICODE) != 0;
1015 MDICREATESTRUCTA mdi_cs;
1016 CBT_CREATEWNDA cbtc;
1019 TRACE("%s %s ex=%08x style=%08x %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
1020 unicode ? debugstr_w((LPCWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
1021 debugstr_w(className),
1022 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
1023 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
1024 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
1026 /* Fix the styles for MDI children */
1027 if (cs->dwExStyle & WS_EX_MDICHILD)
1031 wndPtr = WIN_GetPtr(cs->hwndParent);
1032 if (wndPtr && wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
1034 flags = wndPtr->flags;
1035 WIN_ReleasePtr(wndPtr);
1038 if (!(flags & WIN_ISMDICLIENT))
1040 WARN("WS_EX_MDICHILD, but parent %p is not MDIClient\n", cs->hwndParent);
1044 /* cs->lpCreateParams of WM_[NC]CREATE is different for MDI children.
1045 * MDICREATESTRUCT members have the originally passed values.
1047 * Note: we rely on the fact that MDICREATESTRUCTA and MDICREATESTRUCTW
1048 * have the same layout.
1050 mdi_cs.szClass = cs->lpszClass;
1051 mdi_cs.szTitle = cs->lpszName;
1052 mdi_cs.hOwner = cs->hInstance;
1057 mdi_cs.style = cs->style;
1058 mdi_cs.lParam = (LPARAM)cs->lpCreateParams;
1060 cs->lpCreateParams = &mdi_cs;
1062 if (GetWindowLongW(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
1064 if (cs->style & WS_POPUP)
1066 TRACE("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n");
1069 cs->style |= WS_CHILD | WS_CLIPSIBLINGS;
1073 cs->style &= ~WS_POPUP;
1074 cs->style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
1075 WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
1078 top_child = GetWindow(cs->hwndParent, GW_CHILD);
1082 /* Restore current maximized child */
1083 if((cs->style & WS_VISIBLE) && IsZoomed(top_child))
1085 TRACE("Restoring current maximized child %p\n", top_child);
1086 SendMessageW( top_child, WM_SETREDRAW, FALSE, 0 );
1087 ShowWindow( top_child, SW_SHOWNORMAL );
1088 SendMessageW( top_child, WM_SETREDRAW, TRUE, 0 );
1093 /* Find the parent window */
1095 parent = cs->hwndParent;
1098 if (cs->hwndParent == HWND_MESSAGE)
1100 cs->hwndParent = parent = get_hwnd_message_parent();
1102 else if (cs->hwndParent)
1104 if ((cs->style & (WS_CHILD|WS_POPUP)) != WS_CHILD)
1106 parent = GetDesktopWindow();
1107 owner = cs->hwndParent;
1112 static const WCHAR messageW[] = {'M','e','s','s','a','g','e',0};
1114 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1116 WARN("No parent for child window\n" );
1117 SetLastError(ERROR_TLW_WITH_WSCHILD);
1118 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1120 /* are we creating the desktop or HWND_MESSAGE parent itself? */
1121 if (className != (LPCWSTR)DESKTOP_CLASS_ATOM &&
1122 (IS_INTRESOURCE(className) || strcmpiW( className, messageW )))
1123 parent = GetDesktopWindow();
1126 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
1128 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
1129 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
1130 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
1131 cs->dwExStyle |= WS_EX_WINDOWEDGE;
1133 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
1135 /* Create the window structure */
1137 if (!(wndPtr = create_window_handle( parent, owner, className, cs->hInstance, unicode )))
1139 hwnd = wndPtr->hwndSelf;
1141 /* Fill the window structure */
1143 wndPtr->tid = GetCurrentThreadId();
1144 wndPtr->hInstance = cs->hInstance;
1145 wndPtr->text = NULL;
1146 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1147 wndPtr->dwExStyle = cs->dwExStyle;
1148 wndPtr->wIDmenu = 0;
1149 wndPtr->helpContext = 0;
1150 wndPtr->pScroll = NULL;
1151 wndPtr->userdata = 0;
1153 wndPtr->hIconSmall = 0;
1154 wndPtr->hSysMenu = 0;
1155 wndPtr->flags |= (flags & WIN_ISWIN32);
1157 wndPtr->min_pos.x = wndPtr->min_pos.y = -1;
1158 wndPtr->max_pos.x = wndPtr->max_pos.y = -1;
1160 if (wndPtr->dwStyle & WS_SYSMENU) SetSystemMenu( hwnd, 0 );
1163 * Correct the window styles.
1165 * It affects only the style loaded into the WIN structure.
1168 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
1170 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1171 if (!(wndPtr->dwStyle & WS_POPUP))
1172 wndPtr->dwStyle |= WS_CAPTION;
1176 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1177 * why does the user get to set it?
1180 if ((wndPtr->dwExStyle & WS_EX_DLGMODALFRAME) ||
1181 (wndPtr->dwStyle & (WS_DLGFRAME | WS_THICKFRAME)))
1182 wndPtr->dwExStyle |= WS_EX_WINDOWEDGE;
1184 wndPtr->dwExStyle &= ~WS_EX_WINDOWEDGE;
1186 if (!(wndPtr->dwStyle & (WS_CHILD | WS_POPUP)))
1187 wndPtr->flags |= WIN_NEED_SIZE;
1189 SERVER_START_REQ( set_window_info )
1191 req->handle = wine_server_user_handle( hwnd );
1192 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE | SET_WIN_UNICODE;
1193 req->style = wndPtr->dwStyle;
1194 req->ex_style = wndPtr->dwExStyle;
1195 req->instance = wine_server_client_ptr( wndPtr->hInstance );
1196 req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
1197 req->extra_offset = -1;
1198 wine_server_call( req );
1202 /* Set the window menu */
1204 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
1208 if (!MENU_SetMenu(hwnd, cs->hMenu))
1210 WIN_ReleasePtr( wndPtr );
1211 free_window_handle( hwnd );
1217 LPCSTR menuName = (LPCSTR)GetClassLongPtrA( hwnd, GCLP_MENUNAME );
1220 if (!cs->hInstance || HIWORD(cs->hInstance))
1221 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1223 cs->hMenu = HMENU_32(LoadMenu16(HINSTANCE_16(cs->hInstance),menuName));
1225 if (cs->hMenu) MENU_SetMenu( hwnd, cs->hMenu );
1229 else SetWindowLongPtrW( hwnd, GWLP_ID, (ULONG_PTR)cs->hMenu );
1231 /* call the WH_CBT hook */
1233 /* the window style passed to the hook must be the real window style,
1234 * rather than just the window style that the caller to CreateWindowEx
1235 * passed in, so we have to copy the original CREATESTRUCT and get the
1236 * the real style. */
1238 cbcs.style = wndPtr->dwStyle;
1240 cbtc.hwndInsertAfter = HWND_TOP;
1241 WIN_ReleasePtr( wndPtr );
1242 if (HOOK_CallHooks( WH_CBT, HCBT_CREATEWND, (WPARAM)hwnd, (LPARAM)&cbtc, unicode )) goto failed;
1244 /* send the WM_GETMINMAXINFO message and fix the size if needed */
1248 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
1250 POINT maxSize, maxPos, minTrack, maxTrack;
1251 WINPOS_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack);
1252 if (maxTrack.x < cx) cx = maxTrack.x;
1253 if (maxTrack.y < cy) cy = maxTrack.y;
1254 if (minTrack.x > cx) cx = minTrack.x;
1255 if (minTrack.y > cy) cy = minTrack.y;
1260 SetRect( &rect, cs->x, cs->y, cs->x + cx, cs->y + cy );
1261 /* check for wraparound */
1262 if (cs->x + cx < cs->x) rect.right = 0x7fffffff;
1263 if (cs->y + cy < cs->y) rect.bottom = 0x7fffffff;
1264 if (!set_window_pos( hwnd, 0, SWP_NOZORDER | SWP_NOACTIVATE, &rect, &rect, NULL )) goto failed;
1266 /* send WM_NCCREATE */
1268 TRACE( "hwnd %p cs %d,%d %dx%d\n", hwnd, cs->x, cs->y, cx, cy );
1270 result = SendMessageW( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
1272 result = SendMessageA( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
1275 WARN( "%p: aborted by WM_NCCREATE\n", hwnd );
1279 /* send WM_NCCALCSIZE */
1281 if ((wndPtr = WIN_GetPtr(hwnd)))
1283 /* yes, even if the CBT hook was called with HWND_TOP */
1285 HWND insert_after = (wndPtr->dwStyle & WS_CHILD) ? HWND_BOTTOM : HWND_TOP;
1286 RECT window_rect = wndPtr->rectWindow;
1287 RECT client_rect = window_rect;
1288 WIN_ReleasePtr( wndPtr );
1290 /* the rectangle is in screen coords for WM_NCCALCSIZE when wparam is FALSE */
1292 MapWindowPoints( parent, 0, &pt, 1 );
1293 OffsetRect( &client_rect, pt.x, pt.y );
1294 SendMessageW( hwnd, WM_NCCALCSIZE, FALSE, (LPARAM)&client_rect );
1295 OffsetRect( &client_rect, -pt.x, -pt.y );
1296 set_window_pos( hwnd, insert_after, SWP_NOACTIVATE, &window_rect, &client_rect, NULL );
1300 /* send WM_CREATE */
1303 result = SendMessageW( hwnd, WM_CREATE, 0, (LPARAM)cs );
1305 result = SendMessageA( hwnd, WM_CREATE, 0, (LPARAM)cs );
1306 if (result == -1) goto failed;
1308 /* call the driver */
1310 if (!USER_Driver->pCreateWindow( hwnd )) goto failed;
1312 NotifyWinEvent(EVENT_OBJECT_CREATE, hwnd, OBJID_WINDOW, 0);
1314 /* send the size messages */
1316 if (!(wndPtr = WIN_GetPtr( hwnd )) ||
1317 wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return 0;
1318 if (!(wndPtr->flags & WIN_NEED_SIZE))
1320 rect = wndPtr->rectClient;
1321 WIN_ReleasePtr( wndPtr );
1322 SendMessageW( hwnd, WM_SIZE, SIZE_RESTORED,
1323 MAKELONG(rect.right-rect.left, rect.bottom-rect.top));
1324 SendMessageW( hwnd, WM_MOVE, 0, MAKELONG( rect.left, rect.top ) );
1326 else WIN_ReleasePtr( wndPtr );
1328 /* Show the window, maximizing or minimizing if needed */
1330 style = WIN_SetStyle( hwnd, 0, WS_MAXIMIZE | WS_MINIMIZE );
1331 if (style & (WS_MINIMIZE | WS_MAXIMIZE))
1334 UINT swFlag = (style & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
1336 swFlag = WINPOS_MinMaximize( hwnd, swFlag, &newPos );
1337 swFlag |= SWP_FRAMECHANGED; /* Frame always gets changed */
1338 if (!(style & WS_VISIBLE) || (style & WS_CHILD) || GetActiveWindow()) swFlag |= SWP_NOACTIVATE;
1339 SetWindowPos( hwnd, 0, newPos.left, newPos.top, newPos.right - newPos.left,
1340 newPos.bottom - newPos.top, swFlag );
1343 /* Notify the parent window only */
1345 send_parent_notify( hwnd, WM_CREATE );
1346 if (!IsWindow( hwnd )) return 0;
1348 if (cs->style & WS_VISIBLE)
1350 if (cs->style & WS_MAXIMIZE)
1352 else if (cs->style & WS_MINIMIZE)
1353 sw = SW_SHOWMINIMIZED;
1355 ShowWindow( hwnd, sw );
1356 if (cs->dwExStyle & WS_EX_MDICHILD)
1358 SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
1359 /* ShowWindow won't activate child windows */
1360 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE );
1364 /* Call WH_SHELL hook */
1366 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1367 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1369 TRACE("created window %p\n", hwnd);
1373 WIN_DestroyWindow( hwnd );
1378 /***********************************************************************
1379 * CreateWindow (USER.41)
1381 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1382 DWORD style, INT16 x, INT16 y, INT16 width,
1383 INT16 height, HWND16 parent, HMENU16 menu,
1384 HINSTANCE16 instance, LPVOID data )
1386 return CreateWindowEx16( 0, className, windowName, style,
1387 x, y, width, height, parent, menu, instance, data );
1391 /***********************************************************************
1392 * CreateWindowEx (USER.452)
1394 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1395 LPCSTR windowName, DWORD style, INT16 x,
1396 INT16 y, INT16 width, INT16 height,
1397 HWND16 parent, HMENU16 menu,
1398 HINSTANCE16 instance, LPVOID data )
1403 /* Fix the coordinates */
1405 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1406 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1407 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1408 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1410 /* Create the window */
1412 cs.lpCreateParams = data;
1413 cs.hInstance = HINSTANCE_32(instance);
1414 cs.hMenu = HMENU_32(menu);
1415 cs.hwndParent = WIN_Handle32( parent );
1417 cs.lpszName = windowName;
1418 cs.lpszClass = className;
1419 cs.dwExStyle = exStyle;
1421 if (!IS_INTRESOURCE(className))
1425 if (!MultiByteToWideChar( CP_ACP, 0, className, -1, bufferW, sizeof(bufferW)/sizeof(WCHAR) ))
1427 return HWND_16( WIN_CreateWindowEx( &cs, bufferW, 0 ));
1431 if (!GlobalGetAtomNameA( LOWORD(className), buffer, sizeof(buffer) ))
1433 ERR( "bad atom %x\n", LOWORD(className));
1436 cs.lpszClass = buffer;
1437 return HWND_16( WIN_CreateWindowEx( &cs, (LPCWSTR)className, 0 ));
1442 /***********************************************************************
1443 * CreateWindowExA (USER32.@)
1445 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1446 LPCSTR windowName, DWORD style, INT x,
1447 INT y, INT width, INT height,
1448 HWND parent, HMENU menu,
1449 HINSTANCE instance, LPVOID data )
1453 cs.lpCreateParams = data;
1454 cs.hInstance = instance;
1456 cs.hwndParent = parent;
1462 cs.lpszName = windowName;
1463 cs.lpszClass = className;
1464 cs.dwExStyle = exStyle;
1466 if (!IS_INTRESOURCE(className))
1469 if (!MultiByteToWideChar( CP_ACP, 0, className, -1, bufferW, sizeof(bufferW)/sizeof(WCHAR) ))
1471 return WIN_CreateWindowEx( &cs, bufferW, WIN_ISWIN32 );
1473 return WIN_CreateWindowEx( &cs, (LPCWSTR)className, WIN_ISWIN32 );
1477 /***********************************************************************
1478 * CreateWindowExW (USER32.@)
1480 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1481 LPCWSTR windowName, DWORD style, INT x,
1482 INT y, INT width, INT height,
1483 HWND parent, HMENU menu,
1484 HINSTANCE instance, LPVOID data )
1488 cs.lpCreateParams = data;
1489 cs.hInstance = instance;
1491 cs.hwndParent = parent;
1497 cs.lpszName = windowName;
1498 cs.lpszClass = className;
1499 cs.dwExStyle = exStyle;
1501 /* Note: we rely on the fact that CREATESTRUCTA and */
1502 /* CREATESTRUCTW have the same layout. */
1503 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, className, WIN_ISWIN32 | WIN_ISUNICODE );
1507 /***********************************************************************
1508 * WIN_SendDestroyMsg
1510 static void WIN_SendDestroyMsg( HWND hwnd )
1514 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1516 if (hwnd == info.hwndCaret) DestroyCaret();
1517 if (hwnd == info.hwndActive) WINPOS_ActivateOtherWindow( hwnd );
1521 * Send the WM_DESTROY to the window.
1523 SendMessageW( hwnd, WM_DESTROY, 0, 0);
1526 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1527 * make sure that the window still exists when we come back.
1534 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1536 for (i = 0; pWndArray[i]; i++)
1538 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1540 HeapFree( GetProcessHeap(), 0, pWndArray );
1543 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1547 /***********************************************************************
1548 * DestroyWindow (USER32.@)
1550 BOOL WINAPI DestroyWindow( HWND hwnd )
1554 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || is_desktop_window( hwnd ))
1556 SetLastError( ERROR_ACCESS_DENIED );
1560 TRACE("(%p)\n", hwnd);
1564 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1566 if (MENU_IsMenuActive() == hwnd)
1569 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1573 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1574 send_parent_notify( hwnd, WM_DESTROY );
1576 else if (!GetWindow( hwnd, GW_OWNER ))
1578 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1579 /* FIXME: clean up palette - see "Internals" p.352 */
1582 if (!IsWindow(hwnd)) return TRUE;
1584 /* Hide the window */
1585 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)
1587 /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
1589 ShowWindow( hwnd, SW_HIDE );
1591 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1592 SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW );
1595 if (!IsWindow(hwnd)) return TRUE;
1597 /* Recursively destroy owned windows */
1604 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1607 for (i = 0; list[i]; i++)
1609 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1610 if (WIN_IsCurrentThread( list[i] ))
1612 DestroyWindow( list[i] );
1616 WIN_SetOwner( list[i], 0 );
1618 HeapFree( GetProcessHeap(), 0, list );
1620 if (!got_one) break;
1624 /* Send destroy messages */
1626 WIN_SendDestroyMsg( hwnd );
1627 if (!IsWindow( hwnd )) return TRUE;
1629 if (GetClipboardOwner() == hwnd)
1630 CLIPBOARD_ReleaseOwner();
1632 /* Destroy the window storage */
1634 WIN_DestroyWindow( hwnd );
1639 /***********************************************************************
1640 * CloseWindow (USER32.@)
1642 BOOL WINAPI CloseWindow( HWND hwnd )
1644 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1645 ShowWindow( hwnd, SW_MINIMIZE );
1650 /***********************************************************************
1651 * OpenIcon (USER32.@)
1653 BOOL WINAPI OpenIcon( HWND hwnd )
1655 if (!IsIconic( hwnd )) return FALSE;
1656 ShowWindow( hwnd, SW_SHOWNORMAL );
1661 /***********************************************************************
1662 * FindWindowExW (USER32.@)
1664 HWND WINAPI FindWindowExW( HWND parent, HWND child, LPCWSTR className, LPCWSTR title )
1669 WCHAR *buffer = NULL;
1671 if (!parent && child) parent = GetDesktopWindow();
1672 else if (parent == HWND_MESSAGE) parent = get_hwnd_message_parent();
1676 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1677 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1680 if (!(list = list_window_children( 0, parent, className, 0 ))) goto done;
1684 child = WIN_GetFullHandle( child );
1685 while (list[i] && list[i] != child) i++;
1686 if (!list[i]) goto done;
1687 i++; /* start from next window */
1694 if (GetWindowTextW( list[i], buffer, len + 1 ) && !strcmpiW( buffer, title )) break;
1701 HeapFree( GetProcessHeap(), 0, list );
1702 HeapFree( GetProcessHeap(), 0, buffer );
1708 /***********************************************************************
1709 * FindWindowA (USER32.@)
1711 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1713 HWND ret = FindWindowExA( 0, 0, className, title );
1714 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1719 /***********************************************************************
1720 * FindWindowExA (USER32.@)
1722 HWND WINAPI FindWindowExA( HWND parent, HWND child, LPCSTR className, LPCSTR title )
1724 LPWSTR titleW = NULL;
1729 DWORD len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1730 if (!(titleW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1731 MultiByteToWideChar( CP_ACP, 0, title, -1, titleW, len );
1734 if (!IS_INTRESOURCE(className))
1737 if (MultiByteToWideChar( CP_ACP, 0, className, -1, classW, sizeof(classW)/sizeof(WCHAR) ))
1738 hwnd = FindWindowExW( parent, child, classW, titleW );
1742 hwnd = FindWindowExW( parent, child, (LPCWSTR)className, titleW );
1745 HeapFree( GetProcessHeap(), 0, titleW );
1750 /***********************************************************************
1751 * FindWindowW (USER32.@)
1753 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1755 return FindWindowExW( 0, 0, className, title );
1759 /**********************************************************************
1760 * GetDesktopWindow (USER32.@)
1762 HWND WINAPI GetDesktopWindow(void)
1764 struct user_thread_info *thread_info = get_user_thread_info();
1766 if (thread_info->top_window) return thread_info->top_window;
1768 SERVER_START_REQ( get_desktop_window )
1771 if (!wine_server_call( req ))
1773 thread_info->top_window = wine_server_ptr_handle( reply->top_window );
1774 thread_info->msg_window = wine_server_ptr_handle( reply->msg_window );
1779 if (!thread_info->top_window)
1781 USEROBJECTFLAGS flags;
1782 if (!GetUserObjectInformationW( GetProcessWindowStation(), UOI_FLAGS, &flags,
1783 sizeof(flags), NULL ) || (flags.dwFlags & WSF_VISIBLE))
1785 static const WCHAR command_line[] = {'\\','e','x','p','l','o','r','e','r','.','e','x','e',' ','/','d','e','s','k','t','o','p',0};
1787 PROCESS_INFORMATION pi;
1788 WCHAR cmdline[MAX_PATH + sizeof(command_line)/sizeof(WCHAR)];
1790 memset( &si, 0, sizeof(si) );
1792 si.dwFlags = STARTF_USESTDHANDLES;
1795 si.hStdError = GetStdHandle( STD_ERROR_HANDLE );
1797 GetSystemDirectoryW( cmdline, MAX_PATH );
1798 lstrcatW( cmdline, command_line );
1799 if (CreateProcessW( NULL, cmdline, NULL, NULL, FALSE, DETACHED_PROCESS,
1800 NULL, NULL, &si, &pi ))
1802 TRACE( "started explorer pid %04x tid %04x\n", pi.dwProcessId, pi.dwThreadId );
1803 WaitForInputIdle( pi.hProcess, 10000 );
1804 CloseHandle( pi.hThread );
1805 CloseHandle( pi.hProcess );
1807 else WARN( "failed to start explorer, err %d\n", GetLastError() );
1809 else TRACE( "not starting explorer since winstation is not visible\n" );
1811 SERVER_START_REQ( get_desktop_window )
1814 if (!wine_server_call( req ))
1816 thread_info->top_window = wine_server_ptr_handle( reply->top_window );
1817 thread_info->msg_window = wine_server_ptr_handle( reply->msg_window );
1823 if (!thread_info->top_window || !USER_Driver->pCreateDesktopWindow( thread_info->top_window ))
1824 ERR( "failed to create desktop window\n" );
1826 return thread_info->top_window;
1830 /*******************************************************************
1831 * EnableWindow (USER32.@)
1833 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1838 if (is_broadcast(hwnd))
1840 SetLastError( ERROR_INVALID_PARAMETER );
1844 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1845 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1849 TRACE("( %p, %d )\n", hwnd, enable);
1851 retvalue = !IsWindowEnabled( hwnd );
1853 if (enable && retvalue)
1855 WIN_SetStyle( hwnd, 0, WS_DISABLED );
1856 SendMessageW( hwnd, WM_ENABLE, TRUE, 0 );
1858 else if (!enable && !retvalue)
1862 SendMessageW( hwnd, WM_CANCELMODE, 0, 0);
1864 WIN_SetStyle( hwnd, WS_DISABLED, 0 );
1866 if (hwnd == GetFocus())
1867 SetFocus( 0 ); /* A disabled window can't have the focus */
1869 capture_wnd = GetCapture();
1870 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1871 ReleaseCapture(); /* A disabled window can't capture the mouse */
1873 SendMessageW( hwnd, WM_ENABLE, FALSE, 0 );
1879 /***********************************************************************
1880 * IsWindowEnabled (USER32.@)
1882 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1884 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1888 /***********************************************************************
1889 * IsWindowUnicode (USER32.@)
1891 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1894 BOOL retvalue = FALSE;
1896 if (!(wndPtr = WIN_GetPtr(hwnd))) return FALSE;
1898 if (wndPtr == WND_DESKTOP) return TRUE;
1900 if (wndPtr != WND_OTHER_PROCESS)
1902 retvalue = (wndPtr->flags & WIN_ISUNICODE) != 0;
1903 WIN_ReleasePtr( wndPtr );
1907 SERVER_START_REQ( get_window_info )
1909 req->handle = wine_server_user_handle( hwnd );
1910 if (!wine_server_call_err( req )) retvalue = reply->is_unicode;
1918 /**********************************************************************
1921 * Helper function for GetWindowLong().
1923 static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, UINT size, BOOL unicode )
1925 LONG_PTR retvalue = 0;
1928 if (offset == GWLP_HWNDPARENT)
1930 HWND parent = GetAncestor( hwnd, GA_PARENT );
1931 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1932 return (ULONG_PTR)parent;
1935 if (!(wndPtr = WIN_GetPtr( hwnd )))
1937 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1941 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1943 if (offset == GWLP_WNDPROC)
1945 SetLastError( ERROR_ACCESS_DENIED );
1948 SERVER_START_REQ( set_window_info )
1950 req->handle = wine_server_user_handle( hwnd );
1951 req->flags = 0; /* don't set anything, just retrieve */
1952 req->extra_offset = (offset >= 0) ? offset : -1;
1953 req->extra_size = (offset >= 0) ? size : 0;
1954 if (!wine_server_call_err( req ))
1958 case GWL_STYLE: retvalue = reply->old_style; break;
1959 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1960 case GWLP_ID: retvalue = reply->old_id; break;
1961 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wine_server_get_ptr( reply->old_instance ); break;
1962 case GWLP_USERDATA: retvalue = reply->old_user_data; break;
1964 if (offset >= 0) retvalue = get_win_data( &reply->old_extra_value, size );
1965 else SetLastError( ERROR_INVALID_INDEX );
1974 /* now we have a valid wndPtr */
1978 if (offset > (int)(wndPtr->cbWndExtra - size))
1980 WARN("Invalid offset %d\n", offset );
1981 WIN_ReleasePtr( wndPtr );
1982 SetLastError( ERROR_INVALID_INDEX );
1985 retvalue = get_win_data( (char *)wndPtr->wExtra + offset, size );
1987 /* Special case for dialog window procedure */
1988 if ((offset == DWLP_DLGPROC) && (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG))
1989 retvalue = (LONG_PTR)WINPROC_GetProc( (WNDPROC)retvalue, unicode );
1990 WIN_ReleasePtr( wndPtr );
1996 case GWLP_USERDATA: retvalue = wndPtr->userdata; break;
1997 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1998 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1999 case GWLP_ID: retvalue = wndPtr->wIDmenu; break;
2000 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wndPtr->hInstance; break;
2002 /* This looks like a hack only for the edit control (see tests). This makes these controls
2003 * more tolerant to A/W mismatches. The lack of W->A->W conversion for such a mismatch suggests
2004 * that the hack is in GetWindowLongPtr[AW], not in winprocs.
2006 if (wndPtr->winproc == EDIT_winproc_handle && (!unicode != !(wndPtr->flags & WIN_ISUNICODE)))
2007 retvalue = (ULONG_PTR)wndPtr->winproc;
2009 retvalue = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, unicode );
2012 WARN("Unknown offset %d\n", offset );
2013 SetLastError( ERROR_INVALID_INDEX );
2016 WIN_ReleasePtr(wndPtr);
2021 /**********************************************************************
2024 * Helper function for SetWindowLong().
2026 * 0 is the failure code. However, in the case of failure SetLastError
2027 * must be set to distinguish between a 0 return value and a failure.
2029 LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, UINT size, LONG_PTR newval, BOOL unicode )
2033 LONG_PTR retval = 0;
2036 TRACE( "%p %d %lx %c\n", hwnd, offset, newval, unicode ? 'W' : 'A' );
2038 if (is_broadcast(hwnd))
2040 SetLastError( ERROR_INVALID_PARAMETER );
2044 if (!(wndPtr = WIN_GetPtr( hwnd )))
2046 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2049 if (wndPtr == WND_DESKTOP)
2051 /* can't change anything on the desktop window */
2052 SetLastError( ERROR_ACCESS_DENIED );
2055 if (wndPtr == WND_OTHER_PROCESS)
2057 if (offset == GWLP_WNDPROC)
2059 SetLastError( ERROR_ACCESS_DENIED );
2062 if (offset > 32767 || offset < -32767)
2064 SetLastError( ERROR_INVALID_INDEX );
2067 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, MAKEWPARAM( offset, size ), newval );
2070 /* first some special cases */
2076 offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
2077 style.styleNew = newval;
2078 WIN_ReleasePtr( wndPtr );
2079 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
2080 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
2081 newval = style.styleNew;
2083 case GWLP_HWNDPARENT:
2084 if (wndPtr->parent == GetDesktopWindow())
2086 WIN_ReleasePtr( wndPtr );
2087 return (ULONG_PTR)WIN_SetOwner( hwnd, (HWND)newval );
2091 WIN_ReleasePtr( wndPtr );
2092 return (ULONG_PTR)SetParent( hwnd, (HWND)newval );
2097 UINT old_flags = wndPtr->flags;
2098 retval = WIN_GetWindowLong( hwnd, offset, size, unicode );
2099 if (unicode) proc = WINPROC_AllocProc( NULL, (WNDPROC)newval );
2100 else proc = WINPROC_AllocProc( (WNDPROC)newval, NULL );
2101 if (proc) wndPtr->winproc = proc;
2102 if (WINPROC_IsUnicode( proc, unicode )) wndPtr->flags |= WIN_ISUNICODE;
2103 else wndPtr->flags &= ~WIN_ISUNICODE;
2104 if (!((old_flags ^ wndPtr->flags) & WIN_ISUNICODE))
2106 WIN_ReleasePtr( wndPtr );
2109 /* update is_unicode flag on the server side */
2113 case GWLP_HINSTANCE:
2117 if ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
2118 (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG))
2120 WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWLP_DLGPROC);
2121 retval = (ULONG_PTR)WINPROC_GetProc( *ptr, unicode );
2122 if (unicode) *ptr = WINPROC_AllocProc( NULL, (WNDPROC)newval );
2123 else *ptr = WINPROC_AllocProc( (WNDPROC)newval, NULL );
2124 WIN_ReleasePtr( wndPtr );
2129 if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - size))
2131 WARN("Invalid offset %d\n", offset );
2132 WIN_ReleasePtr( wndPtr );
2133 SetLastError( ERROR_INVALID_INDEX );
2136 else if (get_win_data( (char *)wndPtr->wExtra + offset, size ) == newval)
2138 /* already set to the same value */
2139 WIN_ReleasePtr( wndPtr );
2145 SERVER_START_REQ( set_window_info )
2147 req->handle = wine_server_user_handle( hwnd );
2148 req->extra_offset = -1;
2152 req->flags = SET_WIN_STYLE;
2153 req->style = newval;
2156 req->flags = SET_WIN_EXSTYLE;
2157 /* WS_EX_TOPMOST can only be changed through SetWindowPos */
2158 newval = (newval & ~WS_EX_TOPMOST) | (wndPtr->dwExStyle & WS_EX_TOPMOST);
2159 req->ex_style = newval;
2162 req->flags = SET_WIN_ID;
2165 case GWLP_HINSTANCE:
2166 req->flags = SET_WIN_INSTANCE;
2167 req->instance = wine_server_client_ptr( (void *)newval );
2170 req->flags = SET_WIN_UNICODE;
2171 req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
2174 req->flags = SET_WIN_USERDATA;
2175 req->user_data = newval;
2178 req->flags = SET_WIN_EXTRA;
2179 req->extra_offset = offset;
2180 req->extra_size = size;
2181 set_win_data( &req->extra_value, newval, size );
2183 if ((ok = !wine_server_call_err( req )))
2188 wndPtr->dwStyle = newval;
2189 retval = reply->old_style;
2192 wndPtr->dwExStyle = newval;
2193 retval = reply->old_ex_style;
2196 wndPtr->wIDmenu = newval;
2197 retval = reply->old_id;
2199 case GWLP_HINSTANCE:
2200 wndPtr->hInstance = (HINSTANCE)newval;
2201 retval = (ULONG_PTR)wine_server_get_ptr( reply->old_instance );
2206 wndPtr->userdata = newval;
2207 retval = reply->old_user_data;
2210 retval = get_win_data( (char *)wndPtr->wExtra + offset, size );
2211 set_win_data( (char *)wndPtr->wExtra + offset, newval, size );
2217 WIN_ReleasePtr( wndPtr );
2221 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2223 USER_Driver->pSetWindowStyle( hwnd, offset, &style );
2224 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2231 /**********************************************************************
2232 * GetWindowLong (USER.135)
2234 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2238 BOOL is_winproc = (offset == GWLP_WNDPROC);
2242 if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2244 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2247 if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2249 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
2252 * Some programs try to access last element from 16 bit
2253 * code using illegal offset value. Hopefully this is
2254 * what those programs really expect.
2256 if (wndPtr->cbWndExtra >= 4 && offset == wndPtr->cbWndExtra - sizeof(WORD))
2258 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
2259 ERR( "- replaced invalid offset %d with %d\n", offset, offset2 );
2264 WARN("Invalid offset %d\n", offset );
2265 WIN_ReleasePtr( wndPtr );
2266 SetLastError( ERROR_INVALID_INDEX );
2270 is_winproc = ((offset == DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG));
2271 WIN_ReleasePtr( wndPtr );
2274 retvalue = GetWindowLongA( WIN_Handle32(hwnd), offset );
2275 if (is_winproc) retvalue = (LONG_PTR)WINPROC_GetProc16( (WNDPROC)retvalue, FALSE );
2280 /**********************************************************************
2281 * GetWindowWord (USER32.@)
2283 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
2288 case GWLP_HINSTANCE:
2289 case GWLP_HWNDPARENT:
2294 WARN("Invalid offset %d\n", offset );
2295 SetLastError( ERROR_INVALID_INDEX );
2300 return WIN_GetWindowLong( hwnd, offset, sizeof(WORD), FALSE );
2304 /**********************************************************************
2305 * GetWindowLongA (USER32.@)
2307 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2309 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), FALSE );
2313 /**********************************************************************
2314 * GetWindowLongW (USER32.@)
2316 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2318 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), TRUE );
2322 /**********************************************************************
2323 * SetWindowLong (USER.136)
2325 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2328 BOOL is_winproc = (offset == GWLP_WNDPROC);
2330 if (offset == DWLP_DLGPROC)
2332 if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2334 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2337 if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2339 is_winproc = ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
2340 (wndPtr->flags & WIN_ISDIALOG));
2341 WIN_ReleasePtr( wndPtr );
2347 WNDPROC new_proc = WINPROC_AllocProc16( (WNDPROC16)newval );
2348 WNDPROC old_proc = (WNDPROC)SetWindowLongPtrA( WIN_Handle32(hwnd), offset, (LONG_PTR)new_proc );
2349 return (LONG)WINPROC_GetProc16( old_proc, FALSE );
2351 else return SetWindowLongA( WIN_Handle32(hwnd), offset, newval );
2355 /**********************************************************************
2356 * SetWindowWord (USER32.@)
2358 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
2363 case GWLP_HINSTANCE:
2364 case GWLP_HWNDPARENT:
2369 WARN("Invalid offset %d\n", offset );
2370 SetLastError( ERROR_INVALID_INDEX );
2375 return WIN_SetWindowLong( hwnd, offset, sizeof(WORD), newval, FALSE );
2379 /**********************************************************************
2380 * SetWindowLongA (USER32.@)
2382 * See SetWindowLongW.
2384 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2386 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, FALSE );
2390 /**********************************************************************
2391 * SetWindowLongW (USER32.@) Set window attribute
2393 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2394 * value in a window's extra memory.
2396 * The _hwnd_ parameter specifies the window. is the handle to a
2397 * window that has extra memory. The _newval_ parameter contains the
2398 * new attribute or extra memory value. If positive, the _offset_
2399 * parameter is the byte-addressed location in the window's extra
2400 * memory to set. If negative, _offset_ specifies the window
2401 * attribute to set, and should be one of the following values:
2403 * GWL_EXSTYLE The window's extended window style
2405 * GWL_STYLE The window's window style.
2407 * GWLP_WNDPROC Pointer to the window's window procedure.
2409 * GWLP_HINSTANCE The window's pplication instance handle.
2411 * GWLP_ID The window's identifier.
2413 * GWLP_USERDATA The window's user-specified data.
2415 * If the window is a dialog box, the _offset_ parameter can be one of
2416 * the following values:
2418 * DWLP_DLGPROC The address of the window's dialog box procedure.
2420 * DWLP_MSGRESULT The return value of a message
2421 * that the dialog box procedure processed.
2423 * DWLP_USER Application specific information.
2427 * If successful, returns the previous value located at _offset_. Otherwise,
2432 * Extra memory for a window class is specified by a nonzero cbWndExtra
2433 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2434 * time of class creation.
2436 * Using GWL_WNDPROC to set a new window procedure effectively creates
2437 * a window subclass. Use CallWindowProc() in the new windows procedure
2438 * to pass messages to the superclass's window procedure.
2440 * The user data is reserved for use by the application which created
2443 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2444 * instead, call the EnableWindow() function to change the window's
2447 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2448 * SetParent() instead.
2451 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2452 * it sends WM_STYLECHANGING before changing the settings
2453 * and WM_STYLECHANGED afterwards.
2454 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2456 LONG WINAPI SetWindowLongW(
2457 HWND hwnd, /* [in] window to alter */
2458 INT offset, /* [in] offset, in bytes, of location to alter */
2459 LONG newval /* [in] new value of location */
2461 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, TRUE );
2465 /*******************************************************************
2466 * GetWindowTextA (USER32.@)
2468 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2472 if (!lpString) return 0;
2474 if (WIN_IsCurrentProcess( hwnd ))
2475 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2477 /* when window belongs to other process, don't send a message */
2478 if (nMaxCount <= 0) return 0;
2479 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2480 get_server_window_text( hwnd, buffer, nMaxCount );
2481 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2482 lpString[nMaxCount-1] = 0;
2483 HeapFree( GetProcessHeap(), 0, buffer );
2484 return strlen(lpString);
2488 /*******************************************************************
2489 * InternalGetWindowText (USER32.@)
2491 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2495 if (nMaxCount <= 0) return 0;
2496 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2497 if (win == WND_DESKTOP) lpString[0] = 0;
2498 else if (win != WND_OTHER_PROCESS)
2500 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2501 else lpString[0] = 0;
2502 WIN_ReleasePtr( win );
2506 get_server_window_text( hwnd, lpString, nMaxCount );
2508 return strlenW(lpString);
2512 /*******************************************************************
2513 * GetWindowTextW (USER32.@)
2515 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2517 if (!lpString) return 0;
2519 if (WIN_IsCurrentProcess( hwnd ))
2520 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2522 /* when window belongs to other process, don't send a message */
2523 if (nMaxCount <= 0) return 0;
2524 get_server_window_text( hwnd, lpString, nMaxCount );
2525 return strlenW(lpString);
2529 /*******************************************************************
2530 * SetWindowTextA (USER32.@)
2531 * SetWindowText (USER32.@)
2533 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2535 if (is_broadcast(hwnd))
2537 SetLastError( ERROR_INVALID_PARAMETER );
2540 if (!WIN_IsCurrentProcess( hwnd ))
2541 WARN( "setting text %s of other process window %p should not use SendMessage\n",
2542 debugstr_a(lpString), hwnd );
2543 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2547 /*******************************************************************
2548 * SetWindowTextW (USER32.@)
2550 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2552 if (is_broadcast(hwnd))
2554 SetLastError( ERROR_INVALID_PARAMETER );
2557 if (!WIN_IsCurrentProcess( hwnd ))
2558 WARN( "setting text %s of other process window %p should not use SendMessage\n",
2559 debugstr_w(lpString), hwnd );
2560 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2564 /*******************************************************************
2565 * GetWindowTextLengthA (USER32.@)
2567 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2569 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2572 /*******************************************************************
2573 * GetWindowTextLengthW (USER32.@)
2575 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2577 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2581 /*******************************************************************
2582 * IsWindow (USER32.@)
2584 BOOL WINAPI IsWindow( HWND hwnd )
2589 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2590 if (ptr == WND_DESKTOP) return TRUE;
2592 if (ptr != WND_OTHER_PROCESS)
2594 WIN_ReleasePtr( ptr );
2598 /* check other processes */
2599 SERVER_START_REQ( get_window_info )
2601 req->handle = wine_server_user_handle( hwnd );
2602 ret = !wine_server_call_err( req );
2609 /***********************************************************************
2610 * GetWindowThreadProcessId (USER32.@)
2612 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2617 if (!(ptr = WIN_GetPtr( hwnd )))
2619 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2623 if (ptr != WND_OTHER_PROCESS && ptr != WND_DESKTOP)
2625 /* got a valid window */
2627 if (process) *process = GetCurrentProcessId();
2628 WIN_ReleasePtr( ptr );
2632 /* check other processes */
2633 SERVER_START_REQ( get_window_info )
2635 req->handle = wine_server_user_handle( hwnd );
2636 if (!wine_server_call_err( req ))
2638 tid = (DWORD)reply->tid;
2639 if (process) *process = (DWORD)reply->pid;
2647 /*****************************************************************
2648 * GetParent (USER32.@)
2650 HWND WINAPI GetParent( HWND hwnd )
2655 if (!(wndPtr = WIN_GetPtr( hwnd )))
2657 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2660 if (wndPtr == WND_DESKTOP) return 0;
2661 if (wndPtr == WND_OTHER_PROCESS)
2663 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2664 if (style & (WS_POPUP | WS_CHILD))
2666 SERVER_START_REQ( get_window_tree )
2668 req->handle = wine_server_user_handle( hwnd );
2669 if (!wine_server_call_err( req ))
2671 if (style & WS_POPUP) retvalue = wine_server_ptr_handle( reply->owner );
2672 else if (style & WS_CHILD) retvalue = wine_server_ptr_handle( reply->parent );
2680 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2681 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2682 WIN_ReleasePtr( wndPtr );
2688 /*****************************************************************
2689 * GetAncestor (USER32.@)
2691 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2694 HWND *list, ret = 0;
2699 if (!(win = WIN_GetPtr( hwnd )))
2701 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2704 if (win == WND_DESKTOP) return 0;
2705 if (win != WND_OTHER_PROCESS)
2708 WIN_ReleasePtr( win );
2710 else /* need to query the server */
2712 SERVER_START_REQ( get_window_tree )
2714 req->handle = wine_server_user_handle( hwnd );
2715 if (!wine_server_call_err( req )) ret = wine_server_ptr_handle( reply->parent );
2722 if (!(list = list_window_parents( hwnd ))) return 0;
2724 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2728 while (list[count]) count++;
2729 ret = list[count - 2]; /* get the one before the desktop */
2731 HeapFree( GetProcessHeap(), 0, list );
2735 if (is_desktop_window( hwnd )) return 0;
2736 ret = WIN_GetFullHandle( hwnd );
2739 HWND parent = GetParent( ret );
2749 /*****************************************************************
2750 * SetParent (USER32.@)
2752 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2755 HWND old_parent = 0;
2760 if (is_broadcast(hwnd) || is_broadcast(parent))
2762 SetLastError(ERROR_INVALID_PARAMETER);
2766 if (!parent) parent = GetDesktopWindow();
2767 else if (parent == HWND_MESSAGE) parent = get_hwnd_message_parent();
2768 else parent = WIN_GetFullHandle( parent );
2770 if (!IsWindow( parent ))
2772 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2776 /* Some applications try to set a child as a parent */
2777 if (IsChild(hwnd, parent))
2779 SetLastError( ERROR_INVALID_PARAMETER );
2783 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2784 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2786 /* Windows hides the window first, then shows it again
2787 * including the WM_SHOWWINDOW messages and all */
2788 was_visible = ShowWindow( hwnd, SW_HIDE );
2790 wndPtr = WIN_GetPtr( hwnd );
2791 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return 0;
2793 SERVER_START_REQ( set_parent )
2795 req->handle = wine_server_user_handle( hwnd );
2796 req->parent = wine_server_user_handle( parent );
2797 if ((ret = !wine_server_call( req )))
2799 old_parent = wine_server_ptr_handle( reply->old_parent );
2800 wndPtr->parent = parent = wine_server_ptr_handle( reply->full_parent );
2805 WIN_ReleasePtr( wndPtr );
2808 USER_Driver->pSetParent( full_handle, parent, old_parent );
2810 /* SetParent additionally needs to make hwnd the topmost window
2811 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2812 WM_WINDOWPOSCHANGED notification messages.
2814 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0,
2815 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2816 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2817 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2823 /*******************************************************************
2824 * IsChild (USER32.@)
2826 BOOL WINAPI IsChild( HWND parent, HWND child )
2828 HWND *list = list_window_parents( child );
2832 if (!list) return FALSE;
2833 parent = WIN_GetFullHandle( parent );
2834 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2835 ret = list[i] && list[i+1];
2836 HeapFree( GetProcessHeap(), 0, list );
2841 /***********************************************************************
2842 * IsWindowVisible (USER32.@)
2844 BOOL WINAPI IsWindowVisible( HWND hwnd )
2850 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2851 if (!(list = list_window_parents( hwnd ))) return TRUE;
2854 for (i = 0; list[i+1]; i++)
2855 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2856 retval = !list[i+1] && (list[i] == GetDesktopWindow()); /* top message window isn't visible */
2858 HeapFree( GetProcessHeap(), 0, list );
2863 /***********************************************************************
2864 * WIN_IsWindowDrawable
2866 * hwnd is drawable when it is visible, all parents are not
2867 * minimized, and it is itself not minimized unless we are
2868 * trying to draw its default class icon.
2870 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2875 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2877 if (!(style & WS_VISIBLE)) return FALSE;
2878 if ((style & WS_MINIMIZE) && icon && GetClassLongPtrW( hwnd, GCLP_HICON )) return FALSE;
2880 if (!(list = list_window_parents( hwnd ))) return TRUE;
2883 for (i = 0; list[i+1]; i++)
2884 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2886 retval = !list[i+1] && (list[i] == GetDesktopWindow()); /* top message window isn't visible */
2888 HeapFree( GetProcessHeap(), 0, list );
2893 /*******************************************************************
2894 * GetTopWindow (USER32.@)
2896 HWND WINAPI GetTopWindow( HWND hwnd )
2898 if (!hwnd) hwnd = GetDesktopWindow();
2899 return GetWindow( hwnd, GW_CHILD );
2903 /*******************************************************************
2904 * GetWindow (USER32.@)
2906 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2910 if (rel == GW_OWNER) /* this one may be available locally */
2912 WND *wndPtr = WIN_GetPtr( hwnd );
2915 SetLastError( ERROR_INVALID_HANDLE );
2918 if (wndPtr == WND_DESKTOP) return 0;
2919 if (wndPtr != WND_OTHER_PROCESS)
2921 retval = wndPtr->owner;
2922 WIN_ReleasePtr( wndPtr );
2925 /* else fall through to server call */
2928 SERVER_START_REQ( get_window_tree )
2930 req->handle = wine_server_user_handle( hwnd );
2931 if (!wine_server_call_err( req ))
2936 retval = wine_server_ptr_handle( reply->first_sibling );
2939 retval = wine_server_ptr_handle( reply->last_sibling );
2942 retval = wine_server_ptr_handle( reply->next_sibling );
2945 retval = wine_server_ptr_handle( reply->prev_sibling );
2948 retval = wine_server_ptr_handle( reply->owner );
2951 retval = wine_server_ptr_handle( reply->first_child );
2961 /*******************************************************************
2962 * ShowOwnedPopups (USER32.@)
2964 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2968 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2970 if (!win_array) return TRUE;
2972 while (win_array[count]) count++;
2973 while (--count >= 0)
2975 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2976 if (!(pWnd = WIN_GetPtr( win_array[count] ))) continue;
2977 if (pWnd == WND_OTHER_PROCESS) continue;
2980 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2982 WIN_ReleasePtr( pWnd );
2983 /* In Windows, ShowOwnedPopups(TRUE) generates
2984 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2985 * regardless of the state of the owner
2987 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_SHOWNORMAL, SW_PARENTOPENING);
2993 if (pWnd->dwStyle & WS_VISIBLE)
2995 WIN_ReleasePtr( pWnd );
2996 /* In Windows, ShowOwnedPopups(FALSE) generates
2997 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2998 * regardless of the state of the owner
3000 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
3004 WIN_ReleasePtr( pWnd );
3006 HeapFree( GetProcessHeap(), 0, win_array );
3011 /*******************************************************************
3012 * GetLastActivePopup (USER32.@)
3014 HWND WINAPI GetLastActivePopup( HWND hwnd )
3018 SERVER_START_REQ( get_window_info )
3020 req->handle = wine_server_user_handle( hwnd );
3021 if (!wine_server_call_err( req )) retval = wine_server_ptr_handle( reply->last_active );
3028 /*******************************************************************
3031 * Build an array of the children of a given window. The array must be
3032 * freed with HeapFree. Returns NULL when no windows are found.
3034 HWND *WIN_ListChildren( HWND hwnd )
3038 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
3041 return list_window_children( 0, hwnd, NULL, 0 );
3045 /*******************************************************************
3046 * EnumWindows (USER32.@)
3048 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
3054 USER_CheckNotLock();
3056 /* We have to build a list of all windows first, to avoid */
3057 /* unpleasant side-effects, for instance if the callback */
3058 /* function changes the Z-order of the windows. */
3060 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
3062 /* Now call the callback function for every window */
3064 for (i = 0; list[i]; i++)
3066 /* Make sure that the window still exists */
3067 if (!IsWindow( list[i] )) continue;
3068 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
3070 HeapFree( GetProcessHeap(), 0, list );
3075 /**********************************************************************
3076 * EnumThreadWindows (USER32.@)
3078 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
3083 USER_CheckNotLock();
3085 if (!(list = list_window_children( 0, GetDesktopWindow(), NULL, id ))) return TRUE;
3087 /* Now call the callback function for every window */
3089 for (i = 0; list[i]; i++)
3090 if (!func( list[i], lParam )) break;
3091 HeapFree( GetProcessHeap(), 0, list );
3096 /***********************************************************************
3097 * EnumDesktopWindows (USER32.@)
3099 BOOL WINAPI EnumDesktopWindows( HDESK desktop, WNDENUMPROC func, LPARAM lparam )
3104 USER_CheckNotLock();
3106 if (!(list = list_window_children( desktop, 0, NULL, 0 ))) return TRUE;
3108 for (i = 0; list[i]; i++)
3109 if (!func( list[i], lparam )) break;
3110 HeapFree( GetProcessHeap(), 0, list );
3115 /**********************************************************************
3116 * WIN_EnumChildWindows
3118 * Helper function for EnumChildWindows().
3120 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
3125 for ( ; *list; list++)
3127 /* Make sure that the window still exists */
3128 if (!IsWindow( *list )) continue;
3129 /* Build children list first */
3130 childList = WIN_ListChildren( *list );
3132 ret = func( *list, lParam );
3136 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
3137 HeapFree( GetProcessHeap(), 0, childList );
3139 if (!ret) return FALSE;
3145 /**********************************************************************
3146 * EnumChildWindows (USER32.@)
3148 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
3153 USER_CheckNotLock();
3155 if (!(list = WIN_ListChildren( parent ))) return FALSE;
3156 ret = WIN_EnumChildWindows( list, func, lParam );
3157 HeapFree( GetProcessHeap(), 0, list );
3162 /*******************************************************************
3163 * AnyPopup (USER.52)
3165 BOOL16 WINAPI AnyPopup16(void)
3171 /*******************************************************************
3172 * AnyPopup (USER32.@)
3174 BOOL WINAPI AnyPopup(void)
3178 HWND *list = WIN_ListChildren( GetDesktopWindow() );
3180 if (!list) return FALSE;
3181 for (i = 0; list[i]; i++)
3183 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
3185 retvalue = (list[i] != 0);
3186 HeapFree( GetProcessHeap(), 0, list );
3191 /*******************************************************************
3192 * FlashWindow (USER32.@)
3194 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3198 TRACE("%p\n", hWnd);
3200 if (IsIconic( hWnd ))
3202 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3204 wndPtr = WIN_GetPtr(hWnd);
3205 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
3206 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3208 wndPtr->flags |= WIN_NCACTIVATED;
3212 wndPtr->flags &= ~WIN_NCACTIVATED;
3214 WIN_ReleasePtr( wndPtr );
3221 wndPtr = WIN_GetPtr(hWnd);
3222 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
3223 hWnd = wndPtr->hwndSelf; /* make it a full handle */
3225 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3226 else wparam = (hWnd == GetForegroundWindow());
3228 WIN_ReleasePtr( wndPtr );
3229 SendMessageW( hWnd, WM_NCACTIVATE, wparam, 0 );
3234 /*******************************************************************
3235 * FlashWindowEx (USER32.@)
3237 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
3239 FIXME("%p\n", pfwi);
3243 /*******************************************************************
3244 * GetWindowContextHelpId (USER32.@)
3246 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3249 WND *wnd = WIN_GetPtr( hwnd );
3250 if (!wnd || wnd == WND_DESKTOP) return 0;
3251 if (wnd == WND_OTHER_PROCESS)
3253 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3256 retval = wnd->helpContext;
3257 WIN_ReleasePtr( wnd );
3262 /*******************************************************************
3263 * SetWindowContextHelpId (USER32.@)
3265 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3267 WND *wnd = WIN_GetPtr( hwnd );
3268 if (!wnd || wnd == WND_DESKTOP) return FALSE;
3269 if (wnd == WND_OTHER_PROCESS)
3271 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3274 wnd->helpContext = id;
3275 WIN_ReleasePtr( wnd );
3280 /*******************************************************************
3281 * DragDetect (USER32.@)
3283 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3287 WORD wDragWidth = GetSystemMetrics(SM_CXDRAG);
3288 WORD wDragHeight= GetSystemMetrics(SM_CYDRAG);
3290 rect.left = pt.x - wDragWidth;
3291 rect.right = pt.x + wDragWidth;
3293 rect.top = pt.y - wDragHeight;
3294 rect.bottom = pt.y + wDragHeight;
3300 while (PeekMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ))
3302 if( msg.message == WM_LBUTTONUP )
3307 if( msg.message == WM_MOUSEMOVE )
3310 tmp.x = (short)LOWORD(msg.lParam);
3311 tmp.y = (short)HIWORD(msg.lParam);
3312 if( !PtInRect( &rect, tmp ))
3324 /******************************************************************************
3325 * GetWindowModuleFileNameA (USER32.@)
3327 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR module, UINT size )
3332 TRACE( "%p, %p, %u\n", hwnd, module, size );
3334 win = WIN_GetPtr( hwnd );
3335 if (!win || win == WND_OTHER_PROCESS || win == WND_DESKTOP)
3337 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
3340 hinst = win->hInstance;
3341 WIN_ReleasePtr( win );
3343 return GetModuleFileNameA( hinst, module, size );
3346 /******************************************************************************
3347 * GetWindowModuleFileNameW (USER32.@)
3349 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR module, UINT size )
3354 TRACE( "%p, %p, %u\n", hwnd, module, size );
3356 win = WIN_GetPtr( hwnd );
3357 if (!win || win == WND_OTHER_PROCESS || win == WND_DESKTOP)
3359 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
3362 hinst = win->hInstance;
3363 WIN_ReleasePtr( win );
3365 return GetModuleFileNameW( hinst, module, size );
3368 /******************************************************************************
3369 * GetWindowInfo (USER32.@)
3371 * Note: tests show that Windows doesn't check cbSize of the structure.
3373 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3375 if (!pwi) return FALSE;
3376 if (!IsWindow(hwnd)) return FALSE;
3378 GetWindowRect(hwnd, &pwi->rcWindow);
3379 GetClientRect(hwnd, &pwi->rcClient);
3380 /* translate to screen coordinates */
3381 MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3383 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3384 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3385 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3387 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3388 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3390 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3391 pwi->wCreatorVersion = 0x0400;
3396 /******************************************************************************
3397 * SwitchDesktop (USER32.@)
3399 * NOTES: Sets the current input or interactive desktop.
3401 BOOL WINAPI SwitchDesktop( HDESK hDesktop)
3403 FIXME("SwitchDesktop(hwnd %p) stub!\n", hDesktop);
3407 /*****************************************************************************
3408 * SetLayeredWindowAttributes (USER32.@)
3410 BOOL WINAPI SetLayeredWindowAttributes( HWND hwnd, COLORREF key, BYTE alpha, DWORD flags )
3414 TRACE("(%p,%08x,%d,%x): stub!\n", hwnd, key, alpha, flags);
3416 SERVER_START_REQ( set_window_layered_info )
3418 req->handle = wine_server_user_handle( hwnd );
3419 req->color_key = key;
3422 ret = !wine_server_call_err( req );
3426 if (ret) USER_Driver->pSetLayeredWindowAttributes( hwnd, key, alpha, flags );
3432 /*****************************************************************************
3433 * GetLayeredWindowAttributes (USER32.@)
3435 BOOL WINAPI GetLayeredWindowAttributes( HWND hwnd, COLORREF *key, BYTE *alpha, DWORD *flags )
3439 SERVER_START_REQ( get_window_layered_info )
3441 req->handle = wine_server_user_handle( hwnd );
3442 if ((ret = !wine_server_call_err( req )))
3444 if (key) *key = reply->color_key;
3445 if (alpha) *alpha = reply->alpha;
3446 if (flags) *flags = reply->flags;
3455 /*****************************************************************************
3456 * UpdateLayeredWindowIndirect (USER32.@)
3458 BOOL WINAPI UpdateLayeredWindowIndirect( HWND hwnd, const UPDATELAYEREDWINDOWINFO *info )
3462 if (!(info->dwFlags & ULW_EX_NORESIZE) && (info->pptDst || info->psize))
3464 int x = 0, y = 0, cx = 0, cy = 0;
3465 DWORD flags = SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW | SWP_NOSENDCHANGING;
3469 x = info->pptDst->x;
3470 y = info->pptDst->y;
3471 flags &= ~SWP_NOMOVE;
3475 cx = info->psize->cx;
3476 cy = info->psize->cy;
3477 flags &= ~SWP_NOSIZE;
3479 TRACE( "moving window %p pos %d,%d %dx%x\n", hwnd, x, y, cx, cy );
3480 SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
3486 HDC hdc = GetDCEx( hwnd, 0, DCX_CACHE );
3492 GetClientRect( hwnd, &rect );
3495 x = info->pptSrc->x;
3496 y = info->pptSrc->y;
3498 /* FIXME: intersect rect with info->prcDirty */
3499 TRACE( "copying window %p pos %d,%d\n", hwnd, x, y );
3500 BitBlt( hdc, rect.left, rect.top, rect.right, rect.bottom,
3501 info->hdcSrc, rect.left + x, rect.top + y, SRCCOPY );
3502 ReleaseDC( hwnd, hdc );
3506 if (info->pblend && !(info->dwFlags & ULW_OPAQUE)) alpha = info->pblend->SourceConstantAlpha;
3507 TRACE( "setting window %p alpha %u\n", hwnd, alpha );
3508 USER_Driver->pSetLayeredWindowAttributes( hwnd, info->crKey, alpha,
3509 info->dwFlags & (LWA_ALPHA | LWA_COLORKEY) );
3514 /*****************************************************************************
3515 * UpdateLayeredWindow (USER32.@)
3517 BOOL WINAPI UpdateLayeredWindow( HWND hwnd, HDC hdcDst, POINT *pptDst, SIZE *psize,
3518 HDC hdcSrc, POINT *pptSrc, COLORREF crKey, BLENDFUNCTION *pblend,
3521 UPDATELAYEREDWINDOWINFO info;
3523 info.cbSize = sizeof(info);
3524 info.hdcDst = hdcDst;
3525 info.pptDst = pptDst;
3527 info.hdcSrc = hdcSrc;
3528 info.pptSrc = pptSrc;
3530 info.pblend = pblend;
3531 info.dwFlags = dwFlags;
3532 info.prcDirty = NULL;
3533 return UpdateLayeredWindowIndirect( hwnd, &info );
3536 /* 64bit versions */
3538 #ifdef GetWindowLongPtrW
3539 #undef GetWindowLongPtrW
3542 #ifdef GetWindowLongPtrA
3543 #undef GetWindowLongPtrA
3546 #ifdef SetWindowLongPtrW
3547 #undef SetWindowLongPtrW
3550 #ifdef SetWindowLongPtrA
3551 #undef SetWindowLongPtrA
3554 /*****************************************************************************
3555 * GetWindowLongPtrW (USER32.@)
3557 LONG_PTR WINAPI GetWindowLongPtrW( HWND hwnd, INT offset )
3559 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), TRUE );
3562 /*****************************************************************************
3563 * GetWindowLongPtrA (USER32.@)
3565 LONG_PTR WINAPI GetWindowLongPtrA( HWND hwnd, INT offset )
3567 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), FALSE );
3570 /*****************************************************************************
3571 * SetWindowLongPtrW (USER32.@)
3573 LONG_PTR WINAPI SetWindowLongPtrW( HWND hwnd, INT offset, LONG_PTR newval )
3575 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, TRUE );
3578 /*****************************************************************************
3579 * SetWindowLongPtrA (USER32.@)
3581 LONG_PTR WINAPI SetWindowLongPtrA( HWND hwnd, INT offset, LONG_PTR newval )
3583 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, FALSE );