Silence some warnings due to casts between pointer and integers of
[wine/multimedia.git] / windows / win.c
blob596449d457465da09d89c1a3c9bdabf1afd8dcd7
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 "hook.h"
39 #include "message.h"
40 #include "queue.h"
41 #include "winpos.h"
42 #include "winerror.h"
43 #include "stackframe.h"
44 #include "wine/debug.h"
46 WINE_DEFAULT_DEBUG_CHANNEL(win);
47 WINE_DECLARE_DEBUG_CHANNEL(msg);
49 #define NB_USER_HANDLES (LAST_USER_HANDLE - FIRST_USER_HANDLE + 1)
51 /**********************************************************************/
53 /* Desktop window */
54 static WND *pWndDesktop = NULL;
56 static WORD wDragWidth = 4;
57 static WORD wDragHeight= 3;
59 static void *user_handles[NB_USER_HANDLES];
61 /* thread safeness */
62 extern SYSLEVEL USER_SysLevel; /* FIXME */
64 /***********************************************************************
65 * WIN_SuspendWndsLock
67 * Suspend the lock on WND structures.
68 * Returns the number of locks suspended
70 int WIN_SuspendWndsLock( void )
72 int isuspendedLocks = _ConfirmSysLevel( &USER_SysLevel );
73 int count = isuspendedLocks;
75 while ( count-- > 0 )
76 _LeaveSysLevel( &USER_SysLevel );
78 return isuspendedLocks;
81 /***********************************************************************
82 * WIN_RestoreWndsLock
84 * Restore the suspended locks on WND structures
86 void WIN_RestoreWndsLock( int ipreviousLocks )
88 while ( ipreviousLocks-- > 0 )
89 _EnterSysLevel( &USER_SysLevel );
92 /***********************************************************************
93 * create_window_handle
95 * Create a window handle with the server.
97 static WND *create_window_handle( HWND parent, HWND owner, ATOM atom, INT size )
99 BOOL res;
100 user_handle_t handle = 0;
101 WORD index;
102 WND *win = HeapAlloc( GetProcessHeap(), 0, size );
104 if (!win) return NULL;
106 USER_Lock();
108 SERVER_START_REQ( create_window )
110 req->parent = parent;
111 req->owner = owner;
112 req->atom = atom;
113 if ((res = !wine_server_call_err( req ))) handle = reply->handle;
115 SERVER_END_REQ;
117 if (!res)
119 USER_Unlock();
120 HeapFree( GetProcessHeap(), 0, win );
121 return NULL;
123 index = LOWORD(handle) - FIRST_USER_HANDLE;
124 assert( index < NB_USER_HANDLES );
125 user_handles[index] = win;
126 win->hwndSelf = handle;
127 win->dwMagic = WND_MAGIC;
128 win->irefCount = 1;
129 return win;
133 /***********************************************************************
134 * free_window_handle
136 * Free a window handle.
138 static WND *free_window_handle( HWND hwnd )
140 WND *ptr;
141 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
143 if (index >= NB_USER_HANDLES) return NULL;
144 USER_Lock();
145 if ((ptr = user_handles[index]))
147 SERVER_START_REQ( destroy_window )
149 req->handle = hwnd;
150 if (!wine_server_call_err( req ))
151 user_handles[index] = NULL;
152 else
153 ptr = NULL;
155 SERVER_END_REQ;
157 USER_Unlock();
158 if (ptr) HeapFree( GetProcessHeap(), 0, ptr );
159 return ptr;
163 /*******************************************************************
164 * list_window_children
166 * Build an array of the children of a given window. The array must be
167 * freed with HeapFree. Returns NULL when no windows are found.
169 static HWND *list_window_children( HWND hwnd, ATOM atom, DWORD tid )
171 HWND *list;
172 int size = 32;
174 for (;;)
176 int count = 0;
178 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
180 SERVER_START_REQ( get_window_children )
182 req->parent = hwnd;
183 req->atom = atom;
184 req->tid = tid;
185 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
186 if (!wine_server_call( req )) count = reply->count;
188 SERVER_END_REQ;
189 if (count && count < size)
191 list[count] = 0;
192 return list;
194 HeapFree( GetProcessHeap(), 0, list );
195 if (!count) break;
196 size = count + 1; /* restart with a large enough buffer */
198 return NULL;
202 /*******************************************************************
203 * send_parent_notify
205 static void send_parent_notify( HWND hwnd, UINT msg )
207 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD)) return;
208 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY) return;
209 SendMessageW( GetParent(hwnd), WM_PARENTNOTIFY,
210 MAKEWPARAM( msg, GetWindowLongW( hwnd, GWL_ID )), (LPARAM)hwnd );
214 /*******************************************************************
215 * get_server_window_text
217 * Retrieve the window text from the server.
219 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
221 size_t len = 0;
223 SERVER_START_REQ( get_window_text )
225 req->handle = hwnd;
226 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
227 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
229 SERVER_END_REQ;
230 text[len / sizeof(WCHAR)] = 0;
234 /***********************************************************************
235 * WIN_GetPtr
237 * Return a pointer to the WND structure if local to the process,
238 * or WND_OTHER_PROCESS if handle may be valid in other process.
239 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
241 WND *WIN_GetPtr( HWND hwnd )
243 WND * ptr;
244 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
246 if (index >= NB_USER_HANDLES) return NULL;
248 USER_Lock();
249 if ((ptr = user_handles[index]))
251 if (ptr->dwMagic == WND_MAGIC && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
252 return ptr;
253 ptr = NULL;
255 else ptr = WND_OTHER_PROCESS;
256 USER_Unlock();
257 return ptr;
261 /***********************************************************************
262 * WIN_IsCurrentProcess
264 * Check whether a given window belongs to the current process (and return the full handle).
266 HWND WIN_IsCurrentProcess( HWND hwnd )
268 WND *ptr;
269 HWND ret;
271 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS) return 0;
272 ret = ptr->hwndSelf;
273 WIN_ReleasePtr( ptr );
274 return ret;
278 /***********************************************************************
279 * WIN_IsCurrentThread
281 * Check whether a given window belongs to the current thread (and return the full handle).
283 HWND WIN_IsCurrentThread( HWND hwnd )
285 WND *ptr;
286 HWND ret = 0;
288 if ((ptr = WIN_GetPtr( hwnd )) && ptr != WND_OTHER_PROCESS)
290 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
291 WIN_ReleasePtr( ptr );
293 return ret;
297 /***********************************************************************
298 * WIN_Handle32
300 * Convert a 16-bit window handle to a full 32-bit handle.
302 HWND WIN_Handle32( HWND16 hwnd16 )
304 WND *ptr;
305 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
307 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
308 /* do sign extension for -2 and -3 */
309 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
311 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
313 if (ptr != WND_OTHER_PROCESS)
315 hwnd = ptr->hwndSelf;
316 WIN_ReleasePtr( ptr );
318 else /* may belong to another process */
320 SERVER_START_REQ( get_window_info )
322 req->handle = hwnd;
323 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
325 SERVER_END_REQ;
327 return hwnd;
331 /***********************************************************************
332 * WIN_FindWndPtr
334 * Return a pointer to the WND structure corresponding to a HWND.
336 WND * WIN_FindWndPtr( HWND hwnd )
338 WND * ptr;
340 if (!hwnd) return NULL;
342 if ((ptr = WIN_GetPtr( hwnd )))
344 if (ptr != WND_OTHER_PROCESS)
346 /* increment destruction monitoring */
347 ptr->irefCount++;
348 return ptr;
350 if (IsWindow( hwnd )) /* check other processes */
352 ERR( "window %04x belongs to other process\n", hwnd );
353 /* DbgBreakPoint(); */
356 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
357 return NULL;
361 /***********************************************************************
362 * WIN_ReleaseWndPtr
364 * Release the pointer to the WND structure.
366 void WIN_ReleaseWndPtr(WND *wndPtr)
368 if(!wndPtr) return;
370 /* Decrement destruction monitoring value */
371 wndPtr->irefCount--;
372 /* Check if it's time to release the memory */
373 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
375 /* Release memory */
376 free_window_handle( wndPtr->hwndSelf );
378 else if(wndPtr->irefCount < 0)
380 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
381 ERR("forgot a Lock on %p somewhere\n",wndPtr);
383 /* unlock all WND structures for thread safeness */
384 USER_Unlock();
388 /***********************************************************************
389 * WIN_UnlinkWindow
391 * Remove a window from the siblings linked list.
393 void WIN_UnlinkWindow( HWND hwnd )
395 WIN_LinkWindow( hwnd, 0, 0 );
399 /***********************************************************************
400 * WIN_LinkWindow
402 * Insert a window into the siblings linked list.
403 * The window is inserted after the specified window, which can also
404 * be specified as HWND_TOP or HWND_BOTTOM.
405 * If parent is 0, window is unlinked from the tree.
407 void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
409 WND *wndPtr = WIN_GetPtr( hwnd );
411 if (!wndPtr) return;
412 if (wndPtr == WND_OTHER_PROCESS)
414 if (IsWindow(hwnd)) ERR(" cannot link other process window %x\n", hwnd );
415 return;
418 SERVER_START_REQ( link_window )
420 req->handle = hwnd;
421 req->parent = parent;
422 req->previous = hwndInsertAfter;
423 if (!wine_server_call( req ))
425 if (reply->full_parent) wndPtr->parent = reply->full_parent;
429 SERVER_END_REQ;
430 WIN_ReleasePtr( wndPtr );
434 /***********************************************************************
435 * WIN_SetOwner
437 * Change the owner of a window.
439 HWND WIN_SetOwner( HWND hwnd, HWND owner )
441 WND *win = WIN_GetPtr( hwnd );
442 HWND ret = 0;
444 if (!win) return 0;
445 if (win == WND_OTHER_PROCESS)
447 if (IsWindow(hwnd)) ERR( "cannot set owner %x on other process window %x\n", owner, hwnd );
448 return 0;
450 SERVER_START_REQ( set_window_owner )
452 req->handle = hwnd;
453 req->owner = owner;
454 if (!wine_server_call( req ))
456 win->owner = reply->full_owner;
457 ret = reply->prev_owner;
460 SERVER_END_REQ;
461 WIN_ReleasePtr( win );
462 return ret;
466 /***********************************************************************
467 * WIN_SetStyle
469 * Change the style of a window.
471 LONG WIN_SetStyle( HWND hwnd, LONG style )
473 BOOL ok;
474 LONG ret = 0;
475 WND *win = WIN_GetPtr( hwnd );
477 if (!win) return 0;
478 if (win == WND_OTHER_PROCESS)
480 if (IsWindow(hwnd))
481 ERR( "cannot set style %lx on other process window %x\n", style, hwnd );
482 return 0;
484 if (style == win->dwStyle)
486 WIN_ReleasePtr( win );
487 return style;
489 SERVER_START_REQ( set_window_info )
491 req->handle = hwnd;
492 req->flags = SET_WIN_STYLE;
493 req->style = style;
494 if ((ok = !wine_server_call( req )))
496 ret = reply->old_style;
497 win->dwStyle = style;
500 SERVER_END_REQ;
501 WIN_ReleasePtr( win );
502 if (ok && USER_Driver.pSetWindowStyle) USER_Driver.pSetWindowStyle( hwnd, ret );
503 return ret;
507 /***********************************************************************
508 * WIN_SetExStyle
510 * Change the extended style of a window.
512 LONG WIN_SetExStyle( HWND hwnd, LONG style )
514 LONG ret = 0;
515 WND *win = WIN_GetPtr( hwnd );
517 if (!win) return 0;
518 if (win == WND_OTHER_PROCESS)
520 if (IsWindow(hwnd))
521 ERR( "cannot set exstyle %lx on other process window %x\n", style, hwnd );
522 return 0;
524 if (style == win->dwExStyle)
526 WIN_ReleasePtr( win );
527 return style;
529 SERVER_START_REQ( set_window_info )
531 req->handle = hwnd;
532 req->flags = SET_WIN_EXSTYLE;
533 req->ex_style = style;
534 if (!wine_server_call( req ))
536 ret = reply->old_ex_style;
537 win->dwExStyle = style;
540 SERVER_END_REQ;
541 WIN_ReleasePtr( win );
542 return ret;
546 /***********************************************************************
547 * WIN_SetRectangles
549 * Set the window and client rectangles.
551 void WIN_SetRectangles( HWND hwnd, const RECT *rectWindow, const RECT *rectClient )
553 WND *win = WIN_GetPtr( hwnd );
554 BOOL ret;
556 if (!win) return;
557 if (win == WND_OTHER_PROCESS)
559 if (IsWindow( hwnd )) ERR( "cannot set rectangles of other process window %x\n", hwnd );
560 return;
562 SERVER_START_REQ( set_window_rectangles )
564 req->handle = hwnd;
565 req->window.left = rectWindow->left;
566 req->window.top = rectWindow->top;
567 req->window.right = rectWindow->right;
568 req->window.bottom = rectWindow->bottom;
569 req->client.left = rectClient->left;
570 req->client.top = rectClient->top;
571 req->client.right = rectClient->right;
572 req->client.bottom = rectClient->bottom;
573 ret = !wine_server_call( req );
575 SERVER_END_REQ;
576 if (ret)
578 win->rectWindow = *rectWindow;
579 win->rectClient = *rectClient;
581 TRACE( "win %x window (%d,%d)-(%d,%d) client (%d,%d)-(%d,%d)\n", hwnd,
582 rectWindow->left, rectWindow->top, rectWindow->right, rectWindow->bottom,
583 rectClient->left, rectClient->top, rectClient->right, rectClient->bottom );
585 WIN_ReleasePtr( win );
589 /***********************************************************************
590 * WIN_GetRectangles
592 * Get the window and client rectangles.
594 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
596 WND *win = WIN_GetPtr( hwnd );
597 BOOL ret = TRUE;
599 if (!win) return FALSE;
600 if (win == WND_OTHER_PROCESS)
602 SERVER_START_REQ( get_window_rectangles )
604 req->handle = hwnd;
605 if ((ret = !wine_server_call( req )))
607 if (rectWindow)
609 rectWindow->left = reply->window.left;
610 rectWindow->top = reply->window.top;
611 rectWindow->right = reply->window.right;
612 rectWindow->bottom = reply->window.bottom;
614 if (rectClient)
616 rectClient->left = reply->client.left;
617 rectClient->top = reply->client.top;
618 rectClient->right = reply->client.right;
619 rectClient->bottom = reply->client.bottom;
623 SERVER_END_REQ;
625 else
627 if (rectWindow) *rectWindow = win->rectWindow;
628 if (rectClient) *rectClient = win->rectClient;
629 WIN_ReleasePtr( win );
631 return ret;
635 /***********************************************************************
636 * WIN_DestroyWindow
638 * Destroy storage associated to a window. "Internals" p.358
640 LRESULT WIN_DestroyWindow( HWND hwnd )
642 WND *wndPtr;
643 HWND *list;
645 TRACE("%04x\n", hwnd );
647 if (!(hwnd = WIN_IsCurrentThread( hwnd )))
649 ERR( "window doesn't belong to current thread\n" );
650 return 0;
653 /* free child windows */
654 if ((list = WIN_ListChildren( hwnd )))
656 int i;
657 for (i = 0; list[i]; i++)
659 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
660 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
662 HeapFree( GetProcessHeap(), 0, list );
666 * Clear the update region to make sure no WM_PAINT messages will be
667 * generated for this window while processing the WM_NCDESTROY.
669 RedrawWindow( hwnd, NULL, 0,
670 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
673 * Send the WM_NCDESTROY to the window being destroyed.
675 SendMessageA( hwnd, WM_NCDESTROY, 0, 0);
677 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
679 WINPOS_CheckInternalPos( hwnd );
680 if( hwnd == GetCapture()) ReleaseCapture();
682 /* free resources associated with the window */
684 TIMER_RemoveWindowTimers( hwnd );
686 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
687 wndPtr->hmemTaskQ = 0;
689 if (!(wndPtr->dwStyle & WS_CHILD))
691 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
692 if (menu) DestroyMenu( menu );
694 if (wndPtr->hSysMenu)
696 DestroyMenu( wndPtr->hSysMenu );
697 wndPtr->hSysMenu = 0;
699 USER_Driver.pDestroyWindow( hwnd );
700 DCE_FreeWindowDCE( hwnd ); /* Always do this to catch orphaned DCs */
701 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
702 CLASS_RemoveWindow( wndPtr->class );
703 wndPtr->class = NULL;
704 wndPtr->dwMagic = 0; /* Mark it as invalid */
705 WIN_ReleaseWndPtr( wndPtr );
706 return 0;
709 /***********************************************************************
710 * WIN_DestroyThreadWindows
712 * Destroy all children of 'wnd' owned by the current thread.
713 * Return TRUE if something was done.
715 void WIN_DestroyThreadWindows( HWND hwnd )
717 HWND *list;
718 int i;
720 if (!(list = WIN_ListChildren( hwnd ))) return;
721 for (i = 0; list[i]; i++)
723 if (WIN_IsCurrentThread( list[i] ))
724 DestroyWindow( list[i] );
725 else
726 WIN_DestroyThreadWindows( list[i] );
728 HeapFree( GetProcessHeap(), 0, list );
731 /***********************************************************************
732 * WIN_CreateDesktopWindow
734 * Create the desktop window.
736 BOOL WIN_CreateDesktopWindow(void)
738 struct tagCLASS *class;
739 HWND hwndDesktop;
740 INT wndExtra;
741 DWORD clsStyle;
742 WNDPROC winproc;
743 DCE *dce;
744 CREATESTRUCTA cs;
745 RECT rect;
747 TRACE("Creating desktop window\n");
749 if (!WINPOS_CreateInternalPosAtom() ||
750 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
751 &wndExtra, &winproc, &clsStyle, &dce )))
752 return FALSE;
754 pWndDesktop = create_window_handle( 0, 0, LOWORD(DESKTOP_CLASS_ATOM),
755 sizeof(WND) + wndExtra - sizeof(pWndDesktop->wExtra) );
756 if (!pWndDesktop) return FALSE;
757 hwndDesktop = pWndDesktop->hwndSelf;
759 pWndDesktop->tid = 0; /* nobody owns the desktop */
760 pWndDesktop->parent = 0;
761 pWndDesktop->owner = 0;
762 pWndDesktop->class = class;
763 pWndDesktop->text = NULL;
764 pWndDesktop->hmemTaskQ = 0;
765 pWndDesktop->hrgnUpdate = 0;
766 pWndDesktop->clsStyle = clsStyle;
767 pWndDesktop->dce = NULL;
768 pWndDesktop->pVScroll = NULL;
769 pWndDesktop->pHScroll = NULL;
770 pWndDesktop->helpContext = 0;
771 pWndDesktop->flags = 0;
772 pWndDesktop->hSysMenu = 0;
773 pWndDesktop->winproc = winproc;
774 pWndDesktop->cbWndExtra = wndExtra;
776 cs.lpCreateParams = NULL;
777 cs.hInstance = 0;
778 cs.hMenu = 0;
779 cs.hwndParent = 0;
780 cs.x = 0;
781 cs.y = 0;
782 cs.cx = GetSystemMetrics( SM_CXSCREEN );
783 cs.cy = GetSystemMetrics( SM_CYSCREEN );
784 cs.style = pWndDesktop->dwStyle;
785 cs.dwExStyle = pWndDesktop->dwExStyle;
786 cs.lpszName = NULL;
787 cs.lpszClass = DESKTOP_CLASS_ATOM;
789 SetRect( &rect, 0, 0, cs.cx, cs.cy );
790 WIN_SetRectangles( hwndDesktop, &rect, &rect );
792 SERVER_START_REQ( set_window_info )
794 req->handle = hwndDesktop;
795 req->flags = 0; /* don't set anything, just retrieve */
796 wine_server_call( req );
797 pWndDesktop->dwStyle = reply->old_style;
798 pWndDesktop->dwExStyle = reply->old_ex_style;
799 pWndDesktop->hInstance = (ULONG_PTR)reply->old_instance;
800 pWndDesktop->userdata = (ULONG_PTR)reply->old_user_data;
801 pWndDesktop->wIDmenu = reply->old_id;
803 SERVER_END_REQ;
805 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE ))
807 WIN_ReleaseWndPtr( pWndDesktop );
808 return FALSE;
811 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
812 WIN_ReleaseWndPtr( pWndDesktop );
813 return TRUE;
817 /***********************************************************************
818 * WIN_FixCoordinates
820 * Fix the coordinates - Helper for WIN_CreateWindowEx.
821 * returns default show mode in sw.
822 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
824 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
826 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
827 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
829 if (cs->style & (WS_CHILD | WS_POPUP))
831 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
832 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
834 else /* overlapped window */
836 STARTUPINFOA info;
838 GetStartupInfoA( &info );
840 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
842 /* Never believe Microsoft's documentation... CreateWindowEx doc says
843 * that if an overlapped window is created with WS_VISIBLE style bit
844 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
845 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
846 * reveals that
848 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
849 * 2) it does not ignore the y parameter as the docs claim; instead, it
850 * uses it as second parameter to ShowWindow() unless y is either
851 * CW_USEDEFAULT or CW_USEDEFAULT16.
853 * The fact that we didn't do 2) caused bogus windows pop up when wine
854 * was running apps that were using this obscure feature. Example -
855 * calc.exe that comes with Win98 (only Win98, it's different from
856 * the one that comes with Win95 and NT)
858 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
859 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
860 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
863 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
865 if (info.dwFlags & STARTF_USESIZE)
867 cs->cx = info.dwXSize;
868 cs->cy = info.dwYSize;
870 else /* if no other hint from the app, pick 3/4 of the screen real estate */
872 RECT r;
873 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
874 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
875 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
880 else
882 /* neither x nor cx are default. Check the y values .
883 * In the trace we see Outlook and Outlook Express using
884 * cy set to CW_USEDEFAULT when opening the address book.
886 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16) {
887 RECT r;
888 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
889 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
890 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
895 /***********************************************************************
896 * dump_window_styles
898 static void dump_window_styles( DWORD style, DWORD exstyle )
900 TRACE( "style:" );
901 if(style & WS_POPUP) DPRINTF(" WS_POPUP");
902 if(style & WS_CHILD) DPRINTF(" WS_CHILD");
903 if(style & WS_MINIMIZE) DPRINTF(" WS_MINIMIZE");
904 if(style & WS_VISIBLE) DPRINTF(" WS_VISIBLE");
905 if(style & WS_DISABLED) DPRINTF(" WS_DISABLED");
906 if(style & WS_CLIPSIBLINGS) DPRINTF(" WS_CLIPSIBLINGS");
907 if(style & WS_CLIPCHILDREN) DPRINTF(" WS_CLIPCHILDREN");
908 if(style & WS_MAXIMIZE) DPRINTF(" WS_MAXIMIZE");
909 if((style & WS_CAPTION) == WS_CAPTION) DPRINTF(" WS_CAPTION");
910 else
912 if(style & WS_BORDER) DPRINTF(" WS_BORDER");
913 if(style & WS_DLGFRAME) DPRINTF(" WS_DLGFRAME");
915 if(style & WS_VSCROLL) DPRINTF(" WS_VSCROLL");
916 if(style & WS_HSCROLL) DPRINTF(" WS_HSCROLL");
917 if(style & WS_SYSMENU) DPRINTF(" WS_SYSMENU");
918 if(style & WS_THICKFRAME) DPRINTF(" WS_THICKFRAME");
919 if(style & WS_GROUP) DPRINTF(" WS_GROUP");
920 if(style & WS_TABSTOP) DPRINTF(" WS_TABSTOP");
921 if(style & WS_MINIMIZEBOX) DPRINTF(" WS_MINIMIZEBOX");
922 if(style & WS_MAXIMIZEBOX) DPRINTF(" WS_MAXIMIZEBOX");
924 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
925 #define DUMPED_STYLES \
926 (WS_POPUP | \
927 WS_CHILD | \
928 WS_MINIMIZE | \
929 WS_VISIBLE | \
930 WS_DISABLED | \
931 WS_CLIPSIBLINGS | \
932 WS_CLIPCHILDREN | \
933 WS_MAXIMIZE | \
934 WS_BORDER | \
935 WS_DLGFRAME | \
936 WS_VSCROLL | \
937 WS_HSCROLL | \
938 WS_SYSMENU | \
939 WS_THICKFRAME | \
940 WS_GROUP | \
941 WS_TABSTOP | \
942 WS_MINIMIZEBOX | \
943 WS_MAXIMIZEBOX)
945 if(style & ~DUMPED_STYLES) DPRINTF(" %08lx", style & ~DUMPED_STYLES);
946 DPRINTF("\n");
947 #undef DUMPED_STYLES
949 TRACE( "exstyle:" );
950 if(exstyle & WS_EX_DLGMODALFRAME) DPRINTF(" WS_EX_DLGMODALFRAME");
951 if(exstyle & WS_EX_DRAGDETECT) DPRINTF(" WS_EX_DRAGDETECT");
952 if(exstyle & WS_EX_NOPARENTNOTIFY) DPRINTF(" WS_EX_NOPARENTNOTIFY");
953 if(exstyle & WS_EX_TOPMOST) DPRINTF(" WS_EX_TOPMOST");
954 if(exstyle & WS_EX_ACCEPTFILES) DPRINTF(" WS_EX_ACCEPTFILES");
955 if(exstyle & WS_EX_TRANSPARENT) DPRINTF(" WS_EX_TRANSPARENT");
956 if(exstyle & WS_EX_MDICHILD) DPRINTF(" WS_EX_MDICHILD");
957 if(exstyle & WS_EX_TOOLWINDOW) DPRINTF(" WS_EX_TOOLWINDOW");
958 if(exstyle & WS_EX_WINDOWEDGE) DPRINTF(" WS_EX_WINDOWEDGE");
959 if(exstyle & WS_EX_CLIENTEDGE) DPRINTF(" WS_EX_CLIENTEDGE");
960 if(exstyle & WS_EX_CONTEXTHELP) DPRINTF(" WS_EX_CONTEXTHELP");
961 if(exstyle & WS_EX_RIGHT) DPRINTF(" WS_EX_RIGHT");
962 if(exstyle & WS_EX_RTLREADING) DPRINTF(" WS_EX_RTLREADING");
963 if(exstyle & WS_EX_LEFTSCROLLBAR) DPRINTF(" WS_EX_LEFTSCROLLBAR");
964 if(exstyle & WS_EX_CONTROLPARENT) DPRINTF(" WS_EX_CONTROLPARENT");
965 if(exstyle & WS_EX_STATICEDGE) DPRINTF(" WS_EX_STATICEDGE");
966 if(exstyle & WS_EX_APPWINDOW) DPRINTF(" WS_EX_APPWINDOW");
967 if(exstyle & WS_EX_LAYERED) DPRINTF(" WS_EX_LAYERED");
969 #define DUMPED_EX_STYLES \
970 (WS_EX_DLGMODALFRAME | \
971 WS_EX_DRAGDETECT | \
972 WS_EX_NOPARENTNOTIFY | \
973 WS_EX_TOPMOST | \
974 WS_EX_ACCEPTFILES | \
975 WS_EX_TRANSPARENT | \
976 WS_EX_MDICHILD | \
977 WS_EX_TOOLWINDOW | \
978 WS_EX_WINDOWEDGE | \
979 WS_EX_CLIENTEDGE | \
980 WS_EX_CONTEXTHELP | \
981 WS_EX_RIGHT | \
982 WS_EX_RTLREADING | \
983 WS_EX_LEFTSCROLLBAR | \
984 WS_EX_CONTROLPARENT | \
985 WS_EX_STATICEDGE | \
986 WS_EX_APPWINDOW | \
987 WS_EX_LAYERED)
989 if(exstyle & ~DUMPED_EX_STYLES) DPRINTF(" %08lx", exstyle & ~DUMPED_EX_STYLES);
990 DPRINTF("\n");
991 #undef DUMPED_EX_STYLES
995 /***********************************************************************
996 * WIN_CreateWindowEx
998 * Implementation of CreateWindowEx().
1000 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
1001 WINDOWPROCTYPE type )
1003 INT sw = SW_SHOW;
1004 struct tagCLASS *classPtr;
1005 WND *wndPtr;
1006 HWND hwnd, parent, owner;
1007 INT wndExtra;
1008 DWORD clsStyle;
1009 WNDPROC winproc;
1010 DCE *dce;
1011 BOOL unicode = (type == WIN_PROC_32W);
1013 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%04x menu=%04x inst=%08x params=%p\n",
1014 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
1015 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszClass) : debugstr_a(cs->lpszClass),
1016 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
1017 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
1019 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
1021 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
1022 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
1024 /* Find the parent window */
1026 parent = GetDesktopWindow();
1027 owner = 0;
1029 if (cs->hwndParent == HWND_MESSAGE)
1031 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
1032 * message window (style: WS_POPUP|WS_DISABLED)
1034 FIXME("Parent is HWND_MESSAGE\n");
1036 else if (cs->hwndParent)
1038 /* Make sure parent is valid */
1039 if (!IsWindow( cs->hwndParent ))
1041 WARN("Bad parent %04x\n", cs->hwndParent );
1042 return 0;
1044 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1045 parent = WIN_GetFullHandle(cs->hwndParent);
1046 else
1047 owner = GetAncestor( cs->hwndParent, GA_ROOT );
1049 else if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1051 WARN("No parent for child window\n" );
1052 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1055 /* Find the window class */
1056 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
1057 &wndExtra, &winproc, &clsStyle, &dce )))
1059 WARN("Bad class '%s'\n", cs->lpszClass );
1060 return 0;
1063 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
1065 /* Correct the window style - stage 1
1067 * These are patches that appear to affect both the style loaded into the
1068 * WIN structure and passed in the CreateStruct to the WM_CREATE etc.
1070 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1071 * why does the user get to set it?
1074 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
1075 * tested for WS_POPUP
1077 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
1078 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
1079 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
1080 cs->dwExStyle |= WS_EX_WINDOWEDGE;
1081 else
1082 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
1084 /* Create the window structure */
1086 if (!(wndPtr = create_window_handle( parent, owner, classAtom,
1087 sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
1089 TRACE("out of memory\n" );
1090 return 0;
1092 hwnd = wndPtr->hwndSelf;
1094 /* Fill the window structure */
1096 wndPtr->tid = GetCurrentThreadId();
1097 wndPtr->owner = owner;
1098 wndPtr->parent = parent;
1099 wndPtr->class = classPtr;
1100 wndPtr->winproc = winproc;
1101 wndPtr->hInstance = cs->hInstance;
1102 wndPtr->text = NULL;
1103 wndPtr->hmemTaskQ = InitThreadInput16( 0, 0 );
1104 wndPtr->hrgnUpdate = 0;
1105 wndPtr->hrgnWnd = 0;
1106 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1107 wndPtr->dwExStyle = cs->dwExStyle;
1108 wndPtr->clsStyle = clsStyle;
1109 wndPtr->wIDmenu = 0;
1110 wndPtr->helpContext = 0;
1111 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
1112 wndPtr->pVScroll = NULL;
1113 wndPtr->pHScroll = NULL;
1114 wndPtr->userdata = 0;
1115 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
1116 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
1117 wndPtr->cbWndExtra = wndExtra;
1119 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
1121 /* Correct the window style - stage 2 */
1123 if (!(cs->style & WS_CHILD))
1125 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1126 if (!(cs->style & WS_POPUP))
1128 wndPtr->dwStyle |= WS_CAPTION;
1129 wndPtr->flags |= WIN_NEED_SIZE;
1132 SERVER_START_REQ( set_window_info )
1134 req->handle = hwnd;
1135 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE;
1136 req->style = wndPtr->dwStyle;
1137 req->ex_style = wndPtr->dwExStyle;
1138 req->instance = (void *)wndPtr->hInstance;
1139 wine_server_call( req );
1141 SERVER_END_REQ;
1143 /* Get class or window DC if needed */
1145 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
1146 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
1147 else wndPtr->dce = NULL;
1149 /* Set the window menu */
1151 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
1153 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
1154 else
1156 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
1157 if (menuName)
1159 if (HIWORD(cs->hInstance))
1160 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1161 else
1162 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
1164 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
1168 else SetWindowLongW( hwnd, GWL_ID, (UINT)cs->hMenu );
1169 WIN_ReleaseWndPtr( wndPtr );
1171 if (!USER_Driver.pCreateWindow( hwnd, cs, unicode))
1173 WIN_DestroyWindow( hwnd );
1174 return 0;
1177 /* Notify the parent window only */
1179 send_parent_notify( hwnd, WM_CREATE );
1180 if (!IsWindow( hwnd )) return 0;
1182 if (cs->style & WS_VISIBLE)
1184 /* in case WS_VISIBLE got set in the meantime */
1185 if (!(wndPtr = WIN_GetPtr( hwnd ))) return 0;
1186 WIN_SetStyle( hwnd, wndPtr->dwStyle & ~WS_VISIBLE );
1187 WIN_ReleasePtr( wndPtr );
1188 ShowWindow( hwnd, sw );
1191 /* Call WH_SHELL hook */
1193 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1194 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0 );
1196 TRACE("created window %04x\n", hwnd);
1197 return hwnd;
1201 /***********************************************************************
1202 * CreateWindow (USER.41)
1204 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1205 DWORD style, INT16 x, INT16 y, INT16 width,
1206 INT16 height, HWND16 parent, HMENU16 menu,
1207 HINSTANCE16 instance, LPVOID data )
1209 return CreateWindowEx16( 0, className, windowName, style,
1210 x, y, width, height, parent, menu, instance, data );
1214 /***********************************************************************
1215 * CreateWindowEx (USER.452)
1217 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1218 LPCSTR windowName, DWORD style, INT16 x,
1219 INT16 y, INT16 width, INT16 height,
1220 HWND16 parent, HMENU16 menu,
1221 HINSTANCE16 instance, LPVOID data )
1223 ATOM classAtom;
1224 CREATESTRUCTA cs;
1225 char buffer[256];
1227 /* Find the class atom */
1229 if (HIWORD(className))
1231 if (!(classAtom = GlobalFindAtomA( className )))
1233 ERR( "bad class name %s\n", debugstr_a(className) );
1234 return 0;
1237 else
1239 classAtom = LOWORD(className);
1240 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1242 ERR( "bad atom %x\n", classAtom);
1243 return 0;
1245 className = buffer;
1248 /* Fix the coordinates */
1250 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1251 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1252 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1253 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1255 /* Create the window */
1257 cs.lpCreateParams = data;
1258 cs.hInstance = (HINSTANCE)instance;
1259 cs.hMenu = (HMENU)menu;
1260 cs.hwndParent = WIN_Handle32( parent );
1261 cs.style = style;
1262 cs.lpszName = windowName;
1263 cs.lpszClass = className;
1264 cs.dwExStyle = exStyle;
1266 return HWND_16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
1270 /***********************************************************************
1271 * CreateWindowExA (USER32.@)
1273 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1274 LPCSTR windowName, DWORD style, INT x,
1275 INT y, INT width, INT height,
1276 HWND parent, HMENU menu,
1277 HINSTANCE instance, LPVOID data )
1279 ATOM classAtom;
1280 CREATESTRUCTA cs;
1281 char buffer[256];
1283 if(!instance)
1284 instance=GetModuleHandleA(NULL);
1286 if(exStyle & WS_EX_MDICHILD)
1287 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1289 /* Find the class atom */
1291 if (HIWORD(className))
1293 if (!(classAtom = GlobalFindAtomA( className )))
1295 ERR( "bad class name %s\n", debugstr_a(className) );
1296 return 0;
1299 else
1301 classAtom = LOWORD(className);
1302 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1304 ERR( "bad atom %x\n", classAtom);
1305 return 0;
1307 className = buffer;
1310 /* Create the window */
1312 cs.lpCreateParams = data;
1313 cs.hInstance = instance;
1314 cs.hMenu = menu;
1315 cs.hwndParent = parent;
1316 cs.x = x;
1317 cs.y = y;
1318 cs.cx = width;
1319 cs.cy = height;
1320 cs.style = style;
1321 cs.lpszName = windowName;
1322 cs.lpszClass = className;
1323 cs.dwExStyle = exStyle;
1325 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1329 /***********************************************************************
1330 * CreateWindowExW (USER32.@)
1332 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1333 LPCWSTR windowName, DWORD style, INT x,
1334 INT y, INT width, INT height,
1335 HWND parent, HMENU menu,
1336 HINSTANCE instance, LPVOID data )
1338 ATOM classAtom;
1339 CREATESTRUCTW cs;
1340 WCHAR buffer[256];
1342 if(!instance)
1343 instance=GetModuleHandleA(NULL);
1345 if(exStyle & WS_EX_MDICHILD)
1346 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1348 /* Find the class atom */
1350 if (HIWORD(className))
1352 if (!(classAtom = GlobalFindAtomW( className )))
1354 ERR( "bad class name %s\n", debugstr_w(className) );
1355 return 0;
1358 else
1360 classAtom = LOWORD(className);
1361 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1363 ERR( "bad atom %x\n", classAtom);
1364 return 0;
1366 className = buffer;
1369 /* Create the window */
1371 cs.lpCreateParams = data;
1372 cs.hInstance = instance;
1373 cs.hMenu = menu;
1374 cs.hwndParent = parent;
1375 cs.x = x;
1376 cs.y = y;
1377 cs.cx = width;
1378 cs.cy = height;
1379 cs.style = style;
1380 cs.lpszName = windowName;
1381 cs.lpszClass = className;
1382 cs.dwExStyle = exStyle;
1384 /* Note: we rely on the fact that CREATESTRUCTA and */
1385 /* CREATESTRUCTW have the same layout. */
1386 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1390 /***********************************************************************
1391 * WIN_SendDestroyMsg
1393 static void WIN_SendDestroyMsg( HWND hwnd )
1395 GUITHREADINFO info;
1397 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1399 if (hwnd == info.hwndCaret) DestroyCaret();
1401 if (USER_Driver.pResetSelectionOwner)
1402 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1405 * Send the WM_DESTROY to the window.
1407 SendMessageA( hwnd, WM_DESTROY, 0, 0);
1410 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1411 * make sure that the window still exists when we come back.
1413 if (IsWindow(hwnd))
1415 HWND* pWndArray;
1416 int i;
1418 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1420 /* start from the end (FIXME: is this needed?) */
1421 for (i = 0; pWndArray[i]; i++) ;
1423 while (--i >= 0)
1425 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1427 HeapFree( GetProcessHeap(), 0, pWndArray );
1429 else
1430 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1434 /***********************************************************************
1435 * DestroyWindow (USER32.@)
1437 BOOL WINAPI DestroyWindow( HWND hwnd )
1439 BOOL is_child;
1440 HWND h;
1442 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1444 SetLastError( ERROR_ACCESS_DENIED );
1445 return FALSE;
1448 TRACE("(%04x)\n", hwnd);
1450 /* Look whether the focus is within the tree of windows we will
1451 * be destroying.
1453 h = GetFocus();
1454 if (h == hwnd || IsChild( hwnd, h ))
1456 HWND parent = GetAncestor( hwnd, GA_PARENT );
1457 if (parent == GetDesktopWindow()) parent = 0;
1458 SetFocus( parent );
1461 /* Call hooks */
1463 if( HOOK_CallHooksA( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0L) ) return FALSE;
1465 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1467 if (is_child)
1469 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1470 send_parent_notify( hwnd, WM_DESTROY );
1472 else if (!GetWindow( hwnd, GW_OWNER ))
1474 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L );
1475 /* FIXME: clean up palette - see "Internals" p.352 */
1478 if (!IsWindow(hwnd)) return TRUE;
1480 if (USER_Driver.pResetSelectionOwner)
1481 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1483 /* Hide the window */
1485 if (!ShowWindow( hwnd, SW_HIDE ))
1487 if (hwnd == GetActiveWindow()) WINPOS_ActivateOtherWindow( hwnd );
1489 if (!IsWindow(hwnd)) return TRUE;
1491 /* Recursively destroy owned windows */
1493 if (!is_child)
1495 for (;;)
1497 int i, got_one = 0;
1498 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1499 if (list)
1501 for (i = 0; list[i]; i++)
1503 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1504 if (WIN_IsCurrentThread( list[i] ))
1506 DestroyWindow( list[i] );
1507 got_one = 1;
1508 continue;
1510 WIN_SetOwner( list[i], 0 );
1512 HeapFree( GetProcessHeap(), 0, list );
1514 if (!got_one) break;
1518 /* Send destroy messages */
1520 WIN_SendDestroyMsg( hwnd );
1521 if (!IsWindow( hwnd )) return TRUE;
1523 /* Unlink now so we won't bother with the children later on */
1525 WIN_UnlinkWindow( hwnd );
1527 /* Destroy the window storage */
1529 WIN_DestroyWindow( hwnd );
1530 return TRUE;
1534 /***********************************************************************
1535 * CloseWindow (USER32.@)
1537 BOOL WINAPI CloseWindow( HWND hwnd )
1539 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1540 ShowWindow( hwnd, SW_MINIMIZE );
1541 return TRUE;
1545 /***********************************************************************
1546 * OpenIcon (USER32.@)
1548 BOOL WINAPI OpenIcon( HWND hwnd )
1550 if (!IsIconic( hwnd )) return FALSE;
1551 ShowWindow( hwnd, SW_SHOWNORMAL );
1552 return TRUE;
1556 /***********************************************************************
1557 * WIN_FindWindow
1559 * Implementation of FindWindow() and FindWindowEx().
1561 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1563 HWND *list = NULL;
1564 HWND retvalue = 0;
1565 int i = 0, len = 0;
1566 WCHAR *buffer = NULL;
1568 if (!parent) parent = GetDesktopWindow();
1569 if (title)
1571 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1572 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1575 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1577 if (child)
1579 child = WIN_GetFullHandle( child );
1580 while (list[i] && list[i] != child) i++;
1581 if (!list[i]) goto done;
1582 i++; /* start from next window */
1585 if (title)
1587 while (list[i])
1589 if (GetWindowTextW( list[i], buffer, len ) && !strcmpiW( buffer, title )) break;
1590 i++;
1593 retvalue = list[i];
1595 done:
1596 if (list) HeapFree( GetProcessHeap(), 0, list );
1597 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1598 return retvalue;
1603 /***********************************************************************
1604 * FindWindowA (USER32.@)
1606 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1608 HWND ret = FindWindowExA( 0, 0, className, title );
1609 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1610 return ret;
1614 /***********************************************************************
1615 * FindWindowExA (USER32.@)
1617 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1618 LPCSTR className, LPCSTR title )
1620 ATOM atom = 0;
1621 LPWSTR buffer;
1622 HWND hwnd;
1623 INT len;
1625 if (className)
1627 /* If the atom doesn't exist, then no class */
1628 /* with this name exists either. */
1629 if (!(atom = GlobalFindAtomA( className )))
1631 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1632 return 0;
1635 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
1637 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1638 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1639 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
1640 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1641 HeapFree( GetProcessHeap(), 0, buffer );
1642 return hwnd;
1646 /***********************************************************************
1647 * FindWindowExW (USER32.@)
1649 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1650 LPCWSTR className, LPCWSTR title )
1652 ATOM atom = 0;
1654 if (className)
1656 /* If the atom doesn't exist, then no class */
1657 /* with this name exists either. */
1658 if (!(atom = GlobalFindAtomW( className )))
1660 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1661 return 0;
1664 return WIN_FindWindow( parent, child, atom, title );
1668 /***********************************************************************
1669 * FindWindowW (USER32.@)
1671 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1673 return FindWindowExW( 0, 0, className, title );
1677 /**********************************************************************
1678 * GetDesktopWindow (USER32.@)
1680 HWND WINAPI GetDesktopWindow(void)
1682 if (pWndDesktop) return pWndDesktop->hwndSelf;
1683 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" );
1684 ExitProcess(1);
1685 return 0;
1689 /*******************************************************************
1690 * EnableWindow (USER32.@)
1692 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1694 WND *wndPtr;
1695 BOOL retvalue;
1696 LONG style;
1697 HWND full_handle;
1699 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1700 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1702 hwnd = full_handle;
1704 TRACE("( %x, %d )\n", hwnd, enable);
1706 if (!(wndPtr = WIN_GetPtr( hwnd ))) return FALSE;
1707 style = wndPtr->dwStyle;
1708 retvalue = ((style & WS_DISABLED) != 0);
1709 WIN_ReleasePtr( wndPtr );
1711 if (enable && retvalue)
1713 WIN_SetStyle( hwnd, style & ~WS_DISABLED );
1714 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1716 else if (!enable && !retvalue)
1718 SendMessageA( hwnd, WM_CANCELMODE, 0, 0);
1720 WIN_SetStyle( hwnd, style | WS_DISABLED );
1722 if (hwnd == GetFocus() || IsChild(hwnd, GetFocus()))
1723 SetFocus( 0 ); /* A disabled window can't have the focus */
1725 if (hwnd == GetCapture() || IsChild(hwnd, GetCapture()))
1726 ReleaseCapture(); /* A disabled window can't capture the mouse */
1728 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1730 return retvalue;
1734 /***********************************************************************
1735 * IsWindowEnabled (USER32.@)
1737 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1739 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1743 /***********************************************************************
1744 * IsWindowUnicode (USER32.@)
1746 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1748 WND * wndPtr;
1749 BOOL retvalue;
1751 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1752 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1753 WIN_ReleaseWndPtr(wndPtr);
1754 return retvalue;
1758 /**********************************************************************
1759 * GetWindowWord (USER32.@)
1761 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1763 if (offset >= 0)
1765 WORD retvalue = 0;
1766 WND *wndPtr = WIN_GetPtr( hwnd );
1767 if (!wndPtr)
1769 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1770 return 0;
1772 if (wndPtr == WND_OTHER_PROCESS)
1774 if (IsWindow( hwnd ))
1775 FIXME( "(%d) not supported yet on other process window %x\n", offset, hwnd );
1776 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1777 return 0;
1779 if (offset > wndPtr->cbWndExtra - sizeof(WORD))
1781 WARN("Invalid offset %d\n", offset );
1782 SetLastError( ERROR_INVALID_INDEX );
1784 else retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1785 WIN_ReleasePtr( wndPtr );
1786 return retvalue;
1789 switch(offset)
1791 case GWL_HWNDPARENT:
1792 return GetWindowLongW( hwnd, offset );
1793 case GWL_ID:
1794 case GWL_HINSTANCE:
1796 LONG ret = GetWindowLongW( hwnd, offset );
1797 if (HIWORD(ret))
1798 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1799 return LOWORD(ret);
1801 default:
1802 WARN("Invalid offset %d\n", offset );
1803 return 0;
1808 /**********************************************************************
1809 * SetWindowWord (USER32.@)
1811 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1813 WORD *ptr, retval;
1814 WND * wndPtr;
1816 switch(offset)
1818 case GWL_ID:
1819 case GWL_HINSTANCE:
1820 case GWL_HWNDPARENT:
1821 return SetWindowLongW( hwnd, offset, (UINT)newval );
1822 default:
1823 if (offset < 0)
1825 WARN("Invalid offset %d\n", offset );
1826 SetLastError( ERROR_INVALID_INDEX );
1827 return 0;
1831 wndPtr = WIN_GetPtr( hwnd );
1832 if (wndPtr == WND_OTHER_PROCESS)
1834 if (IsWindow(hwnd))
1835 FIXME( "set %d <- %x not supported yet on other process window %x\n",
1836 offset, newval, hwnd );
1837 wndPtr = NULL;
1839 if (!wndPtr)
1841 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1842 return 0;
1845 if (offset > wndPtr->cbWndExtra - sizeof(WORD))
1847 WARN("Invalid offset %d\n", offset );
1848 WIN_ReleasePtr(wndPtr);
1849 SetLastError( ERROR_INVALID_INDEX );
1850 return 0;
1852 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1853 retval = *ptr;
1854 *ptr = newval;
1855 WIN_ReleasePtr(wndPtr);
1856 return retval;
1860 /**********************************************************************
1861 * WIN_GetWindowLong
1863 * Helper function for GetWindowLong().
1865 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1867 LONG retvalue = 0;
1868 WND *wndPtr;
1870 if (offset == GWL_HWNDPARENT)
1872 HWND parent = GetAncestor( hwnd, GA_PARENT );
1873 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1874 return (LONG)parent;
1877 if (!(wndPtr = WIN_GetPtr( hwnd )))
1879 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1880 return 0;
1883 if (wndPtr == WND_OTHER_PROCESS)
1885 if (offset >= 0)
1887 if (IsWindow(hwnd))
1888 FIXME( "(%d) not supported on other process window %x\n", offset, hwnd );
1889 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1890 return 0;
1892 if (offset == GWL_WNDPROC)
1894 SetLastError( ERROR_ACCESS_DENIED );
1895 return 0;
1897 SERVER_START_REQ( set_window_info )
1899 req->handle = hwnd;
1900 req->flags = 0; /* don't set anything, just retrieve */
1901 if (!wine_server_call_err( req ))
1903 switch(offset)
1905 case GWL_STYLE: retvalue = reply->old_style; break;
1906 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1907 case GWL_ID: retvalue = reply->old_id; break;
1908 case GWL_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1909 case GWL_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
1910 default:
1911 SetLastError( ERROR_INVALID_INDEX );
1912 break;
1916 SERVER_END_REQ;
1917 return retvalue;
1920 /* now we have a valid wndPtr */
1922 if (offset >= 0)
1924 if (offset > wndPtr->cbWndExtra - sizeof(LONG))
1927 * Some programs try to access last element from 16 bit
1928 * code using illegal offset value. Hopefully this is
1929 * what those programs really expect.
1931 if (type == WIN_PROC_16 &&
1932 wndPtr->cbWndExtra >= 4 &&
1933 offset == wndPtr->cbWndExtra - sizeof(WORD))
1935 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
1937 ERR( "- replaced invalid offset %d with %d\n",
1938 offset, offset2 );
1940 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset2);
1941 WIN_ReleasePtr( wndPtr );
1942 return retvalue;
1944 WARN("Invalid offset %d\n", offset );
1945 WIN_ReleasePtr( wndPtr );
1946 SetLastError( ERROR_INVALID_INDEX );
1947 return 0;
1949 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1950 /* Special case for dialog window procedure */
1951 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1952 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1953 WIN_ReleasePtr( wndPtr );
1954 return retvalue;
1957 switch(offset)
1959 case GWL_USERDATA: retvalue = wndPtr->userdata; break;
1960 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1961 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1962 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu; break;
1963 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc, type ); break;
1964 case GWL_HINSTANCE: retvalue = wndPtr->hInstance; break;
1965 default:
1966 WARN("Unknown offset %d\n", offset );
1967 SetLastError( ERROR_INVALID_INDEX );
1968 break;
1970 WIN_ReleasePtr(wndPtr);
1971 return retvalue;
1975 /**********************************************************************
1976 * WIN_SetWindowLong
1978 * Helper function for SetWindowLong().
1980 * 0 is the failure code. However, in the case of failure SetLastError
1981 * must be set to distinguish between a 0 return value and a failure.
1983 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1984 WINDOWPROCTYPE type )
1986 LONG retval = 0;
1987 WND *wndPtr;
1989 TRACE( "%x %d %lx %x\n", hwnd, offset, newval, type );
1991 if (!WIN_IsCurrentProcess( hwnd ))
1993 if (offset == GWL_WNDPROC)
1995 SetLastError( ERROR_ACCESS_DENIED );
1996 return 0;
1998 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
2001 wndPtr = WIN_GetPtr( hwnd );
2002 if (wndPtr->hwndSelf == GetDesktopWindow())
2004 /* can't change anything on the desktop window */
2005 WIN_ReleasePtr( wndPtr );
2006 SetLastError( ERROR_ACCESS_DENIED );
2007 return 0;
2010 if (offset >= 0)
2012 LONG *ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
2013 if (offset > wndPtr->cbWndExtra - sizeof(LONG))
2015 WARN("Invalid offset %d\n", offset );
2016 WIN_ReleasePtr( wndPtr );
2017 SetLastError( ERROR_INVALID_INDEX );
2018 return 0;
2020 /* Special case for dialog window procedure */
2021 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2023 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
2024 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
2025 type, WIN_PROC_WINDOW );
2026 WIN_ReleasePtr( wndPtr );
2027 return retval;
2029 retval = *ptr;
2030 *ptr = newval;
2031 WIN_ReleasePtr( wndPtr );
2033 else
2035 STYLESTRUCT style;
2036 BOOL ok;
2038 /* first some special cases */
2039 switch( offset )
2041 case GWL_STYLE:
2042 case GWL_EXSTYLE:
2043 style.styleOld = wndPtr->dwStyle;
2044 style.styleNew = newval;
2045 WIN_ReleasePtr( wndPtr );
2046 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
2047 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
2048 newval = style.styleNew;
2049 break;
2050 case GWL_HWNDPARENT:
2051 if (wndPtr->parent == GetDesktopWindow())
2053 WIN_ReleasePtr( wndPtr );
2054 return (LONG)WIN_SetOwner( hwnd, (HWND)newval );
2056 else
2058 WIN_ReleasePtr( wndPtr );
2059 return (LONG)SetParent( hwnd, (HWND)newval );
2061 case GWL_WNDPROC:
2062 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2063 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
2064 type, WIN_PROC_WINDOW );
2065 WIN_ReleasePtr( wndPtr );
2066 return retval;
2067 case GWL_ID:
2068 case GWL_HINSTANCE:
2069 case GWL_USERDATA:
2070 break;
2071 default:
2072 WIN_ReleasePtr( wndPtr );
2073 WARN("Invalid offset %d\n", offset );
2074 SetLastError( ERROR_INVALID_INDEX );
2075 return 0;
2078 SERVER_START_REQ( set_window_info )
2080 req->handle = hwnd;
2081 switch(offset)
2083 case GWL_STYLE:
2084 req->flags = SET_WIN_STYLE;
2085 req->style = newval;
2086 break;
2087 case GWL_EXSTYLE:
2088 req->flags = SET_WIN_EXSTYLE;
2089 req->ex_style = newval;
2090 break;
2091 case GWL_ID:
2092 req->flags = SET_WIN_ID;
2093 req->id = newval;
2094 break;
2095 case GWL_HINSTANCE:
2096 req->flags = SET_WIN_INSTANCE;
2097 req->instance = (void *)newval;
2098 break;
2099 case GWL_USERDATA:
2100 req->flags = SET_WIN_USERDATA;
2101 req->user_data = (void *)newval;
2102 break;
2104 if ((ok = !wine_server_call_err( req )))
2106 switch(offset)
2108 case GWL_STYLE:
2109 wndPtr->dwStyle = newval;
2110 retval = reply->old_style;
2111 break;
2112 case GWL_EXSTYLE:
2113 wndPtr->dwExStyle = newval;
2114 retval = reply->old_ex_style;
2115 break;
2116 case GWL_ID:
2117 wndPtr->wIDmenu = newval;
2118 retval = reply->old_id;
2119 break;
2120 case GWL_HINSTANCE:
2121 wndPtr->hInstance = newval;
2122 retval = (HINSTANCE)reply->old_instance;
2123 break;
2124 case GWL_USERDATA:
2125 wndPtr->userdata = newval;
2126 retval = (ULONG_PTR)reply->old_user_data;
2127 break;
2131 SERVER_END_REQ;
2132 WIN_ReleasePtr( wndPtr );
2134 if (!ok) return 0;
2136 if (offset == GWL_STYLE && USER_Driver.pSetWindowStyle)
2137 USER_Driver.pSetWindowStyle( hwnd, retval );
2139 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2140 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2143 return retval;
2147 /**********************************************************************
2148 * GetWindowLong (USER.135)
2150 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2152 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
2156 /**********************************************************************
2157 * GetWindowLongA (USER32.@)
2159 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2161 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2165 /**********************************************************************
2166 * GetWindowLongW (USER32.@)
2168 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2170 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2174 /**********************************************************************
2175 * SetWindowLong (USER.136)
2177 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2179 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
2183 /**********************************************************************
2184 * SetWindowLongA (USER32.@)
2186 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2188 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2192 /**********************************************************************
2193 * SetWindowLongW (USER32.@) Set window attribute
2195 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2196 * value in a window's extra memory.
2198 * The _hwnd_ parameter specifies the window. is the handle to a
2199 * window that has extra memory. The _newval_ parameter contains the
2200 * new attribute or extra memory value. If positive, the _offset_
2201 * parameter is the byte-addressed location in the window's extra
2202 * memory to set. If negative, _offset_ specifies the window
2203 * attribute to set, and should be one of the following values:
2205 * GWL_EXSTYLE The window's extended window style
2207 * GWL_STYLE The window's window style.
2209 * GWL_WNDPROC Pointer to the window's window procedure.
2211 * GWL_HINSTANCE The window's pplication instance handle.
2213 * GWL_ID The window's identifier.
2215 * GWL_USERDATA The window's user-specified data.
2217 * If the window is a dialog box, the _offset_ parameter can be one of
2218 * the following values:
2220 * DWL_DLGPROC The address of the window's dialog box procedure.
2222 * DWL_MSGRESULT The return value of a message
2223 * that the dialog box procedure processed.
2225 * DWL_USER Application specific information.
2227 * RETURNS
2229 * If successful, returns the previous value located at _offset_. Otherwise,
2230 * returns 0.
2232 * NOTES
2234 * Extra memory for a window class is specified by a nonzero cbWndExtra
2235 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2236 * time of class creation.
2238 * Using GWL_WNDPROC to set a new window procedure effectively creates
2239 * a window subclass. Use CallWindowProc() in the new windows procedure
2240 * to pass messages to the superclass's window procedure.
2242 * The user data is reserved for use by the application which created
2243 * the window.
2245 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2246 * instead, call the EnableWindow() function to change the window's
2247 * disabled state.
2249 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2250 * SetParent() instead.
2252 * Win95:
2253 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2254 * it sends WM_STYLECHANGING before changing the settings
2255 * and WM_STYLECHANGED afterwards.
2256 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2258 LONG WINAPI SetWindowLongW(
2259 HWND hwnd, /* [in] window to alter */
2260 INT offset, /* [in] offset, in bytes, of location to alter */
2261 LONG newval /* [in] new value of location */
2263 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2267 /*******************************************************************
2268 * GetWindowTextA (USER32.@)
2270 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2272 WCHAR *buffer;
2274 if (WIN_IsCurrentProcess( hwnd ))
2275 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2277 /* when window belongs to other process, don't send a message */
2278 if (nMaxCount <= 0) return 0;
2279 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2280 get_server_window_text( hwnd, buffer, nMaxCount );
2281 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2282 lpString[nMaxCount-1] = 0;
2283 HeapFree( GetProcessHeap(), 0, buffer );
2284 return strlen(lpString);
2288 /*******************************************************************
2289 * InternalGetWindowText (USER32.@)
2291 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2293 WND *win;
2295 if (nMaxCount <= 0) return 0;
2296 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2297 if (win != WND_OTHER_PROCESS)
2299 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2300 else lpString[0] = 0;
2301 WIN_ReleasePtr( win );
2303 else
2305 get_server_window_text( hwnd, lpString, nMaxCount );
2307 return strlenW(lpString);
2311 /*******************************************************************
2312 * GetWindowTextW (USER32.@)
2314 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2316 if (WIN_IsCurrentProcess( hwnd ))
2317 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2319 /* when window belongs to other process, don't send a message */
2320 if (nMaxCount <= 0) return 0;
2321 get_server_window_text( hwnd, lpString, nMaxCount );
2322 return strlenW(lpString);
2326 /*******************************************************************
2327 * SetWindowText (USER32.@)
2328 * SetWindowTextA (USER32.@)
2330 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2332 if (!WIN_IsCurrentProcess( hwnd ))
2334 FIXME( "cannot set text %s of other process window %x\n", debugstr_a(lpString), hwnd );
2335 SetLastError( ERROR_ACCESS_DENIED );
2336 return FALSE;
2338 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2342 /*******************************************************************
2343 * SetWindowTextW (USER32.@)
2345 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2347 if (!WIN_IsCurrentProcess( hwnd ))
2349 FIXME( "cannot set text %s of other process window %x\n", debugstr_w(lpString), hwnd );
2350 SetLastError( ERROR_ACCESS_DENIED );
2351 return FALSE;
2353 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2357 /*******************************************************************
2358 * GetWindowTextLengthA (USER32.@)
2360 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2362 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2365 /*******************************************************************
2366 * GetWindowTextLengthW (USER32.@)
2368 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2370 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2374 /*******************************************************************
2375 * IsWindow (USER32.@)
2377 BOOL WINAPI IsWindow( HWND hwnd )
2379 WND *ptr;
2380 BOOL ret;
2382 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2384 if (ptr != WND_OTHER_PROCESS)
2386 WIN_ReleasePtr( ptr );
2387 return TRUE;
2390 /* check other processes */
2391 SERVER_START_REQ( get_window_info )
2393 req->handle = hwnd;
2394 ret = !wine_server_call_err( req );
2396 SERVER_END_REQ;
2397 return ret;
2401 /***********************************************************************
2402 * GetWindowThreadProcessId (USER32.@)
2404 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2406 WND *ptr;
2407 DWORD tid = 0;
2409 if (!(ptr = WIN_GetPtr( hwnd )))
2411 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2412 return 0;
2415 if (ptr != WND_OTHER_PROCESS)
2417 /* got a valid window */
2418 tid = ptr->tid;
2419 if (process) *process = GetCurrentProcessId();
2420 WIN_ReleasePtr( ptr );
2421 return tid;
2424 /* check other processes */
2425 SERVER_START_REQ( get_window_info )
2427 req->handle = hwnd;
2428 if (!wine_server_call_err( req ))
2430 tid = (DWORD)reply->tid;
2431 if (process) *process = (DWORD)reply->pid;
2434 SERVER_END_REQ;
2435 return tid;
2439 /*****************************************************************
2440 * GetParent (USER32.@)
2442 HWND WINAPI GetParent( HWND hwnd )
2444 WND *wndPtr;
2445 HWND retvalue = 0;
2447 if (!(wndPtr = WIN_GetPtr( hwnd )))
2449 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2450 return 0;
2452 if (wndPtr == WND_OTHER_PROCESS)
2454 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2455 if (style & (WS_POPUP | WS_CHILD))
2457 SERVER_START_REQ( get_window_tree )
2459 req->handle = hwnd;
2460 if (!wine_server_call_err( req ))
2462 if (style & WS_POPUP) retvalue = reply->owner;
2463 else if (style & WS_CHILD) retvalue = reply->parent;
2466 SERVER_END_REQ;
2469 else
2471 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2472 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2473 WIN_ReleasePtr( wndPtr );
2475 return retvalue;
2479 /*****************************************************************
2480 * GetAncestor (USER32.@)
2482 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2484 WND *win;
2485 HWND *list, ret = 0;
2487 switch(type)
2489 case GA_PARENT:
2490 if (!(win = WIN_GetPtr( hwnd )))
2492 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2493 return 0;
2495 if (win != WND_OTHER_PROCESS)
2497 ret = win->parent;
2498 WIN_ReleasePtr( win );
2500 else /* need to query the server */
2502 SERVER_START_REQ( get_window_tree )
2504 req->handle = hwnd;
2505 if (!wine_server_call_err( req )) ret = reply->parent;
2507 SERVER_END_REQ;
2509 break;
2511 case GA_ROOT:
2512 if (!(list = WIN_ListParents( hwnd ))) return 0;
2514 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2515 else
2517 int count = 2;
2518 while (list[count]) count++;
2519 ret = list[count - 2]; /* get the one before the desktop */
2521 HeapFree( GetProcessHeap(), 0, list );
2522 break;
2524 case GA_ROOTOWNER:
2525 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2526 for (;;)
2528 HWND parent = GetParent( ret );
2529 if (!parent) break;
2530 ret = parent;
2532 break;
2534 return ret;
2538 /*****************************************************************
2539 * SetParent (USER32.@)
2541 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2543 WND *wndPtr;
2544 HWND retvalue, full_handle;
2545 BOOL was_visible;
2547 if (!parent) parent = GetDesktopWindow();
2548 else parent = WIN_GetFullHandle( parent );
2550 if (!IsWindow( parent ))
2552 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2553 return 0;
2556 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2557 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2559 hwnd = full_handle;
2561 if (USER_Driver.pSetParent)
2562 return USER_Driver.pSetParent( hwnd, parent );
2564 /* Windows hides the window first, then shows it again
2565 * including the WM_SHOWWINDOW messages and all */
2566 was_visible = ShowWindow( hwnd, SW_HIDE );
2568 if (!IsWindow( parent )) return 0;
2569 if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return 0;
2571 retvalue = wndPtr->parent; /* old parent */
2572 if (parent != retvalue)
2574 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2576 if (parent != GetDesktopWindow()) /* a child window */
2578 if (!(wndPtr->dwStyle & WS_CHILD))
2580 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
2581 if (menu) DestroyMenu( menu );
2585 WIN_ReleasePtr( wndPtr );
2587 /* SetParent additionally needs to make hwnd the topmost window
2588 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2589 WM_WINDOWPOSCHANGED notification messages.
2591 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2592 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2593 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2594 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2595 return retvalue;
2599 /*******************************************************************
2600 * IsChild (USER32.@)
2602 BOOL WINAPI IsChild( HWND parent, HWND child )
2604 HWND *list = WIN_ListParents( child );
2605 int i;
2606 BOOL ret;
2608 if (!list) return FALSE;
2609 parent = WIN_GetFullHandle( parent );
2610 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2611 ret = (list[i] != 0);
2612 HeapFree( GetProcessHeap(), 0, list );
2613 return ret;
2617 /***********************************************************************
2618 * IsWindowVisible (USER32.@)
2620 BOOL WINAPI IsWindowVisible( HWND hwnd )
2622 HWND *list;
2623 BOOL retval;
2624 int i;
2626 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2627 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2628 for (i = 0; list[i]; i++)
2629 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2630 retval = !list[i];
2631 HeapFree( GetProcessHeap(), 0, list );
2632 return retval;
2636 /***********************************************************************
2637 * WIN_IsWindowDrawable
2639 * hwnd is drawable when it is visible, all parents are not
2640 * minimized, and it is itself not minimized unless we are
2641 * trying to draw its default class icon.
2643 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2645 HWND *list;
2646 BOOL retval;
2647 int i;
2648 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2650 if (!(style & WS_VISIBLE)) return FALSE;
2651 if ((style & WS_MINIMIZE) && icon && GetClassLongA( hwnd, GCL_HICON )) return FALSE;
2653 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2654 for (i = 0; list[i]; i++)
2655 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2656 break;
2657 retval = !list[i];
2658 HeapFree( GetProcessHeap(), 0, list );
2659 return retval;
2663 /*******************************************************************
2664 * GetTopWindow (USER32.@)
2666 HWND WINAPI GetTopWindow( HWND hwnd )
2668 if (!hwnd) hwnd = GetDesktopWindow();
2669 return GetWindow( hwnd, GW_CHILD );
2673 /*******************************************************************
2674 * GetWindow (USER32.@)
2676 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2678 HWND retval = 0;
2680 if (rel == GW_OWNER) /* this one may be available locally */
2682 WND *wndPtr = WIN_GetPtr( hwnd );
2683 if (!wndPtr)
2685 SetLastError( ERROR_INVALID_HANDLE );
2686 return 0;
2688 if (wndPtr != WND_OTHER_PROCESS)
2690 retval = wndPtr->owner;
2691 WIN_ReleasePtr( wndPtr );
2692 return retval;
2694 /* else fall through to server call */
2697 SERVER_START_REQ( get_window_tree )
2699 req->handle = hwnd;
2700 if (!wine_server_call_err( req ))
2702 switch(rel)
2704 case GW_HWNDFIRST:
2705 retval = reply->first_sibling;
2706 break;
2707 case GW_HWNDLAST:
2708 retval = reply->last_sibling;
2709 break;
2710 case GW_HWNDNEXT:
2711 retval = reply->next_sibling;
2712 break;
2713 case GW_HWNDPREV:
2714 retval = reply->prev_sibling;
2715 break;
2716 case GW_OWNER:
2717 retval = reply->owner;
2718 break;
2719 case GW_CHILD:
2720 retval = reply->first_child;
2721 break;
2725 SERVER_END_REQ;
2726 return retval;
2730 /***********************************************************************
2731 * WIN_InternalShowOwnedPopups
2733 * Internal version of ShowOwnedPopups; Wine functions should use this
2734 * to avoid interfering with application calls to ShowOwnedPopups
2735 * and to make sure the application can't prevent showing/hiding.
2737 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2741 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2743 int count = 0;
2744 WND *pWnd;
2745 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2747 if (!win_array) return TRUE;
2750 * Show windows Lowest first, Highest last to preserve Z-Order
2752 while (win_array[count]) count++;
2753 while (--count >= 0)
2755 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2756 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2758 if (pWnd->dwStyle & WS_POPUP)
2760 if (fShow)
2762 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2763 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
2766 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2768 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2769 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2772 else
2774 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2775 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2776 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2779 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2781 ShowWindow(pWnd->hwndSelf,SW_HIDE);
2782 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2783 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
2787 WIN_ReleaseWndPtr( pWnd );
2789 HeapFree( GetProcessHeap(), 0, win_array );
2791 return TRUE;
2794 /*******************************************************************
2795 * ShowOwnedPopups (USER32.@)
2797 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2799 int count = 0;
2800 WND *pWnd;
2801 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2803 if (!win_array) return TRUE;
2805 while (win_array[count]) count++;
2806 while (--count >= 0)
2808 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2809 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2811 if (pWnd->dwStyle & WS_POPUP)
2813 if (fShow)
2815 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2817 /* In Windows, ShowOwnedPopups(TRUE) generates
2818 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2819 * regardless of the state of the owner
2821 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2822 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2825 else
2827 if (IsWindowVisible(pWnd->hwndSelf))
2829 /* In Windows, ShowOwnedPopups(FALSE) generates
2830 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2831 * regardless of the state of the owner
2833 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2834 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2838 WIN_ReleaseWndPtr( pWnd );
2840 HeapFree( GetProcessHeap(), 0, win_array );
2841 return TRUE;
2845 /*******************************************************************
2846 * GetLastActivePopup (USER32.@)
2848 HWND WINAPI GetLastActivePopup( HWND hwnd )
2850 HWND retval = hwnd;
2852 SERVER_START_REQ( get_window_info )
2854 req->handle = hwnd;
2855 if (!wine_server_call_err( req )) retval = reply->last_active;
2857 SERVER_END_REQ;
2858 return retval;
2862 /*******************************************************************
2863 * WIN_ListParents
2865 * Build an array of all parents of a given window, starting with
2866 * the immediate parent. The array must be freed with HeapFree.
2867 * Returns NULL if window is a top-level window.
2869 HWND *WIN_ListParents( HWND hwnd )
2871 WND *win;
2872 HWND current, *list;
2873 int pos = 0, size = 16, count = 0;
2875 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2877 current = hwnd;
2878 for (;;)
2880 if (!(win = WIN_GetPtr( current ))) goto empty;
2881 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
2882 list[pos] = win->parent;
2883 WIN_ReleasePtr( win );
2884 if (!(current = list[pos]))
2886 if (!pos) goto empty;
2887 return list;
2889 if (++pos == size - 1)
2891 /* need to grow the list */
2892 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
2893 if (!new_list) goto empty;
2894 list = new_list;
2895 size += 16;
2899 /* at least one parent belongs to another process, have to query the server */
2901 for (;;)
2903 count = 0;
2904 SERVER_START_REQ( get_window_parents )
2906 req->handle = hwnd;
2907 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
2908 if (!wine_server_call( req )) count = reply->count;
2910 SERVER_END_REQ;
2911 if (!count) goto empty;
2912 if (size > count)
2914 list[count] = 0;
2915 return list;
2917 HeapFree( GetProcessHeap(), 0, list );
2918 size = count + 1;
2919 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2922 empty:
2923 HeapFree( GetProcessHeap(), 0, list );
2924 return NULL;
2928 /*******************************************************************
2929 * WIN_ListChildren
2931 * Build an array of the children of a given window. The array must be
2932 * freed with HeapFree. Returns NULL when no windows are found.
2934 HWND *WIN_ListChildren( HWND hwnd )
2936 return list_window_children( hwnd, 0, 0 );
2940 /*******************************************************************
2941 * EnumWindows (USER32.@)
2943 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2945 HWND *list;
2946 BOOL ret = TRUE;
2947 int i, iWndsLocks;
2949 /* We have to build a list of all windows first, to avoid */
2950 /* unpleasant side-effects, for instance if the callback */
2951 /* function changes the Z-order of the windows. */
2953 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2955 /* Now call the callback function for every window */
2957 iWndsLocks = WIN_SuspendWndsLock();
2958 for (i = 0; list[i]; i++)
2960 /* Make sure that the window still exists */
2961 if (!IsWindow( list[i] )) continue;
2962 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2964 WIN_RestoreWndsLock(iWndsLocks);
2965 HeapFree( GetProcessHeap(), 0, list );
2966 return ret;
2970 /**********************************************************************
2971 * EnumThreadWindows (USER32.@)
2973 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2975 HWND *list;
2976 int i, iWndsLocks;
2978 if (!(list = list_window_children( GetDesktopWindow(), 0, id ))) return TRUE;
2980 /* Now call the callback function for every window */
2982 iWndsLocks = WIN_SuspendWndsLock();
2983 for (i = 0; list[i]; i++)
2984 if (!func( list[i], lParam )) break;
2985 WIN_RestoreWndsLock(iWndsLocks);
2986 HeapFree( GetProcessHeap(), 0, list );
2987 return TRUE;
2991 /**********************************************************************
2992 * WIN_EnumChildWindows
2994 * Helper function for EnumChildWindows().
2996 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2998 HWND *childList;
2999 BOOL ret = FALSE;
3001 for ( ; *list; list++)
3003 /* Make sure that the window still exists */
3004 if (!IsWindow( *list )) continue;
3005 /* skip owned windows */
3006 if (GetWindow( *list, GW_OWNER )) continue;
3007 /* Build children list first */
3008 childList = WIN_ListChildren( *list );
3010 ret = func( *list, lParam );
3012 if (childList)
3014 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
3015 HeapFree( GetProcessHeap(), 0, childList );
3017 if (!ret) return FALSE;
3019 return TRUE;
3023 /**********************************************************************
3024 * EnumChildWindows (USER32.@)
3026 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
3028 HWND *list;
3029 int iWndsLocks;
3031 if (!(list = WIN_ListChildren( parent ))) return FALSE;
3032 iWndsLocks = WIN_SuspendWndsLock();
3033 WIN_EnumChildWindows( list, func, lParam );
3034 WIN_RestoreWndsLock(iWndsLocks);
3035 HeapFree( GetProcessHeap(), 0, list );
3036 return TRUE;
3040 /*******************************************************************
3041 * AnyPopup (USER.52)
3043 BOOL16 WINAPI AnyPopup16(void)
3045 return AnyPopup();
3049 /*******************************************************************
3050 * AnyPopup (USER32.@)
3052 BOOL WINAPI AnyPopup(void)
3054 int i;
3055 BOOL retvalue;
3056 HWND *list = WIN_ListChildren( GetDesktopWindow() );
3058 if (!list) return FALSE;
3059 for (i = 0; list[i]; i++)
3061 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
3063 retvalue = (list[i] != 0);
3064 HeapFree( GetProcessHeap(), 0, list );
3065 return retvalue;
3069 /*******************************************************************
3070 * FlashWindow (USER32.@)
3072 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3074 WND *wndPtr = WIN_FindWndPtr(hWnd);
3076 TRACE("%04x\n", hWnd);
3078 if (!wndPtr) return FALSE;
3079 hWnd = wndPtr->hwndSelf; /* make it a full handle */
3081 if (wndPtr->dwStyle & WS_MINIMIZE)
3083 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3085 HDC hDC = GetDC(hWnd);
3087 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM)hDC, 0 ))
3088 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
3090 ReleaseDC( hWnd, hDC );
3091 wndPtr->flags |= WIN_NCACTIVATED;
3093 else
3095 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3096 wndPtr->flags &= ~WIN_NCACTIVATED;
3098 WIN_ReleaseWndPtr(wndPtr);
3099 return TRUE;
3101 else
3103 WPARAM16 wparam;
3104 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3105 else wparam = (hWnd == GetForegroundWindow());
3107 WIN_ReleaseWndPtr(wndPtr);
3108 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3109 return wparam;
3114 /*******************************************************************
3115 * GetWindowContextHelpId (USER32.@)
3117 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3119 DWORD retval;
3120 WND *wnd = WIN_FindWndPtr( hwnd );
3121 if (!wnd) return 0;
3122 retval = wnd->helpContext;
3123 WIN_ReleaseWndPtr(wnd);
3124 return retval;
3128 /*******************************************************************
3129 * SetWindowContextHelpId (USER32.@)
3131 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3133 WND *wnd = WIN_FindWndPtr( hwnd );
3134 if (!wnd) return FALSE;
3135 wnd->helpContext = id;
3136 WIN_ReleaseWndPtr(wnd);
3137 return TRUE;
3141 /*******************************************************************
3142 * DRAG_QueryUpdate16
3144 * recursively find a child that contains spDragInfo->pt point
3145 * and send WM_QUERYDROPOBJECT
3147 static BOOL16 DRAG_QueryUpdate16( HWND hQueryWnd, SEGPTR spDragInfo )
3149 BOOL16 wParam, bResult = 0;
3150 POINT pt;
3151 LPDRAGINFO16 ptrDragInfo = MapSL(spDragInfo);
3152 RECT tempRect;
3154 if (!ptrDragInfo) return FALSE;
3156 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3158 GetWindowRect(hQueryWnd,&tempRect);
3160 if( !PtInRect(&tempRect,pt) || !IsWindowEnabled(hQueryWnd)) return FALSE;
3162 if (!IsIconic( hQueryWnd ))
3164 GetClientRect( hQueryWnd, &tempRect );
3165 MapWindowPoints( hQueryWnd, 0, (LPPOINT)&tempRect, 2 );
3167 if (PtInRect( &tempRect, pt))
3169 int i;
3170 HWND *list = WIN_ListChildren( hQueryWnd );
3172 wParam = 0;
3174 if (list)
3176 for (i = 0; list[i]; i++)
3178 if (GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)
3180 GetWindowRect( list[i], &tempRect );
3181 if (PtInRect( &tempRect, pt )) break;
3184 if (list[i])
3186 if (IsWindowEnabled( list[i] ))
3187 bResult = DRAG_QueryUpdate16( list[i], spDragInfo );
3189 HeapFree( GetProcessHeap(), 0, list );
3191 if(bResult) return bResult;
3193 else wParam = 1;
3195 else wParam = 1;
3197 ScreenToClient16(HWND_16(hQueryWnd),&ptrDragInfo->pt);
3199 ptrDragInfo->hScope = HWND_16(hQueryWnd);
3201 bResult = SendMessage16( HWND_16(hQueryWnd), WM_QUERYDROPOBJECT, (WPARAM16)wParam, spDragInfo );
3203 if( !bResult ) CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3205 return bResult;
3209 /*******************************************************************
3210 * DragDetect (USER32.@)
3212 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3214 MSG msg;
3215 RECT rect;
3217 rect.left = pt.x - wDragWidth;
3218 rect.right = pt.x + wDragWidth;
3220 rect.top = pt.y - wDragHeight;
3221 rect.bottom = pt.y + wDragHeight;
3223 SetCapture(hWnd);
3225 while(1)
3227 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3229 if( msg.message == WM_LBUTTONUP )
3231 ReleaseCapture();
3232 return 0;
3234 if( msg.message == WM_MOUSEMOVE )
3236 POINT tmp;
3237 tmp.x = LOWORD(msg.lParam);
3238 tmp.y = HIWORD(msg.lParam);
3239 if( !PtInRect( &rect, tmp ))
3241 ReleaseCapture();
3242 return 1;
3246 WaitMessage();
3248 return 0;
3251 /******************************************************************************
3252 * DragObject (USER.464)
3254 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3255 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3257 MSG msg;
3258 LPDRAGINFO16 lpDragInfo;
3259 SEGPTR spDragInfo;
3260 HCURSOR hOldCursor=0, hBummer=0;
3261 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
3262 HCURSOR hCurrentCursor = 0;
3263 HWND16 hCurrentWnd = 0;
3265 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
3266 spDragInfo = K32WOWGlobalLock16(hDragInfo);
3268 if( !lpDragInfo || !spDragInfo ) return 0L;
3270 if (!(hBummer = LoadCursorA(0, MAKEINTRESOURCEA(OCR_NO))))
3272 GlobalFree16(hDragInfo);
3273 return 0L;
3276 if(hCursor) hOldCursor = SetCursor(HCURSOR_32(hCursor));
3278 lpDragInfo->hWnd = hWnd;
3279 lpDragInfo->hScope = 0;
3280 lpDragInfo->wFlags = wObj;
3281 lpDragInfo->hList = szList; /* near pointer! */
3282 lpDragInfo->hOfStruct = hOfStruct;
3283 lpDragInfo->l = 0L;
3285 SetCapture(WIN_Handle32(hWnd));
3286 ShowCursor( TRUE );
3290 GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST );
3292 *(lpDragInfo+1) = *lpDragInfo;
3294 lpDragInfo->pt.x = msg.pt.x;
3295 lpDragInfo->pt.y = msg.pt.y;
3297 /* update DRAGINFO struct */
3298 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3300 if( DRAG_QueryUpdate16(WIN_Handle32(hwndScope), spDragInfo) > 0 )
3301 hCurrentCursor = HCURSOR_32(hCursor);
3302 else
3304 hCurrentCursor = hBummer;
3305 lpDragInfo->hScope = 0;
3307 if( hCurrentCursor )
3308 SetCursor(hCurrentCursor);
3310 /* send WM_DRAGLOOP */
3311 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3312 (LPARAM) spDragInfo );
3313 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3314 if( hCurrentWnd != lpDragInfo->hScope )
3316 if( hCurrentWnd )
3317 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3318 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
3319 HIWORD(spDragInfo)) );
3320 hCurrentWnd = lpDragInfo->hScope;
3321 if( hCurrentWnd )
3322 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3324 else
3325 if( hCurrentWnd )
3326 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3328 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3330 ReleaseCapture();
3331 ShowCursor( FALSE );
3333 if( hCursor ) SetCursor(hOldCursor);
3335 if( hCurrentCursor != hBummer )
3336 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3337 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3338 else
3339 msg.lParam = 0;
3340 GlobalFree16(hDragInfo);
3342 return (DWORD)(msg.lParam);
3346 /******************************************************************************
3347 * GetWindowModuleFileNameA (USER32.@)
3349 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3351 FIXME("GetWindowModuleFileNameA(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3352 hwnd, lpszFileName, cchFileNameMax);
3353 return 0;
3356 /******************************************************************************
3357 * GetWindowModuleFileNameW (USER32.@)
3359 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3361 FIXME("GetWindowModuleFileNameW(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3362 hwnd, lpszFileName, cchFileNameMax);
3363 return 0;
3366 /******************************************************************************
3367 * GetWindowInfo (USER32.@)
3368 * hwnd: in
3369 * pwi: out.
3370 * MS Documentation mentions that pwi->cbSize must be set to SIZEOF(WINDOWINFO)
3371 * this may be because this structure changed over time. If this is the
3372 * the case, then please: FIXME.
3373 * Using the structure described in MSDN for 98/ME/NT(4.0 SP3)/2000/XP.
3375 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3377 WND *wndInfo = NULL;
3378 if (!pwi) return FALSE;
3379 if (pwi->cbSize != sizeof(WINDOWINFO))
3381 FIXME("windowinfo->cbSize != sizeof(WINDOWINFO). Please report\n");
3382 return FALSE;
3384 wndInfo = WIN_GetPtr(hwnd);
3385 if (!wndInfo) return FALSE;
3386 if (wndInfo == WND_OTHER_PROCESS)
3388 FIXME("window belong to other process\n");
3389 return FALSE;
3392 pwi->rcWindow = wndInfo->rectWindow;
3393 pwi->rcClient = wndInfo->rectClient;
3394 pwi->dwStyle = wndInfo->dwStyle;
3395 pwi->dwExStyle = wndInfo->dwExStyle;
3396 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3397 /* if active WS_ACTIVECAPTION, else 0 */
3399 pwi->cxWindowBorders = ((wndInfo->dwStyle & WS_BORDER) ?
3400 GetSystemMetrics(SM_CXBORDER) : 0);
3401 pwi->cyWindowBorders = ((wndInfo->dwStyle & WS_BORDER) ?
3402 GetSystemMetrics(SM_CYBORDER) : 0);
3403 /* above two: I'm presuming that borders widths are the same
3404 * for each window - so long as its actually using a border.. */
3406 pwi->atomWindowType = GetClassLongA( hwnd, GCW_ATOM );
3407 pwi->wCreatorVersion = GetVersion();
3408 /* Docs say this should be the version that
3409 * CREATED the window. But eh?.. Isn't that just the
3410 * version we are running.. Unless ofcourse its some wacky
3411 * RPC stuff or something */
3413 WIN_ReleasePtr(wndInfo);
3414 return TRUE;