Fix spec for InitiateSystemShutdownExA, as pointed out by Stefan
[wine/hacks.git] / windows / win.c
blob6abf4a9923d10dbc955cbea1c22a4ee2af6ba28b
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 /***********************************************************************
60 * create_window_handle
62 * Create a window handle with the server.
64 static WND *create_window_handle( HWND parent, HWND owner, ATOM atom, INT size )
66 BOOL res;
67 user_handle_t handle = 0;
68 WORD index;
69 WND *win = HeapAlloc( GetProcessHeap(), 0, size );
71 if (!win) return NULL;
73 USER_Lock();
75 SERVER_START_REQ( create_window )
77 req->parent = parent;
78 req->owner = owner;
79 req->atom = atom;
80 if ((res = !wine_server_call_err( req ))) handle = reply->handle;
82 SERVER_END_REQ;
84 if (!res)
86 USER_Unlock();
87 HeapFree( GetProcessHeap(), 0, win );
88 return NULL;
90 index = LOWORD(handle) - FIRST_USER_HANDLE;
91 assert( index < NB_USER_HANDLES );
92 user_handles[index] = win;
93 win->hwndSelf = handle;
94 win->dwMagic = WND_MAGIC;
95 win->irefCount = 1;
96 return win;
100 /***********************************************************************
101 * free_window_handle
103 * Free a window handle.
105 static WND *free_window_handle( HWND hwnd )
107 WND *ptr;
108 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
110 if (index >= NB_USER_HANDLES) return NULL;
111 USER_Lock();
112 if ((ptr = user_handles[index]))
114 SERVER_START_REQ( destroy_window )
116 req->handle = hwnd;
117 if (!wine_server_call_err( req ))
118 user_handles[index] = NULL;
119 else
120 ptr = NULL;
122 SERVER_END_REQ;
124 USER_Unlock();
125 if (ptr) HeapFree( GetProcessHeap(), 0, ptr );
126 return ptr;
130 /*******************************************************************
131 * list_window_children
133 * Build an array of the children of a given window. The array must be
134 * freed with HeapFree. Returns NULL when no windows are found.
136 static HWND *list_window_children( HWND hwnd, ATOM atom, DWORD tid )
138 HWND *list;
139 int size = 32;
141 for (;;)
143 int count = 0;
145 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
147 SERVER_START_REQ( get_window_children )
149 req->parent = hwnd;
150 req->atom = atom;
151 req->tid = tid;
152 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
153 if (!wine_server_call( req )) count = reply->count;
155 SERVER_END_REQ;
156 if (count && count < size)
158 list[count] = 0;
159 return list;
161 HeapFree( GetProcessHeap(), 0, list );
162 if (!count) break;
163 size = count + 1; /* restart with a large enough buffer */
165 return NULL;
169 /*******************************************************************
170 * send_parent_notify
172 static void send_parent_notify( HWND hwnd, UINT msg )
174 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD)) return;
175 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY) return;
176 SendMessageW( GetParent(hwnd), WM_PARENTNOTIFY,
177 MAKEWPARAM( msg, GetWindowLongW( hwnd, GWL_ID )), (LPARAM)hwnd );
181 /*******************************************************************
182 * get_server_window_text
184 * Retrieve the window text from the server.
186 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
188 size_t len = 0;
190 SERVER_START_REQ( get_window_text )
192 req->handle = hwnd;
193 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
194 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
196 SERVER_END_REQ;
197 text[len / sizeof(WCHAR)] = 0;
201 /***********************************************************************
202 * WIN_GetPtr
204 * Return a pointer to the WND structure if local to the process,
205 * or WND_OTHER_PROCESS if handle may be valid in other process.
206 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
208 WND *WIN_GetPtr( HWND hwnd )
210 WND * ptr;
211 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
213 if (index >= NB_USER_HANDLES) return NULL;
215 USER_Lock();
216 if ((ptr = user_handles[index]))
218 if (ptr->dwMagic == WND_MAGIC && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
219 return ptr;
220 ptr = NULL;
222 else ptr = WND_OTHER_PROCESS;
223 USER_Unlock();
224 return ptr;
228 /***********************************************************************
229 * WIN_IsCurrentProcess
231 * Check whether a given window belongs to the current process (and return the full handle).
233 HWND WIN_IsCurrentProcess( HWND hwnd )
235 WND *ptr;
236 HWND ret;
238 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS) return 0;
239 ret = ptr->hwndSelf;
240 WIN_ReleasePtr( ptr );
241 return ret;
245 /***********************************************************************
246 * WIN_IsCurrentThread
248 * Check whether a given window belongs to the current thread (and return the full handle).
250 HWND WIN_IsCurrentThread( HWND hwnd )
252 WND *ptr;
253 HWND ret = 0;
255 if ((ptr = WIN_GetPtr( hwnd )) && ptr != WND_OTHER_PROCESS)
257 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
258 WIN_ReleasePtr( ptr );
260 return ret;
264 /***********************************************************************
265 * WIN_Handle32
267 * Convert a 16-bit window handle to a full 32-bit handle.
269 HWND WIN_Handle32( HWND16 hwnd16 )
271 WND *ptr;
272 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
274 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
275 /* do sign extension for -2 and -3 */
276 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
278 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
280 if (ptr != WND_OTHER_PROCESS)
282 hwnd = ptr->hwndSelf;
283 WIN_ReleasePtr( ptr );
285 else /* may belong to another process */
287 SERVER_START_REQ( get_window_info )
289 req->handle = hwnd;
290 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
292 SERVER_END_REQ;
294 return hwnd;
298 /***********************************************************************
299 * WIN_FindWndPtr
301 * Return a pointer to the WND structure corresponding to a HWND.
303 WND * WIN_FindWndPtr( HWND hwnd )
305 WND * ptr;
307 if (!hwnd) return NULL;
309 if ((ptr = WIN_GetPtr( hwnd )))
311 if (ptr != WND_OTHER_PROCESS)
313 /* increment destruction monitoring */
314 ptr->irefCount++;
315 return ptr;
317 if (IsWindow( hwnd )) /* check other processes */
319 ERR( "window %p belongs to other process\n", hwnd );
320 /* DbgBreakPoint(); */
323 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
324 return NULL;
328 /***********************************************************************
329 * WIN_ReleaseWndPtr
331 * Release the pointer to the WND structure.
333 void WIN_ReleaseWndPtr(WND *wndPtr)
335 if(!wndPtr) return;
337 /* Decrement destruction monitoring value */
338 wndPtr->irefCount--;
339 /* Check if it's time to release the memory */
340 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
342 /* Release memory */
343 free_window_handle( wndPtr->hwndSelf );
345 else if(wndPtr->irefCount < 0)
347 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
348 ERR("forgot a Lock on %p somewhere\n",wndPtr);
350 /* unlock all WND structures for thread safeness */
351 USER_Unlock();
355 /***********************************************************************
356 * WIN_UnlinkWindow
358 * Remove a window from the siblings linked list.
360 void WIN_UnlinkWindow( HWND hwnd )
362 WIN_LinkWindow( hwnd, 0, 0 );
366 /***********************************************************************
367 * WIN_LinkWindow
369 * Insert a window into the siblings linked list.
370 * The window is inserted after the specified window, which can also
371 * be specified as HWND_TOP or HWND_BOTTOM.
372 * If parent is 0, window is unlinked from the tree.
374 void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
376 WND *wndPtr = WIN_GetPtr( hwnd );
378 if (!wndPtr) return;
379 if (wndPtr == WND_OTHER_PROCESS)
381 if (IsWindow(hwnd)) ERR(" cannot link other process window %p\n", hwnd );
382 return;
385 SERVER_START_REQ( link_window )
387 req->handle = hwnd;
388 req->parent = parent;
389 req->previous = hwndInsertAfter;
390 if (!wine_server_call( req ))
392 if (reply->full_parent) wndPtr->parent = reply->full_parent;
396 SERVER_END_REQ;
397 WIN_ReleasePtr( wndPtr );
401 /***********************************************************************
402 * WIN_SetOwner
404 * Change the owner of a window.
406 HWND WIN_SetOwner( HWND hwnd, HWND owner )
408 WND *win = WIN_GetPtr( hwnd );
409 HWND ret = 0;
411 if (!win) return 0;
412 if (win == WND_OTHER_PROCESS)
414 if (IsWindow(hwnd)) ERR( "cannot set owner %p on other process window %p\n", owner, hwnd );
415 return 0;
417 SERVER_START_REQ( set_window_owner )
419 req->handle = hwnd;
420 req->owner = owner;
421 if (!wine_server_call( req ))
423 win->owner = reply->full_owner;
424 ret = reply->prev_owner;
427 SERVER_END_REQ;
428 WIN_ReleasePtr( win );
429 return ret;
433 /***********************************************************************
434 * WIN_SetStyle
436 * Change the style of a window.
438 LONG WIN_SetStyle( HWND hwnd, LONG style )
440 BOOL ok;
441 LONG ret = 0;
442 WND *win = WIN_GetPtr( hwnd );
444 if (!win) return 0;
445 if (win == WND_OTHER_PROCESS)
447 if (IsWindow(hwnd))
448 ERR( "cannot set style %lx on other process window %p\n", style, hwnd );
449 return 0;
451 if (style == win->dwStyle)
453 WIN_ReleasePtr( win );
454 return style;
456 SERVER_START_REQ( set_window_info )
458 req->handle = hwnd;
459 req->flags = SET_WIN_STYLE;
460 req->style = style;
461 if ((ok = !wine_server_call( req )))
463 ret = reply->old_style;
464 win->dwStyle = style;
467 SERVER_END_REQ;
468 WIN_ReleasePtr( win );
469 if (ok && USER_Driver.pSetWindowStyle) USER_Driver.pSetWindowStyle( hwnd, ret );
470 return ret;
474 /***********************************************************************
475 * WIN_SetExStyle
477 * Change the extended style of a window.
479 LONG WIN_SetExStyle( HWND hwnd, LONG style )
481 LONG ret = 0;
482 WND *win = WIN_GetPtr( hwnd );
484 if (!win) return 0;
485 if (win == WND_OTHER_PROCESS)
487 if (IsWindow(hwnd))
488 ERR( "cannot set exstyle %lx on other process window %p\n", style, hwnd );
489 return 0;
491 if (style == win->dwExStyle)
493 WIN_ReleasePtr( win );
494 return style;
496 SERVER_START_REQ( set_window_info )
498 req->handle = hwnd;
499 req->flags = SET_WIN_EXSTYLE;
500 req->ex_style = style;
501 if (!wine_server_call( req ))
503 ret = reply->old_ex_style;
504 win->dwExStyle = style;
507 SERVER_END_REQ;
508 WIN_ReleasePtr( win );
509 return ret;
513 /***********************************************************************
514 * WIN_SetRectangles
516 * Set the window and client rectangles.
518 void WIN_SetRectangles( HWND hwnd, const RECT *rectWindow, const RECT *rectClient )
520 WND *win = WIN_GetPtr( hwnd );
521 BOOL ret;
523 if (!win) return;
524 if (win == WND_OTHER_PROCESS)
526 if (IsWindow( hwnd )) ERR( "cannot set rectangles of other process window %p\n", hwnd );
527 return;
529 SERVER_START_REQ( set_window_rectangles )
531 req->handle = hwnd;
532 req->window.left = rectWindow->left;
533 req->window.top = rectWindow->top;
534 req->window.right = rectWindow->right;
535 req->window.bottom = rectWindow->bottom;
536 req->client.left = rectClient->left;
537 req->client.top = rectClient->top;
538 req->client.right = rectClient->right;
539 req->client.bottom = rectClient->bottom;
540 ret = !wine_server_call( req );
542 SERVER_END_REQ;
543 if (ret)
545 win->rectWindow = *rectWindow;
546 win->rectClient = *rectClient;
548 TRACE( "win %p window (%ld,%ld)-(%ld,%ld) client (%ld,%ld)-(%ld,%ld)\n", hwnd,
549 rectWindow->left, rectWindow->top, rectWindow->right, rectWindow->bottom,
550 rectClient->left, rectClient->top, rectClient->right, rectClient->bottom );
552 WIN_ReleasePtr( win );
556 /***********************************************************************
557 * WIN_GetRectangles
559 * Get the window and client rectangles.
561 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
563 WND *win = WIN_GetPtr( hwnd );
564 BOOL ret = TRUE;
566 if (!win) return FALSE;
567 if (win == WND_OTHER_PROCESS)
569 SERVER_START_REQ( get_window_rectangles )
571 req->handle = hwnd;
572 if ((ret = !wine_server_call( req )))
574 if (rectWindow)
576 rectWindow->left = reply->window.left;
577 rectWindow->top = reply->window.top;
578 rectWindow->right = reply->window.right;
579 rectWindow->bottom = reply->window.bottom;
581 if (rectClient)
583 rectClient->left = reply->client.left;
584 rectClient->top = reply->client.top;
585 rectClient->right = reply->client.right;
586 rectClient->bottom = reply->client.bottom;
590 SERVER_END_REQ;
592 else
594 if (rectWindow) *rectWindow = win->rectWindow;
595 if (rectClient) *rectClient = win->rectClient;
596 WIN_ReleasePtr( win );
598 return ret;
602 /***********************************************************************
603 * WIN_DestroyWindow
605 * Destroy storage associated to a window. "Internals" p.358
607 LRESULT WIN_DestroyWindow( HWND hwnd )
609 WND *wndPtr;
610 HWND *list;
612 TRACE("%p\n", hwnd );
614 if (!(hwnd = WIN_IsCurrentThread( hwnd )))
616 ERR( "window doesn't belong to current thread\n" );
617 return 0;
620 /* free child windows */
621 if ((list = WIN_ListChildren( hwnd )))
623 int i;
624 for (i = 0; list[i]; i++)
626 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
627 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
629 HeapFree( GetProcessHeap(), 0, list );
633 * Clear the update region to make sure no WM_PAINT messages will be
634 * generated for this window while processing the WM_NCDESTROY.
636 RedrawWindow( hwnd, NULL, 0,
637 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
640 * Send the WM_NCDESTROY to the window being destroyed.
642 SendMessageA( hwnd, WM_NCDESTROY, 0, 0);
644 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
646 WINPOS_CheckInternalPos( hwnd );
647 if( hwnd == GetCapture()) ReleaseCapture();
649 /* free resources associated with the window */
651 TIMER_RemoveWindowTimers( hwnd );
653 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
655 if (!(wndPtr->dwStyle & WS_CHILD))
657 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
658 if (menu) DestroyMenu( menu );
660 if (wndPtr->hSysMenu)
662 DestroyMenu( wndPtr->hSysMenu );
663 wndPtr->hSysMenu = 0;
665 DCE_FreeWindowDCE( hwnd ); /* Always do this to catch orphaned DCs */
666 USER_Driver.pDestroyWindow( hwnd );
667 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
668 CLASS_RemoveWindow( wndPtr->class );
669 wndPtr->class = NULL;
670 wndPtr->dwMagic = 0; /* Mark it as invalid */
671 WIN_ReleaseWndPtr( wndPtr );
672 return 0;
675 /***********************************************************************
676 * WIN_DestroyThreadWindows
678 * Destroy all children of 'wnd' owned by the current thread.
679 * Return TRUE if something was done.
681 void WIN_DestroyThreadWindows( HWND hwnd )
683 HWND *list;
684 int i;
686 if (!(list = WIN_ListChildren( hwnd ))) return;
687 for (i = 0; list[i]; i++)
689 if (WIN_IsCurrentThread( list[i] ))
690 DestroyWindow( list[i] );
691 else
692 WIN_DestroyThreadWindows( list[i] );
694 HeapFree( GetProcessHeap(), 0, list );
697 /***********************************************************************
698 * WIN_CreateDesktopWindow
700 * Create the desktop window.
702 BOOL WIN_CreateDesktopWindow(void)
704 struct tagCLASS *class;
705 HWND hwndDesktop;
706 INT wndExtra;
707 DWORD clsStyle;
708 WNDPROC winproc;
709 DCE *dce;
710 CREATESTRUCTA cs;
711 RECT rect;
713 TRACE("Creating desktop window\n");
715 if (!WINPOS_CreateInternalPosAtom() ||
716 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
717 &wndExtra, &winproc, &clsStyle, &dce )))
718 return FALSE;
720 pWndDesktop = create_window_handle( 0, 0, LOWORD(DESKTOP_CLASS_ATOM),
721 sizeof(WND) + wndExtra - sizeof(pWndDesktop->wExtra) );
722 if (!pWndDesktop) return FALSE;
723 hwndDesktop = pWndDesktop->hwndSelf;
725 pWndDesktop->tid = 0; /* nobody owns the desktop */
726 pWndDesktop->parent = 0;
727 pWndDesktop->owner = 0;
728 pWndDesktop->class = class;
729 pWndDesktop->text = NULL;
730 pWndDesktop->hrgnUpdate = 0;
731 pWndDesktop->clsStyle = clsStyle;
732 pWndDesktop->dce = NULL;
733 pWndDesktop->pVScroll = NULL;
734 pWndDesktop->pHScroll = NULL;
735 pWndDesktop->helpContext = 0;
736 pWndDesktop->flags = 0;
737 pWndDesktop->hSysMenu = 0;
738 pWndDesktop->winproc = winproc;
739 pWndDesktop->cbWndExtra = wndExtra;
741 cs.lpCreateParams = NULL;
742 cs.hInstance = 0;
743 cs.hMenu = 0;
744 cs.hwndParent = 0;
745 cs.x = 0;
746 cs.y = 0;
747 cs.cx = GetSystemMetrics( SM_CXSCREEN );
748 cs.cy = GetSystemMetrics( SM_CYSCREEN );
749 cs.style = pWndDesktop->dwStyle;
750 cs.dwExStyle = pWndDesktop->dwExStyle;
751 cs.lpszName = NULL;
752 cs.lpszClass = DESKTOP_CLASS_ATOM;
754 SetRect( &rect, 0, 0, cs.cx, cs.cy );
755 WIN_SetRectangles( hwndDesktop, &rect, &rect );
757 SERVER_START_REQ( set_window_info )
759 req->handle = hwndDesktop;
760 req->flags = 0; /* don't set anything, just retrieve */
761 wine_server_call( req );
762 pWndDesktop->dwStyle = reply->old_style;
763 pWndDesktop->dwExStyle = reply->old_ex_style;
764 pWndDesktop->hInstance = (HINSTANCE)reply->old_instance;
765 pWndDesktop->userdata = (ULONG_PTR)reply->old_user_data;
766 pWndDesktop->wIDmenu = reply->old_id;
768 SERVER_END_REQ;
770 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE ))
772 WIN_ReleaseWndPtr( pWndDesktop );
773 return FALSE;
776 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
777 WIN_ReleaseWndPtr( pWndDesktop );
778 return TRUE;
782 /***********************************************************************
783 * WIN_FixCoordinates
785 * Fix the coordinates - Helper for WIN_CreateWindowEx.
786 * returns default show mode in sw.
787 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
789 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
791 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
792 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
794 if (cs->style & (WS_CHILD | WS_POPUP))
796 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
797 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
799 else /* overlapped window */
801 STARTUPINFOA info;
803 GetStartupInfoA( &info );
805 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
807 /* Never believe Microsoft's documentation... CreateWindowEx doc says
808 * that if an overlapped window is created with WS_VISIBLE style bit
809 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
810 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
811 * reveals that
813 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
814 * 2) it does not ignore the y parameter as the docs claim; instead, it
815 * uses it as second parameter to ShowWindow() unless y is either
816 * CW_USEDEFAULT or CW_USEDEFAULT16.
818 * The fact that we didn't do 2) caused bogus windows pop up when wine
819 * was running apps that were using this obscure feature. Example -
820 * calc.exe that comes with Win98 (only Win98, it's different from
821 * the one that comes with Win95 and NT)
823 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
824 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
825 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
828 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
830 if (info.dwFlags & STARTF_USESIZE)
832 cs->cx = info.dwXSize;
833 cs->cy = info.dwYSize;
835 else /* if no other hint from the app, pick 3/4 of the screen real estate */
837 RECT r;
838 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
839 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
840 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
845 else
847 /* neither x nor cx are default. Check the y values .
848 * In the trace we see Outlook and Outlook Express using
849 * cy set to CW_USEDEFAULT when opening the address book.
851 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16) {
852 RECT r;
853 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
854 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
855 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
860 /***********************************************************************
861 * dump_window_styles
863 static void dump_window_styles( DWORD style, DWORD exstyle )
865 TRACE( "style:" );
866 if(style & WS_POPUP) TRACE(" WS_POPUP");
867 if(style & WS_CHILD) TRACE(" WS_CHILD");
868 if(style & WS_MINIMIZE) TRACE(" WS_MINIMIZE");
869 if(style & WS_VISIBLE) TRACE(" WS_VISIBLE");
870 if(style & WS_DISABLED) TRACE(" WS_DISABLED");
871 if(style & WS_CLIPSIBLINGS) TRACE(" WS_CLIPSIBLINGS");
872 if(style & WS_CLIPCHILDREN) TRACE(" WS_CLIPCHILDREN");
873 if(style & WS_MAXIMIZE) TRACE(" WS_MAXIMIZE");
874 if((style & WS_CAPTION) == WS_CAPTION) TRACE(" WS_CAPTION");
875 else
877 if(style & WS_BORDER) TRACE(" WS_BORDER");
878 if(style & WS_DLGFRAME) TRACE(" WS_DLGFRAME");
880 if(style & WS_VSCROLL) TRACE(" WS_VSCROLL");
881 if(style & WS_HSCROLL) TRACE(" WS_HSCROLL");
882 if(style & WS_SYSMENU) TRACE(" WS_SYSMENU");
883 if(style & WS_THICKFRAME) TRACE(" WS_THICKFRAME");
884 if(style & WS_GROUP) TRACE(" WS_GROUP");
885 if(style & WS_TABSTOP) TRACE(" WS_TABSTOP");
886 if(style & WS_MINIMIZEBOX) TRACE(" WS_MINIMIZEBOX");
887 if(style & WS_MAXIMIZEBOX) TRACE(" WS_MAXIMIZEBOX");
889 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
890 #define DUMPED_STYLES \
891 (WS_POPUP | \
892 WS_CHILD | \
893 WS_MINIMIZE | \
894 WS_VISIBLE | \
895 WS_DISABLED | \
896 WS_CLIPSIBLINGS | \
897 WS_CLIPCHILDREN | \
898 WS_MAXIMIZE | \
899 WS_BORDER | \
900 WS_DLGFRAME | \
901 WS_VSCROLL | \
902 WS_HSCROLL | \
903 WS_SYSMENU | \
904 WS_THICKFRAME | \
905 WS_GROUP | \
906 WS_TABSTOP | \
907 WS_MINIMIZEBOX | \
908 WS_MAXIMIZEBOX)
910 if(style & ~DUMPED_STYLES) TRACE(" %08lx", style & ~DUMPED_STYLES);
911 TRACE("\n");
912 #undef DUMPED_STYLES
914 TRACE( "exstyle:" );
915 if(exstyle & WS_EX_DLGMODALFRAME) TRACE(" WS_EX_DLGMODALFRAME");
916 if(exstyle & WS_EX_DRAGDETECT) TRACE(" WS_EX_DRAGDETECT");
917 if(exstyle & WS_EX_NOPARENTNOTIFY) TRACE(" WS_EX_NOPARENTNOTIFY");
918 if(exstyle & WS_EX_TOPMOST) TRACE(" WS_EX_TOPMOST");
919 if(exstyle & WS_EX_ACCEPTFILES) TRACE(" WS_EX_ACCEPTFILES");
920 if(exstyle & WS_EX_TRANSPARENT) TRACE(" WS_EX_TRANSPARENT");
921 if(exstyle & WS_EX_MDICHILD) TRACE(" WS_EX_MDICHILD");
922 if(exstyle & WS_EX_TOOLWINDOW) TRACE(" WS_EX_TOOLWINDOW");
923 if(exstyle & WS_EX_WINDOWEDGE) TRACE(" WS_EX_WINDOWEDGE");
924 if(exstyle & WS_EX_CLIENTEDGE) TRACE(" WS_EX_CLIENTEDGE");
925 if(exstyle & WS_EX_CONTEXTHELP) TRACE(" WS_EX_CONTEXTHELP");
926 if(exstyle & WS_EX_RIGHT) TRACE(" WS_EX_RIGHT");
927 if(exstyle & WS_EX_RTLREADING) TRACE(" WS_EX_RTLREADING");
928 if(exstyle & WS_EX_LEFTSCROLLBAR) TRACE(" WS_EX_LEFTSCROLLBAR");
929 if(exstyle & WS_EX_CONTROLPARENT) TRACE(" WS_EX_CONTROLPARENT");
930 if(exstyle & WS_EX_STATICEDGE) TRACE(" WS_EX_STATICEDGE");
931 if(exstyle & WS_EX_APPWINDOW) TRACE(" WS_EX_APPWINDOW");
932 if(exstyle & WS_EX_LAYERED) TRACE(" WS_EX_LAYERED");
934 #define DUMPED_EX_STYLES \
935 (WS_EX_DLGMODALFRAME | \
936 WS_EX_DRAGDETECT | \
937 WS_EX_NOPARENTNOTIFY | \
938 WS_EX_TOPMOST | \
939 WS_EX_ACCEPTFILES | \
940 WS_EX_TRANSPARENT | \
941 WS_EX_MDICHILD | \
942 WS_EX_TOOLWINDOW | \
943 WS_EX_WINDOWEDGE | \
944 WS_EX_CLIENTEDGE | \
945 WS_EX_CONTEXTHELP | \
946 WS_EX_RIGHT | \
947 WS_EX_RTLREADING | \
948 WS_EX_LEFTSCROLLBAR | \
949 WS_EX_CONTROLPARENT | \
950 WS_EX_STATICEDGE | \
951 WS_EX_APPWINDOW | \
952 WS_EX_LAYERED)
954 if(exstyle & ~DUMPED_EX_STYLES) TRACE(" %08lx", exstyle & ~DUMPED_EX_STYLES);
955 TRACE("\n");
956 #undef DUMPED_EX_STYLES
960 /***********************************************************************
961 * WIN_CreateWindowEx
963 * Implementation of CreateWindowEx().
965 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
966 WINDOWPROCTYPE type )
968 INT sw = SW_SHOW;
969 struct tagCLASS *classPtr;
970 WND *wndPtr;
971 HWND hwnd, parent, owner;
972 INT wndExtra;
973 DWORD clsStyle;
974 WNDPROC winproc;
975 DCE *dce;
976 BOOL unicode = (type == WIN_PROC_32W);
978 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
979 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
980 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszClass) : debugstr_a(cs->lpszClass),
981 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
982 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
984 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
986 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
987 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
989 /* Find the parent window */
991 parent = GetDesktopWindow();
992 owner = 0;
994 if (cs->hwndParent == HWND_MESSAGE)
996 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
997 * message window (style: WS_POPUP|WS_DISABLED)
999 FIXME("Parent is HWND_MESSAGE\n");
1001 else if (cs->hwndParent)
1003 /* Make sure parent is valid */
1004 if (!IsWindow( cs->hwndParent ))
1006 WARN("Bad parent %p\n", cs->hwndParent );
1007 return 0;
1009 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1010 parent = WIN_GetFullHandle(cs->hwndParent);
1011 else
1012 owner = GetAncestor( cs->hwndParent, GA_ROOT );
1014 else if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1016 WARN("No parent for child window\n" );
1017 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1020 /* Find the window class */
1021 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
1022 &wndExtra, &winproc, &clsStyle, &dce )))
1024 WARN("Bad class '%s'\n", cs->lpszClass );
1025 return 0;
1028 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
1030 /* Correct the window style - stage 1
1032 * These are patches that appear to affect both the style loaded into the
1033 * WIN structure and passed in the CreateStruct to the WM_CREATE etc.
1035 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1036 * why does the user get to set it?
1039 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
1040 * tested for WS_POPUP
1042 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
1043 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
1044 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
1045 cs->dwExStyle |= WS_EX_WINDOWEDGE;
1046 else
1047 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
1049 /* Create the window structure */
1051 if (!(wndPtr = create_window_handle( parent, owner, classAtom,
1052 sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
1054 TRACE("out of memory\n" );
1055 return 0;
1057 hwnd = wndPtr->hwndSelf;
1059 /* Fill the window structure */
1061 wndPtr->tid = GetCurrentThreadId();
1062 wndPtr->owner = owner;
1063 wndPtr->parent = parent;
1064 wndPtr->class = classPtr;
1065 wndPtr->winproc = winproc;
1066 wndPtr->hInstance = cs->hInstance;
1067 wndPtr->text = NULL;
1068 wndPtr->hrgnUpdate = 0;
1069 wndPtr->hrgnWnd = 0;
1070 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1071 wndPtr->dwExStyle = cs->dwExStyle;
1072 wndPtr->clsStyle = clsStyle;
1073 wndPtr->wIDmenu = 0;
1074 wndPtr->helpContext = 0;
1075 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
1076 wndPtr->pVScroll = NULL;
1077 wndPtr->pHScroll = NULL;
1078 wndPtr->userdata = 0;
1079 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU) ? MENU_GetSysMenu( hwnd, 0 ) : 0;
1080 wndPtr->cbWndExtra = wndExtra;
1082 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
1084 /* Correct the window style - stage 2 */
1086 if (!(cs->style & WS_CHILD))
1088 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1089 if (!(cs->style & WS_POPUP))
1091 wndPtr->dwStyle |= WS_CAPTION;
1092 wndPtr->flags |= WIN_NEED_SIZE;
1095 SERVER_START_REQ( set_window_info )
1097 req->handle = hwnd;
1098 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE;
1099 req->style = wndPtr->dwStyle;
1100 req->ex_style = wndPtr->dwExStyle;
1101 req->instance = (void *)wndPtr->hInstance;
1102 wine_server_call( req );
1104 SERVER_END_REQ;
1106 /* Get class or window DC if needed */
1108 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
1109 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
1110 else wndPtr->dce = NULL;
1112 /* Set the window menu */
1114 if (((wndPtr->dwStyle & (WS_CAPTION|WS_CHILD)) == WS_CAPTION) ||
1115 (wndPtr->dwExStyle & WS_EX_APPWINDOW))
1117 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
1118 else
1120 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
1121 if (menuName)
1123 if (HIWORD(cs->hInstance))
1124 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1125 else
1126 cs->hMenu = HMENU_32(LoadMenu16(HINSTANCE_16(cs->hInstance),menuName));
1128 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
1132 else SetWindowLongW( hwnd, GWL_ID, (UINT)cs->hMenu );
1133 WIN_ReleaseWndPtr( wndPtr );
1135 if (!USER_Driver.pCreateWindow( hwnd, cs, unicode))
1137 WIN_DestroyWindow( hwnd );
1138 return 0;
1141 /* Notify the parent window only */
1143 send_parent_notify( hwnd, WM_CREATE );
1144 if (!IsWindow( hwnd )) return 0;
1146 if (cs->style & WS_VISIBLE)
1148 /* in case WS_VISIBLE got set in the meantime */
1149 if (!(wndPtr = WIN_GetPtr( hwnd ))) return 0;
1150 WIN_SetStyle( hwnd, wndPtr->dwStyle & ~WS_VISIBLE );
1151 WIN_ReleasePtr( wndPtr );
1152 ShowWindow( hwnd, sw );
1155 /* Call WH_SHELL hook */
1157 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1158 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1160 TRACE("created window %p\n", hwnd);
1161 return hwnd;
1165 /***********************************************************************
1166 * CreateWindow (USER.41)
1168 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1169 DWORD style, INT16 x, INT16 y, INT16 width,
1170 INT16 height, HWND16 parent, HMENU16 menu,
1171 HINSTANCE16 instance, LPVOID data )
1173 return CreateWindowEx16( 0, className, windowName, style,
1174 x, y, width, height, parent, menu, instance, data );
1178 /***********************************************************************
1179 * CreateWindowEx (USER.452)
1181 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1182 LPCSTR windowName, DWORD style, INT16 x,
1183 INT16 y, INT16 width, INT16 height,
1184 HWND16 parent, HMENU16 menu,
1185 HINSTANCE16 instance, LPVOID data )
1187 ATOM classAtom;
1188 CREATESTRUCTA cs;
1189 char buffer[256];
1191 /* Find the class atom */
1193 if (HIWORD(className))
1195 if (!(classAtom = GlobalFindAtomA( className )))
1197 ERR( "bad class name %s\n", debugstr_a(className) );
1198 return 0;
1201 else
1203 classAtom = LOWORD(className);
1204 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1206 ERR( "bad atom %x\n", classAtom);
1207 return 0;
1209 className = buffer;
1212 /* Fix the coordinates */
1214 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1215 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1216 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1217 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1219 /* Create the window */
1221 cs.lpCreateParams = data;
1222 cs.hInstance = HINSTANCE_32(instance);
1223 cs.hMenu = HMENU_32(menu);
1224 cs.hwndParent = WIN_Handle32( parent );
1225 cs.style = style;
1226 cs.lpszName = windowName;
1227 cs.lpszClass = className;
1228 cs.dwExStyle = exStyle;
1230 return HWND_16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
1234 /***********************************************************************
1235 * CreateWindowExA (USER32.@)
1237 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1238 LPCSTR windowName, DWORD style, INT x,
1239 INT y, INT width, INT height,
1240 HWND parent, HMENU menu,
1241 HINSTANCE instance, LPVOID data )
1243 ATOM classAtom;
1244 CREATESTRUCTA cs;
1245 char buffer[256];
1247 if(!instance)
1248 instance=GetModuleHandleA(NULL);
1250 if(exStyle & WS_EX_MDICHILD)
1251 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1253 /* Find the class atom */
1255 if (HIWORD(className))
1257 if (!(classAtom = GlobalFindAtomA( className )))
1259 ERR( "bad class name %s\n", debugstr_a(className) );
1260 return 0;
1263 else
1265 classAtom = LOWORD(className);
1266 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1268 ERR( "bad atom %x\n", classAtom);
1269 return 0;
1271 className = buffer;
1274 /* Create the window */
1276 cs.lpCreateParams = data;
1277 cs.hInstance = instance;
1278 cs.hMenu = menu;
1279 cs.hwndParent = parent;
1280 cs.x = x;
1281 cs.y = y;
1282 cs.cx = width;
1283 cs.cy = height;
1284 cs.style = style;
1285 cs.lpszName = windowName;
1286 cs.lpszClass = className;
1287 cs.dwExStyle = exStyle;
1289 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1293 /***********************************************************************
1294 * CreateWindowExW (USER32.@)
1296 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1297 LPCWSTR windowName, DWORD style, INT x,
1298 INT y, INT width, INT height,
1299 HWND parent, HMENU menu,
1300 HINSTANCE instance, LPVOID data )
1302 ATOM classAtom;
1303 CREATESTRUCTW cs;
1304 WCHAR buffer[256];
1306 if(!instance)
1307 instance=GetModuleHandleW(NULL);
1309 if(exStyle & WS_EX_MDICHILD)
1310 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1312 /* Find the class atom */
1314 if (HIWORD(className))
1316 if (!(classAtom = GlobalFindAtomW( className )))
1318 ERR( "bad class name %s\n", debugstr_w(className) );
1319 return 0;
1322 else
1324 classAtom = LOWORD(className);
1325 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1327 ERR( "bad atom %x\n", classAtom);
1328 return 0;
1330 className = buffer;
1333 /* Create the window */
1335 cs.lpCreateParams = data;
1336 cs.hInstance = instance;
1337 cs.hMenu = menu;
1338 cs.hwndParent = parent;
1339 cs.x = x;
1340 cs.y = y;
1341 cs.cx = width;
1342 cs.cy = height;
1343 cs.style = style;
1344 cs.lpszName = windowName;
1345 cs.lpszClass = className;
1346 cs.dwExStyle = exStyle;
1348 /* Note: we rely on the fact that CREATESTRUCTA and */
1349 /* CREATESTRUCTW have the same layout. */
1350 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1354 /***********************************************************************
1355 * WIN_SendDestroyMsg
1357 static void WIN_SendDestroyMsg( HWND hwnd )
1359 GUITHREADINFO info;
1361 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1363 if (hwnd == info.hwndCaret) DestroyCaret();
1365 if (USER_Driver.pResetSelectionOwner)
1366 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1369 * Send the WM_DESTROY to the window.
1371 SendMessageA( hwnd, WM_DESTROY, 0, 0);
1374 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1375 * make sure that the window still exists when we come back.
1377 if (IsWindow(hwnd))
1379 HWND* pWndArray;
1380 int i;
1382 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1384 /* start from the end (FIXME: is this needed?) */
1385 for (i = 0; pWndArray[i]; i++) ;
1387 while (--i >= 0)
1389 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1391 HeapFree( GetProcessHeap(), 0, pWndArray );
1393 else
1394 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1398 /***********************************************************************
1399 * DestroyWindow (USER32.@)
1401 BOOL WINAPI DestroyWindow( HWND hwnd )
1403 BOOL is_child;
1404 HWND h;
1406 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1408 SetLastError( ERROR_ACCESS_DENIED );
1409 return FALSE;
1412 TRACE("(%p)\n", hwnd);
1414 /* Look whether the focus is within the tree of windows we will
1415 * be destroying.
1417 h = GetFocus();
1418 if (h == hwnd || IsChild( hwnd, h ))
1420 HWND parent = GetAncestor( hwnd, GA_PARENT );
1421 if (parent == GetDesktopWindow()) parent = 0;
1422 SetFocus( parent );
1425 /* Call hooks */
1427 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1429 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1431 if (is_child)
1433 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1434 send_parent_notify( hwnd, WM_DESTROY );
1436 else if (!GetWindow( hwnd, GW_OWNER ))
1438 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1439 /* FIXME: clean up palette - see "Internals" p.352 */
1442 if (!IsWindow(hwnd)) return TRUE;
1444 if (USER_Driver.pResetSelectionOwner)
1445 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1447 /* Hide the window */
1449 if (!ShowWindow( hwnd, SW_HIDE ))
1451 if (hwnd == GetActiveWindow()) WINPOS_ActivateOtherWindow( hwnd );
1453 if (!IsWindow(hwnd)) return TRUE;
1455 /* Recursively destroy owned windows */
1457 if (!is_child)
1459 for (;;)
1461 int i, got_one = 0;
1462 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1463 if (list)
1465 for (i = 0; list[i]; i++)
1467 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1468 if (WIN_IsCurrentThread( list[i] ))
1470 DestroyWindow( list[i] );
1471 got_one = 1;
1472 continue;
1474 WIN_SetOwner( list[i], 0 );
1476 HeapFree( GetProcessHeap(), 0, list );
1478 if (!got_one) break;
1482 /* Send destroy messages */
1484 WIN_SendDestroyMsg( hwnd );
1485 if (!IsWindow( hwnd )) return TRUE;
1487 if (GetClipboardOwner() == hwnd)
1488 CLIPBOARD_ReleaseOwner();
1490 /* Unlink now so we won't bother with the children later on */
1492 WIN_UnlinkWindow( hwnd );
1494 /* Destroy the window storage */
1496 WIN_DestroyWindow( hwnd );
1497 return TRUE;
1501 /***********************************************************************
1502 * CloseWindow (USER32.@)
1504 BOOL WINAPI CloseWindow( HWND hwnd )
1506 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1507 ShowWindow( hwnd, SW_MINIMIZE );
1508 return TRUE;
1512 /***********************************************************************
1513 * OpenIcon (USER32.@)
1515 BOOL WINAPI OpenIcon( HWND hwnd )
1517 if (!IsIconic( hwnd )) return FALSE;
1518 ShowWindow( hwnd, SW_SHOWNORMAL );
1519 return TRUE;
1523 /***********************************************************************
1524 * WIN_FindWindow
1526 * Implementation of FindWindow() and FindWindowEx().
1528 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1530 HWND *list = NULL;
1531 HWND retvalue = 0;
1532 int i = 0, len = 0;
1533 WCHAR *buffer = NULL;
1535 if (!parent) parent = GetDesktopWindow();
1536 if (title)
1538 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1539 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1542 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1544 if (child)
1546 child = WIN_GetFullHandle( child );
1547 while (list[i] && list[i] != child) i++;
1548 if (!list[i]) goto done;
1549 i++; /* start from next window */
1552 if (title)
1554 while (list[i])
1556 if (GetWindowTextW( list[i], buffer, len ) && !strcmpiW( buffer, title )) break;
1557 i++;
1560 retvalue = list[i];
1562 done:
1563 if (list) HeapFree( GetProcessHeap(), 0, list );
1564 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1565 return retvalue;
1570 /***********************************************************************
1571 * FindWindowA (USER32.@)
1573 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1575 HWND ret = FindWindowExA( 0, 0, className, title );
1576 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1577 return ret;
1581 /***********************************************************************
1582 * FindWindowExA (USER32.@)
1584 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1585 LPCSTR className, LPCSTR title )
1587 ATOM atom = 0;
1588 LPWSTR buffer;
1589 HWND hwnd;
1590 INT len;
1592 if (className)
1594 /* If the atom doesn't exist, then no class */
1595 /* with this name exists either. */
1596 if (!(atom = GlobalFindAtomA( className )))
1598 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1599 return 0;
1602 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
1604 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1605 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1606 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
1607 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1608 HeapFree( GetProcessHeap(), 0, buffer );
1609 return hwnd;
1613 /***********************************************************************
1614 * FindWindowExW (USER32.@)
1616 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1617 LPCWSTR className, LPCWSTR title )
1619 ATOM atom = 0;
1621 if (className)
1623 /* If the atom doesn't exist, then no class */
1624 /* with this name exists either. */
1625 if (!(atom = GlobalFindAtomW( className )))
1627 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1628 return 0;
1631 return WIN_FindWindow( parent, child, atom, title );
1635 /***********************************************************************
1636 * FindWindowW (USER32.@)
1638 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1640 return FindWindowExW( 0, 0, className, title );
1644 /**********************************************************************
1645 * GetDesktopWindow (USER32.@)
1647 HWND WINAPI GetDesktopWindow(void)
1649 if (pWndDesktop) return pWndDesktop->hwndSelf;
1650 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" );
1651 ExitProcess(1);
1652 return 0;
1656 /*******************************************************************
1657 * EnableWindow (USER32.@)
1659 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1661 WND *wndPtr;
1662 BOOL retvalue;
1663 LONG style;
1664 HWND full_handle;
1666 if (is_broadcast(hwnd))
1668 SetLastError( ERROR_INVALID_PARAMETER );
1669 return FALSE;
1672 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1673 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1675 hwnd = full_handle;
1677 TRACE("( %p, %d )\n", hwnd, enable);
1679 if (!(wndPtr = WIN_GetPtr( hwnd ))) return FALSE;
1680 style = wndPtr->dwStyle;
1681 retvalue = ((style & WS_DISABLED) != 0);
1682 WIN_ReleasePtr( wndPtr );
1684 if (enable && retvalue)
1686 WIN_SetStyle( hwnd, style & ~WS_DISABLED );
1687 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1689 else if (!enable && !retvalue)
1691 HWND focus_wnd, capture_wnd;
1693 SendMessageA( hwnd, WM_CANCELMODE, 0, 0);
1695 WIN_SetStyle( hwnd, style | WS_DISABLED );
1697 focus_wnd = GetFocus();
1698 if (hwnd == focus_wnd || IsChild(hwnd, focus_wnd))
1699 SetFocus( 0 ); /* A disabled window can't have the focus */
1701 capture_wnd = GetCapture();
1702 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1703 ReleaseCapture(); /* A disabled window can't capture the mouse */
1705 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1707 return retvalue;
1711 /***********************************************************************
1712 * IsWindowEnabled (USER32.@)
1714 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1716 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1720 /***********************************************************************
1721 * IsWindowUnicode (USER32.@)
1723 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1725 WND * wndPtr;
1726 BOOL retvalue;
1728 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1729 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1730 WIN_ReleaseWndPtr(wndPtr);
1731 return retvalue;
1735 /**********************************************************************
1736 * GetWindowWord (USER32.@)
1738 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1740 if (offset >= 0)
1742 WORD retvalue = 0;
1743 WND *wndPtr = WIN_GetPtr( hwnd );
1744 if (!wndPtr)
1746 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1747 return 0;
1749 if (wndPtr == WND_OTHER_PROCESS)
1751 if (IsWindow( hwnd ))
1752 FIXME( "(%d) not supported yet on other process window %p\n", offset, hwnd );
1753 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1754 return 0;
1756 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1758 WARN("Invalid offset %d\n", offset );
1759 SetLastError( ERROR_INVALID_INDEX );
1761 else retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1762 WIN_ReleasePtr( wndPtr );
1763 return retvalue;
1766 switch(offset)
1768 case GWL_HWNDPARENT:
1769 return GetWindowLongW( hwnd, offset );
1770 case GWL_ID:
1771 case GWL_HINSTANCE:
1773 LONG ret = GetWindowLongW( hwnd, offset );
1774 if (HIWORD(ret))
1775 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1776 return LOWORD(ret);
1778 default:
1779 WARN("Invalid offset %d\n", offset );
1780 return 0;
1785 /**********************************************************************
1786 * SetWindowWord (USER32.@)
1788 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1790 WORD *ptr, retval;
1791 WND * wndPtr;
1793 switch(offset)
1795 case GWL_ID:
1796 case GWL_HINSTANCE:
1797 case GWL_HWNDPARENT:
1798 return SetWindowLongW( hwnd, offset, (UINT)newval );
1799 default:
1800 if (offset < 0)
1802 WARN("Invalid offset %d\n", offset );
1803 SetLastError( ERROR_INVALID_INDEX );
1804 return 0;
1808 wndPtr = WIN_GetPtr( hwnd );
1809 if (wndPtr == WND_OTHER_PROCESS)
1811 if (IsWindow(hwnd))
1812 FIXME( "set %d <- %x not supported yet on other process window %p\n",
1813 offset, newval, hwnd );
1814 wndPtr = NULL;
1816 if (!wndPtr)
1818 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1819 return 0;
1822 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1824 WARN("Invalid offset %d\n", offset );
1825 WIN_ReleasePtr(wndPtr);
1826 SetLastError( ERROR_INVALID_INDEX );
1827 return 0;
1829 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1830 retval = *ptr;
1831 *ptr = newval;
1832 WIN_ReleasePtr(wndPtr);
1833 return retval;
1837 /**********************************************************************
1838 * WIN_GetWindowLong
1840 * Helper function for GetWindowLong().
1842 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1844 LONG retvalue = 0;
1845 WND *wndPtr;
1847 if (offset == GWL_HWNDPARENT)
1849 HWND parent = GetAncestor( hwnd, GA_PARENT );
1850 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1851 return (LONG)parent;
1854 if (!(wndPtr = WIN_GetPtr( hwnd )))
1856 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1857 return 0;
1860 if (wndPtr == WND_OTHER_PROCESS)
1862 if (offset >= 0)
1864 if (IsWindow(hwnd))
1865 FIXME( "(%d) not supported on other process window %p\n", offset, hwnd );
1866 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1867 return 0;
1869 if (offset == GWL_WNDPROC)
1871 SetLastError( ERROR_ACCESS_DENIED );
1872 return 0;
1874 SERVER_START_REQ( set_window_info )
1876 req->handle = hwnd;
1877 req->flags = 0; /* don't set anything, just retrieve */
1878 if (!wine_server_call_err( req ))
1880 switch(offset)
1882 case GWL_STYLE: retvalue = reply->old_style; break;
1883 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1884 case GWL_ID: retvalue = reply->old_id; break;
1885 case GWL_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1886 case GWL_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
1887 default:
1888 SetLastError( ERROR_INVALID_INDEX );
1889 break;
1893 SERVER_END_REQ;
1894 return retvalue;
1897 /* now we have a valid wndPtr */
1899 if (offset >= 0)
1901 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
1904 * Some programs try to access last element from 16 bit
1905 * code using illegal offset value. Hopefully this is
1906 * what those programs really expect.
1908 if (type == WIN_PROC_16 &&
1909 wndPtr->cbWndExtra >= 4 &&
1910 offset == wndPtr->cbWndExtra - sizeof(WORD))
1912 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
1914 ERR( "- replaced invalid offset %d with %d\n",
1915 offset, offset2 );
1917 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset2);
1918 WIN_ReleasePtr( wndPtr );
1919 return retvalue;
1921 WARN("Invalid offset %d\n", offset );
1922 WIN_ReleasePtr( wndPtr );
1923 SetLastError( ERROR_INVALID_INDEX );
1924 return 0;
1926 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1927 /* Special case for dialog window procedure */
1928 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1929 retvalue = (LONG)WINPROC_GetProc( (WNDPROC)retvalue, type );
1930 WIN_ReleasePtr( wndPtr );
1931 return retvalue;
1934 switch(offset)
1936 case GWL_USERDATA: retvalue = wndPtr->userdata; break;
1937 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1938 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1939 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu; break;
1940 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc, type ); break;
1941 case GWL_HINSTANCE: retvalue = (LONG)wndPtr->hInstance; break;
1942 default:
1943 WARN("Unknown offset %d\n", offset );
1944 SetLastError( ERROR_INVALID_INDEX );
1945 break;
1947 WIN_ReleasePtr(wndPtr);
1948 return retvalue;
1952 /**********************************************************************
1953 * WIN_SetWindowLong
1955 * Helper function for SetWindowLong().
1957 * 0 is the failure code. However, in the case of failure SetLastError
1958 * must be set to distinguish between a 0 return value and a failure.
1960 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1961 WINDOWPROCTYPE type )
1963 LONG retval = 0;
1964 WND *wndPtr;
1966 TRACE( "%p %d %lx %x\n", hwnd, offset, newval, type );
1968 if (is_broadcast(hwnd))
1970 SetLastError( ERROR_INVALID_PARAMETER );
1971 return FALSE;
1973 if (!WIN_IsCurrentProcess( hwnd ))
1975 if (offset == GWL_WNDPROC)
1977 SetLastError( ERROR_ACCESS_DENIED );
1978 return 0;
1980 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
1983 wndPtr = WIN_GetPtr( hwnd );
1984 if (wndPtr->hwndSelf == GetDesktopWindow())
1986 /* can't change anything on the desktop window */
1987 WIN_ReleasePtr( wndPtr );
1988 SetLastError( ERROR_ACCESS_DENIED );
1989 return 0;
1992 if (offset >= 0)
1994 LONG *ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1995 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
1997 WARN("Invalid offset %d\n", offset );
1998 WIN_ReleasePtr( wndPtr );
1999 SetLastError( ERROR_INVALID_INDEX );
2000 return 0;
2002 /* Special case for dialog window procedure */
2003 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2005 retval = (LONG)WINPROC_GetProc( (WNDPROC)*ptr, type );
2006 WINPROC_SetProc( (WNDPROC *)ptr, (WNDPROC)newval, type, WIN_PROC_WINDOW );
2007 WIN_ReleasePtr( wndPtr );
2008 return retval;
2010 retval = *ptr;
2011 *ptr = newval;
2012 WIN_ReleasePtr( wndPtr );
2014 else
2016 STYLESTRUCT style;
2017 BOOL ok;
2019 /* first some special cases */
2020 switch( offset )
2022 case GWL_STYLE:
2023 case GWL_EXSTYLE:
2024 style.styleOld = wndPtr->dwStyle;
2025 style.styleNew = newval;
2026 WIN_ReleasePtr( wndPtr );
2027 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
2028 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
2029 newval = style.styleNew;
2030 break;
2031 case GWL_HWNDPARENT:
2032 if (wndPtr->parent == GetDesktopWindow())
2034 WIN_ReleasePtr( wndPtr );
2035 return (LONG)WIN_SetOwner( hwnd, (HWND)newval );
2037 else
2039 WIN_ReleasePtr( wndPtr );
2040 return (LONG)SetParent( hwnd, (HWND)newval );
2042 case GWL_WNDPROC:
2043 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2044 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC)newval, type, WIN_PROC_WINDOW );
2045 WIN_ReleasePtr( wndPtr );
2046 return retval;
2047 case GWL_ID:
2048 case GWL_HINSTANCE:
2049 case GWL_USERDATA:
2050 break;
2051 default:
2052 WIN_ReleasePtr( wndPtr );
2053 WARN("Invalid offset %d\n", offset );
2054 SetLastError( ERROR_INVALID_INDEX );
2055 return 0;
2058 SERVER_START_REQ( set_window_info )
2060 req->handle = hwnd;
2061 switch(offset)
2063 case GWL_STYLE:
2064 req->flags = SET_WIN_STYLE;
2065 req->style = newval;
2066 break;
2067 case GWL_EXSTYLE:
2068 req->flags = SET_WIN_EXSTYLE;
2069 req->ex_style = newval;
2070 break;
2071 case GWL_ID:
2072 req->flags = SET_WIN_ID;
2073 req->id = newval;
2074 break;
2075 case GWL_HINSTANCE:
2076 req->flags = SET_WIN_INSTANCE;
2077 req->instance = (void *)newval;
2078 break;
2079 case GWL_USERDATA:
2080 req->flags = SET_WIN_USERDATA;
2081 req->user_data = (void *)newval;
2082 break;
2084 if ((ok = !wine_server_call_err( req )))
2086 switch(offset)
2088 case GWL_STYLE:
2089 wndPtr->dwStyle = newval;
2090 retval = reply->old_style;
2091 break;
2092 case GWL_EXSTYLE:
2093 wndPtr->dwExStyle = newval;
2094 retval = reply->old_ex_style;
2095 break;
2096 case GWL_ID:
2097 wndPtr->wIDmenu = newval;
2098 retval = reply->old_id;
2099 break;
2100 case GWL_HINSTANCE:
2101 wndPtr->hInstance = (HINSTANCE)newval;
2102 retval = (ULONG_PTR)reply->old_instance;
2103 break;
2104 case GWL_USERDATA:
2105 wndPtr->userdata = newval;
2106 retval = (ULONG_PTR)reply->old_user_data;
2107 break;
2111 SERVER_END_REQ;
2112 WIN_ReleasePtr( wndPtr );
2114 if (!ok) return 0;
2116 if (offset == GWL_STYLE && USER_Driver.pSetWindowStyle)
2117 USER_Driver.pSetWindowStyle( hwnd, retval );
2119 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2120 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2123 return retval;
2127 /**********************************************************************
2128 * GetWindowLong (USER.135)
2130 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2132 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
2136 /**********************************************************************
2137 * GetWindowLongA (USER32.@)
2139 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2141 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2145 /**********************************************************************
2146 * GetWindowLongW (USER32.@)
2148 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2150 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2154 /**********************************************************************
2155 * SetWindowLong (USER.136)
2157 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2159 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
2163 /**********************************************************************
2164 * SetWindowLongA (USER32.@)
2166 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2168 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2172 /**********************************************************************
2173 * SetWindowLongW (USER32.@) Set window attribute
2175 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2176 * value in a window's extra memory.
2178 * The _hwnd_ parameter specifies the window. is the handle to a
2179 * window that has extra memory. The _newval_ parameter contains the
2180 * new attribute or extra memory value. If positive, the _offset_
2181 * parameter is the byte-addressed location in the window's extra
2182 * memory to set. If negative, _offset_ specifies the window
2183 * attribute to set, and should be one of the following values:
2185 * GWL_EXSTYLE The window's extended window style
2187 * GWL_STYLE The window's window style.
2189 * GWL_WNDPROC Pointer to the window's window procedure.
2191 * GWL_HINSTANCE The window's pplication instance handle.
2193 * GWL_ID The window's identifier.
2195 * GWL_USERDATA The window's user-specified data.
2197 * If the window is a dialog box, the _offset_ parameter can be one of
2198 * the following values:
2200 * DWL_DLGPROC The address of the window's dialog box procedure.
2202 * DWL_MSGRESULT The return value of a message
2203 * that the dialog box procedure processed.
2205 * DWL_USER Application specific information.
2207 * RETURNS
2209 * If successful, returns the previous value located at _offset_. Otherwise,
2210 * returns 0.
2212 * NOTES
2214 * Extra memory for a window class is specified by a nonzero cbWndExtra
2215 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2216 * time of class creation.
2218 * Using GWL_WNDPROC to set a new window procedure effectively creates
2219 * a window subclass. Use CallWindowProc() in the new windows procedure
2220 * to pass messages to the superclass's window procedure.
2222 * The user data is reserved for use by the application which created
2223 * the window.
2225 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2226 * instead, call the EnableWindow() function to change the window's
2227 * disabled state.
2229 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2230 * SetParent() instead.
2232 * Win95:
2233 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2234 * it sends WM_STYLECHANGING before changing the settings
2235 * and WM_STYLECHANGED afterwards.
2236 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2238 LONG WINAPI SetWindowLongW(
2239 HWND hwnd, /* [in] window to alter */
2240 INT offset, /* [in] offset, in bytes, of location to alter */
2241 LONG newval /* [in] new value of location */
2243 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2247 /*******************************************************************
2248 * GetWindowTextA (USER32.@)
2250 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2252 WCHAR *buffer;
2254 if (WIN_IsCurrentProcess( hwnd ))
2255 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2257 /* when window belongs to other process, don't send a message */
2258 if (nMaxCount <= 0) return 0;
2259 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2260 get_server_window_text( hwnd, buffer, nMaxCount );
2261 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2262 lpString[nMaxCount-1] = 0;
2263 HeapFree( GetProcessHeap(), 0, buffer );
2264 return strlen(lpString);
2268 /*******************************************************************
2269 * InternalGetWindowText (USER32.@)
2271 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2273 WND *win;
2275 if (nMaxCount <= 0) return 0;
2276 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2277 if (win != WND_OTHER_PROCESS)
2279 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2280 else lpString[0] = 0;
2281 WIN_ReleasePtr( win );
2283 else
2285 get_server_window_text( hwnd, lpString, nMaxCount );
2287 return strlenW(lpString);
2291 /*******************************************************************
2292 * GetWindowTextW (USER32.@)
2294 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2296 if (WIN_IsCurrentProcess( hwnd ))
2297 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2299 /* when window belongs to other process, don't send a message */
2300 if (nMaxCount <= 0) return 0;
2301 get_server_window_text( hwnd, lpString, nMaxCount );
2302 return strlenW(lpString);
2306 /*******************************************************************
2307 * SetWindowText (USER32.@)
2308 * SetWindowTextA (USER32.@)
2310 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2312 if (is_broadcast(hwnd))
2314 SetLastError( ERROR_INVALID_PARAMETER );
2315 return FALSE;
2317 if (!WIN_IsCurrentProcess( hwnd ))
2319 FIXME( "cannot set text %s of other process window %p\n", debugstr_a(lpString), hwnd );
2320 SetLastError( ERROR_ACCESS_DENIED );
2321 return FALSE;
2323 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2327 /*******************************************************************
2328 * SetWindowTextW (USER32.@)
2330 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2332 if (is_broadcast(hwnd))
2334 SetLastError( ERROR_INVALID_PARAMETER );
2335 return FALSE;
2337 if (!WIN_IsCurrentProcess( hwnd ))
2339 FIXME( "cannot set text %s of other process window %p\n", debugstr_w(lpString), hwnd );
2340 SetLastError( ERROR_ACCESS_DENIED );
2341 return FALSE;
2343 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2347 /*******************************************************************
2348 * GetWindowTextLengthA (USER32.@)
2350 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2352 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2355 /*******************************************************************
2356 * GetWindowTextLengthW (USER32.@)
2358 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2360 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2364 /*******************************************************************
2365 * IsWindow (USER32.@)
2367 BOOL WINAPI IsWindow( HWND hwnd )
2369 WND *ptr;
2370 BOOL ret;
2372 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2374 if (ptr != WND_OTHER_PROCESS)
2376 WIN_ReleasePtr( ptr );
2377 return TRUE;
2380 /* check other processes */
2381 SERVER_START_REQ( get_window_info )
2383 req->handle = hwnd;
2384 ret = !wine_server_call_err( req );
2386 SERVER_END_REQ;
2387 return ret;
2391 /***********************************************************************
2392 * GetWindowThreadProcessId (USER32.@)
2394 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2396 WND *ptr;
2397 DWORD tid = 0;
2399 if (!(ptr = WIN_GetPtr( hwnd )))
2401 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2402 return 0;
2405 if (ptr != WND_OTHER_PROCESS)
2407 /* got a valid window */
2408 tid = ptr->tid;
2409 if (process) *process = GetCurrentProcessId();
2410 WIN_ReleasePtr( ptr );
2411 return tid;
2414 /* check other processes */
2415 SERVER_START_REQ( get_window_info )
2417 req->handle = hwnd;
2418 if (!wine_server_call_err( req ))
2420 tid = (DWORD)reply->tid;
2421 if (process) *process = (DWORD)reply->pid;
2424 SERVER_END_REQ;
2425 return tid;
2429 /*****************************************************************
2430 * GetParent (USER32.@)
2432 HWND WINAPI GetParent( HWND hwnd )
2434 WND *wndPtr;
2435 HWND retvalue = 0;
2437 if (!(wndPtr = WIN_GetPtr( hwnd )))
2439 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2440 return 0;
2442 if (wndPtr == WND_OTHER_PROCESS)
2444 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2445 if (style & (WS_POPUP | WS_CHILD))
2447 SERVER_START_REQ( get_window_tree )
2449 req->handle = hwnd;
2450 if (!wine_server_call_err( req ))
2452 if (style & WS_POPUP) retvalue = reply->owner;
2453 else if (style & WS_CHILD) retvalue = reply->parent;
2456 SERVER_END_REQ;
2459 else
2461 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2462 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2463 WIN_ReleasePtr( wndPtr );
2465 return retvalue;
2469 /*****************************************************************
2470 * GetAncestor (USER32.@)
2472 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2474 WND *win;
2475 HWND *list, ret = 0;
2477 switch(type)
2479 case GA_PARENT:
2480 if (!(win = WIN_GetPtr( hwnd )))
2482 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2483 return 0;
2485 if (win != WND_OTHER_PROCESS)
2487 ret = win->parent;
2488 WIN_ReleasePtr( win );
2490 else /* need to query the server */
2492 SERVER_START_REQ( get_window_tree )
2494 req->handle = hwnd;
2495 if (!wine_server_call_err( req )) ret = reply->parent;
2497 SERVER_END_REQ;
2499 break;
2501 case GA_ROOT:
2502 if (!(list = WIN_ListParents( hwnd ))) return 0;
2504 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2505 else
2507 int count = 2;
2508 while (list[count]) count++;
2509 ret = list[count - 2]; /* get the one before the desktop */
2511 HeapFree( GetProcessHeap(), 0, list );
2512 break;
2514 case GA_ROOTOWNER:
2515 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2516 for (;;)
2518 HWND parent = GetParent( ret );
2519 if (!parent) break;
2520 ret = parent;
2522 break;
2524 return ret;
2528 /*****************************************************************
2529 * SetParent (USER32.@)
2531 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2533 WND *wndPtr;
2534 HWND retvalue, full_handle;
2535 BOOL was_visible;
2537 if (is_broadcast(hwnd) || is_broadcast(parent))
2539 SetLastError(ERROR_INVALID_PARAMETER);
2540 return 0;
2543 if (!parent) parent = GetDesktopWindow();
2544 else parent = WIN_GetFullHandle( parent );
2546 if (!IsWindow( parent ))
2548 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2549 return 0;
2552 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2553 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2555 hwnd = full_handle;
2557 if (USER_Driver.pSetParent)
2558 return USER_Driver.pSetParent( hwnd, parent );
2560 /* Windows hides the window first, then shows it again
2561 * including the WM_SHOWWINDOW messages and all */
2562 was_visible = ShowWindow( hwnd, SW_HIDE );
2564 if (!IsWindow( parent )) return 0;
2565 if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return 0;
2567 retvalue = wndPtr->parent; /* old parent */
2568 if (parent != retvalue)
2570 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2572 if (parent != GetDesktopWindow()) /* a child window */
2574 if (!(wndPtr->dwStyle & WS_CHILD))
2576 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
2577 if (menu) DestroyMenu( menu );
2581 WIN_ReleasePtr( wndPtr );
2583 /* SetParent additionally needs to make hwnd the topmost window
2584 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2585 WM_WINDOWPOSCHANGED notification messages.
2587 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2588 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2589 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2590 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2591 return retvalue;
2595 /*******************************************************************
2596 * IsChild (USER32.@)
2598 BOOL WINAPI IsChild( HWND parent, HWND child )
2600 HWND *list = WIN_ListParents( child );
2601 int i;
2602 BOOL ret;
2604 if (!list) return FALSE;
2605 parent = WIN_GetFullHandle( parent );
2606 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2607 ret = (list[i] != 0);
2608 HeapFree( GetProcessHeap(), 0, list );
2609 return ret;
2613 /***********************************************************************
2614 * IsWindowVisible (USER32.@)
2616 BOOL WINAPI IsWindowVisible( HWND hwnd )
2618 HWND *list;
2619 BOOL retval;
2620 int i;
2622 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2623 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2624 for (i = 0; list[i]; i++)
2625 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2626 retval = !list[i];
2627 HeapFree( GetProcessHeap(), 0, list );
2628 return retval;
2632 /***********************************************************************
2633 * WIN_IsWindowDrawable
2635 * hwnd is drawable when it is visible, all parents are not
2636 * minimized, and it is itself not minimized unless we are
2637 * trying to draw its default class icon.
2639 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2641 HWND *list;
2642 BOOL retval;
2643 int i;
2644 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2646 if (!(style & WS_VISIBLE)) return FALSE;
2647 if ((style & WS_MINIMIZE) && icon && GetClassLongA( hwnd, GCL_HICON )) return FALSE;
2649 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2650 for (i = 0; list[i]; i++)
2651 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2652 break;
2653 retval = !list[i];
2654 HeapFree( GetProcessHeap(), 0, list );
2655 return retval;
2659 /*******************************************************************
2660 * GetTopWindow (USER32.@)
2662 HWND WINAPI GetTopWindow( HWND hwnd )
2664 if (!hwnd) hwnd = GetDesktopWindow();
2665 return GetWindow( hwnd, GW_CHILD );
2669 /*******************************************************************
2670 * GetWindow (USER32.@)
2672 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2674 HWND retval = 0;
2676 if (rel == GW_OWNER) /* this one may be available locally */
2678 WND *wndPtr = WIN_GetPtr( hwnd );
2679 if (!wndPtr)
2681 SetLastError( ERROR_INVALID_HANDLE );
2682 return 0;
2684 if (wndPtr != WND_OTHER_PROCESS)
2686 retval = wndPtr->owner;
2687 WIN_ReleasePtr( wndPtr );
2688 return retval;
2690 /* else fall through to server call */
2693 SERVER_START_REQ( get_window_tree )
2695 req->handle = hwnd;
2696 if (!wine_server_call_err( req ))
2698 switch(rel)
2700 case GW_HWNDFIRST:
2701 retval = reply->first_sibling;
2702 break;
2703 case GW_HWNDLAST:
2704 retval = reply->last_sibling;
2705 break;
2706 case GW_HWNDNEXT:
2707 retval = reply->next_sibling;
2708 break;
2709 case GW_HWNDPREV:
2710 retval = reply->prev_sibling;
2711 break;
2712 case GW_OWNER:
2713 retval = reply->owner;
2714 break;
2715 case GW_CHILD:
2716 retval = reply->first_child;
2717 break;
2721 SERVER_END_REQ;
2722 return retval;
2726 /***********************************************************************
2727 * WIN_InternalShowOwnedPopups
2729 * Internal version of ShowOwnedPopups; Wine functions should use this
2730 * to avoid interfering with application calls to ShowOwnedPopups
2731 * and to make sure the application can't prevent showing/hiding.
2733 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2737 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2739 int count = 0;
2740 WND *pWnd;
2741 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2743 if (!win_array) return TRUE;
2746 * Show windows Lowest first, Highest last to preserve Z-Order
2748 while (win_array[count]) count++;
2749 while (--count >= 0)
2751 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2752 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2754 if (pWnd->dwStyle & WS_POPUP)
2756 if (fShow)
2758 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2759 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
2762 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2764 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2765 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2768 else
2770 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2771 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2772 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2775 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2777 ShowWindow(pWnd->hwndSelf,SW_HIDE);
2778 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2779 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
2783 WIN_ReleaseWndPtr( pWnd );
2785 HeapFree( GetProcessHeap(), 0, win_array );
2787 return TRUE;
2790 /*******************************************************************
2791 * ShowOwnedPopups (USER32.@)
2793 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2795 int count = 0;
2796 WND *pWnd;
2797 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2799 if (!win_array) return TRUE;
2801 while (win_array[count]) count++;
2802 while (--count >= 0)
2804 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2805 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2807 if (pWnd->dwStyle & WS_POPUP)
2809 if (fShow)
2811 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2813 /* In Windows, ShowOwnedPopups(TRUE) generates
2814 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2815 * regardless of the state of the owner
2817 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2818 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2821 else
2823 if (IsWindowVisible(pWnd->hwndSelf))
2825 /* In Windows, ShowOwnedPopups(FALSE) generates
2826 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2827 * regardless of the state of the owner
2829 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2830 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2834 WIN_ReleaseWndPtr( pWnd );
2836 HeapFree( GetProcessHeap(), 0, win_array );
2837 return TRUE;
2841 /*******************************************************************
2842 * GetLastActivePopup (USER32.@)
2844 HWND WINAPI GetLastActivePopup( HWND hwnd )
2846 HWND retval = hwnd;
2848 SERVER_START_REQ( get_window_info )
2850 req->handle = hwnd;
2851 if (!wine_server_call_err( req )) retval = reply->last_active;
2853 SERVER_END_REQ;
2854 return retval;
2858 /*******************************************************************
2859 * WIN_ListParents
2861 * Build an array of all parents of a given window, starting with
2862 * the immediate parent. The array must be freed with HeapFree.
2863 * Returns NULL if window is a top-level window.
2865 HWND *WIN_ListParents( HWND hwnd )
2867 WND *win;
2868 HWND current, *list;
2869 int pos = 0, size = 16, count = 0;
2871 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2873 current = hwnd;
2874 for (;;)
2876 if (!(win = WIN_GetPtr( current ))) goto empty;
2877 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
2878 list[pos] = win->parent;
2879 WIN_ReleasePtr( win );
2880 if (!(current = list[pos]))
2882 if (!pos) goto empty;
2883 return list;
2885 if (++pos == size - 1)
2887 /* need to grow the list */
2888 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
2889 if (!new_list) goto empty;
2890 list = new_list;
2891 size += 16;
2895 /* at least one parent belongs to another process, have to query the server */
2897 for (;;)
2899 count = 0;
2900 SERVER_START_REQ( get_window_parents )
2902 req->handle = hwnd;
2903 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
2904 if (!wine_server_call( req )) count = reply->count;
2906 SERVER_END_REQ;
2907 if (!count) goto empty;
2908 if (size > count)
2910 list[count] = 0;
2911 return list;
2913 HeapFree( GetProcessHeap(), 0, list );
2914 size = count + 1;
2915 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2918 empty:
2919 HeapFree( GetProcessHeap(), 0, list );
2920 return NULL;
2924 /*******************************************************************
2925 * WIN_ListChildren
2927 * Build an array of the children of a given window. The array must be
2928 * freed with HeapFree. Returns NULL when no windows are found.
2930 HWND *WIN_ListChildren( HWND hwnd )
2932 return list_window_children( hwnd, 0, 0 );
2936 /*******************************************************************
2937 * EnumWindows (USER32.@)
2939 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2941 HWND *list;
2942 BOOL ret = TRUE;
2943 int i, iWndsLocks;
2945 /* We have to build a list of all windows first, to avoid */
2946 /* unpleasant side-effects, for instance if the callback */
2947 /* function changes the Z-order of the windows. */
2949 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2951 /* Now call the callback function for every window */
2953 iWndsLocks = WIN_SuspendWndsLock();
2954 for (i = 0; list[i]; i++)
2956 /* Make sure that the window still exists */
2957 if (!IsWindow( list[i] )) continue;
2958 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2960 WIN_RestoreWndsLock(iWndsLocks);
2961 HeapFree( GetProcessHeap(), 0, list );
2962 return ret;
2966 /**********************************************************************
2967 * EnumThreadWindows (USER32.@)
2969 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2971 HWND *list;
2972 int i, iWndsLocks;
2974 if (!(list = list_window_children( GetDesktopWindow(), 0, id ))) return TRUE;
2976 /* Now call the callback function for every window */
2978 iWndsLocks = WIN_SuspendWndsLock();
2979 for (i = 0; list[i]; i++)
2980 if (!func( list[i], lParam )) break;
2981 WIN_RestoreWndsLock(iWndsLocks);
2982 HeapFree( GetProcessHeap(), 0, list );
2983 return TRUE;
2987 /**********************************************************************
2988 * WIN_EnumChildWindows
2990 * Helper function for EnumChildWindows().
2992 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2994 HWND *childList;
2995 BOOL ret = FALSE;
2997 for ( ; *list; list++)
2999 /* Make sure that the window still exists */
3000 if (!IsWindow( *list )) continue;
3001 /* skip owned windows */
3002 if (GetWindow( *list, GW_OWNER )) continue;
3003 /* Build children list first */
3004 childList = WIN_ListChildren( *list );
3006 ret = func( *list, lParam );
3008 if (childList)
3010 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
3011 HeapFree( GetProcessHeap(), 0, childList );
3013 if (!ret) return FALSE;
3015 return TRUE;
3019 /**********************************************************************
3020 * EnumChildWindows (USER32.@)
3022 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
3024 HWND *list;
3025 int iWndsLocks;
3027 if (!(list = WIN_ListChildren( parent ))) return FALSE;
3028 iWndsLocks = WIN_SuspendWndsLock();
3029 WIN_EnumChildWindows( list, func, lParam );
3030 WIN_RestoreWndsLock(iWndsLocks);
3031 HeapFree( GetProcessHeap(), 0, list );
3032 return TRUE;
3036 /*******************************************************************
3037 * AnyPopup (USER.52)
3039 BOOL16 WINAPI AnyPopup16(void)
3041 return AnyPopup();
3045 /*******************************************************************
3046 * AnyPopup (USER32.@)
3048 BOOL WINAPI AnyPopup(void)
3050 int i;
3051 BOOL retvalue;
3052 HWND *list = WIN_ListChildren( GetDesktopWindow() );
3054 if (!list) return FALSE;
3055 for (i = 0; list[i]; i++)
3057 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
3059 retvalue = (list[i] != 0);
3060 HeapFree( GetProcessHeap(), 0, list );
3061 return retvalue;
3065 /*******************************************************************
3066 * FlashWindow (USER32.@)
3068 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3070 WND *wndPtr = WIN_FindWndPtr(hWnd);
3072 TRACE("%p\n", hWnd);
3074 if (!wndPtr) return FALSE;
3075 hWnd = wndPtr->hwndSelf; /* make it a full handle */
3077 if (wndPtr->dwStyle & WS_MINIMIZE)
3079 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3081 HDC hDC = GetDC(hWnd);
3083 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM)hDC, 0 ))
3084 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
3086 ReleaseDC( hWnd, hDC );
3087 wndPtr->flags |= WIN_NCACTIVATED;
3089 else
3091 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3092 wndPtr->flags &= ~WIN_NCACTIVATED;
3094 WIN_ReleaseWndPtr(wndPtr);
3095 return TRUE;
3097 else
3099 WPARAM16 wparam;
3100 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3101 else wparam = (hWnd == GetForegroundWindow());
3103 WIN_ReleaseWndPtr(wndPtr);
3104 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3105 return wparam;
3109 /*******************************************************************
3110 * FlashWindowEx (USER32.@)
3112 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
3114 FIXME("%p\n", pfwi);
3115 return TRUE;
3118 /*******************************************************************
3119 * GetWindowContextHelpId (USER32.@)
3121 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3123 DWORD retval;
3124 WND *wnd = WIN_FindWndPtr( hwnd );
3125 if (!wnd) return 0;
3126 retval = wnd->helpContext;
3127 WIN_ReleaseWndPtr(wnd);
3128 return retval;
3132 /*******************************************************************
3133 * SetWindowContextHelpId (USER32.@)
3135 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3137 WND *wnd = WIN_FindWndPtr( hwnd );
3138 if (!wnd) return FALSE;
3139 wnd->helpContext = id;
3140 WIN_ReleaseWndPtr(wnd);
3141 return TRUE;
3145 /*******************************************************************
3146 * DragDetect (USER32.@)
3148 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3150 MSG msg;
3151 RECT rect;
3153 rect.left = pt.x - wDragWidth;
3154 rect.right = pt.x + wDragWidth;
3156 rect.top = pt.y - wDragHeight;
3157 rect.bottom = pt.y + wDragHeight;
3159 SetCapture(hWnd);
3161 while(1)
3163 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3165 if( msg.message == WM_LBUTTONUP )
3167 ReleaseCapture();
3168 return 0;
3170 if( msg.message == WM_MOUSEMOVE )
3172 POINT tmp;
3173 tmp.x = LOWORD(msg.lParam);
3174 tmp.y = HIWORD(msg.lParam);
3175 if( !PtInRect( &rect, tmp ))
3177 ReleaseCapture();
3178 return 1;
3182 WaitMessage();
3184 return 0;
3187 /******************************************************************************
3188 * GetWindowModuleFileNameA (USER32.@)
3190 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3192 FIXME("GetWindowModuleFileNameA(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3193 hwnd, lpszFileName, cchFileNameMax);
3194 return 0;
3197 /******************************************************************************
3198 * GetWindowModuleFileNameW (USER32.@)
3200 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3202 FIXME("GetWindowModuleFileNameW(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3203 hwnd, lpszFileName, cchFileNameMax);
3204 return 0;
3207 /******************************************************************************
3208 * GetWindowInfo (USER32.@)
3209 * hwnd: in
3210 * pwi: out.
3211 * MS Documentation mentions that pwi->cbSize must be set to SIZEOF(WINDOWINFO)
3212 * this may be because this structure changed over time. If this is the
3213 * the case, then please: FIXME.
3214 * Using the structure described in MSDN for 98/ME/NT(4.0 SP3)/2000/XP.
3216 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3218 if (!pwi) return FALSE;
3219 if (pwi->cbSize != sizeof(WINDOWINFO))
3221 FIXME("windowinfo->cbSize != sizeof(WINDOWINFO). Please report\n");
3222 return FALSE;
3224 if (!IsWindow(hwnd)) return FALSE;
3226 GetWindowRect(hwnd, &pwi->rcWindow);
3227 GetClientRect(hwnd, &pwi->rcClient);
3228 /* translate to screen coordinates */
3229 MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3231 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3232 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3233 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3235 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3236 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3238 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3239 pwi->wCreatorVersion = 0x0400;
3241 return TRUE;