Add a test for creation of a maximized child window.
[wine.git] / windows / win.c
bloba99288a7fb65df520799ff7340b57d0bf5869c5f
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.h"
37 #include "dce.h"
38 #include "controls.h"
39 #include "cursoricon.h"
40 #include "message.h"
41 #include "winpos.h"
42 #include "winerror.h"
43 #include "wine/debug.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(win);
46 WINE_DECLARE_DEBUG_CHANNEL(msg);
48 #define NB_USER_HANDLES (LAST_USER_HANDLE - FIRST_USER_HANDLE + 1)
50 /**********************************************************************/
52 /* Desktop window */
53 static WND *pWndDesktop = NULL;
55 static WORD wDragWidth = 4;
56 static WORD wDragHeight= 3;
58 static void *user_handles[NB_USER_HANDLES];
60 /***********************************************************************
61 * create_window_handle
63 * Create a window handle with the server.
65 static WND *create_window_handle( HWND parent, HWND owner, ATOM atom,
66 HINSTANCE instance, WINDOWPROCTYPE type )
68 WORD index;
69 WND *win;
70 struct tagCLASS *class = NULL;
71 user_handle_t handle = 0;
72 int extra_bytes = 0;
74 /* if 16-bit instance, map to module handle */
75 if (instance && !HIWORD(instance))
76 instance = HINSTANCE_32(GetExePtr(HINSTANCE_16(instance)));
78 SERVER_START_REQ( create_window )
80 req->parent = parent;
81 req->owner = owner;
82 req->atom = atom;
83 req->instance = instance;
84 if (!wine_server_call_err( req ))
86 handle = reply->handle;
87 extra_bytes = reply->extra;
88 class = reply->class_ptr;
91 SERVER_END_REQ;
93 if (!handle)
95 WARN( "error %ld creating window\n", GetLastError() );
96 return NULL;
99 if (!(win = HeapAlloc( GetProcessHeap(), 0, sizeof(WND) + extra_bytes - sizeof(win->wExtra) )))
101 SERVER_START_REQ( destroy_window )
103 req->handle = handle;
104 wine_server_call( req );
106 SERVER_END_REQ;
107 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
108 return NULL;
111 USER_Lock();
113 index = LOWORD(handle) - FIRST_USER_HANDLE;
114 assert( index < NB_USER_HANDLES );
115 user_handles[index] = win;
116 win->hwndSelf = handle;
117 win->dwMagic = WND_MAGIC;
118 win->irefCount = 1;
119 win->cbWndExtra = extra_bytes;
120 memset( win->wExtra, 0, extra_bytes );
121 CLASS_AddWindow( class, win, type );
122 return win;
126 /***********************************************************************
127 * free_window_handle
129 * Free a window handle.
131 static WND *free_window_handle( HWND hwnd )
133 WND *ptr;
134 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
136 if (index >= NB_USER_HANDLES) return NULL;
137 USER_Lock();
138 if ((ptr = user_handles[index]))
140 SERVER_START_REQ( destroy_window )
142 req->handle = hwnd;
143 if (!wine_server_call_err( req ))
144 user_handles[index] = NULL;
145 else
146 ptr = NULL;
148 SERVER_END_REQ;
150 USER_Unlock();
151 if (ptr) HeapFree( GetProcessHeap(), 0, ptr );
152 return ptr;
156 /*******************************************************************
157 * list_window_children
159 * Build an array of the children of a given window. The array must be
160 * freed with HeapFree. Returns NULL when no windows are found.
162 static HWND *list_window_children( HWND hwnd, ATOM atom, DWORD tid )
164 HWND *list;
165 int size = 32;
167 for (;;)
169 int count = 0;
171 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
173 SERVER_START_REQ( get_window_children )
175 req->parent = hwnd;
176 req->atom = atom;
177 req->tid = tid;
178 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
179 if (!wine_server_call( req )) count = reply->count;
181 SERVER_END_REQ;
182 if (count && count < size)
184 list[count] = 0;
185 return list;
187 HeapFree( GetProcessHeap(), 0, list );
188 if (!count) break;
189 size = count + 1; /* restart with a large enough buffer */
191 return NULL;
195 /*******************************************************************
196 * send_parent_notify
198 static void send_parent_notify( HWND hwnd, UINT msg )
200 if ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_CHILD | WS_POPUP)) == WS_CHILD &&
201 !(GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY))
202 SendMessageW( GetParent(hwnd), WM_PARENTNOTIFY,
203 MAKEWPARAM( msg, GetWindowLongW( hwnd, GWL_ID )), (LPARAM)hwnd );
207 /*******************************************************************
208 * get_server_window_text
210 * Retrieve the window text from the server.
212 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
214 size_t len = 0;
216 SERVER_START_REQ( get_window_text )
218 req->handle = hwnd;
219 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
220 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
222 SERVER_END_REQ;
223 text[len / sizeof(WCHAR)] = 0;
227 /***********************************************************************
228 * WIN_GetPtr
230 * Return a pointer to the WND structure if local to the process,
231 * or WND_OTHER_PROCESS if handle may be valid in other process.
232 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
234 WND *WIN_GetPtr( HWND hwnd )
236 WND * ptr;
237 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
239 if (index >= NB_USER_HANDLES) return NULL;
241 USER_Lock();
242 if ((ptr = user_handles[index]))
244 if (ptr->dwMagic == WND_MAGIC && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
245 return ptr;
246 ptr = NULL;
248 else ptr = WND_OTHER_PROCESS;
249 USER_Unlock();
250 return ptr;
254 /***********************************************************************
255 * WIN_IsCurrentProcess
257 * Check whether a given window belongs to the current process (and return the full handle).
259 HWND WIN_IsCurrentProcess( HWND hwnd )
261 WND *ptr;
262 HWND ret;
264 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS) return 0;
265 ret = ptr->hwndSelf;
266 WIN_ReleasePtr( ptr );
267 return ret;
271 /***********************************************************************
272 * WIN_IsCurrentThread
274 * Check whether a given window belongs to the current thread (and return the full handle).
276 HWND WIN_IsCurrentThread( HWND hwnd )
278 WND *ptr;
279 HWND ret = 0;
281 if ((ptr = WIN_GetPtr( hwnd )) && ptr != WND_OTHER_PROCESS)
283 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
284 WIN_ReleasePtr( ptr );
286 return ret;
290 /***********************************************************************
291 * WIN_Handle32
293 * Convert a 16-bit window handle to a full 32-bit handle.
295 HWND WIN_Handle32( HWND16 hwnd16 )
297 WND *ptr;
298 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
300 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
301 /* do sign extension for -2 and -3 */
302 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
304 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
306 if (ptr != WND_OTHER_PROCESS)
308 hwnd = ptr->hwndSelf;
309 WIN_ReleasePtr( ptr );
311 else /* may belong to another process */
313 SERVER_START_REQ( get_window_info )
315 req->handle = hwnd;
316 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
318 SERVER_END_REQ;
320 return hwnd;
324 /***********************************************************************
325 * WIN_FindWndPtr
327 * Return a pointer to the WND structure corresponding to a HWND.
329 WND * WIN_FindWndPtr( HWND hwnd )
331 WND * ptr;
333 if (!hwnd) return NULL;
335 if ((ptr = WIN_GetPtr( hwnd )))
337 if (ptr != WND_OTHER_PROCESS)
339 /* increment destruction monitoring */
340 ptr->irefCount++;
341 return ptr;
343 if (IsWindow( hwnd )) /* check other processes */
345 ERR( "window %p belongs to other process\n", hwnd );
346 /* DbgBreakPoint(); */
349 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
350 return NULL;
354 /***********************************************************************
355 * WIN_ReleaseWndPtr
357 * Release the pointer to the WND structure.
359 void WIN_ReleaseWndPtr(WND *wndPtr)
361 if(!wndPtr) return;
363 /* Decrement destruction monitoring value */
364 wndPtr->irefCount--;
365 /* Check if it's time to release the memory */
366 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
368 /* Release memory */
369 free_window_handle( wndPtr->hwndSelf );
371 else if(wndPtr->irefCount < 0)
373 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
374 ERR("forgot a Lock on %p somewhere\n",wndPtr);
376 /* unlock all WND structures for thread safeness */
377 USER_Unlock();
381 /***********************************************************************
382 * WIN_UnlinkWindow
384 * Remove a window from the siblings linked list.
386 void WIN_UnlinkWindow( HWND hwnd )
388 WIN_LinkWindow( hwnd, 0, 0 );
392 /***********************************************************************
393 * WIN_LinkWindow
395 * Insert a window into the siblings linked list.
396 * The window is inserted after the specified window, which can also
397 * be specified as HWND_TOP or HWND_BOTTOM.
398 * If parent is 0, window is unlinked from the tree.
400 void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
402 WND *wndPtr = WIN_GetPtr( hwnd );
404 if (!wndPtr) return;
405 if (wndPtr == WND_OTHER_PROCESS)
407 if (IsWindow(hwnd)) ERR(" cannot link other process window %p\n", hwnd );
408 return;
411 SERVER_START_REQ( link_window )
413 req->handle = hwnd;
414 req->parent = parent;
415 req->previous = hwndInsertAfter;
416 if (!wine_server_call( req ))
418 if (reply->full_parent) wndPtr->parent = reply->full_parent;
422 SERVER_END_REQ;
423 WIN_ReleasePtr( wndPtr );
427 /***********************************************************************
428 * WIN_SetOwner
430 * Change the owner of a window.
432 HWND WIN_SetOwner( HWND hwnd, HWND owner )
434 WND *win = WIN_GetPtr( hwnd );
435 HWND ret = 0;
437 if (!win) return 0;
438 if (win == WND_OTHER_PROCESS)
440 if (IsWindow(hwnd)) ERR( "cannot set owner %p on other process window %p\n", owner, hwnd );
441 return 0;
443 SERVER_START_REQ( set_window_owner )
445 req->handle = hwnd;
446 req->owner = owner;
447 if (!wine_server_call( req ))
449 win->owner = reply->full_owner;
450 ret = reply->prev_owner;
453 SERVER_END_REQ;
454 WIN_ReleasePtr( win );
455 return ret;
459 /***********************************************************************
460 * WIN_SetStyle
462 * Change the style of a window.
464 LONG WIN_SetStyle( HWND hwnd, LONG style )
466 BOOL ok;
467 LONG ret = 0;
468 WND *win = WIN_GetPtr( hwnd );
470 if (!win) return 0;
471 if (win == WND_OTHER_PROCESS)
473 if (IsWindow(hwnd))
474 ERR( "cannot set style %lx on other process window %p\n", style, hwnd );
475 return 0;
477 if (style == win->dwStyle)
479 WIN_ReleasePtr( win );
480 return style;
482 SERVER_START_REQ( set_window_info )
484 req->handle = hwnd;
485 req->flags = SET_WIN_STYLE;
486 req->style = style;
487 req->extra_offset = -1;
488 if ((ok = !wine_server_call( req )))
490 ret = reply->old_style;
491 win->dwStyle = style;
494 SERVER_END_REQ;
495 WIN_ReleasePtr( win );
496 if (ok && USER_Driver.pSetWindowStyle) USER_Driver.pSetWindowStyle( hwnd, ret );
497 return ret;
501 /***********************************************************************
502 * WIN_SetExStyle
504 * Change the extended style of a window.
506 LONG WIN_SetExStyle( HWND hwnd, LONG style )
508 LONG ret = 0;
509 WND *win = WIN_GetPtr( hwnd );
511 if (!win) return 0;
512 if (win == WND_OTHER_PROCESS)
514 if (IsWindow(hwnd))
515 ERR( "cannot set exstyle %lx on other process window %p\n", style, hwnd );
516 return 0;
518 if (style == win->dwExStyle)
520 WIN_ReleasePtr( win );
521 return style;
523 SERVER_START_REQ( set_window_info )
525 req->handle = hwnd;
526 req->flags = SET_WIN_EXSTYLE;
527 req->ex_style = style;
528 req->extra_offset = -1;
529 if (!wine_server_call( req ))
531 ret = reply->old_ex_style;
532 win->dwExStyle = style;
535 SERVER_END_REQ;
536 WIN_ReleasePtr( win );
537 return ret;
541 /***********************************************************************
542 * WIN_SetRectangles
544 * Set the window and client rectangles.
546 void WIN_SetRectangles( HWND hwnd, const RECT *rectWindow, const RECT *rectClient )
548 WND *win = WIN_GetPtr( hwnd );
549 BOOL ret;
551 if (!win) return;
552 if (win == WND_OTHER_PROCESS)
554 if (IsWindow( hwnd )) ERR( "cannot set rectangles of other process window %p\n", hwnd );
555 return;
557 SERVER_START_REQ( set_window_rectangles )
559 req->handle = hwnd;
560 req->window.left = rectWindow->left;
561 req->window.top = rectWindow->top;
562 req->window.right = rectWindow->right;
563 req->window.bottom = rectWindow->bottom;
564 req->client.left = rectClient->left;
565 req->client.top = rectClient->top;
566 req->client.right = rectClient->right;
567 req->client.bottom = rectClient->bottom;
568 ret = !wine_server_call( req );
570 SERVER_END_REQ;
571 if (ret)
573 win->rectWindow = *rectWindow;
574 win->rectClient = *rectClient;
576 TRACE( "win %p window (%ld,%ld)-(%ld,%ld) client (%ld,%ld)-(%ld,%ld)\n", hwnd,
577 rectWindow->left, rectWindow->top, rectWindow->right, rectWindow->bottom,
578 rectClient->left, rectClient->top, rectClient->right, rectClient->bottom );
580 WIN_ReleasePtr( win );
584 /***********************************************************************
585 * WIN_GetRectangles
587 * Get the window and client rectangles.
589 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
591 WND *win = WIN_GetPtr( hwnd );
592 BOOL ret = TRUE;
594 if (!win) return FALSE;
595 if (win == WND_OTHER_PROCESS)
597 SERVER_START_REQ( get_window_rectangles )
599 req->handle = hwnd;
600 if ((ret = !wine_server_call( req )))
602 if (rectWindow)
604 rectWindow->left = reply->window.left;
605 rectWindow->top = reply->window.top;
606 rectWindow->right = reply->window.right;
607 rectWindow->bottom = reply->window.bottom;
609 if (rectClient)
611 rectClient->left = reply->client.left;
612 rectClient->top = reply->client.top;
613 rectClient->right = reply->client.right;
614 rectClient->bottom = reply->client.bottom;
618 SERVER_END_REQ;
620 else
622 if (rectWindow) *rectWindow = win->rectWindow;
623 if (rectClient) *rectClient = win->rectClient;
624 WIN_ReleasePtr( win );
626 return ret;
630 /***********************************************************************
631 * WIN_DestroyWindow
633 * Destroy storage associated to a window. "Internals" p.358
635 LRESULT WIN_DestroyWindow( HWND hwnd )
637 WND *wndPtr;
638 HWND *list;
640 TRACE("%p\n", hwnd );
642 if (!(hwnd = WIN_IsCurrentThread( hwnd )))
644 ERR( "window doesn't belong to current thread\n" );
645 return 0;
648 /* free child windows */
649 if ((list = WIN_ListChildren( hwnd )))
651 int i;
652 for (i = 0; list[i]; i++)
654 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
655 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
657 HeapFree( GetProcessHeap(), 0, list );
661 * Clear the update region to make sure no WM_PAINT messages will be
662 * generated for this window while processing the WM_NCDESTROY.
664 RedrawWindow( hwnd, NULL, 0,
665 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
668 * Send the WM_NCDESTROY to the window being destroyed.
670 SendMessageA( hwnd, WM_NCDESTROY, 0, 0);
672 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
674 WINPOS_CheckInternalPos( hwnd );
675 if( hwnd == GetCapture()) ReleaseCapture();
677 /* free resources associated with the window */
679 TIMER_RemoveWindowTimers( hwnd );
681 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
683 if (!(wndPtr->dwStyle & WS_CHILD))
685 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
686 if (menu) DestroyMenu( menu );
688 if (wndPtr->hSysMenu)
690 DestroyMenu( wndPtr->hSysMenu );
691 wndPtr->hSysMenu = 0;
693 DCE_FreeWindowDCE( hwnd ); /* Always do this to catch orphaned DCs */
694 USER_Driver.pDestroyWindow( hwnd );
695 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
696 wndPtr->class = NULL;
697 wndPtr->dwMagic = 0; /* Mark it as invalid */
698 WIN_ReleaseWndPtr( wndPtr );
699 return 0;
702 /***********************************************************************
703 * WIN_DestroyThreadWindows
705 * Destroy all children of 'wnd' owned by the current thread.
706 * Return TRUE if something was done.
708 void WIN_DestroyThreadWindows( HWND hwnd )
710 HWND *list;
711 int i;
713 if (!(list = WIN_ListChildren( hwnd ))) return;
714 for (i = 0; list[i]; i++)
716 if (WIN_IsCurrentThread( list[i] ))
717 DestroyWindow( list[i] );
718 else
719 WIN_DestroyThreadWindows( list[i] );
721 HeapFree( GetProcessHeap(), 0, list );
724 /***********************************************************************
725 * WIN_CreateDesktopWindow
727 * Create the desktop window.
729 BOOL WIN_CreateDesktopWindow(void)
731 HWND hwndDesktop;
732 CREATESTRUCTA cs;
733 RECT rect;
735 TRACE("Creating desktop window\n");
737 if (!WINPOS_CreateInternalPosAtom()) return FALSE;
739 pWndDesktop = create_window_handle( 0, 0, LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W );
740 if (!pWndDesktop) return FALSE;
741 hwndDesktop = pWndDesktop->hwndSelf;
743 pWndDesktop->tid = 0; /* nobody owns the desktop */
744 pWndDesktop->parent = 0;
745 pWndDesktop->owner = 0;
746 pWndDesktop->text = NULL;
747 pWndDesktop->hrgnUpdate = 0;
748 pWndDesktop->pVScroll = NULL;
749 pWndDesktop->pHScroll = NULL;
750 pWndDesktop->helpContext = 0;
751 pWndDesktop->flags = 0;
752 pWndDesktop->hSysMenu = 0;
754 cs.lpCreateParams = NULL;
755 cs.hInstance = 0;
756 cs.hMenu = 0;
757 cs.hwndParent = 0;
758 cs.x = 0;
759 cs.y = 0;
760 cs.cx = GetSystemMetrics( SM_CXSCREEN );
761 cs.cy = GetSystemMetrics( SM_CYSCREEN );
762 cs.style = pWndDesktop->dwStyle;
763 cs.dwExStyle = pWndDesktop->dwExStyle;
764 cs.lpszName = NULL;
765 cs.lpszClass = DESKTOP_CLASS_ATOM;
767 SetRect( &rect, 0, 0, cs.cx, cs.cy );
768 WIN_SetRectangles( hwndDesktop, &rect, &rect );
770 SERVER_START_REQ( set_window_info )
772 req->handle = hwndDesktop;
773 req->flags = 0; /* don't set anything, just retrieve */
774 req->extra_offset = -1;
775 wine_server_call( req );
776 pWndDesktop->dwStyle = reply->old_style;
777 pWndDesktop->dwExStyle = reply->old_ex_style;
778 pWndDesktop->hInstance = (HINSTANCE)reply->old_instance;
779 pWndDesktop->userdata = (ULONG_PTR)reply->old_user_data;
780 pWndDesktop->wIDmenu = reply->old_id;
782 SERVER_END_REQ;
784 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE ))
786 WIN_ReleaseWndPtr( pWndDesktop );
787 return FALSE;
790 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
791 WIN_ReleaseWndPtr( pWndDesktop );
792 return TRUE;
796 /***********************************************************************
797 * WIN_FixCoordinates
799 * Fix the coordinates - Helper for WIN_CreateWindowEx.
800 * returns default show mode in sw.
801 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
803 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
805 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
806 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
808 if (cs->style & (WS_CHILD | WS_POPUP))
810 if (cs->dwExStyle & WS_EX_MDICHILD)
812 POINT pos[2];
814 MDI_CalcDefaultChildPos(cs->hwndParent, -1, pos, 0);
816 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
818 cs->x = pos[0].x;
819 cs->y = pos[0].y;
821 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16 || !cs->cx)
822 cs->cx = pos[1].x;
823 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16 || !cs->cy)
824 cs->cy = pos[1].y;
826 else
828 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
829 cs->x = cs->y = 0;
830 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
831 cs->cx = cs->cy = 0;
834 else /* overlapped window */
836 STARTUPINFOA info;
838 GetStartupInfoA( &info );
840 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
842 /* Never believe Microsoft's documentation... CreateWindowEx doc says
843 * that if an overlapped window is created with WS_VISIBLE style bit
844 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
845 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
846 * reveals that
848 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
849 * 2) it does not ignore the y parameter as the docs claim; instead, it
850 * uses it as second parameter to ShowWindow() unless y is either
851 * CW_USEDEFAULT or CW_USEDEFAULT16.
853 * The fact that we didn't do 2) caused bogus windows pop up when wine
854 * was running apps that were using this obscure feature. Example -
855 * calc.exe that comes with Win98 (only Win98, it's different from
856 * the one that comes with Win95 and NT)
858 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
859 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
860 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
863 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
865 if (info.dwFlags & STARTF_USESIZE)
867 cs->cx = info.dwXSize;
868 cs->cy = info.dwYSize;
870 else /* if no other hint from the app, pick 3/4 of the screen real estate */
872 RECT r;
873 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
874 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
875 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
880 else
882 /* neither x nor cx are default. Check the y values .
883 * In the trace we see Outlook and Outlook Express using
884 * cy set to CW_USEDEFAULT when opening the address book.
886 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16) {
887 RECT r;
888 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
889 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
890 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
895 /***********************************************************************
896 * dump_window_styles
898 static void dump_window_styles( DWORD style, DWORD exstyle )
900 TRACE( "style:" );
901 if(style & WS_POPUP) TRACE(" WS_POPUP");
902 if(style & WS_CHILD) TRACE(" WS_CHILD");
903 if(style & WS_MINIMIZE) TRACE(" WS_MINIMIZE");
904 if(style & WS_VISIBLE) TRACE(" WS_VISIBLE");
905 if(style & WS_DISABLED) TRACE(" WS_DISABLED");
906 if(style & WS_CLIPSIBLINGS) TRACE(" WS_CLIPSIBLINGS");
907 if(style & WS_CLIPCHILDREN) TRACE(" WS_CLIPCHILDREN");
908 if(style & WS_MAXIMIZE) TRACE(" WS_MAXIMIZE");
909 if((style & WS_CAPTION) == WS_CAPTION) TRACE(" WS_CAPTION");
910 else
912 if(style & WS_BORDER) TRACE(" WS_BORDER");
913 if(style & WS_DLGFRAME) TRACE(" WS_DLGFRAME");
915 if(style & WS_VSCROLL) TRACE(" WS_VSCROLL");
916 if(style & WS_HSCROLL) TRACE(" WS_HSCROLL");
917 if(style & WS_SYSMENU) TRACE(" WS_SYSMENU");
918 if(style & WS_THICKFRAME) TRACE(" WS_THICKFRAME");
919 if(style & WS_GROUP) TRACE(" WS_GROUP");
920 if(style & WS_TABSTOP) TRACE(" WS_TABSTOP");
921 if(style & WS_MINIMIZEBOX) TRACE(" WS_MINIMIZEBOX");
922 if(style & WS_MAXIMIZEBOX) TRACE(" WS_MAXIMIZEBOX");
924 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
925 #define DUMPED_STYLES \
926 (WS_POPUP | \
927 WS_CHILD | \
928 WS_MINIMIZE | \
929 WS_VISIBLE | \
930 WS_DISABLED | \
931 WS_CLIPSIBLINGS | \
932 WS_CLIPCHILDREN | \
933 WS_MAXIMIZE | \
934 WS_BORDER | \
935 WS_DLGFRAME | \
936 WS_VSCROLL | \
937 WS_HSCROLL | \
938 WS_SYSMENU | \
939 WS_THICKFRAME | \
940 WS_GROUP | \
941 WS_TABSTOP | \
942 WS_MINIMIZEBOX | \
943 WS_MAXIMIZEBOX)
945 if(style & ~DUMPED_STYLES) TRACE(" %08lx", style & ~DUMPED_STYLES);
946 TRACE("\n");
947 #undef DUMPED_STYLES
949 TRACE( "exstyle:" );
950 if(exstyle & WS_EX_DLGMODALFRAME) TRACE(" WS_EX_DLGMODALFRAME");
951 if(exstyle & WS_EX_DRAGDETECT) TRACE(" WS_EX_DRAGDETECT");
952 if(exstyle & WS_EX_NOPARENTNOTIFY) TRACE(" WS_EX_NOPARENTNOTIFY");
953 if(exstyle & WS_EX_TOPMOST) TRACE(" WS_EX_TOPMOST");
954 if(exstyle & WS_EX_ACCEPTFILES) TRACE(" WS_EX_ACCEPTFILES");
955 if(exstyle & WS_EX_TRANSPARENT) TRACE(" WS_EX_TRANSPARENT");
956 if(exstyle & WS_EX_MDICHILD) TRACE(" WS_EX_MDICHILD");
957 if(exstyle & WS_EX_TOOLWINDOW) TRACE(" WS_EX_TOOLWINDOW");
958 if(exstyle & WS_EX_WINDOWEDGE) TRACE(" WS_EX_WINDOWEDGE");
959 if(exstyle & WS_EX_CLIENTEDGE) TRACE(" WS_EX_CLIENTEDGE");
960 if(exstyle & WS_EX_CONTEXTHELP) TRACE(" WS_EX_CONTEXTHELP");
961 if(exstyle & WS_EX_RIGHT) TRACE(" WS_EX_RIGHT");
962 if(exstyle & WS_EX_RTLREADING) TRACE(" WS_EX_RTLREADING");
963 if(exstyle & WS_EX_LEFTSCROLLBAR) TRACE(" WS_EX_LEFTSCROLLBAR");
964 if(exstyle & WS_EX_CONTROLPARENT) TRACE(" WS_EX_CONTROLPARENT");
965 if(exstyle & WS_EX_STATICEDGE) TRACE(" WS_EX_STATICEDGE");
966 if(exstyle & WS_EX_APPWINDOW) TRACE(" WS_EX_APPWINDOW");
967 if(exstyle & WS_EX_LAYERED) TRACE(" WS_EX_LAYERED");
969 #define DUMPED_EX_STYLES \
970 (WS_EX_DLGMODALFRAME | \
971 WS_EX_DRAGDETECT | \
972 WS_EX_NOPARENTNOTIFY | \
973 WS_EX_TOPMOST | \
974 WS_EX_ACCEPTFILES | \
975 WS_EX_TRANSPARENT | \
976 WS_EX_MDICHILD | \
977 WS_EX_TOOLWINDOW | \
978 WS_EX_WINDOWEDGE | \
979 WS_EX_CLIENTEDGE | \
980 WS_EX_CONTEXTHELP | \
981 WS_EX_RIGHT | \
982 WS_EX_RTLREADING | \
983 WS_EX_LEFTSCROLLBAR | \
984 WS_EX_CONTROLPARENT | \
985 WS_EX_STATICEDGE | \
986 WS_EX_APPWINDOW | \
987 WS_EX_LAYERED)
989 if(exstyle & ~DUMPED_EX_STYLES) TRACE(" %08lx", exstyle & ~DUMPED_EX_STYLES);
990 TRACE("\n");
991 #undef DUMPED_EX_STYLES
995 /***********************************************************************
996 * WIN_CreateWindowEx
998 * Implementation of CreateWindowEx().
1000 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
1001 WINDOWPROCTYPE type )
1003 INT sw = SW_SHOW;
1004 WND *wndPtr;
1005 HWND hwnd, parent, owner, top_child = 0;
1006 BOOL unicode = (type == WIN_PROC_32W);
1008 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
1009 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
1010 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszClass) : debugstr_a(cs->lpszClass),
1011 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
1012 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
1014 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
1016 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
1017 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
1019 /* Fix the styles for MDI children */
1020 if (cs->dwExStyle & WS_EX_MDICHILD)
1022 MDICREATESTRUCTA mdi_cs;
1023 UINT flags = 0;
1025 wndPtr = WIN_GetPtr(cs->hwndParent);
1026 if (wndPtr && wndPtr != WND_OTHER_PROCESS)
1028 flags = wndPtr->flags;
1029 WIN_ReleasePtr(wndPtr);
1032 if (!(flags & WIN_ISMDICLIENT))
1034 WARN("WS_EX_MDICHILD, but parent %p is not MDIClient\n", cs->hwndParent);
1035 return 0;
1038 /* cs->lpCreateParams of WM_[NC]CREATE is different for MDI children.
1039 * MDICREATESTRUCT members have the originally passed values.
1041 * Note: we rely on the fact that MDICREATESTRUCTA and MDICREATESTRUCTW
1042 * have the same layout.
1044 mdi_cs.szClass = cs->lpszClass;
1045 mdi_cs.szTitle = cs->lpszName;
1046 mdi_cs.hOwner = cs->hInstance;
1047 mdi_cs.x = cs->x;
1048 mdi_cs.y = cs->y;
1049 mdi_cs.cx = cs->cx;
1050 mdi_cs.cy = cs->cy;
1051 mdi_cs.style = cs->style;
1052 mdi_cs.lParam = (LPARAM)cs->lpCreateParams;
1054 cs->lpCreateParams = (LPVOID)&mdi_cs;
1056 if (GetWindowLongW(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
1058 if (cs->style & WS_POPUP)
1060 TRACE("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n");
1061 return 0;
1063 cs->style |= WS_CHILD | WS_CLIPSIBLINGS;
1065 else
1067 cs->style &= ~WS_POPUP;
1068 cs->style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
1069 WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
1072 top_child = GetWindow(cs->hwndParent, GW_CHILD);
1075 /* Find the parent window */
1077 parent = GetDesktopWindow();
1078 owner = 0;
1080 if (cs->hwndParent == HWND_MESSAGE)
1082 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
1083 * message window (style: WS_POPUP|WS_DISABLED)
1085 FIXME("Parent is HWND_MESSAGE\n");
1087 else if (cs->hwndParent)
1089 /* Make sure parent is valid */
1090 if (!IsWindow( cs->hwndParent ))
1092 WARN("Bad parent %p\n", cs->hwndParent );
1093 return 0;
1095 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1096 parent = WIN_GetFullHandle(cs->hwndParent);
1097 else
1098 owner = GetAncestor( cs->hwndParent, GA_ROOT );
1100 else if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1102 WARN("No parent for child window\n" );
1103 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1106 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
1108 /* Correct the window styles.
1110 * It affects both the style loaded into the WIN structure and
1111 * passed in the CREATESTRUCT to the WM_[NC]CREATE.
1113 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1114 * why does the user get to set it?
1117 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
1118 * tested for WS_POPUP
1120 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
1121 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
1122 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
1123 cs->dwExStyle |= WS_EX_WINDOWEDGE;
1124 else
1125 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
1127 if (!(cs->style & WS_CHILD))
1129 cs->style |= WS_CLIPSIBLINGS;
1130 if (!(cs->style & WS_POPUP))
1131 cs->style |= WS_CAPTION;
1134 /* Create the window structure */
1136 if (!(wndPtr = create_window_handle( parent, owner, classAtom, cs->hInstance, type )))
1138 TRACE("out of memory\n" );
1139 return 0;
1141 hwnd = wndPtr->hwndSelf;
1143 /* Fill the window structure */
1145 wndPtr->tid = GetCurrentThreadId();
1146 wndPtr->owner = owner;
1147 wndPtr->parent = parent;
1148 wndPtr->hInstance = cs->hInstance;
1149 wndPtr->text = NULL;
1150 wndPtr->hrgnUpdate = 0;
1151 wndPtr->hrgnWnd = 0;
1152 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1153 wndPtr->dwExStyle = cs->dwExStyle;
1154 wndPtr->wIDmenu = 0;
1155 wndPtr->helpContext = 0;
1156 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
1157 wndPtr->pVScroll = NULL;
1158 wndPtr->pHScroll = NULL;
1159 wndPtr->userdata = 0;
1160 wndPtr->hIcon = 0;
1161 wndPtr->hIconSmall = 0;
1162 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU) ? MENU_GetSysMenu( hwnd, 0 ) : 0;
1164 if (!(cs->style & (WS_CHILD | WS_POPUP)))
1165 wndPtr->flags |= WIN_NEED_SIZE;
1167 SERVER_START_REQ( set_window_info )
1169 req->handle = hwnd;
1170 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE;
1171 req->style = wndPtr->dwStyle;
1172 req->ex_style = wndPtr->dwExStyle;
1173 req->instance = (void *)wndPtr->hInstance;
1174 req->extra_offset = -1;
1175 wine_server_call( req );
1177 SERVER_END_REQ;
1179 /* Get class or window DC if needed */
1181 if (wndPtr->clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
1183 /* Set the window menu */
1185 if (((wndPtr->dwStyle & (WS_CAPTION|WS_CHILD)) == WS_CAPTION) ||
1186 (wndPtr->dwExStyle & WS_EX_APPWINDOW))
1188 if (cs->hMenu) MENU_SetMenu(hwnd, cs->hMenu);
1189 else
1191 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
1192 if (menuName)
1194 if (HIWORD(cs->hInstance))
1195 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1196 else
1197 cs->hMenu = HMENU_32(LoadMenu16(HINSTANCE_16(cs->hInstance),menuName));
1199 if (cs->hMenu) MENU_SetMenu( hwnd, cs->hMenu );
1203 else SetWindowLongW( hwnd, GWL_ID, (UINT)cs->hMenu );
1204 WIN_ReleaseWndPtr( wndPtr );
1206 if (!USER_Driver.pCreateWindow( hwnd, cs, unicode))
1208 WIN_DestroyWindow( hwnd );
1209 return 0;
1212 /* Notify the parent window only */
1214 send_parent_notify( hwnd, WM_CREATE );
1215 if (!IsWindow( hwnd )) return 0;
1217 if (cs->dwExStyle & WS_EX_MDICHILD)
1219 if (top_child)
1221 /* Restore current maximized child */
1222 if((cs->style & WS_VISIBLE) && IsZoomed(top_child))
1224 TRACE("Restoring current maximized child %p\n", top_child);
1225 ShowWindow(top_child, SW_SHOWNOACTIVATE);
1229 SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
1232 if (cs->style & WS_VISIBLE)
1233 ShowWindow( hwnd, sw );
1235 /* Call WH_SHELL hook */
1237 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1238 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1240 TRACE("created window %p\n", hwnd);
1241 return hwnd;
1245 /***********************************************************************
1246 * CreateWindow (USER.41)
1248 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1249 DWORD style, INT16 x, INT16 y, INT16 width,
1250 INT16 height, HWND16 parent, HMENU16 menu,
1251 HINSTANCE16 instance, LPVOID data )
1253 return CreateWindowEx16( 0, className, windowName, style,
1254 x, y, width, height, parent, menu, instance, data );
1258 /***********************************************************************
1259 * CreateWindowEx (USER.452)
1261 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1262 LPCSTR windowName, DWORD style, INT16 x,
1263 INT16 y, INT16 width, INT16 height,
1264 HWND16 parent, HMENU16 menu,
1265 HINSTANCE16 instance, LPVOID data )
1267 ATOM classAtom;
1268 CREATESTRUCTA cs;
1269 char buffer[256];
1271 /* Find the class atom */
1273 if (HIWORD(className))
1275 if (!(classAtom = GlobalFindAtomA( className )))
1277 ERR( "bad class name %s\n", debugstr_a(className) );
1278 return 0;
1281 else
1283 classAtom = LOWORD(className);
1284 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1286 ERR( "bad atom %x\n", classAtom);
1287 return 0;
1289 className = buffer;
1292 /* Fix the coordinates */
1294 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1295 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1296 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1297 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1299 /* Create the window */
1301 cs.lpCreateParams = data;
1302 cs.hInstance = HINSTANCE_32(instance);
1303 cs.hMenu = HMENU_32(menu);
1304 cs.hwndParent = WIN_Handle32( parent );
1305 cs.style = style;
1306 cs.lpszName = windowName;
1307 cs.lpszClass = className;
1308 cs.dwExStyle = exStyle;
1310 return HWND_16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
1314 /***********************************************************************
1315 * CreateWindowExA (USER32.@)
1317 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1318 LPCSTR windowName, DWORD style, INT x,
1319 INT y, INT width, INT height,
1320 HWND parent, HMENU menu,
1321 HINSTANCE instance, LPVOID data )
1323 ATOM classAtom;
1324 CREATESTRUCTA cs;
1325 char buffer[256];
1327 /* Find the class atom */
1329 if (HIWORD(className))
1331 if (!(classAtom = GlobalFindAtomA( className )))
1333 ERR( "bad class name %s\n", debugstr_a(className) );
1334 return 0;
1337 else
1339 classAtom = LOWORD(className);
1340 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1342 ERR( "bad atom %x\n", classAtom);
1343 return 0;
1345 className = buffer;
1348 /* Create the window */
1350 cs.lpCreateParams = data;
1351 cs.hInstance = instance;
1352 cs.hMenu = menu;
1353 cs.hwndParent = parent;
1354 cs.x = x;
1355 cs.y = y;
1356 cs.cx = width;
1357 cs.cy = height;
1358 cs.style = style;
1359 cs.lpszName = windowName;
1360 cs.lpszClass = className;
1361 cs.dwExStyle = exStyle;
1363 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1367 /***********************************************************************
1368 * CreateWindowExW (USER32.@)
1370 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1371 LPCWSTR windowName, DWORD style, INT x,
1372 INT y, INT width, INT height,
1373 HWND parent, HMENU menu,
1374 HINSTANCE instance, LPVOID data )
1376 ATOM classAtom;
1377 CREATESTRUCTW cs;
1378 WCHAR buffer[256];
1380 /* Find the class atom */
1382 if (HIWORD(className))
1384 if (!(classAtom = GlobalFindAtomW( className )))
1386 ERR( "bad class name %s\n", debugstr_w(className) );
1387 return 0;
1390 else
1392 classAtom = LOWORD(className);
1393 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1395 ERR( "bad atom %x\n", classAtom);
1396 return 0;
1398 className = buffer;
1401 /* Create the window */
1403 cs.lpCreateParams = data;
1404 cs.hInstance = instance;
1405 cs.hMenu = menu;
1406 cs.hwndParent = parent;
1407 cs.x = x;
1408 cs.y = y;
1409 cs.cx = width;
1410 cs.cy = height;
1411 cs.style = style;
1412 cs.lpszName = windowName;
1413 cs.lpszClass = className;
1414 cs.dwExStyle = exStyle;
1416 /* Note: we rely on the fact that CREATESTRUCTA and */
1417 /* CREATESTRUCTW have the same layout. */
1418 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1422 /***********************************************************************
1423 * WIN_SendDestroyMsg
1425 static void WIN_SendDestroyMsg( HWND hwnd )
1427 GUITHREADINFO info;
1429 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1431 if (hwnd == info.hwndCaret) DestroyCaret();
1433 if (USER_Driver.pResetSelectionOwner)
1434 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1437 * Send the WM_DESTROY to the window.
1439 SendMessageA( hwnd, WM_DESTROY, 0, 0);
1442 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1443 * make sure that the window still exists when we come back.
1445 if (IsWindow(hwnd))
1447 HWND* pWndArray;
1448 int i;
1450 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1452 /* start from the end (FIXME: is this needed?) */
1453 for (i = 0; pWndArray[i]; i++) ;
1455 while (--i >= 0)
1457 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1459 HeapFree( GetProcessHeap(), 0, pWndArray );
1461 else
1462 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1466 /***********************************************************************
1467 * DestroyWindow (USER32.@)
1469 BOOL WINAPI DestroyWindow( HWND hwnd )
1471 BOOL is_child;
1473 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1475 SetLastError( ERROR_ACCESS_DENIED );
1476 return FALSE;
1479 TRACE("(%p)\n", hwnd);
1481 if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
1482 SendMessageW(GetAncestor(hwnd, GA_PARENT), WM_MDIREFRESHMENU, 0, 0);
1484 /* Call hooks */
1486 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1488 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1490 if (is_child)
1492 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1493 send_parent_notify( hwnd, WM_DESTROY );
1495 else if (!GetWindow( hwnd, GW_OWNER ))
1497 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1498 /* FIXME: clean up palette - see "Internals" p.352 */
1501 if (!IsWindow(hwnd)) return TRUE;
1503 if (USER_Driver.pResetSelectionOwner)
1504 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1506 /* Hide the window */
1508 if (!ShowWindow( hwnd, SW_HIDE ))
1510 if (hwnd == GetActiveWindow()) WINPOS_ActivateOtherWindow( hwnd );
1512 if (!IsWindow(hwnd)) return TRUE;
1514 /* Recursively destroy owned windows */
1516 if (!is_child)
1518 for (;;)
1520 int i, got_one = 0;
1521 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1522 if (list)
1524 for (i = 0; list[i]; i++)
1526 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1527 if (WIN_IsCurrentThread( list[i] ))
1529 DestroyWindow( list[i] );
1530 got_one = 1;
1531 continue;
1533 WIN_SetOwner( list[i], 0 );
1535 HeapFree( GetProcessHeap(), 0, list );
1537 if (!got_one) break;
1541 /* Send destroy messages */
1543 WIN_SendDestroyMsg( hwnd );
1544 if (!IsWindow( hwnd )) return TRUE;
1546 if (GetClipboardOwner() == hwnd)
1547 CLIPBOARD_ReleaseOwner();
1549 /* Unlink now so we won't bother with the children later on */
1551 WIN_UnlinkWindow( hwnd );
1553 /* Destroy the window storage */
1555 WIN_DestroyWindow( hwnd );
1556 return TRUE;
1560 /***********************************************************************
1561 * CloseWindow (USER32.@)
1563 BOOL WINAPI CloseWindow( HWND hwnd )
1565 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1566 ShowWindow( hwnd, SW_MINIMIZE );
1567 return TRUE;
1571 /***********************************************************************
1572 * OpenIcon (USER32.@)
1574 BOOL WINAPI OpenIcon( HWND hwnd )
1576 if (!IsIconic( hwnd )) return FALSE;
1577 ShowWindow( hwnd, SW_SHOWNORMAL );
1578 return TRUE;
1582 /***********************************************************************
1583 * WIN_FindWindow
1585 * Implementation of FindWindow() and FindWindowEx().
1587 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1589 HWND *list = NULL;
1590 HWND retvalue = 0;
1591 int i = 0, len = 0;
1592 WCHAR *buffer = NULL;
1594 if (!parent) parent = GetDesktopWindow();
1595 if (title)
1597 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1598 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1601 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1603 if (child)
1605 child = WIN_GetFullHandle( child );
1606 while (list[i] && list[i] != child) i++;
1607 if (!list[i]) goto done;
1608 i++; /* start from next window */
1611 if (title)
1613 while (list[i])
1615 if (GetWindowTextW( list[i], buffer, len + 1 ) && !strcmpiW( buffer, title )) break;
1616 i++;
1619 retvalue = list[i];
1621 done:
1622 if (list) HeapFree( GetProcessHeap(), 0, list );
1623 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1624 return retvalue;
1629 /***********************************************************************
1630 * FindWindowA (USER32.@)
1632 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1634 HWND ret = FindWindowExA( 0, 0, className, title );
1635 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1636 return ret;
1640 /***********************************************************************
1641 * FindWindowExA (USER32.@)
1643 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1644 LPCSTR className, LPCSTR title )
1646 ATOM atom = 0;
1647 LPWSTR buffer;
1648 HWND hwnd;
1649 INT len;
1651 if (className)
1653 /* If the atom doesn't exist, then no class */
1654 /* with this name exists either. */
1655 if (!(atom = GlobalFindAtomA( className )))
1657 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1658 return 0;
1661 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
1663 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1664 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1665 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
1666 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1667 HeapFree( GetProcessHeap(), 0, buffer );
1668 return hwnd;
1672 /***********************************************************************
1673 * FindWindowExW (USER32.@)
1675 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1676 LPCWSTR className, LPCWSTR title )
1678 ATOM atom = 0;
1680 if (className)
1682 /* If the atom doesn't exist, then no class */
1683 /* with this name exists either. */
1684 if (!(atom = GlobalFindAtomW( className )))
1686 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1687 return 0;
1690 return WIN_FindWindow( parent, child, atom, title );
1694 /***********************************************************************
1695 * FindWindowW (USER32.@)
1697 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1699 return FindWindowExW( 0, 0, className, title );
1703 /**********************************************************************
1704 * GetDesktopWindow (USER32.@)
1706 HWND WINAPI GetDesktopWindow(void)
1708 if (pWndDesktop) return pWndDesktop->hwndSelf;
1709 ERR( "Wine init error: either you're trying to use an invalid native USER.EXE config, or some graphics/GUI libraries or DLLs didn't initialize properly. Aborting.\n" );
1710 ExitProcess(1);
1711 return 0;
1715 /*******************************************************************
1716 * EnableWindow (USER32.@)
1718 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1720 WND *wndPtr;
1721 BOOL retvalue;
1722 LONG style;
1723 HWND full_handle;
1725 if (is_broadcast(hwnd))
1727 SetLastError( ERROR_INVALID_PARAMETER );
1728 return FALSE;
1731 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1732 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1734 hwnd = full_handle;
1736 TRACE("( %p, %d )\n", hwnd, enable);
1738 if (!(wndPtr = WIN_GetPtr( hwnd ))) return FALSE;
1739 style = wndPtr->dwStyle;
1740 retvalue = ((style & WS_DISABLED) != 0);
1741 WIN_ReleasePtr( wndPtr );
1743 if (enable && retvalue)
1745 WIN_SetStyle( hwnd, style & ~WS_DISABLED );
1746 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1748 else if (!enable && !retvalue)
1750 HWND focus_wnd, capture_wnd;
1752 SendMessageA( hwnd, WM_CANCELMODE, 0, 0);
1754 WIN_SetStyle( hwnd, style | WS_DISABLED );
1756 focus_wnd = GetFocus();
1757 if (hwnd == focus_wnd || IsChild(hwnd, focus_wnd))
1758 SetFocus( 0 ); /* A disabled window can't have the focus */
1760 capture_wnd = GetCapture();
1761 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1762 ReleaseCapture(); /* A disabled window can't capture the mouse */
1764 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1766 return retvalue;
1770 /***********************************************************************
1771 * IsWindowEnabled (USER32.@)
1773 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1775 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1779 /***********************************************************************
1780 * IsWindowUnicode (USER32.@)
1782 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1784 WND * wndPtr;
1785 BOOL retvalue;
1787 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1788 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1789 WIN_ReleaseWndPtr(wndPtr);
1790 return retvalue;
1794 /**********************************************************************
1795 * GetWindowWord (USER32.@)
1797 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1799 if (offset >= 0)
1801 WORD retvalue = 0;
1802 WND *wndPtr = WIN_GetPtr( hwnd );
1803 if (!wndPtr)
1805 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1806 return 0;
1808 if (wndPtr == WND_OTHER_PROCESS)
1810 SERVER_START_REQ( set_window_info )
1812 req->handle = hwnd;
1813 req->flags = 0; /* don't set anything, just retrieve */
1814 req->extra_offset = offset;
1815 req->extra_size = sizeof(retvalue);
1816 if (!wine_server_call_err( req ))
1817 memcpy( &retvalue, &reply->old_extra_value, sizeof(retvalue) );
1819 SERVER_END_REQ;
1820 return retvalue;
1822 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1824 WARN("Invalid offset %d\n", offset );
1825 SetLastError( ERROR_INVALID_INDEX );
1827 else memcpy( &retvalue, (char *)wndPtr->wExtra + offset, sizeof(retvalue) );
1828 WIN_ReleasePtr( wndPtr );
1829 return retvalue;
1832 switch(offset)
1834 case GWL_HWNDPARENT:
1835 return GetWindowLongW( hwnd, offset );
1836 case GWL_ID:
1837 case GWL_HINSTANCE:
1839 LONG ret = GetWindowLongW( hwnd, offset );
1840 if (HIWORD(ret))
1841 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1842 return LOWORD(ret);
1844 default:
1845 WARN("Invalid offset %d\n", offset );
1846 return 0;
1851 /**********************************************************************
1852 * SetWindowWord (USER32.@)
1854 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1856 WORD retval = 0;
1857 WND * wndPtr;
1859 switch(offset)
1861 case GWL_ID:
1862 case GWL_HINSTANCE:
1863 case GWL_HWNDPARENT:
1864 return SetWindowLongW( hwnd, offset, (UINT)newval );
1865 default:
1866 if (offset < 0)
1868 WARN("Invalid offset %d\n", offset );
1869 SetLastError( ERROR_INVALID_INDEX );
1870 return 0;
1874 wndPtr = WIN_GetPtr( hwnd );
1875 if (wndPtr == WND_OTHER_PROCESS)
1877 if (IsWindow(hwnd))
1878 FIXME( "set %d <- %x not supported yet on other process window %p\n",
1879 offset, newval, hwnd );
1880 wndPtr = NULL;
1882 if (!wndPtr)
1884 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1885 return 0;
1888 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1890 WARN("Invalid offset %d\n", offset );
1891 WIN_ReleasePtr(wndPtr);
1892 SetLastError( ERROR_INVALID_INDEX );
1893 return 0;
1896 SERVER_START_REQ( set_window_info )
1898 req->handle = hwnd;
1899 req->flags = SET_WIN_EXTRA;
1900 req->extra_offset = offset;
1901 req->extra_size = sizeof(newval);
1902 memcpy( &req->extra_value, &newval, sizeof(newval) );
1903 if (!wine_server_call_err( req ))
1905 void *ptr = (char *)wndPtr->wExtra + offset;
1906 memcpy( &retval, ptr, sizeof(retval) );
1907 memcpy( ptr, &newval, sizeof(newval) );
1910 SERVER_END_REQ;
1911 WIN_ReleasePtr( wndPtr );
1912 return retval;
1916 /**********************************************************************
1917 * WIN_GetWindowLong
1919 * Helper function for GetWindowLong().
1921 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1923 LONG retvalue = 0;
1924 WND *wndPtr;
1926 if (offset == GWL_HWNDPARENT)
1928 HWND parent = GetAncestor( hwnd, GA_PARENT );
1929 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1930 return (LONG)parent;
1933 if (!(wndPtr = WIN_GetPtr( hwnd )))
1935 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1936 return 0;
1939 if (wndPtr == WND_OTHER_PROCESS)
1941 if (offset == GWL_WNDPROC)
1943 SetLastError( ERROR_ACCESS_DENIED );
1944 return 0;
1946 SERVER_START_REQ( set_window_info )
1948 req->handle = hwnd;
1949 req->flags = 0; /* don't set anything, just retrieve */
1950 req->extra_offset = (offset >= 0) ? offset : -1;
1951 req->extra_size = (offset >= 0) ? sizeof(retvalue) : 0;
1952 if (!wine_server_call_err( req ))
1954 switch(offset)
1956 case GWL_STYLE: retvalue = reply->old_style; break;
1957 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1958 case GWL_ID: retvalue = reply->old_id; break;
1959 case GWL_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1960 case GWL_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
1961 default:
1962 if (offset >= 0) retvalue = reply->old_extra_value;
1963 else SetLastError( ERROR_INVALID_INDEX );
1964 break;
1968 SERVER_END_REQ;
1969 return retvalue;
1972 /* now we have a valid wndPtr */
1974 if (offset >= 0)
1976 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
1979 * Some programs try to access last element from 16 bit
1980 * code using illegal offset value. Hopefully this is
1981 * what those programs really expect.
1983 if (type == WIN_PROC_16 &&
1984 wndPtr->cbWndExtra >= 4 &&
1985 offset == wndPtr->cbWndExtra - sizeof(WORD))
1987 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
1989 ERR( "- replaced invalid offset %d with %d\n",
1990 offset, offset2 );
1992 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset2);
1993 WIN_ReleasePtr( wndPtr );
1994 return retvalue;
1996 WARN("Invalid offset %d\n", offset );
1997 WIN_ReleasePtr( wndPtr );
1998 SetLastError( ERROR_INVALID_INDEX );
1999 return 0;
2001 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
2002 /* Special case for dialog window procedure */
2003 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2004 retvalue = (LONG)WINPROC_GetProc( (WNDPROC)retvalue, type );
2005 WIN_ReleasePtr( wndPtr );
2006 return retvalue;
2009 switch(offset)
2011 case GWL_USERDATA: retvalue = wndPtr->userdata; break;
2012 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
2013 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
2014 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu; break;
2015 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc, type ); break;
2016 case GWL_HINSTANCE: retvalue = (LONG)wndPtr->hInstance; break;
2017 default:
2018 WARN("Unknown offset %d\n", offset );
2019 SetLastError( ERROR_INVALID_INDEX );
2020 break;
2022 WIN_ReleasePtr(wndPtr);
2023 return retvalue;
2027 /**********************************************************************
2028 * WIN_SetWindowLong
2030 * Helper function for SetWindowLong().
2032 * 0 is the failure code. However, in the case of failure SetLastError
2033 * must be set to distinguish between a 0 return value and a failure.
2035 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
2036 WINDOWPROCTYPE type )
2038 STYLESTRUCT style;
2039 BOOL ok;
2040 LONG retval = 0;
2041 WND *wndPtr;
2043 TRACE( "%p %d %lx %x\n", hwnd, offset, newval, type );
2045 if (is_broadcast(hwnd))
2047 SetLastError( ERROR_INVALID_PARAMETER );
2048 return FALSE;
2050 if (!WIN_IsCurrentProcess( hwnd ))
2052 if (offset == GWL_WNDPROC)
2054 SetLastError( ERROR_ACCESS_DENIED );
2055 return 0;
2057 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
2060 wndPtr = WIN_GetPtr( hwnd );
2061 if (wndPtr->hwndSelf == GetDesktopWindow())
2063 /* can't change anything on the desktop window */
2064 WIN_ReleasePtr( wndPtr );
2065 SetLastError( ERROR_ACCESS_DENIED );
2066 return 0;
2069 /* first some special cases */
2070 switch( offset )
2072 case GWL_STYLE:
2073 case GWL_EXSTYLE:
2074 style.styleOld =
2075 offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
2076 style.styleNew = newval;
2077 WIN_ReleasePtr( wndPtr );
2078 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
2079 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
2080 newval = style.styleNew;
2081 break;
2082 case GWL_HWNDPARENT:
2083 if (wndPtr->parent == GetDesktopWindow())
2085 WIN_ReleasePtr( wndPtr );
2086 return (LONG)WIN_SetOwner( hwnd, (HWND)newval );
2088 else
2090 WIN_ReleasePtr( wndPtr );
2091 return (LONG)SetParent( hwnd, (HWND)newval );
2093 case GWL_WNDPROC:
2094 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2095 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC)newval, type, WIN_PROC_WINDOW );
2096 WIN_ReleasePtr( wndPtr );
2097 return retval;
2098 case GWL_ID:
2099 case GWL_HINSTANCE:
2100 case GWL_USERDATA:
2101 break;
2102 case DWL_DLGPROC:
2103 if ((wndPtr->cbWndExtra + sizeof(LONG) >= DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2105 WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWL_DLGPROC);
2106 retval = (LONG)WINPROC_GetProc( *ptr, type );
2107 WINPROC_SetProc( ptr, (WNDPROC)newval, type, WIN_PROC_WINDOW );
2108 WIN_ReleasePtr( wndPtr );
2109 return retval;
2111 /* fall through */
2112 default:
2113 if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
2115 WARN("Invalid offset %d\n", offset );
2116 WIN_ReleasePtr( wndPtr );
2117 SetLastError( ERROR_INVALID_INDEX );
2118 return 0;
2120 else
2122 LONG *ptr = (LONG *)((char *)wndPtr->wExtra + offset);
2123 if (*ptr == newval) /* already set to the same value */
2125 WIN_ReleasePtr( wndPtr );
2126 return newval;
2129 break;
2132 SERVER_START_REQ( set_window_info )
2134 req->handle = hwnd;
2135 req->extra_offset = -1;
2136 switch(offset)
2138 case GWL_STYLE:
2139 req->flags = SET_WIN_STYLE;
2140 req->style = newval;
2141 break;
2142 case GWL_EXSTYLE:
2143 req->flags = SET_WIN_EXSTYLE;
2144 req->ex_style = newval;
2145 break;
2146 case GWL_ID:
2147 req->flags = SET_WIN_ID;
2148 req->id = newval;
2149 break;
2150 case GWL_HINSTANCE:
2151 req->flags = SET_WIN_INSTANCE;
2152 req->instance = (void *)newval;
2153 break;
2154 case GWL_USERDATA:
2155 req->flags = SET_WIN_USERDATA;
2156 req->user_data = (void *)newval;
2157 break;
2158 default:
2159 req->flags = SET_WIN_EXTRA;
2160 req->extra_offset = offset;
2161 req->extra_size = sizeof(newval);
2162 memcpy( &req->extra_value, &newval, sizeof(newval) );
2164 if ((ok = !wine_server_call_err( req )))
2166 switch(offset)
2168 case GWL_STYLE:
2169 wndPtr->dwStyle = newval;
2170 retval = reply->old_style;
2171 break;
2172 case GWL_EXSTYLE:
2173 wndPtr->dwExStyle = newval;
2174 retval = reply->old_ex_style;
2175 break;
2176 case GWL_ID:
2177 wndPtr->wIDmenu = newval;
2178 retval = reply->old_id;
2179 break;
2180 case GWL_HINSTANCE:
2181 wndPtr->hInstance = (HINSTANCE)newval;
2182 retval = (ULONG_PTR)reply->old_instance;
2183 break;
2184 case GWL_USERDATA:
2185 wndPtr->userdata = newval;
2186 retval = (ULONG_PTR)reply->old_user_data;
2187 break;
2188 default:
2190 void *ptr = (char *)wndPtr->wExtra + offset;
2191 memcpy( &retval, ptr, sizeof(retval) );
2192 memcpy( ptr, &newval, sizeof(newval) );
2194 break;
2198 SERVER_END_REQ;
2199 WIN_ReleasePtr( wndPtr );
2201 if (!ok) return 0;
2203 if (offset == GWL_STYLE && USER_Driver.pSetWindowStyle)
2204 USER_Driver.pSetWindowStyle( hwnd, retval );
2206 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2207 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2209 return retval;
2213 /**********************************************************************
2214 * GetWindowLong (USER.135)
2216 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2218 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
2222 /**********************************************************************
2223 * GetWindowLongA (USER32.@)
2225 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2227 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2231 /**********************************************************************
2232 * GetWindowLongW (USER32.@)
2234 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2236 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2240 /**********************************************************************
2241 * SetWindowLong (USER.136)
2243 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2245 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
2249 /**********************************************************************
2250 * SetWindowLongA (USER32.@)
2252 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2254 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2258 /**********************************************************************
2259 * SetWindowLongW (USER32.@) Set window attribute
2261 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2262 * value in a window's extra memory.
2264 * The _hwnd_ parameter specifies the window. is the handle to a
2265 * window that has extra memory. The _newval_ parameter contains the
2266 * new attribute or extra memory value. If positive, the _offset_
2267 * parameter is the byte-addressed location in the window's extra
2268 * memory to set. If negative, _offset_ specifies the window
2269 * attribute to set, and should be one of the following values:
2271 * GWL_EXSTYLE The window's extended window style
2273 * GWL_STYLE The window's window style.
2275 * GWL_WNDPROC Pointer to the window's window procedure.
2277 * GWL_HINSTANCE The window's pplication instance handle.
2279 * GWL_ID The window's identifier.
2281 * GWL_USERDATA The window's user-specified data.
2283 * If the window is a dialog box, the _offset_ parameter can be one of
2284 * the following values:
2286 * DWL_DLGPROC The address of the window's dialog box procedure.
2288 * DWL_MSGRESULT The return value of a message
2289 * that the dialog box procedure processed.
2291 * DWL_USER Application specific information.
2293 * RETURNS
2295 * If successful, returns the previous value located at _offset_. Otherwise,
2296 * returns 0.
2298 * NOTES
2300 * Extra memory for a window class is specified by a nonzero cbWndExtra
2301 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2302 * time of class creation.
2304 * Using GWL_WNDPROC to set a new window procedure effectively creates
2305 * a window subclass. Use CallWindowProc() in the new windows procedure
2306 * to pass messages to the superclass's window procedure.
2308 * The user data is reserved for use by the application which created
2309 * the window.
2311 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2312 * instead, call the EnableWindow() function to change the window's
2313 * disabled state.
2315 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2316 * SetParent() instead.
2318 * Win95:
2319 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2320 * it sends WM_STYLECHANGING before changing the settings
2321 * and WM_STYLECHANGED afterwards.
2322 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2324 LONG WINAPI SetWindowLongW(
2325 HWND hwnd, /* [in] window to alter */
2326 INT offset, /* [in] offset, in bytes, of location to alter */
2327 LONG newval /* [in] new value of location */
2329 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2333 /*******************************************************************
2334 * GetWindowTextA (USER32.@)
2336 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2338 WCHAR *buffer;
2340 if (WIN_IsCurrentProcess( hwnd ))
2341 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2343 /* when window belongs to other process, don't send a message */
2344 if (nMaxCount <= 0) return 0;
2345 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2346 get_server_window_text( hwnd, buffer, nMaxCount );
2347 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2348 lpString[nMaxCount-1] = 0;
2349 HeapFree( GetProcessHeap(), 0, buffer );
2350 return strlen(lpString);
2354 /*******************************************************************
2355 * InternalGetWindowText (USER32.@)
2357 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2359 WND *win;
2361 if (nMaxCount <= 0) return 0;
2362 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2363 if (win != WND_OTHER_PROCESS)
2365 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2366 else lpString[0] = 0;
2367 WIN_ReleasePtr( win );
2369 else
2371 get_server_window_text( hwnd, lpString, nMaxCount );
2373 return strlenW(lpString);
2377 /*******************************************************************
2378 * GetWindowTextW (USER32.@)
2380 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2382 if (WIN_IsCurrentProcess( hwnd ))
2383 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2385 /* when window belongs to other process, don't send a message */
2386 if (nMaxCount <= 0) return 0;
2387 get_server_window_text( hwnd, lpString, nMaxCount );
2388 return strlenW(lpString);
2392 /*******************************************************************
2393 * SetWindowText (USER32.@)
2394 * SetWindowTextA (USER32.@)
2396 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2398 if (is_broadcast(hwnd))
2400 SetLastError( ERROR_INVALID_PARAMETER );
2401 return FALSE;
2403 if (!WIN_IsCurrentProcess( hwnd ))
2405 FIXME( "cannot set text %s of other process window %p\n", debugstr_a(lpString), hwnd );
2406 SetLastError( ERROR_ACCESS_DENIED );
2407 return FALSE;
2409 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2413 /*******************************************************************
2414 * SetWindowTextW (USER32.@)
2416 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2418 if (is_broadcast(hwnd))
2420 SetLastError( ERROR_INVALID_PARAMETER );
2421 return FALSE;
2423 if (!WIN_IsCurrentProcess( hwnd ))
2425 FIXME( "cannot set text %s of other process window %p\n", debugstr_w(lpString), hwnd );
2426 SetLastError( ERROR_ACCESS_DENIED );
2427 return FALSE;
2429 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2433 /*******************************************************************
2434 * GetWindowTextLengthA (USER32.@)
2436 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2438 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2441 /*******************************************************************
2442 * GetWindowTextLengthW (USER32.@)
2444 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2446 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2450 /*******************************************************************
2451 * IsWindow (USER32.@)
2453 BOOL WINAPI IsWindow( HWND hwnd )
2455 WND *ptr;
2456 BOOL ret;
2458 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2460 if (ptr != WND_OTHER_PROCESS)
2462 WIN_ReleasePtr( ptr );
2463 return TRUE;
2466 /* check other processes */
2467 SERVER_START_REQ( get_window_info )
2469 req->handle = hwnd;
2470 ret = !wine_server_call_err( req );
2472 SERVER_END_REQ;
2473 return ret;
2477 /***********************************************************************
2478 * GetWindowThreadProcessId (USER32.@)
2480 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2482 WND *ptr;
2483 DWORD tid = 0;
2485 if (!(ptr = WIN_GetPtr( hwnd )))
2487 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2488 return 0;
2491 if (ptr != WND_OTHER_PROCESS)
2493 /* got a valid window */
2494 tid = ptr->tid;
2495 if (process) *process = GetCurrentProcessId();
2496 WIN_ReleasePtr( ptr );
2497 return tid;
2500 /* check other processes */
2501 SERVER_START_REQ( get_window_info )
2503 req->handle = hwnd;
2504 if (!wine_server_call_err( req ))
2506 tid = (DWORD)reply->tid;
2507 if (process) *process = (DWORD)reply->pid;
2510 SERVER_END_REQ;
2511 return tid;
2515 /*****************************************************************
2516 * GetParent (USER32.@)
2518 HWND WINAPI GetParent( HWND hwnd )
2520 WND *wndPtr;
2521 HWND retvalue = 0;
2523 if (!(wndPtr = WIN_GetPtr( hwnd )))
2525 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2526 return 0;
2528 if (wndPtr == WND_OTHER_PROCESS)
2530 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2531 if (style & (WS_POPUP | WS_CHILD))
2533 SERVER_START_REQ( get_window_tree )
2535 req->handle = hwnd;
2536 if (!wine_server_call_err( req ))
2538 if (style & WS_POPUP) retvalue = reply->owner;
2539 else if (style & WS_CHILD) retvalue = reply->parent;
2542 SERVER_END_REQ;
2545 else
2547 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2548 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2549 WIN_ReleasePtr( wndPtr );
2551 return retvalue;
2555 /*****************************************************************
2556 * GetAncestor (USER32.@)
2558 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2560 WND *win;
2561 HWND *list, ret = 0;
2563 switch(type)
2565 case GA_PARENT:
2566 if (!(win = WIN_GetPtr( hwnd )))
2568 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2569 return 0;
2571 if (win != WND_OTHER_PROCESS)
2573 ret = win->parent;
2574 WIN_ReleasePtr( win );
2576 else /* need to query the server */
2578 SERVER_START_REQ( get_window_tree )
2580 req->handle = hwnd;
2581 if (!wine_server_call_err( req )) ret = reply->parent;
2583 SERVER_END_REQ;
2585 break;
2587 case GA_ROOT:
2588 if (!(list = WIN_ListParents( hwnd ))) return 0;
2590 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2591 else
2593 int count = 2;
2594 while (list[count]) count++;
2595 ret = list[count - 2]; /* get the one before the desktop */
2597 HeapFree( GetProcessHeap(), 0, list );
2598 break;
2600 case GA_ROOTOWNER:
2601 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2602 for (;;)
2604 HWND parent = GetParent( ret );
2605 if (!parent) break;
2606 ret = parent;
2608 break;
2610 return ret;
2614 /*****************************************************************
2615 * SetParent (USER32.@)
2617 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2619 WND *wndPtr;
2620 HWND retvalue, full_handle;
2621 BOOL was_visible;
2623 if (is_broadcast(hwnd) || is_broadcast(parent))
2625 SetLastError(ERROR_INVALID_PARAMETER);
2626 return 0;
2629 if (!parent) parent = GetDesktopWindow();
2630 else parent = WIN_GetFullHandle( parent );
2632 if (!IsWindow( parent ))
2634 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2635 return 0;
2638 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2639 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2641 hwnd = full_handle;
2643 if (USER_Driver.pSetParent)
2644 return USER_Driver.pSetParent( hwnd, parent );
2646 /* Windows hides the window first, then shows it again
2647 * including the WM_SHOWWINDOW messages and all */
2648 was_visible = ShowWindow( hwnd, SW_HIDE );
2650 if (!IsWindow( parent )) return 0;
2651 if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return 0;
2653 retvalue = wndPtr->parent; /* old parent */
2654 if (parent != retvalue)
2656 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2658 if (parent != GetDesktopWindow()) /* a child window */
2660 if (!(wndPtr->dwStyle & WS_CHILD))
2662 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
2663 if (menu) DestroyMenu( menu );
2667 WIN_ReleasePtr( wndPtr );
2669 /* SetParent additionally needs to make hwnd the topmost window
2670 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2671 WM_WINDOWPOSCHANGED notification messages.
2673 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2674 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2675 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2676 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2677 return retvalue;
2681 /*******************************************************************
2682 * IsChild (USER32.@)
2684 BOOL WINAPI IsChild( HWND parent, HWND child )
2686 HWND *list = WIN_ListParents( child );
2687 int i;
2688 BOOL ret;
2690 if (!list) return FALSE;
2691 parent = WIN_GetFullHandle( parent );
2692 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2693 ret = (list[i] != 0);
2694 HeapFree( GetProcessHeap(), 0, list );
2695 return ret;
2699 /***********************************************************************
2700 * IsWindowVisible (USER32.@)
2702 BOOL WINAPI IsWindowVisible( HWND hwnd )
2704 HWND *list;
2705 BOOL retval;
2706 int i;
2708 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2709 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2710 for (i = 0; list[i]; i++)
2711 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2712 retval = !list[i];
2713 HeapFree( GetProcessHeap(), 0, list );
2714 return retval;
2718 /***********************************************************************
2719 * WIN_IsWindowDrawable
2721 * hwnd is drawable when it is visible, all parents are not
2722 * minimized, and it is itself not minimized unless we are
2723 * trying to draw its default class icon.
2725 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2727 HWND *list;
2728 BOOL retval;
2729 int i;
2730 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2732 if (!(style & WS_VISIBLE)) return FALSE;
2733 if ((style & WS_MINIMIZE) && icon && GetClassLongA( hwnd, GCL_HICON )) return FALSE;
2735 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2736 for (i = 0; list[i]; i++)
2737 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2738 break;
2739 retval = !list[i];
2740 HeapFree( GetProcessHeap(), 0, list );
2741 return retval;
2745 /*******************************************************************
2746 * GetTopWindow (USER32.@)
2748 HWND WINAPI GetTopWindow( HWND hwnd )
2750 if (!hwnd) hwnd = GetDesktopWindow();
2751 return GetWindow( hwnd, GW_CHILD );
2755 /*******************************************************************
2756 * GetWindow (USER32.@)
2758 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2760 HWND retval = 0;
2762 if (rel == GW_OWNER) /* this one may be available locally */
2764 WND *wndPtr = WIN_GetPtr( hwnd );
2765 if (!wndPtr)
2767 SetLastError( ERROR_INVALID_HANDLE );
2768 return 0;
2770 if (wndPtr != WND_OTHER_PROCESS)
2772 retval = wndPtr->owner;
2773 WIN_ReleasePtr( wndPtr );
2774 return retval;
2776 /* else fall through to server call */
2779 SERVER_START_REQ( get_window_tree )
2781 req->handle = hwnd;
2782 if (!wine_server_call_err( req ))
2784 switch(rel)
2786 case GW_HWNDFIRST:
2787 retval = reply->first_sibling;
2788 break;
2789 case GW_HWNDLAST:
2790 retval = reply->last_sibling;
2791 break;
2792 case GW_HWNDNEXT:
2793 retval = reply->next_sibling;
2794 break;
2795 case GW_HWNDPREV:
2796 retval = reply->prev_sibling;
2797 break;
2798 case GW_OWNER:
2799 retval = reply->owner;
2800 break;
2801 case GW_CHILD:
2802 retval = reply->first_child;
2803 break;
2807 SERVER_END_REQ;
2808 return retval;
2812 /***********************************************************************
2813 * WIN_InternalShowOwnedPopups
2815 * Internal version of ShowOwnedPopups; Wine functions should use this
2816 * to avoid interfering with application calls to ShowOwnedPopups
2817 * and to make sure the application can't prevent showing/hiding.
2819 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2823 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2825 int count = 0;
2826 WND *pWnd;
2827 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2829 if (!win_array) return TRUE;
2832 * Show windows Lowest first, Highest last to preserve Z-Order
2834 while (win_array[count]) count++;
2835 while (--count >= 0)
2837 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2838 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2840 if (pWnd->dwStyle & WS_POPUP)
2842 if (fShow)
2844 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2845 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
2848 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2850 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2851 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2854 else
2856 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2857 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2858 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2861 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2863 ShowWindow(pWnd->hwndSelf,SW_HIDE);
2864 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2865 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
2869 WIN_ReleaseWndPtr( pWnd );
2871 HeapFree( GetProcessHeap(), 0, win_array );
2873 return TRUE;
2876 /*******************************************************************
2877 * ShowOwnedPopups (USER32.@)
2879 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2881 int count = 0;
2882 WND *pWnd;
2883 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2885 if (!win_array) return TRUE;
2887 while (win_array[count]) count++;
2888 while (--count >= 0)
2890 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2891 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2893 if (pWnd->dwStyle & WS_POPUP)
2895 if (fShow)
2897 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2899 /* In Windows, ShowOwnedPopups(TRUE) generates
2900 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2901 * regardless of the state of the owner
2903 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2904 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2907 else
2909 if (IsWindowVisible(pWnd->hwndSelf))
2911 /* In Windows, ShowOwnedPopups(FALSE) generates
2912 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2913 * regardless of the state of the owner
2915 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2916 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2920 WIN_ReleaseWndPtr( pWnd );
2922 HeapFree( GetProcessHeap(), 0, win_array );
2923 return TRUE;
2927 /*******************************************************************
2928 * GetLastActivePopup (USER32.@)
2930 HWND WINAPI GetLastActivePopup( HWND hwnd )
2932 HWND retval = hwnd;
2934 SERVER_START_REQ( get_window_info )
2936 req->handle = hwnd;
2937 if (!wine_server_call_err( req )) retval = reply->last_active;
2939 SERVER_END_REQ;
2940 return retval;
2944 /*******************************************************************
2945 * WIN_ListParents
2947 * Build an array of all parents of a given window, starting with
2948 * the immediate parent. The array must be freed with HeapFree.
2949 * Returns NULL if window is a top-level window.
2951 HWND *WIN_ListParents( HWND hwnd )
2953 WND *win;
2954 HWND current, *list;
2955 int pos = 0, size = 16, count = 0;
2957 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2959 current = hwnd;
2960 for (;;)
2962 if (!(win = WIN_GetPtr( current ))) goto empty;
2963 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
2964 list[pos] = win->parent;
2965 WIN_ReleasePtr( win );
2966 if (!(current = list[pos]))
2968 if (!pos) goto empty;
2969 return list;
2971 if (++pos == size - 1)
2973 /* need to grow the list */
2974 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
2975 if (!new_list) goto empty;
2976 list = new_list;
2977 size += 16;
2981 /* at least one parent belongs to another process, have to query the server */
2983 for (;;)
2985 count = 0;
2986 SERVER_START_REQ( get_window_parents )
2988 req->handle = hwnd;
2989 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
2990 if (!wine_server_call( req )) count = reply->count;
2992 SERVER_END_REQ;
2993 if (!count) goto empty;
2994 if (size > count)
2996 list[count] = 0;
2997 return list;
2999 HeapFree( GetProcessHeap(), 0, list );
3000 size = count + 1;
3001 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
3004 empty:
3005 HeapFree( GetProcessHeap(), 0, list );
3006 return NULL;
3010 /*******************************************************************
3011 * WIN_ListChildren
3013 * Build an array of the children of a given window. The array must be
3014 * freed with HeapFree. Returns NULL when no windows are found.
3016 HWND *WIN_ListChildren( HWND hwnd )
3018 return list_window_children( hwnd, 0, 0 );
3022 /*******************************************************************
3023 * EnumWindows (USER32.@)
3025 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
3027 HWND *list;
3028 BOOL ret = TRUE;
3029 int i, iWndsLocks;
3031 /* We have to build a list of all windows first, to avoid */
3032 /* unpleasant side-effects, for instance if the callback */
3033 /* function changes the Z-order of the windows. */
3035 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
3037 /* Now call the callback function for every window */
3039 iWndsLocks = WIN_SuspendWndsLock();
3040 for (i = 0; list[i]; i++)
3042 /* Make sure that the window still exists */
3043 if (!IsWindow( list[i] )) continue;
3044 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
3046 WIN_RestoreWndsLock(iWndsLocks);
3047 HeapFree( GetProcessHeap(), 0, list );
3048 return ret;
3052 /**********************************************************************
3053 * EnumThreadWindows (USER32.@)
3055 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
3057 HWND *list;
3058 int i, iWndsLocks;
3060 if (!(list = list_window_children( GetDesktopWindow(), 0, id ))) return TRUE;
3062 /* Now call the callback function for every window */
3064 iWndsLocks = WIN_SuspendWndsLock();
3065 for (i = 0; list[i]; i++)
3066 if (!func( list[i], lParam )) break;
3067 WIN_RestoreWndsLock(iWndsLocks);
3068 HeapFree( GetProcessHeap(), 0, list );
3069 return TRUE;
3073 /**********************************************************************
3074 * WIN_EnumChildWindows
3076 * Helper function for EnumChildWindows().
3078 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
3080 HWND *childList;
3081 BOOL ret = FALSE;
3083 for ( ; *list; list++)
3085 /* Make sure that the window still exists */
3086 if (!IsWindow( *list )) continue;
3087 /* skip owned windows */
3088 if (GetWindow( *list, GW_OWNER )) continue;
3089 /* Build children list first */
3090 childList = WIN_ListChildren( *list );
3092 ret = func( *list, lParam );
3094 if (childList)
3096 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
3097 HeapFree( GetProcessHeap(), 0, childList );
3099 if (!ret) return FALSE;
3101 return TRUE;
3105 /**********************************************************************
3106 * EnumChildWindows (USER32.@)
3108 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
3110 HWND *list;
3111 int iWndsLocks;
3113 if (!(list = WIN_ListChildren( parent ))) return FALSE;
3114 iWndsLocks = WIN_SuspendWndsLock();
3115 WIN_EnumChildWindows( list, func, lParam );
3116 WIN_RestoreWndsLock(iWndsLocks);
3117 HeapFree( GetProcessHeap(), 0, list );
3118 return TRUE;
3122 /*******************************************************************
3123 * AnyPopup (USER.52)
3125 BOOL16 WINAPI AnyPopup16(void)
3127 return AnyPopup();
3131 /*******************************************************************
3132 * AnyPopup (USER32.@)
3134 BOOL WINAPI AnyPopup(void)
3136 int i;
3137 BOOL retvalue;
3138 HWND *list = WIN_ListChildren( GetDesktopWindow() );
3140 if (!list) return FALSE;
3141 for (i = 0; list[i]; i++)
3143 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
3145 retvalue = (list[i] != 0);
3146 HeapFree( GetProcessHeap(), 0, list );
3147 return retvalue;
3151 /*******************************************************************
3152 * FlashWindow (USER32.@)
3154 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3156 WND *wndPtr = WIN_FindWndPtr(hWnd);
3158 TRACE("%p\n", hWnd);
3160 if (!wndPtr) return FALSE;
3161 hWnd = wndPtr->hwndSelf; /* make it a full handle */
3163 if (wndPtr->dwStyle & WS_MINIMIZE)
3165 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3167 HDC hDC = GetDC(hWnd);
3169 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM)hDC, 0 ))
3170 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
3172 ReleaseDC( hWnd, hDC );
3173 wndPtr->flags |= WIN_NCACTIVATED;
3175 else
3177 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3178 wndPtr->flags &= ~WIN_NCACTIVATED;
3180 WIN_ReleaseWndPtr(wndPtr);
3181 return TRUE;
3183 else
3185 WPARAM16 wparam;
3186 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3187 else wparam = (hWnd == GetForegroundWindow());
3189 WIN_ReleaseWndPtr(wndPtr);
3190 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3191 return wparam;
3195 /*******************************************************************
3196 * FlashWindowEx (USER32.@)
3198 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
3200 FIXME("%p\n", pfwi);
3201 return TRUE;
3204 /*******************************************************************
3205 * GetWindowContextHelpId (USER32.@)
3207 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3209 DWORD retval;
3210 WND *wnd = WIN_FindWndPtr( hwnd );
3211 if (!wnd) return 0;
3212 retval = wnd->helpContext;
3213 WIN_ReleaseWndPtr(wnd);
3214 return retval;
3218 /*******************************************************************
3219 * SetWindowContextHelpId (USER32.@)
3221 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3223 WND *wnd = WIN_FindWndPtr( hwnd );
3224 if (!wnd) return FALSE;
3225 wnd->helpContext = id;
3226 WIN_ReleaseWndPtr(wnd);
3227 return TRUE;
3231 /*******************************************************************
3232 * DragDetect (USER32.@)
3234 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3236 MSG msg;
3237 RECT rect;
3239 rect.left = pt.x - wDragWidth;
3240 rect.right = pt.x + wDragWidth;
3242 rect.top = pt.y - wDragHeight;
3243 rect.bottom = pt.y + wDragHeight;
3245 SetCapture(hWnd);
3247 while(1)
3249 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3251 if( msg.message == WM_LBUTTONUP )
3253 ReleaseCapture();
3254 return 0;
3256 if( msg.message == WM_MOUSEMOVE )
3258 POINT tmp;
3259 tmp.x = LOWORD(msg.lParam);
3260 tmp.y = HIWORD(msg.lParam);
3261 if( !PtInRect( &rect, tmp ))
3263 ReleaseCapture();
3264 return 1;
3268 WaitMessage();
3270 return 0;
3273 /******************************************************************************
3274 * GetWindowModuleFileNameA (USER32.@)
3276 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3278 FIXME("GetWindowModuleFileNameA(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3279 hwnd, lpszFileName, cchFileNameMax);
3280 return 0;
3283 /******************************************************************************
3284 * GetWindowModuleFileNameW (USER32.@)
3286 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR lpszFileName, UINT cchFileNameMax)
3288 FIXME("GetWindowModuleFileNameW(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3289 hwnd, lpszFileName, cchFileNameMax);
3290 return 0;
3293 /******************************************************************************
3294 * GetWindowInfo (USER32.@)
3295 * hwnd: in
3296 * pwi: out.
3297 * MS Documentation mentions that pwi->cbSize must be set to SIZEOF(WINDOWINFO)
3298 * this may be because this structure changed over time. If this is the
3299 * the case, then please: FIXME.
3300 * Using the structure described in MSDN for 98/ME/NT(4.0 SP3)/2000/XP.
3302 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3304 if (!pwi) return FALSE;
3305 if (pwi->cbSize != sizeof(WINDOWINFO))
3307 FIXME("windowinfo->cbSize != sizeof(WINDOWINFO). Please report\n");
3308 return FALSE;
3310 if (!IsWindow(hwnd)) return FALSE;
3312 GetWindowRect(hwnd, &pwi->rcWindow);
3313 GetClientRect(hwnd, &pwi->rcClient);
3314 /* translate to screen coordinates */
3315 MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3317 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3318 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3319 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3321 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3322 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3324 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3325 pwi->wCreatorVersion = 0x0400;
3327 return TRUE;