user32: Store the window placement information directly in the main window structure.
[wine/wine-kai.git] / dlls / user32 / win.c
blob6d065bef41c83afcf3e2026df506240298a89775
1 /*
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
21 #include "config.h"
22 #include "wine/port.h"
24 #include <assert.h>
25 #include <stdarg.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include "windef.h"
29 #include "winbase.h"
30 #include "wine/winbase16.h"
31 #include "wine/winuser16.h"
32 #include "wownt32.h"
33 #include "wine/server.h"
34 #include "wine/unicode.h"
35 #include "win.h"
36 #include "user_private.h"
37 #include "controls.h"
38 #include "winerror.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))
53 WORD ret;
54 memcpy( &ret, ptr, sizeof(ret) );
55 return ret;
57 else if (size == sizeof(DWORD))
59 DWORD ret;
60 memcpy( &ret, ptr, sizeof(ret) );
61 return ret;
63 else
65 LONG_PTR ret;
66 memcpy( &ret, ptr, sizeof(ret) );
67 return 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))
76 WORD newval = val;
77 memcpy( ptr, &newval, sizeof(newval) );
79 else if (size == sizeof(DWORD))
81 DWORD newval = val;
82 memcpy( ptr, &newval, sizeof(newval) );
84 else
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 )
101 WORD index;
102 WND *win;
103 HWND full_parent = 0, full_owner = 0;
104 struct tagCLASS *class = NULL;
105 user_handle_t handle = 0;
106 int extra_bytes = 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;
115 req->owner = owner;
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;
128 SERVER_END_REQ;
130 if (!handle)
132 WARN( "error %d creating window\n", GetLastError() );
133 return NULL;
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 );
144 SERVER_END_REQ;
145 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
146 return NULL;
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 (!thread_info->desktop) thread_info->desktop = full_parent ? full_parent : handle;
154 else assert( full_parent == thread_info->desktop );
155 if (full_parent && !USER_Driver->pCreateDesktopWindow( thread_info->desktop ))
156 ERR( "failed to create desktop window\n" );
159 USER_Lock();
161 index = USER_HANDLE_TO_INDEX(handle);
162 assert( index < NB_USER_HANDLES );
163 user_handles[index] = win;
164 win->hwndSelf = handle;
165 win->parent = full_parent;
166 win->owner = full_owner;
167 win->class = class;
168 win->winproc = get_class_winproc( class );
169 win->dwMagic = WND_MAGIC;
170 win->cbWndExtra = extra_bytes;
171 if (WINPROC_IsUnicode( win->winproc, unicode )) win->flags |= WIN_ISUNICODE;
172 return win;
176 /***********************************************************************
177 * free_window_handle
179 * Free a window handle.
181 static WND *free_window_handle( HWND hwnd )
183 WND *ptr;
184 WORD index = USER_HANDLE_TO_INDEX(hwnd);
186 if (index >= NB_USER_HANDLES) return NULL;
187 USER_Lock();
188 if ((ptr = user_handles[index]))
190 SERVER_START_REQ( destroy_window )
192 req->handle = hwnd;
193 if (!wine_server_call_err( req ))
195 user_handles[index] = NULL;
196 ptr->dwMagic = 0;
198 else
199 ptr = NULL;
201 SERVER_END_REQ;
203 USER_Unlock();
204 HeapFree( GetProcessHeap(), 0, ptr );
205 return ptr;
209 /*******************************************************************
210 * list_window_children
212 * Build an array of the children of a given window. The array must be
213 * freed with HeapFree. Returns NULL when no windows are found.
215 static HWND *list_window_children( HWND hwnd, LPCWSTR class, DWORD tid )
217 HWND *list;
218 int size = 32;
220 for (;;)
222 int count = 0;
224 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
226 SERVER_START_REQ( get_window_children )
228 req->parent = hwnd;
229 req->tid = tid;
230 if (!(req->atom = get_int_atom_value( class )) && class)
231 wine_server_add_data( req, class, strlenW(class)*sizeof(WCHAR) );
232 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
233 if (!wine_server_call( req )) count = reply->count;
235 SERVER_END_REQ;
236 if (count && count < size)
238 list[count] = 0;
239 return list;
241 HeapFree( GetProcessHeap(), 0, list );
242 if (!count) break;
243 size = count + 1; /* restart with a large enough buffer */
245 return NULL;
249 /*******************************************************************
250 * list_window_parents
252 * Build an array of all parents of a given window, starting with
253 * the immediate parent. The array must be freed with HeapFree.
255 static HWND *list_window_parents( HWND hwnd )
257 WND *win;
258 HWND current, *list;
259 int pos = 0, size = 16, count = 0;
261 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
263 current = hwnd;
264 for (;;)
266 if (!(win = WIN_GetPtr( current ))) goto empty;
267 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
268 if (win == WND_DESKTOP)
270 if (!pos) goto empty;
271 list[pos] = 0;
272 return list;
274 list[pos] = current = win->parent;
275 WIN_ReleasePtr( win );
276 if (++pos == size - 1)
278 /* need to grow the list */
279 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
280 if (!new_list) goto empty;
281 list = new_list;
282 size += 16;
286 /* at least one parent belongs to another process, have to query the server */
288 for (;;)
290 count = 0;
291 SERVER_START_REQ( get_window_parents )
293 req->handle = hwnd;
294 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
295 if (!wine_server_call( req )) count = reply->count;
297 SERVER_END_REQ;
298 if (!count) goto empty;
299 if (size > count)
301 list[count] = 0;
302 return list;
304 HeapFree( GetProcessHeap(), 0, list );
305 size = count + 1;
306 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
309 empty:
310 HeapFree( GetProcessHeap(), 0, list );
311 return NULL;
315 /*******************************************************************
316 * send_parent_notify
318 static void send_parent_notify( HWND hwnd, UINT msg )
320 if ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_CHILD | WS_POPUP)) == WS_CHILD &&
321 !(GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY))
323 HWND parent = GetParent(hwnd);
324 if (parent && parent != GetDesktopWindow())
325 SendMessageW( parent, WM_PARENTNOTIFY,
326 MAKEWPARAM( msg, GetWindowLongPtrW( hwnd, GWLP_ID )), (LPARAM)hwnd );
331 /*******************************************************************
332 * get_server_window_text
334 * Retrieve the window text from the server.
336 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
338 size_t len = 0;
340 SERVER_START_REQ( get_window_text )
342 req->handle = hwnd;
343 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
344 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
346 SERVER_END_REQ;
347 text[len / sizeof(WCHAR)] = 0;
351 /***********************************************************************
352 * WIN_GetPtr
354 * Return a pointer to the WND structure if local to the process,
355 * or WND_OTHER_PROCESS if handle may be valid in other process.
356 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
358 WND *WIN_GetPtr( HWND hwnd )
360 WND * ptr;
361 WORD index = USER_HANDLE_TO_INDEX(hwnd);
363 if (index >= NB_USER_HANDLES) return NULL;
365 USER_Lock();
366 if ((ptr = user_handles[index]))
368 if (ptr->dwMagic == WND_MAGIC &&
369 (hwnd == ptr->hwndSelf || !HIWORD(hwnd) || HIWORD(hwnd) == 0xffff))
370 return ptr;
371 ptr = NULL;
373 else if (index == USER_HANDLE_TO_INDEX(GetDesktopWindow()))
375 if (hwnd == GetDesktopWindow() || !HIWORD(hwnd) || HIWORD(hwnd) == 0xffff) ptr = WND_DESKTOP;
376 else ptr = NULL;
378 else ptr = WND_OTHER_PROCESS;
379 USER_Unlock();
380 return ptr;
384 /***********************************************************************
385 * WIN_IsCurrentProcess
387 * Check whether a given window belongs to the current process (and return the full handle).
389 HWND WIN_IsCurrentProcess( HWND hwnd )
391 WND *ptr;
392 HWND ret;
394 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
395 ret = ptr->hwndSelf;
396 WIN_ReleasePtr( ptr );
397 return ret;
401 /***********************************************************************
402 * WIN_IsCurrentThread
404 * Check whether a given window belongs to the current thread (and return the full handle).
406 HWND WIN_IsCurrentThread( HWND hwnd )
408 WND *ptr;
409 HWND ret = 0;
411 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
412 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
413 WIN_ReleasePtr( ptr );
414 return ret;
418 /***********************************************************************
419 * WIN_Handle32
421 * Convert a 16-bit window handle to a full 32-bit handle.
423 HWND WIN_Handle32( HWND16 hwnd16 )
425 WND *ptr;
426 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
428 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
429 /* do sign extension for -2 and -3 */
430 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
432 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
434 if (ptr == WND_DESKTOP) return GetDesktopWindow();
436 if (ptr != WND_OTHER_PROCESS)
438 hwnd = ptr->hwndSelf;
439 WIN_ReleasePtr( ptr );
441 else /* may belong to another process */
443 SERVER_START_REQ( get_window_info )
445 req->handle = hwnd;
446 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
448 SERVER_END_REQ;
450 return hwnd;
454 /***********************************************************************
455 * WIN_SetOwner
457 * Change the owner of a window.
459 HWND WIN_SetOwner( HWND hwnd, HWND owner )
461 WND *win = WIN_GetPtr( hwnd );
462 HWND ret = 0;
464 if (!win || win == WND_DESKTOP) return 0;
465 if (win == WND_OTHER_PROCESS)
467 if (IsWindow(hwnd)) ERR( "cannot set owner %p on other process window %p\n", owner, hwnd );
468 return 0;
470 SERVER_START_REQ( set_window_owner )
472 req->handle = hwnd;
473 req->owner = owner;
474 if (!wine_server_call( req ))
476 win->owner = reply->full_owner;
477 ret = reply->prev_owner;
480 SERVER_END_REQ;
481 WIN_ReleasePtr( win );
482 return ret;
486 /***********************************************************************
487 * WIN_SetStyle
489 * Change the style of a window.
491 ULONG WIN_SetStyle( HWND hwnd, ULONG set_bits, ULONG clear_bits )
493 BOOL ok;
494 ULONG new_style, old_style = 0;
495 WND *win = WIN_GetPtr( hwnd );
497 if (!win || win == WND_DESKTOP) return 0;
498 if (win == WND_OTHER_PROCESS)
500 if (IsWindow(hwnd))
501 ERR( "cannot set style %x/%x on other process window %p\n",
502 set_bits, clear_bits, hwnd );
503 return 0;
505 new_style = (win->dwStyle | set_bits) & ~clear_bits;
506 if (new_style == win->dwStyle)
508 WIN_ReleasePtr( win );
509 return new_style;
511 SERVER_START_REQ( set_window_info )
513 req->handle = hwnd;
514 req->flags = SET_WIN_STYLE;
515 req->style = new_style;
516 req->extra_offset = -1;
517 if ((ok = !wine_server_call( req )))
519 old_style = reply->old_style;
520 win->dwStyle = new_style;
523 SERVER_END_REQ;
524 WIN_ReleasePtr( win );
525 if (ok)
527 USER_Driver->pSetWindowStyle( hwnd, old_style );
528 if ((old_style ^ new_style) & WS_VISIBLE) invalidate_dce( hwnd, NULL );
530 return old_style;
534 /***********************************************************************
535 * WIN_GetRectangles
537 * Get the window and client rectangles.
539 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
541 WND *win = WIN_GetPtr( hwnd );
542 BOOL ret = TRUE;
544 if (!win) return FALSE;
545 if (win == WND_DESKTOP)
547 RECT rect;
548 rect.left = rect.top = 0;
549 rect.right = GetSystemMetrics(SM_CXSCREEN);
550 rect.bottom = GetSystemMetrics(SM_CYSCREEN);
551 if (rectWindow) *rectWindow = rect;
552 if (rectClient) *rectClient = rect;
554 else if (win == WND_OTHER_PROCESS)
556 SERVER_START_REQ( get_window_rectangles )
558 req->handle = hwnd;
559 if ((ret = !wine_server_call( req )))
561 if (rectWindow)
563 rectWindow->left = reply->window.left;
564 rectWindow->top = reply->window.top;
565 rectWindow->right = reply->window.right;
566 rectWindow->bottom = reply->window.bottom;
568 if (rectClient)
570 rectClient->left = reply->client.left;
571 rectClient->top = reply->client.top;
572 rectClient->right = reply->client.right;
573 rectClient->bottom = reply->client.bottom;
577 SERVER_END_REQ;
579 else
581 if (rectWindow) *rectWindow = win->rectWindow;
582 if (rectClient) *rectClient = win->rectClient;
583 WIN_ReleasePtr( win );
585 return ret;
589 /***********************************************************************
590 * WIN_DestroyWindow
592 * Destroy storage associated to a window. "Internals" p.358
594 LRESULT WIN_DestroyWindow( HWND hwnd )
596 WND *wndPtr;
597 HWND *list;
598 HMENU menu = 0, sys_menu;
599 HWND icon_title;
601 TRACE("%p\n", hwnd );
603 /* free child windows */
604 if ((list = WIN_ListChildren( hwnd )))
606 int i;
607 for (i = 0; list[i]; i++)
609 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
610 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
612 HeapFree( GetProcessHeap(), 0, list );
615 /* Unlink now so we won't bother with the children later on */
616 SERVER_START_REQ( set_parent )
618 req->handle = hwnd;
619 req->parent = 0;
620 wine_server_call( req );
622 SERVER_END_REQ;
625 * Send the WM_NCDESTROY to the window being destroyed.
627 SendMessageW( hwnd, WM_NCDESTROY, 0, 0 );
629 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
631 /* free resources associated with the window */
633 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
634 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
635 menu = (HMENU)wndPtr->wIDmenu;
636 sys_menu = wndPtr->hSysMenu;
637 free_dce( wndPtr->dce, hwnd );
638 wndPtr->dce = NULL;
639 icon_title = wndPtr->icon_title;
640 WIN_ReleasePtr( wndPtr );
642 if (icon_title) DestroyWindow( icon_title );
643 if (menu) DestroyMenu( menu );
644 if (sys_menu) DestroyMenu( sys_menu );
646 USER_Driver->pDestroyWindow( hwnd );
648 free_window_handle( hwnd );
649 return 0;
652 /***********************************************************************
653 * WIN_DestroyThreadWindows
655 * Destroy all children of 'wnd' owned by the current thread.
657 void WIN_DestroyThreadWindows( HWND hwnd )
659 HWND *list;
660 int i;
662 if (!(list = WIN_ListChildren( hwnd ))) return;
663 for (i = 0; list[i]; i++)
665 if (WIN_IsCurrentThread( list[i] ))
666 DestroyWindow( list[i] );
667 else
668 WIN_DestroyThreadWindows( list[i] );
670 HeapFree( GetProcessHeap(), 0, list );
674 /***********************************************************************
675 * WIN_FixCoordinates
677 * Fix the coordinates - Helper for WIN_CreateWindowEx.
678 * returns default show mode in sw.
680 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
682 #define IS_DEFAULT(x) ((x) == CW_USEDEFAULT || (x) == CW_USEDEFAULT16)
683 POINT pos[2];
685 if (cs->dwExStyle & WS_EX_MDICHILD)
687 UINT id = 0;
689 MDI_CalcDefaultChildPos(cs->hwndParent, -1, pos, 0, &id);
690 if (!(cs->style & WS_POPUP)) cs->hMenu = ULongToHandle(id);
692 TRACE("MDI child id %04x\n", id);
695 if (cs->style & (WS_CHILD | WS_POPUP))
697 if (cs->dwExStyle & WS_EX_MDICHILD)
699 if (IS_DEFAULT(cs->x))
701 cs->x = pos[0].x;
702 cs->y = pos[0].y;
704 if (IS_DEFAULT(cs->cx) || !cs->cx) cs->cx = pos[1].x;
705 if (IS_DEFAULT(cs->cy) || !cs->cy) cs->cy = pos[1].y;
707 else
709 if (IS_DEFAULT(cs->x)) cs->x = cs->y = 0;
710 if (IS_DEFAULT(cs->cx)) cs->cx = cs->cy = 0;
713 else /* overlapped window */
715 HMONITOR monitor;
716 MONITORINFO mon_info;
717 STARTUPINFOW info;
719 if (!IS_DEFAULT(cs->x) && !IS_DEFAULT(cs->cx) && !IS_DEFAULT(cs->cy)) return;
721 monitor = MonitorFromWindow( cs->hwndParent, MONITOR_DEFAULTTOPRIMARY );
722 mon_info.cbSize = sizeof(mon_info);
723 GetMonitorInfoW( monitor, &mon_info );
724 GetStartupInfoW( &info );
726 if (IS_DEFAULT(cs->x))
728 if (!IS_DEFAULT(cs->y)) *sw = cs->y;
729 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : mon_info.rcWork.left;
730 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : mon_info.rcWork.top;
733 if (IS_DEFAULT(cs->cx))
735 if (info.dwFlags & STARTF_USESIZE)
737 cs->cx = info.dwXSize;
738 cs->cy = info.dwYSize;
740 else
742 cs->cx = (mon_info.rcWork.right - mon_info.rcWork.left) * 3 / 4 - cs->x;
743 cs->cy = (mon_info.rcWork.bottom - mon_info.rcWork.top) * 3 / 4 - cs->y;
746 /* neither x nor cx are default. Check the y values .
747 * In the trace we see Outlook and Outlook Express using
748 * cy set to CW_USEDEFAULT when opening the address book.
750 else if (IS_DEFAULT(cs->cy))
752 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
753 cs->cy = (mon_info.rcWork.bottom - mon_info.rcWork.top) * 3 / 4 - cs->y;
756 #undef IS_DEFAULT
759 /***********************************************************************
760 * dump_window_styles
762 static void dump_window_styles( DWORD style, DWORD exstyle )
764 TRACE( "style:" );
765 if(style & WS_POPUP) TRACE(" WS_POPUP");
766 if(style & WS_CHILD) TRACE(" WS_CHILD");
767 if(style & WS_MINIMIZE) TRACE(" WS_MINIMIZE");
768 if(style & WS_VISIBLE) TRACE(" WS_VISIBLE");
769 if(style & WS_DISABLED) TRACE(" WS_DISABLED");
770 if(style & WS_CLIPSIBLINGS) TRACE(" WS_CLIPSIBLINGS");
771 if(style & WS_CLIPCHILDREN) TRACE(" WS_CLIPCHILDREN");
772 if(style & WS_MAXIMIZE) TRACE(" WS_MAXIMIZE");
773 if((style & WS_CAPTION) == WS_CAPTION) TRACE(" WS_CAPTION");
774 else
776 if(style & WS_BORDER) TRACE(" WS_BORDER");
777 if(style & WS_DLGFRAME) TRACE(" WS_DLGFRAME");
779 if(style & WS_VSCROLL) TRACE(" WS_VSCROLL");
780 if(style & WS_HSCROLL) TRACE(" WS_HSCROLL");
781 if(style & WS_SYSMENU) TRACE(" WS_SYSMENU");
782 if(style & WS_THICKFRAME) TRACE(" WS_THICKFRAME");
783 if (style & WS_CHILD)
785 if(style & WS_GROUP) TRACE(" WS_GROUP");
786 if(style & WS_TABSTOP) TRACE(" WS_TABSTOP");
788 else
790 if(style & WS_MINIMIZEBOX) TRACE(" WS_MINIMIZEBOX");
791 if(style & WS_MAXIMIZEBOX) TRACE(" WS_MAXIMIZEBOX");
794 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
795 #define DUMPED_STYLES \
796 (WS_POPUP | \
797 WS_CHILD | \
798 WS_MINIMIZE | \
799 WS_VISIBLE | \
800 WS_DISABLED | \
801 WS_CLIPSIBLINGS | \
802 WS_CLIPCHILDREN | \
803 WS_MAXIMIZE | \
804 WS_BORDER | \
805 WS_DLGFRAME | \
806 WS_VSCROLL | \
807 WS_HSCROLL | \
808 WS_SYSMENU | \
809 WS_THICKFRAME | \
810 WS_GROUP | \
811 WS_TABSTOP | \
812 WS_MINIMIZEBOX | \
813 WS_MAXIMIZEBOX)
815 if(style & ~DUMPED_STYLES) TRACE(" %08lx", style & ~DUMPED_STYLES);
816 TRACE("\n");
817 #undef DUMPED_STYLES
819 TRACE( "exstyle:" );
820 if(exstyle & WS_EX_DLGMODALFRAME) TRACE(" WS_EX_DLGMODALFRAME");
821 if(exstyle & WS_EX_DRAGDETECT) TRACE(" WS_EX_DRAGDETECT");
822 if(exstyle & WS_EX_NOPARENTNOTIFY) TRACE(" WS_EX_NOPARENTNOTIFY");
823 if(exstyle & WS_EX_TOPMOST) TRACE(" WS_EX_TOPMOST");
824 if(exstyle & WS_EX_ACCEPTFILES) TRACE(" WS_EX_ACCEPTFILES");
825 if(exstyle & WS_EX_TRANSPARENT) TRACE(" WS_EX_TRANSPARENT");
826 if(exstyle & WS_EX_MDICHILD) TRACE(" WS_EX_MDICHILD");
827 if(exstyle & WS_EX_TOOLWINDOW) TRACE(" WS_EX_TOOLWINDOW");
828 if(exstyle & WS_EX_WINDOWEDGE) TRACE(" WS_EX_WINDOWEDGE");
829 if(exstyle & WS_EX_CLIENTEDGE) TRACE(" WS_EX_CLIENTEDGE");
830 if(exstyle & WS_EX_CONTEXTHELP) TRACE(" WS_EX_CONTEXTHELP");
831 if(exstyle & WS_EX_RIGHT) TRACE(" WS_EX_RIGHT");
832 if(exstyle & WS_EX_RTLREADING) TRACE(" WS_EX_RTLREADING");
833 if(exstyle & WS_EX_LEFTSCROLLBAR) TRACE(" WS_EX_LEFTSCROLLBAR");
834 if(exstyle & WS_EX_CONTROLPARENT) TRACE(" WS_EX_CONTROLPARENT");
835 if(exstyle & WS_EX_STATICEDGE) TRACE(" WS_EX_STATICEDGE");
836 if(exstyle & WS_EX_APPWINDOW) TRACE(" WS_EX_APPWINDOW");
837 if(exstyle & WS_EX_LAYERED) TRACE(" WS_EX_LAYERED");
839 #define DUMPED_EX_STYLES \
840 (WS_EX_DLGMODALFRAME | \
841 WS_EX_DRAGDETECT | \
842 WS_EX_NOPARENTNOTIFY | \
843 WS_EX_TOPMOST | \
844 WS_EX_ACCEPTFILES | \
845 WS_EX_TRANSPARENT | \
846 WS_EX_MDICHILD | \
847 WS_EX_TOOLWINDOW | \
848 WS_EX_WINDOWEDGE | \
849 WS_EX_CLIENTEDGE | \
850 WS_EX_CONTEXTHELP | \
851 WS_EX_RIGHT | \
852 WS_EX_RTLREADING | \
853 WS_EX_LEFTSCROLLBAR | \
854 WS_EX_CONTROLPARENT | \
855 WS_EX_STATICEDGE | \
856 WS_EX_APPWINDOW | \
857 WS_EX_LAYERED)
859 if(exstyle & ~DUMPED_EX_STYLES) TRACE(" %08lx", exstyle & ~DUMPED_EX_STYLES);
860 TRACE("\n");
861 #undef DUMPED_EX_STYLES
865 /***********************************************************************
866 * WIN_CreateWindowEx
868 * Implementation of CreateWindowEx().
870 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, LPCWSTR className, UINT flags )
872 INT cx, cy, style, sw = SW_SHOW;
873 LRESULT result;
874 RECT rect;
875 WND *wndPtr;
876 HWND hwnd, parent, owner, top_child = 0;
877 BOOL unicode = (flags & WIN_ISUNICODE) != 0;
878 MDICREATESTRUCTA mdi_cs;
879 CBT_CREATEWNDA cbtc;
880 CREATESTRUCTA cbcs;
882 TRACE("%s %s ex=%08x style=%08x %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
883 unicode ? debugstr_w((LPCWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
884 debugstr_w(className),
885 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
886 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
887 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
889 /* Fix the styles for MDI children */
890 if (cs->dwExStyle & WS_EX_MDICHILD)
892 UINT flags = 0;
894 wndPtr = WIN_GetPtr(cs->hwndParent);
895 if (wndPtr && wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
897 flags = wndPtr->flags;
898 WIN_ReleasePtr(wndPtr);
901 if (!(flags & WIN_ISMDICLIENT))
903 WARN("WS_EX_MDICHILD, but parent %p is not MDIClient\n", cs->hwndParent);
904 return 0;
907 /* cs->lpCreateParams of WM_[NC]CREATE is different for MDI children.
908 * MDICREATESTRUCT members have the originally passed values.
910 * Note: we rely on the fact that MDICREATESTRUCTA and MDICREATESTRUCTW
911 * have the same layout.
913 mdi_cs.szClass = cs->lpszClass;
914 mdi_cs.szTitle = cs->lpszName;
915 mdi_cs.hOwner = cs->hInstance;
916 mdi_cs.x = cs->x;
917 mdi_cs.y = cs->y;
918 mdi_cs.cx = cs->cx;
919 mdi_cs.cy = cs->cy;
920 mdi_cs.style = cs->style;
921 mdi_cs.lParam = (LPARAM)cs->lpCreateParams;
923 cs->lpCreateParams = (LPVOID)&mdi_cs;
925 if (GetWindowLongW(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
927 if (cs->style & WS_POPUP)
929 TRACE("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n");
930 return 0;
932 cs->style |= WS_CHILD | WS_CLIPSIBLINGS;
934 else
936 cs->style &= ~WS_POPUP;
937 cs->style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
938 WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
941 top_child = GetWindow(cs->hwndParent, GW_CHILD);
943 if (top_child)
945 /* Restore current maximized child */
946 if((cs->style & WS_VISIBLE) && IsZoomed(top_child))
948 TRACE("Restoring current maximized child %p\n", top_child);
949 SendMessageW( top_child, WM_SETREDRAW, FALSE, 0 );
950 ShowWindow( top_child, SW_SHOWNORMAL );
951 SendMessageW( top_child, WM_SETREDRAW, TRUE, 0 );
956 /* Find the parent window */
958 parent = cs->hwndParent;
959 owner = 0;
961 if (cs->hwndParent == HWND_MESSAGE)
963 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
964 * message window (style: WS_POPUP|WS_DISABLED)
966 FIXME("Parent is HWND_MESSAGE\n");
967 parent = GetDesktopWindow();
969 else if (cs->hwndParent)
971 if ((cs->style & (WS_CHILD|WS_POPUP)) != WS_CHILD)
973 parent = GetDesktopWindow();
974 owner = cs->hwndParent;
977 else
979 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
981 WARN("No parent for child window\n" );
982 SetLastError(ERROR_TLW_WITH_WSCHILD);
983 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
985 if (className != (LPCWSTR)DESKTOP_CLASS_ATOM) /* are we creating the desktop itself? */
986 parent = GetDesktopWindow();
989 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
991 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
992 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
993 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
994 cs->dwExStyle |= WS_EX_WINDOWEDGE;
995 else
996 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
998 /* Create the window structure */
1000 if (!(wndPtr = create_window_handle( parent, owner, className, cs->hInstance, unicode )))
1001 return 0;
1002 hwnd = wndPtr->hwndSelf;
1004 /* Fill the window structure */
1006 wndPtr->tid = GetCurrentThreadId();
1007 wndPtr->hInstance = cs->hInstance;
1008 wndPtr->text = NULL;
1009 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1010 wndPtr->dwExStyle = cs->dwExStyle;
1011 wndPtr->wIDmenu = 0;
1012 wndPtr->helpContext = 0;
1013 wndPtr->pVScroll = NULL;
1014 wndPtr->pHScroll = NULL;
1015 wndPtr->userdata = 0;
1016 wndPtr->hIcon = 0;
1017 wndPtr->hIconSmall = 0;
1018 wndPtr->hSysMenu = 0;
1019 wndPtr->flags |= (flags & WIN_ISWIN32);
1021 if (wndPtr->dwStyle & WS_SYSMENU) SetSystemMenu( hwnd, 0 );
1024 * Correct the window styles.
1026 * It affects only the style loaded into the WIN structure.
1029 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
1031 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1032 if (!(wndPtr->dwStyle & WS_POPUP))
1033 wndPtr->dwStyle |= WS_CAPTION;
1037 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1038 * why does the user get to set it?
1041 if ((wndPtr->dwExStyle & WS_EX_DLGMODALFRAME) ||
1042 (wndPtr->dwStyle & (WS_DLGFRAME | WS_THICKFRAME)))
1043 wndPtr->dwExStyle |= WS_EX_WINDOWEDGE;
1044 else
1045 wndPtr->dwExStyle &= ~WS_EX_WINDOWEDGE;
1047 if (!(wndPtr->dwStyle & (WS_CHILD | WS_POPUP)))
1048 wndPtr->flags |= WIN_NEED_SIZE;
1050 SERVER_START_REQ( set_window_info )
1052 req->handle = hwnd;
1053 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE | SET_WIN_UNICODE;
1054 req->style = wndPtr->dwStyle;
1055 req->ex_style = wndPtr->dwExStyle;
1056 req->instance = (void *)wndPtr->hInstance;
1057 req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
1058 req->extra_offset = -1;
1059 wine_server_call( req );
1061 SERVER_END_REQ;
1063 /* Set the window menu */
1065 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
1067 if (cs->hMenu)
1069 if (!MENU_SetMenu(hwnd, cs->hMenu))
1071 WIN_ReleasePtr( wndPtr );
1072 free_window_handle( hwnd );
1073 return 0;
1076 else
1078 LPCSTR menuName = (LPCSTR)GetClassLongPtrA( hwnd, GCLP_MENUNAME );
1079 if (menuName)
1081 if (!cs->hInstance || HIWORD(cs->hInstance))
1082 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1083 else
1084 cs->hMenu = HMENU_32(LoadMenu16(HINSTANCE_16(cs->hInstance),menuName));
1086 if (cs->hMenu) MENU_SetMenu( hwnd, cs->hMenu );
1090 else SetWindowLongPtrW( hwnd, GWLP_ID, (ULONG_PTR)cs->hMenu );
1092 /* call the WH_CBT hook */
1094 /* the window style passed to the hook must be the real window style,
1095 * rather than just the window style that the caller to CreateWindowEx
1096 * passed in, so we have to copy the original CREATESTRUCT and get the
1097 * the real style. */
1098 cbcs = *cs;
1099 cbcs.style = wndPtr->dwStyle;
1100 cbtc.lpcs = &cbcs;
1101 cbtc.hwndInsertAfter = HWND_TOP;
1102 WIN_ReleasePtr( wndPtr );
1103 if (HOOK_CallHooks( WH_CBT, HCBT_CREATEWND, (WPARAM)hwnd, (LPARAM)&cbtc, unicode )) goto failed;
1105 /* send the WM_GETMINMAXINFO message and fix the size if needed */
1107 cx = cs->cx;
1108 cy = cs->cy;
1109 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
1111 POINT maxSize, maxPos, minTrack, maxTrack;
1112 WINPOS_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack);
1113 if (maxTrack.x < cx) cx = maxTrack.x;
1114 if (maxTrack.y < cy) cy = maxTrack.y;
1117 if (cx < 0) cx = 0;
1118 if (cy < 0) cy = 0;
1119 SetRect( &rect, cs->x, cs->y, cs->x + cx, cs->y + cy );
1120 if (!set_window_pos( hwnd, 0, SWP_NOZORDER | SWP_NOACTIVATE, &rect, &rect, NULL )) goto failed;
1122 /* send WM_NCCREATE */
1124 TRACE( "hwnd %p cs %d,%d %dx%d\n", hwnd, cs->x, cs->y, cx, cy );
1125 if (unicode)
1126 result = SendMessageW( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
1127 else
1128 result = SendMessageA( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
1129 if (!result)
1131 WARN( "%p: aborted by WM_NCCREATE\n", hwnd );
1132 goto failed;
1135 /* send WM_NCCALCSIZE */
1137 if ((wndPtr = WIN_GetPtr(hwnd)))
1139 /* yes, even if the CBT hook was called with HWND_TOP */
1140 HWND insert_after = (wndPtr->dwStyle & WS_CHILD) ? HWND_BOTTOM : HWND_TOP;
1141 RECT window_rect = wndPtr->rectWindow;
1142 RECT client_rect = window_rect;
1143 WIN_ReleasePtr( wndPtr );
1144 SendMessageW( hwnd, WM_NCCALCSIZE, FALSE, (LPARAM)&client_rect );
1145 set_window_pos( hwnd, insert_after, SWP_NOACTIVATE, &window_rect, &client_rect, NULL );
1147 else return 0;
1149 /* send WM_CREATE */
1151 if (unicode)
1152 result = SendMessageW( hwnd, WM_CREATE, 0, (LPARAM)cs );
1153 else
1154 result = SendMessageA( hwnd, WM_CREATE, 0, (LPARAM)cs );
1155 if (result == -1) goto failed;
1157 /* call the driver */
1159 if (!USER_Driver->pCreateWindow( hwnd )) goto failed;
1161 NotifyWinEvent(EVENT_OBJECT_CREATE, hwnd, OBJID_WINDOW, 0);
1163 /* send the size messages */
1165 if (!(wndPtr = WIN_GetPtr(hwnd))) return 0;
1166 if (!(wndPtr->flags & WIN_NEED_SIZE))
1168 rect = wndPtr->rectClient;
1169 WIN_ReleasePtr( wndPtr );
1170 SendMessageW( hwnd, WM_SIZE, SIZE_RESTORED,
1171 MAKELONG(rect.right-rect.left, rect.bottom-rect.top));
1172 SendMessageW( hwnd, WM_MOVE, 0, MAKELONG( rect.left, rect.top ) );
1174 else WIN_ReleasePtr( wndPtr );
1176 /* Show the window, maximizing or minimizing if needed */
1178 style = WIN_SetStyle( hwnd, 0, WS_MAXIMIZE | WS_MINIMIZE );
1179 if (style & (WS_MINIMIZE | WS_MAXIMIZE))
1181 RECT newPos;
1182 UINT swFlag = (style & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
1184 swFlag = WINPOS_MinMaximize( hwnd, swFlag, &newPos );
1185 swFlag |= SWP_FRAMECHANGED; /* Frame always gets changed */
1186 if (!(style & WS_VISIBLE) || (style & WS_CHILD) || GetActiveWindow()) swFlag |= SWP_NOACTIVATE;
1187 SetWindowPos( hwnd, 0, newPos.left, newPos.top, newPos.right, newPos.bottom, swFlag );
1190 /* Notify the parent window only */
1192 send_parent_notify( hwnd, WM_CREATE );
1193 if (!IsWindow( hwnd )) return 0;
1195 if (cs->style & WS_VISIBLE)
1197 if (cs->style & WS_MAXIMIZE)
1198 sw = SW_SHOW;
1199 else if (cs->style & WS_MINIMIZE)
1200 sw = SW_SHOWMINIMIZED;
1202 ShowWindow( hwnd, sw );
1203 if (cs->dwExStyle & WS_EX_MDICHILD)
1205 SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
1206 /* ShowWindow won't activate child windows */
1207 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE );
1211 /* Call WH_SHELL hook */
1213 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1214 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1216 TRACE("created window %p\n", hwnd);
1217 return hwnd;
1219 failed:
1220 WIN_DestroyWindow( hwnd );
1221 return 0;
1225 /***********************************************************************
1226 * CreateWindow (USER.41)
1228 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1229 DWORD style, INT16 x, INT16 y, INT16 width,
1230 INT16 height, HWND16 parent, HMENU16 menu,
1231 HINSTANCE16 instance, LPVOID data )
1233 return CreateWindowEx16( 0, className, windowName, style,
1234 x, y, width, height, parent, menu, instance, data );
1238 /***********************************************************************
1239 * CreateWindowEx (USER.452)
1241 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1242 LPCSTR windowName, DWORD style, INT16 x,
1243 INT16 y, INT16 width, INT16 height,
1244 HWND16 parent, HMENU16 menu,
1245 HINSTANCE16 instance, LPVOID data )
1247 CREATESTRUCTA cs;
1248 char buffer[256];
1250 /* Fix the coordinates */
1252 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1253 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1254 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1255 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1257 /* Create the window */
1259 cs.lpCreateParams = data;
1260 cs.hInstance = HINSTANCE_32(instance);
1261 cs.hMenu = HMENU_32(menu);
1262 cs.hwndParent = WIN_Handle32( parent );
1263 cs.style = style;
1264 cs.lpszName = windowName;
1265 cs.lpszClass = className;
1266 cs.dwExStyle = exStyle;
1268 if (!IS_INTRESOURCE(className))
1270 WCHAR bufferW[256];
1272 if (!MultiByteToWideChar( CP_ACP, 0, className, -1, bufferW, sizeof(bufferW)/sizeof(WCHAR) ))
1273 return 0;
1274 return HWND_16( WIN_CreateWindowEx( &cs, bufferW, 0 ));
1276 else
1278 if (!GlobalGetAtomNameA( LOWORD(className), buffer, sizeof(buffer) ))
1280 ERR( "bad atom %x\n", LOWORD(className));
1281 return 0;
1283 cs.lpszClass = buffer;
1284 return HWND_16( WIN_CreateWindowEx( &cs, (LPCWSTR)className, 0 ));
1289 /***********************************************************************
1290 * CreateWindowExA (USER32.@)
1292 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1293 LPCSTR windowName, DWORD style, INT x,
1294 INT y, INT width, INT height,
1295 HWND parent, HMENU menu,
1296 HINSTANCE instance, LPVOID data )
1298 CREATESTRUCTA cs;
1300 cs.lpCreateParams = data;
1301 cs.hInstance = instance;
1302 cs.hMenu = menu;
1303 cs.hwndParent = parent;
1304 cs.x = x;
1305 cs.y = y;
1306 cs.cx = width;
1307 cs.cy = height;
1308 cs.style = style;
1309 cs.lpszName = windowName;
1310 cs.lpszClass = className;
1311 cs.dwExStyle = exStyle;
1313 if (!IS_INTRESOURCE(className))
1315 WCHAR bufferW[256];
1316 if (!MultiByteToWideChar( CP_ACP, 0, className, -1, bufferW, sizeof(bufferW)/sizeof(WCHAR) ))
1317 return 0;
1318 return WIN_CreateWindowEx( &cs, bufferW, WIN_ISWIN32 );
1320 return WIN_CreateWindowEx( &cs, (LPCWSTR)className, WIN_ISWIN32 );
1324 /***********************************************************************
1325 * CreateWindowExW (USER32.@)
1327 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1328 LPCWSTR windowName, DWORD style, INT x,
1329 INT y, INT width, INT height,
1330 HWND parent, HMENU menu,
1331 HINSTANCE instance, LPVOID data )
1333 CREATESTRUCTW cs;
1335 cs.lpCreateParams = data;
1336 cs.hInstance = instance;
1337 cs.hMenu = menu;
1338 cs.hwndParent = parent;
1339 cs.x = x;
1340 cs.y = y;
1341 cs.cx = width;
1342 cs.cy = height;
1343 cs.style = style;
1344 cs.lpszName = windowName;
1345 cs.lpszClass = className;
1346 cs.dwExStyle = exStyle;
1348 /* Note: we rely on the fact that CREATESTRUCTA and */
1349 /* CREATESTRUCTW have the same layout. */
1350 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, className, WIN_ISWIN32 | WIN_ISUNICODE );
1354 /***********************************************************************
1355 * WIN_SendDestroyMsg
1357 static void WIN_SendDestroyMsg( HWND hwnd )
1359 GUITHREADINFO info;
1361 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1363 if (hwnd == info.hwndCaret) DestroyCaret();
1364 if (hwnd == info.hwndActive) WINPOS_ActivateOtherWindow( hwnd );
1368 * Send the WM_DESTROY to the window.
1370 SendMessageW( hwnd, WM_DESTROY, 0, 0);
1373 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1374 * make sure that the window still exists when we come back.
1376 if (IsWindow(hwnd))
1378 HWND* pWndArray;
1379 int i;
1381 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1383 for (i = 0; pWndArray[i]; i++)
1385 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1387 HeapFree( GetProcessHeap(), 0, pWndArray );
1389 else
1390 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1394 /***********************************************************************
1395 * DestroyWindow (USER32.@)
1397 BOOL WINAPI DestroyWindow( HWND hwnd )
1399 BOOL is_child;
1401 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1403 SetLastError( ERROR_ACCESS_DENIED );
1404 return FALSE;
1407 TRACE("(%p)\n", hwnd);
1409 /* Call hooks */
1411 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1413 if (MENU_IsMenuActive() == hwnd)
1414 EndMenu();
1416 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1418 if (is_child)
1420 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1421 send_parent_notify( hwnd, WM_DESTROY );
1423 else if (!GetWindow( hwnd, GW_OWNER ))
1425 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1426 /* FIXME: clean up palette - see "Internals" p.352 */
1429 if (!IsWindow(hwnd)) return TRUE;
1431 /* Hide the window */
1432 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)
1434 /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
1435 if (is_child)
1436 ShowWindow( hwnd, SW_HIDE );
1437 else
1438 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1439 SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW );
1442 if (!IsWindow(hwnd)) return TRUE;
1444 /* Recursively destroy owned windows */
1446 if (!is_child)
1448 for (;;)
1450 int i, got_one = 0;
1451 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1452 if (list)
1454 for (i = 0; list[i]; i++)
1456 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1457 if (WIN_IsCurrentThread( list[i] ))
1459 DestroyWindow( list[i] );
1460 got_one = 1;
1461 continue;
1463 WIN_SetOwner( list[i], 0 );
1465 HeapFree( GetProcessHeap(), 0, list );
1467 if (!got_one) break;
1471 /* Send destroy messages */
1473 WIN_SendDestroyMsg( hwnd );
1474 if (!IsWindow( hwnd )) return TRUE;
1476 if (GetClipboardOwner() == hwnd)
1477 CLIPBOARD_ReleaseOwner();
1479 /* Destroy the window storage */
1481 WIN_DestroyWindow( hwnd );
1482 return TRUE;
1486 /***********************************************************************
1487 * CloseWindow (USER32.@)
1489 BOOL WINAPI CloseWindow( HWND hwnd )
1491 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1492 ShowWindow( hwnd, SW_MINIMIZE );
1493 return TRUE;
1497 /***********************************************************************
1498 * OpenIcon (USER32.@)
1500 BOOL WINAPI OpenIcon( HWND hwnd )
1502 if (!IsIconic( hwnd )) return FALSE;
1503 ShowWindow( hwnd, SW_SHOWNORMAL );
1504 return TRUE;
1508 /***********************************************************************
1509 * FindWindowExW (USER32.@)
1511 HWND WINAPI FindWindowExW( HWND parent, HWND child, LPCWSTR className, LPCWSTR title )
1513 HWND *list = NULL;
1514 HWND retvalue = 0;
1515 int i = 0, len = 0;
1516 WCHAR *buffer = NULL;
1518 if (!parent) parent = GetDesktopWindow();
1519 if (title)
1521 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1522 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1525 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1527 if (child)
1529 child = WIN_GetFullHandle( child );
1530 while (list[i] && list[i] != child) i++;
1531 if (!list[i]) goto done;
1532 i++; /* start from next window */
1535 if (title)
1537 while (list[i])
1539 if (GetWindowTextW( list[i], buffer, len + 1 ) && !strcmpiW( buffer, title )) break;
1540 i++;
1543 retvalue = list[i];
1545 done:
1546 HeapFree( GetProcessHeap(), 0, list );
1547 HeapFree( GetProcessHeap(), 0, buffer );
1548 return retvalue;
1553 /***********************************************************************
1554 * FindWindowA (USER32.@)
1556 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1558 HWND ret = FindWindowExA( 0, 0, className, title );
1559 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1560 return ret;
1564 /***********************************************************************
1565 * FindWindowExA (USER32.@)
1567 HWND WINAPI FindWindowExA( HWND parent, HWND child, LPCSTR className, LPCSTR title )
1569 LPWSTR titleW = NULL;
1570 HWND hwnd = 0;
1572 if (title)
1574 DWORD len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1575 if (!(titleW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1576 MultiByteToWideChar( CP_ACP, 0, title, -1, titleW, len );
1579 if (!IS_INTRESOURCE(className))
1581 WCHAR classW[256];
1582 if (MultiByteToWideChar( CP_ACP, 0, className, -1, classW, sizeof(classW)/sizeof(WCHAR) ))
1583 hwnd = FindWindowExW( parent, child, classW, titleW );
1585 else
1587 hwnd = FindWindowExW( parent, child, (LPCWSTR)className, titleW );
1590 HeapFree( GetProcessHeap(), 0, titleW );
1591 return hwnd;
1595 /***********************************************************************
1596 * FindWindowW (USER32.@)
1598 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1600 return FindWindowExW( 0, 0, className, title );
1604 /**********************************************************************
1605 * GetDesktopWindow (USER32.@)
1607 HWND WINAPI GetDesktopWindow(void)
1609 struct user_thread_info *thread_info = get_user_thread_info();
1611 if (thread_info->desktop) return thread_info->desktop;
1613 SERVER_START_REQ( get_desktop_window )
1615 req->force = 0;
1616 if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1618 SERVER_END_REQ;
1620 if (!thread_info->desktop)
1622 static const WCHAR command_line[] = {'\\','e','x','p','l','o','r','e','r','.','e','x','e',' ','/','d','e','s','k','t','o','p',0};
1623 STARTUPINFOW si;
1624 PROCESS_INFORMATION pi;
1625 WCHAR cmdline[MAX_PATH + sizeof(command_line)/sizeof(WCHAR)];
1627 memset( &si, 0, sizeof(si) );
1628 si.cb = sizeof(si);
1629 si.dwFlags = STARTF_USESTDHANDLES;
1630 si.hStdInput = 0;
1631 si.hStdOutput = 0;
1632 si.hStdError = GetStdHandle( STD_ERROR_HANDLE );
1634 GetSystemDirectoryW( cmdline, MAX_PATH );
1635 lstrcatW( cmdline, command_line );
1636 if (CreateProcessW( NULL, cmdline, NULL, NULL, FALSE, DETACHED_PROCESS,
1637 NULL, NULL, &si, &pi ))
1639 TRACE( "started explorer pid %04x tid %04x\n", pi.dwProcessId, pi.dwThreadId );
1640 WaitForInputIdle( pi.hProcess, 10000 );
1641 CloseHandle( pi.hThread );
1642 CloseHandle( pi.hProcess );
1645 else WARN( "failed to start explorer, err %d\n", GetLastError() );
1647 SERVER_START_REQ( get_desktop_window )
1649 req->force = 1;
1650 if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1652 SERVER_END_REQ;
1655 if (!thread_info->desktop || !USER_Driver->pCreateDesktopWindow( thread_info->desktop ))
1656 ERR( "failed to create desktop window\n" );
1658 return thread_info->desktop;
1662 /*******************************************************************
1663 * EnableWindow (USER32.@)
1665 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1667 BOOL retvalue;
1668 HWND full_handle;
1670 if (is_broadcast(hwnd))
1672 SetLastError( ERROR_INVALID_PARAMETER );
1673 return FALSE;
1676 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1677 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1679 hwnd = full_handle;
1681 TRACE("( %p, %d )\n", hwnd, enable);
1683 retvalue = !IsWindowEnabled( hwnd );
1685 if (enable && retvalue)
1687 WIN_SetStyle( hwnd, 0, WS_DISABLED );
1688 SendMessageW( hwnd, WM_ENABLE, TRUE, 0 );
1690 else if (!enable && !retvalue)
1692 HWND capture_wnd;
1694 SendMessageW( hwnd, WM_CANCELMODE, 0, 0);
1696 WIN_SetStyle( hwnd, WS_DISABLED, 0 );
1698 if (hwnd == GetFocus())
1699 SetFocus( 0 ); /* A disabled window can't have the focus */
1701 capture_wnd = GetCapture();
1702 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1703 ReleaseCapture(); /* A disabled window can't capture the mouse */
1705 SendMessageW( hwnd, WM_ENABLE, FALSE, 0 );
1707 return retvalue;
1711 /***********************************************************************
1712 * IsWindowEnabled (USER32.@)
1714 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1716 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1720 /***********************************************************************
1721 * IsWindowUnicode (USER32.@)
1723 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1725 WND * wndPtr;
1726 BOOL retvalue = FALSE;
1728 if (!(wndPtr = WIN_GetPtr(hwnd))) return FALSE;
1730 if (wndPtr == WND_DESKTOP) return TRUE;
1732 if (wndPtr != WND_OTHER_PROCESS)
1734 retvalue = (wndPtr->flags & WIN_ISUNICODE) != 0;
1735 WIN_ReleasePtr( wndPtr );
1737 else
1739 SERVER_START_REQ( get_window_info )
1741 req->handle = hwnd;
1742 if (!wine_server_call_err( req )) retvalue = reply->is_unicode;
1744 SERVER_END_REQ;
1746 return retvalue;
1750 /**********************************************************************
1751 * WIN_GetWindowLong
1753 * Helper function for GetWindowLong().
1755 static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, UINT size, BOOL unicode )
1757 LONG_PTR retvalue = 0;
1758 WND *wndPtr;
1760 if (offset == GWLP_HWNDPARENT)
1762 HWND parent = GetAncestor( hwnd, GA_PARENT );
1763 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1764 return (ULONG_PTR)parent;
1767 if (!(wndPtr = WIN_GetPtr( hwnd )))
1769 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1770 return 0;
1773 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1775 if (offset == GWLP_WNDPROC)
1777 SetLastError( ERROR_ACCESS_DENIED );
1778 return 0;
1780 SERVER_START_REQ( set_window_info )
1782 req->handle = hwnd;
1783 req->flags = 0; /* don't set anything, just retrieve */
1784 req->extra_offset = (offset >= 0) ? offset : -1;
1785 req->extra_size = (offset >= 0) ? size : 0;
1786 if (!wine_server_call_err( req ))
1788 switch(offset)
1790 case GWL_STYLE: retvalue = reply->old_style; break;
1791 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1792 case GWLP_ID: retvalue = reply->old_id; break;
1793 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1794 case GWLP_USERDATA: retvalue = reply->old_user_data; break;
1795 default:
1796 if (offset >= 0) retvalue = get_win_data( &reply->old_extra_value, size );
1797 else SetLastError( ERROR_INVALID_INDEX );
1798 break;
1802 SERVER_END_REQ;
1803 return retvalue;
1806 /* now we have a valid wndPtr */
1808 if (offset >= 0)
1810 if (offset > (int)(wndPtr->cbWndExtra - size))
1812 WARN("Invalid offset %d\n", offset );
1813 WIN_ReleasePtr( wndPtr );
1814 SetLastError( ERROR_INVALID_INDEX );
1815 return 0;
1817 retvalue = get_win_data( (char *)wndPtr->wExtra + offset, size );
1819 /* Special case for dialog window procedure */
1820 if ((offset == DWLP_DLGPROC) && (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG))
1821 retvalue = (LONG_PTR)WINPROC_GetProc( (WNDPROC)retvalue, unicode );
1822 WIN_ReleasePtr( wndPtr );
1823 return retvalue;
1826 switch(offset)
1828 case GWLP_USERDATA: retvalue = wndPtr->userdata; break;
1829 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1830 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1831 case GWLP_ID: retvalue = wndPtr->wIDmenu; break;
1832 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wndPtr->hInstance; break;
1833 case GWLP_WNDPROC:
1834 /* This looks like a hack only for the edit control (see tests). This makes these controls
1835 * more tolerant to A/W mismatches. The lack of W->A->W conversion for such a mismatch suggests
1836 * that the hack is in GetWindowLongPtr[AW], not in winprocs.
1838 if (wndPtr->winproc == EDIT_winproc_handle && (!unicode != !(wndPtr->flags & WIN_ISUNICODE)))
1839 retvalue = (ULONG_PTR)wndPtr->winproc;
1840 else
1841 retvalue = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, unicode );
1842 break;
1843 default:
1844 WARN("Unknown offset %d\n", offset );
1845 SetLastError( ERROR_INVALID_INDEX );
1846 break;
1848 WIN_ReleasePtr(wndPtr);
1849 return retvalue;
1853 /**********************************************************************
1854 * WIN_SetWindowLong
1856 * Helper function for SetWindowLong().
1858 * 0 is the failure code. However, in the case of failure SetLastError
1859 * must be set to distinguish between a 0 return value and a failure.
1861 LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, UINT size, LONG_PTR newval, BOOL unicode )
1863 STYLESTRUCT style;
1864 BOOL ok;
1865 LONG_PTR retval = 0;
1866 WND *wndPtr;
1868 TRACE( "%p %d %lx %c\n", hwnd, offset, newval, unicode ? 'W' : 'A' );
1870 if (is_broadcast(hwnd))
1872 SetLastError( ERROR_INVALID_PARAMETER );
1873 return FALSE;
1876 if (!(wndPtr = WIN_GetPtr( hwnd )))
1878 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1879 return 0;
1881 if (wndPtr == WND_DESKTOP)
1883 /* can't change anything on the desktop window */
1884 SetLastError( ERROR_ACCESS_DENIED );
1885 return 0;
1887 if (wndPtr == WND_OTHER_PROCESS)
1889 if (offset == GWLP_WNDPROC)
1891 SetLastError( ERROR_ACCESS_DENIED );
1892 return 0;
1894 if (offset > 32767 || offset < -32767)
1896 SetLastError( ERROR_INVALID_INDEX );
1897 return 0;
1899 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, MAKEWPARAM( offset, size ), newval );
1902 /* first some special cases */
1903 switch( offset )
1905 case GWL_STYLE:
1906 case GWL_EXSTYLE:
1907 style.styleOld =
1908 offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
1909 style.styleNew = newval;
1910 WIN_ReleasePtr( wndPtr );
1911 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
1912 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
1913 newval = style.styleNew;
1914 break;
1915 case GWLP_HWNDPARENT:
1916 if (wndPtr->parent == GetDesktopWindow())
1918 WIN_ReleasePtr( wndPtr );
1919 return (ULONG_PTR)WIN_SetOwner( hwnd, (HWND)newval );
1921 else
1923 WIN_ReleasePtr( wndPtr );
1924 return (ULONG_PTR)SetParent( hwnd, (HWND)newval );
1926 case GWLP_WNDPROC:
1928 WNDPROC proc;
1929 UINT old_flags = wndPtr->flags;
1930 retval = WIN_GetWindowLong( hwnd, offset, size, unicode );
1931 if (unicode) proc = WINPROC_AllocProc( NULL, (WNDPROC)newval );
1932 else proc = WINPROC_AllocProc( (WNDPROC)newval, NULL );
1933 if (proc) wndPtr->winproc = proc;
1934 if (WINPROC_IsUnicode( proc, unicode )) wndPtr->flags |= WIN_ISUNICODE;
1935 else wndPtr->flags &= ~WIN_ISUNICODE;
1936 if (!((old_flags ^ wndPtr->flags) & WIN_ISUNICODE))
1938 WIN_ReleasePtr( wndPtr );
1939 return retval;
1941 /* update is_unicode flag on the server side */
1942 break;
1944 case GWLP_ID:
1945 case GWLP_HINSTANCE:
1946 case GWLP_USERDATA:
1947 break;
1948 case DWLP_DLGPROC:
1949 if ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
1950 (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG))
1952 WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWLP_DLGPROC);
1953 retval = (ULONG_PTR)WINPROC_GetProc( *ptr, unicode );
1954 if (unicode) *ptr = WINPROC_AllocProc( NULL, (WNDPROC)newval );
1955 else *ptr = WINPROC_AllocProc( (WNDPROC)newval, NULL );
1956 WIN_ReleasePtr( wndPtr );
1957 return retval;
1959 /* fall through */
1960 default:
1961 if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - size))
1963 WARN("Invalid offset %d\n", offset );
1964 WIN_ReleasePtr( wndPtr );
1965 SetLastError( ERROR_INVALID_INDEX );
1966 return 0;
1968 else if (get_win_data( (char *)wndPtr->wExtra + offset, size ) == newval)
1970 /* already set to the same value */
1971 WIN_ReleasePtr( wndPtr );
1972 return newval;
1974 break;
1977 SERVER_START_REQ( set_window_info )
1979 req->handle = hwnd;
1980 req->extra_offset = -1;
1981 switch(offset)
1983 case GWL_STYLE:
1984 req->flags = SET_WIN_STYLE;
1985 req->style = newval;
1986 break;
1987 case GWL_EXSTYLE:
1988 req->flags = SET_WIN_EXSTYLE;
1989 /* WS_EX_TOPMOST can only be changed through SetWindowPos */
1990 newval = (newval & ~WS_EX_TOPMOST) | (wndPtr->dwExStyle & WS_EX_TOPMOST);
1991 req->ex_style = newval;
1992 break;
1993 case GWLP_ID:
1994 req->flags = SET_WIN_ID;
1995 req->id = newval;
1996 break;
1997 case GWLP_HINSTANCE:
1998 req->flags = SET_WIN_INSTANCE;
1999 req->instance = (void *)newval;
2000 break;
2001 case GWLP_WNDPROC:
2002 req->flags = SET_WIN_UNICODE;
2003 req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
2004 break;
2005 case GWLP_USERDATA:
2006 req->flags = SET_WIN_USERDATA;
2007 req->user_data = newval;
2008 break;
2009 default:
2010 req->flags = SET_WIN_EXTRA;
2011 req->extra_offset = offset;
2012 req->extra_size = size;
2013 set_win_data( &req->extra_value, newval, size );
2015 if ((ok = !wine_server_call_err( req )))
2017 switch(offset)
2019 case GWL_STYLE:
2020 wndPtr->dwStyle = newval;
2021 retval = reply->old_style;
2022 break;
2023 case GWL_EXSTYLE:
2024 wndPtr->dwExStyle = newval;
2025 retval = reply->old_ex_style;
2026 break;
2027 case GWLP_ID:
2028 wndPtr->wIDmenu = newval;
2029 retval = reply->old_id;
2030 break;
2031 case GWLP_HINSTANCE:
2032 wndPtr->hInstance = (HINSTANCE)newval;
2033 retval = (ULONG_PTR)reply->old_instance;
2034 break;
2035 case GWLP_WNDPROC:
2036 break;
2037 case GWLP_USERDATA:
2038 wndPtr->userdata = newval;
2039 retval = reply->old_user_data;
2040 break;
2041 default:
2042 retval = get_win_data( (char *)wndPtr->wExtra + offset, size );
2043 set_win_data( (char *)wndPtr->wExtra + offset, newval, size );
2044 break;
2048 SERVER_END_REQ;
2049 WIN_ReleasePtr( wndPtr );
2051 if (!ok) return 0;
2053 if (offset == GWL_STYLE) USER_Driver->pSetWindowStyle( hwnd, retval );
2055 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2056 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2058 return retval;
2062 /**********************************************************************
2063 * GetWindowLong (USER.135)
2065 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2067 WND *wndPtr;
2068 LONG_PTR retvalue;
2069 BOOL is_winproc = (offset == GWLP_WNDPROC);
2071 if (offset >= 0)
2073 if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2075 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2076 return 0;
2078 if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2080 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
2083 * Some programs try to access last element from 16 bit
2084 * code using illegal offset value. Hopefully this is
2085 * what those programs really expect.
2087 if (wndPtr->cbWndExtra >= 4 && offset == wndPtr->cbWndExtra - sizeof(WORD))
2089 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
2090 ERR( "- replaced invalid offset %d with %d\n", offset, offset2 );
2091 offset = offset2;
2093 else
2095 WARN("Invalid offset %d\n", offset );
2096 WIN_ReleasePtr( wndPtr );
2097 SetLastError( ERROR_INVALID_INDEX );
2098 return 0;
2101 is_winproc = ((offset == DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG));
2102 WIN_ReleasePtr( wndPtr );
2105 retvalue = GetWindowLongA( WIN_Handle32(hwnd), offset );
2106 if (is_winproc) retvalue = (LONG_PTR)WINPROC_GetProc16( (WNDPROC)retvalue, FALSE );
2107 return retvalue;
2111 /**********************************************************************
2112 * GetWindowWord (USER32.@)
2114 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
2116 switch(offset)
2118 case GWLP_ID:
2119 case GWLP_HINSTANCE:
2120 case GWLP_HWNDPARENT:
2121 break;
2122 default:
2123 if (offset < 0)
2125 WARN("Invalid offset %d\n", offset );
2126 SetLastError( ERROR_INVALID_INDEX );
2127 return 0;
2129 break;
2131 return WIN_GetWindowLong( hwnd, offset, sizeof(WORD), FALSE );
2135 /**********************************************************************
2136 * GetWindowLongA (USER32.@)
2138 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2140 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), FALSE );
2144 /**********************************************************************
2145 * GetWindowLongW (USER32.@)
2147 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2149 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), TRUE );
2153 /**********************************************************************
2154 * SetWindowLong (USER.136)
2156 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2158 WND *wndPtr;
2159 BOOL is_winproc = (offset == GWLP_WNDPROC);
2161 if (offset == DWLP_DLGPROC)
2163 if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2165 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2166 return 0;
2168 if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2170 is_winproc = ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
2171 (wndPtr->flags & WIN_ISDIALOG));
2172 WIN_ReleasePtr( wndPtr );
2176 if (is_winproc)
2178 WNDPROC new_proc = WINPROC_AllocProc16( (WNDPROC16)newval );
2179 WNDPROC old_proc = (WNDPROC)SetWindowLongPtrA( WIN_Handle32(hwnd), offset, (LONG_PTR)new_proc );
2180 return (LONG)WINPROC_GetProc16( old_proc, FALSE );
2182 else return SetWindowLongA( WIN_Handle32(hwnd), offset, newval );
2186 /**********************************************************************
2187 * SetWindowWord (USER32.@)
2189 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
2191 switch(offset)
2193 case GWLP_ID:
2194 case GWLP_HINSTANCE:
2195 case GWLP_HWNDPARENT:
2196 break;
2197 default:
2198 if (offset < 0)
2200 WARN("Invalid offset %d\n", offset );
2201 SetLastError( ERROR_INVALID_INDEX );
2202 return 0;
2204 break;
2206 return WIN_SetWindowLong( hwnd, offset, sizeof(WORD), newval, FALSE );
2210 /**********************************************************************
2211 * SetWindowLongA (USER32.@)
2213 * See SetWindowLongW.
2215 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2217 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, FALSE );
2221 /**********************************************************************
2222 * SetWindowLongW (USER32.@) Set window attribute
2224 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2225 * value in a window's extra memory.
2227 * The _hwnd_ parameter specifies the window. is the handle to a
2228 * window that has extra memory. The _newval_ parameter contains the
2229 * new attribute or extra memory value. If positive, the _offset_
2230 * parameter is the byte-addressed location in the window's extra
2231 * memory to set. If negative, _offset_ specifies the window
2232 * attribute to set, and should be one of the following values:
2234 * GWL_EXSTYLE The window's extended window style
2236 * GWL_STYLE The window's window style.
2238 * GWLP_WNDPROC Pointer to the window's window procedure.
2240 * GWLP_HINSTANCE The window's pplication instance handle.
2242 * GWLP_ID The window's identifier.
2244 * GWLP_USERDATA The window's user-specified data.
2246 * If the window is a dialog box, the _offset_ parameter can be one of
2247 * the following values:
2249 * DWLP_DLGPROC The address of the window's dialog box procedure.
2251 * DWLP_MSGRESULT The return value of a message
2252 * that the dialog box procedure processed.
2254 * DWLP_USER Application specific information.
2256 * RETURNS
2258 * If successful, returns the previous value located at _offset_. Otherwise,
2259 * returns 0.
2261 * NOTES
2263 * Extra memory for a window class is specified by a nonzero cbWndExtra
2264 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2265 * time of class creation.
2267 * Using GWL_WNDPROC to set a new window procedure effectively creates
2268 * a window subclass. Use CallWindowProc() in the new windows procedure
2269 * to pass messages to the superclass's window procedure.
2271 * The user data is reserved for use by the application which created
2272 * the window.
2274 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2275 * instead, call the EnableWindow() function to change the window's
2276 * disabled state.
2278 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2279 * SetParent() instead.
2281 * Win95:
2282 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2283 * it sends WM_STYLECHANGING before changing the settings
2284 * and WM_STYLECHANGED afterwards.
2285 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2287 LONG WINAPI SetWindowLongW(
2288 HWND hwnd, /* [in] window to alter */
2289 INT offset, /* [in] offset, in bytes, of location to alter */
2290 LONG newval /* [in] new value of location */
2292 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, TRUE );
2296 /*******************************************************************
2297 * GetWindowTextA (USER32.@)
2299 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2301 WCHAR *buffer;
2303 if (!lpString) return 0;
2305 if (WIN_IsCurrentProcess( hwnd ))
2306 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2308 /* when window belongs to other process, don't send a message */
2309 if (nMaxCount <= 0) return 0;
2310 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2311 get_server_window_text( hwnd, buffer, nMaxCount );
2312 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2313 lpString[nMaxCount-1] = 0;
2314 HeapFree( GetProcessHeap(), 0, buffer );
2315 return strlen(lpString);
2319 /*******************************************************************
2320 * InternalGetWindowText (USER32.@)
2322 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2324 WND *win;
2326 if (nMaxCount <= 0) return 0;
2327 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2328 if (win == WND_DESKTOP) lpString[0] = 0;
2329 else if (win != WND_OTHER_PROCESS)
2331 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2332 else lpString[0] = 0;
2333 WIN_ReleasePtr( win );
2335 else
2337 get_server_window_text( hwnd, lpString, nMaxCount );
2339 return strlenW(lpString);
2343 /*******************************************************************
2344 * GetWindowTextW (USER32.@)
2346 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2348 if (!lpString) return 0;
2350 if (WIN_IsCurrentProcess( hwnd ))
2351 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2353 /* when window belongs to other process, don't send a message */
2354 if (nMaxCount <= 0) return 0;
2355 get_server_window_text( hwnd, lpString, nMaxCount );
2356 return strlenW(lpString);
2360 /*******************************************************************
2361 * SetWindowTextA (USER32.@)
2362 * SetWindowText (USER32.@)
2364 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2366 if (is_broadcast(hwnd))
2368 SetLastError( ERROR_INVALID_PARAMETER );
2369 return FALSE;
2371 if (!WIN_IsCurrentProcess( hwnd ))
2372 WARN( "setting text %s of other process window %p should not use SendMessage\n",
2373 debugstr_a(lpString), hwnd );
2374 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2378 /*******************************************************************
2379 * SetWindowTextW (USER32.@)
2381 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2383 if (is_broadcast(hwnd))
2385 SetLastError( ERROR_INVALID_PARAMETER );
2386 return FALSE;
2388 if (!WIN_IsCurrentProcess( hwnd ))
2389 WARN( "setting text %s of other process window %p should not use SendMessage\n",
2390 debugstr_w(lpString), hwnd );
2391 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2395 /*******************************************************************
2396 * GetWindowTextLengthA (USER32.@)
2398 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2400 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2403 /*******************************************************************
2404 * GetWindowTextLengthW (USER32.@)
2406 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2408 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2412 /*******************************************************************
2413 * IsWindow (USER32.@)
2415 BOOL WINAPI IsWindow( HWND hwnd )
2417 WND *ptr;
2418 BOOL ret;
2420 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2421 if (ptr == WND_DESKTOP) return TRUE;
2423 if (ptr != WND_OTHER_PROCESS)
2425 WIN_ReleasePtr( ptr );
2426 return TRUE;
2429 /* check other processes */
2430 SERVER_START_REQ( get_window_info )
2432 req->handle = hwnd;
2433 ret = !wine_server_call_err( req );
2435 SERVER_END_REQ;
2436 return ret;
2440 /***********************************************************************
2441 * GetWindowThreadProcessId (USER32.@)
2443 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2445 WND *ptr;
2446 DWORD tid = 0;
2448 if (!(ptr = WIN_GetPtr( hwnd )))
2450 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2451 return 0;
2454 if (ptr != WND_OTHER_PROCESS && ptr != WND_DESKTOP)
2456 /* got a valid window */
2457 tid = ptr->tid;
2458 if (process) *process = GetCurrentProcessId();
2459 WIN_ReleasePtr( ptr );
2460 return tid;
2463 /* check other processes */
2464 SERVER_START_REQ( get_window_info )
2466 req->handle = hwnd;
2467 if (!wine_server_call_err( req ))
2469 tid = (DWORD)reply->tid;
2470 if (process) *process = (DWORD)reply->pid;
2473 SERVER_END_REQ;
2474 return tid;
2478 /*****************************************************************
2479 * GetParent (USER32.@)
2481 HWND WINAPI GetParent( HWND hwnd )
2483 WND *wndPtr;
2484 HWND retvalue = 0;
2486 if (!(wndPtr = WIN_GetPtr( hwnd )))
2488 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2489 return 0;
2491 if (wndPtr == WND_DESKTOP) return 0;
2492 if (wndPtr == WND_OTHER_PROCESS)
2494 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2495 if (style & (WS_POPUP | WS_CHILD))
2497 SERVER_START_REQ( get_window_tree )
2499 req->handle = hwnd;
2500 if (!wine_server_call_err( req ))
2502 if (style & WS_POPUP) retvalue = reply->owner;
2503 else if (style & WS_CHILD) retvalue = reply->parent;
2506 SERVER_END_REQ;
2509 else
2511 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2512 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2513 WIN_ReleasePtr( wndPtr );
2515 return retvalue;
2519 /*****************************************************************
2520 * GetAncestor (USER32.@)
2522 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2524 WND *win;
2525 HWND *list, ret = 0;
2527 switch(type)
2529 case GA_PARENT:
2530 if (!(win = WIN_GetPtr( hwnd )))
2532 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2533 return 0;
2535 if (win == WND_DESKTOP) return 0;
2536 if (win != WND_OTHER_PROCESS)
2538 ret = win->parent;
2539 WIN_ReleasePtr( win );
2541 else /* need to query the server */
2543 SERVER_START_REQ( get_window_tree )
2545 req->handle = hwnd;
2546 if (!wine_server_call_err( req )) ret = reply->parent;
2548 SERVER_END_REQ;
2550 break;
2552 case GA_ROOT:
2553 if (!(list = list_window_parents( hwnd ))) return 0;
2555 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2556 else
2558 int count = 2;
2559 while (list[count]) count++;
2560 ret = list[count - 2]; /* get the one before the desktop */
2562 HeapFree( GetProcessHeap(), 0, list );
2563 break;
2565 case GA_ROOTOWNER:
2566 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2567 for (;;)
2569 HWND parent = GetParent( ret );
2570 if (!parent) break;
2571 ret = parent;
2573 break;
2575 return ret;
2579 /*****************************************************************
2580 * SetParent (USER32.@)
2582 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2584 HWND full_handle;
2585 HWND old_parent = 0;
2586 BOOL was_visible;
2587 WND *wndPtr;
2588 BOOL ret;
2590 if (is_broadcast(hwnd) || is_broadcast(parent))
2592 SetLastError(ERROR_INVALID_PARAMETER);
2593 return 0;
2596 if (!parent) parent = GetDesktopWindow();
2597 else parent = WIN_GetFullHandle( parent );
2599 if (!IsWindow( parent ))
2601 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2602 return 0;
2605 /* Some applications try to set a child as a parent */
2606 if (IsChild(hwnd, parent))
2608 SetLastError( ERROR_INVALID_PARAMETER );
2609 return 0;
2612 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2613 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2615 /* Windows hides the window first, then shows it again
2616 * including the WM_SHOWWINDOW messages and all */
2617 was_visible = ShowWindow( hwnd, SW_HIDE );
2619 wndPtr = WIN_GetPtr( hwnd );
2620 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return 0;
2622 SERVER_START_REQ( set_parent )
2624 req->handle = hwnd;
2625 req->parent = parent;
2626 if ((ret = !wine_server_call( req )))
2628 old_parent = reply->old_parent;
2629 wndPtr->parent = parent = reply->full_parent;
2633 SERVER_END_REQ;
2634 WIN_ReleasePtr( wndPtr );
2635 if (!ret) return 0;
2637 USER_Driver->pSetParent( full_handle, parent, old_parent );
2639 /* SetParent additionally needs to make hwnd the topmost window
2640 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2641 WM_WINDOWPOSCHANGED notification messages.
2643 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0,
2644 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2645 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2646 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2648 return old_parent;
2652 /*******************************************************************
2653 * IsChild (USER32.@)
2655 BOOL WINAPI IsChild( HWND parent, HWND child )
2657 HWND *list = list_window_parents( child );
2658 int i;
2659 BOOL ret;
2661 if (!list) return FALSE;
2662 parent = WIN_GetFullHandle( parent );
2663 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2664 ret = list[i] && list[i+1];
2665 HeapFree( GetProcessHeap(), 0, list );
2666 return ret;
2670 /***********************************************************************
2671 * IsWindowVisible (USER32.@)
2673 BOOL WINAPI IsWindowVisible( HWND hwnd )
2675 HWND *list;
2676 BOOL retval = TRUE;
2677 int i;
2679 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2680 if (!(list = list_window_parents( hwnd ))) return TRUE;
2681 if (list[0] && list[1]) /* desktop window is considered always visible so we don't check it */
2683 for (i = 0; list[i+1]; i++)
2684 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2685 retval = !list[i+1];
2687 HeapFree( GetProcessHeap(), 0, list );
2688 return retval;
2692 /***********************************************************************
2693 * WIN_IsWindowDrawable
2695 * hwnd is drawable when it is visible, all parents are not
2696 * minimized, and it is itself not minimized unless we are
2697 * trying to draw its default class icon.
2699 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2701 HWND *list;
2702 BOOL retval = TRUE;
2703 int i;
2704 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2706 if (!(style & WS_VISIBLE)) return FALSE;
2707 if ((style & WS_MINIMIZE) && icon && GetClassLongPtrW( hwnd, GCLP_HICON )) return FALSE;
2709 if (!(list = list_window_parents( hwnd ))) return TRUE;
2710 if (list[0] && list[1]) /* desktop window is considered always visible so we don't check it */
2712 for (i = 0; list[i+1]; i++)
2713 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2714 break;
2715 retval = !list[i+1];
2717 HeapFree( GetProcessHeap(), 0, list );
2718 return retval;
2722 /*******************************************************************
2723 * GetTopWindow (USER32.@)
2725 HWND WINAPI GetTopWindow( HWND hwnd )
2727 if (!hwnd) hwnd = GetDesktopWindow();
2728 return GetWindow( hwnd, GW_CHILD );
2732 /*******************************************************************
2733 * GetWindow (USER32.@)
2735 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2737 HWND retval = 0;
2739 if (rel == GW_OWNER) /* this one may be available locally */
2741 WND *wndPtr = WIN_GetPtr( hwnd );
2742 if (!wndPtr)
2744 SetLastError( ERROR_INVALID_HANDLE );
2745 return 0;
2747 if (wndPtr == WND_DESKTOP) return 0;
2748 if (wndPtr != WND_OTHER_PROCESS)
2750 retval = wndPtr->owner;
2751 WIN_ReleasePtr( wndPtr );
2752 return retval;
2754 /* else fall through to server call */
2757 SERVER_START_REQ( get_window_tree )
2759 req->handle = hwnd;
2760 if (!wine_server_call_err( req ))
2762 switch(rel)
2764 case GW_HWNDFIRST:
2765 retval = reply->first_sibling;
2766 break;
2767 case GW_HWNDLAST:
2768 retval = reply->last_sibling;
2769 break;
2770 case GW_HWNDNEXT:
2771 retval = reply->next_sibling;
2772 break;
2773 case GW_HWNDPREV:
2774 retval = reply->prev_sibling;
2775 break;
2776 case GW_OWNER:
2777 retval = reply->owner;
2778 break;
2779 case GW_CHILD:
2780 retval = reply->first_child;
2781 break;
2785 SERVER_END_REQ;
2786 return retval;
2790 /*******************************************************************
2791 * ShowOwnedPopups (USER32.@)
2793 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2795 int count = 0;
2796 WND *pWnd;
2797 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2799 if (!win_array) return TRUE;
2801 while (win_array[count]) count++;
2802 while (--count >= 0)
2804 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2805 if (!(pWnd = WIN_GetPtr( win_array[count] ))) continue;
2806 if (pWnd == WND_OTHER_PROCESS) continue;
2807 if (fShow)
2809 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2811 WIN_ReleasePtr( pWnd );
2812 /* In Windows, ShowOwnedPopups(TRUE) generates
2813 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2814 * regardless of the state of the owner
2816 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_SHOWNORMAL, SW_PARENTOPENING);
2817 continue;
2820 else
2822 if (pWnd->dwStyle & WS_VISIBLE)
2824 WIN_ReleasePtr( pWnd );
2825 /* In Windows, ShowOwnedPopups(FALSE) generates
2826 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2827 * regardless of the state of the owner
2829 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2830 continue;
2833 WIN_ReleasePtr( pWnd );
2835 HeapFree( GetProcessHeap(), 0, win_array );
2836 return TRUE;
2840 /*******************************************************************
2841 * GetLastActivePopup (USER32.@)
2843 HWND WINAPI GetLastActivePopup( HWND hwnd )
2845 HWND retval = hwnd;
2847 SERVER_START_REQ( get_window_info )
2849 req->handle = hwnd;
2850 if (!wine_server_call_err( req )) retval = reply->last_active;
2852 SERVER_END_REQ;
2853 return retval;
2857 /*******************************************************************
2858 * WIN_ListChildren
2860 * Build an array of the children of a given window. The array must be
2861 * freed with HeapFree. Returns NULL when no windows are found.
2863 HWND *WIN_ListChildren( HWND hwnd )
2865 return list_window_children( hwnd, NULL, 0 );
2869 /*******************************************************************
2870 * EnumWindows (USER32.@)
2872 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2874 HWND *list;
2875 BOOL ret = TRUE;
2876 int i;
2878 USER_CheckNotLock();
2880 /* We have to build a list of all windows first, to avoid */
2881 /* unpleasant side-effects, for instance if the callback */
2882 /* function changes the Z-order of the windows. */
2884 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2886 /* Now call the callback function for every window */
2888 for (i = 0; list[i]; i++)
2890 /* Make sure that the window still exists */
2891 if (!IsWindow( list[i] )) continue;
2892 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2894 HeapFree( GetProcessHeap(), 0, list );
2895 return ret;
2899 /**********************************************************************
2900 * EnumThreadWindows (USER32.@)
2902 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2904 HWND *list;
2905 int i;
2907 USER_CheckNotLock();
2909 if (!(list = list_window_children( GetDesktopWindow(), NULL, id ))) return TRUE;
2911 /* Now call the callback function for every window */
2913 for (i = 0; list[i]; i++)
2914 if (!func( list[i], lParam )) break;
2915 HeapFree( GetProcessHeap(), 0, list );
2916 return TRUE;
2920 /**********************************************************************
2921 * WIN_EnumChildWindows
2923 * Helper function for EnumChildWindows().
2925 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2927 HWND *childList;
2928 BOOL ret = FALSE;
2930 for ( ; *list; list++)
2932 /* Make sure that the window still exists */
2933 if (!IsWindow( *list )) continue;
2934 /* Build children list first */
2935 childList = WIN_ListChildren( *list );
2937 ret = func( *list, lParam );
2939 if (childList)
2941 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2942 HeapFree( GetProcessHeap(), 0, childList );
2944 if (!ret) return FALSE;
2946 return TRUE;
2950 /**********************************************************************
2951 * EnumChildWindows (USER32.@)
2953 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2955 HWND *list;
2956 BOOL ret;
2958 USER_CheckNotLock();
2960 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2961 ret = WIN_EnumChildWindows( list, func, lParam );
2962 HeapFree( GetProcessHeap(), 0, list );
2963 return ret;
2967 /*******************************************************************
2968 * AnyPopup (USER.52)
2970 BOOL16 WINAPI AnyPopup16(void)
2972 return AnyPopup();
2976 /*******************************************************************
2977 * AnyPopup (USER32.@)
2979 BOOL WINAPI AnyPopup(void)
2981 int i;
2982 BOOL retvalue;
2983 HWND *list = WIN_ListChildren( GetDesktopWindow() );
2985 if (!list) return FALSE;
2986 for (i = 0; list[i]; i++)
2988 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
2990 retvalue = (list[i] != 0);
2991 HeapFree( GetProcessHeap(), 0, list );
2992 return retvalue;
2996 /*******************************************************************
2997 * FlashWindow (USER32.@)
2999 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3001 WND *wndPtr;
3003 TRACE("%p\n", hWnd);
3005 if (IsIconic( hWnd ))
3007 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3009 wndPtr = WIN_GetPtr(hWnd);
3010 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
3011 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3013 wndPtr->flags |= WIN_NCACTIVATED;
3015 else
3017 wndPtr->flags &= ~WIN_NCACTIVATED;
3019 WIN_ReleasePtr( wndPtr );
3020 return TRUE;
3022 else
3024 WPARAM wparam;
3026 wndPtr = WIN_GetPtr(hWnd);
3027 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
3028 hWnd = wndPtr->hwndSelf; /* make it a full handle */
3030 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3031 else wparam = (hWnd == GetForegroundWindow());
3033 WIN_ReleasePtr( wndPtr );
3034 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3035 return wparam;
3039 /*******************************************************************
3040 * FlashWindowEx (USER32.@)
3042 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
3044 FIXME("%p\n", pfwi);
3045 return TRUE;
3048 /*******************************************************************
3049 * GetWindowContextHelpId (USER32.@)
3051 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3053 DWORD retval;
3054 WND *wnd = WIN_GetPtr( hwnd );
3055 if (!wnd || wnd == WND_DESKTOP) return 0;
3056 if (wnd == WND_OTHER_PROCESS)
3058 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3059 return 0;
3061 retval = wnd->helpContext;
3062 WIN_ReleasePtr( wnd );
3063 return retval;
3067 /*******************************************************************
3068 * SetWindowContextHelpId (USER32.@)
3070 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3072 WND *wnd = WIN_GetPtr( hwnd );
3073 if (!wnd || wnd == WND_DESKTOP) return FALSE;
3074 if (wnd == WND_OTHER_PROCESS)
3076 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3077 return 0;
3079 wnd->helpContext = id;
3080 WIN_ReleasePtr( wnd );
3081 return TRUE;
3085 /*******************************************************************
3086 * DragDetect (USER32.@)
3088 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3090 MSG msg;
3091 RECT rect;
3092 WORD wDragWidth = GetSystemMetrics(SM_CXDRAG);
3093 WORD wDragHeight= GetSystemMetrics(SM_CYDRAG);
3095 rect.left = pt.x - wDragWidth;
3096 rect.right = pt.x + wDragWidth;
3098 rect.top = pt.y - wDragHeight;
3099 rect.bottom = pt.y + wDragHeight;
3101 SetCapture(hWnd);
3103 while(1)
3105 while (PeekMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ))
3107 if( msg.message == WM_LBUTTONUP )
3109 ReleaseCapture();
3110 return 0;
3112 if( msg.message == WM_MOUSEMOVE )
3114 POINT tmp;
3115 tmp.x = (short)LOWORD(msg.lParam);
3116 tmp.y = (short)HIWORD(msg.lParam);
3117 if( !PtInRect( &rect, tmp ))
3119 ReleaseCapture();
3120 return 1;
3124 WaitMessage();
3126 return 0;
3129 /******************************************************************************
3130 * GetWindowModuleFileNameA (USER32.@)
3132 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3134 FIXME("GetWindowModuleFileNameA(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3135 hwnd, lpszFileName, cchFileNameMax);
3136 return 0;
3139 /******************************************************************************
3140 * GetWindowModuleFileNameW (USER32.@)
3142 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR lpszFileName, UINT cchFileNameMax)
3144 FIXME("GetWindowModuleFileNameW(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3145 hwnd, lpszFileName, cchFileNameMax);
3146 return 0;
3149 /******************************************************************************
3150 * GetWindowInfo (USER32.@)
3152 * Note: tests show that Windows doesn't check cbSize of the structure.
3154 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3156 if (!pwi) return FALSE;
3157 if (!IsWindow(hwnd)) return FALSE;
3159 GetWindowRect(hwnd, &pwi->rcWindow);
3160 GetClientRect(hwnd, &pwi->rcClient);
3161 /* translate to screen coordinates */
3162 MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3164 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3165 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3166 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3168 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3169 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3171 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3172 pwi->wCreatorVersion = 0x0400;
3174 return TRUE;
3177 /******************************************************************************
3178 * SwitchDesktop (USER32.@)
3180 * NOTES: Sets the current input or interactive desktop.
3182 BOOL WINAPI SwitchDesktop( HDESK hDesktop)
3184 FIXME("SwitchDesktop(hwnd %p) stub!\n", hDesktop);
3185 return TRUE;
3188 /*****************************************************************************
3189 * SetLayeredWindowAttributes (USER32.@)
3191 BOOL WINAPI SetLayeredWindowAttributes( HWND hWnd, COLORREF rgbKey,
3192 BYTE bAlpha, DWORD dwFlags )
3194 FIXME("(%p,0x%.8x,%d,%d): stub!\n", hWnd, rgbKey, bAlpha, dwFlags);
3195 return TRUE;
3198 /*****************************************************************************
3199 * GetLayeredWindowAttributes (USER32.@)
3201 BOOL WINAPI GetLayeredWindowAttributes( HWND hWnd, COLORREF *prgbKey,
3202 BYTE *pbAlpha, DWORD *pdwFlags )
3204 FIXME("(%p,%p,%p,%p): stub!\n", hWnd, prgbKey, pbAlpha, pdwFlags);
3205 return FALSE;
3208 /*****************************************************************************
3209 * UpdateLayeredWindow (USER32.@)
3211 BOOL WINAPI UpdateLayeredWindow( HWND hwnd, HDC hdcDst, POINT *pptDst, SIZE *psize,
3212 HDC hdcSrc, POINT *pptSrc, COLORREF crKey, BLENDFUNCTION *pblend,
3213 DWORD dwFlags)
3215 static int once;
3216 if (!once)
3218 once = 1;
3219 FIXME("(%p,%p,%p,%p,%p,%p,0x%08x,%p,%d): stub!\n",
3220 hwnd, hdcDst, pptDst, psize, hdcSrc, pptSrc, crKey, pblend, dwFlags);
3222 return 0;
3225 /* 64bit versions */
3227 #ifdef GetWindowLongPtrW
3228 #undef GetWindowLongPtrW
3229 #endif
3231 #ifdef GetWindowLongPtrA
3232 #undef GetWindowLongPtrA
3233 #endif
3235 #ifdef SetWindowLongPtrW
3236 #undef SetWindowLongPtrW
3237 #endif
3239 #ifdef SetWindowLongPtrA
3240 #undef SetWindowLongPtrA
3241 #endif
3243 /*****************************************************************************
3244 * GetWindowLongPtrW (USER32.@)
3246 LONG_PTR WINAPI GetWindowLongPtrW( HWND hwnd, INT offset )
3248 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), TRUE );
3251 /*****************************************************************************
3252 * GetWindowLongPtrA (USER32.@)
3254 LONG_PTR WINAPI GetWindowLongPtrA( HWND hwnd, INT offset )
3256 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), FALSE );
3259 /*****************************************************************************
3260 * SetWindowLongPtrW (USER32.@)
3262 LONG_PTR WINAPI SetWindowLongPtrW( HWND hwnd, INT offset, LONG_PTR newval )
3264 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, TRUE );
3267 /*****************************************************************************
3268 * SetWindowLongPtrA (USER32.@)
3270 LONG_PTR WINAPI SetWindowLongPtrA( HWND hwnd, INT offset, LONG_PTR newval )
3272 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, FALSE );