In OSS_RawOpenDevice, always retrieve the device format and store it
[wine/multimedia.git] / windows / win.c
blob7cdb36e28c8ae5518e98d1c3d9401534fe044604
1 /*
2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "config.h"
22 #include "wine/port.h"
24 #include <assert.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include "windef.h"
28 #include "wine/winbase16.h"
29 #include "wine/winuser16.h"
30 #include "wownt32.h"
31 #include "wine/server.h"
32 #include "wine/unicode.h"
33 #include "win.h"
34 #include "user.h"
35 #include "dce.h"
36 #include "controls.h"
37 #include "cursoricon.h"
38 #include "message.h"
39 #include "winpos.h"
40 #include "winerror.h"
41 #include "stackframe.h"
42 #include "wine/debug.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(win);
45 WINE_DECLARE_DEBUG_CHANNEL(msg);
47 #define NB_USER_HANDLES (LAST_USER_HANDLE - FIRST_USER_HANDLE + 1)
49 /**********************************************************************/
51 /* Desktop window */
52 static WND *pWndDesktop = NULL;
54 static WORD wDragWidth = 4;
55 static WORD wDragHeight= 3;
57 static void *user_handles[NB_USER_HANDLES];
59 /* thread safeness */
60 extern SYSLEVEL USER_SysLevel; /* FIXME */
62 /***********************************************************************
63 * WIN_SuspendWndsLock
65 * Suspend the lock on WND structures.
66 * Returns the number of locks suspended
68 int WIN_SuspendWndsLock( void )
70 int isuspendedLocks = _ConfirmSysLevel( &USER_SysLevel );
71 int count = isuspendedLocks;
73 while ( count-- > 0 )
74 _LeaveSysLevel( &USER_SysLevel );
76 return isuspendedLocks;
79 /***********************************************************************
80 * WIN_RestoreWndsLock
82 * Restore the suspended locks on WND structures
84 void WIN_RestoreWndsLock( int ipreviousLocks )
86 while ( ipreviousLocks-- > 0 )
87 _EnterSysLevel( &USER_SysLevel );
90 /***********************************************************************
91 * create_window_handle
93 * Create a window handle with the server.
95 static WND *create_window_handle( HWND parent, HWND owner, ATOM atom, INT size )
97 BOOL res;
98 user_handle_t handle = 0;
99 WORD index;
100 WND *win = HeapAlloc( GetProcessHeap(), 0, size );
102 if (!win) return NULL;
104 USER_Lock();
106 SERVER_START_REQ( create_window )
108 req->parent = parent;
109 req->owner = owner;
110 req->atom = atom;
111 if ((res = !wine_server_call_err( req ))) handle = reply->handle;
113 SERVER_END_REQ;
115 if (!res)
117 USER_Unlock();
118 HeapFree( GetProcessHeap(), 0, win );
119 return NULL;
121 index = LOWORD(handle) - FIRST_USER_HANDLE;
122 assert( index < NB_USER_HANDLES );
123 user_handles[index] = win;
124 win->hwndSelf = handle;
125 win->dwMagic = WND_MAGIC;
126 win->irefCount = 1;
127 return win;
131 /***********************************************************************
132 * free_window_handle
134 * Free a window handle.
136 static WND *free_window_handle( HWND hwnd )
138 WND *ptr;
139 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
141 if (index >= NB_USER_HANDLES) return NULL;
142 USER_Lock();
143 if ((ptr = user_handles[index]))
145 SERVER_START_REQ( destroy_window )
147 req->handle = hwnd;
148 if (!wine_server_call_err( req ))
149 user_handles[index] = NULL;
150 else
151 ptr = NULL;
153 SERVER_END_REQ;
155 USER_Unlock();
156 if (ptr) HeapFree( GetProcessHeap(), 0, ptr );
157 return ptr;
161 /*******************************************************************
162 * list_window_children
164 * Build an array of the children of a given window. The array must be
165 * freed with HeapFree. Returns NULL when no windows are found.
167 static HWND *list_window_children( HWND hwnd, ATOM atom, DWORD tid )
169 HWND *list;
170 int size = 32;
172 for (;;)
174 int count = 0;
176 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
178 SERVER_START_REQ( get_window_children )
180 req->parent = hwnd;
181 req->atom = atom;
182 req->tid = tid;
183 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
184 if (!wine_server_call( req )) count = reply->count;
186 SERVER_END_REQ;
187 if (count && count < size)
189 list[count] = 0;
190 return list;
192 HeapFree( GetProcessHeap(), 0, list );
193 if (!count) break;
194 size = count + 1; /* restart with a large enough buffer */
196 return NULL;
200 /*******************************************************************
201 * send_parent_notify
203 static void send_parent_notify( HWND hwnd, UINT msg )
205 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD)) return;
206 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY) return;
207 SendMessageW( GetParent(hwnd), WM_PARENTNOTIFY,
208 MAKEWPARAM( msg, GetWindowLongW( hwnd, GWL_ID )), (LPARAM)hwnd );
212 /*******************************************************************
213 * get_server_window_text
215 * Retrieve the window text from the server.
217 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
219 size_t len = 0;
221 SERVER_START_REQ( get_window_text )
223 req->handle = hwnd;
224 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
225 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
227 SERVER_END_REQ;
228 text[len / sizeof(WCHAR)] = 0;
232 /***********************************************************************
233 * WIN_GetPtr
235 * Return a pointer to the WND structure if local to the process,
236 * or WND_OTHER_PROCESS if handle may be valid in other process.
237 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
239 WND *WIN_GetPtr( HWND hwnd )
241 WND * ptr;
242 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
244 if (index >= NB_USER_HANDLES) return NULL;
246 USER_Lock();
247 if ((ptr = user_handles[index]))
249 if (ptr->dwMagic == WND_MAGIC && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
250 return ptr;
251 ptr = NULL;
253 else ptr = WND_OTHER_PROCESS;
254 USER_Unlock();
255 return ptr;
259 /***********************************************************************
260 * WIN_IsCurrentProcess
262 * Check whether a given window belongs to the current process (and return the full handle).
264 HWND WIN_IsCurrentProcess( HWND hwnd )
266 WND *ptr;
267 HWND ret;
269 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS) return 0;
270 ret = ptr->hwndSelf;
271 WIN_ReleasePtr( ptr );
272 return ret;
276 /***********************************************************************
277 * WIN_IsCurrentThread
279 * Check whether a given window belongs to the current thread (and return the full handle).
281 HWND WIN_IsCurrentThread( HWND hwnd )
283 WND *ptr;
284 HWND ret = 0;
286 if ((ptr = WIN_GetPtr( hwnd )) && ptr != WND_OTHER_PROCESS)
288 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
289 WIN_ReleasePtr( ptr );
291 return ret;
295 /***********************************************************************
296 * WIN_Handle32
298 * Convert a 16-bit window handle to a full 32-bit handle.
300 HWND WIN_Handle32( HWND16 hwnd16 )
302 WND *ptr;
303 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
305 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
306 /* do sign extension for -2 and -3 */
307 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
309 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
311 if (ptr != WND_OTHER_PROCESS)
313 hwnd = ptr->hwndSelf;
314 WIN_ReleasePtr( ptr );
316 else /* may belong to another process */
318 SERVER_START_REQ( get_window_info )
320 req->handle = hwnd;
321 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
323 SERVER_END_REQ;
325 return hwnd;
329 /***********************************************************************
330 * WIN_FindWndPtr
332 * Return a pointer to the WND structure corresponding to a HWND.
334 WND * WIN_FindWndPtr( HWND hwnd )
336 WND * ptr;
338 if (!hwnd) return NULL;
340 if ((ptr = WIN_GetPtr( hwnd )))
342 if (ptr != WND_OTHER_PROCESS)
344 /* increment destruction monitoring */
345 ptr->irefCount++;
346 return ptr;
348 if (IsWindow( hwnd )) /* check other processes */
350 ERR( "window %p belongs to other process\n", hwnd );
351 /* DbgBreakPoint(); */
354 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
355 return NULL;
359 /***********************************************************************
360 * WIN_ReleaseWndPtr
362 * Release the pointer to the WND structure.
364 void WIN_ReleaseWndPtr(WND *wndPtr)
366 if(!wndPtr) return;
368 /* Decrement destruction monitoring value */
369 wndPtr->irefCount--;
370 /* Check if it's time to release the memory */
371 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
373 /* Release memory */
374 free_window_handle( wndPtr->hwndSelf );
376 else if(wndPtr->irefCount < 0)
378 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
379 ERR("forgot a Lock on %p somewhere\n",wndPtr);
381 /* unlock all WND structures for thread safeness */
382 USER_Unlock();
386 /***********************************************************************
387 * WIN_UnlinkWindow
389 * Remove a window from the siblings linked list.
391 void WIN_UnlinkWindow( HWND hwnd )
393 WIN_LinkWindow( hwnd, 0, 0 );
397 /***********************************************************************
398 * WIN_LinkWindow
400 * Insert a window into the siblings linked list.
401 * The window is inserted after the specified window, which can also
402 * be specified as HWND_TOP or HWND_BOTTOM.
403 * If parent is 0, window is unlinked from the tree.
405 void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
407 WND *wndPtr = WIN_GetPtr( hwnd );
409 if (!wndPtr) return;
410 if (wndPtr == WND_OTHER_PROCESS)
412 if (IsWindow(hwnd)) ERR(" cannot link other process window %p\n", hwnd );
413 return;
416 SERVER_START_REQ( link_window )
418 req->handle = hwnd;
419 req->parent = parent;
420 req->previous = hwndInsertAfter;
421 if (!wine_server_call( req ))
423 if (reply->full_parent) wndPtr->parent = reply->full_parent;
427 SERVER_END_REQ;
428 WIN_ReleasePtr( wndPtr );
432 /***********************************************************************
433 * WIN_SetOwner
435 * Change the owner of a window.
437 HWND WIN_SetOwner( HWND hwnd, HWND owner )
439 WND *win = WIN_GetPtr( hwnd );
440 HWND ret = 0;
442 if (!win) return 0;
443 if (win == WND_OTHER_PROCESS)
445 if (IsWindow(hwnd)) ERR( "cannot set owner %p on other process window %p\n", owner, hwnd );
446 return 0;
448 SERVER_START_REQ( set_window_owner )
450 req->handle = hwnd;
451 req->owner = owner;
452 if (!wine_server_call( req ))
454 win->owner = reply->full_owner;
455 ret = reply->prev_owner;
458 SERVER_END_REQ;
459 WIN_ReleasePtr( win );
460 return ret;
464 /***********************************************************************
465 * WIN_SetStyle
467 * Change the style of a window.
469 LONG WIN_SetStyle( HWND hwnd, LONG style )
471 BOOL ok;
472 LONG ret = 0;
473 WND *win = WIN_GetPtr( hwnd );
475 if (!win) return 0;
476 if (win == WND_OTHER_PROCESS)
478 if (IsWindow(hwnd))
479 ERR( "cannot set style %lx on other process window %p\n", style, hwnd );
480 return 0;
482 if (style == win->dwStyle)
484 WIN_ReleasePtr( win );
485 return style;
487 SERVER_START_REQ( set_window_info )
489 req->handle = hwnd;
490 req->flags = SET_WIN_STYLE;
491 req->style = style;
492 if ((ok = !wine_server_call( req )))
494 ret = reply->old_style;
495 win->dwStyle = style;
498 SERVER_END_REQ;
499 WIN_ReleasePtr( win );
500 if (ok && USER_Driver.pSetWindowStyle) USER_Driver.pSetWindowStyle( hwnd, ret );
501 return ret;
505 /***********************************************************************
506 * WIN_SetExStyle
508 * Change the extended style of a window.
510 LONG WIN_SetExStyle( HWND hwnd, LONG style )
512 LONG ret = 0;
513 WND *win = WIN_GetPtr( hwnd );
515 if (!win) return 0;
516 if (win == WND_OTHER_PROCESS)
518 if (IsWindow(hwnd))
519 ERR( "cannot set exstyle %lx on other process window %p\n", style, hwnd );
520 return 0;
522 if (style == win->dwExStyle)
524 WIN_ReleasePtr( win );
525 return style;
527 SERVER_START_REQ( set_window_info )
529 req->handle = hwnd;
530 req->flags = SET_WIN_EXSTYLE;
531 req->ex_style = style;
532 if (!wine_server_call( req ))
534 ret = reply->old_ex_style;
535 win->dwExStyle = style;
538 SERVER_END_REQ;
539 WIN_ReleasePtr( win );
540 return ret;
544 /***********************************************************************
545 * WIN_SetRectangles
547 * Set the window and client rectangles.
549 void WIN_SetRectangles( HWND hwnd, const RECT *rectWindow, const RECT *rectClient )
551 WND *win = WIN_GetPtr( hwnd );
552 BOOL ret;
554 if (!win) return;
555 if (win == WND_OTHER_PROCESS)
557 if (IsWindow( hwnd )) ERR( "cannot set rectangles of other process window %p\n", hwnd );
558 return;
560 SERVER_START_REQ( set_window_rectangles )
562 req->handle = hwnd;
563 req->window.left = rectWindow->left;
564 req->window.top = rectWindow->top;
565 req->window.right = rectWindow->right;
566 req->window.bottom = rectWindow->bottom;
567 req->client.left = rectClient->left;
568 req->client.top = rectClient->top;
569 req->client.right = rectClient->right;
570 req->client.bottom = rectClient->bottom;
571 ret = !wine_server_call( req );
573 SERVER_END_REQ;
574 if (ret)
576 win->rectWindow = *rectWindow;
577 win->rectClient = *rectClient;
579 TRACE( "win %p window (%d,%d)-(%d,%d) client (%d,%d)-(%d,%d)\n", hwnd,
580 rectWindow->left, rectWindow->top, rectWindow->right, rectWindow->bottom,
581 rectClient->left, rectClient->top, rectClient->right, rectClient->bottom );
583 WIN_ReleasePtr( win );
587 /***********************************************************************
588 * WIN_GetRectangles
590 * Get the window and client rectangles.
592 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
594 WND *win = WIN_GetPtr( hwnd );
595 BOOL ret = TRUE;
597 if (!win) return FALSE;
598 if (win == WND_OTHER_PROCESS)
600 SERVER_START_REQ( get_window_rectangles )
602 req->handle = hwnd;
603 if ((ret = !wine_server_call( req )))
605 if (rectWindow)
607 rectWindow->left = reply->window.left;
608 rectWindow->top = reply->window.top;
609 rectWindow->right = reply->window.right;
610 rectWindow->bottom = reply->window.bottom;
612 if (rectClient)
614 rectClient->left = reply->client.left;
615 rectClient->top = reply->client.top;
616 rectClient->right = reply->client.right;
617 rectClient->bottom = reply->client.bottom;
621 SERVER_END_REQ;
623 else
625 if (rectWindow) *rectWindow = win->rectWindow;
626 if (rectClient) *rectClient = win->rectClient;
627 WIN_ReleasePtr( win );
629 return ret;
633 /***********************************************************************
634 * WIN_DestroyWindow
636 * Destroy storage associated to a window. "Internals" p.358
638 LRESULT WIN_DestroyWindow( HWND hwnd )
640 WND *wndPtr;
641 HWND *list;
643 TRACE("%p\n", hwnd );
645 if (!(hwnd = WIN_IsCurrentThread( hwnd )))
647 ERR( "window doesn't belong to current thread\n" );
648 return 0;
651 /* free child windows */
652 if ((list = WIN_ListChildren( hwnd )))
654 int i;
655 for (i = 0; list[i]; i++)
657 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
658 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
660 HeapFree( GetProcessHeap(), 0, list );
664 * Clear the update region to make sure no WM_PAINT messages will be
665 * generated for this window while processing the WM_NCDESTROY.
667 RedrawWindow( hwnd, NULL, 0,
668 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
671 * Send the WM_NCDESTROY to the window being destroyed.
673 SendMessageA( hwnd, WM_NCDESTROY, 0, 0);
675 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
677 WINPOS_CheckInternalPos( hwnd );
678 if( hwnd == GetCapture()) ReleaseCapture();
680 /* free resources associated with the window */
682 TIMER_RemoveWindowTimers( hwnd );
684 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
686 if (!(wndPtr->dwStyle & WS_CHILD))
688 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
689 if (menu) DestroyMenu( menu );
691 if (wndPtr->hSysMenu)
693 DestroyMenu( wndPtr->hSysMenu );
694 wndPtr->hSysMenu = 0;
696 DCE_FreeWindowDCE( hwnd ); /* Always do this to catch orphaned DCs */
697 USER_Driver.pDestroyWindow( hwnd );
698 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
699 CLASS_RemoveWindow( wndPtr->class );
700 wndPtr->class = NULL;
701 wndPtr->dwMagic = 0; /* Mark it as invalid */
702 WIN_ReleaseWndPtr( wndPtr );
703 return 0;
706 /***********************************************************************
707 * WIN_DestroyThreadWindows
709 * Destroy all children of 'wnd' owned by the current thread.
710 * Return TRUE if something was done.
712 void WIN_DestroyThreadWindows( HWND hwnd )
714 HWND *list;
715 int i;
717 if (!(list = WIN_ListChildren( hwnd ))) return;
718 for (i = 0; list[i]; i++)
720 if (WIN_IsCurrentThread( list[i] ))
721 DestroyWindow( list[i] );
722 else
723 WIN_DestroyThreadWindows( list[i] );
725 HeapFree( GetProcessHeap(), 0, list );
728 /***********************************************************************
729 * WIN_CreateDesktopWindow
731 * Create the desktop window.
733 BOOL WIN_CreateDesktopWindow(void)
735 struct tagCLASS *class;
736 HWND hwndDesktop;
737 INT wndExtra;
738 DWORD clsStyle;
739 WNDPROC winproc;
740 DCE *dce;
741 CREATESTRUCTA cs;
742 RECT rect;
744 TRACE("Creating desktop window\n");
746 if (!WINPOS_CreateInternalPosAtom() ||
747 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
748 &wndExtra, &winproc, &clsStyle, &dce )))
749 return FALSE;
751 pWndDesktop = create_window_handle( 0, 0, LOWORD(DESKTOP_CLASS_ATOM),
752 sizeof(WND) + wndExtra - sizeof(pWndDesktop->wExtra) );
753 if (!pWndDesktop) return FALSE;
754 hwndDesktop = pWndDesktop->hwndSelf;
756 pWndDesktop->tid = 0; /* nobody owns the desktop */
757 pWndDesktop->parent = 0;
758 pWndDesktop->owner = 0;
759 pWndDesktop->class = class;
760 pWndDesktop->text = NULL;
761 pWndDesktop->hrgnUpdate = 0;
762 pWndDesktop->clsStyle = clsStyle;
763 pWndDesktop->dce = NULL;
764 pWndDesktop->pVScroll = NULL;
765 pWndDesktop->pHScroll = NULL;
766 pWndDesktop->helpContext = 0;
767 pWndDesktop->flags = 0;
768 pWndDesktop->hSysMenu = 0;
769 pWndDesktop->winproc = winproc;
770 pWndDesktop->cbWndExtra = wndExtra;
772 cs.lpCreateParams = NULL;
773 cs.hInstance = 0;
774 cs.hMenu = 0;
775 cs.hwndParent = 0;
776 cs.x = 0;
777 cs.y = 0;
778 cs.cx = GetSystemMetrics( SM_CXSCREEN );
779 cs.cy = GetSystemMetrics( SM_CYSCREEN );
780 cs.style = pWndDesktop->dwStyle;
781 cs.dwExStyle = pWndDesktop->dwExStyle;
782 cs.lpszName = NULL;
783 cs.lpszClass = DESKTOP_CLASS_ATOM;
785 SetRect( &rect, 0, 0, cs.cx, cs.cy );
786 WIN_SetRectangles( hwndDesktop, &rect, &rect );
788 SERVER_START_REQ( set_window_info )
790 req->handle = hwndDesktop;
791 req->flags = 0; /* don't set anything, just retrieve */
792 wine_server_call( req );
793 pWndDesktop->dwStyle = reply->old_style;
794 pWndDesktop->dwExStyle = reply->old_ex_style;
795 pWndDesktop->hInstance = (HINSTANCE)reply->old_instance;
796 pWndDesktop->userdata = (ULONG_PTR)reply->old_user_data;
797 pWndDesktop->wIDmenu = reply->old_id;
799 SERVER_END_REQ;
801 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE ))
803 WIN_ReleaseWndPtr( pWndDesktop );
804 return FALSE;
807 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
808 WIN_ReleaseWndPtr( pWndDesktop );
809 return TRUE;
813 /***********************************************************************
814 * WIN_FixCoordinates
816 * Fix the coordinates - Helper for WIN_CreateWindowEx.
817 * returns default show mode in sw.
818 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
820 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
822 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
823 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
825 if (cs->style & (WS_CHILD | WS_POPUP))
827 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
828 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
830 else /* overlapped window */
832 STARTUPINFOA info;
834 GetStartupInfoA( &info );
836 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
838 /* Never believe Microsoft's documentation... CreateWindowEx doc says
839 * that if an overlapped window is created with WS_VISIBLE style bit
840 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
841 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
842 * reveals that
844 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
845 * 2) it does not ignore the y parameter as the docs claim; instead, it
846 * uses it as second parameter to ShowWindow() unless y is either
847 * CW_USEDEFAULT or CW_USEDEFAULT16.
849 * The fact that we didn't do 2) caused bogus windows pop up when wine
850 * was running apps that were using this obscure feature. Example -
851 * calc.exe that comes with Win98 (only Win98, it's different from
852 * the one that comes with Win95 and NT)
854 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
855 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
856 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
859 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
861 if (info.dwFlags & STARTF_USESIZE)
863 cs->cx = info.dwXSize;
864 cs->cy = info.dwYSize;
866 else /* if no other hint from the app, pick 3/4 of the screen real estate */
868 RECT r;
869 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
870 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
871 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
876 else
878 /* neither x nor cx are default. Check the y values .
879 * In the trace we see Outlook and Outlook Express using
880 * cy set to CW_USEDEFAULT when opening the address book.
882 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16) {
883 RECT r;
884 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
885 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
886 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
891 /***********************************************************************
892 * dump_window_styles
894 static void dump_window_styles( DWORD style, DWORD exstyle )
896 TRACE( "style:" );
897 if(style & WS_POPUP) DPRINTF(" WS_POPUP");
898 if(style & WS_CHILD) DPRINTF(" WS_CHILD");
899 if(style & WS_MINIMIZE) DPRINTF(" WS_MINIMIZE");
900 if(style & WS_VISIBLE) DPRINTF(" WS_VISIBLE");
901 if(style & WS_DISABLED) DPRINTF(" WS_DISABLED");
902 if(style & WS_CLIPSIBLINGS) DPRINTF(" WS_CLIPSIBLINGS");
903 if(style & WS_CLIPCHILDREN) DPRINTF(" WS_CLIPCHILDREN");
904 if(style & WS_MAXIMIZE) DPRINTF(" WS_MAXIMIZE");
905 if((style & WS_CAPTION) == WS_CAPTION) DPRINTF(" WS_CAPTION");
906 else
908 if(style & WS_BORDER) DPRINTF(" WS_BORDER");
909 if(style & WS_DLGFRAME) DPRINTF(" WS_DLGFRAME");
911 if(style & WS_VSCROLL) DPRINTF(" WS_VSCROLL");
912 if(style & WS_HSCROLL) DPRINTF(" WS_HSCROLL");
913 if(style & WS_SYSMENU) DPRINTF(" WS_SYSMENU");
914 if(style & WS_THICKFRAME) DPRINTF(" WS_THICKFRAME");
915 if(style & WS_GROUP) DPRINTF(" WS_GROUP");
916 if(style & WS_TABSTOP) DPRINTF(" WS_TABSTOP");
917 if(style & WS_MINIMIZEBOX) DPRINTF(" WS_MINIMIZEBOX");
918 if(style & WS_MAXIMIZEBOX) DPRINTF(" WS_MAXIMIZEBOX");
920 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
921 #define DUMPED_STYLES \
922 (WS_POPUP | \
923 WS_CHILD | \
924 WS_MINIMIZE | \
925 WS_VISIBLE | \
926 WS_DISABLED | \
927 WS_CLIPSIBLINGS | \
928 WS_CLIPCHILDREN | \
929 WS_MAXIMIZE | \
930 WS_BORDER | \
931 WS_DLGFRAME | \
932 WS_VSCROLL | \
933 WS_HSCROLL | \
934 WS_SYSMENU | \
935 WS_THICKFRAME | \
936 WS_GROUP | \
937 WS_TABSTOP | \
938 WS_MINIMIZEBOX | \
939 WS_MAXIMIZEBOX)
941 if(style & ~DUMPED_STYLES) DPRINTF(" %08lx", style & ~DUMPED_STYLES);
942 DPRINTF("\n");
943 #undef DUMPED_STYLES
945 TRACE( "exstyle:" );
946 if(exstyle & WS_EX_DLGMODALFRAME) DPRINTF(" WS_EX_DLGMODALFRAME");
947 if(exstyle & WS_EX_DRAGDETECT) DPRINTF(" WS_EX_DRAGDETECT");
948 if(exstyle & WS_EX_NOPARENTNOTIFY) DPRINTF(" WS_EX_NOPARENTNOTIFY");
949 if(exstyle & WS_EX_TOPMOST) DPRINTF(" WS_EX_TOPMOST");
950 if(exstyle & WS_EX_ACCEPTFILES) DPRINTF(" WS_EX_ACCEPTFILES");
951 if(exstyle & WS_EX_TRANSPARENT) DPRINTF(" WS_EX_TRANSPARENT");
952 if(exstyle & WS_EX_MDICHILD) DPRINTF(" WS_EX_MDICHILD");
953 if(exstyle & WS_EX_TOOLWINDOW) DPRINTF(" WS_EX_TOOLWINDOW");
954 if(exstyle & WS_EX_WINDOWEDGE) DPRINTF(" WS_EX_WINDOWEDGE");
955 if(exstyle & WS_EX_CLIENTEDGE) DPRINTF(" WS_EX_CLIENTEDGE");
956 if(exstyle & WS_EX_CONTEXTHELP) DPRINTF(" WS_EX_CONTEXTHELP");
957 if(exstyle & WS_EX_RIGHT) DPRINTF(" WS_EX_RIGHT");
958 if(exstyle & WS_EX_RTLREADING) DPRINTF(" WS_EX_RTLREADING");
959 if(exstyle & WS_EX_LEFTSCROLLBAR) DPRINTF(" WS_EX_LEFTSCROLLBAR");
960 if(exstyle & WS_EX_CONTROLPARENT) DPRINTF(" WS_EX_CONTROLPARENT");
961 if(exstyle & WS_EX_STATICEDGE) DPRINTF(" WS_EX_STATICEDGE");
962 if(exstyle & WS_EX_APPWINDOW) DPRINTF(" WS_EX_APPWINDOW");
963 if(exstyle & WS_EX_LAYERED) DPRINTF(" WS_EX_LAYERED");
965 #define DUMPED_EX_STYLES \
966 (WS_EX_DLGMODALFRAME | \
967 WS_EX_DRAGDETECT | \
968 WS_EX_NOPARENTNOTIFY | \
969 WS_EX_TOPMOST | \
970 WS_EX_ACCEPTFILES | \
971 WS_EX_TRANSPARENT | \
972 WS_EX_MDICHILD | \
973 WS_EX_TOOLWINDOW | \
974 WS_EX_WINDOWEDGE | \
975 WS_EX_CLIENTEDGE | \
976 WS_EX_CONTEXTHELP | \
977 WS_EX_RIGHT | \
978 WS_EX_RTLREADING | \
979 WS_EX_LEFTSCROLLBAR | \
980 WS_EX_CONTROLPARENT | \
981 WS_EX_STATICEDGE | \
982 WS_EX_APPWINDOW | \
983 WS_EX_LAYERED)
985 if(exstyle & ~DUMPED_EX_STYLES) DPRINTF(" %08lx", exstyle & ~DUMPED_EX_STYLES);
986 DPRINTF("\n");
987 #undef DUMPED_EX_STYLES
991 /***********************************************************************
992 * WIN_CreateWindowEx
994 * Implementation of CreateWindowEx().
996 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
997 WINDOWPROCTYPE type )
999 INT sw = SW_SHOW;
1000 struct tagCLASS *classPtr;
1001 WND *wndPtr;
1002 HWND hwnd, parent, owner;
1003 INT wndExtra;
1004 DWORD clsStyle;
1005 WNDPROC winproc;
1006 DCE *dce;
1007 BOOL unicode = (type == WIN_PROC_32W);
1009 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
1010 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
1011 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszClass) : debugstr_a(cs->lpszClass),
1012 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
1013 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
1015 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
1017 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
1018 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
1020 /* Find the parent window */
1022 parent = GetDesktopWindow();
1023 owner = 0;
1025 if (cs->hwndParent == HWND_MESSAGE)
1027 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
1028 * message window (style: WS_POPUP|WS_DISABLED)
1030 FIXME("Parent is HWND_MESSAGE\n");
1032 else if (cs->hwndParent)
1034 /* Make sure parent is valid */
1035 if (!IsWindow( cs->hwndParent ))
1037 WARN("Bad parent %p\n", cs->hwndParent );
1038 return 0;
1040 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1041 parent = WIN_GetFullHandle(cs->hwndParent);
1042 else
1043 owner = GetAncestor( cs->hwndParent, GA_ROOT );
1045 else if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1047 WARN("No parent for child window\n" );
1048 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1051 /* Find the window class */
1052 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
1053 &wndExtra, &winproc, &clsStyle, &dce )))
1055 WARN("Bad class '%s'\n", cs->lpszClass );
1056 return 0;
1059 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
1061 /* Correct the window style - stage 1
1063 * These are patches that appear to affect both the style loaded into the
1064 * WIN structure and passed in the CreateStruct to the WM_CREATE etc.
1066 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1067 * why does the user get to set it?
1070 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
1071 * tested for WS_POPUP
1073 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
1074 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
1075 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
1076 cs->dwExStyle |= WS_EX_WINDOWEDGE;
1077 else
1078 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
1080 /* Create the window structure */
1082 if (!(wndPtr = create_window_handle( parent, owner, classAtom,
1083 sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
1085 TRACE("out of memory\n" );
1086 return 0;
1088 hwnd = wndPtr->hwndSelf;
1090 /* Fill the window structure */
1092 wndPtr->tid = GetCurrentThreadId();
1093 wndPtr->owner = owner;
1094 wndPtr->parent = parent;
1095 wndPtr->class = classPtr;
1096 wndPtr->winproc = winproc;
1097 wndPtr->hInstance = cs->hInstance;
1098 wndPtr->text = NULL;
1099 wndPtr->hrgnUpdate = 0;
1100 wndPtr->hrgnWnd = 0;
1101 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1102 wndPtr->dwExStyle = cs->dwExStyle;
1103 wndPtr->clsStyle = clsStyle;
1104 wndPtr->wIDmenu = 0;
1105 wndPtr->helpContext = 0;
1106 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
1107 wndPtr->pVScroll = NULL;
1108 wndPtr->pHScroll = NULL;
1109 wndPtr->userdata = 0;
1110 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU) ? MENU_GetSysMenu( hwnd, 0 ) : 0;
1111 wndPtr->cbWndExtra = wndExtra;
1113 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
1115 /* Correct the window style - stage 2 */
1117 if (!(cs->style & WS_CHILD))
1119 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1120 if (!(cs->style & WS_POPUP))
1122 wndPtr->dwStyle |= WS_CAPTION;
1123 wndPtr->flags |= WIN_NEED_SIZE;
1126 SERVER_START_REQ( set_window_info )
1128 req->handle = hwnd;
1129 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE;
1130 req->style = wndPtr->dwStyle;
1131 req->ex_style = wndPtr->dwExStyle;
1132 req->instance = (void *)wndPtr->hInstance;
1133 wine_server_call( req );
1135 SERVER_END_REQ;
1137 /* Get class or window DC if needed */
1139 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
1140 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
1141 else wndPtr->dce = NULL;
1143 /* Set the window menu */
1145 if ((wndPtr->dwStyle & WS_CAPTION || wndPtr->dwExStyle & WS_EX_APPWINDOW)
1146 && !( wndPtr->dwStyle & WS_CHILD) )
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 (!(full_handle = WIN_IsCurrentThread( hwnd )))
1695 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1697 hwnd = full_handle;
1699 TRACE("( %p, %d )\n", hwnd, enable);
1701 if (!(wndPtr = WIN_GetPtr( hwnd ))) return FALSE;
1702 style = wndPtr->dwStyle;
1703 retvalue = ((style & WS_DISABLED) != 0);
1704 WIN_ReleasePtr( wndPtr );
1706 if (enable && retvalue)
1708 WIN_SetStyle( hwnd, style & ~WS_DISABLED );
1709 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1711 else if (!enable && !retvalue)
1713 SendMessageA( hwnd, WM_CANCELMODE, 0, 0);
1715 WIN_SetStyle( hwnd, style | WS_DISABLED );
1717 if (hwnd == GetFocus() || IsChild(hwnd, GetFocus()))
1718 SetFocus( 0 ); /* A disabled window can't have the focus */
1720 if (hwnd == GetCapture() || IsChild(hwnd, GetCapture()))
1721 ReleaseCapture(); /* A disabled window can't capture the mouse */
1723 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1725 return retvalue;
1729 /***********************************************************************
1730 * IsWindowEnabled (USER32.@)
1732 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1734 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1738 /***********************************************************************
1739 * IsWindowUnicode (USER32.@)
1741 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1743 WND * wndPtr;
1744 BOOL retvalue;
1746 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1747 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1748 WIN_ReleaseWndPtr(wndPtr);
1749 return retvalue;
1753 /**********************************************************************
1754 * GetWindowWord (USER32.@)
1756 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1758 if (offset >= 0)
1760 WORD retvalue = 0;
1761 WND *wndPtr = WIN_GetPtr( hwnd );
1762 if (!wndPtr)
1764 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1765 return 0;
1767 if (wndPtr == WND_OTHER_PROCESS)
1769 if (IsWindow( hwnd ))
1770 FIXME( "(%d) not supported yet on other process window %p\n", offset, hwnd );
1771 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1772 return 0;
1774 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1776 WARN("Invalid offset %d\n", offset );
1777 SetLastError( ERROR_INVALID_INDEX );
1779 else retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1780 WIN_ReleasePtr( wndPtr );
1781 return retvalue;
1784 switch(offset)
1786 case GWL_HWNDPARENT:
1787 return GetWindowLongW( hwnd, offset );
1788 case GWL_ID:
1789 case GWL_HINSTANCE:
1791 LONG ret = GetWindowLongW( hwnd, offset );
1792 if (HIWORD(ret))
1793 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1794 return LOWORD(ret);
1796 default:
1797 WARN("Invalid offset %d\n", offset );
1798 return 0;
1803 /**********************************************************************
1804 * SetWindowWord (USER32.@)
1806 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1808 WORD *ptr, retval;
1809 WND * wndPtr;
1811 switch(offset)
1813 case GWL_ID:
1814 case GWL_HINSTANCE:
1815 case GWL_HWNDPARENT:
1816 return SetWindowLongW( hwnd, offset, (UINT)newval );
1817 default:
1818 if (offset < 0)
1820 WARN("Invalid offset %d\n", offset );
1821 SetLastError( ERROR_INVALID_INDEX );
1822 return 0;
1826 wndPtr = WIN_GetPtr( hwnd );
1827 if (wndPtr == WND_OTHER_PROCESS)
1829 if (IsWindow(hwnd))
1830 FIXME( "set %d <- %x not supported yet on other process window %p\n",
1831 offset, newval, hwnd );
1832 wndPtr = NULL;
1834 if (!wndPtr)
1836 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1837 return 0;
1840 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1842 WARN("Invalid offset %d\n", offset );
1843 WIN_ReleasePtr(wndPtr);
1844 SetLastError( ERROR_INVALID_INDEX );
1845 return 0;
1847 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1848 retval = *ptr;
1849 *ptr = newval;
1850 WIN_ReleasePtr(wndPtr);
1851 return retval;
1855 /**********************************************************************
1856 * WIN_GetWindowLong
1858 * Helper function for GetWindowLong().
1860 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1862 LONG retvalue = 0;
1863 WND *wndPtr;
1865 if (offset == GWL_HWNDPARENT)
1867 HWND parent = GetAncestor( hwnd, GA_PARENT );
1868 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1869 return (LONG)parent;
1872 if (!(wndPtr = WIN_GetPtr( hwnd )))
1874 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1875 return 0;
1878 if (wndPtr == WND_OTHER_PROCESS)
1880 if (offset >= 0)
1882 if (IsWindow(hwnd))
1883 FIXME( "(%d) not supported on other process window %p\n", offset, hwnd );
1884 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1885 return 0;
1887 if (offset == GWL_WNDPROC)
1889 SetLastError( ERROR_ACCESS_DENIED );
1890 return 0;
1892 SERVER_START_REQ( set_window_info )
1894 req->handle = hwnd;
1895 req->flags = 0; /* don't set anything, just retrieve */
1896 if (!wine_server_call_err( req ))
1898 switch(offset)
1900 case GWL_STYLE: retvalue = reply->old_style; break;
1901 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1902 case GWL_ID: retvalue = reply->old_id; break;
1903 case GWL_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1904 case GWL_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
1905 default:
1906 SetLastError( ERROR_INVALID_INDEX );
1907 break;
1911 SERVER_END_REQ;
1912 return retvalue;
1915 /* now we have a valid wndPtr */
1917 if (offset >= 0)
1919 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
1922 * Some programs try to access last element from 16 bit
1923 * code using illegal offset value. Hopefully this is
1924 * what those programs really expect.
1926 if (type == WIN_PROC_16 &&
1927 wndPtr->cbWndExtra >= 4 &&
1928 offset == wndPtr->cbWndExtra - sizeof(WORD))
1930 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
1932 ERR( "- replaced invalid offset %d with %d\n",
1933 offset, offset2 );
1935 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset2);
1936 WIN_ReleasePtr( wndPtr );
1937 return retvalue;
1939 WARN("Invalid offset %d\n", offset );
1940 WIN_ReleasePtr( wndPtr );
1941 SetLastError( ERROR_INVALID_INDEX );
1942 return 0;
1944 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1945 /* Special case for dialog window procedure */
1946 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1947 retvalue = (LONG)WINPROC_GetProc( (WNDPROC)retvalue, type );
1948 WIN_ReleasePtr( wndPtr );
1949 return retvalue;
1952 switch(offset)
1954 case GWL_USERDATA: retvalue = wndPtr->userdata; break;
1955 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1956 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1957 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu; break;
1958 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc, type ); break;
1959 case GWL_HINSTANCE: retvalue = (LONG)wndPtr->hInstance; break;
1960 default:
1961 WARN("Unknown offset %d\n", offset );
1962 SetLastError( ERROR_INVALID_INDEX );
1963 break;
1965 WIN_ReleasePtr(wndPtr);
1966 return retvalue;
1970 /**********************************************************************
1971 * WIN_SetWindowLong
1973 * Helper function for SetWindowLong().
1975 * 0 is the failure code. However, in the case of failure SetLastError
1976 * must be set to distinguish between a 0 return value and a failure.
1978 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1979 WINDOWPROCTYPE type )
1981 LONG retval = 0;
1982 WND *wndPtr;
1984 TRACE( "%p %d %lx %x\n", hwnd, offset, newval, type );
1986 if (!WIN_IsCurrentProcess( hwnd ))
1988 if (offset == GWL_WNDPROC)
1990 SetLastError( ERROR_ACCESS_DENIED );
1991 return 0;
1993 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
1996 wndPtr = WIN_GetPtr( hwnd );
1997 if (wndPtr->hwndSelf == GetDesktopWindow())
1999 /* can't change anything on the desktop window */
2000 WIN_ReleasePtr( wndPtr );
2001 SetLastError( ERROR_ACCESS_DENIED );
2002 return 0;
2005 if (offset >= 0)
2007 LONG *ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
2008 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
2010 WARN("Invalid offset %d\n", offset );
2011 WIN_ReleasePtr( wndPtr );
2012 SetLastError( ERROR_INVALID_INDEX );
2013 return 0;
2015 /* Special case for dialog window procedure */
2016 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2018 retval = (LONG)WINPROC_GetProc( (WNDPROC)*ptr, type );
2019 WINPROC_SetProc( (WNDPROC *)ptr, (WNDPROC)newval, type, WIN_PROC_WINDOW );
2020 WIN_ReleasePtr( wndPtr );
2021 return retval;
2023 retval = *ptr;
2024 *ptr = newval;
2025 WIN_ReleasePtr( wndPtr );
2027 else
2029 STYLESTRUCT style;
2030 BOOL ok;
2032 /* first some special cases */
2033 switch( offset )
2035 case GWL_STYLE:
2036 case GWL_EXSTYLE:
2037 style.styleOld = wndPtr->dwStyle;
2038 style.styleNew = newval;
2039 WIN_ReleasePtr( wndPtr );
2040 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
2041 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
2042 newval = style.styleNew;
2043 break;
2044 case GWL_HWNDPARENT:
2045 if (wndPtr->parent == GetDesktopWindow())
2047 WIN_ReleasePtr( wndPtr );
2048 return (LONG)WIN_SetOwner( hwnd, (HWND)newval );
2050 else
2052 WIN_ReleasePtr( wndPtr );
2053 return (LONG)SetParent( hwnd, (HWND)newval );
2055 case GWL_WNDPROC:
2056 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2057 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC)newval, type, WIN_PROC_WINDOW );
2058 WIN_ReleasePtr( wndPtr );
2059 return retval;
2060 case GWL_ID:
2061 case GWL_HINSTANCE:
2062 case GWL_USERDATA:
2063 break;
2064 default:
2065 WIN_ReleasePtr( wndPtr );
2066 WARN("Invalid offset %d\n", offset );
2067 SetLastError( ERROR_INVALID_INDEX );
2068 return 0;
2071 SERVER_START_REQ( set_window_info )
2073 req->handle = hwnd;
2074 switch(offset)
2076 case GWL_STYLE:
2077 req->flags = SET_WIN_STYLE;
2078 req->style = newval;
2079 break;
2080 case GWL_EXSTYLE:
2081 req->flags = SET_WIN_EXSTYLE;
2082 req->ex_style = newval;
2083 break;
2084 case GWL_ID:
2085 req->flags = SET_WIN_ID;
2086 req->id = newval;
2087 break;
2088 case GWL_HINSTANCE:
2089 req->flags = SET_WIN_INSTANCE;
2090 req->instance = (void *)newval;
2091 break;
2092 case GWL_USERDATA:
2093 req->flags = SET_WIN_USERDATA;
2094 req->user_data = (void *)newval;
2095 break;
2097 if ((ok = !wine_server_call_err( req )))
2099 switch(offset)
2101 case GWL_STYLE:
2102 wndPtr->dwStyle = newval;
2103 retval = reply->old_style;
2104 break;
2105 case GWL_EXSTYLE:
2106 wndPtr->dwExStyle = newval;
2107 retval = reply->old_ex_style;
2108 break;
2109 case GWL_ID:
2110 wndPtr->wIDmenu = newval;
2111 retval = reply->old_id;
2112 break;
2113 case GWL_HINSTANCE:
2114 wndPtr->hInstance = (HINSTANCE)newval;
2115 retval = (ULONG_PTR)reply->old_instance;
2116 break;
2117 case GWL_USERDATA:
2118 wndPtr->userdata = newval;
2119 retval = (ULONG_PTR)reply->old_user_data;
2120 break;
2124 SERVER_END_REQ;
2125 WIN_ReleasePtr( wndPtr );
2127 if (!ok) return 0;
2129 if (offset == GWL_STYLE && USER_Driver.pSetWindowStyle)
2130 USER_Driver.pSetWindowStyle( hwnd, retval );
2132 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2133 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2136 return retval;
2140 /**********************************************************************
2141 * GetWindowLong (USER.135)
2143 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2145 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
2149 /**********************************************************************
2150 * GetWindowLongA (USER32.@)
2152 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2154 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2158 /**********************************************************************
2159 * GetWindowLongW (USER32.@)
2161 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2163 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2167 /**********************************************************************
2168 * SetWindowLong (USER.136)
2170 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2172 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
2176 /**********************************************************************
2177 * SetWindowLongA (USER32.@)
2179 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2181 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2185 /**********************************************************************
2186 * SetWindowLongW (USER32.@) Set window attribute
2188 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2189 * value in a window's extra memory.
2191 * The _hwnd_ parameter specifies the window. is the handle to a
2192 * window that has extra memory. The _newval_ parameter contains the
2193 * new attribute or extra memory value. If positive, the _offset_
2194 * parameter is the byte-addressed location in the window's extra
2195 * memory to set. If negative, _offset_ specifies the window
2196 * attribute to set, and should be one of the following values:
2198 * GWL_EXSTYLE The window's extended window style
2200 * GWL_STYLE The window's window style.
2202 * GWL_WNDPROC Pointer to the window's window procedure.
2204 * GWL_HINSTANCE The window's pplication instance handle.
2206 * GWL_ID The window's identifier.
2208 * GWL_USERDATA The window's user-specified data.
2210 * If the window is a dialog box, the _offset_ parameter can be one of
2211 * the following values:
2213 * DWL_DLGPROC The address of the window's dialog box procedure.
2215 * DWL_MSGRESULT The return value of a message
2216 * that the dialog box procedure processed.
2218 * DWL_USER Application specific information.
2220 * RETURNS
2222 * If successful, returns the previous value located at _offset_. Otherwise,
2223 * returns 0.
2225 * NOTES
2227 * Extra memory for a window class is specified by a nonzero cbWndExtra
2228 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2229 * time of class creation.
2231 * Using GWL_WNDPROC to set a new window procedure effectively creates
2232 * a window subclass. Use CallWindowProc() in the new windows procedure
2233 * to pass messages to the superclass's window procedure.
2235 * The user data is reserved for use by the application which created
2236 * the window.
2238 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2239 * instead, call the EnableWindow() function to change the window's
2240 * disabled state.
2242 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2243 * SetParent() instead.
2245 * Win95:
2246 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2247 * it sends WM_STYLECHANGING before changing the settings
2248 * and WM_STYLECHANGED afterwards.
2249 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2251 LONG WINAPI SetWindowLongW(
2252 HWND hwnd, /* [in] window to alter */
2253 INT offset, /* [in] offset, in bytes, of location to alter */
2254 LONG newval /* [in] new value of location */
2256 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2260 /*******************************************************************
2261 * GetWindowTextA (USER32.@)
2263 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2265 WCHAR *buffer;
2267 if (WIN_IsCurrentProcess( hwnd ))
2268 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2270 /* when window belongs to other process, don't send a message */
2271 if (nMaxCount <= 0) return 0;
2272 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2273 get_server_window_text( hwnd, buffer, nMaxCount );
2274 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2275 lpString[nMaxCount-1] = 0;
2276 HeapFree( GetProcessHeap(), 0, buffer );
2277 return strlen(lpString);
2281 /*******************************************************************
2282 * InternalGetWindowText (USER32.@)
2284 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2286 WND *win;
2288 if (nMaxCount <= 0) return 0;
2289 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2290 if (win != WND_OTHER_PROCESS)
2292 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2293 else lpString[0] = 0;
2294 WIN_ReleasePtr( win );
2296 else
2298 get_server_window_text( hwnd, lpString, nMaxCount );
2300 return strlenW(lpString);
2304 /*******************************************************************
2305 * GetWindowTextW (USER32.@)
2307 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2309 if (WIN_IsCurrentProcess( hwnd ))
2310 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2312 /* when window belongs to other process, don't send a message */
2313 if (nMaxCount <= 0) return 0;
2314 get_server_window_text( hwnd, lpString, nMaxCount );
2315 return strlenW(lpString);
2319 /*******************************************************************
2320 * SetWindowText (USER32.@)
2321 * SetWindowTextA (USER32.@)
2323 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2325 if (!WIN_IsCurrentProcess( hwnd ))
2327 FIXME( "cannot set text %s of other process window %p\n", debugstr_a(lpString), hwnd );
2328 SetLastError( ERROR_ACCESS_DENIED );
2329 return FALSE;
2331 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2335 /*******************************************************************
2336 * SetWindowTextW (USER32.@)
2338 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2340 if (!WIN_IsCurrentProcess( hwnd ))
2342 FIXME( "cannot set text %s of other process window %p\n", debugstr_w(lpString), hwnd );
2343 SetLastError( ERROR_ACCESS_DENIED );
2344 return FALSE;
2346 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2350 /*******************************************************************
2351 * GetWindowTextLengthA (USER32.@)
2353 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2355 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2358 /*******************************************************************
2359 * GetWindowTextLengthW (USER32.@)
2361 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2363 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2367 /*******************************************************************
2368 * IsWindow (USER32.@)
2370 BOOL WINAPI IsWindow( HWND hwnd )
2372 WND *ptr;
2373 BOOL ret;
2375 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2377 if (ptr != WND_OTHER_PROCESS)
2379 WIN_ReleasePtr( ptr );
2380 return TRUE;
2383 /* check other processes */
2384 SERVER_START_REQ( get_window_info )
2386 req->handle = hwnd;
2387 ret = !wine_server_call_err( req );
2389 SERVER_END_REQ;
2390 return ret;
2394 /***********************************************************************
2395 * GetWindowThreadProcessId (USER32.@)
2397 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2399 WND *ptr;
2400 DWORD tid = 0;
2402 if (!(ptr = WIN_GetPtr( hwnd )))
2404 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2405 return 0;
2408 if (ptr != WND_OTHER_PROCESS)
2410 /* got a valid window */
2411 tid = ptr->tid;
2412 if (process) *process = GetCurrentProcessId();
2413 WIN_ReleasePtr( ptr );
2414 return tid;
2417 /* check other processes */
2418 SERVER_START_REQ( get_window_info )
2420 req->handle = hwnd;
2421 if (!wine_server_call_err( req ))
2423 tid = (DWORD)reply->tid;
2424 if (process) *process = (DWORD)reply->pid;
2427 SERVER_END_REQ;
2428 return tid;
2432 /*****************************************************************
2433 * GetParent (USER32.@)
2435 HWND WINAPI GetParent( HWND hwnd )
2437 WND *wndPtr;
2438 HWND retvalue = 0;
2440 if (!(wndPtr = WIN_GetPtr( hwnd )))
2442 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2443 return 0;
2445 if (wndPtr == WND_OTHER_PROCESS)
2447 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2448 if (style & (WS_POPUP | WS_CHILD))
2450 SERVER_START_REQ( get_window_tree )
2452 req->handle = hwnd;
2453 if (!wine_server_call_err( req ))
2455 if (style & WS_POPUP) retvalue = reply->owner;
2456 else if (style & WS_CHILD) retvalue = reply->parent;
2459 SERVER_END_REQ;
2462 else
2464 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2465 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2466 WIN_ReleasePtr( wndPtr );
2468 return retvalue;
2472 /*****************************************************************
2473 * GetAncestor (USER32.@)
2475 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2477 WND *win;
2478 HWND *list, ret = 0;
2480 switch(type)
2482 case GA_PARENT:
2483 if (!(win = WIN_GetPtr( hwnd )))
2485 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2486 return 0;
2488 if (win != WND_OTHER_PROCESS)
2490 ret = win->parent;
2491 WIN_ReleasePtr( win );
2493 else /* need to query the server */
2495 SERVER_START_REQ( get_window_tree )
2497 req->handle = hwnd;
2498 if (!wine_server_call_err( req )) ret = reply->parent;
2500 SERVER_END_REQ;
2502 break;
2504 case GA_ROOT:
2505 if (!(list = WIN_ListParents( hwnd ))) return 0;
2507 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2508 else
2510 int count = 2;
2511 while (list[count]) count++;
2512 ret = list[count - 2]; /* get the one before the desktop */
2514 HeapFree( GetProcessHeap(), 0, list );
2515 break;
2517 case GA_ROOTOWNER:
2518 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2519 for (;;)
2521 HWND parent = GetParent( ret );
2522 if (!parent) break;
2523 ret = parent;
2525 break;
2527 return ret;
2531 /*****************************************************************
2532 * SetParent (USER32.@)
2534 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2536 WND *wndPtr;
2537 HWND retvalue, full_handle;
2538 BOOL was_visible;
2540 if (!parent) parent = GetDesktopWindow();
2541 else parent = WIN_GetFullHandle( parent );
2543 if (!IsWindow( parent ))
2545 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2546 return 0;
2549 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2550 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2552 hwnd = full_handle;
2554 if (USER_Driver.pSetParent)
2555 return USER_Driver.pSetParent( hwnd, parent );
2557 /* Windows hides the window first, then shows it again
2558 * including the WM_SHOWWINDOW messages and all */
2559 was_visible = ShowWindow( hwnd, SW_HIDE );
2561 if (!IsWindow( parent )) return 0;
2562 if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return 0;
2564 retvalue = wndPtr->parent; /* old parent */
2565 if (parent != retvalue)
2567 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2569 if (parent != GetDesktopWindow()) /* a child window */
2571 if (!(wndPtr->dwStyle & WS_CHILD))
2573 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
2574 if (menu) DestroyMenu( menu );
2578 WIN_ReleasePtr( wndPtr );
2580 /* SetParent additionally needs to make hwnd the topmost window
2581 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2582 WM_WINDOWPOSCHANGED notification messages.
2584 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2585 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2586 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2587 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2588 return retvalue;
2592 /*******************************************************************
2593 * IsChild (USER32.@)
2595 BOOL WINAPI IsChild( HWND parent, HWND child )
2597 HWND *list = WIN_ListParents( child );
2598 int i;
2599 BOOL ret;
2601 if (!list) return FALSE;
2602 parent = WIN_GetFullHandle( parent );
2603 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2604 ret = (list[i] != 0);
2605 HeapFree( GetProcessHeap(), 0, list );
2606 return ret;
2610 /***********************************************************************
2611 * IsWindowVisible (USER32.@)
2613 BOOL WINAPI IsWindowVisible( HWND hwnd )
2615 HWND *list;
2616 BOOL retval;
2617 int i;
2619 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2620 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2621 for (i = 0; list[i]; i++)
2622 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2623 retval = !list[i];
2624 HeapFree( GetProcessHeap(), 0, list );
2625 return retval;
2629 /***********************************************************************
2630 * WIN_IsWindowDrawable
2632 * hwnd is drawable when it is visible, all parents are not
2633 * minimized, and it is itself not minimized unless we are
2634 * trying to draw its default class icon.
2636 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2638 HWND *list;
2639 BOOL retval;
2640 int i;
2641 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2643 if (!(style & WS_VISIBLE)) return FALSE;
2644 if ((style & WS_MINIMIZE) && icon && GetClassLongA( hwnd, GCL_HICON )) return FALSE;
2646 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2647 for (i = 0; list[i]; i++)
2648 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2649 break;
2650 retval = !list[i];
2651 HeapFree( GetProcessHeap(), 0, list );
2652 return retval;
2656 /*******************************************************************
2657 * GetTopWindow (USER32.@)
2659 HWND WINAPI GetTopWindow( HWND hwnd )
2661 if (!hwnd) hwnd = GetDesktopWindow();
2662 return GetWindow( hwnd, GW_CHILD );
2666 /*******************************************************************
2667 * GetWindow (USER32.@)
2669 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2671 HWND retval = 0;
2673 if (rel == GW_OWNER) /* this one may be available locally */
2675 WND *wndPtr = WIN_GetPtr( hwnd );
2676 if (!wndPtr)
2678 SetLastError( ERROR_INVALID_HANDLE );
2679 return 0;
2681 if (wndPtr != WND_OTHER_PROCESS)
2683 retval = wndPtr->owner;
2684 WIN_ReleasePtr( wndPtr );
2685 return retval;
2687 /* else fall through to server call */
2690 SERVER_START_REQ( get_window_tree )
2692 req->handle = hwnd;
2693 if (!wine_server_call_err( req ))
2695 switch(rel)
2697 case GW_HWNDFIRST:
2698 retval = reply->first_sibling;
2699 break;
2700 case GW_HWNDLAST:
2701 retval = reply->last_sibling;
2702 break;
2703 case GW_HWNDNEXT:
2704 retval = reply->next_sibling;
2705 break;
2706 case GW_HWNDPREV:
2707 retval = reply->prev_sibling;
2708 break;
2709 case GW_OWNER:
2710 retval = reply->owner;
2711 break;
2712 case GW_CHILD:
2713 retval = reply->first_child;
2714 break;
2718 SERVER_END_REQ;
2719 return retval;
2723 /***********************************************************************
2724 * WIN_InternalShowOwnedPopups
2726 * Internal version of ShowOwnedPopups; Wine functions should use this
2727 * to avoid interfering with application calls to ShowOwnedPopups
2728 * and to make sure the application can't prevent showing/hiding.
2730 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2734 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2736 int count = 0;
2737 WND *pWnd;
2738 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2740 if (!win_array) return TRUE;
2743 * Show windows Lowest first, Highest last to preserve Z-Order
2745 while (win_array[count]) count++;
2746 while (--count >= 0)
2748 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2749 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2751 if (pWnd->dwStyle & WS_POPUP)
2753 if (fShow)
2755 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2756 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
2759 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2761 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2762 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2765 else
2767 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2768 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2769 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2772 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2774 ShowWindow(pWnd->hwndSelf,SW_HIDE);
2775 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2776 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
2780 WIN_ReleaseWndPtr( pWnd );
2782 HeapFree( GetProcessHeap(), 0, win_array );
2784 return TRUE;
2787 /*******************************************************************
2788 * ShowOwnedPopups (USER32.@)
2790 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2792 int count = 0;
2793 WND *pWnd;
2794 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2796 if (!win_array) return TRUE;
2798 while (win_array[count]) count++;
2799 while (--count >= 0)
2801 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2802 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2804 if (pWnd->dwStyle & WS_POPUP)
2806 if (fShow)
2808 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2810 /* In Windows, ShowOwnedPopups(TRUE) generates
2811 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2812 * regardless of the state of the owner
2814 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2815 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2818 else
2820 if (IsWindowVisible(pWnd->hwndSelf))
2822 /* In Windows, ShowOwnedPopups(FALSE) generates
2823 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2824 * regardless of the state of the owner
2826 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2827 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2831 WIN_ReleaseWndPtr( pWnd );
2833 HeapFree( GetProcessHeap(), 0, win_array );
2834 return TRUE;
2838 /*******************************************************************
2839 * GetLastActivePopup (USER32.@)
2841 HWND WINAPI GetLastActivePopup( HWND hwnd )
2843 HWND retval = hwnd;
2845 SERVER_START_REQ( get_window_info )
2847 req->handle = hwnd;
2848 if (!wine_server_call_err( req )) retval = reply->last_active;
2850 SERVER_END_REQ;
2851 return retval;
2855 /*******************************************************************
2856 * WIN_ListParents
2858 * Build an array of all parents of a given window, starting with
2859 * the immediate parent. The array must be freed with HeapFree.
2860 * Returns NULL if window is a top-level window.
2862 HWND *WIN_ListParents( HWND hwnd )
2864 WND *win;
2865 HWND current, *list;
2866 int pos = 0, size = 16, count = 0;
2868 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2870 current = hwnd;
2871 for (;;)
2873 if (!(win = WIN_GetPtr( current ))) goto empty;
2874 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
2875 list[pos] = win->parent;
2876 WIN_ReleasePtr( win );
2877 if (!(current = list[pos]))
2879 if (!pos) goto empty;
2880 return list;
2882 if (++pos == size - 1)
2884 /* need to grow the list */
2885 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
2886 if (!new_list) goto empty;
2887 list = new_list;
2888 size += 16;
2892 /* at least one parent belongs to another process, have to query the server */
2894 for (;;)
2896 count = 0;
2897 SERVER_START_REQ( get_window_parents )
2899 req->handle = hwnd;
2900 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
2901 if (!wine_server_call( req )) count = reply->count;
2903 SERVER_END_REQ;
2904 if (!count) goto empty;
2905 if (size > count)
2907 list[count] = 0;
2908 return list;
2910 HeapFree( GetProcessHeap(), 0, list );
2911 size = count + 1;
2912 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2915 empty:
2916 HeapFree( GetProcessHeap(), 0, list );
2917 return NULL;
2921 /*******************************************************************
2922 * WIN_ListChildren
2924 * Build an array of the children of a given window. The array must be
2925 * freed with HeapFree. Returns NULL when no windows are found.
2927 HWND *WIN_ListChildren( HWND hwnd )
2929 return list_window_children( hwnd, 0, 0 );
2933 /*******************************************************************
2934 * EnumWindows (USER32.@)
2936 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2938 HWND *list;
2939 BOOL ret = TRUE;
2940 int i, iWndsLocks;
2942 /* We have to build a list of all windows first, to avoid */
2943 /* unpleasant side-effects, for instance if the callback */
2944 /* function changes the Z-order of the windows. */
2946 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2948 /* Now call the callback function for every window */
2950 iWndsLocks = WIN_SuspendWndsLock();
2951 for (i = 0; list[i]; i++)
2953 /* Make sure that the window still exists */
2954 if (!IsWindow( list[i] )) continue;
2955 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2957 WIN_RestoreWndsLock(iWndsLocks);
2958 HeapFree( GetProcessHeap(), 0, list );
2959 return ret;
2963 /**********************************************************************
2964 * EnumThreadWindows (USER32.@)
2966 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2968 HWND *list;
2969 int i, iWndsLocks;
2971 if (!(list = list_window_children( GetDesktopWindow(), 0, id ))) return TRUE;
2973 /* Now call the callback function for every window */
2975 iWndsLocks = WIN_SuspendWndsLock();
2976 for (i = 0; list[i]; i++)
2977 if (!func( list[i], lParam )) break;
2978 WIN_RestoreWndsLock(iWndsLocks);
2979 HeapFree( GetProcessHeap(), 0, list );
2980 return TRUE;
2984 /**********************************************************************
2985 * WIN_EnumChildWindows
2987 * Helper function for EnumChildWindows().
2989 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2991 HWND *childList;
2992 BOOL ret = FALSE;
2994 for ( ; *list; list++)
2996 /* Make sure that the window still exists */
2997 if (!IsWindow( *list )) continue;
2998 /* skip owned windows */
2999 if (GetWindow( *list, GW_OWNER )) continue;
3000 /* Build children list first */
3001 childList = WIN_ListChildren( *list );
3003 ret = func( *list, lParam );
3005 if (childList)
3007 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
3008 HeapFree( GetProcessHeap(), 0, childList );
3010 if (!ret) return FALSE;
3012 return TRUE;
3016 /**********************************************************************
3017 * EnumChildWindows (USER32.@)
3019 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
3021 HWND *list;
3022 int iWndsLocks;
3024 if (!(list = WIN_ListChildren( parent ))) return FALSE;
3025 iWndsLocks = WIN_SuspendWndsLock();
3026 WIN_EnumChildWindows( list, func, lParam );
3027 WIN_RestoreWndsLock(iWndsLocks);
3028 HeapFree( GetProcessHeap(), 0, list );
3029 return TRUE;
3033 /*******************************************************************
3034 * AnyPopup (USER.52)
3036 BOOL16 WINAPI AnyPopup16(void)
3038 return AnyPopup();
3042 /*******************************************************************
3043 * AnyPopup (USER32.@)
3045 BOOL WINAPI AnyPopup(void)
3047 int i;
3048 BOOL retvalue;
3049 HWND *list = WIN_ListChildren( GetDesktopWindow() );
3051 if (!list) return FALSE;
3052 for (i = 0; list[i]; i++)
3054 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
3056 retvalue = (list[i] != 0);
3057 HeapFree( GetProcessHeap(), 0, list );
3058 return retvalue;
3062 /*******************************************************************
3063 * FlashWindow (USER32.@)
3065 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3067 WND *wndPtr = WIN_FindWndPtr(hWnd);
3069 TRACE("%p\n", hWnd);
3071 if (!wndPtr) return FALSE;
3072 hWnd = wndPtr->hwndSelf; /* make it a full handle */
3074 if (wndPtr->dwStyle & WS_MINIMIZE)
3076 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3078 HDC hDC = GetDC(hWnd);
3080 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM)hDC, 0 ))
3081 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
3083 ReleaseDC( hWnd, hDC );
3084 wndPtr->flags |= WIN_NCACTIVATED;
3086 else
3088 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3089 wndPtr->flags &= ~WIN_NCACTIVATED;
3091 WIN_ReleaseWndPtr(wndPtr);
3092 return TRUE;
3094 else
3096 WPARAM16 wparam;
3097 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3098 else wparam = (hWnd == GetForegroundWindow());
3100 WIN_ReleaseWndPtr(wndPtr);
3101 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3102 return wparam;
3107 /*******************************************************************
3108 * GetWindowContextHelpId (USER32.@)
3110 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3112 DWORD retval;
3113 WND *wnd = WIN_FindWndPtr( hwnd );
3114 if (!wnd) return 0;
3115 retval = wnd->helpContext;
3116 WIN_ReleaseWndPtr(wnd);
3117 return retval;
3121 /*******************************************************************
3122 * SetWindowContextHelpId (USER32.@)
3124 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3126 WND *wnd = WIN_FindWndPtr( hwnd );
3127 if (!wnd) return FALSE;
3128 wnd->helpContext = id;
3129 WIN_ReleaseWndPtr(wnd);
3130 return TRUE;
3134 /*******************************************************************
3135 * DragDetect (USER32.@)
3137 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3139 MSG msg;
3140 RECT rect;
3142 rect.left = pt.x - wDragWidth;
3143 rect.right = pt.x + wDragWidth;
3145 rect.top = pt.y - wDragHeight;
3146 rect.bottom = pt.y + wDragHeight;
3148 SetCapture(hWnd);
3150 while(1)
3152 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3154 if( msg.message == WM_LBUTTONUP )
3156 ReleaseCapture();
3157 return 0;
3159 if( msg.message == WM_MOUSEMOVE )
3161 POINT tmp;
3162 tmp.x = LOWORD(msg.lParam);
3163 tmp.y = HIWORD(msg.lParam);
3164 if( !PtInRect( &rect, tmp ))
3166 ReleaseCapture();
3167 return 1;
3171 WaitMessage();
3173 return 0;
3176 /******************************************************************************
3177 * GetWindowModuleFileNameA (USER32.@)
3179 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3181 FIXME("GetWindowModuleFileNameA(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3182 hwnd, lpszFileName, cchFileNameMax);
3183 return 0;
3186 /******************************************************************************
3187 * GetWindowModuleFileNameW (USER32.@)
3189 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3191 FIXME("GetWindowModuleFileNameW(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3192 hwnd, lpszFileName, cchFileNameMax);
3193 return 0;
3196 /******************************************************************************
3197 * GetWindowInfo (USER32.@)
3198 * hwnd: in
3199 * pwi: out.
3200 * MS Documentation mentions that pwi->cbSize must be set to SIZEOF(WINDOWINFO)
3201 * this may be because this structure changed over time. If this is the
3202 * the case, then please: FIXME.
3203 * Using the structure described in MSDN for 98/ME/NT(4.0 SP3)/2000/XP.
3205 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3207 WND *wndInfo = NULL;
3208 if (!pwi) return FALSE;
3209 if (pwi->cbSize != sizeof(WINDOWINFO))
3211 FIXME("windowinfo->cbSize != sizeof(WINDOWINFO). Please report\n");
3212 return FALSE;
3214 wndInfo = WIN_GetPtr(hwnd);
3215 if (!wndInfo) return FALSE;
3216 if (wndInfo == WND_OTHER_PROCESS)
3218 FIXME("window belong to other process\n");
3219 return FALSE;
3222 pwi->rcWindow = wndInfo->rectWindow;
3223 pwi->rcClient = wndInfo->rectClient;
3224 pwi->dwStyle = wndInfo->dwStyle;
3225 pwi->dwExStyle = wndInfo->dwExStyle;
3226 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3227 /* if active WS_ACTIVECAPTION, else 0 */
3229 pwi->cxWindowBorders = ((wndInfo->dwStyle & WS_BORDER) ?
3230 GetSystemMetrics(SM_CXBORDER) : 0);
3231 pwi->cyWindowBorders = ((wndInfo->dwStyle & WS_BORDER) ?
3232 GetSystemMetrics(SM_CYBORDER) : 0);
3233 /* above two: I'm presuming that borders widths are the same
3234 * for each window - so long as its actually using a border.. */
3236 pwi->atomWindowType = GetClassLongA( hwnd, GCW_ATOM );
3237 pwi->wCreatorVersion = GetVersion();
3238 /* Docs say this should be the version that
3239 * CREATED the window. But eh?.. Isn't that just the
3240 * version we are running.. Unless ofcourse its some wacky
3241 * RPC stuff or something */
3243 WIN_ReleasePtr(wndInfo);
3244 return TRUE;