Move the name directive from the .spec file to the Makefile.
[wine/gsoc_dplay.git] / windows / win.c
blobf84b8dff36488981af68f84dd2c46ac991b95199
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 "wine/server.h"
31 #include "wine/unicode.h"
32 #include "win.h"
33 #include "user.h"
34 #include "dce.h"
35 #include "controls.h"
36 #include "cursoricon.h"
37 #include "hook.h"
38 #include "message.h"
39 #include "queue.h"
40 #include "task.h"
41 #include "winpos.h"
42 #include "winerror.h"
43 #include "stackframe.h"
44 #include "wine/debug.h"
46 WINE_DEFAULT_DEBUG_CHANNEL(win);
47 WINE_DECLARE_DEBUG_CHANNEL(msg);
49 #define NB_USER_HANDLES (LAST_USER_HANDLE - FIRST_USER_HANDLE + 1)
51 /**********************************************************************/
53 /* Desktop window */
54 static WND *pWndDesktop = NULL;
56 static WORD wDragWidth = 4;
57 static WORD wDragHeight= 3;
59 static void *user_handles[NB_USER_HANDLES];
61 /* thread safeness */
62 extern SYSLEVEL USER_SysLevel; /* FIXME */
64 /***********************************************************************
65 * WIN_SuspendWndsLock
67 * Suspend the lock on WND structures.
68 * Returns the number of locks suspended
70 int WIN_SuspendWndsLock( void )
72 int isuspendedLocks = _ConfirmSysLevel( &USER_SysLevel );
73 int count = isuspendedLocks;
75 while ( count-- > 0 )
76 _LeaveSysLevel( &USER_SysLevel );
78 return isuspendedLocks;
81 /***********************************************************************
82 * WIN_RestoreWndsLock
84 * Restore the suspended locks on WND structures
86 void WIN_RestoreWndsLock( int ipreviousLocks )
88 while ( ipreviousLocks-- > 0 )
89 _EnterSysLevel( &USER_SysLevel );
92 /***********************************************************************
93 * create_window_handle
95 * Create a window handle with the server.
97 static WND *create_window_handle( HWND parent, HWND owner, ATOM atom, INT size )
99 BOOL res;
100 user_handle_t handle = 0;
101 WORD index;
102 WND *win = HeapAlloc( GetProcessHeap(), 0, size );
104 if (!win) return NULL;
106 USER_Lock();
108 SERVER_START_REQ( create_window )
110 req->parent = parent;
111 req->owner = owner;
112 req->atom = atom;
113 if ((res = !wine_server_call_err( req ))) handle = reply->handle;
115 SERVER_END_REQ;
117 if (!res)
119 USER_Unlock();
120 HeapFree( GetProcessHeap(), 0, win );
121 return NULL;
123 index = LOWORD(handle) - FIRST_USER_HANDLE;
124 assert( index < NB_USER_HANDLES );
125 user_handles[index] = win;
126 win->hwndSelf = handle;
127 win->dwMagic = WND_MAGIC;
128 win->irefCount = 1;
129 return win;
133 /***********************************************************************
134 * free_window_handle
136 * Free a window handle.
138 static WND *free_window_handle( HWND hwnd )
140 WND *ptr;
141 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
143 if (index >= NB_USER_HANDLES) return NULL;
144 USER_Lock();
145 if ((ptr = user_handles[index]))
147 SERVER_START_REQ( destroy_window )
149 req->handle = hwnd;
150 if (!wine_server_call_err( req ))
151 user_handles[index] = NULL;
152 else
153 ptr = NULL;
155 SERVER_END_REQ;
157 USER_Unlock();
158 if (ptr) HeapFree( GetProcessHeap(), 0, ptr );
159 return ptr;
163 /*******************************************************************
164 * list_window_children
166 * Build an array of the children of a given window. The array must be
167 * freed with HeapFree. Returns NULL when no windows are found.
169 static HWND *list_window_children( HWND hwnd, ATOM atom, DWORD tid )
171 HWND *list;
172 int size = 32;
174 for (;;)
176 int count = 0;
178 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
180 SERVER_START_REQ( get_window_children )
182 req->parent = hwnd;
183 req->atom = atom;
184 req->tid = (void *)tid;
185 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
186 if (!wine_server_call( req )) count = reply->count;
188 SERVER_END_REQ;
189 if (count && count < size)
191 list[count] = 0;
192 return list;
194 HeapFree( GetProcessHeap(), 0, list );
195 if (!count) break;
196 size = count + 1; /* restart with a large enough buffer */
198 return NULL;
202 /*******************************************************************
203 * send_parent_notify
205 static void send_parent_notify( HWND hwnd, UINT msg )
207 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD)) return;
208 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY) return;
209 SendMessageW( GetParent(hwnd), WM_PARENTNOTIFY,
210 MAKEWPARAM( msg, GetWindowLongW( hwnd, GWL_ID )), (LPARAM)hwnd );
214 /*******************************************************************
215 * get_server_window_text
217 * Retrieve the window text from the server.
219 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
221 size_t len = 0;
223 SERVER_START_REQ( get_window_text )
225 req->handle = hwnd;
226 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
227 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
229 SERVER_END_REQ;
230 text[len / sizeof(WCHAR)] = 0;
234 /***********************************************************************
235 * WIN_GetPtr
237 * Return a pointer to the WND structure if local to the process,
238 * or WND_OTHER_PROCESS if handle may be valid in other process.
239 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
241 WND *WIN_GetPtr( HWND hwnd )
243 WND * ptr;
244 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
246 if (index >= NB_USER_HANDLES) return NULL;
248 USER_Lock();
249 if ((ptr = user_handles[index]))
251 if (ptr->dwMagic == WND_MAGIC && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
252 return ptr;
253 ptr = NULL;
255 else ptr = WND_OTHER_PROCESS;
256 USER_Unlock();
257 return ptr;
261 /***********************************************************************
262 * WIN_IsCurrentProcess
264 * Check whether a given window belongs to the current process (and return the full handle).
266 HWND WIN_IsCurrentProcess( HWND hwnd )
268 WND *ptr;
269 HWND ret;
271 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS) return 0;
272 ret = ptr->hwndSelf;
273 WIN_ReleasePtr( ptr );
274 return ret;
278 /***********************************************************************
279 * WIN_IsCurrentThread
281 * Check whether a given window belongs to the current thread (and return the full handle).
283 HWND WIN_IsCurrentThread( HWND hwnd )
285 WND *ptr;
286 HWND ret = 0;
288 if ((ptr = WIN_GetPtr( hwnd )) && ptr != WND_OTHER_PROCESS)
290 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
291 WIN_ReleasePtr( ptr );
293 return ret;
297 /***********************************************************************
298 * WIN_Handle32
300 * Convert a 16-bit window handle to a full 32-bit handle.
302 HWND WIN_Handle32( HWND16 hwnd16 )
304 WND *ptr;
305 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
307 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
308 /* do sign extension for -2 and -3 */
309 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
311 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
313 if (ptr != WND_OTHER_PROCESS)
315 hwnd = ptr->hwndSelf;
316 WIN_ReleasePtr( ptr );
318 else /* may belong to another process */
320 SERVER_START_REQ( get_window_info )
322 req->handle = hwnd;
323 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
325 SERVER_END_REQ;
327 return hwnd;
331 /***********************************************************************
332 * WIN_FindWndPtr
334 * Return a pointer to the WND structure corresponding to a HWND.
336 WND * WIN_FindWndPtr( HWND hwnd )
338 WND * ptr;
340 if (!hwnd) return NULL;
342 if ((ptr = WIN_GetPtr( hwnd )))
344 if (ptr != WND_OTHER_PROCESS)
346 /* increment destruction monitoring */
347 ptr->irefCount++;
348 return ptr;
350 if (IsWindow( hwnd )) /* check other processes */
352 ERR( "window %04x belongs to other process\n", hwnd );
353 /* DbgBreakPoint(); */
356 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
357 return NULL;
361 /***********************************************************************
362 * WIN_ReleaseWndPtr
364 * Release the pointer to the WND structure.
366 void WIN_ReleaseWndPtr(WND *wndPtr)
368 if(!wndPtr) return;
370 /* Decrement destruction monitoring value */
371 wndPtr->irefCount--;
372 /* Check if it's time to release the memory */
373 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
375 /* Release memory */
376 free_window_handle( wndPtr->hwndSelf );
378 else if(wndPtr->irefCount < 0)
380 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
381 ERR("forgot a Lock on %p somewhere\n",wndPtr);
383 /* unlock all WND structures for thread safeness */
384 USER_Unlock();
388 /***********************************************************************
389 * WIN_UnlinkWindow
391 * Remove a window from the siblings linked list.
393 void WIN_UnlinkWindow( HWND hwnd )
395 WIN_LinkWindow( hwnd, 0, 0 );
399 /***********************************************************************
400 * WIN_LinkWindow
402 * Insert a window into the siblings linked list.
403 * The window is inserted after the specified window, which can also
404 * be specified as HWND_TOP or HWND_BOTTOM.
405 * If parent is 0, window is unlinked from the tree.
407 void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
409 WND *wndPtr = WIN_GetPtr( hwnd );
411 if (!wndPtr) return;
412 if (wndPtr == WND_OTHER_PROCESS)
414 if (IsWindow(hwnd)) ERR(" cannot link other process window %x\n", hwnd );
415 return;
418 SERVER_START_REQ( link_window )
420 req->handle = hwnd;
421 req->parent = parent;
422 req->previous = hwndInsertAfter;
423 if (!wine_server_call( req ))
425 if (reply->full_parent && reply->full_parent != wndPtr->parent)
427 wndPtr->owner = 0; /* reset owner when changing parent */
428 wndPtr->parent = reply->full_parent;
433 SERVER_END_REQ;
434 WIN_ReleasePtr( wndPtr );
438 /***********************************************************************
439 * WIN_SetOwner
441 * Change the owner of a window.
443 void WIN_SetOwner( HWND hwnd, HWND owner )
445 WND *win = WIN_GetPtr( hwnd );
447 if (!win) return;
448 if (win == WND_OTHER_PROCESS)
450 if (IsWindow(hwnd)) ERR( "cannot set owner %x on other process window %x\n", owner, hwnd );
451 return;
453 SERVER_START_REQ( set_window_owner )
455 req->handle = hwnd;
456 req->owner = owner;
457 if (!wine_server_call( req )) win->owner = reply->full_owner;
459 SERVER_END_REQ;
460 WIN_ReleasePtr( win );
464 /***********************************************************************
465 * WIN_SetStyle
467 * Change the style of a window.
469 LONG WIN_SetStyle( HWND hwnd, LONG style )
471 BOOL ok;
472 LONG ret = 0;
473 WND *win = WIN_GetPtr( hwnd );
475 if (!win) return 0;
476 if (win == WND_OTHER_PROCESS)
478 if (IsWindow(hwnd))
479 ERR( "cannot set style %lx on other process window %x\n", style, hwnd );
480 return 0;
482 if (style == win->dwStyle)
484 WIN_ReleasePtr( win );
485 return style;
487 SERVER_START_REQ( set_window_info )
489 req->handle = hwnd;
490 req->flags = SET_WIN_STYLE;
491 req->style = style;
492 if ((ok = !wine_server_call( req )))
494 ret = reply->old_style;
495 win->dwStyle = style;
498 SERVER_END_REQ;
499 WIN_ReleasePtr( win );
500 if (ok && USER_Driver.pSetWindowStyle) USER_Driver.pSetWindowStyle( hwnd, ret );
501 return ret;
505 /***********************************************************************
506 * WIN_SetExStyle
508 * Change the extended style of a window.
510 LONG WIN_SetExStyle( HWND hwnd, LONG style )
512 LONG ret = 0;
513 WND *win = WIN_GetPtr( hwnd );
515 if (!win) return 0;
516 if (win == WND_OTHER_PROCESS)
518 if (IsWindow(hwnd))
519 ERR( "cannot set exstyle %lx on other process window %x\n", style, hwnd );
520 return 0;
522 if (style == win->dwExStyle)
524 WIN_ReleasePtr( win );
525 return style;
527 SERVER_START_REQ( set_window_info )
529 req->handle = hwnd;
530 req->flags = SET_WIN_EXSTYLE;
531 req->ex_style = style;
532 if (!wine_server_call( req ))
534 ret = reply->old_ex_style;
535 win->dwExStyle = style;
538 SERVER_END_REQ;
539 WIN_ReleasePtr( win );
540 return ret;
544 /***********************************************************************
545 * WIN_SetRectangles
547 * Set the window and client rectangles.
549 void WIN_SetRectangles( HWND hwnd, const RECT *rectWindow, const RECT *rectClient )
551 WND *win = WIN_GetPtr( hwnd );
552 BOOL ret;
554 if (!win) return;
555 if (win == WND_OTHER_PROCESS)
557 if (IsWindow( hwnd )) ERR( "cannot set rectangles of other process window %x\n", hwnd );
558 return;
560 SERVER_START_REQ( set_window_rectangles )
562 req->handle = hwnd;
563 req->window.left = rectWindow->left;
564 req->window.top = rectWindow->top;
565 req->window.right = rectWindow->right;
566 req->window.bottom = rectWindow->bottom;
567 req->client.left = rectClient->left;
568 req->client.top = rectClient->top;
569 req->client.right = rectClient->right;
570 req->client.bottom = rectClient->bottom;
571 ret = !wine_server_call( req );
573 SERVER_END_REQ;
574 if (ret)
576 win->rectWindow = *rectWindow;
577 win->rectClient = *rectClient;
579 TRACE( "win %x window (%d,%d)-(%d,%d) client (%d,%d)-(%d,%d)\n", hwnd,
580 rectWindow->left, rectWindow->top, rectWindow->right, rectWindow->bottom,
581 rectClient->left, rectClient->top, rectClient->right, rectClient->bottom );
583 WIN_ReleasePtr( win );
587 /***********************************************************************
588 * WIN_GetRectangles
590 * Get the window and client rectangles.
592 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
594 WND *win = WIN_GetPtr( hwnd );
595 BOOL ret = TRUE;
597 if (!win) return FALSE;
598 if (win == WND_OTHER_PROCESS)
600 SERVER_START_REQ( get_window_rectangles )
602 req->handle = hwnd;
603 if ((ret = !wine_server_call( req )))
605 if (rectWindow)
607 rectWindow->left = reply->window.left;
608 rectWindow->top = reply->window.top;
609 rectWindow->right = reply->window.right;
610 rectWindow->bottom = reply->window.bottom;
612 if (rectClient)
614 rectClient->left = reply->client.left;
615 rectClient->top = reply->client.top;
616 rectClient->right = reply->client.right;
617 rectClient->bottom = reply->client.bottom;
621 SERVER_END_REQ;
623 else
625 if (rectWindow) *rectWindow = win->rectWindow;
626 if (rectClient) *rectClient = win->rectClient;
627 WIN_ReleasePtr( win );
629 return ret;
633 /***********************************************************************
634 * WIN_DestroyWindow
636 * Destroy storage associated to a window. "Internals" p.358
638 LRESULT WIN_DestroyWindow( HWND hwnd )
640 WND *wndPtr;
641 HWND *list;
643 TRACE("%04x\n", hwnd );
645 if (!(hwnd = WIN_IsCurrentThread( hwnd )))
647 ERR( "window doesn't belong to current thread\n" );
648 return 0;
651 /* free child windows */
652 if ((list = WIN_ListChildren( hwnd )))
654 int i;
655 for (i = 0; list[i]; i++)
657 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
658 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
660 HeapFree( GetProcessHeap(), 0, list );
664 * Clear the update region to make sure no WM_PAINT messages will be
665 * generated for this window while processing the WM_NCDESTROY.
667 RedrawWindow( hwnd, NULL, 0,
668 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
671 * Send the WM_NCDESTROY to the window being destroyed.
673 SendMessageA( hwnd, WM_NCDESTROY, 0, 0);
675 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
677 WINPOS_CheckInternalPos( hwnd );
678 if( hwnd == GetCapture()) ReleaseCapture();
680 /* free resources associated with the window */
682 TIMER_RemoveWindowTimers( hwnd );
684 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
685 wndPtr->hmemTaskQ = 0;
687 if (!(wndPtr->dwStyle & WS_CHILD))
689 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
690 if (menu) DestroyMenu( menu );
692 if (wndPtr->hSysMenu)
694 DestroyMenu( wndPtr->hSysMenu );
695 wndPtr->hSysMenu = 0;
697 USER_Driver.pDestroyWindow( hwnd );
698 DCE_FreeWindowDCE( hwnd ); /* Always do this to catch orphaned DCs */
699 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
700 CLASS_RemoveWindow( wndPtr->class );
701 wndPtr->class = NULL;
702 wndPtr->dwMagic = 0; /* Mark it as invalid */
703 WIN_ReleaseWndPtr( wndPtr );
704 return 0;
707 /***********************************************************************
708 * WIN_DestroyThreadWindows
710 * Destroy all children of 'wnd' owned by the current thread.
711 * Return TRUE if something was done.
713 void WIN_DestroyThreadWindows( HWND hwnd )
715 HWND *list;
716 int i;
718 if (!(list = WIN_ListChildren( hwnd ))) return;
719 for (i = 0; list[i]; i++)
721 if (WIN_IsCurrentThread( list[i] ))
722 DestroyWindow( list[i] );
723 else
724 WIN_DestroyThreadWindows( list[i] );
726 HeapFree( GetProcessHeap(), 0, list );
729 /***********************************************************************
730 * WIN_CreateDesktopWindow
732 * Create the desktop window.
734 BOOL WIN_CreateDesktopWindow(void)
736 struct tagCLASS *class;
737 HWND hwndDesktop;
738 INT wndExtra;
739 DWORD clsStyle;
740 WNDPROC winproc;
741 DCE *dce;
742 CREATESTRUCTA cs;
743 RECT rect;
745 TRACE("Creating desktop window\n");
747 if (!WINPOS_CreateInternalPosAtom() ||
748 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
749 &wndExtra, &winproc, &clsStyle, &dce )))
750 return FALSE;
752 pWndDesktop = create_window_handle( 0, 0, LOWORD(DESKTOP_CLASS_ATOM),
753 sizeof(WND) + wndExtra - sizeof(pWndDesktop->wExtra) );
754 if (!pWndDesktop) return FALSE;
755 hwndDesktop = pWndDesktop->hwndSelf;
757 pWndDesktop->tid = 0; /* nobody owns the desktop */
758 pWndDesktop->parent = 0;
759 pWndDesktop->owner = 0;
760 pWndDesktop->class = class;
761 pWndDesktop->hInstance = 0;
762 pWndDesktop->text = NULL;
763 pWndDesktop->hmemTaskQ = 0;
764 pWndDesktop->hrgnUpdate = 0;
765 pWndDesktop->hwndLastActive = hwndDesktop;
766 pWndDesktop->dwStyle = 0;
767 pWndDesktop->dwExStyle = 0;
768 pWndDesktop->clsStyle = clsStyle;
769 pWndDesktop->dce = NULL;
770 pWndDesktop->pVScroll = NULL;
771 pWndDesktop->pHScroll = NULL;
772 pWndDesktop->wIDmenu = 0;
773 pWndDesktop->helpContext = 0;
774 pWndDesktop->flags = 0;
775 pWndDesktop->hSysMenu = 0;
776 pWndDesktop->userdata = 0;
777 pWndDesktop->winproc = winproc;
778 pWndDesktop->cbWndExtra = wndExtra;
780 cs.lpCreateParams = NULL;
781 cs.hInstance = 0;
782 cs.hMenu = 0;
783 cs.hwndParent = 0;
784 cs.x = 0;
785 cs.y = 0;
786 cs.cx = GetSystemMetrics( SM_CXSCREEN );
787 cs.cy = GetSystemMetrics( SM_CYSCREEN );
788 cs.style = pWndDesktop->dwStyle;
789 cs.dwExStyle = pWndDesktop->dwExStyle;
790 cs.lpszName = NULL;
791 cs.lpszClass = DESKTOP_CLASS_ATOM;
793 SetRect( &rect, 0, 0, cs.cx, cs.cy );
794 WIN_SetRectangles( hwndDesktop, &rect, &rect );
795 WIN_SetStyle( hwndDesktop, WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS );
797 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE ))
799 WIN_ReleaseWndPtr( pWndDesktop );
800 return FALSE;
803 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
804 WIN_ReleaseWndPtr( pWndDesktop );
805 return TRUE;
809 /***********************************************************************
810 * WIN_FixCoordinates
812 * Fix the coordinates - Helper for WIN_CreateWindowEx.
813 * returns default show mode in sw.
814 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
816 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
818 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
819 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
821 if (cs->style & (WS_CHILD | WS_POPUP))
823 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
824 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
826 else /* overlapped window */
828 STARTUPINFOA info;
830 GetStartupInfoA( &info );
832 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
834 /* Never believe Microsoft's documentation... CreateWindowEx doc says
835 * that if an overlapped window is created with WS_VISIBLE style bit
836 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
837 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
838 * reveals that
840 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
841 * 2) it does not ignore the y parameter as the docs claim; instead, it
842 * uses it as second parameter to ShowWindow() unless y is either
843 * CW_USEDEFAULT or CW_USEDEFAULT16.
845 * The fact that we didn't do 2) caused bogus windows pop up when wine
846 * was running apps that were using this obscure feature. Example -
847 * calc.exe that comes with Win98 (only Win98, it's different from
848 * the one that comes with Win95 and NT)
850 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
851 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
852 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
855 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
857 if (info.dwFlags & STARTF_USESIZE)
859 cs->cx = info.dwXSize;
860 cs->cy = info.dwYSize;
862 else /* if no other hint from the app, pick 3/4 of the screen real estate */
864 RECT r;
865 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
866 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
867 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
872 else
874 /* neither x nor cx are default. Check the y values .
875 * In the trace we see Outlook and Outlook Express using
876 * cy set to CW_USEDEFAULT when opening the address book.
878 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16) {
879 RECT r;
880 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
881 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
882 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
887 /***********************************************************************
888 * dump_window_styles
890 static void dump_window_styles( DWORD style, DWORD exstyle )
892 TRACE( "style:" );
893 if(style & WS_POPUP) DPRINTF(" WS_POPUP");
894 if(style & WS_CHILD) DPRINTF(" WS_CHILD");
895 if(style & WS_MINIMIZE) DPRINTF(" WS_MINIMIZE");
896 if(style & WS_VISIBLE) DPRINTF(" WS_VISIBLE");
897 if(style & WS_DISABLED) DPRINTF(" WS_DISABLED");
898 if(style & WS_CLIPSIBLINGS) DPRINTF(" WS_CLIPSIBLINGS");
899 if(style & WS_CLIPCHILDREN) DPRINTF(" WS_CLIPCHILDREN");
900 if(style & WS_MAXIMIZE) DPRINTF(" WS_MAXIMIZE");
901 if((style & WS_CAPTION) == WS_CAPTION) DPRINTF(" WS_CAPTION");
902 else
904 if(style & WS_BORDER) DPRINTF(" WS_BORDER");
905 if(style & WS_DLGFRAME) DPRINTF(" WS_DLGFRAME");
907 if(style & WS_VSCROLL) DPRINTF(" WS_VSCROLL");
908 if(style & WS_HSCROLL) DPRINTF(" WS_HSCROLL");
909 if(style & WS_SYSMENU) DPRINTF(" WS_SYSMENU");
910 if(style & WS_THICKFRAME) DPRINTF(" WS_THICKFRAME");
911 if(style & WS_GROUP) DPRINTF(" WS_GROUP");
912 if(style & WS_TABSTOP) DPRINTF(" WS_TABSTOP");
913 if(style & WS_MINIMIZEBOX) DPRINTF(" WS_MINIMIZEBOX");
914 if(style & WS_MAXIMIZEBOX) DPRINTF(" WS_MAXIMIZEBOX");
916 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
917 #define DUMPED_STYLES \
918 (WS_POPUP | \
919 WS_CHILD | \
920 WS_MINIMIZE | \
921 WS_VISIBLE | \
922 WS_DISABLED | \
923 WS_CLIPSIBLINGS | \
924 WS_CLIPCHILDREN | \
925 WS_MAXIMIZE | \
926 WS_BORDER | \
927 WS_DLGFRAME | \
928 WS_VSCROLL | \
929 WS_HSCROLL | \
930 WS_SYSMENU | \
931 WS_THICKFRAME | \
932 WS_GROUP | \
933 WS_TABSTOP | \
934 WS_MINIMIZEBOX | \
935 WS_MAXIMIZEBOX)
937 if(style & ~DUMPED_STYLES) DPRINTF(" %08lx", style & ~DUMPED_STYLES);
938 DPRINTF("\n");
939 #undef DUMPED_STYLES
941 TRACE( "exstyle:" );
942 if(exstyle & WS_EX_DLGMODALFRAME) DPRINTF(" WS_EX_DLGMODALFRAME");
943 if(exstyle & WS_EX_DRAGDETECT) DPRINTF(" WS_EX_DRAGDETECT");
944 if(exstyle & WS_EX_NOPARENTNOTIFY) DPRINTF(" WS_EX_NOPARENTNOTIFY");
945 if(exstyle & WS_EX_TOPMOST) DPRINTF(" WS_EX_TOPMOST");
946 if(exstyle & WS_EX_ACCEPTFILES) DPRINTF(" WS_EX_ACCEPTFILES");
947 if(exstyle & WS_EX_TRANSPARENT) DPRINTF(" WS_EX_TRANSPARENT");
948 if(exstyle & WS_EX_MDICHILD) DPRINTF(" WS_EX_MDICHILD");
949 if(exstyle & WS_EX_TOOLWINDOW) DPRINTF(" WS_EX_TOOLWINDOW");
950 if(exstyle & WS_EX_WINDOWEDGE) DPRINTF(" WS_EX_WINDOWEDGE");
951 if(exstyle & WS_EX_CLIENTEDGE) DPRINTF(" WS_EX_CLIENTEDGE");
952 if(exstyle & WS_EX_CONTEXTHELP) DPRINTF(" WS_EX_CONTEXTHELP");
953 if(exstyle & WS_EX_RIGHT) DPRINTF(" WS_EX_RIGHT");
954 if(exstyle & WS_EX_RTLREADING) DPRINTF(" WS_EX_RTLREADING");
955 if(exstyle & WS_EX_LEFTSCROLLBAR) DPRINTF(" WS_EX_LEFTSCROLLBAR");
956 if(exstyle & WS_EX_CONTROLPARENT) DPRINTF(" WS_EX_CONTROLPARENT");
957 if(exstyle & WS_EX_STATICEDGE) DPRINTF(" WS_EX_STATICEDGE");
958 if(exstyle & WS_EX_APPWINDOW) DPRINTF(" WS_EX_APPWINDOW");
959 if(exstyle & WS_EX_LAYERED) DPRINTF(" WS_EX_LAYERED");
961 #define DUMPED_EX_STYLES \
962 (WS_EX_DLGMODALFRAME | \
963 WS_EX_DRAGDETECT | \
964 WS_EX_NOPARENTNOTIFY | \
965 WS_EX_TOPMOST | \
966 WS_EX_ACCEPTFILES | \
967 WS_EX_TRANSPARENT | \
968 WS_EX_MDICHILD | \
969 WS_EX_TOOLWINDOW | \
970 WS_EX_WINDOWEDGE | \
971 WS_EX_CLIENTEDGE | \
972 WS_EX_CONTEXTHELP | \
973 WS_EX_RIGHT | \
974 WS_EX_RTLREADING | \
975 WS_EX_LEFTSCROLLBAR | \
976 WS_EX_CONTROLPARENT | \
977 WS_EX_STATICEDGE | \
978 WS_EX_APPWINDOW | \
979 WS_EX_LAYERED)
981 if(exstyle & ~DUMPED_EX_STYLES) DPRINTF(" %08lx", exstyle & ~DUMPED_EX_STYLES);
982 DPRINTF("\n");
983 #undef DUMPED_EX_STYLES
987 /***********************************************************************
988 * WIN_CreateWindowEx
990 * Implementation of CreateWindowEx().
992 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
993 WINDOWPROCTYPE type )
995 INT sw = SW_SHOW;
996 struct tagCLASS *classPtr;
997 WND *wndPtr;
998 HWND hwnd, parent, owner;
999 INT wndExtra;
1000 DWORD clsStyle;
1001 WNDPROC winproc;
1002 DCE *dce;
1003 BOOL unicode = (type == WIN_PROC_32W);
1005 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%04x menu=%04x inst=%08x params=%p\n",
1006 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
1007 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszClass) : debugstr_a(cs->lpszClass),
1008 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
1009 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
1011 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
1013 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
1014 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
1016 /* Find the parent window */
1018 parent = GetDesktopWindow();
1019 owner = 0;
1021 if (cs->hwndParent == HWND_MESSAGE)
1023 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
1024 * message window (style: WS_POPUP|WS_DISABLED)
1026 FIXME("Parent is HWND_MESSAGE\n");
1028 else if (cs->hwndParent)
1030 /* Make sure parent is valid */
1031 if (!IsWindow( cs->hwndParent ))
1033 WARN("Bad parent %04x\n", cs->hwndParent );
1034 return 0;
1036 if (cs->style & WS_CHILD) parent = WIN_GetFullHandle(cs->hwndParent);
1037 else owner = GetAncestor( cs->hwndParent, GA_ROOT );
1039 else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP))
1041 WARN("No parent for child window\n" );
1042 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1045 /* Find the window class */
1046 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
1047 &wndExtra, &winproc, &clsStyle, &dce )))
1049 WARN("Bad class '%s'\n", cs->lpszClass );
1050 return 0;
1053 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
1055 /* Correct the window style - stage 1
1057 * These are patches that appear to affect both the style loaded into the
1058 * WIN structure and passed in the CreateStruct to the WM_CREATE etc.
1060 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1061 * why does the user get to set it?
1064 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
1065 * tested for WS_POPUP
1067 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
1068 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
1069 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
1070 cs->dwExStyle |= WS_EX_WINDOWEDGE;
1071 else
1072 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
1074 /* Create the window structure */
1076 if (!(wndPtr = create_window_handle( parent, owner, classAtom,
1077 sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
1079 TRACE("out of memory\n" );
1080 return 0;
1082 hwnd = wndPtr->hwndSelf;
1084 /* Fill the window structure */
1086 wndPtr->tid = GetCurrentThreadId();
1087 wndPtr->owner = owner;
1088 wndPtr->parent = parent;
1089 wndPtr->class = classPtr;
1090 wndPtr->winproc = winproc;
1091 wndPtr->hInstance = cs->hInstance;
1092 wndPtr->text = NULL;
1093 wndPtr->hmemTaskQ = InitThreadInput16( 0, 0 );
1094 wndPtr->hrgnUpdate = 0;
1095 wndPtr->hrgnWnd = 0;
1096 wndPtr->hwndLastActive = hwnd;
1097 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1098 wndPtr->dwExStyle = cs->dwExStyle;
1099 wndPtr->clsStyle = clsStyle;
1100 wndPtr->wIDmenu = 0;
1101 wndPtr->helpContext = 0;
1102 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
1103 wndPtr->pVScroll = NULL;
1104 wndPtr->pHScroll = NULL;
1105 wndPtr->userdata = 0;
1106 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
1107 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
1108 wndPtr->cbWndExtra = wndExtra;
1110 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
1112 /* Correct the window style - stage 2 */
1114 if (!(cs->style & WS_CHILD))
1116 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1117 if (!(cs->style & WS_POPUP))
1119 wndPtr->dwStyle |= WS_CAPTION;
1120 wndPtr->flags |= WIN_NEED_SIZE;
1123 SERVER_START_REQ( set_window_info )
1125 req->handle = hwnd;
1126 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE;
1127 req->style = wndPtr->dwStyle;
1128 req->ex_style = wndPtr->dwExStyle;
1129 req->instance = (void *)wndPtr->hInstance;
1130 wine_server_call( req );
1132 SERVER_END_REQ;
1134 /* Get class or window DC if needed */
1136 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
1137 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
1138 else wndPtr->dce = NULL;
1140 /* Set the window menu */
1142 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
1144 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
1145 else
1147 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
1148 if (menuName)
1150 if (HIWORD(cs->hInstance))
1151 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1152 else
1153 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
1155 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
1159 else SetWindowLongW( hwnd, GWL_ID, (UINT)cs->hMenu );
1160 WIN_ReleaseWndPtr( wndPtr );
1162 if (!USER_Driver.pCreateWindow( hwnd, cs, unicode))
1164 WIN_DestroyWindow( hwnd );
1165 return 0;
1168 /* Notify the parent window only */
1170 send_parent_notify( hwnd, WM_CREATE );
1171 if (!IsWindow( hwnd )) return 0;
1173 if (cs->style & WS_VISIBLE)
1175 /* in case WS_VISIBLE got set in the meantime */
1176 if (!(wndPtr = WIN_GetPtr( hwnd ))) return 0;
1177 WIN_SetStyle( hwnd, wndPtr->dwStyle & ~WS_VISIBLE );
1178 WIN_ReleasePtr( wndPtr );
1179 ShowWindow( hwnd, sw );
1182 /* Call WH_SHELL hook */
1184 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1185 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0 );
1187 TRACE("created window %04x\n", hwnd);
1188 return hwnd;
1192 /***********************************************************************
1193 * CreateWindow (USER.41)
1195 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1196 DWORD style, INT16 x, INT16 y, INT16 width,
1197 INT16 height, HWND16 parent, HMENU16 menu,
1198 HINSTANCE16 instance, LPVOID data )
1200 return CreateWindowEx16( 0, className, windowName, style,
1201 x, y, width, height, parent, menu, instance, data );
1205 /***********************************************************************
1206 * CreateWindowEx (USER.452)
1208 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1209 LPCSTR windowName, DWORD style, INT16 x,
1210 INT16 y, INT16 width, INT16 height,
1211 HWND16 parent, HMENU16 menu,
1212 HINSTANCE16 instance, LPVOID data )
1214 ATOM classAtom;
1215 CREATESTRUCTA cs;
1216 char buffer[256];
1218 /* Find the class atom */
1220 if (HIWORD(className))
1222 if (!(classAtom = GlobalFindAtomA( className )))
1224 ERR( "bad class name %s\n", debugstr_a(className) );
1225 return 0;
1228 else
1230 classAtom = LOWORD(className);
1231 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1233 ERR( "bad atom %x\n", classAtom);
1234 return 0;
1236 className = buffer;
1239 /* Fix the coordinates */
1241 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1242 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1243 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1244 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1246 /* Create the window */
1248 cs.lpCreateParams = data;
1249 cs.hInstance = (HINSTANCE)instance;
1250 cs.hMenu = (HMENU)menu;
1251 cs.hwndParent = WIN_Handle32( parent );
1252 cs.style = style;
1253 cs.lpszName = windowName;
1254 cs.lpszClass = className;
1255 cs.dwExStyle = exStyle;
1257 return HWND_16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
1261 /***********************************************************************
1262 * CreateWindowExA (USER32.@)
1264 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1265 LPCSTR windowName, DWORD style, INT x,
1266 INT y, INT width, INT height,
1267 HWND parent, HMENU menu,
1268 HINSTANCE instance, LPVOID data )
1270 ATOM classAtom;
1271 CREATESTRUCTA cs;
1272 char buffer[256];
1274 if(!instance)
1275 instance=GetModuleHandleA(NULL);
1277 if(exStyle & WS_EX_MDICHILD)
1278 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1280 /* Find the class atom */
1282 if (HIWORD(className))
1284 if (!(classAtom = GlobalFindAtomA( className )))
1286 ERR( "bad class name %s\n", debugstr_a(className) );
1287 return 0;
1290 else
1292 classAtom = LOWORD(className);
1293 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1295 ERR( "bad atom %x\n", classAtom);
1296 return 0;
1298 className = buffer;
1301 /* Create the window */
1303 cs.lpCreateParams = data;
1304 cs.hInstance = instance;
1305 cs.hMenu = menu;
1306 cs.hwndParent = parent;
1307 cs.x = x;
1308 cs.y = y;
1309 cs.cx = width;
1310 cs.cy = height;
1311 cs.style = style;
1312 cs.lpszName = windowName;
1313 cs.lpszClass = className;
1314 cs.dwExStyle = exStyle;
1316 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1320 /***********************************************************************
1321 * CreateWindowExW (USER32.@)
1323 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1324 LPCWSTR windowName, DWORD style, INT x,
1325 INT y, INT width, INT height,
1326 HWND parent, HMENU menu,
1327 HINSTANCE instance, LPVOID data )
1329 ATOM classAtom;
1330 CREATESTRUCTW cs;
1331 WCHAR buffer[256];
1333 if(!instance)
1334 instance=GetModuleHandleA(NULL);
1336 if(exStyle & WS_EX_MDICHILD)
1337 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1339 /* Find the class atom */
1341 if (HIWORD(className))
1343 if (!(classAtom = GlobalFindAtomW( className )))
1345 ERR( "bad class name %s\n", debugstr_w(className) );
1346 return 0;
1349 else
1351 classAtom = LOWORD(className);
1352 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1354 ERR( "bad atom %x\n", classAtom);
1355 return 0;
1357 className = buffer;
1360 /* Create the window */
1362 cs.lpCreateParams = data;
1363 cs.hInstance = instance;
1364 cs.hMenu = menu;
1365 cs.hwndParent = parent;
1366 cs.x = x;
1367 cs.y = y;
1368 cs.cx = width;
1369 cs.cy = height;
1370 cs.style = style;
1371 cs.lpszName = windowName;
1372 cs.lpszClass = className;
1373 cs.dwExStyle = exStyle;
1375 /* Note: we rely on the fact that CREATESTRUCTA and */
1376 /* CREATESTRUCTW have the same layout. */
1377 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1381 /***********************************************************************
1382 * WIN_SendDestroyMsg
1384 static void WIN_SendDestroyMsg( HWND hwnd )
1386 if( CARET_GetHwnd() == hwnd) DestroyCaret();
1387 if (USER_Driver.pResetSelectionOwner)
1388 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1391 * Send the WM_DESTROY to the window.
1393 SendMessageA( hwnd, WM_DESTROY, 0, 0);
1396 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1397 * make sure that the window still exists when we come back.
1399 if (IsWindow(hwnd))
1401 HWND* pWndArray;
1402 int i;
1404 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1406 /* start from the end (FIXME: is this needed?) */
1407 for (i = 0; pWndArray[i]; i++) ;
1409 while (--i >= 0)
1411 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1413 HeapFree( GetProcessHeap(), 0, pWndArray );
1415 else
1416 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1420 /***********************************************************************
1421 * DestroyWindow (USER32.@)
1423 BOOL WINAPI DestroyWindow( HWND hwnd )
1425 BOOL is_child;
1426 HWND h;
1428 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1430 SetLastError( ERROR_ACCESS_DENIED );
1431 return FALSE;
1434 TRACE("(%04x)\n", hwnd);
1436 /* Look whether the focus is within the tree of windows we will
1437 * be destroying.
1439 h = GetFocus();
1440 if (h == hwnd || IsChild( hwnd, h ))
1442 HWND parent = GetAncestor( hwnd, GA_PARENT );
1443 if (parent == GetDesktopWindow()) parent = 0;
1444 SetFocus( parent );
1447 /* Call hooks */
1449 if( HOOK_CallHooksA( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0L) ) return FALSE;
1451 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1453 if (is_child)
1455 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1456 send_parent_notify( hwnd, WM_DESTROY );
1458 else if (!GetWindow( hwnd, GW_OWNER ))
1460 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L );
1461 /* FIXME: clean up palette - see "Internals" p.352 */
1464 if (!IsWindow(hwnd)) return TRUE;
1466 if (USER_Driver.pResetSelectionOwner)
1467 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1469 /* Hide the window */
1471 ShowWindow( hwnd, SW_HIDE );
1472 if (!IsWindow(hwnd)) return TRUE;
1474 /* Recursively destroy owned windows */
1476 if (!is_child)
1478 HWND owner;
1480 for (;;)
1482 int i, got_one = 0;
1483 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1484 if (list)
1486 for (i = 0; list[i]; i++)
1488 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1489 if (WIN_IsCurrentThread( list[i] ))
1491 DestroyWindow( list[i] );
1492 got_one = 1;
1493 continue;
1495 WIN_SetOwner( list[i], 0 );
1497 HeapFree( GetProcessHeap(), 0, list );
1499 if (!got_one) break;
1502 WINPOS_ActivateOtherWindow( hwnd );
1504 if ((owner = GetWindow( hwnd, GW_OWNER )))
1506 WND *ptr = WIN_FindWndPtr( owner );
1507 if (ptr)
1509 if (ptr->hwndLastActive == hwnd) ptr->hwndLastActive = owner;
1510 WIN_ReleaseWndPtr( ptr );
1515 /* Send destroy messages */
1517 WIN_SendDestroyMsg( hwnd );
1518 if (!IsWindow( hwnd )) return TRUE;
1520 /* Unlink now so we won't bother with the children later on */
1522 WIN_UnlinkWindow( hwnd );
1524 /* Destroy the window storage */
1526 WIN_DestroyWindow( hwnd );
1527 return TRUE;
1531 /***********************************************************************
1532 * CloseWindow (USER32.@)
1534 BOOL WINAPI CloseWindow( HWND hwnd )
1536 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1537 ShowWindow( hwnd, SW_MINIMIZE );
1538 return TRUE;
1542 /***********************************************************************
1543 * OpenIcon (USER32.@)
1545 BOOL WINAPI OpenIcon( HWND hwnd )
1547 if (!IsIconic( hwnd )) return FALSE;
1548 ShowWindow( hwnd, SW_SHOWNORMAL );
1549 return TRUE;
1553 /***********************************************************************
1554 * WIN_FindWindow
1556 * Implementation of FindWindow() and FindWindowEx().
1558 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1560 HWND *list = NULL;
1561 HWND retvalue = 0;
1562 int i = 0, len = 0;
1563 WCHAR *buffer = NULL;
1565 if (!parent) parent = GetDesktopWindow();
1566 if (title)
1568 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1569 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1572 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1574 if (child)
1576 child = WIN_GetFullHandle( child );
1577 while (list[i] && list[i] != child) i++;
1578 if (!list[i]) goto done;
1579 i++; /* start from next window */
1582 if (title)
1584 while (list[i])
1586 if (GetWindowTextW( list[i], buffer, len ) && !strcmpiW( buffer, title )) break;
1587 i++;
1590 retvalue = list[i];
1592 done:
1593 if (list) HeapFree( GetProcessHeap(), 0, list );
1594 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1595 return retvalue;
1600 /***********************************************************************
1601 * FindWindowA (USER32.@)
1603 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1605 HWND ret = FindWindowExA( 0, 0, className, title );
1606 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1607 return ret;
1611 /***********************************************************************
1612 * FindWindowExA (USER32.@)
1614 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1615 LPCSTR className, LPCSTR title )
1617 ATOM atom = 0;
1618 LPWSTR buffer;
1619 HWND hwnd;
1620 INT len;
1622 if (className)
1624 /* If the atom doesn't exist, then no class */
1625 /* with this name exists either. */
1626 if (!(atom = GlobalFindAtomA( className )))
1628 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1629 return 0;
1632 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
1634 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1635 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1636 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
1637 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1638 HeapFree( GetProcessHeap(), 0, buffer );
1639 return hwnd;
1643 /***********************************************************************
1644 * FindWindowExW (USER32.@)
1646 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1647 LPCWSTR className, LPCWSTR title )
1649 ATOM atom = 0;
1651 if (className)
1653 /* If the atom doesn't exist, then no class */
1654 /* with this name exists either. */
1655 if (!(atom = GlobalFindAtomW( className )))
1657 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1658 return 0;
1661 return WIN_FindWindow( parent, child, atom, title );
1665 /***********************************************************************
1666 * FindWindowW (USER32.@)
1668 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1670 return FindWindowExW( 0, 0, className, title );
1674 /**********************************************************************
1675 * GetDesktopWindow (USER32.@)
1677 HWND WINAPI GetDesktopWindow(void)
1679 if (pWndDesktop) return pWndDesktop->hwndSelf;
1680 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" );
1681 ExitProcess(1);
1682 return 0;
1686 /*******************************************************************
1687 * EnableWindow (USER32.@)
1689 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1691 WND *wndPtr;
1692 BOOL retvalue;
1693 LONG style;
1694 HWND full_handle;
1696 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1697 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1699 hwnd = full_handle;
1701 TRACE("( %x, %d )\n", hwnd, enable);
1703 if (!(wndPtr = WIN_GetPtr( hwnd ))) return FALSE;
1704 style = wndPtr->dwStyle;
1705 retvalue = ((style & WS_DISABLED) != 0);
1706 WIN_ReleasePtr( wndPtr );
1708 if (enable && retvalue)
1710 WIN_SetStyle( hwnd, style & ~WS_DISABLED );
1711 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1713 else if (!enable && !retvalue)
1715 SendMessageA( hwnd, WM_CANCELMODE, 0, 0);
1717 WIN_SetStyle( hwnd, style | WS_DISABLED );
1719 if (hwnd == GetFocus() || IsChild(hwnd, GetFocus()))
1720 SetFocus( 0 ); /* A disabled window can't have the focus */
1722 if (hwnd == GetCapture() || IsChild(hwnd, GetCapture()))
1723 ReleaseCapture(); /* A disabled window can't capture the mouse */
1725 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1727 return retvalue;
1731 /***********************************************************************
1732 * IsWindowEnabled (USER32.@)
1734 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1736 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1740 /***********************************************************************
1741 * IsWindowUnicode (USER32.@)
1743 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1745 WND * wndPtr;
1746 BOOL retvalue;
1748 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1749 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1750 WIN_ReleaseWndPtr(wndPtr);
1751 return retvalue;
1755 /**********************************************************************
1756 * GetWindowWord (USER32.@)
1758 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1760 if (offset >= 0)
1762 WORD retvalue = 0;
1763 WND *wndPtr = WIN_GetPtr( hwnd );
1764 if (!wndPtr)
1766 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1767 return 0;
1769 if (wndPtr == WND_OTHER_PROCESS)
1771 if (IsWindow( hwnd ))
1772 FIXME( "(%d) not supported yet on other process window %x\n", offset, hwnd );
1773 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1774 return 0;
1776 if (offset > wndPtr->cbWndExtra - sizeof(WORD))
1778 WARN("Invalid offset %d\n", offset );
1779 SetLastError( ERROR_INVALID_INDEX );
1781 else retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1782 WIN_ReleasePtr( wndPtr );
1783 return retvalue;
1786 switch(offset)
1788 case GWL_HWNDPARENT:
1789 return GetWindowLongW( hwnd, offset );
1790 case GWL_ID:
1791 case GWL_HINSTANCE:
1793 LONG ret = GetWindowLongW( hwnd, offset );
1794 if (HIWORD(ret))
1795 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1796 return LOWORD(ret);
1798 default:
1799 WARN("Invalid offset %d\n", offset );
1800 return 0;
1805 /**********************************************************************
1806 * SetWindowWord (USER32.@)
1808 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1810 WORD *ptr, retval;
1811 WND * wndPtr;
1813 switch(offset)
1815 case GWL_ID:
1816 case GWL_HINSTANCE:
1817 case GWL_HWNDPARENT:
1818 return SetWindowLongW( hwnd, offset, (UINT)newval );
1819 default:
1820 if (offset < 0)
1822 WARN("Invalid offset %d\n", offset );
1823 SetLastError( ERROR_INVALID_INDEX );
1824 return 0;
1828 wndPtr = WIN_GetPtr( hwnd );
1829 if (wndPtr == WND_OTHER_PROCESS)
1831 if (IsWindow(hwnd))
1832 FIXME( "set %d <- %x not supported yet on other process window %x\n",
1833 offset, newval, hwnd );
1834 wndPtr = NULL;
1836 if (!wndPtr)
1838 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1839 return 0;
1842 if (offset > wndPtr->cbWndExtra - sizeof(WORD))
1844 WARN("Invalid offset %d\n", offset );
1845 WIN_ReleasePtr(wndPtr);
1846 SetLastError( ERROR_INVALID_INDEX );
1847 return 0;
1849 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1850 retval = *ptr;
1851 *ptr = newval;
1852 WIN_ReleasePtr(wndPtr);
1853 return retval;
1857 /**********************************************************************
1858 * WIN_GetWindowLong
1860 * Helper function for GetWindowLong().
1862 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1864 LONG retvalue = 0;
1865 WND *wndPtr;
1867 if (offset == GWL_HWNDPARENT) return (LONG)GetParent( hwnd );
1869 if (!(wndPtr = WIN_GetPtr( hwnd )))
1871 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1872 return 0;
1875 if (wndPtr == WND_OTHER_PROCESS)
1877 if (offset >= 0)
1879 if (IsWindow(hwnd))
1880 FIXME( "(%d) not supported on other process window %x\n", offset, hwnd );
1881 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1882 return 0;
1884 if (offset == GWL_WNDPROC)
1886 SetLastError( ERROR_ACCESS_DENIED );
1887 return 0;
1889 SERVER_START_REQ( set_window_info )
1891 req->handle = hwnd;
1892 req->flags = 0; /* don't set anything, just retrieve */
1893 if (!wine_server_call_err( req ))
1895 switch(offset)
1897 case GWL_STYLE: retvalue = reply->old_style; break;
1898 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1899 case GWL_ID: retvalue = reply->old_id; break;
1900 case GWL_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1901 case GWL_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
1902 default:
1903 SetLastError( ERROR_INVALID_INDEX );
1904 break;
1908 SERVER_END_REQ;
1909 return retvalue;
1912 /* now we have a valid wndPtr */
1914 if (offset >= 0)
1916 if (offset > wndPtr->cbWndExtra - sizeof(LONG))
1919 * Some programs try to access last element from 16 bit
1920 * code using illegal offset value. Hopefully this is
1921 * what those programs really expect.
1923 if (type == WIN_PROC_16 &&
1924 wndPtr->cbWndExtra >= 4 &&
1925 offset == wndPtr->cbWndExtra - sizeof(WORD))
1927 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
1929 ERR( "- replaced invalid offset %d with %d\n",
1930 offset, offset2 );
1932 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset2);
1933 WIN_ReleasePtr( wndPtr );
1934 return retvalue;
1936 WARN("Invalid offset %d\n", offset );
1937 WIN_ReleasePtr( wndPtr );
1938 SetLastError( ERROR_INVALID_INDEX );
1939 return 0;
1941 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1942 /* Special case for dialog window procedure */
1943 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1944 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1945 WIN_ReleasePtr( wndPtr );
1946 return retvalue;
1949 switch(offset)
1951 case GWL_USERDATA: retvalue = wndPtr->userdata; break;
1952 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1953 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1954 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu; break;
1955 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc, type ); break;
1956 case GWL_HINSTANCE: retvalue = wndPtr->hInstance; break;
1957 default:
1958 WARN("Unknown offset %d\n", offset );
1959 SetLastError( ERROR_INVALID_INDEX );
1960 break;
1962 WIN_ReleasePtr(wndPtr);
1963 return retvalue;
1967 /**********************************************************************
1968 * WIN_SetWindowLong
1970 * Helper function for SetWindowLong().
1972 * 0 is the failure code. However, in the case of failure SetLastError
1973 * must be set to distinguish between a 0 return value and a failure.
1975 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1976 WINDOWPROCTYPE type )
1978 LONG retval = 0;
1979 WND *wndPtr;
1981 TRACE( "%x %d %lx %x\n", hwnd, offset, newval, type );
1983 if (!WIN_IsCurrentProcess( hwnd ))
1985 if (offset == GWL_WNDPROC)
1987 SetLastError( ERROR_ACCESS_DENIED );
1988 return 0;
1990 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
1993 wndPtr = WIN_GetPtr( hwnd );
1995 if (offset >= 0)
1997 LONG *ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1998 if (offset > wndPtr->cbWndExtra - sizeof(LONG))
2000 WARN("Invalid offset %d\n", offset );
2001 WIN_ReleasePtr( wndPtr );
2002 SetLastError( ERROR_INVALID_INDEX );
2003 return 0;
2005 /* Special case for dialog window procedure */
2006 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2008 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
2009 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
2010 type, WIN_PROC_WINDOW );
2011 WIN_ReleasePtr( wndPtr );
2012 return retval;
2014 retval = *ptr;
2015 *ptr = newval;
2016 WIN_ReleasePtr( wndPtr );
2018 else
2020 STYLESTRUCT style;
2021 BOOL ok;
2023 /* first some special cases */
2024 switch( offset )
2026 case GWL_STYLE:
2027 case GWL_EXSTYLE:
2028 style.styleOld = wndPtr->dwStyle;
2029 style.styleNew = newval;
2030 WIN_ReleasePtr( wndPtr );
2031 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
2032 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
2033 newval = style.styleNew;
2034 break;
2035 case GWL_HWNDPARENT:
2036 WIN_ReleasePtr( wndPtr );
2037 return (LONG)SetParent( hwnd, (HWND)newval );
2038 case GWL_WNDPROC:
2039 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2040 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
2041 type, WIN_PROC_WINDOW );
2042 WIN_ReleasePtr( wndPtr );
2043 return retval;
2044 case GWL_ID:
2045 case GWL_HINSTANCE:
2046 case GWL_USERDATA:
2047 break;
2048 default:
2049 WIN_ReleasePtr( wndPtr );
2050 WARN("Invalid offset %d\n", offset );
2051 SetLastError( ERROR_INVALID_INDEX );
2052 return 0;
2055 SERVER_START_REQ( set_window_info )
2057 req->handle = hwnd;
2058 switch(offset)
2060 case GWL_STYLE:
2061 req->flags = SET_WIN_STYLE;
2062 req->style = newval;
2063 break;
2064 case GWL_EXSTYLE:
2065 req->flags = SET_WIN_EXSTYLE;
2066 req->ex_style = newval;
2067 break;
2068 case GWL_ID:
2069 req->flags = SET_WIN_ID;
2070 req->id = newval;
2071 break;
2072 case GWL_HINSTANCE:
2073 req->flags = SET_WIN_INSTANCE;
2074 req->instance = (void *)newval;
2075 break;
2076 case GWL_USERDATA:
2077 req->flags = SET_WIN_USERDATA;
2078 req->user_data = (void *)newval;
2079 break;
2081 if ((ok = !wine_server_call_err( req )))
2083 switch(offset)
2085 case GWL_STYLE:
2086 wndPtr->dwStyle = newval;
2087 retval = reply->old_style;
2088 break;
2089 case GWL_EXSTYLE:
2090 wndPtr->dwExStyle = newval;
2091 retval = reply->old_ex_style;
2092 break;
2093 case GWL_ID:
2094 wndPtr->wIDmenu = newval;
2095 retval = reply->old_id;
2096 break;
2097 case GWL_HINSTANCE:
2098 wndPtr->hInstance = newval;
2099 retval = (HINSTANCE)reply->old_instance;
2100 break;
2101 case GWL_USERDATA:
2102 wndPtr->userdata = newval;
2103 retval = (ULONG_PTR)reply->old_user_data;
2104 break;
2108 SERVER_END_REQ;
2109 WIN_ReleasePtr( wndPtr );
2111 if (!ok) return 0;
2113 if (offset == GWL_STYLE && USER_Driver.pSetWindowStyle)
2114 USER_Driver.pSetWindowStyle( hwnd, retval );
2116 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2117 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2120 return retval;
2124 /**********************************************************************
2125 * GetWindowLong (USER.135)
2127 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2129 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
2133 /**********************************************************************
2134 * GetWindowLongA (USER32.@)
2136 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2138 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2142 /**********************************************************************
2143 * GetWindowLongW (USER32.@)
2145 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2147 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2151 /**********************************************************************
2152 * SetWindowLong (USER.136)
2154 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2156 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
2160 /**********************************************************************
2161 * SetWindowLongA (USER32.@)
2163 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2165 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2169 /**********************************************************************
2170 * SetWindowLongW (USER32.@) Set window attribute
2172 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2173 * value in a window's extra memory.
2175 * The _hwnd_ parameter specifies the window. is the handle to a
2176 * window that has extra memory. The _newval_ parameter contains the
2177 * new attribute or extra memory value. If positive, the _offset_
2178 * parameter is the byte-addressed location in the window's extra
2179 * memory to set. If negative, _offset_ specifies the window
2180 * attribute to set, and should be one of the following values:
2182 * GWL_EXSTYLE The window's extended window style
2184 * GWL_STYLE The window's window style.
2186 * GWL_WNDPROC Pointer to the window's window procedure.
2188 * GWL_HINSTANCE The window's pplication instance handle.
2190 * GWL_ID The window's identifier.
2192 * GWL_USERDATA The window's user-specified data.
2194 * If the window is a dialog box, the _offset_ parameter can be one of
2195 * the following values:
2197 * DWL_DLGPROC The address of the window's dialog box procedure.
2199 * DWL_MSGRESULT The return value of a message
2200 * that the dialog box procedure processed.
2202 * DWL_USER Application specific information.
2204 * RETURNS
2206 * If successful, returns the previous value located at _offset_. Otherwise,
2207 * returns 0.
2209 * NOTES
2211 * Extra memory for a window class is specified by a nonzero cbWndExtra
2212 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2213 * time of class creation.
2215 * Using GWL_WNDPROC to set a new window procedure effectively creates
2216 * a window subclass. Use CallWindowProc() in the new windows procedure
2217 * to pass messages to the superclass's window procedure.
2219 * The user data is reserved for use by the application which created
2220 * the window.
2222 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2223 * instead, call the EnableWindow() function to change the window's
2224 * disabled state.
2226 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2227 * SetParent() instead.
2229 * Win95:
2230 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2231 * it sends WM_STYLECHANGING before changing the settings
2232 * and WM_STYLECHANGED afterwards.
2233 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2235 LONG WINAPI SetWindowLongW(
2236 HWND hwnd, /* [in] window to alter */
2237 INT offset, /* [in] offset, in bytes, of location to alter */
2238 LONG newval /* [in] new value of location */
2240 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2244 /*******************************************************************
2245 * GetWindowTextA (USER32.@)
2247 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2249 WCHAR *buffer;
2251 if (WIN_IsCurrentProcess( hwnd ))
2252 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2254 /* when window belongs to other process, don't send a message */
2255 if (nMaxCount <= 0) return 0;
2256 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2257 get_server_window_text( hwnd, buffer, nMaxCount );
2258 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2259 lpString[nMaxCount-1] = 0;
2260 HeapFree( GetProcessHeap(), 0, buffer );
2261 return strlen(lpString);
2265 /*******************************************************************
2266 * InternalGetWindowText (USER32.@)
2268 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2270 WND *win;
2272 if (nMaxCount <= 0) return 0;
2273 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2274 if (win != WND_OTHER_PROCESS)
2276 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2277 else lpString[0] = 0;
2278 WIN_ReleasePtr( win );
2280 else
2282 get_server_window_text( hwnd, lpString, nMaxCount );
2284 return strlenW(lpString);
2288 /*******************************************************************
2289 * GetWindowTextW (USER32.@)
2291 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2293 if (WIN_IsCurrentProcess( hwnd ))
2294 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2296 /* when window belongs to other process, don't send a message */
2297 if (nMaxCount <= 0) return 0;
2298 get_server_window_text( hwnd, lpString, nMaxCount );
2299 return strlenW(lpString);
2303 /*******************************************************************
2304 * SetWindowText (USER32.@)
2305 * SetWindowTextA (USER32.@)
2307 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2309 if (!WIN_IsCurrentProcess( hwnd ))
2311 FIXME( "cannot set text %s of other process window %x\n", debugstr_a(lpString), hwnd );
2312 SetLastError( ERROR_ACCESS_DENIED );
2313 return FALSE;
2315 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2319 /*******************************************************************
2320 * SetWindowTextW (USER32.@)
2322 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2324 if (!WIN_IsCurrentProcess( hwnd ))
2326 FIXME( "cannot set text %s of other process window %x\n", debugstr_w(lpString), hwnd );
2327 SetLastError( ERROR_ACCESS_DENIED );
2328 return FALSE;
2330 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2334 /*******************************************************************
2335 * GetWindowTextLengthA (USER32.@)
2337 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2339 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2342 /*******************************************************************
2343 * GetWindowTextLengthW (USER32.@)
2345 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2347 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2351 /*******************************************************************
2352 * IsWindow (USER32.@)
2354 BOOL WINAPI IsWindow( HWND hwnd )
2356 WND *ptr;
2357 BOOL ret;
2359 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2361 if (ptr != WND_OTHER_PROCESS)
2363 WIN_ReleasePtr( ptr );
2364 return TRUE;
2367 /* check other processes */
2368 SERVER_START_REQ( get_window_info )
2370 req->handle = hwnd;
2371 ret = !wine_server_call_err( req );
2373 SERVER_END_REQ;
2374 return ret;
2378 /***********************************************************************
2379 * GetWindowThreadProcessId (USER32.@)
2381 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2383 WND *ptr;
2384 DWORD tid = 0;
2386 if (!(ptr = WIN_GetPtr( hwnd )))
2388 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2389 return 0;
2392 if (ptr != WND_OTHER_PROCESS)
2394 /* got a valid window */
2395 tid = ptr->tid;
2396 if (process) *process = GetCurrentProcessId();
2397 WIN_ReleasePtr( ptr );
2398 return tid;
2401 /* check other processes */
2402 SERVER_START_REQ( get_window_info )
2404 req->handle = hwnd;
2405 if (!wine_server_call_err( req ))
2407 tid = (DWORD)reply->tid;
2408 if (process) *process = (DWORD)reply->pid;
2411 SERVER_END_REQ;
2412 return tid;
2416 /*****************************************************************
2417 * GetParent (USER32.@)
2419 HWND WINAPI GetParent( HWND hwnd )
2421 WND *wndPtr;
2422 HWND retvalue = 0;
2424 if (!(wndPtr = WIN_GetPtr( hwnd )))
2426 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2427 return 0;
2429 if (wndPtr == WND_OTHER_PROCESS)
2431 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2432 if (style & (WS_POPUP | WS_CHILD))
2434 SERVER_START_REQ( get_window_tree )
2436 req->handle = hwnd;
2437 if (!wine_server_call_err( req ))
2439 if (style & WS_CHILD) retvalue = reply->parent;
2440 else retvalue = reply->owner;
2443 SERVER_END_REQ;
2446 else
2448 if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2449 else if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2450 WIN_ReleasePtr( wndPtr );
2452 return retvalue;
2456 /*****************************************************************
2457 * GetAncestor (USER32.@)
2459 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2461 WND *win;
2462 HWND *list, ret = 0;
2464 if (type == GA_PARENT)
2466 if (!(win = WIN_GetPtr( hwnd )))
2468 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2469 return 0;
2471 if (win != WND_OTHER_PROCESS)
2473 ret = win->parent;
2474 WIN_ReleasePtr( win );
2476 else /* need to query the server */
2478 SERVER_START_REQ( get_window_tree )
2480 req->handle = hwnd;
2481 if (!wine_server_call_err( req )) ret = reply->parent;
2483 SERVER_END_REQ;
2485 return ret;
2488 if (!(list = WIN_ListParents( hwnd ))) return 0;
2490 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2491 else
2493 int count = 2;
2494 while (list[count]) count++;
2495 ret = list[count - 2]; /* get the one before the desktop */
2497 HeapFree( GetProcessHeap(), 0, list );
2499 if (ret && type == GA_ROOTOWNER)
2501 for (;;)
2503 HWND owner = GetWindow( ret, GW_OWNER );
2504 if (!owner) break;
2505 ret = owner;
2508 return ret;
2512 /*****************************************************************
2513 * SetParent (USER32.@)
2515 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2517 WND *wndPtr;
2518 HWND retvalue, full_handle;
2519 BOOL was_visible;
2521 if (!parent) parent = GetDesktopWindow();
2522 else parent = WIN_GetFullHandle( parent );
2524 if (!IsWindow( parent ))
2526 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2527 return 0;
2530 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2531 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2533 hwnd = full_handle;
2535 if (USER_Driver.pSetParent)
2536 return USER_Driver.pSetParent( hwnd, parent );
2538 /* Windows hides the window first, then shows it again
2539 * including the WM_SHOWWINDOW messages and all */
2540 was_visible = ShowWindow( hwnd, SW_HIDE );
2542 if (!IsWindow( parent )) return 0;
2543 if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return 0;
2545 retvalue = wndPtr->parent; /* old parent */
2546 if (parent != retvalue)
2548 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2550 if (parent != GetDesktopWindow()) /* a child window */
2552 if (!(wndPtr->dwStyle & WS_CHILD))
2554 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
2555 if (menu) DestroyMenu( menu );
2559 WIN_ReleasePtr( wndPtr );
2561 /* SetParent additionally needs to make hwnd the topmost window
2562 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2563 WM_WINDOWPOSCHANGED notification messages.
2565 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2566 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2567 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2568 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2569 return retvalue;
2573 /*******************************************************************
2574 * IsChild (USER32.@)
2576 BOOL WINAPI IsChild( HWND parent, HWND child )
2578 HWND *list = WIN_ListParents( child );
2579 int i;
2580 BOOL ret;
2582 if (!list) return FALSE;
2583 parent = WIN_GetFullHandle( parent );
2584 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2585 ret = (list[i] != 0);
2586 HeapFree( GetProcessHeap(), 0, list );
2587 return ret;
2591 /***********************************************************************
2592 * IsWindowVisible (USER32.@)
2594 BOOL WINAPI IsWindowVisible( HWND hwnd )
2596 HWND *list;
2597 BOOL retval;
2598 int i;
2600 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2601 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2602 for (i = 0; list[i]; i++)
2603 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2604 retval = !list[i];
2605 HeapFree( GetProcessHeap(), 0, list );
2606 return retval;
2610 /***********************************************************************
2611 * WIN_IsWindowDrawable
2613 * hwnd is drawable when it is visible, all parents are not
2614 * minimized, and it is itself not minimized unless we are
2615 * trying to draw its default class icon.
2617 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2619 HWND *list;
2620 BOOL retval;
2621 int i;
2622 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2624 if (!(style & WS_VISIBLE)) return FALSE;
2625 if ((style & WS_MINIMIZE) && icon && GetClassLongA( hwnd, GCL_HICON )) return FALSE;
2627 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2628 for (i = 0; list[i]; i++)
2629 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2630 break;
2631 retval = !list[i];
2632 HeapFree( GetProcessHeap(), 0, list );
2633 return retval;
2637 /*******************************************************************
2638 * GetTopWindow (USER32.@)
2640 HWND WINAPI GetTopWindow( HWND hwnd )
2642 if (!hwnd) hwnd = GetDesktopWindow();
2643 return GetWindow( hwnd, GW_CHILD );
2647 /*******************************************************************
2648 * GetWindow (USER32.@)
2650 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2652 HWND retval = 0;
2654 if (rel == GW_OWNER) /* this one may be available locally */
2656 WND *wndPtr = WIN_GetPtr( hwnd );
2657 if (!wndPtr)
2659 SetLastError( ERROR_INVALID_HANDLE );
2660 return 0;
2662 if (wndPtr != WND_OTHER_PROCESS)
2664 retval = wndPtr->owner;
2665 WIN_ReleasePtr( wndPtr );
2666 return retval;
2668 /* else fall through to server call */
2671 SERVER_START_REQ( get_window_tree )
2673 req->handle = hwnd;
2674 if (!wine_server_call_err( req ))
2676 switch(rel)
2678 case GW_HWNDFIRST:
2679 retval = reply->first_sibling;
2680 break;
2681 case GW_HWNDLAST:
2682 retval = reply->last_sibling;
2683 break;
2684 case GW_HWNDNEXT:
2685 retval = reply->next_sibling;
2686 break;
2687 case GW_HWNDPREV:
2688 retval = reply->prev_sibling;
2689 break;
2690 case GW_OWNER:
2691 retval = reply->owner;
2692 break;
2693 case GW_CHILD:
2694 retval = reply->first_child;
2695 break;
2699 SERVER_END_REQ;
2700 return retval;
2704 /***********************************************************************
2705 * WIN_InternalShowOwnedPopups
2707 * Internal version of ShowOwnedPopups; Wine functions should use this
2708 * to avoid interfering with application calls to ShowOwnedPopups
2709 * and to make sure the application can't prevent showing/hiding.
2711 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2715 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2717 int count = 0;
2718 WND *pWnd;
2719 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2721 if (!win_array) return TRUE;
2724 * Show windows Lowest first, Highest last to preserve Z-Order
2726 while (win_array[count]) count++;
2727 while (--count >= 0)
2729 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2730 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2732 if (pWnd->dwStyle & WS_POPUP)
2734 if (fShow)
2736 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2737 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
2740 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2742 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2743 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2746 else
2748 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2749 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2750 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2753 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2755 ShowWindow(pWnd->hwndSelf,SW_HIDE);
2756 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2757 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
2761 WIN_ReleaseWndPtr( pWnd );
2763 HeapFree( GetProcessHeap(), 0, win_array );
2765 return TRUE;
2768 /*******************************************************************
2769 * ShowOwnedPopups (USER32.@)
2771 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2773 int count = 0;
2774 WND *pWnd;
2775 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2777 if (!win_array) return TRUE;
2779 while (win_array[count]) count++;
2780 while (--count >= 0)
2782 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2783 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2785 if (pWnd->dwStyle & WS_POPUP)
2787 if (fShow)
2789 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2791 /* In Windows, ShowOwnedPopups(TRUE) generates
2792 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2793 * regardless of the state of the owner
2795 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2796 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2799 else
2801 if (IsWindowVisible(pWnd->hwndSelf))
2803 /* In Windows, ShowOwnedPopups(FALSE) generates
2804 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2805 * regardless of the state of the owner
2807 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2808 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2812 WIN_ReleaseWndPtr( pWnd );
2814 HeapFree( GetProcessHeap(), 0, win_array );
2815 return TRUE;
2819 /*******************************************************************
2820 * GetLastActivePopup (USER32.@)
2822 HWND WINAPI GetLastActivePopup( HWND hwnd )
2824 HWND retval;
2825 WND *wndPtr =WIN_FindWndPtr(hwnd);
2826 if (!wndPtr) return hwnd;
2827 retval = wndPtr->hwndLastActive;
2828 if (!IsWindow( retval )) retval = wndPtr->hwndSelf;
2829 WIN_ReleaseWndPtr(wndPtr);
2830 return retval;
2834 /*******************************************************************
2835 * WIN_ListParents
2837 * Build an array of all parents of a given window, starting with
2838 * the immediate parent. The array must be freed with HeapFree.
2839 * Returns NULL if window is a top-level window.
2841 HWND *WIN_ListParents( HWND hwnd )
2843 WND *win;
2844 HWND current, *list;
2845 int pos = 0, size = 16, count = 0;
2847 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2849 current = hwnd;
2850 for (;;)
2852 if (!(win = WIN_GetPtr( current ))) goto empty;
2853 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
2854 list[pos] = win->parent;
2855 WIN_ReleasePtr( win );
2856 if (!(current = list[pos]))
2858 if (!pos) goto empty;
2859 return list;
2861 if (++pos == size - 1)
2863 /* need to grow the list */
2864 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
2865 if (!new_list) goto empty;
2866 list = new_list;
2867 size += 16;
2871 /* at least one parent belongs to another process, have to query the server */
2873 for (;;)
2875 count = 0;
2876 SERVER_START_REQ( get_window_parents )
2878 req->handle = hwnd;
2879 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
2880 if (!wine_server_call( req )) count = reply->count;
2882 SERVER_END_REQ;
2883 if (!count) goto empty;
2884 if (size > count)
2886 list[count] = 0;
2887 return list;
2889 HeapFree( GetProcessHeap(), 0, list );
2890 size = count + 1;
2891 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2894 empty:
2895 HeapFree( GetProcessHeap(), 0, list );
2896 return NULL;
2900 /*******************************************************************
2901 * WIN_ListChildren
2903 * Build an array of the children of a given window. The array must be
2904 * freed with HeapFree. Returns NULL when no windows are found.
2906 HWND *WIN_ListChildren( HWND hwnd )
2908 return list_window_children( hwnd, 0, 0 );
2912 /*******************************************************************
2913 * EnumWindows (USER32.@)
2915 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2917 HWND *list;
2918 BOOL ret = TRUE;
2919 int i, iWndsLocks;
2921 /* We have to build a list of all windows first, to avoid */
2922 /* unpleasant side-effects, for instance if the callback */
2923 /* function changes the Z-order of the windows. */
2925 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2927 /* Now call the callback function for every window */
2929 iWndsLocks = WIN_SuspendWndsLock();
2930 for (i = 0; list[i]; i++)
2932 /* Make sure that the window still exists */
2933 if (!IsWindow( list[i] )) continue;
2934 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2936 WIN_RestoreWndsLock(iWndsLocks);
2937 HeapFree( GetProcessHeap(), 0, list );
2938 return ret;
2942 /**********************************************************************
2943 * EnumThreadWindows (USER32.@)
2945 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2947 HWND *list;
2948 int i, iWndsLocks;
2950 if (!(list = list_window_children( GetDesktopWindow(), 0, GetCurrentThreadId() )))
2951 return TRUE ;
2953 /* Now call the callback function for every window */
2955 iWndsLocks = WIN_SuspendWndsLock();
2956 for (i = 0; list[i]; i++)
2957 if (!func( list[i], lParam )) break;
2958 WIN_RestoreWndsLock(iWndsLocks);
2959 HeapFree( GetProcessHeap(), 0, list );
2960 return TRUE;
2964 /**********************************************************************
2965 * WIN_EnumChildWindows
2967 * Helper function for EnumChildWindows().
2969 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2971 HWND *childList;
2972 BOOL ret = FALSE;
2974 for ( ; *list; list++)
2976 /* Make sure that the window still exists */
2977 if (!IsWindow( *list )) continue;
2978 /* skip owned windows */
2979 if (GetWindow( *list, GW_OWNER )) continue;
2980 /* Build children list first */
2981 childList = WIN_ListChildren( *list );
2983 ret = func( *list, lParam );
2985 if (childList)
2987 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2988 HeapFree( GetProcessHeap(), 0, childList );
2990 if (!ret) return FALSE;
2992 return TRUE;
2996 /**********************************************************************
2997 * EnumChildWindows (USER32.@)
2999 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
3001 HWND *list;
3002 int iWndsLocks;
3004 if (!(list = WIN_ListChildren( parent ))) return FALSE;
3005 iWndsLocks = WIN_SuspendWndsLock();
3006 WIN_EnumChildWindows( list, func, lParam );
3007 WIN_RestoreWndsLock(iWndsLocks);
3008 HeapFree( GetProcessHeap(), 0, list );
3009 return TRUE;
3013 /*******************************************************************
3014 * AnyPopup (USER.52)
3016 BOOL16 WINAPI AnyPopup16(void)
3018 return AnyPopup();
3022 /*******************************************************************
3023 * AnyPopup (USER32.@)
3025 BOOL WINAPI AnyPopup(void)
3027 int i;
3028 BOOL retvalue;
3029 HWND *list = WIN_ListChildren( GetDesktopWindow() );
3031 if (!list) return FALSE;
3032 for (i = 0; list[i]; i++)
3034 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
3036 retvalue = (list[i] != 0);
3037 HeapFree( GetProcessHeap(), 0, list );
3038 return retvalue;
3042 /*******************************************************************
3043 * FlashWindow (USER32.@)
3045 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3047 WND *wndPtr = WIN_FindWndPtr(hWnd);
3049 TRACE("%04x\n", hWnd);
3051 if (!wndPtr) return FALSE;
3052 hWnd = wndPtr->hwndSelf; /* make it a full handle */
3054 if (wndPtr->dwStyle & WS_MINIMIZE)
3056 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3058 HDC hDC = GetDC(hWnd);
3060 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
3061 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
3063 ReleaseDC( hWnd, hDC );
3064 wndPtr->flags |= WIN_NCACTIVATED;
3066 else
3068 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3069 wndPtr->flags &= ~WIN_NCACTIVATED;
3071 WIN_ReleaseWndPtr(wndPtr);
3072 return TRUE;
3074 else
3076 WPARAM16 wparam;
3077 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3078 else wparam = (hWnd == GetActiveWindow());
3080 WIN_ReleaseWndPtr(wndPtr);
3081 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3082 return wparam;
3087 /*******************************************************************
3088 * GetWindowContextHelpId (USER32.@)
3090 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3092 DWORD retval;
3093 WND *wnd = WIN_FindWndPtr( hwnd );
3094 if (!wnd) return 0;
3095 retval = wnd->helpContext;
3096 WIN_ReleaseWndPtr(wnd);
3097 return retval;
3101 /*******************************************************************
3102 * SetWindowContextHelpId (USER32.@)
3104 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3106 WND *wnd = WIN_FindWndPtr( hwnd );
3107 if (!wnd) return FALSE;
3108 wnd->helpContext = id;
3109 WIN_ReleaseWndPtr(wnd);
3110 return TRUE;
3114 /*******************************************************************
3115 * DRAG_QueryUpdate
3117 * recursively find a child that contains spDragInfo->pt point
3118 * and send WM_QUERYDROPOBJECT
3120 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3122 BOOL16 wParam, bResult = 0;
3123 POINT pt;
3124 LPDRAGINFO16 ptrDragInfo = MapSL(spDragInfo);
3125 RECT tempRect;
3127 if (!ptrDragInfo) return FALSE;
3129 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3131 GetWindowRect(hQueryWnd,&tempRect);
3133 if( !PtInRect(&tempRect,pt) || !IsWindowEnabled(hQueryWnd)) return FALSE;
3135 if (!IsIconic( hQueryWnd ))
3137 GetClientRect( hQueryWnd, &tempRect );
3138 MapWindowPoints( hQueryWnd, 0, (LPPOINT)&tempRect, 2 );
3140 if (PtInRect( &tempRect, pt))
3142 int i;
3143 HWND *list = WIN_ListChildren( hQueryWnd );
3145 wParam = 0;
3147 if (list)
3149 for (i = 0; list[i]; i++)
3151 if (GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)
3153 GetWindowRect( list[i], &tempRect );
3154 if (PtInRect( &tempRect, pt )) break;
3157 if (list[i])
3159 if (IsWindowEnabled( list[i] ))
3160 bResult = DRAG_QueryUpdate( list[i], spDragInfo, bNoSend );
3162 HeapFree( GetProcessHeap(), 0, list );
3164 if(bResult) return bResult;
3166 else wParam = 1;
3168 else wParam = 1;
3170 ScreenToClient16(HWND_16(hQueryWnd),&ptrDragInfo->pt);
3172 ptrDragInfo->hScope = HWND_16(hQueryWnd);
3174 if (bNoSend) bResult = (GetWindowLongA( hQueryWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES) != 0;
3175 else bResult = SendMessage16( HWND_16(hQueryWnd), WM_QUERYDROPOBJECT,
3176 (WPARAM16)wParam, spDragInfo );
3178 if( !bResult ) CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3180 return bResult;
3184 /*******************************************************************
3185 * DragDetect (USER32.@)
3187 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3189 MSG msg;
3190 RECT rect;
3192 rect.left = pt.x - wDragWidth;
3193 rect.right = pt.x + wDragWidth;
3195 rect.top = pt.y - wDragHeight;
3196 rect.bottom = pt.y + wDragHeight;
3198 SetCapture(hWnd);
3200 while(1)
3202 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3204 if( msg.message == WM_LBUTTONUP )
3206 ReleaseCapture();
3207 return 0;
3209 if( msg.message == WM_MOUSEMOVE )
3211 POINT tmp;
3212 tmp.x = LOWORD(msg.lParam);
3213 tmp.y = HIWORD(msg.lParam);
3214 if( !PtInRect( &rect, tmp ))
3216 ReleaseCapture();
3217 return 1;
3221 WaitMessage();
3223 return 0;
3226 /******************************************************************************
3227 * DragObject (USER.464)
3229 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3230 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3232 MSG msg;
3233 LPDRAGINFO16 lpDragInfo;
3234 SEGPTR spDragInfo;
3235 HCURSOR16 hOldCursor=0, hBummer=0;
3236 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
3237 HCURSOR16 hCurrentCursor = 0;
3238 HWND16 hCurrentWnd = 0;
3240 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
3241 spDragInfo = K32WOWGlobalLock16(hDragInfo);
3243 if( !lpDragInfo || !spDragInfo ) return 0L;
3245 if (!(hBummer = LoadCursorA(0, MAKEINTRESOURCEA(OCR_NO))))
3247 GlobalFree16(hDragInfo);
3248 return 0L;
3251 if(hCursor) hOldCursor = SetCursor(hCursor);
3253 lpDragInfo->hWnd = hWnd;
3254 lpDragInfo->hScope = 0;
3255 lpDragInfo->wFlags = wObj;
3256 lpDragInfo->hList = szList; /* near pointer! */
3257 lpDragInfo->hOfStruct = hOfStruct;
3258 lpDragInfo->l = 0L;
3260 SetCapture(WIN_Handle32(hWnd));
3261 ShowCursor( TRUE );
3265 GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST );
3267 *(lpDragInfo+1) = *lpDragInfo;
3269 lpDragInfo->pt.x = msg.pt.x;
3270 lpDragInfo->pt.y = msg.pt.y;
3272 /* update DRAGINFO struct */
3273 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3275 if( DRAG_QueryUpdate(WIN_Handle32(hwndScope), spDragInfo, FALSE) > 0 )
3276 hCurrentCursor = hCursor;
3277 else
3279 hCurrentCursor = hBummer;
3280 lpDragInfo->hScope = 0;
3282 if( hCurrentCursor )
3283 SetCursor(hCurrentCursor);
3285 /* send WM_DRAGLOOP */
3286 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3287 (LPARAM) spDragInfo );
3288 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3289 if( hCurrentWnd != lpDragInfo->hScope )
3291 if( hCurrentWnd )
3292 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3293 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
3294 HIWORD(spDragInfo)) );
3295 hCurrentWnd = lpDragInfo->hScope;
3296 if( hCurrentWnd )
3297 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3299 else
3300 if( hCurrentWnd )
3301 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3303 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3305 ReleaseCapture();
3306 ShowCursor( FALSE );
3308 if( hCursor ) SetCursor( hOldCursor );
3310 if( hCurrentCursor != hBummer )
3311 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3312 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3313 else
3314 msg.lParam = 0;
3315 GlobalFree16(hDragInfo);
3317 return (DWORD)(msg.lParam);
3321 /******************************************************************************
3322 * GetWindowModuleFileNameA (USER32.@)
3324 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3326 FIXME("GetWindowModuleFileNameA(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3327 hwnd, lpszFileName, cchFileNameMax);
3328 return 0;
3331 /******************************************************************************
3332 * GetWindowModuleFileNameW (USER32.@)
3334 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3336 FIXME("GetWindowModuleFileNameW(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3337 hwnd, lpszFileName, cchFileNameMax);
3338 return 0;
3341 /******************************************************************************
3342 * GetWindowInfo (USER32.@)
3343 * hwnd: in
3344 * pwi: out.
3345 * MS Documentation mentions that pwi->cbSize must be set to SIZEOF(WINDOWINFO)
3346 * this may be because this structure changed over time. If this is the
3347 * the case, then please: FIXME.
3348 * Using the structure described in MSDN for 98/ME/NT(4.0 SP3)/2000/XP.
3350 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3352 WND *wndInfo = NULL;
3353 if (!pwi) return FALSE;
3354 if (pwi->cbSize != sizeof(WINDOWINFO))
3356 FIXME("windowinfo->cbSize != sizeof(WINDOWINFO). Please report\n");
3357 return FALSE;
3359 wndInfo = WIN_GetPtr(hwnd);
3360 if (!wndInfo) return FALSE;
3361 if (wndInfo == WND_OTHER_PROCESS)
3363 FIXME("window belong to other process\n");
3364 return FALSE;
3367 pwi->rcWindow = wndInfo->rectWindow;
3368 pwi->rcClient = wndInfo->rectClient;
3369 pwi->dwStyle = wndInfo->dwStyle;
3370 pwi->dwExStyle = wndInfo->dwExStyle;
3371 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3372 /* if active WS_ACTIVECAPTION, else 0 */
3374 pwi->cxWindowBorders = ((wndInfo->dwStyle & WS_BORDER) ?
3375 GetSystemMetrics(SM_CXBORDER) : 0);
3376 pwi->cyWindowBorders = ((wndInfo->dwStyle & WS_BORDER) ?
3377 GetSystemMetrics(SM_CYBORDER) : 0);
3378 /* above two: I'm presuming that borders widths are the same
3379 * for each window - so long as its actually using a border.. */
3381 pwi->atomWindowType = GetClassLongA( hwnd, GCW_ATOM );
3382 pwi->wCreatorVersion = GetVersion();
3383 /* Docs say this should be the version that
3384 * CREATED the window. But eh?.. Isn't that just the
3385 * version we are running.. Unless ofcourse its some wacky
3386 * RPC stuff or something */
3388 WIN_ReleasePtr(wndInfo);
3389 return TRUE;