Prevent false matches in WIN_FindWindow.
[wine/wine-gecko.git] / windows / win.c
blob6dc7baf7a841f1c9c74017a2563d1ee7a3dd293f
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 (type == WIN_PROC_16) instance = HINSTANCE_32(GetExePtr(HINSTANCE_16(instance)));
76 SERVER_START_REQ( create_window )
78 req->parent = parent;
79 req->owner = owner;
80 req->atom = atom;
81 req->instance = instance;
82 if (!wine_server_call_err( req ))
84 handle = reply->handle;
85 extra_bytes = reply->extra;
86 class = reply->class_ptr;
89 SERVER_END_REQ;
91 if (!handle)
93 WARN( "error %ld creating window\n", GetLastError() );
94 return NULL;
97 if (!(win = HeapAlloc( GetProcessHeap(), 0, sizeof(WND) + extra_bytes - sizeof(win->wExtra) )))
99 SERVER_START_REQ( destroy_window )
101 req->handle = handle;
102 wine_server_call( req );
104 SERVER_END_REQ;
105 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
106 return NULL;
109 USER_Lock();
111 index = LOWORD(handle) - FIRST_USER_HANDLE;
112 assert( index < NB_USER_HANDLES );
113 user_handles[index] = win;
114 win->hwndSelf = handle;
115 win->dwMagic = WND_MAGIC;
116 win->irefCount = 1;
117 win->cbWndExtra = extra_bytes;
118 memset( win->wExtra, 0, extra_bytes );
119 CLASS_AddWindow( class, win, type );
120 return win;
124 /***********************************************************************
125 * free_window_handle
127 * Free a window handle.
129 static WND *free_window_handle( HWND hwnd )
131 WND *ptr;
132 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
134 if (index >= NB_USER_HANDLES) return NULL;
135 USER_Lock();
136 if ((ptr = user_handles[index]))
138 SERVER_START_REQ( destroy_window )
140 req->handle = hwnd;
141 if (!wine_server_call_err( req ))
142 user_handles[index] = NULL;
143 else
144 ptr = NULL;
146 SERVER_END_REQ;
148 USER_Unlock();
149 if (ptr) HeapFree( GetProcessHeap(), 0, ptr );
150 return ptr;
154 /*******************************************************************
155 * list_window_children
157 * Build an array of the children of a given window. The array must be
158 * freed with HeapFree. Returns NULL when no windows are found.
160 static HWND *list_window_children( HWND hwnd, ATOM atom, DWORD tid )
162 HWND *list;
163 int size = 32;
165 for (;;)
167 int count = 0;
169 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
171 SERVER_START_REQ( get_window_children )
173 req->parent = hwnd;
174 req->atom = atom;
175 req->tid = tid;
176 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
177 if (!wine_server_call( req )) count = reply->count;
179 SERVER_END_REQ;
180 if (count && count < size)
182 list[count] = 0;
183 return list;
185 HeapFree( GetProcessHeap(), 0, list );
186 if (!count) break;
187 size = count + 1; /* restart with a large enough buffer */
189 return NULL;
193 /*******************************************************************
194 * send_parent_notify
196 static void send_parent_notify( HWND hwnd, UINT msg )
198 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD)) return;
199 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY) return;
200 SendMessageW( GetParent(hwnd), WM_PARENTNOTIFY,
201 MAKEWPARAM( msg, GetWindowLongW( hwnd, GWL_ID )), (LPARAM)hwnd );
205 /*******************************************************************
206 * get_server_window_text
208 * Retrieve the window text from the server.
210 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
212 size_t len = 0;
214 SERVER_START_REQ( get_window_text )
216 req->handle = hwnd;
217 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
218 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
220 SERVER_END_REQ;
221 text[len / sizeof(WCHAR)] = 0;
225 /***********************************************************************
226 * WIN_GetPtr
228 * Return a pointer to the WND structure if local to the process,
229 * or WND_OTHER_PROCESS if handle may be valid in other process.
230 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
232 WND *WIN_GetPtr( HWND hwnd )
234 WND * ptr;
235 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
237 if (index >= NB_USER_HANDLES) return NULL;
239 USER_Lock();
240 if ((ptr = user_handles[index]))
242 if (ptr->dwMagic == WND_MAGIC && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
243 return ptr;
244 ptr = NULL;
246 else ptr = WND_OTHER_PROCESS;
247 USER_Unlock();
248 return ptr;
252 /***********************************************************************
253 * WIN_IsCurrentProcess
255 * Check whether a given window belongs to the current process (and return the full handle).
257 HWND WIN_IsCurrentProcess( HWND hwnd )
259 WND *ptr;
260 HWND ret;
262 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS) return 0;
263 ret = ptr->hwndSelf;
264 WIN_ReleasePtr( ptr );
265 return ret;
269 /***********************************************************************
270 * WIN_IsCurrentThread
272 * Check whether a given window belongs to the current thread (and return the full handle).
274 HWND WIN_IsCurrentThread( HWND hwnd )
276 WND *ptr;
277 HWND ret = 0;
279 if ((ptr = WIN_GetPtr( hwnd )) && ptr != WND_OTHER_PROCESS)
281 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
282 WIN_ReleasePtr( ptr );
284 return ret;
288 /***********************************************************************
289 * WIN_Handle32
291 * Convert a 16-bit window handle to a full 32-bit handle.
293 HWND WIN_Handle32( HWND16 hwnd16 )
295 WND *ptr;
296 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
298 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
299 /* do sign extension for -2 and -3 */
300 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
302 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
304 if (ptr != WND_OTHER_PROCESS)
306 hwnd = ptr->hwndSelf;
307 WIN_ReleasePtr( ptr );
309 else /* may belong to another process */
311 SERVER_START_REQ( get_window_info )
313 req->handle = hwnd;
314 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
316 SERVER_END_REQ;
318 return hwnd;
322 /***********************************************************************
323 * WIN_FindWndPtr
325 * Return a pointer to the WND structure corresponding to a HWND.
327 WND * WIN_FindWndPtr( HWND hwnd )
329 WND * ptr;
331 if (!hwnd) return NULL;
333 if ((ptr = WIN_GetPtr( hwnd )))
335 if (ptr != WND_OTHER_PROCESS)
337 /* increment destruction monitoring */
338 ptr->irefCount++;
339 return ptr;
341 if (IsWindow( hwnd )) /* check other processes */
343 ERR( "window %p belongs to other process\n", hwnd );
344 /* DbgBreakPoint(); */
347 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
348 return NULL;
352 /***********************************************************************
353 * WIN_ReleaseWndPtr
355 * Release the pointer to the WND structure.
357 void WIN_ReleaseWndPtr(WND *wndPtr)
359 if(!wndPtr) return;
361 /* Decrement destruction monitoring value */
362 wndPtr->irefCount--;
363 /* Check if it's time to release the memory */
364 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
366 /* Release memory */
367 free_window_handle( wndPtr->hwndSelf );
369 else if(wndPtr->irefCount < 0)
371 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
372 ERR("forgot a Lock on %p somewhere\n",wndPtr);
374 /* unlock all WND structures for thread safeness */
375 USER_Unlock();
379 /***********************************************************************
380 * WIN_UnlinkWindow
382 * Remove a window from the siblings linked list.
384 void WIN_UnlinkWindow( HWND hwnd )
386 WIN_LinkWindow( hwnd, 0, 0 );
390 /***********************************************************************
391 * WIN_LinkWindow
393 * Insert a window into the siblings linked list.
394 * The window is inserted after the specified window, which can also
395 * be specified as HWND_TOP or HWND_BOTTOM.
396 * If parent is 0, window is unlinked from the tree.
398 void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
400 WND *wndPtr = WIN_GetPtr( hwnd );
402 if (!wndPtr) return;
403 if (wndPtr == WND_OTHER_PROCESS)
405 if (IsWindow(hwnd)) ERR(" cannot link other process window %p\n", hwnd );
406 return;
409 SERVER_START_REQ( link_window )
411 req->handle = hwnd;
412 req->parent = parent;
413 req->previous = hwndInsertAfter;
414 if (!wine_server_call( req ))
416 if (reply->full_parent) wndPtr->parent = reply->full_parent;
420 SERVER_END_REQ;
421 WIN_ReleasePtr( wndPtr );
425 /***********************************************************************
426 * WIN_SetOwner
428 * Change the owner of a window.
430 HWND WIN_SetOwner( HWND hwnd, HWND owner )
432 WND *win = WIN_GetPtr( hwnd );
433 HWND ret = 0;
435 if (!win) return 0;
436 if (win == WND_OTHER_PROCESS)
438 if (IsWindow(hwnd)) ERR( "cannot set owner %p on other process window %p\n", owner, hwnd );
439 return 0;
441 SERVER_START_REQ( set_window_owner )
443 req->handle = hwnd;
444 req->owner = owner;
445 if (!wine_server_call( req ))
447 win->owner = reply->full_owner;
448 ret = reply->prev_owner;
451 SERVER_END_REQ;
452 WIN_ReleasePtr( win );
453 return ret;
457 /***********************************************************************
458 * WIN_SetStyle
460 * Change the style of a window.
462 LONG WIN_SetStyle( HWND hwnd, LONG style )
464 BOOL ok;
465 LONG ret = 0;
466 WND *win = WIN_GetPtr( hwnd );
468 if (!win) return 0;
469 if (win == WND_OTHER_PROCESS)
471 if (IsWindow(hwnd))
472 ERR( "cannot set style %lx on other process window %p\n", style, hwnd );
473 return 0;
475 if (style == win->dwStyle)
477 WIN_ReleasePtr( win );
478 return style;
480 SERVER_START_REQ( set_window_info )
482 req->handle = hwnd;
483 req->flags = SET_WIN_STYLE;
484 req->style = style;
485 req->extra_offset = -1;
486 if ((ok = !wine_server_call( req )))
488 ret = reply->old_style;
489 win->dwStyle = style;
492 SERVER_END_REQ;
493 WIN_ReleasePtr( win );
494 if (ok && USER_Driver.pSetWindowStyle) USER_Driver.pSetWindowStyle( hwnd, ret );
495 return ret;
499 /***********************************************************************
500 * WIN_SetExStyle
502 * Change the extended style of a window.
504 LONG WIN_SetExStyle( HWND hwnd, LONG style )
506 LONG ret = 0;
507 WND *win = WIN_GetPtr( hwnd );
509 if (!win) return 0;
510 if (win == WND_OTHER_PROCESS)
512 if (IsWindow(hwnd))
513 ERR( "cannot set exstyle %lx on other process window %p\n", style, hwnd );
514 return 0;
516 if (style == win->dwExStyle)
518 WIN_ReleasePtr( win );
519 return style;
521 SERVER_START_REQ( set_window_info )
523 req->handle = hwnd;
524 req->flags = SET_WIN_EXSTYLE;
525 req->ex_style = style;
526 req->extra_offset = -1;
527 if (!wine_server_call( req ))
529 ret = reply->old_ex_style;
530 win->dwExStyle = style;
533 SERVER_END_REQ;
534 WIN_ReleasePtr( win );
535 return ret;
539 /***********************************************************************
540 * WIN_SetRectangles
542 * Set the window and client rectangles.
544 void WIN_SetRectangles( HWND hwnd, const RECT *rectWindow, const RECT *rectClient )
546 WND *win = WIN_GetPtr( hwnd );
547 BOOL ret;
549 if (!win) return;
550 if (win == WND_OTHER_PROCESS)
552 if (IsWindow( hwnd )) ERR( "cannot set rectangles of other process window %p\n", hwnd );
553 return;
555 SERVER_START_REQ( set_window_rectangles )
557 req->handle = hwnd;
558 req->window.left = rectWindow->left;
559 req->window.top = rectWindow->top;
560 req->window.right = rectWindow->right;
561 req->window.bottom = rectWindow->bottom;
562 req->client.left = rectClient->left;
563 req->client.top = rectClient->top;
564 req->client.right = rectClient->right;
565 req->client.bottom = rectClient->bottom;
566 ret = !wine_server_call( req );
568 SERVER_END_REQ;
569 if (ret)
571 win->rectWindow = *rectWindow;
572 win->rectClient = *rectClient;
574 TRACE( "win %p window (%ld,%ld)-(%ld,%ld) client (%ld,%ld)-(%ld,%ld)\n", hwnd,
575 rectWindow->left, rectWindow->top, rectWindow->right, rectWindow->bottom,
576 rectClient->left, rectClient->top, rectClient->right, rectClient->bottom );
578 WIN_ReleasePtr( win );
582 /***********************************************************************
583 * WIN_GetRectangles
585 * Get the window and client rectangles.
587 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
589 WND *win = WIN_GetPtr( hwnd );
590 BOOL ret = TRUE;
592 if (!win) return FALSE;
593 if (win == WND_OTHER_PROCESS)
595 SERVER_START_REQ( get_window_rectangles )
597 req->handle = hwnd;
598 if ((ret = !wine_server_call( req )))
600 if (rectWindow)
602 rectWindow->left = reply->window.left;
603 rectWindow->top = reply->window.top;
604 rectWindow->right = reply->window.right;
605 rectWindow->bottom = reply->window.bottom;
607 if (rectClient)
609 rectClient->left = reply->client.left;
610 rectClient->top = reply->client.top;
611 rectClient->right = reply->client.right;
612 rectClient->bottom = reply->client.bottom;
616 SERVER_END_REQ;
618 else
620 if (rectWindow) *rectWindow = win->rectWindow;
621 if (rectClient) *rectClient = win->rectClient;
622 WIN_ReleasePtr( win );
624 return ret;
628 /***********************************************************************
629 * WIN_DestroyWindow
631 * Destroy storage associated to a window. "Internals" p.358
633 LRESULT WIN_DestroyWindow( HWND hwnd )
635 WND *wndPtr;
636 HWND *list;
638 TRACE("%p\n", hwnd );
640 if (!(hwnd = WIN_IsCurrentThread( hwnd )))
642 ERR( "window doesn't belong to current thread\n" );
643 return 0;
646 /* free child windows */
647 if ((list = WIN_ListChildren( hwnd )))
649 int i;
650 for (i = 0; list[i]; i++)
652 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
653 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
655 HeapFree( GetProcessHeap(), 0, list );
659 * Clear the update region to make sure no WM_PAINT messages will be
660 * generated for this window while processing the WM_NCDESTROY.
662 RedrawWindow( hwnd, NULL, 0,
663 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
666 * Send the WM_NCDESTROY to the window being destroyed.
668 SendMessageA( hwnd, WM_NCDESTROY, 0, 0);
670 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
672 WINPOS_CheckInternalPos( hwnd );
673 if( hwnd == GetCapture()) ReleaseCapture();
675 /* free resources associated with the window */
677 TIMER_RemoveWindowTimers( hwnd );
679 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
681 if (!(wndPtr->dwStyle & WS_CHILD))
683 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
684 if (menu) DestroyMenu( menu );
686 if (wndPtr->hSysMenu)
688 DestroyMenu( wndPtr->hSysMenu );
689 wndPtr->hSysMenu = 0;
691 DCE_FreeWindowDCE( hwnd ); /* Always do this to catch orphaned DCs */
692 USER_Driver.pDestroyWindow( hwnd );
693 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
694 wndPtr->class = NULL;
695 wndPtr->dwMagic = 0; /* Mark it as invalid */
696 WIN_ReleaseWndPtr( wndPtr );
697 return 0;
700 /***********************************************************************
701 * WIN_DestroyThreadWindows
703 * Destroy all children of 'wnd' owned by the current thread.
704 * Return TRUE if something was done.
706 void WIN_DestroyThreadWindows( HWND hwnd )
708 HWND *list;
709 int i;
711 if (!(list = WIN_ListChildren( hwnd ))) return;
712 for (i = 0; list[i]; i++)
714 if (WIN_IsCurrentThread( list[i] ))
715 DestroyWindow( list[i] );
716 else
717 WIN_DestroyThreadWindows( list[i] );
719 HeapFree( GetProcessHeap(), 0, list );
722 /***********************************************************************
723 * WIN_CreateDesktopWindow
725 * Create the desktop window.
727 BOOL WIN_CreateDesktopWindow(void)
729 HWND hwndDesktop;
730 CREATESTRUCTA cs;
731 RECT rect;
733 TRACE("Creating desktop window\n");
735 if (!WINPOS_CreateInternalPosAtom()) return FALSE;
737 pWndDesktop = create_window_handle( 0, 0, LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W );
738 if (!pWndDesktop) return FALSE;
739 hwndDesktop = pWndDesktop->hwndSelf;
741 pWndDesktop->tid = 0; /* nobody owns the desktop */
742 pWndDesktop->parent = 0;
743 pWndDesktop->owner = 0;
744 pWndDesktop->text = NULL;
745 pWndDesktop->hrgnUpdate = 0;
746 pWndDesktop->pVScroll = NULL;
747 pWndDesktop->pHScroll = NULL;
748 pWndDesktop->helpContext = 0;
749 pWndDesktop->flags = 0;
750 pWndDesktop->hSysMenu = 0;
752 cs.lpCreateParams = NULL;
753 cs.hInstance = 0;
754 cs.hMenu = 0;
755 cs.hwndParent = 0;
756 cs.x = 0;
757 cs.y = 0;
758 cs.cx = GetSystemMetrics( SM_CXSCREEN );
759 cs.cy = GetSystemMetrics( SM_CYSCREEN );
760 cs.style = pWndDesktop->dwStyle;
761 cs.dwExStyle = pWndDesktop->dwExStyle;
762 cs.lpszName = NULL;
763 cs.lpszClass = DESKTOP_CLASS_ATOM;
765 SetRect( &rect, 0, 0, cs.cx, cs.cy );
766 WIN_SetRectangles( hwndDesktop, &rect, &rect );
768 SERVER_START_REQ( set_window_info )
770 req->handle = hwndDesktop;
771 req->flags = 0; /* don't set anything, just retrieve */
772 req->extra_offset = -1;
773 wine_server_call( req );
774 pWndDesktop->dwStyle = reply->old_style;
775 pWndDesktop->dwExStyle = reply->old_ex_style;
776 pWndDesktop->hInstance = (HINSTANCE)reply->old_instance;
777 pWndDesktop->userdata = (ULONG_PTR)reply->old_user_data;
778 pWndDesktop->wIDmenu = reply->old_id;
780 SERVER_END_REQ;
782 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE ))
784 WIN_ReleaseWndPtr( pWndDesktop );
785 return FALSE;
788 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
789 WIN_ReleaseWndPtr( pWndDesktop );
790 return TRUE;
794 /***********************************************************************
795 * WIN_FixCoordinates
797 * Fix the coordinates - Helper for WIN_CreateWindowEx.
798 * returns default show mode in sw.
799 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
801 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
803 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
804 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
806 if (cs->style & (WS_CHILD | WS_POPUP))
808 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
809 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
811 else /* overlapped window */
813 STARTUPINFOA info;
815 GetStartupInfoA( &info );
817 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
819 /* Never believe Microsoft's documentation... CreateWindowEx doc says
820 * that if an overlapped window is created with WS_VISIBLE style bit
821 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
822 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
823 * reveals that
825 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
826 * 2) it does not ignore the y parameter as the docs claim; instead, it
827 * uses it as second parameter to ShowWindow() unless y is either
828 * CW_USEDEFAULT or CW_USEDEFAULT16.
830 * The fact that we didn't do 2) caused bogus windows pop up when wine
831 * was running apps that were using this obscure feature. Example -
832 * calc.exe that comes with Win98 (only Win98, it's different from
833 * the one that comes with Win95 and NT)
835 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
836 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
837 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
840 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
842 if (info.dwFlags & STARTF_USESIZE)
844 cs->cx = info.dwXSize;
845 cs->cy = info.dwYSize;
847 else /* if no other hint from the app, pick 3/4 of the screen real estate */
849 RECT r;
850 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
851 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
852 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
857 else
859 /* neither x nor cx are default. Check the y values .
860 * In the trace we see Outlook and Outlook Express using
861 * cy set to CW_USEDEFAULT when opening the address book.
863 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16) {
864 RECT r;
865 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
866 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
867 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
872 /***********************************************************************
873 * dump_window_styles
875 static void dump_window_styles( DWORD style, DWORD exstyle )
877 TRACE( "style:" );
878 if(style & WS_POPUP) TRACE(" WS_POPUP");
879 if(style & WS_CHILD) TRACE(" WS_CHILD");
880 if(style & WS_MINIMIZE) TRACE(" WS_MINIMIZE");
881 if(style & WS_VISIBLE) TRACE(" WS_VISIBLE");
882 if(style & WS_DISABLED) TRACE(" WS_DISABLED");
883 if(style & WS_CLIPSIBLINGS) TRACE(" WS_CLIPSIBLINGS");
884 if(style & WS_CLIPCHILDREN) TRACE(" WS_CLIPCHILDREN");
885 if(style & WS_MAXIMIZE) TRACE(" WS_MAXIMIZE");
886 if((style & WS_CAPTION) == WS_CAPTION) TRACE(" WS_CAPTION");
887 else
889 if(style & WS_BORDER) TRACE(" WS_BORDER");
890 if(style & WS_DLGFRAME) TRACE(" WS_DLGFRAME");
892 if(style & WS_VSCROLL) TRACE(" WS_VSCROLL");
893 if(style & WS_HSCROLL) TRACE(" WS_HSCROLL");
894 if(style & WS_SYSMENU) TRACE(" WS_SYSMENU");
895 if(style & WS_THICKFRAME) TRACE(" WS_THICKFRAME");
896 if(style & WS_GROUP) TRACE(" WS_GROUP");
897 if(style & WS_TABSTOP) TRACE(" WS_TABSTOP");
898 if(style & WS_MINIMIZEBOX) TRACE(" WS_MINIMIZEBOX");
899 if(style & WS_MAXIMIZEBOX) TRACE(" WS_MAXIMIZEBOX");
901 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
902 #define DUMPED_STYLES \
903 (WS_POPUP | \
904 WS_CHILD | \
905 WS_MINIMIZE | \
906 WS_VISIBLE | \
907 WS_DISABLED | \
908 WS_CLIPSIBLINGS | \
909 WS_CLIPCHILDREN | \
910 WS_MAXIMIZE | \
911 WS_BORDER | \
912 WS_DLGFRAME | \
913 WS_VSCROLL | \
914 WS_HSCROLL | \
915 WS_SYSMENU | \
916 WS_THICKFRAME | \
917 WS_GROUP | \
918 WS_TABSTOP | \
919 WS_MINIMIZEBOX | \
920 WS_MAXIMIZEBOX)
922 if(style & ~DUMPED_STYLES) TRACE(" %08lx", style & ~DUMPED_STYLES);
923 TRACE("\n");
924 #undef DUMPED_STYLES
926 TRACE( "exstyle:" );
927 if(exstyle & WS_EX_DLGMODALFRAME) TRACE(" WS_EX_DLGMODALFRAME");
928 if(exstyle & WS_EX_DRAGDETECT) TRACE(" WS_EX_DRAGDETECT");
929 if(exstyle & WS_EX_NOPARENTNOTIFY) TRACE(" WS_EX_NOPARENTNOTIFY");
930 if(exstyle & WS_EX_TOPMOST) TRACE(" WS_EX_TOPMOST");
931 if(exstyle & WS_EX_ACCEPTFILES) TRACE(" WS_EX_ACCEPTFILES");
932 if(exstyle & WS_EX_TRANSPARENT) TRACE(" WS_EX_TRANSPARENT");
933 if(exstyle & WS_EX_MDICHILD) TRACE(" WS_EX_MDICHILD");
934 if(exstyle & WS_EX_TOOLWINDOW) TRACE(" WS_EX_TOOLWINDOW");
935 if(exstyle & WS_EX_WINDOWEDGE) TRACE(" WS_EX_WINDOWEDGE");
936 if(exstyle & WS_EX_CLIENTEDGE) TRACE(" WS_EX_CLIENTEDGE");
937 if(exstyle & WS_EX_CONTEXTHELP) TRACE(" WS_EX_CONTEXTHELP");
938 if(exstyle & WS_EX_RIGHT) TRACE(" WS_EX_RIGHT");
939 if(exstyle & WS_EX_RTLREADING) TRACE(" WS_EX_RTLREADING");
940 if(exstyle & WS_EX_LEFTSCROLLBAR) TRACE(" WS_EX_LEFTSCROLLBAR");
941 if(exstyle & WS_EX_CONTROLPARENT) TRACE(" WS_EX_CONTROLPARENT");
942 if(exstyle & WS_EX_STATICEDGE) TRACE(" WS_EX_STATICEDGE");
943 if(exstyle & WS_EX_APPWINDOW) TRACE(" WS_EX_APPWINDOW");
944 if(exstyle & WS_EX_LAYERED) TRACE(" WS_EX_LAYERED");
946 #define DUMPED_EX_STYLES \
947 (WS_EX_DLGMODALFRAME | \
948 WS_EX_DRAGDETECT | \
949 WS_EX_NOPARENTNOTIFY | \
950 WS_EX_TOPMOST | \
951 WS_EX_ACCEPTFILES | \
952 WS_EX_TRANSPARENT | \
953 WS_EX_MDICHILD | \
954 WS_EX_TOOLWINDOW | \
955 WS_EX_WINDOWEDGE | \
956 WS_EX_CLIENTEDGE | \
957 WS_EX_CONTEXTHELP | \
958 WS_EX_RIGHT | \
959 WS_EX_RTLREADING | \
960 WS_EX_LEFTSCROLLBAR | \
961 WS_EX_CONTROLPARENT | \
962 WS_EX_STATICEDGE | \
963 WS_EX_APPWINDOW | \
964 WS_EX_LAYERED)
966 if(exstyle & ~DUMPED_EX_STYLES) TRACE(" %08lx", exstyle & ~DUMPED_EX_STYLES);
967 TRACE("\n");
968 #undef DUMPED_EX_STYLES
972 /***********************************************************************
973 * WIN_CreateWindowEx
975 * Implementation of CreateWindowEx().
977 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
978 WINDOWPROCTYPE type )
980 INT sw = SW_SHOW;
981 WND *wndPtr;
982 HWND hwnd, parent, owner;
983 BOOL unicode = (type == WIN_PROC_32W);
985 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
986 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
987 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszClass) : debugstr_a(cs->lpszClass),
988 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
989 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
991 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
993 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
994 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
996 /* Find the parent window */
998 parent = GetDesktopWindow();
999 owner = 0;
1001 if (cs->hwndParent == HWND_MESSAGE)
1003 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
1004 * message window (style: WS_POPUP|WS_DISABLED)
1006 FIXME("Parent is HWND_MESSAGE\n");
1008 else if (cs->hwndParent)
1010 /* Make sure parent is valid */
1011 if (!IsWindow( cs->hwndParent ))
1013 WARN("Bad parent %p\n", cs->hwndParent );
1014 return 0;
1016 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1017 parent = WIN_GetFullHandle(cs->hwndParent);
1018 else
1019 owner = GetAncestor( cs->hwndParent, GA_ROOT );
1021 else if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1023 WARN("No parent for child window\n" );
1024 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1027 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
1029 /* Correct the window style - stage 1
1031 * These are patches that appear to affect both the style loaded into the
1032 * WIN structure and passed in the CreateStruct to the WM_CREATE etc.
1034 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1035 * why does the user get to set it?
1038 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
1039 * tested for WS_POPUP
1041 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
1042 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
1043 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
1044 cs->dwExStyle |= WS_EX_WINDOWEDGE;
1045 else
1046 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
1048 /* Create the window structure */
1050 if (!(wndPtr = create_window_handle( parent, owner, classAtom, cs->hInstance, type )))
1052 TRACE("out of memory\n" );
1053 return 0;
1055 hwnd = wndPtr->hwndSelf;
1057 /* Fill the window structure */
1059 wndPtr->tid = GetCurrentThreadId();
1060 wndPtr->owner = owner;
1061 wndPtr->parent = parent;
1062 wndPtr->hInstance = cs->hInstance;
1063 wndPtr->text = NULL;
1064 wndPtr->hrgnUpdate = 0;
1065 wndPtr->hrgnWnd = 0;
1066 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1067 wndPtr->dwExStyle = cs->dwExStyle;
1068 wndPtr->wIDmenu = 0;
1069 wndPtr->helpContext = 0;
1070 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
1071 wndPtr->pVScroll = NULL;
1072 wndPtr->pHScroll = NULL;
1073 wndPtr->userdata = 0;
1074 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU) ? MENU_GetSysMenu( hwnd, 0 ) : 0;
1076 /* Correct the window style - stage 2 */
1078 if (!(cs->style & WS_CHILD))
1080 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1081 if (!(cs->style & WS_POPUP))
1083 wndPtr->dwStyle |= WS_CAPTION;
1084 wndPtr->flags |= WIN_NEED_SIZE;
1087 SERVER_START_REQ( set_window_info )
1089 req->handle = hwnd;
1090 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE;
1091 req->style = wndPtr->dwStyle;
1092 req->ex_style = wndPtr->dwExStyle;
1093 req->instance = (void *)wndPtr->hInstance;
1094 req->extra_offset = -1;
1095 wine_server_call( req );
1097 SERVER_END_REQ;
1099 /* Get class or window DC if needed */
1101 if (wndPtr->clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
1103 /* Set the window menu */
1105 if (((wndPtr->dwStyle & (WS_CAPTION|WS_CHILD)) == WS_CAPTION) ||
1106 (wndPtr->dwExStyle & WS_EX_APPWINDOW))
1108 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
1109 else
1111 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
1112 if (menuName)
1114 if (HIWORD(cs->hInstance))
1115 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1116 else
1117 cs->hMenu = HMENU_32(LoadMenu16(HINSTANCE_16(cs->hInstance),menuName));
1119 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
1123 else SetWindowLongW( hwnd, GWL_ID, (UINT)cs->hMenu );
1124 WIN_ReleaseWndPtr( wndPtr );
1126 if (!USER_Driver.pCreateWindow( hwnd, cs, unicode))
1128 WIN_DestroyWindow( hwnd );
1129 return 0;
1132 /* Notify the parent window only */
1134 send_parent_notify( hwnd, WM_CREATE );
1135 if (!IsWindow( hwnd )) return 0;
1137 if (cs->style & WS_VISIBLE)
1139 /* in case WS_VISIBLE got set in the meantime */
1140 if (!(wndPtr = WIN_GetPtr( hwnd ))) return 0;
1141 WIN_SetStyle( hwnd, wndPtr->dwStyle & ~WS_VISIBLE );
1142 WIN_ReleasePtr( wndPtr );
1143 ShowWindow( hwnd, sw );
1146 /* Call WH_SHELL hook */
1148 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1149 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1151 TRACE("created window %p\n", hwnd);
1152 return hwnd;
1156 /***********************************************************************
1157 * CreateWindow (USER.41)
1159 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1160 DWORD style, INT16 x, INT16 y, INT16 width,
1161 INT16 height, HWND16 parent, HMENU16 menu,
1162 HINSTANCE16 instance, LPVOID data )
1164 return CreateWindowEx16( 0, className, windowName, style,
1165 x, y, width, height, parent, menu, instance, data );
1169 /***********************************************************************
1170 * CreateWindowEx (USER.452)
1172 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1173 LPCSTR windowName, DWORD style, INT16 x,
1174 INT16 y, INT16 width, INT16 height,
1175 HWND16 parent, HMENU16 menu,
1176 HINSTANCE16 instance, LPVOID data )
1178 ATOM classAtom;
1179 CREATESTRUCTA cs;
1180 char buffer[256];
1182 /* Find the class atom */
1184 if (HIWORD(className))
1186 if (!(classAtom = GlobalFindAtomA( className )))
1188 ERR( "bad class name %s\n", debugstr_a(className) );
1189 return 0;
1192 else
1194 classAtom = LOWORD(className);
1195 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1197 ERR( "bad atom %x\n", classAtom);
1198 return 0;
1200 className = buffer;
1203 /* Fix the coordinates */
1205 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1206 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1207 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1208 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1210 /* Create the window */
1212 cs.lpCreateParams = data;
1213 cs.hInstance = HINSTANCE_32(instance);
1214 cs.hMenu = HMENU_32(menu);
1215 cs.hwndParent = WIN_Handle32( parent );
1216 cs.style = style;
1217 cs.lpszName = windowName;
1218 cs.lpszClass = className;
1219 cs.dwExStyle = exStyle;
1221 return HWND_16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
1225 /***********************************************************************
1226 * CreateWindowExA (USER32.@)
1228 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1229 LPCSTR windowName, DWORD style, INT x,
1230 INT y, INT width, INT height,
1231 HWND parent, HMENU menu,
1232 HINSTANCE instance, LPVOID data )
1234 ATOM classAtom;
1235 CREATESTRUCTA cs;
1236 char buffer[256];
1238 if(exStyle & WS_EX_MDICHILD)
1239 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1241 /* Find the class atom */
1243 if (HIWORD(className))
1245 if (!(classAtom = GlobalFindAtomA( className )))
1247 ERR( "bad class name %s\n", debugstr_a(className) );
1248 return 0;
1251 else
1253 classAtom = LOWORD(className);
1254 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1256 ERR( "bad atom %x\n", classAtom);
1257 return 0;
1259 className = buffer;
1262 /* Create the window */
1264 cs.lpCreateParams = data;
1265 cs.hInstance = instance;
1266 cs.hMenu = menu;
1267 cs.hwndParent = parent;
1268 cs.x = x;
1269 cs.y = y;
1270 cs.cx = width;
1271 cs.cy = height;
1272 cs.style = style;
1273 cs.lpszName = windowName;
1274 cs.lpszClass = className;
1275 cs.dwExStyle = exStyle;
1277 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1281 /***********************************************************************
1282 * CreateWindowExW (USER32.@)
1284 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1285 LPCWSTR windowName, DWORD style, INT x,
1286 INT y, INT width, INT height,
1287 HWND parent, HMENU menu,
1288 HINSTANCE instance, LPVOID data )
1290 ATOM classAtom;
1291 CREATESTRUCTW cs;
1292 WCHAR buffer[256];
1294 if(exStyle & WS_EX_MDICHILD)
1295 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1297 /* Find the class atom */
1299 if (HIWORD(className))
1301 if (!(classAtom = GlobalFindAtomW( className )))
1303 ERR( "bad class name %s\n", debugstr_w(className) );
1304 return 0;
1307 else
1309 classAtom = LOWORD(className);
1310 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1312 ERR( "bad atom %x\n", classAtom);
1313 return 0;
1315 className = buffer;
1318 /* Create the window */
1320 cs.lpCreateParams = data;
1321 cs.hInstance = instance;
1322 cs.hMenu = menu;
1323 cs.hwndParent = parent;
1324 cs.x = x;
1325 cs.y = y;
1326 cs.cx = width;
1327 cs.cy = height;
1328 cs.style = style;
1329 cs.lpszName = windowName;
1330 cs.lpszClass = className;
1331 cs.dwExStyle = exStyle;
1333 /* Note: we rely on the fact that CREATESTRUCTA and */
1334 /* CREATESTRUCTW have the same layout. */
1335 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1339 /***********************************************************************
1340 * WIN_SendDestroyMsg
1342 static void WIN_SendDestroyMsg( HWND hwnd )
1344 GUITHREADINFO info;
1346 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1348 if (hwnd == info.hwndCaret) DestroyCaret();
1350 if (USER_Driver.pResetSelectionOwner)
1351 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1354 * Send the WM_DESTROY to the window.
1356 SendMessageA( hwnd, WM_DESTROY, 0, 0);
1359 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1360 * make sure that the window still exists when we come back.
1362 if (IsWindow(hwnd))
1364 HWND* pWndArray;
1365 int i;
1367 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1369 /* start from the end (FIXME: is this needed?) */
1370 for (i = 0; pWndArray[i]; i++) ;
1372 while (--i >= 0)
1374 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1376 HeapFree( GetProcessHeap(), 0, pWndArray );
1378 else
1379 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1383 /***********************************************************************
1384 * DestroyWindow (USER32.@)
1386 BOOL WINAPI DestroyWindow( HWND hwnd )
1388 BOOL is_child;
1389 HWND h;
1391 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1393 SetLastError( ERROR_ACCESS_DENIED );
1394 return FALSE;
1397 TRACE("(%p)\n", hwnd);
1399 /* Look whether the focus is within the tree of windows we will
1400 * be destroying.
1402 h = GetFocus();
1403 if (h == hwnd || IsChild( hwnd, h ))
1405 HWND parent = GetAncestor( hwnd, GA_PARENT );
1406 if (parent == GetDesktopWindow()) parent = 0;
1407 SetFocus( parent );
1410 /* Call hooks */
1412 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1414 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1416 if (is_child)
1418 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1419 send_parent_notify( hwnd, WM_DESTROY );
1421 else if (!GetWindow( hwnd, GW_OWNER ))
1423 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1424 /* FIXME: clean up palette - see "Internals" p.352 */
1427 if (!IsWindow(hwnd)) return TRUE;
1429 if (USER_Driver.pResetSelectionOwner)
1430 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1432 /* Hide the window */
1434 if (!ShowWindow( hwnd, SW_HIDE ))
1436 if (hwnd == GetActiveWindow()) WINPOS_ActivateOtherWindow( hwnd );
1438 if (!IsWindow(hwnd)) return TRUE;
1440 /* Recursively destroy owned windows */
1442 if (!is_child)
1444 for (;;)
1446 int i, got_one = 0;
1447 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1448 if (list)
1450 for (i = 0; list[i]; i++)
1452 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1453 if (WIN_IsCurrentThread( list[i] ))
1455 DestroyWindow( list[i] );
1456 got_one = 1;
1457 continue;
1459 WIN_SetOwner( list[i], 0 );
1461 HeapFree( GetProcessHeap(), 0, list );
1463 if (!got_one) break;
1467 /* Send destroy messages */
1469 WIN_SendDestroyMsg( hwnd );
1470 if (!IsWindow( hwnd )) return TRUE;
1472 if (GetClipboardOwner() == hwnd)
1473 CLIPBOARD_ReleaseOwner();
1475 /* Unlink now so we won't bother with the children later on */
1477 WIN_UnlinkWindow( hwnd );
1479 /* Destroy the window storage */
1481 WIN_DestroyWindow( hwnd );
1482 return TRUE;
1486 /***********************************************************************
1487 * CloseWindow (USER32.@)
1489 BOOL WINAPI CloseWindow( HWND hwnd )
1491 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1492 ShowWindow( hwnd, SW_MINIMIZE );
1493 return TRUE;
1497 /***********************************************************************
1498 * OpenIcon (USER32.@)
1500 BOOL WINAPI OpenIcon( HWND hwnd )
1502 if (!IsIconic( hwnd )) return FALSE;
1503 ShowWindow( hwnd, SW_SHOWNORMAL );
1504 return TRUE;
1508 /***********************************************************************
1509 * WIN_FindWindow
1511 * Implementation of FindWindow() and FindWindowEx().
1513 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1515 HWND *list = NULL;
1516 HWND retvalue = 0;
1517 int i = 0, len = 0;
1518 WCHAR *buffer = NULL;
1520 if (!parent) parent = GetDesktopWindow();
1521 if (title)
1523 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1524 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1527 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1529 if (child)
1531 child = WIN_GetFullHandle( child );
1532 while (list[i] && list[i] != child) i++;
1533 if (!list[i]) goto done;
1534 i++; /* start from next window */
1537 if (title)
1539 while (list[i])
1541 if (GetWindowTextW( list[i], buffer, len + 1 ) && !strcmpiW( buffer, title )) break;
1542 i++;
1545 retvalue = list[i];
1547 done:
1548 if (list) HeapFree( GetProcessHeap(), 0, list );
1549 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1550 return retvalue;
1555 /***********************************************************************
1556 * FindWindowA (USER32.@)
1558 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1560 HWND ret = FindWindowExA( 0, 0, className, title );
1561 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1562 return ret;
1566 /***********************************************************************
1567 * FindWindowExA (USER32.@)
1569 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1570 LPCSTR className, LPCSTR title )
1572 ATOM atom = 0;
1573 LPWSTR buffer;
1574 HWND hwnd;
1575 INT len;
1577 if (className)
1579 /* If the atom doesn't exist, then no class */
1580 /* with this name exists either. */
1581 if (!(atom = GlobalFindAtomA( className )))
1583 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1584 return 0;
1587 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
1589 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1590 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1591 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
1592 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1593 HeapFree( GetProcessHeap(), 0, buffer );
1594 return hwnd;
1598 /***********************************************************************
1599 * FindWindowExW (USER32.@)
1601 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1602 LPCWSTR className, LPCWSTR title )
1604 ATOM atom = 0;
1606 if (className)
1608 /* If the atom doesn't exist, then no class */
1609 /* with this name exists either. */
1610 if (!(atom = GlobalFindAtomW( className )))
1612 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1613 return 0;
1616 return WIN_FindWindow( parent, child, atom, title );
1620 /***********************************************************************
1621 * FindWindowW (USER32.@)
1623 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1625 return FindWindowExW( 0, 0, className, title );
1629 /**********************************************************************
1630 * GetDesktopWindow (USER32.@)
1632 HWND WINAPI GetDesktopWindow(void)
1634 if (pWndDesktop) return pWndDesktop->hwndSelf;
1635 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" );
1636 ExitProcess(1);
1637 return 0;
1641 /*******************************************************************
1642 * EnableWindow (USER32.@)
1644 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1646 WND *wndPtr;
1647 BOOL retvalue;
1648 LONG style;
1649 HWND full_handle;
1651 if (is_broadcast(hwnd))
1653 SetLastError( ERROR_INVALID_PARAMETER );
1654 return FALSE;
1657 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1658 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1660 hwnd = full_handle;
1662 TRACE("( %p, %d )\n", hwnd, enable);
1664 if (!(wndPtr = WIN_GetPtr( hwnd ))) return FALSE;
1665 style = wndPtr->dwStyle;
1666 retvalue = ((style & WS_DISABLED) != 0);
1667 WIN_ReleasePtr( wndPtr );
1669 if (enable && retvalue)
1671 WIN_SetStyle( hwnd, style & ~WS_DISABLED );
1672 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1674 else if (!enable && !retvalue)
1676 HWND focus_wnd, capture_wnd;
1678 SendMessageA( hwnd, WM_CANCELMODE, 0, 0);
1680 WIN_SetStyle( hwnd, style | WS_DISABLED );
1682 focus_wnd = GetFocus();
1683 if (hwnd == focus_wnd || IsChild(hwnd, focus_wnd))
1684 SetFocus( 0 ); /* A disabled window can't have the focus */
1686 capture_wnd = GetCapture();
1687 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1688 ReleaseCapture(); /* A disabled window can't capture the mouse */
1690 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1692 return retvalue;
1696 /***********************************************************************
1697 * IsWindowEnabled (USER32.@)
1699 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1701 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1705 /***********************************************************************
1706 * IsWindowUnicode (USER32.@)
1708 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1710 WND * wndPtr;
1711 BOOL retvalue;
1713 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1714 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1715 WIN_ReleaseWndPtr(wndPtr);
1716 return retvalue;
1720 /**********************************************************************
1721 * GetWindowWord (USER32.@)
1723 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1725 if (offset >= 0)
1727 WORD retvalue = 0;
1728 WND *wndPtr = WIN_GetPtr( hwnd );
1729 if (!wndPtr)
1731 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1732 return 0;
1734 if (wndPtr == WND_OTHER_PROCESS)
1736 SERVER_START_REQ( set_window_info )
1738 req->handle = hwnd;
1739 req->flags = 0; /* don't set anything, just retrieve */
1740 req->extra_offset = offset;
1741 req->extra_size = sizeof(retvalue);
1742 if (!wine_server_call_err( req ))
1743 memcpy( &retvalue, &reply->old_extra_value, sizeof(retvalue) );
1745 SERVER_END_REQ;
1746 return retvalue;
1748 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1750 WARN("Invalid offset %d\n", offset );
1751 SetLastError( ERROR_INVALID_INDEX );
1753 else memcpy( &retvalue, (char *)wndPtr->wExtra + offset, sizeof(retvalue) );
1754 WIN_ReleasePtr( wndPtr );
1755 return retvalue;
1758 switch(offset)
1760 case GWL_HWNDPARENT:
1761 return GetWindowLongW( hwnd, offset );
1762 case GWL_ID:
1763 case GWL_HINSTANCE:
1765 LONG ret = GetWindowLongW( hwnd, offset );
1766 if (HIWORD(ret))
1767 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1768 return LOWORD(ret);
1770 default:
1771 WARN("Invalid offset %d\n", offset );
1772 return 0;
1777 /**********************************************************************
1778 * SetWindowWord (USER32.@)
1780 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1782 WORD retval = 0;
1783 WND * wndPtr;
1785 switch(offset)
1787 case GWL_ID:
1788 case GWL_HINSTANCE:
1789 case GWL_HWNDPARENT:
1790 return SetWindowLongW( hwnd, offset, (UINT)newval );
1791 default:
1792 if (offset < 0)
1794 WARN("Invalid offset %d\n", offset );
1795 SetLastError( ERROR_INVALID_INDEX );
1796 return 0;
1800 wndPtr = WIN_GetPtr( hwnd );
1801 if (wndPtr == WND_OTHER_PROCESS)
1803 if (IsWindow(hwnd))
1804 FIXME( "set %d <- %x not supported yet on other process window %p\n",
1805 offset, newval, hwnd );
1806 wndPtr = NULL;
1808 if (!wndPtr)
1810 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1811 return 0;
1814 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1816 WARN("Invalid offset %d\n", offset );
1817 WIN_ReleasePtr(wndPtr);
1818 SetLastError( ERROR_INVALID_INDEX );
1819 return 0;
1822 SERVER_START_REQ( set_window_info )
1824 req->handle = hwnd;
1825 req->flags = SET_WIN_EXTRA;
1826 req->extra_offset = offset;
1827 req->extra_size = sizeof(newval);
1828 memcpy( &req->extra_value, &newval, sizeof(newval) );
1829 if (!wine_server_call_err( req ))
1831 void *ptr = (char *)wndPtr->wExtra + offset;
1832 memcpy( &retval, ptr, sizeof(retval) );
1833 memcpy( ptr, &newval, sizeof(newval) );
1836 SERVER_END_REQ;
1837 WIN_ReleasePtr( wndPtr );
1838 return retval;
1842 /**********************************************************************
1843 * WIN_GetWindowLong
1845 * Helper function for GetWindowLong().
1847 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1849 LONG retvalue = 0;
1850 WND *wndPtr;
1852 if (offset == GWL_HWNDPARENT)
1854 HWND parent = GetAncestor( hwnd, GA_PARENT );
1855 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1856 return (LONG)parent;
1859 if (!(wndPtr = WIN_GetPtr( hwnd )))
1861 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1862 return 0;
1865 if (wndPtr == WND_OTHER_PROCESS)
1867 if (offset == GWL_WNDPROC)
1869 SetLastError( ERROR_ACCESS_DENIED );
1870 return 0;
1872 SERVER_START_REQ( set_window_info )
1874 req->handle = hwnd;
1875 req->flags = 0; /* don't set anything, just retrieve */
1876 req->extra_offset = (offset >= 0) ? offset : -1;
1877 req->extra_size = (offset >= 0) ? sizeof(retvalue) : 0;
1878 if (!wine_server_call_err( req ))
1880 switch(offset)
1882 case GWL_STYLE: retvalue = reply->old_style; break;
1883 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1884 case GWL_ID: retvalue = reply->old_id; break;
1885 case GWL_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1886 case GWL_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
1887 default:
1888 if (offset >= 0) retvalue = reply->old_extra_value;
1889 else SetLastError( ERROR_INVALID_INDEX );
1890 break;
1894 SERVER_END_REQ;
1895 return retvalue;
1898 /* now we have a valid wndPtr */
1900 if (offset >= 0)
1902 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
1905 * Some programs try to access last element from 16 bit
1906 * code using illegal offset value. Hopefully this is
1907 * what those programs really expect.
1909 if (type == WIN_PROC_16 &&
1910 wndPtr->cbWndExtra >= 4 &&
1911 offset == wndPtr->cbWndExtra - sizeof(WORD))
1913 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
1915 ERR( "- replaced invalid offset %d with %d\n",
1916 offset, offset2 );
1918 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset2);
1919 WIN_ReleasePtr( wndPtr );
1920 return retvalue;
1922 WARN("Invalid offset %d\n", offset );
1923 WIN_ReleasePtr( wndPtr );
1924 SetLastError( ERROR_INVALID_INDEX );
1925 return 0;
1927 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1928 /* Special case for dialog window procedure */
1929 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1930 retvalue = (LONG)WINPROC_GetProc( (WNDPROC)retvalue, type );
1931 WIN_ReleasePtr( wndPtr );
1932 return retvalue;
1935 switch(offset)
1937 case GWL_USERDATA: retvalue = wndPtr->userdata; break;
1938 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1939 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1940 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu; break;
1941 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc, type ); break;
1942 case GWL_HINSTANCE: retvalue = (LONG)wndPtr->hInstance; break;
1943 default:
1944 WARN("Unknown offset %d\n", offset );
1945 SetLastError( ERROR_INVALID_INDEX );
1946 break;
1948 WIN_ReleasePtr(wndPtr);
1949 return retvalue;
1953 /**********************************************************************
1954 * WIN_SetWindowLong
1956 * Helper function for SetWindowLong().
1958 * 0 is the failure code. However, in the case of failure SetLastError
1959 * must be set to distinguish between a 0 return value and a failure.
1961 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1962 WINDOWPROCTYPE type )
1964 STYLESTRUCT style;
1965 BOOL ok;
1966 LONG retval = 0;
1967 WND *wndPtr;
1969 TRACE( "%p %d %lx %x\n", hwnd, offset, newval, type );
1971 if (is_broadcast(hwnd))
1973 SetLastError( ERROR_INVALID_PARAMETER );
1974 return FALSE;
1976 if (!WIN_IsCurrentProcess( hwnd ))
1978 if (offset == GWL_WNDPROC)
1980 SetLastError( ERROR_ACCESS_DENIED );
1981 return 0;
1983 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
1986 wndPtr = WIN_GetPtr( hwnd );
1987 if (wndPtr->hwndSelf == GetDesktopWindow())
1989 /* can't change anything on the desktop window */
1990 WIN_ReleasePtr( wndPtr );
1991 SetLastError( ERROR_ACCESS_DENIED );
1992 return 0;
1995 /* first some special cases */
1996 switch( offset )
1998 case GWL_STYLE:
1999 case GWL_EXSTYLE:
2000 style.styleOld =
2001 offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
2002 style.styleNew = newval;
2003 WIN_ReleasePtr( wndPtr );
2004 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
2005 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
2006 newval = style.styleNew;
2007 break;
2008 case GWL_HWNDPARENT:
2009 if (wndPtr->parent == GetDesktopWindow())
2011 WIN_ReleasePtr( wndPtr );
2012 return (LONG)WIN_SetOwner( hwnd, (HWND)newval );
2014 else
2016 WIN_ReleasePtr( wndPtr );
2017 return (LONG)SetParent( hwnd, (HWND)newval );
2019 case GWL_WNDPROC:
2020 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2021 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC)newval, type, WIN_PROC_WINDOW );
2022 WIN_ReleasePtr( wndPtr );
2023 return retval;
2024 case GWL_ID:
2025 case GWL_HINSTANCE:
2026 case GWL_USERDATA:
2027 break;
2028 case DWL_DLGPROC:
2029 if ((wndPtr->cbWndExtra + sizeof(LONG) >= DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2031 WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWL_DLGPROC);
2032 retval = (LONG)WINPROC_GetProc( *ptr, type );
2033 WINPROC_SetProc( ptr, (WNDPROC)newval, type, WIN_PROC_WINDOW );
2034 WIN_ReleasePtr( wndPtr );
2035 return retval;
2037 /* fall through */
2038 default:
2039 if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
2041 WARN("Invalid offset %d\n", offset );
2042 WIN_ReleasePtr( wndPtr );
2043 SetLastError( ERROR_INVALID_INDEX );
2044 return 0;
2046 else
2048 LONG *ptr = (LONG *)((char *)wndPtr->wExtra + offset);
2049 if (*ptr == newval) /* already set to the same value */
2051 WIN_ReleasePtr( wndPtr );
2052 return newval;
2055 break;
2058 SERVER_START_REQ( set_window_info )
2060 req->handle = hwnd;
2061 req->extra_offset = -1;
2062 switch(offset)
2064 case GWL_STYLE:
2065 req->flags = SET_WIN_STYLE;
2066 req->style = newval;
2067 break;
2068 case GWL_EXSTYLE:
2069 req->flags = SET_WIN_EXSTYLE;
2070 req->ex_style = newval;
2071 break;
2072 case GWL_ID:
2073 req->flags = SET_WIN_ID;
2074 req->id = newval;
2075 break;
2076 case GWL_HINSTANCE:
2077 req->flags = SET_WIN_INSTANCE;
2078 req->instance = (void *)newval;
2079 break;
2080 case GWL_USERDATA:
2081 req->flags = SET_WIN_USERDATA;
2082 req->user_data = (void *)newval;
2083 break;
2084 default:
2085 req->flags = SET_WIN_EXTRA;
2086 req->extra_offset = offset;
2087 req->extra_size = sizeof(newval);
2088 memcpy( &req->extra_value, &newval, sizeof(newval) );
2090 if ((ok = !wine_server_call_err( req )))
2092 switch(offset)
2094 case GWL_STYLE:
2095 wndPtr->dwStyle = newval;
2096 retval = reply->old_style;
2097 break;
2098 case GWL_EXSTYLE:
2099 wndPtr->dwExStyle = newval;
2100 retval = reply->old_ex_style;
2101 break;
2102 case GWL_ID:
2103 wndPtr->wIDmenu = newval;
2104 retval = reply->old_id;
2105 break;
2106 case GWL_HINSTANCE:
2107 wndPtr->hInstance = (HINSTANCE)newval;
2108 retval = (ULONG_PTR)reply->old_instance;
2109 break;
2110 case GWL_USERDATA:
2111 wndPtr->userdata = newval;
2112 retval = (ULONG_PTR)reply->old_user_data;
2113 break;
2114 default:
2116 void *ptr = (char *)wndPtr->wExtra + offset;
2117 memcpy( &retval, ptr, sizeof(retval) );
2118 memcpy( ptr, &newval, sizeof(newval) );
2120 break;
2124 SERVER_END_REQ;
2125 WIN_ReleasePtr( wndPtr );
2127 if (!ok) return 0;
2129 if (offset == GWL_STYLE && USER_Driver.pSetWindowStyle)
2130 USER_Driver.pSetWindowStyle( hwnd, retval );
2132 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2133 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2135 return retval;
2139 /**********************************************************************
2140 * GetWindowLong (USER.135)
2142 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2144 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
2148 /**********************************************************************
2149 * GetWindowLongA (USER32.@)
2151 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2153 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2157 /**********************************************************************
2158 * GetWindowLongW (USER32.@)
2160 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2162 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2166 /**********************************************************************
2167 * SetWindowLong (USER.136)
2169 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2171 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
2175 /**********************************************************************
2176 * SetWindowLongA (USER32.@)
2178 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2180 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2184 /**********************************************************************
2185 * SetWindowLongW (USER32.@) Set window attribute
2187 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2188 * value in a window's extra memory.
2190 * The _hwnd_ parameter specifies the window. is the handle to a
2191 * window that has extra memory. The _newval_ parameter contains the
2192 * new attribute or extra memory value. If positive, the _offset_
2193 * parameter is the byte-addressed location in the window's extra
2194 * memory to set. If negative, _offset_ specifies the window
2195 * attribute to set, and should be one of the following values:
2197 * GWL_EXSTYLE The window's extended window style
2199 * GWL_STYLE The window's window style.
2201 * GWL_WNDPROC Pointer to the window's window procedure.
2203 * GWL_HINSTANCE The window's pplication instance handle.
2205 * GWL_ID The window's identifier.
2207 * GWL_USERDATA The window's user-specified data.
2209 * If the window is a dialog box, the _offset_ parameter can be one of
2210 * the following values:
2212 * DWL_DLGPROC The address of the window's dialog box procedure.
2214 * DWL_MSGRESULT The return value of a message
2215 * that the dialog box procedure processed.
2217 * DWL_USER Application specific information.
2219 * RETURNS
2221 * If successful, returns the previous value located at _offset_. Otherwise,
2222 * returns 0.
2224 * NOTES
2226 * Extra memory for a window class is specified by a nonzero cbWndExtra
2227 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2228 * time of class creation.
2230 * Using GWL_WNDPROC to set a new window procedure effectively creates
2231 * a window subclass. Use CallWindowProc() in the new windows procedure
2232 * to pass messages to the superclass's window procedure.
2234 * The user data is reserved for use by the application which created
2235 * the window.
2237 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2238 * instead, call the EnableWindow() function to change the window's
2239 * disabled state.
2241 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2242 * SetParent() instead.
2244 * Win95:
2245 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2246 * it sends WM_STYLECHANGING before changing the settings
2247 * and WM_STYLECHANGED afterwards.
2248 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2250 LONG WINAPI SetWindowLongW(
2251 HWND hwnd, /* [in] window to alter */
2252 INT offset, /* [in] offset, in bytes, of location to alter */
2253 LONG newval /* [in] new value of location */
2255 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2259 /*******************************************************************
2260 * GetWindowTextA (USER32.@)
2262 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2264 WCHAR *buffer;
2266 if (WIN_IsCurrentProcess( hwnd ))
2267 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2269 /* when window belongs to other process, don't send a message */
2270 if (nMaxCount <= 0) return 0;
2271 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2272 get_server_window_text( hwnd, buffer, nMaxCount );
2273 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2274 lpString[nMaxCount-1] = 0;
2275 HeapFree( GetProcessHeap(), 0, buffer );
2276 return strlen(lpString);
2280 /*******************************************************************
2281 * InternalGetWindowText (USER32.@)
2283 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2285 WND *win;
2287 if (nMaxCount <= 0) return 0;
2288 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2289 if (win != WND_OTHER_PROCESS)
2291 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2292 else lpString[0] = 0;
2293 WIN_ReleasePtr( win );
2295 else
2297 get_server_window_text( hwnd, lpString, nMaxCount );
2299 return strlenW(lpString);
2303 /*******************************************************************
2304 * GetWindowTextW (USER32.@)
2306 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2308 if (WIN_IsCurrentProcess( hwnd ))
2309 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2311 /* when window belongs to other process, don't send a message */
2312 if (nMaxCount <= 0) return 0;
2313 get_server_window_text( hwnd, lpString, nMaxCount );
2314 return strlenW(lpString);
2318 /*******************************************************************
2319 * SetWindowText (USER32.@)
2320 * SetWindowTextA (USER32.@)
2322 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2324 if (is_broadcast(hwnd))
2326 SetLastError( ERROR_INVALID_PARAMETER );
2327 return FALSE;
2329 if (!WIN_IsCurrentProcess( hwnd ))
2331 FIXME( "cannot set text %s of other process window %p\n", debugstr_a(lpString), hwnd );
2332 SetLastError( ERROR_ACCESS_DENIED );
2333 return FALSE;
2335 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2339 /*******************************************************************
2340 * SetWindowTextW (USER32.@)
2342 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2344 if (is_broadcast(hwnd))
2346 SetLastError( ERROR_INVALID_PARAMETER );
2347 return FALSE;
2349 if (!WIN_IsCurrentProcess( hwnd ))
2351 FIXME( "cannot set text %s of other process window %p\n", debugstr_w(lpString), hwnd );
2352 SetLastError( ERROR_ACCESS_DENIED );
2353 return FALSE;
2355 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2359 /*******************************************************************
2360 * GetWindowTextLengthA (USER32.@)
2362 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2364 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2367 /*******************************************************************
2368 * GetWindowTextLengthW (USER32.@)
2370 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2372 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2376 /*******************************************************************
2377 * IsWindow (USER32.@)
2379 BOOL WINAPI IsWindow( HWND hwnd )
2381 WND *ptr;
2382 BOOL ret;
2384 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2386 if (ptr != WND_OTHER_PROCESS)
2388 WIN_ReleasePtr( ptr );
2389 return TRUE;
2392 /* check other processes */
2393 SERVER_START_REQ( get_window_info )
2395 req->handle = hwnd;
2396 ret = !wine_server_call_err( req );
2398 SERVER_END_REQ;
2399 return ret;
2403 /***********************************************************************
2404 * GetWindowThreadProcessId (USER32.@)
2406 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2408 WND *ptr;
2409 DWORD tid = 0;
2411 if (!(ptr = WIN_GetPtr( hwnd )))
2413 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2414 return 0;
2417 if (ptr != WND_OTHER_PROCESS)
2419 /* got a valid window */
2420 tid = ptr->tid;
2421 if (process) *process = GetCurrentProcessId();
2422 WIN_ReleasePtr( ptr );
2423 return tid;
2426 /* check other processes */
2427 SERVER_START_REQ( get_window_info )
2429 req->handle = hwnd;
2430 if (!wine_server_call_err( req ))
2432 tid = (DWORD)reply->tid;
2433 if (process) *process = (DWORD)reply->pid;
2436 SERVER_END_REQ;
2437 return tid;
2441 /*****************************************************************
2442 * GetParent (USER32.@)
2444 HWND WINAPI GetParent( HWND hwnd )
2446 WND *wndPtr;
2447 HWND retvalue = 0;
2449 if (!(wndPtr = WIN_GetPtr( hwnd )))
2451 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2452 return 0;
2454 if (wndPtr == WND_OTHER_PROCESS)
2456 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2457 if (style & (WS_POPUP | WS_CHILD))
2459 SERVER_START_REQ( get_window_tree )
2461 req->handle = hwnd;
2462 if (!wine_server_call_err( req ))
2464 if (style & WS_POPUP) retvalue = reply->owner;
2465 else if (style & WS_CHILD) retvalue = reply->parent;
2468 SERVER_END_REQ;
2471 else
2473 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2474 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2475 WIN_ReleasePtr( wndPtr );
2477 return retvalue;
2481 /*****************************************************************
2482 * GetAncestor (USER32.@)
2484 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2486 WND *win;
2487 HWND *list, ret = 0;
2489 switch(type)
2491 case GA_PARENT:
2492 if (!(win = WIN_GetPtr( hwnd )))
2494 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2495 return 0;
2497 if (win != WND_OTHER_PROCESS)
2499 ret = win->parent;
2500 WIN_ReleasePtr( win );
2502 else /* need to query the server */
2504 SERVER_START_REQ( get_window_tree )
2506 req->handle = hwnd;
2507 if (!wine_server_call_err( req )) ret = reply->parent;
2509 SERVER_END_REQ;
2511 break;
2513 case GA_ROOT:
2514 if (!(list = WIN_ListParents( hwnd ))) return 0;
2516 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2517 else
2519 int count = 2;
2520 while (list[count]) count++;
2521 ret = list[count - 2]; /* get the one before the desktop */
2523 HeapFree( GetProcessHeap(), 0, list );
2524 break;
2526 case GA_ROOTOWNER:
2527 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2528 for (;;)
2530 HWND parent = GetParent( ret );
2531 if (!parent) break;
2532 ret = parent;
2534 break;
2536 return ret;
2540 /*****************************************************************
2541 * SetParent (USER32.@)
2543 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2545 WND *wndPtr;
2546 HWND retvalue, full_handle;
2547 BOOL was_visible;
2549 if (is_broadcast(hwnd) || is_broadcast(parent))
2551 SetLastError(ERROR_INVALID_PARAMETER);
2552 return 0;
2555 if (!parent) parent = GetDesktopWindow();
2556 else parent = WIN_GetFullHandle( parent );
2558 if (!IsWindow( parent ))
2560 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2561 return 0;
2564 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2565 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2567 hwnd = full_handle;
2569 if (USER_Driver.pSetParent)
2570 return USER_Driver.pSetParent( hwnd, parent );
2572 /* Windows hides the window first, then shows it again
2573 * including the WM_SHOWWINDOW messages and all */
2574 was_visible = ShowWindow( hwnd, SW_HIDE );
2576 if (!IsWindow( parent )) return 0;
2577 if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return 0;
2579 retvalue = wndPtr->parent; /* old parent */
2580 if (parent != retvalue)
2582 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2584 if (parent != GetDesktopWindow()) /* a child window */
2586 if (!(wndPtr->dwStyle & WS_CHILD))
2588 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
2589 if (menu) DestroyMenu( menu );
2593 WIN_ReleasePtr( wndPtr );
2595 /* SetParent additionally needs to make hwnd the topmost window
2596 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2597 WM_WINDOWPOSCHANGED notification messages.
2599 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2600 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2601 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2602 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2603 return retvalue;
2607 /*******************************************************************
2608 * IsChild (USER32.@)
2610 BOOL WINAPI IsChild( HWND parent, HWND child )
2612 HWND *list = WIN_ListParents( child );
2613 int i;
2614 BOOL ret;
2616 if (!list) return FALSE;
2617 parent = WIN_GetFullHandle( parent );
2618 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2619 ret = (list[i] != 0);
2620 HeapFree( GetProcessHeap(), 0, list );
2621 return ret;
2625 /***********************************************************************
2626 * IsWindowVisible (USER32.@)
2628 BOOL WINAPI IsWindowVisible( HWND hwnd )
2630 HWND *list;
2631 BOOL retval;
2632 int i;
2634 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2635 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2636 for (i = 0; list[i]; i++)
2637 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2638 retval = !list[i];
2639 HeapFree( GetProcessHeap(), 0, list );
2640 return retval;
2644 /***********************************************************************
2645 * WIN_IsWindowDrawable
2647 * hwnd is drawable when it is visible, all parents are not
2648 * minimized, and it is itself not minimized unless we are
2649 * trying to draw its default class icon.
2651 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2653 HWND *list;
2654 BOOL retval;
2655 int i;
2656 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2658 if (!(style & WS_VISIBLE)) return FALSE;
2659 if ((style & WS_MINIMIZE) && icon && GetClassLongA( hwnd, GCL_HICON )) return FALSE;
2661 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2662 for (i = 0; list[i]; i++)
2663 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2664 break;
2665 retval = !list[i];
2666 HeapFree( GetProcessHeap(), 0, list );
2667 return retval;
2671 /*******************************************************************
2672 * GetTopWindow (USER32.@)
2674 HWND WINAPI GetTopWindow( HWND hwnd )
2676 if (!hwnd) hwnd = GetDesktopWindow();
2677 return GetWindow( hwnd, GW_CHILD );
2681 /*******************************************************************
2682 * GetWindow (USER32.@)
2684 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2686 HWND retval = 0;
2688 if (rel == GW_OWNER) /* this one may be available locally */
2690 WND *wndPtr = WIN_GetPtr( hwnd );
2691 if (!wndPtr)
2693 SetLastError( ERROR_INVALID_HANDLE );
2694 return 0;
2696 if (wndPtr != WND_OTHER_PROCESS)
2698 retval = wndPtr->owner;
2699 WIN_ReleasePtr( wndPtr );
2700 return retval;
2702 /* else fall through to server call */
2705 SERVER_START_REQ( get_window_tree )
2707 req->handle = hwnd;
2708 if (!wine_server_call_err( req ))
2710 switch(rel)
2712 case GW_HWNDFIRST:
2713 retval = reply->first_sibling;
2714 break;
2715 case GW_HWNDLAST:
2716 retval = reply->last_sibling;
2717 break;
2718 case GW_HWNDNEXT:
2719 retval = reply->next_sibling;
2720 break;
2721 case GW_HWNDPREV:
2722 retval = reply->prev_sibling;
2723 break;
2724 case GW_OWNER:
2725 retval = reply->owner;
2726 break;
2727 case GW_CHILD:
2728 retval = reply->first_child;
2729 break;
2733 SERVER_END_REQ;
2734 return retval;
2738 /***********************************************************************
2739 * WIN_InternalShowOwnedPopups
2741 * Internal version of ShowOwnedPopups; Wine functions should use this
2742 * to avoid interfering with application calls to ShowOwnedPopups
2743 * and to make sure the application can't prevent showing/hiding.
2745 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2749 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2751 int count = 0;
2752 WND *pWnd;
2753 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2755 if (!win_array) return TRUE;
2758 * Show windows Lowest first, Highest last to preserve Z-Order
2760 while (win_array[count]) count++;
2761 while (--count >= 0)
2763 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2764 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2766 if (pWnd->dwStyle & WS_POPUP)
2768 if (fShow)
2770 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2771 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
2774 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2776 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2777 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2780 else
2782 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2783 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2784 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2787 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2789 ShowWindow(pWnd->hwndSelf,SW_HIDE);
2790 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2791 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
2795 WIN_ReleaseWndPtr( pWnd );
2797 HeapFree( GetProcessHeap(), 0, win_array );
2799 return TRUE;
2802 /*******************************************************************
2803 * ShowOwnedPopups (USER32.@)
2805 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2807 int count = 0;
2808 WND *pWnd;
2809 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2811 if (!win_array) return TRUE;
2813 while (win_array[count]) count++;
2814 while (--count >= 0)
2816 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2817 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2819 if (pWnd->dwStyle & WS_POPUP)
2821 if (fShow)
2823 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2825 /* In Windows, ShowOwnedPopups(TRUE) generates
2826 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2827 * regardless of the state of the owner
2829 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2830 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2833 else
2835 if (IsWindowVisible(pWnd->hwndSelf))
2837 /* In Windows, ShowOwnedPopups(FALSE) generates
2838 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2839 * regardless of the state of the owner
2841 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2842 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2846 WIN_ReleaseWndPtr( pWnd );
2848 HeapFree( GetProcessHeap(), 0, win_array );
2849 return TRUE;
2853 /*******************************************************************
2854 * GetLastActivePopup (USER32.@)
2856 HWND WINAPI GetLastActivePopup( HWND hwnd )
2858 HWND retval = hwnd;
2860 SERVER_START_REQ( get_window_info )
2862 req->handle = hwnd;
2863 if (!wine_server_call_err( req )) retval = reply->last_active;
2865 SERVER_END_REQ;
2866 return retval;
2870 /*******************************************************************
2871 * WIN_ListParents
2873 * Build an array of all parents of a given window, starting with
2874 * the immediate parent. The array must be freed with HeapFree.
2875 * Returns NULL if window is a top-level window.
2877 HWND *WIN_ListParents( HWND hwnd )
2879 WND *win;
2880 HWND current, *list;
2881 int pos = 0, size = 16, count = 0;
2883 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2885 current = hwnd;
2886 for (;;)
2888 if (!(win = WIN_GetPtr( current ))) goto empty;
2889 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
2890 list[pos] = win->parent;
2891 WIN_ReleasePtr( win );
2892 if (!(current = list[pos]))
2894 if (!pos) goto empty;
2895 return list;
2897 if (++pos == size - 1)
2899 /* need to grow the list */
2900 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
2901 if (!new_list) goto empty;
2902 list = new_list;
2903 size += 16;
2907 /* at least one parent belongs to another process, have to query the server */
2909 for (;;)
2911 count = 0;
2912 SERVER_START_REQ( get_window_parents )
2914 req->handle = hwnd;
2915 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
2916 if (!wine_server_call( req )) count = reply->count;
2918 SERVER_END_REQ;
2919 if (!count) goto empty;
2920 if (size > count)
2922 list[count] = 0;
2923 return list;
2925 HeapFree( GetProcessHeap(), 0, list );
2926 size = count + 1;
2927 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2930 empty:
2931 HeapFree( GetProcessHeap(), 0, list );
2932 return NULL;
2936 /*******************************************************************
2937 * WIN_ListChildren
2939 * Build an array of the children of a given window. The array must be
2940 * freed with HeapFree. Returns NULL when no windows are found.
2942 HWND *WIN_ListChildren( HWND hwnd )
2944 return list_window_children( hwnd, 0, 0 );
2948 /*******************************************************************
2949 * EnumWindows (USER32.@)
2951 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2953 HWND *list;
2954 BOOL ret = TRUE;
2955 int i, iWndsLocks;
2957 /* We have to build a list of all windows first, to avoid */
2958 /* unpleasant side-effects, for instance if the callback */
2959 /* function changes the Z-order of the windows. */
2961 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2963 /* Now call the callback function for every window */
2965 iWndsLocks = WIN_SuspendWndsLock();
2966 for (i = 0; list[i]; i++)
2968 /* Make sure that the window still exists */
2969 if (!IsWindow( list[i] )) continue;
2970 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2972 WIN_RestoreWndsLock(iWndsLocks);
2973 HeapFree( GetProcessHeap(), 0, list );
2974 return ret;
2978 /**********************************************************************
2979 * EnumThreadWindows (USER32.@)
2981 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2983 HWND *list;
2984 int i, iWndsLocks;
2986 if (!(list = list_window_children( GetDesktopWindow(), 0, id ))) return TRUE;
2988 /* Now call the callback function for every window */
2990 iWndsLocks = WIN_SuspendWndsLock();
2991 for (i = 0; list[i]; i++)
2992 if (!func( list[i], lParam )) break;
2993 WIN_RestoreWndsLock(iWndsLocks);
2994 HeapFree( GetProcessHeap(), 0, list );
2995 return TRUE;
2999 /**********************************************************************
3000 * WIN_EnumChildWindows
3002 * Helper function for EnumChildWindows().
3004 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
3006 HWND *childList;
3007 BOOL ret = FALSE;
3009 for ( ; *list; list++)
3011 /* Make sure that the window still exists */
3012 if (!IsWindow( *list )) continue;
3013 /* skip owned windows */
3014 if (GetWindow( *list, GW_OWNER )) continue;
3015 /* Build children list first */
3016 childList = WIN_ListChildren( *list );
3018 ret = func( *list, lParam );
3020 if (childList)
3022 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
3023 HeapFree( GetProcessHeap(), 0, childList );
3025 if (!ret) return FALSE;
3027 return TRUE;
3031 /**********************************************************************
3032 * EnumChildWindows (USER32.@)
3034 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
3036 HWND *list;
3037 int iWndsLocks;
3039 if (!(list = WIN_ListChildren( parent ))) return FALSE;
3040 iWndsLocks = WIN_SuspendWndsLock();
3041 WIN_EnumChildWindows( list, func, lParam );
3042 WIN_RestoreWndsLock(iWndsLocks);
3043 HeapFree( GetProcessHeap(), 0, list );
3044 return TRUE;
3048 /*******************************************************************
3049 * AnyPopup (USER.52)
3051 BOOL16 WINAPI AnyPopup16(void)
3053 return AnyPopup();
3057 /*******************************************************************
3058 * AnyPopup (USER32.@)
3060 BOOL WINAPI AnyPopup(void)
3062 int i;
3063 BOOL retvalue;
3064 HWND *list = WIN_ListChildren( GetDesktopWindow() );
3066 if (!list) return FALSE;
3067 for (i = 0; list[i]; i++)
3069 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
3071 retvalue = (list[i] != 0);
3072 HeapFree( GetProcessHeap(), 0, list );
3073 return retvalue;
3077 /*******************************************************************
3078 * FlashWindow (USER32.@)
3080 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3082 WND *wndPtr = WIN_FindWndPtr(hWnd);
3084 TRACE("%p\n", hWnd);
3086 if (!wndPtr) return FALSE;
3087 hWnd = wndPtr->hwndSelf; /* make it a full handle */
3089 if (wndPtr->dwStyle & WS_MINIMIZE)
3091 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3093 HDC hDC = GetDC(hWnd);
3095 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM)hDC, 0 ))
3096 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
3098 ReleaseDC( hWnd, hDC );
3099 wndPtr->flags |= WIN_NCACTIVATED;
3101 else
3103 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3104 wndPtr->flags &= ~WIN_NCACTIVATED;
3106 WIN_ReleaseWndPtr(wndPtr);
3107 return TRUE;
3109 else
3111 WPARAM16 wparam;
3112 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3113 else wparam = (hWnd == GetForegroundWindow());
3115 WIN_ReleaseWndPtr(wndPtr);
3116 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3117 return wparam;
3121 /*******************************************************************
3122 * FlashWindowEx (USER32.@)
3124 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
3126 FIXME("%p\n", pfwi);
3127 return TRUE;
3130 /*******************************************************************
3131 * GetWindowContextHelpId (USER32.@)
3133 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3135 DWORD retval;
3136 WND *wnd = WIN_FindWndPtr( hwnd );
3137 if (!wnd) return 0;
3138 retval = wnd->helpContext;
3139 WIN_ReleaseWndPtr(wnd);
3140 return retval;
3144 /*******************************************************************
3145 * SetWindowContextHelpId (USER32.@)
3147 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3149 WND *wnd = WIN_FindWndPtr( hwnd );
3150 if (!wnd) return FALSE;
3151 wnd->helpContext = id;
3152 WIN_ReleaseWndPtr(wnd);
3153 return TRUE;
3157 /*******************************************************************
3158 * DragDetect (USER32.@)
3160 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3162 MSG msg;
3163 RECT rect;
3165 rect.left = pt.x - wDragWidth;
3166 rect.right = pt.x + wDragWidth;
3168 rect.top = pt.y - wDragHeight;
3169 rect.bottom = pt.y + wDragHeight;
3171 SetCapture(hWnd);
3173 while(1)
3175 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3177 if( msg.message == WM_LBUTTONUP )
3179 ReleaseCapture();
3180 return 0;
3182 if( msg.message == WM_MOUSEMOVE )
3184 POINT tmp;
3185 tmp.x = LOWORD(msg.lParam);
3186 tmp.y = HIWORD(msg.lParam);
3187 if( !PtInRect( &rect, tmp ))
3189 ReleaseCapture();
3190 return 1;
3194 WaitMessage();
3196 return 0;
3199 /******************************************************************************
3200 * GetWindowModuleFileNameA (USER32.@)
3202 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3204 FIXME("GetWindowModuleFileNameA(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3205 hwnd, lpszFileName, cchFileNameMax);
3206 return 0;
3209 /******************************************************************************
3210 * GetWindowModuleFileNameW (USER32.@)
3212 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR lpszFileName, UINT cchFileNameMax)
3214 FIXME("GetWindowModuleFileNameW(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3215 hwnd, lpszFileName, cchFileNameMax);
3216 return 0;
3219 /******************************************************************************
3220 * GetWindowInfo (USER32.@)
3221 * hwnd: in
3222 * pwi: out.
3223 * MS Documentation mentions that pwi->cbSize must be set to SIZEOF(WINDOWINFO)
3224 * this may be because this structure changed over time. If this is the
3225 * the case, then please: FIXME.
3226 * Using the structure described in MSDN for 98/ME/NT(4.0 SP3)/2000/XP.
3228 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3230 if (!pwi) return FALSE;
3231 if (pwi->cbSize != sizeof(WINDOWINFO))
3233 FIXME("windowinfo->cbSize != sizeof(WINDOWINFO). Please report\n");
3234 return FALSE;
3236 if (!IsWindow(hwnd)) return FALSE;
3238 GetWindowRect(hwnd, &pwi->rcWindow);
3239 GetClientRect(hwnd, &pwi->rcClient);
3240 /* translate to screen coordinates */
3241 MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3243 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3244 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3245 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3247 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3248 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3250 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3251 pwi->wCreatorVersion = 0x0400;
3253 return TRUE;