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 /***********************************************************************
96 HANDLE alloc_user_handle( struct user_object *ptr, enum user_obj_type type )
100 SERVER_START_REQ( alloc_user_handle )
102 if (!wine_server_call_err( req )) handle = wine_server_ptr_handle( reply->handle );
108 UINT index = USER_HANDLE_TO_INDEX( handle );
110 assert( index < NB_USER_HANDLES );
111 ptr->handle = handle;
113 user_handles[index] = ptr;
119 /***********************************************************************
120 * get_user_handle_ptr
122 void *get_user_handle_ptr( HANDLE handle, enum user_obj_type type )
124 struct user_object *ptr;
125 WORD index = USER_HANDLE_TO_INDEX( handle );
127 if (index >= NB_USER_HANDLES) return NULL;
130 if ((ptr = user_handles[index]))
132 if (ptr->type == type &&
133 ((UINT)(UINT_PTR)ptr->handle == (UINT)(UINT_PTR)handle ||
134 !HIWORD(handle) || HIWORD(handle) == 0xffff))
138 else ptr = OBJ_OTHER_PROCESS;
144 /***********************************************************************
145 * release_user_handle_ptr
147 void release_user_handle_ptr( void *ptr )
153 /***********************************************************************
156 void *free_user_handle( HANDLE handle, enum user_obj_type type )
158 struct user_object *ptr;
159 WORD index = USER_HANDLE_TO_INDEX( handle );
161 if ((ptr = get_user_handle_ptr( handle, type )) && ptr != OBJ_OTHER_PROCESS)
163 SERVER_START_REQ( free_user_handle )
165 req->handle = wine_server_user_handle( handle );
166 if (!wine_server_call( req )) user_handles[index] = NULL;
170 release_user_handle_ptr( ptr );
176 /***********************************************************************
177 * create_window_handle
179 * Create a window handle with the server.
181 static WND *create_window_handle( HWND parent, HWND owner, LPCWSTR name,
182 HINSTANCE instance, BOOL unicode )
186 HWND handle = 0, full_parent = 0, full_owner = 0;
187 struct tagCLASS *class = NULL;
190 /* if 16-bit instance, map to module handle */
191 if (instance && !HIWORD(instance))
192 instance = HINSTANCE_32(GetExePtr(HINSTANCE_16(instance)));
194 SERVER_START_REQ( create_window )
196 req->parent = wine_server_user_handle( parent );
197 req->owner = wine_server_user_handle( owner );
198 req->instance = wine_server_client_ptr( instance );
199 if (!(req->atom = get_int_atom_value( name )) && name)
200 wine_server_add_data( req, name, strlenW(name)*sizeof(WCHAR) );
201 if (!wine_server_call_err( req ))
203 handle = wine_server_ptr_handle( reply->handle );
204 full_parent = wine_server_ptr_handle( reply->parent );
205 full_owner = wine_server_ptr_handle( reply->owner );
206 extra_bytes = reply->extra;
207 class = wine_server_get_ptr( reply->class_ptr );
214 WARN( "error %d creating window\n", GetLastError() );
218 if (!(win = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
219 sizeof(WND) + extra_bytes - sizeof(win->wExtra) )))
221 SERVER_START_REQ( destroy_window )
223 req->handle = wine_server_user_handle( handle );
224 wine_server_call( req );
227 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
231 if (!parent) /* if parent is 0 we don't have a desktop window yet */
233 struct user_thread_info *thread_info = get_user_thread_info();
235 if (name == (LPCWSTR)DESKTOP_CLASS_ATOM)
237 if (!thread_info->top_window) thread_info->top_window = full_parent ? full_parent : handle;
238 else assert( full_parent == thread_info->top_window );
239 if (full_parent && !USER_Driver->pCreateDesktopWindow( thread_info->top_window ))
240 ERR( "failed to create desktop window\n" );
242 else /* HWND_MESSAGE parent */
244 if (!thread_info->msg_window && !full_parent) thread_info->msg_window = handle;
250 index = USER_HANDLE_TO_INDEX(handle);
251 assert( index < NB_USER_HANDLES );
252 user_handles[index] = win;
253 win->obj.handle = handle;
254 win->obj.type = USER_WINDOW;
255 win->parent = full_parent;
256 win->owner = full_owner;
258 win->winproc = get_class_winproc( class );
259 win->cbWndExtra = extra_bytes;
260 if (WINPROC_IsUnicode( win->winproc, unicode )) win->flags |= WIN_ISUNICODE;
265 /***********************************************************************
268 * Free a window handle.
270 static void free_window_handle( HWND hwnd )
272 struct user_object *ptr;
273 WORD index = USER_HANDLE_TO_INDEX(hwnd);
275 if ((ptr = get_user_handle_ptr( hwnd, USER_WINDOW )) && ptr != OBJ_OTHER_PROCESS)
277 SERVER_START_REQ( destroy_window )
279 req->handle = wine_server_user_handle( hwnd );
280 if (!wine_server_call_err( req )) user_handles[index] = NULL;
284 release_user_handle_ptr( ptr );
285 HeapFree( GetProcessHeap(), 0, ptr );
290 /*******************************************************************
291 * list_window_children
293 * Build an array of the children of a given window. The array must be
294 * freed with HeapFree. Returns NULL when no windows are found.
296 static HWND *list_window_children( HDESK desktop, HWND hwnd, LPCWSTR class, DWORD tid )
300 ATOM atom = get_int_atom_value( class );
302 /* empty class is not the same as NULL class */
303 if (!atom && class && !class[0]) return NULL;
309 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
311 SERVER_START_REQ( get_window_children )
313 req->desktop = wine_server_obj_handle( desktop );
314 req->parent = wine_server_user_handle( hwnd );
317 if (!atom && class) wine_server_add_data( req, class, strlenW(class)*sizeof(WCHAR) );
318 wine_server_set_reply( req, list, (size-1) * sizeof(user_handle_t) );
319 if (!wine_server_call( req )) count = reply->count;
322 if (count && count < size)
324 /* start from the end since HWND is potentially larger than user_handle_t */
325 for (i = count - 1; i >= 0; i--)
326 list[i] = wine_server_ptr_handle( ((user_handle_t *)list)[i] );
330 HeapFree( GetProcessHeap(), 0, list );
332 size = count + 1; /* restart with a large enough buffer */
338 /*******************************************************************
339 * list_window_parents
341 * Build an array of all parents of a given window, starting with
342 * the immediate parent. The array must be freed with HeapFree.
344 static HWND *list_window_parents( HWND hwnd )
348 int i, pos = 0, size = 16, count = 0;
350 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
355 if (!(win = WIN_GetPtr( current ))) goto empty;
356 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
357 if (win == WND_DESKTOP)
359 if (!pos) goto empty;
363 list[pos] = current = win->parent;
364 WIN_ReleasePtr( win );
365 if (!current) return list;
366 if (++pos == size - 1)
368 /* need to grow the list */
369 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
370 if (!new_list) goto empty;
376 /* at least one parent belongs to another process, have to query the server */
381 SERVER_START_REQ( get_window_parents )
383 req->handle = wine_server_user_handle( hwnd );
384 wine_server_set_reply( req, list, (size-1) * sizeof(user_handle_t) );
385 if (!wine_server_call( req )) count = reply->count;
388 if (!count) goto empty;
391 /* start from the end since HWND is potentially larger than user_handle_t */
392 for (i = count - 1; i >= 0; i--)
393 list[i] = wine_server_ptr_handle( ((user_handle_t *)list)[i] );
397 HeapFree( GetProcessHeap(), 0, list );
399 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
403 HeapFree( GetProcessHeap(), 0, list );
408 /*******************************************************************
411 static void send_parent_notify( HWND hwnd, UINT msg )
413 if ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_CHILD | WS_POPUP)) == WS_CHILD &&
414 !(GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY))
416 HWND parent = GetParent(hwnd);
417 if (parent && parent != GetDesktopWindow())
418 SendMessageW( parent, WM_PARENTNOTIFY,
419 MAKEWPARAM( msg, GetWindowLongPtrW( hwnd, GWLP_ID )), (LPARAM)hwnd );
424 /*******************************************************************
425 * get_server_window_text
427 * Retrieve the window text from the server.
429 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
433 SERVER_START_REQ( get_window_text )
435 req->handle = wine_server_user_handle( hwnd );
436 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
437 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
440 text[len / sizeof(WCHAR)] = 0;
444 /*******************************************************************
445 * get_hwnd_message_parent
447 * Return the parent for HWND_MESSAGE windows.
449 HWND get_hwnd_message_parent(void)
451 struct user_thread_info *thread_info = get_user_thread_info();
453 if (!thread_info->msg_window) GetDesktopWindow(); /* trigger creation */
454 return thread_info->msg_window;
458 /*******************************************************************
461 * Check if window is the desktop or the HWND_MESSAGE top parent.
463 BOOL is_desktop_window( HWND hwnd )
465 struct user_thread_info *thread_info = get_user_thread_info();
467 if (!hwnd) return FALSE;
468 if (hwnd == thread_info->top_window) return TRUE;
469 if (hwnd == thread_info->msg_window) return TRUE;
471 if (!HIWORD(hwnd) || HIWORD(hwnd) == 0xffff)
473 if (LOWORD(thread_info->top_window) == LOWORD(hwnd)) return TRUE;
474 if (LOWORD(thread_info->msg_window) == LOWORD(hwnd)) return TRUE;
480 /***********************************************************************
483 * Return a pointer to the WND structure if local to the process,
484 * or WND_OTHER_PROCESS if handle may be valid in other process.
485 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
487 WND *WIN_GetPtr( HWND hwnd )
491 if ((ptr = get_user_handle_ptr( hwnd, USER_WINDOW )) == WND_OTHER_PROCESS)
493 if (is_desktop_window( hwnd )) ptr = WND_DESKTOP;
499 /***********************************************************************
500 * WIN_IsCurrentProcess
502 * Check whether a given window belongs to the current process (and return the full handle).
504 HWND WIN_IsCurrentProcess( HWND hwnd )
509 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
510 ret = ptr->obj.handle;
511 WIN_ReleasePtr( ptr );
516 /***********************************************************************
517 * WIN_IsCurrentThread
519 * Check whether a given window belongs to the current thread (and return the full handle).
521 HWND WIN_IsCurrentThread( HWND hwnd )
526 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
527 if (ptr->tid == GetCurrentThreadId()) ret = ptr->obj.handle;
528 WIN_ReleasePtr( ptr );
533 /***********************************************************************
536 * Convert a 16-bit window handle to a full 32-bit handle.
538 HWND WIN_Handle32( HWND16 hwnd16 )
541 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
543 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
544 /* do sign extension for -2 and -3 */
545 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
547 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
549 if (ptr == WND_DESKTOP)
551 if (LOWORD(hwnd) == LOWORD(GetDesktopWindow())) return GetDesktopWindow();
552 else return get_hwnd_message_parent();
555 if (ptr != WND_OTHER_PROCESS)
557 hwnd = ptr->obj.handle;
558 WIN_ReleasePtr( ptr );
560 else /* may belong to another process */
562 SERVER_START_REQ( get_window_info )
564 req->handle = wine_server_user_handle( hwnd );
565 if (!wine_server_call_err( req )) hwnd = wine_server_ptr_handle( reply->full_handle );
573 /***********************************************************************
576 * Change the owner of a window.
578 HWND WIN_SetOwner( HWND hwnd, HWND owner )
580 WND *win = WIN_GetPtr( hwnd );
583 if (!win || win == WND_DESKTOP) return 0;
584 if (win == WND_OTHER_PROCESS)
586 if (IsWindow(hwnd)) ERR( "cannot set owner %p on other process window %p\n", owner, hwnd );
589 SERVER_START_REQ( set_window_owner )
591 req->handle = wine_server_user_handle( hwnd );
592 req->owner = wine_server_user_handle( owner );
593 if (!wine_server_call( req ))
595 win->owner = wine_server_ptr_handle( reply->full_owner );
596 ret = wine_server_ptr_handle( reply->prev_owner );
600 WIN_ReleasePtr( win );
605 /***********************************************************************
608 * Change the style of a window.
610 ULONG WIN_SetStyle( HWND hwnd, ULONG set_bits, ULONG clear_bits )
614 WND *win = WIN_GetPtr( hwnd );
616 if (!win || win == WND_DESKTOP) return 0;
617 if (win == WND_OTHER_PROCESS)
620 ERR( "cannot set style %x/%x on other process window %p\n",
621 set_bits, clear_bits, hwnd );
624 style.styleOld = win->dwStyle;
625 style.styleNew = (win->dwStyle | set_bits) & ~clear_bits;
626 if (style.styleNew == style.styleOld)
628 WIN_ReleasePtr( win );
629 return style.styleNew;
631 SERVER_START_REQ( set_window_info )
633 req->handle = wine_server_user_handle( hwnd );
634 req->flags = SET_WIN_STYLE;
635 req->style = style.styleNew;
636 req->extra_offset = -1;
637 if ((ok = !wine_server_call( req )))
639 style.styleOld = reply->old_style;
640 win->dwStyle = style.styleNew;
644 WIN_ReleasePtr( win );
647 USER_Driver->pSetWindowStyle( hwnd, GWL_STYLE, &style );
648 if ((style.styleOld ^ style.styleNew) & WS_VISIBLE) invalidate_dce( hwnd, NULL );
650 return style.styleOld;
654 /***********************************************************************
657 * Get the window and client rectangles.
659 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
661 WND *win = WIN_GetPtr( hwnd );
664 if (!win) return FALSE;
665 if (win == WND_DESKTOP)
668 rect.left = rect.top = 0;
669 if (hwnd == get_hwnd_message_parent())
676 rect.right = GetSystemMetrics(SM_CXSCREEN);
677 rect.bottom = GetSystemMetrics(SM_CYSCREEN);
679 if (rectWindow) *rectWindow = rect;
680 if (rectClient) *rectClient = rect;
682 else if (win == WND_OTHER_PROCESS)
684 SERVER_START_REQ( get_window_rectangles )
686 req->handle = wine_server_user_handle( hwnd );
687 if ((ret = !wine_server_call( req )))
691 rectWindow->left = reply->window.left;
692 rectWindow->top = reply->window.top;
693 rectWindow->right = reply->window.right;
694 rectWindow->bottom = reply->window.bottom;
698 rectClient->left = reply->client.left;
699 rectClient->top = reply->client.top;
700 rectClient->right = reply->client.right;
701 rectClient->bottom = reply->client.bottom;
709 if (rectWindow) *rectWindow = win->rectWindow;
710 if (rectClient) *rectClient = win->rectClient;
711 WIN_ReleasePtr( win );
717 /***********************************************************************
720 * Destroy storage associated to a window. "Internals" p.358
722 LRESULT WIN_DestroyWindow( HWND hwnd )
726 HMENU menu = 0, sys_menu;
729 TRACE("%p\n", hwnd );
731 /* free child windows */
732 if ((list = WIN_ListChildren( hwnd )))
735 for (i = 0; list[i]; i++)
737 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
738 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
740 HeapFree( GetProcessHeap(), 0, list );
743 /* Unlink now so we won't bother with the children later on */
744 SERVER_START_REQ( set_parent )
746 req->handle = wine_server_user_handle( hwnd );
748 wine_server_call( req );
753 * Send the WM_NCDESTROY to the window being destroyed.
755 SendMessageW( hwnd, WM_NCDESTROY, 0, 0 );
757 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
759 /* free resources associated with the window */
761 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
762 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
763 menu = (HMENU)wndPtr->wIDmenu;
764 sys_menu = wndPtr->hSysMenu;
765 free_dce( wndPtr->dce, hwnd );
767 icon_title = wndPtr->icon_title;
768 WIN_ReleasePtr( wndPtr );
770 if (icon_title) DestroyWindow( icon_title );
771 if (menu) DestroyMenu( menu );
772 if (sys_menu) DestroyMenu( sys_menu );
774 USER_Driver->pDestroyWindow( hwnd );
776 free_window_handle( hwnd );
781 /***********************************************************************
782 * destroy_thread_window
784 * Destroy a window upon exit of its thread.
786 static void destroy_thread_window( HWND hwnd )
790 HMENU menu = 0, sys_menu = 0;
793 /* free child windows */
795 if ((list = WIN_ListChildren( hwnd )))
798 for (i = 0; list[i]; i++)
800 if (WIN_IsCurrentThread( list[i] )) destroy_thread_window( list[i] );
801 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
803 HeapFree( GetProcessHeap(), 0, list );
806 /* destroy the client-side storage */
808 index = USER_HANDLE_TO_INDEX(hwnd);
809 if (index >= NB_USER_HANDLES) return;
811 if ((wndPtr = user_handles[index]))
813 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD) menu = (HMENU)wndPtr->wIDmenu;
814 sys_menu = wndPtr->hSysMenu;
815 free_dce( wndPtr->dce, hwnd );
816 user_handles[index] = NULL;
820 HeapFree( GetProcessHeap(), 0, wndPtr );
821 if (menu) DestroyMenu( menu );
822 if (sys_menu) DestroyMenu( sys_menu );
826 /***********************************************************************
827 * destroy_thread_child_windows
829 * Destroy child windows upon exit of its thread.
831 static void destroy_thread_child_windows( HWND hwnd )
836 if (WIN_IsCurrentThread( hwnd ))
838 destroy_thread_window( hwnd );
840 else if ((list = WIN_ListChildren( hwnd )))
842 for (i = 0; list[i]; i++) destroy_thread_child_windows( list[i] );
843 HeapFree( GetProcessHeap(), 0, list );
848 /***********************************************************************
849 * WIN_DestroyThreadWindows
851 * Destroy all children of 'wnd' owned by the current thread.
853 void WIN_DestroyThreadWindows( HWND hwnd )
858 if (!(list = WIN_ListChildren( hwnd ))) return;
860 /* reset owners of top-level windows */
861 for (i = 0; list[i]; i++)
863 if (!WIN_IsCurrentThread( list[i] ))
865 HWND owner = GetWindow( list[i], GW_OWNER );
866 if (owner && WIN_IsCurrentThread( owner )) WIN_SetOwner( list[i], 0 );
870 for (i = 0; list[i]; i++) destroy_thread_child_windows( list[i] );
871 HeapFree( GetProcessHeap(), 0, list );
875 /***********************************************************************
878 * Fix the coordinates - Helper for WIN_CreateWindowEx.
879 * returns default show mode in sw.
881 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
883 #define IS_DEFAULT(x) ((x) == CW_USEDEFAULT || (x) == CW_USEDEFAULT16)
886 if (cs->dwExStyle & WS_EX_MDICHILD)
890 MDI_CalcDefaultChildPos(cs->hwndParent, -1, pos, 0, &id);
891 if (!(cs->style & WS_POPUP)) cs->hMenu = ULongToHandle(id);
893 TRACE("MDI child id %04x\n", id);
896 if (cs->style & (WS_CHILD | WS_POPUP))
898 if (cs->dwExStyle & WS_EX_MDICHILD)
900 if (IS_DEFAULT(cs->x))
905 if (IS_DEFAULT(cs->cx) || !cs->cx) cs->cx = pos[1].x;
906 if (IS_DEFAULT(cs->cy) || !cs->cy) cs->cy = pos[1].y;
910 if (IS_DEFAULT(cs->x)) cs->x = cs->y = 0;
911 if (IS_DEFAULT(cs->cx)) cs->cx = cs->cy = 0;
914 else /* overlapped window */
917 MONITORINFO mon_info;
920 if (!IS_DEFAULT(cs->x) && !IS_DEFAULT(cs->cx) && !IS_DEFAULT(cs->cy)) return;
922 monitor = MonitorFromWindow( cs->hwndParent, MONITOR_DEFAULTTOPRIMARY );
923 mon_info.cbSize = sizeof(mon_info);
924 GetMonitorInfoW( monitor, &mon_info );
925 GetStartupInfoW( &info );
927 if (IS_DEFAULT(cs->x))
929 if (!IS_DEFAULT(cs->y)) *sw = cs->y;
930 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : mon_info.rcWork.left;
931 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : mon_info.rcWork.top;
934 if (IS_DEFAULT(cs->cx))
936 if (info.dwFlags & STARTF_USESIZE)
938 cs->cx = info.dwXSize;
939 cs->cy = info.dwYSize;
943 cs->cx = (mon_info.rcWork.right - mon_info.rcWork.left) * 3 / 4 - cs->x;
944 cs->cy = (mon_info.rcWork.bottom - mon_info.rcWork.top) * 3 / 4 - cs->y;
947 /* neither x nor cx are default. Check the y values .
948 * In the trace we see Outlook and Outlook Express using
949 * cy set to CW_USEDEFAULT when opening the address book.
951 else if (IS_DEFAULT(cs->cy))
953 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
954 cs->cy = (mon_info.rcWork.bottom - mon_info.rcWork.top) * 3 / 4 - cs->y;
960 /***********************************************************************
963 static void dump_window_styles( DWORD style, DWORD exstyle )
966 if(style & WS_POPUP) TRACE(" WS_POPUP");
967 if(style & WS_CHILD) TRACE(" WS_CHILD");
968 if(style & WS_MINIMIZE) TRACE(" WS_MINIMIZE");
969 if(style & WS_VISIBLE) TRACE(" WS_VISIBLE");
970 if(style & WS_DISABLED) TRACE(" WS_DISABLED");
971 if(style & WS_CLIPSIBLINGS) TRACE(" WS_CLIPSIBLINGS");
972 if(style & WS_CLIPCHILDREN) TRACE(" WS_CLIPCHILDREN");
973 if(style & WS_MAXIMIZE) TRACE(" WS_MAXIMIZE");
974 if((style & WS_CAPTION) == WS_CAPTION) TRACE(" WS_CAPTION");
977 if(style & WS_BORDER) TRACE(" WS_BORDER");
978 if(style & WS_DLGFRAME) TRACE(" WS_DLGFRAME");
980 if(style & WS_VSCROLL) TRACE(" WS_VSCROLL");
981 if(style & WS_HSCROLL) TRACE(" WS_HSCROLL");
982 if(style & WS_SYSMENU) TRACE(" WS_SYSMENU");
983 if(style & WS_THICKFRAME) TRACE(" WS_THICKFRAME");
984 if (style & WS_CHILD)
986 if(style & WS_GROUP) TRACE(" WS_GROUP");
987 if(style & WS_TABSTOP) TRACE(" WS_TABSTOP");
991 if(style & WS_MINIMIZEBOX) TRACE(" WS_MINIMIZEBOX");
992 if(style & WS_MAXIMIZEBOX) TRACE(" WS_MAXIMIZEBOX");
995 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
996 #define DUMPED_STYLES \
1016 if(style & ~DUMPED_STYLES) TRACE(" %08lx", style & ~DUMPED_STYLES);
1018 #undef DUMPED_STYLES
1020 TRACE( "exstyle:" );
1021 if(exstyle & WS_EX_DLGMODALFRAME) TRACE(" WS_EX_DLGMODALFRAME");
1022 if(exstyle & WS_EX_DRAGDETECT) TRACE(" WS_EX_DRAGDETECT");
1023 if(exstyle & WS_EX_NOPARENTNOTIFY) TRACE(" WS_EX_NOPARENTNOTIFY");
1024 if(exstyle & WS_EX_TOPMOST) TRACE(" WS_EX_TOPMOST");
1025 if(exstyle & WS_EX_ACCEPTFILES) TRACE(" WS_EX_ACCEPTFILES");
1026 if(exstyle & WS_EX_TRANSPARENT) TRACE(" WS_EX_TRANSPARENT");
1027 if(exstyle & WS_EX_MDICHILD) TRACE(" WS_EX_MDICHILD");
1028 if(exstyle & WS_EX_TOOLWINDOW) TRACE(" WS_EX_TOOLWINDOW");
1029 if(exstyle & WS_EX_WINDOWEDGE) TRACE(" WS_EX_WINDOWEDGE");
1030 if(exstyle & WS_EX_CLIENTEDGE) TRACE(" WS_EX_CLIENTEDGE");
1031 if(exstyle & WS_EX_CONTEXTHELP) TRACE(" WS_EX_CONTEXTHELP");
1032 if(exstyle & WS_EX_RIGHT) TRACE(" WS_EX_RIGHT");
1033 if(exstyle & WS_EX_RTLREADING) TRACE(" WS_EX_RTLREADING");
1034 if(exstyle & WS_EX_LEFTSCROLLBAR) TRACE(" WS_EX_LEFTSCROLLBAR");
1035 if(exstyle & WS_EX_CONTROLPARENT) TRACE(" WS_EX_CONTROLPARENT");
1036 if(exstyle & WS_EX_STATICEDGE) TRACE(" WS_EX_STATICEDGE");
1037 if(exstyle & WS_EX_APPWINDOW) TRACE(" WS_EX_APPWINDOW");
1038 if(exstyle & WS_EX_LAYERED) TRACE(" WS_EX_LAYERED");
1040 #define DUMPED_EX_STYLES \
1041 (WS_EX_DLGMODALFRAME | \
1042 WS_EX_DRAGDETECT | \
1043 WS_EX_NOPARENTNOTIFY | \
1045 WS_EX_ACCEPTFILES | \
1046 WS_EX_TRANSPARENT | \
1048 WS_EX_TOOLWINDOW | \
1049 WS_EX_WINDOWEDGE | \
1050 WS_EX_CLIENTEDGE | \
1051 WS_EX_CONTEXTHELP | \
1053 WS_EX_RTLREADING | \
1054 WS_EX_LEFTSCROLLBAR | \
1055 WS_EX_CONTROLPARENT | \
1056 WS_EX_STATICEDGE | \
1060 if(exstyle & ~DUMPED_EX_STYLES) TRACE(" %08lx", exstyle & ~DUMPED_EX_STYLES);
1062 #undef DUMPED_EX_STYLES
1066 /***********************************************************************
1067 * WIN_CreateWindowEx
1069 * Implementation of CreateWindowEx().
1071 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, LPCWSTR className, UINT flags )
1073 INT cx, cy, style, sw = SW_SHOW;
1077 HWND hwnd, parent, owner, top_child = 0;
1078 BOOL unicode = (flags & WIN_ISUNICODE) != 0;
1079 MDICREATESTRUCTA mdi_cs;
1080 CBT_CREATEWNDA cbtc;
1083 TRACE("%s %s ex=%08x style=%08x %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
1084 unicode ? debugstr_w((LPCWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
1085 debugstr_w(className),
1086 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
1087 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
1088 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
1090 /* Fix the styles for MDI children */
1091 if (cs->dwExStyle & WS_EX_MDICHILD)
1095 wndPtr = WIN_GetPtr(cs->hwndParent);
1096 if (wndPtr && wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
1098 flags = wndPtr->flags;
1099 WIN_ReleasePtr(wndPtr);
1102 if (!(flags & WIN_ISMDICLIENT))
1104 WARN("WS_EX_MDICHILD, but parent %p is not MDIClient\n", cs->hwndParent);
1108 /* cs->lpCreateParams of WM_[NC]CREATE is different for MDI children.
1109 * MDICREATESTRUCT members have the originally passed values.
1111 * Note: we rely on the fact that MDICREATESTRUCTA and MDICREATESTRUCTW
1112 * have the same layout.
1114 mdi_cs.szClass = cs->lpszClass;
1115 mdi_cs.szTitle = cs->lpszName;
1116 mdi_cs.hOwner = cs->hInstance;
1121 mdi_cs.style = cs->style;
1122 mdi_cs.lParam = (LPARAM)cs->lpCreateParams;
1124 cs->lpCreateParams = &mdi_cs;
1126 if (GetWindowLongW(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
1128 if (cs->style & WS_POPUP)
1130 TRACE("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n");
1133 cs->style |= WS_CHILD | WS_CLIPSIBLINGS;
1137 cs->style &= ~WS_POPUP;
1138 cs->style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
1139 WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
1142 top_child = GetWindow(cs->hwndParent, GW_CHILD);
1146 /* Restore current maximized child */
1147 if((cs->style & WS_VISIBLE) && IsZoomed(top_child))
1149 TRACE("Restoring current maximized child %p\n", top_child);
1150 SendMessageW( top_child, WM_SETREDRAW, FALSE, 0 );
1151 ShowWindow( top_child, SW_SHOWNORMAL );
1152 SendMessageW( top_child, WM_SETREDRAW, TRUE, 0 );
1157 /* Find the parent window */
1159 parent = cs->hwndParent;
1162 if (cs->hwndParent == HWND_MESSAGE)
1164 cs->hwndParent = parent = get_hwnd_message_parent();
1166 else if (cs->hwndParent)
1168 if ((cs->style & (WS_CHILD|WS_POPUP)) != WS_CHILD)
1170 parent = GetDesktopWindow();
1171 owner = cs->hwndParent;
1176 static const WCHAR messageW[] = {'M','e','s','s','a','g','e',0};
1178 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1180 WARN("No parent for child window\n" );
1181 SetLastError(ERROR_TLW_WITH_WSCHILD);
1182 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1184 /* are we creating the desktop or HWND_MESSAGE parent itself? */
1185 if (className != (LPCWSTR)DESKTOP_CLASS_ATOM &&
1186 (IS_INTRESOURCE(className) || strcmpiW( className, messageW )))
1187 parent = GetDesktopWindow();
1190 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
1192 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
1193 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
1194 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
1195 cs->dwExStyle |= WS_EX_WINDOWEDGE;
1197 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
1199 /* Create the window structure */
1201 if (!(wndPtr = create_window_handle( parent, owner, className, cs->hInstance, unicode )))
1203 hwnd = wndPtr->obj.handle;
1205 /* Fill the window structure */
1207 wndPtr->tid = GetCurrentThreadId();
1208 wndPtr->hInstance = cs->hInstance;
1209 wndPtr->text = NULL;
1210 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1211 wndPtr->dwExStyle = cs->dwExStyle;
1212 wndPtr->wIDmenu = 0;
1213 wndPtr->helpContext = 0;
1214 wndPtr->pScroll = NULL;
1215 wndPtr->userdata = 0;
1217 wndPtr->hIconSmall = 0;
1218 wndPtr->hSysMenu = 0;
1219 wndPtr->flags |= (flags & WIN_ISWIN32);
1221 wndPtr->min_pos.x = wndPtr->min_pos.y = -1;
1222 wndPtr->max_pos.x = wndPtr->max_pos.y = -1;
1224 if (wndPtr->dwStyle & WS_SYSMENU) SetSystemMenu( hwnd, 0 );
1227 * Correct the window styles.
1229 * It affects only the style loaded into the WIN structure.
1232 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
1234 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1235 if (!(wndPtr->dwStyle & WS_POPUP))
1236 wndPtr->dwStyle |= WS_CAPTION;
1240 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1241 * why does the user get to set it?
1244 if ((wndPtr->dwExStyle & WS_EX_DLGMODALFRAME) ||
1245 (wndPtr->dwStyle & (WS_DLGFRAME | WS_THICKFRAME)))
1246 wndPtr->dwExStyle |= WS_EX_WINDOWEDGE;
1248 wndPtr->dwExStyle &= ~WS_EX_WINDOWEDGE;
1250 if (!(wndPtr->dwStyle & (WS_CHILD | WS_POPUP)))
1251 wndPtr->flags |= WIN_NEED_SIZE;
1253 SERVER_START_REQ( set_window_info )
1255 req->handle = wine_server_user_handle( hwnd );
1256 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE | SET_WIN_UNICODE;
1257 req->style = wndPtr->dwStyle;
1258 req->ex_style = wndPtr->dwExStyle;
1259 req->instance = wine_server_client_ptr( wndPtr->hInstance );
1260 req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
1261 req->extra_offset = -1;
1262 wine_server_call( req );
1266 /* Set the window menu */
1268 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
1272 if (!MENU_SetMenu(hwnd, cs->hMenu))
1274 WIN_ReleasePtr( wndPtr );
1275 free_window_handle( hwnd );
1281 LPCSTR menuName = (LPCSTR)GetClassLongPtrA( hwnd, GCLP_MENUNAME );
1284 if (!cs->hInstance || HIWORD(cs->hInstance))
1285 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1287 cs->hMenu = HMENU_32(LoadMenu16(HINSTANCE_16(cs->hInstance),menuName));
1289 if (cs->hMenu) MENU_SetMenu( hwnd, cs->hMenu );
1293 else SetWindowLongPtrW( hwnd, GWLP_ID, (ULONG_PTR)cs->hMenu );
1295 /* call the WH_CBT hook */
1297 /* the window style passed to the hook must be the real window style,
1298 * rather than just the window style that the caller to CreateWindowEx
1299 * passed in, so we have to copy the original CREATESTRUCT and get the
1300 * the real style. */
1302 cbcs.style = wndPtr->dwStyle;
1304 cbtc.hwndInsertAfter = HWND_TOP;
1305 WIN_ReleasePtr( wndPtr );
1306 if (HOOK_CallHooks( WH_CBT, HCBT_CREATEWND, (WPARAM)hwnd, (LPARAM)&cbtc, unicode )) goto failed;
1308 /* send the WM_GETMINMAXINFO message and fix the size if needed */
1312 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
1314 POINT maxSize, maxPos, minTrack, maxTrack;
1315 WINPOS_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack);
1316 if (maxTrack.x < cx) cx = maxTrack.x;
1317 if (maxTrack.y < cy) cy = maxTrack.y;
1318 if (minTrack.x > cx) cx = minTrack.x;
1319 if (minTrack.y > cy) cy = minTrack.y;
1324 SetRect( &rect, cs->x, cs->y, cs->x + cx, cs->y + cy );
1325 /* check for wraparound */
1326 if (cs->x + cx < cs->x) rect.right = 0x7fffffff;
1327 if (cs->y + cy < cs->y) rect.bottom = 0x7fffffff;
1328 if (!set_window_pos( hwnd, 0, SWP_NOZORDER | SWP_NOACTIVATE, &rect, &rect, NULL )) goto failed;
1330 /* send WM_NCCREATE */
1332 TRACE( "hwnd %p cs %d,%d %dx%d\n", hwnd, cs->x, cs->y, cx, cy );
1334 result = SendMessageW( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
1336 result = SendMessageA( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
1339 WARN( "%p: aborted by WM_NCCREATE\n", hwnd );
1343 /* send WM_NCCALCSIZE */
1345 if ((wndPtr = WIN_GetPtr(hwnd)))
1347 /* yes, even if the CBT hook was called with HWND_TOP */
1349 HWND insert_after = (wndPtr->dwStyle & WS_CHILD) ? HWND_BOTTOM : HWND_TOP;
1350 RECT window_rect = wndPtr->rectWindow;
1351 RECT client_rect = window_rect;
1352 WIN_ReleasePtr( wndPtr );
1354 /* the rectangle is in screen coords for WM_NCCALCSIZE when wparam is FALSE */
1356 MapWindowPoints( parent, 0, &pt, 1 );
1357 OffsetRect( &client_rect, pt.x, pt.y );
1358 SendMessageW( hwnd, WM_NCCALCSIZE, FALSE, (LPARAM)&client_rect );
1359 OffsetRect( &client_rect, -pt.x, -pt.y );
1360 set_window_pos( hwnd, insert_after, SWP_NOACTIVATE, &window_rect, &client_rect, NULL );
1364 /* send WM_CREATE */
1367 result = SendMessageW( hwnd, WM_CREATE, 0, (LPARAM)cs );
1369 result = SendMessageA( hwnd, WM_CREATE, 0, (LPARAM)cs );
1370 if (result == -1) goto failed;
1372 /* call the driver */
1374 if (!USER_Driver->pCreateWindow( hwnd )) goto failed;
1376 NotifyWinEvent(EVENT_OBJECT_CREATE, hwnd, OBJID_WINDOW, 0);
1378 /* send the size messages */
1380 if (!(wndPtr = WIN_GetPtr( hwnd )) ||
1381 wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return 0;
1382 if (!(wndPtr->flags & WIN_NEED_SIZE))
1384 rect = wndPtr->rectClient;
1385 WIN_ReleasePtr( wndPtr );
1386 SendMessageW( hwnd, WM_SIZE, SIZE_RESTORED,
1387 MAKELONG(rect.right-rect.left, rect.bottom-rect.top));
1388 SendMessageW( hwnd, WM_MOVE, 0, MAKELONG( rect.left, rect.top ) );
1390 else WIN_ReleasePtr( wndPtr );
1392 /* Show the window, maximizing or minimizing if needed */
1394 style = WIN_SetStyle( hwnd, 0, WS_MAXIMIZE | WS_MINIMIZE );
1395 if (style & (WS_MINIMIZE | WS_MAXIMIZE))
1398 UINT swFlag = (style & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
1400 swFlag = WINPOS_MinMaximize( hwnd, swFlag, &newPos );
1401 swFlag |= SWP_FRAMECHANGED; /* Frame always gets changed */
1402 if (!(style & WS_VISIBLE) || (style & WS_CHILD) || GetActiveWindow()) swFlag |= SWP_NOACTIVATE;
1403 SetWindowPos( hwnd, 0, newPos.left, newPos.top, newPos.right - newPos.left,
1404 newPos.bottom - newPos.top, swFlag );
1407 /* Notify the parent window only */
1409 send_parent_notify( hwnd, WM_CREATE );
1410 if (!IsWindow( hwnd )) return 0;
1412 if (cs->style & WS_VISIBLE)
1414 if (cs->style & WS_MAXIMIZE)
1416 else if (cs->style & WS_MINIMIZE)
1417 sw = SW_SHOWMINIMIZED;
1419 ShowWindow( hwnd, sw );
1420 if (cs->dwExStyle & WS_EX_MDICHILD)
1422 SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
1423 /* ShowWindow won't activate child windows */
1424 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE );
1428 /* Call WH_SHELL hook */
1430 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1431 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1433 TRACE("created window %p\n", hwnd);
1437 WIN_DestroyWindow( hwnd );
1442 /***********************************************************************
1443 * CreateWindow (USER.41)
1445 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1446 DWORD style, INT16 x, INT16 y, INT16 width,
1447 INT16 height, HWND16 parent, HMENU16 menu,
1448 HINSTANCE16 instance, LPVOID data )
1450 return CreateWindowEx16( 0, className, windowName, style,
1451 x, y, width, height, parent, menu, instance, data );
1455 /***********************************************************************
1456 * CreateWindowEx (USER.452)
1458 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1459 LPCSTR windowName, DWORD style, INT16 x,
1460 INT16 y, INT16 width, INT16 height,
1461 HWND16 parent, HMENU16 menu,
1462 HINSTANCE16 instance, LPVOID data )
1467 /* Fix the coordinates */
1469 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1470 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1471 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1472 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1474 /* Create the window */
1476 cs.lpCreateParams = data;
1477 cs.hInstance = HINSTANCE_32(instance);
1478 cs.hMenu = HMENU_32(menu);
1479 cs.hwndParent = WIN_Handle32( parent );
1481 cs.lpszName = windowName;
1482 cs.lpszClass = className;
1483 cs.dwExStyle = exStyle;
1485 if (!IS_INTRESOURCE(className))
1489 if (!MultiByteToWideChar( CP_ACP, 0, className, -1, bufferW, sizeof(bufferW)/sizeof(WCHAR) ))
1491 return HWND_16( WIN_CreateWindowEx( &cs, bufferW, 0 ));
1495 if (!GlobalGetAtomNameA( LOWORD(className), buffer, sizeof(buffer) ))
1497 ERR( "bad atom %x\n", LOWORD(className));
1500 cs.lpszClass = buffer;
1501 return HWND_16( WIN_CreateWindowEx( &cs, (LPCWSTR)className, 0 ));
1506 /***********************************************************************
1507 * CreateWindowExA (USER32.@)
1509 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1510 LPCSTR windowName, DWORD style, INT x,
1511 INT y, INT width, INT height,
1512 HWND parent, HMENU menu,
1513 HINSTANCE instance, LPVOID data )
1517 cs.lpCreateParams = data;
1518 cs.hInstance = instance;
1520 cs.hwndParent = parent;
1526 cs.lpszName = windowName;
1527 cs.lpszClass = className;
1528 cs.dwExStyle = exStyle;
1530 if (!IS_INTRESOURCE(className))
1533 if (!MultiByteToWideChar( CP_ACP, 0, className, -1, bufferW, sizeof(bufferW)/sizeof(WCHAR) ))
1535 return WIN_CreateWindowEx( &cs, bufferW, WIN_ISWIN32 );
1537 return WIN_CreateWindowEx( &cs, (LPCWSTR)className, WIN_ISWIN32 );
1541 /***********************************************************************
1542 * CreateWindowExW (USER32.@)
1544 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1545 LPCWSTR windowName, DWORD style, INT x,
1546 INT y, INT width, INT height,
1547 HWND parent, HMENU menu,
1548 HINSTANCE instance, LPVOID data )
1552 cs.lpCreateParams = data;
1553 cs.hInstance = instance;
1555 cs.hwndParent = parent;
1561 cs.lpszName = windowName;
1562 cs.lpszClass = className;
1563 cs.dwExStyle = exStyle;
1565 /* Note: we rely on the fact that CREATESTRUCTA and */
1566 /* CREATESTRUCTW have the same layout. */
1567 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, className, WIN_ISWIN32 | WIN_ISUNICODE );
1571 /***********************************************************************
1572 * WIN_SendDestroyMsg
1574 static void WIN_SendDestroyMsg( HWND hwnd )
1578 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1580 if (hwnd == info.hwndCaret) DestroyCaret();
1581 if (hwnd == info.hwndActive) WINPOS_ActivateOtherWindow( hwnd );
1585 * Send the WM_DESTROY to the window.
1587 SendMessageW( hwnd, WM_DESTROY, 0, 0);
1590 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1591 * make sure that the window still exists when we come back.
1598 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1600 for (i = 0; pWndArray[i]; i++)
1602 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1604 HeapFree( GetProcessHeap(), 0, pWndArray );
1607 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1611 /***********************************************************************
1612 * DestroyWindow (USER32.@)
1614 BOOL WINAPI DestroyWindow( HWND hwnd )
1618 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || is_desktop_window( hwnd ))
1620 SetLastError( ERROR_ACCESS_DENIED );
1624 TRACE("(%p)\n", hwnd);
1628 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1630 if (MENU_IsMenuActive() == hwnd)
1633 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1637 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1638 send_parent_notify( hwnd, WM_DESTROY );
1640 else if (!GetWindow( hwnd, GW_OWNER ))
1642 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1643 /* FIXME: clean up palette - see "Internals" p.352 */
1646 if (!IsWindow(hwnd)) return TRUE;
1648 /* Hide the window */
1649 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)
1651 /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
1653 ShowWindow( hwnd, SW_HIDE );
1655 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1656 SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW );
1659 if (!IsWindow(hwnd)) return TRUE;
1661 /* Recursively destroy owned windows */
1668 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1671 for (i = 0; list[i]; i++)
1673 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1674 if (WIN_IsCurrentThread( list[i] ))
1676 DestroyWindow( list[i] );
1680 WIN_SetOwner( list[i], 0 );
1682 HeapFree( GetProcessHeap(), 0, list );
1684 if (!got_one) break;
1688 /* Send destroy messages */
1690 WIN_SendDestroyMsg( hwnd );
1691 if (!IsWindow( hwnd )) return TRUE;
1693 if (GetClipboardOwner() == hwnd)
1694 CLIPBOARD_ReleaseOwner();
1696 /* Destroy the window storage */
1698 WIN_DestroyWindow( hwnd );
1703 /***********************************************************************
1704 * CloseWindow (USER32.@)
1706 BOOL WINAPI CloseWindow( HWND hwnd )
1708 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1709 ShowWindow( hwnd, SW_MINIMIZE );
1714 /***********************************************************************
1715 * OpenIcon (USER32.@)
1717 BOOL WINAPI OpenIcon( HWND hwnd )
1719 if (!IsIconic( hwnd )) return FALSE;
1720 ShowWindow( hwnd, SW_SHOWNORMAL );
1725 /***********************************************************************
1726 * FindWindowExW (USER32.@)
1728 HWND WINAPI FindWindowExW( HWND parent, HWND child, LPCWSTR className, LPCWSTR title )
1733 WCHAR *buffer = NULL;
1735 if (!parent && child) parent = GetDesktopWindow();
1736 else if (parent == HWND_MESSAGE) parent = get_hwnd_message_parent();
1740 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1741 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1744 if (!(list = list_window_children( 0, parent, className, 0 ))) goto done;
1748 child = WIN_GetFullHandle( child );
1749 while (list[i] && list[i] != child) i++;
1750 if (!list[i]) goto done;
1751 i++; /* start from next window */
1758 if (GetWindowTextW( list[i], buffer, len + 1 ) && !strcmpiW( buffer, title )) break;
1765 HeapFree( GetProcessHeap(), 0, list );
1766 HeapFree( GetProcessHeap(), 0, buffer );
1772 /***********************************************************************
1773 * FindWindowA (USER32.@)
1775 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1777 HWND ret = FindWindowExA( 0, 0, className, title );
1778 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1783 /***********************************************************************
1784 * FindWindowExA (USER32.@)
1786 HWND WINAPI FindWindowExA( HWND parent, HWND child, LPCSTR className, LPCSTR title )
1788 LPWSTR titleW = NULL;
1793 DWORD len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1794 if (!(titleW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1795 MultiByteToWideChar( CP_ACP, 0, title, -1, titleW, len );
1798 if (!IS_INTRESOURCE(className))
1801 if (MultiByteToWideChar( CP_ACP, 0, className, -1, classW, sizeof(classW)/sizeof(WCHAR) ))
1802 hwnd = FindWindowExW( parent, child, classW, titleW );
1806 hwnd = FindWindowExW( parent, child, (LPCWSTR)className, titleW );
1809 HeapFree( GetProcessHeap(), 0, titleW );
1814 /***********************************************************************
1815 * FindWindowW (USER32.@)
1817 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1819 return FindWindowExW( 0, 0, className, title );
1823 /**********************************************************************
1824 * GetDesktopWindow (USER32.@)
1826 HWND WINAPI GetDesktopWindow(void)
1828 struct user_thread_info *thread_info = get_user_thread_info();
1830 if (thread_info->top_window) return thread_info->top_window;
1832 SERVER_START_REQ( get_desktop_window )
1835 if (!wine_server_call( req ))
1837 thread_info->top_window = wine_server_ptr_handle( reply->top_window );
1838 thread_info->msg_window = wine_server_ptr_handle( reply->msg_window );
1843 if (!thread_info->top_window)
1845 USEROBJECTFLAGS flags;
1846 if (!GetUserObjectInformationW( GetProcessWindowStation(), UOI_FLAGS, &flags,
1847 sizeof(flags), NULL ) || (flags.dwFlags & WSF_VISIBLE))
1849 static const WCHAR command_line[] = {'\\','e','x','p','l','o','r','e','r','.','e','x','e',' ','/','d','e','s','k','t','o','p',0};
1851 PROCESS_INFORMATION pi;
1852 WCHAR systemdir[MAX_PATH];
1853 WCHAR cmdline[MAX_PATH + sizeof(command_line)/sizeof(WCHAR)];
1855 memset( &si, 0, sizeof(si) );
1857 si.dwFlags = STARTF_USESTDHANDLES;
1860 si.hStdError = GetStdHandle( STD_ERROR_HANDLE );
1862 GetSystemDirectoryW( systemdir, MAX_PATH );
1863 lstrcpyW( cmdline, systemdir );
1864 lstrcatW( cmdline, command_line );
1865 if (CreateProcessW( NULL, cmdline, NULL, NULL, FALSE, DETACHED_PROCESS,
1866 NULL, systemdir, &si, &pi ))
1868 TRACE( "started explorer pid %04x tid %04x\n", pi.dwProcessId, pi.dwThreadId );
1869 WaitForInputIdle( pi.hProcess, 10000 );
1870 CloseHandle( pi.hThread );
1871 CloseHandle( pi.hProcess );
1873 else WARN( "failed to start explorer, err %d\n", GetLastError() );
1875 else TRACE( "not starting explorer since winstation is not visible\n" );
1877 SERVER_START_REQ( get_desktop_window )
1880 if (!wine_server_call( req ))
1882 thread_info->top_window = wine_server_ptr_handle( reply->top_window );
1883 thread_info->msg_window = wine_server_ptr_handle( reply->msg_window );
1889 if (!thread_info->top_window || !USER_Driver->pCreateDesktopWindow( thread_info->top_window ))
1890 ERR( "failed to create desktop window\n" );
1892 return thread_info->top_window;
1896 /*******************************************************************
1897 * EnableWindow (USER32.@)
1899 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1904 if (is_broadcast(hwnd))
1906 SetLastError( ERROR_INVALID_PARAMETER );
1910 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1911 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1915 TRACE("( %p, %d )\n", hwnd, enable);
1917 retvalue = !IsWindowEnabled( hwnd );
1919 if (enable && retvalue)
1921 WIN_SetStyle( hwnd, 0, WS_DISABLED );
1922 SendMessageW( hwnd, WM_ENABLE, TRUE, 0 );
1924 else if (!enable && !retvalue)
1928 SendMessageW( hwnd, WM_CANCELMODE, 0, 0);
1930 WIN_SetStyle( hwnd, WS_DISABLED, 0 );
1932 if (hwnd == GetFocus())
1933 SetFocus( 0 ); /* A disabled window can't have the focus */
1935 capture_wnd = GetCapture();
1936 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1937 ReleaseCapture(); /* A disabled window can't capture the mouse */
1939 SendMessageW( hwnd, WM_ENABLE, FALSE, 0 );
1945 /***********************************************************************
1946 * IsWindowEnabled (USER32.@)
1948 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1950 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1954 /***********************************************************************
1955 * IsWindowUnicode (USER32.@)
1957 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1960 BOOL retvalue = FALSE;
1962 if (!(wndPtr = WIN_GetPtr(hwnd))) return FALSE;
1964 if (wndPtr == WND_DESKTOP) return TRUE;
1966 if (wndPtr != WND_OTHER_PROCESS)
1968 retvalue = (wndPtr->flags & WIN_ISUNICODE) != 0;
1969 WIN_ReleasePtr( wndPtr );
1973 SERVER_START_REQ( get_window_info )
1975 req->handle = wine_server_user_handle( hwnd );
1976 if (!wine_server_call_err( req )) retvalue = reply->is_unicode;
1984 /**********************************************************************
1987 * Helper function for GetWindowLong().
1989 static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, UINT size, BOOL unicode )
1991 LONG_PTR retvalue = 0;
1994 if (offset == GWLP_HWNDPARENT)
1996 HWND parent = GetAncestor( hwnd, GA_PARENT );
1997 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1998 return (ULONG_PTR)parent;
2001 if (!(wndPtr = WIN_GetPtr( hwnd )))
2003 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2007 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
2009 if (offset == GWLP_WNDPROC)
2011 SetLastError( ERROR_ACCESS_DENIED );
2014 SERVER_START_REQ( set_window_info )
2016 req->handle = wine_server_user_handle( hwnd );
2017 req->flags = 0; /* don't set anything, just retrieve */
2018 req->extra_offset = (offset >= 0) ? offset : -1;
2019 req->extra_size = (offset >= 0) ? size : 0;
2020 if (!wine_server_call_err( req ))
2024 case GWL_STYLE: retvalue = reply->old_style; break;
2025 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
2026 case GWLP_ID: retvalue = reply->old_id; break;
2027 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wine_server_get_ptr( reply->old_instance ); break;
2028 case GWLP_USERDATA: retvalue = reply->old_user_data; break;
2030 if (offset >= 0) retvalue = get_win_data( &reply->old_extra_value, size );
2031 else SetLastError( ERROR_INVALID_INDEX );
2040 /* now we have a valid wndPtr */
2044 if (offset > (int)(wndPtr->cbWndExtra - size))
2046 WARN("Invalid offset %d\n", offset );
2047 WIN_ReleasePtr( wndPtr );
2048 SetLastError( ERROR_INVALID_INDEX );
2051 retvalue = get_win_data( (char *)wndPtr->wExtra + offset, size );
2053 /* Special case for dialog window procedure */
2054 if ((offset == DWLP_DLGPROC) && (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG))
2055 retvalue = (LONG_PTR)WINPROC_GetProc( (WNDPROC)retvalue, unicode );
2056 WIN_ReleasePtr( wndPtr );
2062 case GWLP_USERDATA: retvalue = wndPtr->userdata; break;
2063 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
2064 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
2065 case GWLP_ID: retvalue = wndPtr->wIDmenu; break;
2066 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wndPtr->hInstance; break;
2068 /* This looks like a hack only for the edit control (see tests). This makes these controls
2069 * more tolerant to A/W mismatches. The lack of W->A->W conversion for such a mismatch suggests
2070 * that the hack is in GetWindowLongPtr[AW], not in winprocs.
2072 if (wndPtr->winproc == EDIT_winproc_handle && (!unicode != !(wndPtr->flags & WIN_ISUNICODE)))
2073 retvalue = (ULONG_PTR)wndPtr->winproc;
2075 retvalue = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, unicode );
2078 WARN("Unknown offset %d\n", offset );
2079 SetLastError( ERROR_INVALID_INDEX );
2082 WIN_ReleasePtr(wndPtr);
2087 /**********************************************************************
2090 * Helper function for SetWindowLong().
2092 * 0 is the failure code. However, in the case of failure SetLastError
2093 * must be set to distinguish between a 0 return value and a failure.
2095 LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, UINT size, LONG_PTR newval, BOOL unicode )
2099 LONG_PTR retval = 0;
2102 TRACE( "%p %d %lx %c\n", hwnd, offset, newval, unicode ? 'W' : 'A' );
2104 if (is_broadcast(hwnd))
2106 SetLastError( ERROR_INVALID_PARAMETER );
2110 if (!(wndPtr = WIN_GetPtr( hwnd )))
2112 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2115 if (wndPtr == WND_DESKTOP)
2117 /* can't change anything on the desktop window */
2118 SetLastError( ERROR_ACCESS_DENIED );
2121 if (wndPtr == WND_OTHER_PROCESS)
2123 if (offset == GWLP_WNDPROC)
2125 SetLastError( ERROR_ACCESS_DENIED );
2128 if (offset > 32767 || offset < -32767)
2130 SetLastError( ERROR_INVALID_INDEX );
2133 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, MAKEWPARAM( offset, size ), newval );
2136 /* first some special cases */
2142 offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
2143 style.styleNew = newval;
2144 WIN_ReleasePtr( wndPtr );
2145 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
2146 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
2147 newval = style.styleNew;
2149 case GWLP_HWNDPARENT:
2150 if (wndPtr->parent == GetDesktopWindow())
2152 WIN_ReleasePtr( wndPtr );
2153 return (ULONG_PTR)WIN_SetOwner( hwnd, (HWND)newval );
2157 WIN_ReleasePtr( wndPtr );
2158 return (ULONG_PTR)SetParent( hwnd, (HWND)newval );
2163 UINT old_flags = wndPtr->flags;
2164 retval = WIN_GetWindowLong( hwnd, offset, size, unicode );
2165 if (unicode) proc = WINPROC_AllocProc( NULL, (WNDPROC)newval );
2166 else proc = WINPROC_AllocProc( (WNDPROC)newval, NULL );
2167 if (proc) wndPtr->winproc = proc;
2168 if (WINPROC_IsUnicode( proc, unicode )) wndPtr->flags |= WIN_ISUNICODE;
2169 else wndPtr->flags &= ~WIN_ISUNICODE;
2170 if (!((old_flags ^ wndPtr->flags) & WIN_ISUNICODE))
2172 WIN_ReleasePtr( wndPtr );
2175 /* update is_unicode flag on the server side */
2179 case GWLP_HINSTANCE:
2183 if ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
2184 (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG))
2186 WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWLP_DLGPROC);
2187 retval = (ULONG_PTR)WINPROC_GetProc( *ptr, unicode );
2188 if (unicode) *ptr = WINPROC_AllocProc( NULL, (WNDPROC)newval );
2189 else *ptr = WINPROC_AllocProc( (WNDPROC)newval, NULL );
2190 WIN_ReleasePtr( wndPtr );
2195 if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - size))
2197 WARN("Invalid offset %d\n", offset );
2198 WIN_ReleasePtr( wndPtr );
2199 SetLastError( ERROR_INVALID_INDEX );
2202 else if (get_win_data( (char *)wndPtr->wExtra + offset, size ) == newval)
2204 /* already set to the same value */
2205 WIN_ReleasePtr( wndPtr );
2211 SERVER_START_REQ( set_window_info )
2213 req->handle = wine_server_user_handle( hwnd );
2214 req->extra_offset = -1;
2218 req->flags = SET_WIN_STYLE;
2219 req->style = newval;
2222 req->flags = SET_WIN_EXSTYLE;
2223 /* WS_EX_TOPMOST can only be changed through SetWindowPos */
2224 newval = (newval & ~WS_EX_TOPMOST) | (wndPtr->dwExStyle & WS_EX_TOPMOST);
2225 req->ex_style = newval;
2228 req->flags = SET_WIN_ID;
2231 case GWLP_HINSTANCE:
2232 req->flags = SET_WIN_INSTANCE;
2233 req->instance = wine_server_client_ptr( (void *)newval );
2236 req->flags = SET_WIN_UNICODE;
2237 req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
2240 req->flags = SET_WIN_USERDATA;
2241 req->user_data = newval;
2244 req->flags = SET_WIN_EXTRA;
2245 req->extra_offset = offset;
2246 req->extra_size = size;
2247 set_win_data( &req->extra_value, newval, size );
2249 if ((ok = !wine_server_call_err( req )))
2254 wndPtr->dwStyle = newval;
2255 retval = reply->old_style;
2258 wndPtr->dwExStyle = newval;
2259 retval = reply->old_ex_style;
2262 wndPtr->wIDmenu = newval;
2263 retval = reply->old_id;
2265 case GWLP_HINSTANCE:
2266 wndPtr->hInstance = (HINSTANCE)newval;
2267 retval = (ULONG_PTR)wine_server_get_ptr( reply->old_instance );
2272 wndPtr->userdata = newval;
2273 retval = reply->old_user_data;
2276 retval = get_win_data( (char *)wndPtr->wExtra + offset, size );
2277 set_win_data( (char *)wndPtr->wExtra + offset, newval, size );
2283 WIN_ReleasePtr( wndPtr );
2287 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2289 USER_Driver->pSetWindowStyle( hwnd, offset, &style );
2290 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2297 /**********************************************************************
2298 * GetWindowLong (USER.135)
2300 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2304 BOOL is_winproc = (offset == GWLP_WNDPROC);
2308 if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2310 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2313 if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2315 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
2318 * Some programs try to access last element from 16 bit
2319 * code using illegal offset value. Hopefully this is
2320 * what those programs really expect.
2322 if (wndPtr->cbWndExtra >= 4 && offset == wndPtr->cbWndExtra - sizeof(WORD))
2324 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
2325 ERR( "- replaced invalid offset %d with %d\n", offset, offset2 );
2330 WARN("Invalid offset %d\n", offset );
2331 WIN_ReleasePtr( wndPtr );
2332 SetLastError( ERROR_INVALID_INDEX );
2336 is_winproc = ((offset == DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG));
2337 WIN_ReleasePtr( wndPtr );
2340 retvalue = GetWindowLongA( WIN_Handle32(hwnd), offset );
2341 if (is_winproc) retvalue = (LONG_PTR)WINPROC_GetProc16( (WNDPROC)retvalue, FALSE );
2346 /**********************************************************************
2347 * GetWindowWord (USER32.@)
2349 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
2354 case GWLP_HINSTANCE:
2355 case GWLP_HWNDPARENT:
2360 WARN("Invalid offset %d\n", offset );
2361 SetLastError( ERROR_INVALID_INDEX );
2366 return WIN_GetWindowLong( hwnd, offset, sizeof(WORD), FALSE );
2370 /**********************************************************************
2371 * GetWindowLongA (USER32.@)
2373 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2375 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), FALSE );
2379 /**********************************************************************
2380 * GetWindowLongW (USER32.@)
2382 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2384 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), TRUE );
2388 /**********************************************************************
2389 * SetWindowLong (USER.136)
2391 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2394 BOOL is_winproc = (offset == GWLP_WNDPROC);
2396 if (offset == DWLP_DLGPROC)
2398 if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2400 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2403 if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2405 is_winproc = ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
2406 (wndPtr->flags & WIN_ISDIALOG));
2407 WIN_ReleasePtr( wndPtr );
2413 WNDPROC new_proc = WINPROC_AllocProc16( (WNDPROC16)newval );
2414 WNDPROC old_proc = (WNDPROC)SetWindowLongPtrA( WIN_Handle32(hwnd), offset, (LONG_PTR)new_proc );
2415 return (LONG)WINPROC_GetProc16( old_proc, FALSE );
2417 else return SetWindowLongA( WIN_Handle32(hwnd), offset, newval );
2421 /**********************************************************************
2422 * SetWindowWord (USER32.@)
2424 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
2429 case GWLP_HINSTANCE:
2430 case GWLP_HWNDPARENT:
2435 WARN("Invalid offset %d\n", offset );
2436 SetLastError( ERROR_INVALID_INDEX );
2441 return WIN_SetWindowLong( hwnd, offset, sizeof(WORD), newval, FALSE );
2445 /**********************************************************************
2446 * SetWindowLongA (USER32.@)
2448 * See SetWindowLongW.
2450 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2452 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, FALSE );
2456 /**********************************************************************
2457 * SetWindowLongW (USER32.@) Set window attribute
2459 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2460 * value in a window's extra memory.
2462 * The _hwnd_ parameter specifies the window. is the handle to a
2463 * window that has extra memory. The _newval_ parameter contains the
2464 * new attribute or extra memory value. If positive, the _offset_
2465 * parameter is the byte-addressed location in the window's extra
2466 * memory to set. If negative, _offset_ specifies the window
2467 * attribute to set, and should be one of the following values:
2469 * GWL_EXSTYLE The window's extended window style
2471 * GWL_STYLE The window's window style.
2473 * GWLP_WNDPROC Pointer to the window's window procedure.
2475 * GWLP_HINSTANCE The window's pplication instance handle.
2477 * GWLP_ID The window's identifier.
2479 * GWLP_USERDATA The window's user-specified data.
2481 * If the window is a dialog box, the _offset_ parameter can be one of
2482 * the following values:
2484 * DWLP_DLGPROC The address of the window's dialog box procedure.
2486 * DWLP_MSGRESULT The return value of a message
2487 * that the dialog box procedure processed.
2489 * DWLP_USER Application specific information.
2493 * If successful, returns the previous value located at _offset_. Otherwise,
2498 * Extra memory for a window class is specified by a nonzero cbWndExtra
2499 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2500 * time of class creation.
2502 * Using GWL_WNDPROC to set a new window procedure effectively creates
2503 * a window subclass. Use CallWindowProc() in the new windows procedure
2504 * to pass messages to the superclass's window procedure.
2506 * The user data is reserved for use by the application which created
2509 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2510 * instead, call the EnableWindow() function to change the window's
2513 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2514 * SetParent() instead.
2517 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2518 * it sends WM_STYLECHANGING before changing the settings
2519 * and WM_STYLECHANGED afterwards.
2520 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2522 LONG WINAPI SetWindowLongW(
2523 HWND hwnd, /* [in] window to alter */
2524 INT offset, /* [in] offset, in bytes, of location to alter */
2525 LONG newval /* [in] new value of location */
2527 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, TRUE );
2531 /*******************************************************************
2532 * GetWindowTextA (USER32.@)
2534 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2538 if (!lpString) return 0;
2540 if (WIN_IsCurrentProcess( hwnd ))
2541 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2543 /* when window belongs to other process, don't send a message */
2544 if (nMaxCount <= 0) return 0;
2545 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2546 get_server_window_text( hwnd, buffer, nMaxCount );
2547 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2548 lpString[nMaxCount-1] = 0;
2549 HeapFree( GetProcessHeap(), 0, buffer );
2550 return strlen(lpString);
2554 /*******************************************************************
2555 * InternalGetWindowText (USER32.@)
2557 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2561 if (nMaxCount <= 0) return 0;
2562 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2563 if (win == WND_DESKTOP) lpString[0] = 0;
2564 else if (win != WND_OTHER_PROCESS)
2566 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2567 else lpString[0] = 0;
2568 WIN_ReleasePtr( win );
2572 get_server_window_text( hwnd, lpString, nMaxCount );
2574 return strlenW(lpString);
2578 /*******************************************************************
2579 * GetWindowTextW (USER32.@)
2581 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2583 if (!lpString) return 0;
2585 if (WIN_IsCurrentProcess( hwnd ))
2586 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2588 /* when window belongs to other process, don't send a message */
2589 if (nMaxCount <= 0) return 0;
2590 get_server_window_text( hwnd, lpString, nMaxCount );
2591 return strlenW(lpString);
2595 /*******************************************************************
2596 * SetWindowTextA (USER32.@)
2597 * SetWindowText (USER32.@)
2599 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2601 if (is_broadcast(hwnd))
2603 SetLastError( ERROR_INVALID_PARAMETER );
2606 if (!WIN_IsCurrentProcess( hwnd ))
2607 WARN( "setting text %s of other process window %p should not use SendMessage\n",
2608 debugstr_a(lpString), hwnd );
2609 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2613 /*******************************************************************
2614 * SetWindowTextW (USER32.@)
2616 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2618 if (is_broadcast(hwnd))
2620 SetLastError( ERROR_INVALID_PARAMETER );
2623 if (!WIN_IsCurrentProcess( hwnd ))
2624 WARN( "setting text %s of other process window %p should not use SendMessage\n",
2625 debugstr_w(lpString), hwnd );
2626 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2630 /*******************************************************************
2631 * GetWindowTextLengthA (USER32.@)
2633 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2635 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2638 /*******************************************************************
2639 * GetWindowTextLengthW (USER32.@)
2641 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2643 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2647 /*******************************************************************
2648 * IsWindow (USER32.@)
2650 BOOL WINAPI IsWindow( HWND hwnd )
2655 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2656 if (ptr == WND_DESKTOP) return TRUE;
2658 if (ptr != WND_OTHER_PROCESS)
2660 WIN_ReleasePtr( ptr );
2664 /* check other processes */
2665 SERVER_START_REQ( get_window_info )
2667 req->handle = wine_server_user_handle( hwnd );
2668 ret = !wine_server_call_err( req );
2675 /***********************************************************************
2676 * GetWindowThreadProcessId (USER32.@)
2678 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2683 if (!(ptr = WIN_GetPtr( hwnd )))
2685 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2689 if (ptr != WND_OTHER_PROCESS && ptr != WND_DESKTOP)
2691 /* got a valid window */
2693 if (process) *process = GetCurrentProcessId();
2694 WIN_ReleasePtr( ptr );
2698 /* check other processes */
2699 SERVER_START_REQ( get_window_info )
2701 req->handle = wine_server_user_handle( hwnd );
2702 if (!wine_server_call_err( req ))
2704 tid = (DWORD)reply->tid;
2705 if (process) *process = (DWORD)reply->pid;
2713 /*****************************************************************
2714 * GetParent (USER32.@)
2716 HWND WINAPI GetParent( HWND hwnd )
2721 if (!(wndPtr = WIN_GetPtr( hwnd )))
2723 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2726 if (wndPtr == WND_DESKTOP) return 0;
2727 if (wndPtr == WND_OTHER_PROCESS)
2729 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2730 if (style & (WS_POPUP | WS_CHILD))
2732 SERVER_START_REQ( get_window_tree )
2734 req->handle = wine_server_user_handle( hwnd );
2735 if (!wine_server_call_err( req ))
2737 if (style & WS_POPUP) retvalue = wine_server_ptr_handle( reply->owner );
2738 else if (style & WS_CHILD) retvalue = wine_server_ptr_handle( reply->parent );
2746 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2747 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2748 WIN_ReleasePtr( wndPtr );
2754 /*****************************************************************
2755 * GetAncestor (USER32.@)
2757 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2760 HWND *list, ret = 0;
2765 if (!(win = WIN_GetPtr( hwnd )))
2767 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2770 if (win == WND_DESKTOP) return 0;
2771 if (win != WND_OTHER_PROCESS)
2774 WIN_ReleasePtr( win );
2776 else /* need to query the server */
2778 SERVER_START_REQ( get_window_tree )
2780 req->handle = wine_server_user_handle( hwnd );
2781 if (!wine_server_call_err( req )) ret = wine_server_ptr_handle( reply->parent );
2788 if (!(list = list_window_parents( hwnd ))) return 0;
2790 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2794 while (list[count]) count++;
2795 ret = list[count - 2]; /* get the one before the desktop */
2797 HeapFree( GetProcessHeap(), 0, list );
2801 if (is_desktop_window( hwnd )) return 0;
2802 ret = WIN_GetFullHandle( hwnd );
2805 HWND parent = GetParent( ret );
2815 /*****************************************************************
2816 * SetParent (USER32.@)
2818 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2821 HWND old_parent = 0;
2826 if (is_broadcast(hwnd) || is_broadcast(parent))
2828 SetLastError(ERROR_INVALID_PARAMETER);
2832 if (!parent) parent = GetDesktopWindow();
2833 else if (parent == HWND_MESSAGE) parent = get_hwnd_message_parent();
2834 else parent = WIN_GetFullHandle( parent );
2836 if (!IsWindow( parent ))
2838 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2842 /* Some applications try to set a child as a parent */
2843 if (IsChild(hwnd, parent))
2845 SetLastError( ERROR_INVALID_PARAMETER );
2849 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2850 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2852 /* Windows hides the window first, then shows it again
2853 * including the WM_SHOWWINDOW messages and all */
2854 was_visible = ShowWindow( hwnd, SW_HIDE );
2856 wndPtr = WIN_GetPtr( hwnd );
2857 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return 0;
2859 SERVER_START_REQ( set_parent )
2861 req->handle = wine_server_user_handle( hwnd );
2862 req->parent = wine_server_user_handle( parent );
2863 if ((ret = !wine_server_call( req )))
2865 old_parent = wine_server_ptr_handle( reply->old_parent );
2866 wndPtr->parent = parent = wine_server_ptr_handle( reply->full_parent );
2871 WIN_ReleasePtr( wndPtr );
2874 USER_Driver->pSetParent( full_handle, parent, old_parent );
2876 /* SetParent additionally needs to make hwnd the topmost window
2877 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2878 WM_WINDOWPOSCHANGED notification messages.
2880 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0,
2881 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2882 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2883 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2889 /*******************************************************************
2890 * IsChild (USER32.@)
2892 BOOL WINAPI IsChild( HWND parent, HWND child )
2894 HWND *list = list_window_parents( child );
2898 if (!list) return FALSE;
2899 parent = WIN_GetFullHandle( parent );
2900 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2901 ret = list[i] && list[i+1];
2902 HeapFree( GetProcessHeap(), 0, list );
2907 /***********************************************************************
2908 * IsWindowVisible (USER32.@)
2910 BOOL WINAPI IsWindowVisible( HWND hwnd )
2916 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2917 if (!(list = list_window_parents( hwnd ))) return TRUE;
2920 for (i = 0; list[i+1]; i++)
2921 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2922 retval = !list[i+1] && (list[i] == GetDesktopWindow()); /* top message window isn't visible */
2924 HeapFree( GetProcessHeap(), 0, list );
2929 /***********************************************************************
2930 * WIN_IsWindowDrawable
2932 * hwnd is drawable when it is visible, all parents are not
2933 * minimized, and it is itself not minimized unless we are
2934 * trying to draw its default class icon.
2936 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2941 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2943 if (!(style & WS_VISIBLE)) return FALSE;
2944 if ((style & WS_MINIMIZE) && icon && GetClassLongPtrW( hwnd, GCLP_HICON )) return FALSE;
2946 if (!(list = list_window_parents( hwnd ))) return TRUE;
2949 for (i = 0; list[i+1]; i++)
2950 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2952 retval = !list[i+1] && (list[i] == GetDesktopWindow()); /* top message window isn't visible */
2954 HeapFree( GetProcessHeap(), 0, list );
2959 /*******************************************************************
2960 * GetTopWindow (USER32.@)
2962 HWND WINAPI GetTopWindow( HWND hwnd )
2964 if (!hwnd) hwnd = GetDesktopWindow();
2965 return GetWindow( hwnd, GW_CHILD );
2969 /*******************************************************************
2970 * GetWindow (USER32.@)
2972 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2976 if (rel == GW_OWNER) /* this one may be available locally */
2978 WND *wndPtr = WIN_GetPtr( hwnd );
2981 SetLastError( ERROR_INVALID_HANDLE );
2984 if (wndPtr == WND_DESKTOP) return 0;
2985 if (wndPtr != WND_OTHER_PROCESS)
2987 retval = wndPtr->owner;
2988 WIN_ReleasePtr( wndPtr );
2991 /* else fall through to server call */
2994 SERVER_START_REQ( get_window_tree )
2996 req->handle = wine_server_user_handle( hwnd );
2997 if (!wine_server_call_err( req ))
3002 retval = wine_server_ptr_handle( reply->first_sibling );
3005 retval = wine_server_ptr_handle( reply->last_sibling );
3008 retval = wine_server_ptr_handle( reply->next_sibling );
3011 retval = wine_server_ptr_handle( reply->prev_sibling );
3014 retval = wine_server_ptr_handle( reply->owner );
3017 retval = wine_server_ptr_handle( reply->first_child );
3027 /*******************************************************************
3028 * ShowOwnedPopups (USER32.@)
3030 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
3034 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
3036 if (!win_array) return TRUE;
3038 while (win_array[count]) count++;
3039 while (--count >= 0)
3041 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
3042 if (!(pWnd = WIN_GetPtr( win_array[count] ))) continue;
3043 if (pWnd == WND_OTHER_PROCESS) continue;
3046 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
3048 WIN_ReleasePtr( pWnd );
3049 /* In Windows, ShowOwnedPopups(TRUE) generates
3050 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
3051 * regardless of the state of the owner
3053 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_SHOWNORMAL, SW_PARENTOPENING);
3059 if (pWnd->dwStyle & WS_VISIBLE)
3061 WIN_ReleasePtr( pWnd );
3062 /* In Windows, ShowOwnedPopups(FALSE) generates
3063 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
3064 * regardless of the state of the owner
3066 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
3070 WIN_ReleasePtr( pWnd );
3072 HeapFree( GetProcessHeap(), 0, win_array );
3077 /*******************************************************************
3078 * GetLastActivePopup (USER32.@)
3080 HWND WINAPI GetLastActivePopup( HWND hwnd )
3084 SERVER_START_REQ( get_window_info )
3086 req->handle = wine_server_user_handle( hwnd );
3087 if (!wine_server_call_err( req )) retval = wine_server_ptr_handle( reply->last_active );
3094 /*******************************************************************
3097 * Build an array of the children of a given window. The array must be
3098 * freed with HeapFree. Returns NULL when no windows are found.
3100 HWND *WIN_ListChildren( HWND hwnd )
3104 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
3107 return list_window_children( 0, hwnd, NULL, 0 );
3111 /*******************************************************************
3112 * EnumWindows (USER32.@)
3114 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
3120 USER_CheckNotLock();
3122 /* We have to build a list of all windows first, to avoid */
3123 /* unpleasant side-effects, for instance if the callback */
3124 /* function changes the Z-order of the windows. */
3126 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
3128 /* Now call the callback function for every window */
3130 for (i = 0; list[i]; i++)
3132 /* Make sure that the window still exists */
3133 if (!IsWindow( list[i] )) continue;
3134 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
3136 HeapFree( GetProcessHeap(), 0, list );
3141 /**********************************************************************
3142 * EnumThreadWindows (USER32.@)
3144 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
3149 USER_CheckNotLock();
3151 if (!(list = list_window_children( 0, GetDesktopWindow(), NULL, id ))) return TRUE;
3153 /* Now call the callback function for every window */
3155 for (i = 0; list[i]; i++)
3156 if (!func( list[i], lParam )) break;
3157 HeapFree( GetProcessHeap(), 0, list );
3162 /***********************************************************************
3163 * EnumDesktopWindows (USER32.@)
3165 BOOL WINAPI EnumDesktopWindows( HDESK desktop, WNDENUMPROC func, LPARAM lparam )
3170 USER_CheckNotLock();
3172 if (!(list = list_window_children( desktop, 0, NULL, 0 ))) return TRUE;
3174 for (i = 0; list[i]; i++)
3175 if (!func( list[i], lparam )) break;
3176 HeapFree( GetProcessHeap(), 0, list );
3181 /**********************************************************************
3182 * WIN_EnumChildWindows
3184 * Helper function for EnumChildWindows().
3186 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
3191 for ( ; *list; list++)
3193 /* Make sure that the window still exists */
3194 if (!IsWindow( *list )) continue;
3195 /* Build children list first */
3196 childList = WIN_ListChildren( *list );
3198 ret = func( *list, lParam );
3202 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
3203 HeapFree( GetProcessHeap(), 0, childList );
3205 if (!ret) return FALSE;
3211 /**********************************************************************
3212 * EnumChildWindows (USER32.@)
3214 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
3219 USER_CheckNotLock();
3221 if (!(list = WIN_ListChildren( parent ))) return FALSE;
3222 ret = WIN_EnumChildWindows( list, func, lParam );
3223 HeapFree( GetProcessHeap(), 0, list );
3228 /*******************************************************************
3229 * AnyPopup (USER.52)
3231 BOOL16 WINAPI AnyPopup16(void)
3237 /*******************************************************************
3238 * AnyPopup (USER32.@)
3240 BOOL WINAPI AnyPopup(void)
3244 HWND *list = WIN_ListChildren( GetDesktopWindow() );
3246 if (!list) return FALSE;
3247 for (i = 0; list[i]; i++)
3249 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
3251 retvalue = (list[i] != 0);
3252 HeapFree( GetProcessHeap(), 0, list );
3257 /*******************************************************************
3258 * FlashWindow (USER32.@)
3260 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3264 TRACE("%p\n", hWnd);
3266 if (IsIconic( hWnd ))
3268 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3270 wndPtr = WIN_GetPtr(hWnd);
3271 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
3272 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3274 wndPtr->flags |= WIN_NCACTIVATED;
3278 wndPtr->flags &= ~WIN_NCACTIVATED;
3280 WIN_ReleasePtr( wndPtr );
3287 wndPtr = WIN_GetPtr(hWnd);
3288 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
3289 hWnd = wndPtr->obj.handle; /* make it a full handle */
3291 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3292 else wparam = (hWnd == GetForegroundWindow());
3294 WIN_ReleasePtr( wndPtr );
3295 SendMessageW( hWnd, WM_NCACTIVATE, wparam, 0 );
3300 /*******************************************************************
3301 * FlashWindowEx (USER32.@)
3303 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
3305 FIXME("%p\n", pfwi);
3309 /*******************************************************************
3310 * GetWindowContextHelpId (USER32.@)
3312 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3315 WND *wnd = WIN_GetPtr( hwnd );
3316 if (!wnd || wnd == WND_DESKTOP) return 0;
3317 if (wnd == WND_OTHER_PROCESS)
3319 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3322 retval = wnd->helpContext;
3323 WIN_ReleasePtr( wnd );
3328 /*******************************************************************
3329 * SetWindowContextHelpId (USER32.@)
3331 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3333 WND *wnd = WIN_GetPtr( hwnd );
3334 if (!wnd || wnd == WND_DESKTOP) return FALSE;
3335 if (wnd == WND_OTHER_PROCESS)
3337 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3340 wnd->helpContext = id;
3341 WIN_ReleasePtr( wnd );
3346 /*******************************************************************
3347 * DragDetect (USER32.@)
3349 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3353 WORD wDragWidth = GetSystemMetrics(SM_CXDRAG);
3354 WORD wDragHeight= GetSystemMetrics(SM_CYDRAG);
3356 rect.left = pt.x - wDragWidth;
3357 rect.right = pt.x + wDragWidth;
3359 rect.top = pt.y - wDragHeight;
3360 rect.bottom = pt.y + wDragHeight;
3366 while (PeekMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ))
3368 if( msg.message == WM_LBUTTONUP )
3373 if( msg.message == WM_MOUSEMOVE )
3376 tmp.x = (short)LOWORD(msg.lParam);
3377 tmp.y = (short)HIWORD(msg.lParam);
3378 if( !PtInRect( &rect, tmp ))
3390 /******************************************************************************
3391 * GetWindowModuleFileNameA (USER32.@)
3393 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR module, UINT size )
3398 TRACE( "%p, %p, %u\n", hwnd, module, size );
3400 win = WIN_GetPtr( hwnd );
3401 if (!win || win == WND_OTHER_PROCESS || win == WND_DESKTOP)
3403 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
3406 hinst = win->hInstance;
3407 WIN_ReleasePtr( win );
3409 return GetModuleFileNameA( hinst, module, size );
3412 /******************************************************************************
3413 * GetWindowModuleFileNameW (USER32.@)
3415 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR module, UINT size )
3420 TRACE( "%p, %p, %u\n", hwnd, module, size );
3422 win = WIN_GetPtr( hwnd );
3423 if (!win || win == WND_OTHER_PROCESS || win == WND_DESKTOP)
3425 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
3428 hinst = win->hInstance;
3429 WIN_ReleasePtr( win );
3431 return GetModuleFileNameW( hinst, module, size );
3434 /******************************************************************************
3435 * GetWindowInfo (USER32.@)
3437 * Note: tests show that Windows doesn't check cbSize of the structure.
3439 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3441 if (!pwi) return FALSE;
3442 if (!IsWindow(hwnd)) return FALSE;
3444 GetWindowRect(hwnd, &pwi->rcWindow);
3445 GetClientRect(hwnd, &pwi->rcClient);
3446 /* translate to screen coordinates */
3447 MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3449 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3450 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3451 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3453 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3454 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3456 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3457 pwi->wCreatorVersion = 0x0400;
3462 /******************************************************************************
3463 * SwitchDesktop (USER32.@)
3465 * NOTES: Sets the current input or interactive desktop.
3467 BOOL WINAPI SwitchDesktop( HDESK hDesktop)
3469 FIXME("SwitchDesktop(hwnd %p) stub!\n", hDesktop);
3473 /*****************************************************************************
3474 * SetLayeredWindowAttributes (USER32.@)
3476 BOOL WINAPI SetLayeredWindowAttributes( HWND hwnd, COLORREF key, BYTE alpha, DWORD flags )
3480 TRACE("(%p,%08x,%d,%x): stub!\n", hwnd, key, alpha, flags);
3482 SERVER_START_REQ( set_window_layered_info )
3484 req->handle = wine_server_user_handle( hwnd );
3485 req->color_key = key;
3488 ret = !wine_server_call_err( req );
3492 if (ret) USER_Driver->pSetLayeredWindowAttributes( hwnd, key, alpha, flags );
3498 /*****************************************************************************
3499 * GetLayeredWindowAttributes (USER32.@)
3501 BOOL WINAPI GetLayeredWindowAttributes( HWND hwnd, COLORREF *key, BYTE *alpha, DWORD *flags )
3505 SERVER_START_REQ( get_window_layered_info )
3507 req->handle = wine_server_user_handle( hwnd );
3508 if ((ret = !wine_server_call_err( req )))
3510 if (key) *key = reply->color_key;
3511 if (alpha) *alpha = reply->alpha;
3512 if (flags) *flags = reply->flags;
3521 /*****************************************************************************
3522 * UpdateLayeredWindowIndirect (USER32.@)
3524 BOOL WINAPI UpdateLayeredWindowIndirect( HWND hwnd, const UPDATELAYEREDWINDOWINFO *info )
3528 if (!(info->dwFlags & ULW_EX_NORESIZE) && (info->pptDst || info->psize))
3530 int x = 0, y = 0, cx = 0, cy = 0;
3531 DWORD flags = SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW | SWP_NOSENDCHANGING;
3535 x = info->pptDst->x;
3536 y = info->pptDst->y;
3537 flags &= ~SWP_NOMOVE;
3541 cx = info->psize->cx;
3542 cy = info->psize->cy;
3543 flags &= ~SWP_NOSIZE;
3545 TRACE( "moving window %p pos %d,%d %dx%x\n", hwnd, x, y, cx, cy );
3546 SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
3552 HDC hdc = GetDCEx( hwnd, 0, DCX_CACHE );
3558 GetClientRect( hwnd, &rect );
3561 x = info->pptSrc->x;
3562 y = info->pptSrc->y;
3564 /* FIXME: intersect rect with info->prcDirty */
3565 TRACE( "copying window %p pos %d,%d\n", hwnd, x, y );
3566 BitBlt( hdc, rect.left, rect.top, rect.right, rect.bottom,
3567 info->hdcSrc, rect.left + x, rect.top + y, SRCCOPY );
3568 ReleaseDC( hwnd, hdc );
3572 if (info->pblend && !(info->dwFlags & ULW_OPAQUE)) alpha = info->pblend->SourceConstantAlpha;
3573 TRACE( "setting window %p alpha %u\n", hwnd, alpha );
3574 USER_Driver->pSetLayeredWindowAttributes( hwnd, info->crKey, alpha,
3575 info->dwFlags & (LWA_ALPHA | LWA_COLORKEY) );
3580 /*****************************************************************************
3581 * UpdateLayeredWindow (USER32.@)
3583 BOOL WINAPI UpdateLayeredWindow( HWND hwnd, HDC hdcDst, POINT *pptDst, SIZE *psize,
3584 HDC hdcSrc, POINT *pptSrc, COLORREF crKey, BLENDFUNCTION *pblend,
3587 UPDATELAYEREDWINDOWINFO info;
3589 info.cbSize = sizeof(info);
3590 info.hdcDst = hdcDst;
3591 info.pptDst = pptDst;
3593 info.hdcSrc = hdcSrc;
3594 info.pptSrc = pptSrc;
3596 info.pblend = pblend;
3597 info.dwFlags = dwFlags;
3598 info.prcDirty = NULL;
3599 return UpdateLayeredWindowIndirect( hwnd, &info );
3602 /* 64bit versions */
3604 #ifdef GetWindowLongPtrW
3605 #undef GetWindowLongPtrW
3608 #ifdef GetWindowLongPtrA
3609 #undef GetWindowLongPtrA
3612 #ifdef SetWindowLongPtrW
3613 #undef SetWindowLongPtrW
3616 #ifdef SetWindowLongPtrA
3617 #undef SetWindowLongPtrA
3620 /*****************************************************************************
3621 * GetWindowLongPtrW (USER32.@)
3623 LONG_PTR WINAPI GetWindowLongPtrW( HWND hwnd, INT offset )
3625 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), TRUE );
3628 /*****************************************************************************
3629 * GetWindowLongPtrA (USER32.@)
3631 LONG_PTR WINAPI GetWindowLongPtrA( HWND hwnd, INT offset )
3633 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), FALSE );
3636 /*****************************************************************************
3637 * SetWindowLongPtrW (USER32.@)
3639 LONG_PTR WINAPI SetWindowLongPtrW( HWND hwnd, INT offset, LONG_PTR newval )
3641 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, TRUE );
3644 /*****************************************************************************
3645 * SetWindowLongPtrA (USER32.@)
3647 LONG_PTR WINAPI SetWindowLongPtrA( HWND hwnd, INT offset, LONG_PTR newval )
3649 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, FALSE );