Moved a few remaining 16-bit window functions to wnd16.c and moved it
[wine/multimedia.git] / windows / win.c
blob714b1ffbfadabdf853b4a5214fdb9905531fd6f8
1 /*
2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "config.h"
22 #include "wine/port.h"
24 #include <assert.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include "windef.h"
28 #include "wine/winbase16.h"
29 #include "wine/winuser16.h"
30 #include "wownt32.h"
31 #include "wine/server.h"
32 #include "wine/unicode.h"
33 #include "win.h"
34 #include "user.h"
35 #include "dce.h"
36 #include "controls.h"
37 #include "cursoricon.h"
38 #include "hook.h"
39 #include "message.h"
40 #include "queue.h"
41 #include "winpos.h"
42 #include "winerror.h"
43 #include "stackframe.h"
44 #include "wine/debug.h"
46 WINE_DEFAULT_DEBUG_CHANNEL(win);
47 WINE_DECLARE_DEBUG_CHANNEL(msg);
49 #define NB_USER_HANDLES (LAST_USER_HANDLE - FIRST_USER_HANDLE + 1)
51 /**********************************************************************/
53 /* Desktop window */
54 static WND *pWndDesktop = NULL;
56 static WORD wDragWidth = 4;
57 static WORD wDragHeight= 3;
59 static void *user_handles[NB_USER_HANDLES];
61 /* thread safeness */
62 extern SYSLEVEL USER_SysLevel; /* FIXME */
64 /***********************************************************************
65 * WIN_SuspendWndsLock
67 * Suspend the lock on WND structures.
68 * Returns the number of locks suspended
70 int WIN_SuspendWndsLock( void )
72 int isuspendedLocks = _ConfirmSysLevel( &USER_SysLevel );
73 int count = isuspendedLocks;
75 while ( count-- > 0 )
76 _LeaveSysLevel( &USER_SysLevel );
78 return isuspendedLocks;
81 /***********************************************************************
82 * WIN_RestoreWndsLock
84 * Restore the suspended locks on WND structures
86 void WIN_RestoreWndsLock( int ipreviousLocks )
88 while ( ipreviousLocks-- > 0 )
89 _EnterSysLevel( &USER_SysLevel );
92 /***********************************************************************
93 * create_window_handle
95 * Create a window handle with the server.
97 static WND *create_window_handle( HWND parent, HWND owner, ATOM atom, INT size )
99 BOOL res;
100 user_handle_t handle = 0;
101 WORD index;
102 WND *win = HeapAlloc( GetProcessHeap(), 0, size );
104 if (!win) return NULL;
106 USER_Lock();
108 SERVER_START_REQ( create_window )
110 req->parent = parent;
111 req->owner = owner;
112 req->atom = atom;
113 if ((res = !wine_server_call_err( req ))) handle = reply->handle;
115 SERVER_END_REQ;
117 if (!res)
119 USER_Unlock();
120 HeapFree( GetProcessHeap(), 0, win );
121 return NULL;
123 index = LOWORD(handle) - FIRST_USER_HANDLE;
124 assert( index < NB_USER_HANDLES );
125 user_handles[index] = win;
126 win->hwndSelf = handle;
127 win->dwMagic = WND_MAGIC;
128 win->irefCount = 1;
129 return win;
133 /***********************************************************************
134 * free_window_handle
136 * Free a window handle.
138 static WND *free_window_handle( HWND hwnd )
140 WND *ptr;
141 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
143 if (index >= NB_USER_HANDLES) return NULL;
144 USER_Lock();
145 if ((ptr = user_handles[index]))
147 SERVER_START_REQ( destroy_window )
149 req->handle = hwnd;
150 if (!wine_server_call_err( req ))
151 user_handles[index] = NULL;
152 else
153 ptr = NULL;
155 SERVER_END_REQ;
157 USER_Unlock();
158 if (ptr) HeapFree( GetProcessHeap(), 0, ptr );
159 return ptr;
163 /*******************************************************************
164 * list_window_children
166 * Build an array of the children of a given window. The array must be
167 * freed with HeapFree. Returns NULL when no windows are found.
169 static HWND *list_window_children( HWND hwnd, ATOM atom, DWORD tid )
171 HWND *list;
172 int size = 32;
174 for (;;)
176 int count = 0;
178 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
180 SERVER_START_REQ( get_window_children )
182 req->parent = hwnd;
183 req->atom = atom;
184 req->tid = tid;
185 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
186 if (!wine_server_call( req )) count = reply->count;
188 SERVER_END_REQ;
189 if (count && count < size)
191 list[count] = 0;
192 return list;
194 HeapFree( GetProcessHeap(), 0, list );
195 if (!count) break;
196 size = count + 1; /* restart with a large enough buffer */
198 return NULL;
202 /*******************************************************************
203 * send_parent_notify
205 static void send_parent_notify( HWND hwnd, UINT msg )
207 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD)) return;
208 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY) return;
209 SendMessageW( GetParent(hwnd), WM_PARENTNOTIFY,
210 MAKEWPARAM( msg, GetWindowLongW( hwnd, GWL_ID )), (LPARAM)hwnd );
214 /*******************************************************************
215 * get_server_window_text
217 * Retrieve the window text from the server.
219 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
221 size_t len = 0;
223 SERVER_START_REQ( get_window_text )
225 req->handle = hwnd;
226 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
227 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
229 SERVER_END_REQ;
230 text[len / sizeof(WCHAR)] = 0;
234 /***********************************************************************
235 * WIN_GetPtr
237 * Return a pointer to the WND structure if local to the process,
238 * or WND_OTHER_PROCESS if handle may be valid in other process.
239 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
241 WND *WIN_GetPtr( HWND hwnd )
243 WND * ptr;
244 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
246 if (index >= NB_USER_HANDLES) return NULL;
248 USER_Lock();
249 if ((ptr = user_handles[index]))
251 if (ptr->dwMagic == WND_MAGIC && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
252 return ptr;
253 ptr = NULL;
255 else ptr = WND_OTHER_PROCESS;
256 USER_Unlock();
257 return ptr;
261 /***********************************************************************
262 * WIN_IsCurrentProcess
264 * Check whether a given window belongs to the current process (and return the full handle).
266 HWND WIN_IsCurrentProcess( HWND hwnd )
268 WND *ptr;
269 HWND ret;
271 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS) return 0;
272 ret = ptr->hwndSelf;
273 WIN_ReleasePtr( ptr );
274 return ret;
278 /***********************************************************************
279 * WIN_IsCurrentThread
281 * Check whether a given window belongs to the current thread (and return the full handle).
283 HWND WIN_IsCurrentThread( HWND hwnd )
285 WND *ptr;
286 HWND ret = 0;
288 if ((ptr = WIN_GetPtr( hwnd )) && ptr != WND_OTHER_PROCESS)
290 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
291 WIN_ReleasePtr( ptr );
293 return ret;
297 /***********************************************************************
298 * WIN_Handle32
300 * Convert a 16-bit window handle to a full 32-bit handle.
302 HWND WIN_Handle32( HWND16 hwnd16 )
304 WND *ptr;
305 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
307 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
308 /* do sign extension for -2 and -3 */
309 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
311 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
313 if (ptr != WND_OTHER_PROCESS)
315 hwnd = ptr->hwndSelf;
316 WIN_ReleasePtr( ptr );
318 else /* may belong to another process */
320 SERVER_START_REQ( get_window_info )
322 req->handle = hwnd;
323 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
325 SERVER_END_REQ;
327 return hwnd;
331 /***********************************************************************
332 * WIN_FindWndPtr
334 * Return a pointer to the WND structure corresponding to a HWND.
336 WND * WIN_FindWndPtr( HWND hwnd )
338 WND * ptr;
340 if (!hwnd) return NULL;
342 if ((ptr = WIN_GetPtr( hwnd )))
344 if (ptr != WND_OTHER_PROCESS)
346 /* increment destruction monitoring */
347 ptr->irefCount++;
348 return ptr;
350 if (IsWindow( hwnd )) /* check other processes */
352 ERR( "window %04x belongs to other process\n", hwnd );
353 /* DbgBreakPoint(); */
356 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
357 return NULL;
361 /***********************************************************************
362 * WIN_ReleaseWndPtr
364 * Release the pointer to the WND structure.
366 void WIN_ReleaseWndPtr(WND *wndPtr)
368 if(!wndPtr) return;
370 /* Decrement destruction monitoring value */
371 wndPtr->irefCount--;
372 /* Check if it's time to release the memory */
373 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
375 /* Release memory */
376 free_window_handle( wndPtr->hwndSelf );
378 else if(wndPtr->irefCount < 0)
380 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
381 ERR("forgot a Lock on %p somewhere\n",wndPtr);
383 /* unlock all WND structures for thread safeness */
384 USER_Unlock();
388 /***********************************************************************
389 * WIN_UnlinkWindow
391 * Remove a window from the siblings linked list.
393 void WIN_UnlinkWindow( HWND hwnd )
395 WIN_LinkWindow( hwnd, 0, 0 );
399 /***********************************************************************
400 * WIN_LinkWindow
402 * Insert a window into the siblings linked list.
403 * The window is inserted after the specified window, which can also
404 * be specified as HWND_TOP or HWND_BOTTOM.
405 * If parent is 0, window is unlinked from the tree.
407 void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
409 WND *wndPtr = WIN_GetPtr( hwnd );
411 if (!wndPtr) return;
412 if (wndPtr == WND_OTHER_PROCESS)
414 if (IsWindow(hwnd)) ERR(" cannot link other process window %x\n", hwnd );
415 return;
418 SERVER_START_REQ( link_window )
420 req->handle = hwnd;
421 req->parent = parent;
422 req->previous = hwndInsertAfter;
423 if (!wine_server_call( req ))
425 if (reply->full_parent) wndPtr->parent = reply->full_parent;
429 SERVER_END_REQ;
430 WIN_ReleasePtr( wndPtr );
434 /***********************************************************************
435 * WIN_SetOwner
437 * Change the owner of a window.
439 HWND WIN_SetOwner( HWND hwnd, HWND owner )
441 WND *win = WIN_GetPtr( hwnd );
442 HWND ret = 0;
444 if (!win) return 0;
445 if (win == WND_OTHER_PROCESS)
447 if (IsWindow(hwnd)) ERR( "cannot set owner %x on other process window %x\n", owner, hwnd );
448 return 0;
450 SERVER_START_REQ( set_window_owner )
452 req->handle = hwnd;
453 req->owner = owner;
454 if (!wine_server_call( req ))
456 win->owner = reply->full_owner;
457 ret = reply->prev_owner;
460 SERVER_END_REQ;
461 WIN_ReleasePtr( win );
462 return ret;
466 /***********************************************************************
467 * WIN_SetStyle
469 * Change the style of a window.
471 LONG WIN_SetStyle( HWND hwnd, LONG style )
473 BOOL ok;
474 LONG ret = 0;
475 WND *win = WIN_GetPtr( hwnd );
477 if (!win) return 0;
478 if (win == WND_OTHER_PROCESS)
480 if (IsWindow(hwnd))
481 ERR( "cannot set style %lx on other process window %x\n", style, hwnd );
482 return 0;
484 if (style == win->dwStyle)
486 WIN_ReleasePtr( win );
487 return style;
489 SERVER_START_REQ( set_window_info )
491 req->handle = hwnd;
492 req->flags = SET_WIN_STYLE;
493 req->style = style;
494 if ((ok = !wine_server_call( req )))
496 ret = reply->old_style;
497 win->dwStyle = style;
500 SERVER_END_REQ;
501 WIN_ReleasePtr( win );
502 if (ok && USER_Driver.pSetWindowStyle) USER_Driver.pSetWindowStyle( hwnd, ret );
503 return ret;
507 /***********************************************************************
508 * WIN_SetExStyle
510 * Change the extended style of a window.
512 LONG WIN_SetExStyle( HWND hwnd, LONG style )
514 LONG ret = 0;
515 WND *win = WIN_GetPtr( hwnd );
517 if (!win) return 0;
518 if (win == WND_OTHER_PROCESS)
520 if (IsWindow(hwnd))
521 ERR( "cannot set exstyle %lx on other process window %x\n", style, hwnd );
522 return 0;
524 if (style == win->dwExStyle)
526 WIN_ReleasePtr( win );
527 return style;
529 SERVER_START_REQ( set_window_info )
531 req->handle = hwnd;
532 req->flags = SET_WIN_EXSTYLE;
533 req->ex_style = style;
534 if (!wine_server_call( req ))
536 ret = reply->old_ex_style;
537 win->dwExStyle = style;
540 SERVER_END_REQ;
541 WIN_ReleasePtr( win );
542 return ret;
546 /***********************************************************************
547 * WIN_SetRectangles
549 * Set the window and client rectangles.
551 void WIN_SetRectangles( HWND hwnd, const RECT *rectWindow, const RECT *rectClient )
553 WND *win = WIN_GetPtr( hwnd );
554 BOOL ret;
556 if (!win) return;
557 if (win == WND_OTHER_PROCESS)
559 if (IsWindow( hwnd )) ERR( "cannot set rectangles of other process window %x\n", hwnd );
560 return;
562 SERVER_START_REQ( set_window_rectangles )
564 req->handle = hwnd;
565 req->window.left = rectWindow->left;
566 req->window.top = rectWindow->top;
567 req->window.right = rectWindow->right;
568 req->window.bottom = rectWindow->bottom;
569 req->client.left = rectClient->left;
570 req->client.top = rectClient->top;
571 req->client.right = rectClient->right;
572 req->client.bottom = rectClient->bottom;
573 ret = !wine_server_call( req );
575 SERVER_END_REQ;
576 if (ret)
578 win->rectWindow = *rectWindow;
579 win->rectClient = *rectClient;
581 TRACE( "win %x window (%d,%d)-(%d,%d) client (%d,%d)-(%d,%d)\n", hwnd,
582 rectWindow->left, rectWindow->top, rectWindow->right, rectWindow->bottom,
583 rectClient->left, rectClient->top, rectClient->right, rectClient->bottom );
585 WIN_ReleasePtr( win );
589 /***********************************************************************
590 * WIN_GetRectangles
592 * Get the window and client rectangles.
594 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
596 WND *win = WIN_GetPtr( hwnd );
597 BOOL ret = TRUE;
599 if (!win) return FALSE;
600 if (win == WND_OTHER_PROCESS)
602 SERVER_START_REQ( get_window_rectangles )
604 req->handle = hwnd;
605 if ((ret = !wine_server_call( req )))
607 if (rectWindow)
609 rectWindow->left = reply->window.left;
610 rectWindow->top = reply->window.top;
611 rectWindow->right = reply->window.right;
612 rectWindow->bottom = reply->window.bottom;
614 if (rectClient)
616 rectClient->left = reply->client.left;
617 rectClient->top = reply->client.top;
618 rectClient->right = reply->client.right;
619 rectClient->bottom = reply->client.bottom;
623 SERVER_END_REQ;
625 else
627 if (rectWindow) *rectWindow = win->rectWindow;
628 if (rectClient) *rectClient = win->rectClient;
629 WIN_ReleasePtr( win );
631 return ret;
635 /***********************************************************************
636 * WIN_DestroyWindow
638 * Destroy storage associated to a window. "Internals" p.358
640 LRESULT WIN_DestroyWindow( HWND hwnd )
642 WND *wndPtr;
643 HWND *list;
645 TRACE("%04x\n", hwnd );
647 if (!(hwnd = WIN_IsCurrentThread( hwnd )))
649 ERR( "window doesn't belong to current thread\n" );
650 return 0;
653 /* free child windows */
654 if ((list = WIN_ListChildren( hwnd )))
656 int i;
657 for (i = 0; list[i]; i++)
659 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
660 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
662 HeapFree( GetProcessHeap(), 0, list );
666 * Clear the update region to make sure no WM_PAINT messages will be
667 * generated for this window while processing the WM_NCDESTROY.
669 RedrawWindow( hwnd, NULL, 0,
670 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
673 * Send the WM_NCDESTROY to the window being destroyed.
675 SendMessageA( hwnd, WM_NCDESTROY, 0, 0);
677 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
679 WINPOS_CheckInternalPos( hwnd );
680 if( hwnd == GetCapture()) ReleaseCapture();
682 /* free resources associated with the window */
684 TIMER_RemoveWindowTimers( hwnd );
686 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
688 if (!(wndPtr->dwStyle & WS_CHILD))
690 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
691 if (menu) DestroyMenu( menu );
693 if (wndPtr->hSysMenu)
695 DestroyMenu( wndPtr->hSysMenu );
696 wndPtr->hSysMenu = 0;
698 USER_Driver.pDestroyWindow( hwnd );
699 DCE_FreeWindowDCE( hwnd ); /* Always do this to catch orphaned DCs */
700 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
701 CLASS_RemoveWindow( wndPtr->class );
702 wndPtr->class = NULL;
703 wndPtr->dwMagic = 0; /* Mark it as invalid */
704 WIN_ReleaseWndPtr( wndPtr );
705 return 0;
708 /***********************************************************************
709 * WIN_DestroyThreadWindows
711 * Destroy all children of 'wnd' owned by the current thread.
712 * Return TRUE if something was done.
714 void WIN_DestroyThreadWindows( HWND hwnd )
716 HWND *list;
717 int i;
719 if (!(list = WIN_ListChildren( hwnd ))) return;
720 for (i = 0; list[i]; i++)
722 if (WIN_IsCurrentThread( list[i] ))
723 DestroyWindow( list[i] );
724 else
725 WIN_DestroyThreadWindows( list[i] );
727 HeapFree( GetProcessHeap(), 0, list );
730 /***********************************************************************
731 * WIN_CreateDesktopWindow
733 * Create the desktop window.
735 BOOL WIN_CreateDesktopWindow(void)
737 struct tagCLASS *class;
738 HWND hwndDesktop;
739 INT wndExtra;
740 DWORD clsStyle;
741 WNDPROC winproc;
742 DCE *dce;
743 CREATESTRUCTA cs;
744 RECT rect;
746 TRACE("Creating desktop window\n");
748 if (!WINPOS_CreateInternalPosAtom() ||
749 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
750 &wndExtra, &winproc, &clsStyle, &dce )))
751 return FALSE;
753 pWndDesktop = create_window_handle( 0, 0, LOWORD(DESKTOP_CLASS_ATOM),
754 sizeof(WND) + wndExtra - sizeof(pWndDesktop->wExtra) );
755 if (!pWndDesktop) return FALSE;
756 hwndDesktop = pWndDesktop->hwndSelf;
758 pWndDesktop->tid = 0; /* nobody owns the desktop */
759 pWndDesktop->parent = 0;
760 pWndDesktop->owner = 0;
761 pWndDesktop->class = class;
762 pWndDesktop->text = NULL;
763 pWndDesktop->hrgnUpdate = 0;
764 pWndDesktop->clsStyle = clsStyle;
765 pWndDesktop->dce = NULL;
766 pWndDesktop->pVScroll = NULL;
767 pWndDesktop->pHScroll = NULL;
768 pWndDesktop->helpContext = 0;
769 pWndDesktop->flags = 0;
770 pWndDesktop->hSysMenu = 0;
771 pWndDesktop->winproc = winproc;
772 pWndDesktop->cbWndExtra = wndExtra;
774 cs.lpCreateParams = NULL;
775 cs.hInstance = 0;
776 cs.hMenu = 0;
777 cs.hwndParent = 0;
778 cs.x = 0;
779 cs.y = 0;
780 cs.cx = GetSystemMetrics( SM_CXSCREEN );
781 cs.cy = GetSystemMetrics( SM_CYSCREEN );
782 cs.style = pWndDesktop->dwStyle;
783 cs.dwExStyle = pWndDesktop->dwExStyle;
784 cs.lpszName = NULL;
785 cs.lpszClass = DESKTOP_CLASS_ATOM;
787 SetRect( &rect, 0, 0, cs.cx, cs.cy );
788 WIN_SetRectangles( hwndDesktop, &rect, &rect );
790 SERVER_START_REQ( set_window_info )
792 req->handle = hwndDesktop;
793 req->flags = 0; /* don't set anything, just retrieve */
794 wine_server_call( req );
795 pWndDesktop->dwStyle = reply->old_style;
796 pWndDesktop->dwExStyle = reply->old_ex_style;
797 pWndDesktop->hInstance = (ULONG_PTR)reply->old_instance;
798 pWndDesktop->userdata = (ULONG_PTR)reply->old_user_data;
799 pWndDesktop->wIDmenu = reply->old_id;
801 SERVER_END_REQ;
803 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE ))
805 WIN_ReleaseWndPtr( pWndDesktop );
806 return FALSE;
809 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
810 WIN_ReleaseWndPtr( pWndDesktop );
811 return TRUE;
815 /***********************************************************************
816 * WIN_FixCoordinates
818 * Fix the coordinates - Helper for WIN_CreateWindowEx.
819 * returns default show mode in sw.
820 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
822 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
824 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
825 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
827 if (cs->style & (WS_CHILD | WS_POPUP))
829 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
830 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
832 else /* overlapped window */
834 STARTUPINFOA info;
836 GetStartupInfoA( &info );
838 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
840 /* Never believe Microsoft's documentation... CreateWindowEx doc says
841 * that if an overlapped window is created with WS_VISIBLE style bit
842 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
843 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
844 * reveals that
846 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
847 * 2) it does not ignore the y parameter as the docs claim; instead, it
848 * uses it as second parameter to ShowWindow() unless y is either
849 * CW_USEDEFAULT or CW_USEDEFAULT16.
851 * The fact that we didn't do 2) caused bogus windows pop up when wine
852 * was running apps that were using this obscure feature. Example -
853 * calc.exe that comes with Win98 (only Win98, it's different from
854 * the one that comes with Win95 and NT)
856 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
857 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
858 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
861 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
863 if (info.dwFlags & STARTF_USESIZE)
865 cs->cx = info.dwXSize;
866 cs->cy = info.dwYSize;
868 else /* if no other hint from the app, pick 3/4 of the screen real estate */
870 RECT r;
871 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
872 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
873 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
878 else
880 /* neither x nor cx are default. Check the y values .
881 * In the trace we see Outlook and Outlook Express using
882 * cy set to CW_USEDEFAULT when opening the address book.
884 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16) {
885 RECT r;
886 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
887 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
888 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
893 /***********************************************************************
894 * dump_window_styles
896 static void dump_window_styles( DWORD style, DWORD exstyle )
898 TRACE( "style:" );
899 if(style & WS_POPUP) DPRINTF(" WS_POPUP");
900 if(style & WS_CHILD) DPRINTF(" WS_CHILD");
901 if(style & WS_MINIMIZE) DPRINTF(" WS_MINIMIZE");
902 if(style & WS_VISIBLE) DPRINTF(" WS_VISIBLE");
903 if(style & WS_DISABLED) DPRINTF(" WS_DISABLED");
904 if(style & WS_CLIPSIBLINGS) DPRINTF(" WS_CLIPSIBLINGS");
905 if(style & WS_CLIPCHILDREN) DPRINTF(" WS_CLIPCHILDREN");
906 if(style & WS_MAXIMIZE) DPRINTF(" WS_MAXIMIZE");
907 if((style & WS_CAPTION) == WS_CAPTION) DPRINTF(" WS_CAPTION");
908 else
910 if(style & WS_BORDER) DPRINTF(" WS_BORDER");
911 if(style & WS_DLGFRAME) DPRINTF(" WS_DLGFRAME");
913 if(style & WS_VSCROLL) DPRINTF(" WS_VSCROLL");
914 if(style & WS_HSCROLL) DPRINTF(" WS_HSCROLL");
915 if(style & WS_SYSMENU) DPRINTF(" WS_SYSMENU");
916 if(style & WS_THICKFRAME) DPRINTF(" WS_THICKFRAME");
917 if(style & WS_GROUP) DPRINTF(" WS_GROUP");
918 if(style & WS_TABSTOP) DPRINTF(" WS_TABSTOP");
919 if(style & WS_MINIMIZEBOX) DPRINTF(" WS_MINIMIZEBOX");
920 if(style & WS_MAXIMIZEBOX) DPRINTF(" WS_MAXIMIZEBOX");
922 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
923 #define DUMPED_STYLES \
924 (WS_POPUP | \
925 WS_CHILD | \
926 WS_MINIMIZE | \
927 WS_VISIBLE | \
928 WS_DISABLED | \
929 WS_CLIPSIBLINGS | \
930 WS_CLIPCHILDREN | \
931 WS_MAXIMIZE | \
932 WS_BORDER | \
933 WS_DLGFRAME | \
934 WS_VSCROLL | \
935 WS_HSCROLL | \
936 WS_SYSMENU | \
937 WS_THICKFRAME | \
938 WS_GROUP | \
939 WS_TABSTOP | \
940 WS_MINIMIZEBOX | \
941 WS_MAXIMIZEBOX)
943 if(style & ~DUMPED_STYLES) DPRINTF(" %08lx", style & ~DUMPED_STYLES);
944 DPRINTF("\n");
945 #undef DUMPED_STYLES
947 TRACE( "exstyle:" );
948 if(exstyle & WS_EX_DLGMODALFRAME) DPRINTF(" WS_EX_DLGMODALFRAME");
949 if(exstyle & WS_EX_DRAGDETECT) DPRINTF(" WS_EX_DRAGDETECT");
950 if(exstyle & WS_EX_NOPARENTNOTIFY) DPRINTF(" WS_EX_NOPARENTNOTIFY");
951 if(exstyle & WS_EX_TOPMOST) DPRINTF(" WS_EX_TOPMOST");
952 if(exstyle & WS_EX_ACCEPTFILES) DPRINTF(" WS_EX_ACCEPTFILES");
953 if(exstyle & WS_EX_TRANSPARENT) DPRINTF(" WS_EX_TRANSPARENT");
954 if(exstyle & WS_EX_MDICHILD) DPRINTF(" WS_EX_MDICHILD");
955 if(exstyle & WS_EX_TOOLWINDOW) DPRINTF(" WS_EX_TOOLWINDOW");
956 if(exstyle & WS_EX_WINDOWEDGE) DPRINTF(" WS_EX_WINDOWEDGE");
957 if(exstyle & WS_EX_CLIENTEDGE) DPRINTF(" WS_EX_CLIENTEDGE");
958 if(exstyle & WS_EX_CONTEXTHELP) DPRINTF(" WS_EX_CONTEXTHELP");
959 if(exstyle & WS_EX_RIGHT) DPRINTF(" WS_EX_RIGHT");
960 if(exstyle & WS_EX_RTLREADING) DPRINTF(" WS_EX_RTLREADING");
961 if(exstyle & WS_EX_LEFTSCROLLBAR) DPRINTF(" WS_EX_LEFTSCROLLBAR");
962 if(exstyle & WS_EX_CONTROLPARENT) DPRINTF(" WS_EX_CONTROLPARENT");
963 if(exstyle & WS_EX_STATICEDGE) DPRINTF(" WS_EX_STATICEDGE");
964 if(exstyle & WS_EX_APPWINDOW) DPRINTF(" WS_EX_APPWINDOW");
965 if(exstyle & WS_EX_LAYERED) DPRINTF(" WS_EX_LAYERED");
967 #define DUMPED_EX_STYLES \
968 (WS_EX_DLGMODALFRAME | \
969 WS_EX_DRAGDETECT | \
970 WS_EX_NOPARENTNOTIFY | \
971 WS_EX_TOPMOST | \
972 WS_EX_ACCEPTFILES | \
973 WS_EX_TRANSPARENT | \
974 WS_EX_MDICHILD | \
975 WS_EX_TOOLWINDOW | \
976 WS_EX_WINDOWEDGE | \
977 WS_EX_CLIENTEDGE | \
978 WS_EX_CONTEXTHELP | \
979 WS_EX_RIGHT | \
980 WS_EX_RTLREADING | \
981 WS_EX_LEFTSCROLLBAR | \
982 WS_EX_CONTROLPARENT | \
983 WS_EX_STATICEDGE | \
984 WS_EX_APPWINDOW | \
985 WS_EX_LAYERED)
987 if(exstyle & ~DUMPED_EX_STYLES) DPRINTF(" %08lx", exstyle & ~DUMPED_EX_STYLES);
988 DPRINTF("\n");
989 #undef DUMPED_EX_STYLES
993 /***********************************************************************
994 * WIN_CreateWindowEx
996 * Implementation of CreateWindowEx().
998 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
999 WINDOWPROCTYPE type )
1001 INT sw = SW_SHOW;
1002 struct tagCLASS *classPtr;
1003 WND *wndPtr;
1004 HWND hwnd, parent, owner;
1005 INT wndExtra;
1006 DWORD clsStyle;
1007 WNDPROC winproc;
1008 DCE *dce;
1009 BOOL unicode = (type == WIN_PROC_32W);
1011 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%04x menu=%04x inst=%08x params=%p\n",
1012 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
1013 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszClass) : debugstr_a(cs->lpszClass),
1014 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
1015 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
1017 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
1019 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
1020 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
1022 /* Find the parent window */
1024 parent = GetDesktopWindow();
1025 owner = 0;
1027 if (cs->hwndParent == HWND_MESSAGE)
1029 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
1030 * message window (style: WS_POPUP|WS_DISABLED)
1032 FIXME("Parent is HWND_MESSAGE\n");
1034 else if (cs->hwndParent)
1036 /* Make sure parent is valid */
1037 if (!IsWindow( cs->hwndParent ))
1039 WARN("Bad parent %04x\n", cs->hwndParent );
1040 return 0;
1042 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1043 parent = WIN_GetFullHandle(cs->hwndParent);
1044 else
1045 owner = GetAncestor( cs->hwndParent, GA_ROOT );
1047 else if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1049 WARN("No parent for child window\n" );
1050 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1053 /* Find the window class */
1054 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
1055 &wndExtra, &winproc, &clsStyle, &dce )))
1057 WARN("Bad class '%s'\n", cs->lpszClass );
1058 return 0;
1061 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
1063 /* Correct the window style - stage 1
1065 * These are patches that appear to affect both the style loaded into the
1066 * WIN structure and passed in the CreateStruct to the WM_CREATE etc.
1068 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1069 * why does the user get to set it?
1072 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
1073 * tested for WS_POPUP
1075 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
1076 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
1077 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
1078 cs->dwExStyle |= WS_EX_WINDOWEDGE;
1079 else
1080 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
1082 /* Create the window structure */
1084 if (!(wndPtr = create_window_handle( parent, owner, classAtom,
1085 sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
1087 TRACE("out of memory\n" );
1088 return 0;
1090 hwnd = wndPtr->hwndSelf;
1092 /* Fill the window structure */
1094 wndPtr->tid = GetCurrentThreadId();
1095 wndPtr->owner = owner;
1096 wndPtr->parent = parent;
1097 wndPtr->class = classPtr;
1098 wndPtr->winproc = winproc;
1099 wndPtr->hInstance = cs->hInstance;
1100 wndPtr->text = NULL;
1101 wndPtr->hrgnUpdate = 0;
1102 wndPtr->hrgnWnd = 0;
1103 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1104 wndPtr->dwExStyle = cs->dwExStyle;
1105 wndPtr->clsStyle = clsStyle;
1106 wndPtr->wIDmenu = 0;
1107 wndPtr->helpContext = 0;
1108 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
1109 wndPtr->pVScroll = NULL;
1110 wndPtr->pHScroll = NULL;
1111 wndPtr->userdata = 0;
1112 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
1113 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
1114 wndPtr->cbWndExtra = wndExtra;
1116 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
1118 /* Correct the window style - stage 2 */
1120 if (!(cs->style & WS_CHILD))
1122 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1123 if (!(cs->style & WS_POPUP))
1125 wndPtr->dwStyle |= WS_CAPTION;
1126 wndPtr->flags |= WIN_NEED_SIZE;
1129 SERVER_START_REQ( set_window_info )
1131 req->handle = hwnd;
1132 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE;
1133 req->style = wndPtr->dwStyle;
1134 req->ex_style = wndPtr->dwExStyle;
1135 req->instance = (void *)wndPtr->hInstance;
1136 wine_server_call( req );
1138 SERVER_END_REQ;
1140 /* Get class or window DC if needed */
1142 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
1143 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
1144 else wndPtr->dce = NULL;
1146 /* Set the window menu */
1148 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
1150 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
1151 else
1153 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
1154 if (menuName)
1156 if (HIWORD(cs->hInstance))
1157 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1158 else
1159 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
1161 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
1165 else SetWindowLongW( hwnd, GWL_ID, (UINT)cs->hMenu );
1166 WIN_ReleaseWndPtr( wndPtr );
1168 if (!USER_Driver.pCreateWindow( hwnd, cs, unicode))
1170 WIN_DestroyWindow( hwnd );
1171 return 0;
1174 /* Notify the parent window only */
1176 send_parent_notify( hwnd, WM_CREATE );
1177 if (!IsWindow( hwnd )) return 0;
1179 if (cs->style & WS_VISIBLE)
1181 /* in case WS_VISIBLE got set in the meantime */
1182 if (!(wndPtr = WIN_GetPtr( hwnd ))) return 0;
1183 WIN_SetStyle( hwnd, wndPtr->dwStyle & ~WS_VISIBLE );
1184 WIN_ReleasePtr( wndPtr );
1185 ShowWindow( hwnd, sw );
1188 /* Call WH_SHELL hook */
1190 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1191 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0 );
1193 TRACE("created window %04x\n", hwnd);
1194 return hwnd;
1198 /***********************************************************************
1199 * CreateWindow (USER.41)
1201 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1202 DWORD style, INT16 x, INT16 y, INT16 width,
1203 INT16 height, HWND16 parent, HMENU16 menu,
1204 HINSTANCE16 instance, LPVOID data )
1206 return CreateWindowEx16( 0, className, windowName, style,
1207 x, y, width, height, parent, menu, instance, data );
1211 /***********************************************************************
1212 * CreateWindowEx (USER.452)
1214 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1215 LPCSTR windowName, DWORD style, INT16 x,
1216 INT16 y, INT16 width, INT16 height,
1217 HWND16 parent, HMENU16 menu,
1218 HINSTANCE16 instance, LPVOID data )
1220 ATOM classAtom;
1221 CREATESTRUCTA cs;
1222 char buffer[256];
1224 /* Find the class atom */
1226 if (HIWORD(className))
1228 if (!(classAtom = GlobalFindAtomA( className )))
1230 ERR( "bad class name %s\n", debugstr_a(className) );
1231 return 0;
1234 else
1236 classAtom = LOWORD(className);
1237 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1239 ERR( "bad atom %x\n", classAtom);
1240 return 0;
1242 className = buffer;
1245 /* Fix the coordinates */
1247 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1248 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1249 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1250 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1252 /* Create the window */
1254 cs.lpCreateParams = data;
1255 cs.hInstance = (HINSTANCE)instance;
1256 cs.hMenu = (HMENU)menu;
1257 cs.hwndParent = WIN_Handle32( parent );
1258 cs.style = style;
1259 cs.lpszName = windowName;
1260 cs.lpszClass = className;
1261 cs.dwExStyle = exStyle;
1263 return HWND_16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
1267 /***********************************************************************
1268 * CreateWindowExA (USER32.@)
1270 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1271 LPCSTR windowName, DWORD style, INT x,
1272 INT y, INT width, INT height,
1273 HWND parent, HMENU menu,
1274 HINSTANCE instance, LPVOID data )
1276 ATOM classAtom;
1277 CREATESTRUCTA cs;
1278 char buffer[256];
1280 if(!instance)
1281 instance=GetModuleHandleA(NULL);
1283 if(exStyle & WS_EX_MDICHILD)
1284 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1286 /* Find the class atom */
1288 if (HIWORD(className))
1290 if (!(classAtom = GlobalFindAtomA( className )))
1292 ERR( "bad class name %s\n", debugstr_a(className) );
1293 return 0;
1296 else
1298 classAtom = LOWORD(className);
1299 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1301 ERR( "bad atom %x\n", classAtom);
1302 return 0;
1304 className = buffer;
1307 /* Create the window */
1309 cs.lpCreateParams = data;
1310 cs.hInstance = instance;
1311 cs.hMenu = menu;
1312 cs.hwndParent = parent;
1313 cs.x = x;
1314 cs.y = y;
1315 cs.cx = width;
1316 cs.cy = height;
1317 cs.style = style;
1318 cs.lpszName = windowName;
1319 cs.lpszClass = className;
1320 cs.dwExStyle = exStyle;
1322 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1326 /***********************************************************************
1327 * CreateWindowExW (USER32.@)
1329 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1330 LPCWSTR windowName, DWORD style, INT x,
1331 INT y, INT width, INT height,
1332 HWND parent, HMENU menu,
1333 HINSTANCE instance, LPVOID data )
1335 ATOM classAtom;
1336 CREATESTRUCTW cs;
1337 WCHAR buffer[256];
1339 if(!instance)
1340 instance=GetModuleHandleA(NULL);
1342 if(exStyle & WS_EX_MDICHILD)
1343 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1345 /* Find the class atom */
1347 if (HIWORD(className))
1349 if (!(classAtom = GlobalFindAtomW( className )))
1351 ERR( "bad class name %s\n", debugstr_w(className) );
1352 return 0;
1355 else
1357 classAtom = LOWORD(className);
1358 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1360 ERR( "bad atom %x\n", classAtom);
1361 return 0;
1363 className = buffer;
1366 /* Create the window */
1368 cs.lpCreateParams = data;
1369 cs.hInstance = instance;
1370 cs.hMenu = menu;
1371 cs.hwndParent = parent;
1372 cs.x = x;
1373 cs.y = y;
1374 cs.cx = width;
1375 cs.cy = height;
1376 cs.style = style;
1377 cs.lpszName = windowName;
1378 cs.lpszClass = className;
1379 cs.dwExStyle = exStyle;
1381 /* Note: we rely on the fact that CREATESTRUCTA and */
1382 /* CREATESTRUCTW have the same layout. */
1383 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1387 /***********************************************************************
1388 * WIN_SendDestroyMsg
1390 static void WIN_SendDestroyMsg( HWND hwnd )
1392 GUITHREADINFO info;
1394 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1396 if (hwnd == info.hwndCaret) DestroyCaret();
1398 if (USER_Driver.pResetSelectionOwner)
1399 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1402 * Send the WM_DESTROY to the window.
1404 SendMessageA( hwnd, WM_DESTROY, 0, 0);
1407 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1408 * make sure that the window still exists when we come back.
1410 if (IsWindow(hwnd))
1412 HWND* pWndArray;
1413 int i;
1415 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1417 /* start from the end (FIXME: is this needed?) */
1418 for (i = 0; pWndArray[i]; i++) ;
1420 while (--i >= 0)
1422 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1424 HeapFree( GetProcessHeap(), 0, pWndArray );
1426 else
1427 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1431 /***********************************************************************
1432 * DestroyWindow (USER32.@)
1434 BOOL WINAPI DestroyWindow( HWND hwnd )
1436 BOOL is_child;
1437 HWND h;
1439 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1441 SetLastError( ERROR_ACCESS_DENIED );
1442 return FALSE;
1445 TRACE("(%04x)\n", hwnd);
1447 /* Look whether the focus is within the tree of windows we will
1448 * be destroying.
1450 h = GetFocus();
1451 if (h == hwnd || IsChild( hwnd, h ))
1453 HWND parent = GetAncestor( hwnd, GA_PARENT );
1454 if (parent == GetDesktopWindow()) parent = 0;
1455 SetFocus( parent );
1458 /* Call hooks */
1460 if( HOOK_CallHooksA( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0L) ) return FALSE;
1462 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1464 if (is_child)
1466 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1467 send_parent_notify( hwnd, WM_DESTROY );
1469 else if (!GetWindow( hwnd, GW_OWNER ))
1471 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L );
1472 /* FIXME: clean up palette - see "Internals" p.352 */
1475 if (!IsWindow(hwnd)) return TRUE;
1477 if (USER_Driver.pResetSelectionOwner)
1478 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1480 /* Hide the window */
1482 if (!ShowWindow( hwnd, SW_HIDE ))
1484 if (hwnd == GetActiveWindow()) WINPOS_ActivateOtherWindow( hwnd );
1486 if (!IsWindow(hwnd)) return TRUE;
1488 /* Recursively destroy owned windows */
1490 if (!is_child)
1492 for (;;)
1494 int i, got_one = 0;
1495 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1496 if (list)
1498 for (i = 0; list[i]; i++)
1500 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1501 if (WIN_IsCurrentThread( list[i] ))
1503 DestroyWindow( list[i] );
1504 got_one = 1;
1505 continue;
1507 WIN_SetOwner( list[i], 0 );
1509 HeapFree( GetProcessHeap(), 0, list );
1511 if (!got_one) break;
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)
1869 HWND parent = GetAncestor( hwnd, GA_PARENT );
1870 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1871 return (LONG)parent;
1874 if (!(wndPtr = WIN_GetPtr( hwnd )))
1876 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1877 return 0;
1880 if (wndPtr == WND_OTHER_PROCESS)
1882 if (offset >= 0)
1884 if (IsWindow(hwnd))
1885 FIXME( "(%d) not supported on other process window %x\n", offset, hwnd );
1886 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1887 return 0;
1889 if (offset == GWL_WNDPROC)
1891 SetLastError( ERROR_ACCESS_DENIED );
1892 return 0;
1894 SERVER_START_REQ( set_window_info )
1896 req->handle = hwnd;
1897 req->flags = 0; /* don't set anything, just retrieve */
1898 if (!wine_server_call_err( req ))
1900 switch(offset)
1902 case GWL_STYLE: retvalue = reply->old_style; break;
1903 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1904 case GWL_ID: retvalue = reply->old_id; break;
1905 case GWL_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1906 case GWL_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
1907 default:
1908 SetLastError( ERROR_INVALID_INDEX );
1909 break;
1913 SERVER_END_REQ;
1914 return retvalue;
1917 /* now we have a valid wndPtr */
1919 if (offset >= 0)
1921 if (offset > wndPtr->cbWndExtra - sizeof(LONG))
1924 * Some programs try to access last element from 16 bit
1925 * code using illegal offset value. Hopefully this is
1926 * what those programs really expect.
1928 if (type == WIN_PROC_16 &&
1929 wndPtr->cbWndExtra >= 4 &&
1930 offset == wndPtr->cbWndExtra - sizeof(WORD))
1932 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
1934 ERR( "- replaced invalid offset %d with %d\n",
1935 offset, offset2 );
1937 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset2);
1938 WIN_ReleasePtr( wndPtr );
1939 return retvalue;
1941 WARN("Invalid offset %d\n", offset );
1942 WIN_ReleasePtr( wndPtr );
1943 SetLastError( ERROR_INVALID_INDEX );
1944 return 0;
1946 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1947 /* Special case for dialog window procedure */
1948 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1949 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1950 WIN_ReleasePtr( wndPtr );
1951 return retvalue;
1954 switch(offset)
1956 case GWL_USERDATA: retvalue = wndPtr->userdata; break;
1957 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1958 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1959 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu; break;
1960 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc, type ); break;
1961 case GWL_HINSTANCE: retvalue = wndPtr->hInstance; break;
1962 default:
1963 WARN("Unknown offset %d\n", offset );
1964 SetLastError( ERROR_INVALID_INDEX );
1965 break;
1967 WIN_ReleasePtr(wndPtr);
1968 return retvalue;
1972 /**********************************************************************
1973 * WIN_SetWindowLong
1975 * Helper function for SetWindowLong().
1977 * 0 is the failure code. However, in the case of failure SetLastError
1978 * must be set to distinguish between a 0 return value and a failure.
1980 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1981 WINDOWPROCTYPE type )
1983 LONG retval = 0;
1984 WND *wndPtr;
1986 TRACE( "%x %d %lx %x\n", hwnd, offset, newval, type );
1988 if (!WIN_IsCurrentProcess( hwnd ))
1990 if (offset == GWL_WNDPROC)
1992 SetLastError( ERROR_ACCESS_DENIED );
1993 return 0;
1995 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
1998 wndPtr = WIN_GetPtr( hwnd );
1999 if (wndPtr->hwndSelf == GetDesktopWindow())
2001 /* can't change anything on the desktop window */
2002 WIN_ReleasePtr( wndPtr );
2003 SetLastError( ERROR_ACCESS_DENIED );
2004 return 0;
2007 if (offset >= 0)
2009 LONG *ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
2010 if (offset > wndPtr->cbWndExtra - sizeof(LONG))
2012 WARN("Invalid offset %d\n", offset );
2013 WIN_ReleasePtr( wndPtr );
2014 SetLastError( ERROR_INVALID_INDEX );
2015 return 0;
2017 /* Special case for dialog window procedure */
2018 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2020 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
2021 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
2022 type, WIN_PROC_WINDOW );
2023 WIN_ReleasePtr( wndPtr );
2024 return retval;
2026 retval = *ptr;
2027 *ptr = newval;
2028 WIN_ReleasePtr( wndPtr );
2030 else
2032 STYLESTRUCT style;
2033 BOOL ok;
2035 /* first some special cases */
2036 switch( offset )
2038 case GWL_STYLE:
2039 case GWL_EXSTYLE:
2040 style.styleOld = wndPtr->dwStyle;
2041 style.styleNew = newval;
2042 WIN_ReleasePtr( wndPtr );
2043 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
2044 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
2045 newval = style.styleNew;
2046 break;
2047 case GWL_HWNDPARENT:
2048 if (wndPtr->parent == GetDesktopWindow())
2050 WIN_ReleasePtr( wndPtr );
2051 return (LONG)WIN_SetOwner( hwnd, (HWND)newval );
2053 else
2055 WIN_ReleasePtr( wndPtr );
2056 return (LONG)SetParent( hwnd, (HWND)newval );
2058 case GWL_WNDPROC:
2059 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2060 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
2061 type, WIN_PROC_WINDOW );
2062 WIN_ReleasePtr( wndPtr );
2063 return retval;
2064 case GWL_ID:
2065 case GWL_HINSTANCE:
2066 case GWL_USERDATA:
2067 break;
2068 default:
2069 WIN_ReleasePtr( wndPtr );
2070 WARN("Invalid offset %d\n", offset );
2071 SetLastError( ERROR_INVALID_INDEX );
2072 return 0;
2075 SERVER_START_REQ( set_window_info )
2077 req->handle = hwnd;
2078 switch(offset)
2080 case GWL_STYLE:
2081 req->flags = SET_WIN_STYLE;
2082 req->style = newval;
2083 break;
2084 case GWL_EXSTYLE:
2085 req->flags = SET_WIN_EXSTYLE;
2086 req->ex_style = newval;
2087 break;
2088 case GWL_ID:
2089 req->flags = SET_WIN_ID;
2090 req->id = newval;
2091 break;
2092 case GWL_HINSTANCE:
2093 req->flags = SET_WIN_INSTANCE;
2094 req->instance = (void *)newval;
2095 break;
2096 case GWL_USERDATA:
2097 req->flags = SET_WIN_USERDATA;
2098 req->user_data = (void *)newval;
2099 break;
2101 if ((ok = !wine_server_call_err( req )))
2103 switch(offset)
2105 case GWL_STYLE:
2106 wndPtr->dwStyle = newval;
2107 retval = reply->old_style;
2108 break;
2109 case GWL_EXSTYLE:
2110 wndPtr->dwExStyle = newval;
2111 retval = reply->old_ex_style;
2112 break;
2113 case GWL_ID:
2114 wndPtr->wIDmenu = newval;
2115 retval = reply->old_id;
2116 break;
2117 case GWL_HINSTANCE:
2118 wndPtr->hInstance = newval;
2119 retval = (HINSTANCE)reply->old_instance;
2120 break;
2121 case GWL_USERDATA:
2122 wndPtr->userdata = newval;
2123 retval = (ULONG_PTR)reply->old_user_data;
2124 break;
2128 SERVER_END_REQ;
2129 WIN_ReleasePtr( wndPtr );
2131 if (!ok) return 0;
2133 if (offset == GWL_STYLE && USER_Driver.pSetWindowStyle)
2134 USER_Driver.pSetWindowStyle( hwnd, retval );
2136 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2137 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2140 return retval;
2144 /**********************************************************************
2145 * GetWindowLong (USER.135)
2147 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2149 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
2153 /**********************************************************************
2154 * GetWindowLongA (USER32.@)
2156 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2158 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2162 /**********************************************************************
2163 * GetWindowLongW (USER32.@)
2165 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2167 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2171 /**********************************************************************
2172 * SetWindowLong (USER.136)
2174 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2176 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
2180 /**********************************************************************
2181 * SetWindowLongA (USER32.@)
2183 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2185 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2189 /**********************************************************************
2190 * SetWindowLongW (USER32.@) Set window attribute
2192 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2193 * value in a window's extra memory.
2195 * The _hwnd_ parameter specifies the window. is the handle to a
2196 * window that has extra memory. The _newval_ parameter contains the
2197 * new attribute or extra memory value. If positive, the _offset_
2198 * parameter is the byte-addressed location in the window's extra
2199 * memory to set. If negative, _offset_ specifies the window
2200 * attribute to set, and should be one of the following values:
2202 * GWL_EXSTYLE The window's extended window style
2204 * GWL_STYLE The window's window style.
2206 * GWL_WNDPROC Pointer to the window's window procedure.
2208 * GWL_HINSTANCE The window's pplication instance handle.
2210 * GWL_ID The window's identifier.
2212 * GWL_USERDATA The window's user-specified data.
2214 * If the window is a dialog box, the _offset_ parameter can be one of
2215 * the following values:
2217 * DWL_DLGPROC The address of the window's dialog box procedure.
2219 * DWL_MSGRESULT The return value of a message
2220 * that the dialog box procedure processed.
2222 * DWL_USER Application specific information.
2224 * RETURNS
2226 * If successful, returns the previous value located at _offset_. Otherwise,
2227 * returns 0.
2229 * NOTES
2231 * Extra memory for a window class is specified by a nonzero cbWndExtra
2232 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2233 * time of class creation.
2235 * Using GWL_WNDPROC to set a new window procedure effectively creates
2236 * a window subclass. Use CallWindowProc() in the new windows procedure
2237 * to pass messages to the superclass's window procedure.
2239 * The user data is reserved for use by the application which created
2240 * the window.
2242 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2243 * instead, call the EnableWindow() function to change the window's
2244 * disabled state.
2246 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2247 * SetParent() instead.
2249 * Win95:
2250 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2251 * it sends WM_STYLECHANGING before changing the settings
2252 * and WM_STYLECHANGED afterwards.
2253 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2255 LONG WINAPI SetWindowLongW(
2256 HWND hwnd, /* [in] window to alter */
2257 INT offset, /* [in] offset, in bytes, of location to alter */
2258 LONG newval /* [in] new value of location */
2260 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2264 /*******************************************************************
2265 * GetWindowTextA (USER32.@)
2267 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2269 WCHAR *buffer;
2271 if (WIN_IsCurrentProcess( hwnd ))
2272 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2274 /* when window belongs to other process, don't send a message */
2275 if (nMaxCount <= 0) return 0;
2276 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2277 get_server_window_text( hwnd, buffer, nMaxCount );
2278 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2279 lpString[nMaxCount-1] = 0;
2280 HeapFree( GetProcessHeap(), 0, buffer );
2281 return strlen(lpString);
2285 /*******************************************************************
2286 * InternalGetWindowText (USER32.@)
2288 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2290 WND *win;
2292 if (nMaxCount <= 0) return 0;
2293 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2294 if (win != WND_OTHER_PROCESS)
2296 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2297 else lpString[0] = 0;
2298 WIN_ReleasePtr( win );
2300 else
2302 get_server_window_text( hwnd, lpString, nMaxCount );
2304 return strlenW(lpString);
2308 /*******************************************************************
2309 * GetWindowTextW (USER32.@)
2311 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2313 if (WIN_IsCurrentProcess( hwnd ))
2314 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2316 /* when window belongs to other process, don't send a message */
2317 if (nMaxCount <= 0) return 0;
2318 get_server_window_text( hwnd, lpString, nMaxCount );
2319 return strlenW(lpString);
2323 /*******************************************************************
2324 * SetWindowText (USER32.@)
2325 * SetWindowTextA (USER32.@)
2327 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2329 if (!WIN_IsCurrentProcess( hwnd ))
2331 FIXME( "cannot set text %s of other process window %x\n", debugstr_a(lpString), hwnd );
2332 SetLastError( ERROR_ACCESS_DENIED );
2333 return FALSE;
2335 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2339 /*******************************************************************
2340 * SetWindowTextW (USER32.@)
2342 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2344 if (!WIN_IsCurrentProcess( hwnd ))
2346 FIXME( "cannot set text %s of other process window %x\n", debugstr_w(lpString), hwnd );
2347 SetLastError( ERROR_ACCESS_DENIED );
2348 return FALSE;
2350 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2354 /*******************************************************************
2355 * GetWindowTextLengthA (USER32.@)
2357 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2359 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2362 /*******************************************************************
2363 * GetWindowTextLengthW (USER32.@)
2365 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2367 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2371 /*******************************************************************
2372 * IsWindow (USER32.@)
2374 BOOL WINAPI IsWindow( HWND hwnd )
2376 WND *ptr;
2377 BOOL ret;
2379 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2381 if (ptr != WND_OTHER_PROCESS)
2383 WIN_ReleasePtr( ptr );
2384 return TRUE;
2387 /* check other processes */
2388 SERVER_START_REQ( get_window_info )
2390 req->handle = hwnd;
2391 ret = !wine_server_call_err( req );
2393 SERVER_END_REQ;
2394 return ret;
2398 /***********************************************************************
2399 * GetWindowThreadProcessId (USER32.@)
2401 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2403 WND *ptr;
2404 DWORD tid = 0;
2406 if (!(ptr = WIN_GetPtr( hwnd )))
2408 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2409 return 0;
2412 if (ptr != WND_OTHER_PROCESS)
2414 /* got a valid window */
2415 tid = ptr->tid;
2416 if (process) *process = GetCurrentProcessId();
2417 WIN_ReleasePtr( ptr );
2418 return tid;
2421 /* check other processes */
2422 SERVER_START_REQ( get_window_info )
2424 req->handle = hwnd;
2425 if (!wine_server_call_err( req ))
2427 tid = (DWORD)reply->tid;
2428 if (process) *process = (DWORD)reply->pid;
2431 SERVER_END_REQ;
2432 return tid;
2436 /*****************************************************************
2437 * GetParent (USER32.@)
2439 HWND WINAPI GetParent( HWND hwnd )
2441 WND *wndPtr;
2442 HWND retvalue = 0;
2444 if (!(wndPtr = WIN_GetPtr( hwnd )))
2446 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2447 return 0;
2449 if (wndPtr == WND_OTHER_PROCESS)
2451 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2452 if (style & (WS_POPUP | WS_CHILD))
2454 SERVER_START_REQ( get_window_tree )
2456 req->handle = hwnd;
2457 if (!wine_server_call_err( req ))
2459 if (style & WS_POPUP) retvalue = reply->owner;
2460 else if (style & WS_CHILD) retvalue = reply->parent;
2463 SERVER_END_REQ;
2466 else
2468 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2469 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2470 WIN_ReleasePtr( wndPtr );
2472 return retvalue;
2476 /*****************************************************************
2477 * GetAncestor (USER32.@)
2479 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2481 WND *win;
2482 HWND *list, ret = 0;
2484 switch(type)
2486 case GA_PARENT:
2487 if (!(win = WIN_GetPtr( hwnd )))
2489 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2490 return 0;
2492 if (win != WND_OTHER_PROCESS)
2494 ret = win->parent;
2495 WIN_ReleasePtr( win );
2497 else /* need to query the server */
2499 SERVER_START_REQ( get_window_tree )
2501 req->handle = hwnd;
2502 if (!wine_server_call_err( req )) ret = reply->parent;
2504 SERVER_END_REQ;
2506 break;
2508 case GA_ROOT:
2509 if (!(list = WIN_ListParents( hwnd ))) return 0;
2511 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2512 else
2514 int count = 2;
2515 while (list[count]) count++;
2516 ret = list[count - 2]; /* get the one before the desktop */
2518 HeapFree( GetProcessHeap(), 0, list );
2519 break;
2521 case GA_ROOTOWNER:
2522 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2523 for (;;)
2525 HWND parent = GetParent( ret );
2526 if (!parent) break;
2527 ret = parent;
2529 break;
2531 return ret;
2535 /*****************************************************************
2536 * SetParent (USER32.@)
2538 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2540 WND *wndPtr;
2541 HWND retvalue, full_handle;
2542 BOOL was_visible;
2544 if (!parent) parent = GetDesktopWindow();
2545 else parent = WIN_GetFullHandle( parent );
2547 if (!IsWindow( parent ))
2549 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2550 return 0;
2553 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2554 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2556 hwnd = full_handle;
2558 if (USER_Driver.pSetParent)
2559 return USER_Driver.pSetParent( hwnd, parent );
2561 /* Windows hides the window first, then shows it again
2562 * including the WM_SHOWWINDOW messages and all */
2563 was_visible = ShowWindow( hwnd, SW_HIDE );
2565 if (!IsWindow( parent )) return 0;
2566 if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return 0;
2568 retvalue = wndPtr->parent; /* old parent */
2569 if (parent != retvalue)
2571 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2573 if (parent != GetDesktopWindow()) /* a child window */
2575 if (!(wndPtr->dwStyle & WS_CHILD))
2577 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
2578 if (menu) DestroyMenu( menu );
2582 WIN_ReleasePtr( wndPtr );
2584 /* SetParent additionally needs to make hwnd the topmost window
2585 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2586 WM_WINDOWPOSCHANGED notification messages.
2588 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2589 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2590 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2591 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2592 return retvalue;
2596 /*******************************************************************
2597 * IsChild (USER32.@)
2599 BOOL WINAPI IsChild( HWND parent, HWND child )
2601 HWND *list = WIN_ListParents( child );
2602 int i;
2603 BOOL ret;
2605 if (!list) return FALSE;
2606 parent = WIN_GetFullHandle( parent );
2607 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2608 ret = (list[i] != 0);
2609 HeapFree( GetProcessHeap(), 0, list );
2610 return ret;
2614 /***********************************************************************
2615 * IsWindowVisible (USER32.@)
2617 BOOL WINAPI IsWindowVisible( HWND hwnd )
2619 HWND *list;
2620 BOOL retval;
2621 int i;
2623 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2624 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2625 for (i = 0; list[i]; i++)
2626 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2627 retval = !list[i];
2628 HeapFree( GetProcessHeap(), 0, list );
2629 return retval;
2633 /***********************************************************************
2634 * WIN_IsWindowDrawable
2636 * hwnd is drawable when it is visible, all parents are not
2637 * minimized, and it is itself not minimized unless we are
2638 * trying to draw its default class icon.
2640 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2642 HWND *list;
2643 BOOL retval;
2644 int i;
2645 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2647 if (!(style & WS_VISIBLE)) return FALSE;
2648 if ((style & WS_MINIMIZE) && icon && GetClassLongA( hwnd, GCL_HICON )) return FALSE;
2650 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2651 for (i = 0; list[i]; i++)
2652 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2653 break;
2654 retval = !list[i];
2655 HeapFree( GetProcessHeap(), 0, list );
2656 return retval;
2660 /*******************************************************************
2661 * GetTopWindow (USER32.@)
2663 HWND WINAPI GetTopWindow( HWND hwnd )
2665 if (!hwnd) hwnd = GetDesktopWindow();
2666 return GetWindow( hwnd, GW_CHILD );
2670 /*******************************************************************
2671 * GetWindow (USER32.@)
2673 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2675 HWND retval = 0;
2677 if (rel == GW_OWNER) /* this one may be available locally */
2679 WND *wndPtr = WIN_GetPtr( hwnd );
2680 if (!wndPtr)
2682 SetLastError( ERROR_INVALID_HANDLE );
2683 return 0;
2685 if (wndPtr != WND_OTHER_PROCESS)
2687 retval = wndPtr->owner;
2688 WIN_ReleasePtr( wndPtr );
2689 return retval;
2691 /* else fall through to server call */
2694 SERVER_START_REQ( get_window_tree )
2696 req->handle = hwnd;
2697 if (!wine_server_call_err( req ))
2699 switch(rel)
2701 case GW_HWNDFIRST:
2702 retval = reply->first_sibling;
2703 break;
2704 case GW_HWNDLAST:
2705 retval = reply->last_sibling;
2706 break;
2707 case GW_HWNDNEXT:
2708 retval = reply->next_sibling;
2709 break;
2710 case GW_HWNDPREV:
2711 retval = reply->prev_sibling;
2712 break;
2713 case GW_OWNER:
2714 retval = reply->owner;
2715 break;
2716 case GW_CHILD:
2717 retval = reply->first_child;
2718 break;
2722 SERVER_END_REQ;
2723 return retval;
2727 /***********************************************************************
2728 * WIN_InternalShowOwnedPopups
2730 * Internal version of ShowOwnedPopups; Wine functions should use this
2731 * to avoid interfering with application calls to ShowOwnedPopups
2732 * and to make sure the application can't prevent showing/hiding.
2734 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2738 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2740 int count = 0;
2741 WND *pWnd;
2742 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2744 if (!win_array) return TRUE;
2747 * Show windows Lowest first, Highest last to preserve Z-Order
2749 while (win_array[count]) count++;
2750 while (--count >= 0)
2752 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2753 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2755 if (pWnd->dwStyle & WS_POPUP)
2757 if (fShow)
2759 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2760 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
2763 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2765 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2766 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2769 else
2771 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2772 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2773 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2776 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2778 ShowWindow(pWnd->hwndSelf,SW_HIDE);
2779 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2780 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
2784 WIN_ReleaseWndPtr( pWnd );
2786 HeapFree( GetProcessHeap(), 0, win_array );
2788 return TRUE;
2791 /*******************************************************************
2792 * ShowOwnedPopups (USER32.@)
2794 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2796 int count = 0;
2797 WND *pWnd;
2798 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2800 if (!win_array) return TRUE;
2802 while (win_array[count]) count++;
2803 while (--count >= 0)
2805 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2806 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2808 if (pWnd->dwStyle & WS_POPUP)
2810 if (fShow)
2812 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2814 /* In Windows, ShowOwnedPopups(TRUE) generates
2815 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2816 * regardless of the state of the owner
2818 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2819 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2822 else
2824 if (IsWindowVisible(pWnd->hwndSelf))
2826 /* In Windows, ShowOwnedPopups(FALSE) generates
2827 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2828 * regardless of the state of the owner
2830 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2831 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2835 WIN_ReleaseWndPtr( pWnd );
2837 HeapFree( GetProcessHeap(), 0, win_array );
2838 return TRUE;
2842 /*******************************************************************
2843 * GetLastActivePopup (USER32.@)
2845 HWND WINAPI GetLastActivePopup( HWND hwnd )
2847 HWND retval = hwnd;
2849 SERVER_START_REQ( get_window_info )
2851 req->handle = hwnd;
2852 if (!wine_server_call_err( req )) retval = reply->last_active;
2854 SERVER_END_REQ;
2855 return retval;
2859 /*******************************************************************
2860 * WIN_ListParents
2862 * Build an array of all parents of a given window, starting with
2863 * the immediate parent. The array must be freed with HeapFree.
2864 * Returns NULL if window is a top-level window.
2866 HWND *WIN_ListParents( HWND hwnd )
2868 WND *win;
2869 HWND current, *list;
2870 int pos = 0, size = 16, count = 0;
2872 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2874 current = hwnd;
2875 for (;;)
2877 if (!(win = WIN_GetPtr( current ))) goto empty;
2878 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
2879 list[pos] = win->parent;
2880 WIN_ReleasePtr( win );
2881 if (!(current = list[pos]))
2883 if (!pos) goto empty;
2884 return list;
2886 if (++pos == size - 1)
2888 /* need to grow the list */
2889 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
2890 if (!new_list) goto empty;
2891 list = new_list;
2892 size += 16;
2896 /* at least one parent belongs to another process, have to query the server */
2898 for (;;)
2900 count = 0;
2901 SERVER_START_REQ( get_window_parents )
2903 req->handle = hwnd;
2904 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
2905 if (!wine_server_call( req )) count = reply->count;
2907 SERVER_END_REQ;
2908 if (!count) goto empty;
2909 if (size > count)
2911 list[count] = 0;
2912 return list;
2914 HeapFree( GetProcessHeap(), 0, list );
2915 size = count + 1;
2916 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2919 empty:
2920 HeapFree( GetProcessHeap(), 0, list );
2921 return NULL;
2925 /*******************************************************************
2926 * WIN_ListChildren
2928 * Build an array of the children of a given window. The array must be
2929 * freed with HeapFree. Returns NULL when no windows are found.
2931 HWND *WIN_ListChildren( HWND hwnd )
2933 return list_window_children( hwnd, 0, 0 );
2937 /*******************************************************************
2938 * EnumWindows (USER32.@)
2940 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2942 HWND *list;
2943 BOOL ret = TRUE;
2944 int i, iWndsLocks;
2946 /* We have to build a list of all windows first, to avoid */
2947 /* unpleasant side-effects, for instance if the callback */
2948 /* function changes the Z-order of the windows. */
2950 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2952 /* Now call the callback function for every window */
2954 iWndsLocks = WIN_SuspendWndsLock();
2955 for (i = 0; list[i]; i++)
2957 /* Make sure that the window still exists */
2958 if (!IsWindow( list[i] )) continue;
2959 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2961 WIN_RestoreWndsLock(iWndsLocks);
2962 HeapFree( GetProcessHeap(), 0, list );
2963 return ret;
2967 /**********************************************************************
2968 * EnumThreadWindows (USER32.@)
2970 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2972 HWND *list;
2973 int i, iWndsLocks;
2975 if (!(list = list_window_children( GetDesktopWindow(), 0, id ))) return TRUE;
2977 /* Now call the callback function for every window */
2979 iWndsLocks = WIN_SuspendWndsLock();
2980 for (i = 0; list[i]; i++)
2981 if (!func( list[i], lParam )) break;
2982 WIN_RestoreWndsLock(iWndsLocks);
2983 HeapFree( GetProcessHeap(), 0, list );
2984 return TRUE;
2988 /**********************************************************************
2989 * WIN_EnumChildWindows
2991 * Helper function for EnumChildWindows().
2993 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2995 HWND *childList;
2996 BOOL ret = FALSE;
2998 for ( ; *list; list++)
3000 /* Make sure that the window still exists */
3001 if (!IsWindow( *list )) continue;
3002 /* skip owned windows */
3003 if (GetWindow( *list, GW_OWNER )) continue;
3004 /* Build children list first */
3005 childList = WIN_ListChildren( *list );
3007 ret = func( *list, lParam );
3009 if (childList)
3011 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
3012 HeapFree( GetProcessHeap(), 0, childList );
3014 if (!ret) return FALSE;
3016 return TRUE;
3020 /**********************************************************************
3021 * EnumChildWindows (USER32.@)
3023 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
3025 HWND *list;
3026 int iWndsLocks;
3028 if (!(list = WIN_ListChildren( parent ))) return FALSE;
3029 iWndsLocks = WIN_SuspendWndsLock();
3030 WIN_EnumChildWindows( list, func, lParam );
3031 WIN_RestoreWndsLock(iWndsLocks);
3032 HeapFree( GetProcessHeap(), 0, list );
3033 return TRUE;
3037 /*******************************************************************
3038 * AnyPopup (USER.52)
3040 BOOL16 WINAPI AnyPopup16(void)
3042 return AnyPopup();
3046 /*******************************************************************
3047 * AnyPopup (USER32.@)
3049 BOOL WINAPI AnyPopup(void)
3051 int i;
3052 BOOL retvalue;
3053 HWND *list = WIN_ListChildren( GetDesktopWindow() );
3055 if (!list) return FALSE;
3056 for (i = 0; list[i]; i++)
3058 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
3060 retvalue = (list[i] != 0);
3061 HeapFree( GetProcessHeap(), 0, list );
3062 return retvalue;
3066 /*******************************************************************
3067 * FlashWindow (USER32.@)
3069 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3071 WND *wndPtr = WIN_FindWndPtr(hWnd);
3073 TRACE("%04x\n", hWnd);
3075 if (!wndPtr) return FALSE;
3076 hWnd = wndPtr->hwndSelf; /* make it a full handle */
3078 if (wndPtr->dwStyle & WS_MINIMIZE)
3080 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3082 HDC hDC = GetDC(hWnd);
3084 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM)hDC, 0 ))
3085 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
3087 ReleaseDC( hWnd, hDC );
3088 wndPtr->flags |= WIN_NCACTIVATED;
3090 else
3092 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3093 wndPtr->flags &= ~WIN_NCACTIVATED;
3095 WIN_ReleaseWndPtr(wndPtr);
3096 return TRUE;
3098 else
3100 WPARAM16 wparam;
3101 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3102 else wparam = (hWnd == GetForegroundWindow());
3104 WIN_ReleaseWndPtr(wndPtr);
3105 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3106 return wparam;
3111 /*******************************************************************
3112 * GetWindowContextHelpId (USER32.@)
3114 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3116 DWORD retval;
3117 WND *wnd = WIN_FindWndPtr( hwnd );
3118 if (!wnd) return 0;
3119 retval = wnd->helpContext;
3120 WIN_ReleaseWndPtr(wnd);
3121 return retval;
3125 /*******************************************************************
3126 * SetWindowContextHelpId (USER32.@)
3128 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3130 WND *wnd = WIN_FindWndPtr( hwnd );
3131 if (!wnd) return FALSE;
3132 wnd->helpContext = id;
3133 WIN_ReleaseWndPtr(wnd);
3134 return TRUE;
3138 /*******************************************************************
3139 * DRAG_QueryUpdate16
3141 * recursively find a child that contains spDragInfo->pt point
3142 * and send WM_QUERYDROPOBJECT
3144 static BOOL16 DRAG_QueryUpdate16( HWND hQueryWnd, SEGPTR spDragInfo )
3146 BOOL16 wParam, bResult = 0;
3147 POINT pt, client_pt;
3148 LPDRAGINFO16 ptrDragInfo = MapSL(spDragInfo);
3149 RECT tempRect;
3151 if (!ptrDragInfo) return FALSE;
3153 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3155 GetWindowRect(hQueryWnd,&tempRect);
3157 if( !PtInRect(&tempRect,pt) || !IsWindowEnabled(hQueryWnd)) return FALSE;
3159 if (!IsIconic( hQueryWnd ))
3161 GetClientRect( hQueryWnd, &tempRect );
3162 MapWindowPoints( hQueryWnd, 0, (LPPOINT)&tempRect, 2 );
3164 if (PtInRect( &tempRect, pt))
3166 int i;
3167 HWND *list = WIN_ListChildren( hQueryWnd );
3169 wParam = 0;
3171 if (list)
3173 for (i = 0; list[i]; i++)
3175 if (GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)
3177 GetWindowRect( list[i], &tempRect );
3178 if (PtInRect( &tempRect, pt )) break;
3181 if (list[i])
3183 if (IsWindowEnabled( list[i] ))
3184 bResult = DRAG_QueryUpdate16( list[i], spDragInfo );
3186 HeapFree( GetProcessHeap(), 0, list );
3188 if(bResult) return bResult;
3190 else wParam = 1;
3192 else wParam = 1;
3194 client_pt = pt;
3195 ScreenToClient( hQueryWnd, &client_pt );
3196 ptrDragInfo->pt.x = client_pt.x;
3197 ptrDragInfo->pt.y = client_pt.y;
3198 ptrDragInfo->hScope = HWND_16(hQueryWnd);
3200 bResult = SendMessage16( HWND_16(hQueryWnd), WM_QUERYDROPOBJECT, (WPARAM16)wParam, spDragInfo );
3202 if( !bResult ) CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3204 return bResult;
3208 /*******************************************************************
3209 * DragDetect (USER32.@)
3211 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3213 MSG msg;
3214 RECT rect;
3216 rect.left = pt.x - wDragWidth;
3217 rect.right = pt.x + wDragWidth;
3219 rect.top = pt.y - wDragHeight;
3220 rect.bottom = pt.y + wDragHeight;
3222 SetCapture(hWnd);
3224 while(1)
3226 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3228 if( msg.message == WM_LBUTTONUP )
3230 ReleaseCapture();
3231 return 0;
3233 if( msg.message == WM_MOUSEMOVE )
3235 POINT tmp;
3236 tmp.x = LOWORD(msg.lParam);
3237 tmp.y = HIWORD(msg.lParam);
3238 if( !PtInRect( &rect, tmp ))
3240 ReleaseCapture();
3241 return 1;
3245 WaitMessage();
3247 return 0;
3250 /******************************************************************************
3251 * DragObject (USER.464)
3253 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3254 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3256 MSG msg;
3257 LPDRAGINFO16 lpDragInfo;
3258 SEGPTR spDragInfo;
3259 HCURSOR hOldCursor=0, hBummer=0;
3260 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
3261 HCURSOR hCurrentCursor = 0;
3262 HWND16 hCurrentWnd = 0;
3264 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
3265 spDragInfo = K32WOWGlobalLock16(hDragInfo);
3267 if( !lpDragInfo || !spDragInfo ) return 0L;
3269 if (!(hBummer = LoadCursorA(0, MAKEINTRESOURCEA(OCR_NO))))
3271 GlobalFree16(hDragInfo);
3272 return 0L;
3275 if(hCursor) hOldCursor = SetCursor(HCURSOR_32(hCursor));
3277 lpDragInfo->hWnd = hWnd;
3278 lpDragInfo->hScope = 0;
3279 lpDragInfo->wFlags = wObj;
3280 lpDragInfo->hList = szList; /* near pointer! */
3281 lpDragInfo->hOfStruct = hOfStruct;
3282 lpDragInfo->l = 0L;
3284 SetCapture(WIN_Handle32(hWnd));
3285 ShowCursor( TRUE );
3289 GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST );
3291 *(lpDragInfo+1) = *lpDragInfo;
3293 lpDragInfo->pt.x = msg.pt.x;
3294 lpDragInfo->pt.y = msg.pt.y;
3296 /* update DRAGINFO struct */
3297 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3299 if( DRAG_QueryUpdate16(WIN_Handle32(hwndScope), spDragInfo) > 0 )
3300 hCurrentCursor = HCURSOR_32(hCursor);
3301 else
3303 hCurrentCursor = hBummer;
3304 lpDragInfo->hScope = 0;
3306 if( hCurrentCursor )
3307 SetCursor(hCurrentCursor);
3309 /* send WM_DRAGLOOP */
3310 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3311 (LPARAM) spDragInfo );
3312 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3313 if( hCurrentWnd != lpDragInfo->hScope )
3315 if( hCurrentWnd )
3316 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3317 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
3318 HIWORD(spDragInfo)) );
3319 hCurrentWnd = lpDragInfo->hScope;
3320 if( hCurrentWnd )
3321 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3323 else
3324 if( hCurrentWnd )
3325 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3327 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3329 ReleaseCapture();
3330 ShowCursor( FALSE );
3332 if( hCursor ) SetCursor(hOldCursor);
3334 if( hCurrentCursor != hBummer )
3335 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3336 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3337 else
3338 msg.lParam = 0;
3339 GlobalFree16(hDragInfo);
3341 return (DWORD)(msg.lParam);
3345 /******************************************************************************
3346 * GetWindowModuleFileNameA (USER32.@)
3348 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3350 FIXME("GetWindowModuleFileNameA(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3351 hwnd, lpszFileName, cchFileNameMax);
3352 return 0;
3355 /******************************************************************************
3356 * GetWindowModuleFileNameW (USER32.@)
3358 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3360 FIXME("GetWindowModuleFileNameW(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3361 hwnd, lpszFileName, cchFileNameMax);
3362 return 0;
3365 /******************************************************************************
3366 * GetWindowInfo (USER32.@)
3367 * hwnd: in
3368 * pwi: out.
3369 * MS Documentation mentions that pwi->cbSize must be set to SIZEOF(WINDOWINFO)
3370 * this may be because this structure changed over time. If this is the
3371 * the case, then please: FIXME.
3372 * Using the structure described in MSDN for 98/ME/NT(4.0 SP3)/2000/XP.
3374 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3376 WND *wndInfo = NULL;
3377 if (!pwi) return FALSE;
3378 if (pwi->cbSize != sizeof(WINDOWINFO))
3380 FIXME("windowinfo->cbSize != sizeof(WINDOWINFO). Please report\n");
3381 return FALSE;
3383 wndInfo = WIN_GetPtr(hwnd);
3384 if (!wndInfo) return FALSE;
3385 if (wndInfo == WND_OTHER_PROCESS)
3387 FIXME("window belong to other process\n");
3388 return FALSE;
3391 pwi->rcWindow = wndInfo->rectWindow;
3392 pwi->rcClient = wndInfo->rectClient;
3393 pwi->dwStyle = wndInfo->dwStyle;
3394 pwi->dwExStyle = wndInfo->dwExStyle;
3395 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3396 /* if active WS_ACTIVECAPTION, else 0 */
3398 pwi->cxWindowBorders = ((wndInfo->dwStyle & WS_BORDER) ?
3399 GetSystemMetrics(SM_CXBORDER) : 0);
3400 pwi->cyWindowBorders = ((wndInfo->dwStyle & WS_BORDER) ?
3401 GetSystemMetrics(SM_CYBORDER) : 0);
3402 /* above two: I'm presuming that borders widths are the same
3403 * for each window - so long as its actually using a border.. */
3405 pwi->atomWindowType = GetClassLongA( hwnd, GCW_ATOM );
3406 pwi->wCreatorVersion = GetVersion();
3407 /* Docs say this should be the version that
3408 * CREATED the window. But eh?.. Isn't that just the
3409 * version we are running.. Unless ofcourse its some wacky
3410 * RPC stuff or something */
3412 WIN_ReleasePtr(wndInfo);
3413 return TRUE;