Include arpa/nameser.h before resolv.h.
[wine/dibdrv.git] / windows / win.c
blob1ed1104df87725b3275bb2f23271863c88bd3461
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 /* Unlink now so we won't bother with the children later on */
1520 WIN_UnlinkWindow( hwnd );
1522 /* Destroy the window storage */
1524 WIN_DestroyWindow( hwnd );
1525 return TRUE;
1529 /***********************************************************************
1530 * CloseWindow (USER32.@)
1532 BOOL WINAPI CloseWindow( HWND hwnd )
1534 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1535 ShowWindow( hwnd, SW_MINIMIZE );
1536 return TRUE;
1540 /***********************************************************************
1541 * OpenIcon (USER32.@)
1543 BOOL WINAPI OpenIcon( HWND hwnd )
1545 if (!IsIconic( hwnd )) return FALSE;
1546 ShowWindow( hwnd, SW_SHOWNORMAL );
1547 return TRUE;
1551 /***********************************************************************
1552 * WIN_FindWindow
1554 * Implementation of FindWindow() and FindWindowEx().
1556 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1558 HWND *list = NULL;
1559 HWND retvalue = 0;
1560 int i = 0, len = 0;
1561 WCHAR *buffer = NULL;
1563 if (!parent) parent = GetDesktopWindow();
1564 if (title)
1566 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1567 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1570 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1572 if (child)
1574 child = WIN_GetFullHandle( child );
1575 while (list[i] && list[i] != child) i++;
1576 if (!list[i]) goto done;
1577 i++; /* start from next window */
1580 if (title)
1582 while (list[i])
1584 if (GetWindowTextW( list[i], buffer, len ) && !strcmpiW( buffer, title )) break;
1585 i++;
1588 retvalue = list[i];
1590 done:
1591 if (list) HeapFree( GetProcessHeap(), 0, list );
1592 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1593 return retvalue;
1598 /***********************************************************************
1599 * FindWindowA (USER32.@)
1601 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1603 HWND ret = FindWindowExA( 0, 0, className, title );
1604 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1605 return ret;
1609 /***********************************************************************
1610 * FindWindowExA (USER32.@)
1612 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1613 LPCSTR className, LPCSTR title )
1615 ATOM atom = 0;
1616 LPWSTR buffer;
1617 HWND hwnd;
1618 INT len;
1620 if (className)
1622 /* If the atom doesn't exist, then no class */
1623 /* with this name exists either. */
1624 if (!(atom = GlobalFindAtomA( className )))
1626 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1627 return 0;
1630 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
1632 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1633 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1634 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
1635 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1636 HeapFree( GetProcessHeap(), 0, buffer );
1637 return hwnd;
1641 /***********************************************************************
1642 * FindWindowExW (USER32.@)
1644 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1645 LPCWSTR className, LPCWSTR title )
1647 ATOM atom = 0;
1649 if (className)
1651 /* If the atom doesn't exist, then no class */
1652 /* with this name exists either. */
1653 if (!(atom = GlobalFindAtomW( className )))
1655 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1656 return 0;
1659 return WIN_FindWindow( parent, child, atom, title );
1663 /***********************************************************************
1664 * FindWindowW (USER32.@)
1666 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1668 return FindWindowExW( 0, 0, className, title );
1672 /**********************************************************************
1673 * GetDesktopWindow (USER32.@)
1675 HWND WINAPI GetDesktopWindow(void)
1677 if (pWndDesktop) return pWndDesktop->hwndSelf;
1678 ERR( "Wine init error: either you're trying to use an invalid native USER.EXE config, or some graphics/GUI libraries or DLLs didn't initialize properly. Aborting.\n" );
1679 ExitProcess(1);
1680 return 0;
1684 /*******************************************************************
1685 * EnableWindow (USER32.@)
1687 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1689 WND *wndPtr;
1690 BOOL retvalue;
1691 LONG style;
1692 HWND full_handle;
1694 if (is_broadcast(hwnd))
1696 SetLastError( ERROR_INVALID_PARAMETER );
1697 return FALSE;
1700 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1701 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1703 hwnd = full_handle;
1705 TRACE("( %p, %d )\n", hwnd, enable);
1707 if (!(wndPtr = WIN_GetPtr( hwnd ))) return FALSE;
1708 style = wndPtr->dwStyle;
1709 retvalue = ((style & WS_DISABLED) != 0);
1710 WIN_ReleasePtr( wndPtr );
1712 if (enable && retvalue)
1714 WIN_SetStyle( hwnd, style & ~WS_DISABLED );
1715 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1717 else if (!enable && !retvalue)
1719 SendMessageA( hwnd, WM_CANCELMODE, 0, 0);
1721 WIN_SetStyle( hwnd, style | WS_DISABLED );
1723 if (hwnd == GetFocus() || IsChild(hwnd, GetFocus()))
1724 SetFocus( 0 ); /* A disabled window can't have the focus */
1726 if (hwnd == GetCapture() || IsChild(hwnd, GetCapture()))
1727 ReleaseCapture(); /* A disabled window can't capture the mouse */
1729 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1731 return retvalue;
1735 /***********************************************************************
1736 * IsWindowEnabled (USER32.@)
1738 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1740 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1744 /***********************************************************************
1745 * IsWindowUnicode (USER32.@)
1747 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1749 WND * wndPtr;
1750 BOOL retvalue;
1752 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1753 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1754 WIN_ReleaseWndPtr(wndPtr);
1755 return retvalue;
1759 /**********************************************************************
1760 * GetWindowWord (USER32.@)
1762 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1764 if (offset >= 0)
1766 WORD retvalue = 0;
1767 WND *wndPtr = WIN_GetPtr( hwnd );
1768 if (!wndPtr)
1770 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1771 return 0;
1773 if (wndPtr == WND_OTHER_PROCESS)
1775 if (IsWindow( hwnd ))
1776 FIXME( "(%d) not supported yet on other process window %p\n", offset, hwnd );
1777 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1778 return 0;
1780 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1782 WARN("Invalid offset %d\n", offset );
1783 SetLastError( ERROR_INVALID_INDEX );
1785 else retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1786 WIN_ReleasePtr( wndPtr );
1787 return retvalue;
1790 switch(offset)
1792 case GWL_HWNDPARENT:
1793 return GetWindowLongW( hwnd, offset );
1794 case GWL_ID:
1795 case GWL_HINSTANCE:
1797 LONG ret = GetWindowLongW( hwnd, offset );
1798 if (HIWORD(ret))
1799 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1800 return LOWORD(ret);
1802 default:
1803 WARN("Invalid offset %d\n", offset );
1804 return 0;
1809 /**********************************************************************
1810 * SetWindowWord (USER32.@)
1812 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1814 WORD *ptr, retval;
1815 WND * wndPtr;
1817 switch(offset)
1819 case GWL_ID:
1820 case GWL_HINSTANCE:
1821 case GWL_HWNDPARENT:
1822 return SetWindowLongW( hwnd, offset, (UINT)newval );
1823 default:
1824 if (offset < 0)
1826 WARN("Invalid offset %d\n", offset );
1827 SetLastError( ERROR_INVALID_INDEX );
1828 return 0;
1832 wndPtr = WIN_GetPtr( hwnd );
1833 if (wndPtr == WND_OTHER_PROCESS)
1835 if (IsWindow(hwnd))
1836 FIXME( "set %d <- %x not supported yet on other process window %p\n",
1837 offset, newval, hwnd );
1838 wndPtr = NULL;
1840 if (!wndPtr)
1842 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1843 return 0;
1846 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1848 WARN("Invalid offset %d\n", offset );
1849 WIN_ReleasePtr(wndPtr);
1850 SetLastError( ERROR_INVALID_INDEX );
1851 return 0;
1853 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1854 retval = *ptr;
1855 *ptr = newval;
1856 WIN_ReleasePtr(wndPtr);
1857 return retval;
1861 /**********************************************************************
1862 * WIN_GetWindowLong
1864 * Helper function for GetWindowLong().
1866 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1868 LONG retvalue = 0;
1869 WND *wndPtr;
1871 if (offset == GWL_HWNDPARENT)
1873 HWND parent = GetAncestor( hwnd, GA_PARENT );
1874 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1875 return (LONG)parent;
1878 if (!(wndPtr = WIN_GetPtr( hwnd )))
1880 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1881 return 0;
1884 if (wndPtr == WND_OTHER_PROCESS)
1886 if (offset >= 0)
1888 if (IsWindow(hwnd))
1889 FIXME( "(%d) not supported on other process window %p\n", offset, hwnd );
1890 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1891 return 0;
1893 if (offset == GWL_WNDPROC)
1895 SetLastError( ERROR_ACCESS_DENIED );
1896 return 0;
1898 SERVER_START_REQ( set_window_info )
1900 req->handle = hwnd;
1901 req->flags = 0; /* don't set anything, just retrieve */
1902 if (!wine_server_call_err( req ))
1904 switch(offset)
1906 case GWL_STYLE: retvalue = reply->old_style; break;
1907 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1908 case GWL_ID: retvalue = reply->old_id; break;
1909 case GWL_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1910 case GWL_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
1911 default:
1912 SetLastError( ERROR_INVALID_INDEX );
1913 break;
1917 SERVER_END_REQ;
1918 return retvalue;
1921 /* now we have a valid wndPtr */
1923 if (offset >= 0)
1925 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
1928 * Some programs try to access last element from 16 bit
1929 * code using illegal offset value. Hopefully this is
1930 * what those programs really expect.
1932 if (type == WIN_PROC_16 &&
1933 wndPtr->cbWndExtra >= 4 &&
1934 offset == wndPtr->cbWndExtra - sizeof(WORD))
1936 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
1938 ERR( "- replaced invalid offset %d with %d\n",
1939 offset, offset2 );
1941 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset2);
1942 WIN_ReleasePtr( wndPtr );
1943 return retvalue;
1945 WARN("Invalid offset %d\n", offset );
1946 WIN_ReleasePtr( wndPtr );
1947 SetLastError( ERROR_INVALID_INDEX );
1948 return 0;
1950 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1951 /* Special case for dialog window procedure */
1952 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1953 retvalue = (LONG)WINPROC_GetProc( (WNDPROC)retvalue, type );
1954 WIN_ReleasePtr( wndPtr );
1955 return retvalue;
1958 switch(offset)
1960 case GWL_USERDATA: retvalue = wndPtr->userdata; break;
1961 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1962 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1963 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu; break;
1964 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc, type ); break;
1965 case GWL_HINSTANCE: retvalue = (LONG)wndPtr->hInstance; break;
1966 default:
1967 WARN("Unknown offset %d\n", offset );
1968 SetLastError( ERROR_INVALID_INDEX );
1969 break;
1971 WIN_ReleasePtr(wndPtr);
1972 return retvalue;
1976 /**********************************************************************
1977 * WIN_SetWindowLong
1979 * Helper function for SetWindowLong().
1981 * 0 is the failure code. However, in the case of failure SetLastError
1982 * must be set to distinguish between a 0 return value and a failure.
1984 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1985 WINDOWPROCTYPE type )
1987 LONG retval = 0;
1988 WND *wndPtr;
1990 TRACE( "%p %d %lx %x\n", hwnd, offset, newval, type );
1992 if (is_broadcast(hwnd))
1994 SetLastError( ERROR_INVALID_PARAMETER );
1995 return FALSE;
1997 if (!WIN_IsCurrentProcess( hwnd ))
1999 if (offset == GWL_WNDPROC)
2001 SetLastError( ERROR_ACCESS_DENIED );
2002 return 0;
2004 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
2007 wndPtr = WIN_GetPtr( hwnd );
2008 if (wndPtr->hwndSelf == GetDesktopWindow())
2010 /* can't change anything on the desktop window */
2011 WIN_ReleasePtr( wndPtr );
2012 SetLastError( ERROR_ACCESS_DENIED );
2013 return 0;
2016 if (offset >= 0)
2018 LONG *ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
2019 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
2021 WARN("Invalid offset %d\n", offset );
2022 WIN_ReleasePtr( wndPtr );
2023 SetLastError( ERROR_INVALID_INDEX );
2024 return 0;
2026 /* Special case for dialog window procedure */
2027 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2029 retval = (LONG)WINPROC_GetProc( (WNDPROC)*ptr, type );
2030 WINPROC_SetProc( (WNDPROC *)ptr, (WNDPROC)newval, type, WIN_PROC_WINDOW );
2031 WIN_ReleasePtr( wndPtr );
2032 return retval;
2034 retval = *ptr;
2035 *ptr = newval;
2036 WIN_ReleasePtr( wndPtr );
2038 else
2040 STYLESTRUCT style;
2041 BOOL ok;
2043 /* first some special cases */
2044 switch( offset )
2046 case GWL_STYLE:
2047 case GWL_EXSTYLE:
2048 style.styleOld = wndPtr->dwStyle;
2049 style.styleNew = newval;
2050 WIN_ReleasePtr( wndPtr );
2051 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
2052 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
2053 newval = style.styleNew;
2054 break;
2055 case GWL_HWNDPARENT:
2056 if (wndPtr->parent == GetDesktopWindow())
2058 WIN_ReleasePtr( wndPtr );
2059 return (LONG)WIN_SetOwner( hwnd, (HWND)newval );
2061 else
2063 WIN_ReleasePtr( wndPtr );
2064 return (LONG)SetParent( hwnd, (HWND)newval );
2066 case GWL_WNDPROC:
2067 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2068 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC)newval, type, WIN_PROC_WINDOW );
2069 WIN_ReleasePtr( wndPtr );
2070 return retval;
2071 case GWL_ID:
2072 case GWL_HINSTANCE:
2073 case GWL_USERDATA:
2074 break;
2075 default:
2076 WIN_ReleasePtr( wndPtr );
2077 WARN("Invalid offset %d\n", offset );
2078 SetLastError( ERROR_INVALID_INDEX );
2079 return 0;
2082 SERVER_START_REQ( set_window_info )
2084 req->handle = hwnd;
2085 switch(offset)
2087 case GWL_STYLE:
2088 req->flags = SET_WIN_STYLE;
2089 req->style = newval;
2090 break;
2091 case GWL_EXSTYLE:
2092 req->flags = SET_WIN_EXSTYLE;
2093 req->ex_style = newval;
2094 break;
2095 case GWL_ID:
2096 req->flags = SET_WIN_ID;
2097 req->id = newval;
2098 break;
2099 case GWL_HINSTANCE:
2100 req->flags = SET_WIN_INSTANCE;
2101 req->instance = (void *)newval;
2102 break;
2103 case GWL_USERDATA:
2104 req->flags = SET_WIN_USERDATA;
2105 req->user_data = (void *)newval;
2106 break;
2108 if ((ok = !wine_server_call_err( req )))
2110 switch(offset)
2112 case GWL_STYLE:
2113 wndPtr->dwStyle = newval;
2114 retval = reply->old_style;
2115 break;
2116 case GWL_EXSTYLE:
2117 wndPtr->dwExStyle = newval;
2118 retval = reply->old_ex_style;
2119 break;
2120 case GWL_ID:
2121 wndPtr->wIDmenu = newval;
2122 retval = reply->old_id;
2123 break;
2124 case GWL_HINSTANCE:
2125 wndPtr->hInstance = (HINSTANCE)newval;
2126 retval = (ULONG_PTR)reply->old_instance;
2127 break;
2128 case GWL_USERDATA:
2129 wndPtr->userdata = newval;
2130 retval = (ULONG_PTR)reply->old_user_data;
2131 break;
2135 SERVER_END_REQ;
2136 WIN_ReleasePtr( wndPtr );
2138 if (!ok) return 0;
2140 if (offset == GWL_STYLE && USER_Driver.pSetWindowStyle)
2141 USER_Driver.pSetWindowStyle( hwnd, retval );
2143 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2144 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2147 return retval;
2151 /**********************************************************************
2152 * GetWindowLong (USER.135)
2154 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2156 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
2160 /**********************************************************************
2161 * GetWindowLongA (USER32.@)
2163 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2165 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2169 /**********************************************************************
2170 * GetWindowLongW (USER32.@)
2172 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2174 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2178 /**********************************************************************
2179 * SetWindowLong (USER.136)
2181 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2183 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
2187 /**********************************************************************
2188 * SetWindowLongA (USER32.@)
2190 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2192 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2196 /**********************************************************************
2197 * SetWindowLongW (USER32.@) Set window attribute
2199 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2200 * value in a window's extra memory.
2202 * The _hwnd_ parameter specifies the window. is the handle to a
2203 * window that has extra memory. The _newval_ parameter contains the
2204 * new attribute or extra memory value. If positive, the _offset_
2205 * parameter is the byte-addressed location in the window's extra
2206 * memory to set. If negative, _offset_ specifies the window
2207 * attribute to set, and should be one of the following values:
2209 * GWL_EXSTYLE The window's extended window style
2211 * GWL_STYLE The window's window style.
2213 * GWL_WNDPROC Pointer to the window's window procedure.
2215 * GWL_HINSTANCE The window's pplication instance handle.
2217 * GWL_ID The window's identifier.
2219 * GWL_USERDATA The window's user-specified data.
2221 * If the window is a dialog box, the _offset_ parameter can be one of
2222 * the following values:
2224 * DWL_DLGPROC The address of the window's dialog box procedure.
2226 * DWL_MSGRESULT The return value of a message
2227 * that the dialog box procedure processed.
2229 * DWL_USER Application specific information.
2231 * RETURNS
2233 * If successful, returns the previous value located at _offset_. Otherwise,
2234 * returns 0.
2236 * NOTES
2238 * Extra memory for a window class is specified by a nonzero cbWndExtra
2239 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2240 * time of class creation.
2242 * Using GWL_WNDPROC to set a new window procedure effectively creates
2243 * a window subclass. Use CallWindowProc() in the new windows procedure
2244 * to pass messages to the superclass's window procedure.
2246 * The user data is reserved for use by the application which created
2247 * the window.
2249 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2250 * instead, call the EnableWindow() function to change the window's
2251 * disabled state.
2253 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2254 * SetParent() instead.
2256 * Win95:
2257 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2258 * it sends WM_STYLECHANGING before changing the settings
2259 * and WM_STYLECHANGED afterwards.
2260 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2262 LONG WINAPI SetWindowLongW(
2263 HWND hwnd, /* [in] window to alter */
2264 INT offset, /* [in] offset, in bytes, of location to alter */
2265 LONG newval /* [in] new value of location */
2267 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2271 /*******************************************************************
2272 * GetWindowTextA (USER32.@)
2274 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2276 WCHAR *buffer;
2278 if (WIN_IsCurrentProcess( hwnd ))
2279 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2281 /* when window belongs to other process, don't send a message */
2282 if (nMaxCount <= 0) return 0;
2283 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2284 get_server_window_text( hwnd, buffer, nMaxCount );
2285 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2286 lpString[nMaxCount-1] = 0;
2287 HeapFree( GetProcessHeap(), 0, buffer );
2288 return strlen(lpString);
2292 /*******************************************************************
2293 * InternalGetWindowText (USER32.@)
2295 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2297 WND *win;
2299 if (nMaxCount <= 0) return 0;
2300 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2301 if (win != WND_OTHER_PROCESS)
2303 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2304 else lpString[0] = 0;
2305 WIN_ReleasePtr( win );
2307 else
2309 get_server_window_text( hwnd, lpString, nMaxCount );
2311 return strlenW(lpString);
2315 /*******************************************************************
2316 * GetWindowTextW (USER32.@)
2318 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2320 if (WIN_IsCurrentProcess( hwnd ))
2321 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2323 /* when window belongs to other process, don't send a message */
2324 if (nMaxCount <= 0) return 0;
2325 get_server_window_text( hwnd, lpString, nMaxCount );
2326 return strlenW(lpString);
2330 /*******************************************************************
2331 * SetWindowText (USER32.@)
2332 * SetWindowTextA (USER32.@)
2334 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2336 if (is_broadcast(hwnd))
2338 SetLastError( ERROR_INVALID_PARAMETER );
2339 return FALSE;
2341 if (!WIN_IsCurrentProcess( hwnd ))
2343 FIXME( "cannot set text %s of other process window %p\n", debugstr_a(lpString), hwnd );
2344 SetLastError( ERROR_ACCESS_DENIED );
2345 return FALSE;
2347 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2351 /*******************************************************************
2352 * SetWindowTextW (USER32.@)
2354 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2356 if (is_broadcast(hwnd))
2358 SetLastError( ERROR_INVALID_PARAMETER );
2359 return FALSE;
2361 if (!WIN_IsCurrentProcess( hwnd ))
2363 FIXME( "cannot set text %s of other process window %p\n", debugstr_w(lpString), hwnd );
2364 SetLastError( ERROR_ACCESS_DENIED );
2365 return FALSE;
2367 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2371 /*******************************************************************
2372 * GetWindowTextLengthA (USER32.@)
2374 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2376 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2379 /*******************************************************************
2380 * GetWindowTextLengthW (USER32.@)
2382 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2384 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2388 /*******************************************************************
2389 * IsWindow (USER32.@)
2391 BOOL WINAPI IsWindow( HWND hwnd )
2393 WND *ptr;
2394 BOOL ret;
2396 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2398 if (ptr != WND_OTHER_PROCESS)
2400 WIN_ReleasePtr( ptr );
2401 return TRUE;
2404 /* check other processes */
2405 SERVER_START_REQ( get_window_info )
2407 req->handle = hwnd;
2408 ret = !wine_server_call_err( req );
2410 SERVER_END_REQ;
2411 return ret;
2415 /***********************************************************************
2416 * GetWindowThreadProcessId (USER32.@)
2418 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2420 WND *ptr;
2421 DWORD tid = 0;
2423 if (!(ptr = WIN_GetPtr( hwnd )))
2425 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2426 return 0;
2429 if (ptr != WND_OTHER_PROCESS)
2431 /* got a valid window */
2432 tid = ptr->tid;
2433 if (process) *process = GetCurrentProcessId();
2434 WIN_ReleasePtr( ptr );
2435 return tid;
2438 /* check other processes */
2439 SERVER_START_REQ( get_window_info )
2441 req->handle = hwnd;
2442 if (!wine_server_call_err( req ))
2444 tid = (DWORD)reply->tid;
2445 if (process) *process = (DWORD)reply->pid;
2448 SERVER_END_REQ;
2449 return tid;
2453 /*****************************************************************
2454 * GetParent (USER32.@)
2456 HWND WINAPI GetParent( HWND hwnd )
2458 WND *wndPtr;
2459 HWND retvalue = 0;
2461 if (!(wndPtr = WIN_GetPtr( hwnd )))
2463 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2464 return 0;
2466 if (wndPtr == WND_OTHER_PROCESS)
2468 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2469 if (style & (WS_POPUP | WS_CHILD))
2471 SERVER_START_REQ( get_window_tree )
2473 req->handle = hwnd;
2474 if (!wine_server_call_err( req ))
2476 if (style & WS_POPUP) retvalue = reply->owner;
2477 else if (style & WS_CHILD) retvalue = reply->parent;
2480 SERVER_END_REQ;
2483 else
2485 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2486 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2487 WIN_ReleasePtr( wndPtr );
2489 return retvalue;
2493 /*****************************************************************
2494 * GetAncestor (USER32.@)
2496 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2498 WND *win;
2499 HWND *list, ret = 0;
2501 switch(type)
2503 case GA_PARENT:
2504 if (!(win = WIN_GetPtr( hwnd )))
2506 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2507 return 0;
2509 if (win != WND_OTHER_PROCESS)
2511 ret = win->parent;
2512 WIN_ReleasePtr( win );
2514 else /* need to query the server */
2516 SERVER_START_REQ( get_window_tree )
2518 req->handle = hwnd;
2519 if (!wine_server_call_err( req )) ret = reply->parent;
2521 SERVER_END_REQ;
2523 break;
2525 case GA_ROOT:
2526 if (!(list = WIN_ListParents( hwnd ))) return 0;
2528 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2529 else
2531 int count = 2;
2532 while (list[count]) count++;
2533 ret = list[count - 2]; /* get the one before the desktop */
2535 HeapFree( GetProcessHeap(), 0, list );
2536 break;
2538 case GA_ROOTOWNER:
2539 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2540 for (;;)
2542 HWND parent = GetParent( ret );
2543 if (!parent) break;
2544 ret = parent;
2546 break;
2548 return ret;
2552 /*****************************************************************
2553 * SetParent (USER32.@)
2555 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2557 WND *wndPtr;
2558 HWND retvalue, full_handle;
2559 BOOL was_visible;
2561 if (is_broadcast(hwnd) || is_broadcast(parent))
2563 SetLastError(ERROR_INVALID_PARAMETER);
2564 return 0;
2567 if (!parent) parent = GetDesktopWindow();
2568 else parent = WIN_GetFullHandle( parent );
2570 if (!IsWindow( parent ))
2572 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2573 return 0;
2576 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2577 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2579 hwnd = full_handle;
2581 if (USER_Driver.pSetParent)
2582 return USER_Driver.pSetParent( hwnd, parent );
2584 /* Windows hides the window first, then shows it again
2585 * including the WM_SHOWWINDOW messages and all */
2586 was_visible = ShowWindow( hwnd, SW_HIDE );
2588 if (!IsWindow( parent )) return 0;
2589 if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return 0;
2591 retvalue = wndPtr->parent; /* old parent */
2592 if (parent != retvalue)
2594 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2596 if (parent != GetDesktopWindow()) /* a child window */
2598 if (!(wndPtr->dwStyle & WS_CHILD))
2600 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
2601 if (menu) DestroyMenu( menu );
2605 WIN_ReleasePtr( wndPtr );
2607 /* SetParent additionally needs to make hwnd the topmost window
2608 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2609 WM_WINDOWPOSCHANGED notification messages.
2611 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2612 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2613 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2614 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2615 return retvalue;
2619 /*******************************************************************
2620 * IsChild (USER32.@)
2622 BOOL WINAPI IsChild( HWND parent, HWND child )
2624 HWND *list = WIN_ListParents( child );
2625 int i;
2626 BOOL ret;
2628 if (!list) return FALSE;
2629 parent = WIN_GetFullHandle( parent );
2630 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2631 ret = (list[i] != 0);
2632 HeapFree( GetProcessHeap(), 0, list );
2633 return ret;
2637 /***********************************************************************
2638 * IsWindowVisible (USER32.@)
2640 BOOL WINAPI IsWindowVisible( HWND hwnd )
2642 HWND *list;
2643 BOOL retval;
2644 int i;
2646 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2647 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2648 for (i = 0; list[i]; i++)
2649 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2650 retval = !list[i];
2651 HeapFree( GetProcessHeap(), 0, list );
2652 return retval;
2656 /***********************************************************************
2657 * WIN_IsWindowDrawable
2659 * hwnd is drawable when it is visible, all parents are not
2660 * minimized, and it is itself not minimized unless we are
2661 * trying to draw its default class icon.
2663 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2665 HWND *list;
2666 BOOL retval;
2667 int i;
2668 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2670 if (!(style & WS_VISIBLE)) return FALSE;
2671 if ((style & WS_MINIMIZE) && icon && GetClassLongA( hwnd, GCL_HICON )) return FALSE;
2673 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2674 for (i = 0; list[i]; i++)
2675 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2676 break;
2677 retval = !list[i];
2678 HeapFree( GetProcessHeap(), 0, list );
2679 return retval;
2683 /*******************************************************************
2684 * GetTopWindow (USER32.@)
2686 HWND WINAPI GetTopWindow( HWND hwnd )
2688 if (!hwnd) hwnd = GetDesktopWindow();
2689 return GetWindow( hwnd, GW_CHILD );
2693 /*******************************************************************
2694 * GetWindow (USER32.@)
2696 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2698 HWND retval = 0;
2700 if (rel == GW_OWNER) /* this one may be available locally */
2702 WND *wndPtr = WIN_GetPtr( hwnd );
2703 if (!wndPtr)
2705 SetLastError( ERROR_INVALID_HANDLE );
2706 return 0;
2708 if (wndPtr != WND_OTHER_PROCESS)
2710 retval = wndPtr->owner;
2711 WIN_ReleasePtr( wndPtr );
2712 return retval;
2714 /* else fall through to server call */
2717 SERVER_START_REQ( get_window_tree )
2719 req->handle = hwnd;
2720 if (!wine_server_call_err( req ))
2722 switch(rel)
2724 case GW_HWNDFIRST:
2725 retval = reply->first_sibling;
2726 break;
2727 case GW_HWNDLAST:
2728 retval = reply->last_sibling;
2729 break;
2730 case GW_HWNDNEXT:
2731 retval = reply->next_sibling;
2732 break;
2733 case GW_HWNDPREV:
2734 retval = reply->prev_sibling;
2735 break;
2736 case GW_OWNER:
2737 retval = reply->owner;
2738 break;
2739 case GW_CHILD:
2740 retval = reply->first_child;
2741 break;
2745 SERVER_END_REQ;
2746 return retval;
2750 /***********************************************************************
2751 * WIN_InternalShowOwnedPopups
2753 * Internal version of ShowOwnedPopups; Wine functions should use this
2754 * to avoid interfering with application calls to ShowOwnedPopups
2755 * and to make sure the application can't prevent showing/hiding.
2757 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2761 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2763 int count = 0;
2764 WND *pWnd;
2765 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2767 if (!win_array) return TRUE;
2770 * Show windows Lowest first, Highest last to preserve Z-Order
2772 while (win_array[count]) count++;
2773 while (--count >= 0)
2775 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2776 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2778 if (pWnd->dwStyle & WS_POPUP)
2780 if (fShow)
2782 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2783 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
2786 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2788 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2789 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2792 else
2794 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2795 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2796 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2799 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2801 ShowWindow(pWnd->hwndSelf,SW_HIDE);
2802 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2803 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
2807 WIN_ReleaseWndPtr( pWnd );
2809 HeapFree( GetProcessHeap(), 0, win_array );
2811 return TRUE;
2814 /*******************************************************************
2815 * ShowOwnedPopups (USER32.@)
2817 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2819 int count = 0;
2820 WND *pWnd;
2821 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2823 if (!win_array) return TRUE;
2825 while (win_array[count]) count++;
2826 while (--count >= 0)
2828 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2829 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2831 if (pWnd->dwStyle & WS_POPUP)
2833 if (fShow)
2835 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2837 /* In Windows, ShowOwnedPopups(TRUE) generates
2838 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2839 * regardless of the state of the owner
2841 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2842 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2845 else
2847 if (IsWindowVisible(pWnd->hwndSelf))
2849 /* In Windows, ShowOwnedPopups(FALSE) generates
2850 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2851 * regardless of the state of the owner
2853 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2854 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2858 WIN_ReleaseWndPtr( pWnd );
2860 HeapFree( GetProcessHeap(), 0, win_array );
2861 return TRUE;
2865 /*******************************************************************
2866 * GetLastActivePopup (USER32.@)
2868 HWND WINAPI GetLastActivePopup( HWND hwnd )
2870 HWND retval = hwnd;
2872 SERVER_START_REQ( get_window_info )
2874 req->handle = hwnd;
2875 if (!wine_server_call_err( req )) retval = reply->last_active;
2877 SERVER_END_REQ;
2878 return retval;
2882 /*******************************************************************
2883 * WIN_ListParents
2885 * Build an array of all parents of a given window, starting with
2886 * the immediate parent. The array must be freed with HeapFree.
2887 * Returns NULL if window is a top-level window.
2889 HWND *WIN_ListParents( HWND hwnd )
2891 WND *win;
2892 HWND current, *list;
2893 int pos = 0, size = 16, count = 0;
2895 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2897 current = hwnd;
2898 for (;;)
2900 if (!(win = WIN_GetPtr( current ))) goto empty;
2901 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
2902 list[pos] = win->parent;
2903 WIN_ReleasePtr( win );
2904 if (!(current = list[pos]))
2906 if (!pos) goto empty;
2907 return list;
2909 if (++pos == size - 1)
2911 /* need to grow the list */
2912 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
2913 if (!new_list) goto empty;
2914 list = new_list;
2915 size += 16;
2919 /* at least one parent belongs to another process, have to query the server */
2921 for (;;)
2923 count = 0;
2924 SERVER_START_REQ( get_window_parents )
2926 req->handle = hwnd;
2927 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
2928 if (!wine_server_call( req )) count = reply->count;
2930 SERVER_END_REQ;
2931 if (!count) goto empty;
2932 if (size > count)
2934 list[count] = 0;
2935 return list;
2937 HeapFree( GetProcessHeap(), 0, list );
2938 size = count + 1;
2939 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2942 empty:
2943 HeapFree( GetProcessHeap(), 0, list );
2944 return NULL;
2948 /*******************************************************************
2949 * WIN_ListChildren
2951 * Build an array of the children of a given window. The array must be
2952 * freed with HeapFree. Returns NULL when no windows are found.
2954 HWND *WIN_ListChildren( HWND hwnd )
2956 return list_window_children( hwnd, 0, 0 );
2960 /*******************************************************************
2961 * EnumWindows (USER32.@)
2963 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2965 HWND *list;
2966 BOOL ret = TRUE;
2967 int i, iWndsLocks;
2969 /* We have to build a list of all windows first, to avoid */
2970 /* unpleasant side-effects, for instance if the callback */
2971 /* function changes the Z-order of the windows. */
2973 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2975 /* Now call the callback function for every window */
2977 iWndsLocks = WIN_SuspendWndsLock();
2978 for (i = 0; list[i]; i++)
2980 /* Make sure that the window still exists */
2981 if (!IsWindow( list[i] )) continue;
2982 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2984 WIN_RestoreWndsLock(iWndsLocks);
2985 HeapFree( GetProcessHeap(), 0, list );
2986 return ret;
2990 /**********************************************************************
2991 * EnumThreadWindows (USER32.@)
2993 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2995 HWND *list;
2996 int i, iWndsLocks;
2998 if (!(list = list_window_children( GetDesktopWindow(), 0, id ))) return TRUE;
3000 /* Now call the callback function for every window */
3002 iWndsLocks = WIN_SuspendWndsLock();
3003 for (i = 0; list[i]; i++)
3004 if (!func( list[i], lParam )) break;
3005 WIN_RestoreWndsLock(iWndsLocks);
3006 HeapFree( GetProcessHeap(), 0, list );
3007 return TRUE;
3011 /**********************************************************************
3012 * WIN_EnumChildWindows
3014 * Helper function for EnumChildWindows().
3016 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
3018 HWND *childList;
3019 BOOL ret = FALSE;
3021 for ( ; *list; list++)
3023 /* Make sure that the window still exists */
3024 if (!IsWindow( *list )) continue;
3025 /* skip owned windows */
3026 if (GetWindow( *list, GW_OWNER )) continue;
3027 /* Build children list first */
3028 childList = WIN_ListChildren( *list );
3030 ret = func( *list, lParam );
3032 if (childList)
3034 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
3035 HeapFree( GetProcessHeap(), 0, childList );
3037 if (!ret) return FALSE;
3039 return TRUE;
3043 /**********************************************************************
3044 * EnumChildWindows (USER32.@)
3046 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
3048 HWND *list;
3049 int iWndsLocks;
3051 if (!(list = WIN_ListChildren( parent ))) return FALSE;
3052 iWndsLocks = WIN_SuspendWndsLock();
3053 WIN_EnumChildWindows( list, func, lParam );
3054 WIN_RestoreWndsLock(iWndsLocks);
3055 HeapFree( GetProcessHeap(), 0, list );
3056 return TRUE;
3060 /*******************************************************************
3061 * AnyPopup (USER.52)
3063 BOOL16 WINAPI AnyPopup16(void)
3065 return AnyPopup();
3069 /*******************************************************************
3070 * AnyPopup (USER32.@)
3072 BOOL WINAPI AnyPopup(void)
3074 int i;
3075 BOOL retvalue;
3076 HWND *list = WIN_ListChildren( GetDesktopWindow() );
3078 if (!list) return FALSE;
3079 for (i = 0; list[i]; i++)
3081 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
3083 retvalue = (list[i] != 0);
3084 HeapFree( GetProcessHeap(), 0, list );
3085 return retvalue;
3089 /*******************************************************************
3090 * FlashWindow (USER32.@)
3092 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3094 WND *wndPtr = WIN_FindWndPtr(hWnd);
3096 TRACE("%p\n", hWnd);
3098 if (!wndPtr) return FALSE;
3099 hWnd = wndPtr->hwndSelf; /* make it a full handle */
3101 if (wndPtr->dwStyle & WS_MINIMIZE)
3103 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3105 HDC hDC = GetDC(hWnd);
3107 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM)hDC, 0 ))
3108 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
3110 ReleaseDC( hWnd, hDC );
3111 wndPtr->flags |= WIN_NCACTIVATED;
3113 else
3115 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3116 wndPtr->flags &= ~WIN_NCACTIVATED;
3118 WIN_ReleaseWndPtr(wndPtr);
3119 return TRUE;
3121 else
3123 WPARAM16 wparam;
3124 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3125 else wparam = (hWnd == GetForegroundWindow());
3127 WIN_ReleaseWndPtr(wndPtr);
3128 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3129 return wparam;
3134 /*******************************************************************
3135 * GetWindowContextHelpId (USER32.@)
3137 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3139 DWORD retval;
3140 WND *wnd = WIN_FindWndPtr( hwnd );
3141 if (!wnd) return 0;
3142 retval = wnd->helpContext;
3143 WIN_ReleaseWndPtr(wnd);
3144 return retval;
3148 /*******************************************************************
3149 * SetWindowContextHelpId (USER32.@)
3151 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3153 WND *wnd = WIN_FindWndPtr( hwnd );
3154 if (!wnd) return FALSE;
3155 wnd->helpContext = id;
3156 WIN_ReleaseWndPtr(wnd);
3157 return TRUE;
3161 /*******************************************************************
3162 * DragDetect (USER32.@)
3164 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3166 MSG msg;
3167 RECT rect;
3169 rect.left = pt.x - wDragWidth;
3170 rect.right = pt.x + wDragWidth;
3172 rect.top = pt.y - wDragHeight;
3173 rect.bottom = pt.y + wDragHeight;
3175 SetCapture(hWnd);
3177 while(1)
3179 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3181 if( msg.message == WM_LBUTTONUP )
3183 ReleaseCapture();
3184 return 0;
3186 if( msg.message == WM_MOUSEMOVE )
3188 POINT tmp;
3189 tmp.x = LOWORD(msg.lParam);
3190 tmp.y = HIWORD(msg.lParam);
3191 if( !PtInRect( &rect, tmp ))
3193 ReleaseCapture();
3194 return 1;
3198 WaitMessage();
3200 return 0;
3203 /******************************************************************************
3204 * GetWindowModuleFileNameA (USER32.@)
3206 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3208 FIXME("GetWindowModuleFileNameA(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3209 hwnd, lpszFileName, cchFileNameMax);
3210 return 0;
3213 /******************************************************************************
3214 * GetWindowModuleFileNameW (USER32.@)
3216 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3218 FIXME("GetWindowModuleFileNameW(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3219 hwnd, lpszFileName, cchFileNameMax);
3220 return 0;
3223 /******************************************************************************
3224 * GetWindowInfo (USER32.@)
3225 * hwnd: in
3226 * pwi: out.
3227 * MS Documentation mentions that pwi->cbSize must be set to SIZEOF(WINDOWINFO)
3228 * this may be because this structure changed over time. If this is the
3229 * the case, then please: FIXME.
3230 * Using the structure described in MSDN for 98/ME/NT(4.0 SP3)/2000/XP.
3232 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3234 WND *wndInfo = NULL;
3235 if (!pwi) return FALSE;
3236 if (pwi->cbSize != sizeof(WINDOWINFO))
3238 FIXME("windowinfo->cbSize != sizeof(WINDOWINFO). Please report\n");
3239 return FALSE;
3241 wndInfo = WIN_GetPtr(hwnd);
3242 if (!wndInfo) return FALSE;
3243 if (wndInfo == WND_OTHER_PROCESS)
3245 FIXME("window belong to other process\n");
3246 return FALSE;
3249 pwi->rcWindow = wndInfo->rectWindow;
3250 pwi->rcClient = wndInfo->rectClient;
3251 pwi->dwStyle = wndInfo->dwStyle;
3252 pwi->dwExStyle = wndInfo->dwExStyle;
3253 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3254 /* if active WS_ACTIVECAPTION, else 0 */
3256 pwi->cxWindowBorders = ((wndInfo->dwStyle & WS_BORDER) ?
3257 GetSystemMetrics(SM_CXBORDER) : 0);
3258 pwi->cyWindowBorders = ((wndInfo->dwStyle & WS_BORDER) ?
3259 GetSystemMetrics(SM_CYBORDER) : 0);
3260 /* above two: I'm presuming that borders widths are the same
3261 * for each window - so long as its actually using a border.. */
3263 pwi->atomWindowType = GetClassLongA( hwnd, GCW_ATOM );
3264 pwi->wCreatorVersion = GetVersion();
3265 /* Docs say this should be the version that
3266 * CREATED the window. But eh?.. Isn't that just the
3267 * version we are running.. Unless ofcourse its some wacky
3268 * RPC stuff or something */
3270 WIN_ReleasePtr(wndInfo);
3271 return TRUE;