Release 20031118.
[wine/multimedia.git] / windows / win.c
blob987abd29939cc1ea318430420b9755764c167e17
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, INT size )
67 BOOL res;
68 user_handle_t handle = 0;
69 WORD index;
70 WND *win = HeapAlloc( GetProcessHeap(), 0, size );
72 if (!win) return NULL;
74 USER_Lock();
76 SERVER_START_REQ( create_window )
78 req->parent = parent;
79 req->owner = owner;
80 req->atom = atom;
81 if ((res = !wine_server_call_err( req ))) handle = reply->handle;
83 SERVER_END_REQ;
85 if (!res)
87 USER_Unlock();
88 HeapFree( GetProcessHeap(), 0, win );
89 return NULL;
91 index = LOWORD(handle) - FIRST_USER_HANDLE;
92 assert( index < NB_USER_HANDLES );
93 user_handles[index] = win;
94 win->hwndSelf = handle;
95 win->dwMagic = WND_MAGIC;
96 win->irefCount = 1;
97 return win;
101 /***********************************************************************
102 * free_window_handle
104 * Free a window handle.
106 static WND *free_window_handle( HWND hwnd )
108 WND *ptr;
109 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
111 if (index >= NB_USER_HANDLES) return NULL;
112 USER_Lock();
113 if ((ptr = user_handles[index]))
115 SERVER_START_REQ( destroy_window )
117 req->handle = hwnd;
118 if (!wine_server_call_err( req ))
119 user_handles[index] = NULL;
120 else
121 ptr = NULL;
123 SERVER_END_REQ;
125 USER_Unlock();
126 if (ptr) HeapFree( GetProcessHeap(), 0, ptr );
127 return ptr;
131 /*******************************************************************
132 * list_window_children
134 * Build an array of the children of a given window. The array must be
135 * freed with HeapFree. Returns NULL when no windows are found.
137 static HWND *list_window_children( HWND hwnd, ATOM atom, DWORD tid )
139 HWND *list;
140 int size = 32;
142 for (;;)
144 int count = 0;
146 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
148 SERVER_START_REQ( get_window_children )
150 req->parent = hwnd;
151 req->atom = atom;
152 req->tid = tid;
153 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
154 if (!wine_server_call( req )) count = reply->count;
156 SERVER_END_REQ;
157 if (count && count < size)
159 list[count] = 0;
160 return list;
162 HeapFree( GetProcessHeap(), 0, list );
163 if (!count) break;
164 size = count + 1; /* restart with a large enough buffer */
166 return NULL;
170 /*******************************************************************
171 * send_parent_notify
173 static void send_parent_notify( HWND hwnd, UINT msg )
175 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD)) return;
176 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY) return;
177 SendMessageW( GetParent(hwnd), WM_PARENTNOTIFY,
178 MAKEWPARAM( msg, GetWindowLongW( hwnd, GWL_ID )), (LPARAM)hwnd );
182 /*******************************************************************
183 * get_server_window_text
185 * Retrieve the window text from the server.
187 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
189 size_t len = 0;
191 SERVER_START_REQ( get_window_text )
193 req->handle = hwnd;
194 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
195 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
197 SERVER_END_REQ;
198 text[len / sizeof(WCHAR)] = 0;
202 /***********************************************************************
203 * WIN_GetPtr
205 * Return a pointer to the WND structure if local to the process,
206 * or WND_OTHER_PROCESS if handle may be valid in other process.
207 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
209 WND *WIN_GetPtr( HWND hwnd )
211 WND * ptr;
212 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
214 if (index >= NB_USER_HANDLES) return NULL;
216 USER_Lock();
217 if ((ptr = user_handles[index]))
219 if (ptr->dwMagic == WND_MAGIC && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
220 return ptr;
221 ptr = NULL;
223 else ptr = WND_OTHER_PROCESS;
224 USER_Unlock();
225 return ptr;
229 /***********************************************************************
230 * WIN_IsCurrentProcess
232 * Check whether a given window belongs to the current process (and return the full handle).
234 HWND WIN_IsCurrentProcess( HWND hwnd )
236 WND *ptr;
237 HWND ret;
239 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS) return 0;
240 ret = ptr->hwndSelf;
241 WIN_ReleasePtr( ptr );
242 return ret;
246 /***********************************************************************
247 * WIN_IsCurrentThread
249 * Check whether a given window belongs to the current thread (and return the full handle).
251 HWND WIN_IsCurrentThread( HWND hwnd )
253 WND *ptr;
254 HWND ret = 0;
256 if ((ptr = WIN_GetPtr( hwnd )) && ptr != WND_OTHER_PROCESS)
258 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
259 WIN_ReleasePtr( ptr );
261 return ret;
265 /***********************************************************************
266 * WIN_Handle32
268 * Convert a 16-bit window handle to a full 32-bit handle.
270 HWND WIN_Handle32( HWND16 hwnd16 )
272 WND *ptr;
273 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
275 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
276 /* do sign extension for -2 and -3 */
277 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
279 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
281 if (ptr != WND_OTHER_PROCESS)
283 hwnd = ptr->hwndSelf;
284 WIN_ReleasePtr( ptr );
286 else /* may belong to another process */
288 SERVER_START_REQ( get_window_info )
290 req->handle = hwnd;
291 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
293 SERVER_END_REQ;
295 return hwnd;
299 /***********************************************************************
300 * WIN_FindWndPtr
302 * Return a pointer to the WND structure corresponding to a HWND.
304 WND * WIN_FindWndPtr( HWND hwnd )
306 WND * ptr;
308 if (!hwnd) return NULL;
310 if ((ptr = WIN_GetPtr( hwnd )))
312 if (ptr != WND_OTHER_PROCESS)
314 /* increment destruction monitoring */
315 ptr->irefCount++;
316 return ptr;
318 if (IsWindow( hwnd )) /* check other processes */
320 ERR( "window %p belongs to other process\n", hwnd );
321 /* DbgBreakPoint(); */
324 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
325 return NULL;
329 /***********************************************************************
330 * WIN_ReleaseWndPtr
332 * Release the pointer to the WND structure.
334 void WIN_ReleaseWndPtr(WND *wndPtr)
336 if(!wndPtr) return;
338 /* Decrement destruction monitoring value */
339 wndPtr->irefCount--;
340 /* Check if it's time to release the memory */
341 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
343 /* Release memory */
344 free_window_handle( wndPtr->hwndSelf );
346 else if(wndPtr->irefCount < 0)
348 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
349 ERR("forgot a Lock on %p somewhere\n",wndPtr);
351 /* unlock all WND structures for thread safeness */
352 USER_Unlock();
356 /***********************************************************************
357 * WIN_UnlinkWindow
359 * Remove a window from the siblings linked list.
361 void WIN_UnlinkWindow( HWND hwnd )
363 WIN_LinkWindow( hwnd, 0, 0 );
367 /***********************************************************************
368 * WIN_LinkWindow
370 * Insert a window into the siblings linked list.
371 * The window is inserted after the specified window, which can also
372 * be specified as HWND_TOP or HWND_BOTTOM.
373 * If parent is 0, window is unlinked from the tree.
375 void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
377 WND *wndPtr = WIN_GetPtr( hwnd );
379 if (!wndPtr) return;
380 if (wndPtr == WND_OTHER_PROCESS)
382 if (IsWindow(hwnd)) ERR(" cannot link other process window %p\n", hwnd );
383 return;
386 SERVER_START_REQ( link_window )
388 req->handle = hwnd;
389 req->parent = parent;
390 req->previous = hwndInsertAfter;
391 if (!wine_server_call( req ))
393 if (reply->full_parent) wndPtr->parent = reply->full_parent;
397 SERVER_END_REQ;
398 WIN_ReleasePtr( wndPtr );
402 /***********************************************************************
403 * WIN_SetOwner
405 * Change the owner of a window.
407 HWND WIN_SetOwner( HWND hwnd, HWND owner )
409 WND *win = WIN_GetPtr( hwnd );
410 HWND ret = 0;
412 if (!win) return 0;
413 if (win == WND_OTHER_PROCESS)
415 if (IsWindow(hwnd)) ERR( "cannot set owner %p on other process window %p\n", owner, hwnd );
416 return 0;
418 SERVER_START_REQ( set_window_owner )
420 req->handle = hwnd;
421 req->owner = owner;
422 if (!wine_server_call( req ))
424 win->owner = reply->full_owner;
425 ret = reply->prev_owner;
428 SERVER_END_REQ;
429 WIN_ReleasePtr( win );
430 return ret;
434 /***********************************************************************
435 * WIN_SetStyle
437 * Change the style of a window.
439 LONG WIN_SetStyle( HWND hwnd, LONG style )
441 BOOL ok;
442 LONG ret = 0;
443 WND *win = WIN_GetPtr( hwnd );
445 if (!win) return 0;
446 if (win == WND_OTHER_PROCESS)
448 if (IsWindow(hwnd))
449 ERR( "cannot set style %lx on other process window %p\n", style, hwnd );
450 return 0;
452 if (style == win->dwStyle)
454 WIN_ReleasePtr( win );
455 return style;
457 SERVER_START_REQ( set_window_info )
459 req->handle = hwnd;
460 req->flags = SET_WIN_STYLE;
461 req->style = style;
462 if ((ok = !wine_server_call( req )))
464 ret = reply->old_style;
465 win->dwStyle = style;
468 SERVER_END_REQ;
469 WIN_ReleasePtr( win );
470 if (ok && USER_Driver.pSetWindowStyle) USER_Driver.pSetWindowStyle( hwnd, ret );
471 return ret;
475 /***********************************************************************
476 * WIN_SetExStyle
478 * Change the extended style of a window.
480 LONG WIN_SetExStyle( HWND hwnd, LONG style )
482 LONG ret = 0;
483 WND *win = WIN_GetPtr( hwnd );
485 if (!win) return 0;
486 if (win == WND_OTHER_PROCESS)
488 if (IsWindow(hwnd))
489 ERR( "cannot set exstyle %lx on other process window %p\n", style, hwnd );
490 return 0;
492 if (style == win->dwExStyle)
494 WIN_ReleasePtr( win );
495 return style;
497 SERVER_START_REQ( set_window_info )
499 req->handle = hwnd;
500 req->flags = SET_WIN_EXSTYLE;
501 req->ex_style = style;
502 if (!wine_server_call( req ))
504 ret = reply->old_ex_style;
505 win->dwExStyle = style;
508 SERVER_END_REQ;
509 WIN_ReleasePtr( win );
510 return ret;
514 /***********************************************************************
515 * WIN_SetRectangles
517 * Set the window and client rectangles.
519 void WIN_SetRectangles( HWND hwnd, const RECT *rectWindow, const RECT *rectClient )
521 WND *win = WIN_GetPtr( hwnd );
522 BOOL ret;
524 if (!win) return;
525 if (win == WND_OTHER_PROCESS)
527 if (IsWindow( hwnd )) ERR( "cannot set rectangles of other process window %p\n", hwnd );
528 return;
530 SERVER_START_REQ( set_window_rectangles )
532 req->handle = hwnd;
533 req->window.left = rectWindow->left;
534 req->window.top = rectWindow->top;
535 req->window.right = rectWindow->right;
536 req->window.bottom = rectWindow->bottom;
537 req->client.left = rectClient->left;
538 req->client.top = rectClient->top;
539 req->client.right = rectClient->right;
540 req->client.bottom = rectClient->bottom;
541 ret = !wine_server_call( req );
543 SERVER_END_REQ;
544 if (ret)
546 win->rectWindow = *rectWindow;
547 win->rectClient = *rectClient;
549 TRACE( "win %p window (%ld,%ld)-(%ld,%ld) client (%ld,%ld)-(%ld,%ld)\n", hwnd,
550 rectWindow->left, rectWindow->top, rectWindow->right, rectWindow->bottom,
551 rectClient->left, rectClient->top, rectClient->right, rectClient->bottom );
553 WIN_ReleasePtr( win );
557 /***********************************************************************
558 * WIN_GetRectangles
560 * Get the window and client rectangles.
562 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
564 WND *win = WIN_GetPtr( hwnd );
565 BOOL ret = TRUE;
567 if (!win) return FALSE;
568 if (win == WND_OTHER_PROCESS)
570 SERVER_START_REQ( get_window_rectangles )
572 req->handle = hwnd;
573 if ((ret = !wine_server_call( req )))
575 if (rectWindow)
577 rectWindow->left = reply->window.left;
578 rectWindow->top = reply->window.top;
579 rectWindow->right = reply->window.right;
580 rectWindow->bottom = reply->window.bottom;
582 if (rectClient)
584 rectClient->left = reply->client.left;
585 rectClient->top = reply->client.top;
586 rectClient->right = reply->client.right;
587 rectClient->bottom = reply->client.bottom;
591 SERVER_END_REQ;
593 else
595 if (rectWindow) *rectWindow = win->rectWindow;
596 if (rectClient) *rectClient = win->rectClient;
597 WIN_ReleasePtr( win );
599 return ret;
603 /***********************************************************************
604 * WIN_DestroyWindow
606 * Destroy storage associated to a window. "Internals" p.358
608 LRESULT WIN_DestroyWindow( HWND hwnd )
610 WND *wndPtr;
611 HWND *list;
613 TRACE("%p\n", hwnd );
615 if (!(hwnd = WIN_IsCurrentThread( hwnd )))
617 ERR( "window doesn't belong to current thread\n" );
618 return 0;
621 /* free child windows */
622 if ((list = WIN_ListChildren( hwnd )))
624 int i;
625 for (i = 0; list[i]; i++)
627 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
628 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
630 HeapFree( GetProcessHeap(), 0, list );
634 * Clear the update region to make sure no WM_PAINT messages will be
635 * generated for this window while processing the WM_NCDESTROY.
637 RedrawWindow( hwnd, NULL, 0,
638 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
641 * Send the WM_NCDESTROY to the window being destroyed.
643 SendMessageA( hwnd, WM_NCDESTROY, 0, 0);
645 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
647 WINPOS_CheckInternalPos( hwnd );
648 if( hwnd == GetCapture()) ReleaseCapture();
650 /* free resources associated with the window */
652 TIMER_RemoveWindowTimers( hwnd );
654 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
656 if (!(wndPtr->dwStyle & WS_CHILD))
658 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
659 if (menu) DestroyMenu( menu );
661 if (wndPtr->hSysMenu)
663 DestroyMenu( wndPtr->hSysMenu );
664 wndPtr->hSysMenu = 0;
666 DCE_FreeWindowDCE( hwnd ); /* Always do this to catch orphaned DCs */
667 USER_Driver.pDestroyWindow( hwnd );
668 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
669 CLASS_RemoveWindow( wndPtr->class );
670 wndPtr->class = NULL;
671 wndPtr->dwMagic = 0; /* Mark it as invalid */
672 WIN_ReleaseWndPtr( wndPtr );
673 return 0;
676 /***********************************************************************
677 * WIN_DestroyThreadWindows
679 * Destroy all children of 'wnd' owned by the current thread.
680 * Return TRUE if something was done.
682 void WIN_DestroyThreadWindows( HWND hwnd )
684 HWND *list;
685 int i;
687 if (!(list = WIN_ListChildren( hwnd ))) return;
688 for (i = 0; list[i]; i++)
690 if (WIN_IsCurrentThread( list[i] ))
691 DestroyWindow( list[i] );
692 else
693 WIN_DestroyThreadWindows( list[i] );
695 HeapFree( GetProcessHeap(), 0, list );
698 /***********************************************************************
699 * WIN_CreateDesktopWindow
701 * Create the desktop window.
703 BOOL WIN_CreateDesktopWindow(void)
705 struct tagCLASS *class;
706 HWND hwndDesktop;
707 INT wndExtra;
708 DWORD clsStyle;
709 WNDPROC winproc;
710 DCE *dce;
711 CREATESTRUCTA cs;
712 RECT rect;
714 TRACE("Creating desktop window\n");
716 if (!WINPOS_CreateInternalPosAtom() ||
717 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
718 &wndExtra, &winproc, &clsStyle, &dce )))
719 return FALSE;
721 pWndDesktop = create_window_handle( 0, 0, LOWORD(DESKTOP_CLASS_ATOM),
722 sizeof(WND) + wndExtra - sizeof(pWndDesktop->wExtra) );
723 if (!pWndDesktop) return FALSE;
724 hwndDesktop = pWndDesktop->hwndSelf;
726 pWndDesktop->tid = 0; /* nobody owns the desktop */
727 pWndDesktop->parent = 0;
728 pWndDesktop->owner = 0;
729 pWndDesktop->class = class;
730 pWndDesktop->text = NULL;
731 pWndDesktop->hrgnUpdate = 0;
732 pWndDesktop->clsStyle = clsStyle;
733 pWndDesktop->dce = NULL;
734 pWndDesktop->pVScroll = NULL;
735 pWndDesktop->pHScroll = NULL;
736 pWndDesktop->helpContext = 0;
737 pWndDesktop->flags = 0;
738 pWndDesktop->hSysMenu = 0;
739 pWndDesktop->winproc = winproc;
740 pWndDesktop->cbWndExtra = wndExtra;
742 cs.lpCreateParams = NULL;
743 cs.hInstance = 0;
744 cs.hMenu = 0;
745 cs.hwndParent = 0;
746 cs.x = 0;
747 cs.y = 0;
748 cs.cx = GetSystemMetrics( SM_CXSCREEN );
749 cs.cy = GetSystemMetrics( SM_CYSCREEN );
750 cs.style = pWndDesktop->dwStyle;
751 cs.dwExStyle = pWndDesktop->dwExStyle;
752 cs.lpszName = NULL;
753 cs.lpszClass = DESKTOP_CLASS_ATOM;
755 SetRect( &rect, 0, 0, cs.cx, cs.cy );
756 WIN_SetRectangles( hwndDesktop, &rect, &rect );
758 SERVER_START_REQ( set_window_info )
760 req->handle = hwndDesktop;
761 req->flags = 0; /* don't set anything, just retrieve */
762 wine_server_call( req );
763 pWndDesktop->dwStyle = reply->old_style;
764 pWndDesktop->dwExStyle = reply->old_ex_style;
765 pWndDesktop->hInstance = (HINSTANCE)reply->old_instance;
766 pWndDesktop->userdata = (ULONG_PTR)reply->old_user_data;
767 pWndDesktop->wIDmenu = reply->old_id;
769 SERVER_END_REQ;
771 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE ))
773 WIN_ReleaseWndPtr( pWndDesktop );
774 return FALSE;
777 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
778 WIN_ReleaseWndPtr( pWndDesktop );
779 return TRUE;
783 /***********************************************************************
784 * WIN_FixCoordinates
786 * Fix the coordinates - Helper for WIN_CreateWindowEx.
787 * returns default show mode in sw.
788 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
790 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
792 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
793 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
795 if (cs->style & (WS_CHILD | WS_POPUP))
797 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
798 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
800 else /* overlapped window */
802 STARTUPINFOA info;
804 GetStartupInfoA( &info );
806 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
808 /* Never believe Microsoft's documentation... CreateWindowEx doc says
809 * that if an overlapped window is created with WS_VISIBLE style bit
810 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
811 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
812 * reveals that
814 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
815 * 2) it does not ignore the y parameter as the docs claim; instead, it
816 * uses it as second parameter to ShowWindow() unless y is either
817 * CW_USEDEFAULT or CW_USEDEFAULT16.
819 * The fact that we didn't do 2) caused bogus windows pop up when wine
820 * was running apps that were using this obscure feature. Example -
821 * calc.exe that comes with Win98 (only Win98, it's different from
822 * the one that comes with Win95 and NT)
824 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
825 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
826 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
829 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
831 if (info.dwFlags & STARTF_USESIZE)
833 cs->cx = info.dwXSize;
834 cs->cy = info.dwYSize;
836 else /* if no other hint from the app, pick 3/4 of the screen real estate */
838 RECT r;
839 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
840 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
841 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
846 else
848 /* neither x nor cx are default. Check the y values .
849 * In the trace we see Outlook and Outlook Express using
850 * cy set to CW_USEDEFAULT when opening the address book.
852 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16) {
853 RECT r;
854 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
855 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
856 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
861 /***********************************************************************
862 * dump_window_styles
864 static void dump_window_styles( DWORD style, DWORD exstyle )
866 TRACE( "style:" );
867 if(style & WS_POPUP) TRACE(" WS_POPUP");
868 if(style & WS_CHILD) TRACE(" WS_CHILD");
869 if(style & WS_MINIMIZE) TRACE(" WS_MINIMIZE");
870 if(style & WS_VISIBLE) TRACE(" WS_VISIBLE");
871 if(style & WS_DISABLED) TRACE(" WS_DISABLED");
872 if(style & WS_CLIPSIBLINGS) TRACE(" WS_CLIPSIBLINGS");
873 if(style & WS_CLIPCHILDREN) TRACE(" WS_CLIPCHILDREN");
874 if(style & WS_MAXIMIZE) TRACE(" WS_MAXIMIZE");
875 if((style & WS_CAPTION) == WS_CAPTION) TRACE(" WS_CAPTION");
876 else
878 if(style & WS_BORDER) TRACE(" WS_BORDER");
879 if(style & WS_DLGFRAME) TRACE(" WS_DLGFRAME");
881 if(style & WS_VSCROLL) TRACE(" WS_VSCROLL");
882 if(style & WS_HSCROLL) TRACE(" WS_HSCROLL");
883 if(style & WS_SYSMENU) TRACE(" WS_SYSMENU");
884 if(style & WS_THICKFRAME) TRACE(" WS_THICKFRAME");
885 if(style & WS_GROUP) TRACE(" WS_GROUP");
886 if(style & WS_TABSTOP) TRACE(" WS_TABSTOP");
887 if(style & WS_MINIMIZEBOX) TRACE(" WS_MINIMIZEBOX");
888 if(style & WS_MAXIMIZEBOX) TRACE(" WS_MAXIMIZEBOX");
890 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
891 #define DUMPED_STYLES \
892 (WS_POPUP | \
893 WS_CHILD | \
894 WS_MINIMIZE | \
895 WS_VISIBLE | \
896 WS_DISABLED | \
897 WS_CLIPSIBLINGS | \
898 WS_CLIPCHILDREN | \
899 WS_MAXIMIZE | \
900 WS_BORDER | \
901 WS_DLGFRAME | \
902 WS_VSCROLL | \
903 WS_HSCROLL | \
904 WS_SYSMENU | \
905 WS_THICKFRAME | \
906 WS_GROUP | \
907 WS_TABSTOP | \
908 WS_MINIMIZEBOX | \
909 WS_MAXIMIZEBOX)
911 if(style & ~DUMPED_STYLES) TRACE(" %08lx", style & ~DUMPED_STYLES);
912 TRACE("\n");
913 #undef DUMPED_STYLES
915 TRACE( "exstyle:" );
916 if(exstyle & WS_EX_DLGMODALFRAME) TRACE(" WS_EX_DLGMODALFRAME");
917 if(exstyle & WS_EX_DRAGDETECT) TRACE(" WS_EX_DRAGDETECT");
918 if(exstyle & WS_EX_NOPARENTNOTIFY) TRACE(" WS_EX_NOPARENTNOTIFY");
919 if(exstyle & WS_EX_TOPMOST) TRACE(" WS_EX_TOPMOST");
920 if(exstyle & WS_EX_ACCEPTFILES) TRACE(" WS_EX_ACCEPTFILES");
921 if(exstyle & WS_EX_TRANSPARENT) TRACE(" WS_EX_TRANSPARENT");
922 if(exstyle & WS_EX_MDICHILD) TRACE(" WS_EX_MDICHILD");
923 if(exstyle & WS_EX_TOOLWINDOW) TRACE(" WS_EX_TOOLWINDOW");
924 if(exstyle & WS_EX_WINDOWEDGE) TRACE(" WS_EX_WINDOWEDGE");
925 if(exstyle & WS_EX_CLIENTEDGE) TRACE(" WS_EX_CLIENTEDGE");
926 if(exstyle & WS_EX_CONTEXTHELP) TRACE(" WS_EX_CONTEXTHELP");
927 if(exstyle & WS_EX_RIGHT) TRACE(" WS_EX_RIGHT");
928 if(exstyle & WS_EX_RTLREADING) TRACE(" WS_EX_RTLREADING");
929 if(exstyle & WS_EX_LEFTSCROLLBAR) TRACE(" WS_EX_LEFTSCROLLBAR");
930 if(exstyle & WS_EX_CONTROLPARENT) TRACE(" WS_EX_CONTROLPARENT");
931 if(exstyle & WS_EX_STATICEDGE) TRACE(" WS_EX_STATICEDGE");
932 if(exstyle & WS_EX_APPWINDOW) TRACE(" WS_EX_APPWINDOW");
933 if(exstyle & WS_EX_LAYERED) TRACE(" WS_EX_LAYERED");
935 #define DUMPED_EX_STYLES \
936 (WS_EX_DLGMODALFRAME | \
937 WS_EX_DRAGDETECT | \
938 WS_EX_NOPARENTNOTIFY | \
939 WS_EX_TOPMOST | \
940 WS_EX_ACCEPTFILES | \
941 WS_EX_TRANSPARENT | \
942 WS_EX_MDICHILD | \
943 WS_EX_TOOLWINDOW | \
944 WS_EX_WINDOWEDGE | \
945 WS_EX_CLIENTEDGE | \
946 WS_EX_CONTEXTHELP | \
947 WS_EX_RIGHT | \
948 WS_EX_RTLREADING | \
949 WS_EX_LEFTSCROLLBAR | \
950 WS_EX_CONTROLPARENT | \
951 WS_EX_STATICEDGE | \
952 WS_EX_APPWINDOW | \
953 WS_EX_LAYERED)
955 if(exstyle & ~DUMPED_EX_STYLES) TRACE(" %08lx", exstyle & ~DUMPED_EX_STYLES);
956 TRACE("\n");
957 #undef DUMPED_EX_STYLES
961 /***********************************************************************
962 * WIN_CreateWindowEx
964 * Implementation of CreateWindowEx().
966 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
967 WINDOWPROCTYPE type )
969 INT sw = SW_SHOW;
970 struct tagCLASS *classPtr;
971 WND *wndPtr;
972 HWND hwnd, parent, owner;
973 INT wndExtra;
974 DWORD clsStyle;
975 WNDPROC winproc;
976 DCE *dce;
977 BOOL unicode = (type == WIN_PROC_32W);
979 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
980 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
981 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszClass) : debugstr_a(cs->lpszClass),
982 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
983 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
985 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
987 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
988 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
990 /* Find the parent window */
992 parent = GetDesktopWindow();
993 owner = 0;
995 if (cs->hwndParent == HWND_MESSAGE)
997 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
998 * message window (style: WS_POPUP|WS_DISABLED)
1000 FIXME("Parent is HWND_MESSAGE\n");
1002 else if (cs->hwndParent)
1004 /* Make sure parent is valid */
1005 if (!IsWindow( cs->hwndParent ))
1007 WARN("Bad parent %p\n", cs->hwndParent );
1008 return 0;
1010 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1011 parent = WIN_GetFullHandle(cs->hwndParent);
1012 else
1013 owner = GetAncestor( cs->hwndParent, GA_ROOT );
1015 else if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1017 WARN("No parent for child window\n" );
1018 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1021 /* Find the window class */
1022 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
1023 &wndExtra, &winproc, &clsStyle, &dce )))
1025 WARN("Bad class '%s'\n", cs->lpszClass );
1026 return 0;
1029 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
1031 /* Correct the window style - stage 1
1033 * These are patches that appear to affect both the style loaded into the
1034 * WIN structure and passed in the CreateStruct to the WM_CREATE etc.
1036 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1037 * why does the user get to set it?
1040 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
1041 * tested for WS_POPUP
1043 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
1044 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
1045 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
1046 cs->dwExStyle |= WS_EX_WINDOWEDGE;
1047 else
1048 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
1050 /* Create the window structure */
1052 if (!(wndPtr = create_window_handle( parent, owner, classAtom,
1053 sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
1055 TRACE("out of memory\n" );
1056 return 0;
1058 hwnd = wndPtr->hwndSelf;
1060 /* Fill the window structure */
1062 wndPtr->tid = GetCurrentThreadId();
1063 wndPtr->owner = owner;
1064 wndPtr->parent = parent;
1065 wndPtr->class = classPtr;
1066 wndPtr->winproc = winproc;
1067 wndPtr->hInstance = cs->hInstance;
1068 wndPtr->text = NULL;
1069 wndPtr->hrgnUpdate = 0;
1070 wndPtr->hrgnWnd = 0;
1071 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1072 wndPtr->dwExStyle = cs->dwExStyle;
1073 wndPtr->clsStyle = clsStyle;
1074 wndPtr->wIDmenu = 0;
1075 wndPtr->helpContext = 0;
1076 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
1077 wndPtr->pVScroll = NULL;
1078 wndPtr->pHScroll = NULL;
1079 wndPtr->userdata = 0;
1080 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU) ? MENU_GetSysMenu( hwnd, 0 ) : 0;
1081 wndPtr->cbWndExtra = wndExtra;
1083 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
1085 /* Correct the window style - stage 2 */
1087 if (!(cs->style & WS_CHILD))
1089 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1090 if (!(cs->style & WS_POPUP))
1092 wndPtr->dwStyle |= WS_CAPTION;
1093 wndPtr->flags |= WIN_NEED_SIZE;
1096 SERVER_START_REQ( set_window_info )
1098 req->handle = hwnd;
1099 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE;
1100 req->style = wndPtr->dwStyle;
1101 req->ex_style = wndPtr->dwExStyle;
1102 req->instance = (void *)wndPtr->hInstance;
1103 wine_server_call( req );
1105 SERVER_END_REQ;
1107 /* Get class or window DC if needed */
1109 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
1110 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
1111 else wndPtr->dce = NULL;
1113 /* Set the window menu */
1115 if (((wndPtr->dwStyle & (WS_CAPTION|WS_CHILD)) == WS_CAPTION) ||
1116 (wndPtr->dwExStyle & WS_EX_APPWINDOW))
1118 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
1119 else
1121 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
1122 if (menuName)
1124 if (HIWORD(cs->hInstance))
1125 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1126 else
1127 cs->hMenu = HMENU_32(LoadMenu16(HINSTANCE_16(cs->hInstance),menuName));
1129 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
1133 else SetWindowLongW( hwnd, GWL_ID, (UINT)cs->hMenu );
1134 WIN_ReleaseWndPtr( wndPtr );
1136 if (!USER_Driver.pCreateWindow( hwnd, cs, unicode))
1138 WIN_DestroyWindow( hwnd );
1139 return 0;
1142 /* Notify the parent window only */
1144 send_parent_notify( hwnd, WM_CREATE );
1145 if (!IsWindow( hwnd )) return 0;
1147 if (cs->style & WS_VISIBLE)
1149 /* in case WS_VISIBLE got set in the meantime */
1150 if (!(wndPtr = WIN_GetPtr( hwnd ))) return 0;
1151 WIN_SetStyle( hwnd, wndPtr->dwStyle & ~WS_VISIBLE );
1152 WIN_ReleasePtr( wndPtr );
1153 ShowWindow( hwnd, sw );
1156 /* Call WH_SHELL hook */
1158 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1159 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1161 TRACE("created window %p\n", hwnd);
1162 return hwnd;
1166 /***********************************************************************
1167 * CreateWindow (USER.41)
1169 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1170 DWORD style, INT16 x, INT16 y, INT16 width,
1171 INT16 height, HWND16 parent, HMENU16 menu,
1172 HINSTANCE16 instance, LPVOID data )
1174 return CreateWindowEx16( 0, className, windowName, style,
1175 x, y, width, height, parent, menu, instance, data );
1179 /***********************************************************************
1180 * CreateWindowEx (USER.452)
1182 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1183 LPCSTR windowName, DWORD style, INT16 x,
1184 INT16 y, INT16 width, INT16 height,
1185 HWND16 parent, HMENU16 menu,
1186 HINSTANCE16 instance, LPVOID data )
1188 ATOM classAtom;
1189 CREATESTRUCTA cs;
1190 char buffer[256];
1192 /* Find the class atom */
1194 if (HIWORD(className))
1196 if (!(classAtom = GlobalFindAtomA( className )))
1198 ERR( "bad class name %s\n", debugstr_a(className) );
1199 return 0;
1202 else
1204 classAtom = LOWORD(className);
1205 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1207 ERR( "bad atom %x\n", classAtom);
1208 return 0;
1210 className = buffer;
1213 /* Fix the coordinates */
1215 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1216 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1217 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1218 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1220 /* Create the window */
1222 cs.lpCreateParams = data;
1223 cs.hInstance = HINSTANCE_32(instance);
1224 cs.hMenu = HMENU_32(menu);
1225 cs.hwndParent = WIN_Handle32( parent );
1226 cs.style = style;
1227 cs.lpszName = windowName;
1228 cs.lpszClass = className;
1229 cs.dwExStyle = exStyle;
1231 return HWND_16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
1235 /***********************************************************************
1236 * CreateWindowExA (USER32.@)
1238 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1239 LPCSTR windowName, DWORD style, INT x,
1240 INT y, INT width, INT height,
1241 HWND parent, HMENU menu,
1242 HINSTANCE instance, LPVOID data )
1244 ATOM classAtom;
1245 CREATESTRUCTA cs;
1246 char buffer[256];
1248 if(!instance)
1249 instance=GetModuleHandleA(NULL);
1251 if(exStyle & WS_EX_MDICHILD)
1252 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1254 /* Find the class atom */
1256 if (HIWORD(className))
1258 if (!(classAtom = GlobalFindAtomA( className )))
1260 ERR( "bad class name %s\n", debugstr_a(className) );
1261 return 0;
1264 else
1266 classAtom = LOWORD(className);
1267 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1269 ERR( "bad atom %x\n", classAtom);
1270 return 0;
1272 className = buffer;
1275 /* Create the window */
1277 cs.lpCreateParams = data;
1278 cs.hInstance = instance;
1279 cs.hMenu = menu;
1280 cs.hwndParent = parent;
1281 cs.x = x;
1282 cs.y = y;
1283 cs.cx = width;
1284 cs.cy = height;
1285 cs.style = style;
1286 cs.lpszName = windowName;
1287 cs.lpszClass = className;
1288 cs.dwExStyle = exStyle;
1290 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1294 /***********************************************************************
1295 * CreateWindowExW (USER32.@)
1297 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1298 LPCWSTR windowName, DWORD style, INT x,
1299 INT y, INT width, INT height,
1300 HWND parent, HMENU menu,
1301 HINSTANCE instance, LPVOID data )
1303 ATOM classAtom;
1304 CREATESTRUCTW cs;
1305 WCHAR buffer[256];
1307 if(!instance)
1308 instance=GetModuleHandleW(NULL);
1310 if(exStyle & WS_EX_MDICHILD)
1311 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1313 /* Find the class atom */
1315 if (HIWORD(className))
1317 if (!(classAtom = GlobalFindAtomW( className )))
1319 ERR( "bad class name %s\n", debugstr_w(className) );
1320 return 0;
1323 else
1325 classAtom = LOWORD(className);
1326 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1328 ERR( "bad atom %x\n", classAtom);
1329 return 0;
1331 className = buffer;
1334 /* Create the window */
1336 cs.lpCreateParams = data;
1337 cs.hInstance = instance;
1338 cs.hMenu = menu;
1339 cs.hwndParent = parent;
1340 cs.x = x;
1341 cs.y = y;
1342 cs.cx = width;
1343 cs.cy = height;
1344 cs.style = style;
1345 cs.lpszName = windowName;
1346 cs.lpszClass = className;
1347 cs.dwExStyle = exStyle;
1349 /* Note: we rely on the fact that CREATESTRUCTA and */
1350 /* CREATESTRUCTW have the same layout. */
1351 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1355 /***********************************************************************
1356 * WIN_SendDestroyMsg
1358 static void WIN_SendDestroyMsg( HWND hwnd )
1360 GUITHREADINFO info;
1362 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1364 if (hwnd == info.hwndCaret) DestroyCaret();
1366 if (USER_Driver.pResetSelectionOwner)
1367 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1370 * Send the WM_DESTROY to the window.
1372 SendMessageA( hwnd, WM_DESTROY, 0, 0);
1375 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1376 * make sure that the window still exists when we come back.
1378 if (IsWindow(hwnd))
1380 HWND* pWndArray;
1381 int i;
1383 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1385 /* start from the end (FIXME: is this needed?) */
1386 for (i = 0; pWndArray[i]; i++) ;
1388 while (--i >= 0)
1390 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1392 HeapFree( GetProcessHeap(), 0, pWndArray );
1394 else
1395 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1399 /***********************************************************************
1400 * DestroyWindow (USER32.@)
1402 BOOL WINAPI DestroyWindow( HWND hwnd )
1404 BOOL is_child;
1405 HWND h;
1407 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1409 SetLastError( ERROR_ACCESS_DENIED );
1410 return FALSE;
1413 TRACE("(%p)\n", hwnd);
1415 /* Look whether the focus is within the tree of windows we will
1416 * be destroying.
1418 h = GetFocus();
1419 if (h == hwnd || IsChild( hwnd, h ))
1421 HWND parent = GetAncestor( hwnd, GA_PARENT );
1422 if (parent == GetDesktopWindow()) parent = 0;
1423 SetFocus( parent );
1426 /* Call hooks */
1428 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1430 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1432 if (is_child)
1434 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1435 send_parent_notify( hwnd, WM_DESTROY );
1437 else if (!GetWindow( hwnd, GW_OWNER ))
1439 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1440 /* FIXME: clean up palette - see "Internals" p.352 */
1443 if (!IsWindow(hwnd)) return TRUE;
1445 if (USER_Driver.pResetSelectionOwner)
1446 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1448 /* Hide the window */
1450 if (!ShowWindow( hwnd, SW_HIDE ))
1452 if (hwnd == GetActiveWindow()) WINPOS_ActivateOtherWindow( hwnd );
1454 if (!IsWindow(hwnd)) return TRUE;
1456 /* Recursively destroy owned windows */
1458 if (!is_child)
1460 for (;;)
1462 int i, got_one = 0;
1463 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1464 if (list)
1466 for (i = 0; list[i]; i++)
1468 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1469 if (WIN_IsCurrentThread( list[i] ))
1471 DestroyWindow( list[i] );
1472 got_one = 1;
1473 continue;
1475 WIN_SetOwner( list[i], 0 );
1477 HeapFree( GetProcessHeap(), 0, list );
1479 if (!got_one) break;
1483 /* Send destroy messages */
1485 WIN_SendDestroyMsg( hwnd );
1486 if (!IsWindow( hwnd )) return TRUE;
1488 if (GetClipboardOwner() == hwnd)
1489 CLIPBOARD_ReleaseOwner();
1491 /* Unlink now so we won't bother with the children later on */
1493 WIN_UnlinkWindow( hwnd );
1495 /* Destroy the window storage */
1497 WIN_DestroyWindow( hwnd );
1498 return TRUE;
1502 /***********************************************************************
1503 * CloseWindow (USER32.@)
1505 BOOL WINAPI CloseWindow( HWND hwnd )
1507 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1508 ShowWindow( hwnd, SW_MINIMIZE );
1509 return TRUE;
1513 /***********************************************************************
1514 * OpenIcon (USER32.@)
1516 BOOL WINAPI OpenIcon( HWND hwnd )
1518 if (!IsIconic( hwnd )) return FALSE;
1519 ShowWindow( hwnd, SW_SHOWNORMAL );
1520 return TRUE;
1524 /***********************************************************************
1525 * WIN_FindWindow
1527 * Implementation of FindWindow() and FindWindowEx().
1529 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1531 HWND *list = NULL;
1532 HWND retvalue = 0;
1533 int i = 0, len = 0;
1534 WCHAR *buffer = NULL;
1536 if (!parent) parent = GetDesktopWindow();
1537 if (title)
1539 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1540 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1543 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1545 if (child)
1547 child = WIN_GetFullHandle( child );
1548 while (list[i] && list[i] != child) i++;
1549 if (!list[i]) goto done;
1550 i++; /* start from next window */
1553 if (title)
1555 while (list[i])
1557 if (GetWindowTextW( list[i], buffer, len ) && !strcmpiW( buffer, title )) break;
1558 i++;
1561 retvalue = list[i];
1563 done:
1564 if (list) HeapFree( GetProcessHeap(), 0, list );
1565 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1566 return retvalue;
1571 /***********************************************************************
1572 * FindWindowA (USER32.@)
1574 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1576 HWND ret = FindWindowExA( 0, 0, className, title );
1577 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1578 return ret;
1582 /***********************************************************************
1583 * FindWindowExA (USER32.@)
1585 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1586 LPCSTR className, LPCSTR title )
1588 ATOM atom = 0;
1589 LPWSTR buffer;
1590 HWND hwnd;
1591 INT len;
1593 if (className)
1595 /* If the atom doesn't exist, then no class */
1596 /* with this name exists either. */
1597 if (!(atom = GlobalFindAtomA( className )))
1599 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1600 return 0;
1603 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
1605 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1606 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1607 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
1608 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1609 HeapFree( GetProcessHeap(), 0, buffer );
1610 return hwnd;
1614 /***********************************************************************
1615 * FindWindowExW (USER32.@)
1617 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1618 LPCWSTR className, LPCWSTR title )
1620 ATOM atom = 0;
1622 if (className)
1624 /* If the atom doesn't exist, then no class */
1625 /* with this name exists either. */
1626 if (!(atom = GlobalFindAtomW( className )))
1628 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1629 return 0;
1632 return WIN_FindWindow( parent, child, atom, title );
1636 /***********************************************************************
1637 * FindWindowW (USER32.@)
1639 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1641 return FindWindowExW( 0, 0, className, title );
1645 /**********************************************************************
1646 * GetDesktopWindow (USER32.@)
1648 HWND WINAPI GetDesktopWindow(void)
1650 if (pWndDesktop) return pWndDesktop->hwndSelf;
1651 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" );
1652 ExitProcess(1);
1653 return 0;
1657 /*******************************************************************
1658 * EnableWindow (USER32.@)
1660 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1662 WND *wndPtr;
1663 BOOL retvalue;
1664 LONG style;
1665 HWND full_handle;
1667 if (is_broadcast(hwnd))
1669 SetLastError( ERROR_INVALID_PARAMETER );
1670 return FALSE;
1673 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1674 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1676 hwnd = full_handle;
1678 TRACE("( %p, %d )\n", hwnd, enable);
1680 if (!(wndPtr = WIN_GetPtr( hwnd ))) return FALSE;
1681 style = wndPtr->dwStyle;
1682 retvalue = ((style & WS_DISABLED) != 0);
1683 WIN_ReleasePtr( wndPtr );
1685 if (enable && retvalue)
1687 WIN_SetStyle( hwnd, style & ~WS_DISABLED );
1688 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1690 else if (!enable && !retvalue)
1692 HWND focus_wnd, capture_wnd;
1694 SendMessageA( hwnd, WM_CANCELMODE, 0, 0);
1696 WIN_SetStyle( hwnd, style | WS_DISABLED );
1698 focus_wnd = GetFocus();
1699 if (hwnd == focus_wnd || IsChild(hwnd, focus_wnd))
1700 SetFocus( 0 ); /* A disabled window can't have the focus */
1702 capture_wnd = GetCapture();
1703 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1704 ReleaseCapture(); /* A disabled window can't capture the mouse */
1706 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1708 return retvalue;
1712 /***********************************************************************
1713 * IsWindowEnabled (USER32.@)
1715 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1717 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1721 /***********************************************************************
1722 * IsWindowUnicode (USER32.@)
1724 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1726 WND * wndPtr;
1727 BOOL retvalue;
1729 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1730 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1731 WIN_ReleaseWndPtr(wndPtr);
1732 return retvalue;
1736 /**********************************************************************
1737 * GetWindowWord (USER32.@)
1739 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1741 if (offset >= 0)
1743 WORD retvalue = 0;
1744 WND *wndPtr = WIN_GetPtr( hwnd );
1745 if (!wndPtr)
1747 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1748 return 0;
1750 if (wndPtr == WND_OTHER_PROCESS)
1752 if (IsWindow( hwnd ))
1753 FIXME( "(%d) not supported yet on other process window %p\n", offset, hwnd );
1754 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1755 return 0;
1757 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1759 WARN("Invalid offset %d\n", offset );
1760 SetLastError( ERROR_INVALID_INDEX );
1762 else retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1763 WIN_ReleasePtr( wndPtr );
1764 return retvalue;
1767 switch(offset)
1769 case GWL_HWNDPARENT:
1770 return GetWindowLongW( hwnd, offset );
1771 case GWL_ID:
1772 case GWL_HINSTANCE:
1774 LONG ret = GetWindowLongW( hwnd, offset );
1775 if (HIWORD(ret))
1776 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1777 return LOWORD(ret);
1779 default:
1780 WARN("Invalid offset %d\n", offset );
1781 return 0;
1786 /**********************************************************************
1787 * SetWindowWord (USER32.@)
1789 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1791 WORD *ptr, retval;
1792 WND * wndPtr;
1794 switch(offset)
1796 case GWL_ID:
1797 case GWL_HINSTANCE:
1798 case GWL_HWNDPARENT:
1799 return SetWindowLongW( hwnd, offset, (UINT)newval );
1800 default:
1801 if (offset < 0)
1803 WARN("Invalid offset %d\n", offset );
1804 SetLastError( ERROR_INVALID_INDEX );
1805 return 0;
1809 wndPtr = WIN_GetPtr( hwnd );
1810 if (wndPtr == WND_OTHER_PROCESS)
1812 if (IsWindow(hwnd))
1813 FIXME( "set %d <- %x not supported yet on other process window %p\n",
1814 offset, newval, hwnd );
1815 wndPtr = NULL;
1817 if (!wndPtr)
1819 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1820 return 0;
1823 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1825 WARN("Invalid offset %d\n", offset );
1826 WIN_ReleasePtr(wndPtr);
1827 SetLastError( ERROR_INVALID_INDEX );
1828 return 0;
1830 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1831 retval = *ptr;
1832 *ptr = newval;
1833 WIN_ReleasePtr(wndPtr);
1834 return retval;
1838 /**********************************************************************
1839 * WIN_GetWindowLong
1841 * Helper function for GetWindowLong().
1843 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1845 LONG retvalue = 0;
1846 WND *wndPtr;
1848 if (offset == GWL_HWNDPARENT)
1850 HWND parent = GetAncestor( hwnd, GA_PARENT );
1851 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1852 return (LONG)parent;
1855 if (!(wndPtr = WIN_GetPtr( hwnd )))
1857 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1858 return 0;
1861 if (wndPtr == WND_OTHER_PROCESS)
1863 if (offset >= 0)
1865 if (IsWindow(hwnd))
1866 FIXME( "(%d) not supported on other process window %p\n", offset, hwnd );
1867 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1868 return 0;
1870 if (offset == GWL_WNDPROC)
1872 SetLastError( ERROR_ACCESS_DENIED );
1873 return 0;
1875 SERVER_START_REQ( set_window_info )
1877 req->handle = hwnd;
1878 req->flags = 0; /* don't set anything, just retrieve */
1879 if (!wine_server_call_err( req ))
1881 switch(offset)
1883 case GWL_STYLE: retvalue = reply->old_style; break;
1884 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1885 case GWL_ID: retvalue = reply->old_id; break;
1886 case GWL_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1887 case GWL_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
1888 default:
1889 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 LONG retval = 0;
1965 WND *wndPtr;
1967 TRACE( "%p %d %lx %x\n", hwnd, offset, newval, type );
1969 if (is_broadcast(hwnd))
1971 SetLastError( ERROR_INVALID_PARAMETER );
1972 return FALSE;
1974 if (!WIN_IsCurrentProcess( hwnd ))
1976 if (offset == GWL_WNDPROC)
1978 SetLastError( ERROR_ACCESS_DENIED );
1979 return 0;
1981 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
1984 wndPtr = WIN_GetPtr( hwnd );
1985 if (wndPtr->hwndSelf == GetDesktopWindow())
1987 /* can't change anything on the desktop window */
1988 WIN_ReleasePtr( wndPtr );
1989 SetLastError( ERROR_ACCESS_DENIED );
1990 return 0;
1993 if (offset >= 0)
1995 LONG *ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1996 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
1998 WARN("Invalid offset %d\n", offset );
1999 WIN_ReleasePtr( wndPtr );
2000 SetLastError( ERROR_INVALID_INDEX );
2001 return 0;
2003 /* Special case for dialog window procedure */
2004 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2006 retval = (LONG)WINPROC_GetProc( (WNDPROC)*ptr, type );
2007 WINPROC_SetProc( (WNDPROC *)ptr, (WNDPROC)newval, type, WIN_PROC_WINDOW );
2008 WIN_ReleasePtr( wndPtr );
2009 return retval;
2011 retval = *ptr;
2012 *ptr = newval;
2013 WIN_ReleasePtr( wndPtr );
2015 else
2017 STYLESTRUCT style;
2018 BOOL ok;
2020 /* first some special cases */
2021 switch( offset )
2023 case GWL_STYLE:
2024 case GWL_EXSTYLE:
2025 style.styleOld =
2026 offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
2027 style.styleNew = newval;
2028 WIN_ReleasePtr( wndPtr );
2029 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
2030 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
2031 newval = style.styleNew;
2032 break;
2033 case GWL_HWNDPARENT:
2034 if (wndPtr->parent == GetDesktopWindow())
2036 WIN_ReleasePtr( wndPtr );
2037 return (LONG)WIN_SetOwner( hwnd, (HWND)newval );
2039 else
2041 WIN_ReleasePtr( wndPtr );
2042 return (LONG)SetParent( hwnd, (HWND)newval );
2044 case GWL_WNDPROC:
2045 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2046 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC)newval, type, WIN_PROC_WINDOW );
2047 WIN_ReleasePtr( wndPtr );
2048 return retval;
2049 case GWL_ID:
2050 case GWL_HINSTANCE:
2051 case GWL_USERDATA:
2052 break;
2053 default:
2054 WIN_ReleasePtr( wndPtr );
2055 WARN("Invalid offset %d\n", offset );
2056 SetLastError( ERROR_INVALID_INDEX );
2057 return 0;
2060 SERVER_START_REQ( set_window_info )
2062 req->handle = hwnd;
2063 switch(offset)
2065 case GWL_STYLE:
2066 req->flags = SET_WIN_STYLE;
2067 req->style = newval;
2068 break;
2069 case GWL_EXSTYLE:
2070 req->flags = SET_WIN_EXSTYLE;
2071 req->ex_style = newval;
2072 break;
2073 case GWL_ID:
2074 req->flags = SET_WIN_ID;
2075 req->id = newval;
2076 break;
2077 case GWL_HINSTANCE:
2078 req->flags = SET_WIN_INSTANCE;
2079 req->instance = (void *)newval;
2080 break;
2081 case GWL_USERDATA:
2082 req->flags = SET_WIN_USERDATA;
2083 req->user_data = (void *)newval;
2084 break;
2086 if ((ok = !wine_server_call_err( req )))
2088 switch(offset)
2090 case GWL_STYLE:
2091 wndPtr->dwStyle = newval;
2092 retval = reply->old_style;
2093 break;
2094 case GWL_EXSTYLE:
2095 wndPtr->dwExStyle = newval;
2096 retval = reply->old_ex_style;
2097 break;
2098 case GWL_ID:
2099 wndPtr->wIDmenu = newval;
2100 retval = reply->old_id;
2101 break;
2102 case GWL_HINSTANCE:
2103 wndPtr->hInstance = (HINSTANCE)newval;
2104 retval = (ULONG_PTR)reply->old_instance;
2105 break;
2106 case GWL_USERDATA:
2107 wndPtr->userdata = newval;
2108 retval = (ULONG_PTR)reply->old_user_data;
2109 break;
2113 SERVER_END_REQ;
2114 WIN_ReleasePtr( wndPtr );
2116 if (!ok) return 0;
2118 if (offset == GWL_STYLE && USER_Driver.pSetWindowStyle)
2119 USER_Driver.pSetWindowStyle( hwnd, retval );
2121 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2122 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2125 return retval;
2129 /**********************************************************************
2130 * GetWindowLong (USER.135)
2132 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2134 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
2138 /**********************************************************************
2139 * GetWindowLongA (USER32.@)
2141 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2143 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2147 /**********************************************************************
2148 * GetWindowLongW (USER32.@)
2150 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2152 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2156 /**********************************************************************
2157 * SetWindowLong (USER.136)
2159 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2161 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
2165 /**********************************************************************
2166 * SetWindowLongA (USER32.@)
2168 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2170 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2174 /**********************************************************************
2175 * SetWindowLongW (USER32.@) Set window attribute
2177 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2178 * value in a window's extra memory.
2180 * The _hwnd_ parameter specifies the window. is the handle to a
2181 * window that has extra memory. The _newval_ parameter contains the
2182 * new attribute or extra memory value. If positive, the _offset_
2183 * parameter is the byte-addressed location in the window's extra
2184 * memory to set. If negative, _offset_ specifies the window
2185 * attribute to set, and should be one of the following values:
2187 * GWL_EXSTYLE The window's extended window style
2189 * GWL_STYLE The window's window style.
2191 * GWL_WNDPROC Pointer to the window's window procedure.
2193 * GWL_HINSTANCE The window's pplication instance handle.
2195 * GWL_ID The window's identifier.
2197 * GWL_USERDATA The window's user-specified data.
2199 * If the window is a dialog box, the _offset_ parameter can be one of
2200 * the following values:
2202 * DWL_DLGPROC The address of the window's dialog box procedure.
2204 * DWL_MSGRESULT The return value of a message
2205 * that the dialog box procedure processed.
2207 * DWL_USER Application specific information.
2209 * RETURNS
2211 * If successful, returns the previous value located at _offset_. Otherwise,
2212 * returns 0.
2214 * NOTES
2216 * Extra memory for a window class is specified by a nonzero cbWndExtra
2217 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2218 * time of class creation.
2220 * Using GWL_WNDPROC to set a new window procedure effectively creates
2221 * a window subclass. Use CallWindowProc() in the new windows procedure
2222 * to pass messages to the superclass's window procedure.
2224 * The user data is reserved for use by the application which created
2225 * the window.
2227 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2228 * instead, call the EnableWindow() function to change the window's
2229 * disabled state.
2231 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2232 * SetParent() instead.
2234 * Win95:
2235 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2236 * it sends WM_STYLECHANGING before changing the settings
2237 * and WM_STYLECHANGED afterwards.
2238 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2240 LONG WINAPI SetWindowLongW(
2241 HWND hwnd, /* [in] window to alter */
2242 INT offset, /* [in] offset, in bytes, of location to alter */
2243 LONG newval /* [in] new value of location */
2245 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2249 /*******************************************************************
2250 * GetWindowTextA (USER32.@)
2252 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2254 WCHAR *buffer;
2256 if (WIN_IsCurrentProcess( hwnd ))
2257 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2259 /* when window belongs to other process, don't send a message */
2260 if (nMaxCount <= 0) return 0;
2261 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2262 get_server_window_text( hwnd, buffer, nMaxCount );
2263 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2264 lpString[nMaxCount-1] = 0;
2265 HeapFree( GetProcessHeap(), 0, buffer );
2266 return strlen(lpString);
2270 /*******************************************************************
2271 * InternalGetWindowText (USER32.@)
2273 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2275 WND *win;
2277 if (nMaxCount <= 0) return 0;
2278 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2279 if (win != WND_OTHER_PROCESS)
2281 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2282 else lpString[0] = 0;
2283 WIN_ReleasePtr( win );
2285 else
2287 get_server_window_text( hwnd, lpString, nMaxCount );
2289 return strlenW(lpString);
2293 /*******************************************************************
2294 * GetWindowTextW (USER32.@)
2296 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2298 if (WIN_IsCurrentProcess( hwnd ))
2299 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2301 /* when window belongs to other process, don't send a message */
2302 if (nMaxCount <= 0) return 0;
2303 get_server_window_text( hwnd, lpString, nMaxCount );
2304 return strlenW(lpString);
2308 /*******************************************************************
2309 * SetWindowText (USER32.@)
2310 * SetWindowTextA (USER32.@)
2312 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2314 if (is_broadcast(hwnd))
2316 SetLastError( ERROR_INVALID_PARAMETER );
2317 return FALSE;
2319 if (!WIN_IsCurrentProcess( hwnd ))
2321 FIXME( "cannot set text %s of other process window %p\n", debugstr_a(lpString), hwnd );
2322 SetLastError( ERROR_ACCESS_DENIED );
2323 return FALSE;
2325 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2329 /*******************************************************************
2330 * SetWindowTextW (USER32.@)
2332 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2334 if (is_broadcast(hwnd))
2336 SetLastError( ERROR_INVALID_PARAMETER );
2337 return FALSE;
2339 if (!WIN_IsCurrentProcess( hwnd ))
2341 FIXME( "cannot set text %s of other process window %p\n", debugstr_w(lpString), hwnd );
2342 SetLastError( ERROR_ACCESS_DENIED );
2343 return FALSE;
2345 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2349 /*******************************************************************
2350 * GetWindowTextLengthA (USER32.@)
2352 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2354 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2357 /*******************************************************************
2358 * GetWindowTextLengthW (USER32.@)
2360 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2362 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2366 /*******************************************************************
2367 * IsWindow (USER32.@)
2369 BOOL WINAPI IsWindow( HWND hwnd )
2371 WND *ptr;
2372 BOOL ret;
2374 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2376 if (ptr != WND_OTHER_PROCESS)
2378 WIN_ReleasePtr( ptr );
2379 return TRUE;
2382 /* check other processes */
2383 SERVER_START_REQ( get_window_info )
2385 req->handle = hwnd;
2386 ret = !wine_server_call_err( req );
2388 SERVER_END_REQ;
2389 return ret;
2393 /***********************************************************************
2394 * GetWindowThreadProcessId (USER32.@)
2396 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2398 WND *ptr;
2399 DWORD tid = 0;
2401 if (!(ptr = WIN_GetPtr( hwnd )))
2403 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2404 return 0;
2407 if (ptr != WND_OTHER_PROCESS)
2409 /* got a valid window */
2410 tid = ptr->tid;
2411 if (process) *process = GetCurrentProcessId();
2412 WIN_ReleasePtr( ptr );
2413 return tid;
2416 /* check other processes */
2417 SERVER_START_REQ( get_window_info )
2419 req->handle = hwnd;
2420 if (!wine_server_call_err( req ))
2422 tid = (DWORD)reply->tid;
2423 if (process) *process = (DWORD)reply->pid;
2426 SERVER_END_REQ;
2427 return tid;
2431 /*****************************************************************
2432 * GetParent (USER32.@)
2434 HWND WINAPI GetParent( HWND hwnd )
2436 WND *wndPtr;
2437 HWND retvalue = 0;
2439 if (!(wndPtr = WIN_GetPtr( hwnd )))
2441 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2442 return 0;
2444 if (wndPtr == WND_OTHER_PROCESS)
2446 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2447 if (style & (WS_POPUP | WS_CHILD))
2449 SERVER_START_REQ( get_window_tree )
2451 req->handle = hwnd;
2452 if (!wine_server_call_err( req ))
2454 if (style & WS_POPUP) retvalue = reply->owner;
2455 else if (style & WS_CHILD) retvalue = reply->parent;
2458 SERVER_END_REQ;
2461 else
2463 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2464 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2465 WIN_ReleasePtr( wndPtr );
2467 return retvalue;
2471 /*****************************************************************
2472 * GetAncestor (USER32.@)
2474 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2476 WND *win;
2477 HWND *list, ret = 0;
2479 switch(type)
2481 case GA_PARENT:
2482 if (!(win = WIN_GetPtr( hwnd )))
2484 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2485 return 0;
2487 if (win != WND_OTHER_PROCESS)
2489 ret = win->parent;
2490 WIN_ReleasePtr( win );
2492 else /* need to query the server */
2494 SERVER_START_REQ( get_window_tree )
2496 req->handle = hwnd;
2497 if (!wine_server_call_err( req )) ret = reply->parent;
2499 SERVER_END_REQ;
2501 break;
2503 case GA_ROOT:
2504 if (!(list = WIN_ListParents( hwnd ))) return 0;
2506 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2507 else
2509 int count = 2;
2510 while (list[count]) count++;
2511 ret = list[count - 2]; /* get the one before the desktop */
2513 HeapFree( GetProcessHeap(), 0, list );
2514 break;
2516 case GA_ROOTOWNER:
2517 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2518 for (;;)
2520 HWND parent = GetParent( ret );
2521 if (!parent) break;
2522 ret = parent;
2524 break;
2526 return ret;
2530 /*****************************************************************
2531 * SetParent (USER32.@)
2533 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2535 WND *wndPtr;
2536 HWND retvalue, full_handle;
2537 BOOL was_visible;
2539 if (is_broadcast(hwnd) || is_broadcast(parent))
2541 SetLastError(ERROR_INVALID_PARAMETER);
2542 return 0;
2545 if (!parent) parent = GetDesktopWindow();
2546 else parent = WIN_GetFullHandle( parent );
2548 if (!IsWindow( parent ))
2550 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2551 return 0;
2554 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2555 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2557 hwnd = full_handle;
2559 if (USER_Driver.pSetParent)
2560 return USER_Driver.pSetParent( hwnd, parent );
2562 /* Windows hides the window first, then shows it again
2563 * including the WM_SHOWWINDOW messages and all */
2564 was_visible = ShowWindow( hwnd, SW_HIDE );
2566 if (!IsWindow( parent )) return 0;
2567 if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return 0;
2569 retvalue = wndPtr->parent; /* old parent */
2570 if (parent != retvalue)
2572 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2574 if (parent != GetDesktopWindow()) /* a child window */
2576 if (!(wndPtr->dwStyle & WS_CHILD))
2578 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
2579 if (menu) DestroyMenu( menu );
2583 WIN_ReleasePtr( wndPtr );
2585 /* SetParent additionally needs to make hwnd the topmost window
2586 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2587 WM_WINDOWPOSCHANGED notification messages.
2589 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2590 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2591 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2592 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2593 return retvalue;
2597 /*******************************************************************
2598 * IsChild (USER32.@)
2600 BOOL WINAPI IsChild( HWND parent, HWND child )
2602 HWND *list = WIN_ListParents( child );
2603 int i;
2604 BOOL ret;
2606 if (!list) return FALSE;
2607 parent = WIN_GetFullHandle( parent );
2608 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2609 ret = (list[i] != 0);
2610 HeapFree( GetProcessHeap(), 0, list );
2611 return ret;
2615 /***********************************************************************
2616 * IsWindowVisible (USER32.@)
2618 BOOL WINAPI IsWindowVisible( HWND hwnd )
2620 HWND *list;
2621 BOOL retval;
2622 int i;
2624 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2625 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2626 for (i = 0; list[i]; i++)
2627 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2628 retval = !list[i];
2629 HeapFree( GetProcessHeap(), 0, list );
2630 return retval;
2634 /***********************************************************************
2635 * WIN_IsWindowDrawable
2637 * hwnd is drawable when it is visible, all parents are not
2638 * minimized, and it is itself not minimized unless we are
2639 * trying to draw its default class icon.
2641 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2643 HWND *list;
2644 BOOL retval;
2645 int i;
2646 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2648 if (!(style & WS_VISIBLE)) return FALSE;
2649 if ((style & WS_MINIMIZE) && icon && GetClassLongA( hwnd, GCL_HICON )) return FALSE;
2651 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2652 for (i = 0; list[i]; i++)
2653 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2654 break;
2655 retval = !list[i];
2656 HeapFree( GetProcessHeap(), 0, list );
2657 return retval;
2661 /*******************************************************************
2662 * GetTopWindow (USER32.@)
2664 HWND WINAPI GetTopWindow( HWND hwnd )
2666 if (!hwnd) hwnd = GetDesktopWindow();
2667 return GetWindow( hwnd, GW_CHILD );
2671 /*******************************************************************
2672 * GetWindow (USER32.@)
2674 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2676 HWND retval = 0;
2678 if (rel == GW_OWNER) /* this one may be available locally */
2680 WND *wndPtr = WIN_GetPtr( hwnd );
2681 if (!wndPtr)
2683 SetLastError( ERROR_INVALID_HANDLE );
2684 return 0;
2686 if (wndPtr != WND_OTHER_PROCESS)
2688 retval = wndPtr->owner;
2689 WIN_ReleasePtr( wndPtr );
2690 return retval;
2692 /* else fall through to server call */
2695 SERVER_START_REQ( get_window_tree )
2697 req->handle = hwnd;
2698 if (!wine_server_call_err( req ))
2700 switch(rel)
2702 case GW_HWNDFIRST:
2703 retval = reply->first_sibling;
2704 break;
2705 case GW_HWNDLAST:
2706 retval = reply->last_sibling;
2707 break;
2708 case GW_HWNDNEXT:
2709 retval = reply->next_sibling;
2710 break;
2711 case GW_HWNDPREV:
2712 retval = reply->prev_sibling;
2713 break;
2714 case GW_OWNER:
2715 retval = reply->owner;
2716 break;
2717 case GW_CHILD:
2718 retval = reply->first_child;
2719 break;
2723 SERVER_END_REQ;
2724 return retval;
2728 /***********************************************************************
2729 * WIN_InternalShowOwnedPopups
2731 * Internal version of ShowOwnedPopups; Wine functions should use this
2732 * to avoid interfering with application calls to ShowOwnedPopups
2733 * and to make sure the application can't prevent showing/hiding.
2735 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2739 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2741 int count = 0;
2742 WND *pWnd;
2743 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2745 if (!win_array) return TRUE;
2748 * Show windows Lowest first, Highest last to preserve Z-Order
2750 while (win_array[count]) count++;
2751 while (--count >= 0)
2753 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2754 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2756 if (pWnd->dwStyle & WS_POPUP)
2758 if (fShow)
2760 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2761 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
2764 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2766 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2767 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2770 else
2772 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2773 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2774 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2777 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2779 ShowWindow(pWnd->hwndSelf,SW_HIDE);
2780 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2781 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
2785 WIN_ReleaseWndPtr( pWnd );
2787 HeapFree( GetProcessHeap(), 0, win_array );
2789 return TRUE;
2792 /*******************************************************************
2793 * ShowOwnedPopups (USER32.@)
2795 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2797 int count = 0;
2798 WND *pWnd;
2799 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2801 if (!win_array) return TRUE;
2803 while (win_array[count]) count++;
2804 while (--count >= 0)
2806 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2807 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2809 if (pWnd->dwStyle & WS_POPUP)
2811 if (fShow)
2813 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2815 /* In Windows, ShowOwnedPopups(TRUE) generates
2816 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2817 * regardless of the state of the owner
2819 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2820 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2823 else
2825 if (IsWindowVisible(pWnd->hwndSelf))
2827 /* In Windows, ShowOwnedPopups(FALSE) generates
2828 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2829 * regardless of the state of the owner
2831 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2832 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2836 WIN_ReleaseWndPtr( pWnd );
2838 HeapFree( GetProcessHeap(), 0, win_array );
2839 return TRUE;
2843 /*******************************************************************
2844 * GetLastActivePopup (USER32.@)
2846 HWND WINAPI GetLastActivePopup( HWND hwnd )
2848 HWND retval = hwnd;
2850 SERVER_START_REQ( get_window_info )
2852 req->handle = hwnd;
2853 if (!wine_server_call_err( req )) retval = reply->last_active;
2855 SERVER_END_REQ;
2856 return retval;
2860 /*******************************************************************
2861 * WIN_ListParents
2863 * Build an array of all parents of a given window, starting with
2864 * the immediate parent. The array must be freed with HeapFree.
2865 * Returns NULL if window is a top-level window.
2867 HWND *WIN_ListParents( HWND hwnd )
2869 WND *win;
2870 HWND current, *list;
2871 int pos = 0, size = 16, count = 0;
2873 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2875 current = hwnd;
2876 for (;;)
2878 if (!(win = WIN_GetPtr( current ))) goto empty;
2879 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
2880 list[pos] = win->parent;
2881 WIN_ReleasePtr( win );
2882 if (!(current = list[pos]))
2884 if (!pos) goto empty;
2885 return list;
2887 if (++pos == size - 1)
2889 /* need to grow the list */
2890 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
2891 if (!new_list) goto empty;
2892 list = new_list;
2893 size += 16;
2897 /* at least one parent belongs to another process, have to query the server */
2899 for (;;)
2901 count = 0;
2902 SERVER_START_REQ( get_window_parents )
2904 req->handle = hwnd;
2905 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
2906 if (!wine_server_call( req )) count = reply->count;
2908 SERVER_END_REQ;
2909 if (!count) goto empty;
2910 if (size > count)
2912 list[count] = 0;
2913 return list;
2915 HeapFree( GetProcessHeap(), 0, list );
2916 size = count + 1;
2917 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2920 empty:
2921 HeapFree( GetProcessHeap(), 0, list );
2922 return NULL;
2926 /*******************************************************************
2927 * WIN_ListChildren
2929 * Build an array of the children of a given window. The array must be
2930 * freed with HeapFree. Returns NULL when no windows are found.
2932 HWND *WIN_ListChildren( HWND hwnd )
2934 return list_window_children( hwnd, 0, 0 );
2938 /*******************************************************************
2939 * EnumWindows (USER32.@)
2941 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2943 HWND *list;
2944 BOOL ret = TRUE;
2945 int i, iWndsLocks;
2947 /* We have to build a list of all windows first, to avoid */
2948 /* unpleasant side-effects, for instance if the callback */
2949 /* function changes the Z-order of the windows. */
2951 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2953 /* Now call the callback function for every window */
2955 iWndsLocks = WIN_SuspendWndsLock();
2956 for (i = 0; list[i]; i++)
2958 /* Make sure that the window still exists */
2959 if (!IsWindow( list[i] )) continue;
2960 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2962 WIN_RestoreWndsLock(iWndsLocks);
2963 HeapFree( GetProcessHeap(), 0, list );
2964 return ret;
2968 /**********************************************************************
2969 * EnumThreadWindows (USER32.@)
2971 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2973 HWND *list;
2974 int i, iWndsLocks;
2976 if (!(list = list_window_children( GetDesktopWindow(), 0, id ))) return TRUE;
2978 /* Now call the callback function for every window */
2980 iWndsLocks = WIN_SuspendWndsLock();
2981 for (i = 0; list[i]; i++)
2982 if (!func( list[i], lParam )) break;
2983 WIN_RestoreWndsLock(iWndsLocks);
2984 HeapFree( GetProcessHeap(), 0, list );
2985 return TRUE;
2989 /**********************************************************************
2990 * WIN_EnumChildWindows
2992 * Helper function for EnumChildWindows().
2994 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2996 HWND *childList;
2997 BOOL ret = FALSE;
2999 for ( ; *list; list++)
3001 /* Make sure that the window still exists */
3002 if (!IsWindow( *list )) continue;
3003 /* skip owned windows */
3004 if (GetWindow( *list, GW_OWNER )) continue;
3005 /* Build children list first */
3006 childList = WIN_ListChildren( *list );
3008 ret = func( *list, lParam );
3010 if (childList)
3012 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
3013 HeapFree( GetProcessHeap(), 0, childList );
3015 if (!ret) return FALSE;
3017 return TRUE;
3021 /**********************************************************************
3022 * EnumChildWindows (USER32.@)
3024 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
3026 HWND *list;
3027 int iWndsLocks;
3029 if (!(list = WIN_ListChildren( parent ))) return FALSE;
3030 iWndsLocks = WIN_SuspendWndsLock();
3031 WIN_EnumChildWindows( list, func, lParam );
3032 WIN_RestoreWndsLock(iWndsLocks);
3033 HeapFree( GetProcessHeap(), 0, list );
3034 return TRUE;
3038 /*******************************************************************
3039 * AnyPopup (USER.52)
3041 BOOL16 WINAPI AnyPopup16(void)
3043 return AnyPopup();
3047 /*******************************************************************
3048 * AnyPopup (USER32.@)
3050 BOOL WINAPI AnyPopup(void)
3052 int i;
3053 BOOL retvalue;
3054 HWND *list = WIN_ListChildren( GetDesktopWindow() );
3056 if (!list) return FALSE;
3057 for (i = 0; list[i]; i++)
3059 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
3061 retvalue = (list[i] != 0);
3062 HeapFree( GetProcessHeap(), 0, list );
3063 return retvalue;
3067 /*******************************************************************
3068 * FlashWindow (USER32.@)
3070 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3072 WND *wndPtr = WIN_FindWndPtr(hWnd);
3074 TRACE("%p\n", hWnd);
3076 if (!wndPtr) return FALSE;
3077 hWnd = wndPtr->hwndSelf; /* make it a full handle */
3079 if (wndPtr->dwStyle & WS_MINIMIZE)
3081 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3083 HDC hDC = GetDC(hWnd);
3085 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM)hDC, 0 ))
3086 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
3088 ReleaseDC( hWnd, hDC );
3089 wndPtr->flags |= WIN_NCACTIVATED;
3091 else
3093 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3094 wndPtr->flags &= ~WIN_NCACTIVATED;
3096 WIN_ReleaseWndPtr(wndPtr);
3097 return TRUE;
3099 else
3101 WPARAM16 wparam;
3102 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3103 else wparam = (hWnd == GetForegroundWindow());
3105 WIN_ReleaseWndPtr(wndPtr);
3106 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3107 return wparam;
3111 /*******************************************************************
3112 * FlashWindowEx (USER32.@)
3114 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
3116 FIXME("%p\n", pfwi);
3117 return TRUE;
3120 /*******************************************************************
3121 * GetWindowContextHelpId (USER32.@)
3123 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3125 DWORD retval;
3126 WND *wnd = WIN_FindWndPtr( hwnd );
3127 if (!wnd) return 0;
3128 retval = wnd->helpContext;
3129 WIN_ReleaseWndPtr(wnd);
3130 return retval;
3134 /*******************************************************************
3135 * SetWindowContextHelpId (USER32.@)
3137 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3139 WND *wnd = WIN_FindWndPtr( hwnd );
3140 if (!wnd) return FALSE;
3141 wnd->helpContext = id;
3142 WIN_ReleaseWndPtr(wnd);
3143 return TRUE;
3147 /*******************************************************************
3148 * DragDetect (USER32.@)
3150 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3152 MSG msg;
3153 RECT rect;
3155 rect.left = pt.x - wDragWidth;
3156 rect.right = pt.x + wDragWidth;
3158 rect.top = pt.y - wDragHeight;
3159 rect.bottom = pt.y + wDragHeight;
3161 SetCapture(hWnd);
3163 while(1)
3165 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3167 if( msg.message == WM_LBUTTONUP )
3169 ReleaseCapture();
3170 return 0;
3172 if( msg.message == WM_MOUSEMOVE )
3174 POINT tmp;
3175 tmp.x = LOWORD(msg.lParam);
3176 tmp.y = HIWORD(msg.lParam);
3177 if( !PtInRect( &rect, tmp ))
3179 ReleaseCapture();
3180 return 1;
3184 WaitMessage();
3186 return 0;
3189 /******************************************************************************
3190 * GetWindowModuleFileNameA (USER32.@)
3192 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3194 FIXME("GetWindowModuleFileNameA(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3195 hwnd, lpszFileName, cchFileNameMax);
3196 return 0;
3199 /******************************************************************************
3200 * GetWindowModuleFileNameW (USER32.@)
3202 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3204 FIXME("GetWindowModuleFileNameW(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3205 hwnd, lpszFileName, cchFileNameMax);
3206 return 0;
3209 /******************************************************************************
3210 * GetWindowInfo (USER32.@)
3211 * hwnd: in
3212 * pwi: out.
3213 * MS Documentation mentions that pwi->cbSize must be set to SIZEOF(WINDOWINFO)
3214 * this may be because this structure changed over time. If this is the
3215 * the case, then please: FIXME.
3216 * Using the structure described in MSDN for 98/ME/NT(4.0 SP3)/2000/XP.
3218 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3220 if (!pwi) return FALSE;
3221 if (pwi->cbSize != sizeof(WINDOWINFO))
3223 FIXME("windowinfo->cbSize != sizeof(WINDOWINFO). Please report\n");
3224 return FALSE;
3226 if (!IsWindow(hwnd)) return FALSE;
3228 GetWindowRect(hwnd, &pwi->rcWindow);
3229 GetClientRect(hwnd, &pwi->rcClient);
3230 /* translate to screen coordinates */
3231 MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3233 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3234 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3235 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3237 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3238 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3240 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3241 pwi->wCreatorVersion = 0x0400;
3243 return TRUE;