qmgr: Implement IEnumBackgroundCopyFiles_Next.
[wine.git] / dlls / user32 / win.c
blob76351f462321490697e13d72a4e29c5b8deae2c6
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;
600 TRACE("%p\n", hwnd );
602 /* free child windows */
603 if ((list = WIN_ListChildren( hwnd )))
605 int i;
606 for (i = 0; list[i]; i++)
608 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
609 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
611 HeapFree( GetProcessHeap(), 0, list );
614 /* Unlink now so we won't bother with the children later on */
615 SERVER_START_REQ( set_parent )
617 req->handle = hwnd;
618 req->parent = 0;
619 wine_server_call( req );
621 SERVER_END_REQ;
624 * Send the WM_NCDESTROY to the window being destroyed.
626 SendMessageW( hwnd, WM_NCDESTROY, 0, 0 );
628 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
630 WINPOS_CheckInternalPos( hwnd );
632 /* free resources associated with the window */
634 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
635 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
636 menu = (HMENU)wndPtr->wIDmenu;
637 sys_menu = wndPtr->hSysMenu;
638 free_dce( wndPtr->dce, hwnd );
639 wndPtr->dce = NULL;
640 WIN_ReleasePtr( wndPtr );
642 if (menu) DestroyMenu( menu );
643 if (sys_menu) DestroyMenu( sys_menu );
645 USER_Driver->pDestroyWindow( hwnd );
647 free_window_handle( hwnd );
648 return 0;
651 /***********************************************************************
652 * WIN_DestroyThreadWindows
654 * Destroy all children of 'wnd' owned by the current thread.
656 void WIN_DestroyThreadWindows( HWND hwnd )
658 HWND *list;
659 int i;
661 if (!(list = WIN_ListChildren( hwnd ))) return;
662 for (i = 0; list[i]; i++)
664 if (WIN_IsCurrentThread( list[i] ))
665 DestroyWindow( list[i] );
666 else
667 WIN_DestroyThreadWindows( list[i] );
669 HeapFree( GetProcessHeap(), 0, list );
673 /***********************************************************************
674 * WIN_FixCoordinates
676 * Fix the coordinates - Helper for WIN_CreateWindowEx.
677 * returns default show mode in sw.
679 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
681 #define IS_DEFAULT(x) ((x) == CW_USEDEFAULT || (x) == CW_USEDEFAULT16)
682 POINT pos[2];
684 if (cs->dwExStyle & WS_EX_MDICHILD)
686 UINT id = 0;
688 MDI_CalcDefaultChildPos(cs->hwndParent, -1, pos, 0, &id);
689 if (!(cs->style & WS_POPUP)) cs->hMenu = ULongToHandle(id);
691 TRACE("MDI child id %04x\n", id);
694 if (cs->style & (WS_CHILD | WS_POPUP))
696 if (cs->dwExStyle & WS_EX_MDICHILD)
698 if (IS_DEFAULT(cs->x))
700 cs->x = pos[0].x;
701 cs->y = pos[0].y;
703 if (IS_DEFAULT(cs->cx) || !cs->cx) cs->cx = pos[1].x;
704 if (IS_DEFAULT(cs->cy) || !cs->cy) cs->cy = pos[1].y;
706 else
708 if (IS_DEFAULT(cs->x)) cs->x = cs->y = 0;
709 if (IS_DEFAULT(cs->cx)) cs->cx = cs->cy = 0;
712 else /* overlapped window */
714 HMONITOR monitor;
715 MONITORINFO mon_info;
716 STARTUPINFOW info;
718 if (!IS_DEFAULT(cs->x) && !IS_DEFAULT(cs->cx) && !IS_DEFAULT(cs->cy)) return;
720 monitor = MonitorFromWindow( cs->hwndParent, MONITOR_DEFAULTTOPRIMARY );
721 mon_info.cbSize = sizeof(mon_info);
722 GetMonitorInfoW( monitor, &mon_info );
723 GetStartupInfoW( &info );
725 if (IS_DEFAULT(cs->x))
727 if (!IS_DEFAULT(cs->y)) *sw = cs->y;
728 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : mon_info.rcWork.left;
729 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : mon_info.rcWork.top;
732 if (IS_DEFAULT(cs->cx))
734 if (info.dwFlags & STARTF_USESIZE)
736 cs->cx = info.dwXSize;
737 cs->cy = info.dwYSize;
739 else
741 cs->cx = (mon_info.rcWork.right - mon_info.rcWork.left) * 3 / 4 - cs->x;
742 cs->cy = (mon_info.rcWork.bottom - mon_info.rcWork.top) * 3 / 4 - cs->y;
745 /* neither x nor cx are default. Check the y values .
746 * In the trace we see Outlook and Outlook Express using
747 * cy set to CW_USEDEFAULT when opening the address book.
749 else if (IS_DEFAULT(cs->cy))
751 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
752 cs->cy = (mon_info.rcWork.bottom - mon_info.rcWork.top) * 3 / 4 - cs->y;
755 #undef IS_DEFAULT
758 /***********************************************************************
759 * dump_window_styles
761 static void dump_window_styles( DWORD style, DWORD exstyle )
763 TRACE( "style:" );
764 if(style & WS_POPUP) TRACE(" WS_POPUP");
765 if(style & WS_CHILD) TRACE(" WS_CHILD");
766 if(style & WS_MINIMIZE) TRACE(" WS_MINIMIZE");
767 if(style & WS_VISIBLE) TRACE(" WS_VISIBLE");
768 if(style & WS_DISABLED) TRACE(" WS_DISABLED");
769 if(style & WS_CLIPSIBLINGS) TRACE(" WS_CLIPSIBLINGS");
770 if(style & WS_CLIPCHILDREN) TRACE(" WS_CLIPCHILDREN");
771 if(style & WS_MAXIMIZE) TRACE(" WS_MAXIMIZE");
772 if((style & WS_CAPTION) == WS_CAPTION) TRACE(" WS_CAPTION");
773 else
775 if(style & WS_BORDER) TRACE(" WS_BORDER");
776 if(style & WS_DLGFRAME) TRACE(" WS_DLGFRAME");
778 if(style & WS_VSCROLL) TRACE(" WS_VSCROLL");
779 if(style & WS_HSCROLL) TRACE(" WS_HSCROLL");
780 if(style & WS_SYSMENU) TRACE(" WS_SYSMENU");
781 if(style & WS_THICKFRAME) TRACE(" WS_THICKFRAME");
782 if (style & WS_CHILD)
784 if(style & WS_GROUP) TRACE(" WS_GROUP");
785 if(style & WS_TABSTOP) TRACE(" WS_TABSTOP");
787 else
789 if(style & WS_MINIMIZEBOX) TRACE(" WS_MINIMIZEBOX");
790 if(style & WS_MAXIMIZEBOX) TRACE(" WS_MAXIMIZEBOX");
793 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
794 #define DUMPED_STYLES \
795 (WS_POPUP | \
796 WS_CHILD | \
797 WS_MINIMIZE | \
798 WS_VISIBLE | \
799 WS_DISABLED | \
800 WS_CLIPSIBLINGS | \
801 WS_CLIPCHILDREN | \
802 WS_MAXIMIZE | \
803 WS_BORDER | \
804 WS_DLGFRAME | \
805 WS_VSCROLL | \
806 WS_HSCROLL | \
807 WS_SYSMENU | \
808 WS_THICKFRAME | \
809 WS_GROUP | \
810 WS_TABSTOP | \
811 WS_MINIMIZEBOX | \
812 WS_MAXIMIZEBOX)
814 if(style & ~DUMPED_STYLES) TRACE(" %08lx", style & ~DUMPED_STYLES);
815 TRACE("\n");
816 #undef DUMPED_STYLES
818 TRACE( "exstyle:" );
819 if(exstyle & WS_EX_DLGMODALFRAME) TRACE(" WS_EX_DLGMODALFRAME");
820 if(exstyle & WS_EX_DRAGDETECT) TRACE(" WS_EX_DRAGDETECT");
821 if(exstyle & WS_EX_NOPARENTNOTIFY) TRACE(" WS_EX_NOPARENTNOTIFY");
822 if(exstyle & WS_EX_TOPMOST) TRACE(" WS_EX_TOPMOST");
823 if(exstyle & WS_EX_ACCEPTFILES) TRACE(" WS_EX_ACCEPTFILES");
824 if(exstyle & WS_EX_TRANSPARENT) TRACE(" WS_EX_TRANSPARENT");
825 if(exstyle & WS_EX_MDICHILD) TRACE(" WS_EX_MDICHILD");
826 if(exstyle & WS_EX_TOOLWINDOW) TRACE(" WS_EX_TOOLWINDOW");
827 if(exstyle & WS_EX_WINDOWEDGE) TRACE(" WS_EX_WINDOWEDGE");
828 if(exstyle & WS_EX_CLIENTEDGE) TRACE(" WS_EX_CLIENTEDGE");
829 if(exstyle & WS_EX_CONTEXTHELP) TRACE(" WS_EX_CONTEXTHELP");
830 if(exstyle & WS_EX_RIGHT) TRACE(" WS_EX_RIGHT");
831 if(exstyle & WS_EX_RTLREADING) TRACE(" WS_EX_RTLREADING");
832 if(exstyle & WS_EX_LEFTSCROLLBAR) TRACE(" WS_EX_LEFTSCROLLBAR");
833 if(exstyle & WS_EX_CONTROLPARENT) TRACE(" WS_EX_CONTROLPARENT");
834 if(exstyle & WS_EX_STATICEDGE) TRACE(" WS_EX_STATICEDGE");
835 if(exstyle & WS_EX_APPWINDOW) TRACE(" WS_EX_APPWINDOW");
836 if(exstyle & WS_EX_LAYERED) TRACE(" WS_EX_LAYERED");
838 #define DUMPED_EX_STYLES \
839 (WS_EX_DLGMODALFRAME | \
840 WS_EX_DRAGDETECT | \
841 WS_EX_NOPARENTNOTIFY | \
842 WS_EX_TOPMOST | \
843 WS_EX_ACCEPTFILES | \
844 WS_EX_TRANSPARENT | \
845 WS_EX_MDICHILD | \
846 WS_EX_TOOLWINDOW | \
847 WS_EX_WINDOWEDGE | \
848 WS_EX_CLIENTEDGE | \
849 WS_EX_CONTEXTHELP | \
850 WS_EX_RIGHT | \
851 WS_EX_RTLREADING | \
852 WS_EX_LEFTSCROLLBAR | \
853 WS_EX_CONTROLPARENT | \
854 WS_EX_STATICEDGE | \
855 WS_EX_APPWINDOW | \
856 WS_EX_LAYERED)
858 if(exstyle & ~DUMPED_EX_STYLES) TRACE(" %08lx", exstyle & ~DUMPED_EX_STYLES);
859 TRACE("\n");
860 #undef DUMPED_EX_STYLES
864 /***********************************************************************
865 * WIN_CreateWindowEx
867 * Implementation of CreateWindowEx().
869 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, LPCWSTR className, UINT flags )
871 INT cx, cy, style, sw = SW_SHOW;
872 LRESULT result;
873 RECT rect;
874 WND *wndPtr;
875 HWND hwnd, parent, owner, top_child = 0;
876 BOOL unicode = (flags & WIN_ISUNICODE) != 0;
877 MDICREATESTRUCTA mdi_cs;
878 CBT_CREATEWNDA cbtc;
879 CREATESTRUCTA cbcs;
881 TRACE("%s %s ex=%08x style=%08x %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
882 unicode ? debugstr_w((LPCWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
883 debugstr_w(className),
884 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
885 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
886 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
888 /* Fix the styles for MDI children */
889 if (cs->dwExStyle & WS_EX_MDICHILD)
891 UINT flags = 0;
893 wndPtr = WIN_GetPtr(cs->hwndParent);
894 if (wndPtr && wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
896 flags = wndPtr->flags;
897 WIN_ReleasePtr(wndPtr);
900 if (!(flags & WIN_ISMDICLIENT))
902 WARN("WS_EX_MDICHILD, but parent %p is not MDIClient\n", cs->hwndParent);
903 return 0;
906 /* cs->lpCreateParams of WM_[NC]CREATE is different for MDI children.
907 * MDICREATESTRUCT members have the originally passed values.
909 * Note: we rely on the fact that MDICREATESTRUCTA and MDICREATESTRUCTW
910 * have the same layout.
912 mdi_cs.szClass = cs->lpszClass;
913 mdi_cs.szTitle = cs->lpszName;
914 mdi_cs.hOwner = cs->hInstance;
915 mdi_cs.x = cs->x;
916 mdi_cs.y = cs->y;
917 mdi_cs.cx = cs->cx;
918 mdi_cs.cy = cs->cy;
919 mdi_cs.style = cs->style;
920 mdi_cs.lParam = (LPARAM)cs->lpCreateParams;
922 cs->lpCreateParams = (LPVOID)&mdi_cs;
924 if (GetWindowLongW(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
926 if (cs->style & WS_POPUP)
928 TRACE("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n");
929 return 0;
931 cs->style |= WS_CHILD | WS_CLIPSIBLINGS;
933 else
935 cs->style &= ~WS_POPUP;
936 cs->style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
937 WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
940 top_child = GetWindow(cs->hwndParent, GW_CHILD);
942 if (top_child)
944 /* Restore current maximized child */
945 if((cs->style & WS_VISIBLE) && IsZoomed(top_child))
947 TRACE("Restoring current maximized child %p\n", top_child);
948 SendMessageW( top_child, WM_SETREDRAW, FALSE, 0 );
949 ShowWindow( top_child, SW_SHOWNORMAL );
950 SendMessageW( top_child, WM_SETREDRAW, TRUE, 0 );
955 /* Find the parent window */
957 parent = cs->hwndParent;
958 owner = 0;
960 if (cs->hwndParent == HWND_MESSAGE)
962 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
963 * message window (style: WS_POPUP|WS_DISABLED)
965 FIXME("Parent is HWND_MESSAGE\n");
966 parent = GetDesktopWindow();
968 else if (cs->hwndParent)
970 if ((cs->style & (WS_CHILD|WS_POPUP)) != WS_CHILD)
972 parent = GetDesktopWindow();
973 owner = cs->hwndParent;
976 else
978 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
980 WARN("No parent for child window\n" );
981 SetLastError(ERROR_TLW_WITH_WSCHILD);
982 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
984 if (className != (LPCWSTR)DESKTOP_CLASS_ATOM) /* are we creating the desktop itself? */
985 parent = GetDesktopWindow();
988 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
990 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
991 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
992 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
993 cs->dwExStyle |= WS_EX_WINDOWEDGE;
994 else
995 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
997 /* Create the window structure */
999 if (!(wndPtr = create_window_handle( parent, owner, className, cs->hInstance, unicode )))
1000 return 0;
1001 hwnd = wndPtr->hwndSelf;
1003 /* Fill the window structure */
1005 wndPtr->tid = GetCurrentThreadId();
1006 wndPtr->hInstance = cs->hInstance;
1007 wndPtr->text = NULL;
1008 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1009 wndPtr->dwExStyle = cs->dwExStyle;
1010 wndPtr->wIDmenu = 0;
1011 wndPtr->helpContext = 0;
1012 wndPtr->pVScroll = NULL;
1013 wndPtr->pHScroll = NULL;
1014 wndPtr->userdata = 0;
1015 wndPtr->hIcon = 0;
1016 wndPtr->hIconSmall = 0;
1017 wndPtr->hSysMenu = 0;
1018 wndPtr->flags |= (flags & WIN_ISWIN32);
1020 if (wndPtr->dwStyle & WS_SYSMENU) SetSystemMenu( hwnd, 0 );
1023 * Correct the window styles.
1025 * It affects only the style loaded into the WIN structure.
1028 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
1030 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1031 if (!(wndPtr->dwStyle & WS_POPUP))
1032 wndPtr->dwStyle |= WS_CAPTION;
1036 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1037 * why does the user get to set it?
1040 if ((wndPtr->dwExStyle & WS_EX_DLGMODALFRAME) ||
1041 (wndPtr->dwStyle & (WS_DLGFRAME | WS_THICKFRAME)))
1042 wndPtr->dwExStyle |= WS_EX_WINDOWEDGE;
1043 else
1044 wndPtr->dwExStyle &= ~WS_EX_WINDOWEDGE;
1046 if (!(wndPtr->dwStyle & (WS_CHILD | WS_POPUP)))
1047 wndPtr->flags |= WIN_NEED_SIZE;
1049 SERVER_START_REQ( set_window_info )
1051 req->handle = hwnd;
1052 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE | SET_WIN_UNICODE;
1053 req->style = wndPtr->dwStyle;
1054 req->ex_style = wndPtr->dwExStyle;
1055 req->instance = (void *)wndPtr->hInstance;
1056 req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
1057 req->extra_offset = -1;
1058 wine_server_call( req );
1060 SERVER_END_REQ;
1062 /* Set the window menu */
1064 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
1066 if (cs->hMenu)
1068 if (!MENU_SetMenu(hwnd, cs->hMenu))
1070 WIN_ReleasePtr( wndPtr );
1071 free_window_handle( hwnd );
1072 return 0;
1075 else
1077 LPCSTR menuName = (LPCSTR)GetClassLongPtrA( hwnd, GCLP_MENUNAME );
1078 if (menuName)
1080 if (!cs->hInstance || HIWORD(cs->hInstance))
1081 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1082 else
1083 cs->hMenu = HMENU_32(LoadMenu16(HINSTANCE_16(cs->hInstance),menuName));
1085 if (cs->hMenu) MENU_SetMenu( hwnd, cs->hMenu );
1089 else SetWindowLongPtrW( hwnd, GWLP_ID, (ULONG_PTR)cs->hMenu );
1091 /* call the WH_CBT hook */
1093 /* the window style passed to the hook must be the real window style,
1094 * rather than just the window style that the caller to CreateWindowEx
1095 * passed in, so we have to copy the original CREATESTRUCT and get the
1096 * the real style. */
1097 cbcs = *cs;
1098 cbcs.style = wndPtr->dwStyle;
1099 cbtc.lpcs = &cbcs;
1100 cbtc.hwndInsertAfter = HWND_TOP;
1101 WIN_ReleasePtr( wndPtr );
1102 if (HOOK_CallHooks( WH_CBT, HCBT_CREATEWND, (WPARAM)hwnd, (LPARAM)&cbtc, unicode )) goto failed;
1104 /* send the WM_GETMINMAXINFO message and fix the size if needed */
1106 cx = cs->cx;
1107 cy = cs->cy;
1108 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
1110 POINT maxSize, maxPos, minTrack, maxTrack;
1111 WINPOS_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack);
1112 if (maxTrack.x < cx) cx = maxTrack.x;
1113 if (maxTrack.y < cy) cy = maxTrack.y;
1116 if (cx < 0) cx = 0;
1117 if (cy < 0) cy = 0;
1118 SetRect( &rect, cs->x, cs->y, cs->x + cx, cs->y + cy );
1119 if (!set_window_pos( hwnd, 0, SWP_NOZORDER | SWP_NOACTIVATE, &rect, &rect, NULL )) goto failed;
1121 /* send WM_NCCREATE */
1123 TRACE( "hwnd %p cs %d,%d %dx%d\n", hwnd, cs->x, cs->y, cx, cy );
1124 if (unicode)
1125 result = SendMessageW( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
1126 else
1127 result = SendMessageA( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
1128 if (!result)
1130 WARN( "%p: aborted by WM_NCCREATE\n", hwnd );
1131 goto failed;
1134 /* send WM_NCCALCSIZE */
1136 if ((wndPtr = WIN_GetPtr(hwnd)))
1138 /* yes, even if the CBT hook was called with HWND_TOP */
1139 HWND insert_after = (wndPtr->dwStyle & WS_CHILD) ? HWND_BOTTOM : HWND_TOP;
1140 RECT window_rect = wndPtr->rectWindow;
1141 RECT client_rect = window_rect;
1142 WIN_ReleasePtr( wndPtr );
1143 SendMessageW( hwnd, WM_NCCALCSIZE, FALSE, (LPARAM)&client_rect );
1144 set_window_pos( hwnd, insert_after, SWP_NOACTIVATE, &window_rect, &client_rect, NULL );
1146 else return 0;
1148 /* send WM_CREATE */
1150 if (unicode)
1151 result = SendMessageW( hwnd, WM_CREATE, 0, (LPARAM)cs );
1152 else
1153 result = SendMessageA( hwnd, WM_CREATE, 0, (LPARAM)cs );
1154 if (result == -1) goto failed;
1156 /* call the driver */
1158 if (!USER_Driver->pCreateWindow( hwnd )) goto failed;
1160 NotifyWinEvent(EVENT_OBJECT_CREATE, hwnd, OBJID_WINDOW, 0);
1162 /* send the size messages */
1164 if (!(wndPtr = WIN_GetPtr(hwnd))) return 0;
1165 if (!(wndPtr->flags & WIN_NEED_SIZE))
1167 rect = wndPtr->rectClient;
1168 WIN_ReleasePtr( wndPtr );
1169 SendMessageW( hwnd, WM_SIZE, SIZE_RESTORED,
1170 MAKELONG(rect.right-rect.left, rect.bottom-rect.top));
1171 SendMessageW( hwnd, WM_MOVE, 0, MAKELONG( rect.left, rect.top ) );
1173 else WIN_ReleasePtr( wndPtr );
1175 /* Show the window, maximizing or minimizing if needed */
1177 style = WIN_SetStyle( hwnd, 0, WS_MAXIMIZE | WS_MINIMIZE );
1178 if (style & (WS_MINIMIZE | WS_MAXIMIZE))
1180 RECT newPos;
1181 UINT swFlag = (style & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
1183 swFlag = WINPOS_MinMaximize( hwnd, swFlag, &newPos );
1184 swFlag |= SWP_FRAMECHANGED; /* Frame always gets changed */
1185 if (!(style & WS_VISIBLE) || (style & WS_CHILD) || GetActiveWindow()) swFlag |= SWP_NOACTIVATE;
1186 SetWindowPos( hwnd, 0, newPos.left, newPos.top, newPos.right, newPos.bottom, swFlag );
1189 /* Notify the parent window only */
1191 send_parent_notify( hwnd, WM_CREATE );
1192 if (!IsWindow( hwnd )) return 0;
1194 if (cs->style & WS_VISIBLE)
1196 if (cs->style & WS_MAXIMIZE)
1197 sw = SW_SHOW;
1198 else if (cs->style & WS_MINIMIZE)
1199 sw = SW_SHOWMINIMIZED;
1201 ShowWindow( hwnd, sw );
1202 if (cs->dwExStyle & WS_EX_MDICHILD)
1204 SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
1205 /* ShowWindow won't activate child windows */
1206 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE );
1210 /* Call WH_SHELL hook */
1212 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1213 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1215 TRACE("created window %p\n", hwnd);
1216 return hwnd;
1218 failed:
1219 WIN_DestroyWindow( hwnd );
1220 return 0;
1224 /***********************************************************************
1225 * CreateWindow (USER.41)
1227 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1228 DWORD style, INT16 x, INT16 y, INT16 width,
1229 INT16 height, HWND16 parent, HMENU16 menu,
1230 HINSTANCE16 instance, LPVOID data )
1232 return CreateWindowEx16( 0, className, windowName, style,
1233 x, y, width, height, parent, menu, instance, data );
1237 /***********************************************************************
1238 * CreateWindowEx (USER.452)
1240 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1241 LPCSTR windowName, DWORD style, INT16 x,
1242 INT16 y, INT16 width, INT16 height,
1243 HWND16 parent, HMENU16 menu,
1244 HINSTANCE16 instance, LPVOID data )
1246 CREATESTRUCTA cs;
1247 char buffer[256];
1249 /* Fix the coordinates */
1251 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1252 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1253 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1254 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1256 /* Create the window */
1258 cs.lpCreateParams = data;
1259 cs.hInstance = HINSTANCE_32(instance);
1260 cs.hMenu = HMENU_32(menu);
1261 cs.hwndParent = WIN_Handle32( parent );
1262 cs.style = style;
1263 cs.lpszName = windowName;
1264 cs.lpszClass = className;
1265 cs.dwExStyle = exStyle;
1267 if (!IS_INTRESOURCE(className))
1269 WCHAR bufferW[256];
1271 if (!MultiByteToWideChar( CP_ACP, 0, className, -1, bufferW, sizeof(bufferW)/sizeof(WCHAR) ))
1272 return 0;
1273 return HWND_16( WIN_CreateWindowEx( &cs, bufferW, 0 ));
1275 else
1277 if (!GlobalGetAtomNameA( LOWORD(className), buffer, sizeof(buffer) ))
1279 ERR( "bad atom %x\n", LOWORD(className));
1280 return 0;
1282 cs.lpszClass = buffer;
1283 return HWND_16( WIN_CreateWindowEx( &cs, (LPCWSTR)className, 0 ));
1288 /***********************************************************************
1289 * CreateWindowExA (USER32.@)
1291 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1292 LPCSTR windowName, DWORD style, INT x,
1293 INT y, INT width, INT height,
1294 HWND parent, HMENU menu,
1295 HINSTANCE instance, LPVOID data )
1297 CREATESTRUCTA cs;
1299 cs.lpCreateParams = data;
1300 cs.hInstance = instance;
1301 cs.hMenu = menu;
1302 cs.hwndParent = parent;
1303 cs.x = x;
1304 cs.y = y;
1305 cs.cx = width;
1306 cs.cy = height;
1307 cs.style = style;
1308 cs.lpszName = windowName;
1309 cs.lpszClass = className;
1310 cs.dwExStyle = exStyle;
1312 if (!IS_INTRESOURCE(className))
1314 WCHAR bufferW[256];
1315 if (!MultiByteToWideChar( CP_ACP, 0, className, -1, bufferW, sizeof(bufferW)/sizeof(WCHAR) ))
1316 return 0;
1317 return WIN_CreateWindowEx( &cs, bufferW, WIN_ISWIN32 );
1319 return WIN_CreateWindowEx( &cs, (LPCWSTR)className, WIN_ISWIN32 );
1323 /***********************************************************************
1324 * CreateWindowExW (USER32.@)
1326 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1327 LPCWSTR windowName, DWORD style, INT x,
1328 INT y, INT width, INT height,
1329 HWND parent, HMENU menu,
1330 HINSTANCE instance, LPVOID data )
1332 CREATESTRUCTW cs;
1334 cs.lpCreateParams = data;
1335 cs.hInstance = instance;
1336 cs.hMenu = menu;
1337 cs.hwndParent = parent;
1338 cs.x = x;
1339 cs.y = y;
1340 cs.cx = width;
1341 cs.cy = height;
1342 cs.style = style;
1343 cs.lpszName = windowName;
1344 cs.lpszClass = className;
1345 cs.dwExStyle = exStyle;
1347 /* Note: we rely on the fact that CREATESTRUCTA and */
1348 /* CREATESTRUCTW have the same layout. */
1349 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, className, WIN_ISWIN32 | WIN_ISUNICODE );
1353 /***********************************************************************
1354 * WIN_SendDestroyMsg
1356 static void WIN_SendDestroyMsg( HWND hwnd )
1358 GUITHREADINFO info;
1360 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1362 if (hwnd == info.hwndCaret) DestroyCaret();
1363 if (hwnd == info.hwndActive) WINPOS_ActivateOtherWindow( hwnd );
1367 * Send the WM_DESTROY to the window.
1369 SendMessageW( hwnd, WM_DESTROY, 0, 0);
1372 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1373 * make sure that the window still exists when we come back.
1375 if (IsWindow(hwnd))
1377 HWND* pWndArray;
1378 int i;
1380 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1382 for (i = 0; pWndArray[i]; i++)
1384 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1386 HeapFree( GetProcessHeap(), 0, pWndArray );
1388 else
1389 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1393 /***********************************************************************
1394 * DestroyWindow (USER32.@)
1396 BOOL WINAPI DestroyWindow( HWND hwnd )
1398 BOOL is_child;
1400 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1402 SetLastError( ERROR_ACCESS_DENIED );
1403 return FALSE;
1406 TRACE("(%p)\n", hwnd);
1408 /* Call hooks */
1410 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1412 if (MENU_IsMenuActive() == hwnd)
1413 EndMenu();
1415 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1417 if (is_child)
1419 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1420 send_parent_notify( hwnd, WM_DESTROY );
1422 else if (!GetWindow( hwnd, GW_OWNER ))
1424 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1425 /* FIXME: clean up palette - see "Internals" p.352 */
1428 if (!IsWindow(hwnd)) return TRUE;
1430 /* Hide the window */
1431 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)
1433 /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
1434 if (is_child)
1435 ShowWindow( hwnd, SW_HIDE );
1436 else
1437 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1438 SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW );
1441 if (!IsWindow(hwnd)) return TRUE;
1443 /* Recursively destroy owned windows */
1445 if (!is_child)
1447 for (;;)
1449 int i, got_one = 0;
1450 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1451 if (list)
1453 for (i = 0; list[i]; i++)
1455 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1456 if (WIN_IsCurrentThread( list[i] ))
1458 DestroyWindow( list[i] );
1459 got_one = 1;
1460 continue;
1462 WIN_SetOwner( list[i], 0 );
1464 HeapFree( GetProcessHeap(), 0, list );
1466 if (!got_one) break;
1470 /* Send destroy messages */
1472 WIN_SendDestroyMsg( hwnd );
1473 if (!IsWindow( hwnd )) return TRUE;
1475 if (GetClipboardOwner() == hwnd)
1476 CLIPBOARD_ReleaseOwner();
1478 /* Destroy the window storage */
1480 WIN_DestroyWindow( hwnd );
1481 return TRUE;
1485 /***********************************************************************
1486 * CloseWindow (USER32.@)
1488 BOOL WINAPI CloseWindow( HWND hwnd )
1490 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1491 ShowWindow( hwnd, SW_MINIMIZE );
1492 return TRUE;
1496 /***********************************************************************
1497 * OpenIcon (USER32.@)
1499 BOOL WINAPI OpenIcon( HWND hwnd )
1501 if (!IsIconic( hwnd )) return FALSE;
1502 ShowWindow( hwnd, SW_SHOWNORMAL );
1503 return TRUE;
1507 /***********************************************************************
1508 * FindWindowExW (USER32.@)
1510 HWND WINAPI FindWindowExW( HWND parent, HWND child, LPCWSTR className, LPCWSTR title )
1512 HWND *list = NULL;
1513 HWND retvalue = 0;
1514 int i = 0, len = 0;
1515 WCHAR *buffer = NULL;
1517 if (!parent) parent = GetDesktopWindow();
1518 if (title)
1520 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1521 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1524 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1526 if (child)
1528 child = WIN_GetFullHandle( child );
1529 while (list[i] && list[i] != child) i++;
1530 if (!list[i]) goto done;
1531 i++; /* start from next window */
1534 if (title)
1536 while (list[i])
1538 if (GetWindowTextW( list[i], buffer, len + 1 ) && !strcmpiW( buffer, title )) break;
1539 i++;
1542 retvalue = list[i];
1544 done:
1545 HeapFree( GetProcessHeap(), 0, list );
1546 HeapFree( GetProcessHeap(), 0, buffer );
1547 return retvalue;
1552 /***********************************************************************
1553 * FindWindowA (USER32.@)
1555 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1557 HWND ret = FindWindowExA( 0, 0, className, title );
1558 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1559 return ret;
1563 /***********************************************************************
1564 * FindWindowExA (USER32.@)
1566 HWND WINAPI FindWindowExA( HWND parent, HWND child, LPCSTR className, LPCSTR title )
1568 LPWSTR titleW = NULL;
1569 HWND hwnd = 0;
1571 if (title)
1573 DWORD len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1574 if (!(titleW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1575 MultiByteToWideChar( CP_ACP, 0, title, -1, titleW, len );
1578 if (!IS_INTRESOURCE(className))
1580 WCHAR classW[256];
1581 if (MultiByteToWideChar( CP_ACP, 0, className, -1, classW, sizeof(classW)/sizeof(WCHAR) ))
1582 hwnd = FindWindowExW( parent, child, classW, titleW );
1584 else
1586 hwnd = FindWindowExW( parent, child, (LPCWSTR)className, titleW );
1589 HeapFree( GetProcessHeap(), 0, titleW );
1590 return hwnd;
1594 /***********************************************************************
1595 * FindWindowW (USER32.@)
1597 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1599 return FindWindowExW( 0, 0, className, title );
1603 /**********************************************************************
1604 * GetDesktopWindow (USER32.@)
1606 HWND WINAPI GetDesktopWindow(void)
1608 struct user_thread_info *thread_info = get_user_thread_info();
1610 if (thread_info->desktop) return thread_info->desktop;
1612 SERVER_START_REQ( get_desktop_window )
1614 req->force = 0;
1615 if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1617 SERVER_END_REQ;
1619 if (!thread_info->desktop)
1621 static const WCHAR command_line[] = {'\\','e','x','p','l','o','r','e','r','.','e','x','e',' ','/','d','e','s','k','t','o','p',0};
1622 STARTUPINFOW si;
1623 PROCESS_INFORMATION pi;
1624 WCHAR cmdline[MAX_PATH + sizeof(command_line)/sizeof(WCHAR)];
1626 memset( &si, 0, sizeof(si) );
1627 si.cb = sizeof(si);
1628 si.dwFlags = STARTF_USESTDHANDLES;
1629 si.hStdInput = 0;
1630 si.hStdOutput = 0;
1631 si.hStdError = GetStdHandle( STD_ERROR_HANDLE );
1633 GetSystemDirectoryW( cmdline, MAX_PATH );
1634 lstrcatW( cmdline, command_line );
1635 if (CreateProcessW( NULL, cmdline, NULL, NULL, FALSE, DETACHED_PROCESS,
1636 NULL, NULL, &si, &pi ))
1638 TRACE( "started explorer pid %04x tid %04x\n", pi.dwProcessId, pi.dwThreadId );
1639 WaitForInputIdle( pi.hProcess, 10000 );
1640 CloseHandle( pi.hThread );
1641 CloseHandle( pi.hProcess );
1644 else WARN( "failed to start explorer, err %d\n", GetLastError() );
1646 SERVER_START_REQ( get_desktop_window )
1648 req->force = 1;
1649 if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1651 SERVER_END_REQ;
1654 if (!thread_info->desktop || !USER_Driver->pCreateDesktopWindow( thread_info->desktop ))
1655 ERR( "failed to create desktop window\n" );
1657 return thread_info->desktop;
1661 /*******************************************************************
1662 * EnableWindow (USER32.@)
1664 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1666 BOOL retvalue;
1667 HWND full_handle;
1669 if (is_broadcast(hwnd))
1671 SetLastError( ERROR_INVALID_PARAMETER );
1672 return FALSE;
1675 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1676 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1678 hwnd = full_handle;
1680 TRACE("( %p, %d )\n", hwnd, enable);
1682 retvalue = !IsWindowEnabled( hwnd );
1684 if (enable && retvalue)
1686 WIN_SetStyle( hwnd, 0, WS_DISABLED );
1687 SendMessageW( hwnd, WM_ENABLE, TRUE, 0 );
1689 else if (!enable && !retvalue)
1691 HWND capture_wnd;
1693 SendMessageW( hwnd, WM_CANCELMODE, 0, 0);
1695 WIN_SetStyle( hwnd, WS_DISABLED, 0 );
1697 if (hwnd == GetFocus())
1698 SetFocus( 0 ); /* A disabled window can't have the focus */
1700 capture_wnd = GetCapture();
1701 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1702 ReleaseCapture(); /* A disabled window can't capture the mouse */
1704 SendMessageW( hwnd, WM_ENABLE, FALSE, 0 );
1706 return retvalue;
1710 /***********************************************************************
1711 * IsWindowEnabled (USER32.@)
1713 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1715 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1719 /***********************************************************************
1720 * IsWindowUnicode (USER32.@)
1722 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1724 WND * wndPtr;
1725 BOOL retvalue = FALSE;
1727 if (!(wndPtr = WIN_GetPtr(hwnd))) return FALSE;
1729 if (wndPtr == WND_DESKTOP) return TRUE;
1731 if (wndPtr != WND_OTHER_PROCESS)
1733 retvalue = (wndPtr->flags & WIN_ISUNICODE) != 0;
1734 WIN_ReleasePtr( wndPtr );
1736 else
1738 SERVER_START_REQ( get_window_info )
1740 req->handle = hwnd;
1741 if (!wine_server_call_err( req )) retvalue = reply->is_unicode;
1743 SERVER_END_REQ;
1745 return retvalue;
1749 /**********************************************************************
1750 * WIN_GetWindowLong
1752 * Helper function for GetWindowLong().
1754 static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, UINT size, BOOL unicode )
1756 LONG_PTR retvalue = 0;
1757 WND *wndPtr;
1759 if (offset == GWLP_HWNDPARENT)
1761 HWND parent = GetAncestor( hwnd, GA_PARENT );
1762 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1763 return (ULONG_PTR)parent;
1766 if (!(wndPtr = WIN_GetPtr( hwnd )))
1768 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1769 return 0;
1772 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1774 if (offset == GWLP_WNDPROC)
1776 SetLastError( ERROR_ACCESS_DENIED );
1777 return 0;
1779 SERVER_START_REQ( set_window_info )
1781 req->handle = hwnd;
1782 req->flags = 0; /* don't set anything, just retrieve */
1783 req->extra_offset = (offset >= 0) ? offset : -1;
1784 req->extra_size = (offset >= 0) ? size : 0;
1785 if (!wine_server_call_err( req ))
1787 switch(offset)
1789 case GWL_STYLE: retvalue = reply->old_style; break;
1790 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1791 case GWLP_ID: retvalue = reply->old_id; break;
1792 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1793 case GWLP_USERDATA: retvalue = reply->old_user_data; break;
1794 default:
1795 if (offset >= 0) retvalue = get_win_data( &reply->old_extra_value, size );
1796 else SetLastError( ERROR_INVALID_INDEX );
1797 break;
1801 SERVER_END_REQ;
1802 return retvalue;
1805 /* now we have a valid wndPtr */
1807 if (offset >= 0)
1809 if (offset > (int)(wndPtr->cbWndExtra - size))
1811 WARN("Invalid offset %d\n", offset );
1812 WIN_ReleasePtr( wndPtr );
1813 SetLastError( ERROR_INVALID_INDEX );
1814 return 0;
1816 retvalue = get_win_data( (char *)wndPtr->wExtra + offset, size );
1818 /* Special case for dialog window procedure */
1819 if ((offset == DWLP_DLGPROC) && (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG))
1820 retvalue = (LONG_PTR)WINPROC_GetProc( (WNDPROC)retvalue, unicode );
1821 WIN_ReleasePtr( wndPtr );
1822 return retvalue;
1825 switch(offset)
1827 case GWLP_USERDATA: retvalue = wndPtr->userdata; break;
1828 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1829 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1830 case GWLP_ID: retvalue = wndPtr->wIDmenu; break;
1831 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wndPtr->hInstance; break;
1832 case GWLP_WNDPROC:
1833 /* This looks like a hack only for the edit control (see tests). This makes these controls
1834 * more tolerant to A/W mismatches. The lack of W->A->W conversion for such a mismatch suggests
1835 * that the hack is in GetWindowLongPtr[AW], not in winprocs.
1837 if (wndPtr->winproc == EDIT_winproc_handle && (!unicode != !(wndPtr->flags & WIN_ISUNICODE)))
1838 retvalue = (ULONG_PTR)wndPtr->winproc;
1839 else
1840 retvalue = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, unicode );
1841 break;
1842 default:
1843 WARN("Unknown offset %d\n", offset );
1844 SetLastError( ERROR_INVALID_INDEX );
1845 break;
1847 WIN_ReleasePtr(wndPtr);
1848 return retvalue;
1852 /**********************************************************************
1853 * WIN_SetWindowLong
1855 * Helper function for SetWindowLong().
1857 * 0 is the failure code. However, in the case of failure SetLastError
1858 * must be set to distinguish between a 0 return value and a failure.
1860 LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, UINT size, LONG_PTR newval, BOOL unicode )
1862 STYLESTRUCT style;
1863 BOOL ok;
1864 LONG_PTR retval = 0;
1865 WND *wndPtr;
1867 TRACE( "%p %d %lx %c\n", hwnd, offset, newval, unicode ? 'W' : 'A' );
1869 if (is_broadcast(hwnd))
1871 SetLastError( ERROR_INVALID_PARAMETER );
1872 return FALSE;
1875 if (!(wndPtr = WIN_GetPtr( hwnd )))
1877 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1878 return 0;
1880 if (wndPtr == WND_DESKTOP)
1882 /* can't change anything on the desktop window */
1883 SetLastError( ERROR_ACCESS_DENIED );
1884 return 0;
1886 if (wndPtr == WND_OTHER_PROCESS)
1888 if (offset == GWLP_WNDPROC)
1890 SetLastError( ERROR_ACCESS_DENIED );
1891 return 0;
1893 if (offset > 32767 || offset < -32767)
1895 SetLastError( ERROR_INVALID_INDEX );
1896 return 0;
1898 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, MAKEWPARAM( offset, size ), newval );
1901 /* first some special cases */
1902 switch( offset )
1904 case GWL_STYLE:
1905 case GWL_EXSTYLE:
1906 style.styleOld =
1907 offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
1908 style.styleNew = newval;
1909 WIN_ReleasePtr( wndPtr );
1910 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
1911 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
1912 newval = style.styleNew;
1913 break;
1914 case GWLP_HWNDPARENT:
1915 if (wndPtr->parent == GetDesktopWindow())
1917 WIN_ReleasePtr( wndPtr );
1918 return (ULONG_PTR)WIN_SetOwner( hwnd, (HWND)newval );
1920 else
1922 WIN_ReleasePtr( wndPtr );
1923 return (ULONG_PTR)SetParent( hwnd, (HWND)newval );
1925 case GWLP_WNDPROC:
1927 WNDPROC proc;
1928 UINT old_flags = wndPtr->flags;
1929 retval = WIN_GetWindowLong( hwnd, offset, size, unicode );
1930 if (unicode) proc = WINPROC_AllocProc( NULL, (WNDPROC)newval );
1931 else proc = WINPROC_AllocProc( (WNDPROC)newval, NULL );
1932 if (proc) wndPtr->winproc = proc;
1933 if (WINPROC_IsUnicode( proc, unicode )) wndPtr->flags |= WIN_ISUNICODE;
1934 else wndPtr->flags &= ~WIN_ISUNICODE;
1935 if (!((old_flags ^ wndPtr->flags) & WIN_ISUNICODE))
1937 WIN_ReleasePtr( wndPtr );
1938 return retval;
1940 /* update is_unicode flag on the server side */
1941 break;
1943 case GWLP_ID:
1944 case GWLP_HINSTANCE:
1945 case GWLP_USERDATA:
1946 break;
1947 case DWLP_DLGPROC:
1948 if ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
1949 (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG))
1951 WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWLP_DLGPROC);
1952 retval = (ULONG_PTR)WINPROC_GetProc( *ptr, unicode );
1953 if (unicode) *ptr = WINPROC_AllocProc( NULL, (WNDPROC)newval );
1954 else *ptr = WINPROC_AllocProc( (WNDPROC)newval, NULL );
1955 WIN_ReleasePtr( wndPtr );
1956 return retval;
1958 /* fall through */
1959 default:
1960 if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - size))
1962 WARN("Invalid offset %d\n", offset );
1963 WIN_ReleasePtr( wndPtr );
1964 SetLastError( ERROR_INVALID_INDEX );
1965 return 0;
1967 else if (get_win_data( (char *)wndPtr->wExtra + offset, size ) == newval)
1969 /* already set to the same value */
1970 WIN_ReleasePtr( wndPtr );
1971 return newval;
1973 break;
1976 SERVER_START_REQ( set_window_info )
1978 req->handle = hwnd;
1979 req->extra_offset = -1;
1980 switch(offset)
1982 case GWL_STYLE:
1983 req->flags = SET_WIN_STYLE;
1984 req->style = newval;
1985 break;
1986 case GWL_EXSTYLE:
1987 req->flags = SET_WIN_EXSTYLE;
1988 /* WS_EX_TOPMOST can only be changed through SetWindowPos */
1989 newval = (newval & ~WS_EX_TOPMOST) | (wndPtr->dwExStyle & WS_EX_TOPMOST);
1990 req->ex_style = newval;
1991 break;
1992 case GWLP_ID:
1993 req->flags = SET_WIN_ID;
1994 req->id = newval;
1995 break;
1996 case GWLP_HINSTANCE:
1997 req->flags = SET_WIN_INSTANCE;
1998 req->instance = (void *)newval;
1999 break;
2000 case GWLP_WNDPROC:
2001 req->flags = SET_WIN_UNICODE;
2002 req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
2003 break;
2004 case GWLP_USERDATA:
2005 req->flags = SET_WIN_USERDATA;
2006 req->user_data = newval;
2007 break;
2008 default:
2009 req->flags = SET_WIN_EXTRA;
2010 req->extra_offset = offset;
2011 req->extra_size = size;
2012 set_win_data( &req->extra_value, newval, size );
2014 if ((ok = !wine_server_call_err( req )))
2016 switch(offset)
2018 case GWL_STYLE:
2019 wndPtr->dwStyle = newval;
2020 retval = reply->old_style;
2021 break;
2022 case GWL_EXSTYLE:
2023 wndPtr->dwExStyle = newval;
2024 retval = reply->old_ex_style;
2025 break;
2026 case GWLP_ID:
2027 wndPtr->wIDmenu = newval;
2028 retval = reply->old_id;
2029 break;
2030 case GWLP_HINSTANCE:
2031 wndPtr->hInstance = (HINSTANCE)newval;
2032 retval = (ULONG_PTR)reply->old_instance;
2033 break;
2034 case GWLP_WNDPROC:
2035 break;
2036 case GWLP_USERDATA:
2037 wndPtr->userdata = newval;
2038 retval = reply->old_user_data;
2039 break;
2040 default:
2041 retval = get_win_data( (char *)wndPtr->wExtra + offset, size );
2042 set_win_data( (char *)wndPtr->wExtra + offset, newval, size );
2043 break;
2047 SERVER_END_REQ;
2048 WIN_ReleasePtr( wndPtr );
2050 if (!ok) return 0;
2052 if (offset == GWL_STYLE) USER_Driver->pSetWindowStyle( hwnd, retval );
2054 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2055 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2057 return retval;
2061 /**********************************************************************
2062 * GetWindowLong (USER.135)
2064 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2066 WND *wndPtr;
2067 LONG_PTR retvalue;
2068 BOOL is_winproc = (offset == GWLP_WNDPROC);
2070 if (offset >= 0)
2072 if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2074 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2075 return 0;
2077 if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2079 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
2082 * Some programs try to access last element from 16 bit
2083 * code using illegal offset value. Hopefully this is
2084 * what those programs really expect.
2086 if (wndPtr->cbWndExtra >= 4 && offset == wndPtr->cbWndExtra - sizeof(WORD))
2088 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
2089 ERR( "- replaced invalid offset %d with %d\n", offset, offset2 );
2090 offset = offset2;
2092 else
2094 WARN("Invalid offset %d\n", offset );
2095 WIN_ReleasePtr( wndPtr );
2096 SetLastError( ERROR_INVALID_INDEX );
2097 return 0;
2100 is_winproc = ((offset == DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG));
2101 WIN_ReleasePtr( wndPtr );
2104 retvalue = GetWindowLongA( WIN_Handle32(hwnd), offset );
2105 if (is_winproc) retvalue = (LONG_PTR)WINPROC_GetProc16( (WNDPROC)retvalue, FALSE );
2106 return retvalue;
2110 /**********************************************************************
2111 * GetWindowWord (USER32.@)
2113 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
2115 switch(offset)
2117 case GWLP_ID:
2118 case GWLP_HINSTANCE:
2119 case GWLP_HWNDPARENT:
2120 break;
2121 default:
2122 if (offset < 0)
2124 WARN("Invalid offset %d\n", offset );
2125 SetLastError( ERROR_INVALID_INDEX );
2126 return 0;
2128 break;
2130 return WIN_GetWindowLong( hwnd, offset, sizeof(WORD), FALSE );
2134 /**********************************************************************
2135 * GetWindowLongA (USER32.@)
2137 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2139 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), FALSE );
2143 /**********************************************************************
2144 * GetWindowLongW (USER32.@)
2146 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2148 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), TRUE );
2152 /**********************************************************************
2153 * SetWindowLong (USER.136)
2155 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2157 WND *wndPtr;
2158 BOOL is_winproc = (offset == GWLP_WNDPROC);
2160 if (offset == DWLP_DLGPROC)
2162 if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2164 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2165 return 0;
2167 if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2169 is_winproc = ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
2170 (wndPtr->flags & WIN_ISDIALOG));
2171 WIN_ReleasePtr( wndPtr );
2175 if (is_winproc)
2177 WNDPROC new_proc = WINPROC_AllocProc16( (WNDPROC16)newval );
2178 WNDPROC old_proc = (WNDPROC)SetWindowLongPtrA( WIN_Handle32(hwnd), offset, (LONG_PTR)new_proc );
2179 return (LONG)WINPROC_GetProc16( old_proc, FALSE );
2181 else return SetWindowLongA( WIN_Handle32(hwnd), offset, newval );
2185 /**********************************************************************
2186 * SetWindowWord (USER32.@)
2188 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
2190 switch(offset)
2192 case GWLP_ID:
2193 case GWLP_HINSTANCE:
2194 case GWLP_HWNDPARENT:
2195 break;
2196 default:
2197 if (offset < 0)
2199 WARN("Invalid offset %d\n", offset );
2200 SetLastError( ERROR_INVALID_INDEX );
2201 return 0;
2203 break;
2205 return WIN_SetWindowLong( hwnd, offset, sizeof(WORD), newval, FALSE );
2209 /**********************************************************************
2210 * SetWindowLongA (USER32.@)
2212 * See SetWindowLongW.
2214 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2216 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, FALSE );
2220 /**********************************************************************
2221 * SetWindowLongW (USER32.@) Set window attribute
2223 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2224 * value in a window's extra memory.
2226 * The _hwnd_ parameter specifies the window. is the handle to a
2227 * window that has extra memory. The _newval_ parameter contains the
2228 * new attribute or extra memory value. If positive, the _offset_
2229 * parameter is the byte-addressed location in the window's extra
2230 * memory to set. If negative, _offset_ specifies the window
2231 * attribute to set, and should be one of the following values:
2233 * GWL_EXSTYLE The window's extended window style
2235 * GWL_STYLE The window's window style.
2237 * GWLP_WNDPROC Pointer to the window's window procedure.
2239 * GWLP_HINSTANCE The window's pplication instance handle.
2241 * GWLP_ID The window's identifier.
2243 * GWLP_USERDATA The window's user-specified data.
2245 * If the window is a dialog box, the _offset_ parameter can be one of
2246 * the following values:
2248 * DWLP_DLGPROC The address of the window's dialog box procedure.
2250 * DWLP_MSGRESULT The return value of a message
2251 * that the dialog box procedure processed.
2253 * DWLP_USER Application specific information.
2255 * RETURNS
2257 * If successful, returns the previous value located at _offset_. Otherwise,
2258 * returns 0.
2260 * NOTES
2262 * Extra memory for a window class is specified by a nonzero cbWndExtra
2263 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2264 * time of class creation.
2266 * Using GWL_WNDPROC to set a new window procedure effectively creates
2267 * a window subclass. Use CallWindowProc() in the new windows procedure
2268 * to pass messages to the superclass's window procedure.
2270 * The user data is reserved for use by the application which created
2271 * the window.
2273 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2274 * instead, call the EnableWindow() function to change the window's
2275 * disabled state.
2277 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2278 * SetParent() instead.
2280 * Win95:
2281 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2282 * it sends WM_STYLECHANGING before changing the settings
2283 * and WM_STYLECHANGED afterwards.
2284 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2286 LONG WINAPI SetWindowLongW(
2287 HWND hwnd, /* [in] window to alter */
2288 INT offset, /* [in] offset, in bytes, of location to alter */
2289 LONG newval /* [in] new value of location */
2291 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, TRUE );
2295 /*******************************************************************
2296 * GetWindowTextA (USER32.@)
2298 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2300 WCHAR *buffer;
2302 if (!lpString) return 0;
2304 if (WIN_IsCurrentProcess( hwnd ))
2305 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2307 /* when window belongs to other process, don't send a message */
2308 if (nMaxCount <= 0) return 0;
2309 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2310 get_server_window_text( hwnd, buffer, nMaxCount );
2311 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2312 lpString[nMaxCount-1] = 0;
2313 HeapFree( GetProcessHeap(), 0, buffer );
2314 return strlen(lpString);
2318 /*******************************************************************
2319 * InternalGetWindowText (USER32.@)
2321 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2323 WND *win;
2325 if (nMaxCount <= 0) return 0;
2326 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2327 if (win == WND_DESKTOP) lpString[0] = 0;
2328 else if (win != WND_OTHER_PROCESS)
2330 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2331 else lpString[0] = 0;
2332 WIN_ReleasePtr( win );
2334 else
2336 get_server_window_text( hwnd, lpString, nMaxCount );
2338 return strlenW(lpString);
2342 /*******************************************************************
2343 * GetWindowTextW (USER32.@)
2345 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2347 if (!lpString) return 0;
2349 if (WIN_IsCurrentProcess( hwnd ))
2350 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2352 /* when window belongs to other process, don't send a message */
2353 if (nMaxCount <= 0) return 0;
2354 get_server_window_text( hwnd, lpString, nMaxCount );
2355 return strlenW(lpString);
2359 /*******************************************************************
2360 * SetWindowTextA (USER32.@)
2361 * SetWindowText (USER32.@)
2363 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2365 if (is_broadcast(hwnd))
2367 SetLastError( ERROR_INVALID_PARAMETER );
2368 return FALSE;
2370 if (!WIN_IsCurrentProcess( hwnd ))
2371 WARN( "setting text %s of other process window %p should not use SendMessage\n",
2372 debugstr_a(lpString), hwnd );
2373 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2377 /*******************************************************************
2378 * SetWindowTextW (USER32.@)
2380 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2382 if (is_broadcast(hwnd))
2384 SetLastError( ERROR_INVALID_PARAMETER );
2385 return FALSE;
2387 if (!WIN_IsCurrentProcess( hwnd ))
2388 WARN( "setting text %s of other process window %p should not use SendMessage\n",
2389 debugstr_w(lpString), hwnd );
2390 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2394 /*******************************************************************
2395 * GetWindowTextLengthA (USER32.@)
2397 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2399 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2402 /*******************************************************************
2403 * GetWindowTextLengthW (USER32.@)
2405 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2407 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2411 /*******************************************************************
2412 * IsWindow (USER32.@)
2414 BOOL WINAPI IsWindow( HWND hwnd )
2416 WND *ptr;
2417 BOOL ret;
2419 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2420 if (ptr == WND_DESKTOP) return TRUE;
2422 if (ptr != WND_OTHER_PROCESS)
2424 WIN_ReleasePtr( ptr );
2425 return TRUE;
2428 /* check other processes */
2429 SERVER_START_REQ( get_window_info )
2431 req->handle = hwnd;
2432 ret = !wine_server_call_err( req );
2434 SERVER_END_REQ;
2435 return ret;
2439 /***********************************************************************
2440 * GetWindowThreadProcessId (USER32.@)
2442 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2444 WND *ptr;
2445 DWORD tid = 0;
2447 if (!(ptr = WIN_GetPtr( hwnd )))
2449 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2450 return 0;
2453 if (ptr != WND_OTHER_PROCESS && ptr != WND_DESKTOP)
2455 /* got a valid window */
2456 tid = ptr->tid;
2457 if (process) *process = GetCurrentProcessId();
2458 WIN_ReleasePtr( ptr );
2459 return tid;
2462 /* check other processes */
2463 SERVER_START_REQ( get_window_info )
2465 req->handle = hwnd;
2466 if (!wine_server_call_err( req ))
2468 tid = (DWORD)reply->tid;
2469 if (process) *process = (DWORD)reply->pid;
2472 SERVER_END_REQ;
2473 return tid;
2477 /*****************************************************************
2478 * GetParent (USER32.@)
2480 HWND WINAPI GetParent( HWND hwnd )
2482 WND *wndPtr;
2483 HWND retvalue = 0;
2485 if (!(wndPtr = WIN_GetPtr( hwnd )))
2487 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2488 return 0;
2490 if (wndPtr == WND_DESKTOP) return 0;
2491 if (wndPtr == WND_OTHER_PROCESS)
2493 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2494 if (style & (WS_POPUP | WS_CHILD))
2496 SERVER_START_REQ( get_window_tree )
2498 req->handle = hwnd;
2499 if (!wine_server_call_err( req ))
2501 if (style & WS_POPUP) retvalue = reply->owner;
2502 else if (style & WS_CHILD) retvalue = reply->parent;
2505 SERVER_END_REQ;
2508 else
2510 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2511 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2512 WIN_ReleasePtr( wndPtr );
2514 return retvalue;
2518 /*****************************************************************
2519 * GetAncestor (USER32.@)
2521 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2523 WND *win;
2524 HWND *list, ret = 0;
2526 switch(type)
2528 case GA_PARENT:
2529 if (!(win = WIN_GetPtr( hwnd )))
2531 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2532 return 0;
2534 if (win == WND_DESKTOP) return 0;
2535 if (win != WND_OTHER_PROCESS)
2537 ret = win->parent;
2538 WIN_ReleasePtr( win );
2540 else /* need to query the server */
2542 SERVER_START_REQ( get_window_tree )
2544 req->handle = hwnd;
2545 if (!wine_server_call_err( req )) ret = reply->parent;
2547 SERVER_END_REQ;
2549 break;
2551 case GA_ROOT:
2552 if (!(list = list_window_parents( hwnd ))) return 0;
2554 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2555 else
2557 int count = 2;
2558 while (list[count]) count++;
2559 ret = list[count - 2]; /* get the one before the desktop */
2561 HeapFree( GetProcessHeap(), 0, list );
2562 break;
2564 case GA_ROOTOWNER:
2565 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2566 for (;;)
2568 HWND parent = GetParent( ret );
2569 if (!parent) break;
2570 ret = parent;
2572 break;
2574 return ret;
2578 /*****************************************************************
2579 * SetParent (USER32.@)
2581 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2583 HWND full_handle;
2584 HWND old_parent = 0;
2585 BOOL was_visible;
2586 WND *wndPtr;
2587 BOOL ret;
2589 if (is_broadcast(hwnd) || is_broadcast(parent))
2591 SetLastError(ERROR_INVALID_PARAMETER);
2592 return 0;
2595 if (!parent) parent = GetDesktopWindow();
2596 else parent = WIN_GetFullHandle( parent );
2598 if (!IsWindow( parent ))
2600 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2601 return 0;
2604 /* Some applications try to set a child as a parent */
2605 if (IsChild(hwnd, parent))
2607 SetLastError( ERROR_INVALID_PARAMETER );
2608 return 0;
2611 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2612 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2614 /* Windows hides the window first, then shows it again
2615 * including the WM_SHOWWINDOW messages and all */
2616 was_visible = ShowWindow( hwnd, SW_HIDE );
2618 wndPtr = WIN_GetPtr( hwnd );
2619 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return 0;
2621 SERVER_START_REQ( set_parent )
2623 req->handle = hwnd;
2624 req->parent = parent;
2625 if ((ret = !wine_server_call( req )))
2627 old_parent = reply->old_parent;
2628 wndPtr->parent = parent = reply->full_parent;
2632 SERVER_END_REQ;
2633 WIN_ReleasePtr( wndPtr );
2634 if (!ret) return 0;
2636 USER_Driver->pSetParent( full_handle, parent, old_parent );
2638 /* SetParent additionally needs to make hwnd the topmost window
2639 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2640 WM_WINDOWPOSCHANGED notification messages.
2642 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0,
2643 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2644 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2645 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2647 return old_parent;
2651 /*******************************************************************
2652 * IsChild (USER32.@)
2654 BOOL WINAPI IsChild( HWND parent, HWND child )
2656 HWND *list = list_window_parents( child );
2657 int i;
2658 BOOL ret;
2660 if (!list) return FALSE;
2661 parent = WIN_GetFullHandle( parent );
2662 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2663 ret = list[i] && list[i+1];
2664 HeapFree( GetProcessHeap(), 0, list );
2665 return ret;
2669 /***********************************************************************
2670 * IsWindowVisible (USER32.@)
2672 BOOL WINAPI IsWindowVisible( HWND hwnd )
2674 HWND *list;
2675 BOOL retval = TRUE;
2676 int i;
2678 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2679 if (!(list = list_window_parents( hwnd ))) return TRUE;
2680 if (list[0] && list[1]) /* desktop window is considered always visible so we don't check it */
2682 for (i = 0; list[i+1]; i++)
2683 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2684 retval = !list[i+1];
2686 HeapFree( GetProcessHeap(), 0, list );
2687 return retval;
2691 /***********************************************************************
2692 * WIN_IsWindowDrawable
2694 * hwnd is drawable when it is visible, all parents are not
2695 * minimized, and it is itself not minimized unless we are
2696 * trying to draw its default class icon.
2698 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2700 HWND *list;
2701 BOOL retval = TRUE;
2702 int i;
2703 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2705 if (!(style & WS_VISIBLE)) return FALSE;
2706 if ((style & WS_MINIMIZE) && icon && GetClassLongPtrW( hwnd, GCLP_HICON )) return FALSE;
2708 if (!(list = list_window_parents( hwnd ))) return TRUE;
2709 if (list[0] && list[1]) /* desktop window is considered always visible so we don't check it */
2711 for (i = 0; list[i+1]; i++)
2712 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2713 break;
2714 retval = !list[i+1];
2716 HeapFree( GetProcessHeap(), 0, list );
2717 return retval;
2721 /*******************************************************************
2722 * GetTopWindow (USER32.@)
2724 HWND WINAPI GetTopWindow( HWND hwnd )
2726 if (!hwnd) hwnd = GetDesktopWindow();
2727 return GetWindow( hwnd, GW_CHILD );
2731 /*******************************************************************
2732 * GetWindow (USER32.@)
2734 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2736 HWND retval = 0;
2738 if (rel == GW_OWNER) /* this one may be available locally */
2740 WND *wndPtr = WIN_GetPtr( hwnd );
2741 if (!wndPtr)
2743 SetLastError( ERROR_INVALID_HANDLE );
2744 return 0;
2746 if (wndPtr == WND_DESKTOP) return 0;
2747 if (wndPtr != WND_OTHER_PROCESS)
2749 retval = wndPtr->owner;
2750 WIN_ReleasePtr( wndPtr );
2751 return retval;
2753 /* else fall through to server call */
2756 SERVER_START_REQ( get_window_tree )
2758 req->handle = hwnd;
2759 if (!wine_server_call_err( req ))
2761 switch(rel)
2763 case GW_HWNDFIRST:
2764 retval = reply->first_sibling;
2765 break;
2766 case GW_HWNDLAST:
2767 retval = reply->last_sibling;
2768 break;
2769 case GW_HWNDNEXT:
2770 retval = reply->next_sibling;
2771 break;
2772 case GW_HWNDPREV:
2773 retval = reply->prev_sibling;
2774 break;
2775 case GW_OWNER:
2776 retval = reply->owner;
2777 break;
2778 case GW_CHILD:
2779 retval = reply->first_child;
2780 break;
2784 SERVER_END_REQ;
2785 return retval;
2789 /*******************************************************************
2790 * ShowOwnedPopups (USER32.@)
2792 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2794 int count = 0;
2795 WND *pWnd;
2796 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2798 if (!win_array) return TRUE;
2800 while (win_array[count]) count++;
2801 while (--count >= 0)
2803 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2804 if (!(pWnd = WIN_GetPtr( win_array[count] ))) continue;
2805 if (pWnd == WND_OTHER_PROCESS) continue;
2806 if (fShow)
2808 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2810 WIN_ReleasePtr( pWnd );
2811 /* In Windows, ShowOwnedPopups(TRUE) generates
2812 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2813 * regardless of the state of the owner
2815 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_SHOWNORMAL, SW_PARENTOPENING);
2816 continue;
2819 else
2821 if (pWnd->dwStyle & WS_VISIBLE)
2823 WIN_ReleasePtr( pWnd );
2824 /* In Windows, ShowOwnedPopups(FALSE) generates
2825 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2826 * regardless of the state of the owner
2828 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2829 continue;
2832 WIN_ReleasePtr( pWnd );
2834 HeapFree( GetProcessHeap(), 0, win_array );
2835 return TRUE;
2839 /*******************************************************************
2840 * GetLastActivePopup (USER32.@)
2842 HWND WINAPI GetLastActivePopup( HWND hwnd )
2844 HWND retval = hwnd;
2846 SERVER_START_REQ( get_window_info )
2848 req->handle = hwnd;
2849 if (!wine_server_call_err( req )) retval = reply->last_active;
2851 SERVER_END_REQ;
2852 return retval;
2856 /*******************************************************************
2857 * WIN_ListChildren
2859 * Build an array of the children of a given window. The array must be
2860 * freed with HeapFree. Returns NULL when no windows are found.
2862 HWND *WIN_ListChildren( HWND hwnd )
2864 return list_window_children( hwnd, NULL, 0 );
2868 /*******************************************************************
2869 * EnumWindows (USER32.@)
2871 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2873 HWND *list;
2874 BOOL ret = TRUE;
2875 int i;
2877 USER_CheckNotLock();
2879 /* We have to build a list of all windows first, to avoid */
2880 /* unpleasant side-effects, for instance if the callback */
2881 /* function changes the Z-order of the windows. */
2883 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2885 /* Now call the callback function for every window */
2887 for (i = 0; list[i]; i++)
2889 /* Make sure that the window still exists */
2890 if (!IsWindow( list[i] )) continue;
2891 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2893 HeapFree( GetProcessHeap(), 0, list );
2894 return ret;
2898 /**********************************************************************
2899 * EnumThreadWindows (USER32.@)
2901 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2903 HWND *list;
2904 int i;
2906 USER_CheckNotLock();
2908 if (!(list = list_window_children( GetDesktopWindow(), NULL, id ))) return TRUE;
2910 /* Now call the callback function for every window */
2912 for (i = 0; list[i]; i++)
2913 if (!func( list[i], lParam )) break;
2914 HeapFree( GetProcessHeap(), 0, list );
2915 return TRUE;
2919 /**********************************************************************
2920 * WIN_EnumChildWindows
2922 * Helper function for EnumChildWindows().
2924 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2926 HWND *childList;
2927 BOOL ret = FALSE;
2929 for ( ; *list; list++)
2931 /* Make sure that the window still exists */
2932 if (!IsWindow( *list )) continue;
2933 /* Build children list first */
2934 childList = WIN_ListChildren( *list );
2936 ret = func( *list, lParam );
2938 if (childList)
2940 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2941 HeapFree( GetProcessHeap(), 0, childList );
2943 if (!ret) return FALSE;
2945 return TRUE;
2949 /**********************************************************************
2950 * EnumChildWindows (USER32.@)
2952 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2954 HWND *list;
2955 BOOL ret;
2957 USER_CheckNotLock();
2959 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2960 ret = WIN_EnumChildWindows( list, func, lParam );
2961 HeapFree( GetProcessHeap(), 0, list );
2962 return ret;
2966 /*******************************************************************
2967 * AnyPopup (USER.52)
2969 BOOL16 WINAPI AnyPopup16(void)
2971 return AnyPopup();
2975 /*******************************************************************
2976 * AnyPopup (USER32.@)
2978 BOOL WINAPI AnyPopup(void)
2980 int i;
2981 BOOL retvalue;
2982 HWND *list = WIN_ListChildren( GetDesktopWindow() );
2984 if (!list) return FALSE;
2985 for (i = 0; list[i]; i++)
2987 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
2989 retvalue = (list[i] != 0);
2990 HeapFree( GetProcessHeap(), 0, list );
2991 return retvalue;
2995 /*******************************************************************
2996 * FlashWindow (USER32.@)
2998 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3000 WND *wndPtr;
3002 TRACE("%p\n", hWnd);
3004 if (IsIconic( hWnd ))
3006 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3008 wndPtr = WIN_GetPtr(hWnd);
3009 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
3010 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3012 wndPtr->flags |= WIN_NCACTIVATED;
3014 else
3016 wndPtr->flags &= ~WIN_NCACTIVATED;
3018 WIN_ReleasePtr( wndPtr );
3019 return TRUE;
3021 else
3023 WPARAM wparam;
3025 wndPtr = WIN_GetPtr(hWnd);
3026 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
3027 hWnd = wndPtr->hwndSelf; /* make it a full handle */
3029 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3030 else wparam = (hWnd == GetForegroundWindow());
3032 WIN_ReleasePtr( wndPtr );
3033 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3034 return wparam;
3038 /*******************************************************************
3039 * FlashWindowEx (USER32.@)
3041 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
3043 FIXME("%p\n", pfwi);
3044 return TRUE;
3047 /*******************************************************************
3048 * GetWindowContextHelpId (USER32.@)
3050 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3052 DWORD retval;
3053 WND *wnd = WIN_GetPtr( hwnd );
3054 if (!wnd || wnd == WND_DESKTOP) return 0;
3055 if (wnd == WND_OTHER_PROCESS)
3057 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3058 return 0;
3060 retval = wnd->helpContext;
3061 WIN_ReleasePtr( wnd );
3062 return retval;
3066 /*******************************************************************
3067 * SetWindowContextHelpId (USER32.@)
3069 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3071 WND *wnd = WIN_GetPtr( hwnd );
3072 if (!wnd || wnd == WND_DESKTOP) return FALSE;
3073 if (wnd == WND_OTHER_PROCESS)
3075 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3076 return 0;
3078 wnd->helpContext = id;
3079 WIN_ReleasePtr( wnd );
3080 return TRUE;
3084 /*******************************************************************
3085 * DragDetect (USER32.@)
3087 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3089 MSG msg;
3090 RECT rect;
3091 WORD wDragWidth = GetSystemMetrics(SM_CXDRAG);
3092 WORD wDragHeight= GetSystemMetrics(SM_CYDRAG);
3094 rect.left = pt.x - wDragWidth;
3095 rect.right = pt.x + wDragWidth;
3097 rect.top = pt.y - wDragHeight;
3098 rect.bottom = pt.y + wDragHeight;
3100 SetCapture(hWnd);
3102 while(1)
3104 while (PeekMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ))
3106 if( msg.message == WM_LBUTTONUP )
3108 ReleaseCapture();
3109 return 0;
3111 if( msg.message == WM_MOUSEMOVE )
3113 POINT tmp;
3114 tmp.x = (short)LOWORD(msg.lParam);
3115 tmp.y = (short)HIWORD(msg.lParam);
3116 if( !PtInRect( &rect, tmp ))
3118 ReleaseCapture();
3119 return 1;
3123 WaitMessage();
3125 return 0;
3128 /******************************************************************************
3129 * GetWindowModuleFileNameA (USER32.@)
3131 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3133 FIXME("GetWindowModuleFileNameA(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3134 hwnd, lpszFileName, cchFileNameMax);
3135 return 0;
3138 /******************************************************************************
3139 * GetWindowModuleFileNameW (USER32.@)
3141 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR lpszFileName, UINT cchFileNameMax)
3143 FIXME("GetWindowModuleFileNameW(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3144 hwnd, lpszFileName, cchFileNameMax);
3145 return 0;
3148 /******************************************************************************
3149 * GetWindowInfo (USER32.@)
3151 * Note: tests show that Windows doesn't check cbSize of the structure.
3153 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3155 if (!pwi) return FALSE;
3156 if (!IsWindow(hwnd)) return FALSE;
3158 GetWindowRect(hwnd, &pwi->rcWindow);
3159 GetClientRect(hwnd, &pwi->rcClient);
3160 /* translate to screen coordinates */
3161 MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3163 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3164 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3165 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3167 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3168 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3170 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3171 pwi->wCreatorVersion = 0x0400;
3173 return TRUE;
3176 /******************************************************************************
3177 * SwitchDesktop (USER32.@)
3179 * NOTES: Sets the current input or interactive desktop.
3181 BOOL WINAPI SwitchDesktop( HDESK hDesktop)
3183 FIXME("SwitchDesktop(hwnd %p) stub!\n", hDesktop);
3184 return TRUE;
3187 /*****************************************************************************
3188 * SetLayeredWindowAttributes (USER32.@)
3190 BOOL WINAPI SetLayeredWindowAttributes( HWND hWnd, COLORREF rgbKey,
3191 BYTE bAlpha, DWORD dwFlags )
3193 FIXME("(%p,0x%.8x,%d,%d): stub!\n", hWnd, rgbKey, bAlpha, dwFlags);
3194 return TRUE;
3197 /*****************************************************************************
3198 * GetLayeredWindowAttributes (USER32.@)
3200 BOOL WINAPI GetLayeredWindowAttributes( HWND hWnd, COLORREF *prgbKey,
3201 BYTE *pbAlpha, DWORD *pdwFlags )
3203 FIXME("(%p,%p,%p,%p): stub!\n", hWnd, prgbKey, pbAlpha, pdwFlags);
3204 return FALSE;
3207 /*****************************************************************************
3208 * UpdateLayeredWindow (USER32.@)
3210 BOOL WINAPI UpdateLayeredWindow( HWND hwnd, HDC hdcDst, POINT *pptDst, SIZE *psize,
3211 HDC hdcSrc, POINT *pptSrc, COLORREF crKey, BLENDFUNCTION *pblend,
3212 DWORD dwFlags)
3214 static int once;
3215 if (!once)
3217 once = 1;
3218 FIXME("(%p,%p,%p,%p,%p,%p,0x%08x,%p,%d): stub!\n",
3219 hwnd, hdcDst, pptDst, psize, hdcSrc, pptSrc, crKey, pblend, dwFlags);
3221 return 0;
3224 /* 64bit versions */
3226 #ifdef GetWindowLongPtrW
3227 #undef GetWindowLongPtrW
3228 #endif
3230 #ifdef GetWindowLongPtrA
3231 #undef GetWindowLongPtrA
3232 #endif
3234 #ifdef SetWindowLongPtrW
3235 #undef SetWindowLongPtrW
3236 #endif
3238 #ifdef SetWindowLongPtrA
3239 #undef SetWindowLongPtrA
3240 #endif
3242 /*****************************************************************************
3243 * GetWindowLongPtrW (USER32.@)
3245 LONG_PTR WINAPI GetWindowLongPtrW( HWND hwnd, INT offset )
3247 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), TRUE );
3250 /*****************************************************************************
3251 * GetWindowLongPtrA (USER32.@)
3253 LONG_PTR WINAPI GetWindowLongPtrA( HWND hwnd, INT offset )
3255 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), FALSE );
3258 /*****************************************************************************
3259 * SetWindowLongPtrW (USER32.@)
3261 LONG_PTR WINAPI SetWindowLongPtrW( HWND hwnd, INT offset, LONG_PTR newval )
3263 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, TRUE );
3266 /*****************************************************************************
3267 * SetWindowLongPtrA (USER32.@)
3269 LONG_PTR WINAPI SetWindowLongPtrA( HWND hwnd, INT offset, LONG_PTR newval )
3271 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, FALSE );