Call IDirectSound::Initialize() as per MSDN before using the
[wine/multimedia.git] / windows / win.c
bloba73fbf090a7916af930c852d7557936333bcb127
1 /*
2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "config.h"
22 #include "wine/port.h"
24 #include <assert.h>
25 #include <stdarg.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include "windef.h"
29 #include "winbase.h"
30 #include "wine/winbase16.h"
31 #include "wine/winuser16.h"
32 #include "wownt32.h"
33 #include "wine/server.h"
34 #include "wine/unicode.h"
35 #include "win.h"
36 #include "user.h"
37 #include "dce.h"
38 #include "controls.h"
39 #include "cursoricon.h"
40 #include "message.h"
41 #include "winpos.h"
42 #include "winerror.h"
43 #include "wine/debug.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(win);
46 WINE_DECLARE_DEBUG_CHANNEL(msg);
48 #define NB_USER_HANDLES ((LAST_USER_HANDLE - FIRST_USER_HANDLE + 1) >> 1)
49 #define USER_HANDLE_TO_INDEX(hwnd) ((LOWORD(hwnd) - 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 /***********************************************************************
62 * create_window_handle
64 * Create a window handle with the server.
66 static WND *create_window_handle( HWND parent, HWND owner, ATOM atom,
67 HINSTANCE instance, WINDOWPROCTYPE type )
69 WORD index;
70 WND *win;
71 struct tagCLASS *class = NULL;
72 user_handle_t handle = 0;
73 int extra_bytes = 0;
75 /* if 16-bit instance, map to module handle */
76 if (instance && !HIWORD(instance))
77 instance = HINSTANCE_32(GetExePtr(HINSTANCE_16(instance)));
79 SERVER_START_REQ( create_window )
81 req->parent = parent;
82 req->owner = owner;
83 req->atom = atom;
84 req->instance = instance;
85 if (!wine_server_call_err( req ))
87 handle = reply->handle;
88 extra_bytes = reply->extra;
89 class = reply->class_ptr;
92 SERVER_END_REQ;
94 if (!handle)
96 WARN( "error %ld creating window\n", GetLastError() );
97 return NULL;
100 if (!(win = HeapAlloc( GetProcessHeap(), 0, sizeof(WND) + extra_bytes - sizeof(win->wExtra) )))
102 SERVER_START_REQ( destroy_window )
104 req->handle = handle;
105 wine_server_call( req );
107 SERVER_END_REQ;
108 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
109 return NULL;
112 USER_Lock();
114 index = USER_HANDLE_TO_INDEX(handle);
115 assert( index < NB_USER_HANDLES );
116 user_handles[index] = win;
117 win->hwndSelf = handle;
118 win->dwMagic = WND_MAGIC;
119 win->irefCount = 1;
120 win->cbWndExtra = extra_bytes;
121 memset( win->wExtra, 0, extra_bytes );
122 CLASS_AddWindow( class, win, type );
123 return win;
127 /***********************************************************************
128 * free_window_handle
130 * Free a window handle.
132 static WND *free_window_handle( HWND hwnd )
134 WND *ptr;
135 WORD index = USER_HANDLE_TO_INDEX(hwnd);
137 if (index >= NB_USER_HANDLES) return NULL;
138 USER_Lock();
139 if ((ptr = user_handles[index]))
141 SERVER_START_REQ( destroy_window )
143 req->handle = hwnd;
144 if (!wine_server_call_err( req ))
145 user_handles[index] = NULL;
146 else
147 ptr = NULL;
149 SERVER_END_REQ;
151 USER_Unlock();
152 if (ptr) HeapFree( GetProcessHeap(), 0, ptr );
153 return ptr;
157 /*******************************************************************
158 * list_window_children
160 * Build an array of the children of a given window. The array must be
161 * freed with HeapFree. Returns NULL when no windows are found.
163 static HWND *list_window_children( HWND hwnd, ATOM atom, DWORD tid )
165 HWND *list;
166 int size = 32;
168 for (;;)
170 int count = 0;
172 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
174 SERVER_START_REQ( get_window_children )
176 req->parent = hwnd;
177 req->atom = atom;
178 req->tid = tid;
179 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
180 if (!wine_server_call( req )) count = reply->count;
182 SERVER_END_REQ;
183 if (count && count < size)
185 list[count] = 0;
186 return list;
188 HeapFree( GetProcessHeap(), 0, list );
189 if (!count) break;
190 size = count + 1; /* restart with a large enough buffer */
192 return NULL;
196 /*******************************************************************
197 * send_parent_notify
199 static void send_parent_notify( HWND hwnd, UINT msg )
201 if ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_CHILD | WS_POPUP)) == WS_CHILD &&
202 !(GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY))
203 SendMessageW( GetParent(hwnd), WM_PARENTNOTIFY,
204 MAKEWPARAM( msg, GetWindowLongW( hwnd, GWL_ID )), (LPARAM)hwnd );
208 /*******************************************************************
209 * get_server_window_text
211 * Retrieve the window text from the server.
213 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
215 size_t len = 0;
217 SERVER_START_REQ( get_window_text )
219 req->handle = hwnd;
220 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
221 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
223 SERVER_END_REQ;
224 text[len / sizeof(WCHAR)] = 0;
228 /***********************************************************************
229 * WIN_GetPtr
231 * Return a pointer to the WND structure if local to the process,
232 * or WND_OTHER_PROCESS if handle may be valid in other process.
233 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
235 WND *WIN_GetPtr( HWND hwnd )
237 WND * ptr;
238 WORD index = USER_HANDLE_TO_INDEX(hwnd);
240 if (index >= NB_USER_HANDLES) return NULL;
242 USER_Lock();
243 if ((ptr = user_handles[index]))
245 if (ptr->dwMagic == WND_MAGIC && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
246 return ptr;
247 ptr = NULL;
249 else ptr = WND_OTHER_PROCESS;
250 USER_Unlock();
251 return ptr;
255 /***********************************************************************
256 * WIN_IsCurrentProcess
258 * Check whether a given window belongs to the current process (and return the full handle).
260 HWND WIN_IsCurrentProcess( HWND hwnd )
262 WND *ptr;
263 HWND ret;
265 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS) return 0;
266 ret = ptr->hwndSelf;
267 WIN_ReleasePtr( ptr );
268 return ret;
272 /***********************************************************************
273 * WIN_IsCurrentThread
275 * Check whether a given window belongs to the current thread (and return the full handle).
277 HWND WIN_IsCurrentThread( HWND hwnd )
279 WND *ptr;
280 HWND ret = 0;
282 if ((ptr = WIN_GetPtr( hwnd )) && ptr != WND_OTHER_PROCESS)
284 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
285 WIN_ReleasePtr( ptr );
287 return ret;
291 /***********************************************************************
292 * WIN_Handle32
294 * Convert a 16-bit window handle to a full 32-bit handle.
296 HWND WIN_Handle32( HWND16 hwnd16 )
298 WND *ptr;
299 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
301 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
302 /* do sign extension for -2 and -3 */
303 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
305 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
307 if (ptr != WND_OTHER_PROCESS)
309 hwnd = ptr->hwndSelf;
310 WIN_ReleasePtr( ptr );
312 else /* may belong to another process */
314 SERVER_START_REQ( get_window_info )
316 req->handle = hwnd;
317 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
319 SERVER_END_REQ;
321 return hwnd;
325 /***********************************************************************
326 * WIN_FindWndPtr
328 * Return a pointer to the WND structure corresponding to a HWND.
330 WND * WIN_FindWndPtr( HWND hwnd )
332 WND * ptr;
334 if (!hwnd) return NULL;
336 if ((ptr = WIN_GetPtr( hwnd )))
338 if (ptr != WND_OTHER_PROCESS)
340 /* increment destruction monitoring */
341 ptr->irefCount++;
342 return ptr;
344 if (IsWindow( hwnd )) /* check other processes */
346 ERR( "window %p belongs to other process\n", hwnd );
347 /* DbgBreakPoint(); */
350 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
351 return NULL;
355 /***********************************************************************
356 * WIN_ReleaseWndPtr
358 * Release the pointer to the WND structure.
360 void WIN_ReleaseWndPtr(WND *wndPtr)
362 if(!wndPtr) return;
364 /* Decrement destruction monitoring value */
365 wndPtr->irefCount--;
366 /* Check if it's time to release the memory */
367 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
369 /* Release memory */
370 free_window_handle( wndPtr->hwndSelf );
372 else if(wndPtr->irefCount < 0)
374 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
375 ERR("forgot a Lock on %p somewhere\n",wndPtr);
377 /* unlock all WND structures for thread safeness */
378 USER_Unlock();
382 /***********************************************************************
383 * WIN_UnlinkWindow
385 * Remove a window from the siblings linked list.
387 void WIN_UnlinkWindow( HWND hwnd )
389 WIN_LinkWindow( hwnd, 0, 0 );
393 /***********************************************************************
394 * WIN_LinkWindow
396 * Insert a window into the siblings linked list.
397 * The window is inserted after the specified window, which can also
398 * be specified as HWND_TOP or HWND_BOTTOM.
399 * If parent is 0, window is unlinked from the tree.
401 void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
403 WND *wndPtr = WIN_GetPtr( hwnd );
405 if (!wndPtr) return;
406 if (wndPtr == WND_OTHER_PROCESS)
408 if (IsWindow(hwnd)) ERR(" cannot link other process window %p\n", hwnd );
409 return;
412 SERVER_START_REQ( link_window )
414 req->handle = hwnd;
415 req->parent = parent;
416 req->previous = hwndInsertAfter;
417 if (!wine_server_call( req ))
419 if (reply->full_parent) wndPtr->parent = reply->full_parent;
423 SERVER_END_REQ;
424 WIN_ReleasePtr( wndPtr );
428 /***********************************************************************
429 * WIN_SetOwner
431 * Change the owner of a window.
433 HWND WIN_SetOwner( HWND hwnd, HWND owner )
435 WND *win = WIN_GetPtr( hwnd );
436 HWND ret = 0;
438 if (!win) return 0;
439 if (win == WND_OTHER_PROCESS)
441 if (IsWindow(hwnd)) ERR( "cannot set owner %p on other process window %p\n", owner, hwnd );
442 return 0;
444 SERVER_START_REQ( set_window_owner )
446 req->handle = hwnd;
447 req->owner = owner;
448 if (!wine_server_call( req ))
450 win->owner = reply->full_owner;
451 ret = reply->prev_owner;
454 SERVER_END_REQ;
455 WIN_ReleasePtr( win );
456 return ret;
460 /***********************************************************************
461 * WIN_SetStyle
463 * Change the style of a window.
465 LONG WIN_SetStyle( HWND hwnd, LONG style )
467 BOOL ok;
468 LONG ret = 0;
469 WND *win = WIN_GetPtr( hwnd );
471 if (!win) return 0;
472 if (win == WND_OTHER_PROCESS)
474 if (IsWindow(hwnd))
475 ERR( "cannot set style %lx on other process window %p\n", style, hwnd );
476 return 0;
478 if (style == win->dwStyle)
480 WIN_ReleasePtr( win );
481 return style;
483 SERVER_START_REQ( set_window_info )
485 req->handle = hwnd;
486 req->flags = SET_WIN_STYLE;
487 req->style = style;
488 req->extra_offset = -1;
489 if ((ok = !wine_server_call( req )))
491 ret = reply->old_style;
492 win->dwStyle = style;
495 SERVER_END_REQ;
496 WIN_ReleasePtr( win );
497 if (ok && USER_Driver.pSetWindowStyle) USER_Driver.pSetWindowStyle( hwnd, ret );
498 return ret;
502 /***********************************************************************
503 * WIN_SetExStyle
505 * Change the extended style of a window.
507 LONG WIN_SetExStyle( HWND hwnd, LONG style )
509 LONG ret = 0;
510 WND *win = WIN_GetPtr( hwnd );
512 if (!win) return 0;
513 if (win == WND_OTHER_PROCESS)
515 if (IsWindow(hwnd))
516 ERR( "cannot set exstyle %lx on other process window %p\n", style, hwnd );
517 return 0;
519 if (style == win->dwExStyle)
521 WIN_ReleasePtr( win );
522 return style;
524 SERVER_START_REQ( set_window_info )
526 req->handle = hwnd;
527 req->flags = SET_WIN_EXSTYLE;
528 req->ex_style = style;
529 req->extra_offset = -1;
530 if (!wine_server_call( req ))
532 ret = reply->old_ex_style;
533 win->dwExStyle = style;
536 SERVER_END_REQ;
537 WIN_ReleasePtr( win );
538 return ret;
542 /***********************************************************************
543 * WIN_SetRectangles
545 * Set the window and client rectangles.
547 void WIN_SetRectangles( HWND hwnd, const RECT *rectWindow, const RECT *rectClient )
549 WND *win = WIN_GetPtr( hwnd );
550 BOOL ret;
552 if (!win) return;
553 if (win == WND_OTHER_PROCESS)
555 if (IsWindow( hwnd )) ERR( "cannot set rectangles of other process window %p\n", hwnd );
556 return;
558 SERVER_START_REQ( set_window_rectangles )
560 req->handle = hwnd;
561 req->window.left = rectWindow->left;
562 req->window.top = rectWindow->top;
563 req->window.right = rectWindow->right;
564 req->window.bottom = rectWindow->bottom;
565 req->client.left = rectClient->left;
566 req->client.top = rectClient->top;
567 req->client.right = rectClient->right;
568 req->client.bottom = rectClient->bottom;
569 ret = !wine_server_call( req );
571 SERVER_END_REQ;
572 if (ret)
574 win->rectWindow = *rectWindow;
575 win->rectClient = *rectClient;
577 TRACE( "win %p window (%ld,%ld)-(%ld,%ld) client (%ld,%ld)-(%ld,%ld)\n", hwnd,
578 rectWindow->left, rectWindow->top, rectWindow->right, rectWindow->bottom,
579 rectClient->left, rectClient->top, rectClient->right, rectClient->bottom );
581 WIN_ReleasePtr( win );
585 /***********************************************************************
586 * WIN_GetRectangles
588 * Get the window and client rectangles.
590 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
592 WND *win = WIN_GetPtr( hwnd );
593 BOOL ret = TRUE;
595 if (!win) return FALSE;
596 if (win == WND_OTHER_PROCESS)
598 SERVER_START_REQ( get_window_rectangles )
600 req->handle = hwnd;
601 if ((ret = !wine_server_call( req )))
603 if (rectWindow)
605 rectWindow->left = reply->window.left;
606 rectWindow->top = reply->window.top;
607 rectWindow->right = reply->window.right;
608 rectWindow->bottom = reply->window.bottom;
610 if (rectClient)
612 rectClient->left = reply->client.left;
613 rectClient->top = reply->client.top;
614 rectClient->right = reply->client.right;
615 rectClient->bottom = reply->client.bottom;
619 SERVER_END_REQ;
621 else
623 if (rectWindow) *rectWindow = win->rectWindow;
624 if (rectClient) *rectClient = win->rectClient;
625 WIN_ReleasePtr( win );
627 return ret;
631 /***********************************************************************
632 * WIN_DestroyWindow
634 * Destroy storage associated to a window. "Internals" p.358
636 LRESULT WIN_DestroyWindow( HWND hwnd )
638 WND *wndPtr;
639 HWND *list;
641 TRACE("%p\n", hwnd );
643 if (!(hwnd = WIN_IsCurrentThread( hwnd )))
645 ERR( "window doesn't belong to current thread\n" );
646 return 0;
649 /* free child windows */
650 if ((list = WIN_ListChildren( hwnd )))
652 int i;
653 for (i = 0; list[i]; i++)
655 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
656 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
658 HeapFree( GetProcessHeap(), 0, list );
662 * Clear the update region to make sure no WM_PAINT messages will be
663 * generated for this window while processing the WM_NCDESTROY.
665 RedrawWindow( hwnd, NULL, 0,
666 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
669 * Send the WM_NCDESTROY to the window being destroyed.
671 SendMessageA( hwnd, WM_NCDESTROY, 0, 0);
673 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
675 WINPOS_CheckInternalPos( hwnd );
676 if( hwnd == GetCapture()) ReleaseCapture();
678 /* free resources associated with the window */
680 TIMER_RemoveWindowTimers( hwnd );
682 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
684 if (!(wndPtr->dwStyle & WS_CHILD))
686 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
687 if (menu) DestroyMenu( menu );
689 if (wndPtr->hSysMenu)
691 DestroyMenu( wndPtr->hSysMenu );
692 wndPtr->hSysMenu = 0;
694 DCE_FreeWindowDCE( hwnd ); /* Always do this to catch orphaned DCs */
695 USER_Driver.pDestroyWindow( hwnd );
696 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
697 wndPtr->class = NULL;
698 wndPtr->dwMagic = 0; /* Mark it as invalid */
699 WIN_ReleaseWndPtr( wndPtr );
700 return 0;
703 /***********************************************************************
704 * WIN_DestroyThreadWindows
706 * Destroy all children of 'wnd' owned by the current thread.
707 * Return TRUE if something was done.
709 void WIN_DestroyThreadWindows( HWND hwnd )
711 HWND *list;
712 int i;
714 if (!(list = WIN_ListChildren( hwnd ))) return;
715 for (i = 0; list[i]; i++)
717 if (WIN_IsCurrentThread( list[i] ))
718 DestroyWindow( list[i] );
719 else
720 WIN_DestroyThreadWindows( list[i] );
722 HeapFree( GetProcessHeap(), 0, list );
725 /***********************************************************************
726 * WIN_CreateDesktopWindow
728 * Create the desktop window.
730 BOOL WIN_CreateDesktopWindow(void)
732 HWND hwndDesktop;
733 CREATESTRUCTA cs;
734 RECT rect;
736 TRACE("Creating desktop window\n");
738 if (!WINPOS_CreateInternalPosAtom()) return FALSE;
740 pWndDesktop = create_window_handle( 0, 0, LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W );
741 if (!pWndDesktop) return FALSE;
742 hwndDesktop = pWndDesktop->hwndSelf;
744 pWndDesktop->tid = 0; /* nobody owns the desktop */
745 pWndDesktop->parent = 0;
746 pWndDesktop->owner = 0;
747 pWndDesktop->text = NULL;
748 pWndDesktop->hrgnUpdate = 0;
749 pWndDesktop->pVScroll = NULL;
750 pWndDesktop->pHScroll = NULL;
751 pWndDesktop->helpContext = 0;
752 pWndDesktop->flags = 0;
753 pWndDesktop->hSysMenu = 0;
755 cs.lpCreateParams = NULL;
756 cs.hInstance = 0;
757 cs.hMenu = 0;
758 cs.hwndParent = 0;
759 cs.x = 0;
760 cs.y = 0;
761 cs.cx = GetSystemMetrics( SM_CXSCREEN );
762 cs.cy = GetSystemMetrics( SM_CYSCREEN );
763 cs.style = pWndDesktop->dwStyle;
764 cs.dwExStyle = pWndDesktop->dwExStyle;
765 cs.lpszName = NULL;
766 cs.lpszClass = DESKTOP_CLASS_ATOM;
768 SetRect( &rect, 0, 0, cs.cx, cs.cy );
769 WIN_SetRectangles( hwndDesktop, &rect, &rect );
771 SERVER_START_REQ( set_window_info )
773 req->handle = hwndDesktop;
774 req->flags = 0; /* don't set anything, just retrieve */
775 req->extra_offset = -1;
776 wine_server_call( req );
777 pWndDesktop->dwStyle = reply->old_style;
778 pWndDesktop->dwExStyle = reply->old_ex_style;
779 pWndDesktop->hInstance = (HINSTANCE)reply->old_instance;
780 pWndDesktop->userdata = (ULONG_PTR)reply->old_user_data;
781 pWndDesktop->wIDmenu = reply->old_id;
783 SERVER_END_REQ;
785 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE ))
787 WIN_ReleaseWndPtr( pWndDesktop );
788 return FALSE;
791 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
792 WIN_ReleaseWndPtr( pWndDesktop );
793 return TRUE;
797 /***********************************************************************
798 * WIN_FixCoordinates
800 * Fix the coordinates - Helper for WIN_CreateWindowEx.
801 * returns default show mode in sw.
802 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
804 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
806 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
807 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
809 if (cs->style & (WS_CHILD | WS_POPUP))
811 if (cs->dwExStyle & WS_EX_MDICHILD)
813 POINT pos[2];
815 MDI_CalcDefaultChildPos(cs->hwndParent, -1, pos, 0);
817 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
819 cs->x = pos[0].x;
820 cs->y = pos[0].y;
822 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16 || !cs->cx)
823 cs->cx = pos[1].x;
824 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16 || !cs->cy)
825 cs->cy = pos[1].y;
827 else
829 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
830 cs->x = cs->y = 0;
831 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
832 cs->cx = cs->cy = 0;
835 else /* overlapped window */
837 STARTUPINFOA info;
839 GetStartupInfoA( &info );
841 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
843 /* Never believe Microsoft's documentation... CreateWindowEx doc says
844 * that if an overlapped window is created with WS_VISIBLE style bit
845 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
846 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
847 * reveals that
849 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
850 * 2) it does not ignore the y parameter as the docs claim; instead, it
851 * uses it as second parameter to ShowWindow() unless y is either
852 * CW_USEDEFAULT or CW_USEDEFAULT16.
854 * The fact that we didn't do 2) caused bogus windows pop up when wine
855 * was running apps that were using this obscure feature. Example -
856 * calc.exe that comes with Win98 (only Win98, it's different from
857 * the one that comes with Win95 and NT)
859 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
860 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
861 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
864 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
866 if (info.dwFlags & STARTF_USESIZE)
868 cs->cx = info.dwXSize;
869 cs->cy = info.dwYSize;
871 else /* if no other hint from the app, pick 3/4 of the screen real estate */
873 RECT r;
874 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
875 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
876 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
881 else
883 /* neither x nor cx are default. Check the y values .
884 * In the trace we see Outlook and Outlook Express using
885 * cy set to CW_USEDEFAULT when opening the address book.
887 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16) {
888 RECT r;
889 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
890 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
891 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
896 /***********************************************************************
897 * dump_window_styles
899 static void dump_window_styles( DWORD style, DWORD exstyle )
901 TRACE( "style:" );
902 if(style & WS_POPUP) TRACE(" WS_POPUP");
903 if(style & WS_CHILD) TRACE(" WS_CHILD");
904 if(style & WS_MINIMIZE) TRACE(" WS_MINIMIZE");
905 if(style & WS_VISIBLE) TRACE(" WS_VISIBLE");
906 if(style & WS_DISABLED) TRACE(" WS_DISABLED");
907 if(style & WS_CLIPSIBLINGS) TRACE(" WS_CLIPSIBLINGS");
908 if(style & WS_CLIPCHILDREN) TRACE(" WS_CLIPCHILDREN");
909 if(style & WS_MAXIMIZE) TRACE(" WS_MAXIMIZE");
910 if((style & WS_CAPTION) == WS_CAPTION) TRACE(" WS_CAPTION");
911 else
913 if(style & WS_BORDER) TRACE(" WS_BORDER");
914 if(style & WS_DLGFRAME) TRACE(" WS_DLGFRAME");
916 if(style & WS_VSCROLL) TRACE(" WS_VSCROLL");
917 if(style & WS_HSCROLL) TRACE(" WS_HSCROLL");
918 if(style & WS_SYSMENU) TRACE(" WS_SYSMENU");
919 if(style & WS_THICKFRAME) TRACE(" WS_THICKFRAME");
920 if(style & WS_GROUP) TRACE(" WS_GROUP");
921 if(style & WS_TABSTOP) TRACE(" WS_TABSTOP");
922 if(style & WS_MINIMIZEBOX) TRACE(" WS_MINIMIZEBOX");
923 if(style & WS_MAXIMIZEBOX) TRACE(" WS_MAXIMIZEBOX");
925 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
926 #define DUMPED_STYLES \
927 (WS_POPUP | \
928 WS_CHILD | \
929 WS_MINIMIZE | \
930 WS_VISIBLE | \
931 WS_DISABLED | \
932 WS_CLIPSIBLINGS | \
933 WS_CLIPCHILDREN | \
934 WS_MAXIMIZE | \
935 WS_BORDER | \
936 WS_DLGFRAME | \
937 WS_VSCROLL | \
938 WS_HSCROLL | \
939 WS_SYSMENU | \
940 WS_THICKFRAME | \
941 WS_GROUP | \
942 WS_TABSTOP | \
943 WS_MINIMIZEBOX | \
944 WS_MAXIMIZEBOX)
946 if(style & ~DUMPED_STYLES) TRACE(" %08lx", style & ~DUMPED_STYLES);
947 TRACE("\n");
948 #undef DUMPED_STYLES
950 TRACE( "exstyle:" );
951 if(exstyle & WS_EX_DLGMODALFRAME) TRACE(" WS_EX_DLGMODALFRAME");
952 if(exstyle & WS_EX_DRAGDETECT) TRACE(" WS_EX_DRAGDETECT");
953 if(exstyle & WS_EX_NOPARENTNOTIFY) TRACE(" WS_EX_NOPARENTNOTIFY");
954 if(exstyle & WS_EX_TOPMOST) TRACE(" WS_EX_TOPMOST");
955 if(exstyle & WS_EX_ACCEPTFILES) TRACE(" WS_EX_ACCEPTFILES");
956 if(exstyle & WS_EX_TRANSPARENT) TRACE(" WS_EX_TRANSPARENT");
957 if(exstyle & WS_EX_MDICHILD) TRACE(" WS_EX_MDICHILD");
958 if(exstyle & WS_EX_TOOLWINDOW) TRACE(" WS_EX_TOOLWINDOW");
959 if(exstyle & WS_EX_WINDOWEDGE) TRACE(" WS_EX_WINDOWEDGE");
960 if(exstyle & WS_EX_CLIENTEDGE) TRACE(" WS_EX_CLIENTEDGE");
961 if(exstyle & WS_EX_CONTEXTHELP) TRACE(" WS_EX_CONTEXTHELP");
962 if(exstyle & WS_EX_RIGHT) TRACE(" WS_EX_RIGHT");
963 if(exstyle & WS_EX_RTLREADING) TRACE(" WS_EX_RTLREADING");
964 if(exstyle & WS_EX_LEFTSCROLLBAR) TRACE(" WS_EX_LEFTSCROLLBAR");
965 if(exstyle & WS_EX_CONTROLPARENT) TRACE(" WS_EX_CONTROLPARENT");
966 if(exstyle & WS_EX_STATICEDGE) TRACE(" WS_EX_STATICEDGE");
967 if(exstyle & WS_EX_APPWINDOW) TRACE(" WS_EX_APPWINDOW");
968 if(exstyle & WS_EX_LAYERED) TRACE(" WS_EX_LAYERED");
970 #define DUMPED_EX_STYLES \
971 (WS_EX_DLGMODALFRAME | \
972 WS_EX_DRAGDETECT | \
973 WS_EX_NOPARENTNOTIFY | \
974 WS_EX_TOPMOST | \
975 WS_EX_ACCEPTFILES | \
976 WS_EX_TRANSPARENT | \
977 WS_EX_MDICHILD | \
978 WS_EX_TOOLWINDOW | \
979 WS_EX_WINDOWEDGE | \
980 WS_EX_CLIENTEDGE | \
981 WS_EX_CONTEXTHELP | \
982 WS_EX_RIGHT | \
983 WS_EX_RTLREADING | \
984 WS_EX_LEFTSCROLLBAR | \
985 WS_EX_CONTROLPARENT | \
986 WS_EX_STATICEDGE | \
987 WS_EX_APPWINDOW | \
988 WS_EX_LAYERED)
990 if(exstyle & ~DUMPED_EX_STYLES) TRACE(" %08lx", exstyle & ~DUMPED_EX_STYLES);
991 TRACE("\n");
992 #undef DUMPED_EX_STYLES
996 /***********************************************************************
997 * WIN_CreateWindowEx
999 * Implementation of CreateWindowEx().
1001 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
1002 WINDOWPROCTYPE type )
1004 INT sw = SW_SHOW;
1005 WND *wndPtr;
1006 HWND hwnd, parent, owner, top_child = 0;
1007 BOOL unicode = (type == WIN_PROC_32W);
1009 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
1010 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
1011 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszClass) : debugstr_a(cs->lpszClass),
1012 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
1013 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
1015 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
1017 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
1018 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
1020 /* Fix the styles for MDI children */
1021 if (cs->dwExStyle & WS_EX_MDICHILD)
1023 MDICREATESTRUCTA mdi_cs;
1024 UINT flags = 0;
1026 wndPtr = WIN_GetPtr(cs->hwndParent);
1027 if (wndPtr && wndPtr != WND_OTHER_PROCESS)
1029 flags = wndPtr->flags;
1030 WIN_ReleasePtr(wndPtr);
1033 if (!(flags & WIN_ISMDICLIENT))
1035 WARN("WS_EX_MDICHILD, but parent %p is not MDIClient\n", cs->hwndParent);
1036 return 0;
1039 /* cs->lpCreateParams of WM_[NC]CREATE is different for MDI children.
1040 * MDICREATESTRUCT members have the originally passed values.
1042 * Note: we rely on the fact that MDICREATESTRUCTA and MDICREATESTRUCTW
1043 * have the same layout.
1045 mdi_cs.szClass = cs->lpszClass;
1046 mdi_cs.szTitle = cs->lpszName;
1047 mdi_cs.hOwner = cs->hInstance;
1048 mdi_cs.x = cs->x;
1049 mdi_cs.y = cs->y;
1050 mdi_cs.cx = cs->cx;
1051 mdi_cs.cy = cs->cy;
1052 mdi_cs.style = cs->style;
1053 mdi_cs.lParam = (LPARAM)cs->lpCreateParams;
1055 cs->lpCreateParams = (LPVOID)&mdi_cs;
1057 if (GetWindowLongW(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
1059 if (cs->style & WS_POPUP)
1061 TRACE("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n");
1062 return 0;
1064 cs->style |= WS_CHILD | WS_CLIPSIBLINGS;
1066 else
1068 cs->style &= ~WS_POPUP;
1069 cs->style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
1070 WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
1073 top_child = GetWindow(cs->hwndParent, GW_CHILD);
1076 /* Find the parent window */
1078 parent = GetDesktopWindow();
1079 owner = 0;
1081 if (cs->hwndParent == HWND_MESSAGE)
1083 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
1084 * message window (style: WS_POPUP|WS_DISABLED)
1086 FIXME("Parent is HWND_MESSAGE\n");
1088 else if (cs->hwndParent)
1090 /* Make sure parent is valid */
1091 if (!IsWindow( cs->hwndParent ))
1093 WARN("Bad parent %p\n", cs->hwndParent );
1094 return 0;
1096 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1097 parent = WIN_GetFullHandle(cs->hwndParent);
1098 else
1099 owner = GetAncestor( cs->hwndParent, GA_ROOT );
1101 else if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1103 WARN("No parent for child window\n" );
1104 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1107 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
1109 /* Correct the window styles.
1111 * It affects both the style loaded into the WIN structure and
1112 * passed in the CREATESTRUCT to the WM_[NC]CREATE.
1114 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1115 * why does the user get to set it?
1118 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
1119 * tested for WS_POPUP
1121 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
1122 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
1123 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
1124 cs->dwExStyle |= WS_EX_WINDOWEDGE;
1125 else
1126 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
1128 if (!(cs->style & WS_CHILD))
1130 cs->style |= WS_CLIPSIBLINGS;
1131 if (!(cs->style & WS_POPUP))
1132 cs->style |= WS_CAPTION;
1135 /* Create the window structure */
1137 if (!(wndPtr = create_window_handle( parent, owner, classAtom, cs->hInstance, type )))
1139 TRACE("out of memory\n" );
1140 return 0;
1142 hwnd = wndPtr->hwndSelf;
1144 /* Fill the window structure */
1146 wndPtr->tid = GetCurrentThreadId();
1147 wndPtr->owner = owner;
1148 wndPtr->parent = parent;
1149 wndPtr->hInstance = cs->hInstance;
1150 wndPtr->text = NULL;
1151 wndPtr->hrgnUpdate = 0;
1152 wndPtr->hrgnWnd = 0;
1153 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1154 wndPtr->dwExStyle = cs->dwExStyle;
1155 wndPtr->wIDmenu = 0;
1156 wndPtr->helpContext = 0;
1157 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
1158 wndPtr->pVScroll = NULL;
1159 wndPtr->pHScroll = NULL;
1160 wndPtr->userdata = 0;
1161 wndPtr->hIcon = 0;
1162 wndPtr->hIconSmall = 0;
1163 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU) ? MENU_GetSysMenu( hwnd, 0 ) : 0;
1165 if (!(cs->style & (WS_CHILD | WS_POPUP)))
1166 wndPtr->flags |= WIN_NEED_SIZE;
1168 SERVER_START_REQ( set_window_info )
1170 req->handle = hwnd;
1171 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE;
1172 req->style = wndPtr->dwStyle;
1173 req->ex_style = wndPtr->dwExStyle;
1174 req->instance = (void *)wndPtr->hInstance;
1175 req->extra_offset = -1;
1176 wine_server_call( req );
1178 SERVER_END_REQ;
1180 /* Get class or window DC if needed */
1182 if (wndPtr->clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
1184 /* Set the window menu */
1186 if (((wndPtr->dwStyle & (WS_CAPTION|WS_CHILD)) == WS_CAPTION) ||
1187 (wndPtr->dwExStyle & WS_EX_APPWINDOW))
1189 if (cs->hMenu) MENU_SetMenu(hwnd, cs->hMenu);
1190 else
1192 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
1193 if (menuName)
1195 if (HIWORD(cs->hInstance))
1196 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1197 else
1198 cs->hMenu = HMENU_32(LoadMenu16(HINSTANCE_16(cs->hInstance),menuName));
1200 if (cs->hMenu) MENU_SetMenu( hwnd, cs->hMenu );
1204 else SetWindowLongW( hwnd, GWL_ID, (UINT)cs->hMenu );
1205 WIN_ReleaseWndPtr( wndPtr );
1207 if (!USER_Driver.pCreateWindow( hwnd, cs, unicode))
1209 WIN_DestroyWindow( hwnd );
1210 return 0;
1213 /* Notify the parent window only */
1215 send_parent_notify( hwnd, WM_CREATE );
1216 if (!IsWindow( hwnd )) return 0;
1218 if (cs->dwExStyle & WS_EX_MDICHILD)
1220 if (top_child)
1222 /* Restore current maximized child */
1223 if((cs->style & WS_VISIBLE) && IsZoomed(top_child))
1225 TRACE("Restoring current maximized child %p\n", top_child);
1226 ShowWindow(top_child, SW_SHOWNOACTIVATE);
1230 SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
1233 if (cs->style & WS_VISIBLE)
1234 ShowWindow( hwnd, sw );
1236 /* Call WH_SHELL hook */
1238 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1239 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1241 TRACE("created window %p\n", hwnd);
1242 return hwnd;
1246 /***********************************************************************
1247 * CreateWindow (USER.41)
1249 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1250 DWORD style, INT16 x, INT16 y, INT16 width,
1251 INT16 height, HWND16 parent, HMENU16 menu,
1252 HINSTANCE16 instance, LPVOID data )
1254 return CreateWindowEx16( 0, className, windowName, style,
1255 x, y, width, height, parent, menu, instance, data );
1259 /***********************************************************************
1260 * CreateWindowEx (USER.452)
1262 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1263 LPCSTR windowName, DWORD style, INT16 x,
1264 INT16 y, INT16 width, INT16 height,
1265 HWND16 parent, HMENU16 menu,
1266 HINSTANCE16 instance, LPVOID data )
1268 ATOM classAtom;
1269 CREATESTRUCTA cs;
1270 char buffer[256];
1272 /* Find the class atom */
1274 if (HIWORD(className))
1276 if (!(classAtom = GlobalFindAtomA( className )))
1278 ERR( "bad class name %s\n", debugstr_a(className) );
1279 return 0;
1282 else
1284 classAtom = LOWORD(className);
1285 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1287 ERR( "bad atom %x\n", classAtom);
1288 return 0;
1290 className = buffer;
1293 /* Fix the coordinates */
1295 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1296 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1297 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1298 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1300 /* Create the window */
1302 cs.lpCreateParams = data;
1303 cs.hInstance = HINSTANCE_32(instance);
1304 cs.hMenu = HMENU_32(menu);
1305 cs.hwndParent = WIN_Handle32( parent );
1306 cs.style = style;
1307 cs.lpszName = windowName;
1308 cs.lpszClass = className;
1309 cs.dwExStyle = exStyle;
1311 return HWND_16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
1315 /***********************************************************************
1316 * CreateWindowExA (USER32.@)
1318 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1319 LPCSTR windowName, DWORD style, INT x,
1320 INT y, INT width, INT height,
1321 HWND parent, HMENU menu,
1322 HINSTANCE instance, LPVOID data )
1324 ATOM classAtom;
1325 CREATESTRUCTA cs;
1326 char buffer[256];
1328 /* Find the class atom */
1330 if (HIWORD(className))
1332 if (!(classAtom = GlobalFindAtomA( className )))
1334 ERR( "bad class name %s\n", debugstr_a(className) );
1335 return 0;
1338 else
1340 classAtom = LOWORD(className);
1341 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1343 ERR( "bad atom %x\n", classAtom);
1344 return 0;
1346 className = buffer;
1349 /* Create the window */
1351 cs.lpCreateParams = data;
1352 cs.hInstance = instance;
1353 cs.hMenu = menu;
1354 cs.hwndParent = parent;
1355 cs.x = x;
1356 cs.y = y;
1357 cs.cx = width;
1358 cs.cy = height;
1359 cs.style = style;
1360 cs.lpszName = windowName;
1361 cs.lpszClass = className;
1362 cs.dwExStyle = exStyle;
1364 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1368 /***********************************************************************
1369 * CreateWindowExW (USER32.@)
1371 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1372 LPCWSTR windowName, DWORD style, INT x,
1373 INT y, INT width, INT height,
1374 HWND parent, HMENU menu,
1375 HINSTANCE instance, LPVOID data )
1377 ATOM classAtom;
1378 CREATESTRUCTW cs;
1379 WCHAR buffer[256];
1381 /* Find the class atom */
1383 if (HIWORD(className))
1385 if (!(classAtom = GlobalFindAtomW( className )))
1387 ERR( "bad class name %s\n", debugstr_w(className) );
1388 return 0;
1391 else
1393 classAtom = LOWORD(className);
1394 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1396 ERR( "bad atom %x\n", classAtom);
1397 return 0;
1399 className = buffer;
1402 /* Create the window */
1404 cs.lpCreateParams = data;
1405 cs.hInstance = instance;
1406 cs.hMenu = menu;
1407 cs.hwndParent = parent;
1408 cs.x = x;
1409 cs.y = y;
1410 cs.cx = width;
1411 cs.cy = height;
1412 cs.style = style;
1413 cs.lpszName = windowName;
1414 cs.lpszClass = className;
1415 cs.dwExStyle = exStyle;
1417 /* Note: we rely on the fact that CREATESTRUCTA and */
1418 /* CREATESTRUCTW have the same layout. */
1419 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1423 /***********************************************************************
1424 * WIN_SendDestroyMsg
1426 static void WIN_SendDestroyMsg( HWND hwnd )
1428 GUITHREADINFO info;
1430 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1432 if (hwnd == info.hwndCaret) DestroyCaret();
1433 if (hwnd == info.hwndActive) WINPOS_ActivateOtherWindow( hwnd );
1435 if (USER_Driver.pResetSelectionOwner)
1436 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1439 * Send the WM_DESTROY to the window.
1441 SendMessageA( hwnd, WM_DESTROY, 0, 0);
1444 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1445 * make sure that the window still exists when we come back.
1447 if (IsWindow(hwnd))
1449 HWND* pWndArray;
1450 int i;
1452 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1454 /* start from the end (FIXME: is this needed?) */
1455 for (i = 0; pWndArray[i]; i++) ;
1457 while (--i >= 0)
1459 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1461 HeapFree( GetProcessHeap(), 0, pWndArray );
1463 else
1464 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1468 /***********************************************************************
1469 * DestroyWindow (USER32.@)
1471 BOOL WINAPI DestroyWindow( HWND hwnd )
1473 BOOL is_child;
1475 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1477 SetLastError( ERROR_ACCESS_DENIED );
1478 return FALSE;
1481 TRACE("(%p)\n", hwnd);
1483 if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
1484 SendMessageW(GetAncestor(hwnd, GA_PARENT), WM_MDIREFRESHMENU, 0, 0);
1486 /* Call hooks */
1488 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1490 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1492 if (is_child)
1494 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1495 send_parent_notify( hwnd, WM_DESTROY );
1497 else if (!GetWindow( hwnd, GW_OWNER ))
1499 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1500 /* FIXME: clean up palette - see "Internals" p.352 */
1503 if (!IsWindow(hwnd)) return TRUE;
1505 if (USER_Driver.pResetSelectionOwner)
1506 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1508 /* Hide the window */
1510 /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
1511 if (is_child)
1512 ShowWindow( hwnd, SW_HIDE );
1513 else
1514 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1515 SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW );
1517 if (!IsWindow(hwnd)) return TRUE;
1519 /* Recursively destroy owned windows */
1521 if (!is_child)
1523 for (;;)
1525 int i, got_one = 0;
1526 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1527 if (list)
1529 for (i = 0; list[i]; i++)
1531 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1532 if (WIN_IsCurrentThread( list[i] ))
1534 DestroyWindow( list[i] );
1535 got_one = 1;
1536 continue;
1538 WIN_SetOwner( list[i], 0 );
1540 HeapFree( GetProcessHeap(), 0, list );
1542 if (!got_one) break;
1546 /* Send destroy messages */
1548 WIN_SendDestroyMsg( hwnd );
1549 if (!IsWindow( hwnd )) return TRUE;
1551 if (GetClipboardOwner() == hwnd)
1552 CLIPBOARD_ReleaseOwner();
1554 /* Unlink now so we won't bother with the children later on */
1556 WIN_UnlinkWindow( hwnd );
1558 /* Destroy the window storage */
1560 WIN_DestroyWindow( hwnd );
1561 return TRUE;
1565 /***********************************************************************
1566 * CloseWindow (USER32.@)
1568 BOOL WINAPI CloseWindow( HWND hwnd )
1570 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1571 ShowWindow( hwnd, SW_MINIMIZE );
1572 return TRUE;
1576 /***********************************************************************
1577 * OpenIcon (USER32.@)
1579 BOOL WINAPI OpenIcon( HWND hwnd )
1581 if (!IsIconic( hwnd )) return FALSE;
1582 ShowWindow( hwnd, SW_SHOWNORMAL );
1583 return TRUE;
1587 /***********************************************************************
1588 * WIN_FindWindow
1590 * Implementation of FindWindow() and FindWindowEx().
1592 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1594 HWND *list = NULL;
1595 HWND retvalue = 0;
1596 int i = 0, len = 0;
1597 WCHAR *buffer = NULL;
1599 if (!parent) parent = GetDesktopWindow();
1600 if (title)
1602 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1603 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1606 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1608 if (child)
1610 child = WIN_GetFullHandle( child );
1611 while (list[i] && list[i] != child) i++;
1612 if (!list[i]) goto done;
1613 i++; /* start from next window */
1616 if (title)
1618 while (list[i])
1620 if (GetWindowTextW( list[i], buffer, len + 1 ) && !strcmpiW( buffer, title )) break;
1621 i++;
1624 retvalue = list[i];
1626 done:
1627 if (list) HeapFree( GetProcessHeap(), 0, list );
1628 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1629 return retvalue;
1634 /***********************************************************************
1635 * FindWindowA (USER32.@)
1637 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1639 HWND ret = FindWindowExA( 0, 0, className, title );
1640 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1641 return ret;
1645 /***********************************************************************
1646 * FindWindowExA (USER32.@)
1648 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1649 LPCSTR className, LPCSTR title )
1651 ATOM atom = 0;
1652 LPWSTR buffer;
1653 HWND hwnd;
1654 INT len;
1656 if (className)
1658 /* If the atom doesn't exist, then no class */
1659 /* with this name exists either. */
1660 if (!(atom = GlobalFindAtomA( className )))
1662 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1663 return 0;
1666 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
1668 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1669 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1670 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
1671 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1672 HeapFree( GetProcessHeap(), 0, buffer );
1673 return hwnd;
1677 /***********************************************************************
1678 * FindWindowExW (USER32.@)
1680 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1681 LPCWSTR className, LPCWSTR title )
1683 ATOM atom = 0;
1685 if (className)
1687 /* If the atom doesn't exist, then no class */
1688 /* with this name exists either. */
1689 if (!(atom = GlobalFindAtomW( className )))
1691 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1692 return 0;
1695 return WIN_FindWindow( parent, child, atom, title );
1699 /***********************************************************************
1700 * FindWindowW (USER32.@)
1702 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1704 return FindWindowExW( 0, 0, className, title );
1708 /**********************************************************************
1709 * GetDesktopWindow (USER32.@)
1711 HWND WINAPI GetDesktopWindow(void)
1713 if (pWndDesktop) return pWndDesktop->hwndSelf;
1714 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" );
1715 ExitProcess(1);
1716 return 0;
1720 /*******************************************************************
1721 * EnableWindow (USER32.@)
1723 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1725 WND *wndPtr;
1726 BOOL retvalue;
1727 LONG style;
1728 HWND full_handle;
1730 if (is_broadcast(hwnd))
1732 SetLastError( ERROR_INVALID_PARAMETER );
1733 return FALSE;
1736 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1737 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1739 hwnd = full_handle;
1741 TRACE("( %p, %d )\n", hwnd, enable);
1743 if (!(wndPtr = WIN_GetPtr( hwnd ))) return FALSE;
1744 style = wndPtr->dwStyle;
1745 retvalue = ((style & WS_DISABLED) != 0);
1746 WIN_ReleasePtr( wndPtr );
1748 if (enable && retvalue)
1750 WIN_SetStyle( hwnd, style & ~WS_DISABLED );
1751 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1753 else if (!enable && !retvalue)
1755 HWND capture_wnd;
1757 SendMessageA( hwnd, WM_CANCELMODE, 0, 0);
1759 WIN_SetStyle( hwnd, style | WS_DISABLED );
1761 if (hwnd == GetFocus())
1762 SetFocus( 0 ); /* A disabled window can't have the focus */
1764 capture_wnd = GetCapture();
1765 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1766 ReleaseCapture(); /* A disabled window can't capture the mouse */
1768 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1770 return retvalue;
1774 /***********************************************************************
1775 * IsWindowEnabled (USER32.@)
1777 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1779 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1783 /***********************************************************************
1784 * IsWindowUnicode (USER32.@)
1786 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1788 WND * wndPtr;
1789 BOOL retvalue;
1791 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1792 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1793 WIN_ReleaseWndPtr(wndPtr);
1794 return retvalue;
1798 /**********************************************************************
1799 * GetWindowWord (USER32.@)
1801 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1803 if (offset >= 0)
1805 WORD retvalue = 0;
1806 WND *wndPtr = WIN_GetPtr( hwnd );
1807 if (!wndPtr)
1809 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1810 return 0;
1812 if (wndPtr == WND_OTHER_PROCESS)
1814 SERVER_START_REQ( set_window_info )
1816 req->handle = hwnd;
1817 req->flags = 0; /* don't set anything, just retrieve */
1818 req->extra_offset = offset;
1819 req->extra_size = sizeof(retvalue);
1820 if (!wine_server_call_err( req ))
1821 memcpy( &retvalue, &reply->old_extra_value, sizeof(retvalue) );
1823 SERVER_END_REQ;
1824 return retvalue;
1826 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1828 WARN("Invalid offset %d\n", offset );
1829 SetLastError( ERROR_INVALID_INDEX );
1831 else memcpy( &retvalue, (char *)wndPtr->wExtra + offset, sizeof(retvalue) );
1832 WIN_ReleasePtr( wndPtr );
1833 return retvalue;
1836 switch(offset)
1838 case GWL_HWNDPARENT:
1839 return GetWindowLongW( hwnd, offset );
1840 case GWL_ID:
1841 case GWL_HINSTANCE:
1843 LONG ret = GetWindowLongW( hwnd, offset );
1844 if (HIWORD(ret))
1845 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1846 return LOWORD(ret);
1848 default:
1849 WARN("Invalid offset %d\n", offset );
1850 return 0;
1855 /**********************************************************************
1856 * SetWindowWord (USER32.@)
1858 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1860 WORD retval = 0;
1861 WND * wndPtr;
1863 switch(offset)
1865 case GWL_ID:
1866 case GWL_HINSTANCE:
1867 case GWL_HWNDPARENT:
1868 return SetWindowLongW( hwnd, offset, (UINT)newval );
1869 default:
1870 if (offset < 0)
1872 WARN("Invalid offset %d\n", offset );
1873 SetLastError( ERROR_INVALID_INDEX );
1874 return 0;
1878 wndPtr = WIN_GetPtr( hwnd );
1879 if (wndPtr == WND_OTHER_PROCESS)
1881 if (IsWindow(hwnd))
1882 FIXME( "set %d <- %x not supported yet on other process window %p\n",
1883 offset, newval, hwnd );
1884 wndPtr = NULL;
1886 if (!wndPtr)
1888 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1889 return 0;
1892 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1894 WARN("Invalid offset %d\n", offset );
1895 WIN_ReleasePtr(wndPtr);
1896 SetLastError( ERROR_INVALID_INDEX );
1897 return 0;
1900 SERVER_START_REQ( set_window_info )
1902 req->handle = hwnd;
1903 req->flags = SET_WIN_EXTRA;
1904 req->extra_offset = offset;
1905 req->extra_size = sizeof(newval);
1906 memcpy( &req->extra_value, &newval, sizeof(newval) );
1907 if (!wine_server_call_err( req ))
1909 void *ptr = (char *)wndPtr->wExtra + offset;
1910 memcpy( &retval, ptr, sizeof(retval) );
1911 memcpy( ptr, &newval, sizeof(newval) );
1914 SERVER_END_REQ;
1915 WIN_ReleasePtr( wndPtr );
1916 return retval;
1920 /**********************************************************************
1921 * WIN_GetWindowLong
1923 * Helper function for GetWindowLong().
1925 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1927 LONG retvalue = 0;
1928 WND *wndPtr;
1930 if (offset == GWL_HWNDPARENT)
1932 HWND parent = GetAncestor( hwnd, GA_PARENT );
1933 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1934 return (LONG)parent;
1937 if (!(wndPtr = WIN_GetPtr( hwnd )))
1939 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1940 return 0;
1943 if (wndPtr == WND_OTHER_PROCESS)
1945 if (offset == GWL_WNDPROC)
1947 SetLastError( ERROR_ACCESS_DENIED );
1948 return 0;
1950 SERVER_START_REQ( set_window_info )
1952 req->handle = hwnd;
1953 req->flags = 0; /* don't set anything, just retrieve */
1954 req->extra_offset = (offset >= 0) ? offset : -1;
1955 req->extra_size = (offset >= 0) ? sizeof(retvalue) : 0;
1956 if (!wine_server_call_err( req ))
1958 switch(offset)
1960 case GWL_STYLE: retvalue = reply->old_style; break;
1961 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1962 case GWL_ID: retvalue = reply->old_id; break;
1963 case GWL_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1964 case GWL_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
1965 default:
1966 if (offset >= 0) retvalue = reply->old_extra_value;
1967 else SetLastError( ERROR_INVALID_INDEX );
1968 break;
1972 SERVER_END_REQ;
1973 return retvalue;
1976 /* now we have a valid wndPtr */
1978 if (offset >= 0)
1980 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
1983 * Some programs try to access last element from 16 bit
1984 * code using illegal offset value. Hopefully this is
1985 * what those programs really expect.
1987 if (type == WIN_PROC_16 &&
1988 wndPtr->cbWndExtra >= 4 &&
1989 offset == wndPtr->cbWndExtra - sizeof(WORD))
1991 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
1993 ERR( "- replaced invalid offset %d with %d\n",
1994 offset, offset2 );
1996 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset2);
1997 WIN_ReleasePtr( wndPtr );
1998 return retvalue;
2000 WARN("Invalid offset %d\n", offset );
2001 WIN_ReleasePtr( wndPtr );
2002 SetLastError( ERROR_INVALID_INDEX );
2003 return 0;
2005 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
2006 /* Special case for dialog window procedure */
2007 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2008 retvalue = (LONG)WINPROC_GetProc( (WNDPROC)retvalue, type );
2009 WIN_ReleasePtr( wndPtr );
2010 return retvalue;
2013 switch(offset)
2015 case GWL_USERDATA: retvalue = wndPtr->userdata; break;
2016 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
2017 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
2018 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu; break;
2019 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc, type ); break;
2020 case GWL_HINSTANCE: retvalue = (LONG)wndPtr->hInstance; break;
2021 default:
2022 WARN("Unknown offset %d\n", offset );
2023 SetLastError( ERROR_INVALID_INDEX );
2024 break;
2026 WIN_ReleasePtr(wndPtr);
2027 return retvalue;
2031 /**********************************************************************
2032 * WIN_SetWindowLong
2034 * Helper function for SetWindowLong().
2036 * 0 is the failure code. However, in the case of failure SetLastError
2037 * must be set to distinguish between a 0 return value and a failure.
2039 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
2040 WINDOWPROCTYPE type )
2042 STYLESTRUCT style;
2043 BOOL ok;
2044 LONG retval = 0;
2045 WND *wndPtr;
2047 TRACE( "%p %d %lx %x\n", hwnd, offset, newval, type );
2049 if (is_broadcast(hwnd))
2051 SetLastError( ERROR_INVALID_PARAMETER );
2052 return FALSE;
2054 if (!WIN_IsCurrentProcess( hwnd ))
2056 if (offset == GWL_WNDPROC)
2058 SetLastError( ERROR_ACCESS_DENIED );
2059 return 0;
2061 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
2064 wndPtr = WIN_GetPtr( hwnd );
2065 if (wndPtr->hwndSelf == GetDesktopWindow())
2067 /* can't change anything on the desktop window */
2068 WIN_ReleasePtr( wndPtr );
2069 SetLastError( ERROR_ACCESS_DENIED );
2070 return 0;
2073 /* first some special cases */
2074 switch( offset )
2076 case GWL_STYLE:
2077 case GWL_EXSTYLE:
2078 style.styleOld =
2079 offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
2080 style.styleNew = newval;
2081 WIN_ReleasePtr( wndPtr );
2082 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
2083 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
2084 newval = style.styleNew;
2085 break;
2086 case GWL_HWNDPARENT:
2087 if (wndPtr->parent == GetDesktopWindow())
2089 WIN_ReleasePtr( wndPtr );
2090 return (LONG)WIN_SetOwner( hwnd, (HWND)newval );
2092 else
2094 WIN_ReleasePtr( wndPtr );
2095 return (LONG)SetParent( hwnd, (HWND)newval );
2097 case GWL_WNDPROC:
2098 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2099 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC)newval, type, WIN_PROC_WINDOW );
2100 WIN_ReleasePtr( wndPtr );
2101 return retval;
2102 case GWL_ID:
2103 case GWL_HINSTANCE:
2104 case GWL_USERDATA:
2105 break;
2106 case DWL_DLGPROC:
2107 if ((wndPtr->cbWndExtra + sizeof(LONG) >= DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2109 WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWL_DLGPROC);
2110 retval = (LONG)WINPROC_GetProc( *ptr, type );
2111 WINPROC_SetProc( ptr, (WNDPROC)newval, type, WIN_PROC_WINDOW );
2112 WIN_ReleasePtr( wndPtr );
2113 return retval;
2115 /* fall through */
2116 default:
2117 if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
2119 WARN("Invalid offset %d\n", offset );
2120 WIN_ReleasePtr( wndPtr );
2121 SetLastError( ERROR_INVALID_INDEX );
2122 return 0;
2124 else
2126 LONG *ptr = (LONG *)((char *)wndPtr->wExtra + offset);
2127 if (*ptr == newval) /* already set to the same value */
2129 WIN_ReleasePtr( wndPtr );
2130 return newval;
2133 break;
2136 SERVER_START_REQ( set_window_info )
2138 req->handle = hwnd;
2139 req->extra_offset = -1;
2140 switch(offset)
2142 case GWL_STYLE:
2143 req->flags = SET_WIN_STYLE;
2144 req->style = newval;
2145 break;
2146 case GWL_EXSTYLE:
2147 req->flags = SET_WIN_EXSTYLE;
2148 req->ex_style = newval;
2149 break;
2150 case GWL_ID:
2151 req->flags = SET_WIN_ID;
2152 req->id = newval;
2153 break;
2154 case GWL_HINSTANCE:
2155 req->flags = SET_WIN_INSTANCE;
2156 req->instance = (void *)newval;
2157 break;
2158 case GWL_USERDATA:
2159 req->flags = SET_WIN_USERDATA;
2160 req->user_data = (void *)newval;
2161 break;
2162 default:
2163 req->flags = SET_WIN_EXTRA;
2164 req->extra_offset = offset;
2165 req->extra_size = sizeof(newval);
2166 memcpy( &req->extra_value, &newval, sizeof(newval) );
2168 if ((ok = !wine_server_call_err( req )))
2170 switch(offset)
2172 case GWL_STYLE:
2173 wndPtr->dwStyle = newval;
2174 retval = reply->old_style;
2175 break;
2176 case GWL_EXSTYLE:
2177 wndPtr->dwExStyle = newval;
2178 retval = reply->old_ex_style;
2179 break;
2180 case GWL_ID:
2181 wndPtr->wIDmenu = newval;
2182 retval = reply->old_id;
2183 break;
2184 case GWL_HINSTANCE:
2185 wndPtr->hInstance = (HINSTANCE)newval;
2186 retval = (ULONG_PTR)reply->old_instance;
2187 break;
2188 case GWL_USERDATA:
2189 wndPtr->userdata = newval;
2190 retval = (ULONG_PTR)reply->old_user_data;
2191 break;
2192 default:
2194 void *ptr = (char *)wndPtr->wExtra + offset;
2195 memcpy( &retval, ptr, sizeof(retval) );
2196 memcpy( ptr, &newval, sizeof(newval) );
2198 break;
2202 SERVER_END_REQ;
2203 WIN_ReleasePtr( wndPtr );
2205 if (!ok) return 0;
2207 if (offset == GWL_STYLE && USER_Driver.pSetWindowStyle)
2208 USER_Driver.pSetWindowStyle( hwnd, retval );
2210 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2211 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2213 return retval;
2217 /**********************************************************************
2218 * GetWindowLong (USER.135)
2220 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2222 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
2226 /**********************************************************************
2227 * GetWindowLongA (USER32.@)
2229 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2231 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2235 /**********************************************************************
2236 * GetWindowLongW (USER32.@)
2238 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2240 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2244 /**********************************************************************
2245 * SetWindowLong (USER.136)
2247 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2249 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
2253 /**********************************************************************
2254 * SetWindowLongA (USER32.@)
2256 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2258 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2262 /**********************************************************************
2263 * SetWindowLongW (USER32.@) Set window attribute
2265 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2266 * value in a window's extra memory.
2268 * The _hwnd_ parameter specifies the window. is the handle to a
2269 * window that has extra memory. The _newval_ parameter contains the
2270 * new attribute or extra memory value. If positive, the _offset_
2271 * parameter is the byte-addressed location in the window's extra
2272 * memory to set. If negative, _offset_ specifies the window
2273 * attribute to set, and should be one of the following values:
2275 * GWL_EXSTYLE The window's extended window style
2277 * GWL_STYLE The window's window style.
2279 * GWL_WNDPROC Pointer to the window's window procedure.
2281 * GWL_HINSTANCE The window's pplication instance handle.
2283 * GWL_ID The window's identifier.
2285 * GWL_USERDATA The window's user-specified data.
2287 * If the window is a dialog box, the _offset_ parameter can be one of
2288 * the following values:
2290 * DWL_DLGPROC The address of the window's dialog box procedure.
2292 * DWL_MSGRESULT The return value of a message
2293 * that the dialog box procedure processed.
2295 * DWL_USER Application specific information.
2297 * RETURNS
2299 * If successful, returns the previous value located at _offset_. Otherwise,
2300 * returns 0.
2302 * NOTES
2304 * Extra memory for a window class is specified by a nonzero cbWndExtra
2305 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2306 * time of class creation.
2308 * Using GWL_WNDPROC to set a new window procedure effectively creates
2309 * a window subclass. Use CallWindowProc() in the new windows procedure
2310 * to pass messages to the superclass's window procedure.
2312 * The user data is reserved for use by the application which created
2313 * the window.
2315 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2316 * instead, call the EnableWindow() function to change the window's
2317 * disabled state.
2319 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2320 * SetParent() instead.
2322 * Win95:
2323 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2324 * it sends WM_STYLECHANGING before changing the settings
2325 * and WM_STYLECHANGED afterwards.
2326 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2328 LONG WINAPI SetWindowLongW(
2329 HWND hwnd, /* [in] window to alter */
2330 INT offset, /* [in] offset, in bytes, of location to alter */
2331 LONG newval /* [in] new value of location */
2333 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2337 /*******************************************************************
2338 * GetWindowTextA (USER32.@)
2340 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2342 WCHAR *buffer;
2344 if (WIN_IsCurrentProcess( hwnd ))
2345 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2347 /* when window belongs to other process, don't send a message */
2348 if (nMaxCount <= 0) return 0;
2349 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2350 get_server_window_text( hwnd, buffer, nMaxCount );
2351 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2352 lpString[nMaxCount-1] = 0;
2353 HeapFree( GetProcessHeap(), 0, buffer );
2354 return strlen(lpString);
2358 /*******************************************************************
2359 * InternalGetWindowText (USER32.@)
2361 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2363 WND *win;
2365 if (nMaxCount <= 0) return 0;
2366 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2367 if (win != WND_OTHER_PROCESS)
2369 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2370 else lpString[0] = 0;
2371 WIN_ReleasePtr( win );
2373 else
2375 get_server_window_text( hwnd, lpString, nMaxCount );
2377 return strlenW(lpString);
2381 /*******************************************************************
2382 * GetWindowTextW (USER32.@)
2384 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2386 if (WIN_IsCurrentProcess( hwnd ))
2387 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2389 /* when window belongs to other process, don't send a message */
2390 if (nMaxCount <= 0) return 0;
2391 get_server_window_text( hwnd, lpString, nMaxCount );
2392 return strlenW(lpString);
2396 /*******************************************************************
2397 * SetWindowText (USER32.@)
2398 * SetWindowTextA (USER32.@)
2400 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2402 if (is_broadcast(hwnd))
2404 SetLastError( ERROR_INVALID_PARAMETER );
2405 return FALSE;
2407 if (!WIN_IsCurrentProcess( hwnd ))
2409 FIXME( "cannot set text %s of other process window %p\n", debugstr_a(lpString), hwnd );
2410 SetLastError( ERROR_ACCESS_DENIED );
2411 return FALSE;
2413 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2417 /*******************************************************************
2418 * SetWindowTextW (USER32.@)
2420 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2422 if (is_broadcast(hwnd))
2424 SetLastError( ERROR_INVALID_PARAMETER );
2425 return FALSE;
2427 if (!WIN_IsCurrentProcess( hwnd ))
2429 FIXME( "cannot set text %s of other process window %p\n", debugstr_w(lpString), hwnd );
2430 SetLastError( ERROR_ACCESS_DENIED );
2431 return FALSE;
2433 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2437 /*******************************************************************
2438 * GetWindowTextLengthA (USER32.@)
2440 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2442 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2445 /*******************************************************************
2446 * GetWindowTextLengthW (USER32.@)
2448 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2450 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2454 /*******************************************************************
2455 * IsWindow (USER32.@)
2457 BOOL WINAPI IsWindow( HWND hwnd )
2459 WND *ptr;
2460 BOOL ret;
2462 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2464 if (ptr != WND_OTHER_PROCESS)
2466 WIN_ReleasePtr( ptr );
2467 return TRUE;
2470 /* check other processes */
2471 SERVER_START_REQ( get_window_info )
2473 req->handle = hwnd;
2474 ret = !wine_server_call_err( req );
2476 SERVER_END_REQ;
2477 return ret;
2481 /***********************************************************************
2482 * GetWindowThreadProcessId (USER32.@)
2484 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2486 WND *ptr;
2487 DWORD tid = 0;
2489 if (!(ptr = WIN_GetPtr( hwnd )))
2491 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2492 return 0;
2495 if (ptr != WND_OTHER_PROCESS)
2497 /* got a valid window */
2498 tid = ptr->tid;
2499 if (process) *process = GetCurrentProcessId();
2500 WIN_ReleasePtr( ptr );
2501 return tid;
2504 /* check other processes */
2505 SERVER_START_REQ( get_window_info )
2507 req->handle = hwnd;
2508 if (!wine_server_call_err( req ))
2510 tid = (DWORD)reply->tid;
2511 if (process) *process = (DWORD)reply->pid;
2514 SERVER_END_REQ;
2515 return tid;
2519 /*****************************************************************
2520 * GetParent (USER32.@)
2522 HWND WINAPI GetParent( HWND hwnd )
2524 WND *wndPtr;
2525 HWND retvalue = 0;
2527 if (!(wndPtr = WIN_GetPtr( hwnd )))
2529 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2530 return 0;
2532 if (wndPtr == WND_OTHER_PROCESS)
2534 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2535 if (style & (WS_POPUP | WS_CHILD))
2537 SERVER_START_REQ( get_window_tree )
2539 req->handle = hwnd;
2540 if (!wine_server_call_err( req ))
2542 if (style & WS_POPUP) retvalue = reply->owner;
2543 else if (style & WS_CHILD) retvalue = reply->parent;
2546 SERVER_END_REQ;
2549 else
2551 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2552 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2553 WIN_ReleasePtr( wndPtr );
2555 return retvalue;
2559 /*****************************************************************
2560 * GetAncestor (USER32.@)
2562 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2564 WND *win;
2565 HWND *list, ret = 0;
2567 switch(type)
2569 case GA_PARENT:
2570 if (!(win = WIN_GetPtr( hwnd )))
2572 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2573 return 0;
2575 if (win != WND_OTHER_PROCESS)
2577 ret = win->parent;
2578 WIN_ReleasePtr( win );
2580 else /* need to query the server */
2582 SERVER_START_REQ( get_window_tree )
2584 req->handle = hwnd;
2585 if (!wine_server_call_err( req )) ret = reply->parent;
2587 SERVER_END_REQ;
2589 break;
2591 case GA_ROOT:
2592 if (!(list = WIN_ListParents( hwnd ))) return 0;
2594 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2595 else
2597 int count = 2;
2598 while (list[count]) count++;
2599 ret = list[count - 2]; /* get the one before the desktop */
2601 HeapFree( GetProcessHeap(), 0, list );
2602 break;
2604 case GA_ROOTOWNER:
2605 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2606 for (;;)
2608 HWND parent = GetParent( ret );
2609 if (!parent) break;
2610 ret = parent;
2612 break;
2614 return ret;
2618 /*****************************************************************
2619 * SetParent (USER32.@)
2621 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2623 WND *wndPtr;
2624 HWND retvalue, full_handle;
2625 BOOL was_visible;
2627 if (is_broadcast(hwnd) || is_broadcast(parent))
2629 SetLastError(ERROR_INVALID_PARAMETER);
2630 return 0;
2633 if (!parent) parent = GetDesktopWindow();
2634 else parent = WIN_GetFullHandle( parent );
2636 if (!IsWindow( parent ))
2638 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2639 return 0;
2642 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2643 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2645 hwnd = full_handle;
2647 if (USER_Driver.pSetParent)
2648 return USER_Driver.pSetParent( hwnd, parent );
2650 /* Windows hides the window first, then shows it again
2651 * including the WM_SHOWWINDOW messages and all */
2652 was_visible = ShowWindow( hwnd, SW_HIDE );
2654 if (!IsWindow( parent )) return 0;
2655 if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return 0;
2657 retvalue = wndPtr->parent; /* old parent */
2658 if (parent != retvalue)
2660 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2662 if (parent != GetDesktopWindow()) /* a child window */
2664 if (!(wndPtr->dwStyle & WS_CHILD))
2666 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
2667 if (menu) DestroyMenu( menu );
2671 WIN_ReleasePtr( wndPtr );
2673 /* SetParent additionally needs to make hwnd the topmost window
2674 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2675 WM_WINDOWPOSCHANGED notification messages.
2677 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2678 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2679 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2680 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2681 return retvalue;
2685 /*******************************************************************
2686 * IsChild (USER32.@)
2688 BOOL WINAPI IsChild( HWND parent, HWND child )
2690 HWND *list = WIN_ListParents( child );
2691 int i;
2692 BOOL ret;
2694 if (!list) return FALSE;
2695 parent = WIN_GetFullHandle( parent );
2696 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2697 ret = (list[i] != 0);
2698 HeapFree( GetProcessHeap(), 0, list );
2699 return ret;
2703 /***********************************************************************
2704 * IsWindowVisible (USER32.@)
2706 BOOL WINAPI IsWindowVisible( HWND hwnd )
2708 HWND *list;
2709 BOOL retval;
2710 int i;
2712 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2713 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2714 for (i = 0; list[i]; i++)
2715 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2716 retval = !list[i];
2717 HeapFree( GetProcessHeap(), 0, list );
2718 return retval;
2722 /***********************************************************************
2723 * WIN_IsWindowDrawable
2725 * hwnd is drawable when it is visible, all parents are not
2726 * minimized, and it is itself not minimized unless we are
2727 * trying to draw its default class icon.
2729 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2731 HWND *list;
2732 BOOL retval;
2733 int i;
2734 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2736 if (!(style & WS_VISIBLE)) return FALSE;
2737 if ((style & WS_MINIMIZE) && icon && GetClassLongA( hwnd, GCL_HICON )) return FALSE;
2739 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2740 for (i = 0; list[i]; i++)
2741 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2742 break;
2743 retval = !list[i];
2744 HeapFree( GetProcessHeap(), 0, list );
2745 return retval;
2749 /*******************************************************************
2750 * GetTopWindow (USER32.@)
2752 HWND WINAPI GetTopWindow( HWND hwnd )
2754 if (!hwnd) hwnd = GetDesktopWindow();
2755 return GetWindow( hwnd, GW_CHILD );
2759 /*******************************************************************
2760 * GetWindow (USER32.@)
2762 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2764 HWND retval = 0;
2766 if (rel == GW_OWNER) /* this one may be available locally */
2768 WND *wndPtr = WIN_GetPtr( hwnd );
2769 if (!wndPtr)
2771 SetLastError( ERROR_INVALID_HANDLE );
2772 return 0;
2774 if (wndPtr != WND_OTHER_PROCESS)
2776 retval = wndPtr->owner;
2777 WIN_ReleasePtr( wndPtr );
2778 return retval;
2780 /* else fall through to server call */
2783 SERVER_START_REQ( get_window_tree )
2785 req->handle = hwnd;
2786 if (!wine_server_call_err( req ))
2788 switch(rel)
2790 case GW_HWNDFIRST:
2791 retval = reply->first_sibling;
2792 break;
2793 case GW_HWNDLAST:
2794 retval = reply->last_sibling;
2795 break;
2796 case GW_HWNDNEXT:
2797 retval = reply->next_sibling;
2798 break;
2799 case GW_HWNDPREV:
2800 retval = reply->prev_sibling;
2801 break;
2802 case GW_OWNER:
2803 retval = reply->owner;
2804 break;
2805 case GW_CHILD:
2806 retval = reply->first_child;
2807 break;
2811 SERVER_END_REQ;
2812 return retval;
2816 /***********************************************************************
2817 * WIN_InternalShowOwnedPopups
2819 * Internal version of ShowOwnedPopups; Wine functions should use this
2820 * to avoid interfering with application calls to ShowOwnedPopups
2821 * and to make sure the application can't prevent showing/hiding.
2823 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2827 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2829 int count = 0;
2830 WND *pWnd;
2831 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2833 if (!win_array) return TRUE;
2836 * Show windows Lowest first, Highest last to preserve Z-Order
2838 while (win_array[count]) count++;
2839 while (--count >= 0)
2841 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2842 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2844 if (pWnd->dwStyle & WS_POPUP)
2846 if (fShow)
2848 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2849 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
2852 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2854 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2855 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2858 else
2860 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2861 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2862 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2865 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2867 ShowWindow(pWnd->hwndSelf,SW_HIDE);
2868 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2869 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
2873 WIN_ReleaseWndPtr( pWnd );
2875 HeapFree( GetProcessHeap(), 0, win_array );
2877 return TRUE;
2880 /*******************************************************************
2881 * ShowOwnedPopups (USER32.@)
2883 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2885 int count = 0;
2886 WND *pWnd;
2887 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2889 if (!win_array) return TRUE;
2891 while (win_array[count]) count++;
2892 while (--count >= 0)
2894 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2895 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2897 if (pWnd->dwStyle & WS_POPUP)
2899 if (fShow)
2901 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2903 /* In Windows, ShowOwnedPopups(TRUE) generates
2904 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2905 * regardless of the state of the owner
2907 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2908 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2911 else
2913 if (IsWindowVisible(pWnd->hwndSelf))
2915 /* In Windows, ShowOwnedPopups(FALSE) generates
2916 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2917 * regardless of the state of the owner
2919 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2920 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2924 WIN_ReleaseWndPtr( pWnd );
2926 HeapFree( GetProcessHeap(), 0, win_array );
2927 return TRUE;
2931 /*******************************************************************
2932 * GetLastActivePopup (USER32.@)
2934 HWND WINAPI GetLastActivePopup( HWND hwnd )
2936 HWND retval = hwnd;
2938 SERVER_START_REQ( get_window_info )
2940 req->handle = hwnd;
2941 if (!wine_server_call_err( req )) retval = reply->last_active;
2943 SERVER_END_REQ;
2944 return retval;
2948 /*******************************************************************
2949 * WIN_ListParents
2951 * Build an array of all parents of a given window, starting with
2952 * the immediate parent. The array must be freed with HeapFree.
2953 * Returns NULL if window is a top-level window.
2955 HWND *WIN_ListParents( HWND hwnd )
2957 WND *win;
2958 HWND current, *list;
2959 int pos = 0, size = 16, count = 0;
2961 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2963 current = hwnd;
2964 for (;;)
2966 if (!(win = WIN_GetPtr( current ))) goto empty;
2967 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
2968 list[pos] = win->parent;
2969 WIN_ReleasePtr( win );
2970 if (!(current = list[pos]))
2972 if (!pos) goto empty;
2973 return list;
2975 if (++pos == size - 1)
2977 /* need to grow the list */
2978 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
2979 if (!new_list) goto empty;
2980 list = new_list;
2981 size += 16;
2985 /* at least one parent belongs to another process, have to query the server */
2987 for (;;)
2989 count = 0;
2990 SERVER_START_REQ( get_window_parents )
2992 req->handle = hwnd;
2993 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
2994 if (!wine_server_call( req )) count = reply->count;
2996 SERVER_END_REQ;
2997 if (!count) goto empty;
2998 if (size > count)
3000 list[count] = 0;
3001 return list;
3003 HeapFree( GetProcessHeap(), 0, list );
3004 size = count + 1;
3005 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
3008 empty:
3009 HeapFree( GetProcessHeap(), 0, list );
3010 return NULL;
3014 /*******************************************************************
3015 * WIN_ListChildren
3017 * Build an array of the children of a given window. The array must be
3018 * freed with HeapFree. Returns NULL when no windows are found.
3020 HWND *WIN_ListChildren( HWND hwnd )
3022 return list_window_children( hwnd, 0, 0 );
3026 /*******************************************************************
3027 * EnumWindows (USER32.@)
3029 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
3031 HWND *list;
3032 BOOL ret = TRUE;
3033 int i, iWndsLocks;
3035 /* We have to build a list of all windows first, to avoid */
3036 /* unpleasant side-effects, for instance if the callback */
3037 /* function changes the Z-order of the windows. */
3039 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
3041 /* Now call the callback function for every window */
3043 iWndsLocks = WIN_SuspendWndsLock();
3044 for (i = 0; list[i]; i++)
3046 /* Make sure that the window still exists */
3047 if (!IsWindow( list[i] )) continue;
3048 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
3050 WIN_RestoreWndsLock(iWndsLocks);
3051 HeapFree( GetProcessHeap(), 0, list );
3052 return ret;
3056 /**********************************************************************
3057 * EnumThreadWindows (USER32.@)
3059 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
3061 HWND *list;
3062 int i, iWndsLocks;
3064 if (!(list = list_window_children( GetDesktopWindow(), 0, id ))) return TRUE;
3066 /* Now call the callback function for every window */
3068 iWndsLocks = WIN_SuspendWndsLock();
3069 for (i = 0; list[i]; i++)
3070 if (!func( list[i], lParam )) break;
3071 WIN_RestoreWndsLock(iWndsLocks);
3072 HeapFree( GetProcessHeap(), 0, list );
3073 return TRUE;
3077 /**********************************************************************
3078 * WIN_EnumChildWindows
3080 * Helper function for EnumChildWindows().
3082 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
3084 HWND *childList;
3085 BOOL ret = FALSE;
3087 for ( ; *list; list++)
3089 /* Make sure that the window still exists */
3090 if (!IsWindow( *list )) continue;
3091 /* skip owned windows */
3092 if (GetWindow( *list, GW_OWNER )) continue;
3093 /* Build children list first */
3094 childList = WIN_ListChildren( *list );
3096 ret = func( *list, lParam );
3098 if (childList)
3100 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
3101 HeapFree( GetProcessHeap(), 0, childList );
3103 if (!ret) return FALSE;
3105 return TRUE;
3109 /**********************************************************************
3110 * EnumChildWindows (USER32.@)
3112 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
3114 HWND *list;
3115 int iWndsLocks;
3117 if (!(list = WIN_ListChildren( parent ))) return FALSE;
3118 iWndsLocks = WIN_SuspendWndsLock();
3119 WIN_EnumChildWindows( list, func, lParam );
3120 WIN_RestoreWndsLock(iWndsLocks);
3121 HeapFree( GetProcessHeap(), 0, list );
3122 return TRUE;
3126 /*******************************************************************
3127 * AnyPopup (USER.52)
3129 BOOL16 WINAPI AnyPopup16(void)
3131 return AnyPopup();
3135 /*******************************************************************
3136 * AnyPopup (USER32.@)
3138 BOOL WINAPI AnyPopup(void)
3140 int i;
3141 BOOL retvalue;
3142 HWND *list = WIN_ListChildren( GetDesktopWindow() );
3144 if (!list) return FALSE;
3145 for (i = 0; list[i]; i++)
3147 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
3149 retvalue = (list[i] != 0);
3150 HeapFree( GetProcessHeap(), 0, list );
3151 return retvalue;
3155 /*******************************************************************
3156 * FlashWindow (USER32.@)
3158 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3160 WND *wndPtr = WIN_FindWndPtr(hWnd);
3162 TRACE("%p\n", hWnd);
3164 if (!wndPtr) return FALSE;
3165 hWnd = wndPtr->hwndSelf; /* make it a full handle */
3167 if (wndPtr->dwStyle & WS_MINIMIZE)
3169 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3171 HDC hDC = GetDC(hWnd);
3173 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM)hDC, 0 ))
3174 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
3176 ReleaseDC( hWnd, hDC );
3177 wndPtr->flags |= WIN_NCACTIVATED;
3179 else
3181 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3182 wndPtr->flags &= ~WIN_NCACTIVATED;
3184 WIN_ReleaseWndPtr(wndPtr);
3185 return TRUE;
3187 else
3189 WPARAM16 wparam;
3190 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3191 else wparam = (hWnd == GetForegroundWindow());
3193 WIN_ReleaseWndPtr(wndPtr);
3194 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3195 return wparam;
3199 /*******************************************************************
3200 * FlashWindowEx (USER32.@)
3202 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
3204 FIXME("%p\n", pfwi);
3205 return TRUE;
3208 /*******************************************************************
3209 * GetWindowContextHelpId (USER32.@)
3211 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3213 DWORD retval;
3214 WND *wnd = WIN_FindWndPtr( hwnd );
3215 if (!wnd) return 0;
3216 retval = wnd->helpContext;
3217 WIN_ReleaseWndPtr(wnd);
3218 return retval;
3222 /*******************************************************************
3223 * SetWindowContextHelpId (USER32.@)
3225 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3227 WND *wnd = WIN_FindWndPtr( hwnd );
3228 if (!wnd) return FALSE;
3229 wnd->helpContext = id;
3230 WIN_ReleaseWndPtr(wnd);
3231 return TRUE;
3235 /*******************************************************************
3236 * DragDetect (USER32.@)
3238 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3240 MSG msg;
3241 RECT rect;
3243 rect.left = pt.x - wDragWidth;
3244 rect.right = pt.x + wDragWidth;
3246 rect.top = pt.y - wDragHeight;
3247 rect.bottom = pt.y + wDragHeight;
3249 SetCapture(hWnd);
3251 while(1)
3253 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3255 if( msg.message == WM_LBUTTONUP )
3257 ReleaseCapture();
3258 return 0;
3260 if( msg.message == WM_MOUSEMOVE )
3262 POINT tmp;
3263 tmp.x = LOWORD(msg.lParam);
3264 tmp.y = HIWORD(msg.lParam);
3265 if( !PtInRect( &rect, tmp ))
3267 ReleaseCapture();
3268 return 1;
3272 WaitMessage();
3274 return 0;
3277 /******************************************************************************
3278 * GetWindowModuleFileNameA (USER32.@)
3280 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3282 FIXME("GetWindowModuleFileNameA(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3283 hwnd, lpszFileName, cchFileNameMax);
3284 return 0;
3287 /******************************************************************************
3288 * GetWindowModuleFileNameW (USER32.@)
3290 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR lpszFileName, UINT cchFileNameMax)
3292 FIXME("GetWindowModuleFileNameW(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3293 hwnd, lpszFileName, cchFileNameMax);
3294 return 0;
3297 /******************************************************************************
3298 * GetWindowInfo (USER32.@)
3300 * Note: tests show that Windows doesn't check cbSize of the structure.
3302 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3304 if (!pwi) return FALSE;
3305 if (!IsWindow(hwnd)) return FALSE;
3307 GetWindowRect(hwnd, &pwi->rcWindow);
3308 GetClientRect(hwnd, &pwi->rcClient);
3309 /* translate to screen coordinates */
3310 MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3312 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3313 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3314 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3316 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3317 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3319 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3320 pwi->wCreatorVersion = 0x0400;
3322 return TRUE;