winex11: Fix handling of property sizes for 64-bit platforms.
[wine/multimedia.git] / dlls / user32 / win.c
blobaa5bd878eca2b67e8d920bb29a660d045c462eb6
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( HDESK desktop, HWND hwnd, LPCWSTR class, DWORD tid )
217 HWND *list;
218 int size = 128;
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->desktop = desktop;
229 req->parent = hwnd;
230 req->tid = tid;
231 if (!(req->atom = get_int_atom_value( class )) && class)
232 wine_server_add_data( req, class, strlenW(class)*sizeof(WCHAR) );
233 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
234 if (!wine_server_call( req )) count = reply->count;
236 SERVER_END_REQ;
237 if (count && count < size)
239 list[count] = 0;
240 return list;
242 HeapFree( GetProcessHeap(), 0, list );
243 if (!count) break;
244 size = count + 1; /* restart with a large enough buffer */
246 return NULL;
250 /*******************************************************************
251 * list_window_parents
253 * Build an array of all parents of a given window, starting with
254 * the immediate parent. The array must be freed with HeapFree.
256 static HWND *list_window_parents( HWND hwnd )
258 WND *win;
259 HWND current, *list;
260 int pos = 0, size = 16, count = 0;
262 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
264 current = hwnd;
265 for (;;)
267 if (!(win = WIN_GetPtr( current ))) goto empty;
268 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
269 if (win == WND_DESKTOP)
271 if (!pos) goto empty;
272 list[pos] = 0;
273 return list;
275 list[pos] = current = win->parent;
276 WIN_ReleasePtr( win );
277 if (++pos == size - 1)
279 /* need to grow the list */
280 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
281 if (!new_list) goto empty;
282 list = new_list;
283 size += 16;
287 /* at least one parent belongs to another process, have to query the server */
289 for (;;)
291 count = 0;
292 SERVER_START_REQ( get_window_parents )
294 req->handle = hwnd;
295 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
296 if (!wine_server_call( req )) count = reply->count;
298 SERVER_END_REQ;
299 if (!count) goto empty;
300 if (size > count)
302 list[count] = 0;
303 return list;
305 HeapFree( GetProcessHeap(), 0, list );
306 size = count + 1;
307 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
310 empty:
311 HeapFree( GetProcessHeap(), 0, list );
312 return NULL;
316 /*******************************************************************
317 * send_parent_notify
319 static void send_parent_notify( HWND hwnd, UINT msg )
321 if ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_CHILD | WS_POPUP)) == WS_CHILD &&
322 !(GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY))
324 HWND parent = GetParent(hwnd);
325 if (parent && parent != GetDesktopWindow())
326 SendMessageW( parent, WM_PARENTNOTIFY,
327 MAKEWPARAM( msg, GetWindowLongPtrW( hwnd, GWLP_ID )), (LPARAM)hwnd );
332 /*******************************************************************
333 * get_server_window_text
335 * Retrieve the window text from the server.
337 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
339 size_t len = 0;
341 SERVER_START_REQ( get_window_text )
343 req->handle = hwnd;
344 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
345 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
347 SERVER_END_REQ;
348 text[len / sizeof(WCHAR)] = 0;
352 /***********************************************************************
353 * WIN_GetPtr
355 * Return a pointer to the WND structure if local to the process,
356 * or WND_OTHER_PROCESS if handle may be valid in other process.
357 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
359 WND *WIN_GetPtr( HWND hwnd )
361 WND * ptr;
362 WORD index = USER_HANDLE_TO_INDEX(hwnd);
364 if (index >= NB_USER_HANDLES) return NULL;
366 USER_Lock();
367 if ((ptr = user_handles[index]))
369 if (ptr->dwMagic == WND_MAGIC &&
370 (hwnd == ptr->hwndSelf || !HIWORD(hwnd) || HIWORD(hwnd) == 0xffff))
371 return ptr;
372 ptr = NULL;
374 else if (index == USER_HANDLE_TO_INDEX(GetDesktopWindow()))
376 if (hwnd == GetDesktopWindow() || !HIWORD(hwnd) || HIWORD(hwnd) == 0xffff) ptr = WND_DESKTOP;
377 else ptr = NULL;
379 else ptr = WND_OTHER_PROCESS;
380 USER_Unlock();
381 return ptr;
385 /***********************************************************************
386 * WIN_IsCurrentProcess
388 * Check whether a given window belongs to the current process (and return the full handle).
390 HWND WIN_IsCurrentProcess( HWND hwnd )
392 WND *ptr;
393 HWND ret;
395 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
396 ret = ptr->hwndSelf;
397 WIN_ReleasePtr( ptr );
398 return ret;
402 /***********************************************************************
403 * WIN_IsCurrentThread
405 * Check whether a given window belongs to the current thread (and return the full handle).
407 HWND WIN_IsCurrentThread( HWND hwnd )
409 WND *ptr;
410 HWND ret = 0;
412 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
413 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
414 WIN_ReleasePtr( ptr );
415 return ret;
419 /***********************************************************************
420 * WIN_Handle32
422 * Convert a 16-bit window handle to a full 32-bit handle.
424 HWND WIN_Handle32( HWND16 hwnd16 )
426 WND *ptr;
427 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
429 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
430 /* do sign extension for -2 and -3 */
431 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
433 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
435 if (ptr == WND_DESKTOP) return GetDesktopWindow();
437 if (ptr != WND_OTHER_PROCESS)
439 hwnd = ptr->hwndSelf;
440 WIN_ReleasePtr( ptr );
442 else /* may belong to another process */
444 SERVER_START_REQ( get_window_info )
446 req->handle = hwnd;
447 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
449 SERVER_END_REQ;
451 return hwnd;
455 /***********************************************************************
456 * WIN_SetOwner
458 * Change the owner of a window.
460 HWND WIN_SetOwner( HWND hwnd, HWND owner )
462 WND *win = WIN_GetPtr( hwnd );
463 HWND ret = 0;
465 if (!win || win == WND_DESKTOP) return 0;
466 if (win == WND_OTHER_PROCESS)
468 if (IsWindow(hwnd)) ERR( "cannot set owner %p on other process window %p\n", owner, hwnd );
469 return 0;
471 SERVER_START_REQ( set_window_owner )
473 req->handle = hwnd;
474 req->owner = owner;
475 if (!wine_server_call( req ))
477 win->owner = reply->full_owner;
478 ret = reply->prev_owner;
481 SERVER_END_REQ;
482 WIN_ReleasePtr( win );
483 return ret;
487 /***********************************************************************
488 * WIN_SetStyle
490 * Change the style of a window.
492 ULONG WIN_SetStyle( HWND hwnd, ULONG set_bits, ULONG clear_bits )
494 BOOL ok;
495 ULONG new_style, old_style = 0;
496 WND *win = WIN_GetPtr( hwnd );
498 if (!win || win == WND_DESKTOP) return 0;
499 if (win == WND_OTHER_PROCESS)
501 if (IsWindow(hwnd))
502 ERR( "cannot set style %x/%x on other process window %p\n",
503 set_bits, clear_bits, hwnd );
504 return 0;
506 new_style = (win->dwStyle | set_bits) & ~clear_bits;
507 if (new_style == win->dwStyle)
509 WIN_ReleasePtr( win );
510 return new_style;
512 SERVER_START_REQ( set_window_info )
514 req->handle = hwnd;
515 req->flags = SET_WIN_STYLE;
516 req->style = new_style;
517 req->extra_offset = -1;
518 if ((ok = !wine_server_call( req )))
520 old_style = reply->old_style;
521 win->dwStyle = new_style;
524 SERVER_END_REQ;
525 WIN_ReleasePtr( win );
526 if (ok)
528 USER_Driver->pSetWindowStyle( hwnd, old_style );
529 if ((old_style ^ new_style) & WS_VISIBLE) invalidate_dce( hwnd, NULL );
531 return old_style;
535 /***********************************************************************
536 * WIN_GetRectangles
538 * Get the window and client rectangles.
540 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
542 WND *win = WIN_GetPtr( hwnd );
543 BOOL ret = TRUE;
545 if (!win) return FALSE;
546 if (win == WND_DESKTOP)
548 RECT rect;
549 rect.left = rect.top = 0;
550 rect.right = GetSystemMetrics(SM_CXSCREEN);
551 rect.bottom = GetSystemMetrics(SM_CYSCREEN);
552 if (rectWindow) *rectWindow = rect;
553 if (rectClient) *rectClient = rect;
555 else if (win == WND_OTHER_PROCESS)
557 SERVER_START_REQ( get_window_rectangles )
559 req->handle = hwnd;
560 if ((ret = !wine_server_call( req )))
562 if (rectWindow)
564 rectWindow->left = reply->window.left;
565 rectWindow->top = reply->window.top;
566 rectWindow->right = reply->window.right;
567 rectWindow->bottom = reply->window.bottom;
569 if (rectClient)
571 rectClient->left = reply->client.left;
572 rectClient->top = reply->client.top;
573 rectClient->right = reply->client.right;
574 rectClient->bottom = reply->client.bottom;
578 SERVER_END_REQ;
580 else
582 if (rectWindow) *rectWindow = win->rectWindow;
583 if (rectClient) *rectClient = win->rectClient;
584 WIN_ReleasePtr( win );
586 return ret;
590 /***********************************************************************
591 * WIN_DestroyWindow
593 * Destroy storage associated to a window. "Internals" p.358
595 LRESULT WIN_DestroyWindow( HWND hwnd )
597 WND *wndPtr;
598 HWND *list;
599 HMENU menu = 0, sys_menu;
600 HWND icon_title;
602 TRACE("%p\n", hwnd );
604 /* free child windows */
605 if ((list = WIN_ListChildren( hwnd )))
607 int i;
608 for (i = 0; list[i]; i++)
610 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
611 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
613 HeapFree( GetProcessHeap(), 0, list );
616 /* Unlink now so we won't bother with the children later on */
617 SERVER_START_REQ( set_parent )
619 req->handle = hwnd;
620 req->parent = 0;
621 wine_server_call( req );
623 SERVER_END_REQ;
626 * Send the WM_NCDESTROY to the window being destroyed.
628 SendMessageW( hwnd, WM_NCDESTROY, 0, 0 );
630 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
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 icon_title = wndPtr->icon_title;
641 WIN_ReleasePtr( wndPtr );
643 if (icon_title) DestroyWindow( icon_title );
644 if (menu) DestroyMenu( menu );
645 if (sys_menu) DestroyMenu( sys_menu );
647 USER_Driver->pDestroyWindow( hwnd );
649 free_window_handle( hwnd );
650 return 0;
653 /***********************************************************************
654 * WIN_DestroyThreadWindows
656 * Destroy all children of 'wnd' owned by the current thread.
658 void WIN_DestroyThreadWindows( HWND hwnd )
660 HWND *list;
661 int i;
663 if (!(list = WIN_ListChildren( hwnd ))) return;
664 for (i = 0; list[i]; i++)
666 if (WIN_IsCurrentThread( list[i] ))
667 DestroyWindow( list[i] );
668 else
669 WIN_DestroyThreadWindows( list[i] );
671 HeapFree( GetProcessHeap(), 0, list );
675 /***********************************************************************
676 * WIN_FixCoordinates
678 * Fix the coordinates - Helper for WIN_CreateWindowEx.
679 * returns default show mode in sw.
681 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
683 #define IS_DEFAULT(x) ((x) == CW_USEDEFAULT || (x) == CW_USEDEFAULT16)
684 POINT pos[2];
686 if (cs->dwExStyle & WS_EX_MDICHILD)
688 UINT id = 0;
690 MDI_CalcDefaultChildPos(cs->hwndParent, -1, pos, 0, &id);
691 if (!(cs->style & WS_POPUP)) cs->hMenu = ULongToHandle(id);
693 TRACE("MDI child id %04x\n", id);
696 if (cs->style & (WS_CHILD | WS_POPUP))
698 if (cs->dwExStyle & WS_EX_MDICHILD)
700 if (IS_DEFAULT(cs->x))
702 cs->x = pos[0].x;
703 cs->y = pos[0].y;
705 if (IS_DEFAULT(cs->cx) || !cs->cx) cs->cx = pos[1].x;
706 if (IS_DEFAULT(cs->cy) || !cs->cy) cs->cy = pos[1].y;
708 else
710 if (IS_DEFAULT(cs->x)) cs->x = cs->y = 0;
711 if (IS_DEFAULT(cs->cx)) cs->cx = cs->cy = 0;
714 else /* overlapped window */
716 HMONITOR monitor;
717 MONITORINFO mon_info;
718 STARTUPINFOW info;
720 if (!IS_DEFAULT(cs->x) && !IS_DEFAULT(cs->cx) && !IS_DEFAULT(cs->cy)) return;
722 monitor = MonitorFromWindow( cs->hwndParent, MONITOR_DEFAULTTOPRIMARY );
723 mon_info.cbSize = sizeof(mon_info);
724 GetMonitorInfoW( monitor, &mon_info );
725 GetStartupInfoW( &info );
727 if (IS_DEFAULT(cs->x))
729 if (!IS_DEFAULT(cs->y)) *sw = cs->y;
730 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : mon_info.rcWork.left;
731 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : mon_info.rcWork.top;
734 if (IS_DEFAULT(cs->cx))
736 if (info.dwFlags & STARTF_USESIZE)
738 cs->cx = info.dwXSize;
739 cs->cy = info.dwYSize;
741 else
743 cs->cx = (mon_info.rcWork.right - mon_info.rcWork.left) * 3 / 4 - cs->x;
744 cs->cy = (mon_info.rcWork.bottom - mon_info.rcWork.top) * 3 / 4 - cs->y;
747 /* neither x nor cx are default. Check the y values .
748 * In the trace we see Outlook and Outlook Express using
749 * cy set to CW_USEDEFAULT when opening the address book.
751 else if (IS_DEFAULT(cs->cy))
753 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
754 cs->cy = (mon_info.rcWork.bottom - mon_info.rcWork.top) * 3 / 4 - cs->y;
757 #undef IS_DEFAULT
760 /***********************************************************************
761 * dump_window_styles
763 static void dump_window_styles( DWORD style, DWORD exstyle )
765 TRACE( "style:" );
766 if(style & WS_POPUP) TRACE(" WS_POPUP");
767 if(style & WS_CHILD) TRACE(" WS_CHILD");
768 if(style & WS_MINIMIZE) TRACE(" WS_MINIMIZE");
769 if(style & WS_VISIBLE) TRACE(" WS_VISIBLE");
770 if(style & WS_DISABLED) TRACE(" WS_DISABLED");
771 if(style & WS_CLIPSIBLINGS) TRACE(" WS_CLIPSIBLINGS");
772 if(style & WS_CLIPCHILDREN) TRACE(" WS_CLIPCHILDREN");
773 if(style & WS_MAXIMIZE) TRACE(" WS_MAXIMIZE");
774 if((style & WS_CAPTION) == WS_CAPTION) TRACE(" WS_CAPTION");
775 else
777 if(style & WS_BORDER) TRACE(" WS_BORDER");
778 if(style & WS_DLGFRAME) TRACE(" WS_DLGFRAME");
780 if(style & WS_VSCROLL) TRACE(" WS_VSCROLL");
781 if(style & WS_HSCROLL) TRACE(" WS_HSCROLL");
782 if(style & WS_SYSMENU) TRACE(" WS_SYSMENU");
783 if(style & WS_THICKFRAME) TRACE(" WS_THICKFRAME");
784 if (style & WS_CHILD)
786 if(style & WS_GROUP) TRACE(" WS_GROUP");
787 if(style & WS_TABSTOP) TRACE(" WS_TABSTOP");
789 else
791 if(style & WS_MINIMIZEBOX) TRACE(" WS_MINIMIZEBOX");
792 if(style & WS_MAXIMIZEBOX) TRACE(" WS_MAXIMIZEBOX");
795 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
796 #define DUMPED_STYLES \
797 (WS_POPUP | \
798 WS_CHILD | \
799 WS_MINIMIZE | \
800 WS_VISIBLE | \
801 WS_DISABLED | \
802 WS_CLIPSIBLINGS | \
803 WS_CLIPCHILDREN | \
804 WS_MAXIMIZE | \
805 WS_BORDER | \
806 WS_DLGFRAME | \
807 WS_VSCROLL | \
808 WS_HSCROLL | \
809 WS_SYSMENU | \
810 WS_THICKFRAME | \
811 WS_GROUP | \
812 WS_TABSTOP | \
813 WS_MINIMIZEBOX | \
814 WS_MAXIMIZEBOX)
816 if(style & ~DUMPED_STYLES) TRACE(" %08lx", style & ~DUMPED_STYLES);
817 TRACE("\n");
818 #undef DUMPED_STYLES
820 TRACE( "exstyle:" );
821 if(exstyle & WS_EX_DLGMODALFRAME) TRACE(" WS_EX_DLGMODALFRAME");
822 if(exstyle & WS_EX_DRAGDETECT) TRACE(" WS_EX_DRAGDETECT");
823 if(exstyle & WS_EX_NOPARENTNOTIFY) TRACE(" WS_EX_NOPARENTNOTIFY");
824 if(exstyle & WS_EX_TOPMOST) TRACE(" WS_EX_TOPMOST");
825 if(exstyle & WS_EX_ACCEPTFILES) TRACE(" WS_EX_ACCEPTFILES");
826 if(exstyle & WS_EX_TRANSPARENT) TRACE(" WS_EX_TRANSPARENT");
827 if(exstyle & WS_EX_MDICHILD) TRACE(" WS_EX_MDICHILD");
828 if(exstyle & WS_EX_TOOLWINDOW) TRACE(" WS_EX_TOOLWINDOW");
829 if(exstyle & WS_EX_WINDOWEDGE) TRACE(" WS_EX_WINDOWEDGE");
830 if(exstyle & WS_EX_CLIENTEDGE) TRACE(" WS_EX_CLIENTEDGE");
831 if(exstyle & WS_EX_CONTEXTHELP) TRACE(" WS_EX_CONTEXTHELP");
832 if(exstyle & WS_EX_RIGHT) TRACE(" WS_EX_RIGHT");
833 if(exstyle & WS_EX_RTLREADING) TRACE(" WS_EX_RTLREADING");
834 if(exstyle & WS_EX_LEFTSCROLLBAR) TRACE(" WS_EX_LEFTSCROLLBAR");
835 if(exstyle & WS_EX_CONTROLPARENT) TRACE(" WS_EX_CONTROLPARENT");
836 if(exstyle & WS_EX_STATICEDGE) TRACE(" WS_EX_STATICEDGE");
837 if(exstyle & WS_EX_APPWINDOW) TRACE(" WS_EX_APPWINDOW");
838 if(exstyle & WS_EX_LAYERED) TRACE(" WS_EX_LAYERED");
840 #define DUMPED_EX_STYLES \
841 (WS_EX_DLGMODALFRAME | \
842 WS_EX_DRAGDETECT | \
843 WS_EX_NOPARENTNOTIFY | \
844 WS_EX_TOPMOST | \
845 WS_EX_ACCEPTFILES | \
846 WS_EX_TRANSPARENT | \
847 WS_EX_MDICHILD | \
848 WS_EX_TOOLWINDOW | \
849 WS_EX_WINDOWEDGE | \
850 WS_EX_CLIENTEDGE | \
851 WS_EX_CONTEXTHELP | \
852 WS_EX_RIGHT | \
853 WS_EX_RTLREADING | \
854 WS_EX_LEFTSCROLLBAR | \
855 WS_EX_CONTROLPARENT | \
856 WS_EX_STATICEDGE | \
857 WS_EX_APPWINDOW | \
858 WS_EX_LAYERED)
860 if(exstyle & ~DUMPED_EX_STYLES) TRACE(" %08lx", exstyle & ~DUMPED_EX_STYLES);
861 TRACE("\n");
862 #undef DUMPED_EX_STYLES
866 /***********************************************************************
867 * WIN_CreateWindowEx
869 * Implementation of CreateWindowEx().
871 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, LPCWSTR className, UINT flags )
873 INT cx, cy, style, sw = SW_SHOW;
874 LRESULT result;
875 RECT rect;
876 WND *wndPtr;
877 HWND hwnd, parent, owner, top_child = 0;
878 BOOL unicode = (flags & WIN_ISUNICODE) != 0;
879 MDICREATESTRUCTA mdi_cs;
880 CBT_CREATEWNDA cbtc;
881 CREATESTRUCTA cbcs;
883 TRACE("%s %s ex=%08x style=%08x %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
884 unicode ? debugstr_w((LPCWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
885 debugstr_w(className),
886 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
887 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
888 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
890 /* Fix the styles for MDI children */
891 if (cs->dwExStyle & WS_EX_MDICHILD)
893 UINT flags = 0;
895 wndPtr = WIN_GetPtr(cs->hwndParent);
896 if (wndPtr && wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
898 flags = wndPtr->flags;
899 WIN_ReleasePtr(wndPtr);
902 if (!(flags & WIN_ISMDICLIENT))
904 WARN("WS_EX_MDICHILD, but parent %p is not MDIClient\n", cs->hwndParent);
905 return 0;
908 /* cs->lpCreateParams of WM_[NC]CREATE is different for MDI children.
909 * MDICREATESTRUCT members have the originally passed values.
911 * Note: we rely on the fact that MDICREATESTRUCTA and MDICREATESTRUCTW
912 * have the same layout.
914 mdi_cs.szClass = cs->lpszClass;
915 mdi_cs.szTitle = cs->lpszName;
916 mdi_cs.hOwner = cs->hInstance;
917 mdi_cs.x = cs->x;
918 mdi_cs.y = cs->y;
919 mdi_cs.cx = cs->cx;
920 mdi_cs.cy = cs->cy;
921 mdi_cs.style = cs->style;
922 mdi_cs.lParam = (LPARAM)cs->lpCreateParams;
924 cs->lpCreateParams = (LPVOID)&mdi_cs;
926 if (GetWindowLongW(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
928 if (cs->style & WS_POPUP)
930 TRACE("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n");
931 return 0;
933 cs->style |= WS_CHILD | WS_CLIPSIBLINGS;
935 else
937 cs->style &= ~WS_POPUP;
938 cs->style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
939 WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
942 top_child = GetWindow(cs->hwndParent, GW_CHILD);
944 if (top_child)
946 /* Restore current maximized child */
947 if((cs->style & WS_VISIBLE) && IsZoomed(top_child))
949 TRACE("Restoring current maximized child %p\n", top_child);
950 SendMessageW( top_child, WM_SETREDRAW, FALSE, 0 );
951 ShowWindow( top_child, SW_SHOWNORMAL );
952 SendMessageW( top_child, WM_SETREDRAW, TRUE, 0 );
957 /* Find the parent window */
959 parent = cs->hwndParent;
960 owner = 0;
962 if (cs->hwndParent == HWND_MESSAGE)
964 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
965 * message window (style: WS_POPUP|WS_DISABLED)
967 FIXME("Parent is HWND_MESSAGE\n");
968 parent = GetDesktopWindow();
970 else if (cs->hwndParent)
972 if ((cs->style & (WS_CHILD|WS_POPUP)) != WS_CHILD)
974 parent = GetDesktopWindow();
975 owner = cs->hwndParent;
978 else
980 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
982 WARN("No parent for child window\n" );
983 SetLastError(ERROR_TLW_WITH_WSCHILD);
984 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
986 if (className != (LPCWSTR)DESKTOP_CLASS_ATOM) /* are we creating the desktop itself? */
987 parent = GetDesktopWindow();
990 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
992 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
993 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
994 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
995 cs->dwExStyle |= WS_EX_WINDOWEDGE;
996 else
997 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
999 /* Create the window structure */
1001 if (!(wndPtr = create_window_handle( parent, owner, className, cs->hInstance, unicode )))
1002 return 0;
1003 hwnd = wndPtr->hwndSelf;
1005 /* Fill the window structure */
1007 wndPtr->tid = GetCurrentThreadId();
1008 wndPtr->hInstance = cs->hInstance;
1009 wndPtr->text = NULL;
1010 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1011 wndPtr->dwExStyle = cs->dwExStyle;
1012 wndPtr->wIDmenu = 0;
1013 wndPtr->helpContext = 0;
1014 wndPtr->pVScroll = NULL;
1015 wndPtr->pHScroll = NULL;
1016 wndPtr->userdata = 0;
1017 wndPtr->hIcon = 0;
1018 wndPtr->hIconSmall = 0;
1019 wndPtr->hSysMenu = 0;
1020 wndPtr->flags |= (flags & WIN_ISWIN32);
1022 if (wndPtr->dwStyle & WS_SYSMENU) SetSystemMenu( hwnd, 0 );
1025 * Correct the window styles.
1027 * It affects only the style loaded into the WIN structure.
1030 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
1032 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1033 if (!(wndPtr->dwStyle & WS_POPUP))
1034 wndPtr->dwStyle |= WS_CAPTION;
1038 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1039 * why does the user get to set it?
1042 if ((wndPtr->dwExStyle & WS_EX_DLGMODALFRAME) ||
1043 (wndPtr->dwStyle & (WS_DLGFRAME | WS_THICKFRAME)))
1044 wndPtr->dwExStyle |= WS_EX_WINDOWEDGE;
1045 else
1046 wndPtr->dwExStyle &= ~WS_EX_WINDOWEDGE;
1048 if (!(wndPtr->dwStyle & (WS_CHILD | WS_POPUP)))
1049 wndPtr->flags |= WIN_NEED_SIZE;
1051 SERVER_START_REQ( set_window_info )
1053 req->handle = hwnd;
1054 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE | SET_WIN_UNICODE;
1055 req->style = wndPtr->dwStyle;
1056 req->ex_style = wndPtr->dwExStyle;
1057 req->instance = (void *)wndPtr->hInstance;
1058 req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
1059 req->extra_offset = -1;
1060 wine_server_call( req );
1062 SERVER_END_REQ;
1064 /* Set the window menu */
1066 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
1068 if (cs->hMenu)
1070 if (!MENU_SetMenu(hwnd, cs->hMenu))
1072 WIN_ReleasePtr( wndPtr );
1073 free_window_handle( hwnd );
1074 return 0;
1077 else
1079 LPCSTR menuName = (LPCSTR)GetClassLongPtrA( hwnd, GCLP_MENUNAME );
1080 if (menuName)
1082 if (!cs->hInstance || HIWORD(cs->hInstance))
1083 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1084 else
1085 cs->hMenu = HMENU_32(LoadMenu16(HINSTANCE_16(cs->hInstance),menuName));
1087 if (cs->hMenu) MENU_SetMenu( hwnd, cs->hMenu );
1091 else SetWindowLongPtrW( hwnd, GWLP_ID, (ULONG_PTR)cs->hMenu );
1093 /* call the WH_CBT hook */
1095 /* the window style passed to the hook must be the real window style,
1096 * rather than just the window style that the caller to CreateWindowEx
1097 * passed in, so we have to copy the original CREATESTRUCT and get the
1098 * the real style. */
1099 cbcs = *cs;
1100 cbcs.style = wndPtr->dwStyle;
1101 cbtc.lpcs = &cbcs;
1102 cbtc.hwndInsertAfter = HWND_TOP;
1103 WIN_ReleasePtr( wndPtr );
1104 if (HOOK_CallHooks( WH_CBT, HCBT_CREATEWND, (WPARAM)hwnd, (LPARAM)&cbtc, unicode )) goto failed;
1106 /* send the WM_GETMINMAXINFO message and fix the size if needed */
1108 cx = cs->cx;
1109 cy = cs->cy;
1110 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
1112 POINT maxSize, maxPos, minTrack, maxTrack;
1113 WINPOS_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack);
1114 if (maxTrack.x < cx) cx = maxTrack.x;
1115 if (maxTrack.y < cy) cy = maxTrack.y;
1118 if (cx < 0) cx = 0;
1119 if (cy < 0) cy = 0;
1120 SetRect( &rect, cs->x, cs->y, cs->x + cx, cs->y + cy );
1121 if (!set_window_pos( hwnd, 0, SWP_NOZORDER | SWP_NOACTIVATE, &rect, &rect, NULL )) goto failed;
1123 /* send WM_NCCREATE */
1125 TRACE( "hwnd %p cs %d,%d %dx%d\n", hwnd, cs->x, cs->y, cx, cy );
1126 if (unicode)
1127 result = SendMessageW( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
1128 else
1129 result = SendMessageA( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
1130 if (!result)
1132 WARN( "%p: aborted by WM_NCCREATE\n", hwnd );
1133 goto failed;
1136 /* send WM_NCCALCSIZE */
1138 if ((wndPtr = WIN_GetPtr(hwnd)))
1140 /* yes, even if the CBT hook was called with HWND_TOP */
1141 HWND insert_after = (wndPtr->dwStyle & WS_CHILD) ? HWND_BOTTOM : HWND_TOP;
1142 RECT window_rect = wndPtr->rectWindow;
1143 RECT client_rect = window_rect;
1144 WIN_ReleasePtr( wndPtr );
1145 SendMessageW( hwnd, WM_NCCALCSIZE, FALSE, (LPARAM)&client_rect );
1146 set_window_pos( hwnd, insert_after, SWP_NOACTIVATE, &window_rect, &client_rect, NULL );
1148 else return 0;
1150 /* send WM_CREATE */
1152 if (unicode)
1153 result = SendMessageW( hwnd, WM_CREATE, 0, (LPARAM)cs );
1154 else
1155 result = SendMessageA( hwnd, WM_CREATE, 0, (LPARAM)cs );
1156 if (result == -1) goto failed;
1158 /* call the driver */
1160 if (!USER_Driver->pCreateWindow( hwnd )) goto failed;
1162 NotifyWinEvent(EVENT_OBJECT_CREATE, hwnd, OBJID_WINDOW, 0);
1164 /* send the size messages */
1166 if (!(wndPtr = WIN_GetPtr(hwnd))) return 0;
1167 if (!(wndPtr->flags & WIN_NEED_SIZE))
1169 rect = wndPtr->rectClient;
1170 WIN_ReleasePtr( wndPtr );
1171 SendMessageW( hwnd, WM_SIZE, SIZE_RESTORED,
1172 MAKELONG(rect.right-rect.left, rect.bottom-rect.top));
1173 SendMessageW( hwnd, WM_MOVE, 0, MAKELONG( rect.left, rect.top ) );
1175 else WIN_ReleasePtr( wndPtr );
1177 /* Show the window, maximizing or minimizing if needed */
1179 style = WIN_SetStyle( hwnd, 0, WS_MAXIMIZE | WS_MINIMIZE );
1180 if (style & (WS_MINIMIZE | WS_MAXIMIZE))
1182 RECT newPos;
1183 UINT swFlag = (style & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
1185 swFlag = WINPOS_MinMaximize( hwnd, swFlag, &newPos );
1186 swFlag |= SWP_FRAMECHANGED; /* Frame always gets changed */
1187 if (!(style & WS_VISIBLE) || (style & WS_CHILD) || GetActiveWindow()) swFlag |= SWP_NOACTIVATE;
1188 SetWindowPos( hwnd, 0, newPos.left, newPos.top, newPos.right, newPos.bottom, swFlag );
1191 /* Notify the parent window only */
1193 send_parent_notify( hwnd, WM_CREATE );
1194 if (!IsWindow( hwnd )) return 0;
1196 if (cs->style & WS_VISIBLE)
1198 if (cs->style & WS_MAXIMIZE)
1199 sw = SW_SHOW;
1200 else if (cs->style & WS_MINIMIZE)
1201 sw = SW_SHOWMINIMIZED;
1203 ShowWindow( hwnd, sw );
1204 if (cs->dwExStyle & WS_EX_MDICHILD)
1206 SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
1207 /* ShowWindow won't activate child windows */
1208 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE );
1212 /* Call WH_SHELL hook */
1214 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1215 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1217 TRACE("created window %p\n", hwnd);
1218 return hwnd;
1220 failed:
1221 WIN_DestroyWindow( hwnd );
1222 return 0;
1226 /***********************************************************************
1227 * CreateWindow (USER.41)
1229 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1230 DWORD style, INT16 x, INT16 y, INT16 width,
1231 INT16 height, HWND16 parent, HMENU16 menu,
1232 HINSTANCE16 instance, LPVOID data )
1234 return CreateWindowEx16( 0, className, windowName, style,
1235 x, y, width, height, parent, menu, instance, data );
1239 /***********************************************************************
1240 * CreateWindowEx (USER.452)
1242 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1243 LPCSTR windowName, DWORD style, INT16 x,
1244 INT16 y, INT16 width, INT16 height,
1245 HWND16 parent, HMENU16 menu,
1246 HINSTANCE16 instance, LPVOID data )
1248 CREATESTRUCTA cs;
1249 char buffer[256];
1251 /* Fix the coordinates */
1253 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1254 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1255 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1256 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1258 /* Create the window */
1260 cs.lpCreateParams = data;
1261 cs.hInstance = HINSTANCE_32(instance);
1262 cs.hMenu = HMENU_32(menu);
1263 cs.hwndParent = WIN_Handle32( parent );
1264 cs.style = style;
1265 cs.lpszName = windowName;
1266 cs.lpszClass = className;
1267 cs.dwExStyle = exStyle;
1269 if (!IS_INTRESOURCE(className))
1271 WCHAR bufferW[256];
1273 if (!MultiByteToWideChar( CP_ACP, 0, className, -1, bufferW, sizeof(bufferW)/sizeof(WCHAR) ))
1274 return 0;
1275 return HWND_16( WIN_CreateWindowEx( &cs, bufferW, 0 ));
1277 else
1279 if (!GlobalGetAtomNameA( LOWORD(className), buffer, sizeof(buffer) ))
1281 ERR( "bad atom %x\n", LOWORD(className));
1282 return 0;
1284 cs.lpszClass = buffer;
1285 return HWND_16( WIN_CreateWindowEx( &cs, (LPCWSTR)className, 0 ));
1290 /***********************************************************************
1291 * CreateWindowExA (USER32.@)
1293 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1294 LPCSTR windowName, DWORD style, INT x,
1295 INT y, INT width, INT height,
1296 HWND parent, HMENU menu,
1297 HINSTANCE instance, LPVOID data )
1299 CREATESTRUCTA cs;
1301 cs.lpCreateParams = data;
1302 cs.hInstance = instance;
1303 cs.hMenu = menu;
1304 cs.hwndParent = parent;
1305 cs.x = x;
1306 cs.y = y;
1307 cs.cx = width;
1308 cs.cy = height;
1309 cs.style = style;
1310 cs.lpszName = windowName;
1311 cs.lpszClass = className;
1312 cs.dwExStyle = exStyle;
1314 if (!IS_INTRESOURCE(className))
1316 WCHAR bufferW[256];
1317 if (!MultiByteToWideChar( CP_ACP, 0, className, -1, bufferW, sizeof(bufferW)/sizeof(WCHAR) ))
1318 return 0;
1319 return WIN_CreateWindowEx( &cs, bufferW, WIN_ISWIN32 );
1321 return WIN_CreateWindowEx( &cs, (LPCWSTR)className, WIN_ISWIN32 );
1325 /***********************************************************************
1326 * CreateWindowExW (USER32.@)
1328 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1329 LPCWSTR windowName, DWORD style, INT x,
1330 INT y, INT width, INT height,
1331 HWND parent, HMENU menu,
1332 HINSTANCE instance, LPVOID data )
1334 CREATESTRUCTW cs;
1336 cs.lpCreateParams = data;
1337 cs.hInstance = instance;
1338 cs.hMenu = menu;
1339 cs.hwndParent = parent;
1340 cs.x = x;
1341 cs.y = y;
1342 cs.cx = width;
1343 cs.cy = height;
1344 cs.style = style;
1345 cs.lpszName = windowName;
1346 cs.lpszClass = className;
1347 cs.dwExStyle = exStyle;
1349 /* Note: we rely on the fact that CREATESTRUCTA and */
1350 /* CREATESTRUCTW have the same layout. */
1351 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, className, WIN_ISWIN32 | WIN_ISUNICODE );
1355 /***********************************************************************
1356 * WIN_SendDestroyMsg
1358 static void WIN_SendDestroyMsg( HWND hwnd )
1360 GUITHREADINFO info;
1362 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1364 if (hwnd == info.hwndCaret) DestroyCaret();
1365 if (hwnd == info.hwndActive) WINPOS_ActivateOtherWindow( hwnd );
1369 * Send the WM_DESTROY to the window.
1371 SendMessageW( hwnd, WM_DESTROY, 0, 0);
1374 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1375 * make sure that the window still exists when we come back.
1377 if (IsWindow(hwnd))
1379 HWND* pWndArray;
1380 int i;
1382 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1384 for (i = 0; pWndArray[i]; i++)
1386 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1388 HeapFree( GetProcessHeap(), 0, pWndArray );
1390 else
1391 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1395 /***********************************************************************
1396 * DestroyWindow (USER32.@)
1398 BOOL WINAPI DestroyWindow( HWND hwnd )
1400 BOOL is_child;
1402 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1404 SetLastError( ERROR_ACCESS_DENIED );
1405 return FALSE;
1408 TRACE("(%p)\n", hwnd);
1410 /* Call hooks */
1412 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1414 if (MENU_IsMenuActive() == hwnd)
1415 EndMenu();
1417 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1419 if (is_child)
1421 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1422 send_parent_notify( hwnd, WM_DESTROY );
1424 else if (!GetWindow( hwnd, GW_OWNER ))
1426 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1427 /* FIXME: clean up palette - see "Internals" p.352 */
1430 if (!IsWindow(hwnd)) return TRUE;
1432 /* Hide the window */
1433 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)
1435 /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
1436 if (is_child)
1437 ShowWindow( hwnd, SW_HIDE );
1438 else
1439 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1440 SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW );
1443 if (!IsWindow(hwnd)) return TRUE;
1445 /* Recursively destroy owned windows */
1447 if (!is_child)
1449 for (;;)
1451 int i, got_one = 0;
1452 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1453 if (list)
1455 for (i = 0; list[i]; i++)
1457 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1458 if (WIN_IsCurrentThread( list[i] ))
1460 DestroyWindow( list[i] );
1461 got_one = 1;
1462 continue;
1464 WIN_SetOwner( list[i], 0 );
1466 HeapFree( GetProcessHeap(), 0, list );
1468 if (!got_one) break;
1472 /* Send destroy messages */
1474 WIN_SendDestroyMsg( hwnd );
1475 if (!IsWindow( hwnd )) return TRUE;
1477 if (GetClipboardOwner() == hwnd)
1478 CLIPBOARD_ReleaseOwner();
1480 /* Destroy the window storage */
1482 WIN_DestroyWindow( hwnd );
1483 return TRUE;
1487 /***********************************************************************
1488 * CloseWindow (USER32.@)
1490 BOOL WINAPI CloseWindow( HWND hwnd )
1492 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1493 ShowWindow( hwnd, SW_MINIMIZE );
1494 return TRUE;
1498 /***********************************************************************
1499 * OpenIcon (USER32.@)
1501 BOOL WINAPI OpenIcon( HWND hwnd )
1503 if (!IsIconic( hwnd )) return FALSE;
1504 ShowWindow( hwnd, SW_SHOWNORMAL );
1505 return TRUE;
1509 /***********************************************************************
1510 * FindWindowExW (USER32.@)
1512 HWND WINAPI FindWindowExW( HWND parent, HWND child, LPCWSTR className, LPCWSTR title )
1514 HWND *list = NULL;
1515 HWND retvalue = 0;
1516 int i = 0, len = 0;
1517 WCHAR *buffer = NULL;
1519 if (!parent) parent = GetDesktopWindow();
1520 if (title)
1522 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1523 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1526 if (!(list = list_window_children( 0, parent, className, 0 ))) goto done;
1528 if (child)
1530 child = WIN_GetFullHandle( child );
1531 while (list[i] && list[i] != child) i++;
1532 if (!list[i]) goto done;
1533 i++; /* start from next window */
1536 if (title)
1538 while (list[i])
1540 if (GetWindowTextW( list[i], buffer, len + 1 ) && !strcmpiW( buffer, title )) break;
1541 i++;
1544 retvalue = list[i];
1546 done:
1547 HeapFree( GetProcessHeap(), 0, list );
1548 HeapFree( GetProcessHeap(), 0, buffer );
1549 return retvalue;
1554 /***********************************************************************
1555 * FindWindowA (USER32.@)
1557 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1559 HWND ret = FindWindowExA( 0, 0, className, title );
1560 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1561 return ret;
1565 /***********************************************************************
1566 * FindWindowExA (USER32.@)
1568 HWND WINAPI FindWindowExA( HWND parent, HWND child, LPCSTR className, LPCSTR title )
1570 LPWSTR titleW = NULL;
1571 HWND hwnd = 0;
1573 if (title)
1575 DWORD len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1576 if (!(titleW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1577 MultiByteToWideChar( CP_ACP, 0, title, -1, titleW, len );
1580 if (!IS_INTRESOURCE(className))
1582 WCHAR classW[256];
1583 if (MultiByteToWideChar( CP_ACP, 0, className, -1, classW, sizeof(classW)/sizeof(WCHAR) ))
1584 hwnd = FindWindowExW( parent, child, classW, titleW );
1586 else
1588 hwnd = FindWindowExW( parent, child, (LPCWSTR)className, titleW );
1591 HeapFree( GetProcessHeap(), 0, titleW );
1592 return hwnd;
1596 /***********************************************************************
1597 * FindWindowW (USER32.@)
1599 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1601 return FindWindowExW( 0, 0, className, title );
1605 /**********************************************************************
1606 * GetDesktopWindow (USER32.@)
1608 HWND WINAPI GetDesktopWindow(void)
1610 struct user_thread_info *thread_info = get_user_thread_info();
1612 if (thread_info->desktop) return thread_info->desktop;
1614 SERVER_START_REQ( get_desktop_window )
1616 req->force = 0;
1617 if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1619 SERVER_END_REQ;
1621 if (!thread_info->desktop)
1623 USEROBJECTFLAGS flags;
1624 if (!GetUserObjectInformationW( GetProcessWindowStation(), UOI_FLAGS, &flags,
1625 sizeof(flags), NULL ) || (flags.dwFlags & WSF_VISIBLE))
1627 static const WCHAR command_line[] = {'\\','e','x','p','l','o','r','e','r','.','e','x','e',' ','/','d','e','s','k','t','o','p',0};
1628 STARTUPINFOW si;
1629 PROCESS_INFORMATION pi;
1630 WCHAR cmdline[MAX_PATH + sizeof(command_line)/sizeof(WCHAR)];
1632 memset( &si, 0, sizeof(si) );
1633 si.cb = sizeof(si);
1634 si.dwFlags = STARTF_USESTDHANDLES;
1635 si.hStdInput = 0;
1636 si.hStdOutput = 0;
1637 si.hStdError = GetStdHandle( STD_ERROR_HANDLE );
1639 GetSystemDirectoryW( cmdline, MAX_PATH );
1640 lstrcatW( cmdline, command_line );
1641 if (CreateProcessW( NULL, cmdline, NULL, NULL, FALSE, DETACHED_PROCESS,
1642 NULL, NULL, &si, &pi ))
1644 TRACE( "started explorer pid %04x tid %04x\n", pi.dwProcessId, pi.dwThreadId );
1645 WaitForInputIdle( pi.hProcess, 10000 );
1646 CloseHandle( pi.hThread );
1647 CloseHandle( pi.hProcess );
1649 else WARN( "failed to start explorer, err %d\n", GetLastError() );
1651 else TRACE( "not starting explorer since winstation is not visible\n" );
1653 SERVER_START_REQ( get_desktop_window )
1655 req->force = 1;
1656 if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1658 SERVER_END_REQ;
1661 if (!thread_info->desktop || !USER_Driver->pCreateDesktopWindow( thread_info->desktop ))
1662 ERR( "failed to create desktop window\n" );
1664 return thread_info->desktop;
1668 /*******************************************************************
1669 * EnableWindow (USER32.@)
1671 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1673 BOOL retvalue;
1674 HWND full_handle;
1676 if (is_broadcast(hwnd))
1678 SetLastError( ERROR_INVALID_PARAMETER );
1679 return FALSE;
1682 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1683 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1685 hwnd = full_handle;
1687 TRACE("( %p, %d )\n", hwnd, enable);
1689 retvalue = !IsWindowEnabled( hwnd );
1691 if (enable && retvalue)
1693 WIN_SetStyle( hwnd, 0, WS_DISABLED );
1694 SendMessageW( hwnd, WM_ENABLE, TRUE, 0 );
1696 else if (!enable && !retvalue)
1698 HWND capture_wnd;
1700 SendMessageW( hwnd, WM_CANCELMODE, 0, 0);
1702 WIN_SetStyle( hwnd, WS_DISABLED, 0 );
1704 if (hwnd == GetFocus())
1705 SetFocus( 0 ); /* A disabled window can't have the focus */
1707 capture_wnd = GetCapture();
1708 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1709 ReleaseCapture(); /* A disabled window can't capture the mouse */
1711 SendMessageW( hwnd, WM_ENABLE, FALSE, 0 );
1713 return retvalue;
1717 /***********************************************************************
1718 * IsWindowEnabled (USER32.@)
1720 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1722 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1726 /***********************************************************************
1727 * IsWindowUnicode (USER32.@)
1729 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1731 WND * wndPtr;
1732 BOOL retvalue = FALSE;
1734 if (!(wndPtr = WIN_GetPtr(hwnd))) return FALSE;
1736 if (wndPtr == WND_DESKTOP) return TRUE;
1738 if (wndPtr != WND_OTHER_PROCESS)
1740 retvalue = (wndPtr->flags & WIN_ISUNICODE) != 0;
1741 WIN_ReleasePtr( wndPtr );
1743 else
1745 SERVER_START_REQ( get_window_info )
1747 req->handle = hwnd;
1748 if (!wine_server_call_err( req )) retvalue = reply->is_unicode;
1750 SERVER_END_REQ;
1752 return retvalue;
1756 /**********************************************************************
1757 * WIN_GetWindowLong
1759 * Helper function for GetWindowLong().
1761 static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, UINT size, BOOL unicode )
1763 LONG_PTR retvalue = 0;
1764 WND *wndPtr;
1766 if (offset == GWLP_HWNDPARENT)
1768 HWND parent = GetAncestor( hwnd, GA_PARENT );
1769 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1770 return (ULONG_PTR)parent;
1773 if (!(wndPtr = WIN_GetPtr( hwnd )))
1775 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1776 return 0;
1779 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1781 if (offset == GWLP_WNDPROC)
1783 SetLastError( ERROR_ACCESS_DENIED );
1784 return 0;
1786 SERVER_START_REQ( set_window_info )
1788 req->handle = hwnd;
1789 req->flags = 0; /* don't set anything, just retrieve */
1790 req->extra_offset = (offset >= 0) ? offset : -1;
1791 req->extra_size = (offset >= 0) ? size : 0;
1792 if (!wine_server_call_err( req ))
1794 switch(offset)
1796 case GWL_STYLE: retvalue = reply->old_style; break;
1797 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1798 case GWLP_ID: retvalue = reply->old_id; break;
1799 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1800 case GWLP_USERDATA: retvalue = reply->old_user_data; break;
1801 default:
1802 if (offset >= 0) retvalue = get_win_data( &reply->old_extra_value, size );
1803 else SetLastError( ERROR_INVALID_INDEX );
1804 break;
1808 SERVER_END_REQ;
1809 return retvalue;
1812 /* now we have a valid wndPtr */
1814 if (offset >= 0)
1816 if (offset > (int)(wndPtr->cbWndExtra - size))
1818 WARN("Invalid offset %d\n", offset );
1819 WIN_ReleasePtr( wndPtr );
1820 SetLastError( ERROR_INVALID_INDEX );
1821 return 0;
1823 retvalue = get_win_data( (char *)wndPtr->wExtra + offset, size );
1825 /* Special case for dialog window procedure */
1826 if ((offset == DWLP_DLGPROC) && (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG))
1827 retvalue = (LONG_PTR)WINPROC_GetProc( (WNDPROC)retvalue, unicode );
1828 WIN_ReleasePtr( wndPtr );
1829 return retvalue;
1832 switch(offset)
1834 case GWLP_USERDATA: retvalue = wndPtr->userdata; break;
1835 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1836 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1837 case GWLP_ID: retvalue = wndPtr->wIDmenu; break;
1838 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wndPtr->hInstance; break;
1839 case GWLP_WNDPROC:
1840 /* This looks like a hack only for the edit control (see tests). This makes these controls
1841 * more tolerant to A/W mismatches. The lack of W->A->W conversion for such a mismatch suggests
1842 * that the hack is in GetWindowLongPtr[AW], not in winprocs.
1844 if (wndPtr->winproc == EDIT_winproc_handle && (!unicode != !(wndPtr->flags & WIN_ISUNICODE)))
1845 retvalue = (ULONG_PTR)wndPtr->winproc;
1846 else
1847 retvalue = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, unicode );
1848 break;
1849 default:
1850 WARN("Unknown offset %d\n", offset );
1851 SetLastError( ERROR_INVALID_INDEX );
1852 break;
1854 WIN_ReleasePtr(wndPtr);
1855 return retvalue;
1859 /**********************************************************************
1860 * WIN_SetWindowLong
1862 * Helper function for SetWindowLong().
1864 * 0 is the failure code. However, in the case of failure SetLastError
1865 * must be set to distinguish between a 0 return value and a failure.
1867 LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, UINT size, LONG_PTR newval, BOOL unicode )
1869 STYLESTRUCT style;
1870 BOOL ok;
1871 LONG_PTR retval = 0;
1872 WND *wndPtr;
1874 TRACE( "%p %d %lx %c\n", hwnd, offset, newval, unicode ? 'W' : 'A' );
1876 if (is_broadcast(hwnd))
1878 SetLastError( ERROR_INVALID_PARAMETER );
1879 return FALSE;
1882 if (!(wndPtr = WIN_GetPtr( hwnd )))
1884 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1885 return 0;
1887 if (wndPtr == WND_DESKTOP)
1889 /* can't change anything on the desktop window */
1890 SetLastError( ERROR_ACCESS_DENIED );
1891 return 0;
1893 if (wndPtr == WND_OTHER_PROCESS)
1895 if (offset == GWLP_WNDPROC)
1897 SetLastError( ERROR_ACCESS_DENIED );
1898 return 0;
1900 if (offset > 32767 || offset < -32767)
1902 SetLastError( ERROR_INVALID_INDEX );
1903 return 0;
1905 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, MAKEWPARAM( offset, size ), newval );
1908 /* first some special cases */
1909 switch( offset )
1911 case GWL_STYLE:
1912 case GWL_EXSTYLE:
1913 style.styleOld =
1914 offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
1915 style.styleNew = newval;
1916 WIN_ReleasePtr( wndPtr );
1917 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
1918 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
1919 newval = style.styleNew;
1920 break;
1921 case GWLP_HWNDPARENT:
1922 if (wndPtr->parent == GetDesktopWindow())
1924 WIN_ReleasePtr( wndPtr );
1925 return (ULONG_PTR)WIN_SetOwner( hwnd, (HWND)newval );
1927 else
1929 WIN_ReleasePtr( wndPtr );
1930 return (ULONG_PTR)SetParent( hwnd, (HWND)newval );
1932 case GWLP_WNDPROC:
1934 WNDPROC proc;
1935 UINT old_flags = wndPtr->flags;
1936 retval = WIN_GetWindowLong( hwnd, offset, size, unicode );
1937 if (unicode) proc = WINPROC_AllocProc( NULL, (WNDPROC)newval );
1938 else proc = WINPROC_AllocProc( (WNDPROC)newval, NULL );
1939 if (proc) wndPtr->winproc = proc;
1940 if (WINPROC_IsUnicode( proc, unicode )) wndPtr->flags |= WIN_ISUNICODE;
1941 else wndPtr->flags &= ~WIN_ISUNICODE;
1942 if (!((old_flags ^ wndPtr->flags) & WIN_ISUNICODE))
1944 WIN_ReleasePtr( wndPtr );
1945 return retval;
1947 /* update is_unicode flag on the server side */
1948 break;
1950 case GWLP_ID:
1951 case GWLP_HINSTANCE:
1952 case GWLP_USERDATA:
1953 break;
1954 case DWLP_DLGPROC:
1955 if ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
1956 (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG))
1958 WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWLP_DLGPROC);
1959 retval = (ULONG_PTR)WINPROC_GetProc( *ptr, unicode );
1960 if (unicode) *ptr = WINPROC_AllocProc( NULL, (WNDPROC)newval );
1961 else *ptr = WINPROC_AllocProc( (WNDPROC)newval, NULL );
1962 WIN_ReleasePtr( wndPtr );
1963 return retval;
1965 /* fall through */
1966 default:
1967 if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - size))
1969 WARN("Invalid offset %d\n", offset );
1970 WIN_ReleasePtr( wndPtr );
1971 SetLastError( ERROR_INVALID_INDEX );
1972 return 0;
1974 else if (get_win_data( (char *)wndPtr->wExtra + offset, size ) == newval)
1976 /* already set to the same value */
1977 WIN_ReleasePtr( wndPtr );
1978 return newval;
1980 break;
1983 SERVER_START_REQ( set_window_info )
1985 req->handle = hwnd;
1986 req->extra_offset = -1;
1987 switch(offset)
1989 case GWL_STYLE:
1990 req->flags = SET_WIN_STYLE;
1991 req->style = newval;
1992 break;
1993 case GWL_EXSTYLE:
1994 req->flags = SET_WIN_EXSTYLE;
1995 /* WS_EX_TOPMOST can only be changed through SetWindowPos */
1996 newval = (newval & ~WS_EX_TOPMOST) | (wndPtr->dwExStyle & WS_EX_TOPMOST);
1997 req->ex_style = newval;
1998 break;
1999 case GWLP_ID:
2000 req->flags = SET_WIN_ID;
2001 req->id = newval;
2002 break;
2003 case GWLP_HINSTANCE:
2004 req->flags = SET_WIN_INSTANCE;
2005 req->instance = (void *)newval;
2006 break;
2007 case GWLP_WNDPROC:
2008 req->flags = SET_WIN_UNICODE;
2009 req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
2010 break;
2011 case GWLP_USERDATA:
2012 req->flags = SET_WIN_USERDATA;
2013 req->user_data = newval;
2014 break;
2015 default:
2016 req->flags = SET_WIN_EXTRA;
2017 req->extra_offset = offset;
2018 req->extra_size = size;
2019 set_win_data( &req->extra_value, newval, size );
2021 if ((ok = !wine_server_call_err( req )))
2023 switch(offset)
2025 case GWL_STYLE:
2026 wndPtr->dwStyle = newval;
2027 retval = reply->old_style;
2028 break;
2029 case GWL_EXSTYLE:
2030 wndPtr->dwExStyle = newval;
2031 retval = reply->old_ex_style;
2032 break;
2033 case GWLP_ID:
2034 wndPtr->wIDmenu = newval;
2035 retval = reply->old_id;
2036 break;
2037 case GWLP_HINSTANCE:
2038 wndPtr->hInstance = (HINSTANCE)newval;
2039 retval = (ULONG_PTR)reply->old_instance;
2040 break;
2041 case GWLP_WNDPROC:
2042 break;
2043 case GWLP_USERDATA:
2044 wndPtr->userdata = newval;
2045 retval = reply->old_user_data;
2046 break;
2047 default:
2048 retval = get_win_data( (char *)wndPtr->wExtra + offset, size );
2049 set_win_data( (char *)wndPtr->wExtra + offset, newval, size );
2050 break;
2054 SERVER_END_REQ;
2055 WIN_ReleasePtr( wndPtr );
2057 if (!ok) return 0;
2059 if (offset == GWL_STYLE) USER_Driver->pSetWindowStyle( hwnd, retval );
2061 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2062 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2064 return retval;
2068 /**********************************************************************
2069 * GetWindowLong (USER.135)
2071 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2073 WND *wndPtr;
2074 LONG_PTR retvalue;
2075 BOOL is_winproc = (offset == GWLP_WNDPROC);
2077 if (offset >= 0)
2079 if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2081 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2082 return 0;
2084 if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2086 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
2089 * Some programs try to access last element from 16 bit
2090 * code using illegal offset value. Hopefully this is
2091 * what those programs really expect.
2093 if (wndPtr->cbWndExtra >= 4 && offset == wndPtr->cbWndExtra - sizeof(WORD))
2095 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
2096 ERR( "- replaced invalid offset %d with %d\n", offset, offset2 );
2097 offset = offset2;
2099 else
2101 WARN("Invalid offset %d\n", offset );
2102 WIN_ReleasePtr( wndPtr );
2103 SetLastError( ERROR_INVALID_INDEX );
2104 return 0;
2107 is_winproc = ((offset == DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG));
2108 WIN_ReleasePtr( wndPtr );
2111 retvalue = GetWindowLongA( WIN_Handle32(hwnd), offset );
2112 if (is_winproc) retvalue = (LONG_PTR)WINPROC_GetProc16( (WNDPROC)retvalue, FALSE );
2113 return retvalue;
2117 /**********************************************************************
2118 * GetWindowWord (USER32.@)
2120 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
2122 switch(offset)
2124 case GWLP_ID:
2125 case GWLP_HINSTANCE:
2126 case GWLP_HWNDPARENT:
2127 break;
2128 default:
2129 if (offset < 0)
2131 WARN("Invalid offset %d\n", offset );
2132 SetLastError( ERROR_INVALID_INDEX );
2133 return 0;
2135 break;
2137 return WIN_GetWindowLong( hwnd, offset, sizeof(WORD), FALSE );
2141 /**********************************************************************
2142 * GetWindowLongA (USER32.@)
2144 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2146 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), FALSE );
2150 /**********************************************************************
2151 * GetWindowLongW (USER32.@)
2153 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2155 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), TRUE );
2159 /**********************************************************************
2160 * SetWindowLong (USER.136)
2162 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2164 WND *wndPtr;
2165 BOOL is_winproc = (offset == GWLP_WNDPROC);
2167 if (offset == DWLP_DLGPROC)
2169 if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2171 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2172 return 0;
2174 if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2176 is_winproc = ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
2177 (wndPtr->flags & WIN_ISDIALOG));
2178 WIN_ReleasePtr( wndPtr );
2182 if (is_winproc)
2184 WNDPROC new_proc = WINPROC_AllocProc16( (WNDPROC16)newval );
2185 WNDPROC old_proc = (WNDPROC)SetWindowLongPtrA( WIN_Handle32(hwnd), offset, (LONG_PTR)new_proc );
2186 return (LONG)WINPROC_GetProc16( old_proc, FALSE );
2188 else return SetWindowLongA( WIN_Handle32(hwnd), offset, newval );
2192 /**********************************************************************
2193 * SetWindowWord (USER32.@)
2195 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
2197 switch(offset)
2199 case GWLP_ID:
2200 case GWLP_HINSTANCE:
2201 case GWLP_HWNDPARENT:
2202 break;
2203 default:
2204 if (offset < 0)
2206 WARN("Invalid offset %d\n", offset );
2207 SetLastError( ERROR_INVALID_INDEX );
2208 return 0;
2210 break;
2212 return WIN_SetWindowLong( hwnd, offset, sizeof(WORD), newval, FALSE );
2216 /**********************************************************************
2217 * SetWindowLongA (USER32.@)
2219 * See SetWindowLongW.
2221 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2223 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, FALSE );
2227 /**********************************************************************
2228 * SetWindowLongW (USER32.@) Set window attribute
2230 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2231 * value in a window's extra memory.
2233 * The _hwnd_ parameter specifies the window. is the handle to a
2234 * window that has extra memory. The _newval_ parameter contains the
2235 * new attribute or extra memory value. If positive, the _offset_
2236 * parameter is the byte-addressed location in the window's extra
2237 * memory to set. If negative, _offset_ specifies the window
2238 * attribute to set, and should be one of the following values:
2240 * GWL_EXSTYLE The window's extended window style
2242 * GWL_STYLE The window's window style.
2244 * GWLP_WNDPROC Pointer to the window's window procedure.
2246 * GWLP_HINSTANCE The window's pplication instance handle.
2248 * GWLP_ID The window's identifier.
2250 * GWLP_USERDATA The window's user-specified data.
2252 * If the window is a dialog box, the _offset_ parameter can be one of
2253 * the following values:
2255 * DWLP_DLGPROC The address of the window's dialog box procedure.
2257 * DWLP_MSGRESULT The return value of a message
2258 * that the dialog box procedure processed.
2260 * DWLP_USER Application specific information.
2262 * RETURNS
2264 * If successful, returns the previous value located at _offset_. Otherwise,
2265 * returns 0.
2267 * NOTES
2269 * Extra memory for a window class is specified by a nonzero cbWndExtra
2270 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2271 * time of class creation.
2273 * Using GWL_WNDPROC to set a new window procedure effectively creates
2274 * a window subclass. Use CallWindowProc() in the new windows procedure
2275 * to pass messages to the superclass's window procedure.
2277 * The user data is reserved for use by the application which created
2278 * the window.
2280 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2281 * instead, call the EnableWindow() function to change the window's
2282 * disabled state.
2284 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2285 * SetParent() instead.
2287 * Win95:
2288 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2289 * it sends WM_STYLECHANGING before changing the settings
2290 * and WM_STYLECHANGED afterwards.
2291 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2293 LONG WINAPI SetWindowLongW(
2294 HWND hwnd, /* [in] window to alter */
2295 INT offset, /* [in] offset, in bytes, of location to alter */
2296 LONG newval /* [in] new value of location */
2298 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, TRUE );
2302 /*******************************************************************
2303 * GetWindowTextA (USER32.@)
2305 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2307 WCHAR *buffer;
2309 if (!lpString) return 0;
2311 if (WIN_IsCurrentProcess( hwnd ))
2312 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2314 /* when window belongs to other process, don't send a message */
2315 if (nMaxCount <= 0) return 0;
2316 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2317 get_server_window_text( hwnd, buffer, nMaxCount );
2318 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2319 lpString[nMaxCount-1] = 0;
2320 HeapFree( GetProcessHeap(), 0, buffer );
2321 return strlen(lpString);
2325 /*******************************************************************
2326 * InternalGetWindowText (USER32.@)
2328 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2330 WND *win;
2332 if (nMaxCount <= 0) return 0;
2333 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2334 if (win == WND_DESKTOP) lpString[0] = 0;
2335 else if (win != WND_OTHER_PROCESS)
2337 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2338 else lpString[0] = 0;
2339 WIN_ReleasePtr( win );
2341 else
2343 get_server_window_text( hwnd, lpString, nMaxCount );
2345 return strlenW(lpString);
2349 /*******************************************************************
2350 * GetWindowTextW (USER32.@)
2352 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2354 if (!lpString) return 0;
2356 if (WIN_IsCurrentProcess( hwnd ))
2357 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2359 /* when window belongs to other process, don't send a message */
2360 if (nMaxCount <= 0) return 0;
2361 get_server_window_text( hwnd, lpString, nMaxCount );
2362 return strlenW(lpString);
2366 /*******************************************************************
2367 * SetWindowTextA (USER32.@)
2368 * SetWindowText (USER32.@)
2370 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2372 if (is_broadcast(hwnd))
2374 SetLastError( ERROR_INVALID_PARAMETER );
2375 return FALSE;
2377 if (!WIN_IsCurrentProcess( hwnd ))
2378 WARN( "setting text %s of other process window %p should not use SendMessage\n",
2379 debugstr_a(lpString), hwnd );
2380 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2384 /*******************************************************************
2385 * SetWindowTextW (USER32.@)
2387 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2389 if (is_broadcast(hwnd))
2391 SetLastError( ERROR_INVALID_PARAMETER );
2392 return FALSE;
2394 if (!WIN_IsCurrentProcess( hwnd ))
2395 WARN( "setting text %s of other process window %p should not use SendMessage\n",
2396 debugstr_w(lpString), hwnd );
2397 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2401 /*******************************************************************
2402 * GetWindowTextLengthA (USER32.@)
2404 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2406 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2409 /*******************************************************************
2410 * GetWindowTextLengthW (USER32.@)
2412 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2414 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2418 /*******************************************************************
2419 * IsWindow (USER32.@)
2421 BOOL WINAPI IsWindow( HWND hwnd )
2423 WND *ptr;
2424 BOOL ret;
2426 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2427 if (ptr == WND_DESKTOP) return TRUE;
2429 if (ptr != WND_OTHER_PROCESS)
2431 WIN_ReleasePtr( ptr );
2432 return TRUE;
2435 /* check other processes */
2436 SERVER_START_REQ( get_window_info )
2438 req->handle = hwnd;
2439 ret = !wine_server_call_err( req );
2441 SERVER_END_REQ;
2442 return ret;
2446 /***********************************************************************
2447 * GetWindowThreadProcessId (USER32.@)
2449 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2451 WND *ptr;
2452 DWORD tid = 0;
2454 if (!(ptr = WIN_GetPtr( hwnd )))
2456 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2457 return 0;
2460 if (ptr != WND_OTHER_PROCESS && ptr != WND_DESKTOP)
2462 /* got a valid window */
2463 tid = ptr->tid;
2464 if (process) *process = GetCurrentProcessId();
2465 WIN_ReleasePtr( ptr );
2466 return tid;
2469 /* check other processes */
2470 SERVER_START_REQ( get_window_info )
2472 req->handle = hwnd;
2473 if (!wine_server_call_err( req ))
2475 tid = (DWORD)reply->tid;
2476 if (process) *process = (DWORD)reply->pid;
2479 SERVER_END_REQ;
2480 return tid;
2484 /*****************************************************************
2485 * GetParent (USER32.@)
2487 HWND WINAPI GetParent( HWND hwnd )
2489 WND *wndPtr;
2490 HWND retvalue = 0;
2492 if (!(wndPtr = WIN_GetPtr( hwnd )))
2494 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2495 return 0;
2497 if (wndPtr == WND_DESKTOP) return 0;
2498 if (wndPtr == WND_OTHER_PROCESS)
2500 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2501 if (style & (WS_POPUP | WS_CHILD))
2503 SERVER_START_REQ( get_window_tree )
2505 req->handle = hwnd;
2506 if (!wine_server_call_err( req ))
2508 if (style & WS_POPUP) retvalue = reply->owner;
2509 else if (style & WS_CHILD) retvalue = reply->parent;
2512 SERVER_END_REQ;
2515 else
2517 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2518 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2519 WIN_ReleasePtr( wndPtr );
2521 return retvalue;
2525 /*****************************************************************
2526 * GetAncestor (USER32.@)
2528 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2530 WND *win;
2531 HWND *list, ret = 0;
2533 switch(type)
2535 case GA_PARENT:
2536 if (!(win = WIN_GetPtr( hwnd )))
2538 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2539 return 0;
2541 if (win == WND_DESKTOP) return 0;
2542 if (win != WND_OTHER_PROCESS)
2544 ret = win->parent;
2545 WIN_ReleasePtr( win );
2547 else /* need to query the server */
2549 SERVER_START_REQ( get_window_tree )
2551 req->handle = hwnd;
2552 if (!wine_server_call_err( req )) ret = reply->parent;
2554 SERVER_END_REQ;
2556 break;
2558 case GA_ROOT:
2559 if (!(list = list_window_parents( hwnd ))) return 0;
2561 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2562 else
2564 int count = 2;
2565 while (list[count]) count++;
2566 ret = list[count - 2]; /* get the one before the desktop */
2568 HeapFree( GetProcessHeap(), 0, list );
2569 break;
2571 case GA_ROOTOWNER:
2572 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2573 for (;;)
2575 HWND parent = GetParent( ret );
2576 if (!parent) break;
2577 ret = parent;
2579 break;
2581 return ret;
2585 /*****************************************************************
2586 * SetParent (USER32.@)
2588 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2590 HWND full_handle;
2591 HWND old_parent = 0;
2592 BOOL was_visible;
2593 WND *wndPtr;
2594 BOOL ret;
2596 if (is_broadcast(hwnd) || is_broadcast(parent))
2598 SetLastError(ERROR_INVALID_PARAMETER);
2599 return 0;
2602 if (!parent) parent = GetDesktopWindow();
2603 else parent = WIN_GetFullHandle( parent );
2605 if (!IsWindow( parent ))
2607 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2608 return 0;
2611 /* Some applications try to set a child as a parent */
2612 if (IsChild(hwnd, parent))
2614 SetLastError( ERROR_INVALID_PARAMETER );
2615 return 0;
2618 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2619 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2621 /* Windows hides the window first, then shows it again
2622 * including the WM_SHOWWINDOW messages and all */
2623 was_visible = ShowWindow( hwnd, SW_HIDE );
2625 wndPtr = WIN_GetPtr( hwnd );
2626 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return 0;
2628 SERVER_START_REQ( set_parent )
2630 req->handle = hwnd;
2631 req->parent = parent;
2632 if ((ret = !wine_server_call( req )))
2634 old_parent = reply->old_parent;
2635 wndPtr->parent = parent = reply->full_parent;
2639 SERVER_END_REQ;
2640 WIN_ReleasePtr( wndPtr );
2641 if (!ret) return 0;
2643 USER_Driver->pSetParent( full_handle, parent, old_parent );
2645 /* SetParent additionally needs to make hwnd the topmost window
2646 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2647 WM_WINDOWPOSCHANGED notification messages.
2649 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0,
2650 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2651 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2652 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2654 return old_parent;
2658 /*******************************************************************
2659 * IsChild (USER32.@)
2661 BOOL WINAPI IsChild( HWND parent, HWND child )
2663 HWND *list = list_window_parents( child );
2664 int i;
2665 BOOL ret;
2667 if (!list) return FALSE;
2668 parent = WIN_GetFullHandle( parent );
2669 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2670 ret = list[i] && list[i+1];
2671 HeapFree( GetProcessHeap(), 0, list );
2672 return ret;
2676 /***********************************************************************
2677 * IsWindowVisible (USER32.@)
2679 BOOL WINAPI IsWindowVisible( HWND hwnd )
2681 HWND *list;
2682 BOOL retval = TRUE;
2683 int i;
2685 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2686 if (!(list = list_window_parents( hwnd ))) return TRUE;
2687 if (list[0] && list[1]) /* desktop window is considered always visible so we don't check it */
2689 for (i = 0; list[i+1]; i++)
2690 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2691 retval = !list[i+1];
2693 HeapFree( GetProcessHeap(), 0, list );
2694 return retval;
2698 /***********************************************************************
2699 * WIN_IsWindowDrawable
2701 * hwnd is drawable when it is visible, all parents are not
2702 * minimized, and it is itself not minimized unless we are
2703 * trying to draw its default class icon.
2705 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2707 HWND *list;
2708 BOOL retval = TRUE;
2709 int i;
2710 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2712 if (!(style & WS_VISIBLE)) return FALSE;
2713 if ((style & WS_MINIMIZE) && icon && GetClassLongPtrW( hwnd, GCLP_HICON )) return FALSE;
2715 if (!(list = list_window_parents( hwnd ))) return TRUE;
2716 if (list[0] && list[1]) /* desktop window is considered always visible so we don't check it */
2718 for (i = 0; list[i+1]; i++)
2719 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2720 break;
2721 retval = !list[i+1];
2723 HeapFree( GetProcessHeap(), 0, list );
2724 return retval;
2728 /*******************************************************************
2729 * GetTopWindow (USER32.@)
2731 HWND WINAPI GetTopWindow( HWND hwnd )
2733 if (!hwnd) hwnd = GetDesktopWindow();
2734 return GetWindow( hwnd, GW_CHILD );
2738 /*******************************************************************
2739 * GetWindow (USER32.@)
2741 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2743 HWND retval = 0;
2745 if (rel == GW_OWNER) /* this one may be available locally */
2747 WND *wndPtr = WIN_GetPtr( hwnd );
2748 if (!wndPtr)
2750 SetLastError( ERROR_INVALID_HANDLE );
2751 return 0;
2753 if (wndPtr == WND_DESKTOP) return 0;
2754 if (wndPtr != WND_OTHER_PROCESS)
2756 retval = wndPtr->owner;
2757 WIN_ReleasePtr( wndPtr );
2758 return retval;
2760 /* else fall through to server call */
2763 SERVER_START_REQ( get_window_tree )
2765 req->handle = hwnd;
2766 if (!wine_server_call_err( req ))
2768 switch(rel)
2770 case GW_HWNDFIRST:
2771 retval = reply->first_sibling;
2772 break;
2773 case GW_HWNDLAST:
2774 retval = reply->last_sibling;
2775 break;
2776 case GW_HWNDNEXT:
2777 retval = reply->next_sibling;
2778 break;
2779 case GW_HWNDPREV:
2780 retval = reply->prev_sibling;
2781 break;
2782 case GW_OWNER:
2783 retval = reply->owner;
2784 break;
2785 case GW_CHILD:
2786 retval = reply->first_child;
2787 break;
2791 SERVER_END_REQ;
2792 return retval;
2796 /*******************************************************************
2797 * ShowOwnedPopups (USER32.@)
2799 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2801 int count = 0;
2802 WND *pWnd;
2803 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2805 if (!win_array) return TRUE;
2807 while (win_array[count]) count++;
2808 while (--count >= 0)
2810 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2811 if (!(pWnd = WIN_GetPtr( win_array[count] ))) continue;
2812 if (pWnd == WND_OTHER_PROCESS) continue;
2813 if (fShow)
2815 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2817 WIN_ReleasePtr( pWnd );
2818 /* In Windows, ShowOwnedPopups(TRUE) generates
2819 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2820 * regardless of the state of the owner
2822 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_SHOWNORMAL, SW_PARENTOPENING);
2823 continue;
2826 else
2828 if (pWnd->dwStyle & WS_VISIBLE)
2830 WIN_ReleasePtr( pWnd );
2831 /* In Windows, ShowOwnedPopups(FALSE) generates
2832 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2833 * regardless of the state of the owner
2835 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2836 continue;
2839 WIN_ReleasePtr( pWnd );
2841 HeapFree( GetProcessHeap(), 0, win_array );
2842 return TRUE;
2846 /*******************************************************************
2847 * GetLastActivePopup (USER32.@)
2849 HWND WINAPI GetLastActivePopup( HWND hwnd )
2851 HWND retval = hwnd;
2853 SERVER_START_REQ( get_window_info )
2855 req->handle = hwnd;
2856 if (!wine_server_call_err( req )) retval = reply->last_active;
2858 SERVER_END_REQ;
2859 return retval;
2863 /*******************************************************************
2864 * WIN_ListChildren
2866 * Build an array of the children of a given window. The array must be
2867 * freed with HeapFree. Returns NULL when no windows are found.
2869 HWND *WIN_ListChildren( HWND hwnd )
2871 return list_window_children( 0, hwnd, NULL, 0 );
2875 /*******************************************************************
2876 * EnumWindows (USER32.@)
2878 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2880 HWND *list;
2881 BOOL ret = TRUE;
2882 int i;
2884 USER_CheckNotLock();
2886 /* We have to build a list of all windows first, to avoid */
2887 /* unpleasant side-effects, for instance if the callback */
2888 /* function changes the Z-order of the windows. */
2890 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2892 /* Now call the callback function for every window */
2894 for (i = 0; list[i]; i++)
2896 /* Make sure that the window still exists */
2897 if (!IsWindow( list[i] )) continue;
2898 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2900 HeapFree( GetProcessHeap(), 0, list );
2901 return ret;
2905 /**********************************************************************
2906 * EnumThreadWindows (USER32.@)
2908 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2910 HWND *list;
2911 int i;
2913 USER_CheckNotLock();
2915 if (!(list = list_window_children( 0, GetDesktopWindow(), NULL, id ))) return TRUE;
2917 /* Now call the callback function for every window */
2919 for (i = 0; list[i]; i++)
2920 if (!func( list[i], lParam )) break;
2921 HeapFree( GetProcessHeap(), 0, list );
2922 return TRUE;
2926 /***********************************************************************
2927 * EnumDesktopWindows (USER32.@)
2929 BOOL WINAPI EnumDesktopWindows( HDESK desktop, WNDENUMPROC func, LPARAM lparam )
2931 HWND *list;
2932 int i;
2934 USER_CheckNotLock();
2936 if (!(list = list_window_children( desktop, 0, NULL, 0 ))) return TRUE;
2938 for (i = 0; list[i]; i++)
2939 if (!func( list[i], lparam )) break;
2940 HeapFree( GetProcessHeap(), 0, list );
2941 return TRUE;
2945 /**********************************************************************
2946 * WIN_EnumChildWindows
2948 * Helper function for EnumChildWindows().
2950 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2952 HWND *childList;
2953 BOOL ret = FALSE;
2955 for ( ; *list; list++)
2957 /* Make sure that the window still exists */
2958 if (!IsWindow( *list )) continue;
2959 /* Build children list first */
2960 childList = WIN_ListChildren( *list );
2962 ret = func( *list, lParam );
2964 if (childList)
2966 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2967 HeapFree( GetProcessHeap(), 0, childList );
2969 if (!ret) return FALSE;
2971 return TRUE;
2975 /**********************************************************************
2976 * EnumChildWindows (USER32.@)
2978 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2980 HWND *list;
2981 BOOL ret;
2983 USER_CheckNotLock();
2985 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2986 ret = WIN_EnumChildWindows( list, func, lParam );
2987 HeapFree( GetProcessHeap(), 0, list );
2988 return ret;
2992 /*******************************************************************
2993 * AnyPopup (USER.52)
2995 BOOL16 WINAPI AnyPopup16(void)
2997 return AnyPopup();
3001 /*******************************************************************
3002 * AnyPopup (USER32.@)
3004 BOOL WINAPI AnyPopup(void)
3006 int i;
3007 BOOL retvalue;
3008 HWND *list = WIN_ListChildren( GetDesktopWindow() );
3010 if (!list) return FALSE;
3011 for (i = 0; list[i]; i++)
3013 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
3015 retvalue = (list[i] != 0);
3016 HeapFree( GetProcessHeap(), 0, list );
3017 return retvalue;
3021 /*******************************************************************
3022 * FlashWindow (USER32.@)
3024 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3026 WND *wndPtr;
3028 TRACE("%p\n", hWnd);
3030 if (IsIconic( hWnd ))
3032 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3034 wndPtr = WIN_GetPtr(hWnd);
3035 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
3036 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3038 wndPtr->flags |= WIN_NCACTIVATED;
3040 else
3042 wndPtr->flags &= ~WIN_NCACTIVATED;
3044 WIN_ReleasePtr( wndPtr );
3045 return TRUE;
3047 else
3049 WPARAM wparam;
3051 wndPtr = WIN_GetPtr(hWnd);
3052 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
3053 hWnd = wndPtr->hwndSelf; /* make it a full handle */
3055 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3056 else wparam = (hWnd == GetForegroundWindow());
3058 WIN_ReleasePtr( wndPtr );
3059 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3060 return wparam;
3064 /*******************************************************************
3065 * FlashWindowEx (USER32.@)
3067 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
3069 FIXME("%p\n", pfwi);
3070 return TRUE;
3073 /*******************************************************************
3074 * GetWindowContextHelpId (USER32.@)
3076 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3078 DWORD retval;
3079 WND *wnd = WIN_GetPtr( hwnd );
3080 if (!wnd || wnd == WND_DESKTOP) return 0;
3081 if (wnd == WND_OTHER_PROCESS)
3083 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3084 return 0;
3086 retval = wnd->helpContext;
3087 WIN_ReleasePtr( wnd );
3088 return retval;
3092 /*******************************************************************
3093 * SetWindowContextHelpId (USER32.@)
3095 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3097 WND *wnd = WIN_GetPtr( hwnd );
3098 if (!wnd || wnd == WND_DESKTOP) return FALSE;
3099 if (wnd == WND_OTHER_PROCESS)
3101 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3102 return 0;
3104 wnd->helpContext = id;
3105 WIN_ReleasePtr( wnd );
3106 return TRUE;
3110 /*******************************************************************
3111 * DragDetect (USER32.@)
3113 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3115 MSG msg;
3116 RECT rect;
3117 WORD wDragWidth = GetSystemMetrics(SM_CXDRAG);
3118 WORD wDragHeight= GetSystemMetrics(SM_CYDRAG);
3120 rect.left = pt.x - wDragWidth;
3121 rect.right = pt.x + wDragWidth;
3123 rect.top = pt.y - wDragHeight;
3124 rect.bottom = pt.y + wDragHeight;
3126 SetCapture(hWnd);
3128 while(1)
3130 while (PeekMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ))
3132 if( msg.message == WM_LBUTTONUP )
3134 ReleaseCapture();
3135 return 0;
3137 if( msg.message == WM_MOUSEMOVE )
3139 POINT tmp;
3140 tmp.x = (short)LOWORD(msg.lParam);
3141 tmp.y = (short)HIWORD(msg.lParam);
3142 if( !PtInRect( &rect, tmp ))
3144 ReleaseCapture();
3145 return 1;
3149 WaitMessage();
3151 return 0;
3154 /******************************************************************************
3155 * GetWindowModuleFileNameA (USER32.@)
3157 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3159 FIXME("GetWindowModuleFileNameA(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3160 hwnd, lpszFileName, cchFileNameMax);
3161 return 0;
3164 /******************************************************************************
3165 * GetWindowModuleFileNameW (USER32.@)
3167 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR lpszFileName, UINT cchFileNameMax)
3169 FIXME("GetWindowModuleFileNameW(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3170 hwnd, lpszFileName, cchFileNameMax);
3171 return 0;
3174 /******************************************************************************
3175 * GetWindowInfo (USER32.@)
3177 * Note: tests show that Windows doesn't check cbSize of the structure.
3179 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3181 if (!pwi) return FALSE;
3182 if (!IsWindow(hwnd)) return FALSE;
3184 GetWindowRect(hwnd, &pwi->rcWindow);
3185 GetClientRect(hwnd, &pwi->rcClient);
3186 /* translate to screen coordinates */
3187 MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3189 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3190 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3191 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3193 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3194 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3196 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3197 pwi->wCreatorVersion = 0x0400;
3199 return TRUE;
3202 /******************************************************************************
3203 * SwitchDesktop (USER32.@)
3205 * NOTES: Sets the current input or interactive desktop.
3207 BOOL WINAPI SwitchDesktop( HDESK hDesktop)
3209 FIXME("SwitchDesktop(hwnd %p) stub!\n", hDesktop);
3210 return TRUE;
3213 /*****************************************************************************
3214 * SetLayeredWindowAttributes (USER32.@)
3216 BOOL WINAPI SetLayeredWindowAttributes( HWND hWnd, COLORREF rgbKey,
3217 BYTE bAlpha, DWORD dwFlags )
3219 FIXME("(%p,0x%.8x,%d,%d): stub!\n", hWnd, rgbKey, bAlpha, dwFlags);
3220 return TRUE;
3223 /*****************************************************************************
3224 * GetLayeredWindowAttributes (USER32.@)
3226 BOOL WINAPI GetLayeredWindowAttributes( HWND hWnd, COLORREF *prgbKey,
3227 BYTE *pbAlpha, DWORD *pdwFlags )
3229 FIXME("(%p,%p,%p,%p): stub!\n", hWnd, prgbKey, pbAlpha, pdwFlags);
3230 return FALSE;
3233 /*****************************************************************************
3234 * UpdateLayeredWindow (USER32.@)
3236 BOOL WINAPI UpdateLayeredWindow( HWND hwnd, HDC hdcDst, POINT *pptDst, SIZE *psize,
3237 HDC hdcSrc, POINT *pptSrc, COLORREF crKey, BLENDFUNCTION *pblend,
3238 DWORD dwFlags)
3240 static int once;
3241 if (!once)
3243 once = 1;
3244 FIXME("(%p,%p,%p,%p,%p,%p,0x%08x,%p,%d): stub!\n",
3245 hwnd, hdcDst, pptDst, psize, hdcSrc, pptSrc, crKey, pblend, dwFlags);
3247 return 0;
3250 /* 64bit versions */
3252 #ifdef GetWindowLongPtrW
3253 #undef GetWindowLongPtrW
3254 #endif
3256 #ifdef GetWindowLongPtrA
3257 #undef GetWindowLongPtrA
3258 #endif
3260 #ifdef SetWindowLongPtrW
3261 #undef SetWindowLongPtrW
3262 #endif
3264 #ifdef SetWindowLongPtrA
3265 #undef SetWindowLongPtrA
3266 #endif
3268 /*****************************************************************************
3269 * GetWindowLongPtrW (USER32.@)
3271 LONG_PTR WINAPI GetWindowLongPtrW( HWND hwnd, INT offset )
3273 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), TRUE );
3276 /*****************************************************************************
3277 * GetWindowLongPtrA (USER32.@)
3279 LONG_PTR WINAPI GetWindowLongPtrA( HWND hwnd, INT offset )
3281 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), FALSE );
3284 /*****************************************************************************
3285 * SetWindowLongPtrW (USER32.@)
3287 LONG_PTR WINAPI SetWindowLongPtrW( HWND hwnd, INT offset, LONG_PTR newval )
3289 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, TRUE );
3292 /*****************************************************************************
3293 * SetWindowLongPtrA (USER32.@)
3295 LONG_PTR WINAPI SetWindowLongPtrA( HWND hwnd, INT offset, LONG_PTR newval )
3297 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, FALSE );