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 full_parent = 0, full_owner = 0;
104 struct tagCLASS *class = NULL;
105 user_handle_t handle = 0;
108 /* if 16-bit instance, map to module handle */
109 if (instance && !HIWORD(instance))
110 instance = HINSTANCE_32(GetExePtr(HINSTANCE_16(instance)));
112 SERVER_START_REQ( create_window )
114 req->parent = parent;
116 req->instance = instance;
117 if (!(req->atom = get_int_atom_value( name )) && name)
118 wine_server_add_data( req, name, strlenW(name)*sizeof(WCHAR) );
119 if (!wine_server_call_err( req ))
121 handle = reply->handle;
122 full_parent = reply->parent;
123 full_owner = reply->owner;
124 extra_bytes = reply->extra;
125 class = reply->class_ptr;
132 WARN( "error %d creating window\n", GetLastError() );
136 if (!(win = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
137 sizeof(WND) + extra_bytes - sizeof(win->wExtra) )))
139 SERVER_START_REQ( destroy_window )
141 req->handle = handle;
142 wine_server_call( req );
145 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
149 if (!parent) /* if parent is 0 we don't have a desktop window yet */
151 struct user_thread_info *thread_info = get_user_thread_info();
153 if (name == (LPCWSTR)DESKTOP_CLASS_ATOM)
155 if (!thread_info->top_window) thread_info->top_window = full_parent ? full_parent : handle;
156 else assert( full_parent == thread_info->top_window );
157 if (full_parent && !USER_Driver->pCreateDesktopWindow( thread_info->top_window ))
158 ERR( "failed to create desktop window\n" );
160 else /* HWND_MESSAGE parent */
162 if (!thread_info->msg_window && !full_parent) thread_info->msg_window = handle;
168 index = USER_HANDLE_TO_INDEX(handle);
169 assert( index < NB_USER_HANDLES );
170 user_handles[index] = win;
171 win->hwndSelf = handle;
172 win->parent = full_parent;
173 win->owner = full_owner;
175 win->winproc = get_class_winproc( class );
176 win->dwMagic = WND_MAGIC;
177 win->cbWndExtra = extra_bytes;
178 if (WINPROC_IsUnicode( win->winproc, unicode )) win->flags |= WIN_ISUNICODE;
183 /***********************************************************************
186 * Free a window handle.
188 static WND *free_window_handle( HWND hwnd )
191 WORD index = USER_HANDLE_TO_INDEX(hwnd);
193 if (index >= NB_USER_HANDLES) return NULL;
195 if ((ptr = user_handles[index]))
197 SERVER_START_REQ( destroy_window )
200 if (!wine_server_call_err( req ))
202 user_handles[index] = NULL;
211 HeapFree( GetProcessHeap(), 0, ptr );
216 /*******************************************************************
217 * list_window_children
219 * Build an array of the children of a given window. The array must be
220 * freed with HeapFree. Returns NULL when no windows are found.
222 static HWND *list_window_children( HDESK desktop, HWND hwnd, LPCWSTR class, DWORD tid )
226 ATOM atom = get_int_atom_value( class );
228 /* empty class is not the same as NULL class */
229 if (!atom && class && !class[0]) return NULL;
235 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
237 SERVER_START_REQ( get_window_children )
239 req->desktop = desktop;
243 if (!atom && class) wine_server_add_data( req, class, strlenW(class)*sizeof(WCHAR) );
244 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
245 if (!wine_server_call( req )) count = reply->count;
248 if (count && count < size)
253 HeapFree( GetProcessHeap(), 0, list );
255 size = count + 1; /* restart with a large enough buffer */
261 /*******************************************************************
262 * list_window_parents
264 * Build an array of all parents of a given window, starting with
265 * the immediate parent. The array must be freed with HeapFree.
267 static HWND *list_window_parents( HWND hwnd )
271 int pos = 0, size = 16, count = 0;
273 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
278 if (!(win = WIN_GetPtr( current ))) goto empty;
279 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
280 if (win == WND_DESKTOP)
282 if (!pos) goto empty;
286 list[pos] = current = win->parent;
287 WIN_ReleasePtr( win );
288 if (!current) return list;
289 if (++pos == size - 1)
291 /* need to grow the list */
292 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
293 if (!new_list) goto empty;
299 /* at least one parent belongs to another process, have to query the server */
304 SERVER_START_REQ( get_window_parents )
307 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
308 if (!wine_server_call( req )) count = reply->count;
311 if (!count) goto empty;
317 HeapFree( GetProcessHeap(), 0, list );
319 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
323 HeapFree( GetProcessHeap(), 0, list );
328 /*******************************************************************
331 static void send_parent_notify( HWND hwnd, UINT msg )
333 if ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_CHILD | WS_POPUP)) == WS_CHILD &&
334 !(GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY))
336 HWND parent = GetParent(hwnd);
337 if (parent && parent != GetDesktopWindow())
338 SendMessageW( parent, WM_PARENTNOTIFY,
339 MAKEWPARAM( msg, GetWindowLongPtrW( hwnd, GWLP_ID )), (LPARAM)hwnd );
344 /*******************************************************************
345 * get_server_window_text
347 * Retrieve the window text from the server.
349 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
353 SERVER_START_REQ( get_window_text )
356 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
357 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
360 text[len / sizeof(WCHAR)] = 0;
364 /*******************************************************************
365 * get_hwnd_message_parent
367 * Return the parent for HWND_MESSAGE windows.
369 HWND get_hwnd_message_parent(void)
371 struct user_thread_info *thread_info = get_user_thread_info();
373 if (!thread_info->msg_window) GetDesktopWindow(); /* trigger creation */
374 return thread_info->msg_window;
378 /*******************************************************************
381 * Check if window is the desktop or the HWND_MESSAGE top parent.
383 BOOL is_desktop_window( HWND hwnd )
385 struct user_thread_info *thread_info = get_user_thread_info();
387 if (!hwnd) return FALSE;
388 if (hwnd == thread_info->top_window) return TRUE;
389 if (hwnd == thread_info->msg_window) return TRUE;
391 if (!HIWORD(hwnd) || HIWORD(hwnd) == 0xffff)
393 if (LOWORD(thread_info->top_window) == LOWORD(hwnd)) return TRUE;
394 if (LOWORD(thread_info->msg_window) == LOWORD(hwnd)) return TRUE;
400 /***********************************************************************
403 * Return a pointer to the WND structure if local to the process,
404 * or WND_OTHER_PROCESS if handle may be valid in other process.
405 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
407 WND *WIN_GetPtr( HWND hwnd )
410 WORD index = USER_HANDLE_TO_INDEX(hwnd);
412 if (index >= NB_USER_HANDLES) return NULL;
415 if ((ptr = user_handles[index]))
417 if (ptr->dwMagic == WND_MAGIC &&
418 (hwnd == ptr->hwndSelf || !HIWORD(hwnd) || HIWORD(hwnd) == 0xffff))
422 else if (is_desktop_window( hwnd )) ptr = WND_DESKTOP;
423 else ptr = WND_OTHER_PROCESS;
429 /***********************************************************************
430 * WIN_IsCurrentProcess
432 * Check whether a given window belongs to the current process (and return the full handle).
434 HWND WIN_IsCurrentProcess( HWND hwnd )
439 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
441 WIN_ReleasePtr( ptr );
446 /***********************************************************************
447 * WIN_IsCurrentThread
449 * Check whether a given window belongs to the current thread (and return the full handle).
451 HWND WIN_IsCurrentThread( HWND hwnd )
456 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
457 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
458 WIN_ReleasePtr( ptr );
463 /***********************************************************************
466 * Convert a 16-bit window handle to a full 32-bit handle.
468 HWND WIN_Handle32( HWND16 hwnd16 )
471 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
473 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
474 /* do sign extension for -2 and -3 */
475 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
477 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
479 if (ptr == WND_DESKTOP)
481 if (LOWORD(hwnd) == LOWORD(GetDesktopWindow())) return GetDesktopWindow();
482 else return get_hwnd_message_parent();
485 if (ptr != WND_OTHER_PROCESS)
487 hwnd = ptr->hwndSelf;
488 WIN_ReleasePtr( ptr );
490 else /* may belong to another process */
492 SERVER_START_REQ( get_window_info )
495 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
503 /***********************************************************************
506 * Change the owner of a window.
508 HWND WIN_SetOwner( HWND hwnd, HWND owner )
510 WND *win = WIN_GetPtr( hwnd );
513 if (!win || win == WND_DESKTOP) return 0;
514 if (win == WND_OTHER_PROCESS)
516 if (IsWindow(hwnd)) ERR( "cannot set owner %p on other process window %p\n", owner, hwnd );
519 SERVER_START_REQ( set_window_owner )
523 if (!wine_server_call( req ))
525 win->owner = reply->full_owner;
526 ret = reply->prev_owner;
530 WIN_ReleasePtr( win );
535 /***********************************************************************
538 * Change the style of a window.
540 ULONG WIN_SetStyle( HWND hwnd, ULONG set_bits, ULONG clear_bits )
544 WND *win = WIN_GetPtr( hwnd );
546 if (!win || win == WND_DESKTOP) return 0;
547 if (win == WND_OTHER_PROCESS)
550 ERR( "cannot set style %x/%x on other process window %p\n",
551 set_bits, clear_bits, hwnd );
554 style.styleOld = win->dwStyle;
555 style.styleNew = (win->dwStyle | set_bits) & ~clear_bits;
556 if (style.styleNew == style.styleOld)
558 WIN_ReleasePtr( win );
559 return style.styleNew;
561 SERVER_START_REQ( set_window_info )
564 req->flags = SET_WIN_STYLE;
565 req->style = style.styleNew;
566 req->extra_offset = -1;
567 if ((ok = !wine_server_call( req )))
569 style.styleOld = reply->old_style;
570 win->dwStyle = style.styleNew;
574 WIN_ReleasePtr( win );
577 USER_Driver->pSetWindowStyle( hwnd, GWL_STYLE, &style );
578 if ((style.styleOld ^ style.styleNew) & WS_VISIBLE) invalidate_dce( hwnd, NULL );
580 return style.styleOld;
584 /***********************************************************************
587 * Get the window and client rectangles.
589 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
591 WND *win = WIN_GetPtr( hwnd );
594 if (!win) return FALSE;
595 if (win == WND_DESKTOP)
598 rect.left = rect.top = 0;
599 if (hwnd == get_hwnd_message_parent())
606 rect.right = GetSystemMetrics(SM_CXSCREEN);
607 rect.bottom = GetSystemMetrics(SM_CYSCREEN);
609 if (rectWindow) *rectWindow = rect;
610 if (rectClient) *rectClient = rect;
612 else if (win == WND_OTHER_PROCESS)
614 SERVER_START_REQ( get_window_rectangles )
617 if ((ret = !wine_server_call( req )))
621 rectWindow->left = reply->window.left;
622 rectWindow->top = reply->window.top;
623 rectWindow->right = reply->window.right;
624 rectWindow->bottom = reply->window.bottom;
628 rectClient->left = reply->client.left;
629 rectClient->top = reply->client.top;
630 rectClient->right = reply->client.right;
631 rectClient->bottom = reply->client.bottom;
639 if (rectWindow) *rectWindow = win->rectWindow;
640 if (rectClient) *rectClient = win->rectClient;
641 WIN_ReleasePtr( win );
647 /***********************************************************************
650 * Destroy storage associated to a window. "Internals" p.358
652 LRESULT WIN_DestroyWindow( HWND hwnd )
656 HMENU menu = 0, sys_menu;
659 TRACE("%p\n", hwnd );
661 /* free child windows */
662 if ((list = WIN_ListChildren( hwnd )))
665 for (i = 0; list[i]; i++)
667 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
668 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
670 HeapFree( GetProcessHeap(), 0, list );
673 /* Unlink now so we won't bother with the children later on */
674 SERVER_START_REQ( set_parent )
678 wine_server_call( req );
683 * Send the WM_NCDESTROY to the window being destroyed.
685 SendMessageW( hwnd, WM_NCDESTROY, 0, 0 );
687 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
689 /* free resources associated with the window */
691 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
692 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
693 menu = (HMENU)wndPtr->wIDmenu;
694 sys_menu = wndPtr->hSysMenu;
695 free_dce( wndPtr->dce, hwnd );
697 icon_title = wndPtr->icon_title;
698 WIN_ReleasePtr( wndPtr );
700 if (icon_title) DestroyWindow( icon_title );
701 if (menu) DestroyMenu( menu );
702 if (sys_menu) DestroyMenu( sys_menu );
704 USER_Driver->pDestroyWindow( hwnd );
706 free_window_handle( hwnd );
710 /***********************************************************************
711 * WIN_DestroyThreadWindows
713 * Destroy all children of 'wnd' owned by the current thread.
715 void WIN_DestroyThreadWindows( HWND hwnd )
720 if (!(list = WIN_ListChildren( hwnd ))) return;
721 for (i = 0; list[i]; i++)
723 if (WIN_IsCurrentThread( list[i] ))
724 DestroyWindow( list[i] );
726 WIN_DestroyThreadWindows( list[i] );
728 HeapFree( GetProcessHeap(), 0, list );
732 /***********************************************************************
735 * Fix the coordinates - Helper for WIN_CreateWindowEx.
736 * returns default show mode in sw.
738 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
740 #define IS_DEFAULT(x) ((x) == CW_USEDEFAULT || (x) == CW_USEDEFAULT16)
743 if (cs->dwExStyle & WS_EX_MDICHILD)
747 MDI_CalcDefaultChildPos(cs->hwndParent, -1, pos, 0, &id);
748 if (!(cs->style & WS_POPUP)) cs->hMenu = ULongToHandle(id);
750 TRACE("MDI child id %04x\n", id);
753 if (cs->style & (WS_CHILD | WS_POPUP))
755 if (cs->dwExStyle & WS_EX_MDICHILD)
757 if (IS_DEFAULT(cs->x))
762 if (IS_DEFAULT(cs->cx) || !cs->cx) cs->cx = pos[1].x;
763 if (IS_DEFAULT(cs->cy) || !cs->cy) cs->cy = pos[1].y;
767 if (IS_DEFAULT(cs->x)) cs->x = cs->y = 0;
768 if (IS_DEFAULT(cs->cx)) cs->cx = cs->cy = 0;
771 else /* overlapped window */
774 MONITORINFO mon_info;
777 if (!IS_DEFAULT(cs->x) && !IS_DEFAULT(cs->cx) && !IS_DEFAULT(cs->cy)) return;
779 monitor = MonitorFromWindow( cs->hwndParent, MONITOR_DEFAULTTOPRIMARY );
780 mon_info.cbSize = sizeof(mon_info);
781 GetMonitorInfoW( monitor, &mon_info );
782 GetStartupInfoW( &info );
784 if (IS_DEFAULT(cs->x))
786 if (!IS_DEFAULT(cs->y)) *sw = cs->y;
787 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : mon_info.rcWork.left;
788 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : mon_info.rcWork.top;
791 if (IS_DEFAULT(cs->cx))
793 if (info.dwFlags & STARTF_USESIZE)
795 cs->cx = info.dwXSize;
796 cs->cy = info.dwYSize;
800 cs->cx = (mon_info.rcWork.right - mon_info.rcWork.left) * 3 / 4 - cs->x;
801 cs->cy = (mon_info.rcWork.bottom - mon_info.rcWork.top) * 3 / 4 - cs->y;
804 /* neither x nor cx are default. Check the y values .
805 * In the trace we see Outlook and Outlook Express using
806 * cy set to CW_USEDEFAULT when opening the address book.
808 else if (IS_DEFAULT(cs->cy))
810 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
811 cs->cy = (mon_info.rcWork.bottom - mon_info.rcWork.top) * 3 / 4 - cs->y;
817 /***********************************************************************
820 static void dump_window_styles( DWORD style, DWORD exstyle )
823 if(style & WS_POPUP) TRACE(" WS_POPUP");
824 if(style & WS_CHILD) TRACE(" WS_CHILD");
825 if(style & WS_MINIMIZE) TRACE(" WS_MINIMIZE");
826 if(style & WS_VISIBLE) TRACE(" WS_VISIBLE");
827 if(style & WS_DISABLED) TRACE(" WS_DISABLED");
828 if(style & WS_CLIPSIBLINGS) TRACE(" WS_CLIPSIBLINGS");
829 if(style & WS_CLIPCHILDREN) TRACE(" WS_CLIPCHILDREN");
830 if(style & WS_MAXIMIZE) TRACE(" WS_MAXIMIZE");
831 if((style & WS_CAPTION) == WS_CAPTION) TRACE(" WS_CAPTION");
834 if(style & WS_BORDER) TRACE(" WS_BORDER");
835 if(style & WS_DLGFRAME) TRACE(" WS_DLGFRAME");
837 if(style & WS_VSCROLL) TRACE(" WS_VSCROLL");
838 if(style & WS_HSCROLL) TRACE(" WS_HSCROLL");
839 if(style & WS_SYSMENU) TRACE(" WS_SYSMENU");
840 if(style & WS_THICKFRAME) TRACE(" WS_THICKFRAME");
841 if (style & WS_CHILD)
843 if(style & WS_GROUP) TRACE(" WS_GROUP");
844 if(style & WS_TABSTOP) TRACE(" WS_TABSTOP");
848 if(style & WS_MINIMIZEBOX) TRACE(" WS_MINIMIZEBOX");
849 if(style & WS_MAXIMIZEBOX) TRACE(" WS_MAXIMIZEBOX");
852 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
853 #define DUMPED_STYLES \
873 if(style & ~DUMPED_STYLES) TRACE(" %08lx", style & ~DUMPED_STYLES);
878 if(exstyle & WS_EX_DLGMODALFRAME) TRACE(" WS_EX_DLGMODALFRAME");
879 if(exstyle & WS_EX_DRAGDETECT) TRACE(" WS_EX_DRAGDETECT");
880 if(exstyle & WS_EX_NOPARENTNOTIFY) TRACE(" WS_EX_NOPARENTNOTIFY");
881 if(exstyle & WS_EX_TOPMOST) TRACE(" WS_EX_TOPMOST");
882 if(exstyle & WS_EX_ACCEPTFILES) TRACE(" WS_EX_ACCEPTFILES");
883 if(exstyle & WS_EX_TRANSPARENT) TRACE(" WS_EX_TRANSPARENT");
884 if(exstyle & WS_EX_MDICHILD) TRACE(" WS_EX_MDICHILD");
885 if(exstyle & WS_EX_TOOLWINDOW) TRACE(" WS_EX_TOOLWINDOW");
886 if(exstyle & WS_EX_WINDOWEDGE) TRACE(" WS_EX_WINDOWEDGE");
887 if(exstyle & WS_EX_CLIENTEDGE) TRACE(" WS_EX_CLIENTEDGE");
888 if(exstyle & WS_EX_CONTEXTHELP) TRACE(" WS_EX_CONTEXTHELP");
889 if(exstyle & WS_EX_RIGHT) TRACE(" WS_EX_RIGHT");
890 if(exstyle & WS_EX_RTLREADING) TRACE(" WS_EX_RTLREADING");
891 if(exstyle & WS_EX_LEFTSCROLLBAR) TRACE(" WS_EX_LEFTSCROLLBAR");
892 if(exstyle & WS_EX_CONTROLPARENT) TRACE(" WS_EX_CONTROLPARENT");
893 if(exstyle & WS_EX_STATICEDGE) TRACE(" WS_EX_STATICEDGE");
894 if(exstyle & WS_EX_APPWINDOW) TRACE(" WS_EX_APPWINDOW");
895 if(exstyle & WS_EX_LAYERED) TRACE(" WS_EX_LAYERED");
897 #define DUMPED_EX_STYLES \
898 (WS_EX_DLGMODALFRAME | \
900 WS_EX_NOPARENTNOTIFY | \
902 WS_EX_ACCEPTFILES | \
903 WS_EX_TRANSPARENT | \
908 WS_EX_CONTEXTHELP | \
911 WS_EX_LEFTSCROLLBAR | \
912 WS_EX_CONTROLPARENT | \
917 if(exstyle & ~DUMPED_EX_STYLES) TRACE(" %08lx", exstyle & ~DUMPED_EX_STYLES);
919 #undef DUMPED_EX_STYLES
923 /***********************************************************************
926 * Implementation of CreateWindowEx().
928 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, LPCWSTR className, UINT flags )
930 INT cx, cy, style, sw = SW_SHOW;
934 HWND hwnd, parent, owner, top_child = 0;
935 BOOL unicode = (flags & WIN_ISUNICODE) != 0;
936 MDICREATESTRUCTA mdi_cs;
940 TRACE("%s %s ex=%08x style=%08x %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
941 unicode ? debugstr_w((LPCWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
942 debugstr_w(className),
943 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
944 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
945 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
947 /* Fix the styles for MDI children */
948 if (cs->dwExStyle & WS_EX_MDICHILD)
952 wndPtr = WIN_GetPtr(cs->hwndParent);
953 if (wndPtr && wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
955 flags = wndPtr->flags;
956 WIN_ReleasePtr(wndPtr);
959 if (!(flags & WIN_ISMDICLIENT))
961 WARN("WS_EX_MDICHILD, but parent %p is not MDIClient\n", cs->hwndParent);
965 /* cs->lpCreateParams of WM_[NC]CREATE is different for MDI children.
966 * MDICREATESTRUCT members have the originally passed values.
968 * Note: we rely on the fact that MDICREATESTRUCTA and MDICREATESTRUCTW
969 * have the same layout.
971 mdi_cs.szClass = cs->lpszClass;
972 mdi_cs.szTitle = cs->lpszName;
973 mdi_cs.hOwner = cs->hInstance;
978 mdi_cs.style = cs->style;
979 mdi_cs.lParam = (LPARAM)cs->lpCreateParams;
981 cs->lpCreateParams = (LPVOID)&mdi_cs;
983 if (GetWindowLongW(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
985 if (cs->style & WS_POPUP)
987 TRACE("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n");
990 cs->style |= WS_CHILD | WS_CLIPSIBLINGS;
994 cs->style &= ~WS_POPUP;
995 cs->style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
996 WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
999 top_child = GetWindow(cs->hwndParent, GW_CHILD);
1003 /* Restore current maximized child */
1004 if((cs->style & WS_VISIBLE) && IsZoomed(top_child))
1006 TRACE("Restoring current maximized child %p\n", top_child);
1007 SendMessageW( top_child, WM_SETREDRAW, FALSE, 0 );
1008 ShowWindow( top_child, SW_SHOWNORMAL );
1009 SendMessageW( top_child, WM_SETREDRAW, TRUE, 0 );
1014 /* Find the parent window */
1016 parent = cs->hwndParent;
1019 if (cs->hwndParent == HWND_MESSAGE)
1021 cs->hwndParent = parent = get_hwnd_message_parent();
1023 else if (cs->hwndParent)
1025 if ((cs->style & (WS_CHILD|WS_POPUP)) != WS_CHILD)
1027 parent = GetDesktopWindow();
1028 owner = cs->hwndParent;
1033 static const WCHAR messageW[] = {'M','e','s','s','a','g','e',0};
1035 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1037 WARN("No parent for child window\n" );
1038 SetLastError(ERROR_TLW_WITH_WSCHILD);
1039 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1041 /* are we creating the desktop or HWND_MESSAGE parent itself? */
1042 if (className != (LPCWSTR)DESKTOP_CLASS_ATOM &&
1043 (IS_INTRESOURCE(className) || strcmpiW( className, messageW )))
1044 parent = GetDesktopWindow();
1047 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
1049 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
1050 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
1051 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
1052 cs->dwExStyle |= WS_EX_WINDOWEDGE;
1054 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
1056 /* Create the window structure */
1058 if (!(wndPtr = create_window_handle( parent, owner, className, cs->hInstance, unicode )))
1060 hwnd = wndPtr->hwndSelf;
1062 /* Fill the window structure */
1064 wndPtr->tid = GetCurrentThreadId();
1065 wndPtr->hInstance = cs->hInstance;
1066 wndPtr->text = NULL;
1067 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1068 wndPtr->dwExStyle = cs->dwExStyle;
1069 wndPtr->wIDmenu = 0;
1070 wndPtr->helpContext = 0;
1071 wndPtr->pVScroll = NULL;
1072 wndPtr->pHScroll = NULL;
1073 wndPtr->userdata = 0;
1075 wndPtr->hIconSmall = 0;
1076 wndPtr->hSysMenu = 0;
1077 wndPtr->flags |= (flags & WIN_ISWIN32);
1079 wndPtr->min_pos.x = wndPtr->min_pos.y = -1;
1080 wndPtr->max_pos.x = wndPtr->max_pos.y = -1;
1082 if (wndPtr->dwStyle & WS_SYSMENU) SetSystemMenu( hwnd, 0 );
1085 * Correct the window styles.
1087 * It affects only the style loaded into the WIN structure.
1090 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
1092 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1093 if (!(wndPtr->dwStyle & WS_POPUP))
1094 wndPtr->dwStyle |= WS_CAPTION;
1098 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1099 * why does the user get to set it?
1102 if ((wndPtr->dwExStyle & WS_EX_DLGMODALFRAME) ||
1103 (wndPtr->dwStyle & (WS_DLGFRAME | WS_THICKFRAME)))
1104 wndPtr->dwExStyle |= WS_EX_WINDOWEDGE;
1106 wndPtr->dwExStyle &= ~WS_EX_WINDOWEDGE;
1108 if (!(wndPtr->dwStyle & (WS_CHILD | WS_POPUP)))
1109 wndPtr->flags |= WIN_NEED_SIZE;
1111 SERVER_START_REQ( set_window_info )
1114 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE | SET_WIN_UNICODE;
1115 req->style = wndPtr->dwStyle;
1116 req->ex_style = wndPtr->dwExStyle;
1117 req->instance = (void *)wndPtr->hInstance;
1118 req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
1119 req->extra_offset = -1;
1120 wine_server_call( req );
1124 /* Set the window menu */
1126 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
1130 if (!MENU_SetMenu(hwnd, cs->hMenu))
1132 WIN_ReleasePtr( wndPtr );
1133 free_window_handle( hwnd );
1139 LPCSTR menuName = (LPCSTR)GetClassLongPtrA( hwnd, GCLP_MENUNAME );
1142 if (!cs->hInstance || HIWORD(cs->hInstance))
1143 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1145 cs->hMenu = HMENU_32(LoadMenu16(HINSTANCE_16(cs->hInstance),menuName));
1147 if (cs->hMenu) MENU_SetMenu( hwnd, cs->hMenu );
1151 else SetWindowLongPtrW( hwnd, GWLP_ID, (ULONG_PTR)cs->hMenu );
1153 /* call the WH_CBT hook */
1155 /* the window style passed to the hook must be the real window style,
1156 * rather than just the window style that the caller to CreateWindowEx
1157 * passed in, so we have to copy the original CREATESTRUCT and get the
1158 * the real style. */
1160 cbcs.style = wndPtr->dwStyle;
1162 cbtc.hwndInsertAfter = HWND_TOP;
1163 WIN_ReleasePtr( wndPtr );
1164 if (HOOK_CallHooks( WH_CBT, HCBT_CREATEWND, (WPARAM)hwnd, (LPARAM)&cbtc, unicode )) goto failed;
1166 /* send the WM_GETMINMAXINFO message and fix the size if needed */
1170 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
1172 POINT maxSize, maxPos, minTrack, maxTrack;
1173 WINPOS_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack);
1174 if (maxTrack.x < cx) cx = maxTrack.x;
1175 if (maxTrack.y < cy) cy = maxTrack.y;
1176 if (minTrack.x > cx) cx = minTrack.x;
1177 if (minTrack.y > cy) cy = minTrack.y;
1182 SetRect( &rect, cs->x, cs->y, cs->x + cx, cs->y + cy );
1183 /* check for wraparound */
1184 if (cs->x + cx < cs->x) rect.right = 0x7fffffff;
1185 if (cs->y + cy < cs->y) rect.bottom = 0x7fffffff;
1186 if (!set_window_pos( hwnd, 0, SWP_NOZORDER | SWP_NOACTIVATE, &rect, &rect, NULL )) goto failed;
1188 /* send WM_NCCREATE */
1190 TRACE( "hwnd %p cs %d,%d %dx%d\n", hwnd, cs->x, cs->y, cx, cy );
1192 result = SendMessageW( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
1194 result = SendMessageA( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
1197 WARN( "%p: aborted by WM_NCCREATE\n", hwnd );
1201 /* send WM_NCCALCSIZE */
1203 if ((wndPtr = WIN_GetPtr(hwnd)))
1205 /* yes, even if the CBT hook was called with HWND_TOP */
1207 HWND insert_after = (wndPtr->dwStyle & WS_CHILD) ? HWND_BOTTOM : HWND_TOP;
1208 RECT window_rect = wndPtr->rectWindow;
1209 RECT client_rect = window_rect;
1210 WIN_ReleasePtr( wndPtr );
1212 /* the rectangle is in screen coords for WM_NCCALCSIZE when wparam is FALSE */
1214 MapWindowPoints( parent, 0, &pt, 1 );
1215 OffsetRect( &client_rect, pt.x, pt.y );
1216 SendMessageW( hwnd, WM_NCCALCSIZE, FALSE, (LPARAM)&client_rect );
1217 OffsetRect( &client_rect, -pt.x, -pt.y );
1218 set_window_pos( hwnd, insert_after, SWP_NOACTIVATE, &window_rect, &client_rect, NULL );
1222 /* send WM_CREATE */
1225 result = SendMessageW( hwnd, WM_CREATE, 0, (LPARAM)cs );
1227 result = SendMessageA( hwnd, WM_CREATE, 0, (LPARAM)cs );
1228 if (result == -1) goto failed;
1230 /* call the driver */
1232 if (!USER_Driver->pCreateWindow( hwnd )) goto failed;
1234 NotifyWinEvent(EVENT_OBJECT_CREATE, hwnd, OBJID_WINDOW, 0);
1236 /* send the size messages */
1238 if (!(wndPtr = WIN_GetPtr( hwnd )) ||
1239 wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return 0;
1240 if (!(wndPtr->flags & WIN_NEED_SIZE))
1242 rect = wndPtr->rectClient;
1243 WIN_ReleasePtr( wndPtr );
1244 SendMessageW( hwnd, WM_SIZE, SIZE_RESTORED,
1245 MAKELONG(rect.right-rect.left, rect.bottom-rect.top));
1246 SendMessageW( hwnd, WM_MOVE, 0, MAKELONG( rect.left, rect.top ) );
1248 else WIN_ReleasePtr( wndPtr );
1250 /* Show the window, maximizing or minimizing if needed */
1252 style = WIN_SetStyle( hwnd, 0, WS_MAXIMIZE | WS_MINIMIZE );
1253 if (style & (WS_MINIMIZE | WS_MAXIMIZE))
1256 UINT swFlag = (style & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
1258 swFlag = WINPOS_MinMaximize( hwnd, swFlag, &newPos );
1259 swFlag |= SWP_FRAMECHANGED; /* Frame always gets changed */
1260 if (!(style & WS_VISIBLE) || (style & WS_CHILD) || GetActiveWindow()) swFlag |= SWP_NOACTIVATE;
1261 SetWindowPos( hwnd, 0, newPos.left, newPos.top, newPos.right - newPos.left,
1262 newPos.bottom - newPos.top, swFlag );
1265 /* Notify the parent window only */
1267 send_parent_notify( hwnd, WM_CREATE );
1268 if (!IsWindow( hwnd )) return 0;
1270 if (cs->style & WS_VISIBLE)
1272 if (cs->style & WS_MAXIMIZE)
1274 else if (cs->style & WS_MINIMIZE)
1275 sw = SW_SHOWMINIMIZED;
1277 ShowWindow( hwnd, sw );
1278 if (cs->dwExStyle & WS_EX_MDICHILD)
1280 SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
1281 /* ShowWindow won't activate child windows */
1282 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE );
1286 /* Call WH_SHELL hook */
1288 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1289 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1291 TRACE("created window %p\n", hwnd);
1295 WIN_DestroyWindow( hwnd );
1300 /***********************************************************************
1301 * CreateWindow (USER.41)
1303 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1304 DWORD style, INT16 x, INT16 y, INT16 width,
1305 INT16 height, HWND16 parent, HMENU16 menu,
1306 HINSTANCE16 instance, LPVOID data )
1308 return CreateWindowEx16( 0, className, windowName, style,
1309 x, y, width, height, parent, menu, instance, data );
1313 /***********************************************************************
1314 * CreateWindowEx (USER.452)
1316 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1317 LPCSTR windowName, DWORD style, INT16 x,
1318 INT16 y, INT16 width, INT16 height,
1319 HWND16 parent, HMENU16 menu,
1320 HINSTANCE16 instance, LPVOID data )
1325 /* Fix the coordinates */
1327 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1328 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1329 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1330 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1332 /* Create the window */
1334 cs.lpCreateParams = data;
1335 cs.hInstance = HINSTANCE_32(instance);
1336 cs.hMenu = HMENU_32(menu);
1337 cs.hwndParent = WIN_Handle32( parent );
1339 cs.lpszName = windowName;
1340 cs.lpszClass = className;
1341 cs.dwExStyle = exStyle;
1343 if (!IS_INTRESOURCE(className))
1347 if (!MultiByteToWideChar( CP_ACP, 0, className, -1, bufferW, sizeof(bufferW)/sizeof(WCHAR) ))
1349 return HWND_16( WIN_CreateWindowEx( &cs, bufferW, 0 ));
1353 if (!GlobalGetAtomNameA( LOWORD(className), buffer, sizeof(buffer) ))
1355 ERR( "bad atom %x\n", LOWORD(className));
1358 cs.lpszClass = buffer;
1359 return HWND_16( WIN_CreateWindowEx( &cs, (LPCWSTR)className, 0 ));
1364 /***********************************************************************
1365 * CreateWindowExA (USER32.@)
1367 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1368 LPCSTR windowName, DWORD style, INT x,
1369 INT y, INT width, INT height,
1370 HWND parent, HMENU menu,
1371 HINSTANCE instance, LPVOID data )
1375 cs.lpCreateParams = data;
1376 cs.hInstance = instance;
1378 cs.hwndParent = parent;
1384 cs.lpszName = windowName;
1385 cs.lpszClass = className;
1386 cs.dwExStyle = exStyle;
1388 if (!IS_INTRESOURCE(className))
1391 if (!MultiByteToWideChar( CP_ACP, 0, className, -1, bufferW, sizeof(bufferW)/sizeof(WCHAR) ))
1393 return WIN_CreateWindowEx( &cs, bufferW, WIN_ISWIN32 );
1395 return WIN_CreateWindowEx( &cs, (LPCWSTR)className, WIN_ISWIN32 );
1399 /***********************************************************************
1400 * CreateWindowExW (USER32.@)
1402 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1403 LPCWSTR windowName, DWORD style, INT x,
1404 INT y, INT width, INT height,
1405 HWND parent, HMENU menu,
1406 HINSTANCE instance, LPVOID data )
1410 cs.lpCreateParams = data;
1411 cs.hInstance = instance;
1413 cs.hwndParent = parent;
1419 cs.lpszName = windowName;
1420 cs.lpszClass = className;
1421 cs.dwExStyle = exStyle;
1423 /* Note: we rely on the fact that CREATESTRUCTA and */
1424 /* CREATESTRUCTW have the same layout. */
1425 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, className, WIN_ISWIN32 | WIN_ISUNICODE );
1429 /***********************************************************************
1430 * WIN_SendDestroyMsg
1432 static void WIN_SendDestroyMsg( HWND hwnd )
1436 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1438 if (hwnd == info.hwndCaret) DestroyCaret();
1439 if (hwnd == info.hwndActive) WINPOS_ActivateOtherWindow( hwnd );
1443 * Send the WM_DESTROY to the window.
1445 SendMessageW( hwnd, WM_DESTROY, 0, 0);
1448 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1449 * make sure that the window still exists when we come back.
1456 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1458 for (i = 0; pWndArray[i]; i++)
1460 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1462 HeapFree( GetProcessHeap(), 0, pWndArray );
1465 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1469 /***********************************************************************
1470 * DestroyWindow (USER32.@)
1472 BOOL WINAPI DestroyWindow( HWND hwnd )
1476 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || is_desktop_window( hwnd ))
1478 SetLastError( ERROR_ACCESS_DENIED );
1482 TRACE("(%p)\n", hwnd);
1486 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1488 if (MENU_IsMenuActive() == hwnd)
1491 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1495 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1496 send_parent_notify( hwnd, WM_DESTROY );
1498 else if (!GetWindow( hwnd, GW_OWNER ))
1500 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1501 /* FIXME: clean up palette - see "Internals" p.352 */
1504 if (!IsWindow(hwnd)) return TRUE;
1506 /* Hide the window */
1507 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)
1509 /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
1511 ShowWindow( hwnd, SW_HIDE );
1513 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1514 SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW );
1517 if (!IsWindow(hwnd)) return TRUE;
1519 /* Recursively destroy owned windows */
1526 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1529 for (i = 0; list[i]; i++)
1531 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1532 if (WIN_IsCurrentThread( list[i] ))
1534 DestroyWindow( list[i] );
1538 WIN_SetOwner( list[i], 0 );
1540 HeapFree( GetProcessHeap(), 0, list );
1542 if (!got_one) break;
1546 /* Send destroy messages */
1548 WIN_SendDestroyMsg( hwnd );
1549 if (!IsWindow( hwnd )) return TRUE;
1551 if (GetClipboardOwner() == hwnd)
1552 CLIPBOARD_ReleaseOwner();
1554 /* Destroy the window storage */
1556 WIN_DestroyWindow( hwnd );
1561 /***********************************************************************
1562 * CloseWindow (USER32.@)
1564 BOOL WINAPI CloseWindow( HWND hwnd )
1566 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1567 ShowWindow( hwnd, SW_MINIMIZE );
1572 /***********************************************************************
1573 * OpenIcon (USER32.@)
1575 BOOL WINAPI OpenIcon( HWND hwnd )
1577 if (!IsIconic( hwnd )) return FALSE;
1578 ShowWindow( hwnd, SW_SHOWNORMAL );
1583 /***********************************************************************
1584 * FindWindowExW (USER32.@)
1586 HWND WINAPI FindWindowExW( HWND parent, HWND child, LPCWSTR className, LPCWSTR title )
1591 WCHAR *buffer = NULL;
1593 if (!parent && child) parent = GetDesktopWindow();
1594 else if (parent == HWND_MESSAGE) parent = get_hwnd_message_parent();
1598 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1599 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1602 if (!(list = list_window_children( 0, parent, className, 0 ))) goto done;
1606 child = WIN_GetFullHandle( child );
1607 while (list[i] && list[i] != child) i++;
1608 if (!list[i]) goto done;
1609 i++; /* start from next window */
1616 if (GetWindowTextW( list[i], buffer, len + 1 ) && !strcmpiW( buffer, title )) break;
1623 HeapFree( GetProcessHeap(), 0, list );
1624 HeapFree( GetProcessHeap(), 0, buffer );
1630 /***********************************************************************
1631 * FindWindowA (USER32.@)
1633 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1635 HWND ret = FindWindowExA( 0, 0, className, title );
1636 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1641 /***********************************************************************
1642 * FindWindowExA (USER32.@)
1644 HWND WINAPI FindWindowExA( HWND parent, HWND child, LPCSTR className, LPCSTR title )
1646 LPWSTR titleW = NULL;
1651 DWORD len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1652 if (!(titleW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1653 MultiByteToWideChar( CP_ACP, 0, title, -1, titleW, len );
1656 if (!IS_INTRESOURCE(className))
1659 if (MultiByteToWideChar( CP_ACP, 0, className, -1, classW, sizeof(classW)/sizeof(WCHAR) ))
1660 hwnd = FindWindowExW( parent, child, classW, titleW );
1664 hwnd = FindWindowExW( parent, child, (LPCWSTR)className, titleW );
1667 HeapFree( GetProcessHeap(), 0, titleW );
1672 /***********************************************************************
1673 * FindWindowW (USER32.@)
1675 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1677 return FindWindowExW( 0, 0, className, title );
1681 /**********************************************************************
1682 * GetDesktopWindow (USER32.@)
1684 HWND WINAPI GetDesktopWindow(void)
1686 struct user_thread_info *thread_info = get_user_thread_info();
1688 if (thread_info->top_window) return thread_info->top_window;
1690 SERVER_START_REQ( get_desktop_window )
1693 if (!wine_server_call( req ))
1695 thread_info->top_window = reply->top_window;
1696 thread_info->msg_window = reply->msg_window;
1701 if (!thread_info->top_window)
1703 USEROBJECTFLAGS flags;
1704 if (!GetUserObjectInformationW( GetProcessWindowStation(), UOI_FLAGS, &flags,
1705 sizeof(flags), NULL ) || (flags.dwFlags & WSF_VISIBLE))
1707 static const WCHAR command_line[] = {'\\','e','x','p','l','o','r','e','r','.','e','x','e',' ','/','d','e','s','k','t','o','p',0};
1709 PROCESS_INFORMATION pi;
1710 WCHAR cmdline[MAX_PATH + sizeof(command_line)/sizeof(WCHAR)];
1712 memset( &si, 0, sizeof(si) );
1714 si.dwFlags = STARTF_USESTDHANDLES;
1717 si.hStdError = GetStdHandle( STD_ERROR_HANDLE );
1719 GetSystemDirectoryW( cmdline, MAX_PATH );
1720 lstrcatW( cmdline, command_line );
1721 if (CreateProcessW( NULL, cmdline, NULL, NULL, FALSE, DETACHED_PROCESS,
1722 NULL, NULL, &si, &pi ))
1724 TRACE( "started explorer pid %04x tid %04x\n", pi.dwProcessId, pi.dwThreadId );
1725 WaitForInputIdle( pi.hProcess, 10000 );
1726 CloseHandle( pi.hThread );
1727 CloseHandle( pi.hProcess );
1729 else WARN( "failed to start explorer, err %d\n", GetLastError() );
1731 else TRACE( "not starting explorer since winstation is not visible\n" );
1733 SERVER_START_REQ( get_desktop_window )
1736 if (!wine_server_call( req ))
1738 thread_info->top_window = reply->top_window;
1739 thread_info->msg_window = reply->msg_window;
1745 if (!thread_info->top_window || !USER_Driver->pCreateDesktopWindow( thread_info->top_window ))
1746 ERR( "failed to create desktop window\n" );
1748 return thread_info->top_window;
1752 /*******************************************************************
1753 * EnableWindow (USER32.@)
1755 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1760 if (is_broadcast(hwnd))
1762 SetLastError( ERROR_INVALID_PARAMETER );
1766 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1767 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1771 TRACE("( %p, %d )\n", hwnd, enable);
1773 retvalue = !IsWindowEnabled( hwnd );
1775 if (enable && retvalue)
1777 WIN_SetStyle( hwnd, 0, WS_DISABLED );
1778 SendMessageW( hwnd, WM_ENABLE, TRUE, 0 );
1780 else if (!enable && !retvalue)
1784 SendMessageW( hwnd, WM_CANCELMODE, 0, 0);
1786 WIN_SetStyle( hwnd, WS_DISABLED, 0 );
1788 if (hwnd == GetFocus())
1789 SetFocus( 0 ); /* A disabled window can't have the focus */
1791 capture_wnd = GetCapture();
1792 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1793 ReleaseCapture(); /* A disabled window can't capture the mouse */
1795 SendMessageW( hwnd, WM_ENABLE, FALSE, 0 );
1801 /***********************************************************************
1802 * IsWindowEnabled (USER32.@)
1804 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1806 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1810 /***********************************************************************
1811 * IsWindowUnicode (USER32.@)
1813 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1816 BOOL retvalue = FALSE;
1818 if (!(wndPtr = WIN_GetPtr(hwnd))) return FALSE;
1820 if (wndPtr == WND_DESKTOP) return TRUE;
1822 if (wndPtr != WND_OTHER_PROCESS)
1824 retvalue = (wndPtr->flags & WIN_ISUNICODE) != 0;
1825 WIN_ReleasePtr( wndPtr );
1829 SERVER_START_REQ( get_window_info )
1832 if (!wine_server_call_err( req )) retvalue = reply->is_unicode;
1840 /**********************************************************************
1843 * Helper function for GetWindowLong().
1845 static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, UINT size, BOOL unicode )
1847 LONG_PTR retvalue = 0;
1850 if (offset == GWLP_HWNDPARENT)
1852 HWND parent = GetAncestor( hwnd, GA_PARENT );
1853 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1854 return (ULONG_PTR)parent;
1857 if (!(wndPtr = WIN_GetPtr( hwnd )))
1859 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1863 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1865 if (offset == GWLP_WNDPROC)
1867 SetLastError( ERROR_ACCESS_DENIED );
1870 SERVER_START_REQ( set_window_info )
1873 req->flags = 0; /* don't set anything, just retrieve */
1874 req->extra_offset = (offset >= 0) ? offset : -1;
1875 req->extra_size = (offset >= 0) ? size : 0;
1876 if (!wine_server_call_err( req ))
1880 case GWL_STYLE: retvalue = reply->old_style; break;
1881 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1882 case GWLP_ID: retvalue = reply->old_id; break;
1883 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1884 case GWLP_USERDATA: retvalue = reply->old_user_data; break;
1886 if (offset >= 0) retvalue = get_win_data( &reply->old_extra_value, size );
1887 else SetLastError( ERROR_INVALID_INDEX );
1896 /* now we have a valid wndPtr */
1900 if (offset > (int)(wndPtr->cbWndExtra - size))
1902 WARN("Invalid offset %d\n", offset );
1903 WIN_ReleasePtr( wndPtr );
1904 SetLastError( ERROR_INVALID_INDEX );
1907 retvalue = get_win_data( (char *)wndPtr->wExtra + offset, size );
1909 /* Special case for dialog window procedure */
1910 if ((offset == DWLP_DLGPROC) && (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG))
1911 retvalue = (LONG_PTR)WINPROC_GetProc( (WNDPROC)retvalue, unicode );
1912 WIN_ReleasePtr( wndPtr );
1918 case GWLP_USERDATA: retvalue = wndPtr->userdata; break;
1919 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1920 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1921 case GWLP_ID: retvalue = wndPtr->wIDmenu; break;
1922 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wndPtr->hInstance; break;
1924 /* This looks like a hack only for the edit control (see tests). This makes these controls
1925 * more tolerant to A/W mismatches. The lack of W->A->W conversion for such a mismatch suggests
1926 * that the hack is in GetWindowLongPtr[AW], not in winprocs.
1928 if (wndPtr->winproc == EDIT_winproc_handle && (!unicode != !(wndPtr->flags & WIN_ISUNICODE)))
1929 retvalue = (ULONG_PTR)wndPtr->winproc;
1931 retvalue = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, unicode );
1934 WARN("Unknown offset %d\n", offset );
1935 SetLastError( ERROR_INVALID_INDEX );
1938 WIN_ReleasePtr(wndPtr);
1943 /**********************************************************************
1946 * Helper function for SetWindowLong().
1948 * 0 is the failure code. However, in the case of failure SetLastError
1949 * must be set to distinguish between a 0 return value and a failure.
1951 LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, UINT size, LONG_PTR newval, BOOL unicode )
1955 LONG_PTR retval = 0;
1958 TRACE( "%p %d %lx %c\n", hwnd, offset, newval, unicode ? 'W' : 'A' );
1960 if (is_broadcast(hwnd))
1962 SetLastError( ERROR_INVALID_PARAMETER );
1966 if (!(wndPtr = WIN_GetPtr( hwnd )))
1968 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1971 if (wndPtr == WND_DESKTOP)
1973 /* can't change anything on the desktop window */
1974 SetLastError( ERROR_ACCESS_DENIED );
1977 if (wndPtr == WND_OTHER_PROCESS)
1979 if (offset == GWLP_WNDPROC)
1981 SetLastError( ERROR_ACCESS_DENIED );
1984 if (offset > 32767 || offset < -32767)
1986 SetLastError( ERROR_INVALID_INDEX );
1989 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, MAKEWPARAM( offset, size ), newval );
1992 /* first some special cases */
1998 offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
1999 style.styleNew = newval;
2000 WIN_ReleasePtr( wndPtr );
2001 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
2002 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
2003 newval = style.styleNew;
2005 case GWLP_HWNDPARENT:
2006 if (wndPtr->parent == GetDesktopWindow())
2008 WIN_ReleasePtr( wndPtr );
2009 return (ULONG_PTR)WIN_SetOwner( hwnd, (HWND)newval );
2013 WIN_ReleasePtr( wndPtr );
2014 return (ULONG_PTR)SetParent( hwnd, (HWND)newval );
2019 UINT old_flags = wndPtr->flags;
2020 retval = WIN_GetWindowLong( hwnd, offset, size, unicode );
2021 if (unicode) proc = WINPROC_AllocProc( NULL, (WNDPROC)newval );
2022 else proc = WINPROC_AllocProc( (WNDPROC)newval, NULL );
2023 if (proc) wndPtr->winproc = proc;
2024 if (WINPROC_IsUnicode( proc, unicode )) wndPtr->flags |= WIN_ISUNICODE;
2025 else wndPtr->flags &= ~WIN_ISUNICODE;
2026 if (!((old_flags ^ wndPtr->flags) & WIN_ISUNICODE))
2028 WIN_ReleasePtr( wndPtr );
2031 /* update is_unicode flag on the server side */
2035 case GWLP_HINSTANCE:
2039 if ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
2040 (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG))
2042 WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWLP_DLGPROC);
2043 retval = (ULONG_PTR)WINPROC_GetProc( *ptr, unicode );
2044 if (unicode) *ptr = WINPROC_AllocProc( NULL, (WNDPROC)newval );
2045 else *ptr = WINPROC_AllocProc( (WNDPROC)newval, NULL );
2046 WIN_ReleasePtr( wndPtr );
2051 if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - size))
2053 WARN("Invalid offset %d\n", offset );
2054 WIN_ReleasePtr( wndPtr );
2055 SetLastError( ERROR_INVALID_INDEX );
2058 else if (get_win_data( (char *)wndPtr->wExtra + offset, size ) == newval)
2060 /* already set to the same value */
2061 WIN_ReleasePtr( wndPtr );
2067 SERVER_START_REQ( set_window_info )
2070 req->extra_offset = -1;
2074 req->flags = SET_WIN_STYLE;
2075 req->style = newval;
2078 req->flags = SET_WIN_EXSTYLE;
2079 /* WS_EX_TOPMOST can only be changed through SetWindowPos */
2080 newval = (newval & ~WS_EX_TOPMOST) | (wndPtr->dwExStyle & WS_EX_TOPMOST);
2081 req->ex_style = newval;
2084 req->flags = SET_WIN_ID;
2087 case GWLP_HINSTANCE:
2088 req->flags = SET_WIN_INSTANCE;
2089 req->instance = (void *)newval;
2092 req->flags = SET_WIN_UNICODE;
2093 req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
2096 req->flags = SET_WIN_USERDATA;
2097 req->user_data = newval;
2100 req->flags = SET_WIN_EXTRA;
2101 req->extra_offset = offset;
2102 req->extra_size = size;
2103 set_win_data( &req->extra_value, newval, size );
2105 if ((ok = !wine_server_call_err( req )))
2110 wndPtr->dwStyle = newval;
2111 retval = reply->old_style;
2114 wndPtr->dwExStyle = newval;
2115 retval = reply->old_ex_style;
2118 wndPtr->wIDmenu = newval;
2119 retval = reply->old_id;
2121 case GWLP_HINSTANCE:
2122 wndPtr->hInstance = (HINSTANCE)newval;
2123 retval = (ULONG_PTR)reply->old_instance;
2128 wndPtr->userdata = newval;
2129 retval = reply->old_user_data;
2132 retval = get_win_data( (char *)wndPtr->wExtra + offset, size );
2133 set_win_data( (char *)wndPtr->wExtra + offset, newval, size );
2139 WIN_ReleasePtr( wndPtr );
2143 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2145 USER_Driver->pSetWindowStyle( hwnd, offset, &style );
2146 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2153 /**********************************************************************
2154 * GetWindowLong (USER.135)
2156 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2160 BOOL is_winproc = (offset == GWLP_WNDPROC);
2164 if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2166 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2169 if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2171 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
2174 * Some programs try to access last element from 16 bit
2175 * code using illegal offset value. Hopefully this is
2176 * what those programs really expect.
2178 if (wndPtr->cbWndExtra >= 4 && offset == wndPtr->cbWndExtra - sizeof(WORD))
2180 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
2181 ERR( "- replaced invalid offset %d with %d\n", offset, offset2 );
2186 WARN("Invalid offset %d\n", offset );
2187 WIN_ReleasePtr( wndPtr );
2188 SetLastError( ERROR_INVALID_INDEX );
2192 is_winproc = ((offset == DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG));
2193 WIN_ReleasePtr( wndPtr );
2196 retvalue = GetWindowLongA( WIN_Handle32(hwnd), offset );
2197 if (is_winproc) retvalue = (LONG_PTR)WINPROC_GetProc16( (WNDPROC)retvalue, FALSE );
2202 /**********************************************************************
2203 * GetWindowWord (USER32.@)
2205 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
2210 case GWLP_HINSTANCE:
2211 case GWLP_HWNDPARENT:
2216 WARN("Invalid offset %d\n", offset );
2217 SetLastError( ERROR_INVALID_INDEX );
2222 return WIN_GetWindowLong( hwnd, offset, sizeof(WORD), FALSE );
2226 /**********************************************************************
2227 * GetWindowLongA (USER32.@)
2229 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2231 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), FALSE );
2235 /**********************************************************************
2236 * GetWindowLongW (USER32.@)
2238 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2240 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), TRUE );
2244 /**********************************************************************
2245 * SetWindowLong (USER.136)
2247 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2250 BOOL is_winproc = (offset == GWLP_WNDPROC);
2252 if (offset == DWLP_DLGPROC)
2254 if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2256 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2259 if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2261 is_winproc = ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
2262 (wndPtr->flags & WIN_ISDIALOG));
2263 WIN_ReleasePtr( wndPtr );
2269 WNDPROC new_proc = WINPROC_AllocProc16( (WNDPROC16)newval );
2270 WNDPROC old_proc = (WNDPROC)SetWindowLongPtrA( WIN_Handle32(hwnd), offset, (LONG_PTR)new_proc );
2271 return (LONG)WINPROC_GetProc16( old_proc, FALSE );
2273 else return SetWindowLongA( WIN_Handle32(hwnd), offset, newval );
2277 /**********************************************************************
2278 * SetWindowWord (USER32.@)
2280 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
2285 case GWLP_HINSTANCE:
2286 case GWLP_HWNDPARENT:
2291 WARN("Invalid offset %d\n", offset );
2292 SetLastError( ERROR_INVALID_INDEX );
2297 return WIN_SetWindowLong( hwnd, offset, sizeof(WORD), newval, FALSE );
2301 /**********************************************************************
2302 * SetWindowLongA (USER32.@)
2304 * See SetWindowLongW.
2306 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2308 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, FALSE );
2312 /**********************************************************************
2313 * SetWindowLongW (USER32.@) Set window attribute
2315 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2316 * value in a window's extra memory.
2318 * The _hwnd_ parameter specifies the window. is the handle to a
2319 * window that has extra memory. The _newval_ parameter contains the
2320 * new attribute or extra memory value. If positive, the _offset_
2321 * parameter is the byte-addressed location in the window's extra
2322 * memory to set. If negative, _offset_ specifies the window
2323 * attribute to set, and should be one of the following values:
2325 * GWL_EXSTYLE The window's extended window style
2327 * GWL_STYLE The window's window style.
2329 * GWLP_WNDPROC Pointer to the window's window procedure.
2331 * GWLP_HINSTANCE The window's pplication instance handle.
2333 * GWLP_ID The window's identifier.
2335 * GWLP_USERDATA The window's user-specified data.
2337 * If the window is a dialog box, the _offset_ parameter can be one of
2338 * the following values:
2340 * DWLP_DLGPROC The address of the window's dialog box procedure.
2342 * DWLP_MSGRESULT The return value of a message
2343 * that the dialog box procedure processed.
2345 * DWLP_USER Application specific information.
2349 * If successful, returns the previous value located at _offset_. Otherwise,
2354 * Extra memory for a window class is specified by a nonzero cbWndExtra
2355 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2356 * time of class creation.
2358 * Using GWL_WNDPROC to set a new window procedure effectively creates
2359 * a window subclass. Use CallWindowProc() in the new windows procedure
2360 * to pass messages to the superclass's window procedure.
2362 * The user data is reserved for use by the application which created
2365 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2366 * instead, call the EnableWindow() function to change the window's
2369 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2370 * SetParent() instead.
2373 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2374 * it sends WM_STYLECHANGING before changing the settings
2375 * and WM_STYLECHANGED afterwards.
2376 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2378 LONG WINAPI SetWindowLongW(
2379 HWND hwnd, /* [in] window to alter */
2380 INT offset, /* [in] offset, in bytes, of location to alter */
2381 LONG newval /* [in] new value of location */
2383 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, TRUE );
2387 /*******************************************************************
2388 * GetWindowTextA (USER32.@)
2390 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2394 if (!lpString) return 0;
2396 if (WIN_IsCurrentProcess( hwnd ))
2397 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2399 /* when window belongs to other process, don't send a message */
2400 if (nMaxCount <= 0) return 0;
2401 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2402 get_server_window_text( hwnd, buffer, nMaxCount );
2403 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2404 lpString[nMaxCount-1] = 0;
2405 HeapFree( GetProcessHeap(), 0, buffer );
2406 return strlen(lpString);
2410 /*******************************************************************
2411 * InternalGetWindowText (USER32.@)
2413 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2417 if (nMaxCount <= 0) return 0;
2418 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2419 if (win == WND_DESKTOP) lpString[0] = 0;
2420 else if (win != WND_OTHER_PROCESS)
2422 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2423 else lpString[0] = 0;
2424 WIN_ReleasePtr( win );
2428 get_server_window_text( hwnd, lpString, nMaxCount );
2430 return strlenW(lpString);
2434 /*******************************************************************
2435 * GetWindowTextW (USER32.@)
2437 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2439 if (!lpString) return 0;
2441 if (WIN_IsCurrentProcess( hwnd ))
2442 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2444 /* when window belongs to other process, don't send a message */
2445 if (nMaxCount <= 0) return 0;
2446 get_server_window_text( hwnd, lpString, nMaxCount );
2447 return strlenW(lpString);
2451 /*******************************************************************
2452 * SetWindowTextA (USER32.@)
2453 * SetWindowText (USER32.@)
2455 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2457 if (is_broadcast(hwnd))
2459 SetLastError( ERROR_INVALID_PARAMETER );
2462 if (!WIN_IsCurrentProcess( hwnd ))
2463 WARN( "setting text %s of other process window %p should not use SendMessage\n",
2464 debugstr_a(lpString), hwnd );
2465 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2469 /*******************************************************************
2470 * SetWindowTextW (USER32.@)
2472 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2474 if (is_broadcast(hwnd))
2476 SetLastError( ERROR_INVALID_PARAMETER );
2479 if (!WIN_IsCurrentProcess( hwnd ))
2480 WARN( "setting text %s of other process window %p should not use SendMessage\n",
2481 debugstr_w(lpString), hwnd );
2482 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2486 /*******************************************************************
2487 * GetWindowTextLengthA (USER32.@)
2489 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2491 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2494 /*******************************************************************
2495 * GetWindowTextLengthW (USER32.@)
2497 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2499 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2503 /*******************************************************************
2504 * IsWindow (USER32.@)
2506 BOOL WINAPI IsWindow( HWND hwnd )
2511 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2512 if (ptr == WND_DESKTOP) return TRUE;
2514 if (ptr != WND_OTHER_PROCESS)
2516 WIN_ReleasePtr( ptr );
2520 /* check other processes */
2521 SERVER_START_REQ( get_window_info )
2524 ret = !wine_server_call_err( req );
2531 /***********************************************************************
2532 * GetWindowThreadProcessId (USER32.@)
2534 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2539 if (!(ptr = WIN_GetPtr( hwnd )))
2541 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2545 if (ptr != WND_OTHER_PROCESS && ptr != WND_DESKTOP)
2547 /* got a valid window */
2549 if (process) *process = GetCurrentProcessId();
2550 WIN_ReleasePtr( ptr );
2554 /* check other processes */
2555 SERVER_START_REQ( get_window_info )
2558 if (!wine_server_call_err( req ))
2560 tid = (DWORD)reply->tid;
2561 if (process) *process = (DWORD)reply->pid;
2569 /*****************************************************************
2570 * GetParent (USER32.@)
2572 HWND WINAPI GetParent( HWND hwnd )
2577 if (!(wndPtr = WIN_GetPtr( hwnd )))
2579 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2582 if (wndPtr == WND_DESKTOP) return 0;
2583 if (wndPtr == WND_OTHER_PROCESS)
2585 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2586 if (style & (WS_POPUP | WS_CHILD))
2588 SERVER_START_REQ( get_window_tree )
2591 if (!wine_server_call_err( req ))
2593 if (style & WS_POPUP) retvalue = reply->owner;
2594 else if (style & WS_CHILD) retvalue = reply->parent;
2602 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2603 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2604 WIN_ReleasePtr( wndPtr );
2610 /*****************************************************************
2611 * GetAncestor (USER32.@)
2613 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2616 HWND *list, ret = 0;
2621 if (!(win = WIN_GetPtr( hwnd )))
2623 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2626 if (win == WND_DESKTOP) return 0;
2627 if (win != WND_OTHER_PROCESS)
2630 WIN_ReleasePtr( win );
2632 else /* need to query the server */
2634 SERVER_START_REQ( get_window_tree )
2637 if (!wine_server_call_err( req )) ret = reply->parent;
2644 if (!(list = list_window_parents( hwnd ))) return 0;
2646 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2650 while (list[count]) count++;
2651 ret = list[count - 2]; /* get the one before the desktop */
2653 HeapFree( GetProcessHeap(), 0, list );
2657 if (is_desktop_window( hwnd )) return 0;
2658 ret = WIN_GetFullHandle( hwnd );
2661 HWND parent = GetParent( ret );
2671 /*****************************************************************
2672 * SetParent (USER32.@)
2674 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2677 HWND old_parent = 0;
2682 if (is_broadcast(hwnd) || is_broadcast(parent))
2684 SetLastError(ERROR_INVALID_PARAMETER);
2688 if (!parent) parent = GetDesktopWindow();
2689 else if (parent == HWND_MESSAGE) parent = get_hwnd_message_parent();
2690 else parent = WIN_GetFullHandle( parent );
2692 if (!IsWindow( parent ))
2694 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2698 /* Some applications try to set a child as a parent */
2699 if (IsChild(hwnd, parent))
2701 SetLastError( ERROR_INVALID_PARAMETER );
2705 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2706 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2708 /* Windows hides the window first, then shows it again
2709 * including the WM_SHOWWINDOW messages and all */
2710 was_visible = ShowWindow( hwnd, SW_HIDE );
2712 wndPtr = WIN_GetPtr( hwnd );
2713 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return 0;
2715 SERVER_START_REQ( set_parent )
2718 req->parent = parent;
2719 if ((ret = !wine_server_call( req )))
2721 old_parent = reply->old_parent;
2722 wndPtr->parent = parent = reply->full_parent;
2727 WIN_ReleasePtr( wndPtr );
2730 USER_Driver->pSetParent( full_handle, parent, old_parent );
2732 /* SetParent additionally needs to make hwnd the topmost window
2733 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2734 WM_WINDOWPOSCHANGED notification messages.
2736 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0,
2737 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2738 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2739 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2745 /*******************************************************************
2746 * IsChild (USER32.@)
2748 BOOL WINAPI IsChild( HWND parent, HWND child )
2750 HWND *list = list_window_parents( child );
2754 if (!list) return FALSE;
2755 parent = WIN_GetFullHandle( parent );
2756 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2757 ret = list[i] && list[i+1];
2758 HeapFree( GetProcessHeap(), 0, list );
2763 /***********************************************************************
2764 * IsWindowVisible (USER32.@)
2766 BOOL WINAPI IsWindowVisible( HWND hwnd )
2772 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2773 if (!(list = list_window_parents( hwnd ))) return TRUE;
2776 for (i = 0; list[i+1]; i++)
2777 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2778 retval = !list[i+1] && (list[i] == GetDesktopWindow()); /* top message window isn't visible */
2780 HeapFree( GetProcessHeap(), 0, list );
2785 /***********************************************************************
2786 * WIN_IsWindowDrawable
2788 * hwnd is drawable when it is visible, all parents are not
2789 * minimized, and it is itself not minimized unless we are
2790 * trying to draw its default class icon.
2792 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2797 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2799 if (!(style & WS_VISIBLE)) return FALSE;
2800 if ((style & WS_MINIMIZE) && icon && GetClassLongPtrW( hwnd, GCLP_HICON )) return FALSE;
2802 if (!(list = list_window_parents( hwnd ))) return TRUE;
2805 for (i = 0; list[i+1]; i++)
2806 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2808 retval = !list[i+1] && (list[i] == GetDesktopWindow()); /* top message window isn't visible */
2810 HeapFree( GetProcessHeap(), 0, list );
2815 /*******************************************************************
2816 * GetTopWindow (USER32.@)
2818 HWND WINAPI GetTopWindow( HWND hwnd )
2820 if (!hwnd) hwnd = GetDesktopWindow();
2821 return GetWindow( hwnd, GW_CHILD );
2825 /*******************************************************************
2826 * GetWindow (USER32.@)
2828 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2832 if (rel == GW_OWNER) /* this one may be available locally */
2834 WND *wndPtr = WIN_GetPtr( hwnd );
2837 SetLastError( ERROR_INVALID_HANDLE );
2840 if (wndPtr == WND_DESKTOP) return 0;
2841 if (wndPtr != WND_OTHER_PROCESS)
2843 retval = wndPtr->owner;
2844 WIN_ReleasePtr( wndPtr );
2847 /* else fall through to server call */
2850 SERVER_START_REQ( get_window_tree )
2853 if (!wine_server_call_err( req ))
2858 retval = reply->first_sibling;
2861 retval = reply->last_sibling;
2864 retval = reply->next_sibling;
2867 retval = reply->prev_sibling;
2870 retval = reply->owner;
2873 retval = reply->first_child;
2883 /*******************************************************************
2884 * ShowOwnedPopups (USER32.@)
2886 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2890 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2892 if (!win_array) return TRUE;
2894 while (win_array[count]) count++;
2895 while (--count >= 0)
2897 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2898 if (!(pWnd = WIN_GetPtr( win_array[count] ))) continue;
2899 if (pWnd == WND_OTHER_PROCESS) continue;
2902 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2904 WIN_ReleasePtr( pWnd );
2905 /* In Windows, ShowOwnedPopups(TRUE) generates
2906 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2907 * regardless of the state of the owner
2909 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_SHOWNORMAL, SW_PARENTOPENING);
2915 if (pWnd->dwStyle & WS_VISIBLE)
2917 WIN_ReleasePtr( pWnd );
2918 /* In Windows, ShowOwnedPopups(FALSE) generates
2919 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2920 * regardless of the state of the owner
2922 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2926 WIN_ReleasePtr( pWnd );
2928 HeapFree( GetProcessHeap(), 0, win_array );
2933 /*******************************************************************
2934 * GetLastActivePopup (USER32.@)
2936 HWND WINAPI GetLastActivePopup( HWND hwnd )
2940 SERVER_START_REQ( get_window_info )
2943 if (!wine_server_call_err( req )) retval = reply->last_active;
2950 /*******************************************************************
2953 * Build an array of the children of a given window. The array must be
2954 * freed with HeapFree. Returns NULL when no windows are found.
2956 HWND *WIN_ListChildren( HWND hwnd )
2960 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2963 return list_window_children( 0, hwnd, NULL, 0 );
2967 /*******************************************************************
2968 * EnumWindows (USER32.@)
2970 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2976 USER_CheckNotLock();
2978 /* We have to build a list of all windows first, to avoid */
2979 /* unpleasant side-effects, for instance if the callback */
2980 /* function changes the Z-order of the windows. */
2982 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2984 /* Now call the callback function for every window */
2986 for (i = 0; list[i]; i++)
2988 /* Make sure that the window still exists */
2989 if (!IsWindow( list[i] )) continue;
2990 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2992 HeapFree( GetProcessHeap(), 0, list );
2997 /**********************************************************************
2998 * EnumThreadWindows (USER32.@)
3000 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
3005 USER_CheckNotLock();
3007 if (!(list = list_window_children( 0, GetDesktopWindow(), NULL, id ))) return TRUE;
3009 /* Now call the callback function for every window */
3011 for (i = 0; list[i]; i++)
3012 if (!func( list[i], lParam )) break;
3013 HeapFree( GetProcessHeap(), 0, list );
3018 /***********************************************************************
3019 * EnumDesktopWindows (USER32.@)
3021 BOOL WINAPI EnumDesktopWindows( HDESK desktop, WNDENUMPROC func, LPARAM lparam )
3026 USER_CheckNotLock();
3028 if (!(list = list_window_children( desktop, 0, NULL, 0 ))) return TRUE;
3030 for (i = 0; list[i]; i++)
3031 if (!func( list[i], lparam )) break;
3032 HeapFree( GetProcessHeap(), 0, list );
3037 /**********************************************************************
3038 * WIN_EnumChildWindows
3040 * Helper function for EnumChildWindows().
3042 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
3047 for ( ; *list; list++)
3049 /* Make sure that the window still exists */
3050 if (!IsWindow( *list )) continue;
3051 /* Build children list first */
3052 childList = WIN_ListChildren( *list );
3054 ret = func( *list, lParam );
3058 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
3059 HeapFree( GetProcessHeap(), 0, childList );
3061 if (!ret) return FALSE;
3067 /**********************************************************************
3068 * EnumChildWindows (USER32.@)
3070 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
3075 USER_CheckNotLock();
3077 if (!(list = WIN_ListChildren( parent ))) return FALSE;
3078 ret = WIN_EnumChildWindows( list, func, lParam );
3079 HeapFree( GetProcessHeap(), 0, list );
3084 /*******************************************************************
3085 * AnyPopup (USER.52)
3087 BOOL16 WINAPI AnyPopup16(void)
3093 /*******************************************************************
3094 * AnyPopup (USER32.@)
3096 BOOL WINAPI AnyPopup(void)
3100 HWND *list = WIN_ListChildren( GetDesktopWindow() );
3102 if (!list) return FALSE;
3103 for (i = 0; list[i]; i++)
3105 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
3107 retvalue = (list[i] != 0);
3108 HeapFree( GetProcessHeap(), 0, list );
3113 /*******************************************************************
3114 * FlashWindow (USER32.@)
3116 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3120 TRACE("%p\n", hWnd);
3122 if (IsIconic( hWnd ))
3124 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3126 wndPtr = WIN_GetPtr(hWnd);
3127 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
3128 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3130 wndPtr->flags |= WIN_NCACTIVATED;
3134 wndPtr->flags &= ~WIN_NCACTIVATED;
3136 WIN_ReleasePtr( wndPtr );
3143 wndPtr = WIN_GetPtr(hWnd);
3144 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
3145 hWnd = wndPtr->hwndSelf; /* make it a full handle */
3147 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3148 else wparam = (hWnd == GetForegroundWindow());
3150 WIN_ReleasePtr( wndPtr );
3151 SendMessageW( hWnd, WM_NCACTIVATE, wparam, 0 );
3156 /*******************************************************************
3157 * FlashWindowEx (USER32.@)
3159 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
3161 FIXME("%p\n", pfwi);
3165 /*******************************************************************
3166 * GetWindowContextHelpId (USER32.@)
3168 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3171 WND *wnd = WIN_GetPtr( hwnd );
3172 if (!wnd || wnd == WND_DESKTOP) return 0;
3173 if (wnd == WND_OTHER_PROCESS)
3175 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3178 retval = wnd->helpContext;
3179 WIN_ReleasePtr( wnd );
3184 /*******************************************************************
3185 * SetWindowContextHelpId (USER32.@)
3187 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3189 WND *wnd = WIN_GetPtr( hwnd );
3190 if (!wnd || wnd == WND_DESKTOP) return FALSE;
3191 if (wnd == WND_OTHER_PROCESS)
3193 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3196 wnd->helpContext = id;
3197 WIN_ReleasePtr( wnd );
3202 /*******************************************************************
3203 * DragDetect (USER32.@)
3205 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3209 WORD wDragWidth = GetSystemMetrics(SM_CXDRAG);
3210 WORD wDragHeight= GetSystemMetrics(SM_CYDRAG);
3212 rect.left = pt.x - wDragWidth;
3213 rect.right = pt.x + wDragWidth;
3215 rect.top = pt.y - wDragHeight;
3216 rect.bottom = pt.y + wDragHeight;
3222 while (PeekMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ))
3224 if( msg.message == WM_LBUTTONUP )
3229 if( msg.message == WM_MOUSEMOVE )
3232 tmp.x = (short)LOWORD(msg.lParam);
3233 tmp.y = (short)HIWORD(msg.lParam);
3234 if( !PtInRect( &rect, tmp ))
3246 /******************************************************************************
3247 * GetWindowModuleFileNameA (USER32.@)
3249 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR module, UINT size )
3254 TRACE( "%p, %p, %u\n", hwnd, module, size );
3256 win = WIN_GetPtr( hwnd );
3257 if (!win || win == WND_OTHER_PROCESS || win == WND_DESKTOP)
3259 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
3262 hinst = win->hInstance;
3263 WIN_ReleasePtr( win );
3265 return GetModuleFileNameA( hinst, module, size );
3268 /******************************************************************************
3269 * GetWindowModuleFileNameW (USER32.@)
3271 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR module, UINT size )
3276 TRACE( "%p, %p, %u\n", hwnd, module, size );
3278 win = WIN_GetPtr( hwnd );
3279 if (!win || win == WND_OTHER_PROCESS || win == WND_DESKTOP)
3281 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
3284 hinst = win->hInstance;
3285 WIN_ReleasePtr( win );
3287 return GetModuleFileNameW( hinst, module, size );
3290 /******************************************************************************
3291 * GetWindowInfo (USER32.@)
3293 * Note: tests show that Windows doesn't check cbSize of the structure.
3295 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3297 if (!pwi) return FALSE;
3298 if (!IsWindow(hwnd)) return FALSE;
3300 GetWindowRect(hwnd, &pwi->rcWindow);
3301 GetClientRect(hwnd, &pwi->rcClient);
3302 /* translate to screen coordinates */
3303 MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3305 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3306 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3307 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3309 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3310 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3312 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3313 pwi->wCreatorVersion = 0x0400;
3318 /******************************************************************************
3319 * SwitchDesktop (USER32.@)
3321 * NOTES: Sets the current input or interactive desktop.
3323 BOOL WINAPI SwitchDesktop( HDESK hDesktop)
3325 FIXME("SwitchDesktop(hwnd %p) stub!\n", hDesktop);
3329 /*****************************************************************************
3330 * SetLayeredWindowAttributes (USER32.@)
3332 BOOL WINAPI SetLayeredWindowAttributes( HWND hwnd, COLORREF key, BYTE alpha, DWORD flags )
3336 TRACE("(%p,%08x,%d,%x): stub!\n", hwnd, key, alpha, flags);
3338 SERVER_START_REQ( set_window_layered_info )
3341 req->color_key = key;
3344 ret = !wine_server_call_err( req );
3348 if (ret) USER_Driver->pSetLayeredWindowAttributes( hwnd, key, alpha, flags );
3354 /*****************************************************************************
3355 * GetLayeredWindowAttributes (USER32.@)
3357 BOOL WINAPI GetLayeredWindowAttributes( HWND hwnd, COLORREF *key, BYTE *alpha, DWORD *flags )
3361 SERVER_START_REQ( get_window_layered_info )
3364 if ((ret = !wine_server_call_err( req )))
3366 if (key) *key = reply->color_key;
3367 if (alpha) *alpha = reply->alpha;
3368 if (flags) *flags = reply->flags;
3377 /*****************************************************************************
3378 * UpdateLayeredWindowIndirect (USER32.@)
3380 BOOL WINAPI UpdateLayeredWindowIndirect( HWND hwnd, const UPDATELAYEREDWINDOWINFO *info )
3384 if (!(info->dwFlags & ULW_EX_NORESIZE) && (info->pptDst || info->psize))
3386 int x = 0, y = 0, cx = 0, cy = 0;
3387 DWORD flags = SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW | SWP_NOSENDCHANGING;
3391 x = info->pptDst->x;
3392 y = info->pptDst->y;
3393 flags &= ~SWP_NOMOVE;
3397 cx = info->psize->cx;
3398 cy = info->psize->cy;
3399 flags &= ~SWP_NOSIZE;
3401 TRACE( "moving window %p pos %d,%d %dx%x\n", hwnd, x, y, cx, cy );
3402 SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
3408 HDC hdc = GetDCEx( hwnd, 0, DCX_CACHE );
3414 GetClientRect( hwnd, &rect );
3417 x = info->pptSrc->x;
3418 y = info->pptSrc->y;
3420 /* FIXME: intersect rect with info->prcDirty */
3421 TRACE( "copying window %p pos %d,%d\n", hwnd, x, y );
3422 BitBlt( hdc, rect.left, rect.top, rect.right, rect.bottom,
3423 info->hdcSrc, rect.left + x, rect.top + y, SRCCOPY );
3424 ReleaseDC( hwnd, hdc );
3428 if (info->pblend && !(info->dwFlags & ULW_OPAQUE)) alpha = info->pblend->SourceConstantAlpha;
3429 TRACE( "setting window %p alpha %u\n", hwnd, alpha );
3430 USER_Driver->pSetLayeredWindowAttributes( hwnd, info->crKey, alpha,
3431 info->dwFlags & (LWA_ALPHA | LWA_COLORKEY) );
3436 /*****************************************************************************
3437 * UpdateLayeredWindow (USER32.@)
3439 BOOL WINAPI UpdateLayeredWindow( HWND hwnd, HDC hdcDst, POINT *pptDst, SIZE *psize,
3440 HDC hdcSrc, POINT *pptSrc, COLORREF crKey, BLENDFUNCTION *pblend,
3443 UPDATELAYEREDWINDOWINFO info;
3445 info.cbSize = sizeof(info);
3446 info.hdcDst = hdcDst;
3447 info.pptDst = pptDst;
3449 info.hdcSrc = hdcSrc;
3450 info.pptSrc = pptSrc;
3452 info.pblend = pblend;
3453 info.dwFlags = dwFlags;
3454 info.prcDirty = NULL;
3455 return UpdateLayeredWindowIndirect( hwnd, &info );
3458 /* 64bit versions */
3460 #ifdef GetWindowLongPtrW
3461 #undef GetWindowLongPtrW
3464 #ifdef GetWindowLongPtrA
3465 #undef GetWindowLongPtrA
3468 #ifdef SetWindowLongPtrW
3469 #undef SetWindowLongPtrW
3472 #ifdef SetWindowLongPtrA
3473 #undef SetWindowLongPtrA
3476 /*****************************************************************************
3477 * GetWindowLongPtrW (USER32.@)
3479 LONG_PTR WINAPI GetWindowLongPtrW( HWND hwnd, INT offset )
3481 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), TRUE );
3484 /*****************************************************************************
3485 * GetWindowLongPtrA (USER32.@)
3487 LONG_PTR WINAPI GetWindowLongPtrA( HWND hwnd, INT offset )
3489 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), FALSE );
3492 /*****************************************************************************
3493 * SetWindowLongPtrW (USER32.@)
3495 LONG_PTR WINAPI SetWindowLongPtrW( HWND hwnd, INT offset, LONG_PTR newval )
3497 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, TRUE );
3500 /*****************************************************************************
3501 * SetWindowLongPtrA (USER32.@)
3503 LONG_PTR WINAPI SetWindowLongPtrA( HWND hwnd, INT offset, LONG_PTR newval )
3505 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, FALSE );