Change an ERR to a WARN.
[wine.git] / windows / win.c
blobb1de4a4ed1a41db6d46ce66276ef16e6dcefddfd
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_private.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 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 * list_window_parents
199 * Build an array of all parents of a given window, starting with
200 * the immediate parent. The array must be freed with HeapFree.
201 * Returns NULL if window is a top-level window.
203 static HWND *list_window_parents( HWND hwnd )
205 WND *win;
206 HWND current, *list;
207 int pos = 0, size = 16, count = 0;
209 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
211 current = hwnd;
212 for (;;)
214 if (!(win = WIN_GetPtr( current ))) goto empty;
215 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
216 list[pos] = win->parent;
217 WIN_ReleasePtr( win );
218 if (!(current = list[pos]))
220 if (!pos) goto empty;
221 return list;
223 if (++pos == size - 1)
225 /* need to grow the list */
226 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
227 if (!new_list) goto empty;
228 list = new_list;
229 size += 16;
233 /* at least one parent belongs to another process, have to query the server */
235 for (;;)
237 count = 0;
238 SERVER_START_REQ( get_window_parents )
240 req->handle = hwnd;
241 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
242 if (!wine_server_call( req )) count = reply->count;
244 SERVER_END_REQ;
245 if (!count) goto empty;
246 if (size > count)
248 list[count] = 0;
249 return list;
251 HeapFree( GetProcessHeap(), 0, list );
252 size = count + 1;
253 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
256 empty:
257 HeapFree( GetProcessHeap(), 0, list );
258 return NULL;
262 /*******************************************************************
263 * send_parent_notify
265 static void send_parent_notify( HWND hwnd, UINT msg )
267 if ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_CHILD | WS_POPUP)) == WS_CHILD &&
268 !(GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY))
269 SendMessageW( GetParent(hwnd), WM_PARENTNOTIFY,
270 MAKEWPARAM( msg, GetWindowLongPtrW( hwnd, GWLP_ID )), (LPARAM)hwnd );
274 /*******************************************************************
275 * get_server_window_text
277 * Retrieve the window text from the server.
279 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
281 size_t len = 0;
283 SERVER_START_REQ( get_window_text )
285 req->handle = hwnd;
286 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
287 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
289 SERVER_END_REQ;
290 text[len / sizeof(WCHAR)] = 0;
294 /***********************************************************************
295 * WIN_GetPtr
297 * Return a pointer to the WND structure if local to the process,
298 * or WND_OTHER_PROCESS if handle may be valid in other process.
299 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
301 WND *WIN_GetPtr( HWND hwnd )
303 WND * ptr;
304 WORD index = USER_HANDLE_TO_INDEX(hwnd);
306 if (index >= NB_USER_HANDLES) return NULL;
308 USER_Lock();
309 if ((ptr = user_handles[index]))
311 if (ptr->dwMagic == WND_MAGIC && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
312 return ptr;
313 ptr = NULL;
315 else ptr = WND_OTHER_PROCESS;
316 USER_Unlock();
317 return ptr;
321 /***********************************************************************
322 * WIN_IsCurrentProcess
324 * Check whether a given window belongs to the current process (and return the full handle).
326 HWND WIN_IsCurrentProcess( HWND hwnd )
328 WND *ptr;
329 HWND ret;
331 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS) return 0;
332 ret = ptr->hwndSelf;
333 WIN_ReleasePtr( ptr );
334 return ret;
338 /***********************************************************************
339 * WIN_IsCurrentThread
341 * Check whether a given window belongs to the current thread (and return the full handle).
343 HWND WIN_IsCurrentThread( HWND hwnd )
345 WND *ptr;
346 HWND ret = 0;
348 if ((ptr = WIN_GetPtr( hwnd )) && ptr != WND_OTHER_PROCESS)
350 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
351 WIN_ReleasePtr( ptr );
353 return ret;
357 /***********************************************************************
358 * WIN_Handle32
360 * Convert a 16-bit window handle to a full 32-bit handle.
362 HWND WIN_Handle32( HWND16 hwnd16 )
364 WND *ptr;
365 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
367 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
368 /* do sign extension for -2 and -3 */
369 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
371 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
373 if (ptr != WND_OTHER_PROCESS)
375 hwnd = ptr->hwndSelf;
376 WIN_ReleasePtr( ptr );
378 else /* may belong to another process */
380 SERVER_START_REQ( get_window_info )
382 req->handle = hwnd;
383 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
385 SERVER_END_REQ;
387 return hwnd;
391 /***********************************************************************
392 * WIN_FindWndPtr
394 * Return a pointer to the WND structure corresponding to a HWND.
396 WND * WIN_FindWndPtr( HWND hwnd )
398 WND * ptr;
400 if (!hwnd) return NULL;
402 if ((ptr = WIN_GetPtr( hwnd )))
404 if (ptr != WND_OTHER_PROCESS)
406 /* increment destruction monitoring */
407 ptr->irefCount++;
408 return ptr;
410 if (IsWindow( hwnd )) /* check other processes */
412 ERR( "window %p belongs to other process\n", hwnd );
413 /* DbgBreakPoint(); */
416 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
417 return NULL;
421 /***********************************************************************
422 * WIN_ReleaseWndPtr
424 * Release the pointer to the WND structure.
426 void WIN_ReleaseWndPtr(WND *wndPtr)
428 if(!wndPtr) return;
430 /* Decrement destruction monitoring value */
431 wndPtr->irefCount--;
432 /* Check if it's time to release the memory */
433 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
435 /* Release memory */
436 free_window_handle( wndPtr->hwndSelf );
438 else if(wndPtr->irefCount < 0)
440 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
441 ERR("forgot a Lock on %p somewhere\n",wndPtr);
443 /* unlock all WND structures for thread safeness */
444 USER_Unlock();
448 /***********************************************************************
449 * WIN_UnlinkWindow
451 * Remove a window from the siblings linked list.
453 void WIN_UnlinkWindow( HWND hwnd )
455 WIN_LinkWindow( hwnd, 0, 0 );
459 /***********************************************************************
460 * WIN_LinkWindow
462 * Insert a window into the siblings linked list.
463 * The window is inserted after the specified window, which can also
464 * be specified as HWND_TOP or HWND_BOTTOM.
465 * If parent is 0, window is unlinked from the tree.
467 void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
469 WND *wndPtr = WIN_GetPtr( hwnd );
471 if (!wndPtr) return;
472 if (wndPtr == WND_OTHER_PROCESS)
474 if (IsWindow(hwnd)) ERR(" cannot link other process window %p\n", hwnd );
475 return;
478 SERVER_START_REQ( link_window )
480 req->handle = hwnd;
481 req->parent = parent;
482 req->previous = hwndInsertAfter;
483 if (!wine_server_call( req ))
485 if (reply->full_parent) wndPtr->parent = reply->full_parent;
489 SERVER_END_REQ;
490 WIN_ReleasePtr( wndPtr );
494 /***********************************************************************
495 * WIN_SetOwner
497 * Change the owner of a window.
499 HWND WIN_SetOwner( HWND hwnd, HWND owner )
501 WND *win = WIN_GetPtr( hwnd );
502 HWND ret = 0;
504 if (!win) return 0;
505 if (win == WND_OTHER_PROCESS)
507 if (IsWindow(hwnd)) ERR( "cannot set owner %p on other process window %p\n", owner, hwnd );
508 return 0;
510 SERVER_START_REQ( set_window_owner )
512 req->handle = hwnd;
513 req->owner = owner;
514 if (!wine_server_call( req ))
516 win->owner = reply->full_owner;
517 ret = reply->prev_owner;
520 SERVER_END_REQ;
521 WIN_ReleasePtr( win );
522 return ret;
526 /***********************************************************************
527 * WIN_SetStyle
529 * Change the style of a window.
531 ULONG WIN_SetStyle( HWND hwnd, ULONG set_bits, ULONG clear_bits )
533 BOOL ok;
534 ULONG new_style, old_style = 0;
535 WND *win = WIN_GetPtr( hwnd );
537 if (!win) return 0;
538 if (win == WND_OTHER_PROCESS)
540 if (IsWindow(hwnd))
541 ERR( "cannot set style %lx/%lx on other process window %p\n",
542 set_bits, clear_bits, hwnd );
543 return 0;
545 new_style = (win->dwStyle | set_bits) & ~clear_bits;
546 if (new_style == win->dwStyle)
548 WIN_ReleasePtr( win );
549 return new_style;
551 SERVER_START_REQ( set_window_info )
553 req->handle = hwnd;
554 req->flags = SET_WIN_STYLE;
555 req->style = new_style;
556 req->extra_offset = -1;
557 if ((ok = !wine_server_call( req )))
559 old_style = reply->old_style;
560 win->dwStyle = new_style;
563 SERVER_END_REQ;
564 WIN_ReleasePtr( win );
565 if (ok && USER_Driver.pSetWindowStyle) USER_Driver.pSetWindowStyle( hwnd, old_style );
566 return old_style;
570 /***********************************************************************
571 * WIN_GetRectangles
573 * Get the window and client rectangles.
575 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
577 WND *win = WIN_GetPtr( hwnd );
578 BOOL ret = TRUE;
580 if (!win) return FALSE;
581 if (win == WND_OTHER_PROCESS)
583 SERVER_START_REQ( get_window_rectangles )
585 req->handle = hwnd;
586 if ((ret = !wine_server_call( req )))
588 if (rectWindow)
590 rectWindow->left = reply->window.left;
591 rectWindow->top = reply->window.top;
592 rectWindow->right = reply->window.right;
593 rectWindow->bottom = reply->window.bottom;
595 if (rectClient)
597 rectClient->left = reply->client.left;
598 rectClient->top = reply->client.top;
599 rectClient->right = reply->client.right;
600 rectClient->bottom = reply->client.bottom;
604 SERVER_END_REQ;
606 else
608 if (rectWindow) *rectWindow = win->rectWindow;
609 if (rectClient) *rectClient = win->rectClient;
610 WIN_ReleasePtr( win );
612 return ret;
616 /***********************************************************************
617 * WIN_DestroyWindow
619 * Destroy storage associated to a window. "Internals" p.358
621 LRESULT WIN_DestroyWindow( HWND hwnd )
623 WND *wndPtr;
624 HWND *list;
626 TRACE("%p\n", hwnd );
628 if (!(hwnd = WIN_IsCurrentThread( hwnd )))
630 ERR( "window doesn't belong to current thread\n" );
631 return 0;
634 /* free child windows */
635 if ((list = WIN_ListChildren( hwnd )))
637 int i;
638 for (i = 0; list[i]; i++)
640 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
641 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
643 HeapFree( GetProcessHeap(), 0, list );
647 * Clear the update region to make sure no WM_PAINT messages will be
648 * generated for this window while processing the WM_NCDESTROY.
650 RedrawWindow( hwnd, NULL, 0,
651 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
654 * Send the WM_NCDESTROY to the window being destroyed.
656 SendMessageA( hwnd, WM_NCDESTROY, 0, 0);
658 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
660 WINPOS_CheckInternalPos( hwnd );
661 if( hwnd == GetCapture()) ReleaseCapture();
663 /* free resources associated with the window */
665 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
667 if (!(wndPtr->dwStyle & WS_CHILD))
669 HMENU menu = (HMENU)SetWindowLongPtrW( hwnd, GWLP_ID, 0 );
670 if (menu) DestroyMenu( menu );
672 if (wndPtr->hSysMenu)
674 DestroyMenu( wndPtr->hSysMenu );
675 wndPtr->hSysMenu = 0;
677 DCE_FreeWindowDCE( hwnd ); /* Always do this to catch orphaned DCs */
678 if (USER_Driver.pDestroyWindow) USER_Driver.pDestroyWindow( hwnd );
679 wndPtr->class = NULL;
680 wndPtr->dwMagic = 0; /* Mark it as invalid */
681 WIN_ReleaseWndPtr( wndPtr );
682 return 0;
685 /***********************************************************************
686 * WIN_DestroyThreadWindows
688 * Destroy all children of 'wnd' owned by the current thread.
689 * Return TRUE if something was done.
691 void WIN_DestroyThreadWindows( HWND hwnd )
693 HWND *list;
694 int i;
696 if (!(list = WIN_ListChildren( hwnd ))) return;
697 for (i = 0; list[i]; i++)
699 if (WIN_IsCurrentThread( list[i] ))
700 DestroyWindow( list[i] );
701 else
702 WIN_DestroyThreadWindows( list[i] );
704 HeapFree( GetProcessHeap(), 0, list );
707 /***********************************************************************
708 * WIN_CreateDesktopWindow
710 * Create the desktop window.
712 BOOL WIN_CreateDesktopWindow(void)
714 HWND hwndDesktop;
715 CREATESTRUCTA cs;
717 TRACE("Creating desktop window\n");
719 if (!WINPOS_CreateInternalPosAtom()) return FALSE;
721 pWndDesktop = create_window_handle( 0, 0, LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W );
722 if (!pWndDesktop) return FALSE;
723 hwndDesktop = pWndDesktop->hwndSelf;
725 pWndDesktop->tid = 0; /* nobody owns the desktop */
726 pWndDesktop->parent = 0;
727 pWndDesktop->owner = 0;
728 pWndDesktop->text = NULL;
729 pWndDesktop->pVScroll = NULL;
730 pWndDesktop->pHScroll = NULL;
731 pWndDesktop->helpContext = 0;
732 pWndDesktop->flags = 0;
733 pWndDesktop->hSysMenu = 0;
735 cs.lpCreateParams = NULL;
736 cs.hInstance = 0;
737 cs.hMenu = 0;
738 cs.hwndParent = 0;
739 cs.x = 0;
740 cs.y = 0;
741 cs.cx = GetSystemMetrics( SM_CXSCREEN );
742 cs.cy = GetSystemMetrics( SM_CYSCREEN );
743 cs.style = pWndDesktop->dwStyle;
744 cs.dwExStyle = pWndDesktop->dwExStyle;
745 cs.lpszName = NULL;
746 cs.lpszClass = DESKTOP_CLASS_ATOM;
748 SERVER_START_REQ( set_window_info )
750 req->handle = hwndDesktop;
751 req->flags = 0; /* don't set anything, just retrieve */
752 req->extra_offset = -1;
753 wine_server_call( req );
754 pWndDesktop->dwStyle = reply->old_style;
755 pWndDesktop->dwExStyle = reply->old_ex_style;
756 pWndDesktop->hInstance = (HINSTANCE)reply->old_instance;
757 pWndDesktop->userdata = (ULONG_PTR)reply->old_user_data;
758 pWndDesktop->wIDmenu = reply->old_id;
760 SERVER_END_REQ;
762 if (!USER_Driver.pCreateWindow || !USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE ))
764 WIN_ReleaseWndPtr( pWndDesktop );
765 return FALSE;
768 WIN_ReleaseWndPtr( pWndDesktop );
769 return TRUE;
773 /***********************************************************************
774 * WIN_FixCoordinates
776 * Fix the coordinates - Helper for WIN_CreateWindowEx.
777 * returns default show mode in sw.
778 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
780 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
782 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
783 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
785 if (cs->style & (WS_CHILD | WS_POPUP))
787 if (cs->dwExStyle & WS_EX_MDICHILD)
789 UINT id = 0;
790 POINT pos[2];
792 MDI_CalcDefaultChildPos(cs->hwndParent, -1, pos, 0, &id);
793 if (!(cs->style & WS_POPUP)) cs->hMenu = (HMENU)id;
795 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
797 cs->x = pos[0].x;
798 cs->y = pos[0].y;
800 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16 || !cs->cx)
801 cs->cx = pos[1].x;
802 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16 || !cs->cy)
803 cs->cy = pos[1].y;
805 else
807 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
808 cs->x = cs->y = 0;
809 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
810 cs->cx = cs->cy = 0;
813 else /* overlapped window */
815 STARTUPINFOA info;
817 GetStartupInfoA( &info );
819 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
821 /* Never believe Microsoft's documentation... CreateWindowEx doc says
822 * that if an overlapped window is created with WS_VISIBLE style bit
823 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
824 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
825 * reveals that
827 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
828 * 2) it does not ignore the y parameter as the docs claim; instead, it
829 * uses it as second parameter to ShowWindow() unless y is either
830 * CW_USEDEFAULT or CW_USEDEFAULT16.
832 * The fact that we didn't do 2) caused bogus windows pop up when wine
833 * was running apps that were using this obscure feature. Example -
834 * calc.exe that comes with Win98 (only Win98, it's different from
835 * the one that comes with Win95 and NT)
837 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
838 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
839 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
842 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
844 if (info.dwFlags & STARTF_USESIZE)
846 cs->cx = info.dwXSize;
847 cs->cy = info.dwYSize;
849 else /* if no other hint from the app, pick 3/4 of the screen real estate */
851 RECT r;
852 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
853 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
854 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
857 /* Handle case where only the cy values is set to default */
858 else if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16)
860 RECT r;
861 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
862 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
866 else
868 /* neither x nor cx are default. Check the y values .
869 * In the trace we see Outlook and Outlook Express using
870 * cy set to CW_USEDEFAULT when opening the address book.
872 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16) {
873 RECT r;
874 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
875 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
876 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
881 /***********************************************************************
882 * dump_window_styles
884 static void dump_window_styles( DWORD style, DWORD exstyle )
886 TRACE( "style:" );
887 if(style & WS_POPUP) TRACE(" WS_POPUP");
888 if(style & WS_CHILD) TRACE(" WS_CHILD");
889 if(style & WS_MINIMIZE) TRACE(" WS_MINIMIZE");
890 if(style & WS_VISIBLE) TRACE(" WS_VISIBLE");
891 if(style & WS_DISABLED) TRACE(" WS_DISABLED");
892 if(style & WS_CLIPSIBLINGS) TRACE(" WS_CLIPSIBLINGS");
893 if(style & WS_CLIPCHILDREN) TRACE(" WS_CLIPCHILDREN");
894 if(style & WS_MAXIMIZE) TRACE(" WS_MAXIMIZE");
895 if((style & WS_CAPTION) == WS_CAPTION) TRACE(" WS_CAPTION");
896 else
898 if(style & WS_BORDER) TRACE(" WS_BORDER");
899 if(style & WS_DLGFRAME) TRACE(" WS_DLGFRAME");
901 if(style & WS_VSCROLL) TRACE(" WS_VSCROLL");
902 if(style & WS_HSCROLL) TRACE(" WS_HSCROLL");
903 if(style & WS_SYSMENU) TRACE(" WS_SYSMENU");
904 if(style & WS_THICKFRAME) TRACE(" WS_THICKFRAME");
905 if(style & WS_GROUP) TRACE(" WS_GROUP");
906 if(style & WS_TABSTOP) TRACE(" WS_TABSTOP");
907 if(style & WS_MINIMIZEBOX) TRACE(" WS_MINIMIZEBOX");
908 if(style & WS_MAXIMIZEBOX) TRACE(" WS_MAXIMIZEBOX");
910 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
911 #define DUMPED_STYLES \
912 (WS_POPUP | \
913 WS_CHILD | \
914 WS_MINIMIZE | \
915 WS_VISIBLE | \
916 WS_DISABLED | \
917 WS_CLIPSIBLINGS | \
918 WS_CLIPCHILDREN | \
919 WS_MAXIMIZE | \
920 WS_BORDER | \
921 WS_DLGFRAME | \
922 WS_VSCROLL | \
923 WS_HSCROLL | \
924 WS_SYSMENU | \
925 WS_THICKFRAME | \
926 WS_GROUP | \
927 WS_TABSTOP | \
928 WS_MINIMIZEBOX | \
929 WS_MAXIMIZEBOX)
931 if(style & ~DUMPED_STYLES) TRACE(" %08lx", style & ~DUMPED_STYLES);
932 TRACE("\n");
933 #undef DUMPED_STYLES
935 TRACE( "exstyle:" );
936 if(exstyle & WS_EX_DLGMODALFRAME) TRACE(" WS_EX_DLGMODALFRAME");
937 if(exstyle & WS_EX_DRAGDETECT) TRACE(" WS_EX_DRAGDETECT");
938 if(exstyle & WS_EX_NOPARENTNOTIFY) TRACE(" WS_EX_NOPARENTNOTIFY");
939 if(exstyle & WS_EX_TOPMOST) TRACE(" WS_EX_TOPMOST");
940 if(exstyle & WS_EX_ACCEPTFILES) TRACE(" WS_EX_ACCEPTFILES");
941 if(exstyle & WS_EX_TRANSPARENT) TRACE(" WS_EX_TRANSPARENT");
942 if(exstyle & WS_EX_MDICHILD) TRACE(" WS_EX_MDICHILD");
943 if(exstyle & WS_EX_TOOLWINDOW) TRACE(" WS_EX_TOOLWINDOW");
944 if(exstyle & WS_EX_WINDOWEDGE) TRACE(" WS_EX_WINDOWEDGE");
945 if(exstyle & WS_EX_CLIENTEDGE) TRACE(" WS_EX_CLIENTEDGE");
946 if(exstyle & WS_EX_CONTEXTHELP) TRACE(" WS_EX_CONTEXTHELP");
947 if(exstyle & WS_EX_RIGHT) TRACE(" WS_EX_RIGHT");
948 if(exstyle & WS_EX_RTLREADING) TRACE(" WS_EX_RTLREADING");
949 if(exstyle & WS_EX_LEFTSCROLLBAR) TRACE(" WS_EX_LEFTSCROLLBAR");
950 if(exstyle & WS_EX_CONTROLPARENT) TRACE(" WS_EX_CONTROLPARENT");
951 if(exstyle & WS_EX_STATICEDGE) TRACE(" WS_EX_STATICEDGE");
952 if(exstyle & WS_EX_APPWINDOW) TRACE(" WS_EX_APPWINDOW");
953 if(exstyle & WS_EX_LAYERED) TRACE(" WS_EX_LAYERED");
955 #define DUMPED_EX_STYLES \
956 (WS_EX_DLGMODALFRAME | \
957 WS_EX_DRAGDETECT | \
958 WS_EX_NOPARENTNOTIFY | \
959 WS_EX_TOPMOST | \
960 WS_EX_ACCEPTFILES | \
961 WS_EX_TRANSPARENT | \
962 WS_EX_MDICHILD | \
963 WS_EX_TOOLWINDOW | \
964 WS_EX_WINDOWEDGE | \
965 WS_EX_CLIENTEDGE | \
966 WS_EX_CONTEXTHELP | \
967 WS_EX_RIGHT | \
968 WS_EX_RTLREADING | \
969 WS_EX_LEFTSCROLLBAR | \
970 WS_EX_CONTROLPARENT | \
971 WS_EX_STATICEDGE | \
972 WS_EX_APPWINDOW | \
973 WS_EX_LAYERED)
975 if(exstyle & ~DUMPED_EX_STYLES) TRACE(" %08lx", exstyle & ~DUMPED_EX_STYLES);
976 TRACE("\n");
977 #undef DUMPED_EX_STYLES
981 /***********************************************************************
982 * WIN_CreateWindowEx
984 * Implementation of CreateWindowEx().
986 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
987 WINDOWPROCTYPE type )
989 INT sw = SW_SHOW;
990 WND *wndPtr;
991 HWND hwnd, parent, owner, top_child = 0;
992 BOOL unicode = (type == WIN_PROC_32W);
994 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
995 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
996 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszClass) : debugstr_a(cs->lpszClass),
997 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
998 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
1000 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
1002 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
1003 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
1005 /* Fix the styles for MDI children */
1006 if (cs->dwExStyle & WS_EX_MDICHILD)
1008 MDICREATESTRUCTA mdi_cs;
1009 UINT flags = 0;
1011 wndPtr = WIN_GetPtr(cs->hwndParent);
1012 if (wndPtr && wndPtr != WND_OTHER_PROCESS)
1014 flags = wndPtr->flags;
1015 WIN_ReleasePtr(wndPtr);
1018 if (!(flags & WIN_ISMDICLIENT))
1020 WARN("WS_EX_MDICHILD, but parent %p is not MDIClient\n", cs->hwndParent);
1021 return 0;
1024 /* cs->lpCreateParams of WM_[NC]CREATE is different for MDI children.
1025 * MDICREATESTRUCT members have the originally passed values.
1027 * Note: we rely on the fact that MDICREATESTRUCTA and MDICREATESTRUCTW
1028 * have the same layout.
1030 mdi_cs.szClass = cs->lpszClass;
1031 mdi_cs.szTitle = cs->lpszName;
1032 mdi_cs.hOwner = cs->hInstance;
1033 mdi_cs.x = cs->x;
1034 mdi_cs.y = cs->y;
1035 mdi_cs.cx = cs->cx;
1036 mdi_cs.cy = cs->cy;
1037 mdi_cs.style = cs->style;
1038 mdi_cs.lParam = (LPARAM)cs->lpCreateParams;
1040 cs->lpCreateParams = (LPVOID)&mdi_cs;
1042 if (GetWindowLongW(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
1044 if (cs->style & WS_POPUP)
1046 TRACE("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n");
1047 return 0;
1049 cs->style |= WS_CHILD | WS_CLIPSIBLINGS;
1051 else
1053 cs->style &= ~WS_POPUP;
1054 cs->style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
1055 WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
1058 top_child = GetWindow(cs->hwndParent, GW_CHILD);
1060 if (top_child)
1062 /* Restore current maximized child */
1063 if((cs->style & WS_VISIBLE) && IsZoomed(top_child))
1065 TRACE("Restoring current maximized child %p\n", top_child);
1066 SendMessageW( top_child, WM_SETREDRAW, FALSE, 0 );
1067 ShowWindow(top_child, SW_RESTORE);
1068 SendMessageW( top_child, WM_SETREDRAW, TRUE, 0 );
1073 /* Find the parent window */
1075 parent = GetDesktopWindow();
1076 owner = 0;
1078 if (cs->hwndParent == HWND_MESSAGE)
1080 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
1081 * message window (style: WS_POPUP|WS_DISABLED)
1083 FIXME("Parent is HWND_MESSAGE\n");
1085 else if (cs->hwndParent)
1087 /* Make sure parent is valid */
1088 if (!IsWindow( cs->hwndParent ))
1090 WARN("Bad parent %p\n", cs->hwndParent );
1091 return 0;
1093 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1094 parent = WIN_GetFullHandle(cs->hwndParent);
1095 else
1096 owner = GetAncestor( cs->hwndParent, GA_ROOT );
1098 else if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1100 WARN("No parent for child window\n" );
1101 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1104 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
1106 /* Correct the window styles.
1108 * It affects both the style loaded into the WIN structure and
1109 * passed in the CREATESTRUCT to the WM_[NC]CREATE.
1111 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1112 * why does the user get to set it?
1115 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
1116 * tested for WS_POPUP
1118 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
1119 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
1120 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
1121 cs->dwExStyle |= WS_EX_WINDOWEDGE;
1122 else
1123 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
1125 if (!(cs->style & WS_CHILD))
1127 cs->style |= WS_CLIPSIBLINGS;
1128 if (!(cs->style & WS_POPUP))
1129 cs->style |= WS_CAPTION;
1132 /* Create the window structure */
1134 if (!(wndPtr = create_window_handle( parent, owner, classAtom, cs->hInstance, type )))
1136 TRACE("out of memory\n" );
1137 return 0;
1139 hwnd = wndPtr->hwndSelf;
1141 /* Fill the window structure */
1143 wndPtr->tid = GetCurrentThreadId();
1144 wndPtr->owner = owner;
1145 wndPtr->parent = parent;
1146 wndPtr->hInstance = cs->hInstance;
1147 wndPtr->text = NULL;
1148 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1149 wndPtr->dwExStyle = cs->dwExStyle;
1150 wndPtr->wIDmenu = 0;
1151 wndPtr->helpContext = 0;
1152 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
1153 wndPtr->pVScroll = NULL;
1154 wndPtr->pHScroll = NULL;
1155 wndPtr->userdata = 0;
1156 wndPtr->hIcon = 0;
1157 wndPtr->hIconSmall = 0;
1158 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU) ? MENU_GetSysMenu( hwnd, 0 ) : 0;
1160 if (!(cs->style & (WS_CHILD | WS_POPUP)))
1161 wndPtr->flags |= WIN_NEED_SIZE;
1163 SERVER_START_REQ( set_window_info )
1165 req->handle = hwnd;
1166 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE;
1167 req->style = wndPtr->dwStyle;
1168 req->ex_style = wndPtr->dwExStyle;
1169 req->instance = (void *)wndPtr->hInstance;
1170 req->extra_offset = -1;
1171 wine_server_call( req );
1173 SERVER_END_REQ;
1175 /* Get class or window DC if needed */
1177 if (wndPtr->clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
1179 /* Set the window menu */
1181 if (((wndPtr->dwStyle & (WS_CAPTION|WS_CHILD)) == WS_CAPTION) ||
1182 (wndPtr->dwExStyle & WS_EX_APPWINDOW))
1184 if (cs->hMenu) MENU_SetMenu(hwnd, cs->hMenu);
1185 else
1187 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
1188 if (menuName)
1190 if (HIWORD(cs->hInstance))
1191 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1192 else
1193 cs->hMenu = HMENU_32(LoadMenu16(HINSTANCE_16(cs->hInstance),menuName));
1195 if (cs->hMenu) MENU_SetMenu( hwnd, cs->hMenu );
1199 else SetWindowLongPtrW( hwnd, GWLP_ID, (ULONG_PTR)cs->hMenu );
1200 WIN_ReleaseWndPtr( wndPtr );
1202 if (!USER_Driver.pCreateWindow || !USER_Driver.pCreateWindow( hwnd, cs, unicode))
1204 WIN_DestroyWindow( hwnd );
1205 return 0;
1208 /* Notify the parent window only */
1210 send_parent_notify( hwnd, WM_CREATE );
1211 if (!IsWindow( hwnd )) return 0;
1213 if (cs->style & WS_VISIBLE)
1215 if (cs->style & WS_MAXIMIZE)
1216 sw = SW_SHOWMAXIMIZED;
1217 else if (cs->style & WS_MINIMIZE)
1218 sw = SW_SHOWMINIMIZED;
1220 ShowWindow( hwnd, sw );
1221 if (cs->dwExStyle & WS_EX_MDICHILD)
1223 SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
1224 /* ShowWindow won't activate child windows */
1225 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE );
1229 /* Call WH_SHELL hook */
1231 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1232 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1234 TRACE("created window %p\n", hwnd);
1235 return hwnd;
1239 /***********************************************************************
1240 * CreateWindow (USER.41)
1242 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1243 DWORD style, INT16 x, INT16 y, INT16 width,
1244 INT16 height, HWND16 parent, HMENU16 menu,
1245 HINSTANCE16 instance, LPVOID data )
1247 return CreateWindowEx16( 0, className, windowName, style,
1248 x, y, width, height, parent, menu, instance, data );
1252 /***********************************************************************
1253 * CreateWindowEx (USER.452)
1255 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1256 LPCSTR windowName, DWORD style, INT16 x,
1257 INT16 y, INT16 width, INT16 height,
1258 HWND16 parent, HMENU16 menu,
1259 HINSTANCE16 instance, LPVOID data )
1261 ATOM classAtom;
1262 CREATESTRUCTA cs;
1263 char buffer[256];
1265 /* Find the class atom */
1267 if (HIWORD(className))
1269 if (!(classAtom = GlobalFindAtomA( className )))
1271 ERR( "bad class name %s\n", debugstr_a(className) );
1272 return 0;
1275 else
1277 classAtom = LOWORD(className);
1278 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1280 ERR( "bad atom %x\n", classAtom);
1281 return 0;
1283 className = buffer;
1286 /* Fix the coordinates */
1288 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1289 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1290 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1291 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1293 /* Create the window */
1295 cs.lpCreateParams = data;
1296 cs.hInstance = HINSTANCE_32(instance);
1297 cs.hMenu = HMENU_32(menu);
1298 cs.hwndParent = WIN_Handle32( parent );
1299 cs.style = style;
1300 cs.lpszName = windowName;
1301 cs.lpszClass = className;
1302 cs.dwExStyle = exStyle;
1304 return HWND_16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
1308 /***********************************************************************
1309 * CreateWindowExA (USER32.@)
1311 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1312 LPCSTR windowName, DWORD style, INT x,
1313 INT y, INT width, INT height,
1314 HWND parent, HMENU menu,
1315 HINSTANCE instance, LPVOID data )
1317 ATOM classAtom;
1318 CREATESTRUCTA cs;
1319 char buffer[256];
1321 /* Find the class atom */
1323 if (HIWORD(className))
1325 if (!(classAtom = GlobalFindAtomA( className )))
1327 ERR( "bad class name %s\n", debugstr_a(className) );
1328 return 0;
1331 else
1333 classAtom = LOWORD(className);
1334 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1336 ERR( "bad atom %x\n", classAtom);
1337 return 0;
1339 className = buffer;
1342 /* Create the window */
1344 cs.lpCreateParams = data;
1345 cs.hInstance = instance;
1346 cs.hMenu = menu;
1347 cs.hwndParent = parent;
1348 cs.x = x;
1349 cs.y = y;
1350 cs.cx = width;
1351 cs.cy = height;
1352 cs.style = style;
1353 cs.lpszName = windowName;
1354 cs.lpszClass = className;
1355 cs.dwExStyle = exStyle;
1357 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1361 /***********************************************************************
1362 * CreateWindowExW (USER32.@)
1364 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1365 LPCWSTR windowName, DWORD style, INT x,
1366 INT y, INT width, INT height,
1367 HWND parent, HMENU menu,
1368 HINSTANCE instance, LPVOID data )
1370 ATOM classAtom;
1371 CREATESTRUCTW cs;
1372 WCHAR buffer[256];
1374 /* Find the class atom */
1376 if (HIWORD(className))
1378 if (!(classAtom = GlobalFindAtomW( className )))
1380 ERR( "bad class name %s\n", debugstr_w(className) );
1381 return 0;
1384 else
1386 classAtom = LOWORD(className);
1387 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1389 ERR( "bad atom %x\n", classAtom);
1390 return 0;
1392 className = buffer;
1395 /* Create the window */
1397 cs.lpCreateParams = data;
1398 cs.hInstance = instance;
1399 cs.hMenu = menu;
1400 cs.hwndParent = parent;
1401 cs.x = x;
1402 cs.y = y;
1403 cs.cx = width;
1404 cs.cy = height;
1405 cs.style = style;
1406 cs.lpszName = windowName;
1407 cs.lpszClass = className;
1408 cs.dwExStyle = exStyle;
1410 /* Note: we rely on the fact that CREATESTRUCTA and */
1411 /* CREATESTRUCTW have the same layout. */
1412 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1416 /***********************************************************************
1417 * WIN_SendDestroyMsg
1419 static void WIN_SendDestroyMsg( HWND hwnd )
1421 GUITHREADINFO info;
1423 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1425 if (hwnd == info.hwndCaret) DestroyCaret();
1426 if (hwnd == info.hwndActive) WINPOS_ActivateOtherWindow( hwnd );
1428 if (USER_Driver.pResetSelectionOwner)
1429 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1432 * Send the WM_DESTROY to the window.
1434 SendMessageA( hwnd, WM_DESTROY, 0, 0);
1437 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1438 * make sure that the window still exists when we come back.
1440 if (IsWindow(hwnd))
1442 HWND* pWndArray;
1443 int i;
1445 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1447 /* start from the end (FIXME: is this needed?) */
1448 for (i = 0; pWndArray[i]; i++) ;
1450 while (--i >= 0)
1452 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1454 HeapFree( GetProcessHeap(), 0, pWndArray );
1456 else
1457 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1461 /***********************************************************************
1462 * DestroyWindow (USER32.@)
1464 BOOL WINAPI DestroyWindow( HWND hwnd )
1466 BOOL is_child;
1468 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1470 SetLastError( ERROR_ACCESS_DENIED );
1471 return FALSE;
1474 TRACE("(%p)\n", hwnd);
1476 /* Call hooks */
1478 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1480 if (MENU_IsMenuActive() == hwnd)
1481 EndMenu();
1483 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1485 if (is_child)
1487 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1488 send_parent_notify( hwnd, WM_DESTROY );
1490 else if (!GetWindow( hwnd, GW_OWNER ))
1492 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1493 /* FIXME: clean up palette - see "Internals" p.352 */
1496 if (!IsWindow(hwnd)) return TRUE;
1498 if (USER_Driver.pResetSelectionOwner)
1499 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1501 /* Hide the window */
1503 /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
1504 if (is_child)
1505 ShowWindow( hwnd, SW_HIDE );
1506 else
1507 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1508 SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW );
1510 if (!IsWindow(hwnd)) return TRUE;
1512 /* Recursively destroy owned windows */
1514 if (!is_child)
1516 for (;;)
1518 int i, got_one = 0;
1519 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1520 if (list)
1522 for (i = 0; list[i]; i++)
1524 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1525 if (WIN_IsCurrentThread( list[i] ))
1527 DestroyWindow( list[i] );
1528 got_one = 1;
1529 continue;
1531 WIN_SetOwner( list[i], 0 );
1533 HeapFree( GetProcessHeap(), 0, list );
1535 if (!got_one) break;
1539 /* Send destroy messages */
1541 WIN_SendDestroyMsg( hwnd );
1542 if (!IsWindow( hwnd )) return TRUE;
1544 if (GetClipboardOwner() == hwnd)
1545 CLIPBOARD_ReleaseOwner();
1547 /* Unlink now so we won't bother with the children later on */
1549 WIN_UnlinkWindow( hwnd );
1551 /* Destroy the window storage */
1553 WIN_DestroyWindow( hwnd );
1554 return TRUE;
1558 /***********************************************************************
1559 * CloseWindow (USER32.@)
1561 BOOL WINAPI CloseWindow( HWND hwnd )
1563 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1564 ShowWindow( hwnd, SW_MINIMIZE );
1565 return TRUE;
1569 /***********************************************************************
1570 * OpenIcon (USER32.@)
1572 BOOL WINAPI OpenIcon( HWND hwnd )
1574 if (!IsIconic( hwnd )) return FALSE;
1575 ShowWindow( hwnd, SW_SHOWNORMAL );
1576 return TRUE;
1580 /***********************************************************************
1581 * WIN_FindWindow
1583 * Implementation of FindWindow() and FindWindowEx().
1585 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1587 HWND *list = NULL;
1588 HWND retvalue = 0;
1589 int i = 0, len = 0;
1590 WCHAR *buffer = NULL;
1592 if (!parent) parent = GetDesktopWindow();
1593 if (title)
1595 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1596 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1599 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1601 if (child)
1603 child = WIN_GetFullHandle( child );
1604 while (list[i] && list[i] != child) i++;
1605 if (!list[i]) goto done;
1606 i++; /* start from next window */
1609 if (title)
1611 while (list[i])
1613 if (GetWindowTextW( list[i], buffer, len + 1 ) && !strcmpiW( buffer, title )) break;
1614 i++;
1617 retvalue = list[i];
1619 done:
1620 HeapFree( GetProcessHeap(), 0, list );
1621 HeapFree( GetProcessHeap(), 0, buffer );
1622 return retvalue;
1627 /***********************************************************************
1628 * FindWindowA (USER32.@)
1630 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1632 HWND ret = FindWindowExA( 0, 0, className, title );
1633 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1634 return ret;
1638 /***********************************************************************
1639 * FindWindowExA (USER32.@)
1641 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1642 LPCSTR className, LPCSTR title )
1644 ATOM atom = 0;
1645 LPWSTR buffer;
1646 HWND hwnd;
1647 INT len;
1649 if (className)
1651 /* If the atom doesn't exist, then no class */
1652 /* with this name exists either. */
1653 if (!(atom = GlobalFindAtomA( className )))
1655 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1656 return 0;
1659 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
1661 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1662 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1663 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
1664 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1665 HeapFree( GetProcessHeap(), 0, buffer );
1666 return hwnd;
1670 /***********************************************************************
1671 * FindWindowExW (USER32.@)
1673 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1674 LPCWSTR className, LPCWSTR title )
1676 ATOM atom = 0;
1678 if (className)
1680 /* If the atom doesn't exist, then no class */
1681 /* with this name exists either. */
1682 if (!(atom = GlobalFindAtomW( className )))
1684 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1685 return 0;
1688 return WIN_FindWindow( parent, child, atom, title );
1692 /***********************************************************************
1693 * FindWindowW (USER32.@)
1695 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1697 return FindWindowExW( 0, 0, className, title );
1701 /**********************************************************************
1702 * GetDesktopWindow (USER32.@)
1704 HWND WINAPI GetDesktopWindow(void)
1706 if (pWndDesktop) return pWndDesktop->hwndSelf;
1707 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" );
1708 ExitProcess(1);
1709 return 0;
1713 /*******************************************************************
1714 * EnableWindow (USER32.@)
1716 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1718 BOOL retvalue;
1719 HWND full_handle;
1721 if (is_broadcast(hwnd))
1723 SetLastError( ERROR_INVALID_PARAMETER );
1724 return FALSE;
1727 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1728 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1730 hwnd = full_handle;
1732 TRACE("( %p, %d )\n", hwnd, enable);
1734 retvalue = !IsWindowEnabled( hwnd );
1736 if (enable && retvalue)
1738 WIN_SetStyle( hwnd, 0, WS_DISABLED );
1739 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1741 else if (!enable && !retvalue)
1743 HWND capture_wnd;
1745 SendMessageA( hwnd, WM_CANCELMODE, 0, 0);
1747 WIN_SetStyle( hwnd, WS_DISABLED, 0 );
1749 if (hwnd == GetFocus())
1750 SetFocus( 0 ); /* A disabled window can't have the focus */
1752 capture_wnd = GetCapture();
1753 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1754 ReleaseCapture(); /* A disabled window can't capture the mouse */
1756 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1758 return retvalue;
1762 /***********************************************************************
1763 * IsWindowEnabled (USER32.@)
1765 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1767 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1771 /***********************************************************************
1772 * IsWindowUnicode (USER32.@)
1774 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1776 WND * wndPtr;
1777 BOOL retvalue;
1779 if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return FALSE;
1780 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1781 WIN_ReleasePtr( wndPtr );
1782 return retvalue;
1786 /**********************************************************************
1787 * GetWindowWord (USER32.@)
1789 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1791 if (offset >= 0)
1793 WORD retvalue = 0;
1794 WND *wndPtr = WIN_GetPtr( hwnd );
1795 if (!wndPtr)
1797 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1798 return 0;
1800 if (wndPtr == WND_OTHER_PROCESS)
1802 SERVER_START_REQ( set_window_info )
1804 req->handle = hwnd;
1805 req->flags = 0; /* don't set anything, just retrieve */
1806 req->extra_offset = offset;
1807 req->extra_size = sizeof(retvalue);
1808 if (!wine_server_call_err( req ))
1809 memcpy( &retvalue, &reply->old_extra_value, sizeof(retvalue) );
1811 SERVER_END_REQ;
1812 return retvalue;
1814 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1816 WARN("Invalid offset %d\n", offset );
1817 SetLastError( ERROR_INVALID_INDEX );
1819 else memcpy( &retvalue, (char *)wndPtr->wExtra + offset, sizeof(retvalue) );
1820 WIN_ReleasePtr( wndPtr );
1821 return retvalue;
1824 switch(offset)
1826 case GWLP_HWNDPARENT:
1827 return GetWindowLongPtrW( hwnd, offset );
1828 case GWLP_ID:
1829 case GWLP_HINSTANCE:
1831 LONG_PTR ret = GetWindowLongPtrW( hwnd, offset );
1832 if (HIWORD(ret))
1833 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1834 return LOWORD(ret);
1836 default:
1837 WARN("Invalid offset %d\n", offset );
1838 return 0;
1843 /**********************************************************************
1844 * SetWindowWord (USER32.@)
1846 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1848 WORD retval = 0;
1849 WND * wndPtr;
1851 switch(offset)
1853 case GWLP_ID:
1854 case GWLP_HINSTANCE:
1855 case GWLP_HWNDPARENT:
1856 return SetWindowLongPtrW( hwnd, offset, (ULONG_PTR)newval );
1857 default:
1858 if (offset < 0)
1860 WARN("Invalid offset %d\n", offset );
1861 SetLastError( ERROR_INVALID_INDEX );
1862 return 0;
1866 wndPtr = WIN_GetPtr( hwnd );
1867 if (wndPtr == WND_OTHER_PROCESS)
1869 if (IsWindow(hwnd))
1870 FIXME( "set %d <- %x not supported yet on other process window %p\n",
1871 offset, newval, hwnd );
1872 wndPtr = NULL;
1874 if (!wndPtr)
1876 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1877 return 0;
1880 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1882 WARN("Invalid offset %d\n", offset );
1883 WIN_ReleasePtr(wndPtr);
1884 SetLastError( ERROR_INVALID_INDEX );
1885 return 0;
1888 SERVER_START_REQ( set_window_info )
1890 req->handle = hwnd;
1891 req->flags = SET_WIN_EXTRA;
1892 req->extra_offset = offset;
1893 req->extra_size = sizeof(newval);
1894 memcpy( &req->extra_value, &newval, sizeof(newval) );
1895 if (!wine_server_call_err( req ))
1897 void *ptr = (char *)wndPtr->wExtra + offset;
1898 memcpy( &retval, ptr, sizeof(retval) );
1899 memcpy( ptr, &newval, sizeof(newval) );
1902 SERVER_END_REQ;
1903 WIN_ReleasePtr( wndPtr );
1904 return retval;
1908 /**********************************************************************
1909 * WIN_GetWindowLong
1911 * Helper function for GetWindowLong().
1913 static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1915 LONG_PTR retvalue = 0;
1916 WND *wndPtr;
1918 if (offset == GWLP_HWNDPARENT)
1920 HWND parent = GetAncestor( hwnd, GA_PARENT );
1921 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1922 return (ULONG_PTR)parent;
1925 if (!(wndPtr = WIN_GetPtr( hwnd )))
1927 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1928 return 0;
1931 if (wndPtr == WND_OTHER_PROCESS)
1933 if (offset == GWLP_WNDPROC)
1935 SetLastError( ERROR_ACCESS_DENIED );
1936 return 0;
1938 SERVER_START_REQ( set_window_info )
1940 req->handle = hwnd;
1941 req->flags = 0; /* don't set anything, just retrieve */
1942 req->extra_offset = (offset >= 0) ? offset : -1;
1943 req->extra_size = (offset >= 0) ? sizeof(retvalue) : 0;
1944 if (!wine_server_call_err( req ))
1946 switch(offset)
1948 case GWL_STYLE: retvalue = reply->old_style; break;
1949 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1950 case GWLP_ID: retvalue = reply->old_id; break;
1951 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1952 case GWLP_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
1953 default:
1954 if (offset >= 0) retvalue = reply->old_extra_value;
1955 else SetLastError( ERROR_INVALID_INDEX );
1956 break;
1960 SERVER_END_REQ;
1961 return retvalue;
1964 /* now we have a valid wndPtr */
1966 if (offset >= 0)
1968 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
1971 * Some programs try to access last element from 16 bit
1972 * code using illegal offset value. Hopefully this is
1973 * what those programs really expect.
1975 if (type == WIN_PROC_16 &&
1976 wndPtr->cbWndExtra >= 4 &&
1977 offset == wndPtr->cbWndExtra - sizeof(WORD))
1979 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
1981 ERR( "- replaced invalid offset %d with %d\n",
1982 offset, offset2 );
1984 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset2);
1985 WIN_ReleasePtr( wndPtr );
1986 return retvalue;
1988 WARN("Invalid offset %d\n", offset );
1989 WIN_ReleasePtr( wndPtr );
1990 SetLastError( ERROR_INVALID_INDEX );
1991 return 0;
1993 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1994 /* Special case for dialog window procedure */
1995 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1996 retvalue = (LONG)WINPROC_GetProc( (WNDPROC)retvalue, type );
1997 WIN_ReleasePtr( wndPtr );
1998 return retvalue;
2001 switch(offset)
2003 case GWLP_USERDATA: retvalue = wndPtr->userdata; break;
2004 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
2005 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
2006 case GWLP_ID: retvalue = (ULONG_PTR)wndPtr->wIDmenu; break;
2007 case GWLP_WNDPROC: retvalue = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, type ); break;
2008 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wndPtr->hInstance; break;
2009 default:
2010 WARN("Unknown offset %d\n", offset );
2011 SetLastError( ERROR_INVALID_INDEX );
2012 break;
2014 WIN_ReleasePtr(wndPtr);
2015 return retvalue;
2019 /**********************************************************************
2020 * WIN_SetWindowLong
2022 * Helper function for SetWindowLong().
2024 * 0 is the failure code. However, in the case of failure SetLastError
2025 * must be set to distinguish between a 0 return value and a failure.
2027 static LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, LONG_PTR newval,
2028 WINDOWPROCTYPE type )
2030 STYLESTRUCT style;
2031 BOOL ok;
2032 LONG retval = 0;
2033 WND *wndPtr;
2035 TRACE( "%p %d %lx %x\n", hwnd, offset, newval, type );
2037 if (is_broadcast(hwnd))
2039 SetLastError( ERROR_INVALID_PARAMETER );
2040 return FALSE;
2042 if (!WIN_IsCurrentProcess( hwnd ))
2044 if (offset == GWLP_WNDPROC)
2046 SetLastError( ERROR_ACCESS_DENIED );
2047 return 0;
2049 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
2052 wndPtr = WIN_GetPtr( hwnd );
2053 if (wndPtr->hwndSelf == GetDesktopWindow())
2055 /* can't change anything on the desktop window */
2056 WIN_ReleasePtr( wndPtr );
2057 SetLastError( ERROR_ACCESS_DENIED );
2058 return 0;
2061 /* first some special cases */
2062 switch( offset )
2064 case GWL_STYLE:
2065 case GWL_EXSTYLE:
2066 style.styleOld =
2067 offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
2068 style.styleNew = newval;
2069 WIN_ReleasePtr( wndPtr );
2070 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
2071 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
2072 newval = style.styleNew;
2073 break;
2074 case GWLP_HWNDPARENT:
2075 if (wndPtr->parent == GetDesktopWindow())
2077 WIN_ReleasePtr( wndPtr );
2078 return (ULONG_PTR)WIN_SetOwner( hwnd, (HWND)newval );
2080 else
2082 WIN_ReleasePtr( wndPtr );
2083 return (ULONG_PTR)SetParent( hwnd, (HWND)newval );
2085 case GWLP_WNDPROC:
2086 retval = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, type );
2087 wndPtr->winproc = WINPROC_AllocProc( (WNDPROC)newval, type );
2088 WIN_ReleasePtr( wndPtr );
2089 return retval;
2090 case GWLP_ID:
2091 case GWLP_HINSTANCE:
2092 case GWLP_USERDATA:
2093 break;
2094 case DWLP_DLGPROC:
2095 if ((wndPtr->cbWndExtra + sizeof(LONG) >= DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2097 WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWLP_DLGPROC);
2098 retval = (ULONG_PTR)WINPROC_GetProc( *ptr, type );
2099 *ptr = WINPROC_AllocProc( (WNDPROC)newval, type );
2100 WIN_ReleasePtr( wndPtr );
2101 return retval;
2103 /* fall through */
2104 default:
2105 if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
2107 WARN("Invalid offset %d\n", offset );
2108 WIN_ReleasePtr( wndPtr );
2109 SetLastError( ERROR_INVALID_INDEX );
2110 return 0;
2112 else
2114 LONG_PTR *ptr = (LONG_PTR *)((char *)wndPtr->wExtra + offset);
2115 if (*ptr == newval) /* already set to the same value */
2117 WIN_ReleasePtr( wndPtr );
2118 return newval;
2121 break;
2124 SERVER_START_REQ( set_window_info )
2126 req->handle = hwnd;
2127 req->extra_offset = -1;
2128 switch(offset)
2130 case GWL_STYLE:
2131 req->flags = SET_WIN_STYLE;
2132 req->style = newval;
2133 break;
2134 case GWL_EXSTYLE:
2135 req->flags = SET_WIN_EXSTYLE;
2136 req->ex_style = newval;
2137 break;
2138 case GWLP_ID:
2139 req->flags = SET_WIN_ID;
2140 req->id = newval;
2141 break;
2142 case GWLP_HINSTANCE:
2143 req->flags = SET_WIN_INSTANCE;
2144 req->instance = (void *)newval;
2145 break;
2146 case GWLP_USERDATA:
2147 req->flags = SET_WIN_USERDATA;
2148 req->user_data = (void *)newval;
2149 break;
2150 default:
2151 req->flags = SET_WIN_EXTRA;
2152 req->extra_offset = offset;
2153 req->extra_size = sizeof(newval);
2154 memcpy( &req->extra_value, &newval, sizeof(newval) );
2156 if ((ok = !wine_server_call_err( req )))
2158 switch(offset)
2160 case GWL_STYLE:
2161 wndPtr->dwStyle = newval;
2162 retval = reply->old_style;
2163 break;
2164 case GWL_EXSTYLE:
2165 wndPtr->dwExStyle = newval;
2166 retval = reply->old_ex_style;
2167 break;
2168 case GWLP_ID:
2169 wndPtr->wIDmenu = newval;
2170 retval = reply->old_id;
2171 break;
2172 case GWLP_HINSTANCE:
2173 wndPtr->hInstance = (HINSTANCE)newval;
2174 retval = (ULONG_PTR)reply->old_instance;
2175 break;
2176 case GWLP_USERDATA:
2177 wndPtr->userdata = newval;
2178 retval = (ULONG_PTR)reply->old_user_data;
2179 break;
2180 default:
2182 void *ptr = (char *)wndPtr->wExtra + offset;
2183 memcpy( &retval, ptr, sizeof(retval) );
2184 memcpy( ptr, &newval, sizeof(newval) );
2186 break;
2190 SERVER_END_REQ;
2191 WIN_ReleasePtr( wndPtr );
2193 if (!ok) return 0;
2195 if (offset == GWL_STYLE && USER_Driver.pSetWindowStyle)
2196 USER_Driver.pSetWindowStyle( hwnd, retval );
2198 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2199 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2201 return retval;
2205 /**********************************************************************
2206 * GetWindowLong (USER.135)
2208 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2210 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
2214 /**********************************************************************
2215 * GetWindowLongA (USER32.@)
2217 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2219 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2223 /**********************************************************************
2224 * GetWindowLongW (USER32.@)
2226 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2228 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2232 /**********************************************************************
2233 * SetWindowLong (USER.136)
2235 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2237 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
2241 /**********************************************************************
2242 * SetWindowLongA (USER32.@)
2244 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2246 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2250 /**********************************************************************
2251 * SetWindowLongW (USER32.@) Set window attribute
2253 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2254 * value in a window's extra memory.
2256 * The _hwnd_ parameter specifies the window. is the handle to a
2257 * window that has extra memory. The _newval_ parameter contains the
2258 * new attribute or extra memory value. If positive, the _offset_
2259 * parameter is the byte-addressed location in the window's extra
2260 * memory to set. If negative, _offset_ specifies the window
2261 * attribute to set, and should be one of the following values:
2263 * GWL_EXSTYLE The window's extended window style
2265 * GWL_STYLE The window's window style.
2267 * GWLP_WNDPROC Pointer to the window's window procedure.
2269 * GWLP_HINSTANCE The window's pplication instance handle.
2271 * GWLP_ID The window's identifier.
2273 * GWLP_USERDATA The window's user-specified data.
2275 * If the window is a dialog box, the _offset_ parameter can be one of
2276 * the following values:
2278 * DWLP_DLGPROC The address of the window's dialog box procedure.
2280 * DWLP_MSGRESULT The return value of a message
2281 * that the dialog box procedure processed.
2283 * DWLP_USER Application specific information.
2285 * RETURNS
2287 * If successful, returns the previous value located at _offset_. Otherwise,
2288 * returns 0.
2290 * NOTES
2292 * Extra memory for a window class is specified by a nonzero cbWndExtra
2293 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2294 * time of class creation.
2296 * Using GWL_WNDPROC to set a new window procedure effectively creates
2297 * a window subclass. Use CallWindowProc() in the new windows procedure
2298 * to pass messages to the superclass's window procedure.
2300 * The user data is reserved for use by the application which created
2301 * the window.
2303 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2304 * instead, call the EnableWindow() function to change the window's
2305 * disabled state.
2307 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2308 * SetParent() instead.
2310 * Win95:
2311 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2312 * it sends WM_STYLECHANGING before changing the settings
2313 * and WM_STYLECHANGED afterwards.
2314 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2316 LONG WINAPI SetWindowLongW(
2317 HWND hwnd, /* [in] window to alter */
2318 INT offset, /* [in] offset, in bytes, of location to alter */
2319 LONG newval /* [in] new value of location */
2321 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2325 /*******************************************************************
2326 * GetWindowTextA (USER32.@)
2328 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2330 WCHAR *buffer;
2332 if (WIN_IsCurrentProcess( hwnd ))
2333 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2335 /* when window belongs to other process, don't send a message */
2336 if (nMaxCount <= 0) return 0;
2337 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2338 get_server_window_text( hwnd, buffer, nMaxCount );
2339 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2340 lpString[nMaxCount-1] = 0;
2341 HeapFree( GetProcessHeap(), 0, buffer );
2342 return strlen(lpString);
2346 /*******************************************************************
2347 * InternalGetWindowText (USER32.@)
2349 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2351 WND *win;
2353 if (nMaxCount <= 0) return 0;
2354 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2355 if (win != WND_OTHER_PROCESS)
2357 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2358 else lpString[0] = 0;
2359 WIN_ReleasePtr( win );
2361 else
2363 get_server_window_text( hwnd, lpString, nMaxCount );
2365 return strlenW(lpString);
2369 /*******************************************************************
2370 * GetWindowTextW (USER32.@)
2372 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2374 if (WIN_IsCurrentProcess( hwnd ))
2375 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2377 /* when window belongs to other process, don't send a message */
2378 if (nMaxCount <= 0) return 0;
2379 get_server_window_text( hwnd, lpString, nMaxCount );
2380 return strlenW(lpString);
2384 /*******************************************************************
2385 * SetWindowText (USER32.@)
2386 * SetWindowTextA (USER32.@)
2388 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2390 if (is_broadcast(hwnd))
2392 SetLastError( ERROR_INVALID_PARAMETER );
2393 return FALSE;
2395 if (!WIN_IsCurrentProcess( hwnd ))
2397 FIXME( "cannot set text %s of other process window %p\n", debugstr_a(lpString), hwnd );
2398 SetLastError( ERROR_ACCESS_DENIED );
2399 return FALSE;
2401 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2405 /*******************************************************************
2406 * SetWindowTextW (USER32.@)
2408 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2410 if (is_broadcast(hwnd))
2412 SetLastError( ERROR_INVALID_PARAMETER );
2413 return FALSE;
2415 if (!WIN_IsCurrentProcess( hwnd ))
2417 FIXME( "cannot set text %s of other process window %p\n", debugstr_w(lpString), hwnd );
2418 SetLastError( ERROR_ACCESS_DENIED );
2419 return FALSE;
2421 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2425 /*******************************************************************
2426 * GetWindowTextLengthA (USER32.@)
2428 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2430 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2433 /*******************************************************************
2434 * GetWindowTextLengthW (USER32.@)
2436 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2438 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2442 /*******************************************************************
2443 * IsWindow (USER32.@)
2445 BOOL WINAPI IsWindow( HWND hwnd )
2447 WND *ptr;
2448 BOOL ret;
2450 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2452 if (ptr != WND_OTHER_PROCESS)
2454 WIN_ReleasePtr( ptr );
2455 return TRUE;
2458 /* check other processes */
2459 SERVER_START_REQ( get_window_info )
2461 req->handle = hwnd;
2462 ret = !wine_server_call_err( req );
2464 SERVER_END_REQ;
2465 return ret;
2469 /***********************************************************************
2470 * GetWindowThreadProcessId (USER32.@)
2472 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2474 WND *ptr;
2475 DWORD tid = 0;
2477 if (!(ptr = WIN_GetPtr( hwnd )))
2479 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2480 return 0;
2483 if (ptr != WND_OTHER_PROCESS)
2485 /* got a valid window */
2486 tid = ptr->tid;
2487 if (process) *process = GetCurrentProcessId();
2488 WIN_ReleasePtr( ptr );
2489 return tid;
2492 /* check other processes */
2493 SERVER_START_REQ( get_window_info )
2495 req->handle = hwnd;
2496 if (!wine_server_call_err( req ))
2498 tid = (DWORD)reply->tid;
2499 if (process) *process = (DWORD)reply->pid;
2502 SERVER_END_REQ;
2503 return tid;
2507 /*****************************************************************
2508 * GetParent (USER32.@)
2510 HWND WINAPI GetParent( HWND hwnd )
2512 WND *wndPtr;
2513 HWND retvalue = 0;
2515 if (!(wndPtr = WIN_GetPtr( hwnd )))
2517 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2518 return 0;
2520 if (wndPtr == WND_OTHER_PROCESS)
2522 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2523 if (style & (WS_POPUP | WS_CHILD))
2525 SERVER_START_REQ( get_window_tree )
2527 req->handle = hwnd;
2528 if (!wine_server_call_err( req ))
2530 if (style & WS_POPUP) retvalue = reply->owner;
2531 else if (style & WS_CHILD) retvalue = reply->parent;
2534 SERVER_END_REQ;
2537 else
2539 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2540 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2541 WIN_ReleasePtr( wndPtr );
2543 return retvalue;
2547 /*****************************************************************
2548 * GetAncestor (USER32.@)
2550 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2552 WND *win;
2553 HWND *list, ret = 0;
2555 switch(type)
2557 case GA_PARENT:
2558 if (!(win = WIN_GetPtr( hwnd )))
2560 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2561 return 0;
2563 if (win != WND_OTHER_PROCESS)
2565 ret = win->parent;
2566 WIN_ReleasePtr( win );
2568 else /* need to query the server */
2570 SERVER_START_REQ( get_window_tree )
2572 req->handle = hwnd;
2573 if (!wine_server_call_err( req )) ret = reply->parent;
2575 SERVER_END_REQ;
2577 break;
2579 case GA_ROOT:
2580 if (!(list = list_window_parents( hwnd ))) return 0;
2582 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2583 else
2585 int count = 2;
2586 while (list[count]) count++;
2587 ret = list[count - 2]; /* get the one before the desktop */
2589 HeapFree( GetProcessHeap(), 0, list );
2590 break;
2592 case GA_ROOTOWNER:
2593 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2594 for (;;)
2596 HWND parent = GetParent( ret );
2597 if (!parent) break;
2598 ret = parent;
2600 break;
2602 return ret;
2606 /*****************************************************************
2607 * SetParent (USER32.@)
2609 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2611 WND *wndPtr;
2612 HWND retvalue, full_handle;
2613 BOOL was_visible;
2615 if (is_broadcast(hwnd) || is_broadcast(parent))
2617 SetLastError(ERROR_INVALID_PARAMETER);
2618 return 0;
2621 if (!parent) parent = GetDesktopWindow();
2622 else parent = WIN_GetFullHandle( parent );
2624 if (!IsWindow( parent ))
2626 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2627 return 0;
2630 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2631 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2633 hwnd = full_handle;
2635 if (USER_Driver.pSetParent)
2636 return USER_Driver.pSetParent( hwnd, parent );
2638 /* Windows hides the window first, then shows it again
2639 * including the WM_SHOWWINDOW messages and all */
2640 was_visible = ShowWindow( hwnd, SW_HIDE );
2642 if (!IsWindow( parent )) return 0;
2643 if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return 0;
2645 retvalue = wndPtr->parent; /* old parent */
2646 if (parent != retvalue)
2648 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2650 if (parent != GetDesktopWindow()) /* a child window */
2652 if (!(wndPtr->dwStyle & WS_CHILD))
2654 HMENU menu = (HMENU)SetWindowLongPtrW( hwnd, GWLP_ID, 0 );
2655 if (menu) DestroyMenu( menu );
2659 WIN_ReleasePtr( wndPtr );
2661 /* SetParent additionally needs to make hwnd the topmost window
2662 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2663 WM_WINDOWPOSCHANGED notification messages.
2665 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2666 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2667 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2668 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2669 return retvalue;
2673 /*******************************************************************
2674 * IsChild (USER32.@)
2676 BOOL WINAPI IsChild( HWND parent, HWND child )
2678 HWND *list = list_window_parents( child );
2679 int i;
2680 BOOL ret;
2682 if (!list) return FALSE;
2683 parent = WIN_GetFullHandle( parent );
2684 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2685 ret = (list[i] != 0);
2686 HeapFree( GetProcessHeap(), 0, list );
2687 return ret;
2691 /***********************************************************************
2692 * IsWindowVisible (USER32.@)
2694 BOOL WINAPI IsWindowVisible( HWND hwnd )
2696 HWND *list;
2697 BOOL retval;
2698 int i;
2700 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2701 if (!(list = list_window_parents( hwnd ))) return TRUE;
2702 for (i = 0; list[i]; i++)
2703 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2704 retval = !list[i];
2705 HeapFree( GetProcessHeap(), 0, list );
2706 return retval;
2710 /***********************************************************************
2711 * WIN_IsWindowDrawable
2713 * hwnd is drawable when it is visible, all parents are not
2714 * minimized, and it is itself not minimized unless we are
2715 * trying to draw its default class icon.
2717 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2719 HWND *list;
2720 BOOL retval;
2721 int i;
2722 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2724 if (!(style & WS_VISIBLE)) return FALSE;
2725 if ((style & WS_MINIMIZE) && icon && GetClassLongA( hwnd, GCL_HICON )) return FALSE;
2727 if (!(list = list_window_parents( hwnd ))) return TRUE;
2728 for (i = 0; list[i]; i++)
2729 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2730 break;
2731 retval = !list[i];
2732 HeapFree( GetProcessHeap(), 0, list );
2733 return retval;
2737 /*******************************************************************
2738 * GetTopWindow (USER32.@)
2740 HWND WINAPI GetTopWindow( HWND hwnd )
2742 if (!hwnd) hwnd = GetDesktopWindow();
2743 return GetWindow( hwnd, GW_CHILD );
2747 /*******************************************************************
2748 * GetWindow (USER32.@)
2750 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2752 HWND retval = 0;
2754 if (rel == GW_OWNER) /* this one may be available locally */
2756 WND *wndPtr = WIN_GetPtr( hwnd );
2757 if (!wndPtr)
2759 SetLastError( ERROR_INVALID_HANDLE );
2760 return 0;
2762 if (wndPtr != WND_OTHER_PROCESS)
2764 retval = wndPtr->owner;
2765 WIN_ReleasePtr( wndPtr );
2766 return retval;
2768 /* else fall through to server call */
2771 SERVER_START_REQ( get_window_tree )
2773 req->handle = hwnd;
2774 if (!wine_server_call_err( req ))
2776 switch(rel)
2778 case GW_HWNDFIRST:
2779 retval = reply->first_sibling;
2780 break;
2781 case GW_HWNDLAST:
2782 retval = reply->last_sibling;
2783 break;
2784 case GW_HWNDNEXT:
2785 retval = reply->next_sibling;
2786 break;
2787 case GW_HWNDPREV:
2788 retval = reply->prev_sibling;
2789 break;
2790 case GW_OWNER:
2791 retval = reply->owner;
2792 break;
2793 case GW_CHILD:
2794 retval = reply->first_child;
2795 break;
2799 SERVER_END_REQ;
2800 return retval;
2804 /*******************************************************************
2805 * ShowOwnedPopups (USER32.@)
2807 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2809 int count = 0;
2810 WND *pWnd;
2811 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2813 if (!win_array) return TRUE;
2815 while (win_array[count]) count++;
2816 while (--count >= 0)
2818 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2819 if (!(pWnd = WIN_GetPtr( win_array[count] ))) continue;
2820 if (pWnd == WND_OTHER_PROCESS) continue;
2822 if (pWnd->dwStyle & WS_POPUP)
2824 if (fShow)
2826 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2828 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2829 WIN_ReleasePtr( pWnd );
2830 /* In Windows, ShowOwnedPopups(TRUE) generates
2831 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2832 * regardless of the state of the owner
2834 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2835 continue;
2838 else
2840 if (pWnd->dwStyle & WS_VISIBLE)
2842 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2843 WIN_ReleasePtr( pWnd );
2844 /* In Windows, ShowOwnedPopups(FALSE) generates
2845 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2846 * regardless of the state of the owner
2848 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2849 continue;
2853 WIN_ReleasePtr( pWnd );
2855 HeapFree( GetProcessHeap(), 0, win_array );
2856 return TRUE;
2860 /*******************************************************************
2861 * GetLastActivePopup (USER32.@)
2863 HWND WINAPI GetLastActivePopup( HWND hwnd )
2865 HWND retval = hwnd;
2867 SERVER_START_REQ( get_window_info )
2869 req->handle = hwnd;
2870 if (!wine_server_call_err( req )) retval = reply->last_active;
2872 SERVER_END_REQ;
2873 return retval;
2877 /*******************************************************************
2878 * WIN_ListChildren
2880 * Build an array of the children of a given window. The array must be
2881 * freed with HeapFree. Returns NULL when no windows are found.
2883 HWND *WIN_ListChildren( HWND hwnd )
2885 return list_window_children( hwnd, 0, 0 );
2889 /*******************************************************************
2890 * EnumWindows (USER32.@)
2892 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2894 HWND *list;
2895 BOOL ret = TRUE;
2896 int i, iWndsLocks;
2898 /* We have to build a list of all windows first, to avoid */
2899 /* unpleasant side-effects, for instance if the callback */
2900 /* function changes the Z-order of the windows. */
2902 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2904 /* Now call the callback function for every window */
2906 iWndsLocks = WIN_SuspendWndsLock();
2907 for (i = 0; list[i]; i++)
2909 /* Make sure that the window still exists */
2910 if (!IsWindow( list[i] )) continue;
2911 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2913 WIN_RestoreWndsLock(iWndsLocks);
2914 HeapFree( GetProcessHeap(), 0, list );
2915 return ret;
2919 /**********************************************************************
2920 * EnumThreadWindows (USER32.@)
2922 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2924 HWND *list;
2925 int i, iWndsLocks;
2927 if (!(list = list_window_children( GetDesktopWindow(), 0, id ))) return TRUE;
2929 /* Now call the callback function for every window */
2931 iWndsLocks = WIN_SuspendWndsLock();
2932 for (i = 0; list[i]; i++)
2933 if (!func( list[i], lParam )) break;
2934 WIN_RestoreWndsLock(iWndsLocks);
2935 HeapFree( GetProcessHeap(), 0, list );
2936 return TRUE;
2940 /**********************************************************************
2941 * WIN_EnumChildWindows
2943 * Helper function for EnumChildWindows().
2945 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2947 HWND *childList;
2948 BOOL ret = FALSE;
2950 for ( ; *list; list++)
2952 /* Make sure that the window still exists */
2953 if (!IsWindow( *list )) continue;
2954 /* skip owned windows */
2955 if (GetWindow( *list, GW_OWNER )) continue;
2956 /* Build children list first */
2957 childList = WIN_ListChildren( *list );
2959 ret = func( *list, lParam );
2961 if (childList)
2963 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2964 HeapFree( GetProcessHeap(), 0, childList );
2966 if (!ret) return FALSE;
2968 return TRUE;
2972 /**********************************************************************
2973 * EnumChildWindows (USER32.@)
2975 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2977 HWND *list;
2978 int iWndsLocks;
2980 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2981 iWndsLocks = WIN_SuspendWndsLock();
2982 WIN_EnumChildWindows( list, func, lParam );
2983 WIN_RestoreWndsLock(iWndsLocks);
2984 HeapFree( GetProcessHeap(), 0, list );
2985 return TRUE;
2989 /*******************************************************************
2990 * AnyPopup (USER.52)
2992 BOOL16 WINAPI AnyPopup16(void)
2994 return AnyPopup();
2998 /*******************************************************************
2999 * AnyPopup (USER32.@)
3001 BOOL WINAPI AnyPopup(void)
3003 int i;
3004 BOOL retvalue;
3005 HWND *list = WIN_ListChildren( GetDesktopWindow() );
3007 if (!list) return FALSE;
3008 for (i = 0; list[i]; i++)
3010 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
3012 retvalue = (list[i] != 0);
3013 HeapFree( GetProcessHeap(), 0, list );
3014 return retvalue;
3018 /*******************************************************************
3019 * FlashWindow (USER32.@)
3021 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3023 WND *wndPtr;
3025 TRACE("%p\n", hWnd);
3027 if (IsIconic( hWnd ))
3029 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3031 wndPtr = WIN_GetPtr(hWnd);
3032 if (!wndPtr || wndPtr == WND_OTHER_PROCESS) return FALSE;
3033 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3035 wndPtr->flags |= WIN_NCACTIVATED;
3037 else
3039 wndPtr->flags &= ~WIN_NCACTIVATED;
3041 WIN_ReleasePtr( wndPtr );
3042 return TRUE;
3044 else
3046 WPARAM wparam;
3048 wndPtr = WIN_GetPtr(hWnd);
3049 if (!wndPtr || wndPtr == WND_OTHER_PROCESS) return FALSE;
3050 hWnd = wndPtr->hwndSelf; /* make it a full handle */
3052 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3053 else wparam = (hWnd == GetForegroundWindow());
3055 WIN_ReleasePtr( wndPtr );
3056 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3057 return wparam;
3061 /*******************************************************************
3062 * FlashWindowEx (USER32.@)
3064 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
3066 FIXME("%p\n", pfwi);
3067 return TRUE;
3070 /*******************************************************************
3071 * GetWindowContextHelpId (USER32.@)
3073 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3075 DWORD retval;
3076 WND *wnd = WIN_GetPtr( hwnd );
3077 if (!wnd) return 0;
3078 if (wnd == WND_OTHER_PROCESS)
3080 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3081 return 0;
3083 retval = wnd->helpContext;
3084 WIN_ReleasePtr( wnd );
3085 return retval;
3089 /*******************************************************************
3090 * SetWindowContextHelpId (USER32.@)
3092 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3094 WND *wnd = WIN_GetPtr( hwnd );
3095 if (!wnd) return FALSE;
3096 if (wnd == WND_OTHER_PROCESS)
3098 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3099 return 0;
3101 wnd->helpContext = id;
3102 WIN_ReleasePtr( wnd );
3103 return TRUE;
3107 /*******************************************************************
3108 * DragDetect (USER32.@)
3110 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3112 MSG msg;
3113 RECT rect;
3115 rect.left = pt.x - wDragWidth;
3116 rect.right = pt.x + wDragWidth;
3118 rect.top = pt.y - wDragHeight;
3119 rect.bottom = pt.y + wDragHeight;
3121 SetCapture(hWnd);
3123 while(1)
3125 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3127 if( msg.message == WM_LBUTTONUP )
3129 ReleaseCapture();
3130 return 0;
3132 if( msg.message == WM_MOUSEMOVE )
3134 POINT tmp;
3135 tmp.x = LOWORD(msg.lParam);
3136 tmp.y = HIWORD(msg.lParam);
3137 if( !PtInRect( &rect, tmp ))
3139 ReleaseCapture();
3140 return 1;
3144 WaitMessage();
3146 return 0;
3149 /******************************************************************************
3150 * GetWindowModuleFileNameA (USER32.@)
3152 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3154 FIXME("GetWindowModuleFileNameA(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3155 hwnd, lpszFileName, cchFileNameMax);
3156 return 0;
3159 /******************************************************************************
3160 * GetWindowModuleFileNameW (USER32.@)
3162 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR lpszFileName, UINT cchFileNameMax)
3164 FIXME("GetWindowModuleFileNameW(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3165 hwnd, lpszFileName, cchFileNameMax);
3166 return 0;
3169 /******************************************************************************
3170 * GetWindowInfo (USER32.@)
3172 * Note: tests show that Windows doesn't check cbSize of the structure.
3174 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3176 if (!pwi) return FALSE;
3177 if (!IsWindow(hwnd)) return FALSE;
3179 GetWindowRect(hwnd, &pwi->rcWindow);
3180 GetClientRect(hwnd, &pwi->rcClient);
3181 /* translate to screen coordinates */
3182 MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3184 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3185 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3186 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3188 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3189 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3191 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3192 pwi->wCreatorVersion = 0x0400;
3194 return TRUE;
3197 /******************************************************************************
3198 * SwitchDesktop (USER32.@)
3200 * NOTES: Sets the current input or interactive desktop.
3202 BOOL WINAPI SwitchDesktop( HDESK hDesktop)
3204 FIXME("SwitchDesktop(hwnd %p) stub!\n", hDesktop);
3205 return TRUE;