user32: Moved the DCE support from winex11 back to user32.
[wine/multimedia.git] / dlls / user32 / win.c
blobbdce3343429e61eb743075bd999ed32f9764f3e7
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, 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 NotifyWinEvent(EVENT_OBJECT_CREATE, hwnd, OBJID_WINDOW, 0);
1158 /* send the size messages */
1160 if (!(wndPtr = WIN_GetPtr(hwnd))) return 0;
1161 if (!(wndPtr->flags & WIN_NEED_SIZE))
1163 rect = wndPtr->rectClient;
1164 WIN_ReleasePtr( wndPtr );
1165 SendMessageW( hwnd, WM_SIZE, SIZE_RESTORED,
1166 MAKELONG(rect.right-rect.left, rect.bottom-rect.top));
1167 SendMessageW( hwnd, WM_MOVE, 0, MAKELONG( rect.left, rect.top ) );
1169 else WIN_ReleasePtr( wndPtr );
1171 /* call the driver */
1173 if (!USER_Driver->pCreateWindow( hwnd )) goto failed;
1175 /* Notify the parent window only */
1177 send_parent_notify( hwnd, WM_CREATE );
1178 if (!IsWindow( hwnd )) return 0;
1180 if (cs->style & WS_VISIBLE)
1182 if (cs->style & WS_MAXIMIZE)
1183 sw = SW_SHOW;
1184 else if (cs->style & WS_MINIMIZE)
1185 sw = SW_SHOWMINIMIZED;
1187 ShowWindow( hwnd, sw );
1188 if (cs->dwExStyle & WS_EX_MDICHILD)
1190 SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
1191 /* ShowWindow won't activate child windows */
1192 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE );
1196 /* Call WH_SHELL hook */
1198 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1199 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1201 TRACE("created window %p\n", hwnd);
1202 return hwnd;
1204 failed:
1205 WIN_DestroyWindow( hwnd );
1206 return 0;
1210 /***********************************************************************
1211 * CreateWindow (USER.41)
1213 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1214 DWORD style, INT16 x, INT16 y, INT16 width,
1215 INT16 height, HWND16 parent, HMENU16 menu,
1216 HINSTANCE16 instance, LPVOID data )
1218 return CreateWindowEx16( 0, className, windowName, style,
1219 x, y, width, height, parent, menu, instance, data );
1223 /***********************************************************************
1224 * CreateWindowEx (USER.452)
1226 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1227 LPCSTR windowName, DWORD style, INT16 x,
1228 INT16 y, INT16 width, INT16 height,
1229 HWND16 parent, HMENU16 menu,
1230 HINSTANCE16 instance, LPVOID data )
1232 CREATESTRUCTA cs;
1233 char buffer[256];
1235 /* Fix the coordinates */
1237 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1238 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1239 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1240 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1242 /* Create the window */
1244 cs.lpCreateParams = data;
1245 cs.hInstance = HINSTANCE_32(instance);
1246 cs.hMenu = HMENU_32(menu);
1247 cs.hwndParent = WIN_Handle32( parent );
1248 cs.style = style;
1249 cs.lpszName = windowName;
1250 cs.lpszClass = className;
1251 cs.dwExStyle = exStyle;
1253 if (!IS_INTRESOURCE(className))
1255 WCHAR bufferW[256];
1257 if (!MultiByteToWideChar( CP_ACP, 0, className, -1, bufferW, sizeof(bufferW)/sizeof(WCHAR) ))
1258 return 0;
1259 return HWND_16( WIN_CreateWindowEx( &cs, bufferW, 0 ));
1261 else
1263 if (!GlobalGetAtomNameA( LOWORD(className), buffer, sizeof(buffer) ))
1265 ERR( "bad atom %x\n", LOWORD(className));
1266 return 0;
1268 cs.lpszClass = buffer;
1269 return HWND_16( WIN_CreateWindowEx( &cs, (LPCWSTR)className, 0 ));
1274 /***********************************************************************
1275 * CreateWindowExA (USER32.@)
1277 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1278 LPCSTR windowName, DWORD style, INT x,
1279 INT y, INT width, INT height,
1280 HWND parent, HMENU menu,
1281 HINSTANCE instance, LPVOID data )
1283 CREATESTRUCTA cs;
1285 cs.lpCreateParams = data;
1286 cs.hInstance = instance;
1287 cs.hMenu = menu;
1288 cs.hwndParent = parent;
1289 cs.x = x;
1290 cs.y = y;
1291 cs.cx = width;
1292 cs.cy = height;
1293 cs.style = style;
1294 cs.lpszName = windowName;
1295 cs.lpszClass = className;
1296 cs.dwExStyle = exStyle;
1298 if (!IS_INTRESOURCE(className))
1300 WCHAR bufferW[256];
1301 if (!MultiByteToWideChar( CP_ACP, 0, className, -1, bufferW, sizeof(bufferW)/sizeof(WCHAR) ))
1302 return 0;
1303 return WIN_CreateWindowEx( &cs, bufferW, WIN_ISWIN32 );
1305 return WIN_CreateWindowEx( &cs, (LPCWSTR)className, WIN_ISWIN32 );
1309 /***********************************************************************
1310 * CreateWindowExW (USER32.@)
1312 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1313 LPCWSTR windowName, DWORD style, INT x,
1314 INT y, INT width, INT height,
1315 HWND parent, HMENU menu,
1316 HINSTANCE instance, LPVOID data )
1318 CREATESTRUCTW cs;
1320 cs.lpCreateParams = data;
1321 cs.hInstance = instance;
1322 cs.hMenu = menu;
1323 cs.hwndParent = parent;
1324 cs.x = x;
1325 cs.y = y;
1326 cs.cx = width;
1327 cs.cy = height;
1328 cs.style = style;
1329 cs.lpszName = windowName;
1330 cs.lpszClass = className;
1331 cs.dwExStyle = exStyle;
1333 /* Note: we rely on the fact that CREATESTRUCTA and */
1334 /* CREATESTRUCTW have the same layout. */
1335 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, className, WIN_ISWIN32 | WIN_ISUNICODE );
1339 /***********************************************************************
1340 * WIN_SendDestroyMsg
1342 static void WIN_SendDestroyMsg( HWND hwnd )
1344 GUITHREADINFO info;
1346 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1348 if (hwnd == info.hwndCaret) DestroyCaret();
1349 if (hwnd == info.hwndActive) WINPOS_ActivateOtherWindow( hwnd );
1353 * Send the WM_DESTROY to the window.
1355 SendMessageW( hwnd, WM_DESTROY, 0, 0);
1358 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1359 * make sure that the window still exists when we come back.
1361 if (IsWindow(hwnd))
1363 HWND* pWndArray;
1364 int i;
1366 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1368 for (i = 0; pWndArray[i]; i++)
1370 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1372 HeapFree( GetProcessHeap(), 0, pWndArray );
1374 else
1375 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1379 /***********************************************************************
1380 * DestroyWindow (USER32.@)
1382 BOOL WINAPI DestroyWindow( HWND hwnd )
1384 BOOL is_child;
1386 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1388 SetLastError( ERROR_ACCESS_DENIED );
1389 return FALSE;
1392 TRACE("(%p)\n", hwnd);
1394 /* Call hooks */
1396 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1398 if (MENU_IsMenuActive() == hwnd)
1399 EndMenu();
1401 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1403 if (is_child)
1405 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1406 send_parent_notify( hwnd, WM_DESTROY );
1408 else if (!GetWindow( hwnd, GW_OWNER ))
1410 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1411 /* FIXME: clean up palette - see "Internals" p.352 */
1414 if (!IsWindow(hwnd)) return TRUE;
1416 /* Hide the window */
1417 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)
1419 /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
1420 if (is_child)
1421 ShowWindow( hwnd, SW_HIDE );
1422 else
1423 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1424 SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW );
1427 if (!IsWindow(hwnd)) return TRUE;
1429 /* Recursively destroy owned windows */
1431 if (!is_child)
1433 for (;;)
1435 int i, got_one = 0;
1436 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1437 if (list)
1439 for (i = 0; list[i]; i++)
1441 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1442 if (WIN_IsCurrentThread( list[i] ))
1444 DestroyWindow( list[i] );
1445 got_one = 1;
1446 continue;
1448 WIN_SetOwner( list[i], 0 );
1450 HeapFree( GetProcessHeap(), 0, list );
1452 if (!got_one) break;
1456 /* Send destroy messages */
1458 WIN_SendDestroyMsg( hwnd );
1459 if (!IsWindow( hwnd )) return TRUE;
1461 if (GetClipboardOwner() == hwnd)
1462 CLIPBOARD_ReleaseOwner();
1464 /* Destroy the window storage */
1466 WIN_DestroyWindow( hwnd );
1467 return TRUE;
1471 /***********************************************************************
1472 * CloseWindow (USER32.@)
1474 BOOL WINAPI CloseWindow( HWND hwnd )
1476 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1477 ShowWindow( hwnd, SW_MINIMIZE );
1478 return TRUE;
1482 /***********************************************************************
1483 * OpenIcon (USER32.@)
1485 BOOL WINAPI OpenIcon( HWND hwnd )
1487 if (!IsIconic( hwnd )) return FALSE;
1488 ShowWindow( hwnd, SW_SHOWNORMAL );
1489 return TRUE;
1493 /***********************************************************************
1494 * FindWindowExW (USER32.@)
1496 HWND WINAPI FindWindowExW( HWND parent, HWND child, LPCWSTR className, LPCWSTR title )
1498 HWND *list = NULL;
1499 HWND retvalue = 0;
1500 int i = 0, len = 0;
1501 WCHAR *buffer = NULL;
1503 if (!parent) parent = GetDesktopWindow();
1504 if (title)
1506 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1507 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1510 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1512 if (child)
1514 child = WIN_GetFullHandle( child );
1515 while (list[i] && list[i] != child) i++;
1516 if (!list[i]) goto done;
1517 i++; /* start from next window */
1520 if (title)
1522 while (list[i])
1524 if (GetWindowTextW( list[i], buffer, len + 1 ) && !strcmpiW( buffer, title )) break;
1525 i++;
1528 retvalue = list[i];
1530 done:
1531 HeapFree( GetProcessHeap(), 0, list );
1532 HeapFree( GetProcessHeap(), 0, buffer );
1533 return retvalue;
1538 /***********************************************************************
1539 * FindWindowA (USER32.@)
1541 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1543 HWND ret = FindWindowExA( 0, 0, className, title );
1544 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1545 return ret;
1549 /***********************************************************************
1550 * FindWindowExA (USER32.@)
1552 HWND WINAPI FindWindowExA( HWND parent, HWND child, LPCSTR className, LPCSTR title )
1554 LPWSTR titleW = NULL;
1555 HWND hwnd = 0;
1557 if (title)
1559 DWORD len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1560 if (!(titleW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1561 MultiByteToWideChar( CP_ACP, 0, title, -1, titleW, len );
1564 if (!IS_INTRESOURCE(className))
1566 WCHAR classW[256];
1567 if (MultiByteToWideChar( CP_ACP, 0, className, -1, classW, sizeof(classW)/sizeof(WCHAR) ))
1568 hwnd = FindWindowExW( parent, child, classW, titleW );
1570 else
1572 hwnd = FindWindowExW( parent, child, (LPCWSTR)className, titleW );
1575 HeapFree( GetProcessHeap(), 0, titleW );
1576 return hwnd;
1580 /***********************************************************************
1581 * FindWindowW (USER32.@)
1583 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1585 return FindWindowExW( 0, 0, className, title );
1589 /**********************************************************************
1590 * GetDesktopWindow (USER32.@)
1592 HWND WINAPI GetDesktopWindow(void)
1594 struct user_thread_info *thread_info = get_user_thread_info();
1596 if (thread_info->desktop) return thread_info->desktop;
1598 SERVER_START_REQ( get_desktop_window )
1600 req->force = 0;
1601 if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1603 SERVER_END_REQ;
1605 if (!thread_info->desktop)
1607 static const WCHAR command_line[] = {'\\','e','x','p','l','o','r','e','r','.','e','x','e',' ','/','d','e','s','k','t','o','p',0};
1608 STARTUPINFOW si;
1609 PROCESS_INFORMATION pi;
1610 WCHAR cmdline[MAX_PATH + sizeof(command_line)/sizeof(WCHAR)];
1612 memset( &si, 0, sizeof(si) );
1613 si.cb = sizeof(si);
1614 si.dwFlags = STARTF_USESTDHANDLES;
1615 si.hStdInput = 0;
1616 si.hStdOutput = 0;
1617 si.hStdError = GetStdHandle( STD_ERROR_HANDLE );
1619 GetSystemDirectoryW( cmdline, MAX_PATH );
1620 lstrcatW( cmdline, command_line );
1621 if (CreateProcessW( NULL, cmdline, NULL, NULL, FALSE, DETACHED_PROCESS,
1622 NULL, NULL, &si, &pi ))
1624 TRACE( "started explorer pid %04x tid %04x\n", pi.dwProcessId, pi.dwThreadId );
1625 WaitForInputIdle( pi.hProcess, 10000 );
1626 CloseHandle( pi.hThread );
1627 CloseHandle( pi.hProcess );
1630 else WARN( "failed to start explorer, err %d\n", GetLastError() );
1632 SERVER_START_REQ( get_desktop_window )
1634 req->force = 1;
1635 if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1637 SERVER_END_REQ;
1640 if (!thread_info->desktop || !USER_Driver->pCreateDesktopWindow( thread_info->desktop ))
1641 ERR( "failed to create desktop window\n" );
1643 return thread_info->desktop;
1647 /*******************************************************************
1648 * EnableWindow (USER32.@)
1650 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1652 BOOL retvalue;
1653 HWND full_handle;
1655 if (is_broadcast(hwnd))
1657 SetLastError( ERROR_INVALID_PARAMETER );
1658 return FALSE;
1661 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1662 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1664 hwnd = full_handle;
1666 TRACE("( %p, %d )\n", hwnd, enable);
1668 retvalue = !IsWindowEnabled( hwnd );
1670 if (enable && retvalue)
1672 WIN_SetStyle( hwnd, 0, WS_DISABLED );
1673 SendMessageW( hwnd, WM_ENABLE, TRUE, 0 );
1675 else if (!enable && !retvalue)
1677 HWND capture_wnd;
1679 SendMessageW( hwnd, WM_CANCELMODE, 0, 0);
1681 WIN_SetStyle( hwnd, WS_DISABLED, 0 );
1683 if (hwnd == GetFocus())
1684 SetFocus( 0 ); /* A disabled window can't have the focus */
1686 capture_wnd = GetCapture();
1687 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1688 ReleaseCapture(); /* A disabled window can't capture the mouse */
1690 SendMessageW( hwnd, WM_ENABLE, FALSE, 0 );
1692 return retvalue;
1696 /***********************************************************************
1697 * IsWindowEnabled (USER32.@)
1699 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1701 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1705 /***********************************************************************
1706 * IsWindowUnicode (USER32.@)
1708 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1710 WND * wndPtr;
1711 BOOL retvalue = FALSE;
1713 if (!(wndPtr = WIN_GetPtr(hwnd))) return FALSE;
1715 if (wndPtr == WND_DESKTOP) return TRUE;
1717 if (wndPtr != WND_OTHER_PROCESS)
1719 retvalue = (wndPtr->flags & WIN_ISUNICODE) != 0;
1720 WIN_ReleasePtr( wndPtr );
1722 else
1724 SERVER_START_REQ( get_window_info )
1726 req->handle = hwnd;
1727 if (!wine_server_call_err( req )) retvalue = reply->is_unicode;
1729 SERVER_END_REQ;
1731 return retvalue;
1735 /**********************************************************************
1736 * WIN_GetWindowLong
1738 * Helper function for GetWindowLong().
1740 static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, UINT size, BOOL unicode )
1742 LONG_PTR retvalue = 0;
1743 WND *wndPtr;
1745 if (offset == GWLP_HWNDPARENT)
1747 HWND parent = GetAncestor( hwnd, GA_PARENT );
1748 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1749 return (ULONG_PTR)parent;
1752 if (!(wndPtr = WIN_GetPtr( hwnd )))
1754 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1755 return 0;
1758 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1760 if (offset == GWLP_WNDPROC)
1762 SetLastError( ERROR_ACCESS_DENIED );
1763 return 0;
1765 SERVER_START_REQ( set_window_info )
1767 req->handle = hwnd;
1768 req->flags = 0; /* don't set anything, just retrieve */
1769 req->extra_offset = (offset >= 0) ? offset : -1;
1770 req->extra_size = (offset >= 0) ? size : 0;
1771 if (!wine_server_call_err( req ))
1773 switch(offset)
1775 case GWL_STYLE: retvalue = reply->old_style; break;
1776 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1777 case GWLP_ID: retvalue = reply->old_id; break;
1778 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1779 case GWLP_USERDATA: retvalue = reply->old_user_data; break;
1780 default:
1781 if (offset >= 0) retvalue = get_win_data( &reply->old_extra_value, size );
1782 else SetLastError( ERROR_INVALID_INDEX );
1783 break;
1787 SERVER_END_REQ;
1788 return retvalue;
1791 /* now we have a valid wndPtr */
1793 if (offset >= 0)
1795 if (offset > (int)(wndPtr->cbWndExtra - size))
1797 WARN("Invalid offset %d\n", offset );
1798 WIN_ReleasePtr( wndPtr );
1799 SetLastError( ERROR_INVALID_INDEX );
1800 return 0;
1802 retvalue = get_win_data( (char *)wndPtr->wExtra + offset, size );
1804 /* Special case for dialog window procedure */
1805 if ((offset == DWLP_DLGPROC) && (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG))
1806 retvalue = (LONG_PTR)WINPROC_GetProc( (WNDPROC)retvalue, unicode );
1807 WIN_ReleasePtr( wndPtr );
1808 return retvalue;
1811 switch(offset)
1813 case GWLP_USERDATA: retvalue = wndPtr->userdata; break;
1814 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1815 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1816 case GWLP_ID: retvalue = wndPtr->wIDmenu; break;
1817 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wndPtr->hInstance; break;
1818 case GWLP_WNDPROC:
1819 /* This looks like a hack only for the edit control (see tests). This makes these controls
1820 * more tolerant to A/W mismatches. The lack of W->A->W conversion for such a mismatch suggests
1821 * that the hack is in GetWindowLongPtr[AW], not in winprocs.
1823 if (wndPtr->winproc == EDIT_winproc_handle && (!unicode != !(wndPtr->flags & WIN_ISUNICODE)))
1824 retvalue = (ULONG_PTR)wndPtr->winproc;
1825 else
1826 retvalue = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, unicode );
1827 break;
1828 default:
1829 WARN("Unknown offset %d\n", offset );
1830 SetLastError( ERROR_INVALID_INDEX );
1831 break;
1833 WIN_ReleasePtr(wndPtr);
1834 return retvalue;
1838 /**********************************************************************
1839 * WIN_SetWindowLong
1841 * Helper function for SetWindowLong().
1843 * 0 is the failure code. However, in the case of failure SetLastError
1844 * must be set to distinguish between a 0 return value and a failure.
1846 LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, UINT size, LONG_PTR newval, BOOL unicode )
1848 STYLESTRUCT style;
1849 BOOL ok;
1850 LONG_PTR retval = 0;
1851 WND *wndPtr;
1853 TRACE( "%p %d %lx %c\n", hwnd, offset, newval, unicode ? 'W' : 'A' );
1855 if (is_broadcast(hwnd))
1857 SetLastError( ERROR_INVALID_PARAMETER );
1858 return FALSE;
1861 if (!(wndPtr = WIN_GetPtr( hwnd )))
1863 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1864 return 0;
1866 if (wndPtr == WND_DESKTOP)
1868 /* can't change anything on the desktop window */
1869 SetLastError( ERROR_ACCESS_DENIED );
1870 return 0;
1872 if (wndPtr == WND_OTHER_PROCESS)
1874 if (offset == GWLP_WNDPROC)
1876 SetLastError( ERROR_ACCESS_DENIED );
1877 return 0;
1879 if (offset > 32767 || offset < -32767)
1881 SetLastError( ERROR_INVALID_INDEX );
1882 return 0;
1884 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, MAKEWPARAM( offset, size ), newval );
1887 /* first some special cases */
1888 switch( offset )
1890 case GWL_STYLE:
1891 case GWL_EXSTYLE:
1892 style.styleOld =
1893 offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
1894 style.styleNew = newval;
1895 WIN_ReleasePtr( wndPtr );
1896 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
1897 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
1898 newval = style.styleNew;
1899 break;
1900 case GWLP_HWNDPARENT:
1901 if (wndPtr->parent == GetDesktopWindow())
1903 WIN_ReleasePtr( wndPtr );
1904 return (ULONG_PTR)WIN_SetOwner( hwnd, (HWND)newval );
1906 else
1908 WIN_ReleasePtr( wndPtr );
1909 return (ULONG_PTR)SetParent( hwnd, (HWND)newval );
1911 case GWLP_WNDPROC:
1913 WNDPROC proc;
1914 UINT old_flags = wndPtr->flags;
1915 retval = WIN_GetWindowLong( hwnd, offset, size, unicode );
1916 if (unicode) proc = WINPROC_AllocProc( NULL, (WNDPROC)newval );
1917 else proc = WINPROC_AllocProc( (WNDPROC)newval, NULL );
1918 if (proc) wndPtr->winproc = proc;
1919 if (WINPROC_IsUnicode( proc, unicode )) wndPtr->flags |= WIN_ISUNICODE;
1920 else wndPtr->flags &= ~WIN_ISUNICODE;
1921 if (!((old_flags ^ wndPtr->flags) & WIN_ISUNICODE))
1923 WIN_ReleasePtr( wndPtr );
1924 return retval;
1926 /* update is_unicode flag on the server side */
1927 break;
1929 case GWLP_ID:
1930 case GWLP_HINSTANCE:
1931 case GWLP_USERDATA:
1932 break;
1933 case DWLP_DLGPROC:
1934 if ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
1935 (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG))
1937 WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWLP_DLGPROC);
1938 retval = (ULONG_PTR)WINPROC_GetProc( *ptr, unicode );
1939 if (unicode) *ptr = WINPROC_AllocProc( NULL, (WNDPROC)newval );
1940 else *ptr = WINPROC_AllocProc( (WNDPROC)newval, NULL );
1941 WIN_ReleasePtr( wndPtr );
1942 return retval;
1944 /* fall through */
1945 default:
1946 if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - size))
1948 WARN("Invalid offset %d\n", offset );
1949 WIN_ReleasePtr( wndPtr );
1950 SetLastError( ERROR_INVALID_INDEX );
1951 return 0;
1953 else if (get_win_data( (char *)wndPtr->wExtra + offset, size ) == newval)
1955 /* already set to the same value */
1956 WIN_ReleasePtr( wndPtr );
1957 return newval;
1959 break;
1962 SERVER_START_REQ( set_window_info )
1964 req->handle = hwnd;
1965 req->extra_offset = -1;
1966 switch(offset)
1968 case GWL_STYLE:
1969 req->flags = SET_WIN_STYLE;
1970 req->style = newval;
1971 break;
1972 case GWL_EXSTYLE:
1973 req->flags = SET_WIN_EXSTYLE;
1974 /* WS_EX_TOPMOST can only be changed through SetWindowPos */
1975 newval = (newval & ~WS_EX_TOPMOST) | (wndPtr->dwExStyle & WS_EX_TOPMOST);
1976 req->ex_style = newval;
1977 break;
1978 case GWLP_ID:
1979 req->flags = SET_WIN_ID;
1980 req->id = newval;
1981 break;
1982 case GWLP_HINSTANCE:
1983 req->flags = SET_WIN_INSTANCE;
1984 req->instance = (void *)newval;
1985 break;
1986 case GWLP_WNDPROC:
1987 req->flags = SET_WIN_UNICODE;
1988 req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
1989 break;
1990 case GWLP_USERDATA:
1991 req->flags = SET_WIN_USERDATA;
1992 req->user_data = newval;
1993 break;
1994 default:
1995 req->flags = SET_WIN_EXTRA;
1996 req->extra_offset = offset;
1997 req->extra_size = size;
1998 set_win_data( &req->extra_value, newval, size );
2000 if ((ok = !wine_server_call_err( req )))
2002 switch(offset)
2004 case GWL_STYLE:
2005 wndPtr->dwStyle = newval;
2006 retval = reply->old_style;
2007 break;
2008 case GWL_EXSTYLE:
2009 wndPtr->dwExStyle = newval;
2010 retval = reply->old_ex_style;
2011 break;
2012 case GWLP_ID:
2013 wndPtr->wIDmenu = newval;
2014 retval = reply->old_id;
2015 break;
2016 case GWLP_HINSTANCE:
2017 wndPtr->hInstance = (HINSTANCE)newval;
2018 retval = (ULONG_PTR)reply->old_instance;
2019 break;
2020 case GWLP_WNDPROC:
2021 break;
2022 case GWLP_USERDATA:
2023 wndPtr->userdata = newval;
2024 retval = reply->old_user_data;
2025 break;
2026 default:
2027 retval = get_win_data( (char *)wndPtr->wExtra + offset, size );
2028 set_win_data( (char *)wndPtr->wExtra + offset, newval, size );
2029 break;
2033 SERVER_END_REQ;
2034 WIN_ReleasePtr( wndPtr );
2036 if (!ok) return 0;
2038 if (offset == GWL_STYLE) USER_Driver->pSetWindowStyle( hwnd, retval );
2040 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2041 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2043 return retval;
2047 /**********************************************************************
2048 * GetWindowLong (USER.135)
2050 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2052 WND *wndPtr;
2053 LONG_PTR retvalue;
2054 BOOL is_winproc = (offset == GWLP_WNDPROC);
2056 if (offset >= 0)
2058 if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2060 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2061 return 0;
2063 if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2065 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
2068 * Some programs try to access last element from 16 bit
2069 * code using illegal offset value. Hopefully this is
2070 * what those programs really expect.
2072 if (wndPtr->cbWndExtra >= 4 && offset == wndPtr->cbWndExtra - sizeof(WORD))
2074 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
2075 ERR( "- replaced invalid offset %d with %d\n", offset, offset2 );
2076 offset = offset2;
2078 else
2080 WARN("Invalid offset %d\n", offset );
2081 WIN_ReleasePtr( wndPtr );
2082 SetLastError( ERROR_INVALID_INDEX );
2083 return 0;
2086 is_winproc = ((offset == DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG));
2087 WIN_ReleasePtr( wndPtr );
2090 retvalue = GetWindowLongA( WIN_Handle32(hwnd), offset );
2091 if (is_winproc) retvalue = (LONG_PTR)WINPROC_GetProc16( (WNDPROC)retvalue, FALSE );
2092 return retvalue;
2096 /**********************************************************************
2097 * GetWindowWord (USER32.@)
2099 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
2101 switch(offset)
2103 case GWLP_ID:
2104 case GWLP_HINSTANCE:
2105 case GWLP_HWNDPARENT:
2106 break;
2107 default:
2108 if (offset < 0)
2110 WARN("Invalid offset %d\n", offset );
2111 SetLastError( ERROR_INVALID_INDEX );
2112 return 0;
2114 break;
2116 return WIN_GetWindowLong( hwnd, offset, sizeof(WORD), FALSE );
2120 /**********************************************************************
2121 * GetWindowLongA (USER32.@)
2123 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2125 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), FALSE );
2129 /**********************************************************************
2130 * GetWindowLongW (USER32.@)
2132 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2134 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), TRUE );
2138 /**********************************************************************
2139 * SetWindowLong (USER.136)
2141 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2143 WND *wndPtr;
2144 BOOL is_winproc = (offset == GWLP_WNDPROC);
2146 if (offset == DWLP_DLGPROC)
2148 if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2150 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2151 return 0;
2153 if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2155 is_winproc = ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
2156 (wndPtr->flags & WIN_ISDIALOG));
2157 WIN_ReleasePtr( wndPtr );
2161 if (is_winproc)
2163 WNDPROC new_proc = WINPROC_AllocProc16( (WNDPROC16)newval );
2164 WNDPROC old_proc = (WNDPROC)SetWindowLongPtrA( WIN_Handle32(hwnd), offset, (LONG_PTR)new_proc );
2165 return (LONG)WINPROC_GetProc16( old_proc, FALSE );
2167 else return SetWindowLongA( WIN_Handle32(hwnd), offset, newval );
2171 /**********************************************************************
2172 * SetWindowWord (USER32.@)
2174 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
2176 switch(offset)
2178 case GWLP_ID:
2179 case GWLP_HINSTANCE:
2180 case GWLP_HWNDPARENT:
2181 break;
2182 default:
2183 if (offset < 0)
2185 WARN("Invalid offset %d\n", offset );
2186 SetLastError( ERROR_INVALID_INDEX );
2187 return 0;
2189 break;
2191 return WIN_SetWindowLong( hwnd, offset, sizeof(WORD), newval, FALSE );
2195 /**********************************************************************
2196 * SetWindowLongA (USER32.@)
2198 * See SetWindowLongW.
2200 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2202 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, FALSE );
2206 /**********************************************************************
2207 * SetWindowLongW (USER32.@) Set window attribute
2209 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2210 * value in a window's extra memory.
2212 * The _hwnd_ parameter specifies the window. is the handle to a
2213 * window that has extra memory. The _newval_ parameter contains the
2214 * new attribute or extra memory value. If positive, the _offset_
2215 * parameter is the byte-addressed location in the window's extra
2216 * memory to set. If negative, _offset_ specifies the window
2217 * attribute to set, and should be one of the following values:
2219 * GWL_EXSTYLE The window's extended window style
2221 * GWL_STYLE The window's window style.
2223 * GWLP_WNDPROC Pointer to the window's window procedure.
2225 * GWLP_HINSTANCE The window's pplication instance handle.
2227 * GWLP_ID The window's identifier.
2229 * GWLP_USERDATA The window's user-specified data.
2231 * If the window is a dialog box, the _offset_ parameter can be one of
2232 * the following values:
2234 * DWLP_DLGPROC The address of the window's dialog box procedure.
2236 * DWLP_MSGRESULT The return value of a message
2237 * that the dialog box procedure processed.
2239 * DWLP_USER Application specific information.
2241 * RETURNS
2243 * If successful, returns the previous value located at _offset_. Otherwise,
2244 * returns 0.
2246 * NOTES
2248 * Extra memory for a window class is specified by a nonzero cbWndExtra
2249 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2250 * time of class creation.
2252 * Using GWL_WNDPROC to set a new window procedure effectively creates
2253 * a window subclass. Use CallWindowProc() in the new windows procedure
2254 * to pass messages to the superclass's window procedure.
2256 * The user data is reserved for use by the application which created
2257 * the window.
2259 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2260 * instead, call the EnableWindow() function to change the window's
2261 * disabled state.
2263 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2264 * SetParent() instead.
2266 * Win95:
2267 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2268 * it sends WM_STYLECHANGING before changing the settings
2269 * and WM_STYLECHANGED afterwards.
2270 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2272 LONG WINAPI SetWindowLongW(
2273 HWND hwnd, /* [in] window to alter */
2274 INT offset, /* [in] offset, in bytes, of location to alter */
2275 LONG newval /* [in] new value of location */
2277 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, TRUE );
2281 /*******************************************************************
2282 * GetWindowTextA (USER32.@)
2284 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2286 WCHAR *buffer;
2288 if (!lpString) return 0;
2290 if (WIN_IsCurrentProcess( hwnd ))
2291 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2293 /* when window belongs to other process, don't send a message */
2294 if (nMaxCount <= 0) return 0;
2295 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2296 get_server_window_text( hwnd, buffer, nMaxCount );
2297 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2298 lpString[nMaxCount-1] = 0;
2299 HeapFree( GetProcessHeap(), 0, buffer );
2300 return strlen(lpString);
2304 /*******************************************************************
2305 * InternalGetWindowText (USER32.@)
2307 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2309 WND *win;
2311 if (nMaxCount <= 0) return 0;
2312 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2313 if (win == WND_DESKTOP) lpString[0] = 0;
2314 else if (win != WND_OTHER_PROCESS)
2316 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2317 else lpString[0] = 0;
2318 WIN_ReleasePtr( win );
2320 else
2322 get_server_window_text( hwnd, lpString, nMaxCount );
2324 return strlenW(lpString);
2328 /*******************************************************************
2329 * GetWindowTextW (USER32.@)
2331 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2333 if (!lpString) return 0;
2335 if (WIN_IsCurrentProcess( hwnd ))
2336 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2338 /* when window belongs to other process, don't send a message */
2339 if (nMaxCount <= 0) return 0;
2340 get_server_window_text( hwnd, lpString, nMaxCount );
2341 return strlenW(lpString);
2345 /*******************************************************************
2346 * SetWindowTextA (USER32.@)
2347 * SetWindowText (USER32.@)
2349 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2351 if (is_broadcast(hwnd))
2353 SetLastError( ERROR_INVALID_PARAMETER );
2354 return FALSE;
2356 if (!WIN_IsCurrentProcess( hwnd ))
2357 WARN( "setting text %s of other process window %p should not use SendMessage\n",
2358 debugstr_a(lpString), hwnd );
2359 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2363 /*******************************************************************
2364 * SetWindowTextW (USER32.@)
2366 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2368 if (is_broadcast(hwnd))
2370 SetLastError( ERROR_INVALID_PARAMETER );
2371 return FALSE;
2373 if (!WIN_IsCurrentProcess( hwnd ))
2374 WARN( "setting text %s of other process window %p should not use SendMessage\n",
2375 debugstr_w(lpString), hwnd );
2376 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2380 /*******************************************************************
2381 * GetWindowTextLengthA (USER32.@)
2383 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2385 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2388 /*******************************************************************
2389 * GetWindowTextLengthW (USER32.@)
2391 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2393 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2397 /*******************************************************************
2398 * IsWindow (USER32.@)
2400 BOOL WINAPI IsWindow( HWND hwnd )
2402 WND *ptr;
2403 BOOL ret;
2405 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2406 if (ptr == WND_DESKTOP) return TRUE;
2408 if (ptr != WND_OTHER_PROCESS)
2410 WIN_ReleasePtr( ptr );
2411 return TRUE;
2414 /* check other processes */
2415 SERVER_START_REQ( get_window_info )
2417 req->handle = hwnd;
2418 ret = !wine_server_call_err( req );
2420 SERVER_END_REQ;
2421 return ret;
2425 /***********************************************************************
2426 * GetWindowThreadProcessId (USER32.@)
2428 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2430 WND *ptr;
2431 DWORD tid = 0;
2433 if (!(ptr = WIN_GetPtr( hwnd )))
2435 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2436 return 0;
2439 if (ptr != WND_OTHER_PROCESS && ptr != WND_DESKTOP)
2441 /* got a valid window */
2442 tid = ptr->tid;
2443 if (process) *process = GetCurrentProcessId();
2444 WIN_ReleasePtr( ptr );
2445 return tid;
2448 /* check other processes */
2449 SERVER_START_REQ( get_window_info )
2451 req->handle = hwnd;
2452 if (!wine_server_call_err( req ))
2454 tid = (DWORD)reply->tid;
2455 if (process) *process = (DWORD)reply->pid;
2458 SERVER_END_REQ;
2459 return tid;
2463 /*****************************************************************
2464 * GetParent (USER32.@)
2466 HWND WINAPI GetParent( HWND hwnd )
2468 WND *wndPtr;
2469 HWND retvalue = 0;
2471 if (!(wndPtr = WIN_GetPtr( hwnd )))
2473 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2474 return 0;
2476 if (wndPtr == WND_DESKTOP) return 0;
2477 if (wndPtr == WND_OTHER_PROCESS)
2479 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2480 if (style & (WS_POPUP | WS_CHILD))
2482 SERVER_START_REQ( get_window_tree )
2484 req->handle = hwnd;
2485 if (!wine_server_call_err( req ))
2487 if (style & WS_POPUP) retvalue = reply->owner;
2488 else if (style & WS_CHILD) retvalue = reply->parent;
2491 SERVER_END_REQ;
2494 else
2496 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2497 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2498 WIN_ReleasePtr( wndPtr );
2500 return retvalue;
2504 /*****************************************************************
2505 * GetAncestor (USER32.@)
2507 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2509 WND *win;
2510 HWND *list, ret = 0;
2512 switch(type)
2514 case GA_PARENT:
2515 if (!(win = WIN_GetPtr( hwnd )))
2517 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2518 return 0;
2520 if (win == WND_DESKTOP) return 0;
2521 if (win != WND_OTHER_PROCESS)
2523 ret = win->parent;
2524 WIN_ReleasePtr( win );
2526 else /* need to query the server */
2528 SERVER_START_REQ( get_window_tree )
2530 req->handle = hwnd;
2531 if (!wine_server_call_err( req )) ret = reply->parent;
2533 SERVER_END_REQ;
2535 break;
2537 case GA_ROOT:
2538 if (!(list = list_window_parents( hwnd ))) return 0;
2540 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2541 else
2543 int count = 2;
2544 while (list[count]) count++;
2545 ret = list[count - 2]; /* get the one before the desktop */
2547 HeapFree( GetProcessHeap(), 0, list );
2548 break;
2550 case GA_ROOTOWNER:
2551 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2552 for (;;)
2554 HWND parent = GetParent( ret );
2555 if (!parent) break;
2556 ret = parent;
2558 break;
2560 return ret;
2564 /*****************************************************************
2565 * SetParent (USER32.@)
2567 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2569 HWND full_handle;
2570 HWND old_parent = 0;
2571 BOOL was_visible;
2572 WND *wndPtr;
2573 BOOL ret;
2575 if (is_broadcast(hwnd) || is_broadcast(parent))
2577 SetLastError(ERROR_INVALID_PARAMETER);
2578 return 0;
2581 if (!parent) parent = GetDesktopWindow();
2582 else parent = WIN_GetFullHandle( parent );
2584 if (!IsWindow( parent ))
2586 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2587 return 0;
2590 /* Some applications try to set a child as a parent */
2591 if (IsChild(hwnd, parent))
2593 SetLastError( ERROR_INVALID_PARAMETER );
2594 return 0;
2597 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2598 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2600 /* Windows hides the window first, then shows it again
2601 * including the WM_SHOWWINDOW messages and all */
2602 was_visible = ShowWindow( hwnd, SW_HIDE );
2604 wndPtr = WIN_GetPtr( hwnd );
2605 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return 0;
2607 SERVER_START_REQ( set_parent )
2609 req->handle = hwnd;
2610 req->parent = parent;
2611 if ((ret = !wine_server_call( req )))
2613 old_parent = reply->old_parent;
2614 wndPtr->parent = parent = reply->full_parent;
2618 SERVER_END_REQ;
2619 WIN_ReleasePtr( wndPtr );
2620 if (!ret) return 0;
2622 USER_Driver->pSetParent( full_handle, parent, old_parent );
2624 /* SetParent additionally needs to make hwnd the topmost window
2625 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2626 WM_WINDOWPOSCHANGED notification messages.
2628 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0,
2629 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2630 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2631 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2633 return old_parent;
2637 /*******************************************************************
2638 * IsChild (USER32.@)
2640 BOOL WINAPI IsChild( HWND parent, HWND child )
2642 HWND *list = list_window_parents( child );
2643 int i;
2644 BOOL ret;
2646 if (!list) return FALSE;
2647 parent = WIN_GetFullHandle( parent );
2648 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2649 ret = list[i] && list[i+1];
2650 HeapFree( GetProcessHeap(), 0, list );
2651 return ret;
2655 /***********************************************************************
2656 * IsWindowVisible (USER32.@)
2658 BOOL WINAPI IsWindowVisible( HWND hwnd )
2660 HWND *list;
2661 BOOL retval = TRUE;
2662 int i;
2664 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2665 if (!(list = list_window_parents( hwnd ))) return TRUE;
2666 if (list[0] && list[1]) /* desktop window is considered always visible so we don't check it */
2668 for (i = 0; list[i+1]; i++)
2669 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2670 retval = !list[i+1];
2672 HeapFree( GetProcessHeap(), 0, list );
2673 return retval;
2677 /***********************************************************************
2678 * WIN_IsWindowDrawable
2680 * hwnd is drawable when it is visible, all parents are not
2681 * minimized, and it is itself not minimized unless we are
2682 * trying to draw its default class icon.
2684 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2686 HWND *list;
2687 BOOL retval = TRUE;
2688 int i;
2689 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2691 if (!(style & WS_VISIBLE)) return FALSE;
2692 if ((style & WS_MINIMIZE) && icon && GetClassLongPtrW( hwnd, GCLP_HICON )) return FALSE;
2694 if (!(list = list_window_parents( hwnd ))) return TRUE;
2695 if (list[0] && list[1]) /* desktop window is considered always visible so we don't check it */
2697 for (i = 0; list[i+1]; i++)
2698 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2699 break;
2700 retval = !list[i+1];
2702 HeapFree( GetProcessHeap(), 0, list );
2703 return retval;
2707 /*******************************************************************
2708 * GetTopWindow (USER32.@)
2710 HWND WINAPI GetTopWindow( HWND hwnd )
2712 if (!hwnd) hwnd = GetDesktopWindow();
2713 return GetWindow( hwnd, GW_CHILD );
2717 /*******************************************************************
2718 * GetWindow (USER32.@)
2720 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2722 HWND retval = 0;
2724 if (rel == GW_OWNER) /* this one may be available locally */
2726 WND *wndPtr = WIN_GetPtr( hwnd );
2727 if (!wndPtr)
2729 SetLastError( ERROR_INVALID_HANDLE );
2730 return 0;
2732 if (wndPtr == WND_DESKTOP) return 0;
2733 if (wndPtr != WND_OTHER_PROCESS)
2735 retval = wndPtr->owner;
2736 WIN_ReleasePtr( wndPtr );
2737 return retval;
2739 /* else fall through to server call */
2742 SERVER_START_REQ( get_window_tree )
2744 req->handle = hwnd;
2745 if (!wine_server_call_err( req ))
2747 switch(rel)
2749 case GW_HWNDFIRST:
2750 retval = reply->first_sibling;
2751 break;
2752 case GW_HWNDLAST:
2753 retval = reply->last_sibling;
2754 break;
2755 case GW_HWNDNEXT:
2756 retval = reply->next_sibling;
2757 break;
2758 case GW_HWNDPREV:
2759 retval = reply->prev_sibling;
2760 break;
2761 case GW_OWNER:
2762 retval = reply->owner;
2763 break;
2764 case GW_CHILD:
2765 retval = reply->first_child;
2766 break;
2770 SERVER_END_REQ;
2771 return retval;
2775 /*******************************************************************
2776 * ShowOwnedPopups (USER32.@)
2778 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2780 int count = 0;
2781 WND *pWnd;
2782 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2784 if (!win_array) return TRUE;
2786 while (win_array[count]) count++;
2787 while (--count >= 0)
2789 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2790 if (!(pWnd = WIN_GetPtr( win_array[count] ))) continue;
2791 if (pWnd == WND_OTHER_PROCESS) continue;
2792 if (fShow)
2794 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2796 WIN_ReleasePtr( pWnd );
2797 /* In Windows, ShowOwnedPopups(TRUE) generates
2798 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2799 * regardless of the state of the owner
2801 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_SHOWNORMAL, SW_PARENTOPENING);
2802 continue;
2805 else
2807 if (pWnd->dwStyle & WS_VISIBLE)
2809 WIN_ReleasePtr( pWnd );
2810 /* In Windows, ShowOwnedPopups(FALSE) generates
2811 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2812 * regardless of the state of the owner
2814 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2815 continue;
2818 WIN_ReleasePtr( pWnd );
2820 HeapFree( GetProcessHeap(), 0, win_array );
2821 return TRUE;
2825 /*******************************************************************
2826 * GetLastActivePopup (USER32.@)
2828 HWND WINAPI GetLastActivePopup( HWND hwnd )
2830 HWND retval = hwnd;
2832 SERVER_START_REQ( get_window_info )
2834 req->handle = hwnd;
2835 if (!wine_server_call_err( req )) retval = reply->last_active;
2837 SERVER_END_REQ;
2838 return retval;
2842 /*******************************************************************
2843 * WIN_ListChildren
2845 * Build an array of the children of a given window. The array must be
2846 * freed with HeapFree. Returns NULL when no windows are found.
2848 HWND *WIN_ListChildren( HWND hwnd )
2850 return list_window_children( hwnd, NULL, 0 );
2854 /*******************************************************************
2855 * EnumWindows (USER32.@)
2857 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2859 HWND *list;
2860 BOOL ret = TRUE;
2861 int i;
2863 USER_CheckNotLock();
2865 /* We have to build a list of all windows first, to avoid */
2866 /* unpleasant side-effects, for instance if the callback */
2867 /* function changes the Z-order of the windows. */
2869 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2871 /* Now call the callback function for every window */
2873 for (i = 0; list[i]; i++)
2875 /* Make sure that the window still exists */
2876 if (!IsWindow( list[i] )) continue;
2877 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2879 HeapFree( GetProcessHeap(), 0, list );
2880 return ret;
2884 /**********************************************************************
2885 * EnumThreadWindows (USER32.@)
2887 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2889 HWND *list;
2890 int i;
2892 USER_CheckNotLock();
2894 if (!(list = list_window_children( GetDesktopWindow(), NULL, id ))) return TRUE;
2896 /* Now call the callback function for every window */
2898 for (i = 0; list[i]; i++)
2899 if (!func( list[i], lParam )) break;
2900 HeapFree( GetProcessHeap(), 0, list );
2901 return TRUE;
2905 /**********************************************************************
2906 * WIN_EnumChildWindows
2908 * Helper function for EnumChildWindows().
2910 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2912 HWND *childList;
2913 BOOL ret = FALSE;
2915 for ( ; *list; list++)
2917 /* Make sure that the window still exists */
2918 if (!IsWindow( *list )) continue;
2919 /* Build children list first */
2920 childList = WIN_ListChildren( *list );
2922 ret = func( *list, lParam );
2924 if (childList)
2926 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2927 HeapFree( GetProcessHeap(), 0, childList );
2929 if (!ret) return FALSE;
2931 return TRUE;
2935 /**********************************************************************
2936 * EnumChildWindows (USER32.@)
2938 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2940 HWND *list;
2941 BOOL ret;
2943 USER_CheckNotLock();
2945 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2946 ret = WIN_EnumChildWindows( list, func, lParam );
2947 HeapFree( GetProcessHeap(), 0, list );
2948 return ret;
2952 /*******************************************************************
2953 * AnyPopup (USER.52)
2955 BOOL16 WINAPI AnyPopup16(void)
2957 return AnyPopup();
2961 /*******************************************************************
2962 * AnyPopup (USER32.@)
2964 BOOL WINAPI AnyPopup(void)
2966 int i;
2967 BOOL retvalue;
2968 HWND *list = WIN_ListChildren( GetDesktopWindow() );
2970 if (!list) return FALSE;
2971 for (i = 0; list[i]; i++)
2973 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
2975 retvalue = (list[i] != 0);
2976 HeapFree( GetProcessHeap(), 0, list );
2977 return retvalue;
2981 /*******************************************************************
2982 * FlashWindow (USER32.@)
2984 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2986 WND *wndPtr;
2988 TRACE("%p\n", hWnd);
2990 if (IsIconic( hWnd ))
2992 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
2994 wndPtr = WIN_GetPtr(hWnd);
2995 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
2996 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2998 wndPtr->flags |= WIN_NCACTIVATED;
3000 else
3002 wndPtr->flags &= ~WIN_NCACTIVATED;
3004 WIN_ReleasePtr( wndPtr );
3005 return TRUE;
3007 else
3009 WPARAM wparam;
3011 wndPtr = WIN_GetPtr(hWnd);
3012 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
3013 hWnd = wndPtr->hwndSelf; /* make it a full handle */
3015 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3016 else wparam = (hWnd == GetForegroundWindow());
3018 WIN_ReleasePtr( wndPtr );
3019 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3020 return wparam;
3024 /*******************************************************************
3025 * FlashWindowEx (USER32.@)
3027 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
3029 FIXME("%p\n", pfwi);
3030 return TRUE;
3033 /*******************************************************************
3034 * GetWindowContextHelpId (USER32.@)
3036 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3038 DWORD retval;
3039 WND *wnd = WIN_GetPtr( hwnd );
3040 if (!wnd || wnd == WND_DESKTOP) return 0;
3041 if (wnd == WND_OTHER_PROCESS)
3043 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3044 return 0;
3046 retval = wnd->helpContext;
3047 WIN_ReleasePtr( wnd );
3048 return retval;
3052 /*******************************************************************
3053 * SetWindowContextHelpId (USER32.@)
3055 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3057 WND *wnd = WIN_GetPtr( hwnd );
3058 if (!wnd || wnd == WND_DESKTOP) return FALSE;
3059 if (wnd == WND_OTHER_PROCESS)
3061 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3062 return 0;
3064 wnd->helpContext = id;
3065 WIN_ReleasePtr( wnd );
3066 return TRUE;
3070 /*******************************************************************
3071 * DragDetect (USER32.@)
3073 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3075 MSG msg;
3076 RECT rect;
3077 WORD wDragWidth = GetSystemMetrics(SM_CXDRAG);
3078 WORD wDragHeight= GetSystemMetrics(SM_CYDRAG);
3080 rect.left = pt.x - wDragWidth;
3081 rect.right = pt.x + wDragWidth;
3083 rect.top = pt.y - wDragHeight;
3084 rect.bottom = pt.y + wDragHeight;
3086 SetCapture(hWnd);
3088 while(1)
3090 while (PeekMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ))
3092 if( msg.message == WM_LBUTTONUP )
3094 ReleaseCapture();
3095 return 0;
3097 if( msg.message == WM_MOUSEMOVE )
3099 POINT tmp;
3100 tmp.x = (short)LOWORD(msg.lParam);
3101 tmp.y = (short)HIWORD(msg.lParam);
3102 if( !PtInRect( &rect, tmp ))
3104 ReleaseCapture();
3105 return 1;
3109 WaitMessage();
3111 return 0;
3114 /******************************************************************************
3115 * GetWindowModuleFileNameA (USER32.@)
3117 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3119 FIXME("GetWindowModuleFileNameA(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3120 hwnd, lpszFileName, cchFileNameMax);
3121 return 0;
3124 /******************************************************************************
3125 * GetWindowModuleFileNameW (USER32.@)
3127 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR lpszFileName, UINT cchFileNameMax)
3129 FIXME("GetWindowModuleFileNameW(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3130 hwnd, lpszFileName, cchFileNameMax);
3131 return 0;
3134 /******************************************************************************
3135 * GetWindowInfo (USER32.@)
3137 * Note: tests show that Windows doesn't check cbSize of the structure.
3139 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3141 if (!pwi) return FALSE;
3142 if (!IsWindow(hwnd)) return FALSE;
3144 GetWindowRect(hwnd, &pwi->rcWindow);
3145 GetClientRect(hwnd, &pwi->rcClient);
3146 /* translate to screen coordinates */
3147 MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3149 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3150 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3151 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3153 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3154 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3156 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3157 pwi->wCreatorVersion = 0x0400;
3159 return TRUE;
3162 /******************************************************************************
3163 * SwitchDesktop (USER32.@)
3165 * NOTES: Sets the current input or interactive desktop.
3167 BOOL WINAPI SwitchDesktop( HDESK hDesktop)
3169 FIXME("SwitchDesktop(hwnd %p) stub!\n", hDesktop);
3170 return TRUE;
3173 /*****************************************************************************
3174 * SetLayeredWindowAttributes (USER32.@)
3176 BOOL WINAPI SetLayeredWindowAttributes( HWND hWnd, COLORREF rgbKey,
3177 BYTE bAlpha, DWORD dwFlags )
3179 FIXME("(%p,0x%.8x,%d,%d): stub!\n", hWnd, rgbKey, bAlpha, dwFlags);
3180 return TRUE;
3183 /*****************************************************************************
3184 * GetLayeredWindowAttributes (USER32.@)
3186 BOOL WINAPI GetLayeredWindowAttributes( HWND hWnd, COLORREF *prgbKey,
3187 BYTE *pbAlpha, DWORD *pdwFlags )
3189 FIXME("(%p,%p,%p,%p): stub!\n", hWnd, prgbKey, pbAlpha, pdwFlags);
3190 return FALSE;
3193 /*****************************************************************************
3194 * UpdateLayeredWindow (USER32.@)
3196 BOOL WINAPI UpdateLayeredWindow( HWND hwnd, HDC hdcDst, POINT *pptDst, SIZE *psize,
3197 HDC hdcSrc, POINT *pptSrc, COLORREF crKey, BLENDFUNCTION *pblend,
3198 DWORD dwFlags)
3200 static int once;
3201 if (!once)
3203 once = 1;
3204 FIXME("(%p,%p,%p,%p,%p,%p,0x%08x,%p,%d): stub!\n",
3205 hwnd, hdcDst, pptDst, psize, hdcSrc, pptSrc, crKey, pblend, dwFlags);
3207 return 0;
3210 /* 64bit versions */
3212 #ifdef GetWindowLongPtrW
3213 #undef GetWindowLongPtrW
3214 #endif
3216 #ifdef GetWindowLongPtrA
3217 #undef GetWindowLongPtrA
3218 #endif
3220 #ifdef SetWindowLongPtrW
3221 #undef SetWindowLongPtrW
3222 #endif
3224 #ifdef SetWindowLongPtrA
3225 #undef SetWindowLongPtrA
3226 #endif
3228 /*****************************************************************************
3229 * GetWindowLongPtrW (USER32.@)
3231 LONG_PTR WINAPI GetWindowLongPtrW( HWND hwnd, INT offset )
3233 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), TRUE );
3236 /*****************************************************************************
3237 * GetWindowLongPtrA (USER32.@)
3239 LONG_PTR WINAPI GetWindowLongPtrA( HWND hwnd, INT offset )
3241 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), FALSE );
3244 /*****************************************************************************
3245 * SetWindowLongPtrW (USER32.@)
3247 LONG_PTR WINAPI SetWindowLongPtrW( HWND hwnd, INT offset, LONG_PTR newval )
3249 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, TRUE );
3252 /*****************************************************************************
3253 * SetWindowLongPtrA (USER32.@)
3255 LONG_PTR WINAPI SetWindowLongPtrA( HWND hwnd, INT offset, LONG_PTR newval )
3257 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, FALSE );