- do not forget to set the 'initial_upload_done' flag (to have better
[wine/multimedia.git] / windows / win.c
blobcb0e871ea055a7d8614a8cf34f33d764ab3d5f63
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 "winpos.h"
40 #include "winerror.h"
41 #include "stackframe.h"
42 #include "wine/debug.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(win);
45 WINE_DECLARE_DEBUG_CHANNEL(msg);
47 #define NB_USER_HANDLES (LAST_USER_HANDLE - FIRST_USER_HANDLE + 1)
49 /**********************************************************************/
51 /* Desktop window */
52 static WND *pWndDesktop = NULL;
54 static WORD wDragWidth = 4;
55 static WORD wDragHeight= 3;
57 static void *user_handles[NB_USER_HANDLES];
59 /* thread safeness */
60 extern SYSLEVEL USER_SysLevel; /* FIXME */
62 /***********************************************************************
63 * WIN_SuspendWndsLock
65 * Suspend the lock on WND structures.
66 * Returns the number of locks suspended
68 int WIN_SuspendWndsLock( void )
70 int isuspendedLocks = _ConfirmSysLevel( &USER_SysLevel );
71 int count = isuspendedLocks;
73 while ( count-- > 0 )
74 _LeaveSysLevel( &USER_SysLevel );
76 return isuspendedLocks;
79 /***********************************************************************
80 * WIN_RestoreWndsLock
82 * Restore the suspended locks on WND structures
84 void WIN_RestoreWndsLock( int ipreviousLocks )
86 while ( ipreviousLocks-- > 0 )
87 _EnterSysLevel( &USER_SysLevel );
90 /***********************************************************************
91 * create_window_handle
93 * Create a window handle with the server.
95 static WND *create_window_handle( HWND parent, HWND owner, ATOM atom, INT size )
97 BOOL res;
98 user_handle_t handle = 0;
99 WORD index;
100 WND *win = HeapAlloc( GetProcessHeap(), 0, size );
102 if (!win) return NULL;
104 USER_Lock();
106 SERVER_START_REQ( create_window )
108 req->parent = parent;
109 req->owner = owner;
110 req->atom = atom;
111 if ((res = !wine_server_call_err( req ))) handle = reply->handle;
113 SERVER_END_REQ;
115 if (!res)
117 USER_Unlock();
118 HeapFree( GetProcessHeap(), 0, win );
119 return NULL;
121 index = LOWORD(handle) - FIRST_USER_HANDLE;
122 assert( index < NB_USER_HANDLES );
123 user_handles[index] = win;
124 win->hwndSelf = handle;
125 win->dwMagic = WND_MAGIC;
126 win->irefCount = 1;
127 return win;
131 /***********************************************************************
132 * free_window_handle
134 * Free a window handle.
136 static WND *free_window_handle( HWND hwnd )
138 WND *ptr;
139 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
141 if (index >= NB_USER_HANDLES) return NULL;
142 USER_Lock();
143 if ((ptr = user_handles[index]))
145 SERVER_START_REQ( destroy_window )
147 req->handle = hwnd;
148 if (!wine_server_call_err( req ))
149 user_handles[index] = NULL;
150 else
151 ptr = NULL;
153 SERVER_END_REQ;
155 USER_Unlock();
156 if (ptr) HeapFree( GetProcessHeap(), 0, ptr );
157 return ptr;
161 /*******************************************************************
162 * list_window_children
164 * Build an array of the children of a given window. The array must be
165 * freed with HeapFree. Returns NULL when no windows are found.
167 static HWND *list_window_children( HWND hwnd, ATOM atom, DWORD tid )
169 HWND *list;
170 int size = 32;
172 for (;;)
174 int count = 0;
176 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
178 SERVER_START_REQ( get_window_children )
180 req->parent = hwnd;
181 req->atom = atom;
182 req->tid = tid;
183 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
184 if (!wine_server_call( req )) count = reply->count;
186 SERVER_END_REQ;
187 if (count && count < size)
189 list[count] = 0;
190 return list;
192 HeapFree( GetProcessHeap(), 0, list );
193 if (!count) break;
194 size = count + 1; /* restart with a large enough buffer */
196 return NULL;
200 /*******************************************************************
201 * send_parent_notify
203 static void send_parent_notify( HWND hwnd, UINT msg )
205 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD)) return;
206 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY) return;
207 SendMessageW( GetParent(hwnd), WM_PARENTNOTIFY,
208 MAKEWPARAM( msg, GetWindowLongW( hwnd, GWL_ID )), (LPARAM)hwnd );
212 /*******************************************************************
213 * get_server_window_text
215 * Retrieve the window text from the server.
217 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
219 size_t len = 0;
221 SERVER_START_REQ( get_window_text )
223 req->handle = hwnd;
224 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
225 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
227 SERVER_END_REQ;
228 text[len / sizeof(WCHAR)] = 0;
232 /***********************************************************************
233 * WIN_GetPtr
235 * Return a pointer to the WND structure if local to the process,
236 * or WND_OTHER_PROCESS if handle may be valid in other process.
237 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
239 WND *WIN_GetPtr( HWND hwnd )
241 WND * ptr;
242 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
244 if (index >= NB_USER_HANDLES) return NULL;
246 USER_Lock();
247 if ((ptr = user_handles[index]))
249 if (ptr->dwMagic == WND_MAGIC && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
250 return ptr;
251 ptr = NULL;
253 else ptr = WND_OTHER_PROCESS;
254 USER_Unlock();
255 return ptr;
259 /***********************************************************************
260 * WIN_IsCurrentProcess
262 * Check whether a given window belongs to the current process (and return the full handle).
264 HWND WIN_IsCurrentProcess( HWND hwnd )
266 WND *ptr;
267 HWND ret;
269 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS) return 0;
270 ret = ptr->hwndSelf;
271 WIN_ReleasePtr( ptr );
272 return ret;
276 /***********************************************************************
277 * WIN_IsCurrentThread
279 * Check whether a given window belongs to the current thread (and return the full handle).
281 HWND WIN_IsCurrentThread( HWND hwnd )
283 WND *ptr;
284 HWND ret = 0;
286 if ((ptr = WIN_GetPtr( hwnd )) && ptr != WND_OTHER_PROCESS)
288 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
289 WIN_ReleasePtr( ptr );
291 return ret;
295 /***********************************************************************
296 * WIN_Handle32
298 * Convert a 16-bit window handle to a full 32-bit handle.
300 HWND WIN_Handle32( HWND16 hwnd16 )
302 WND *ptr;
303 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
305 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
306 /* do sign extension for -2 and -3 */
307 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
309 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
311 if (ptr != WND_OTHER_PROCESS)
313 hwnd = ptr->hwndSelf;
314 WIN_ReleasePtr( ptr );
316 else /* may belong to another process */
318 SERVER_START_REQ( get_window_info )
320 req->handle = hwnd;
321 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
323 SERVER_END_REQ;
325 return hwnd;
329 /***********************************************************************
330 * WIN_FindWndPtr
332 * Return a pointer to the WND structure corresponding to a HWND.
334 WND * WIN_FindWndPtr( HWND hwnd )
336 WND * ptr;
338 if (!hwnd) return NULL;
340 if ((ptr = WIN_GetPtr( hwnd )))
342 if (ptr != WND_OTHER_PROCESS)
344 /* increment destruction monitoring */
345 ptr->irefCount++;
346 return ptr;
348 if (IsWindow( hwnd )) /* check other processes */
350 ERR( "window %p belongs to other process\n", hwnd );
351 /* DbgBreakPoint(); */
354 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
355 return NULL;
359 /***********************************************************************
360 * WIN_ReleaseWndPtr
362 * Release the pointer to the WND structure.
364 void WIN_ReleaseWndPtr(WND *wndPtr)
366 if(!wndPtr) return;
368 /* Decrement destruction monitoring value */
369 wndPtr->irefCount--;
370 /* Check if it's time to release the memory */
371 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
373 /* Release memory */
374 free_window_handle( wndPtr->hwndSelf );
376 else if(wndPtr->irefCount < 0)
378 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
379 ERR("forgot a Lock on %p somewhere\n",wndPtr);
381 /* unlock all WND structures for thread safeness */
382 USER_Unlock();
386 /***********************************************************************
387 * WIN_UnlinkWindow
389 * Remove a window from the siblings linked list.
391 void WIN_UnlinkWindow( HWND hwnd )
393 WIN_LinkWindow( hwnd, 0, 0 );
397 /***********************************************************************
398 * WIN_LinkWindow
400 * Insert a window into the siblings linked list.
401 * The window is inserted after the specified window, which can also
402 * be specified as HWND_TOP or HWND_BOTTOM.
403 * If parent is 0, window is unlinked from the tree.
405 void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
407 WND *wndPtr = WIN_GetPtr( hwnd );
409 if (!wndPtr) return;
410 if (wndPtr == WND_OTHER_PROCESS)
412 if (IsWindow(hwnd)) ERR(" cannot link other process window %p\n", hwnd );
413 return;
416 SERVER_START_REQ( link_window )
418 req->handle = hwnd;
419 req->parent = parent;
420 req->previous = hwndInsertAfter;
421 if (!wine_server_call( req ))
423 if (reply->full_parent) wndPtr->parent = reply->full_parent;
427 SERVER_END_REQ;
428 WIN_ReleasePtr( wndPtr );
432 /***********************************************************************
433 * WIN_SetOwner
435 * Change the owner of a window.
437 HWND WIN_SetOwner( HWND hwnd, HWND owner )
439 WND *win = WIN_GetPtr( hwnd );
440 HWND ret = 0;
442 if (!win) return 0;
443 if (win == WND_OTHER_PROCESS)
445 if (IsWindow(hwnd)) ERR( "cannot set owner %p on other process window %p\n", owner, hwnd );
446 return 0;
448 SERVER_START_REQ( set_window_owner )
450 req->handle = hwnd;
451 req->owner = owner;
452 if (!wine_server_call( req ))
454 win->owner = reply->full_owner;
455 ret = reply->prev_owner;
458 SERVER_END_REQ;
459 WIN_ReleasePtr( win );
460 return ret;
464 /***********************************************************************
465 * WIN_SetStyle
467 * Change the style of a window.
469 LONG WIN_SetStyle( HWND hwnd, LONG style )
471 BOOL ok;
472 LONG ret = 0;
473 WND *win = WIN_GetPtr( hwnd );
475 if (!win) return 0;
476 if (win == WND_OTHER_PROCESS)
478 if (IsWindow(hwnd))
479 ERR( "cannot set style %lx on other process window %p\n", style, hwnd );
480 return 0;
482 if (style == win->dwStyle)
484 WIN_ReleasePtr( win );
485 return style;
487 SERVER_START_REQ( set_window_info )
489 req->handle = hwnd;
490 req->flags = SET_WIN_STYLE;
491 req->style = style;
492 if ((ok = !wine_server_call( req )))
494 ret = reply->old_style;
495 win->dwStyle = style;
498 SERVER_END_REQ;
499 WIN_ReleasePtr( win );
500 if (ok && USER_Driver.pSetWindowStyle) USER_Driver.pSetWindowStyle( hwnd, ret );
501 return ret;
505 /***********************************************************************
506 * WIN_SetExStyle
508 * Change the extended style of a window.
510 LONG WIN_SetExStyle( HWND hwnd, LONG style )
512 LONG ret = 0;
513 WND *win = WIN_GetPtr( hwnd );
515 if (!win) return 0;
516 if (win == WND_OTHER_PROCESS)
518 if (IsWindow(hwnd))
519 ERR( "cannot set exstyle %lx on other process window %p\n", style, hwnd );
520 return 0;
522 if (style == win->dwExStyle)
524 WIN_ReleasePtr( win );
525 return style;
527 SERVER_START_REQ( set_window_info )
529 req->handle = hwnd;
530 req->flags = SET_WIN_EXSTYLE;
531 req->ex_style = style;
532 if (!wine_server_call( req ))
534 ret = reply->old_ex_style;
535 win->dwExStyle = style;
538 SERVER_END_REQ;
539 WIN_ReleasePtr( win );
540 return ret;
544 /***********************************************************************
545 * WIN_SetRectangles
547 * Set the window and client rectangles.
549 void WIN_SetRectangles( HWND hwnd, const RECT *rectWindow, const RECT *rectClient )
551 WND *win = WIN_GetPtr( hwnd );
552 BOOL ret;
554 if (!win) return;
555 if (win == WND_OTHER_PROCESS)
557 if (IsWindow( hwnd )) ERR( "cannot set rectangles of other process window %p\n", hwnd );
558 return;
560 SERVER_START_REQ( set_window_rectangles )
562 req->handle = hwnd;
563 req->window.left = rectWindow->left;
564 req->window.top = rectWindow->top;
565 req->window.right = rectWindow->right;
566 req->window.bottom = rectWindow->bottom;
567 req->client.left = rectClient->left;
568 req->client.top = rectClient->top;
569 req->client.right = rectClient->right;
570 req->client.bottom = rectClient->bottom;
571 ret = !wine_server_call( req );
573 SERVER_END_REQ;
574 if (ret)
576 win->rectWindow = *rectWindow;
577 win->rectClient = *rectClient;
579 TRACE( "win %p window (%ld,%ld)-(%ld,%ld) client (%ld,%ld)-(%ld,%ld)\n", hwnd,
580 rectWindow->left, rectWindow->top, rectWindow->right, rectWindow->bottom,
581 rectClient->left, rectClient->top, rectClient->right, rectClient->bottom );
583 WIN_ReleasePtr( win );
587 /***********************************************************************
588 * WIN_GetRectangles
590 * Get the window and client rectangles.
592 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
594 WND *win = WIN_GetPtr( hwnd );
595 BOOL ret = TRUE;
597 if (!win) return FALSE;
598 if (win == WND_OTHER_PROCESS)
600 SERVER_START_REQ( get_window_rectangles )
602 req->handle = hwnd;
603 if ((ret = !wine_server_call( req )))
605 if (rectWindow)
607 rectWindow->left = reply->window.left;
608 rectWindow->top = reply->window.top;
609 rectWindow->right = reply->window.right;
610 rectWindow->bottom = reply->window.bottom;
612 if (rectClient)
614 rectClient->left = reply->client.left;
615 rectClient->top = reply->client.top;
616 rectClient->right = reply->client.right;
617 rectClient->bottom = reply->client.bottom;
621 SERVER_END_REQ;
623 else
625 if (rectWindow) *rectWindow = win->rectWindow;
626 if (rectClient) *rectClient = win->rectClient;
627 WIN_ReleasePtr( win );
629 return ret;
633 /***********************************************************************
634 * WIN_DestroyWindow
636 * Destroy storage associated to a window. "Internals" p.358
638 LRESULT WIN_DestroyWindow( HWND hwnd )
640 WND *wndPtr;
641 HWND *list;
643 TRACE("%p\n", hwnd );
645 if (!(hwnd = WIN_IsCurrentThread( hwnd )))
647 ERR( "window doesn't belong to current thread\n" );
648 return 0;
651 /* free child windows */
652 if ((list = WIN_ListChildren( hwnd )))
654 int i;
655 for (i = 0; list[i]; i++)
657 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
658 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
660 HeapFree( GetProcessHeap(), 0, list );
664 * Clear the update region to make sure no WM_PAINT messages will be
665 * generated for this window while processing the WM_NCDESTROY.
667 RedrawWindow( hwnd, NULL, 0,
668 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
671 * Send the WM_NCDESTROY to the window being destroyed.
673 SendMessageA( hwnd, WM_NCDESTROY, 0, 0);
675 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
677 WINPOS_CheckInternalPos( hwnd );
678 if( hwnd == GetCapture()) ReleaseCapture();
680 /* free resources associated with the window */
682 TIMER_RemoveWindowTimers( hwnd );
684 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
686 if (!(wndPtr->dwStyle & WS_CHILD))
688 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
689 if (menu) DestroyMenu( menu );
691 if (wndPtr->hSysMenu)
693 DestroyMenu( wndPtr->hSysMenu );
694 wndPtr->hSysMenu = 0;
696 DCE_FreeWindowDCE( hwnd ); /* Always do this to catch orphaned DCs */
697 USER_Driver.pDestroyWindow( hwnd );
698 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
699 CLASS_RemoveWindow( wndPtr->class );
700 wndPtr->class = NULL;
701 wndPtr->dwMagic = 0; /* Mark it as invalid */
702 WIN_ReleaseWndPtr( wndPtr );
703 return 0;
706 /***********************************************************************
707 * WIN_DestroyThreadWindows
709 * Destroy all children of 'wnd' owned by the current thread.
710 * Return TRUE if something was done.
712 void WIN_DestroyThreadWindows( HWND hwnd )
714 HWND *list;
715 int i;
717 if (!(list = WIN_ListChildren( hwnd ))) return;
718 for (i = 0; list[i]; i++)
720 if (WIN_IsCurrentThread( list[i] ))
721 DestroyWindow( list[i] );
722 else
723 WIN_DestroyThreadWindows( list[i] );
725 HeapFree( GetProcessHeap(), 0, list );
728 /***********************************************************************
729 * WIN_CreateDesktopWindow
731 * Create the desktop window.
733 BOOL WIN_CreateDesktopWindow(void)
735 struct tagCLASS *class;
736 HWND hwndDesktop;
737 INT wndExtra;
738 DWORD clsStyle;
739 WNDPROC winproc;
740 DCE *dce;
741 CREATESTRUCTA cs;
742 RECT rect;
744 TRACE("Creating desktop window\n");
746 if (!WINPOS_CreateInternalPosAtom() ||
747 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
748 &wndExtra, &winproc, &clsStyle, &dce )))
749 return FALSE;
751 pWndDesktop = create_window_handle( 0, 0, LOWORD(DESKTOP_CLASS_ATOM),
752 sizeof(WND) + wndExtra - sizeof(pWndDesktop->wExtra) );
753 if (!pWndDesktop) return FALSE;
754 hwndDesktop = pWndDesktop->hwndSelf;
756 pWndDesktop->tid = 0; /* nobody owns the desktop */
757 pWndDesktop->parent = 0;
758 pWndDesktop->owner = 0;
759 pWndDesktop->class = class;
760 pWndDesktop->text = NULL;
761 pWndDesktop->hrgnUpdate = 0;
762 pWndDesktop->clsStyle = clsStyle;
763 pWndDesktop->dce = NULL;
764 pWndDesktop->pVScroll = NULL;
765 pWndDesktop->pHScroll = NULL;
766 pWndDesktop->helpContext = 0;
767 pWndDesktop->flags = 0;
768 pWndDesktop->hSysMenu = 0;
769 pWndDesktop->winproc = winproc;
770 pWndDesktop->cbWndExtra = wndExtra;
772 cs.lpCreateParams = NULL;
773 cs.hInstance = 0;
774 cs.hMenu = 0;
775 cs.hwndParent = 0;
776 cs.x = 0;
777 cs.y = 0;
778 cs.cx = GetSystemMetrics( SM_CXSCREEN );
779 cs.cy = GetSystemMetrics( SM_CYSCREEN );
780 cs.style = pWndDesktop->dwStyle;
781 cs.dwExStyle = pWndDesktop->dwExStyle;
782 cs.lpszName = NULL;
783 cs.lpszClass = DESKTOP_CLASS_ATOM;
785 SetRect( &rect, 0, 0, cs.cx, cs.cy );
786 WIN_SetRectangles( hwndDesktop, &rect, &rect );
788 SERVER_START_REQ( set_window_info )
790 req->handle = hwndDesktop;
791 req->flags = 0; /* don't set anything, just retrieve */
792 wine_server_call( req );
793 pWndDesktop->dwStyle = reply->old_style;
794 pWndDesktop->dwExStyle = reply->old_ex_style;
795 pWndDesktop->hInstance = (HINSTANCE)reply->old_instance;
796 pWndDesktop->userdata = (ULONG_PTR)reply->old_user_data;
797 pWndDesktop->wIDmenu = reply->old_id;
799 SERVER_END_REQ;
801 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE ))
803 WIN_ReleaseWndPtr( pWndDesktop );
804 return FALSE;
807 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
808 WIN_ReleaseWndPtr( pWndDesktop );
809 return TRUE;
813 /***********************************************************************
814 * WIN_FixCoordinates
816 * Fix the coordinates - Helper for WIN_CreateWindowEx.
817 * returns default show mode in sw.
818 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
820 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
822 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
823 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
825 if (cs->style & (WS_CHILD | WS_POPUP))
827 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
828 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
830 else /* overlapped window */
832 STARTUPINFOA info;
834 GetStartupInfoA( &info );
836 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
838 /* Never believe Microsoft's documentation... CreateWindowEx doc says
839 * that if an overlapped window is created with WS_VISIBLE style bit
840 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
841 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
842 * reveals that
844 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
845 * 2) it does not ignore the y parameter as the docs claim; instead, it
846 * uses it as second parameter to ShowWindow() unless y is either
847 * CW_USEDEFAULT or CW_USEDEFAULT16.
849 * The fact that we didn't do 2) caused bogus windows pop up when wine
850 * was running apps that were using this obscure feature. Example -
851 * calc.exe that comes with Win98 (only Win98, it's different from
852 * the one that comes with Win95 and NT)
854 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
855 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
856 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
859 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
861 if (info.dwFlags & STARTF_USESIZE)
863 cs->cx = info.dwXSize;
864 cs->cy = info.dwYSize;
866 else /* if no other hint from the app, pick 3/4 of the screen real estate */
868 RECT r;
869 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
870 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
871 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
876 else
878 /* neither x nor cx are default. Check the y values .
879 * In the trace we see Outlook and Outlook Express using
880 * cy set to CW_USEDEFAULT when opening the address book.
882 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16) {
883 RECT r;
884 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
885 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
886 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
891 /***********************************************************************
892 * dump_window_styles
894 static void dump_window_styles( DWORD style, DWORD exstyle )
896 TRACE( "style:" );
897 if(style & WS_POPUP) TRACE(" WS_POPUP");
898 if(style & WS_CHILD) TRACE(" WS_CHILD");
899 if(style & WS_MINIMIZE) TRACE(" WS_MINIMIZE");
900 if(style & WS_VISIBLE) TRACE(" WS_VISIBLE");
901 if(style & WS_DISABLED) TRACE(" WS_DISABLED");
902 if(style & WS_CLIPSIBLINGS) TRACE(" WS_CLIPSIBLINGS");
903 if(style & WS_CLIPCHILDREN) TRACE(" WS_CLIPCHILDREN");
904 if(style & WS_MAXIMIZE) TRACE(" WS_MAXIMIZE");
905 if((style & WS_CAPTION) == WS_CAPTION) TRACE(" WS_CAPTION");
906 else
908 if(style & WS_BORDER) TRACE(" WS_BORDER");
909 if(style & WS_DLGFRAME) TRACE(" WS_DLGFRAME");
911 if(style & WS_VSCROLL) TRACE(" WS_VSCROLL");
912 if(style & WS_HSCROLL) TRACE(" WS_HSCROLL");
913 if(style & WS_SYSMENU) TRACE(" WS_SYSMENU");
914 if(style & WS_THICKFRAME) TRACE(" WS_THICKFRAME");
915 if(style & WS_GROUP) TRACE(" WS_GROUP");
916 if(style & WS_TABSTOP) TRACE(" WS_TABSTOP");
917 if(style & WS_MINIMIZEBOX) TRACE(" WS_MINIMIZEBOX");
918 if(style & WS_MAXIMIZEBOX) TRACE(" WS_MAXIMIZEBOX");
920 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
921 #define DUMPED_STYLES \
922 (WS_POPUP | \
923 WS_CHILD | \
924 WS_MINIMIZE | \
925 WS_VISIBLE | \
926 WS_DISABLED | \
927 WS_CLIPSIBLINGS | \
928 WS_CLIPCHILDREN | \
929 WS_MAXIMIZE | \
930 WS_BORDER | \
931 WS_DLGFRAME | \
932 WS_VSCROLL | \
933 WS_HSCROLL | \
934 WS_SYSMENU | \
935 WS_THICKFRAME | \
936 WS_GROUP | \
937 WS_TABSTOP | \
938 WS_MINIMIZEBOX | \
939 WS_MAXIMIZEBOX)
941 if(style & ~DUMPED_STYLES) TRACE(" %08lx", style & ~DUMPED_STYLES);
942 TRACE("\n");
943 #undef DUMPED_STYLES
945 TRACE( "exstyle:" );
946 if(exstyle & WS_EX_DLGMODALFRAME) TRACE(" WS_EX_DLGMODALFRAME");
947 if(exstyle & WS_EX_DRAGDETECT) TRACE(" WS_EX_DRAGDETECT");
948 if(exstyle & WS_EX_NOPARENTNOTIFY) TRACE(" WS_EX_NOPARENTNOTIFY");
949 if(exstyle & WS_EX_TOPMOST) TRACE(" WS_EX_TOPMOST");
950 if(exstyle & WS_EX_ACCEPTFILES) TRACE(" WS_EX_ACCEPTFILES");
951 if(exstyle & WS_EX_TRANSPARENT) TRACE(" WS_EX_TRANSPARENT");
952 if(exstyle & WS_EX_MDICHILD) TRACE(" WS_EX_MDICHILD");
953 if(exstyle & WS_EX_TOOLWINDOW) TRACE(" WS_EX_TOOLWINDOW");
954 if(exstyle & WS_EX_WINDOWEDGE) TRACE(" WS_EX_WINDOWEDGE");
955 if(exstyle & WS_EX_CLIENTEDGE) TRACE(" WS_EX_CLIENTEDGE");
956 if(exstyle & WS_EX_CONTEXTHELP) TRACE(" WS_EX_CONTEXTHELP");
957 if(exstyle & WS_EX_RIGHT) TRACE(" WS_EX_RIGHT");
958 if(exstyle & WS_EX_RTLREADING) TRACE(" WS_EX_RTLREADING");
959 if(exstyle & WS_EX_LEFTSCROLLBAR) TRACE(" WS_EX_LEFTSCROLLBAR");
960 if(exstyle & WS_EX_CONTROLPARENT) TRACE(" WS_EX_CONTROLPARENT");
961 if(exstyle & WS_EX_STATICEDGE) TRACE(" WS_EX_STATICEDGE");
962 if(exstyle & WS_EX_APPWINDOW) TRACE(" WS_EX_APPWINDOW");
963 if(exstyle & WS_EX_LAYERED) TRACE(" WS_EX_LAYERED");
965 #define DUMPED_EX_STYLES \
966 (WS_EX_DLGMODALFRAME | \
967 WS_EX_DRAGDETECT | \
968 WS_EX_NOPARENTNOTIFY | \
969 WS_EX_TOPMOST | \
970 WS_EX_ACCEPTFILES | \
971 WS_EX_TRANSPARENT | \
972 WS_EX_MDICHILD | \
973 WS_EX_TOOLWINDOW | \
974 WS_EX_WINDOWEDGE | \
975 WS_EX_CLIENTEDGE | \
976 WS_EX_CONTEXTHELP | \
977 WS_EX_RIGHT | \
978 WS_EX_RTLREADING | \
979 WS_EX_LEFTSCROLLBAR | \
980 WS_EX_CONTROLPARENT | \
981 WS_EX_STATICEDGE | \
982 WS_EX_APPWINDOW | \
983 WS_EX_LAYERED)
985 if(exstyle & ~DUMPED_EX_STYLES) TRACE(" %08lx", exstyle & ~DUMPED_EX_STYLES);
986 TRACE("\n");
987 #undef DUMPED_EX_STYLES
991 /***********************************************************************
992 * WIN_CreateWindowEx
994 * Implementation of CreateWindowEx().
996 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
997 WINDOWPROCTYPE type )
999 INT sw = SW_SHOW;
1000 struct tagCLASS *classPtr;
1001 WND *wndPtr;
1002 HWND hwnd, parent, owner;
1003 INT wndExtra;
1004 DWORD clsStyle;
1005 WNDPROC winproc;
1006 DCE *dce;
1007 BOOL unicode = (type == WIN_PROC_32W);
1009 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
1010 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
1011 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszClass) : debugstr_a(cs->lpszClass),
1012 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
1013 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
1015 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
1017 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
1018 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
1020 /* Find the parent window */
1022 parent = GetDesktopWindow();
1023 owner = 0;
1025 if (cs->hwndParent == HWND_MESSAGE)
1027 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
1028 * message window (style: WS_POPUP|WS_DISABLED)
1030 FIXME("Parent is HWND_MESSAGE\n");
1032 else if (cs->hwndParent)
1034 /* Make sure parent is valid */
1035 if (!IsWindow( cs->hwndParent ))
1037 WARN("Bad parent %p\n", cs->hwndParent );
1038 return 0;
1040 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1041 parent = WIN_GetFullHandle(cs->hwndParent);
1042 else
1043 owner = GetAncestor( cs->hwndParent, GA_ROOT );
1045 else if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1047 WARN("No parent for child window\n" );
1048 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1051 /* Find the window class */
1052 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
1053 &wndExtra, &winproc, &clsStyle, &dce )))
1055 WARN("Bad class '%s'\n", cs->lpszClass );
1056 return 0;
1059 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
1061 /* Correct the window style - stage 1
1063 * These are patches that appear to affect both the style loaded into the
1064 * WIN structure and passed in the CreateStruct to the WM_CREATE etc.
1066 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1067 * why does the user get to set it?
1070 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
1071 * tested for WS_POPUP
1073 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
1074 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
1075 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
1076 cs->dwExStyle |= WS_EX_WINDOWEDGE;
1077 else
1078 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
1080 /* Create the window structure */
1082 if (!(wndPtr = create_window_handle( parent, owner, classAtom,
1083 sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
1085 TRACE("out of memory\n" );
1086 return 0;
1088 hwnd = wndPtr->hwndSelf;
1090 /* Fill the window structure */
1092 wndPtr->tid = GetCurrentThreadId();
1093 wndPtr->owner = owner;
1094 wndPtr->parent = parent;
1095 wndPtr->class = classPtr;
1096 wndPtr->winproc = winproc;
1097 wndPtr->hInstance = cs->hInstance;
1098 wndPtr->text = NULL;
1099 wndPtr->hrgnUpdate = 0;
1100 wndPtr->hrgnWnd = 0;
1101 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1102 wndPtr->dwExStyle = cs->dwExStyle;
1103 wndPtr->clsStyle = clsStyle;
1104 wndPtr->wIDmenu = 0;
1105 wndPtr->helpContext = 0;
1106 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
1107 wndPtr->pVScroll = NULL;
1108 wndPtr->pHScroll = NULL;
1109 wndPtr->userdata = 0;
1110 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU) ? MENU_GetSysMenu( hwnd, 0 ) : 0;
1111 wndPtr->cbWndExtra = wndExtra;
1113 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
1115 /* Correct the window style - stage 2 */
1117 if (!(cs->style & WS_CHILD))
1119 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1120 if (!(cs->style & WS_POPUP))
1122 wndPtr->dwStyle |= WS_CAPTION;
1123 wndPtr->flags |= WIN_NEED_SIZE;
1126 SERVER_START_REQ( set_window_info )
1128 req->handle = hwnd;
1129 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE;
1130 req->style = wndPtr->dwStyle;
1131 req->ex_style = wndPtr->dwExStyle;
1132 req->instance = (void *)wndPtr->hInstance;
1133 wine_server_call( req );
1135 SERVER_END_REQ;
1137 /* Get class or window DC if needed */
1139 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
1140 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
1141 else wndPtr->dce = NULL;
1143 /* Set the window menu */
1145 if (((wndPtr->dwStyle & (WS_CAPTION|WS_CHILD)) == WS_CAPTION) ||
1146 (wndPtr->dwExStyle & WS_EX_APPWINDOW))
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 = HMENU_32(LoadMenu16(HINSTANCE_16(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 %p\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_32(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=GetModuleHandleW(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("(%p)\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 if (GetClipboardOwner() == hwnd)
1519 CLIPBOARD_ReleaseOwner();
1521 /* Unlink now so we won't bother with the children later on */
1523 WIN_UnlinkWindow( hwnd );
1525 /* Destroy the window storage */
1527 WIN_DestroyWindow( hwnd );
1528 return TRUE;
1532 /***********************************************************************
1533 * CloseWindow (USER32.@)
1535 BOOL WINAPI CloseWindow( HWND hwnd )
1537 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1538 ShowWindow( hwnd, SW_MINIMIZE );
1539 return TRUE;
1543 /***********************************************************************
1544 * OpenIcon (USER32.@)
1546 BOOL WINAPI OpenIcon( HWND hwnd )
1548 if (!IsIconic( hwnd )) return FALSE;
1549 ShowWindow( hwnd, SW_SHOWNORMAL );
1550 return TRUE;
1554 /***********************************************************************
1555 * WIN_FindWindow
1557 * Implementation of FindWindow() and FindWindowEx().
1559 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1561 HWND *list = NULL;
1562 HWND retvalue = 0;
1563 int i = 0, len = 0;
1564 WCHAR *buffer = NULL;
1566 if (!parent) parent = GetDesktopWindow();
1567 if (title)
1569 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1570 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1573 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1575 if (child)
1577 child = WIN_GetFullHandle( child );
1578 while (list[i] && list[i] != child) i++;
1579 if (!list[i]) goto done;
1580 i++; /* start from next window */
1583 if (title)
1585 while (list[i])
1587 if (GetWindowTextW( list[i], buffer, len ) && !strcmpiW( buffer, title )) break;
1588 i++;
1591 retvalue = list[i];
1593 done:
1594 if (list) HeapFree( GetProcessHeap(), 0, list );
1595 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1596 return retvalue;
1601 /***********************************************************************
1602 * FindWindowA (USER32.@)
1604 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1606 HWND ret = FindWindowExA( 0, 0, className, title );
1607 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1608 return ret;
1612 /***********************************************************************
1613 * FindWindowExA (USER32.@)
1615 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1616 LPCSTR className, LPCSTR title )
1618 ATOM atom = 0;
1619 LPWSTR buffer;
1620 HWND hwnd;
1621 INT len;
1623 if (className)
1625 /* If the atom doesn't exist, then no class */
1626 /* with this name exists either. */
1627 if (!(atom = GlobalFindAtomA( className )))
1629 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1630 return 0;
1633 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
1635 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1636 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1637 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
1638 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1639 HeapFree( GetProcessHeap(), 0, buffer );
1640 return hwnd;
1644 /***********************************************************************
1645 * FindWindowExW (USER32.@)
1647 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1648 LPCWSTR className, LPCWSTR title )
1650 ATOM atom = 0;
1652 if (className)
1654 /* If the atom doesn't exist, then no class */
1655 /* with this name exists either. */
1656 if (!(atom = GlobalFindAtomW( className )))
1658 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1659 return 0;
1662 return WIN_FindWindow( parent, child, atom, title );
1666 /***********************************************************************
1667 * FindWindowW (USER32.@)
1669 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1671 return FindWindowExW( 0, 0, className, title );
1675 /**********************************************************************
1676 * GetDesktopWindow (USER32.@)
1678 HWND WINAPI GetDesktopWindow(void)
1680 if (pWndDesktop) return pWndDesktop->hwndSelf;
1681 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" );
1682 ExitProcess(1);
1683 return 0;
1687 /*******************************************************************
1688 * EnableWindow (USER32.@)
1690 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1692 WND *wndPtr;
1693 BOOL retvalue;
1694 LONG style;
1695 HWND full_handle;
1697 if (is_broadcast(hwnd))
1699 SetLastError( ERROR_INVALID_PARAMETER );
1700 return FALSE;
1703 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1704 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1706 hwnd = full_handle;
1708 TRACE("( %p, %d )\n", hwnd, enable);
1710 if (!(wndPtr = WIN_GetPtr( hwnd ))) return FALSE;
1711 style = wndPtr->dwStyle;
1712 retvalue = ((style & WS_DISABLED) != 0);
1713 WIN_ReleasePtr( wndPtr );
1715 if (enable && retvalue)
1717 WIN_SetStyle( hwnd, style & ~WS_DISABLED );
1718 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1720 else if (!enable && !retvalue)
1722 HWND focus_wnd, capture_wnd;
1724 SendMessageA( hwnd, WM_CANCELMODE, 0, 0);
1726 WIN_SetStyle( hwnd, style | WS_DISABLED );
1728 focus_wnd = GetFocus();
1729 if (hwnd == focus_wnd || IsChild(hwnd, focus_wnd))
1730 SetFocus( 0 ); /* A disabled window can't have the focus */
1732 capture_wnd = GetCapture();
1733 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1734 ReleaseCapture(); /* A disabled window can't capture the mouse */
1736 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1738 return retvalue;
1742 /***********************************************************************
1743 * IsWindowEnabled (USER32.@)
1745 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1747 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1751 /***********************************************************************
1752 * IsWindowUnicode (USER32.@)
1754 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1756 WND * wndPtr;
1757 BOOL retvalue;
1759 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1760 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1761 WIN_ReleaseWndPtr(wndPtr);
1762 return retvalue;
1766 /**********************************************************************
1767 * GetWindowWord (USER32.@)
1769 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1771 if (offset >= 0)
1773 WORD retvalue = 0;
1774 WND *wndPtr = WIN_GetPtr( hwnd );
1775 if (!wndPtr)
1777 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1778 return 0;
1780 if (wndPtr == WND_OTHER_PROCESS)
1782 if (IsWindow( hwnd ))
1783 FIXME( "(%d) not supported yet on other process window %p\n", offset, hwnd );
1784 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1785 return 0;
1787 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1789 WARN("Invalid offset %d\n", offset );
1790 SetLastError( ERROR_INVALID_INDEX );
1792 else retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1793 WIN_ReleasePtr( wndPtr );
1794 return retvalue;
1797 switch(offset)
1799 case GWL_HWNDPARENT:
1800 return GetWindowLongW( hwnd, offset );
1801 case GWL_ID:
1802 case GWL_HINSTANCE:
1804 LONG ret = GetWindowLongW( hwnd, offset );
1805 if (HIWORD(ret))
1806 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1807 return LOWORD(ret);
1809 default:
1810 WARN("Invalid offset %d\n", offset );
1811 return 0;
1816 /**********************************************************************
1817 * SetWindowWord (USER32.@)
1819 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1821 WORD *ptr, retval;
1822 WND * wndPtr;
1824 switch(offset)
1826 case GWL_ID:
1827 case GWL_HINSTANCE:
1828 case GWL_HWNDPARENT:
1829 return SetWindowLongW( hwnd, offset, (UINT)newval );
1830 default:
1831 if (offset < 0)
1833 WARN("Invalid offset %d\n", offset );
1834 SetLastError( ERROR_INVALID_INDEX );
1835 return 0;
1839 wndPtr = WIN_GetPtr( hwnd );
1840 if (wndPtr == WND_OTHER_PROCESS)
1842 if (IsWindow(hwnd))
1843 FIXME( "set %d <- %x not supported yet on other process window %p\n",
1844 offset, newval, hwnd );
1845 wndPtr = NULL;
1847 if (!wndPtr)
1849 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1850 return 0;
1853 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1855 WARN("Invalid offset %d\n", offset );
1856 WIN_ReleasePtr(wndPtr);
1857 SetLastError( ERROR_INVALID_INDEX );
1858 return 0;
1860 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1861 retval = *ptr;
1862 *ptr = newval;
1863 WIN_ReleasePtr(wndPtr);
1864 return retval;
1868 /**********************************************************************
1869 * WIN_GetWindowLong
1871 * Helper function for GetWindowLong().
1873 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1875 LONG retvalue = 0;
1876 WND *wndPtr;
1878 if (offset == GWL_HWNDPARENT)
1880 HWND parent = GetAncestor( hwnd, GA_PARENT );
1881 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1882 return (LONG)parent;
1885 if (!(wndPtr = WIN_GetPtr( hwnd )))
1887 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1888 return 0;
1891 if (wndPtr == WND_OTHER_PROCESS)
1893 if (offset >= 0)
1895 if (IsWindow(hwnd))
1896 FIXME( "(%d) not supported on other process window %p\n", offset, hwnd );
1897 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1898 return 0;
1900 if (offset == GWL_WNDPROC)
1902 SetLastError( ERROR_ACCESS_DENIED );
1903 return 0;
1905 SERVER_START_REQ( set_window_info )
1907 req->handle = hwnd;
1908 req->flags = 0; /* don't set anything, just retrieve */
1909 if (!wine_server_call_err( req ))
1911 switch(offset)
1913 case GWL_STYLE: retvalue = reply->old_style; break;
1914 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1915 case GWL_ID: retvalue = reply->old_id; break;
1916 case GWL_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1917 case GWL_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
1918 default:
1919 SetLastError( ERROR_INVALID_INDEX );
1920 break;
1924 SERVER_END_REQ;
1925 return retvalue;
1928 /* now we have a valid wndPtr */
1930 if (offset >= 0)
1932 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
1935 * Some programs try to access last element from 16 bit
1936 * code using illegal offset value. Hopefully this is
1937 * what those programs really expect.
1939 if (type == WIN_PROC_16 &&
1940 wndPtr->cbWndExtra >= 4 &&
1941 offset == wndPtr->cbWndExtra - sizeof(WORD))
1943 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
1945 ERR( "- replaced invalid offset %d with %d\n",
1946 offset, offset2 );
1948 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset2);
1949 WIN_ReleasePtr( wndPtr );
1950 return retvalue;
1952 WARN("Invalid offset %d\n", offset );
1953 WIN_ReleasePtr( wndPtr );
1954 SetLastError( ERROR_INVALID_INDEX );
1955 return 0;
1957 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1958 /* Special case for dialog window procedure */
1959 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1960 retvalue = (LONG)WINPROC_GetProc( (WNDPROC)retvalue, type );
1961 WIN_ReleasePtr( wndPtr );
1962 return retvalue;
1965 switch(offset)
1967 case GWL_USERDATA: retvalue = wndPtr->userdata; break;
1968 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1969 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1970 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu; break;
1971 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc, type ); break;
1972 case GWL_HINSTANCE: retvalue = (LONG)wndPtr->hInstance; break;
1973 default:
1974 WARN("Unknown offset %d\n", offset );
1975 SetLastError( ERROR_INVALID_INDEX );
1976 break;
1978 WIN_ReleasePtr(wndPtr);
1979 return retvalue;
1983 /**********************************************************************
1984 * WIN_SetWindowLong
1986 * Helper function for SetWindowLong().
1988 * 0 is the failure code. However, in the case of failure SetLastError
1989 * must be set to distinguish between a 0 return value and a failure.
1991 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1992 WINDOWPROCTYPE type )
1994 LONG retval = 0;
1995 WND *wndPtr;
1997 TRACE( "%p %d %lx %x\n", hwnd, offset, newval, type );
1999 if (is_broadcast(hwnd))
2001 SetLastError( ERROR_INVALID_PARAMETER );
2002 return FALSE;
2004 if (!WIN_IsCurrentProcess( hwnd ))
2006 if (offset == GWL_WNDPROC)
2008 SetLastError( ERROR_ACCESS_DENIED );
2009 return 0;
2011 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
2014 wndPtr = WIN_GetPtr( hwnd );
2015 if (wndPtr->hwndSelf == GetDesktopWindow())
2017 /* can't change anything on the desktop window */
2018 WIN_ReleasePtr( wndPtr );
2019 SetLastError( ERROR_ACCESS_DENIED );
2020 return 0;
2023 if (offset >= 0)
2025 LONG *ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
2026 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
2028 WARN("Invalid offset %d\n", offset );
2029 WIN_ReleasePtr( wndPtr );
2030 SetLastError( ERROR_INVALID_INDEX );
2031 return 0;
2033 /* Special case for dialog window procedure */
2034 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2036 retval = (LONG)WINPROC_GetProc( (WNDPROC)*ptr, type );
2037 WINPROC_SetProc( (WNDPROC *)ptr, (WNDPROC)newval, type, WIN_PROC_WINDOW );
2038 WIN_ReleasePtr( wndPtr );
2039 return retval;
2041 retval = *ptr;
2042 *ptr = newval;
2043 WIN_ReleasePtr( wndPtr );
2045 else
2047 STYLESTRUCT style;
2048 BOOL ok;
2050 /* first some special cases */
2051 switch( offset )
2053 case GWL_STYLE:
2054 case GWL_EXSTYLE:
2055 style.styleOld = wndPtr->dwStyle;
2056 style.styleNew = newval;
2057 WIN_ReleasePtr( wndPtr );
2058 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
2059 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
2060 newval = style.styleNew;
2061 break;
2062 case GWL_HWNDPARENT:
2063 if (wndPtr->parent == GetDesktopWindow())
2065 WIN_ReleasePtr( wndPtr );
2066 return (LONG)WIN_SetOwner( hwnd, (HWND)newval );
2068 else
2070 WIN_ReleasePtr( wndPtr );
2071 return (LONG)SetParent( hwnd, (HWND)newval );
2073 case GWL_WNDPROC:
2074 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2075 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC)newval, type, WIN_PROC_WINDOW );
2076 WIN_ReleasePtr( wndPtr );
2077 return retval;
2078 case GWL_ID:
2079 case GWL_HINSTANCE:
2080 case GWL_USERDATA:
2081 break;
2082 default:
2083 WIN_ReleasePtr( wndPtr );
2084 WARN("Invalid offset %d\n", offset );
2085 SetLastError( ERROR_INVALID_INDEX );
2086 return 0;
2089 SERVER_START_REQ( set_window_info )
2091 req->handle = hwnd;
2092 switch(offset)
2094 case GWL_STYLE:
2095 req->flags = SET_WIN_STYLE;
2096 req->style = newval;
2097 break;
2098 case GWL_EXSTYLE:
2099 req->flags = SET_WIN_EXSTYLE;
2100 req->ex_style = newval;
2101 break;
2102 case GWL_ID:
2103 req->flags = SET_WIN_ID;
2104 req->id = newval;
2105 break;
2106 case GWL_HINSTANCE:
2107 req->flags = SET_WIN_INSTANCE;
2108 req->instance = (void *)newval;
2109 break;
2110 case GWL_USERDATA:
2111 req->flags = SET_WIN_USERDATA;
2112 req->user_data = (void *)newval;
2113 break;
2115 if ((ok = !wine_server_call_err( req )))
2117 switch(offset)
2119 case GWL_STYLE:
2120 wndPtr->dwStyle = newval;
2121 retval = reply->old_style;
2122 break;
2123 case GWL_EXSTYLE:
2124 wndPtr->dwExStyle = newval;
2125 retval = reply->old_ex_style;
2126 break;
2127 case GWL_ID:
2128 wndPtr->wIDmenu = newval;
2129 retval = reply->old_id;
2130 break;
2131 case GWL_HINSTANCE:
2132 wndPtr->hInstance = (HINSTANCE)newval;
2133 retval = (ULONG_PTR)reply->old_instance;
2134 break;
2135 case GWL_USERDATA:
2136 wndPtr->userdata = newval;
2137 retval = (ULONG_PTR)reply->old_user_data;
2138 break;
2142 SERVER_END_REQ;
2143 WIN_ReleasePtr( wndPtr );
2145 if (!ok) return 0;
2147 if (offset == GWL_STYLE && USER_Driver.pSetWindowStyle)
2148 USER_Driver.pSetWindowStyle( hwnd, retval );
2150 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2151 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2154 return retval;
2158 /**********************************************************************
2159 * GetWindowLong (USER.135)
2161 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2163 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
2167 /**********************************************************************
2168 * GetWindowLongA (USER32.@)
2170 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2172 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2176 /**********************************************************************
2177 * GetWindowLongW (USER32.@)
2179 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2181 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2185 /**********************************************************************
2186 * SetWindowLong (USER.136)
2188 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2190 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
2194 /**********************************************************************
2195 * SetWindowLongA (USER32.@)
2197 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2199 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2203 /**********************************************************************
2204 * SetWindowLongW (USER32.@) Set window attribute
2206 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2207 * value in a window's extra memory.
2209 * The _hwnd_ parameter specifies the window. is the handle to a
2210 * window that has extra memory. The _newval_ parameter contains the
2211 * new attribute or extra memory value. If positive, the _offset_
2212 * parameter is the byte-addressed location in the window's extra
2213 * memory to set. If negative, _offset_ specifies the window
2214 * attribute to set, and should be one of the following values:
2216 * GWL_EXSTYLE The window's extended window style
2218 * GWL_STYLE The window's window style.
2220 * GWL_WNDPROC Pointer to the window's window procedure.
2222 * GWL_HINSTANCE The window's pplication instance handle.
2224 * GWL_ID The window's identifier.
2226 * GWL_USERDATA The window's user-specified data.
2228 * If the window is a dialog box, the _offset_ parameter can be one of
2229 * the following values:
2231 * DWL_DLGPROC The address of the window's dialog box procedure.
2233 * DWL_MSGRESULT The return value of a message
2234 * that the dialog box procedure processed.
2236 * DWL_USER Application specific information.
2238 * RETURNS
2240 * If successful, returns the previous value located at _offset_. Otherwise,
2241 * returns 0.
2243 * NOTES
2245 * Extra memory for a window class is specified by a nonzero cbWndExtra
2246 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2247 * time of class creation.
2249 * Using GWL_WNDPROC to set a new window procedure effectively creates
2250 * a window subclass. Use CallWindowProc() in the new windows procedure
2251 * to pass messages to the superclass's window procedure.
2253 * The user data is reserved for use by the application which created
2254 * the window.
2256 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2257 * instead, call the EnableWindow() function to change the window's
2258 * disabled state.
2260 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2261 * SetParent() instead.
2263 * Win95:
2264 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2265 * it sends WM_STYLECHANGING before changing the settings
2266 * and WM_STYLECHANGED afterwards.
2267 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2269 LONG WINAPI SetWindowLongW(
2270 HWND hwnd, /* [in] window to alter */
2271 INT offset, /* [in] offset, in bytes, of location to alter */
2272 LONG newval /* [in] new value of location */
2274 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2278 /*******************************************************************
2279 * GetWindowTextA (USER32.@)
2281 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2283 WCHAR *buffer;
2285 if (WIN_IsCurrentProcess( hwnd ))
2286 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2288 /* when window belongs to other process, don't send a message */
2289 if (nMaxCount <= 0) return 0;
2290 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2291 get_server_window_text( hwnd, buffer, nMaxCount );
2292 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2293 lpString[nMaxCount-1] = 0;
2294 HeapFree( GetProcessHeap(), 0, buffer );
2295 return strlen(lpString);
2299 /*******************************************************************
2300 * InternalGetWindowText (USER32.@)
2302 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2304 WND *win;
2306 if (nMaxCount <= 0) return 0;
2307 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2308 if (win != WND_OTHER_PROCESS)
2310 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2311 else lpString[0] = 0;
2312 WIN_ReleasePtr( win );
2314 else
2316 get_server_window_text( hwnd, lpString, nMaxCount );
2318 return strlenW(lpString);
2322 /*******************************************************************
2323 * GetWindowTextW (USER32.@)
2325 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2327 if (WIN_IsCurrentProcess( hwnd ))
2328 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2330 /* when window belongs to other process, don't send a message */
2331 if (nMaxCount <= 0) return 0;
2332 get_server_window_text( hwnd, lpString, nMaxCount );
2333 return strlenW(lpString);
2337 /*******************************************************************
2338 * SetWindowText (USER32.@)
2339 * SetWindowTextA (USER32.@)
2341 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2343 if (is_broadcast(hwnd))
2345 SetLastError( ERROR_INVALID_PARAMETER );
2346 return FALSE;
2348 if (!WIN_IsCurrentProcess( hwnd ))
2350 FIXME( "cannot set text %s of other process window %p\n", debugstr_a(lpString), hwnd );
2351 SetLastError( ERROR_ACCESS_DENIED );
2352 return FALSE;
2354 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2358 /*******************************************************************
2359 * SetWindowTextW (USER32.@)
2361 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2363 if (is_broadcast(hwnd))
2365 SetLastError( ERROR_INVALID_PARAMETER );
2366 return FALSE;
2368 if (!WIN_IsCurrentProcess( hwnd ))
2370 FIXME( "cannot set text %s of other process window %p\n", debugstr_w(lpString), hwnd );
2371 SetLastError( ERROR_ACCESS_DENIED );
2372 return FALSE;
2374 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2378 /*******************************************************************
2379 * GetWindowTextLengthA (USER32.@)
2381 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2383 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2386 /*******************************************************************
2387 * GetWindowTextLengthW (USER32.@)
2389 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2391 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2395 /*******************************************************************
2396 * IsWindow (USER32.@)
2398 BOOL WINAPI IsWindow( HWND hwnd )
2400 WND *ptr;
2401 BOOL ret;
2403 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2405 if (ptr != WND_OTHER_PROCESS)
2407 WIN_ReleasePtr( ptr );
2408 return TRUE;
2411 /* check other processes */
2412 SERVER_START_REQ( get_window_info )
2414 req->handle = hwnd;
2415 ret = !wine_server_call_err( req );
2417 SERVER_END_REQ;
2418 return ret;
2422 /***********************************************************************
2423 * GetWindowThreadProcessId (USER32.@)
2425 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2427 WND *ptr;
2428 DWORD tid = 0;
2430 if (!(ptr = WIN_GetPtr( hwnd )))
2432 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2433 return 0;
2436 if (ptr != WND_OTHER_PROCESS)
2438 /* got a valid window */
2439 tid = ptr->tid;
2440 if (process) *process = GetCurrentProcessId();
2441 WIN_ReleasePtr( ptr );
2442 return tid;
2445 /* check other processes */
2446 SERVER_START_REQ( get_window_info )
2448 req->handle = hwnd;
2449 if (!wine_server_call_err( req ))
2451 tid = (DWORD)reply->tid;
2452 if (process) *process = (DWORD)reply->pid;
2455 SERVER_END_REQ;
2456 return tid;
2460 /*****************************************************************
2461 * GetParent (USER32.@)
2463 HWND WINAPI GetParent( HWND hwnd )
2465 WND *wndPtr;
2466 HWND retvalue = 0;
2468 if (!(wndPtr = WIN_GetPtr( hwnd )))
2470 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2471 return 0;
2473 if (wndPtr == WND_OTHER_PROCESS)
2475 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2476 if (style & (WS_POPUP | WS_CHILD))
2478 SERVER_START_REQ( get_window_tree )
2480 req->handle = hwnd;
2481 if (!wine_server_call_err( req ))
2483 if (style & WS_POPUP) retvalue = reply->owner;
2484 else if (style & WS_CHILD) retvalue = reply->parent;
2487 SERVER_END_REQ;
2490 else
2492 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2493 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2494 WIN_ReleasePtr( wndPtr );
2496 return retvalue;
2500 /*****************************************************************
2501 * GetAncestor (USER32.@)
2503 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2505 WND *win;
2506 HWND *list, ret = 0;
2508 switch(type)
2510 case GA_PARENT:
2511 if (!(win = WIN_GetPtr( hwnd )))
2513 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2514 return 0;
2516 if (win != WND_OTHER_PROCESS)
2518 ret = win->parent;
2519 WIN_ReleasePtr( win );
2521 else /* need to query the server */
2523 SERVER_START_REQ( get_window_tree )
2525 req->handle = hwnd;
2526 if (!wine_server_call_err( req )) ret = reply->parent;
2528 SERVER_END_REQ;
2530 break;
2532 case GA_ROOT:
2533 if (!(list = WIN_ListParents( hwnd ))) return 0;
2535 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2536 else
2538 int count = 2;
2539 while (list[count]) count++;
2540 ret = list[count - 2]; /* get the one before the desktop */
2542 HeapFree( GetProcessHeap(), 0, list );
2543 break;
2545 case GA_ROOTOWNER:
2546 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2547 for (;;)
2549 HWND parent = GetParent( ret );
2550 if (!parent) break;
2551 ret = parent;
2553 break;
2555 return ret;
2559 /*****************************************************************
2560 * SetParent (USER32.@)
2562 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2564 WND *wndPtr;
2565 HWND retvalue, full_handle;
2566 BOOL was_visible;
2568 if (is_broadcast(hwnd) || is_broadcast(parent))
2570 SetLastError(ERROR_INVALID_PARAMETER);
2571 return 0;
2574 if (!parent) parent = GetDesktopWindow();
2575 else parent = WIN_GetFullHandle( parent );
2577 if (!IsWindow( parent ))
2579 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2580 return 0;
2583 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2584 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2586 hwnd = full_handle;
2588 if (USER_Driver.pSetParent)
2589 return USER_Driver.pSetParent( hwnd, parent );
2591 /* Windows hides the window first, then shows it again
2592 * including the WM_SHOWWINDOW messages and all */
2593 was_visible = ShowWindow( hwnd, SW_HIDE );
2595 if (!IsWindow( parent )) return 0;
2596 if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return 0;
2598 retvalue = wndPtr->parent; /* old parent */
2599 if (parent != retvalue)
2601 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2603 if (parent != GetDesktopWindow()) /* a child window */
2605 if (!(wndPtr->dwStyle & WS_CHILD))
2607 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
2608 if (menu) DestroyMenu( menu );
2612 WIN_ReleasePtr( wndPtr );
2614 /* SetParent additionally needs to make hwnd the topmost window
2615 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2616 WM_WINDOWPOSCHANGED notification messages.
2618 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2619 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2620 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2621 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2622 return retvalue;
2626 /*******************************************************************
2627 * IsChild (USER32.@)
2629 BOOL WINAPI IsChild( HWND parent, HWND child )
2631 HWND *list = WIN_ListParents( child );
2632 int i;
2633 BOOL ret;
2635 if (!list) return FALSE;
2636 parent = WIN_GetFullHandle( parent );
2637 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2638 ret = (list[i] != 0);
2639 HeapFree( GetProcessHeap(), 0, list );
2640 return ret;
2644 /***********************************************************************
2645 * IsWindowVisible (USER32.@)
2647 BOOL WINAPI IsWindowVisible( HWND hwnd )
2649 HWND *list;
2650 BOOL retval;
2651 int i;
2653 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2654 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2655 for (i = 0; list[i]; i++)
2656 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2657 retval = !list[i];
2658 HeapFree( GetProcessHeap(), 0, list );
2659 return retval;
2663 /***********************************************************************
2664 * WIN_IsWindowDrawable
2666 * hwnd is drawable when it is visible, all parents are not
2667 * minimized, and it is itself not minimized unless we are
2668 * trying to draw its default class icon.
2670 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2672 HWND *list;
2673 BOOL retval;
2674 int i;
2675 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2677 if (!(style & WS_VISIBLE)) return FALSE;
2678 if ((style & WS_MINIMIZE) && icon && GetClassLongA( hwnd, GCL_HICON )) return FALSE;
2680 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2681 for (i = 0; list[i]; i++)
2682 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2683 break;
2684 retval = !list[i];
2685 HeapFree( GetProcessHeap(), 0, list );
2686 return retval;
2690 /*******************************************************************
2691 * GetTopWindow (USER32.@)
2693 HWND WINAPI GetTopWindow( HWND hwnd )
2695 if (!hwnd) hwnd = GetDesktopWindow();
2696 return GetWindow( hwnd, GW_CHILD );
2700 /*******************************************************************
2701 * GetWindow (USER32.@)
2703 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2705 HWND retval = 0;
2707 if (rel == GW_OWNER) /* this one may be available locally */
2709 WND *wndPtr = WIN_GetPtr( hwnd );
2710 if (!wndPtr)
2712 SetLastError( ERROR_INVALID_HANDLE );
2713 return 0;
2715 if (wndPtr != WND_OTHER_PROCESS)
2717 retval = wndPtr->owner;
2718 WIN_ReleasePtr( wndPtr );
2719 return retval;
2721 /* else fall through to server call */
2724 SERVER_START_REQ( get_window_tree )
2726 req->handle = hwnd;
2727 if (!wine_server_call_err( req ))
2729 switch(rel)
2731 case GW_HWNDFIRST:
2732 retval = reply->first_sibling;
2733 break;
2734 case GW_HWNDLAST:
2735 retval = reply->last_sibling;
2736 break;
2737 case GW_HWNDNEXT:
2738 retval = reply->next_sibling;
2739 break;
2740 case GW_HWNDPREV:
2741 retval = reply->prev_sibling;
2742 break;
2743 case GW_OWNER:
2744 retval = reply->owner;
2745 break;
2746 case GW_CHILD:
2747 retval = reply->first_child;
2748 break;
2752 SERVER_END_REQ;
2753 return retval;
2757 /***********************************************************************
2758 * WIN_InternalShowOwnedPopups
2760 * Internal version of ShowOwnedPopups; Wine functions should use this
2761 * to avoid interfering with application calls to ShowOwnedPopups
2762 * and to make sure the application can't prevent showing/hiding.
2764 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2768 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2770 int count = 0;
2771 WND *pWnd;
2772 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2774 if (!win_array) return TRUE;
2777 * Show windows Lowest first, Highest last to preserve Z-Order
2779 while (win_array[count]) count++;
2780 while (--count >= 0)
2782 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2783 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2785 if (pWnd->dwStyle & WS_POPUP)
2787 if (fShow)
2789 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2790 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
2793 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2795 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2796 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2799 else
2801 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2802 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2803 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2806 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2808 ShowWindow(pWnd->hwndSelf,SW_HIDE);
2809 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2810 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
2814 WIN_ReleaseWndPtr( pWnd );
2816 HeapFree( GetProcessHeap(), 0, win_array );
2818 return TRUE;
2821 /*******************************************************************
2822 * ShowOwnedPopups (USER32.@)
2824 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2826 int count = 0;
2827 WND *pWnd;
2828 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2830 if (!win_array) return TRUE;
2832 while (win_array[count]) count++;
2833 while (--count >= 0)
2835 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2836 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2838 if (pWnd->dwStyle & WS_POPUP)
2840 if (fShow)
2842 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2844 /* In Windows, ShowOwnedPopups(TRUE) generates
2845 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2846 * regardless of the state of the owner
2848 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2849 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2852 else
2854 if (IsWindowVisible(pWnd->hwndSelf))
2856 /* In Windows, ShowOwnedPopups(FALSE) generates
2857 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2858 * regardless of the state of the owner
2860 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2861 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2865 WIN_ReleaseWndPtr( pWnd );
2867 HeapFree( GetProcessHeap(), 0, win_array );
2868 return TRUE;
2872 /*******************************************************************
2873 * GetLastActivePopup (USER32.@)
2875 HWND WINAPI GetLastActivePopup( HWND hwnd )
2877 HWND retval = hwnd;
2879 SERVER_START_REQ( get_window_info )
2881 req->handle = hwnd;
2882 if (!wine_server_call_err( req )) retval = reply->last_active;
2884 SERVER_END_REQ;
2885 return retval;
2889 /*******************************************************************
2890 * WIN_ListParents
2892 * Build an array of all parents of a given window, starting with
2893 * the immediate parent. The array must be freed with HeapFree.
2894 * Returns NULL if window is a top-level window.
2896 HWND *WIN_ListParents( HWND hwnd )
2898 WND *win;
2899 HWND current, *list;
2900 int pos = 0, size = 16, count = 0;
2902 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2904 current = hwnd;
2905 for (;;)
2907 if (!(win = WIN_GetPtr( current ))) goto empty;
2908 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
2909 list[pos] = win->parent;
2910 WIN_ReleasePtr( win );
2911 if (!(current = list[pos]))
2913 if (!pos) goto empty;
2914 return list;
2916 if (++pos == size - 1)
2918 /* need to grow the list */
2919 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
2920 if (!new_list) goto empty;
2921 list = new_list;
2922 size += 16;
2926 /* at least one parent belongs to another process, have to query the server */
2928 for (;;)
2930 count = 0;
2931 SERVER_START_REQ( get_window_parents )
2933 req->handle = hwnd;
2934 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
2935 if (!wine_server_call( req )) count = reply->count;
2937 SERVER_END_REQ;
2938 if (!count) goto empty;
2939 if (size > count)
2941 list[count] = 0;
2942 return list;
2944 HeapFree( GetProcessHeap(), 0, list );
2945 size = count + 1;
2946 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2949 empty:
2950 HeapFree( GetProcessHeap(), 0, list );
2951 return NULL;
2955 /*******************************************************************
2956 * WIN_ListChildren
2958 * Build an array of the children of a given window. The array must be
2959 * freed with HeapFree. Returns NULL when no windows are found.
2961 HWND *WIN_ListChildren( HWND hwnd )
2963 return list_window_children( hwnd, 0, 0 );
2967 /*******************************************************************
2968 * EnumWindows (USER32.@)
2970 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2972 HWND *list;
2973 BOOL ret = TRUE;
2974 int i, iWndsLocks;
2976 /* We have to build a list of all windows first, to avoid */
2977 /* unpleasant side-effects, for instance if the callback */
2978 /* function changes the Z-order of the windows. */
2980 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2982 /* Now call the callback function for every window */
2984 iWndsLocks = WIN_SuspendWndsLock();
2985 for (i = 0; list[i]; i++)
2987 /* Make sure that the window still exists */
2988 if (!IsWindow( list[i] )) continue;
2989 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2991 WIN_RestoreWndsLock(iWndsLocks);
2992 HeapFree( GetProcessHeap(), 0, list );
2993 return ret;
2997 /**********************************************************************
2998 * EnumThreadWindows (USER32.@)
3000 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
3002 HWND *list;
3003 int i, iWndsLocks;
3005 if (!(list = list_window_children( GetDesktopWindow(), 0, id ))) return TRUE;
3007 /* Now call the callback function for every window */
3009 iWndsLocks = WIN_SuspendWndsLock();
3010 for (i = 0; list[i]; i++)
3011 if (!func( list[i], lParam )) break;
3012 WIN_RestoreWndsLock(iWndsLocks);
3013 HeapFree( GetProcessHeap(), 0, list );
3014 return TRUE;
3018 /**********************************************************************
3019 * WIN_EnumChildWindows
3021 * Helper function for EnumChildWindows().
3023 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
3025 HWND *childList;
3026 BOOL ret = FALSE;
3028 for ( ; *list; list++)
3030 /* Make sure that the window still exists */
3031 if (!IsWindow( *list )) continue;
3032 /* skip owned windows */
3033 if (GetWindow( *list, GW_OWNER )) continue;
3034 /* Build children list first */
3035 childList = WIN_ListChildren( *list );
3037 ret = func( *list, lParam );
3039 if (childList)
3041 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
3042 HeapFree( GetProcessHeap(), 0, childList );
3044 if (!ret) return FALSE;
3046 return TRUE;
3050 /**********************************************************************
3051 * EnumChildWindows (USER32.@)
3053 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
3055 HWND *list;
3056 int iWndsLocks;
3058 if (!(list = WIN_ListChildren( parent ))) return FALSE;
3059 iWndsLocks = WIN_SuspendWndsLock();
3060 WIN_EnumChildWindows( list, func, lParam );
3061 WIN_RestoreWndsLock(iWndsLocks);
3062 HeapFree( GetProcessHeap(), 0, list );
3063 return TRUE;
3067 /*******************************************************************
3068 * AnyPopup (USER.52)
3070 BOOL16 WINAPI AnyPopup16(void)
3072 return AnyPopup();
3076 /*******************************************************************
3077 * AnyPopup (USER32.@)
3079 BOOL WINAPI AnyPopup(void)
3081 int i;
3082 BOOL retvalue;
3083 HWND *list = WIN_ListChildren( GetDesktopWindow() );
3085 if (!list) return FALSE;
3086 for (i = 0; list[i]; i++)
3088 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
3090 retvalue = (list[i] != 0);
3091 HeapFree( GetProcessHeap(), 0, list );
3092 return retvalue;
3096 /*******************************************************************
3097 * FlashWindow (USER32.@)
3099 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3101 WND *wndPtr = WIN_FindWndPtr(hWnd);
3103 TRACE("%p\n", hWnd);
3105 if (!wndPtr) return FALSE;
3106 hWnd = wndPtr->hwndSelf; /* make it a full handle */
3108 if (wndPtr->dwStyle & WS_MINIMIZE)
3110 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3112 HDC hDC = GetDC(hWnd);
3114 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM)hDC, 0 ))
3115 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
3117 ReleaseDC( hWnd, hDC );
3118 wndPtr->flags |= WIN_NCACTIVATED;
3120 else
3122 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3123 wndPtr->flags &= ~WIN_NCACTIVATED;
3125 WIN_ReleaseWndPtr(wndPtr);
3126 return TRUE;
3128 else
3130 WPARAM16 wparam;
3131 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3132 else wparam = (hWnd == GetForegroundWindow());
3134 WIN_ReleaseWndPtr(wndPtr);
3135 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3136 return wparam;
3141 /*******************************************************************
3142 * GetWindowContextHelpId (USER32.@)
3144 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3146 DWORD retval;
3147 WND *wnd = WIN_FindWndPtr( hwnd );
3148 if (!wnd) return 0;
3149 retval = wnd->helpContext;
3150 WIN_ReleaseWndPtr(wnd);
3151 return retval;
3155 /*******************************************************************
3156 * SetWindowContextHelpId (USER32.@)
3158 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3160 WND *wnd = WIN_FindWndPtr( hwnd );
3161 if (!wnd) return FALSE;
3162 wnd->helpContext = id;
3163 WIN_ReleaseWndPtr(wnd);
3164 return TRUE;
3168 /*******************************************************************
3169 * DragDetect (USER32.@)
3171 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3173 MSG msg;
3174 RECT rect;
3176 rect.left = pt.x - wDragWidth;
3177 rect.right = pt.x + wDragWidth;
3179 rect.top = pt.y - wDragHeight;
3180 rect.bottom = pt.y + wDragHeight;
3182 SetCapture(hWnd);
3184 while(1)
3186 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3188 if( msg.message == WM_LBUTTONUP )
3190 ReleaseCapture();
3191 return 0;
3193 if( msg.message == WM_MOUSEMOVE )
3195 POINT tmp;
3196 tmp.x = LOWORD(msg.lParam);
3197 tmp.y = HIWORD(msg.lParam);
3198 if( !PtInRect( &rect, tmp ))
3200 ReleaseCapture();
3201 return 1;
3205 WaitMessage();
3207 return 0;
3210 /******************************************************************************
3211 * GetWindowModuleFileNameA (USER32.@)
3213 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3215 FIXME("GetWindowModuleFileNameA(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3216 hwnd, lpszFileName, cchFileNameMax);
3217 return 0;
3220 /******************************************************************************
3221 * GetWindowModuleFileNameW (USER32.@)
3223 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3225 FIXME("GetWindowModuleFileNameW(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3226 hwnd, lpszFileName, cchFileNameMax);
3227 return 0;
3230 /******************************************************************************
3231 * GetWindowInfo (USER32.@)
3232 * hwnd: in
3233 * pwi: out.
3234 * MS Documentation mentions that pwi->cbSize must be set to SIZEOF(WINDOWINFO)
3235 * this may be because this structure changed over time. If this is the
3236 * the case, then please: FIXME.
3237 * Using the structure described in MSDN for 98/ME/NT(4.0 SP3)/2000/XP.
3239 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3241 WND *wndInfo = NULL;
3242 if (!pwi) return FALSE;
3243 if (pwi->cbSize != sizeof(WINDOWINFO))
3245 FIXME("windowinfo->cbSize != sizeof(WINDOWINFO). Please report\n");
3246 return FALSE;
3248 wndInfo = WIN_GetPtr(hwnd);
3249 if (!wndInfo) return FALSE;
3250 if (wndInfo == WND_OTHER_PROCESS)
3252 FIXME("window belong to other process\n");
3253 return FALSE;
3256 pwi->rcWindow = wndInfo->rectWindow;
3257 pwi->rcClient = wndInfo->rectClient;
3258 pwi->dwStyle = wndInfo->dwStyle;
3259 pwi->dwExStyle = wndInfo->dwExStyle;
3260 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3261 /* if active WS_ACTIVECAPTION, else 0 */
3263 pwi->cxWindowBorders = ((wndInfo->dwStyle & WS_BORDER) ?
3264 GetSystemMetrics(SM_CXBORDER) : 0);
3265 pwi->cyWindowBorders = ((wndInfo->dwStyle & WS_BORDER) ?
3266 GetSystemMetrics(SM_CYBORDER) : 0);
3267 /* above two: I'm presuming that borders widths are the same
3268 * for each window - so long as its actually using a border.. */
3270 pwi->atomWindowType = GetClassLongA( hwnd, GCW_ATOM );
3271 pwi->wCreatorVersion = GetVersion();
3272 /* Docs say this should be the version that
3273 * CREATED the window. But eh?.. Isn't that just the
3274 * version we are running.. Unless ofcourse its some wacky
3275 * RPC stuff or something */
3277 WIN_ReleasePtr(wndInfo);
3278 return TRUE;