Porting fixes.
[wine/wine64.git] / windows / win.c
blob0e9ce70f84399632adce1b0eb40d1271ae4f0212
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 <stdarg.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include "windef.h"
29 #include "winbase.h"
30 #include "wine/winbase16.h"
31 #include "wine/winuser16.h"
32 #include "wownt32.h"
33 #include "wine/server.h"
34 #include "wine/unicode.h"
35 #include "win.h"
36 #include "user.h"
37 #include "dce.h"
38 #include "controls.h"
39 #include "cursoricon.h"
40 #include "message.h"
41 #include "winpos.h"
42 #include "winerror.h"
43 #include "wine/debug.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(win);
46 WINE_DECLARE_DEBUG_CHANNEL(msg);
48 #define NB_USER_HANDLES (LAST_USER_HANDLE - FIRST_USER_HANDLE + 1)
50 /**********************************************************************/
52 /* Desktop window */
53 static WND *pWndDesktop = NULL;
55 static WORD wDragWidth = 4;
56 static WORD wDragHeight= 3;
58 static void *user_handles[NB_USER_HANDLES];
60 /***********************************************************************
61 * create_window_handle
63 * Create a window handle with the server.
65 static WND *create_window_handle( HWND parent, HWND owner, ATOM atom, unsigned int extra_bytes )
67 BOOL res;
68 user_handle_t handle = 0;
69 WORD index;
70 WND *win = HeapAlloc( GetProcessHeap(), 0, sizeof(WND) + extra_bytes - sizeof(win->wExtra) );
72 if (!win) return NULL;
74 USER_Lock();
76 SERVER_START_REQ( create_window )
78 req->parent = parent;
79 req->owner = owner;
80 req->atom = atom;
81 req->extra = extra_bytes;
82 if ((res = !wine_server_call_err( req ))) handle = reply->handle;
84 SERVER_END_REQ;
86 if (!res)
88 USER_Unlock();
89 HeapFree( GetProcessHeap(), 0, win );
90 return NULL;
92 index = LOWORD(handle) - FIRST_USER_HANDLE;
93 assert( index < NB_USER_HANDLES );
94 user_handles[index] = win;
95 win->hwndSelf = handle;
96 win->dwMagic = WND_MAGIC;
97 win->irefCount = 1;
98 return win;
102 /***********************************************************************
103 * free_window_handle
105 * Free a window handle.
107 static WND *free_window_handle( HWND hwnd )
109 WND *ptr;
110 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
112 if (index >= NB_USER_HANDLES) return NULL;
113 USER_Lock();
114 if ((ptr = user_handles[index]))
116 SERVER_START_REQ( destroy_window )
118 req->handle = hwnd;
119 if (!wine_server_call_err( req ))
120 user_handles[index] = NULL;
121 else
122 ptr = NULL;
124 SERVER_END_REQ;
126 USER_Unlock();
127 if (ptr) HeapFree( GetProcessHeap(), 0, ptr );
128 return ptr;
132 /*******************************************************************
133 * list_window_children
135 * Build an array of the children of a given window. The array must be
136 * freed with HeapFree. Returns NULL when no windows are found.
138 static HWND *list_window_children( HWND hwnd, ATOM atom, DWORD tid )
140 HWND *list;
141 int size = 32;
143 for (;;)
145 int count = 0;
147 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
149 SERVER_START_REQ( get_window_children )
151 req->parent = hwnd;
152 req->atom = atom;
153 req->tid = tid;
154 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
155 if (!wine_server_call( req )) count = reply->count;
157 SERVER_END_REQ;
158 if (count && count < size)
160 list[count] = 0;
161 return list;
163 HeapFree( GetProcessHeap(), 0, list );
164 if (!count) break;
165 size = count + 1; /* restart with a large enough buffer */
167 return NULL;
171 /*******************************************************************
172 * send_parent_notify
174 static void send_parent_notify( HWND hwnd, UINT msg )
176 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD)) return;
177 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY) return;
178 SendMessageW( GetParent(hwnd), WM_PARENTNOTIFY,
179 MAKEWPARAM( msg, GetWindowLongW( hwnd, GWL_ID )), (LPARAM)hwnd );
183 /*******************************************************************
184 * get_server_window_text
186 * Retrieve the window text from the server.
188 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
190 size_t len = 0;
192 SERVER_START_REQ( get_window_text )
194 req->handle = hwnd;
195 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
196 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
198 SERVER_END_REQ;
199 text[len / sizeof(WCHAR)] = 0;
203 /***********************************************************************
204 * WIN_GetPtr
206 * Return a pointer to the WND structure if local to the process,
207 * or WND_OTHER_PROCESS if handle may be valid in other process.
208 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
210 WND *WIN_GetPtr( HWND hwnd )
212 WND * ptr;
213 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
215 if (index >= NB_USER_HANDLES) return NULL;
217 USER_Lock();
218 if ((ptr = user_handles[index]))
220 if (ptr->dwMagic == WND_MAGIC && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
221 return ptr;
222 ptr = NULL;
224 else ptr = WND_OTHER_PROCESS;
225 USER_Unlock();
226 return ptr;
230 /***********************************************************************
231 * WIN_IsCurrentProcess
233 * Check whether a given window belongs to the current process (and return the full handle).
235 HWND WIN_IsCurrentProcess( HWND hwnd )
237 WND *ptr;
238 HWND ret;
240 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS) return 0;
241 ret = ptr->hwndSelf;
242 WIN_ReleasePtr( ptr );
243 return ret;
247 /***********************************************************************
248 * WIN_IsCurrentThread
250 * Check whether a given window belongs to the current thread (and return the full handle).
252 HWND WIN_IsCurrentThread( HWND hwnd )
254 WND *ptr;
255 HWND ret = 0;
257 if ((ptr = WIN_GetPtr( hwnd )) && ptr != WND_OTHER_PROCESS)
259 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
260 WIN_ReleasePtr( ptr );
262 return ret;
266 /***********************************************************************
267 * WIN_Handle32
269 * Convert a 16-bit window handle to a full 32-bit handle.
271 HWND WIN_Handle32( HWND16 hwnd16 )
273 WND *ptr;
274 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
276 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
277 /* do sign extension for -2 and -3 */
278 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
280 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
282 if (ptr != WND_OTHER_PROCESS)
284 hwnd = ptr->hwndSelf;
285 WIN_ReleasePtr( ptr );
287 else /* may belong to another process */
289 SERVER_START_REQ( get_window_info )
291 req->handle = hwnd;
292 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
294 SERVER_END_REQ;
296 return hwnd;
300 /***********************************************************************
301 * WIN_FindWndPtr
303 * Return a pointer to the WND structure corresponding to a HWND.
305 WND * WIN_FindWndPtr( HWND hwnd )
307 WND * ptr;
309 if (!hwnd) return NULL;
311 if ((ptr = WIN_GetPtr( hwnd )))
313 if (ptr != WND_OTHER_PROCESS)
315 /* increment destruction monitoring */
316 ptr->irefCount++;
317 return ptr;
319 if (IsWindow( hwnd )) /* check other processes */
321 ERR( "window %p belongs to other process\n", hwnd );
322 /* DbgBreakPoint(); */
325 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
326 return NULL;
330 /***********************************************************************
331 * WIN_ReleaseWndPtr
333 * Release the pointer to the WND structure.
335 void WIN_ReleaseWndPtr(WND *wndPtr)
337 if(!wndPtr) return;
339 /* Decrement destruction monitoring value */
340 wndPtr->irefCount--;
341 /* Check if it's time to release the memory */
342 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
344 /* Release memory */
345 free_window_handle( wndPtr->hwndSelf );
347 else if(wndPtr->irefCount < 0)
349 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
350 ERR("forgot a Lock on %p somewhere\n",wndPtr);
352 /* unlock all WND structures for thread safeness */
353 USER_Unlock();
357 /***********************************************************************
358 * WIN_UnlinkWindow
360 * Remove a window from the siblings linked list.
362 void WIN_UnlinkWindow( HWND hwnd )
364 WIN_LinkWindow( hwnd, 0, 0 );
368 /***********************************************************************
369 * WIN_LinkWindow
371 * Insert a window into the siblings linked list.
372 * The window is inserted after the specified window, which can also
373 * be specified as HWND_TOP or HWND_BOTTOM.
374 * If parent is 0, window is unlinked from the tree.
376 void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
378 WND *wndPtr = WIN_GetPtr( hwnd );
380 if (!wndPtr) return;
381 if (wndPtr == WND_OTHER_PROCESS)
383 if (IsWindow(hwnd)) ERR(" cannot link other process window %p\n", hwnd );
384 return;
387 SERVER_START_REQ( link_window )
389 req->handle = hwnd;
390 req->parent = parent;
391 req->previous = hwndInsertAfter;
392 if (!wine_server_call( req ))
394 if (reply->full_parent) wndPtr->parent = reply->full_parent;
398 SERVER_END_REQ;
399 WIN_ReleasePtr( wndPtr );
403 /***********************************************************************
404 * WIN_SetOwner
406 * Change the owner of a window.
408 HWND WIN_SetOwner( HWND hwnd, HWND owner )
410 WND *win = WIN_GetPtr( hwnd );
411 HWND ret = 0;
413 if (!win) return 0;
414 if (win == WND_OTHER_PROCESS)
416 if (IsWindow(hwnd)) ERR( "cannot set owner %p on other process window %p\n", owner, hwnd );
417 return 0;
419 SERVER_START_REQ( set_window_owner )
421 req->handle = hwnd;
422 req->owner = owner;
423 if (!wine_server_call( req ))
425 win->owner = reply->full_owner;
426 ret = reply->prev_owner;
429 SERVER_END_REQ;
430 WIN_ReleasePtr( win );
431 return ret;
435 /***********************************************************************
436 * WIN_SetStyle
438 * Change the style of a window.
440 LONG WIN_SetStyle( HWND hwnd, LONG style )
442 BOOL ok;
443 LONG ret = 0;
444 WND *win = WIN_GetPtr( hwnd );
446 if (!win) return 0;
447 if (win == WND_OTHER_PROCESS)
449 if (IsWindow(hwnd))
450 ERR( "cannot set style %lx on other process window %p\n", style, hwnd );
451 return 0;
453 if (style == win->dwStyle)
455 WIN_ReleasePtr( win );
456 return style;
458 SERVER_START_REQ( set_window_info )
460 req->handle = hwnd;
461 req->flags = SET_WIN_STYLE;
462 req->style = style;
463 req->extra_offset = -1;
464 if ((ok = !wine_server_call( req )))
466 ret = reply->old_style;
467 win->dwStyle = style;
470 SERVER_END_REQ;
471 WIN_ReleasePtr( win );
472 if (ok && USER_Driver.pSetWindowStyle) USER_Driver.pSetWindowStyle( hwnd, ret );
473 return ret;
477 /***********************************************************************
478 * WIN_SetExStyle
480 * Change the extended style of a window.
482 LONG WIN_SetExStyle( HWND hwnd, LONG style )
484 LONG ret = 0;
485 WND *win = WIN_GetPtr( hwnd );
487 if (!win) return 0;
488 if (win == WND_OTHER_PROCESS)
490 if (IsWindow(hwnd))
491 ERR( "cannot set exstyle %lx on other process window %p\n", style, hwnd );
492 return 0;
494 if (style == win->dwExStyle)
496 WIN_ReleasePtr( win );
497 return style;
499 SERVER_START_REQ( set_window_info )
501 req->handle = hwnd;
502 req->flags = SET_WIN_EXSTYLE;
503 req->ex_style = style;
504 req->extra_offset = -1;
505 if (!wine_server_call( req ))
507 ret = reply->old_ex_style;
508 win->dwExStyle = style;
511 SERVER_END_REQ;
512 WIN_ReleasePtr( win );
513 return ret;
517 /***********************************************************************
518 * WIN_SetRectangles
520 * Set the window and client rectangles.
522 void WIN_SetRectangles( HWND hwnd, const RECT *rectWindow, const RECT *rectClient )
524 WND *win = WIN_GetPtr( hwnd );
525 BOOL ret;
527 if (!win) return;
528 if (win == WND_OTHER_PROCESS)
530 if (IsWindow( hwnd )) ERR( "cannot set rectangles of other process window %p\n", hwnd );
531 return;
533 SERVER_START_REQ( set_window_rectangles )
535 req->handle = hwnd;
536 req->window.left = rectWindow->left;
537 req->window.top = rectWindow->top;
538 req->window.right = rectWindow->right;
539 req->window.bottom = rectWindow->bottom;
540 req->client.left = rectClient->left;
541 req->client.top = rectClient->top;
542 req->client.right = rectClient->right;
543 req->client.bottom = rectClient->bottom;
544 ret = !wine_server_call( req );
546 SERVER_END_REQ;
547 if (ret)
549 win->rectWindow = *rectWindow;
550 win->rectClient = *rectClient;
552 TRACE( "win %p window (%ld,%ld)-(%ld,%ld) client (%ld,%ld)-(%ld,%ld)\n", hwnd,
553 rectWindow->left, rectWindow->top, rectWindow->right, rectWindow->bottom,
554 rectClient->left, rectClient->top, rectClient->right, rectClient->bottom );
556 WIN_ReleasePtr( win );
560 /***********************************************************************
561 * WIN_GetRectangles
563 * Get the window and client rectangles.
565 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
567 WND *win = WIN_GetPtr( hwnd );
568 BOOL ret = TRUE;
570 if (!win) return FALSE;
571 if (win == WND_OTHER_PROCESS)
573 SERVER_START_REQ( get_window_rectangles )
575 req->handle = hwnd;
576 if ((ret = !wine_server_call( req )))
578 if (rectWindow)
580 rectWindow->left = reply->window.left;
581 rectWindow->top = reply->window.top;
582 rectWindow->right = reply->window.right;
583 rectWindow->bottom = reply->window.bottom;
585 if (rectClient)
587 rectClient->left = reply->client.left;
588 rectClient->top = reply->client.top;
589 rectClient->right = reply->client.right;
590 rectClient->bottom = reply->client.bottom;
594 SERVER_END_REQ;
596 else
598 if (rectWindow) *rectWindow = win->rectWindow;
599 if (rectClient) *rectClient = win->rectClient;
600 WIN_ReleasePtr( win );
602 return ret;
606 /***********************************************************************
607 * WIN_DestroyWindow
609 * Destroy storage associated to a window. "Internals" p.358
611 LRESULT WIN_DestroyWindow( HWND hwnd )
613 WND *wndPtr;
614 HWND *list;
616 TRACE("%p\n", hwnd );
618 if (!(hwnd = WIN_IsCurrentThread( hwnd )))
620 ERR( "window doesn't belong to current thread\n" );
621 return 0;
624 /* free child windows */
625 if ((list = WIN_ListChildren( hwnd )))
627 int i;
628 for (i = 0; list[i]; i++)
630 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
631 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
633 HeapFree( GetProcessHeap(), 0, list );
637 * Clear the update region to make sure no WM_PAINT messages will be
638 * generated for this window while processing the WM_NCDESTROY.
640 RedrawWindow( hwnd, NULL, 0,
641 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
644 * Send the WM_NCDESTROY to the window being destroyed.
646 SendMessageA( hwnd, WM_NCDESTROY, 0, 0);
648 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
650 WINPOS_CheckInternalPos( hwnd );
651 if( hwnd == GetCapture()) ReleaseCapture();
653 /* free resources associated with the window */
655 TIMER_RemoveWindowTimers( hwnd );
657 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
659 if (!(wndPtr->dwStyle & WS_CHILD))
661 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
662 if (menu) DestroyMenu( menu );
664 if (wndPtr->hSysMenu)
666 DestroyMenu( wndPtr->hSysMenu );
667 wndPtr->hSysMenu = 0;
669 DCE_FreeWindowDCE( hwnd ); /* Always do this to catch orphaned DCs */
670 USER_Driver.pDestroyWindow( hwnd );
671 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
672 CLASS_RemoveWindow( wndPtr->class );
673 wndPtr->class = NULL;
674 wndPtr->dwMagic = 0; /* Mark it as invalid */
675 WIN_ReleaseWndPtr( wndPtr );
676 return 0;
679 /***********************************************************************
680 * WIN_DestroyThreadWindows
682 * Destroy all children of 'wnd' owned by the current thread.
683 * Return TRUE if something was done.
685 void WIN_DestroyThreadWindows( HWND hwnd )
687 HWND *list;
688 int i;
690 if (!(list = WIN_ListChildren( hwnd ))) return;
691 for (i = 0; list[i]; i++)
693 if (WIN_IsCurrentThread( list[i] ))
694 DestroyWindow( list[i] );
695 else
696 WIN_DestroyThreadWindows( list[i] );
698 HeapFree( GetProcessHeap(), 0, list );
701 /***********************************************************************
702 * WIN_CreateDesktopWindow
704 * Create the desktop window.
706 BOOL WIN_CreateDesktopWindow(void)
708 struct tagCLASS *class;
709 HWND hwndDesktop;
710 INT wndExtra;
711 DWORD clsStyle;
712 WNDPROC winproc;
713 DCE *dce;
714 CREATESTRUCTA cs;
715 RECT rect;
717 TRACE("Creating desktop window\n");
719 if (!WINPOS_CreateInternalPosAtom() ||
720 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
721 &wndExtra, &winproc, &clsStyle, &dce )))
722 return FALSE;
724 pWndDesktop = create_window_handle( 0, 0, LOWORD(DESKTOP_CLASS_ATOM), wndExtra );
725 if (!pWndDesktop) return FALSE;
726 hwndDesktop = pWndDesktop->hwndSelf;
728 pWndDesktop->tid = 0; /* nobody owns the desktop */
729 pWndDesktop->parent = 0;
730 pWndDesktop->owner = 0;
731 pWndDesktop->class = class;
732 pWndDesktop->text = NULL;
733 pWndDesktop->hrgnUpdate = 0;
734 pWndDesktop->clsStyle = clsStyle;
735 pWndDesktop->dce = NULL;
736 pWndDesktop->pVScroll = NULL;
737 pWndDesktop->pHScroll = NULL;
738 pWndDesktop->helpContext = 0;
739 pWndDesktop->flags = 0;
740 pWndDesktop->hSysMenu = 0;
741 pWndDesktop->winproc = winproc;
742 pWndDesktop->cbWndExtra = wndExtra;
744 cs.lpCreateParams = NULL;
745 cs.hInstance = 0;
746 cs.hMenu = 0;
747 cs.hwndParent = 0;
748 cs.x = 0;
749 cs.y = 0;
750 cs.cx = GetSystemMetrics( SM_CXSCREEN );
751 cs.cy = GetSystemMetrics( SM_CYSCREEN );
752 cs.style = pWndDesktop->dwStyle;
753 cs.dwExStyle = pWndDesktop->dwExStyle;
754 cs.lpszName = NULL;
755 cs.lpszClass = DESKTOP_CLASS_ATOM;
757 SetRect( &rect, 0, 0, cs.cx, cs.cy );
758 WIN_SetRectangles( hwndDesktop, &rect, &rect );
760 SERVER_START_REQ( set_window_info )
762 req->handle = hwndDesktop;
763 req->flags = 0; /* don't set anything, just retrieve */
764 req->extra_offset = -1;
765 wine_server_call( req );
766 pWndDesktop->dwStyle = reply->old_style;
767 pWndDesktop->dwExStyle = reply->old_ex_style;
768 pWndDesktop->hInstance = (HINSTANCE)reply->old_instance;
769 pWndDesktop->userdata = (ULONG_PTR)reply->old_user_data;
770 pWndDesktop->wIDmenu = reply->old_id;
772 SERVER_END_REQ;
774 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE ))
776 WIN_ReleaseWndPtr( pWndDesktop );
777 return FALSE;
780 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
781 WIN_ReleaseWndPtr( pWndDesktop );
782 return TRUE;
786 /***********************************************************************
787 * WIN_FixCoordinates
789 * Fix the coordinates - Helper for WIN_CreateWindowEx.
790 * returns default show mode in sw.
791 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
793 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
795 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
796 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
798 if (cs->style & (WS_CHILD | WS_POPUP))
800 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
801 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
803 else /* overlapped window */
805 STARTUPINFOA info;
807 GetStartupInfoA( &info );
809 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
811 /* Never believe Microsoft's documentation... CreateWindowEx doc says
812 * that if an overlapped window is created with WS_VISIBLE style bit
813 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
814 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
815 * reveals that
817 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
818 * 2) it does not ignore the y parameter as the docs claim; instead, it
819 * uses it as second parameter to ShowWindow() unless y is either
820 * CW_USEDEFAULT or CW_USEDEFAULT16.
822 * The fact that we didn't do 2) caused bogus windows pop up when wine
823 * was running apps that were using this obscure feature. Example -
824 * calc.exe that comes with Win98 (only Win98, it's different from
825 * the one that comes with Win95 and NT)
827 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
828 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
829 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
832 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
834 if (info.dwFlags & STARTF_USESIZE)
836 cs->cx = info.dwXSize;
837 cs->cy = info.dwYSize;
839 else /* if no other hint from the app, pick 3/4 of the screen real estate */
841 RECT r;
842 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
843 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
844 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
849 else
851 /* neither x nor cx are default. Check the y values .
852 * In the trace we see Outlook and Outlook Express using
853 * cy set to CW_USEDEFAULT when opening the address book.
855 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16) {
856 RECT r;
857 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
858 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
859 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
864 /***********************************************************************
865 * dump_window_styles
867 static void dump_window_styles( DWORD style, DWORD exstyle )
869 TRACE( "style:" );
870 if(style & WS_POPUP) TRACE(" WS_POPUP");
871 if(style & WS_CHILD) TRACE(" WS_CHILD");
872 if(style & WS_MINIMIZE) TRACE(" WS_MINIMIZE");
873 if(style & WS_VISIBLE) TRACE(" WS_VISIBLE");
874 if(style & WS_DISABLED) TRACE(" WS_DISABLED");
875 if(style & WS_CLIPSIBLINGS) TRACE(" WS_CLIPSIBLINGS");
876 if(style & WS_CLIPCHILDREN) TRACE(" WS_CLIPCHILDREN");
877 if(style & WS_MAXIMIZE) TRACE(" WS_MAXIMIZE");
878 if((style & WS_CAPTION) == WS_CAPTION) TRACE(" WS_CAPTION");
879 else
881 if(style & WS_BORDER) TRACE(" WS_BORDER");
882 if(style & WS_DLGFRAME) TRACE(" WS_DLGFRAME");
884 if(style & WS_VSCROLL) TRACE(" WS_VSCROLL");
885 if(style & WS_HSCROLL) TRACE(" WS_HSCROLL");
886 if(style & WS_SYSMENU) TRACE(" WS_SYSMENU");
887 if(style & WS_THICKFRAME) TRACE(" WS_THICKFRAME");
888 if(style & WS_GROUP) TRACE(" WS_GROUP");
889 if(style & WS_TABSTOP) TRACE(" WS_TABSTOP");
890 if(style & WS_MINIMIZEBOX) TRACE(" WS_MINIMIZEBOX");
891 if(style & WS_MAXIMIZEBOX) TRACE(" WS_MAXIMIZEBOX");
893 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
894 #define DUMPED_STYLES \
895 (WS_POPUP | \
896 WS_CHILD | \
897 WS_MINIMIZE | \
898 WS_VISIBLE | \
899 WS_DISABLED | \
900 WS_CLIPSIBLINGS | \
901 WS_CLIPCHILDREN | \
902 WS_MAXIMIZE | \
903 WS_BORDER | \
904 WS_DLGFRAME | \
905 WS_VSCROLL | \
906 WS_HSCROLL | \
907 WS_SYSMENU | \
908 WS_THICKFRAME | \
909 WS_GROUP | \
910 WS_TABSTOP | \
911 WS_MINIMIZEBOX | \
912 WS_MAXIMIZEBOX)
914 if(style & ~DUMPED_STYLES) TRACE(" %08lx", style & ~DUMPED_STYLES);
915 TRACE("\n");
916 #undef DUMPED_STYLES
918 TRACE( "exstyle:" );
919 if(exstyle & WS_EX_DLGMODALFRAME) TRACE(" WS_EX_DLGMODALFRAME");
920 if(exstyle & WS_EX_DRAGDETECT) TRACE(" WS_EX_DRAGDETECT");
921 if(exstyle & WS_EX_NOPARENTNOTIFY) TRACE(" WS_EX_NOPARENTNOTIFY");
922 if(exstyle & WS_EX_TOPMOST) TRACE(" WS_EX_TOPMOST");
923 if(exstyle & WS_EX_ACCEPTFILES) TRACE(" WS_EX_ACCEPTFILES");
924 if(exstyle & WS_EX_TRANSPARENT) TRACE(" WS_EX_TRANSPARENT");
925 if(exstyle & WS_EX_MDICHILD) TRACE(" WS_EX_MDICHILD");
926 if(exstyle & WS_EX_TOOLWINDOW) TRACE(" WS_EX_TOOLWINDOW");
927 if(exstyle & WS_EX_WINDOWEDGE) TRACE(" WS_EX_WINDOWEDGE");
928 if(exstyle & WS_EX_CLIENTEDGE) TRACE(" WS_EX_CLIENTEDGE");
929 if(exstyle & WS_EX_CONTEXTHELP) TRACE(" WS_EX_CONTEXTHELP");
930 if(exstyle & WS_EX_RIGHT) TRACE(" WS_EX_RIGHT");
931 if(exstyle & WS_EX_RTLREADING) TRACE(" WS_EX_RTLREADING");
932 if(exstyle & WS_EX_LEFTSCROLLBAR) TRACE(" WS_EX_LEFTSCROLLBAR");
933 if(exstyle & WS_EX_CONTROLPARENT) TRACE(" WS_EX_CONTROLPARENT");
934 if(exstyle & WS_EX_STATICEDGE) TRACE(" WS_EX_STATICEDGE");
935 if(exstyle & WS_EX_APPWINDOW) TRACE(" WS_EX_APPWINDOW");
936 if(exstyle & WS_EX_LAYERED) TRACE(" WS_EX_LAYERED");
938 #define DUMPED_EX_STYLES \
939 (WS_EX_DLGMODALFRAME | \
940 WS_EX_DRAGDETECT | \
941 WS_EX_NOPARENTNOTIFY | \
942 WS_EX_TOPMOST | \
943 WS_EX_ACCEPTFILES | \
944 WS_EX_TRANSPARENT | \
945 WS_EX_MDICHILD | \
946 WS_EX_TOOLWINDOW | \
947 WS_EX_WINDOWEDGE | \
948 WS_EX_CLIENTEDGE | \
949 WS_EX_CONTEXTHELP | \
950 WS_EX_RIGHT | \
951 WS_EX_RTLREADING | \
952 WS_EX_LEFTSCROLLBAR | \
953 WS_EX_CONTROLPARENT | \
954 WS_EX_STATICEDGE | \
955 WS_EX_APPWINDOW | \
956 WS_EX_LAYERED)
958 if(exstyle & ~DUMPED_EX_STYLES) TRACE(" %08lx", exstyle & ~DUMPED_EX_STYLES);
959 TRACE("\n");
960 #undef DUMPED_EX_STYLES
964 /***********************************************************************
965 * WIN_CreateWindowEx
967 * Implementation of CreateWindowEx().
969 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
970 WINDOWPROCTYPE type )
972 INT sw = SW_SHOW;
973 struct tagCLASS *classPtr;
974 WND *wndPtr;
975 HWND hwnd, parent, owner;
976 INT wndExtra;
977 DWORD clsStyle;
978 WNDPROC winproc;
979 DCE *dce;
980 BOOL unicode = (type == WIN_PROC_32W);
982 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
983 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
984 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszClass) : debugstr_a(cs->lpszClass),
985 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
986 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
988 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
990 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
991 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
993 /* Find the parent window */
995 parent = GetDesktopWindow();
996 owner = 0;
998 if (cs->hwndParent == HWND_MESSAGE)
1000 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
1001 * message window (style: WS_POPUP|WS_DISABLED)
1003 FIXME("Parent is HWND_MESSAGE\n");
1005 else if (cs->hwndParent)
1007 /* Make sure parent is valid */
1008 if (!IsWindow( cs->hwndParent ))
1010 WARN("Bad parent %p\n", cs->hwndParent );
1011 return 0;
1013 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1014 parent = WIN_GetFullHandle(cs->hwndParent);
1015 else
1016 owner = GetAncestor( cs->hwndParent, GA_ROOT );
1018 else if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1020 WARN("No parent for child window\n" );
1021 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1024 /* Find the window class */
1025 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
1026 &wndExtra, &winproc, &clsStyle, &dce )))
1028 WARN("Bad class '%s'\n", cs->lpszClass );
1029 return 0;
1032 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
1034 /* Correct the window style - stage 1
1036 * These are patches that appear to affect both the style loaded into the
1037 * WIN structure and passed in the CreateStruct to the WM_CREATE etc.
1039 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1040 * why does the user get to set it?
1043 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
1044 * tested for WS_POPUP
1046 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
1047 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
1048 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
1049 cs->dwExStyle |= WS_EX_WINDOWEDGE;
1050 else
1051 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
1053 /* Create the window structure */
1055 if (!(wndPtr = create_window_handle( parent, owner, classAtom, wndExtra )))
1057 TRACE("out of memory\n" );
1058 return 0;
1060 hwnd = wndPtr->hwndSelf;
1062 /* Fill the window structure */
1064 wndPtr->tid = GetCurrentThreadId();
1065 wndPtr->owner = owner;
1066 wndPtr->parent = parent;
1067 wndPtr->class = classPtr;
1068 wndPtr->winproc = winproc;
1069 wndPtr->hInstance = cs->hInstance;
1070 wndPtr->text = NULL;
1071 wndPtr->hrgnUpdate = 0;
1072 wndPtr->hrgnWnd = 0;
1073 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1074 wndPtr->dwExStyle = cs->dwExStyle;
1075 wndPtr->clsStyle = clsStyle;
1076 wndPtr->wIDmenu = 0;
1077 wndPtr->helpContext = 0;
1078 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
1079 wndPtr->pVScroll = NULL;
1080 wndPtr->pHScroll = NULL;
1081 wndPtr->userdata = 0;
1082 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU) ? MENU_GetSysMenu( hwnd, 0 ) : 0;
1083 wndPtr->cbWndExtra = wndExtra;
1085 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
1087 /* Correct the window style - stage 2 */
1089 if (!(cs->style & WS_CHILD))
1091 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1092 if (!(cs->style & WS_POPUP))
1094 wndPtr->dwStyle |= WS_CAPTION;
1095 wndPtr->flags |= WIN_NEED_SIZE;
1098 SERVER_START_REQ( set_window_info )
1100 req->handle = hwnd;
1101 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE;
1102 req->style = wndPtr->dwStyle;
1103 req->ex_style = wndPtr->dwExStyle;
1104 req->instance = (void *)wndPtr->hInstance;
1105 req->extra_offset = -1;
1106 wine_server_call( req );
1108 SERVER_END_REQ;
1110 /* Get class or window DC if needed */
1112 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
1113 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
1114 else wndPtr->dce = NULL;
1116 /* Set the window menu */
1118 if (((wndPtr->dwStyle & (WS_CAPTION|WS_CHILD)) == WS_CAPTION) ||
1119 (wndPtr->dwExStyle & WS_EX_APPWINDOW))
1121 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
1122 else
1124 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
1125 if (menuName)
1127 if (HIWORD(cs->hInstance))
1128 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1129 else
1130 cs->hMenu = HMENU_32(LoadMenu16(HINSTANCE_16(cs->hInstance),menuName));
1132 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
1136 else SetWindowLongW( hwnd, GWL_ID, (UINT)cs->hMenu );
1137 WIN_ReleaseWndPtr( wndPtr );
1139 if (!USER_Driver.pCreateWindow( hwnd, cs, unicode))
1141 WIN_DestroyWindow( hwnd );
1142 return 0;
1145 /* Notify the parent window only */
1147 send_parent_notify( hwnd, WM_CREATE );
1148 if (!IsWindow( hwnd )) return 0;
1150 if (cs->style & WS_VISIBLE)
1152 /* in case WS_VISIBLE got set in the meantime */
1153 if (!(wndPtr = WIN_GetPtr( hwnd ))) return 0;
1154 WIN_SetStyle( hwnd, wndPtr->dwStyle & ~WS_VISIBLE );
1155 WIN_ReleasePtr( wndPtr );
1156 ShowWindow( hwnd, sw );
1159 /* Call WH_SHELL hook */
1161 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1162 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1164 TRACE("created window %p\n", hwnd);
1165 return hwnd;
1169 /***********************************************************************
1170 * CreateWindow (USER.41)
1172 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1173 DWORD style, INT16 x, INT16 y, INT16 width,
1174 INT16 height, HWND16 parent, HMENU16 menu,
1175 HINSTANCE16 instance, LPVOID data )
1177 return CreateWindowEx16( 0, className, windowName, style,
1178 x, y, width, height, parent, menu, instance, data );
1182 /***********************************************************************
1183 * CreateWindowEx (USER.452)
1185 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1186 LPCSTR windowName, DWORD style, INT16 x,
1187 INT16 y, INT16 width, INT16 height,
1188 HWND16 parent, HMENU16 menu,
1189 HINSTANCE16 instance, LPVOID data )
1191 ATOM classAtom;
1192 CREATESTRUCTA cs;
1193 char buffer[256];
1195 /* Find the class atom */
1197 if (HIWORD(className))
1199 if (!(classAtom = GlobalFindAtomA( className )))
1201 ERR( "bad class name %s\n", debugstr_a(className) );
1202 return 0;
1205 else
1207 classAtom = LOWORD(className);
1208 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1210 ERR( "bad atom %x\n", classAtom);
1211 return 0;
1213 className = buffer;
1216 /* Fix the coordinates */
1218 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1219 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1220 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1221 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1223 /* Create the window */
1225 cs.lpCreateParams = data;
1226 cs.hInstance = HINSTANCE_32(instance);
1227 cs.hMenu = HMENU_32(menu);
1228 cs.hwndParent = WIN_Handle32( parent );
1229 cs.style = style;
1230 cs.lpszName = windowName;
1231 cs.lpszClass = className;
1232 cs.dwExStyle = exStyle;
1234 return HWND_16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
1238 /***********************************************************************
1239 * CreateWindowExA (USER32.@)
1241 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1242 LPCSTR windowName, DWORD style, INT x,
1243 INT y, INT width, INT height,
1244 HWND parent, HMENU menu,
1245 HINSTANCE instance, LPVOID data )
1247 ATOM classAtom;
1248 CREATESTRUCTA cs;
1249 char buffer[256];
1251 if(!instance)
1252 instance=GetModuleHandleA(NULL);
1254 if(exStyle & WS_EX_MDICHILD)
1255 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1257 /* Find the class atom */
1259 if (HIWORD(className))
1261 if (!(classAtom = GlobalFindAtomA( className )))
1263 ERR( "bad class name %s\n", debugstr_a(className) );
1264 return 0;
1267 else
1269 classAtom = LOWORD(className);
1270 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1272 ERR( "bad atom %x\n", classAtom);
1273 return 0;
1275 className = buffer;
1278 /* Create the window */
1280 cs.lpCreateParams = data;
1281 cs.hInstance = instance;
1282 cs.hMenu = menu;
1283 cs.hwndParent = parent;
1284 cs.x = x;
1285 cs.y = y;
1286 cs.cx = width;
1287 cs.cy = height;
1288 cs.style = style;
1289 cs.lpszName = windowName;
1290 cs.lpszClass = className;
1291 cs.dwExStyle = exStyle;
1293 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1297 /***********************************************************************
1298 * CreateWindowExW (USER32.@)
1300 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1301 LPCWSTR windowName, DWORD style, INT x,
1302 INT y, INT width, INT height,
1303 HWND parent, HMENU menu,
1304 HINSTANCE instance, LPVOID data )
1306 ATOM classAtom;
1307 CREATESTRUCTW cs;
1308 WCHAR buffer[256];
1310 if(!instance)
1311 instance=GetModuleHandleW(NULL);
1313 if(exStyle & WS_EX_MDICHILD)
1314 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1316 /* Find the class atom */
1318 if (HIWORD(className))
1320 if (!(classAtom = GlobalFindAtomW( className )))
1322 ERR( "bad class name %s\n", debugstr_w(className) );
1323 return 0;
1326 else
1328 classAtom = LOWORD(className);
1329 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1331 ERR( "bad atom %x\n", classAtom);
1332 return 0;
1334 className = buffer;
1337 /* Create the window */
1339 cs.lpCreateParams = data;
1340 cs.hInstance = instance;
1341 cs.hMenu = menu;
1342 cs.hwndParent = parent;
1343 cs.x = x;
1344 cs.y = y;
1345 cs.cx = width;
1346 cs.cy = height;
1347 cs.style = style;
1348 cs.lpszName = windowName;
1349 cs.lpszClass = className;
1350 cs.dwExStyle = exStyle;
1352 /* Note: we rely on the fact that CREATESTRUCTA and */
1353 /* CREATESTRUCTW have the same layout. */
1354 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1358 /***********************************************************************
1359 * WIN_SendDestroyMsg
1361 static void WIN_SendDestroyMsg( HWND hwnd )
1363 GUITHREADINFO info;
1365 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1367 if (hwnd == info.hwndCaret) DestroyCaret();
1369 if (USER_Driver.pResetSelectionOwner)
1370 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1373 * Send the WM_DESTROY to the window.
1375 SendMessageA( hwnd, WM_DESTROY, 0, 0);
1378 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1379 * make sure that the window still exists when we come back.
1381 if (IsWindow(hwnd))
1383 HWND* pWndArray;
1384 int i;
1386 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1388 /* start from the end (FIXME: is this needed?) */
1389 for (i = 0; pWndArray[i]; i++) ;
1391 while (--i >= 0)
1393 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1395 HeapFree( GetProcessHeap(), 0, pWndArray );
1397 else
1398 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1402 /***********************************************************************
1403 * DestroyWindow (USER32.@)
1405 BOOL WINAPI DestroyWindow( HWND hwnd )
1407 BOOL is_child;
1408 HWND h;
1410 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1412 SetLastError( ERROR_ACCESS_DENIED );
1413 return FALSE;
1416 TRACE("(%p)\n", hwnd);
1418 /* Look whether the focus is within the tree of windows we will
1419 * be destroying.
1421 h = GetFocus();
1422 if (h == hwnd || IsChild( hwnd, h ))
1424 HWND parent = GetAncestor( hwnd, GA_PARENT );
1425 if (parent == GetDesktopWindow()) parent = 0;
1426 SetFocus( parent );
1429 /* Call hooks */
1431 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1433 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1435 if (is_child)
1437 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1438 send_parent_notify( hwnd, WM_DESTROY );
1440 else if (!GetWindow( hwnd, GW_OWNER ))
1442 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1443 /* FIXME: clean up palette - see "Internals" p.352 */
1446 if (!IsWindow(hwnd)) return TRUE;
1448 if (USER_Driver.pResetSelectionOwner)
1449 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1451 /* Hide the window */
1453 if (!ShowWindow( hwnd, SW_HIDE ))
1455 if (hwnd == GetActiveWindow()) WINPOS_ActivateOtherWindow( hwnd );
1457 if (!IsWindow(hwnd)) return TRUE;
1459 /* Recursively destroy owned windows */
1461 if (!is_child)
1463 for (;;)
1465 int i, got_one = 0;
1466 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1467 if (list)
1469 for (i = 0; list[i]; i++)
1471 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1472 if (WIN_IsCurrentThread( list[i] ))
1474 DestroyWindow( list[i] );
1475 got_one = 1;
1476 continue;
1478 WIN_SetOwner( list[i], 0 );
1480 HeapFree( GetProcessHeap(), 0, list );
1482 if (!got_one) break;
1486 /* Send destroy messages */
1488 WIN_SendDestroyMsg( hwnd );
1489 if (!IsWindow( hwnd )) return TRUE;
1491 if (GetClipboardOwner() == hwnd)
1492 CLIPBOARD_ReleaseOwner();
1494 /* Unlink now so we won't bother with the children later on */
1496 WIN_UnlinkWindow( hwnd );
1498 /* Destroy the window storage */
1500 WIN_DestroyWindow( hwnd );
1501 return TRUE;
1505 /***********************************************************************
1506 * CloseWindow (USER32.@)
1508 BOOL WINAPI CloseWindow( HWND hwnd )
1510 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1511 ShowWindow( hwnd, SW_MINIMIZE );
1512 return TRUE;
1516 /***********************************************************************
1517 * OpenIcon (USER32.@)
1519 BOOL WINAPI OpenIcon( HWND hwnd )
1521 if (!IsIconic( hwnd )) return FALSE;
1522 ShowWindow( hwnd, SW_SHOWNORMAL );
1523 return TRUE;
1527 /***********************************************************************
1528 * WIN_FindWindow
1530 * Implementation of FindWindow() and FindWindowEx().
1532 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1534 HWND *list = NULL;
1535 HWND retvalue = 0;
1536 int i = 0, len = 0;
1537 WCHAR *buffer = NULL;
1539 if (!parent) parent = GetDesktopWindow();
1540 if (title)
1542 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1543 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1546 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1548 if (child)
1550 child = WIN_GetFullHandle( child );
1551 while (list[i] && list[i] != child) i++;
1552 if (!list[i]) goto done;
1553 i++; /* start from next window */
1556 if (title)
1558 while (list[i])
1560 if (GetWindowTextW( list[i], buffer, len ) && !strcmpiW( buffer, title )) break;
1561 i++;
1564 retvalue = list[i];
1566 done:
1567 if (list) HeapFree( GetProcessHeap(), 0, list );
1568 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1569 return retvalue;
1574 /***********************************************************************
1575 * FindWindowA (USER32.@)
1577 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1579 HWND ret = FindWindowExA( 0, 0, className, title );
1580 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1581 return ret;
1585 /***********************************************************************
1586 * FindWindowExA (USER32.@)
1588 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1589 LPCSTR className, LPCSTR title )
1591 ATOM atom = 0;
1592 LPWSTR buffer;
1593 HWND hwnd;
1594 INT len;
1596 if (className)
1598 /* If the atom doesn't exist, then no class */
1599 /* with this name exists either. */
1600 if (!(atom = GlobalFindAtomA( className )))
1602 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1603 return 0;
1606 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
1608 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1609 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1610 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
1611 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1612 HeapFree( GetProcessHeap(), 0, buffer );
1613 return hwnd;
1617 /***********************************************************************
1618 * FindWindowExW (USER32.@)
1620 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1621 LPCWSTR className, LPCWSTR title )
1623 ATOM atom = 0;
1625 if (className)
1627 /* If the atom doesn't exist, then no class */
1628 /* with this name exists either. */
1629 if (!(atom = GlobalFindAtomW( className )))
1631 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1632 return 0;
1635 return WIN_FindWindow( parent, child, atom, title );
1639 /***********************************************************************
1640 * FindWindowW (USER32.@)
1642 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1644 return FindWindowExW( 0, 0, className, title );
1648 /**********************************************************************
1649 * GetDesktopWindow (USER32.@)
1651 HWND WINAPI GetDesktopWindow(void)
1653 if (pWndDesktop) return pWndDesktop->hwndSelf;
1654 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" );
1655 ExitProcess(1);
1656 return 0;
1660 /*******************************************************************
1661 * EnableWindow (USER32.@)
1663 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1665 WND *wndPtr;
1666 BOOL retvalue;
1667 LONG style;
1668 HWND full_handle;
1670 if (is_broadcast(hwnd))
1672 SetLastError( ERROR_INVALID_PARAMETER );
1673 return FALSE;
1676 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1677 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1679 hwnd = full_handle;
1681 TRACE("( %p, %d )\n", hwnd, enable);
1683 if (!(wndPtr = WIN_GetPtr( hwnd ))) return FALSE;
1684 style = wndPtr->dwStyle;
1685 retvalue = ((style & WS_DISABLED) != 0);
1686 WIN_ReleasePtr( wndPtr );
1688 if (enable && retvalue)
1690 WIN_SetStyle( hwnd, style & ~WS_DISABLED );
1691 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1693 else if (!enable && !retvalue)
1695 HWND focus_wnd, capture_wnd;
1697 SendMessageA( hwnd, WM_CANCELMODE, 0, 0);
1699 WIN_SetStyle( hwnd, style | WS_DISABLED );
1701 focus_wnd = GetFocus();
1702 if (hwnd == focus_wnd || IsChild(hwnd, focus_wnd))
1703 SetFocus( 0 ); /* A disabled window can't have the focus */
1705 capture_wnd = GetCapture();
1706 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1707 ReleaseCapture(); /* A disabled window can't capture the mouse */
1709 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1711 return retvalue;
1715 /***********************************************************************
1716 * IsWindowEnabled (USER32.@)
1718 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1720 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1724 /***********************************************************************
1725 * IsWindowUnicode (USER32.@)
1727 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1729 WND * wndPtr;
1730 BOOL retvalue;
1732 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1733 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1734 WIN_ReleaseWndPtr(wndPtr);
1735 return retvalue;
1739 /**********************************************************************
1740 * GetWindowWord (USER32.@)
1742 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1744 if (offset >= 0)
1746 WORD retvalue = 0;
1747 WND *wndPtr = WIN_GetPtr( hwnd );
1748 if (!wndPtr)
1750 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1751 return 0;
1753 if (wndPtr == WND_OTHER_PROCESS)
1755 if (IsWindow( hwnd ))
1756 FIXME( "(%d) not supported yet on other process window %p\n", offset, hwnd );
1757 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1758 return 0;
1760 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1762 WARN("Invalid offset %d\n", offset );
1763 SetLastError( ERROR_INVALID_INDEX );
1765 else retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1766 WIN_ReleasePtr( wndPtr );
1767 return retvalue;
1770 switch(offset)
1772 case GWL_HWNDPARENT:
1773 return GetWindowLongW( hwnd, offset );
1774 case GWL_ID:
1775 case GWL_HINSTANCE:
1777 LONG ret = GetWindowLongW( hwnd, offset );
1778 if (HIWORD(ret))
1779 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1780 return LOWORD(ret);
1782 default:
1783 WARN("Invalid offset %d\n", offset );
1784 return 0;
1789 /**********************************************************************
1790 * SetWindowWord (USER32.@)
1792 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1794 WORD retval = 0;
1795 WND * wndPtr;
1797 switch(offset)
1799 case GWL_ID:
1800 case GWL_HINSTANCE:
1801 case GWL_HWNDPARENT:
1802 return SetWindowLongW( hwnd, offset, (UINT)newval );
1803 default:
1804 if (offset < 0)
1806 WARN("Invalid offset %d\n", offset );
1807 SetLastError( ERROR_INVALID_INDEX );
1808 return 0;
1812 wndPtr = WIN_GetPtr( hwnd );
1813 if (wndPtr == WND_OTHER_PROCESS)
1815 if (IsWindow(hwnd))
1816 FIXME( "set %d <- %x not supported yet on other process window %p\n",
1817 offset, newval, hwnd );
1818 wndPtr = NULL;
1820 if (!wndPtr)
1822 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1823 return 0;
1826 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1828 WARN("Invalid offset %d\n", offset );
1829 WIN_ReleasePtr(wndPtr);
1830 SetLastError( ERROR_INVALID_INDEX );
1831 return 0;
1834 SERVER_START_REQ( set_window_info )
1836 req->handle = hwnd;
1837 req->flags = SET_WIN_EXTRAWORD;
1838 req->extra_offset = offset;
1839 req->extra_value = newval;
1840 if (!wine_server_call_err( req ))
1842 WORD *ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1843 retval = *ptr;
1844 *ptr = newval;
1847 SERVER_END_REQ;
1848 WIN_ReleasePtr( wndPtr );
1849 return retval;
1853 /**********************************************************************
1854 * WIN_GetWindowLong
1856 * Helper function for GetWindowLong().
1858 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1860 LONG retvalue = 0;
1861 WND *wndPtr;
1863 if (offset == GWL_HWNDPARENT)
1865 HWND parent = GetAncestor( hwnd, GA_PARENT );
1866 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1867 return (LONG)parent;
1870 if (!(wndPtr = WIN_GetPtr( hwnd )))
1872 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1873 return 0;
1876 if (wndPtr == WND_OTHER_PROCESS)
1878 if (offset == GWL_WNDPROC)
1880 SetLastError( ERROR_ACCESS_DENIED );
1881 return 0;
1883 SERVER_START_REQ( set_window_info )
1885 req->handle = hwnd;
1886 req->flags = 0; /* don't set anything, just retrieve */
1887 req->extra_offset = (offset >= 0) ? offset : -1;
1888 if (!wine_server_call_err( req ))
1890 switch(offset)
1892 case GWL_STYLE: retvalue = reply->old_style; break;
1893 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1894 case GWL_ID: retvalue = reply->old_id; break;
1895 case GWL_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1896 case GWL_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
1897 default:
1898 if (offset >= 0) retvalue = reply->old_extra_value;
1899 else SetLastError( ERROR_INVALID_INDEX );
1900 break;
1903 else if (offset >= 0 && GetLastError() == ERROR_INVALID_PARAMETER)
1904 SetLastError( ERROR_INVALID_INDEX );
1906 SERVER_END_REQ;
1907 return retvalue;
1910 /* now we have a valid wndPtr */
1912 if (offset >= 0)
1914 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
1917 * Some programs try to access last element from 16 bit
1918 * code using illegal offset value. Hopefully this is
1919 * what those programs really expect.
1921 if (type == WIN_PROC_16 &&
1922 wndPtr->cbWndExtra >= 4 &&
1923 offset == wndPtr->cbWndExtra - sizeof(WORD))
1925 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
1927 ERR( "- replaced invalid offset %d with %d\n",
1928 offset, offset2 );
1930 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset2);
1931 WIN_ReleasePtr( wndPtr );
1932 return retvalue;
1934 WARN("Invalid offset %d\n", offset );
1935 WIN_ReleasePtr( wndPtr );
1936 SetLastError( ERROR_INVALID_INDEX );
1937 return 0;
1939 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1940 /* Special case for dialog window procedure */
1941 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1942 retvalue = (LONG)WINPROC_GetProc( (WNDPROC)retvalue, type );
1943 WIN_ReleasePtr( wndPtr );
1944 return retvalue;
1947 switch(offset)
1949 case GWL_USERDATA: retvalue = wndPtr->userdata; break;
1950 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1951 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1952 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu; break;
1953 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc, type ); break;
1954 case GWL_HINSTANCE: retvalue = (LONG)wndPtr->hInstance; break;
1955 default:
1956 WARN("Unknown offset %d\n", offset );
1957 SetLastError( ERROR_INVALID_INDEX );
1958 break;
1960 WIN_ReleasePtr(wndPtr);
1961 return retvalue;
1965 /**********************************************************************
1966 * WIN_SetWindowLong
1968 * Helper function for SetWindowLong().
1970 * 0 is the failure code. However, in the case of failure SetLastError
1971 * must be set to distinguish between a 0 return value and a failure.
1973 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1974 WINDOWPROCTYPE type )
1976 STYLESTRUCT style;
1977 BOOL ok;
1978 LONG retval = 0;
1979 WND *wndPtr;
1981 TRACE( "%p %d %lx %x\n", hwnd, offset, newval, type );
1983 if (is_broadcast(hwnd))
1985 SetLastError( ERROR_INVALID_PARAMETER );
1986 return FALSE;
1988 if (!WIN_IsCurrentProcess( hwnd ))
1990 if (offset == GWL_WNDPROC)
1992 SetLastError( ERROR_ACCESS_DENIED );
1993 return 0;
1995 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
1998 wndPtr = WIN_GetPtr( hwnd );
1999 if (wndPtr->hwndSelf == GetDesktopWindow())
2001 /* can't change anything on the desktop window */
2002 WIN_ReleasePtr( wndPtr );
2003 SetLastError( ERROR_ACCESS_DENIED );
2004 return 0;
2007 /* first some special cases */
2008 switch( offset )
2010 case GWL_STYLE:
2011 case GWL_EXSTYLE:
2012 style.styleOld =
2013 offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
2014 style.styleNew = newval;
2015 WIN_ReleasePtr( wndPtr );
2016 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
2017 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
2018 newval = style.styleNew;
2019 break;
2020 case GWL_HWNDPARENT:
2021 if (wndPtr->parent == GetDesktopWindow())
2023 WIN_ReleasePtr( wndPtr );
2024 return (LONG)WIN_SetOwner( hwnd, (HWND)newval );
2026 else
2028 WIN_ReleasePtr( wndPtr );
2029 return (LONG)SetParent( hwnd, (HWND)newval );
2031 case GWL_WNDPROC:
2032 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2033 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC)newval, type, WIN_PROC_WINDOW );
2034 WIN_ReleasePtr( wndPtr );
2035 return retval;
2036 case GWL_ID:
2037 case GWL_HINSTANCE:
2038 case GWL_USERDATA:
2039 break;
2040 case DWL_DLGPROC:
2041 if ((wndPtr->cbWndExtra + sizeof(LONG) >= DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2043 WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWL_DLGPROC);
2044 retval = (LONG)WINPROC_GetProc( *ptr, type );
2045 WINPROC_SetProc( ptr, (WNDPROC)newval, type, WIN_PROC_WINDOW );
2046 WIN_ReleasePtr( wndPtr );
2047 return retval;
2049 /* fall through */
2050 default:
2051 if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
2053 WARN("Invalid offset %d\n", offset );
2054 WIN_ReleasePtr( wndPtr );
2055 SetLastError( ERROR_INVALID_INDEX );
2056 return 0;
2058 else
2060 LONG *ptr = (LONG *)((char *)wndPtr->wExtra + offset);
2061 if (*ptr == newval) /* already set to the same value */
2063 WIN_ReleasePtr( wndPtr );
2064 return newval;
2067 break;
2070 SERVER_START_REQ( set_window_info )
2072 req->handle = hwnd;
2073 req->extra_offset = -1;
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;
2096 default:
2097 req->flags = SET_WIN_EXTRALONG;
2098 req->extra_offset = offset;
2099 req->extra_value = newval;
2101 if ((ok = !wine_server_call_err( req )))
2103 switch(offset)
2105 case GWL_STYLE:
2106 wndPtr->dwStyle = newval;
2107 retval = reply->old_style;
2108 break;
2109 case GWL_EXSTYLE:
2110 wndPtr->dwExStyle = newval;
2111 retval = reply->old_ex_style;
2112 break;
2113 case GWL_ID:
2114 wndPtr->wIDmenu = newval;
2115 retval = reply->old_id;
2116 break;
2117 case GWL_HINSTANCE:
2118 wndPtr->hInstance = (HINSTANCE)newval;
2119 retval = (ULONG_PTR)reply->old_instance;
2120 break;
2121 case GWL_USERDATA:
2122 wndPtr->userdata = newval;
2123 retval = (ULONG_PTR)reply->old_user_data;
2124 break;
2125 default:
2127 LONG *ptr = (LONG *)((char *)wndPtr->wExtra + offset);
2128 retval = *ptr;
2129 *ptr = newval;
2131 break;
2135 SERVER_END_REQ;
2136 WIN_ReleasePtr( wndPtr );
2138 if (!ok) return 0;
2140 if (offset == GWL_STYLE && USER_Driver.pSetWindowStyle)
2141 USER_Driver.pSetWindowStyle( hwnd, retval );
2143 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2144 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2146 return retval;
2150 /**********************************************************************
2151 * GetWindowLong (USER.135)
2153 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2155 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
2159 /**********************************************************************
2160 * GetWindowLongA (USER32.@)
2162 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2164 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2168 /**********************************************************************
2169 * GetWindowLongW (USER32.@)
2171 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2173 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2177 /**********************************************************************
2178 * SetWindowLong (USER.136)
2180 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2182 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
2186 /**********************************************************************
2187 * SetWindowLongA (USER32.@)
2189 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2191 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2195 /**********************************************************************
2196 * SetWindowLongW (USER32.@) Set window attribute
2198 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2199 * value in a window's extra memory.
2201 * The _hwnd_ parameter specifies the window. is the handle to a
2202 * window that has extra memory. The _newval_ parameter contains the
2203 * new attribute or extra memory value. If positive, the _offset_
2204 * parameter is the byte-addressed location in the window's extra
2205 * memory to set. If negative, _offset_ specifies the window
2206 * attribute to set, and should be one of the following values:
2208 * GWL_EXSTYLE The window's extended window style
2210 * GWL_STYLE The window's window style.
2212 * GWL_WNDPROC Pointer to the window's window procedure.
2214 * GWL_HINSTANCE The window's pplication instance handle.
2216 * GWL_ID The window's identifier.
2218 * GWL_USERDATA The window's user-specified data.
2220 * If the window is a dialog box, the _offset_ parameter can be one of
2221 * the following values:
2223 * DWL_DLGPROC The address of the window's dialog box procedure.
2225 * DWL_MSGRESULT The return value of a message
2226 * that the dialog box procedure processed.
2228 * DWL_USER Application specific information.
2230 * RETURNS
2232 * If successful, returns the previous value located at _offset_. Otherwise,
2233 * returns 0.
2235 * NOTES
2237 * Extra memory for a window class is specified by a nonzero cbWndExtra
2238 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2239 * time of class creation.
2241 * Using GWL_WNDPROC to set a new window procedure effectively creates
2242 * a window subclass. Use CallWindowProc() in the new windows procedure
2243 * to pass messages to the superclass's window procedure.
2245 * The user data is reserved for use by the application which created
2246 * the window.
2248 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2249 * instead, call the EnableWindow() function to change the window's
2250 * disabled state.
2252 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2253 * SetParent() instead.
2255 * Win95:
2256 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2257 * it sends WM_STYLECHANGING before changing the settings
2258 * and WM_STYLECHANGED afterwards.
2259 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2261 LONG WINAPI SetWindowLongW(
2262 HWND hwnd, /* [in] window to alter */
2263 INT offset, /* [in] offset, in bytes, of location to alter */
2264 LONG newval /* [in] new value of location */
2266 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2270 /*******************************************************************
2271 * GetWindowTextA (USER32.@)
2273 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2275 WCHAR *buffer;
2277 if (WIN_IsCurrentProcess( hwnd ))
2278 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2280 /* when window belongs to other process, don't send a message */
2281 if (nMaxCount <= 0) return 0;
2282 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2283 get_server_window_text( hwnd, buffer, nMaxCount );
2284 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2285 lpString[nMaxCount-1] = 0;
2286 HeapFree( GetProcessHeap(), 0, buffer );
2287 return strlen(lpString);
2291 /*******************************************************************
2292 * InternalGetWindowText (USER32.@)
2294 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2296 WND *win;
2298 if (nMaxCount <= 0) return 0;
2299 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2300 if (win != WND_OTHER_PROCESS)
2302 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2303 else lpString[0] = 0;
2304 WIN_ReleasePtr( win );
2306 else
2308 get_server_window_text( hwnd, lpString, nMaxCount );
2310 return strlenW(lpString);
2314 /*******************************************************************
2315 * GetWindowTextW (USER32.@)
2317 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2319 if (WIN_IsCurrentProcess( hwnd ))
2320 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2322 /* when window belongs to other process, don't send a message */
2323 if (nMaxCount <= 0) return 0;
2324 get_server_window_text( hwnd, lpString, nMaxCount );
2325 return strlenW(lpString);
2329 /*******************************************************************
2330 * SetWindowText (USER32.@)
2331 * SetWindowTextA (USER32.@)
2333 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2335 if (is_broadcast(hwnd))
2337 SetLastError( ERROR_INVALID_PARAMETER );
2338 return FALSE;
2340 if (!WIN_IsCurrentProcess( hwnd ))
2342 FIXME( "cannot set text %s of other process window %p\n", debugstr_a(lpString), hwnd );
2343 SetLastError( ERROR_ACCESS_DENIED );
2344 return FALSE;
2346 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2350 /*******************************************************************
2351 * SetWindowTextW (USER32.@)
2353 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2355 if (is_broadcast(hwnd))
2357 SetLastError( ERROR_INVALID_PARAMETER );
2358 return FALSE;
2360 if (!WIN_IsCurrentProcess( hwnd ))
2362 FIXME( "cannot set text %s of other process window %p\n", debugstr_w(lpString), hwnd );
2363 SetLastError( ERROR_ACCESS_DENIED );
2364 return FALSE;
2366 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2370 /*******************************************************************
2371 * GetWindowTextLengthA (USER32.@)
2373 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2375 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2378 /*******************************************************************
2379 * GetWindowTextLengthW (USER32.@)
2381 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2383 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2387 /*******************************************************************
2388 * IsWindow (USER32.@)
2390 BOOL WINAPI IsWindow( HWND hwnd )
2392 WND *ptr;
2393 BOOL ret;
2395 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2397 if (ptr != WND_OTHER_PROCESS)
2399 WIN_ReleasePtr( ptr );
2400 return TRUE;
2403 /* check other processes */
2404 SERVER_START_REQ( get_window_info )
2406 req->handle = hwnd;
2407 ret = !wine_server_call_err( req );
2409 SERVER_END_REQ;
2410 return ret;
2414 /***********************************************************************
2415 * GetWindowThreadProcessId (USER32.@)
2417 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2419 WND *ptr;
2420 DWORD tid = 0;
2422 if (!(ptr = WIN_GetPtr( hwnd )))
2424 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2425 return 0;
2428 if (ptr != WND_OTHER_PROCESS)
2430 /* got a valid window */
2431 tid = ptr->tid;
2432 if (process) *process = GetCurrentProcessId();
2433 WIN_ReleasePtr( ptr );
2434 return tid;
2437 /* check other processes */
2438 SERVER_START_REQ( get_window_info )
2440 req->handle = hwnd;
2441 if (!wine_server_call_err( req ))
2443 tid = (DWORD)reply->tid;
2444 if (process) *process = (DWORD)reply->pid;
2447 SERVER_END_REQ;
2448 return tid;
2452 /*****************************************************************
2453 * GetParent (USER32.@)
2455 HWND WINAPI GetParent( HWND hwnd )
2457 WND *wndPtr;
2458 HWND retvalue = 0;
2460 if (!(wndPtr = WIN_GetPtr( hwnd )))
2462 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2463 return 0;
2465 if (wndPtr == WND_OTHER_PROCESS)
2467 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2468 if (style & (WS_POPUP | WS_CHILD))
2470 SERVER_START_REQ( get_window_tree )
2472 req->handle = hwnd;
2473 if (!wine_server_call_err( req ))
2475 if (style & WS_POPUP) retvalue = reply->owner;
2476 else if (style & WS_CHILD) retvalue = reply->parent;
2479 SERVER_END_REQ;
2482 else
2484 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2485 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2486 WIN_ReleasePtr( wndPtr );
2488 return retvalue;
2492 /*****************************************************************
2493 * GetAncestor (USER32.@)
2495 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2497 WND *win;
2498 HWND *list, ret = 0;
2500 switch(type)
2502 case GA_PARENT:
2503 if (!(win = WIN_GetPtr( hwnd )))
2505 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2506 return 0;
2508 if (win != WND_OTHER_PROCESS)
2510 ret = win->parent;
2511 WIN_ReleasePtr( win );
2513 else /* need to query the server */
2515 SERVER_START_REQ( get_window_tree )
2517 req->handle = hwnd;
2518 if (!wine_server_call_err( req )) ret = reply->parent;
2520 SERVER_END_REQ;
2522 break;
2524 case GA_ROOT:
2525 if (!(list = WIN_ListParents( hwnd ))) return 0;
2527 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2528 else
2530 int count = 2;
2531 while (list[count]) count++;
2532 ret = list[count - 2]; /* get the one before the desktop */
2534 HeapFree( GetProcessHeap(), 0, list );
2535 break;
2537 case GA_ROOTOWNER:
2538 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2539 for (;;)
2541 HWND parent = GetParent( ret );
2542 if (!parent) break;
2543 ret = parent;
2545 break;
2547 return ret;
2551 /*****************************************************************
2552 * SetParent (USER32.@)
2554 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2556 WND *wndPtr;
2557 HWND retvalue, full_handle;
2558 BOOL was_visible;
2560 if (is_broadcast(hwnd) || is_broadcast(parent))
2562 SetLastError(ERROR_INVALID_PARAMETER);
2563 return 0;
2566 if (!parent) parent = GetDesktopWindow();
2567 else parent = WIN_GetFullHandle( parent );
2569 if (!IsWindow( parent ))
2571 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2572 return 0;
2575 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2576 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2578 hwnd = full_handle;
2580 if (USER_Driver.pSetParent)
2581 return USER_Driver.pSetParent( hwnd, parent );
2583 /* Windows hides the window first, then shows it again
2584 * including the WM_SHOWWINDOW messages and all */
2585 was_visible = ShowWindow( hwnd, SW_HIDE );
2587 if (!IsWindow( parent )) return 0;
2588 if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return 0;
2590 retvalue = wndPtr->parent; /* old parent */
2591 if (parent != retvalue)
2593 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2595 if (parent != GetDesktopWindow()) /* a child window */
2597 if (!(wndPtr->dwStyle & WS_CHILD))
2599 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
2600 if (menu) DestroyMenu( menu );
2604 WIN_ReleasePtr( wndPtr );
2606 /* SetParent additionally needs to make hwnd the topmost window
2607 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2608 WM_WINDOWPOSCHANGED notification messages.
2610 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2611 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2612 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2613 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2614 return retvalue;
2618 /*******************************************************************
2619 * IsChild (USER32.@)
2621 BOOL WINAPI IsChild( HWND parent, HWND child )
2623 HWND *list = WIN_ListParents( child );
2624 int i;
2625 BOOL ret;
2627 if (!list) return FALSE;
2628 parent = WIN_GetFullHandle( parent );
2629 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2630 ret = (list[i] != 0);
2631 HeapFree( GetProcessHeap(), 0, list );
2632 return ret;
2636 /***********************************************************************
2637 * IsWindowVisible (USER32.@)
2639 BOOL WINAPI IsWindowVisible( HWND hwnd )
2641 HWND *list;
2642 BOOL retval;
2643 int i;
2645 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) 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)) break;
2649 retval = !list[i];
2650 HeapFree( GetProcessHeap(), 0, list );
2651 return retval;
2655 /***********************************************************************
2656 * WIN_IsWindowDrawable
2658 * hwnd is drawable when it is visible, all parents are not
2659 * minimized, and it is itself not minimized unless we are
2660 * trying to draw its default class icon.
2662 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2664 HWND *list;
2665 BOOL retval;
2666 int i;
2667 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2669 if (!(style & WS_VISIBLE)) return FALSE;
2670 if ((style & WS_MINIMIZE) && icon && GetClassLongA( hwnd, GCL_HICON )) return FALSE;
2672 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2673 for (i = 0; list[i]; i++)
2674 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2675 break;
2676 retval = !list[i];
2677 HeapFree( GetProcessHeap(), 0, list );
2678 return retval;
2682 /*******************************************************************
2683 * GetTopWindow (USER32.@)
2685 HWND WINAPI GetTopWindow( HWND hwnd )
2687 if (!hwnd) hwnd = GetDesktopWindow();
2688 return GetWindow( hwnd, GW_CHILD );
2692 /*******************************************************************
2693 * GetWindow (USER32.@)
2695 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2697 HWND retval = 0;
2699 if (rel == GW_OWNER) /* this one may be available locally */
2701 WND *wndPtr = WIN_GetPtr( hwnd );
2702 if (!wndPtr)
2704 SetLastError( ERROR_INVALID_HANDLE );
2705 return 0;
2707 if (wndPtr != WND_OTHER_PROCESS)
2709 retval = wndPtr->owner;
2710 WIN_ReleasePtr( wndPtr );
2711 return retval;
2713 /* else fall through to server call */
2716 SERVER_START_REQ( get_window_tree )
2718 req->handle = hwnd;
2719 if (!wine_server_call_err( req ))
2721 switch(rel)
2723 case GW_HWNDFIRST:
2724 retval = reply->first_sibling;
2725 break;
2726 case GW_HWNDLAST:
2727 retval = reply->last_sibling;
2728 break;
2729 case GW_HWNDNEXT:
2730 retval = reply->next_sibling;
2731 break;
2732 case GW_HWNDPREV:
2733 retval = reply->prev_sibling;
2734 break;
2735 case GW_OWNER:
2736 retval = reply->owner;
2737 break;
2738 case GW_CHILD:
2739 retval = reply->first_child;
2740 break;
2744 SERVER_END_REQ;
2745 return retval;
2749 /***********************************************************************
2750 * WIN_InternalShowOwnedPopups
2752 * Internal version of ShowOwnedPopups; Wine functions should use this
2753 * to avoid interfering with application calls to ShowOwnedPopups
2754 * and to make sure the application can't prevent showing/hiding.
2756 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2760 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2762 int count = 0;
2763 WND *pWnd;
2764 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2766 if (!win_array) return TRUE;
2769 * Show windows Lowest first, Highest last to preserve Z-Order
2771 while (win_array[count]) count++;
2772 while (--count >= 0)
2774 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2775 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2777 if (pWnd->dwStyle & WS_POPUP)
2779 if (fShow)
2781 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2782 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
2785 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2787 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2788 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2791 else
2793 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2794 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2795 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2798 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2800 ShowWindow(pWnd->hwndSelf,SW_HIDE);
2801 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2802 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
2806 WIN_ReleaseWndPtr( pWnd );
2808 HeapFree( GetProcessHeap(), 0, win_array );
2810 return TRUE;
2813 /*******************************************************************
2814 * ShowOwnedPopups (USER32.@)
2816 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2818 int count = 0;
2819 WND *pWnd;
2820 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2822 if (!win_array) return TRUE;
2824 while (win_array[count]) count++;
2825 while (--count >= 0)
2827 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2828 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2830 if (pWnd->dwStyle & WS_POPUP)
2832 if (fShow)
2834 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2836 /* In Windows, ShowOwnedPopups(TRUE) generates
2837 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2838 * regardless of the state of the owner
2840 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2841 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2844 else
2846 if (IsWindowVisible(pWnd->hwndSelf))
2848 /* In Windows, ShowOwnedPopups(FALSE) generates
2849 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2850 * regardless of the state of the owner
2852 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2853 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2857 WIN_ReleaseWndPtr( pWnd );
2859 HeapFree( GetProcessHeap(), 0, win_array );
2860 return TRUE;
2864 /*******************************************************************
2865 * GetLastActivePopup (USER32.@)
2867 HWND WINAPI GetLastActivePopup( HWND hwnd )
2869 HWND retval = hwnd;
2871 SERVER_START_REQ( get_window_info )
2873 req->handle = hwnd;
2874 if (!wine_server_call_err( req )) retval = reply->last_active;
2876 SERVER_END_REQ;
2877 return retval;
2881 /*******************************************************************
2882 * WIN_ListParents
2884 * Build an array of all parents of a given window, starting with
2885 * the immediate parent. The array must be freed with HeapFree.
2886 * Returns NULL if window is a top-level window.
2888 HWND *WIN_ListParents( HWND hwnd )
2890 WND *win;
2891 HWND current, *list;
2892 int pos = 0, size = 16, count = 0;
2894 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2896 current = hwnd;
2897 for (;;)
2899 if (!(win = WIN_GetPtr( current ))) goto empty;
2900 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
2901 list[pos] = win->parent;
2902 WIN_ReleasePtr( win );
2903 if (!(current = list[pos]))
2905 if (!pos) goto empty;
2906 return list;
2908 if (++pos == size - 1)
2910 /* need to grow the list */
2911 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
2912 if (!new_list) goto empty;
2913 list = new_list;
2914 size += 16;
2918 /* at least one parent belongs to another process, have to query the server */
2920 for (;;)
2922 count = 0;
2923 SERVER_START_REQ( get_window_parents )
2925 req->handle = hwnd;
2926 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
2927 if (!wine_server_call( req )) count = reply->count;
2929 SERVER_END_REQ;
2930 if (!count) goto empty;
2931 if (size > count)
2933 list[count] = 0;
2934 return list;
2936 HeapFree( GetProcessHeap(), 0, list );
2937 size = count + 1;
2938 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2941 empty:
2942 HeapFree( GetProcessHeap(), 0, list );
2943 return NULL;
2947 /*******************************************************************
2948 * WIN_ListChildren
2950 * Build an array of the children of a given window. The array must be
2951 * freed with HeapFree. Returns NULL when no windows are found.
2953 HWND *WIN_ListChildren( HWND hwnd )
2955 return list_window_children( hwnd, 0, 0 );
2959 /*******************************************************************
2960 * EnumWindows (USER32.@)
2962 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2964 HWND *list;
2965 BOOL ret = TRUE;
2966 int i, iWndsLocks;
2968 /* We have to build a list of all windows first, to avoid */
2969 /* unpleasant side-effects, for instance if the callback */
2970 /* function changes the Z-order of the windows. */
2972 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2974 /* Now call the callback function for every window */
2976 iWndsLocks = WIN_SuspendWndsLock();
2977 for (i = 0; list[i]; i++)
2979 /* Make sure that the window still exists */
2980 if (!IsWindow( list[i] )) continue;
2981 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2983 WIN_RestoreWndsLock(iWndsLocks);
2984 HeapFree( GetProcessHeap(), 0, list );
2985 return ret;
2989 /**********************************************************************
2990 * EnumThreadWindows (USER32.@)
2992 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2994 HWND *list;
2995 int i, iWndsLocks;
2997 if (!(list = list_window_children( GetDesktopWindow(), 0, id ))) return TRUE;
2999 /* Now call the callback function for every window */
3001 iWndsLocks = WIN_SuspendWndsLock();
3002 for (i = 0; list[i]; i++)
3003 if (!func( list[i], lParam )) break;
3004 WIN_RestoreWndsLock(iWndsLocks);
3005 HeapFree( GetProcessHeap(), 0, list );
3006 return TRUE;
3010 /**********************************************************************
3011 * WIN_EnumChildWindows
3013 * Helper function for EnumChildWindows().
3015 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
3017 HWND *childList;
3018 BOOL ret = FALSE;
3020 for ( ; *list; list++)
3022 /* Make sure that the window still exists */
3023 if (!IsWindow( *list )) continue;
3024 /* skip owned windows */
3025 if (GetWindow( *list, GW_OWNER )) continue;
3026 /* Build children list first */
3027 childList = WIN_ListChildren( *list );
3029 ret = func( *list, lParam );
3031 if (childList)
3033 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
3034 HeapFree( GetProcessHeap(), 0, childList );
3036 if (!ret) return FALSE;
3038 return TRUE;
3042 /**********************************************************************
3043 * EnumChildWindows (USER32.@)
3045 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
3047 HWND *list;
3048 int iWndsLocks;
3050 if (!(list = WIN_ListChildren( parent ))) return FALSE;
3051 iWndsLocks = WIN_SuspendWndsLock();
3052 WIN_EnumChildWindows( list, func, lParam );
3053 WIN_RestoreWndsLock(iWndsLocks);
3054 HeapFree( GetProcessHeap(), 0, list );
3055 return TRUE;
3059 /*******************************************************************
3060 * AnyPopup (USER.52)
3062 BOOL16 WINAPI AnyPopup16(void)
3064 return AnyPopup();
3068 /*******************************************************************
3069 * AnyPopup (USER32.@)
3071 BOOL WINAPI AnyPopup(void)
3073 int i;
3074 BOOL retvalue;
3075 HWND *list = WIN_ListChildren( GetDesktopWindow() );
3077 if (!list) return FALSE;
3078 for (i = 0; list[i]; i++)
3080 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
3082 retvalue = (list[i] != 0);
3083 HeapFree( GetProcessHeap(), 0, list );
3084 return retvalue;
3088 /*******************************************************************
3089 * FlashWindow (USER32.@)
3091 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3093 WND *wndPtr = WIN_FindWndPtr(hWnd);
3095 TRACE("%p\n", hWnd);
3097 if (!wndPtr) return FALSE;
3098 hWnd = wndPtr->hwndSelf; /* make it a full handle */
3100 if (wndPtr->dwStyle & WS_MINIMIZE)
3102 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3104 HDC hDC = GetDC(hWnd);
3106 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM)hDC, 0 ))
3107 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
3109 ReleaseDC( hWnd, hDC );
3110 wndPtr->flags |= WIN_NCACTIVATED;
3112 else
3114 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3115 wndPtr->flags &= ~WIN_NCACTIVATED;
3117 WIN_ReleaseWndPtr(wndPtr);
3118 return TRUE;
3120 else
3122 WPARAM16 wparam;
3123 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3124 else wparam = (hWnd == GetForegroundWindow());
3126 WIN_ReleaseWndPtr(wndPtr);
3127 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3128 return wparam;
3132 /*******************************************************************
3133 * FlashWindowEx (USER32.@)
3135 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
3137 FIXME("%p\n", pfwi);
3138 return TRUE;
3141 /*******************************************************************
3142 * GetWindowContextHelpId (USER32.@)
3144 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3146 DWORD retval;
3147 WND *wnd = WIN_FindWndPtr( hwnd );
3148 if (!wnd) return 0;
3149 retval = wnd->helpContext;
3150 WIN_ReleaseWndPtr(wnd);
3151 return retval;
3155 /*******************************************************************
3156 * SetWindowContextHelpId (USER32.@)
3158 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3160 WND *wnd = WIN_FindWndPtr( hwnd );
3161 if (!wnd) return FALSE;
3162 wnd->helpContext = id;
3163 WIN_ReleaseWndPtr(wnd);
3164 return TRUE;
3168 /*******************************************************************
3169 * DragDetect (USER32.@)
3171 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3173 MSG msg;
3174 RECT rect;
3176 rect.left = pt.x - wDragWidth;
3177 rect.right = pt.x + wDragWidth;
3179 rect.top = pt.y - wDragHeight;
3180 rect.bottom = pt.y + wDragHeight;
3182 SetCapture(hWnd);
3184 while(1)
3186 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3188 if( msg.message == WM_LBUTTONUP )
3190 ReleaseCapture();
3191 return 0;
3193 if( msg.message == WM_MOUSEMOVE )
3195 POINT tmp;
3196 tmp.x = LOWORD(msg.lParam);
3197 tmp.y = HIWORD(msg.lParam);
3198 if( !PtInRect( &rect, tmp ))
3200 ReleaseCapture();
3201 return 1;
3205 WaitMessage();
3207 return 0;
3210 /******************************************************************************
3211 * GetWindowModuleFileNameA (USER32.@)
3213 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3215 FIXME("GetWindowModuleFileNameA(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3216 hwnd, lpszFileName, cchFileNameMax);
3217 return 0;
3220 /******************************************************************************
3221 * GetWindowModuleFileNameW (USER32.@)
3223 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR lpszFileName, UINT cchFileNameMax)
3225 FIXME("GetWindowModuleFileNameW(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3226 hwnd, lpszFileName, cchFileNameMax);
3227 return 0;
3230 /******************************************************************************
3231 * GetWindowInfo (USER32.@)
3232 * hwnd: in
3233 * pwi: out.
3234 * MS Documentation mentions that pwi->cbSize must be set to SIZEOF(WINDOWINFO)
3235 * this may be because this structure changed over time. If this is the
3236 * the case, then please: FIXME.
3237 * Using the structure described in MSDN for 98/ME/NT(4.0 SP3)/2000/XP.
3239 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3241 if (!pwi) return FALSE;
3242 if (pwi->cbSize != sizeof(WINDOWINFO))
3244 FIXME("windowinfo->cbSize != sizeof(WINDOWINFO). Please report\n");
3245 return FALSE;
3247 if (!IsWindow(hwnd)) return FALSE;
3249 GetWindowRect(hwnd, &pwi->rcWindow);
3250 GetClientRect(hwnd, &pwi->rcClient);
3251 /* translate to screen coordinates */
3252 MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3254 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3255 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3256 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3258 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3259 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3261 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3262 pwi->wCreatorVersion = 0x0400;
3264 return TRUE;