Moved a couple of definitions from include/wine/obj_oleaut.h to
[wine/multimedia.git] / windows / win.c
blobbefcd168c6cbaa2ca11079f92f6c10cd4f030614
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 (%d,%d)-(%d,%d) client (%d,%d)-(%d,%d)\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) DPRINTF(" WS_POPUP");
898 if(style & WS_CHILD) DPRINTF(" WS_CHILD");
899 if(style & WS_MINIMIZE) DPRINTF(" WS_MINIMIZE");
900 if(style & WS_VISIBLE) DPRINTF(" WS_VISIBLE");
901 if(style & WS_DISABLED) DPRINTF(" WS_DISABLED");
902 if(style & WS_CLIPSIBLINGS) DPRINTF(" WS_CLIPSIBLINGS");
903 if(style & WS_CLIPCHILDREN) DPRINTF(" WS_CLIPCHILDREN");
904 if(style & WS_MAXIMIZE) DPRINTF(" WS_MAXIMIZE");
905 if((style & WS_CAPTION) == WS_CAPTION) DPRINTF(" WS_CAPTION");
906 else
908 if(style & WS_BORDER) DPRINTF(" WS_BORDER");
909 if(style & WS_DLGFRAME) DPRINTF(" WS_DLGFRAME");
911 if(style & WS_VSCROLL) DPRINTF(" WS_VSCROLL");
912 if(style & WS_HSCROLL) DPRINTF(" WS_HSCROLL");
913 if(style & WS_SYSMENU) DPRINTF(" WS_SYSMENU");
914 if(style & WS_THICKFRAME) DPRINTF(" WS_THICKFRAME");
915 if(style & WS_GROUP) DPRINTF(" WS_GROUP");
916 if(style & WS_TABSTOP) DPRINTF(" WS_TABSTOP");
917 if(style & WS_MINIMIZEBOX) DPRINTF(" WS_MINIMIZEBOX");
918 if(style & WS_MAXIMIZEBOX) DPRINTF(" 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) DPRINTF(" %08lx", style & ~DUMPED_STYLES);
942 DPRINTF("\n");
943 #undef DUMPED_STYLES
945 TRACE( "exstyle:" );
946 if(exstyle & WS_EX_DLGMODALFRAME) DPRINTF(" WS_EX_DLGMODALFRAME");
947 if(exstyle & WS_EX_DRAGDETECT) DPRINTF(" WS_EX_DRAGDETECT");
948 if(exstyle & WS_EX_NOPARENTNOTIFY) DPRINTF(" WS_EX_NOPARENTNOTIFY");
949 if(exstyle & WS_EX_TOPMOST) DPRINTF(" WS_EX_TOPMOST");
950 if(exstyle & WS_EX_ACCEPTFILES) DPRINTF(" WS_EX_ACCEPTFILES");
951 if(exstyle & WS_EX_TRANSPARENT) DPRINTF(" WS_EX_TRANSPARENT");
952 if(exstyle & WS_EX_MDICHILD) DPRINTF(" WS_EX_MDICHILD");
953 if(exstyle & WS_EX_TOOLWINDOW) DPRINTF(" WS_EX_TOOLWINDOW");
954 if(exstyle & WS_EX_WINDOWEDGE) DPRINTF(" WS_EX_WINDOWEDGE");
955 if(exstyle & WS_EX_CLIENTEDGE) DPRINTF(" WS_EX_CLIENTEDGE");
956 if(exstyle & WS_EX_CONTEXTHELP) DPRINTF(" WS_EX_CONTEXTHELP");
957 if(exstyle & WS_EX_RIGHT) DPRINTF(" WS_EX_RIGHT");
958 if(exstyle & WS_EX_RTLREADING) DPRINTF(" WS_EX_RTLREADING");
959 if(exstyle & WS_EX_LEFTSCROLLBAR) DPRINTF(" WS_EX_LEFTSCROLLBAR");
960 if(exstyle & WS_EX_CONTROLPARENT) DPRINTF(" WS_EX_CONTROLPARENT");
961 if(exstyle & WS_EX_STATICEDGE) DPRINTF(" WS_EX_STATICEDGE");
962 if(exstyle & WS_EX_APPWINDOW) DPRINTF(" WS_EX_APPWINDOW");
963 if(exstyle & WS_EX_LAYERED) DPRINTF(" 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) DPRINTF(" %08lx", exstyle & ~DUMPED_EX_STYLES);
986 DPRINTF("\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 )
1147 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
1148 else
1150 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
1151 if (menuName)
1153 if (HIWORD(cs->hInstance))
1154 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1155 else
1156 cs->hMenu = HMENU_32(LoadMenu16(HINSTANCE_16(cs->hInstance),menuName));
1158 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
1162 else SetWindowLongW( hwnd, GWL_ID, (UINT)cs->hMenu );
1163 WIN_ReleaseWndPtr( wndPtr );
1165 if (!USER_Driver.pCreateWindow( hwnd, cs, unicode))
1167 WIN_DestroyWindow( hwnd );
1168 return 0;
1171 /* Notify the parent window only */
1173 send_parent_notify( hwnd, WM_CREATE );
1174 if (!IsWindow( hwnd )) return 0;
1176 if (cs->style & WS_VISIBLE)
1178 /* in case WS_VISIBLE got set in the meantime */
1179 if (!(wndPtr = WIN_GetPtr( hwnd ))) return 0;
1180 WIN_SetStyle( hwnd, wndPtr->dwStyle & ~WS_VISIBLE );
1181 WIN_ReleasePtr( wndPtr );
1182 ShowWindow( hwnd, sw );
1185 /* Call WH_SHELL hook */
1187 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1188 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1190 TRACE("created window %p\n", hwnd);
1191 return hwnd;
1195 /***********************************************************************
1196 * CreateWindow (USER.41)
1198 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1199 DWORD style, INT16 x, INT16 y, INT16 width,
1200 INT16 height, HWND16 parent, HMENU16 menu,
1201 HINSTANCE16 instance, LPVOID data )
1203 return CreateWindowEx16( 0, className, windowName, style,
1204 x, y, width, height, parent, menu, instance, data );
1208 /***********************************************************************
1209 * CreateWindowEx (USER.452)
1211 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1212 LPCSTR windowName, DWORD style, INT16 x,
1213 INT16 y, INT16 width, INT16 height,
1214 HWND16 parent, HMENU16 menu,
1215 HINSTANCE16 instance, LPVOID data )
1217 ATOM classAtom;
1218 CREATESTRUCTA cs;
1219 char buffer[256];
1221 /* Find the class atom */
1223 if (HIWORD(className))
1225 if (!(classAtom = GlobalFindAtomA( className )))
1227 ERR( "bad class name %s\n", debugstr_a(className) );
1228 return 0;
1231 else
1233 classAtom = LOWORD(className);
1234 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1236 ERR( "bad atom %x\n", classAtom);
1237 return 0;
1239 className = buffer;
1242 /* Fix the coordinates */
1244 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1245 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1246 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1247 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1249 /* Create the window */
1251 cs.lpCreateParams = data;
1252 cs.hInstance = HINSTANCE_32(instance);
1253 cs.hMenu = HMENU_32(menu);
1254 cs.hwndParent = WIN_Handle32( parent );
1255 cs.style = style;
1256 cs.lpszName = windowName;
1257 cs.lpszClass = className;
1258 cs.dwExStyle = exStyle;
1260 return HWND_16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
1264 /***********************************************************************
1265 * CreateWindowExA (USER32.@)
1267 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1268 LPCSTR windowName, DWORD style, INT x,
1269 INT y, INT width, INT height,
1270 HWND parent, HMENU menu,
1271 HINSTANCE instance, LPVOID data )
1273 ATOM classAtom;
1274 CREATESTRUCTA cs;
1275 char buffer[256];
1277 if(!instance)
1278 instance=GetModuleHandleA(NULL);
1280 if(exStyle & WS_EX_MDICHILD)
1281 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1283 /* Find the class atom */
1285 if (HIWORD(className))
1287 if (!(classAtom = GlobalFindAtomA( className )))
1289 ERR( "bad class name %s\n", debugstr_a(className) );
1290 return 0;
1293 else
1295 classAtom = LOWORD(className);
1296 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1298 ERR( "bad atom %x\n", classAtom);
1299 return 0;
1301 className = buffer;
1304 /* Create the window */
1306 cs.lpCreateParams = data;
1307 cs.hInstance = instance;
1308 cs.hMenu = menu;
1309 cs.hwndParent = parent;
1310 cs.x = x;
1311 cs.y = y;
1312 cs.cx = width;
1313 cs.cy = height;
1314 cs.style = style;
1315 cs.lpszName = windowName;
1316 cs.lpszClass = className;
1317 cs.dwExStyle = exStyle;
1319 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1323 /***********************************************************************
1324 * CreateWindowExW (USER32.@)
1326 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1327 LPCWSTR windowName, DWORD style, INT x,
1328 INT y, INT width, INT height,
1329 HWND parent, HMENU menu,
1330 HINSTANCE instance, LPVOID data )
1332 ATOM classAtom;
1333 CREATESTRUCTW cs;
1334 WCHAR buffer[256];
1336 if(!instance)
1337 instance=GetModuleHandleW(NULL);
1339 if(exStyle & WS_EX_MDICHILD)
1340 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1342 /* Find the class atom */
1344 if (HIWORD(className))
1346 if (!(classAtom = GlobalFindAtomW( className )))
1348 ERR( "bad class name %s\n", debugstr_w(className) );
1349 return 0;
1352 else
1354 classAtom = LOWORD(className);
1355 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1357 ERR( "bad atom %x\n", classAtom);
1358 return 0;
1360 className = buffer;
1363 /* Create the window */
1365 cs.lpCreateParams = data;
1366 cs.hInstance = instance;
1367 cs.hMenu = menu;
1368 cs.hwndParent = parent;
1369 cs.x = x;
1370 cs.y = y;
1371 cs.cx = width;
1372 cs.cy = height;
1373 cs.style = style;
1374 cs.lpszName = windowName;
1375 cs.lpszClass = className;
1376 cs.dwExStyle = exStyle;
1378 /* Note: we rely on the fact that CREATESTRUCTA and */
1379 /* CREATESTRUCTW have the same layout. */
1380 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1384 /***********************************************************************
1385 * WIN_SendDestroyMsg
1387 static void WIN_SendDestroyMsg( HWND hwnd )
1389 GUITHREADINFO info;
1391 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1393 if (hwnd == info.hwndCaret) DestroyCaret();
1395 if (USER_Driver.pResetSelectionOwner)
1396 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1399 * Send the WM_DESTROY to the window.
1401 SendMessageA( hwnd, WM_DESTROY, 0, 0);
1404 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1405 * make sure that the window still exists when we come back.
1407 if (IsWindow(hwnd))
1409 HWND* pWndArray;
1410 int i;
1412 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1414 /* start from the end (FIXME: is this needed?) */
1415 for (i = 0; pWndArray[i]; i++) ;
1417 while (--i >= 0)
1419 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1421 HeapFree( GetProcessHeap(), 0, pWndArray );
1423 else
1424 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1428 /***********************************************************************
1429 * DestroyWindow (USER32.@)
1431 BOOL WINAPI DestroyWindow( HWND hwnd )
1433 BOOL is_child;
1434 HWND h;
1436 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1438 SetLastError( ERROR_ACCESS_DENIED );
1439 return FALSE;
1442 TRACE("(%p)\n", hwnd);
1444 /* Look whether the focus is within the tree of windows we will
1445 * be destroying.
1447 h = GetFocus();
1448 if (h == hwnd || IsChild( hwnd, h ))
1450 HWND parent = GetAncestor( hwnd, GA_PARENT );
1451 if (parent == GetDesktopWindow()) parent = 0;
1452 SetFocus( parent );
1455 /* Call hooks */
1457 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1459 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1461 if (is_child)
1463 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1464 send_parent_notify( hwnd, WM_DESTROY );
1466 else if (!GetWindow( hwnd, GW_OWNER ))
1468 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1469 /* FIXME: clean up palette - see "Internals" p.352 */
1472 if (!IsWindow(hwnd)) return TRUE;
1474 if (USER_Driver.pResetSelectionOwner)
1475 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1477 /* Hide the window */
1479 if (!ShowWindow( hwnd, SW_HIDE ))
1481 if (hwnd == GetActiveWindow()) WINPOS_ActivateOtherWindow( hwnd );
1483 if (!IsWindow(hwnd)) return TRUE;
1485 /* Recursively destroy owned windows */
1487 if (!is_child)
1489 for (;;)
1491 int i, got_one = 0;
1492 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1493 if (list)
1495 for (i = 0; list[i]; i++)
1497 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1498 if (WIN_IsCurrentThread( list[i] ))
1500 DestroyWindow( list[i] );
1501 got_one = 1;
1502 continue;
1504 WIN_SetOwner( list[i], 0 );
1506 HeapFree( GetProcessHeap(), 0, list );
1508 if (!got_one) break;
1512 /* Send destroy messages */
1514 WIN_SendDestroyMsg( hwnd );
1515 if (!IsWindow( hwnd )) return TRUE;
1517 /* Unlink now so we won't bother with the children later on */
1519 WIN_UnlinkWindow( hwnd );
1521 /* Destroy the window storage */
1523 WIN_DestroyWindow( hwnd );
1524 return TRUE;
1528 /***********************************************************************
1529 * CloseWindow (USER32.@)
1531 BOOL WINAPI CloseWindow( HWND hwnd )
1533 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1534 ShowWindow( hwnd, SW_MINIMIZE );
1535 return TRUE;
1539 /***********************************************************************
1540 * OpenIcon (USER32.@)
1542 BOOL WINAPI OpenIcon( HWND hwnd )
1544 if (!IsIconic( hwnd )) return FALSE;
1545 ShowWindow( hwnd, SW_SHOWNORMAL );
1546 return TRUE;
1550 /***********************************************************************
1551 * WIN_FindWindow
1553 * Implementation of FindWindow() and FindWindowEx().
1555 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1557 HWND *list = NULL;
1558 HWND retvalue = 0;
1559 int i = 0, len = 0;
1560 WCHAR *buffer = NULL;
1562 if (!parent) parent = GetDesktopWindow();
1563 if (title)
1565 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1566 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1569 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1571 if (child)
1573 child = WIN_GetFullHandle( child );
1574 while (list[i] && list[i] != child) i++;
1575 if (!list[i]) goto done;
1576 i++; /* start from next window */
1579 if (title)
1581 while (list[i])
1583 if (GetWindowTextW( list[i], buffer, len ) && !strcmpiW( buffer, title )) break;
1584 i++;
1587 retvalue = list[i];
1589 done:
1590 if (list) HeapFree( GetProcessHeap(), 0, list );
1591 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1592 return retvalue;
1597 /***********************************************************************
1598 * FindWindowA (USER32.@)
1600 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1602 HWND ret = FindWindowExA( 0, 0, className, title );
1603 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1604 return ret;
1608 /***********************************************************************
1609 * FindWindowExA (USER32.@)
1611 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1612 LPCSTR className, LPCSTR title )
1614 ATOM atom = 0;
1615 LPWSTR buffer;
1616 HWND hwnd;
1617 INT len;
1619 if (className)
1621 /* If the atom doesn't exist, then no class */
1622 /* with this name exists either. */
1623 if (!(atom = GlobalFindAtomA( className )))
1625 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1626 return 0;
1629 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
1631 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1632 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1633 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
1634 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1635 HeapFree( GetProcessHeap(), 0, buffer );
1636 return hwnd;
1640 /***********************************************************************
1641 * FindWindowExW (USER32.@)
1643 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1644 LPCWSTR className, LPCWSTR title )
1646 ATOM atom = 0;
1648 if (className)
1650 /* If the atom doesn't exist, then no class */
1651 /* with this name exists either. */
1652 if (!(atom = GlobalFindAtomW( className )))
1654 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1655 return 0;
1658 return WIN_FindWindow( parent, child, atom, title );
1662 /***********************************************************************
1663 * FindWindowW (USER32.@)
1665 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1667 return FindWindowExW( 0, 0, className, title );
1671 /**********************************************************************
1672 * GetDesktopWindow (USER32.@)
1674 HWND WINAPI GetDesktopWindow(void)
1676 if (pWndDesktop) return pWndDesktop->hwndSelf;
1677 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" );
1678 ExitProcess(1);
1679 return 0;
1683 /*******************************************************************
1684 * EnableWindow (USER32.@)
1686 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1688 WND *wndPtr;
1689 BOOL retvalue;
1690 LONG style;
1691 HWND full_handle;
1693 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1694 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1696 hwnd = full_handle;
1698 TRACE("( %p, %d )\n", hwnd, enable);
1700 if (!(wndPtr = WIN_GetPtr( hwnd ))) return FALSE;
1701 style = wndPtr->dwStyle;
1702 retvalue = ((style & WS_DISABLED) != 0);
1703 WIN_ReleasePtr( wndPtr );
1705 if (enable && retvalue)
1707 WIN_SetStyle( hwnd, style & ~WS_DISABLED );
1708 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1710 else if (!enable && !retvalue)
1712 SendMessageA( hwnd, WM_CANCELMODE, 0, 0);
1714 WIN_SetStyle( hwnd, style | WS_DISABLED );
1716 if (hwnd == GetFocus() || IsChild(hwnd, GetFocus()))
1717 SetFocus( 0 ); /* A disabled window can't have the focus */
1719 if (hwnd == GetCapture() || IsChild(hwnd, GetCapture()))
1720 ReleaseCapture(); /* A disabled window can't capture the mouse */
1722 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1724 return retvalue;
1728 /***********************************************************************
1729 * IsWindowEnabled (USER32.@)
1731 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1733 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1737 /***********************************************************************
1738 * IsWindowUnicode (USER32.@)
1740 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1742 WND * wndPtr;
1743 BOOL retvalue;
1745 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1746 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1747 WIN_ReleaseWndPtr(wndPtr);
1748 return retvalue;
1752 /**********************************************************************
1753 * GetWindowWord (USER32.@)
1755 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1757 if (offset >= 0)
1759 WORD retvalue = 0;
1760 WND *wndPtr = WIN_GetPtr( hwnd );
1761 if (!wndPtr)
1763 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1764 return 0;
1766 if (wndPtr == WND_OTHER_PROCESS)
1768 if (IsWindow( hwnd ))
1769 FIXME( "(%d) not supported yet on other process window %p\n", offset, hwnd );
1770 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1771 return 0;
1773 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1775 WARN("Invalid offset %d\n", offset );
1776 SetLastError( ERROR_INVALID_INDEX );
1778 else retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1779 WIN_ReleasePtr( wndPtr );
1780 return retvalue;
1783 switch(offset)
1785 case GWL_HWNDPARENT:
1786 return GetWindowLongW( hwnd, offset );
1787 case GWL_ID:
1788 case GWL_HINSTANCE:
1790 LONG ret = GetWindowLongW( hwnd, offset );
1791 if (HIWORD(ret))
1792 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1793 return LOWORD(ret);
1795 default:
1796 WARN("Invalid offset %d\n", offset );
1797 return 0;
1802 /**********************************************************************
1803 * SetWindowWord (USER32.@)
1805 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1807 WORD *ptr, retval;
1808 WND * wndPtr;
1810 switch(offset)
1812 case GWL_ID:
1813 case GWL_HINSTANCE:
1814 case GWL_HWNDPARENT:
1815 return SetWindowLongW( hwnd, offset, (UINT)newval );
1816 default:
1817 if (offset < 0)
1819 WARN("Invalid offset %d\n", offset );
1820 SetLastError( ERROR_INVALID_INDEX );
1821 return 0;
1825 wndPtr = WIN_GetPtr( hwnd );
1826 if (wndPtr == WND_OTHER_PROCESS)
1828 if (IsWindow(hwnd))
1829 FIXME( "set %d <- %x not supported yet on other process window %p\n",
1830 offset, newval, hwnd );
1831 wndPtr = NULL;
1833 if (!wndPtr)
1835 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1836 return 0;
1839 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1841 WARN("Invalid offset %d\n", offset );
1842 WIN_ReleasePtr(wndPtr);
1843 SetLastError( ERROR_INVALID_INDEX );
1844 return 0;
1846 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1847 retval = *ptr;
1848 *ptr = newval;
1849 WIN_ReleasePtr(wndPtr);
1850 return retval;
1854 /**********************************************************************
1855 * WIN_GetWindowLong
1857 * Helper function for GetWindowLong().
1859 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1861 LONG retvalue = 0;
1862 WND *wndPtr;
1864 if (offset == GWL_HWNDPARENT)
1866 HWND parent = GetAncestor( hwnd, GA_PARENT );
1867 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1868 return (LONG)parent;
1871 if (!(wndPtr = WIN_GetPtr( hwnd )))
1873 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1874 return 0;
1877 if (wndPtr == WND_OTHER_PROCESS)
1879 if (offset >= 0)
1881 if (IsWindow(hwnd))
1882 FIXME( "(%d) not supported on other process window %p\n", offset, hwnd );
1883 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1884 return 0;
1886 if (offset == GWL_WNDPROC)
1888 SetLastError( ERROR_ACCESS_DENIED );
1889 return 0;
1891 SERVER_START_REQ( set_window_info )
1893 req->handle = hwnd;
1894 req->flags = 0; /* don't set anything, just retrieve */
1895 if (!wine_server_call_err( req ))
1897 switch(offset)
1899 case GWL_STYLE: retvalue = reply->old_style; break;
1900 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1901 case GWL_ID: retvalue = reply->old_id; break;
1902 case GWL_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1903 case GWL_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
1904 default:
1905 SetLastError( ERROR_INVALID_INDEX );
1906 break;
1910 SERVER_END_REQ;
1911 return retvalue;
1914 /* now we have a valid wndPtr */
1916 if (offset >= 0)
1918 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
1921 * Some programs try to access last element from 16 bit
1922 * code using illegal offset value. Hopefully this is
1923 * what those programs really expect.
1925 if (type == WIN_PROC_16 &&
1926 wndPtr->cbWndExtra >= 4 &&
1927 offset == wndPtr->cbWndExtra - sizeof(WORD))
1929 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
1931 ERR( "- replaced invalid offset %d with %d\n",
1932 offset, offset2 );
1934 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset2);
1935 WIN_ReleasePtr( wndPtr );
1936 return retvalue;
1938 WARN("Invalid offset %d\n", offset );
1939 WIN_ReleasePtr( wndPtr );
1940 SetLastError( ERROR_INVALID_INDEX );
1941 return 0;
1943 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1944 /* Special case for dialog window procedure */
1945 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1946 retvalue = (LONG)WINPROC_GetProc( (WNDPROC)retvalue, type );
1947 WIN_ReleasePtr( wndPtr );
1948 return retvalue;
1951 switch(offset)
1953 case GWL_USERDATA: retvalue = wndPtr->userdata; break;
1954 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1955 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1956 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu; break;
1957 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc, type ); break;
1958 case GWL_HINSTANCE: retvalue = (LONG)wndPtr->hInstance; break;
1959 default:
1960 WARN("Unknown offset %d\n", offset );
1961 SetLastError( ERROR_INVALID_INDEX );
1962 break;
1964 WIN_ReleasePtr(wndPtr);
1965 return retvalue;
1969 /**********************************************************************
1970 * WIN_SetWindowLong
1972 * Helper function for SetWindowLong().
1974 * 0 is the failure code. However, in the case of failure SetLastError
1975 * must be set to distinguish between a 0 return value and a failure.
1977 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1978 WINDOWPROCTYPE type )
1980 LONG retval = 0;
1981 WND *wndPtr;
1983 TRACE( "%p %d %lx %x\n", hwnd, offset, newval, type );
1985 if (!WIN_IsCurrentProcess( hwnd ))
1987 if (offset == GWL_WNDPROC)
1989 SetLastError( ERROR_ACCESS_DENIED );
1990 return 0;
1992 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
1995 wndPtr = WIN_GetPtr( hwnd );
1996 if (wndPtr->hwndSelf == GetDesktopWindow())
1998 /* can't change anything on the desktop window */
1999 WIN_ReleasePtr( wndPtr );
2000 SetLastError( ERROR_ACCESS_DENIED );
2001 return 0;
2004 if (offset >= 0)
2006 LONG *ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
2007 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
2009 WARN("Invalid offset %d\n", offset );
2010 WIN_ReleasePtr( wndPtr );
2011 SetLastError( ERROR_INVALID_INDEX );
2012 return 0;
2014 /* Special case for dialog window procedure */
2015 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2017 retval = (LONG)WINPROC_GetProc( (WNDPROC)*ptr, type );
2018 WINPROC_SetProc( (WNDPROC *)ptr, (WNDPROC)newval, type, WIN_PROC_WINDOW );
2019 WIN_ReleasePtr( wndPtr );
2020 return retval;
2022 retval = *ptr;
2023 *ptr = newval;
2024 WIN_ReleasePtr( wndPtr );
2026 else
2028 STYLESTRUCT style;
2029 BOOL ok;
2031 /* first some special cases */
2032 switch( offset )
2034 case GWL_STYLE:
2035 case GWL_EXSTYLE:
2036 style.styleOld = wndPtr->dwStyle;
2037 style.styleNew = newval;
2038 WIN_ReleasePtr( wndPtr );
2039 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
2040 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
2041 newval = style.styleNew;
2042 break;
2043 case GWL_HWNDPARENT:
2044 if (wndPtr->parent == GetDesktopWindow())
2046 WIN_ReleasePtr( wndPtr );
2047 return (LONG)WIN_SetOwner( hwnd, (HWND)newval );
2049 else
2051 WIN_ReleasePtr( wndPtr );
2052 return (LONG)SetParent( hwnd, (HWND)newval );
2054 case GWL_WNDPROC:
2055 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2056 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC)newval, type, WIN_PROC_WINDOW );
2057 WIN_ReleasePtr( wndPtr );
2058 return retval;
2059 case GWL_ID:
2060 case GWL_HINSTANCE:
2061 case GWL_USERDATA:
2062 break;
2063 default:
2064 WIN_ReleasePtr( wndPtr );
2065 WARN("Invalid offset %d\n", offset );
2066 SetLastError( ERROR_INVALID_INDEX );
2067 return 0;
2070 SERVER_START_REQ( set_window_info )
2072 req->handle = hwnd;
2073 switch(offset)
2075 case GWL_STYLE:
2076 req->flags = SET_WIN_STYLE;
2077 req->style = newval;
2078 break;
2079 case GWL_EXSTYLE:
2080 req->flags = SET_WIN_EXSTYLE;
2081 req->ex_style = newval;
2082 break;
2083 case GWL_ID:
2084 req->flags = SET_WIN_ID;
2085 req->id = newval;
2086 break;
2087 case GWL_HINSTANCE:
2088 req->flags = SET_WIN_INSTANCE;
2089 req->instance = (void *)newval;
2090 break;
2091 case GWL_USERDATA:
2092 req->flags = SET_WIN_USERDATA;
2093 req->user_data = (void *)newval;
2094 break;
2096 if ((ok = !wine_server_call_err( req )))
2098 switch(offset)
2100 case GWL_STYLE:
2101 wndPtr->dwStyle = newval;
2102 retval = reply->old_style;
2103 break;
2104 case GWL_EXSTYLE:
2105 wndPtr->dwExStyle = newval;
2106 retval = reply->old_ex_style;
2107 break;
2108 case GWL_ID:
2109 wndPtr->wIDmenu = newval;
2110 retval = reply->old_id;
2111 break;
2112 case GWL_HINSTANCE:
2113 wndPtr->hInstance = (HINSTANCE)newval;
2114 retval = (ULONG_PTR)reply->old_instance;
2115 break;
2116 case GWL_USERDATA:
2117 wndPtr->userdata = newval;
2118 retval = (ULONG_PTR)reply->old_user_data;
2119 break;
2123 SERVER_END_REQ;
2124 WIN_ReleasePtr( wndPtr );
2126 if (!ok) return 0;
2128 if (offset == GWL_STYLE && USER_Driver.pSetWindowStyle)
2129 USER_Driver.pSetWindowStyle( hwnd, retval );
2131 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2132 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2135 return retval;
2139 /**********************************************************************
2140 * GetWindowLong (USER.135)
2142 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2144 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
2148 /**********************************************************************
2149 * GetWindowLongA (USER32.@)
2151 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2153 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2157 /**********************************************************************
2158 * GetWindowLongW (USER32.@)
2160 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2162 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2166 /**********************************************************************
2167 * SetWindowLong (USER.136)
2169 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2171 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
2175 /**********************************************************************
2176 * SetWindowLongA (USER32.@)
2178 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2180 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2184 /**********************************************************************
2185 * SetWindowLongW (USER32.@) Set window attribute
2187 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2188 * value in a window's extra memory.
2190 * The _hwnd_ parameter specifies the window. is the handle to a
2191 * window that has extra memory. The _newval_ parameter contains the
2192 * new attribute or extra memory value. If positive, the _offset_
2193 * parameter is the byte-addressed location in the window's extra
2194 * memory to set. If negative, _offset_ specifies the window
2195 * attribute to set, and should be one of the following values:
2197 * GWL_EXSTYLE The window's extended window style
2199 * GWL_STYLE The window's window style.
2201 * GWL_WNDPROC Pointer to the window's window procedure.
2203 * GWL_HINSTANCE The window's pplication instance handle.
2205 * GWL_ID The window's identifier.
2207 * GWL_USERDATA The window's user-specified data.
2209 * If the window is a dialog box, the _offset_ parameter can be one of
2210 * the following values:
2212 * DWL_DLGPROC The address of the window's dialog box procedure.
2214 * DWL_MSGRESULT The return value of a message
2215 * that the dialog box procedure processed.
2217 * DWL_USER Application specific information.
2219 * RETURNS
2221 * If successful, returns the previous value located at _offset_. Otherwise,
2222 * returns 0.
2224 * NOTES
2226 * Extra memory for a window class is specified by a nonzero cbWndExtra
2227 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2228 * time of class creation.
2230 * Using GWL_WNDPROC to set a new window procedure effectively creates
2231 * a window subclass. Use CallWindowProc() in the new windows procedure
2232 * to pass messages to the superclass's window procedure.
2234 * The user data is reserved for use by the application which created
2235 * the window.
2237 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2238 * instead, call the EnableWindow() function to change the window's
2239 * disabled state.
2241 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2242 * SetParent() instead.
2244 * Win95:
2245 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2246 * it sends WM_STYLECHANGING before changing the settings
2247 * and WM_STYLECHANGED afterwards.
2248 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2250 LONG WINAPI SetWindowLongW(
2251 HWND hwnd, /* [in] window to alter */
2252 INT offset, /* [in] offset, in bytes, of location to alter */
2253 LONG newval /* [in] new value of location */
2255 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2259 /*******************************************************************
2260 * GetWindowTextA (USER32.@)
2262 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2264 WCHAR *buffer;
2266 if (WIN_IsCurrentProcess( hwnd ))
2267 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2269 /* when window belongs to other process, don't send a message */
2270 if (nMaxCount <= 0) return 0;
2271 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2272 get_server_window_text( hwnd, buffer, nMaxCount );
2273 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2274 lpString[nMaxCount-1] = 0;
2275 HeapFree( GetProcessHeap(), 0, buffer );
2276 return strlen(lpString);
2280 /*******************************************************************
2281 * InternalGetWindowText (USER32.@)
2283 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2285 WND *win;
2287 if (nMaxCount <= 0) return 0;
2288 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2289 if (win != WND_OTHER_PROCESS)
2291 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2292 else lpString[0] = 0;
2293 WIN_ReleasePtr( win );
2295 else
2297 get_server_window_text( hwnd, lpString, nMaxCount );
2299 return strlenW(lpString);
2303 /*******************************************************************
2304 * GetWindowTextW (USER32.@)
2306 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2308 if (WIN_IsCurrentProcess( hwnd ))
2309 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2311 /* when window belongs to other process, don't send a message */
2312 if (nMaxCount <= 0) return 0;
2313 get_server_window_text( hwnd, lpString, nMaxCount );
2314 return strlenW(lpString);
2318 /*******************************************************************
2319 * SetWindowText (USER32.@)
2320 * SetWindowTextA (USER32.@)
2322 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2324 if (!WIN_IsCurrentProcess( hwnd ))
2326 FIXME( "cannot set text %s of other process window %p\n", debugstr_a(lpString), hwnd );
2327 SetLastError( ERROR_ACCESS_DENIED );
2328 return FALSE;
2330 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2334 /*******************************************************************
2335 * SetWindowTextW (USER32.@)
2337 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2339 if (!WIN_IsCurrentProcess( hwnd ))
2341 FIXME( "cannot set text %s of other process window %p\n", debugstr_w(lpString), hwnd );
2342 SetLastError( ERROR_ACCESS_DENIED );
2343 return FALSE;
2345 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2349 /*******************************************************************
2350 * GetWindowTextLengthA (USER32.@)
2352 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2354 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2357 /*******************************************************************
2358 * GetWindowTextLengthW (USER32.@)
2360 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2362 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2366 /*******************************************************************
2367 * IsWindow (USER32.@)
2369 BOOL WINAPI IsWindow( HWND hwnd )
2371 WND *ptr;
2372 BOOL ret;
2374 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2376 if (ptr != WND_OTHER_PROCESS)
2378 WIN_ReleasePtr( ptr );
2379 return TRUE;
2382 /* check other processes */
2383 SERVER_START_REQ( get_window_info )
2385 req->handle = hwnd;
2386 ret = !wine_server_call_err( req );
2388 SERVER_END_REQ;
2389 return ret;
2393 /***********************************************************************
2394 * GetWindowThreadProcessId (USER32.@)
2396 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2398 WND *ptr;
2399 DWORD tid = 0;
2401 if (!(ptr = WIN_GetPtr( hwnd )))
2403 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2404 return 0;
2407 if (ptr != WND_OTHER_PROCESS)
2409 /* got a valid window */
2410 tid = ptr->tid;
2411 if (process) *process = GetCurrentProcessId();
2412 WIN_ReleasePtr( ptr );
2413 return tid;
2416 /* check other processes */
2417 SERVER_START_REQ( get_window_info )
2419 req->handle = hwnd;
2420 if (!wine_server_call_err( req ))
2422 tid = (DWORD)reply->tid;
2423 if (process) *process = (DWORD)reply->pid;
2426 SERVER_END_REQ;
2427 return tid;
2431 /*****************************************************************
2432 * GetParent (USER32.@)
2434 HWND WINAPI GetParent( HWND hwnd )
2436 WND *wndPtr;
2437 HWND retvalue = 0;
2439 if (!(wndPtr = WIN_GetPtr( hwnd )))
2441 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2442 return 0;
2444 if (wndPtr == WND_OTHER_PROCESS)
2446 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2447 if (style & (WS_POPUP | WS_CHILD))
2449 SERVER_START_REQ( get_window_tree )
2451 req->handle = hwnd;
2452 if (!wine_server_call_err( req ))
2454 if (style & WS_POPUP) retvalue = reply->owner;
2455 else if (style & WS_CHILD) retvalue = reply->parent;
2458 SERVER_END_REQ;
2461 else
2463 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2464 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2465 WIN_ReleasePtr( wndPtr );
2467 return retvalue;
2471 /*****************************************************************
2472 * GetAncestor (USER32.@)
2474 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2476 WND *win;
2477 HWND *list, ret = 0;
2479 switch(type)
2481 case GA_PARENT:
2482 if (!(win = WIN_GetPtr( hwnd )))
2484 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2485 return 0;
2487 if (win != WND_OTHER_PROCESS)
2489 ret = win->parent;
2490 WIN_ReleasePtr( win );
2492 else /* need to query the server */
2494 SERVER_START_REQ( get_window_tree )
2496 req->handle = hwnd;
2497 if (!wine_server_call_err( req )) ret = reply->parent;
2499 SERVER_END_REQ;
2501 break;
2503 case GA_ROOT:
2504 if (!(list = WIN_ListParents( hwnd ))) return 0;
2506 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2507 else
2509 int count = 2;
2510 while (list[count]) count++;
2511 ret = list[count - 2]; /* get the one before the desktop */
2513 HeapFree( GetProcessHeap(), 0, list );
2514 break;
2516 case GA_ROOTOWNER:
2517 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2518 for (;;)
2520 HWND parent = GetParent( ret );
2521 if (!parent) break;
2522 ret = parent;
2524 break;
2526 return ret;
2530 /*****************************************************************
2531 * SetParent (USER32.@)
2533 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2535 WND *wndPtr;
2536 HWND retvalue, full_handle;
2537 BOOL was_visible;
2539 if (!parent) parent = GetDesktopWindow();
2540 else parent = WIN_GetFullHandle( parent );
2542 if (!IsWindow( parent ))
2544 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2545 return 0;
2548 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2549 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2551 hwnd = full_handle;
2553 if (USER_Driver.pSetParent)
2554 return USER_Driver.pSetParent( hwnd, parent );
2556 /* Windows hides the window first, then shows it again
2557 * including the WM_SHOWWINDOW messages and all */
2558 was_visible = ShowWindow( hwnd, SW_HIDE );
2560 if (!IsWindow( parent )) return 0;
2561 if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return 0;
2563 retvalue = wndPtr->parent; /* old parent */
2564 if (parent != retvalue)
2566 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2568 if (parent != GetDesktopWindow()) /* a child window */
2570 if (!(wndPtr->dwStyle & WS_CHILD))
2572 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
2573 if (menu) DestroyMenu( menu );
2577 WIN_ReleasePtr( wndPtr );
2579 /* SetParent additionally needs to make hwnd the topmost window
2580 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2581 WM_WINDOWPOSCHANGED notification messages.
2583 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2584 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2585 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2586 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2587 return retvalue;
2591 /*******************************************************************
2592 * IsChild (USER32.@)
2594 BOOL WINAPI IsChild( HWND parent, HWND child )
2596 HWND *list = WIN_ListParents( child );
2597 int i;
2598 BOOL ret;
2600 if (!list) return FALSE;
2601 parent = WIN_GetFullHandle( parent );
2602 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2603 ret = (list[i] != 0);
2604 HeapFree( GetProcessHeap(), 0, list );
2605 return ret;
2609 /***********************************************************************
2610 * IsWindowVisible (USER32.@)
2612 BOOL WINAPI IsWindowVisible( HWND hwnd )
2614 HWND *list;
2615 BOOL retval;
2616 int i;
2618 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2619 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2620 for (i = 0; list[i]; i++)
2621 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2622 retval = !list[i];
2623 HeapFree( GetProcessHeap(), 0, list );
2624 return retval;
2628 /***********************************************************************
2629 * WIN_IsWindowDrawable
2631 * hwnd is drawable when it is visible, all parents are not
2632 * minimized, and it is itself not minimized unless we are
2633 * trying to draw its default class icon.
2635 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2637 HWND *list;
2638 BOOL retval;
2639 int i;
2640 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2642 if (!(style & WS_VISIBLE)) return FALSE;
2643 if ((style & WS_MINIMIZE) && icon && GetClassLongA( hwnd, GCL_HICON )) return FALSE;
2645 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2646 for (i = 0; list[i]; i++)
2647 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2648 break;
2649 retval = !list[i];
2650 HeapFree( GetProcessHeap(), 0, list );
2651 return retval;
2655 /*******************************************************************
2656 * GetTopWindow (USER32.@)
2658 HWND WINAPI GetTopWindow( HWND hwnd )
2660 if (!hwnd) hwnd = GetDesktopWindow();
2661 return GetWindow( hwnd, GW_CHILD );
2665 /*******************************************************************
2666 * GetWindow (USER32.@)
2668 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2670 HWND retval = 0;
2672 if (rel == GW_OWNER) /* this one may be available locally */
2674 WND *wndPtr = WIN_GetPtr( hwnd );
2675 if (!wndPtr)
2677 SetLastError( ERROR_INVALID_HANDLE );
2678 return 0;
2680 if (wndPtr != WND_OTHER_PROCESS)
2682 retval = wndPtr->owner;
2683 WIN_ReleasePtr( wndPtr );
2684 return retval;
2686 /* else fall through to server call */
2689 SERVER_START_REQ( get_window_tree )
2691 req->handle = hwnd;
2692 if (!wine_server_call_err( req ))
2694 switch(rel)
2696 case GW_HWNDFIRST:
2697 retval = reply->first_sibling;
2698 break;
2699 case GW_HWNDLAST:
2700 retval = reply->last_sibling;
2701 break;
2702 case GW_HWNDNEXT:
2703 retval = reply->next_sibling;
2704 break;
2705 case GW_HWNDPREV:
2706 retval = reply->prev_sibling;
2707 break;
2708 case GW_OWNER:
2709 retval = reply->owner;
2710 break;
2711 case GW_CHILD:
2712 retval = reply->first_child;
2713 break;
2717 SERVER_END_REQ;
2718 return retval;
2722 /***********************************************************************
2723 * WIN_InternalShowOwnedPopups
2725 * Internal version of ShowOwnedPopups; Wine functions should use this
2726 * to avoid interfering with application calls to ShowOwnedPopups
2727 * and to make sure the application can't prevent showing/hiding.
2729 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2733 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2735 int count = 0;
2736 WND *pWnd;
2737 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2739 if (!win_array) return TRUE;
2742 * Show windows Lowest first, Highest last to preserve Z-Order
2744 while (win_array[count]) count++;
2745 while (--count >= 0)
2747 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2748 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2750 if (pWnd->dwStyle & WS_POPUP)
2752 if (fShow)
2754 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2755 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
2758 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2760 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2761 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2764 else
2766 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2767 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2768 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2771 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2773 ShowWindow(pWnd->hwndSelf,SW_HIDE);
2774 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2775 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
2779 WIN_ReleaseWndPtr( pWnd );
2781 HeapFree( GetProcessHeap(), 0, win_array );
2783 return TRUE;
2786 /*******************************************************************
2787 * ShowOwnedPopups (USER32.@)
2789 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2791 int count = 0;
2792 WND *pWnd;
2793 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2795 if (!win_array) return TRUE;
2797 while (win_array[count]) count++;
2798 while (--count >= 0)
2800 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2801 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2803 if (pWnd->dwStyle & WS_POPUP)
2805 if (fShow)
2807 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2809 /* In Windows, ShowOwnedPopups(TRUE) generates
2810 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2811 * regardless of the state of the owner
2813 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2814 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2817 else
2819 if (IsWindowVisible(pWnd->hwndSelf))
2821 /* In Windows, ShowOwnedPopups(FALSE) generates
2822 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2823 * regardless of the state of the owner
2825 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2826 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2830 WIN_ReleaseWndPtr( pWnd );
2832 HeapFree( GetProcessHeap(), 0, win_array );
2833 return TRUE;
2837 /*******************************************************************
2838 * GetLastActivePopup (USER32.@)
2840 HWND WINAPI GetLastActivePopup( HWND hwnd )
2842 HWND retval = hwnd;
2844 SERVER_START_REQ( get_window_info )
2846 req->handle = hwnd;
2847 if (!wine_server_call_err( req )) retval = reply->last_active;
2849 SERVER_END_REQ;
2850 return retval;
2854 /*******************************************************************
2855 * WIN_ListParents
2857 * Build an array of all parents of a given window, starting with
2858 * the immediate parent. The array must be freed with HeapFree.
2859 * Returns NULL if window is a top-level window.
2861 HWND *WIN_ListParents( HWND hwnd )
2863 WND *win;
2864 HWND current, *list;
2865 int pos = 0, size = 16, count = 0;
2867 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2869 current = hwnd;
2870 for (;;)
2872 if (!(win = WIN_GetPtr( current ))) goto empty;
2873 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
2874 list[pos] = win->parent;
2875 WIN_ReleasePtr( win );
2876 if (!(current = list[pos]))
2878 if (!pos) goto empty;
2879 return list;
2881 if (++pos == size - 1)
2883 /* need to grow the list */
2884 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
2885 if (!new_list) goto empty;
2886 list = new_list;
2887 size += 16;
2891 /* at least one parent belongs to another process, have to query the server */
2893 for (;;)
2895 count = 0;
2896 SERVER_START_REQ( get_window_parents )
2898 req->handle = hwnd;
2899 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
2900 if (!wine_server_call( req )) count = reply->count;
2902 SERVER_END_REQ;
2903 if (!count) goto empty;
2904 if (size > count)
2906 list[count] = 0;
2907 return list;
2909 HeapFree( GetProcessHeap(), 0, list );
2910 size = count + 1;
2911 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2914 empty:
2915 HeapFree( GetProcessHeap(), 0, list );
2916 return NULL;
2920 /*******************************************************************
2921 * WIN_ListChildren
2923 * Build an array of the children of a given window. The array must be
2924 * freed with HeapFree. Returns NULL when no windows are found.
2926 HWND *WIN_ListChildren( HWND hwnd )
2928 return list_window_children( hwnd, 0, 0 );
2932 /*******************************************************************
2933 * EnumWindows (USER32.@)
2935 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2937 HWND *list;
2938 BOOL ret = TRUE;
2939 int i, iWndsLocks;
2941 /* We have to build a list of all windows first, to avoid */
2942 /* unpleasant side-effects, for instance if the callback */
2943 /* function changes the Z-order of the windows. */
2945 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2947 /* Now call the callback function for every window */
2949 iWndsLocks = WIN_SuspendWndsLock();
2950 for (i = 0; list[i]; i++)
2952 /* Make sure that the window still exists */
2953 if (!IsWindow( list[i] )) continue;
2954 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2956 WIN_RestoreWndsLock(iWndsLocks);
2957 HeapFree( GetProcessHeap(), 0, list );
2958 return ret;
2962 /**********************************************************************
2963 * EnumThreadWindows (USER32.@)
2965 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2967 HWND *list;
2968 int i, iWndsLocks;
2970 if (!(list = list_window_children( GetDesktopWindow(), 0, id ))) return TRUE;
2972 /* Now call the callback function for every window */
2974 iWndsLocks = WIN_SuspendWndsLock();
2975 for (i = 0; list[i]; i++)
2976 if (!func( list[i], lParam )) break;
2977 WIN_RestoreWndsLock(iWndsLocks);
2978 HeapFree( GetProcessHeap(), 0, list );
2979 return TRUE;
2983 /**********************************************************************
2984 * WIN_EnumChildWindows
2986 * Helper function for EnumChildWindows().
2988 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2990 HWND *childList;
2991 BOOL ret = FALSE;
2993 for ( ; *list; list++)
2995 /* Make sure that the window still exists */
2996 if (!IsWindow( *list )) continue;
2997 /* skip owned windows */
2998 if (GetWindow( *list, GW_OWNER )) continue;
2999 /* Build children list first */
3000 childList = WIN_ListChildren( *list );
3002 ret = func( *list, lParam );
3004 if (childList)
3006 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
3007 HeapFree( GetProcessHeap(), 0, childList );
3009 if (!ret) return FALSE;
3011 return TRUE;
3015 /**********************************************************************
3016 * EnumChildWindows (USER32.@)
3018 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
3020 HWND *list;
3021 int iWndsLocks;
3023 if (!(list = WIN_ListChildren( parent ))) return FALSE;
3024 iWndsLocks = WIN_SuspendWndsLock();
3025 WIN_EnumChildWindows( list, func, lParam );
3026 WIN_RestoreWndsLock(iWndsLocks);
3027 HeapFree( GetProcessHeap(), 0, list );
3028 return TRUE;
3032 /*******************************************************************
3033 * AnyPopup (USER.52)
3035 BOOL16 WINAPI AnyPopup16(void)
3037 return AnyPopup();
3041 /*******************************************************************
3042 * AnyPopup (USER32.@)
3044 BOOL WINAPI AnyPopup(void)
3046 int i;
3047 BOOL retvalue;
3048 HWND *list = WIN_ListChildren( GetDesktopWindow() );
3050 if (!list) return FALSE;
3051 for (i = 0; list[i]; i++)
3053 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
3055 retvalue = (list[i] != 0);
3056 HeapFree( GetProcessHeap(), 0, list );
3057 return retvalue;
3061 /*******************************************************************
3062 * FlashWindow (USER32.@)
3064 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3066 WND *wndPtr = WIN_FindWndPtr(hWnd);
3068 TRACE("%p\n", hWnd);
3070 if (!wndPtr) return FALSE;
3071 hWnd = wndPtr->hwndSelf; /* make it a full handle */
3073 if (wndPtr->dwStyle & WS_MINIMIZE)
3075 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3077 HDC hDC = GetDC(hWnd);
3079 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM)hDC, 0 ))
3080 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
3082 ReleaseDC( hWnd, hDC );
3083 wndPtr->flags |= WIN_NCACTIVATED;
3085 else
3087 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3088 wndPtr->flags &= ~WIN_NCACTIVATED;
3090 WIN_ReleaseWndPtr(wndPtr);
3091 return TRUE;
3093 else
3095 WPARAM16 wparam;
3096 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3097 else wparam = (hWnd == GetForegroundWindow());
3099 WIN_ReleaseWndPtr(wndPtr);
3100 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3101 return wparam;
3106 /*******************************************************************
3107 * GetWindowContextHelpId (USER32.@)
3109 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3111 DWORD retval;
3112 WND *wnd = WIN_FindWndPtr( hwnd );
3113 if (!wnd) return 0;
3114 retval = wnd->helpContext;
3115 WIN_ReleaseWndPtr(wnd);
3116 return retval;
3120 /*******************************************************************
3121 * SetWindowContextHelpId (USER32.@)
3123 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3125 WND *wnd = WIN_FindWndPtr( hwnd );
3126 if (!wnd) return FALSE;
3127 wnd->helpContext = id;
3128 WIN_ReleaseWndPtr(wnd);
3129 return TRUE;
3133 /*******************************************************************
3134 * DragDetect (USER32.@)
3136 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3138 MSG msg;
3139 RECT rect;
3141 rect.left = pt.x - wDragWidth;
3142 rect.right = pt.x + wDragWidth;
3144 rect.top = pt.y - wDragHeight;
3145 rect.bottom = pt.y + wDragHeight;
3147 SetCapture(hWnd);
3149 while(1)
3151 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3153 if( msg.message == WM_LBUTTONUP )
3155 ReleaseCapture();
3156 return 0;
3158 if( msg.message == WM_MOUSEMOVE )
3160 POINT tmp;
3161 tmp.x = LOWORD(msg.lParam);
3162 tmp.y = HIWORD(msg.lParam);
3163 if( !PtInRect( &rect, tmp ))
3165 ReleaseCapture();
3166 return 1;
3170 WaitMessage();
3172 return 0;
3175 /******************************************************************************
3176 * GetWindowModuleFileNameA (USER32.@)
3178 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3180 FIXME("GetWindowModuleFileNameA(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3181 hwnd, lpszFileName, cchFileNameMax);
3182 return 0;
3185 /******************************************************************************
3186 * GetWindowModuleFileNameW (USER32.@)
3188 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3190 FIXME("GetWindowModuleFileNameW(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3191 hwnd, lpszFileName, cchFileNameMax);
3192 return 0;
3195 /******************************************************************************
3196 * GetWindowInfo (USER32.@)
3197 * hwnd: in
3198 * pwi: out.
3199 * MS Documentation mentions that pwi->cbSize must be set to SIZEOF(WINDOWINFO)
3200 * this may be because this structure changed over time. If this is the
3201 * the case, then please: FIXME.
3202 * Using the structure described in MSDN for 98/ME/NT(4.0 SP3)/2000/XP.
3204 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3206 WND *wndInfo = NULL;
3207 if (!pwi) return FALSE;
3208 if (pwi->cbSize != sizeof(WINDOWINFO))
3210 FIXME("windowinfo->cbSize != sizeof(WINDOWINFO). Please report\n");
3211 return FALSE;
3213 wndInfo = WIN_GetPtr(hwnd);
3214 if (!wndInfo) return FALSE;
3215 if (wndInfo == WND_OTHER_PROCESS)
3217 FIXME("window belong to other process\n");
3218 return FALSE;
3221 pwi->rcWindow = wndInfo->rectWindow;
3222 pwi->rcClient = wndInfo->rectClient;
3223 pwi->dwStyle = wndInfo->dwStyle;
3224 pwi->dwExStyle = wndInfo->dwExStyle;
3225 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3226 /* if active WS_ACTIVECAPTION, else 0 */
3228 pwi->cxWindowBorders = ((wndInfo->dwStyle & WS_BORDER) ?
3229 GetSystemMetrics(SM_CXBORDER) : 0);
3230 pwi->cyWindowBorders = ((wndInfo->dwStyle & WS_BORDER) ?
3231 GetSystemMetrics(SM_CYBORDER) : 0);
3232 /* above two: I'm presuming that borders widths are the same
3233 * for each window - so long as its actually using a border.. */
3235 pwi->atomWindowType = GetClassLongA( hwnd, GCW_ATOM );
3236 pwi->wCreatorVersion = GetVersion();
3237 /* Docs say this should be the version that
3238 * CREATED the window. But eh?.. Isn't that just the
3239 * version we are running.. Unless ofcourse its some wacky
3240 * RPC stuff or something */
3242 WIN_ReleasePtr(wndInfo);
3243 return TRUE;