Proper handling for GWL_STYLE.
[wine/testsucceed.git] / windows / win.c
blob0405749080b2eba0412907015df628d63f9e6a01
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 HWND hwndDesktop;
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->cbWndExtra = extra_bytes;
120 memset( win->wExtra, 0, extra_bytes );
121 CLASS_AddWindow( class, win, type );
122 return win;
126 /***********************************************************************
127 * free_window_handle
129 * Free a window handle.
131 static WND *free_window_handle( HWND hwnd )
133 WND *ptr;
134 WORD index = USER_HANDLE_TO_INDEX(hwnd);
136 if (index >= NB_USER_HANDLES) return NULL;
137 USER_Lock();
138 if ((ptr = user_handles[index]))
140 SERVER_START_REQ( destroy_window )
142 req->handle = hwnd;
143 if (!wine_server_call_err( req ))
144 user_handles[index] = NULL;
145 else
146 ptr = NULL;
148 SERVER_END_REQ;
150 USER_Unlock();
151 ptr->dwMagic = 0;
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 if (win == WND_DESKTOP)
218 if (!pos) goto empty;
219 list[pos] = 0;
220 return list;
222 list[pos] = current = win->parent;
223 WIN_ReleasePtr( win );
224 if (++pos == size - 1)
226 /* need to grow the list */
227 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
228 if (!new_list) goto empty;
229 list = new_list;
230 size += 16;
234 /* at least one parent belongs to another process, have to query the server */
236 for (;;)
238 count = 0;
239 SERVER_START_REQ( get_window_parents )
241 req->handle = hwnd;
242 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
243 if (!wine_server_call( req )) count = reply->count;
245 SERVER_END_REQ;
246 if (!count) goto empty;
247 if (size > count)
249 list[count] = 0;
250 return list;
252 HeapFree( GetProcessHeap(), 0, list );
253 size = count + 1;
254 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
257 empty:
258 HeapFree( GetProcessHeap(), 0, list );
259 return NULL;
263 /*******************************************************************
264 * send_parent_notify
266 static void send_parent_notify( HWND hwnd, UINT msg )
268 if ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_CHILD | WS_POPUP)) == WS_CHILD &&
269 !(GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY))
270 SendMessageW( GetParent(hwnd), WM_PARENTNOTIFY,
271 MAKEWPARAM( msg, GetWindowLongPtrW( hwnd, GWLP_ID )), (LPARAM)hwnd );
275 /*******************************************************************
276 * get_server_window_text
278 * Retrieve the window text from the server.
280 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
282 size_t len = 0;
284 SERVER_START_REQ( get_window_text )
286 req->handle = hwnd;
287 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
288 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
290 SERVER_END_REQ;
291 text[len / sizeof(WCHAR)] = 0;
295 /***********************************************************************
296 * WIN_GetPtr
298 * Return a pointer to the WND structure if local to the process,
299 * or WND_OTHER_PROCESS if handle may be valid in other process.
300 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
302 WND *WIN_GetPtr( HWND hwnd )
304 WND * ptr;
305 WORD index = USER_HANDLE_TO_INDEX(hwnd);
307 if (index >= NB_USER_HANDLES) return NULL;
309 USER_Lock();
310 if ((ptr = user_handles[index]))
312 if (ptr->dwMagic == WND_MAGIC && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
313 return ptr;
314 ptr = NULL;
316 else if (index == USER_HANDLE_TO_INDEX(hwndDesktop))
318 if (!HIWORD(hwnd) || hwnd == GetDesktopWindow()) ptr = WND_DESKTOP;
319 else ptr = NULL;
321 else ptr = WND_OTHER_PROCESS;
322 USER_Unlock();
323 return ptr;
327 /***********************************************************************
328 * WIN_IsCurrentProcess
330 * Check whether a given window belongs to the current process (and return the full handle).
332 HWND WIN_IsCurrentProcess( HWND hwnd )
334 WND *ptr;
335 HWND ret;
337 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
338 ret = ptr->hwndSelf;
339 WIN_ReleasePtr( ptr );
340 return ret;
344 /***********************************************************************
345 * WIN_IsCurrentThread
347 * Check whether a given window belongs to the current thread (and return the full handle).
349 HWND WIN_IsCurrentThread( HWND hwnd )
351 WND *ptr;
352 HWND ret = 0;
354 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
355 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
356 WIN_ReleasePtr( ptr );
357 return ret;
361 /***********************************************************************
362 * WIN_Handle32
364 * Convert a 16-bit window handle to a full 32-bit handle.
366 HWND WIN_Handle32( HWND16 hwnd16 )
368 WND *ptr;
369 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
371 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
372 /* do sign extension for -2 and -3 */
373 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
375 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
377 if (ptr == WND_DESKTOP) return GetDesktopWindow();
379 if (ptr != WND_OTHER_PROCESS)
381 hwnd = ptr->hwndSelf;
382 WIN_ReleasePtr( ptr );
384 else /* may belong to another process */
386 SERVER_START_REQ( get_window_info )
388 req->handle = hwnd;
389 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
391 SERVER_END_REQ;
393 return hwnd;
397 /***********************************************************************
398 * WIN_UnlinkWindow
400 * Remove a window from the siblings linked list.
402 void WIN_UnlinkWindow( HWND hwnd )
404 WIN_LinkWindow( hwnd, 0, 0 );
408 /***********************************************************************
409 * WIN_LinkWindow
411 * Insert a window into the siblings linked list.
412 * The window is inserted after the specified window, which can also
413 * be specified as HWND_TOP or HWND_BOTTOM.
414 * If parent is 0, window is unlinked from the tree.
416 void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
418 WND *wndPtr = WIN_GetPtr( hwnd );
420 if (!wndPtr || wndPtr == WND_DESKTOP) return;
421 if (wndPtr == WND_OTHER_PROCESS)
423 if (IsWindow(hwnd)) ERR(" cannot link other process window %p\n", hwnd );
424 return;
427 SERVER_START_REQ( link_window )
429 req->handle = hwnd;
430 req->parent = parent;
431 req->previous = hwndInsertAfter;
432 if (!wine_server_call( req ))
434 if (reply->full_parent) wndPtr->parent = reply->full_parent;
438 SERVER_END_REQ;
439 WIN_ReleasePtr( wndPtr );
443 /***********************************************************************
444 * WIN_SetOwner
446 * Change the owner of a window.
448 HWND WIN_SetOwner( HWND hwnd, HWND owner )
450 WND *win = WIN_GetPtr( hwnd );
451 HWND ret = 0;
453 if (!win || win == WND_DESKTOP) return 0;
454 if (win == WND_OTHER_PROCESS)
456 if (IsWindow(hwnd)) ERR( "cannot set owner %p on other process window %p\n", owner, hwnd );
457 return 0;
459 SERVER_START_REQ( set_window_owner )
461 req->handle = hwnd;
462 req->owner = owner;
463 if (!wine_server_call( req ))
465 win->owner = reply->full_owner;
466 ret = reply->prev_owner;
469 SERVER_END_REQ;
470 WIN_ReleasePtr( win );
471 return ret;
475 /***********************************************************************
476 * WIN_SetStyle
478 * Change the style of a window.
480 ULONG WIN_SetStyle( HWND hwnd, ULONG set_bits, ULONG clear_bits )
482 BOOL ok;
483 ULONG new_style, old_style = 0;
484 WND *win = WIN_GetPtr( hwnd );
486 if (!win || win == WND_DESKTOP) return 0;
487 if (win == WND_OTHER_PROCESS)
489 if (IsWindow(hwnd))
490 ERR( "cannot set style %lx/%lx on other process window %p\n",
491 set_bits, clear_bits, hwnd );
492 return 0;
494 new_style = (win->dwStyle | set_bits) & ~clear_bits;
495 if (new_style == win->dwStyle)
497 WIN_ReleasePtr( win );
498 return new_style;
500 SERVER_START_REQ( set_window_info )
502 req->handle = hwnd;
503 req->flags = SET_WIN_STYLE;
504 req->style = new_style;
505 req->extra_offset = -1;
506 if ((ok = !wine_server_call( req )))
508 old_style = reply->old_style;
509 win->dwStyle = new_style;
512 SERVER_END_REQ;
513 WIN_ReleasePtr( win );
514 if (ok && USER_Driver.pSetWindowStyle) USER_Driver.pSetWindowStyle( hwnd, old_style );
515 return old_style;
519 /***********************************************************************
520 * WIN_GetRectangles
522 * Get the window and client rectangles.
524 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
526 WND *win = WIN_GetPtr( hwnd );
527 BOOL ret = TRUE;
529 if (!win) return FALSE;
530 if (win == WND_DESKTOP)
532 RECT rect;
533 rect.left = rect.top = 0;
534 rect.right = GetSystemMetrics(SM_CXSCREEN);
535 rect.bottom = GetSystemMetrics(SM_CYSCREEN);
536 if (rectWindow) *rectWindow = rect;
537 if (rectClient) *rectClient = rect;
539 else if (win == WND_OTHER_PROCESS)
541 SERVER_START_REQ( get_window_rectangles )
543 req->handle = hwnd;
544 if ((ret = !wine_server_call( req )))
546 if (rectWindow)
548 rectWindow->left = reply->window.left;
549 rectWindow->top = reply->window.top;
550 rectWindow->right = reply->window.right;
551 rectWindow->bottom = reply->window.bottom;
553 if (rectClient)
555 rectClient->left = reply->client.left;
556 rectClient->top = reply->client.top;
557 rectClient->right = reply->client.right;
558 rectClient->bottom = reply->client.bottom;
562 SERVER_END_REQ;
564 else
566 if (rectWindow) *rectWindow = win->rectWindow;
567 if (rectClient) *rectClient = win->rectClient;
568 WIN_ReleasePtr( win );
570 return ret;
574 /***********************************************************************
575 * WIN_DestroyWindow
577 * Destroy storage associated to a window. "Internals" p.358
579 LRESULT WIN_DestroyWindow( HWND hwnd )
581 WND *wndPtr;
582 HWND *list;
583 HMENU menu = 0, sys_menu;
585 TRACE("%p\n", hwnd );
587 if (!(hwnd = WIN_IsCurrentThread( hwnd )))
589 ERR( "window doesn't belong to current thread\n" );
590 return 0;
593 /* free child windows */
594 if ((list = WIN_ListChildren( hwnd )))
596 int i;
597 for (i = 0; list[i]; i++)
599 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
600 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
602 HeapFree( GetProcessHeap(), 0, list );
605 /* Unlink now so we won't bother with the children later on */
606 WIN_UnlinkWindow( hwnd );
609 * Send the WM_NCDESTROY to the window being destroyed.
611 SendMessageW( hwnd, WM_NCDESTROY, 0, 0 );
613 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
615 WINPOS_CheckInternalPos( hwnd );
617 /* free resources associated with the window */
619 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
620 if (!(wndPtr->dwStyle & WS_CHILD)) menu = (HMENU)wndPtr->wIDmenu;
621 sys_menu = wndPtr->hSysMenu;
622 WIN_ReleasePtr( wndPtr );
624 if (menu) DestroyMenu( menu );
625 if (sys_menu) DestroyMenu( sys_menu );
627 DCE_FreeWindowDCE( hwnd ); /* Always do this to catch orphaned DCs */
628 if (USER_Driver.pDestroyWindow) USER_Driver.pDestroyWindow( hwnd );
630 free_window_handle( hwnd );
631 return 0;
634 /***********************************************************************
635 * WIN_DestroyThreadWindows
637 * Destroy all children of 'wnd' owned by the current thread.
638 * Return TRUE if something was done.
640 void WIN_DestroyThreadWindows( HWND hwnd )
642 HWND *list;
643 int i;
645 if (!(list = WIN_ListChildren( hwnd ))) return;
646 for (i = 0; list[i]; i++)
648 if (WIN_IsCurrentThread( list[i] ))
649 DestroyWindow( list[i] );
650 else
651 WIN_DestroyThreadWindows( list[i] );
653 HeapFree( GetProcessHeap(), 0, list );
656 /***********************************************************************
657 * WIN_CreateDesktopWindow
659 * Create the desktop window.
661 BOOL WIN_CreateDesktopWindow(void)
663 CREATESTRUCTA cs;
665 TRACE("Creating desktop window\n");
667 if (!WINPOS_CreateInternalPosAtom()) return FALSE;
669 SERVER_START_REQ( create_window )
671 req->parent = 0;
672 req->owner = 0;
673 req->atom = LOWORD(DESKTOP_CLASS_ATOM);
674 req->instance = 0;
675 if (!wine_server_call_err( req )) hwndDesktop = reply->handle;
677 SERVER_END_REQ;
679 if (!hwndDesktop)
681 ERR( "error %ld creating desktop window\n", GetLastError() );
682 return FALSE;
685 cs.lpCreateParams = NULL;
686 cs.hInstance = 0;
687 cs.hMenu = 0;
688 cs.hwndParent = 0;
689 cs.x = 0;
690 cs.y = 0;
691 cs.cx = GetSystemMetrics( SM_CXSCREEN );
692 cs.cy = GetSystemMetrics( SM_CYSCREEN );
693 cs.style = WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
694 cs.dwExStyle = 0;
695 cs.lpszName = NULL;
696 cs.lpszClass = DESKTOP_CLASS_ATOM;
698 return USER_Driver.pCreateWindow( hwndDesktop, &cs, TRUE );
702 /***********************************************************************
703 * WIN_FixCoordinates
705 * Fix the coordinates - Helper for WIN_CreateWindowEx.
706 * returns default show mode in sw.
707 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
709 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
711 POINT pos[2];
713 if (cs->dwExStyle & WS_EX_MDICHILD)
715 UINT id = 0;
717 MDI_CalcDefaultChildPos(cs->hwndParent, -1, pos, 0, &id);
718 if (!(cs->style & WS_POPUP)) cs->hMenu = (HMENU)id;
720 TRACE("MDI child id %04x\n", id);
723 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
724 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
726 if (cs->style & (WS_CHILD | WS_POPUP))
728 if (cs->dwExStyle & WS_EX_MDICHILD)
730 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
732 cs->x = pos[0].x;
733 cs->y = pos[0].y;
735 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16 || !cs->cx)
736 cs->cx = pos[1].x;
737 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16 || !cs->cy)
738 cs->cy = pos[1].y;
740 else
742 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
743 cs->x = cs->y = 0;
744 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
745 cs->cx = cs->cy = 0;
748 else /* overlapped window */
750 STARTUPINFOW info;
752 GetStartupInfoW( &info );
754 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
756 /* Never believe Microsoft's documentation... CreateWindowEx doc says
757 * that if an overlapped window is created with WS_VISIBLE style bit
758 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
759 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
760 * reveals that
762 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
763 * 2) it does not ignore the y parameter as the docs claim; instead, it
764 * uses it as second parameter to ShowWindow() unless y is either
765 * CW_USEDEFAULT or CW_USEDEFAULT16.
767 * The fact that we didn't do 2) caused bogus windows pop up when wine
768 * was running apps that were using this obscure feature. Example -
769 * calc.exe that comes with Win98 (only Win98, it's different from
770 * the one that comes with Win95 and NT)
772 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
773 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
774 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
777 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
779 if (info.dwFlags & STARTF_USESIZE)
781 cs->cx = info.dwXSize;
782 cs->cy = info.dwYSize;
784 else /* if no other hint from the app, pick 3/4 of the screen real estate */
786 RECT r;
787 SystemParametersInfoW( SPI_GETWORKAREA, 0, &r, 0);
788 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
789 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
792 /* Handle case where only the cy values is set to default */
793 else if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16)
795 RECT r;
796 SystemParametersInfoW( SPI_GETWORKAREA, 0, &r, 0);
797 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
801 else
803 /* neither x nor cx are default. Check the y values .
804 * In the trace we see Outlook and Outlook Express using
805 * cy set to CW_USEDEFAULT when opening the address book.
807 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16) {
808 RECT r;
809 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
810 SystemParametersInfoW( SPI_GETWORKAREA, 0, &r, 0);
811 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
816 /***********************************************************************
817 * dump_window_styles
819 static void dump_window_styles( DWORD style, DWORD exstyle )
821 TRACE( "style:" );
822 if(style & WS_POPUP) TRACE(" WS_POPUP");
823 if(style & WS_CHILD) TRACE(" WS_CHILD");
824 if(style & WS_MINIMIZE) TRACE(" WS_MINIMIZE");
825 if(style & WS_VISIBLE) TRACE(" WS_VISIBLE");
826 if(style & WS_DISABLED) TRACE(" WS_DISABLED");
827 if(style & WS_CLIPSIBLINGS) TRACE(" WS_CLIPSIBLINGS");
828 if(style & WS_CLIPCHILDREN) TRACE(" WS_CLIPCHILDREN");
829 if(style & WS_MAXIMIZE) TRACE(" WS_MAXIMIZE");
830 if((style & WS_CAPTION) == WS_CAPTION) TRACE(" WS_CAPTION");
831 else
833 if(style & WS_BORDER) TRACE(" WS_BORDER");
834 if(style & WS_DLGFRAME) TRACE(" WS_DLGFRAME");
836 if(style & WS_VSCROLL) TRACE(" WS_VSCROLL");
837 if(style & WS_HSCROLL) TRACE(" WS_HSCROLL");
838 if(style & WS_SYSMENU) TRACE(" WS_SYSMENU");
839 if(style & WS_THICKFRAME) TRACE(" WS_THICKFRAME");
840 if(style & WS_GROUP) TRACE(" WS_GROUP");
841 if(style & WS_TABSTOP) TRACE(" WS_TABSTOP");
842 if(style & WS_MINIMIZEBOX) TRACE(" WS_MINIMIZEBOX");
843 if(style & WS_MAXIMIZEBOX) TRACE(" WS_MAXIMIZEBOX");
845 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
846 #define DUMPED_STYLES \
847 (WS_POPUP | \
848 WS_CHILD | \
849 WS_MINIMIZE | \
850 WS_VISIBLE | \
851 WS_DISABLED | \
852 WS_CLIPSIBLINGS | \
853 WS_CLIPCHILDREN | \
854 WS_MAXIMIZE | \
855 WS_BORDER | \
856 WS_DLGFRAME | \
857 WS_VSCROLL | \
858 WS_HSCROLL | \
859 WS_SYSMENU | \
860 WS_THICKFRAME | \
861 WS_GROUP | \
862 WS_TABSTOP | \
863 WS_MINIMIZEBOX | \
864 WS_MAXIMIZEBOX)
866 if(style & ~DUMPED_STYLES) TRACE(" %08lx", style & ~DUMPED_STYLES);
867 TRACE("\n");
868 #undef DUMPED_STYLES
870 TRACE( "exstyle:" );
871 if(exstyle & WS_EX_DLGMODALFRAME) TRACE(" WS_EX_DLGMODALFRAME");
872 if(exstyle & WS_EX_DRAGDETECT) TRACE(" WS_EX_DRAGDETECT");
873 if(exstyle & WS_EX_NOPARENTNOTIFY) TRACE(" WS_EX_NOPARENTNOTIFY");
874 if(exstyle & WS_EX_TOPMOST) TRACE(" WS_EX_TOPMOST");
875 if(exstyle & WS_EX_ACCEPTFILES) TRACE(" WS_EX_ACCEPTFILES");
876 if(exstyle & WS_EX_TRANSPARENT) TRACE(" WS_EX_TRANSPARENT");
877 if(exstyle & WS_EX_MDICHILD) TRACE(" WS_EX_MDICHILD");
878 if(exstyle & WS_EX_TOOLWINDOW) TRACE(" WS_EX_TOOLWINDOW");
879 if(exstyle & WS_EX_WINDOWEDGE) TRACE(" WS_EX_WINDOWEDGE");
880 if(exstyle & WS_EX_CLIENTEDGE) TRACE(" WS_EX_CLIENTEDGE");
881 if(exstyle & WS_EX_CONTEXTHELP) TRACE(" WS_EX_CONTEXTHELP");
882 if(exstyle & WS_EX_RIGHT) TRACE(" WS_EX_RIGHT");
883 if(exstyle & WS_EX_RTLREADING) TRACE(" WS_EX_RTLREADING");
884 if(exstyle & WS_EX_LEFTSCROLLBAR) TRACE(" WS_EX_LEFTSCROLLBAR");
885 if(exstyle & WS_EX_CONTROLPARENT) TRACE(" WS_EX_CONTROLPARENT");
886 if(exstyle & WS_EX_STATICEDGE) TRACE(" WS_EX_STATICEDGE");
887 if(exstyle & WS_EX_APPWINDOW) TRACE(" WS_EX_APPWINDOW");
888 if(exstyle & WS_EX_LAYERED) TRACE(" WS_EX_LAYERED");
890 #define DUMPED_EX_STYLES \
891 (WS_EX_DLGMODALFRAME | \
892 WS_EX_DRAGDETECT | \
893 WS_EX_NOPARENTNOTIFY | \
894 WS_EX_TOPMOST | \
895 WS_EX_ACCEPTFILES | \
896 WS_EX_TRANSPARENT | \
897 WS_EX_MDICHILD | \
898 WS_EX_TOOLWINDOW | \
899 WS_EX_WINDOWEDGE | \
900 WS_EX_CLIENTEDGE | \
901 WS_EX_CONTEXTHELP | \
902 WS_EX_RIGHT | \
903 WS_EX_RTLREADING | \
904 WS_EX_LEFTSCROLLBAR | \
905 WS_EX_CONTROLPARENT | \
906 WS_EX_STATICEDGE | \
907 WS_EX_APPWINDOW | \
908 WS_EX_LAYERED)
910 if(exstyle & ~DUMPED_EX_STYLES) TRACE(" %08lx", exstyle & ~DUMPED_EX_STYLES);
911 TRACE("\n");
912 #undef DUMPED_EX_STYLES
916 /***********************************************************************
917 * WIN_CreateWindowEx
919 * Implementation of CreateWindowEx().
921 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
922 WINDOWPROCTYPE type )
924 INT sw = SW_SHOW;
925 WND *wndPtr;
926 HWND hwnd, parent, owner, top_child = 0;
927 BOOL unicode = (type == WIN_PROC_32W);
929 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
930 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
931 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszClass) : debugstr_a(cs->lpszClass),
932 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
933 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
935 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
937 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
938 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
940 /* Fix the styles for MDI children */
941 if (cs->dwExStyle & WS_EX_MDICHILD)
943 MDICREATESTRUCTA mdi_cs;
944 UINT flags = 0;
946 wndPtr = WIN_GetPtr(cs->hwndParent);
947 if (wndPtr && wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
949 flags = wndPtr->flags;
950 WIN_ReleasePtr(wndPtr);
953 if (!(flags & WIN_ISMDICLIENT))
955 WARN("WS_EX_MDICHILD, but parent %p is not MDIClient\n", cs->hwndParent);
956 return 0;
959 /* cs->lpCreateParams of WM_[NC]CREATE is different for MDI children.
960 * MDICREATESTRUCT members have the originally passed values.
962 * Note: we rely on the fact that MDICREATESTRUCTA and MDICREATESTRUCTW
963 * have the same layout.
965 mdi_cs.szClass = cs->lpszClass;
966 mdi_cs.szTitle = cs->lpszName;
967 mdi_cs.hOwner = cs->hInstance;
968 mdi_cs.x = cs->x;
969 mdi_cs.y = cs->y;
970 mdi_cs.cx = cs->cx;
971 mdi_cs.cy = cs->cy;
972 mdi_cs.style = cs->style;
973 mdi_cs.lParam = (LPARAM)cs->lpCreateParams;
975 cs->lpCreateParams = (LPVOID)&mdi_cs;
977 if (GetWindowLongW(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
979 if (cs->style & WS_POPUP)
981 TRACE("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n");
982 return 0;
984 cs->style |= WS_CHILD | WS_CLIPSIBLINGS;
986 else
988 cs->style &= ~WS_POPUP;
989 cs->style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
990 WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
993 top_child = GetWindow(cs->hwndParent, GW_CHILD);
995 if (top_child)
997 /* Restore current maximized child */
998 if((cs->style & WS_VISIBLE) && IsZoomed(top_child))
1000 TRACE("Restoring current maximized child %p\n", top_child);
1001 SendMessageW( top_child, WM_SETREDRAW, FALSE, 0 );
1002 ShowWindow(top_child, SW_RESTORE);
1003 SendMessageW( top_child, WM_SETREDRAW, TRUE, 0 );
1008 /* Find the parent window */
1010 parent = GetDesktopWindow();
1011 owner = 0;
1013 if (cs->hwndParent == HWND_MESSAGE)
1015 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
1016 * message window (style: WS_POPUP|WS_DISABLED)
1018 FIXME("Parent is HWND_MESSAGE\n");
1020 else if (cs->hwndParent)
1022 /* Make sure parent is valid */
1023 if (!IsWindow( cs->hwndParent ))
1025 WARN("Bad parent %p\n", cs->hwndParent );
1026 return 0;
1028 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1029 parent = WIN_GetFullHandle(cs->hwndParent);
1030 else
1031 owner = GetAncestor( cs->hwndParent, GA_ROOT );
1033 else if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1035 WARN("No parent for child window\n" );
1036 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1039 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
1041 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
1042 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
1043 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
1044 cs->dwExStyle |= WS_EX_WINDOWEDGE;
1045 else
1046 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
1048 /* Create the window structure */
1050 if (!(wndPtr = create_window_handle( parent, owner, classAtom, cs->hInstance, type )))
1052 TRACE("out of memory\n" );
1053 return 0;
1055 hwnd = wndPtr->hwndSelf;
1057 /* Fill the window structure */
1059 wndPtr->tid = GetCurrentThreadId();
1060 wndPtr->owner = owner;
1061 wndPtr->parent = parent;
1062 wndPtr->hInstance = cs->hInstance;
1063 wndPtr->text = NULL;
1064 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1065 wndPtr->dwExStyle = cs->dwExStyle;
1066 wndPtr->wIDmenu = 0;
1067 wndPtr->helpContext = 0;
1068 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
1069 wndPtr->pVScroll = NULL;
1070 wndPtr->pHScroll = NULL;
1071 wndPtr->userdata = 0;
1072 wndPtr->hIcon = 0;
1073 wndPtr->hIconSmall = 0;
1074 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU) ? MENU_GetSysMenu( hwnd, 0 ) : 0;
1077 * Correct the window styles.
1079 * It affects only the style loaded into the WIN structure.
1082 if (!(wndPtr->dwStyle & WS_CHILD))
1084 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1085 if (!(wndPtr->dwStyle & WS_POPUP))
1086 wndPtr->dwStyle |= WS_CAPTION;
1090 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1091 * why does the user get to set it?
1094 if ((wndPtr->dwExStyle & WS_EX_DLGMODALFRAME) ||
1095 (wndPtr->dwStyle & (WS_DLGFRAME | WS_THICKFRAME)))
1096 wndPtr->dwExStyle |= WS_EX_WINDOWEDGE;
1097 else
1098 wndPtr->dwExStyle &= ~WS_EX_WINDOWEDGE;
1100 if (!(wndPtr->dwStyle & (WS_CHILD | WS_POPUP)))
1101 wndPtr->flags |= WIN_NEED_SIZE;
1103 SERVER_START_REQ( set_window_info )
1105 req->handle = hwnd;
1106 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE;
1107 req->style = wndPtr->dwStyle;
1108 req->ex_style = wndPtr->dwExStyle;
1109 req->instance = (void *)wndPtr->hInstance;
1110 req->extra_offset = -1;
1111 wine_server_call( req );
1113 SERVER_END_REQ;
1115 /* Get class or window DC if needed */
1117 if (wndPtr->clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
1119 /* Set the window menu */
1121 if (((wndPtr->dwStyle & (WS_CAPTION|WS_CHILD)) == WS_CAPTION) ||
1122 (wndPtr->dwExStyle & WS_EX_APPWINDOW))
1124 if (cs->hMenu) MENU_SetMenu(hwnd, cs->hMenu);
1125 else
1127 LPCSTR menuName = (LPCSTR)GetClassLongPtrA( hwnd, GCLP_MENUNAME );
1128 if (menuName)
1130 if (HIWORD(cs->hInstance))
1131 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1132 else
1133 cs->hMenu = HMENU_32(LoadMenu16(HINSTANCE_16(cs->hInstance),menuName));
1135 if (cs->hMenu) MENU_SetMenu( hwnd, cs->hMenu );
1139 else SetWindowLongPtrW( hwnd, GWLP_ID, (ULONG_PTR)cs->hMenu );
1140 WIN_ReleasePtr( wndPtr );
1142 if (!USER_Driver.pCreateWindow || !USER_Driver.pCreateWindow( hwnd, cs, unicode))
1144 WIN_DestroyWindow( hwnd );
1145 return 0;
1148 /* Notify the parent window only */
1150 send_parent_notify( hwnd, WM_CREATE );
1151 if (!IsWindow( hwnd )) return 0;
1153 if (cs->style & WS_VISIBLE)
1155 if (cs->style & WS_MAXIMIZE)
1156 sw = SW_SHOWMAXIMIZED;
1157 else if (cs->style & WS_MINIMIZE)
1158 sw = SW_SHOWMINIMIZED;
1160 ShowWindow( hwnd, sw );
1161 if (cs->dwExStyle & WS_EX_MDICHILD)
1163 SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
1164 /* ShowWindow won't activate child windows */
1165 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE );
1169 /* Call WH_SHELL hook */
1171 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1172 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1174 TRACE("created window %p\n", hwnd);
1175 return hwnd;
1179 /***********************************************************************
1180 * CreateWindow (USER.41)
1182 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1183 DWORD style, INT16 x, INT16 y, INT16 width,
1184 INT16 height, HWND16 parent, HMENU16 menu,
1185 HINSTANCE16 instance, LPVOID data )
1187 return CreateWindowEx16( 0, className, windowName, style,
1188 x, y, width, height, parent, menu, instance, data );
1192 /***********************************************************************
1193 * CreateWindowEx (USER.452)
1195 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1196 LPCSTR windowName, DWORD style, INT16 x,
1197 INT16 y, INT16 width, INT16 height,
1198 HWND16 parent, HMENU16 menu,
1199 HINSTANCE16 instance, LPVOID data )
1201 ATOM classAtom;
1202 CREATESTRUCTA cs;
1203 char buffer[256];
1205 /* Find the class atom */
1207 if (HIWORD(className))
1209 if (!(classAtom = GlobalFindAtomA( className )))
1211 ERR( "bad class name %s\n", debugstr_a(className) );
1212 return 0;
1215 else
1217 classAtom = LOWORD(className);
1218 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1220 ERR( "bad atom %x\n", classAtom);
1221 return 0;
1223 className = buffer;
1226 /* Fix the coordinates */
1228 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1229 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1230 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1231 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1233 /* Create the window */
1235 cs.lpCreateParams = data;
1236 cs.hInstance = HINSTANCE_32(instance);
1237 cs.hMenu = HMENU_32(menu);
1238 cs.hwndParent = WIN_Handle32( parent );
1239 cs.style = style;
1240 cs.lpszName = windowName;
1241 cs.lpszClass = className;
1242 cs.dwExStyle = exStyle;
1244 return HWND_16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
1248 /***********************************************************************
1249 * CreateWindowExA (USER32.@)
1251 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1252 LPCSTR windowName, DWORD style, INT x,
1253 INT y, INT width, INT height,
1254 HWND parent, HMENU menu,
1255 HINSTANCE instance, LPVOID data )
1257 ATOM classAtom;
1258 CREATESTRUCTA cs;
1259 char buffer[256];
1261 /* Find the class atom */
1263 if (HIWORD(className))
1265 if (!(classAtom = GlobalFindAtomA( className )))
1267 ERR( "bad class name %s\n", debugstr_a(className) );
1268 return 0;
1271 else
1273 classAtom = LOWORD(className);
1274 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1276 ERR( "bad atom %x\n", classAtom);
1277 return 0;
1279 className = buffer;
1282 /* Create the window */
1284 cs.lpCreateParams = data;
1285 cs.hInstance = instance;
1286 cs.hMenu = menu;
1287 cs.hwndParent = parent;
1288 cs.x = x;
1289 cs.y = y;
1290 cs.cx = width;
1291 cs.cy = height;
1292 cs.style = style;
1293 cs.lpszName = windowName;
1294 cs.lpszClass = className;
1295 cs.dwExStyle = exStyle;
1297 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1301 /***********************************************************************
1302 * CreateWindowExW (USER32.@)
1304 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1305 LPCWSTR windowName, DWORD style, INT x,
1306 INT y, INT width, INT height,
1307 HWND parent, HMENU menu,
1308 HINSTANCE instance, LPVOID data )
1310 ATOM classAtom;
1311 CREATESTRUCTW cs;
1312 WCHAR buffer[256];
1314 /* Find the class atom */
1316 if (HIWORD(className))
1318 if (!(classAtom = GlobalFindAtomW( className )))
1320 ERR( "bad class name %s\n", debugstr_w(className) );
1321 return 0;
1324 else
1326 classAtom = LOWORD(className);
1327 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1329 ERR( "bad atom %x\n", classAtom);
1330 return 0;
1332 className = buffer;
1335 /* Create the window */
1337 cs.lpCreateParams = data;
1338 cs.hInstance = instance;
1339 cs.hMenu = menu;
1340 cs.hwndParent = parent;
1341 cs.x = x;
1342 cs.y = y;
1343 cs.cx = width;
1344 cs.cy = height;
1345 cs.style = style;
1346 cs.lpszName = windowName;
1347 cs.lpszClass = className;
1348 cs.dwExStyle = exStyle;
1350 /* Note: we rely on the fact that CREATESTRUCTA and */
1351 /* CREATESTRUCTW have the same layout. */
1352 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1356 /***********************************************************************
1357 * WIN_SendDestroyMsg
1359 static void WIN_SendDestroyMsg( HWND hwnd )
1361 GUITHREADINFO info;
1363 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1365 if (hwnd == info.hwndCaret) DestroyCaret();
1366 if (hwnd == info.hwndActive) WINPOS_ActivateOtherWindow( hwnd );
1368 if (USER_Driver.pResetSelectionOwner)
1369 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1372 * Send the WM_DESTROY to the window.
1374 SendMessageW( hwnd, WM_DESTROY, 0, 0);
1377 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1378 * make sure that the window still exists when we come back.
1380 if (IsWindow(hwnd))
1382 HWND* pWndArray;
1383 int i;
1385 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1387 for (i = 0; pWndArray[i]; i++)
1389 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1391 HeapFree( GetProcessHeap(), 0, pWndArray );
1393 else
1394 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1398 /***********************************************************************
1399 * DestroyWindow (USER32.@)
1401 BOOL WINAPI DestroyWindow( HWND hwnd )
1403 BOOL is_child;
1405 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1407 SetLastError( ERROR_ACCESS_DENIED );
1408 return FALSE;
1411 TRACE("(%p)\n", hwnd);
1413 /* Call hooks */
1415 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1417 if (MENU_IsMenuActive() == hwnd)
1418 EndMenu();
1420 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1422 if (is_child)
1424 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1425 send_parent_notify( hwnd, WM_DESTROY );
1427 else if (!GetWindow( hwnd, GW_OWNER ))
1429 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1430 /* FIXME: clean up palette - see "Internals" p.352 */
1433 if (!IsWindow(hwnd)) return TRUE;
1435 if (USER_Driver.pResetSelectionOwner)
1436 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1438 /* Hide the window */
1439 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)
1441 /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
1442 if (is_child)
1443 ShowWindow( hwnd, SW_HIDE );
1444 else
1445 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1446 SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW );
1449 if (!IsWindow(hwnd)) return TRUE;
1451 /* Recursively destroy owned windows */
1453 if (!is_child)
1455 for (;;)
1457 int i, got_one = 0;
1458 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1459 if (list)
1461 for (i = 0; list[i]; i++)
1463 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1464 if (WIN_IsCurrentThread( list[i] ))
1466 DestroyWindow( list[i] );
1467 got_one = 1;
1468 continue;
1470 WIN_SetOwner( list[i], 0 );
1472 HeapFree( GetProcessHeap(), 0, list );
1474 if (!got_one) break;
1478 /* Send destroy messages */
1480 WIN_SendDestroyMsg( hwnd );
1481 if (!IsWindow( hwnd )) return TRUE;
1483 if (GetClipboardOwner() == hwnd)
1484 CLIPBOARD_ReleaseOwner();
1486 /* Destroy the window storage */
1488 WIN_DestroyWindow( hwnd );
1489 return TRUE;
1493 /***********************************************************************
1494 * CloseWindow (USER32.@)
1496 BOOL WINAPI CloseWindow( HWND hwnd )
1498 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1499 ShowWindow( hwnd, SW_MINIMIZE );
1500 return TRUE;
1504 /***********************************************************************
1505 * OpenIcon (USER32.@)
1507 BOOL WINAPI OpenIcon( HWND hwnd )
1509 if (!IsIconic( hwnd )) return FALSE;
1510 ShowWindow( hwnd, SW_SHOWNORMAL );
1511 return TRUE;
1515 /***********************************************************************
1516 * WIN_FindWindow
1518 * Implementation of FindWindow() and FindWindowEx().
1520 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1522 HWND *list = NULL;
1523 HWND retvalue = 0;
1524 int i = 0, len = 0;
1525 WCHAR *buffer = NULL;
1527 if (!parent) parent = GetDesktopWindow();
1528 if (title)
1530 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1531 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1534 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1536 if (child)
1538 child = WIN_GetFullHandle( child );
1539 while (list[i] && list[i] != child) i++;
1540 if (!list[i]) goto done;
1541 i++; /* start from next window */
1544 if (title)
1546 while (list[i])
1548 if (GetWindowTextW( list[i], buffer, len + 1 ) && !strcmpiW( buffer, title )) break;
1549 i++;
1552 retvalue = list[i];
1554 done:
1555 HeapFree( GetProcessHeap(), 0, list );
1556 HeapFree( GetProcessHeap(), 0, buffer );
1557 return retvalue;
1562 /***********************************************************************
1563 * FindWindowA (USER32.@)
1565 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1567 HWND ret = FindWindowExA( 0, 0, className, title );
1568 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1569 return ret;
1573 /***********************************************************************
1574 * FindWindowExA (USER32.@)
1576 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1577 LPCSTR className, LPCSTR title )
1579 ATOM atom = 0;
1580 LPWSTR buffer;
1581 HWND hwnd;
1582 INT len;
1584 if (className)
1586 /* If the atom doesn't exist, then no class */
1587 /* with this name exists either. */
1588 if (!(atom = GlobalFindAtomA( className )))
1590 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1591 return 0;
1594 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
1596 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1597 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1598 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
1599 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1600 HeapFree( GetProcessHeap(), 0, buffer );
1601 return hwnd;
1605 /***********************************************************************
1606 * FindWindowExW (USER32.@)
1608 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1609 LPCWSTR className, LPCWSTR title )
1611 ATOM atom = 0;
1613 if (className)
1615 /* If the atom doesn't exist, then no class */
1616 /* with this name exists either. */
1617 if (!(atom = GlobalFindAtomW( className )))
1619 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1620 return 0;
1623 return WIN_FindWindow( parent, child, atom, title );
1627 /***********************************************************************
1628 * FindWindowW (USER32.@)
1630 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1632 return FindWindowExW( 0, 0, className, title );
1636 /**********************************************************************
1637 * GetDesktopWindow (USER32.@)
1639 HWND WINAPI GetDesktopWindow(void)
1641 if (hwndDesktop) return hwndDesktop;
1642 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" );
1643 ExitProcess(1);
1644 return 0;
1648 /*******************************************************************
1649 * EnableWindow (USER32.@)
1651 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1653 BOOL retvalue;
1654 HWND full_handle;
1656 if (is_broadcast(hwnd))
1658 SetLastError( ERROR_INVALID_PARAMETER );
1659 return FALSE;
1662 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1663 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1665 hwnd = full_handle;
1667 TRACE("( %p, %d )\n", hwnd, enable);
1669 retvalue = !IsWindowEnabled( hwnd );
1671 if (enable && retvalue)
1673 WIN_SetStyle( hwnd, 0, WS_DISABLED );
1674 SendMessageW( hwnd, WM_ENABLE, TRUE, 0 );
1676 else if (!enable && !retvalue)
1678 HWND capture_wnd;
1680 SendMessageW( hwnd, WM_CANCELMODE, 0, 0);
1682 WIN_SetStyle( hwnd, WS_DISABLED, 0 );
1684 if (hwnd == GetFocus())
1685 SetFocus( 0 ); /* A disabled window can't have the focus */
1687 capture_wnd = GetCapture();
1688 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1689 ReleaseCapture(); /* A disabled window can't capture the mouse */
1691 SendMessageW( hwnd, WM_ENABLE, FALSE, 0 );
1693 return retvalue;
1697 /***********************************************************************
1698 * IsWindowEnabled (USER32.@)
1700 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1702 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1706 /***********************************************************************
1707 * IsWindowUnicode (USER32.@)
1709 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1711 WND * wndPtr;
1712 BOOL retvalue;
1714 if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return FALSE;
1715 if (wndPtr == WND_DESKTOP) return TRUE;
1716 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1717 WIN_ReleasePtr( wndPtr );
1718 return retvalue;
1722 /**********************************************************************
1723 * GetWindowWord (USER32.@)
1725 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1727 if (offset >= 0)
1729 WORD retvalue = 0;
1730 WND *wndPtr = WIN_GetPtr( hwnd );
1731 if (!wndPtr)
1733 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1734 return 0;
1736 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1738 SERVER_START_REQ( set_window_info )
1740 req->handle = hwnd;
1741 req->flags = 0; /* don't set anything, just retrieve */
1742 req->extra_offset = offset;
1743 req->extra_size = sizeof(retvalue);
1744 if (!wine_server_call_err( req ))
1745 memcpy( &retvalue, &reply->old_extra_value, sizeof(retvalue) );
1747 SERVER_END_REQ;
1748 return retvalue;
1750 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1752 WARN("Invalid offset %d\n", offset );
1753 SetLastError( ERROR_INVALID_INDEX );
1755 else memcpy( &retvalue, (char *)wndPtr->wExtra + offset, sizeof(retvalue) );
1756 WIN_ReleasePtr( wndPtr );
1757 return retvalue;
1760 switch(offset)
1762 case GWLP_HWNDPARENT:
1763 return GetWindowLongPtrW( hwnd, offset );
1764 case GWLP_ID:
1765 case GWLP_HINSTANCE:
1767 LONG_PTR ret = GetWindowLongPtrW( hwnd, offset );
1768 if (HIWORD(ret))
1769 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1770 return LOWORD(ret);
1772 default:
1773 WARN("Invalid offset %d\n", offset );
1774 return 0;
1779 /**********************************************************************
1780 * SetWindowWord (USER32.@)
1782 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1784 WORD retval = 0;
1785 WND * wndPtr;
1787 switch(offset)
1789 case GWLP_ID:
1790 case GWLP_HINSTANCE:
1791 case GWLP_HWNDPARENT:
1792 return SetWindowLongPtrW( hwnd, offset, (ULONG_PTR)newval );
1793 default:
1794 if (offset < 0)
1796 WARN("Invalid offset %d\n", offset );
1797 SetLastError( ERROR_INVALID_INDEX );
1798 return 0;
1802 wndPtr = WIN_GetPtr( hwnd );
1803 if (wndPtr == WND_DESKTOP)
1805 SetLastError( ERROR_ACCESS_DENIED );
1806 return 0;
1808 if (wndPtr == WND_OTHER_PROCESS)
1810 if (IsWindow(hwnd))
1811 FIXME( "set %d <- %x not supported yet on other process window %p\n",
1812 offset, newval, hwnd );
1813 wndPtr = NULL;
1815 if (!wndPtr)
1817 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1818 return 0;
1821 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1823 WARN("Invalid offset %d\n", offset );
1824 WIN_ReleasePtr(wndPtr);
1825 SetLastError( ERROR_INVALID_INDEX );
1826 return 0;
1829 SERVER_START_REQ( set_window_info )
1831 req->handle = hwnd;
1832 req->flags = SET_WIN_EXTRA;
1833 req->extra_offset = offset;
1834 req->extra_size = sizeof(newval);
1835 memcpy( &req->extra_value, &newval, sizeof(newval) );
1836 if (!wine_server_call_err( req ))
1838 void *ptr = (char *)wndPtr->wExtra + offset;
1839 memcpy( &retval, ptr, sizeof(retval) );
1840 memcpy( ptr, &newval, sizeof(newval) );
1843 SERVER_END_REQ;
1844 WIN_ReleasePtr( wndPtr );
1845 return retval;
1849 /**********************************************************************
1850 * WIN_GetWindowLong
1852 * Helper function for GetWindowLong().
1854 static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1856 LONG_PTR retvalue = 0;
1857 WND *wndPtr;
1859 if (offset == GWLP_HWNDPARENT)
1861 HWND parent = GetAncestor( hwnd, GA_PARENT );
1862 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1863 return (ULONG_PTR)parent;
1866 if (!(wndPtr = WIN_GetPtr( hwnd )))
1868 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1869 return 0;
1872 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1874 if (offset == GWLP_WNDPROC)
1876 SetLastError( ERROR_ACCESS_DENIED );
1877 return 0;
1879 SERVER_START_REQ( set_window_info )
1881 req->handle = hwnd;
1882 req->flags = 0; /* don't set anything, just retrieve */
1883 req->extra_offset = (offset >= 0) ? offset : -1;
1884 req->extra_size = (offset >= 0) ? sizeof(retvalue) : 0;
1885 if (!wine_server_call_err( req ))
1887 switch(offset)
1889 case GWL_STYLE: retvalue = reply->old_style; break;
1890 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1891 case GWLP_ID: retvalue = reply->old_id; break;
1892 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1893 case GWLP_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
1894 default:
1895 if (offset >= 0) retvalue = reply->old_extra_value;
1896 else SetLastError( ERROR_INVALID_INDEX );
1897 break;
1901 SERVER_END_REQ;
1902 return retvalue;
1905 /* now we have a valid wndPtr */
1907 if (offset >= 0)
1909 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
1912 * Some programs try to access last element from 16 bit
1913 * code using illegal offset value. Hopefully this is
1914 * what those programs really expect.
1916 if (type == WIN_PROC_16 &&
1917 wndPtr->cbWndExtra >= 4 &&
1918 offset == wndPtr->cbWndExtra - sizeof(WORD))
1920 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
1922 ERR( "- replaced invalid offset %d with %d\n",
1923 offset, offset2 );
1925 retvalue = *(LONG_PTR *)(((char *)wndPtr->wExtra) + offset2);
1926 WIN_ReleasePtr( wndPtr );
1927 return retvalue;
1929 WARN("Invalid offset %d\n", offset );
1930 WIN_ReleasePtr( wndPtr );
1931 SetLastError( ERROR_INVALID_INDEX );
1932 return 0;
1934 retvalue = *(LONG_PTR *)(((char *)wndPtr->wExtra) + offset);
1935 /* Special case for dialog window procedure */
1936 if ((offset == DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1937 retvalue = (LONG_PTR)WINPROC_GetProc( (WNDPROC)retvalue, type );
1938 WIN_ReleasePtr( wndPtr );
1939 return retvalue;
1942 switch(offset)
1944 case GWLP_USERDATA: retvalue = wndPtr->userdata; break;
1945 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1946 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1947 case GWLP_ID: retvalue = (ULONG_PTR)wndPtr->wIDmenu; break;
1948 case GWLP_WNDPROC: retvalue = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, type ); break;
1949 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wndPtr->hInstance; break;
1950 default:
1951 WARN("Unknown offset %d\n", offset );
1952 SetLastError( ERROR_INVALID_INDEX );
1953 break;
1955 WIN_ReleasePtr(wndPtr);
1956 return retvalue;
1960 /**********************************************************************
1961 * WIN_SetWindowLong
1963 * Helper function for SetWindowLong().
1965 * 0 is the failure code. However, in the case of failure SetLastError
1966 * must be set to distinguish between a 0 return value and a failure.
1968 static LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, LONG_PTR newval,
1969 WINDOWPROCTYPE type )
1971 STYLESTRUCT style;
1972 BOOL ok;
1973 LONG_PTR retval = 0;
1974 WND *wndPtr;
1976 TRACE( "%p %d %lx %x\n", hwnd, offset, newval, type );
1978 if (is_broadcast(hwnd))
1980 SetLastError( ERROR_INVALID_PARAMETER );
1981 return FALSE;
1984 if (!(wndPtr = WIN_GetPtr( hwnd )))
1986 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1987 return 0;
1989 if (wndPtr == WND_DESKTOP)
1991 /* can't change anything on the desktop window */
1992 SetLastError( ERROR_ACCESS_DENIED );
1993 return 0;
1995 if (wndPtr == WND_OTHER_PROCESS)
1997 if (offset == GWLP_WNDPROC)
1999 SetLastError( ERROR_ACCESS_DENIED );
2000 return 0;
2002 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
2005 /* first some special cases */
2006 switch( offset )
2008 case GWL_STYLE:
2009 case GWL_EXSTYLE:
2010 style.styleOld =
2011 offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
2012 style.styleNew = newval;
2013 WIN_ReleasePtr( wndPtr );
2014 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
2015 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
2016 newval = style.styleNew;
2017 break;
2018 case GWLP_HWNDPARENT:
2019 if (wndPtr->parent == GetDesktopWindow())
2021 WIN_ReleasePtr( wndPtr );
2022 return (ULONG_PTR)WIN_SetOwner( hwnd, (HWND)newval );
2024 else
2026 WIN_ReleasePtr( wndPtr );
2027 return (ULONG_PTR)SetParent( hwnd, (HWND)newval );
2029 case GWLP_WNDPROC:
2030 retval = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, type );
2031 wndPtr->winproc = WINPROC_AllocProc( (WNDPROC)newval, type );
2032 WIN_ReleasePtr( wndPtr );
2033 return retval;
2034 case GWLP_ID:
2035 case GWLP_HINSTANCE:
2036 case GWLP_USERDATA:
2037 break;
2038 case DWLP_DLGPROC:
2039 if ((wndPtr->cbWndExtra + sizeof(LONG_PTR) >= DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2041 WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWLP_DLGPROC);
2042 retval = (ULONG_PTR)WINPROC_GetProc( *ptr, type );
2043 *ptr = WINPROC_AllocProc( (WNDPROC)newval, type );
2044 WIN_ReleasePtr( wndPtr );
2045 return retval;
2047 /* fall through */
2048 default:
2049 if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - sizeof(LONG_PTR)))
2051 WARN("Invalid offset %d\n", offset );
2052 WIN_ReleasePtr( wndPtr );
2053 SetLastError( ERROR_INVALID_INDEX );
2054 return 0;
2056 else
2058 LONG_PTR *ptr = (LONG_PTR *)((char *)wndPtr->wExtra + offset);
2059 if (*ptr == newval) /* already set to the same value */
2061 WIN_ReleasePtr( wndPtr );
2062 return newval;
2065 break;
2068 SERVER_START_REQ( set_window_info )
2070 req->handle = hwnd;
2071 req->extra_offset = -1;
2072 switch(offset)
2074 case GWL_STYLE:
2075 req->flags = SET_WIN_STYLE;
2076 req->style = newval;
2077 break;
2078 case GWL_EXSTYLE:
2079 req->flags = SET_WIN_EXSTYLE;
2080 req->ex_style = newval;
2081 break;
2082 case GWLP_ID:
2083 req->flags = SET_WIN_ID;
2084 req->id = newval;
2085 break;
2086 case GWLP_HINSTANCE:
2087 req->flags = SET_WIN_INSTANCE;
2088 req->instance = (void *)newval;
2089 break;
2090 case GWLP_USERDATA:
2091 req->flags = SET_WIN_USERDATA;
2092 req->user_data = (void *)newval;
2093 break;
2094 default:
2095 req->flags = SET_WIN_EXTRA;
2096 req->extra_offset = offset;
2097 req->extra_size = sizeof(newval);
2098 memcpy( &req->extra_value, &newval, sizeof(newval) );
2100 if ((ok = !wine_server_call_err( req )))
2102 switch(offset)
2104 case GWL_STYLE:
2105 wndPtr->dwStyle = newval;
2106 retval = reply->old_style;
2107 break;
2108 case GWL_EXSTYLE:
2109 wndPtr->dwExStyle = newval;
2110 retval = reply->old_ex_style;
2111 break;
2112 case GWLP_ID:
2113 wndPtr->wIDmenu = newval;
2114 retval = reply->old_id;
2115 break;
2116 case GWLP_HINSTANCE:
2117 wndPtr->hInstance = (HINSTANCE)newval;
2118 retval = (ULONG_PTR)reply->old_instance;
2119 break;
2120 case GWLP_USERDATA:
2121 wndPtr->userdata = newval;
2122 retval = (ULONG_PTR)reply->old_user_data;
2123 break;
2124 default:
2126 void *ptr = (char *)wndPtr->wExtra + offset;
2127 memcpy( &retval, ptr, sizeof(retval) );
2128 memcpy( ptr, &newval, sizeof(newval) );
2130 break;
2134 SERVER_END_REQ;
2135 WIN_ReleasePtr( wndPtr );
2137 if (!ok) return 0;
2139 if (offset == GWL_STYLE && USER_Driver.pSetWindowStyle)
2140 USER_Driver.pSetWindowStyle( hwnd, retval );
2142 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2143 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2145 return retval;
2149 /**********************************************************************
2150 * GetWindowLong (USER.135)
2152 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2154 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
2158 /**********************************************************************
2159 * GetWindowLongA (USER32.@)
2161 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2163 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2167 /**********************************************************************
2168 * GetWindowLongW (USER32.@)
2170 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2172 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2176 /**********************************************************************
2177 * SetWindowLong (USER.136)
2179 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2181 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
2185 /**********************************************************************
2186 * SetWindowLongA (USER32.@)
2188 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2190 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2194 /**********************************************************************
2195 * SetWindowLongW (USER32.@) Set window attribute
2197 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2198 * value in a window's extra memory.
2200 * The _hwnd_ parameter specifies the window. is the handle to a
2201 * window that has extra memory. The _newval_ parameter contains the
2202 * new attribute or extra memory value. If positive, the _offset_
2203 * parameter is the byte-addressed location in the window's extra
2204 * memory to set. If negative, _offset_ specifies the window
2205 * attribute to set, and should be one of the following values:
2207 * GWL_EXSTYLE The window's extended window style
2209 * GWL_STYLE The window's window style.
2211 * GWLP_WNDPROC Pointer to the window's window procedure.
2213 * GWLP_HINSTANCE The window's pplication instance handle.
2215 * GWLP_ID The window's identifier.
2217 * GWLP_USERDATA The window's user-specified data.
2219 * If the window is a dialog box, the _offset_ parameter can be one of
2220 * the following values:
2222 * DWLP_DLGPROC The address of the window's dialog box procedure.
2224 * DWLP_MSGRESULT The return value of a message
2225 * that the dialog box procedure processed.
2227 * DWLP_USER Application specific information.
2229 * RETURNS
2231 * If successful, returns the previous value located at _offset_. Otherwise,
2232 * returns 0.
2234 * NOTES
2236 * Extra memory for a window class is specified by a nonzero cbWndExtra
2237 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2238 * time of class creation.
2240 * Using GWL_WNDPROC to set a new window procedure effectively creates
2241 * a window subclass. Use CallWindowProc() in the new windows procedure
2242 * to pass messages to the superclass's window procedure.
2244 * The user data is reserved for use by the application which created
2245 * the window.
2247 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2248 * instead, call the EnableWindow() function to change the window's
2249 * disabled state.
2251 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2252 * SetParent() instead.
2254 * Win95:
2255 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2256 * it sends WM_STYLECHANGING before changing the settings
2257 * and WM_STYLECHANGED afterwards.
2258 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2260 LONG WINAPI SetWindowLongW(
2261 HWND hwnd, /* [in] window to alter */
2262 INT offset, /* [in] offset, in bytes, of location to alter */
2263 LONG newval /* [in] new value of location */
2265 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2269 /*******************************************************************
2270 * GetWindowTextA (USER32.@)
2272 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2274 WCHAR *buffer;
2276 if (WIN_IsCurrentProcess( hwnd ))
2277 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2279 /* when window belongs to other process, don't send a message */
2280 if (nMaxCount <= 0) return 0;
2281 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2282 get_server_window_text( hwnd, buffer, nMaxCount );
2283 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2284 lpString[nMaxCount-1] = 0;
2285 HeapFree( GetProcessHeap(), 0, buffer );
2286 return strlen(lpString);
2290 /*******************************************************************
2291 * InternalGetWindowText (USER32.@)
2293 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2295 WND *win;
2297 if (nMaxCount <= 0) return 0;
2298 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2299 if (win == WND_DESKTOP) lpString[0] = 0;
2300 else if (win != WND_OTHER_PROCESS)
2302 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2303 else lpString[0] = 0;
2304 WIN_ReleasePtr( win );
2306 else
2308 get_server_window_text( hwnd, lpString, nMaxCount );
2310 return strlenW(lpString);
2314 /*******************************************************************
2315 * GetWindowTextW (USER32.@)
2317 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2319 if (WIN_IsCurrentProcess( hwnd ))
2320 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2322 /* when window belongs to other process, don't send a message */
2323 if (nMaxCount <= 0) return 0;
2324 get_server_window_text( hwnd, lpString, nMaxCount );
2325 return strlenW(lpString);
2329 /*******************************************************************
2330 * SetWindowText (USER32.@)
2331 * SetWindowTextA (USER32.@)
2333 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2335 if (is_broadcast(hwnd))
2337 SetLastError( ERROR_INVALID_PARAMETER );
2338 return FALSE;
2340 if (!WIN_IsCurrentProcess( hwnd ))
2342 FIXME( "cannot set text %s of other process window %p\n", debugstr_a(lpString), hwnd );
2343 SetLastError( ERROR_ACCESS_DENIED );
2344 return FALSE;
2346 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2350 /*******************************************************************
2351 * SetWindowTextW (USER32.@)
2353 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2355 if (is_broadcast(hwnd))
2357 SetLastError( ERROR_INVALID_PARAMETER );
2358 return FALSE;
2360 if (!WIN_IsCurrentProcess( hwnd ))
2362 FIXME( "cannot set text %s of other process window %p\n", debugstr_w(lpString), hwnd );
2363 SetLastError( ERROR_ACCESS_DENIED );
2364 return FALSE;
2366 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2370 /*******************************************************************
2371 * GetWindowTextLengthA (USER32.@)
2373 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2375 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2378 /*******************************************************************
2379 * GetWindowTextLengthW (USER32.@)
2381 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2383 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2387 /*******************************************************************
2388 * IsWindow (USER32.@)
2390 BOOL WINAPI IsWindow( HWND hwnd )
2392 WND *ptr;
2393 BOOL ret;
2395 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2396 if (ptr == WND_DESKTOP) return TRUE;
2398 if (ptr != WND_OTHER_PROCESS)
2400 WIN_ReleasePtr( ptr );
2401 return TRUE;
2404 /* check other processes */
2405 SERVER_START_REQ( get_window_info )
2407 req->handle = hwnd;
2408 ret = !wine_server_call_err( req );
2410 SERVER_END_REQ;
2411 return ret;
2415 /***********************************************************************
2416 * GetWindowThreadProcessId (USER32.@)
2418 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2420 WND *ptr;
2421 DWORD tid = 0;
2423 if (!(ptr = WIN_GetPtr( hwnd )))
2425 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2426 return 0;
2429 if (ptr != WND_OTHER_PROCESS && ptr != WND_DESKTOP)
2431 /* got a valid window */
2432 tid = ptr->tid;
2433 if (process) *process = GetCurrentProcessId();
2434 WIN_ReleasePtr( ptr );
2435 return tid;
2438 /* check other processes */
2439 SERVER_START_REQ( get_window_info )
2441 req->handle = hwnd;
2442 if (!wine_server_call_err( req ))
2444 tid = (DWORD)reply->tid;
2445 if (process) *process = (DWORD)reply->pid;
2448 SERVER_END_REQ;
2449 return tid;
2453 /*****************************************************************
2454 * GetParent (USER32.@)
2456 HWND WINAPI GetParent( HWND hwnd )
2458 WND *wndPtr;
2459 HWND retvalue = 0;
2461 if (!(wndPtr = WIN_GetPtr( hwnd )))
2463 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2464 return 0;
2466 if (wndPtr == WND_DESKTOP) return 0;
2467 if (wndPtr == WND_OTHER_PROCESS)
2469 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2470 if (style & (WS_POPUP | WS_CHILD))
2472 SERVER_START_REQ( get_window_tree )
2474 req->handle = hwnd;
2475 if (!wine_server_call_err( req ))
2477 if (style & WS_POPUP) retvalue = reply->owner;
2478 else if (style & WS_CHILD) retvalue = reply->parent;
2481 SERVER_END_REQ;
2484 else
2486 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2487 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2488 WIN_ReleasePtr( wndPtr );
2490 return retvalue;
2494 /*****************************************************************
2495 * GetAncestor (USER32.@)
2497 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2499 WND *win;
2500 HWND *list, ret = 0;
2502 switch(type)
2504 case GA_PARENT:
2505 if (!(win = WIN_GetPtr( hwnd )))
2507 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2508 return 0;
2510 if (win == WND_DESKTOP) return 0;
2511 if (win != WND_OTHER_PROCESS)
2513 ret = win->parent;
2514 WIN_ReleasePtr( win );
2516 else /* need to query the server */
2518 SERVER_START_REQ( get_window_tree )
2520 req->handle = hwnd;
2521 if (!wine_server_call_err( req )) ret = reply->parent;
2523 SERVER_END_REQ;
2525 break;
2527 case GA_ROOT:
2528 if (!(list = list_window_parents( hwnd ))) return 0;
2530 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2531 else
2533 int count = 2;
2534 while (list[count]) count++;
2535 ret = list[count - 2]; /* get the one before the desktop */
2537 HeapFree( GetProcessHeap(), 0, list );
2538 break;
2540 case GA_ROOTOWNER:
2541 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2542 for (;;)
2544 HWND parent = GetParent( ret );
2545 if (!parent) break;
2546 ret = parent;
2548 break;
2550 return ret;
2554 /*****************************************************************
2555 * SetParent (USER32.@)
2557 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2559 WND *wndPtr;
2560 HWND retvalue, full_handle;
2561 BOOL was_visible;
2563 if (is_broadcast(hwnd) || is_broadcast(parent))
2565 SetLastError(ERROR_INVALID_PARAMETER);
2566 return 0;
2569 if (!parent) parent = GetDesktopWindow();
2570 else parent = WIN_GetFullHandle( parent );
2572 if (!IsWindow( parent ))
2574 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2575 return 0;
2578 /* Some applications try to set a child as a parent */
2579 if (IsChild(hwnd, parent))
2581 SetLastError( ERROR_INVALID_PARAMETER );
2582 return 0;
2585 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2586 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2588 hwnd = full_handle;
2590 if (USER_Driver.pSetParent)
2591 return USER_Driver.pSetParent( hwnd, parent );
2593 /* Windows hides the window first, then shows it again
2594 * including the WM_SHOWWINDOW messages and all */
2595 was_visible = ShowWindow( hwnd, SW_HIDE );
2597 if (!IsWindow( parent )) return 0;
2598 if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return 0;
2600 retvalue = wndPtr->parent; /* old parent */
2601 if (parent != retvalue)
2603 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2605 if (parent != GetDesktopWindow()) /* a child window */
2607 if (!(wndPtr->dwStyle & WS_CHILD))
2609 HMENU menu = (HMENU)SetWindowLongPtrW( hwnd, GWLP_ID, 0 );
2610 if (menu) DestroyMenu( menu );
2614 WIN_ReleasePtr( wndPtr );
2616 /* SetParent additionally needs to make hwnd the topmost window
2617 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2618 WM_WINDOWPOSCHANGED notification messages.
2620 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2621 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2622 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2623 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2624 return retvalue;
2628 /*******************************************************************
2629 * IsChild (USER32.@)
2631 BOOL WINAPI IsChild( HWND parent, HWND child )
2633 HWND *list = list_window_parents( child );
2634 int i;
2635 BOOL ret;
2637 if (!list) return FALSE;
2638 parent = WIN_GetFullHandle( parent );
2639 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2640 ret = (list[i] != 0);
2641 HeapFree( GetProcessHeap(), 0, list );
2642 return ret;
2646 /***********************************************************************
2647 * IsWindowVisible (USER32.@)
2649 BOOL WINAPI IsWindowVisible( HWND hwnd )
2651 HWND *list;
2652 BOOL retval;
2653 int i;
2655 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2656 if (!(list = list_window_parents( hwnd ))) return TRUE;
2657 for (i = 0; list[i]; i++)
2658 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2659 retval = !list[i];
2660 HeapFree( GetProcessHeap(), 0, list );
2661 return retval;
2665 /***********************************************************************
2666 * WIN_IsWindowDrawable
2668 * hwnd is drawable when it is visible, all parents are not
2669 * minimized, and it is itself not minimized unless we are
2670 * trying to draw its default class icon.
2672 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2674 HWND *list;
2675 BOOL retval;
2676 int i;
2677 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2679 if (!(style & WS_VISIBLE)) return FALSE;
2680 if ((style & WS_MINIMIZE) && icon && GetClassLongPtrW( hwnd, GCLP_HICON )) return FALSE;
2682 if (!(list = list_window_parents( hwnd ))) return TRUE;
2683 for (i = 0; list[i]; i++)
2684 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2685 break;
2686 retval = !list[i];
2687 HeapFree( GetProcessHeap(), 0, list );
2688 return retval;
2692 /*******************************************************************
2693 * GetTopWindow (USER32.@)
2695 HWND WINAPI GetTopWindow( HWND hwnd )
2697 if (!hwnd) hwnd = GetDesktopWindow();
2698 return GetWindow( hwnd, GW_CHILD );
2702 /*******************************************************************
2703 * GetWindow (USER32.@)
2705 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2707 HWND retval = 0;
2709 if (rel == GW_OWNER) /* this one may be available locally */
2711 WND *wndPtr = WIN_GetPtr( hwnd );
2712 if (!wndPtr)
2714 SetLastError( ERROR_INVALID_HANDLE );
2715 return 0;
2717 if (wndPtr == WND_DESKTOP) return 0;
2718 if (wndPtr != WND_OTHER_PROCESS)
2720 retval = wndPtr->owner;
2721 WIN_ReleasePtr( wndPtr );
2722 return retval;
2724 /* else fall through to server call */
2727 SERVER_START_REQ( get_window_tree )
2729 req->handle = hwnd;
2730 if (!wine_server_call_err( req ))
2732 switch(rel)
2734 case GW_HWNDFIRST:
2735 retval = reply->first_sibling;
2736 break;
2737 case GW_HWNDLAST:
2738 retval = reply->last_sibling;
2739 break;
2740 case GW_HWNDNEXT:
2741 retval = reply->next_sibling;
2742 break;
2743 case GW_HWNDPREV:
2744 retval = reply->prev_sibling;
2745 break;
2746 case GW_OWNER:
2747 retval = reply->owner;
2748 break;
2749 case GW_CHILD:
2750 retval = reply->first_child;
2751 break;
2755 SERVER_END_REQ;
2756 return retval;
2760 /*******************************************************************
2761 * ShowOwnedPopups (USER32.@)
2763 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2765 int count = 0;
2766 WND *pWnd;
2767 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2769 if (!win_array) return TRUE;
2771 while (win_array[count]) count++;
2772 while (--count >= 0)
2774 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2775 if (!(pWnd = WIN_GetPtr( win_array[count] ))) continue;
2776 if (pWnd == WND_OTHER_PROCESS) continue;
2778 if (pWnd->dwStyle & WS_POPUP)
2780 if (fShow)
2782 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2784 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2785 WIN_ReleasePtr( pWnd );
2786 /* In Windows, ShowOwnedPopups(TRUE) generates
2787 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2788 * regardless of the state of the owner
2790 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2791 continue;
2794 else
2796 if (pWnd->dwStyle & WS_VISIBLE)
2798 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2799 WIN_ReleasePtr( pWnd );
2800 /* In Windows, ShowOwnedPopups(FALSE) generates
2801 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2802 * regardless of the state of the owner
2804 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2805 continue;
2809 WIN_ReleasePtr( pWnd );
2811 HeapFree( GetProcessHeap(), 0, win_array );
2812 return TRUE;
2816 /*******************************************************************
2817 * GetLastActivePopup (USER32.@)
2819 HWND WINAPI GetLastActivePopup( HWND hwnd )
2821 HWND retval = hwnd;
2823 SERVER_START_REQ( get_window_info )
2825 req->handle = hwnd;
2826 if (!wine_server_call_err( req )) retval = reply->last_active;
2828 SERVER_END_REQ;
2829 return retval;
2833 /*******************************************************************
2834 * WIN_ListChildren
2836 * Build an array of the children of a given window. The array must be
2837 * freed with HeapFree. Returns NULL when no windows are found.
2839 HWND *WIN_ListChildren( HWND hwnd )
2841 return list_window_children( hwnd, 0, 0 );
2845 /*******************************************************************
2846 * EnumWindows (USER32.@)
2848 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2850 HWND *list;
2851 BOOL ret = TRUE;
2852 int i;
2854 USER_CheckNotLock();
2856 /* We have to build a list of all windows first, to avoid */
2857 /* unpleasant side-effects, for instance if the callback */
2858 /* function changes the Z-order of the windows. */
2860 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2862 /* Now call the callback function for every window */
2864 for (i = 0; list[i]; i++)
2866 /* Make sure that the window still exists */
2867 if (!IsWindow( list[i] )) continue;
2868 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2870 HeapFree( GetProcessHeap(), 0, list );
2871 return ret;
2875 /**********************************************************************
2876 * EnumThreadWindows (USER32.@)
2878 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2880 HWND *list;
2881 int i;
2883 USER_CheckNotLock();
2885 if (!(list = list_window_children( GetDesktopWindow(), 0, id ))) return TRUE;
2887 /* Now call the callback function for every window */
2889 for (i = 0; list[i]; i++)
2890 if (!func( list[i], lParam )) break;
2891 HeapFree( GetProcessHeap(), 0, list );
2892 return TRUE;
2896 /**********************************************************************
2897 * WIN_EnumChildWindows
2899 * Helper function for EnumChildWindows().
2901 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2903 HWND *childList;
2904 BOOL ret = FALSE;
2906 for ( ; *list; list++)
2908 /* Make sure that the window still exists */
2909 if (!IsWindow( *list )) continue;
2910 /* skip owned windows */
2911 if (GetWindow( *list, GW_OWNER )) continue;
2912 /* Build children list first */
2913 childList = WIN_ListChildren( *list );
2915 ret = func( *list, lParam );
2917 if (childList)
2919 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2920 HeapFree( GetProcessHeap(), 0, childList );
2922 if (!ret) return FALSE;
2924 return TRUE;
2928 /**********************************************************************
2929 * EnumChildWindows (USER32.@)
2931 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2933 HWND *list;
2935 USER_CheckNotLock();
2937 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2938 WIN_EnumChildWindows( list, func, lParam );
2939 HeapFree( GetProcessHeap(), 0, list );
2940 return TRUE;
2944 /*******************************************************************
2945 * AnyPopup (USER.52)
2947 BOOL16 WINAPI AnyPopup16(void)
2949 return AnyPopup();
2953 /*******************************************************************
2954 * AnyPopup (USER32.@)
2956 BOOL WINAPI AnyPopup(void)
2958 int i;
2959 BOOL retvalue;
2960 HWND *list = WIN_ListChildren( GetDesktopWindow() );
2962 if (!list) return FALSE;
2963 for (i = 0; list[i]; i++)
2965 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
2967 retvalue = (list[i] != 0);
2968 HeapFree( GetProcessHeap(), 0, list );
2969 return retvalue;
2973 /*******************************************************************
2974 * FlashWindow (USER32.@)
2976 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2978 WND *wndPtr;
2980 TRACE("%p\n", hWnd);
2982 if (IsIconic( hWnd ))
2984 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
2986 wndPtr = WIN_GetPtr(hWnd);
2987 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
2988 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2990 wndPtr->flags |= WIN_NCACTIVATED;
2992 else
2994 wndPtr->flags &= ~WIN_NCACTIVATED;
2996 WIN_ReleasePtr( wndPtr );
2997 return TRUE;
2999 else
3001 WPARAM wparam;
3003 wndPtr = WIN_GetPtr(hWnd);
3004 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
3005 hWnd = wndPtr->hwndSelf; /* make it a full handle */
3007 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3008 else wparam = (hWnd == GetForegroundWindow());
3010 WIN_ReleasePtr( wndPtr );
3011 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3012 return wparam;
3016 /*******************************************************************
3017 * FlashWindowEx (USER32.@)
3019 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
3021 FIXME("%p\n", pfwi);
3022 return TRUE;
3025 /*******************************************************************
3026 * GetWindowContextHelpId (USER32.@)
3028 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3030 DWORD retval;
3031 WND *wnd = WIN_GetPtr( hwnd );
3032 if (!wnd || wnd == WND_DESKTOP) return 0;
3033 if (wnd == WND_OTHER_PROCESS)
3035 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3036 return 0;
3038 retval = wnd->helpContext;
3039 WIN_ReleasePtr( wnd );
3040 return retval;
3044 /*******************************************************************
3045 * SetWindowContextHelpId (USER32.@)
3047 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3049 WND *wnd = WIN_GetPtr( hwnd );
3050 if (!wnd || wnd == WND_DESKTOP) return FALSE;
3051 if (wnd == WND_OTHER_PROCESS)
3053 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3054 return 0;
3056 wnd->helpContext = id;
3057 WIN_ReleasePtr( wnd );
3058 return TRUE;
3062 /*******************************************************************
3063 * DragDetect (USER32.@)
3065 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3067 MSG msg;
3068 RECT rect;
3070 rect.left = pt.x - wDragWidth;
3071 rect.right = pt.x + wDragWidth;
3073 rect.top = pt.y - wDragHeight;
3074 rect.bottom = pt.y + wDragHeight;
3076 SetCapture(hWnd);
3078 while(1)
3080 while (PeekMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ))
3082 if( msg.message == WM_LBUTTONUP )
3084 ReleaseCapture();
3085 return 0;
3087 if( msg.message == WM_MOUSEMOVE )
3089 POINT tmp;
3090 tmp.x = LOWORD(msg.lParam);
3091 tmp.y = HIWORD(msg.lParam);
3092 if( !PtInRect( &rect, tmp ))
3094 ReleaseCapture();
3095 return 1;
3099 WaitMessage();
3101 return 0;
3104 /******************************************************************************
3105 * GetWindowModuleFileNameA (USER32.@)
3107 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3109 FIXME("GetWindowModuleFileNameA(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3110 hwnd, lpszFileName, cchFileNameMax);
3111 return 0;
3114 /******************************************************************************
3115 * GetWindowModuleFileNameW (USER32.@)
3117 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR lpszFileName, UINT cchFileNameMax)
3119 FIXME("GetWindowModuleFileNameW(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3120 hwnd, lpszFileName, cchFileNameMax);
3121 return 0;
3124 /******************************************************************************
3125 * GetWindowInfo (USER32.@)
3127 * Note: tests show that Windows doesn't check cbSize of the structure.
3129 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3131 if (!pwi) return FALSE;
3132 if (!IsWindow(hwnd)) return FALSE;
3134 GetWindowRect(hwnd, &pwi->rcWindow);
3135 GetClientRect(hwnd, &pwi->rcClient);
3136 /* translate to screen coordinates */
3137 MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3139 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3140 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3141 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3143 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3144 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3146 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3147 pwi->wCreatorVersion = 0x0400;
3149 return TRUE;
3152 /******************************************************************************
3153 * SwitchDesktop (USER32.@)
3155 * NOTES: Sets the current input or interactive desktop.
3157 BOOL WINAPI SwitchDesktop( HDESK hDesktop)
3159 FIXME("SwitchDesktop(hwnd %p) stub!\n", hDesktop);
3160 return TRUE;