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 systemdir[MAX_PATH];
1789 WCHAR cmdline[MAX_PATH + sizeof(command_line)/sizeof(WCHAR)];
1791 memset( &si, 0, sizeof(si) );
1793 si.dwFlags = STARTF_USESTDHANDLES;
1796 si.hStdError = GetStdHandle( STD_ERROR_HANDLE );
1798 GetSystemDirectoryW( systemdir, MAX_PATH );
1799 lstrcpyW( cmdline, systemdir );
1800 lstrcatW( cmdline, command_line );
1801 if (CreateProcessW( NULL, cmdline, NULL, NULL, FALSE, DETACHED_PROCESS,
1802 NULL, systemdir, &si, &pi ))
1804 TRACE( "started explorer pid %04x tid %04x\n", pi.dwProcessId, pi.dwThreadId );
1805 WaitForInputIdle( pi.hProcess, 10000 );
1806 CloseHandle( pi.hThread );
1807 CloseHandle( pi.hProcess );
1809 else WARN( "failed to start explorer, err %d\n", GetLastError() );
1811 else TRACE( "not starting explorer since winstation is not visible\n" );
1813 SERVER_START_REQ( get_desktop_window )
1816 if (!wine_server_call( req ))
1818 thread_info->top_window = wine_server_ptr_handle( reply->top_window );
1819 thread_info->msg_window = wine_server_ptr_handle( reply->msg_window );
1825 if (!thread_info->top_window || !USER_Driver->pCreateDesktopWindow( thread_info->top_window ))
1826 ERR( "failed to create desktop window\n" );
1828 return thread_info->top_window;
1832 /*******************************************************************
1833 * EnableWindow (USER32.@)
1835 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1840 if (is_broadcast(hwnd))
1842 SetLastError( ERROR_INVALID_PARAMETER );
1846 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1847 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1851 TRACE("( %p, %d )\n", hwnd, enable);
1853 retvalue = !IsWindowEnabled( hwnd );
1855 if (enable && retvalue)
1857 WIN_SetStyle( hwnd, 0, WS_DISABLED );
1858 SendMessageW( hwnd, WM_ENABLE, TRUE, 0 );
1860 else if (!enable && !retvalue)
1864 SendMessageW( hwnd, WM_CANCELMODE, 0, 0);
1866 WIN_SetStyle( hwnd, WS_DISABLED, 0 );
1868 if (hwnd == GetFocus())
1869 SetFocus( 0 ); /* A disabled window can't have the focus */
1871 capture_wnd = GetCapture();
1872 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1873 ReleaseCapture(); /* A disabled window can't capture the mouse */
1875 SendMessageW( hwnd, WM_ENABLE, FALSE, 0 );
1881 /***********************************************************************
1882 * IsWindowEnabled (USER32.@)
1884 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1886 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1890 /***********************************************************************
1891 * IsWindowUnicode (USER32.@)
1893 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1896 BOOL retvalue = FALSE;
1898 if (!(wndPtr = WIN_GetPtr(hwnd))) return FALSE;
1900 if (wndPtr == WND_DESKTOP) return TRUE;
1902 if (wndPtr != WND_OTHER_PROCESS)
1904 retvalue = (wndPtr->flags & WIN_ISUNICODE) != 0;
1905 WIN_ReleasePtr( wndPtr );
1909 SERVER_START_REQ( get_window_info )
1911 req->handle = wine_server_user_handle( hwnd );
1912 if (!wine_server_call_err( req )) retvalue = reply->is_unicode;
1920 /**********************************************************************
1923 * Helper function for GetWindowLong().
1925 static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, UINT size, BOOL unicode )
1927 LONG_PTR retvalue = 0;
1930 if (offset == GWLP_HWNDPARENT)
1932 HWND parent = GetAncestor( hwnd, GA_PARENT );
1933 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1934 return (ULONG_PTR)parent;
1937 if (!(wndPtr = WIN_GetPtr( hwnd )))
1939 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1943 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1945 if (offset == GWLP_WNDPROC)
1947 SetLastError( ERROR_ACCESS_DENIED );
1950 SERVER_START_REQ( set_window_info )
1952 req->handle = wine_server_user_handle( hwnd );
1953 req->flags = 0; /* don't set anything, just retrieve */
1954 req->extra_offset = (offset >= 0) ? offset : -1;
1955 req->extra_size = (offset >= 0) ? size : 0;
1956 if (!wine_server_call_err( req ))
1960 case GWL_STYLE: retvalue = reply->old_style; break;
1961 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1962 case GWLP_ID: retvalue = reply->old_id; break;
1963 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wine_server_get_ptr( reply->old_instance ); break;
1964 case GWLP_USERDATA: retvalue = reply->old_user_data; break;
1966 if (offset >= 0) retvalue = get_win_data( &reply->old_extra_value, size );
1967 else SetLastError( ERROR_INVALID_INDEX );
1976 /* now we have a valid wndPtr */
1980 if (offset > (int)(wndPtr->cbWndExtra - size))
1982 WARN("Invalid offset %d\n", offset );
1983 WIN_ReleasePtr( wndPtr );
1984 SetLastError( ERROR_INVALID_INDEX );
1987 retvalue = get_win_data( (char *)wndPtr->wExtra + offset, size );
1989 /* Special case for dialog window procedure */
1990 if ((offset == DWLP_DLGPROC) && (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG))
1991 retvalue = (LONG_PTR)WINPROC_GetProc( (WNDPROC)retvalue, unicode );
1992 WIN_ReleasePtr( wndPtr );
1998 case GWLP_USERDATA: retvalue = wndPtr->userdata; break;
1999 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
2000 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
2001 case GWLP_ID: retvalue = wndPtr->wIDmenu; break;
2002 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wndPtr->hInstance; break;
2004 /* This looks like a hack only for the edit control (see tests). This makes these controls
2005 * more tolerant to A/W mismatches. The lack of W->A->W conversion for such a mismatch suggests
2006 * that the hack is in GetWindowLongPtr[AW], not in winprocs.
2008 if (wndPtr->winproc == EDIT_winproc_handle && (!unicode != !(wndPtr->flags & WIN_ISUNICODE)))
2009 retvalue = (ULONG_PTR)wndPtr->winproc;
2011 retvalue = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, unicode );
2014 WARN("Unknown offset %d\n", offset );
2015 SetLastError( ERROR_INVALID_INDEX );
2018 WIN_ReleasePtr(wndPtr);
2023 /**********************************************************************
2026 * Helper function for SetWindowLong().
2028 * 0 is the failure code. However, in the case of failure SetLastError
2029 * must be set to distinguish between a 0 return value and a failure.
2031 LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, UINT size, LONG_PTR newval, BOOL unicode )
2035 LONG_PTR retval = 0;
2038 TRACE( "%p %d %lx %c\n", hwnd, offset, newval, unicode ? 'W' : 'A' );
2040 if (is_broadcast(hwnd))
2042 SetLastError( ERROR_INVALID_PARAMETER );
2046 if (!(wndPtr = WIN_GetPtr( hwnd )))
2048 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2051 if (wndPtr == WND_DESKTOP)
2053 /* can't change anything on the desktop window */
2054 SetLastError( ERROR_ACCESS_DENIED );
2057 if (wndPtr == WND_OTHER_PROCESS)
2059 if (offset == GWLP_WNDPROC)
2061 SetLastError( ERROR_ACCESS_DENIED );
2064 if (offset > 32767 || offset < -32767)
2066 SetLastError( ERROR_INVALID_INDEX );
2069 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, MAKEWPARAM( offset, size ), newval );
2072 /* first some special cases */
2078 offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
2079 style.styleNew = newval;
2080 WIN_ReleasePtr( wndPtr );
2081 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
2082 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
2083 newval = style.styleNew;
2085 case GWLP_HWNDPARENT:
2086 if (wndPtr->parent == GetDesktopWindow())
2088 WIN_ReleasePtr( wndPtr );
2089 return (ULONG_PTR)WIN_SetOwner( hwnd, (HWND)newval );
2093 WIN_ReleasePtr( wndPtr );
2094 return (ULONG_PTR)SetParent( hwnd, (HWND)newval );
2099 UINT old_flags = wndPtr->flags;
2100 retval = WIN_GetWindowLong( hwnd, offset, size, unicode );
2101 if (unicode) proc = WINPROC_AllocProc( NULL, (WNDPROC)newval );
2102 else proc = WINPROC_AllocProc( (WNDPROC)newval, NULL );
2103 if (proc) wndPtr->winproc = proc;
2104 if (WINPROC_IsUnicode( proc, unicode )) wndPtr->flags |= WIN_ISUNICODE;
2105 else wndPtr->flags &= ~WIN_ISUNICODE;
2106 if (!((old_flags ^ wndPtr->flags) & WIN_ISUNICODE))
2108 WIN_ReleasePtr( wndPtr );
2111 /* update is_unicode flag on the server side */
2115 case GWLP_HINSTANCE:
2119 if ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
2120 (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG))
2122 WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWLP_DLGPROC);
2123 retval = (ULONG_PTR)WINPROC_GetProc( *ptr, unicode );
2124 if (unicode) *ptr = WINPROC_AllocProc( NULL, (WNDPROC)newval );
2125 else *ptr = WINPROC_AllocProc( (WNDPROC)newval, NULL );
2126 WIN_ReleasePtr( wndPtr );
2131 if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - size))
2133 WARN("Invalid offset %d\n", offset );
2134 WIN_ReleasePtr( wndPtr );
2135 SetLastError( ERROR_INVALID_INDEX );
2138 else if (get_win_data( (char *)wndPtr->wExtra + offset, size ) == newval)
2140 /* already set to the same value */
2141 WIN_ReleasePtr( wndPtr );
2147 SERVER_START_REQ( set_window_info )
2149 req->handle = wine_server_user_handle( hwnd );
2150 req->extra_offset = -1;
2154 req->flags = SET_WIN_STYLE;
2155 req->style = newval;
2158 req->flags = SET_WIN_EXSTYLE;
2159 /* WS_EX_TOPMOST can only be changed through SetWindowPos */
2160 newval = (newval & ~WS_EX_TOPMOST) | (wndPtr->dwExStyle & WS_EX_TOPMOST);
2161 req->ex_style = newval;
2164 req->flags = SET_WIN_ID;
2167 case GWLP_HINSTANCE:
2168 req->flags = SET_WIN_INSTANCE;
2169 req->instance = wine_server_client_ptr( (void *)newval );
2172 req->flags = SET_WIN_UNICODE;
2173 req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
2176 req->flags = SET_WIN_USERDATA;
2177 req->user_data = newval;
2180 req->flags = SET_WIN_EXTRA;
2181 req->extra_offset = offset;
2182 req->extra_size = size;
2183 set_win_data( &req->extra_value, newval, size );
2185 if ((ok = !wine_server_call_err( req )))
2190 wndPtr->dwStyle = newval;
2191 retval = reply->old_style;
2194 wndPtr->dwExStyle = newval;
2195 retval = reply->old_ex_style;
2198 wndPtr->wIDmenu = newval;
2199 retval = reply->old_id;
2201 case GWLP_HINSTANCE:
2202 wndPtr->hInstance = (HINSTANCE)newval;
2203 retval = (ULONG_PTR)wine_server_get_ptr( reply->old_instance );
2208 wndPtr->userdata = newval;
2209 retval = reply->old_user_data;
2212 retval = get_win_data( (char *)wndPtr->wExtra + offset, size );
2213 set_win_data( (char *)wndPtr->wExtra + offset, newval, size );
2219 WIN_ReleasePtr( wndPtr );
2223 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2225 USER_Driver->pSetWindowStyle( hwnd, offset, &style );
2226 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2233 /**********************************************************************
2234 * GetWindowLong (USER.135)
2236 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2240 BOOL is_winproc = (offset == GWLP_WNDPROC);
2244 if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2246 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2249 if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2251 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
2254 * Some programs try to access last element from 16 bit
2255 * code using illegal offset value. Hopefully this is
2256 * what those programs really expect.
2258 if (wndPtr->cbWndExtra >= 4 && offset == wndPtr->cbWndExtra - sizeof(WORD))
2260 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
2261 ERR( "- replaced invalid offset %d with %d\n", offset, offset2 );
2266 WARN("Invalid offset %d\n", offset );
2267 WIN_ReleasePtr( wndPtr );
2268 SetLastError( ERROR_INVALID_INDEX );
2272 is_winproc = ((offset == DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG));
2273 WIN_ReleasePtr( wndPtr );
2276 retvalue = GetWindowLongA( WIN_Handle32(hwnd), offset );
2277 if (is_winproc) retvalue = (LONG_PTR)WINPROC_GetProc16( (WNDPROC)retvalue, FALSE );
2282 /**********************************************************************
2283 * GetWindowWord (USER32.@)
2285 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
2290 case GWLP_HINSTANCE:
2291 case GWLP_HWNDPARENT:
2296 WARN("Invalid offset %d\n", offset );
2297 SetLastError( ERROR_INVALID_INDEX );
2302 return WIN_GetWindowLong( hwnd, offset, sizeof(WORD), FALSE );
2306 /**********************************************************************
2307 * GetWindowLongA (USER32.@)
2309 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2311 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), FALSE );
2315 /**********************************************************************
2316 * GetWindowLongW (USER32.@)
2318 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2320 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), TRUE );
2324 /**********************************************************************
2325 * SetWindowLong (USER.136)
2327 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2330 BOOL is_winproc = (offset == GWLP_WNDPROC);
2332 if (offset == DWLP_DLGPROC)
2334 if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2336 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2339 if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2341 is_winproc = ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
2342 (wndPtr->flags & WIN_ISDIALOG));
2343 WIN_ReleasePtr( wndPtr );
2349 WNDPROC new_proc = WINPROC_AllocProc16( (WNDPROC16)newval );
2350 WNDPROC old_proc = (WNDPROC)SetWindowLongPtrA( WIN_Handle32(hwnd), offset, (LONG_PTR)new_proc );
2351 return (LONG)WINPROC_GetProc16( old_proc, FALSE );
2353 else return SetWindowLongA( WIN_Handle32(hwnd), offset, newval );
2357 /**********************************************************************
2358 * SetWindowWord (USER32.@)
2360 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
2365 case GWLP_HINSTANCE:
2366 case GWLP_HWNDPARENT:
2371 WARN("Invalid offset %d\n", offset );
2372 SetLastError( ERROR_INVALID_INDEX );
2377 return WIN_SetWindowLong( hwnd, offset, sizeof(WORD), newval, FALSE );
2381 /**********************************************************************
2382 * SetWindowLongA (USER32.@)
2384 * See SetWindowLongW.
2386 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2388 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, FALSE );
2392 /**********************************************************************
2393 * SetWindowLongW (USER32.@) Set window attribute
2395 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2396 * value in a window's extra memory.
2398 * The _hwnd_ parameter specifies the window. is the handle to a
2399 * window that has extra memory. The _newval_ parameter contains the
2400 * new attribute or extra memory value. If positive, the _offset_
2401 * parameter is the byte-addressed location in the window's extra
2402 * memory to set. If negative, _offset_ specifies the window
2403 * attribute to set, and should be one of the following values:
2405 * GWL_EXSTYLE The window's extended window style
2407 * GWL_STYLE The window's window style.
2409 * GWLP_WNDPROC Pointer to the window's window procedure.
2411 * GWLP_HINSTANCE The window's pplication instance handle.
2413 * GWLP_ID The window's identifier.
2415 * GWLP_USERDATA The window's user-specified data.
2417 * If the window is a dialog box, the _offset_ parameter can be one of
2418 * the following values:
2420 * DWLP_DLGPROC The address of the window's dialog box procedure.
2422 * DWLP_MSGRESULT The return value of a message
2423 * that the dialog box procedure processed.
2425 * DWLP_USER Application specific information.
2429 * If successful, returns the previous value located at _offset_. Otherwise,
2434 * Extra memory for a window class is specified by a nonzero cbWndExtra
2435 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2436 * time of class creation.
2438 * Using GWL_WNDPROC to set a new window procedure effectively creates
2439 * a window subclass. Use CallWindowProc() in the new windows procedure
2440 * to pass messages to the superclass's window procedure.
2442 * The user data is reserved for use by the application which created
2445 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2446 * instead, call the EnableWindow() function to change the window's
2449 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2450 * SetParent() instead.
2453 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2454 * it sends WM_STYLECHANGING before changing the settings
2455 * and WM_STYLECHANGED afterwards.
2456 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2458 LONG WINAPI SetWindowLongW(
2459 HWND hwnd, /* [in] window to alter */
2460 INT offset, /* [in] offset, in bytes, of location to alter */
2461 LONG newval /* [in] new value of location */
2463 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, TRUE );
2467 /*******************************************************************
2468 * GetWindowTextA (USER32.@)
2470 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2474 if (!lpString) return 0;
2476 if (WIN_IsCurrentProcess( hwnd ))
2477 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2479 /* when window belongs to other process, don't send a message */
2480 if (nMaxCount <= 0) return 0;
2481 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2482 get_server_window_text( hwnd, buffer, nMaxCount );
2483 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2484 lpString[nMaxCount-1] = 0;
2485 HeapFree( GetProcessHeap(), 0, buffer );
2486 return strlen(lpString);
2490 /*******************************************************************
2491 * InternalGetWindowText (USER32.@)
2493 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2497 if (nMaxCount <= 0) return 0;
2498 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2499 if (win == WND_DESKTOP) lpString[0] = 0;
2500 else if (win != WND_OTHER_PROCESS)
2502 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2503 else lpString[0] = 0;
2504 WIN_ReleasePtr( win );
2508 get_server_window_text( hwnd, lpString, nMaxCount );
2510 return strlenW(lpString);
2514 /*******************************************************************
2515 * GetWindowTextW (USER32.@)
2517 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2519 if (!lpString) return 0;
2521 if (WIN_IsCurrentProcess( hwnd ))
2522 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2524 /* when window belongs to other process, don't send a message */
2525 if (nMaxCount <= 0) return 0;
2526 get_server_window_text( hwnd, lpString, nMaxCount );
2527 return strlenW(lpString);
2531 /*******************************************************************
2532 * SetWindowTextA (USER32.@)
2533 * SetWindowText (USER32.@)
2535 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2537 if (is_broadcast(hwnd))
2539 SetLastError( ERROR_INVALID_PARAMETER );
2542 if (!WIN_IsCurrentProcess( hwnd ))
2543 WARN( "setting text %s of other process window %p should not use SendMessage\n",
2544 debugstr_a(lpString), hwnd );
2545 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2549 /*******************************************************************
2550 * SetWindowTextW (USER32.@)
2552 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2554 if (is_broadcast(hwnd))
2556 SetLastError( ERROR_INVALID_PARAMETER );
2559 if (!WIN_IsCurrentProcess( hwnd ))
2560 WARN( "setting text %s of other process window %p should not use SendMessage\n",
2561 debugstr_w(lpString), hwnd );
2562 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2566 /*******************************************************************
2567 * GetWindowTextLengthA (USER32.@)
2569 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2571 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2574 /*******************************************************************
2575 * GetWindowTextLengthW (USER32.@)
2577 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2579 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2583 /*******************************************************************
2584 * IsWindow (USER32.@)
2586 BOOL WINAPI IsWindow( HWND hwnd )
2591 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2592 if (ptr == WND_DESKTOP) return TRUE;
2594 if (ptr != WND_OTHER_PROCESS)
2596 WIN_ReleasePtr( ptr );
2600 /* check other processes */
2601 SERVER_START_REQ( get_window_info )
2603 req->handle = wine_server_user_handle( hwnd );
2604 ret = !wine_server_call_err( req );
2611 /***********************************************************************
2612 * GetWindowThreadProcessId (USER32.@)
2614 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2619 if (!(ptr = WIN_GetPtr( hwnd )))
2621 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2625 if (ptr != WND_OTHER_PROCESS && ptr != WND_DESKTOP)
2627 /* got a valid window */
2629 if (process) *process = GetCurrentProcessId();
2630 WIN_ReleasePtr( ptr );
2634 /* check other processes */
2635 SERVER_START_REQ( get_window_info )
2637 req->handle = wine_server_user_handle( hwnd );
2638 if (!wine_server_call_err( req ))
2640 tid = (DWORD)reply->tid;
2641 if (process) *process = (DWORD)reply->pid;
2649 /*****************************************************************
2650 * GetParent (USER32.@)
2652 HWND WINAPI GetParent( HWND hwnd )
2657 if (!(wndPtr = WIN_GetPtr( hwnd )))
2659 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2662 if (wndPtr == WND_DESKTOP) return 0;
2663 if (wndPtr == WND_OTHER_PROCESS)
2665 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2666 if (style & (WS_POPUP | WS_CHILD))
2668 SERVER_START_REQ( get_window_tree )
2670 req->handle = wine_server_user_handle( hwnd );
2671 if (!wine_server_call_err( req ))
2673 if (style & WS_POPUP) retvalue = wine_server_ptr_handle( reply->owner );
2674 else if (style & WS_CHILD) retvalue = wine_server_ptr_handle( reply->parent );
2682 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2683 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2684 WIN_ReleasePtr( wndPtr );
2690 /*****************************************************************
2691 * GetAncestor (USER32.@)
2693 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2696 HWND *list, ret = 0;
2701 if (!(win = WIN_GetPtr( hwnd )))
2703 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2706 if (win == WND_DESKTOP) return 0;
2707 if (win != WND_OTHER_PROCESS)
2710 WIN_ReleasePtr( win );
2712 else /* need to query the server */
2714 SERVER_START_REQ( get_window_tree )
2716 req->handle = wine_server_user_handle( hwnd );
2717 if (!wine_server_call_err( req )) ret = wine_server_ptr_handle( reply->parent );
2724 if (!(list = list_window_parents( hwnd ))) return 0;
2726 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2730 while (list[count]) count++;
2731 ret = list[count - 2]; /* get the one before the desktop */
2733 HeapFree( GetProcessHeap(), 0, list );
2737 if (is_desktop_window( hwnd )) return 0;
2738 ret = WIN_GetFullHandle( hwnd );
2741 HWND parent = GetParent( ret );
2751 /*****************************************************************
2752 * SetParent (USER32.@)
2754 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2757 HWND old_parent = 0;
2762 if (is_broadcast(hwnd) || is_broadcast(parent))
2764 SetLastError(ERROR_INVALID_PARAMETER);
2768 if (!parent) parent = GetDesktopWindow();
2769 else if (parent == HWND_MESSAGE) parent = get_hwnd_message_parent();
2770 else parent = WIN_GetFullHandle( parent );
2772 if (!IsWindow( parent ))
2774 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2778 /* Some applications try to set a child as a parent */
2779 if (IsChild(hwnd, parent))
2781 SetLastError( ERROR_INVALID_PARAMETER );
2785 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2786 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2788 /* Windows hides the window first, then shows it again
2789 * including the WM_SHOWWINDOW messages and all */
2790 was_visible = ShowWindow( hwnd, SW_HIDE );
2792 wndPtr = WIN_GetPtr( hwnd );
2793 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return 0;
2795 SERVER_START_REQ( set_parent )
2797 req->handle = wine_server_user_handle( hwnd );
2798 req->parent = wine_server_user_handle( parent );
2799 if ((ret = !wine_server_call( req )))
2801 old_parent = wine_server_ptr_handle( reply->old_parent );
2802 wndPtr->parent = parent = wine_server_ptr_handle( reply->full_parent );
2807 WIN_ReleasePtr( wndPtr );
2810 USER_Driver->pSetParent( full_handle, parent, old_parent );
2812 /* SetParent additionally needs to make hwnd the topmost window
2813 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2814 WM_WINDOWPOSCHANGED notification messages.
2816 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0,
2817 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2818 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2819 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2825 /*******************************************************************
2826 * IsChild (USER32.@)
2828 BOOL WINAPI IsChild( HWND parent, HWND child )
2830 HWND *list = list_window_parents( child );
2834 if (!list) return FALSE;
2835 parent = WIN_GetFullHandle( parent );
2836 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2837 ret = list[i] && list[i+1];
2838 HeapFree( GetProcessHeap(), 0, list );
2843 /***********************************************************************
2844 * IsWindowVisible (USER32.@)
2846 BOOL WINAPI IsWindowVisible( HWND hwnd )
2852 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2853 if (!(list = list_window_parents( hwnd ))) return TRUE;
2856 for (i = 0; list[i+1]; i++)
2857 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2858 retval = !list[i+1] && (list[i] == GetDesktopWindow()); /* top message window isn't visible */
2860 HeapFree( GetProcessHeap(), 0, list );
2865 /***********************************************************************
2866 * WIN_IsWindowDrawable
2868 * hwnd is drawable when it is visible, all parents are not
2869 * minimized, and it is itself not minimized unless we are
2870 * trying to draw its default class icon.
2872 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2877 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2879 if (!(style & WS_VISIBLE)) return FALSE;
2880 if ((style & WS_MINIMIZE) && icon && GetClassLongPtrW( hwnd, GCLP_HICON )) return FALSE;
2882 if (!(list = list_window_parents( hwnd ))) return TRUE;
2885 for (i = 0; list[i+1]; i++)
2886 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2888 retval = !list[i+1] && (list[i] == GetDesktopWindow()); /* top message window isn't visible */
2890 HeapFree( GetProcessHeap(), 0, list );
2895 /*******************************************************************
2896 * GetTopWindow (USER32.@)
2898 HWND WINAPI GetTopWindow( HWND hwnd )
2900 if (!hwnd) hwnd = GetDesktopWindow();
2901 return GetWindow( hwnd, GW_CHILD );
2905 /*******************************************************************
2906 * GetWindow (USER32.@)
2908 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2912 if (rel == GW_OWNER) /* this one may be available locally */
2914 WND *wndPtr = WIN_GetPtr( hwnd );
2917 SetLastError( ERROR_INVALID_HANDLE );
2920 if (wndPtr == WND_DESKTOP) return 0;
2921 if (wndPtr != WND_OTHER_PROCESS)
2923 retval = wndPtr->owner;
2924 WIN_ReleasePtr( wndPtr );
2927 /* else fall through to server call */
2930 SERVER_START_REQ( get_window_tree )
2932 req->handle = wine_server_user_handle( hwnd );
2933 if (!wine_server_call_err( req ))
2938 retval = wine_server_ptr_handle( reply->first_sibling );
2941 retval = wine_server_ptr_handle( reply->last_sibling );
2944 retval = wine_server_ptr_handle( reply->next_sibling );
2947 retval = wine_server_ptr_handle( reply->prev_sibling );
2950 retval = wine_server_ptr_handle( reply->owner );
2953 retval = wine_server_ptr_handle( reply->first_child );
2963 /*******************************************************************
2964 * ShowOwnedPopups (USER32.@)
2966 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2970 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2972 if (!win_array) return TRUE;
2974 while (win_array[count]) count++;
2975 while (--count >= 0)
2977 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2978 if (!(pWnd = WIN_GetPtr( win_array[count] ))) continue;
2979 if (pWnd == WND_OTHER_PROCESS) continue;
2982 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2984 WIN_ReleasePtr( pWnd );
2985 /* In Windows, ShowOwnedPopups(TRUE) generates
2986 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2987 * regardless of the state of the owner
2989 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_SHOWNORMAL, SW_PARENTOPENING);
2995 if (pWnd->dwStyle & WS_VISIBLE)
2997 WIN_ReleasePtr( pWnd );
2998 /* In Windows, ShowOwnedPopups(FALSE) generates
2999 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
3000 * regardless of the state of the owner
3002 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
3006 WIN_ReleasePtr( pWnd );
3008 HeapFree( GetProcessHeap(), 0, win_array );
3013 /*******************************************************************
3014 * GetLastActivePopup (USER32.@)
3016 HWND WINAPI GetLastActivePopup( HWND hwnd )
3020 SERVER_START_REQ( get_window_info )
3022 req->handle = wine_server_user_handle( hwnd );
3023 if (!wine_server_call_err( req )) retval = wine_server_ptr_handle( reply->last_active );
3030 /*******************************************************************
3033 * Build an array of the children of a given window. The array must be
3034 * freed with HeapFree. Returns NULL when no windows are found.
3036 HWND *WIN_ListChildren( HWND hwnd )
3040 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
3043 return list_window_children( 0, hwnd, NULL, 0 );
3047 /*******************************************************************
3048 * EnumWindows (USER32.@)
3050 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
3056 USER_CheckNotLock();
3058 /* We have to build a list of all windows first, to avoid */
3059 /* unpleasant side-effects, for instance if the callback */
3060 /* function changes the Z-order of the windows. */
3062 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
3064 /* Now call the callback function for every window */
3066 for (i = 0; list[i]; i++)
3068 /* Make sure that the window still exists */
3069 if (!IsWindow( list[i] )) continue;
3070 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
3072 HeapFree( GetProcessHeap(), 0, list );
3077 /**********************************************************************
3078 * EnumThreadWindows (USER32.@)
3080 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
3085 USER_CheckNotLock();
3087 if (!(list = list_window_children( 0, GetDesktopWindow(), NULL, id ))) return TRUE;
3089 /* Now call the callback function for every window */
3091 for (i = 0; list[i]; i++)
3092 if (!func( list[i], lParam )) break;
3093 HeapFree( GetProcessHeap(), 0, list );
3098 /***********************************************************************
3099 * EnumDesktopWindows (USER32.@)
3101 BOOL WINAPI EnumDesktopWindows( HDESK desktop, WNDENUMPROC func, LPARAM lparam )
3106 USER_CheckNotLock();
3108 if (!(list = list_window_children( desktop, 0, NULL, 0 ))) return TRUE;
3110 for (i = 0; list[i]; i++)
3111 if (!func( list[i], lparam )) break;
3112 HeapFree( GetProcessHeap(), 0, list );
3117 /**********************************************************************
3118 * WIN_EnumChildWindows
3120 * Helper function for EnumChildWindows().
3122 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
3127 for ( ; *list; list++)
3129 /* Make sure that the window still exists */
3130 if (!IsWindow( *list )) continue;
3131 /* Build children list first */
3132 childList = WIN_ListChildren( *list );
3134 ret = func( *list, lParam );
3138 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
3139 HeapFree( GetProcessHeap(), 0, childList );
3141 if (!ret) return FALSE;
3147 /**********************************************************************
3148 * EnumChildWindows (USER32.@)
3150 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
3155 USER_CheckNotLock();
3157 if (!(list = WIN_ListChildren( parent ))) return FALSE;
3158 ret = WIN_EnumChildWindows( list, func, lParam );
3159 HeapFree( GetProcessHeap(), 0, list );
3164 /*******************************************************************
3165 * AnyPopup (USER.52)
3167 BOOL16 WINAPI AnyPopup16(void)
3173 /*******************************************************************
3174 * AnyPopup (USER32.@)
3176 BOOL WINAPI AnyPopup(void)
3180 HWND *list = WIN_ListChildren( GetDesktopWindow() );
3182 if (!list) return FALSE;
3183 for (i = 0; list[i]; i++)
3185 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
3187 retvalue = (list[i] != 0);
3188 HeapFree( GetProcessHeap(), 0, list );
3193 /*******************************************************************
3194 * FlashWindow (USER32.@)
3196 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3200 TRACE("%p\n", hWnd);
3202 if (IsIconic( hWnd ))
3204 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3206 wndPtr = WIN_GetPtr(hWnd);
3207 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
3208 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3210 wndPtr->flags |= WIN_NCACTIVATED;
3214 wndPtr->flags &= ~WIN_NCACTIVATED;
3216 WIN_ReleasePtr( wndPtr );
3223 wndPtr = WIN_GetPtr(hWnd);
3224 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
3225 hWnd = wndPtr->hwndSelf; /* make it a full handle */
3227 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3228 else wparam = (hWnd == GetForegroundWindow());
3230 WIN_ReleasePtr( wndPtr );
3231 SendMessageW( hWnd, WM_NCACTIVATE, wparam, 0 );
3236 /*******************************************************************
3237 * FlashWindowEx (USER32.@)
3239 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
3241 FIXME("%p\n", pfwi);
3245 /*******************************************************************
3246 * GetWindowContextHelpId (USER32.@)
3248 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3251 WND *wnd = WIN_GetPtr( hwnd );
3252 if (!wnd || wnd == WND_DESKTOP) return 0;
3253 if (wnd == WND_OTHER_PROCESS)
3255 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3258 retval = wnd->helpContext;
3259 WIN_ReleasePtr( wnd );
3264 /*******************************************************************
3265 * SetWindowContextHelpId (USER32.@)
3267 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3269 WND *wnd = WIN_GetPtr( hwnd );
3270 if (!wnd || wnd == WND_DESKTOP) return FALSE;
3271 if (wnd == WND_OTHER_PROCESS)
3273 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3276 wnd->helpContext = id;
3277 WIN_ReleasePtr( wnd );
3282 /*******************************************************************
3283 * DragDetect (USER32.@)
3285 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3289 WORD wDragWidth = GetSystemMetrics(SM_CXDRAG);
3290 WORD wDragHeight= GetSystemMetrics(SM_CYDRAG);
3292 rect.left = pt.x - wDragWidth;
3293 rect.right = pt.x + wDragWidth;
3295 rect.top = pt.y - wDragHeight;
3296 rect.bottom = pt.y + wDragHeight;
3302 while (PeekMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ))
3304 if( msg.message == WM_LBUTTONUP )
3309 if( msg.message == WM_MOUSEMOVE )
3312 tmp.x = (short)LOWORD(msg.lParam);
3313 tmp.y = (short)HIWORD(msg.lParam);
3314 if( !PtInRect( &rect, tmp ))
3326 /******************************************************************************
3327 * GetWindowModuleFileNameA (USER32.@)
3329 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR module, UINT size )
3334 TRACE( "%p, %p, %u\n", hwnd, module, size );
3336 win = WIN_GetPtr( hwnd );
3337 if (!win || win == WND_OTHER_PROCESS || win == WND_DESKTOP)
3339 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
3342 hinst = win->hInstance;
3343 WIN_ReleasePtr( win );
3345 return GetModuleFileNameA( hinst, module, size );
3348 /******************************************************************************
3349 * GetWindowModuleFileNameW (USER32.@)
3351 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR module, UINT size )
3356 TRACE( "%p, %p, %u\n", hwnd, module, size );
3358 win = WIN_GetPtr( hwnd );
3359 if (!win || win == WND_OTHER_PROCESS || win == WND_DESKTOP)
3361 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
3364 hinst = win->hInstance;
3365 WIN_ReleasePtr( win );
3367 return GetModuleFileNameW( hinst, module, size );
3370 /******************************************************************************
3371 * GetWindowInfo (USER32.@)
3373 * Note: tests show that Windows doesn't check cbSize of the structure.
3375 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3377 if (!pwi) return FALSE;
3378 if (!IsWindow(hwnd)) return FALSE;
3380 GetWindowRect(hwnd, &pwi->rcWindow);
3381 GetClientRect(hwnd, &pwi->rcClient);
3382 /* translate to screen coordinates */
3383 MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3385 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3386 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3387 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3389 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3390 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3392 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3393 pwi->wCreatorVersion = 0x0400;
3398 /******************************************************************************
3399 * SwitchDesktop (USER32.@)
3401 * NOTES: Sets the current input or interactive desktop.
3403 BOOL WINAPI SwitchDesktop( HDESK hDesktop)
3405 FIXME("SwitchDesktop(hwnd %p) stub!\n", hDesktop);
3409 /*****************************************************************************
3410 * SetLayeredWindowAttributes (USER32.@)
3412 BOOL WINAPI SetLayeredWindowAttributes( HWND hwnd, COLORREF key, BYTE alpha, DWORD flags )
3416 TRACE("(%p,%08x,%d,%x): stub!\n", hwnd, key, alpha, flags);
3418 SERVER_START_REQ( set_window_layered_info )
3420 req->handle = wine_server_user_handle( hwnd );
3421 req->color_key = key;
3424 ret = !wine_server_call_err( req );
3428 if (ret) USER_Driver->pSetLayeredWindowAttributes( hwnd, key, alpha, flags );
3434 /*****************************************************************************
3435 * GetLayeredWindowAttributes (USER32.@)
3437 BOOL WINAPI GetLayeredWindowAttributes( HWND hwnd, COLORREF *key, BYTE *alpha, DWORD *flags )
3441 SERVER_START_REQ( get_window_layered_info )
3443 req->handle = wine_server_user_handle( hwnd );
3444 if ((ret = !wine_server_call_err( req )))
3446 if (key) *key = reply->color_key;
3447 if (alpha) *alpha = reply->alpha;
3448 if (flags) *flags = reply->flags;
3457 /*****************************************************************************
3458 * UpdateLayeredWindowIndirect (USER32.@)
3460 BOOL WINAPI UpdateLayeredWindowIndirect( HWND hwnd, const UPDATELAYEREDWINDOWINFO *info )
3464 if (!(info->dwFlags & ULW_EX_NORESIZE) && (info->pptDst || info->psize))
3466 int x = 0, y = 0, cx = 0, cy = 0;
3467 DWORD flags = SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW | SWP_NOSENDCHANGING;
3471 x = info->pptDst->x;
3472 y = info->pptDst->y;
3473 flags &= ~SWP_NOMOVE;
3477 cx = info->psize->cx;
3478 cy = info->psize->cy;
3479 flags &= ~SWP_NOSIZE;
3481 TRACE( "moving window %p pos %d,%d %dx%x\n", hwnd, x, y, cx, cy );
3482 SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
3488 HDC hdc = GetDCEx( hwnd, 0, DCX_CACHE );
3494 GetClientRect( hwnd, &rect );
3497 x = info->pptSrc->x;
3498 y = info->pptSrc->y;
3500 /* FIXME: intersect rect with info->prcDirty */
3501 TRACE( "copying window %p pos %d,%d\n", hwnd, x, y );
3502 BitBlt( hdc, rect.left, rect.top, rect.right, rect.bottom,
3503 info->hdcSrc, rect.left + x, rect.top + y, SRCCOPY );
3504 ReleaseDC( hwnd, hdc );
3508 if (info->pblend && !(info->dwFlags & ULW_OPAQUE)) alpha = info->pblend->SourceConstantAlpha;
3509 TRACE( "setting window %p alpha %u\n", hwnd, alpha );
3510 USER_Driver->pSetLayeredWindowAttributes( hwnd, info->crKey, alpha,
3511 info->dwFlags & (LWA_ALPHA | LWA_COLORKEY) );
3516 /*****************************************************************************
3517 * UpdateLayeredWindow (USER32.@)
3519 BOOL WINAPI UpdateLayeredWindow( HWND hwnd, HDC hdcDst, POINT *pptDst, SIZE *psize,
3520 HDC hdcSrc, POINT *pptSrc, COLORREF crKey, BLENDFUNCTION *pblend,
3523 UPDATELAYEREDWINDOWINFO info;
3525 info.cbSize = sizeof(info);
3526 info.hdcDst = hdcDst;
3527 info.pptDst = pptDst;
3529 info.hdcSrc = hdcSrc;
3530 info.pptSrc = pptSrc;
3532 info.pblend = pblend;
3533 info.dwFlags = dwFlags;
3534 info.prcDirty = NULL;
3535 return UpdateLayeredWindowIndirect( hwnd, &info );
3538 /* 64bit versions */
3540 #ifdef GetWindowLongPtrW
3541 #undef GetWindowLongPtrW
3544 #ifdef GetWindowLongPtrA
3545 #undef GetWindowLongPtrA
3548 #ifdef SetWindowLongPtrW
3549 #undef SetWindowLongPtrW
3552 #ifdef SetWindowLongPtrA
3553 #undef SetWindowLongPtrA
3556 /*****************************************************************************
3557 * GetWindowLongPtrW (USER32.@)
3559 LONG_PTR WINAPI GetWindowLongPtrW( HWND hwnd, INT offset )
3561 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), TRUE );
3564 /*****************************************************************************
3565 * GetWindowLongPtrA (USER32.@)
3567 LONG_PTR WINAPI GetWindowLongPtrA( HWND hwnd, INT offset )
3569 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), FALSE );
3572 /*****************************************************************************
3573 * SetWindowLongPtrW (USER32.@)
3575 LONG_PTR WINAPI SetWindowLongPtrW( HWND hwnd, INT offset, LONG_PTR newval )
3577 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, TRUE );
3580 /*****************************************************************************
3581 * SetWindowLongPtrA (USER32.@)
3583 LONG_PTR WINAPI SetWindowLongPtrA( HWND hwnd, INT offset, LONG_PTR newval )
3585 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, FALSE );