Release 20021031.
[wine/multimedia.git] / windows / win.c
blob649d071c15d10d566303bfad80a940b87158e0bb
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 <stdlib.h>
26 #include <string.h>
27 #include "windef.h"
28 #include "wine/winbase16.h"
29 #include "wine/winuser16.h"
30 #include "wownt32.h"
31 #include "wine/server.h"
32 #include "wine/unicode.h"
33 #include "win.h"
34 #include "user.h"
35 #include "dce.h"
36 #include "controls.h"
37 #include "cursoricon.h"
38 #include "message.h"
39 #include "queue.h"
40 #include "winpos.h"
41 #include "winerror.h"
42 #include "stackframe.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 /* thread safeness */
61 extern SYSLEVEL USER_SysLevel; /* FIXME */
63 /***********************************************************************
64 * WIN_SuspendWndsLock
66 * Suspend the lock on WND structures.
67 * Returns the number of locks suspended
69 int WIN_SuspendWndsLock( void )
71 int isuspendedLocks = _ConfirmSysLevel( &USER_SysLevel );
72 int count = isuspendedLocks;
74 while ( count-- > 0 )
75 _LeaveSysLevel( &USER_SysLevel );
77 return isuspendedLocks;
80 /***********************************************************************
81 * WIN_RestoreWndsLock
83 * Restore the suspended locks on WND structures
85 void WIN_RestoreWndsLock( int ipreviousLocks )
87 while ( ipreviousLocks-- > 0 )
88 _EnterSysLevel( &USER_SysLevel );
91 /***********************************************************************
92 * create_window_handle
94 * Create a window handle with the server.
96 static WND *create_window_handle( HWND parent, HWND owner, ATOM atom, INT size )
98 BOOL res;
99 user_handle_t handle = 0;
100 WORD index;
101 WND *win = HeapAlloc( GetProcessHeap(), 0, size );
103 if (!win) return NULL;
105 USER_Lock();
107 SERVER_START_REQ( create_window )
109 req->parent = parent;
110 req->owner = owner;
111 req->atom = atom;
112 if ((res = !wine_server_call_err( req ))) handle = reply->handle;
114 SERVER_END_REQ;
116 if (!res)
118 USER_Unlock();
119 HeapFree( GetProcessHeap(), 0, win );
120 return NULL;
122 index = LOWORD(handle) - FIRST_USER_HANDLE;
123 assert( index < NB_USER_HANDLES );
124 user_handles[index] = win;
125 win->hwndSelf = handle;
126 win->dwMagic = WND_MAGIC;
127 win->irefCount = 1;
128 return win;
132 /***********************************************************************
133 * free_window_handle
135 * Free a window handle.
137 static WND *free_window_handle( HWND hwnd )
139 WND *ptr;
140 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
142 if (index >= NB_USER_HANDLES) return NULL;
143 USER_Lock();
144 if ((ptr = user_handles[index]))
146 SERVER_START_REQ( destroy_window )
148 req->handle = hwnd;
149 if (!wine_server_call_err( req ))
150 user_handles[index] = NULL;
151 else
152 ptr = NULL;
154 SERVER_END_REQ;
156 USER_Unlock();
157 if (ptr) HeapFree( GetProcessHeap(), 0, ptr );
158 return ptr;
162 /*******************************************************************
163 * list_window_children
165 * Build an array of the children of a given window. The array must be
166 * freed with HeapFree. Returns NULL when no windows are found.
168 static HWND *list_window_children( HWND hwnd, ATOM atom, DWORD tid )
170 HWND *list;
171 int size = 32;
173 for (;;)
175 int count = 0;
177 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
179 SERVER_START_REQ( get_window_children )
181 req->parent = hwnd;
182 req->atom = atom;
183 req->tid = tid;
184 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
185 if (!wine_server_call( req )) count = reply->count;
187 SERVER_END_REQ;
188 if (count && count < size)
190 list[count] = 0;
191 return list;
193 HeapFree( GetProcessHeap(), 0, list );
194 if (!count) break;
195 size = count + 1; /* restart with a large enough buffer */
197 return NULL;
201 /*******************************************************************
202 * send_parent_notify
204 static void send_parent_notify( HWND hwnd, UINT msg )
206 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD)) return;
207 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY) return;
208 SendMessageW( GetParent(hwnd), WM_PARENTNOTIFY,
209 MAKEWPARAM( msg, GetWindowLongW( hwnd, GWL_ID )), (LPARAM)hwnd );
213 /*******************************************************************
214 * get_server_window_text
216 * Retrieve the window text from the server.
218 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
220 size_t len = 0;
222 SERVER_START_REQ( get_window_text )
224 req->handle = hwnd;
225 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
226 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
228 SERVER_END_REQ;
229 text[len / sizeof(WCHAR)] = 0;
233 /***********************************************************************
234 * WIN_GetPtr
236 * Return a pointer to the WND structure if local to the process,
237 * or WND_OTHER_PROCESS if handle may be valid in other process.
238 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
240 WND *WIN_GetPtr( HWND hwnd )
242 WND * ptr;
243 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
245 if (index >= NB_USER_HANDLES) return NULL;
247 USER_Lock();
248 if ((ptr = user_handles[index]))
250 if (ptr->dwMagic == WND_MAGIC && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
251 return ptr;
252 ptr = NULL;
254 else ptr = WND_OTHER_PROCESS;
255 USER_Unlock();
256 return ptr;
260 /***********************************************************************
261 * WIN_IsCurrentProcess
263 * Check whether a given window belongs to the current process (and return the full handle).
265 HWND WIN_IsCurrentProcess( HWND hwnd )
267 WND *ptr;
268 HWND ret;
270 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS) return 0;
271 ret = ptr->hwndSelf;
272 WIN_ReleasePtr( ptr );
273 return ret;
277 /***********************************************************************
278 * WIN_IsCurrentThread
280 * Check whether a given window belongs to the current thread (and return the full handle).
282 HWND WIN_IsCurrentThread( HWND hwnd )
284 WND *ptr;
285 HWND ret = 0;
287 if ((ptr = WIN_GetPtr( hwnd )) && ptr != WND_OTHER_PROCESS)
289 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
290 WIN_ReleasePtr( ptr );
292 return ret;
296 /***********************************************************************
297 * WIN_Handle32
299 * Convert a 16-bit window handle to a full 32-bit handle.
301 HWND WIN_Handle32( HWND16 hwnd16 )
303 WND *ptr;
304 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
306 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
307 /* do sign extension for -2 and -3 */
308 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
310 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
312 if (ptr != WND_OTHER_PROCESS)
314 hwnd = ptr->hwndSelf;
315 WIN_ReleasePtr( ptr );
317 else /* may belong to another process */
319 SERVER_START_REQ( get_window_info )
321 req->handle = hwnd;
322 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
324 SERVER_END_REQ;
326 return hwnd;
330 /***********************************************************************
331 * WIN_FindWndPtr
333 * Return a pointer to the WND structure corresponding to a HWND.
335 WND * WIN_FindWndPtr( HWND hwnd )
337 WND * ptr;
339 if (!hwnd) return NULL;
341 if ((ptr = WIN_GetPtr( hwnd )))
343 if (ptr != WND_OTHER_PROCESS)
345 /* increment destruction monitoring */
346 ptr->irefCount++;
347 return ptr;
349 if (IsWindow( hwnd )) /* check other processes */
351 ERR( "window %04x belongs to other process\n", hwnd );
352 /* DbgBreakPoint(); */
355 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
356 return NULL;
360 /***********************************************************************
361 * WIN_ReleaseWndPtr
363 * Release the pointer to the WND structure.
365 void WIN_ReleaseWndPtr(WND *wndPtr)
367 if(!wndPtr) return;
369 /* Decrement destruction monitoring value */
370 wndPtr->irefCount--;
371 /* Check if it's time to release the memory */
372 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
374 /* Release memory */
375 free_window_handle( wndPtr->hwndSelf );
377 else if(wndPtr->irefCount < 0)
379 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
380 ERR("forgot a Lock on %p somewhere\n",wndPtr);
382 /* unlock all WND structures for thread safeness */
383 USER_Unlock();
387 /***********************************************************************
388 * WIN_UnlinkWindow
390 * Remove a window from the siblings linked list.
392 void WIN_UnlinkWindow( HWND hwnd )
394 WIN_LinkWindow( hwnd, 0, 0 );
398 /***********************************************************************
399 * WIN_LinkWindow
401 * Insert a window into the siblings linked list.
402 * The window is inserted after the specified window, which can also
403 * be specified as HWND_TOP or HWND_BOTTOM.
404 * If parent is 0, window is unlinked from the tree.
406 void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
408 WND *wndPtr = WIN_GetPtr( hwnd );
410 if (!wndPtr) return;
411 if (wndPtr == WND_OTHER_PROCESS)
413 if (IsWindow(hwnd)) ERR(" cannot link other process window %x\n", hwnd );
414 return;
417 SERVER_START_REQ( link_window )
419 req->handle = hwnd;
420 req->parent = parent;
421 req->previous = hwndInsertAfter;
422 if (!wine_server_call( req ))
424 if (reply->full_parent) wndPtr->parent = reply->full_parent;
428 SERVER_END_REQ;
429 WIN_ReleasePtr( wndPtr );
433 /***********************************************************************
434 * WIN_SetOwner
436 * Change the owner of a window.
438 HWND WIN_SetOwner( HWND hwnd, HWND owner )
440 WND *win = WIN_GetPtr( hwnd );
441 HWND ret = 0;
443 if (!win) return 0;
444 if (win == WND_OTHER_PROCESS)
446 if (IsWindow(hwnd)) ERR( "cannot set owner %x on other process window %x\n", owner, hwnd );
447 return 0;
449 SERVER_START_REQ( set_window_owner )
451 req->handle = hwnd;
452 req->owner = owner;
453 if (!wine_server_call( req ))
455 win->owner = reply->full_owner;
456 ret = reply->prev_owner;
459 SERVER_END_REQ;
460 WIN_ReleasePtr( win );
461 return ret;
465 /***********************************************************************
466 * WIN_SetStyle
468 * Change the style of a window.
470 LONG WIN_SetStyle( HWND hwnd, LONG style )
472 BOOL ok;
473 LONG ret = 0;
474 WND *win = WIN_GetPtr( hwnd );
476 if (!win) return 0;
477 if (win == WND_OTHER_PROCESS)
479 if (IsWindow(hwnd))
480 ERR( "cannot set style %lx on other process window %x\n", style, hwnd );
481 return 0;
483 if (style == win->dwStyle)
485 WIN_ReleasePtr( win );
486 return style;
488 SERVER_START_REQ( set_window_info )
490 req->handle = hwnd;
491 req->flags = SET_WIN_STYLE;
492 req->style = style;
493 if ((ok = !wine_server_call( req )))
495 ret = reply->old_style;
496 win->dwStyle = style;
499 SERVER_END_REQ;
500 WIN_ReleasePtr( win );
501 if (ok && USER_Driver.pSetWindowStyle) USER_Driver.pSetWindowStyle( hwnd, ret );
502 return ret;
506 /***********************************************************************
507 * WIN_SetExStyle
509 * Change the extended style of a window.
511 LONG WIN_SetExStyle( HWND hwnd, LONG style )
513 LONG ret = 0;
514 WND *win = WIN_GetPtr( hwnd );
516 if (!win) return 0;
517 if (win == WND_OTHER_PROCESS)
519 if (IsWindow(hwnd))
520 ERR( "cannot set exstyle %lx on other process window %x\n", style, hwnd );
521 return 0;
523 if (style == win->dwExStyle)
525 WIN_ReleasePtr( win );
526 return style;
528 SERVER_START_REQ( set_window_info )
530 req->handle = hwnd;
531 req->flags = SET_WIN_EXSTYLE;
532 req->ex_style = style;
533 if (!wine_server_call( req ))
535 ret = reply->old_ex_style;
536 win->dwExStyle = style;
539 SERVER_END_REQ;
540 WIN_ReleasePtr( win );
541 return ret;
545 /***********************************************************************
546 * WIN_SetRectangles
548 * Set the window and client rectangles.
550 void WIN_SetRectangles( HWND hwnd, const RECT *rectWindow, const RECT *rectClient )
552 WND *win = WIN_GetPtr( hwnd );
553 BOOL ret;
555 if (!win) return;
556 if (win == WND_OTHER_PROCESS)
558 if (IsWindow( hwnd )) ERR( "cannot set rectangles of other process window %x\n", hwnd );
559 return;
561 SERVER_START_REQ( set_window_rectangles )
563 req->handle = hwnd;
564 req->window.left = rectWindow->left;
565 req->window.top = rectWindow->top;
566 req->window.right = rectWindow->right;
567 req->window.bottom = rectWindow->bottom;
568 req->client.left = rectClient->left;
569 req->client.top = rectClient->top;
570 req->client.right = rectClient->right;
571 req->client.bottom = rectClient->bottom;
572 ret = !wine_server_call( req );
574 SERVER_END_REQ;
575 if (ret)
577 win->rectWindow = *rectWindow;
578 win->rectClient = *rectClient;
580 TRACE( "win %x window (%d,%d)-(%d,%d) client (%d,%d)-(%d,%d)\n", hwnd,
581 rectWindow->left, rectWindow->top, rectWindow->right, rectWindow->bottom,
582 rectClient->left, rectClient->top, rectClient->right, rectClient->bottom );
584 WIN_ReleasePtr( win );
588 /***********************************************************************
589 * WIN_GetRectangles
591 * Get the window and client rectangles.
593 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
595 WND *win = WIN_GetPtr( hwnd );
596 BOOL ret = TRUE;
598 if (!win) return FALSE;
599 if (win == WND_OTHER_PROCESS)
601 SERVER_START_REQ( get_window_rectangles )
603 req->handle = hwnd;
604 if ((ret = !wine_server_call( req )))
606 if (rectWindow)
608 rectWindow->left = reply->window.left;
609 rectWindow->top = reply->window.top;
610 rectWindow->right = reply->window.right;
611 rectWindow->bottom = reply->window.bottom;
613 if (rectClient)
615 rectClient->left = reply->client.left;
616 rectClient->top = reply->client.top;
617 rectClient->right = reply->client.right;
618 rectClient->bottom = reply->client.bottom;
622 SERVER_END_REQ;
624 else
626 if (rectWindow) *rectWindow = win->rectWindow;
627 if (rectClient) *rectClient = win->rectClient;
628 WIN_ReleasePtr( win );
630 return ret;
634 /***********************************************************************
635 * WIN_DestroyWindow
637 * Destroy storage associated to a window. "Internals" p.358
639 LRESULT WIN_DestroyWindow( HWND hwnd )
641 WND *wndPtr;
642 HWND *list;
644 TRACE("%04x\n", hwnd );
646 if (!(hwnd = WIN_IsCurrentThread( hwnd )))
648 ERR( "window doesn't belong to current thread\n" );
649 return 0;
652 /* free child windows */
653 if ((list = WIN_ListChildren( hwnd )))
655 int i;
656 for (i = 0; list[i]; i++)
658 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
659 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
661 HeapFree( GetProcessHeap(), 0, list );
665 * Clear the update region to make sure no WM_PAINT messages will be
666 * generated for this window while processing the WM_NCDESTROY.
668 RedrawWindow( hwnd, NULL, 0,
669 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
672 * Send the WM_NCDESTROY to the window being destroyed.
674 SendMessageA( hwnd, WM_NCDESTROY, 0, 0);
676 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
678 WINPOS_CheckInternalPos( hwnd );
679 if( hwnd == GetCapture()) ReleaseCapture();
681 /* free resources associated with the window */
683 TIMER_RemoveWindowTimers( hwnd );
685 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
687 if (!(wndPtr->dwStyle & WS_CHILD))
689 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
690 if (menu) DestroyMenu( menu );
692 if (wndPtr->hSysMenu)
694 DestroyMenu( wndPtr->hSysMenu );
695 wndPtr->hSysMenu = 0;
697 USER_Driver.pDestroyWindow( hwnd );
698 DCE_FreeWindowDCE( hwnd ); /* Always do this to catch orphaned DCs */
699 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
700 CLASS_RemoveWindow( wndPtr->class );
701 wndPtr->class = NULL;
702 wndPtr->dwMagic = 0; /* Mark it as invalid */
703 WIN_ReleaseWndPtr( wndPtr );
704 return 0;
707 /***********************************************************************
708 * WIN_DestroyThreadWindows
710 * Destroy all children of 'wnd' owned by the current thread.
711 * Return TRUE if something was done.
713 void WIN_DestroyThreadWindows( HWND hwnd )
715 HWND *list;
716 int i;
718 if (!(list = WIN_ListChildren( hwnd ))) return;
719 for (i = 0; list[i]; i++)
721 if (WIN_IsCurrentThread( list[i] ))
722 DestroyWindow( list[i] );
723 else
724 WIN_DestroyThreadWindows( list[i] );
726 HeapFree( GetProcessHeap(), 0, list );
729 /***********************************************************************
730 * WIN_CreateDesktopWindow
732 * Create the desktop window.
734 BOOL WIN_CreateDesktopWindow(void)
736 struct tagCLASS *class;
737 HWND hwndDesktop;
738 INT wndExtra;
739 DWORD clsStyle;
740 WNDPROC winproc;
741 DCE *dce;
742 CREATESTRUCTA cs;
743 RECT rect;
745 TRACE("Creating desktop window\n");
747 if (!WINPOS_CreateInternalPosAtom() ||
748 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
749 &wndExtra, &winproc, &clsStyle, &dce )))
750 return FALSE;
752 pWndDesktop = create_window_handle( 0, 0, LOWORD(DESKTOP_CLASS_ATOM),
753 sizeof(WND) + wndExtra - sizeof(pWndDesktop->wExtra) );
754 if (!pWndDesktop) return FALSE;
755 hwndDesktop = pWndDesktop->hwndSelf;
757 pWndDesktop->tid = 0; /* nobody owns the desktop */
758 pWndDesktop->parent = 0;
759 pWndDesktop->owner = 0;
760 pWndDesktop->class = class;
761 pWndDesktop->text = NULL;
762 pWndDesktop->hrgnUpdate = 0;
763 pWndDesktop->clsStyle = clsStyle;
764 pWndDesktop->dce = NULL;
765 pWndDesktop->pVScroll = NULL;
766 pWndDesktop->pHScroll = NULL;
767 pWndDesktop->helpContext = 0;
768 pWndDesktop->flags = 0;
769 pWndDesktop->hSysMenu = 0;
770 pWndDesktop->winproc = winproc;
771 pWndDesktop->cbWndExtra = wndExtra;
773 cs.lpCreateParams = NULL;
774 cs.hInstance = 0;
775 cs.hMenu = 0;
776 cs.hwndParent = 0;
777 cs.x = 0;
778 cs.y = 0;
779 cs.cx = GetSystemMetrics( SM_CXSCREEN );
780 cs.cy = GetSystemMetrics( SM_CYSCREEN );
781 cs.style = pWndDesktop->dwStyle;
782 cs.dwExStyle = pWndDesktop->dwExStyle;
783 cs.lpszName = NULL;
784 cs.lpszClass = DESKTOP_CLASS_ATOM;
786 SetRect( &rect, 0, 0, cs.cx, cs.cy );
787 WIN_SetRectangles( hwndDesktop, &rect, &rect );
789 SERVER_START_REQ( set_window_info )
791 req->handle = hwndDesktop;
792 req->flags = 0; /* don't set anything, just retrieve */
793 wine_server_call( req );
794 pWndDesktop->dwStyle = reply->old_style;
795 pWndDesktop->dwExStyle = reply->old_ex_style;
796 pWndDesktop->hInstance = (ULONG_PTR)reply->old_instance;
797 pWndDesktop->userdata = (ULONG_PTR)reply->old_user_data;
798 pWndDesktop->wIDmenu = reply->old_id;
800 SERVER_END_REQ;
802 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE ))
804 WIN_ReleaseWndPtr( pWndDesktop );
805 return FALSE;
808 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
809 WIN_ReleaseWndPtr( pWndDesktop );
810 return TRUE;
814 /***********************************************************************
815 * WIN_FixCoordinates
817 * Fix the coordinates - Helper for WIN_CreateWindowEx.
818 * returns default show mode in sw.
819 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
821 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
823 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
824 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
826 if (cs->style & (WS_CHILD | WS_POPUP))
828 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
829 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
831 else /* overlapped window */
833 STARTUPINFOA info;
835 GetStartupInfoA( &info );
837 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
839 /* Never believe Microsoft's documentation... CreateWindowEx doc says
840 * that if an overlapped window is created with WS_VISIBLE style bit
841 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
842 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
843 * reveals that
845 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
846 * 2) it does not ignore the y parameter as the docs claim; instead, it
847 * uses it as second parameter to ShowWindow() unless y is either
848 * CW_USEDEFAULT or CW_USEDEFAULT16.
850 * The fact that we didn't do 2) caused bogus windows pop up when wine
851 * was running apps that were using this obscure feature. Example -
852 * calc.exe that comes with Win98 (only Win98, it's different from
853 * the one that comes with Win95 and NT)
855 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
856 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
857 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
860 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
862 if (info.dwFlags & STARTF_USESIZE)
864 cs->cx = info.dwXSize;
865 cs->cy = info.dwYSize;
867 else /* if no other hint from the app, pick 3/4 of the screen real estate */
869 RECT r;
870 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
871 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
872 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
877 else
879 /* neither x nor cx are default. Check the y values .
880 * In the trace we see Outlook and Outlook Express using
881 * cy set to CW_USEDEFAULT when opening the address book.
883 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16) {
884 RECT r;
885 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
886 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
887 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
892 /***********************************************************************
893 * dump_window_styles
895 static void dump_window_styles( DWORD style, DWORD exstyle )
897 TRACE( "style:" );
898 if(style & WS_POPUP) DPRINTF(" WS_POPUP");
899 if(style & WS_CHILD) DPRINTF(" WS_CHILD");
900 if(style & WS_MINIMIZE) DPRINTF(" WS_MINIMIZE");
901 if(style & WS_VISIBLE) DPRINTF(" WS_VISIBLE");
902 if(style & WS_DISABLED) DPRINTF(" WS_DISABLED");
903 if(style & WS_CLIPSIBLINGS) DPRINTF(" WS_CLIPSIBLINGS");
904 if(style & WS_CLIPCHILDREN) DPRINTF(" WS_CLIPCHILDREN");
905 if(style & WS_MAXIMIZE) DPRINTF(" WS_MAXIMIZE");
906 if((style & WS_CAPTION) == WS_CAPTION) DPRINTF(" WS_CAPTION");
907 else
909 if(style & WS_BORDER) DPRINTF(" WS_BORDER");
910 if(style & WS_DLGFRAME) DPRINTF(" WS_DLGFRAME");
912 if(style & WS_VSCROLL) DPRINTF(" WS_VSCROLL");
913 if(style & WS_HSCROLL) DPRINTF(" WS_HSCROLL");
914 if(style & WS_SYSMENU) DPRINTF(" WS_SYSMENU");
915 if(style & WS_THICKFRAME) DPRINTF(" WS_THICKFRAME");
916 if(style & WS_GROUP) DPRINTF(" WS_GROUP");
917 if(style & WS_TABSTOP) DPRINTF(" WS_TABSTOP");
918 if(style & WS_MINIMIZEBOX) DPRINTF(" WS_MINIMIZEBOX");
919 if(style & WS_MAXIMIZEBOX) DPRINTF(" WS_MAXIMIZEBOX");
921 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
922 #define DUMPED_STYLES \
923 (WS_POPUP | \
924 WS_CHILD | \
925 WS_MINIMIZE | \
926 WS_VISIBLE | \
927 WS_DISABLED | \
928 WS_CLIPSIBLINGS | \
929 WS_CLIPCHILDREN | \
930 WS_MAXIMIZE | \
931 WS_BORDER | \
932 WS_DLGFRAME | \
933 WS_VSCROLL | \
934 WS_HSCROLL | \
935 WS_SYSMENU | \
936 WS_THICKFRAME | \
937 WS_GROUP | \
938 WS_TABSTOP | \
939 WS_MINIMIZEBOX | \
940 WS_MAXIMIZEBOX)
942 if(style & ~DUMPED_STYLES) DPRINTF(" %08lx", style & ~DUMPED_STYLES);
943 DPRINTF("\n");
944 #undef DUMPED_STYLES
946 TRACE( "exstyle:" );
947 if(exstyle & WS_EX_DLGMODALFRAME) DPRINTF(" WS_EX_DLGMODALFRAME");
948 if(exstyle & WS_EX_DRAGDETECT) DPRINTF(" WS_EX_DRAGDETECT");
949 if(exstyle & WS_EX_NOPARENTNOTIFY) DPRINTF(" WS_EX_NOPARENTNOTIFY");
950 if(exstyle & WS_EX_TOPMOST) DPRINTF(" WS_EX_TOPMOST");
951 if(exstyle & WS_EX_ACCEPTFILES) DPRINTF(" WS_EX_ACCEPTFILES");
952 if(exstyle & WS_EX_TRANSPARENT) DPRINTF(" WS_EX_TRANSPARENT");
953 if(exstyle & WS_EX_MDICHILD) DPRINTF(" WS_EX_MDICHILD");
954 if(exstyle & WS_EX_TOOLWINDOW) DPRINTF(" WS_EX_TOOLWINDOW");
955 if(exstyle & WS_EX_WINDOWEDGE) DPRINTF(" WS_EX_WINDOWEDGE");
956 if(exstyle & WS_EX_CLIENTEDGE) DPRINTF(" WS_EX_CLIENTEDGE");
957 if(exstyle & WS_EX_CONTEXTHELP) DPRINTF(" WS_EX_CONTEXTHELP");
958 if(exstyle & WS_EX_RIGHT) DPRINTF(" WS_EX_RIGHT");
959 if(exstyle & WS_EX_RTLREADING) DPRINTF(" WS_EX_RTLREADING");
960 if(exstyle & WS_EX_LEFTSCROLLBAR) DPRINTF(" WS_EX_LEFTSCROLLBAR");
961 if(exstyle & WS_EX_CONTROLPARENT) DPRINTF(" WS_EX_CONTROLPARENT");
962 if(exstyle & WS_EX_STATICEDGE) DPRINTF(" WS_EX_STATICEDGE");
963 if(exstyle & WS_EX_APPWINDOW) DPRINTF(" WS_EX_APPWINDOW");
964 if(exstyle & WS_EX_LAYERED) DPRINTF(" WS_EX_LAYERED");
966 #define DUMPED_EX_STYLES \
967 (WS_EX_DLGMODALFRAME | \
968 WS_EX_DRAGDETECT | \
969 WS_EX_NOPARENTNOTIFY | \
970 WS_EX_TOPMOST | \
971 WS_EX_ACCEPTFILES | \
972 WS_EX_TRANSPARENT | \
973 WS_EX_MDICHILD | \
974 WS_EX_TOOLWINDOW | \
975 WS_EX_WINDOWEDGE | \
976 WS_EX_CLIENTEDGE | \
977 WS_EX_CONTEXTHELP | \
978 WS_EX_RIGHT | \
979 WS_EX_RTLREADING | \
980 WS_EX_LEFTSCROLLBAR | \
981 WS_EX_CONTROLPARENT | \
982 WS_EX_STATICEDGE | \
983 WS_EX_APPWINDOW | \
984 WS_EX_LAYERED)
986 if(exstyle & ~DUMPED_EX_STYLES) DPRINTF(" %08lx", exstyle & ~DUMPED_EX_STYLES);
987 DPRINTF("\n");
988 #undef DUMPED_EX_STYLES
992 /***********************************************************************
993 * WIN_CreateWindowEx
995 * Implementation of CreateWindowEx().
997 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
998 WINDOWPROCTYPE type )
1000 INT sw = SW_SHOW;
1001 struct tagCLASS *classPtr;
1002 WND *wndPtr;
1003 HWND hwnd, parent, owner;
1004 INT wndExtra;
1005 DWORD clsStyle;
1006 WNDPROC winproc;
1007 DCE *dce;
1008 BOOL unicode = (type == WIN_PROC_32W);
1010 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%04x menu=%04x inst=%08x params=%p\n",
1011 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
1012 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszClass) : debugstr_a(cs->lpszClass),
1013 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
1014 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
1016 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
1018 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
1019 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
1021 /* Find the parent window */
1023 parent = GetDesktopWindow();
1024 owner = 0;
1026 if (cs->hwndParent == HWND_MESSAGE)
1028 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
1029 * message window (style: WS_POPUP|WS_DISABLED)
1031 FIXME("Parent is HWND_MESSAGE\n");
1033 else if (cs->hwndParent)
1035 /* Make sure parent is valid */
1036 if (!IsWindow( cs->hwndParent ))
1038 WARN("Bad parent %04x\n", cs->hwndParent );
1039 return 0;
1041 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1042 parent = WIN_GetFullHandle(cs->hwndParent);
1043 else
1044 owner = GetAncestor( cs->hwndParent, GA_ROOT );
1046 else if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1048 WARN("No parent for child window\n" );
1049 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1052 /* Find the window class */
1053 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
1054 &wndExtra, &winproc, &clsStyle, &dce )))
1056 WARN("Bad class '%s'\n", cs->lpszClass );
1057 return 0;
1060 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
1062 /* Correct the window style - stage 1
1064 * These are patches that appear to affect both the style loaded into the
1065 * WIN structure and passed in the CreateStruct to the WM_CREATE etc.
1067 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1068 * why does the user get to set it?
1071 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
1072 * tested for WS_POPUP
1074 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
1075 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
1076 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
1077 cs->dwExStyle |= WS_EX_WINDOWEDGE;
1078 else
1079 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
1081 /* Create the window structure */
1083 if (!(wndPtr = create_window_handle( parent, owner, classAtom,
1084 sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
1086 TRACE("out of memory\n" );
1087 return 0;
1089 hwnd = wndPtr->hwndSelf;
1091 /* Fill the window structure */
1093 wndPtr->tid = GetCurrentThreadId();
1094 wndPtr->owner = owner;
1095 wndPtr->parent = parent;
1096 wndPtr->class = classPtr;
1097 wndPtr->winproc = winproc;
1098 wndPtr->hInstance = cs->hInstance;
1099 wndPtr->text = NULL;
1100 wndPtr->hrgnUpdate = 0;
1101 wndPtr->hrgnWnd = 0;
1102 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1103 wndPtr->dwExStyle = cs->dwExStyle;
1104 wndPtr->clsStyle = clsStyle;
1105 wndPtr->wIDmenu = 0;
1106 wndPtr->helpContext = 0;
1107 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
1108 wndPtr->pVScroll = NULL;
1109 wndPtr->pHScroll = NULL;
1110 wndPtr->userdata = 0;
1111 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU) ? MENU_GetSysMenu( hwnd, 0 ) : 0;
1112 wndPtr->cbWndExtra = wndExtra;
1114 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
1116 /* Correct the window style - stage 2 */
1118 if (!(cs->style & WS_CHILD))
1120 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1121 if (!(cs->style & WS_POPUP))
1123 wndPtr->dwStyle |= WS_CAPTION;
1124 wndPtr->flags |= WIN_NEED_SIZE;
1127 SERVER_START_REQ( set_window_info )
1129 req->handle = hwnd;
1130 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE;
1131 req->style = wndPtr->dwStyle;
1132 req->ex_style = wndPtr->dwExStyle;
1133 req->instance = (void *)wndPtr->hInstance;
1134 wine_server_call( req );
1136 SERVER_END_REQ;
1138 /* Get class or window DC if needed */
1140 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
1141 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
1142 else wndPtr->dce = NULL;
1144 /* Set the window menu */
1146 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
1148 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
1149 else
1151 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
1152 if (menuName)
1154 if (HIWORD(cs->hInstance))
1155 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1156 else
1157 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
1159 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
1163 else SetWindowLongW( hwnd, GWL_ID, (UINT)cs->hMenu );
1164 WIN_ReleaseWndPtr( wndPtr );
1166 if (!USER_Driver.pCreateWindow( hwnd, cs, unicode))
1168 WIN_DestroyWindow( hwnd );
1169 return 0;
1172 /* Notify the parent window only */
1174 send_parent_notify( hwnd, WM_CREATE );
1175 if (!IsWindow( hwnd )) return 0;
1177 if (cs->style & WS_VISIBLE)
1179 /* in case WS_VISIBLE got set in the meantime */
1180 if (!(wndPtr = WIN_GetPtr( hwnd ))) return 0;
1181 WIN_SetStyle( hwnd, wndPtr->dwStyle & ~WS_VISIBLE );
1182 WIN_ReleasePtr( wndPtr );
1183 ShowWindow( hwnd, sw );
1186 /* Call WH_SHELL hook */
1188 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1189 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1191 TRACE("created window %04x\n", hwnd);
1192 return hwnd;
1196 /***********************************************************************
1197 * CreateWindow (USER.41)
1199 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1200 DWORD style, INT16 x, INT16 y, INT16 width,
1201 INT16 height, HWND16 parent, HMENU16 menu,
1202 HINSTANCE16 instance, LPVOID data )
1204 return CreateWindowEx16( 0, className, windowName, style,
1205 x, y, width, height, parent, menu, instance, data );
1209 /***********************************************************************
1210 * CreateWindowEx (USER.452)
1212 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1213 LPCSTR windowName, DWORD style, INT16 x,
1214 INT16 y, INT16 width, INT16 height,
1215 HWND16 parent, HMENU16 menu,
1216 HINSTANCE16 instance, LPVOID data )
1218 ATOM classAtom;
1219 CREATESTRUCTA cs;
1220 char buffer[256];
1222 /* Find the class atom */
1224 if (HIWORD(className))
1226 if (!(classAtom = GlobalFindAtomA( className )))
1228 ERR( "bad class name %s\n", debugstr_a(className) );
1229 return 0;
1232 else
1234 classAtom = LOWORD(className);
1235 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1237 ERR( "bad atom %x\n", classAtom);
1238 return 0;
1240 className = buffer;
1243 /* Fix the coordinates */
1245 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1246 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1247 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1248 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1250 /* Create the window */
1252 cs.lpCreateParams = data;
1253 cs.hInstance = (HINSTANCE)instance;
1254 cs.hMenu = HMENU_32(menu);
1255 cs.hwndParent = WIN_Handle32( parent );
1256 cs.style = style;
1257 cs.lpszName = windowName;
1258 cs.lpszClass = className;
1259 cs.dwExStyle = exStyle;
1261 return HWND_16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
1265 /***********************************************************************
1266 * CreateWindowExA (USER32.@)
1268 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1269 LPCSTR windowName, DWORD style, INT x,
1270 INT y, INT width, INT height,
1271 HWND parent, HMENU menu,
1272 HINSTANCE instance, LPVOID data )
1274 ATOM classAtom;
1275 CREATESTRUCTA cs;
1276 char buffer[256];
1278 if(!instance)
1279 instance=GetModuleHandleA(NULL);
1281 if(exStyle & WS_EX_MDICHILD)
1282 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1284 /* Find the class atom */
1286 if (HIWORD(className))
1288 if (!(classAtom = GlobalFindAtomA( className )))
1290 ERR( "bad class name %s\n", debugstr_a(className) );
1291 return 0;
1294 else
1296 classAtom = LOWORD(className);
1297 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1299 ERR( "bad atom %x\n", classAtom);
1300 return 0;
1302 className = buffer;
1305 /* Create the window */
1307 cs.lpCreateParams = data;
1308 cs.hInstance = instance;
1309 cs.hMenu = menu;
1310 cs.hwndParent = parent;
1311 cs.x = x;
1312 cs.y = y;
1313 cs.cx = width;
1314 cs.cy = height;
1315 cs.style = style;
1316 cs.lpszName = windowName;
1317 cs.lpszClass = className;
1318 cs.dwExStyle = exStyle;
1320 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1324 /***********************************************************************
1325 * CreateWindowExW (USER32.@)
1327 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1328 LPCWSTR windowName, DWORD style, INT x,
1329 INT y, INT width, INT height,
1330 HWND parent, HMENU menu,
1331 HINSTANCE instance, LPVOID data )
1333 ATOM classAtom;
1334 CREATESTRUCTW cs;
1335 WCHAR buffer[256];
1337 if(!instance)
1338 instance=GetModuleHandleA(NULL);
1340 if(exStyle & WS_EX_MDICHILD)
1341 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1343 /* Find the class atom */
1345 if (HIWORD(className))
1347 if (!(classAtom = GlobalFindAtomW( className )))
1349 ERR( "bad class name %s\n", debugstr_w(className) );
1350 return 0;
1353 else
1355 classAtom = LOWORD(className);
1356 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1358 ERR( "bad atom %x\n", classAtom);
1359 return 0;
1361 className = buffer;
1364 /* Create the window */
1366 cs.lpCreateParams = data;
1367 cs.hInstance = instance;
1368 cs.hMenu = menu;
1369 cs.hwndParent = parent;
1370 cs.x = x;
1371 cs.y = y;
1372 cs.cx = width;
1373 cs.cy = height;
1374 cs.style = style;
1375 cs.lpszName = windowName;
1376 cs.lpszClass = className;
1377 cs.dwExStyle = exStyle;
1379 /* Note: we rely on the fact that CREATESTRUCTA and */
1380 /* CREATESTRUCTW have the same layout. */
1381 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1385 /***********************************************************************
1386 * WIN_SendDestroyMsg
1388 static void WIN_SendDestroyMsg( HWND hwnd )
1390 GUITHREADINFO info;
1392 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1394 if (hwnd == info.hwndCaret) DestroyCaret();
1396 if (USER_Driver.pResetSelectionOwner)
1397 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1400 * Send the WM_DESTROY to the window.
1402 SendMessageA( hwnd, WM_DESTROY, 0, 0);
1405 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1406 * make sure that the window still exists when we come back.
1408 if (IsWindow(hwnd))
1410 HWND* pWndArray;
1411 int i;
1413 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1415 /* start from the end (FIXME: is this needed?) */
1416 for (i = 0; pWndArray[i]; i++) ;
1418 while (--i >= 0)
1420 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1422 HeapFree( GetProcessHeap(), 0, pWndArray );
1424 else
1425 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1429 /***********************************************************************
1430 * DestroyWindow (USER32.@)
1432 BOOL WINAPI DestroyWindow( HWND hwnd )
1434 BOOL is_child;
1435 HWND h;
1437 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1439 SetLastError( ERROR_ACCESS_DENIED );
1440 return FALSE;
1443 TRACE("(%04x)\n", hwnd);
1445 /* Look whether the focus is within the tree of windows we will
1446 * be destroying.
1448 h = GetFocus();
1449 if (h == hwnd || IsChild( hwnd, h ))
1451 HWND parent = GetAncestor( hwnd, GA_PARENT );
1452 if (parent == GetDesktopWindow()) parent = 0;
1453 SetFocus( parent );
1456 /* Call hooks */
1458 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1460 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1462 if (is_child)
1464 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1465 send_parent_notify( hwnd, WM_DESTROY );
1467 else if (!GetWindow( hwnd, GW_OWNER ))
1469 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1470 /* FIXME: clean up palette - see "Internals" p.352 */
1473 if (!IsWindow(hwnd)) return TRUE;
1475 if (USER_Driver.pResetSelectionOwner)
1476 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1478 /* Hide the window */
1480 if (!ShowWindow( hwnd, SW_HIDE ))
1482 if (hwnd == GetActiveWindow()) WINPOS_ActivateOtherWindow( hwnd );
1484 if (!IsWindow(hwnd)) return TRUE;
1486 /* Recursively destroy owned windows */
1488 if (!is_child)
1490 for (;;)
1492 int i, got_one = 0;
1493 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1494 if (list)
1496 for (i = 0; list[i]; i++)
1498 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1499 if (WIN_IsCurrentThread( list[i] ))
1501 DestroyWindow( list[i] );
1502 got_one = 1;
1503 continue;
1505 WIN_SetOwner( list[i], 0 );
1507 HeapFree( GetProcessHeap(), 0, list );
1509 if (!got_one) break;
1513 /* Send destroy messages */
1515 WIN_SendDestroyMsg( hwnd );
1516 if (!IsWindow( hwnd )) return TRUE;
1518 /* Unlink now so we won't bother with the children later on */
1520 WIN_UnlinkWindow( hwnd );
1522 /* Destroy the window storage */
1524 WIN_DestroyWindow( hwnd );
1525 return TRUE;
1529 /***********************************************************************
1530 * CloseWindow (USER32.@)
1532 BOOL WINAPI CloseWindow( HWND hwnd )
1534 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1535 ShowWindow( hwnd, SW_MINIMIZE );
1536 return TRUE;
1540 /***********************************************************************
1541 * OpenIcon (USER32.@)
1543 BOOL WINAPI OpenIcon( HWND hwnd )
1545 if (!IsIconic( hwnd )) return FALSE;
1546 ShowWindow( hwnd, SW_SHOWNORMAL );
1547 return TRUE;
1551 /***********************************************************************
1552 * WIN_FindWindow
1554 * Implementation of FindWindow() and FindWindowEx().
1556 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1558 HWND *list = NULL;
1559 HWND retvalue = 0;
1560 int i = 0, len = 0;
1561 WCHAR *buffer = NULL;
1563 if (!parent) parent = GetDesktopWindow();
1564 if (title)
1566 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1567 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1570 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1572 if (child)
1574 child = WIN_GetFullHandle( child );
1575 while (list[i] && list[i] != child) i++;
1576 if (!list[i]) goto done;
1577 i++; /* start from next window */
1580 if (title)
1582 while (list[i])
1584 if (GetWindowTextW( list[i], buffer, len ) && !strcmpiW( buffer, title )) break;
1585 i++;
1588 retvalue = list[i];
1590 done:
1591 if (list) HeapFree( GetProcessHeap(), 0, list );
1592 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1593 return retvalue;
1598 /***********************************************************************
1599 * FindWindowA (USER32.@)
1601 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1603 HWND ret = FindWindowExA( 0, 0, className, title );
1604 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1605 return ret;
1609 /***********************************************************************
1610 * FindWindowExA (USER32.@)
1612 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1613 LPCSTR className, LPCSTR title )
1615 ATOM atom = 0;
1616 LPWSTR buffer;
1617 HWND hwnd;
1618 INT len;
1620 if (className)
1622 /* If the atom doesn't exist, then no class */
1623 /* with this name exists either. */
1624 if (!(atom = GlobalFindAtomA( className )))
1626 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1627 return 0;
1630 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
1632 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1633 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1634 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
1635 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1636 HeapFree( GetProcessHeap(), 0, buffer );
1637 return hwnd;
1641 /***********************************************************************
1642 * FindWindowExW (USER32.@)
1644 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1645 LPCWSTR className, LPCWSTR title )
1647 ATOM atom = 0;
1649 if (className)
1651 /* If the atom doesn't exist, then no class */
1652 /* with this name exists either. */
1653 if (!(atom = GlobalFindAtomW( className )))
1655 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1656 return 0;
1659 return WIN_FindWindow( parent, child, atom, title );
1663 /***********************************************************************
1664 * FindWindowW (USER32.@)
1666 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1668 return FindWindowExW( 0, 0, className, title );
1672 /**********************************************************************
1673 * GetDesktopWindow (USER32.@)
1675 HWND WINAPI GetDesktopWindow(void)
1677 if (pWndDesktop) return pWndDesktop->hwndSelf;
1678 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" );
1679 ExitProcess(1);
1680 return 0;
1684 /*******************************************************************
1685 * EnableWindow (USER32.@)
1687 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1689 WND *wndPtr;
1690 BOOL retvalue;
1691 LONG style;
1692 HWND full_handle;
1694 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1695 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1697 hwnd = full_handle;
1699 TRACE("( %x, %d )\n", hwnd, enable);
1701 if (!(wndPtr = WIN_GetPtr( hwnd ))) return FALSE;
1702 style = wndPtr->dwStyle;
1703 retvalue = ((style & WS_DISABLED) != 0);
1704 WIN_ReleasePtr( wndPtr );
1706 if (enable && retvalue)
1708 WIN_SetStyle( hwnd, style & ~WS_DISABLED );
1709 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1711 else if (!enable && !retvalue)
1713 SendMessageA( hwnd, WM_CANCELMODE, 0, 0);
1715 WIN_SetStyle( hwnd, style | WS_DISABLED );
1717 if (hwnd == GetFocus() || IsChild(hwnd, GetFocus()))
1718 SetFocus( 0 ); /* A disabled window can't have the focus */
1720 if (hwnd == GetCapture() || IsChild(hwnd, GetCapture()))
1721 ReleaseCapture(); /* A disabled window can't capture the mouse */
1723 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1725 return retvalue;
1729 /***********************************************************************
1730 * IsWindowEnabled (USER32.@)
1732 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1734 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1738 /***********************************************************************
1739 * IsWindowUnicode (USER32.@)
1741 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1743 WND * wndPtr;
1744 BOOL retvalue;
1746 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1747 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1748 WIN_ReleaseWndPtr(wndPtr);
1749 return retvalue;
1753 /**********************************************************************
1754 * GetWindowWord (USER32.@)
1756 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1758 if (offset >= 0)
1760 WORD retvalue = 0;
1761 WND *wndPtr = WIN_GetPtr( hwnd );
1762 if (!wndPtr)
1764 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1765 return 0;
1767 if (wndPtr == WND_OTHER_PROCESS)
1769 if (IsWindow( hwnd ))
1770 FIXME( "(%d) not supported yet on other process window %x\n", offset, hwnd );
1771 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1772 return 0;
1774 if (offset > wndPtr->cbWndExtra - sizeof(WORD))
1776 WARN("Invalid offset %d\n", offset );
1777 SetLastError( ERROR_INVALID_INDEX );
1779 else retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1780 WIN_ReleasePtr( wndPtr );
1781 return retvalue;
1784 switch(offset)
1786 case GWL_HWNDPARENT:
1787 return GetWindowLongW( hwnd, offset );
1788 case GWL_ID:
1789 case GWL_HINSTANCE:
1791 LONG ret = GetWindowLongW( hwnd, offset );
1792 if (HIWORD(ret))
1793 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1794 return LOWORD(ret);
1796 default:
1797 WARN("Invalid offset %d\n", offset );
1798 return 0;
1803 /**********************************************************************
1804 * SetWindowWord (USER32.@)
1806 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1808 WORD *ptr, retval;
1809 WND * wndPtr;
1811 switch(offset)
1813 case GWL_ID:
1814 case GWL_HINSTANCE:
1815 case GWL_HWNDPARENT:
1816 return SetWindowLongW( hwnd, offset, (UINT)newval );
1817 default:
1818 if (offset < 0)
1820 WARN("Invalid offset %d\n", offset );
1821 SetLastError( ERROR_INVALID_INDEX );
1822 return 0;
1826 wndPtr = WIN_GetPtr( hwnd );
1827 if (wndPtr == WND_OTHER_PROCESS)
1829 if (IsWindow(hwnd))
1830 FIXME( "set %d <- %x not supported yet on other process window %x\n",
1831 offset, newval, hwnd );
1832 wndPtr = NULL;
1834 if (!wndPtr)
1836 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1837 return 0;
1840 if (offset > wndPtr->cbWndExtra - sizeof(WORD))
1842 WARN("Invalid offset %d\n", offset );
1843 WIN_ReleasePtr(wndPtr);
1844 SetLastError( ERROR_INVALID_INDEX );
1845 return 0;
1847 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1848 retval = *ptr;
1849 *ptr = newval;
1850 WIN_ReleasePtr(wndPtr);
1851 return retval;
1855 /**********************************************************************
1856 * WIN_GetWindowLong
1858 * Helper function for GetWindowLong().
1860 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1862 LONG retvalue = 0;
1863 WND *wndPtr;
1865 if (offset == GWL_HWNDPARENT)
1867 HWND parent = GetAncestor( hwnd, GA_PARENT );
1868 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1869 return (LONG)parent;
1872 if (!(wndPtr = WIN_GetPtr( hwnd )))
1874 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1875 return 0;
1878 if (wndPtr == WND_OTHER_PROCESS)
1880 if (offset >= 0)
1882 if (IsWindow(hwnd))
1883 FIXME( "(%d) not supported on other process window %x\n", offset, hwnd );
1884 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1885 return 0;
1887 if (offset == GWL_WNDPROC)
1889 SetLastError( ERROR_ACCESS_DENIED );
1890 return 0;
1892 SERVER_START_REQ( set_window_info )
1894 req->handle = hwnd;
1895 req->flags = 0; /* don't set anything, just retrieve */
1896 if (!wine_server_call_err( req ))
1898 switch(offset)
1900 case GWL_STYLE: retvalue = reply->old_style; break;
1901 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1902 case GWL_ID: retvalue = reply->old_id; break;
1903 case GWL_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1904 case GWL_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
1905 default:
1906 SetLastError( ERROR_INVALID_INDEX );
1907 break;
1911 SERVER_END_REQ;
1912 return retvalue;
1915 /* now we have a valid wndPtr */
1917 if (offset >= 0)
1919 if (offset > wndPtr->cbWndExtra - sizeof(LONG))
1922 * Some programs try to access last element from 16 bit
1923 * code using illegal offset value. Hopefully this is
1924 * what those programs really expect.
1926 if (type == WIN_PROC_16 &&
1927 wndPtr->cbWndExtra >= 4 &&
1928 offset == wndPtr->cbWndExtra - sizeof(WORD))
1930 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
1932 ERR( "- replaced invalid offset %d with %d\n",
1933 offset, offset2 );
1935 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset2);
1936 WIN_ReleasePtr( wndPtr );
1937 return retvalue;
1939 WARN("Invalid offset %d\n", offset );
1940 WIN_ReleasePtr( wndPtr );
1941 SetLastError( ERROR_INVALID_INDEX );
1942 return 0;
1944 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1945 /* Special case for dialog window procedure */
1946 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1947 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1948 WIN_ReleasePtr( wndPtr );
1949 return retvalue;
1952 switch(offset)
1954 case GWL_USERDATA: retvalue = wndPtr->userdata; break;
1955 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1956 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1957 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu; break;
1958 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc, type ); break;
1959 case GWL_HINSTANCE: retvalue = wndPtr->hInstance; break;
1960 default:
1961 WARN("Unknown offset %d\n", offset );
1962 SetLastError( ERROR_INVALID_INDEX );
1963 break;
1965 WIN_ReleasePtr(wndPtr);
1966 return retvalue;
1970 /**********************************************************************
1971 * WIN_SetWindowLong
1973 * Helper function for SetWindowLong().
1975 * 0 is the failure code. However, in the case of failure SetLastError
1976 * must be set to distinguish between a 0 return value and a failure.
1978 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1979 WINDOWPROCTYPE type )
1981 LONG retval = 0;
1982 WND *wndPtr;
1984 TRACE( "%x %d %lx %x\n", hwnd, offset, newval, type );
1986 if (!WIN_IsCurrentProcess( hwnd ))
1988 if (offset == GWL_WNDPROC)
1990 SetLastError( ERROR_ACCESS_DENIED );
1991 return 0;
1993 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
1996 wndPtr = WIN_GetPtr( hwnd );
1997 if (wndPtr->hwndSelf == GetDesktopWindow())
1999 /* can't change anything on the desktop window */
2000 WIN_ReleasePtr( wndPtr );
2001 SetLastError( ERROR_ACCESS_DENIED );
2002 return 0;
2005 if (offset >= 0)
2007 LONG *ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
2008 if (offset > wndPtr->cbWndExtra - sizeof(LONG))
2010 WARN("Invalid offset %d\n", offset );
2011 WIN_ReleasePtr( wndPtr );
2012 SetLastError( ERROR_INVALID_INDEX );
2013 return 0;
2015 /* Special case for dialog window procedure */
2016 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2018 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
2019 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
2020 type, WIN_PROC_WINDOW );
2021 WIN_ReleasePtr( wndPtr );
2022 return retval;
2024 retval = *ptr;
2025 *ptr = newval;
2026 WIN_ReleasePtr( wndPtr );
2028 else
2030 STYLESTRUCT style;
2031 BOOL ok;
2033 /* first some special cases */
2034 switch( offset )
2036 case GWL_STYLE:
2037 case GWL_EXSTYLE:
2038 style.styleOld = wndPtr->dwStyle;
2039 style.styleNew = newval;
2040 WIN_ReleasePtr( wndPtr );
2041 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
2042 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
2043 newval = style.styleNew;
2044 break;
2045 case GWL_HWNDPARENT:
2046 if (wndPtr->parent == GetDesktopWindow())
2048 WIN_ReleasePtr( wndPtr );
2049 return (LONG)WIN_SetOwner( hwnd, (HWND)newval );
2051 else
2053 WIN_ReleasePtr( wndPtr );
2054 return (LONG)SetParent( hwnd, (HWND)newval );
2056 case GWL_WNDPROC:
2057 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2058 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
2059 type, WIN_PROC_WINDOW );
2060 WIN_ReleasePtr( wndPtr );
2061 return retval;
2062 case GWL_ID:
2063 case GWL_HINSTANCE:
2064 case GWL_USERDATA:
2065 break;
2066 default:
2067 WIN_ReleasePtr( wndPtr );
2068 WARN("Invalid offset %d\n", offset );
2069 SetLastError( ERROR_INVALID_INDEX );
2070 return 0;
2073 SERVER_START_REQ( set_window_info )
2075 req->handle = hwnd;
2076 switch(offset)
2078 case GWL_STYLE:
2079 req->flags = SET_WIN_STYLE;
2080 req->style = newval;
2081 break;
2082 case GWL_EXSTYLE:
2083 req->flags = SET_WIN_EXSTYLE;
2084 req->ex_style = newval;
2085 break;
2086 case GWL_ID:
2087 req->flags = SET_WIN_ID;
2088 req->id = newval;
2089 break;
2090 case GWL_HINSTANCE:
2091 req->flags = SET_WIN_INSTANCE;
2092 req->instance = (void *)newval;
2093 break;
2094 case GWL_USERDATA:
2095 req->flags = SET_WIN_USERDATA;
2096 req->user_data = (void *)newval;
2097 break;
2099 if ((ok = !wine_server_call_err( req )))
2101 switch(offset)
2103 case GWL_STYLE:
2104 wndPtr->dwStyle = newval;
2105 retval = reply->old_style;
2106 break;
2107 case GWL_EXSTYLE:
2108 wndPtr->dwExStyle = newval;
2109 retval = reply->old_ex_style;
2110 break;
2111 case GWL_ID:
2112 wndPtr->wIDmenu = newval;
2113 retval = reply->old_id;
2114 break;
2115 case GWL_HINSTANCE:
2116 wndPtr->hInstance = newval;
2117 retval = (HINSTANCE)reply->old_instance;
2118 break;
2119 case GWL_USERDATA:
2120 wndPtr->userdata = newval;
2121 retval = (ULONG_PTR)reply->old_user_data;
2122 break;
2126 SERVER_END_REQ;
2127 WIN_ReleasePtr( wndPtr );
2129 if (!ok) return 0;
2131 if (offset == GWL_STYLE && USER_Driver.pSetWindowStyle)
2132 USER_Driver.pSetWindowStyle( hwnd, retval );
2134 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2135 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2138 return retval;
2142 /**********************************************************************
2143 * GetWindowLong (USER.135)
2145 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2147 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
2151 /**********************************************************************
2152 * GetWindowLongA (USER32.@)
2154 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2156 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2160 /**********************************************************************
2161 * GetWindowLongW (USER32.@)
2163 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2165 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2169 /**********************************************************************
2170 * SetWindowLong (USER.136)
2172 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2174 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
2178 /**********************************************************************
2179 * SetWindowLongA (USER32.@)
2181 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2183 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2187 /**********************************************************************
2188 * SetWindowLongW (USER32.@) Set window attribute
2190 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2191 * value in a window's extra memory.
2193 * The _hwnd_ parameter specifies the window. is the handle to a
2194 * window that has extra memory. The _newval_ parameter contains the
2195 * new attribute or extra memory value. If positive, the _offset_
2196 * parameter is the byte-addressed location in the window's extra
2197 * memory to set. If negative, _offset_ specifies the window
2198 * attribute to set, and should be one of the following values:
2200 * GWL_EXSTYLE The window's extended window style
2202 * GWL_STYLE The window's window style.
2204 * GWL_WNDPROC Pointer to the window's window procedure.
2206 * GWL_HINSTANCE The window's pplication instance handle.
2208 * GWL_ID The window's identifier.
2210 * GWL_USERDATA The window's user-specified data.
2212 * If the window is a dialog box, the _offset_ parameter can be one of
2213 * the following values:
2215 * DWL_DLGPROC The address of the window's dialog box procedure.
2217 * DWL_MSGRESULT The return value of a message
2218 * that the dialog box procedure processed.
2220 * DWL_USER Application specific information.
2222 * RETURNS
2224 * If successful, returns the previous value located at _offset_. Otherwise,
2225 * returns 0.
2227 * NOTES
2229 * Extra memory for a window class is specified by a nonzero cbWndExtra
2230 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2231 * time of class creation.
2233 * Using GWL_WNDPROC to set a new window procedure effectively creates
2234 * a window subclass. Use CallWindowProc() in the new windows procedure
2235 * to pass messages to the superclass's window procedure.
2237 * The user data is reserved for use by the application which created
2238 * the window.
2240 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2241 * instead, call the EnableWindow() function to change the window's
2242 * disabled state.
2244 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2245 * SetParent() instead.
2247 * Win95:
2248 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2249 * it sends WM_STYLECHANGING before changing the settings
2250 * and WM_STYLECHANGED afterwards.
2251 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2253 LONG WINAPI SetWindowLongW(
2254 HWND hwnd, /* [in] window to alter */
2255 INT offset, /* [in] offset, in bytes, of location to alter */
2256 LONG newval /* [in] new value of location */
2258 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2262 /*******************************************************************
2263 * GetWindowTextA (USER32.@)
2265 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2267 WCHAR *buffer;
2269 if (WIN_IsCurrentProcess( hwnd ))
2270 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2272 /* when window belongs to other process, don't send a message */
2273 if (nMaxCount <= 0) return 0;
2274 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2275 get_server_window_text( hwnd, buffer, nMaxCount );
2276 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2277 lpString[nMaxCount-1] = 0;
2278 HeapFree( GetProcessHeap(), 0, buffer );
2279 return strlen(lpString);
2283 /*******************************************************************
2284 * InternalGetWindowText (USER32.@)
2286 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2288 WND *win;
2290 if (nMaxCount <= 0) return 0;
2291 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2292 if (win != WND_OTHER_PROCESS)
2294 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2295 else lpString[0] = 0;
2296 WIN_ReleasePtr( win );
2298 else
2300 get_server_window_text( hwnd, lpString, nMaxCount );
2302 return strlenW(lpString);
2306 /*******************************************************************
2307 * GetWindowTextW (USER32.@)
2309 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2311 if (WIN_IsCurrentProcess( hwnd ))
2312 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2314 /* when window belongs to other process, don't send a message */
2315 if (nMaxCount <= 0) return 0;
2316 get_server_window_text( hwnd, lpString, nMaxCount );
2317 return strlenW(lpString);
2321 /*******************************************************************
2322 * SetWindowText (USER32.@)
2323 * SetWindowTextA (USER32.@)
2325 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2327 if (!WIN_IsCurrentProcess( hwnd ))
2329 FIXME( "cannot set text %s of other process window %x\n", debugstr_a(lpString), hwnd );
2330 SetLastError( ERROR_ACCESS_DENIED );
2331 return FALSE;
2333 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2337 /*******************************************************************
2338 * SetWindowTextW (USER32.@)
2340 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2342 if (!WIN_IsCurrentProcess( hwnd ))
2344 FIXME( "cannot set text %s of other process window %x\n", debugstr_w(lpString), hwnd );
2345 SetLastError( ERROR_ACCESS_DENIED );
2346 return FALSE;
2348 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2352 /*******************************************************************
2353 * GetWindowTextLengthA (USER32.@)
2355 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2357 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2360 /*******************************************************************
2361 * GetWindowTextLengthW (USER32.@)
2363 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2365 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2369 /*******************************************************************
2370 * IsWindow (USER32.@)
2372 BOOL WINAPI IsWindow( HWND hwnd )
2374 WND *ptr;
2375 BOOL ret;
2377 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2379 if (ptr != WND_OTHER_PROCESS)
2381 WIN_ReleasePtr( ptr );
2382 return TRUE;
2385 /* check other processes */
2386 SERVER_START_REQ( get_window_info )
2388 req->handle = hwnd;
2389 ret = !wine_server_call_err( req );
2391 SERVER_END_REQ;
2392 return ret;
2396 /***********************************************************************
2397 * GetWindowThreadProcessId (USER32.@)
2399 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2401 WND *ptr;
2402 DWORD tid = 0;
2404 if (!(ptr = WIN_GetPtr( hwnd )))
2406 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2407 return 0;
2410 if (ptr != WND_OTHER_PROCESS)
2412 /* got a valid window */
2413 tid = ptr->tid;
2414 if (process) *process = GetCurrentProcessId();
2415 WIN_ReleasePtr( ptr );
2416 return tid;
2419 /* check other processes */
2420 SERVER_START_REQ( get_window_info )
2422 req->handle = hwnd;
2423 if (!wine_server_call_err( req ))
2425 tid = (DWORD)reply->tid;
2426 if (process) *process = (DWORD)reply->pid;
2429 SERVER_END_REQ;
2430 return tid;
2434 /*****************************************************************
2435 * GetParent (USER32.@)
2437 HWND WINAPI GetParent( HWND hwnd )
2439 WND *wndPtr;
2440 HWND retvalue = 0;
2442 if (!(wndPtr = WIN_GetPtr( hwnd )))
2444 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2445 return 0;
2447 if (wndPtr == WND_OTHER_PROCESS)
2449 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2450 if (style & (WS_POPUP | WS_CHILD))
2452 SERVER_START_REQ( get_window_tree )
2454 req->handle = hwnd;
2455 if (!wine_server_call_err( req ))
2457 if (style & WS_POPUP) retvalue = reply->owner;
2458 else if (style & WS_CHILD) retvalue = reply->parent;
2461 SERVER_END_REQ;
2464 else
2466 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2467 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2468 WIN_ReleasePtr( wndPtr );
2470 return retvalue;
2474 /*****************************************************************
2475 * GetAncestor (USER32.@)
2477 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2479 WND *win;
2480 HWND *list, ret = 0;
2482 switch(type)
2484 case GA_PARENT:
2485 if (!(win = WIN_GetPtr( hwnd )))
2487 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2488 return 0;
2490 if (win != WND_OTHER_PROCESS)
2492 ret = win->parent;
2493 WIN_ReleasePtr( win );
2495 else /* need to query the server */
2497 SERVER_START_REQ( get_window_tree )
2499 req->handle = hwnd;
2500 if (!wine_server_call_err( req )) ret = reply->parent;
2502 SERVER_END_REQ;
2504 break;
2506 case GA_ROOT:
2507 if (!(list = WIN_ListParents( hwnd ))) return 0;
2509 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2510 else
2512 int count = 2;
2513 while (list[count]) count++;
2514 ret = list[count - 2]; /* get the one before the desktop */
2516 HeapFree( GetProcessHeap(), 0, list );
2517 break;
2519 case GA_ROOTOWNER:
2520 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2521 for (;;)
2523 HWND parent = GetParent( ret );
2524 if (!parent) break;
2525 ret = parent;
2527 break;
2529 return ret;
2533 /*****************************************************************
2534 * SetParent (USER32.@)
2536 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2538 WND *wndPtr;
2539 HWND retvalue, full_handle;
2540 BOOL was_visible;
2542 if (!parent) parent = GetDesktopWindow();
2543 else parent = WIN_GetFullHandle( parent );
2545 if (!IsWindow( parent ))
2547 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2548 return 0;
2551 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2552 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2554 hwnd = full_handle;
2556 if (USER_Driver.pSetParent)
2557 return USER_Driver.pSetParent( hwnd, parent );
2559 /* Windows hides the window first, then shows it again
2560 * including the WM_SHOWWINDOW messages and all */
2561 was_visible = ShowWindow( hwnd, SW_HIDE );
2563 if (!IsWindow( parent )) return 0;
2564 if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return 0;
2566 retvalue = wndPtr->parent; /* old parent */
2567 if (parent != retvalue)
2569 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2571 if (parent != GetDesktopWindow()) /* a child window */
2573 if (!(wndPtr->dwStyle & WS_CHILD))
2575 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
2576 if (menu) DestroyMenu( menu );
2580 WIN_ReleasePtr( wndPtr );
2582 /* SetParent additionally needs to make hwnd the topmost window
2583 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2584 WM_WINDOWPOSCHANGED notification messages.
2586 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2587 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2588 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2589 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2590 return retvalue;
2594 /*******************************************************************
2595 * IsChild (USER32.@)
2597 BOOL WINAPI IsChild( HWND parent, HWND child )
2599 HWND *list = WIN_ListParents( child );
2600 int i;
2601 BOOL ret;
2603 if (!list) return FALSE;
2604 parent = WIN_GetFullHandle( parent );
2605 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2606 ret = (list[i] != 0);
2607 HeapFree( GetProcessHeap(), 0, list );
2608 return ret;
2612 /***********************************************************************
2613 * IsWindowVisible (USER32.@)
2615 BOOL WINAPI IsWindowVisible( HWND hwnd )
2617 HWND *list;
2618 BOOL retval;
2619 int i;
2621 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2622 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2623 for (i = 0; list[i]; i++)
2624 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2625 retval = !list[i];
2626 HeapFree( GetProcessHeap(), 0, list );
2627 return retval;
2631 /***********************************************************************
2632 * WIN_IsWindowDrawable
2634 * hwnd is drawable when it is visible, all parents are not
2635 * minimized, and it is itself not minimized unless we are
2636 * trying to draw its default class icon.
2638 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2640 HWND *list;
2641 BOOL retval;
2642 int i;
2643 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2645 if (!(style & WS_VISIBLE)) return FALSE;
2646 if ((style & WS_MINIMIZE) && icon && GetClassLongA( hwnd, GCL_HICON )) return FALSE;
2648 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2649 for (i = 0; list[i]; i++)
2650 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2651 break;
2652 retval = !list[i];
2653 HeapFree( GetProcessHeap(), 0, list );
2654 return retval;
2658 /*******************************************************************
2659 * GetTopWindow (USER32.@)
2661 HWND WINAPI GetTopWindow( HWND hwnd )
2663 if (!hwnd) hwnd = GetDesktopWindow();
2664 return GetWindow( hwnd, GW_CHILD );
2668 /*******************************************************************
2669 * GetWindow (USER32.@)
2671 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2673 HWND retval = 0;
2675 if (rel == GW_OWNER) /* this one may be available locally */
2677 WND *wndPtr = WIN_GetPtr( hwnd );
2678 if (!wndPtr)
2680 SetLastError( ERROR_INVALID_HANDLE );
2681 return 0;
2683 if (wndPtr != WND_OTHER_PROCESS)
2685 retval = wndPtr->owner;
2686 WIN_ReleasePtr( wndPtr );
2687 return retval;
2689 /* else fall through to server call */
2692 SERVER_START_REQ( get_window_tree )
2694 req->handle = hwnd;
2695 if (!wine_server_call_err( req ))
2697 switch(rel)
2699 case GW_HWNDFIRST:
2700 retval = reply->first_sibling;
2701 break;
2702 case GW_HWNDLAST:
2703 retval = reply->last_sibling;
2704 break;
2705 case GW_HWNDNEXT:
2706 retval = reply->next_sibling;
2707 break;
2708 case GW_HWNDPREV:
2709 retval = reply->prev_sibling;
2710 break;
2711 case GW_OWNER:
2712 retval = reply->owner;
2713 break;
2714 case GW_CHILD:
2715 retval = reply->first_child;
2716 break;
2720 SERVER_END_REQ;
2721 return retval;
2725 /***********************************************************************
2726 * WIN_InternalShowOwnedPopups
2728 * Internal version of ShowOwnedPopups; Wine functions should use this
2729 * to avoid interfering with application calls to ShowOwnedPopups
2730 * and to make sure the application can't prevent showing/hiding.
2732 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2736 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2738 int count = 0;
2739 WND *pWnd;
2740 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2742 if (!win_array) return TRUE;
2745 * Show windows Lowest first, Highest last to preserve Z-Order
2747 while (win_array[count]) count++;
2748 while (--count >= 0)
2750 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2751 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2753 if (pWnd->dwStyle & WS_POPUP)
2755 if (fShow)
2757 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2758 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
2761 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2763 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2764 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2767 else
2769 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2770 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2771 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2774 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2776 ShowWindow(pWnd->hwndSelf,SW_HIDE);
2777 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2778 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
2782 WIN_ReleaseWndPtr( pWnd );
2784 HeapFree( GetProcessHeap(), 0, win_array );
2786 return TRUE;
2789 /*******************************************************************
2790 * ShowOwnedPopups (USER32.@)
2792 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2794 int count = 0;
2795 WND *pWnd;
2796 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2798 if (!win_array) return TRUE;
2800 while (win_array[count]) count++;
2801 while (--count >= 0)
2803 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2804 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2806 if (pWnd->dwStyle & WS_POPUP)
2808 if (fShow)
2810 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2812 /* In Windows, ShowOwnedPopups(TRUE) generates
2813 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2814 * regardless of the state of the owner
2816 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2817 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2820 else
2822 if (IsWindowVisible(pWnd->hwndSelf))
2824 /* In Windows, ShowOwnedPopups(FALSE) generates
2825 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2826 * regardless of the state of the owner
2828 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2829 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2833 WIN_ReleaseWndPtr( pWnd );
2835 HeapFree( GetProcessHeap(), 0, win_array );
2836 return TRUE;
2840 /*******************************************************************
2841 * GetLastActivePopup (USER32.@)
2843 HWND WINAPI GetLastActivePopup( HWND hwnd )
2845 HWND retval = hwnd;
2847 SERVER_START_REQ( get_window_info )
2849 req->handle = hwnd;
2850 if (!wine_server_call_err( req )) retval = reply->last_active;
2852 SERVER_END_REQ;
2853 return retval;
2857 /*******************************************************************
2858 * WIN_ListParents
2860 * Build an array of all parents of a given window, starting with
2861 * the immediate parent. The array must be freed with HeapFree.
2862 * Returns NULL if window is a top-level window.
2864 HWND *WIN_ListParents( HWND hwnd )
2866 WND *win;
2867 HWND current, *list;
2868 int pos = 0, size = 16, count = 0;
2870 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2872 current = hwnd;
2873 for (;;)
2875 if (!(win = WIN_GetPtr( current ))) goto empty;
2876 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
2877 list[pos] = win->parent;
2878 WIN_ReleasePtr( win );
2879 if (!(current = list[pos]))
2881 if (!pos) goto empty;
2882 return list;
2884 if (++pos == size - 1)
2886 /* need to grow the list */
2887 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
2888 if (!new_list) goto empty;
2889 list = new_list;
2890 size += 16;
2894 /* at least one parent belongs to another process, have to query the server */
2896 for (;;)
2898 count = 0;
2899 SERVER_START_REQ( get_window_parents )
2901 req->handle = hwnd;
2902 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
2903 if (!wine_server_call( req )) count = reply->count;
2905 SERVER_END_REQ;
2906 if (!count) goto empty;
2907 if (size > count)
2909 list[count] = 0;
2910 return list;
2912 HeapFree( GetProcessHeap(), 0, list );
2913 size = count + 1;
2914 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2917 empty:
2918 HeapFree( GetProcessHeap(), 0, list );
2919 return NULL;
2923 /*******************************************************************
2924 * WIN_ListChildren
2926 * Build an array of the children of a given window. The array must be
2927 * freed with HeapFree. Returns NULL when no windows are found.
2929 HWND *WIN_ListChildren( HWND hwnd )
2931 return list_window_children( hwnd, 0, 0 );
2935 /*******************************************************************
2936 * EnumWindows (USER32.@)
2938 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2940 HWND *list;
2941 BOOL ret = TRUE;
2942 int i, iWndsLocks;
2944 /* We have to build a list of all windows first, to avoid */
2945 /* unpleasant side-effects, for instance if the callback */
2946 /* function changes the Z-order of the windows. */
2948 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2950 /* Now call the callback function for every window */
2952 iWndsLocks = WIN_SuspendWndsLock();
2953 for (i = 0; list[i]; i++)
2955 /* Make sure that the window still exists */
2956 if (!IsWindow( list[i] )) continue;
2957 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2959 WIN_RestoreWndsLock(iWndsLocks);
2960 HeapFree( GetProcessHeap(), 0, list );
2961 return ret;
2965 /**********************************************************************
2966 * EnumThreadWindows (USER32.@)
2968 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2970 HWND *list;
2971 int i, iWndsLocks;
2973 if (!(list = list_window_children( GetDesktopWindow(), 0, id ))) return TRUE;
2975 /* Now call the callback function for every window */
2977 iWndsLocks = WIN_SuspendWndsLock();
2978 for (i = 0; list[i]; i++)
2979 if (!func( list[i], lParam )) break;
2980 WIN_RestoreWndsLock(iWndsLocks);
2981 HeapFree( GetProcessHeap(), 0, list );
2982 return TRUE;
2986 /**********************************************************************
2987 * WIN_EnumChildWindows
2989 * Helper function for EnumChildWindows().
2991 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2993 HWND *childList;
2994 BOOL ret = FALSE;
2996 for ( ; *list; list++)
2998 /* Make sure that the window still exists */
2999 if (!IsWindow( *list )) continue;
3000 /* skip owned windows */
3001 if (GetWindow( *list, GW_OWNER )) continue;
3002 /* Build children list first */
3003 childList = WIN_ListChildren( *list );
3005 ret = func( *list, lParam );
3007 if (childList)
3009 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
3010 HeapFree( GetProcessHeap(), 0, childList );
3012 if (!ret) return FALSE;
3014 return TRUE;
3018 /**********************************************************************
3019 * EnumChildWindows (USER32.@)
3021 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
3023 HWND *list;
3024 int iWndsLocks;
3026 if (!(list = WIN_ListChildren( parent ))) return FALSE;
3027 iWndsLocks = WIN_SuspendWndsLock();
3028 WIN_EnumChildWindows( list, func, lParam );
3029 WIN_RestoreWndsLock(iWndsLocks);
3030 HeapFree( GetProcessHeap(), 0, list );
3031 return TRUE;
3035 /*******************************************************************
3036 * AnyPopup (USER.52)
3038 BOOL16 WINAPI AnyPopup16(void)
3040 return AnyPopup();
3044 /*******************************************************************
3045 * AnyPopup (USER32.@)
3047 BOOL WINAPI AnyPopup(void)
3049 int i;
3050 BOOL retvalue;
3051 HWND *list = WIN_ListChildren( GetDesktopWindow() );
3053 if (!list) return FALSE;
3054 for (i = 0; list[i]; i++)
3056 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
3058 retvalue = (list[i] != 0);
3059 HeapFree( GetProcessHeap(), 0, list );
3060 return retvalue;
3064 /*******************************************************************
3065 * FlashWindow (USER32.@)
3067 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3069 WND *wndPtr = WIN_FindWndPtr(hWnd);
3071 TRACE("%04x\n", hWnd);
3073 if (!wndPtr) return FALSE;
3074 hWnd = wndPtr->hwndSelf; /* make it a full handle */
3076 if (wndPtr->dwStyle & WS_MINIMIZE)
3078 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3080 HDC hDC = GetDC(hWnd);
3082 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM)hDC, 0 ))
3083 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
3085 ReleaseDC( hWnd, hDC );
3086 wndPtr->flags |= WIN_NCACTIVATED;
3088 else
3090 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3091 wndPtr->flags &= ~WIN_NCACTIVATED;
3093 WIN_ReleaseWndPtr(wndPtr);
3094 return TRUE;
3096 else
3098 WPARAM16 wparam;
3099 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3100 else wparam = (hWnd == GetForegroundWindow());
3102 WIN_ReleaseWndPtr(wndPtr);
3103 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3104 return wparam;
3109 /*******************************************************************
3110 * GetWindowContextHelpId (USER32.@)
3112 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3114 DWORD retval;
3115 WND *wnd = WIN_FindWndPtr( hwnd );
3116 if (!wnd) return 0;
3117 retval = wnd->helpContext;
3118 WIN_ReleaseWndPtr(wnd);
3119 return retval;
3123 /*******************************************************************
3124 * SetWindowContextHelpId (USER32.@)
3126 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3128 WND *wnd = WIN_FindWndPtr( hwnd );
3129 if (!wnd) return FALSE;
3130 wnd->helpContext = id;
3131 WIN_ReleaseWndPtr(wnd);
3132 return TRUE;
3136 /*******************************************************************
3137 * DragDetect (USER32.@)
3139 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3141 MSG msg;
3142 RECT rect;
3144 rect.left = pt.x - wDragWidth;
3145 rect.right = pt.x + wDragWidth;
3147 rect.top = pt.y - wDragHeight;
3148 rect.bottom = pt.y + wDragHeight;
3150 SetCapture(hWnd);
3152 while(1)
3154 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3156 if( msg.message == WM_LBUTTONUP )
3158 ReleaseCapture();
3159 return 0;
3161 if( msg.message == WM_MOUSEMOVE )
3163 POINT tmp;
3164 tmp.x = LOWORD(msg.lParam);
3165 tmp.y = HIWORD(msg.lParam);
3166 if( !PtInRect( &rect, tmp ))
3168 ReleaseCapture();
3169 return 1;
3173 WaitMessage();
3175 return 0;
3178 /******************************************************************************
3179 * GetWindowModuleFileNameA (USER32.@)
3181 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3183 FIXME("GetWindowModuleFileNameA(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3184 hwnd, lpszFileName, cchFileNameMax);
3185 return 0;
3188 /******************************************************************************
3189 * GetWindowModuleFileNameW (USER32.@)
3191 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3193 FIXME("GetWindowModuleFileNameW(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3194 hwnd, lpszFileName, cchFileNameMax);
3195 return 0;
3198 /******************************************************************************
3199 * GetWindowInfo (USER32.@)
3200 * hwnd: in
3201 * pwi: out.
3202 * MS Documentation mentions that pwi->cbSize must be set to SIZEOF(WINDOWINFO)
3203 * this may be because this structure changed over time. If this is the
3204 * the case, then please: FIXME.
3205 * Using the structure described in MSDN for 98/ME/NT(4.0 SP3)/2000/XP.
3207 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3209 WND *wndInfo = NULL;
3210 if (!pwi) return FALSE;
3211 if (pwi->cbSize != sizeof(WINDOWINFO))
3213 FIXME("windowinfo->cbSize != sizeof(WINDOWINFO). Please report\n");
3214 return FALSE;
3216 wndInfo = WIN_GetPtr(hwnd);
3217 if (!wndInfo) return FALSE;
3218 if (wndInfo == WND_OTHER_PROCESS)
3220 FIXME("window belong to other process\n");
3221 return FALSE;
3224 pwi->rcWindow = wndInfo->rectWindow;
3225 pwi->rcClient = wndInfo->rectClient;
3226 pwi->dwStyle = wndInfo->dwStyle;
3227 pwi->dwExStyle = wndInfo->dwExStyle;
3228 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3229 /* if active WS_ACTIVECAPTION, else 0 */
3231 pwi->cxWindowBorders = ((wndInfo->dwStyle & WS_BORDER) ?
3232 GetSystemMetrics(SM_CXBORDER) : 0);
3233 pwi->cyWindowBorders = ((wndInfo->dwStyle & WS_BORDER) ?
3234 GetSystemMetrics(SM_CYBORDER) : 0);
3235 /* above two: I'm presuming that borders widths are the same
3236 * for each window - so long as its actually using a border.. */
3238 pwi->atomWindowType = GetClassLongA( hwnd, GCW_ATOM );
3239 pwi->wCreatorVersion = GetVersion();
3240 /* Docs say this should be the version that
3241 * CREATED the window. But eh?.. Isn't that just the
3242 * version we are running.. Unless ofcourse its some wacky
3243 * RPC stuff or something */
3245 WIN_ReleasePtr(wndInfo);
3246 return TRUE;