Get rid of the client-side window timer structures.
[wine/wine-kai.git] / windows / win.c
blob338a7488475f54c0fd6c1e91f7c032e9a8c3e167
1 /*
2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "config.h"
22 #include "wine/port.h"
24 #include <assert.h>
25 #include <stdarg.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include "windef.h"
29 #include "winbase.h"
30 #include "wine/winbase16.h"
31 #include "wine/winuser16.h"
32 #include "wownt32.h"
33 #include "wine/server.h"
34 #include "wine/unicode.h"
35 #include "win.h"
36 #include "user.h"
37 #include "dce.h"
38 #include "controls.h"
39 #include "cursoricon.h"
40 #include "message.h"
41 #include "winpos.h"
42 #include "winerror.h"
43 #include "wine/debug.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(win);
46 WINE_DECLARE_DEBUG_CHANNEL(msg);
48 #define NB_USER_HANDLES ((LAST_USER_HANDLE - FIRST_USER_HANDLE + 1) >> 1)
49 #define USER_HANDLE_TO_INDEX(hwnd) ((LOWORD(hwnd) - FIRST_USER_HANDLE) >> 1)
51 /**********************************************************************/
53 /* Desktop window */
54 static WND *pWndDesktop = NULL;
56 static WORD wDragWidth = 4;
57 static WORD wDragHeight= 3;
59 static void *user_handles[NB_USER_HANDLES];
61 /***********************************************************************
62 * create_window_handle
64 * Create a window handle with the server.
66 static WND *create_window_handle( HWND parent, HWND owner, ATOM atom,
67 HINSTANCE instance, WINDOWPROCTYPE type )
69 WORD index;
70 WND *win;
71 struct tagCLASS *class = NULL;
72 user_handle_t handle = 0;
73 int extra_bytes = 0;
75 /* if 16-bit instance, map to module handle */
76 if (instance && !HIWORD(instance))
77 instance = HINSTANCE_32(GetExePtr(HINSTANCE_16(instance)));
79 SERVER_START_REQ( create_window )
81 req->parent = parent;
82 req->owner = owner;
83 req->atom = atom;
84 req->instance = instance;
85 if (!wine_server_call_err( req ))
87 handle = reply->handle;
88 extra_bytes = reply->extra;
89 class = reply->class_ptr;
92 SERVER_END_REQ;
94 if (!handle)
96 WARN( "error %ld creating window\n", GetLastError() );
97 return NULL;
100 if (!(win = HeapAlloc( GetProcessHeap(), 0, sizeof(WND) + extra_bytes - sizeof(win->wExtra) )))
102 SERVER_START_REQ( destroy_window )
104 req->handle = handle;
105 wine_server_call( req );
107 SERVER_END_REQ;
108 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
109 return NULL;
112 USER_Lock();
114 index = USER_HANDLE_TO_INDEX(handle);
115 assert( index < NB_USER_HANDLES );
116 user_handles[index] = win;
117 win->hwndSelf = handle;
118 win->dwMagic = WND_MAGIC;
119 win->irefCount = 1;
120 win->cbWndExtra = extra_bytes;
121 memset( win->wExtra, 0, extra_bytes );
122 CLASS_AddWindow( class, win, type );
123 return win;
127 /***********************************************************************
128 * free_window_handle
130 * Free a window handle.
132 static WND *free_window_handle( HWND hwnd )
134 WND *ptr;
135 WORD index = USER_HANDLE_TO_INDEX(hwnd);
137 if (index >= NB_USER_HANDLES) return NULL;
138 USER_Lock();
139 if ((ptr = user_handles[index]))
141 SERVER_START_REQ( destroy_window )
143 req->handle = hwnd;
144 if (!wine_server_call_err( req ))
145 user_handles[index] = NULL;
146 else
147 ptr = NULL;
149 SERVER_END_REQ;
151 USER_Unlock();
152 if (ptr) HeapFree( GetProcessHeap(), 0, ptr );
153 return ptr;
157 /*******************************************************************
158 * list_window_children
160 * Build an array of the children of a given window. The array must be
161 * freed with HeapFree. Returns NULL when no windows are found.
163 static HWND *list_window_children( HWND hwnd, ATOM atom, DWORD tid )
165 HWND *list;
166 int size = 32;
168 for (;;)
170 int count = 0;
172 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
174 SERVER_START_REQ( get_window_children )
176 req->parent = hwnd;
177 req->atom = atom;
178 req->tid = tid;
179 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
180 if (!wine_server_call( req )) count = reply->count;
182 SERVER_END_REQ;
183 if (count && count < size)
185 list[count] = 0;
186 return list;
188 HeapFree( GetProcessHeap(), 0, list );
189 if (!count) break;
190 size = count + 1; /* restart with a large enough buffer */
192 return NULL;
196 /*******************************************************************
197 * send_parent_notify
199 static void send_parent_notify( HWND hwnd, UINT msg )
201 if ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_CHILD | WS_POPUP)) == WS_CHILD &&
202 !(GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY))
203 SendMessageW( GetParent(hwnd), WM_PARENTNOTIFY,
204 MAKEWPARAM( msg, GetWindowLongPtrW( hwnd, GWLP_ID )), (LPARAM)hwnd );
208 /*******************************************************************
209 * get_server_window_text
211 * Retrieve the window text from the server.
213 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
215 size_t len = 0;
217 SERVER_START_REQ( get_window_text )
219 req->handle = hwnd;
220 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
221 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
223 SERVER_END_REQ;
224 text[len / sizeof(WCHAR)] = 0;
228 /***********************************************************************
229 * WIN_GetPtr
231 * Return a pointer to the WND structure if local to the process,
232 * or WND_OTHER_PROCESS if handle may be valid in other process.
233 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
235 WND *WIN_GetPtr( HWND hwnd )
237 WND * ptr;
238 WORD index = USER_HANDLE_TO_INDEX(hwnd);
240 if (index >= NB_USER_HANDLES) return NULL;
242 USER_Lock();
243 if ((ptr = user_handles[index]))
245 if (ptr->dwMagic == WND_MAGIC && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
246 return ptr;
247 ptr = NULL;
249 else ptr = WND_OTHER_PROCESS;
250 USER_Unlock();
251 return ptr;
255 /***********************************************************************
256 * WIN_IsCurrentProcess
258 * Check whether a given window belongs to the current process (and return the full handle).
260 HWND WIN_IsCurrentProcess( HWND hwnd )
262 WND *ptr;
263 HWND ret;
265 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS) return 0;
266 ret = ptr->hwndSelf;
267 WIN_ReleasePtr( ptr );
268 return ret;
272 /***********************************************************************
273 * WIN_IsCurrentThread
275 * Check whether a given window belongs to the current thread (and return the full handle).
277 HWND WIN_IsCurrentThread( HWND hwnd )
279 WND *ptr;
280 HWND ret = 0;
282 if ((ptr = WIN_GetPtr( hwnd )) && ptr != WND_OTHER_PROCESS)
284 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
285 WIN_ReleasePtr( ptr );
287 return ret;
291 /***********************************************************************
292 * WIN_Handle32
294 * Convert a 16-bit window handle to a full 32-bit handle.
296 HWND WIN_Handle32( HWND16 hwnd16 )
298 WND *ptr;
299 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
301 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
302 /* do sign extension for -2 and -3 */
303 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
305 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
307 if (ptr != WND_OTHER_PROCESS)
309 hwnd = ptr->hwndSelf;
310 WIN_ReleasePtr( ptr );
312 else /* may belong to another process */
314 SERVER_START_REQ( get_window_info )
316 req->handle = hwnd;
317 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
319 SERVER_END_REQ;
321 return hwnd;
325 /***********************************************************************
326 * WIN_FindWndPtr
328 * Return a pointer to the WND structure corresponding to a HWND.
330 WND * WIN_FindWndPtr( HWND hwnd )
332 WND * ptr;
334 if (!hwnd) return NULL;
336 if ((ptr = WIN_GetPtr( hwnd )))
338 if (ptr != WND_OTHER_PROCESS)
340 /* increment destruction monitoring */
341 ptr->irefCount++;
342 return ptr;
344 if (IsWindow( hwnd )) /* check other processes */
346 ERR( "window %p belongs to other process\n", hwnd );
347 /* DbgBreakPoint(); */
350 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
351 return NULL;
355 /***********************************************************************
356 * WIN_ReleaseWndPtr
358 * Release the pointer to the WND structure.
360 void WIN_ReleaseWndPtr(WND *wndPtr)
362 if(!wndPtr) return;
364 /* Decrement destruction monitoring value */
365 wndPtr->irefCount--;
366 /* Check if it's time to release the memory */
367 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
369 /* Release memory */
370 free_window_handle( wndPtr->hwndSelf );
372 else if(wndPtr->irefCount < 0)
374 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
375 ERR("forgot a Lock on %p somewhere\n",wndPtr);
377 /* unlock all WND structures for thread safeness */
378 USER_Unlock();
382 /***********************************************************************
383 * WIN_UnlinkWindow
385 * Remove a window from the siblings linked list.
387 void WIN_UnlinkWindow( HWND hwnd )
389 WIN_LinkWindow( hwnd, 0, 0 );
393 /***********************************************************************
394 * WIN_LinkWindow
396 * Insert a window into the siblings linked list.
397 * The window is inserted after the specified window, which can also
398 * be specified as HWND_TOP or HWND_BOTTOM.
399 * If parent is 0, window is unlinked from the tree.
401 void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
403 WND *wndPtr = WIN_GetPtr( hwnd );
405 if (!wndPtr) return;
406 if (wndPtr == WND_OTHER_PROCESS)
408 if (IsWindow(hwnd)) ERR(" cannot link other process window %p\n", hwnd );
409 return;
412 SERVER_START_REQ( link_window )
414 req->handle = hwnd;
415 req->parent = parent;
416 req->previous = hwndInsertAfter;
417 if (!wine_server_call( req ))
419 if (reply->full_parent) wndPtr->parent = reply->full_parent;
423 SERVER_END_REQ;
424 WIN_ReleasePtr( wndPtr );
428 /***********************************************************************
429 * WIN_SetOwner
431 * Change the owner of a window.
433 HWND WIN_SetOwner( HWND hwnd, HWND owner )
435 WND *win = WIN_GetPtr( hwnd );
436 HWND ret = 0;
438 if (!win) return 0;
439 if (win == WND_OTHER_PROCESS)
441 if (IsWindow(hwnd)) ERR( "cannot set owner %p on other process window %p\n", owner, hwnd );
442 return 0;
444 SERVER_START_REQ( set_window_owner )
446 req->handle = hwnd;
447 req->owner = owner;
448 if (!wine_server_call( req ))
450 win->owner = reply->full_owner;
451 ret = reply->prev_owner;
454 SERVER_END_REQ;
455 WIN_ReleasePtr( win );
456 return ret;
460 /***********************************************************************
461 * WIN_SetStyle
463 * Change the style of a window.
465 LONG WIN_SetStyle( HWND hwnd, LONG style )
467 BOOL ok;
468 LONG ret = 0;
469 WND *win = WIN_GetPtr( hwnd );
471 if (!win) return 0;
472 if (win == WND_OTHER_PROCESS)
474 if (IsWindow(hwnd))
475 ERR( "cannot set style %lx on other process window %p\n", style, hwnd );
476 return 0;
478 if (style == win->dwStyle)
480 WIN_ReleasePtr( win );
481 return style;
483 SERVER_START_REQ( set_window_info )
485 req->handle = hwnd;
486 req->flags = SET_WIN_STYLE;
487 req->style = style;
488 req->extra_offset = -1;
489 if ((ok = !wine_server_call( req )))
491 ret = reply->old_style;
492 win->dwStyle = style;
495 SERVER_END_REQ;
496 WIN_ReleasePtr( win );
497 if (ok && USER_Driver.pSetWindowStyle) USER_Driver.pSetWindowStyle( hwnd, ret );
498 return ret;
502 /***********************************************************************
503 * WIN_SetExStyle
505 * Change the extended style of a window.
507 LONG WIN_SetExStyle( HWND hwnd, LONG style )
509 LONG ret = 0;
510 WND *win = WIN_GetPtr( hwnd );
512 if (!win) return 0;
513 if (win == WND_OTHER_PROCESS)
515 if (IsWindow(hwnd))
516 ERR( "cannot set exstyle %lx on other process window %p\n", style, hwnd );
517 return 0;
519 if (style == win->dwExStyle)
521 WIN_ReleasePtr( win );
522 return style;
524 SERVER_START_REQ( set_window_info )
526 req->handle = hwnd;
527 req->flags = SET_WIN_EXSTYLE;
528 req->ex_style = style;
529 req->extra_offset = -1;
530 if (!wine_server_call( req ))
532 ret = reply->old_ex_style;
533 win->dwExStyle = style;
536 SERVER_END_REQ;
537 WIN_ReleasePtr( win );
538 return ret;
542 /***********************************************************************
543 * WIN_GetRectangles
545 * Get the window and client rectangles.
547 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
549 WND *win = WIN_GetPtr( hwnd );
550 BOOL ret = TRUE;
552 if (!win) return FALSE;
553 if (win == WND_OTHER_PROCESS)
555 SERVER_START_REQ( get_window_rectangles )
557 req->handle = hwnd;
558 if ((ret = !wine_server_call( req )))
560 if (rectWindow)
562 rectWindow->left = reply->window.left;
563 rectWindow->top = reply->window.top;
564 rectWindow->right = reply->window.right;
565 rectWindow->bottom = reply->window.bottom;
567 if (rectClient)
569 rectClient->left = reply->client.left;
570 rectClient->top = reply->client.top;
571 rectClient->right = reply->client.right;
572 rectClient->bottom = reply->client.bottom;
576 SERVER_END_REQ;
578 else
580 if (rectWindow) *rectWindow = win->rectWindow;
581 if (rectClient) *rectClient = win->rectClient;
582 WIN_ReleasePtr( win );
584 return ret;
588 /***********************************************************************
589 * WIN_DestroyWindow
591 * Destroy storage associated to a window. "Internals" p.358
593 LRESULT WIN_DestroyWindow( HWND hwnd )
595 WND *wndPtr;
596 HWND *list;
598 TRACE("%p\n", hwnd );
600 if (!(hwnd = WIN_IsCurrentThread( hwnd )))
602 ERR( "window doesn't belong to current thread\n" );
603 return 0;
606 /* free child windows */
607 if ((list = WIN_ListChildren( hwnd )))
609 int i;
610 for (i = 0; list[i]; i++)
612 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
613 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
615 HeapFree( GetProcessHeap(), 0, list );
619 * Clear the update region to make sure no WM_PAINT messages will be
620 * generated for this window while processing the WM_NCDESTROY.
622 RedrawWindow( hwnd, NULL, 0,
623 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
626 * Send the WM_NCDESTROY to the window being destroyed.
628 SendMessageA( hwnd, WM_NCDESTROY, 0, 0);
630 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
632 WINPOS_CheckInternalPos( hwnd );
633 if( hwnd == GetCapture()) ReleaseCapture();
635 /* free resources associated with the window */
637 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
639 if (!(wndPtr->dwStyle & WS_CHILD))
641 HMENU menu = (HMENU)SetWindowLongPtrW( hwnd, GWLP_ID, 0 );
642 if (menu) DestroyMenu( menu );
644 if (wndPtr->hSysMenu)
646 DestroyMenu( wndPtr->hSysMenu );
647 wndPtr->hSysMenu = 0;
649 DCE_FreeWindowDCE( hwnd ); /* Always do this to catch orphaned DCs */
650 if (USER_Driver.pDestroyWindow) USER_Driver.pDestroyWindow( hwnd );
651 wndPtr->class = NULL;
652 wndPtr->dwMagic = 0; /* Mark it as invalid */
653 WIN_ReleaseWndPtr( wndPtr );
654 return 0;
657 /***********************************************************************
658 * WIN_DestroyThreadWindows
660 * Destroy all children of 'wnd' owned by the current thread.
661 * Return TRUE if something was done.
663 void WIN_DestroyThreadWindows( HWND hwnd )
665 HWND *list;
666 int i;
668 if (!(list = WIN_ListChildren( hwnd ))) return;
669 for (i = 0; list[i]; i++)
671 if (WIN_IsCurrentThread( list[i] ))
672 DestroyWindow( list[i] );
673 else
674 WIN_DestroyThreadWindows( list[i] );
676 HeapFree( GetProcessHeap(), 0, list );
679 /***********************************************************************
680 * WIN_CreateDesktopWindow
682 * Create the desktop window.
684 BOOL WIN_CreateDesktopWindow(void)
686 HWND hwndDesktop;
687 CREATESTRUCTA cs;
689 TRACE("Creating desktop window\n");
691 if (!WINPOS_CreateInternalPosAtom()) return FALSE;
693 pWndDesktop = create_window_handle( 0, 0, LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W );
694 if (!pWndDesktop) return FALSE;
695 hwndDesktop = pWndDesktop->hwndSelf;
697 pWndDesktop->tid = 0; /* nobody owns the desktop */
698 pWndDesktop->parent = 0;
699 pWndDesktop->owner = 0;
700 pWndDesktop->text = NULL;
701 pWndDesktop->hrgnUpdate = 0;
702 pWndDesktop->pVScroll = NULL;
703 pWndDesktop->pHScroll = NULL;
704 pWndDesktop->helpContext = 0;
705 pWndDesktop->flags = 0;
706 pWndDesktop->hSysMenu = 0;
708 cs.lpCreateParams = NULL;
709 cs.hInstance = 0;
710 cs.hMenu = 0;
711 cs.hwndParent = 0;
712 cs.x = 0;
713 cs.y = 0;
714 cs.cx = GetSystemMetrics( SM_CXSCREEN );
715 cs.cy = GetSystemMetrics( SM_CYSCREEN );
716 cs.style = pWndDesktop->dwStyle;
717 cs.dwExStyle = pWndDesktop->dwExStyle;
718 cs.lpszName = NULL;
719 cs.lpszClass = DESKTOP_CLASS_ATOM;
721 SERVER_START_REQ( set_window_info )
723 req->handle = hwndDesktop;
724 req->flags = 0; /* don't set anything, just retrieve */
725 req->extra_offset = -1;
726 wine_server_call( req );
727 pWndDesktop->dwStyle = reply->old_style;
728 pWndDesktop->dwExStyle = reply->old_ex_style;
729 pWndDesktop->hInstance = (HINSTANCE)reply->old_instance;
730 pWndDesktop->userdata = (ULONG_PTR)reply->old_user_data;
731 pWndDesktop->wIDmenu = reply->old_id;
733 SERVER_END_REQ;
735 if (!USER_Driver.pCreateWindow || !USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE ))
737 WIN_ReleaseWndPtr( pWndDesktop );
738 return FALSE;
741 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
742 WIN_ReleaseWndPtr( pWndDesktop );
743 return TRUE;
747 /***********************************************************************
748 * WIN_FixCoordinates
750 * Fix the coordinates - Helper for WIN_CreateWindowEx.
751 * returns default show mode in sw.
752 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
754 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
756 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
757 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
759 if (cs->style & (WS_CHILD | WS_POPUP))
761 if (cs->dwExStyle & WS_EX_MDICHILD)
763 POINT pos[2];
765 MDI_CalcDefaultChildPos(cs->hwndParent, -1, pos, 0);
767 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
769 cs->x = pos[0].x;
770 cs->y = pos[0].y;
772 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16 || !cs->cx)
773 cs->cx = pos[1].x;
774 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16 || !cs->cy)
775 cs->cy = pos[1].y;
777 else
779 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
780 cs->x = cs->y = 0;
781 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
782 cs->cx = cs->cy = 0;
785 else /* overlapped window */
787 STARTUPINFOA info;
789 GetStartupInfoA( &info );
791 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
793 /* Never believe Microsoft's documentation... CreateWindowEx doc says
794 * that if an overlapped window is created with WS_VISIBLE style bit
795 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
796 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
797 * reveals that
799 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
800 * 2) it does not ignore the y parameter as the docs claim; instead, it
801 * uses it as second parameter to ShowWindow() unless y is either
802 * CW_USEDEFAULT or CW_USEDEFAULT16.
804 * The fact that we didn't do 2) caused bogus windows pop up when wine
805 * was running apps that were using this obscure feature. Example -
806 * calc.exe that comes with Win98 (only Win98, it's different from
807 * the one that comes with Win95 and NT)
809 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
810 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
811 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
814 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
816 if (info.dwFlags & STARTF_USESIZE)
818 cs->cx = info.dwXSize;
819 cs->cy = info.dwYSize;
821 else /* if no other hint from the app, pick 3/4 of the screen real estate */
823 RECT r;
824 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
825 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
826 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
831 else
833 /* neither x nor cx are default. Check the y values .
834 * In the trace we see Outlook and Outlook Express using
835 * cy set to CW_USEDEFAULT when opening the address book.
837 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16) {
838 RECT r;
839 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
840 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
841 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
846 /***********************************************************************
847 * dump_window_styles
849 static void dump_window_styles( DWORD style, DWORD exstyle )
851 TRACE( "style:" );
852 if(style & WS_POPUP) TRACE(" WS_POPUP");
853 if(style & WS_CHILD) TRACE(" WS_CHILD");
854 if(style & WS_MINIMIZE) TRACE(" WS_MINIMIZE");
855 if(style & WS_VISIBLE) TRACE(" WS_VISIBLE");
856 if(style & WS_DISABLED) TRACE(" WS_DISABLED");
857 if(style & WS_CLIPSIBLINGS) TRACE(" WS_CLIPSIBLINGS");
858 if(style & WS_CLIPCHILDREN) TRACE(" WS_CLIPCHILDREN");
859 if(style & WS_MAXIMIZE) TRACE(" WS_MAXIMIZE");
860 if((style & WS_CAPTION) == WS_CAPTION) TRACE(" WS_CAPTION");
861 else
863 if(style & WS_BORDER) TRACE(" WS_BORDER");
864 if(style & WS_DLGFRAME) TRACE(" WS_DLGFRAME");
866 if(style & WS_VSCROLL) TRACE(" WS_VSCROLL");
867 if(style & WS_HSCROLL) TRACE(" WS_HSCROLL");
868 if(style & WS_SYSMENU) TRACE(" WS_SYSMENU");
869 if(style & WS_THICKFRAME) TRACE(" WS_THICKFRAME");
870 if(style & WS_GROUP) TRACE(" WS_GROUP");
871 if(style & WS_TABSTOP) TRACE(" WS_TABSTOP");
872 if(style & WS_MINIMIZEBOX) TRACE(" WS_MINIMIZEBOX");
873 if(style & WS_MAXIMIZEBOX) TRACE(" WS_MAXIMIZEBOX");
875 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
876 #define DUMPED_STYLES \
877 (WS_POPUP | \
878 WS_CHILD | \
879 WS_MINIMIZE | \
880 WS_VISIBLE | \
881 WS_DISABLED | \
882 WS_CLIPSIBLINGS | \
883 WS_CLIPCHILDREN | \
884 WS_MAXIMIZE | \
885 WS_BORDER | \
886 WS_DLGFRAME | \
887 WS_VSCROLL | \
888 WS_HSCROLL | \
889 WS_SYSMENU | \
890 WS_THICKFRAME | \
891 WS_GROUP | \
892 WS_TABSTOP | \
893 WS_MINIMIZEBOX | \
894 WS_MAXIMIZEBOX)
896 if(style & ~DUMPED_STYLES) TRACE(" %08lx", style & ~DUMPED_STYLES);
897 TRACE("\n");
898 #undef DUMPED_STYLES
900 TRACE( "exstyle:" );
901 if(exstyle & WS_EX_DLGMODALFRAME) TRACE(" WS_EX_DLGMODALFRAME");
902 if(exstyle & WS_EX_DRAGDETECT) TRACE(" WS_EX_DRAGDETECT");
903 if(exstyle & WS_EX_NOPARENTNOTIFY) TRACE(" WS_EX_NOPARENTNOTIFY");
904 if(exstyle & WS_EX_TOPMOST) TRACE(" WS_EX_TOPMOST");
905 if(exstyle & WS_EX_ACCEPTFILES) TRACE(" WS_EX_ACCEPTFILES");
906 if(exstyle & WS_EX_TRANSPARENT) TRACE(" WS_EX_TRANSPARENT");
907 if(exstyle & WS_EX_MDICHILD) TRACE(" WS_EX_MDICHILD");
908 if(exstyle & WS_EX_TOOLWINDOW) TRACE(" WS_EX_TOOLWINDOW");
909 if(exstyle & WS_EX_WINDOWEDGE) TRACE(" WS_EX_WINDOWEDGE");
910 if(exstyle & WS_EX_CLIENTEDGE) TRACE(" WS_EX_CLIENTEDGE");
911 if(exstyle & WS_EX_CONTEXTHELP) TRACE(" WS_EX_CONTEXTHELP");
912 if(exstyle & WS_EX_RIGHT) TRACE(" WS_EX_RIGHT");
913 if(exstyle & WS_EX_RTLREADING) TRACE(" WS_EX_RTLREADING");
914 if(exstyle & WS_EX_LEFTSCROLLBAR) TRACE(" WS_EX_LEFTSCROLLBAR");
915 if(exstyle & WS_EX_CONTROLPARENT) TRACE(" WS_EX_CONTROLPARENT");
916 if(exstyle & WS_EX_STATICEDGE) TRACE(" WS_EX_STATICEDGE");
917 if(exstyle & WS_EX_APPWINDOW) TRACE(" WS_EX_APPWINDOW");
918 if(exstyle & WS_EX_LAYERED) TRACE(" WS_EX_LAYERED");
920 #define DUMPED_EX_STYLES \
921 (WS_EX_DLGMODALFRAME | \
922 WS_EX_DRAGDETECT | \
923 WS_EX_NOPARENTNOTIFY | \
924 WS_EX_TOPMOST | \
925 WS_EX_ACCEPTFILES | \
926 WS_EX_TRANSPARENT | \
927 WS_EX_MDICHILD | \
928 WS_EX_TOOLWINDOW | \
929 WS_EX_WINDOWEDGE | \
930 WS_EX_CLIENTEDGE | \
931 WS_EX_CONTEXTHELP | \
932 WS_EX_RIGHT | \
933 WS_EX_RTLREADING | \
934 WS_EX_LEFTSCROLLBAR | \
935 WS_EX_CONTROLPARENT | \
936 WS_EX_STATICEDGE | \
937 WS_EX_APPWINDOW | \
938 WS_EX_LAYERED)
940 if(exstyle & ~DUMPED_EX_STYLES) TRACE(" %08lx", exstyle & ~DUMPED_EX_STYLES);
941 TRACE("\n");
942 #undef DUMPED_EX_STYLES
946 /***********************************************************************
947 * WIN_CreateWindowEx
949 * Implementation of CreateWindowEx().
951 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
952 WINDOWPROCTYPE type )
954 INT sw = SW_SHOW;
955 WND *wndPtr;
956 HWND hwnd, parent, owner, top_child = 0;
957 BOOL unicode = (type == WIN_PROC_32W);
959 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
960 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
961 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszClass) : debugstr_a(cs->lpszClass),
962 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
963 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
965 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
967 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
968 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
970 /* Fix the styles for MDI children */
971 if (cs->dwExStyle & WS_EX_MDICHILD)
973 MDICREATESTRUCTA mdi_cs;
974 UINT flags = 0;
976 wndPtr = WIN_GetPtr(cs->hwndParent);
977 if (wndPtr && wndPtr != WND_OTHER_PROCESS)
979 flags = wndPtr->flags;
980 WIN_ReleasePtr(wndPtr);
983 if (!(flags & WIN_ISMDICLIENT))
985 WARN("WS_EX_MDICHILD, but parent %p is not MDIClient\n", cs->hwndParent);
986 return 0;
989 /* cs->lpCreateParams of WM_[NC]CREATE is different for MDI children.
990 * MDICREATESTRUCT members have the originally passed values.
992 * Note: we rely on the fact that MDICREATESTRUCTA and MDICREATESTRUCTW
993 * have the same layout.
995 mdi_cs.szClass = cs->lpszClass;
996 mdi_cs.szTitle = cs->lpszName;
997 mdi_cs.hOwner = cs->hInstance;
998 mdi_cs.x = cs->x;
999 mdi_cs.y = cs->y;
1000 mdi_cs.cx = cs->cx;
1001 mdi_cs.cy = cs->cy;
1002 mdi_cs.style = cs->style;
1003 mdi_cs.lParam = (LPARAM)cs->lpCreateParams;
1005 cs->lpCreateParams = (LPVOID)&mdi_cs;
1007 if (GetWindowLongW(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
1009 if (cs->style & WS_POPUP)
1011 TRACE("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n");
1012 return 0;
1014 cs->style |= WS_CHILD | WS_CLIPSIBLINGS;
1016 else
1018 cs->style &= ~WS_POPUP;
1019 cs->style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
1020 WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
1023 top_child = GetWindow(cs->hwndParent, GW_CHILD);
1025 if (top_child)
1027 /* Restore current maximized child */
1028 if((cs->style & WS_VISIBLE) && IsZoomed(top_child))
1030 TRACE("Restoring current maximized child %p\n", top_child);
1031 SendMessageW( top_child, WM_SETREDRAW, FALSE, 0 );
1032 ShowWindow(top_child, SW_RESTORE);
1033 SendMessageW( top_child, WM_SETREDRAW, TRUE, 0 );
1038 /* Find the parent window */
1040 parent = GetDesktopWindow();
1041 owner = 0;
1043 if (cs->hwndParent == HWND_MESSAGE)
1045 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
1046 * message window (style: WS_POPUP|WS_DISABLED)
1048 FIXME("Parent is HWND_MESSAGE\n");
1050 else if (cs->hwndParent)
1052 /* Make sure parent is valid */
1053 if (!IsWindow( cs->hwndParent ))
1055 WARN("Bad parent %p\n", cs->hwndParent );
1056 return 0;
1058 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1059 parent = WIN_GetFullHandle(cs->hwndParent);
1060 else
1061 owner = GetAncestor( cs->hwndParent, GA_ROOT );
1063 else if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1065 WARN("No parent for child window\n" );
1066 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1069 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
1071 /* Correct the window styles.
1073 * It affects both the style loaded into the WIN structure and
1074 * passed in the CREATESTRUCT to the WM_[NC]CREATE.
1076 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1077 * why does the user get to set it?
1080 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
1081 * tested for WS_POPUP
1083 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
1084 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
1085 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
1086 cs->dwExStyle |= WS_EX_WINDOWEDGE;
1087 else
1088 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
1090 if (!(cs->style & WS_CHILD))
1092 cs->style |= WS_CLIPSIBLINGS;
1093 if (!(cs->style & WS_POPUP))
1094 cs->style |= WS_CAPTION;
1097 /* Create the window structure */
1099 if (!(wndPtr = create_window_handle( parent, owner, classAtom, cs->hInstance, type )))
1101 TRACE("out of memory\n" );
1102 return 0;
1104 hwnd = wndPtr->hwndSelf;
1106 /* Fill the window structure */
1108 wndPtr->tid = GetCurrentThreadId();
1109 wndPtr->owner = owner;
1110 wndPtr->parent = parent;
1111 wndPtr->hInstance = cs->hInstance;
1112 wndPtr->text = NULL;
1113 wndPtr->hrgnUpdate = 0;
1114 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1115 wndPtr->dwExStyle = cs->dwExStyle;
1116 wndPtr->wIDmenu = 0;
1117 wndPtr->helpContext = 0;
1118 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
1119 wndPtr->pVScroll = NULL;
1120 wndPtr->pHScroll = NULL;
1121 wndPtr->userdata = 0;
1122 wndPtr->hIcon = 0;
1123 wndPtr->hIconSmall = 0;
1124 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU) ? MENU_GetSysMenu( hwnd, 0 ) : 0;
1126 if (!(cs->style & (WS_CHILD | WS_POPUP)))
1127 wndPtr->flags |= WIN_NEED_SIZE;
1129 SERVER_START_REQ( set_window_info )
1131 req->handle = hwnd;
1132 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE;
1133 req->style = wndPtr->dwStyle;
1134 req->ex_style = wndPtr->dwExStyle;
1135 req->instance = (void *)wndPtr->hInstance;
1136 req->extra_offset = -1;
1137 wine_server_call( req );
1139 SERVER_END_REQ;
1141 /* Get class or window DC if needed */
1143 if (wndPtr->clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
1145 /* Set the window menu */
1147 if (((wndPtr->dwStyle & (WS_CAPTION|WS_CHILD)) == WS_CAPTION) ||
1148 (wndPtr->dwExStyle & WS_EX_APPWINDOW))
1150 if (cs->hMenu) MENU_SetMenu(hwnd, cs->hMenu);
1151 else
1153 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
1154 if (menuName)
1156 if (HIWORD(cs->hInstance))
1157 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1158 else
1159 cs->hMenu = HMENU_32(LoadMenu16(HINSTANCE_16(cs->hInstance),menuName));
1161 if (cs->hMenu) MENU_SetMenu( hwnd, cs->hMenu );
1165 else SetWindowLongPtrW( hwnd, GWLP_ID, (ULONG_PTR)cs->hMenu );
1166 WIN_ReleaseWndPtr( wndPtr );
1168 if (!USER_Driver.pCreateWindow || !USER_Driver.pCreateWindow( hwnd, cs, unicode))
1170 WIN_DestroyWindow( hwnd );
1171 return 0;
1174 /* Notify the parent window only */
1176 send_parent_notify( hwnd, WM_CREATE );
1177 if (!IsWindow( hwnd )) return 0;
1179 if (cs->style & WS_VISIBLE)
1181 if (cs->style & WS_MAXIMIZE)
1182 sw = SW_SHOWMAXIMIZED;
1183 else if (cs->style & WS_MINIMIZE)
1184 sw = SW_SHOWMINIMIZED;
1186 ShowWindow( hwnd, sw );
1187 if (cs->dwExStyle & WS_EX_MDICHILD)
1189 SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
1190 /* ShowWindow won't activate child windows */
1191 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE );
1195 /* Call WH_SHELL hook */
1197 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1198 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1200 TRACE("created window %p\n", hwnd);
1201 return hwnd;
1205 /***********************************************************************
1206 * CreateWindow (USER.41)
1208 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1209 DWORD style, INT16 x, INT16 y, INT16 width,
1210 INT16 height, HWND16 parent, HMENU16 menu,
1211 HINSTANCE16 instance, LPVOID data )
1213 return CreateWindowEx16( 0, className, windowName, style,
1214 x, y, width, height, parent, menu, instance, data );
1218 /***********************************************************************
1219 * CreateWindowEx (USER.452)
1221 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1222 LPCSTR windowName, DWORD style, INT16 x,
1223 INT16 y, INT16 width, INT16 height,
1224 HWND16 parent, HMENU16 menu,
1225 HINSTANCE16 instance, LPVOID data )
1227 ATOM classAtom;
1228 CREATESTRUCTA cs;
1229 char buffer[256];
1231 /* Find the class atom */
1233 if (HIWORD(className))
1235 if (!(classAtom = GlobalFindAtomA( className )))
1237 ERR( "bad class name %s\n", debugstr_a(className) );
1238 return 0;
1241 else
1243 classAtom = LOWORD(className);
1244 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1246 ERR( "bad atom %x\n", classAtom);
1247 return 0;
1249 className = buffer;
1252 /* Fix the coordinates */
1254 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1255 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1256 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1257 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1259 /* Create the window */
1261 cs.lpCreateParams = data;
1262 cs.hInstance = HINSTANCE_32(instance);
1263 cs.hMenu = HMENU_32(menu);
1264 cs.hwndParent = WIN_Handle32( parent );
1265 cs.style = style;
1266 cs.lpszName = windowName;
1267 cs.lpszClass = className;
1268 cs.dwExStyle = exStyle;
1270 return HWND_16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
1274 /***********************************************************************
1275 * CreateWindowExA (USER32.@)
1277 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1278 LPCSTR windowName, DWORD style, INT x,
1279 INT y, INT width, INT height,
1280 HWND parent, HMENU menu,
1281 HINSTANCE instance, LPVOID data )
1283 ATOM classAtom;
1284 CREATESTRUCTA cs;
1285 char buffer[256];
1287 /* Find the class atom */
1289 if (HIWORD(className))
1291 if (!(classAtom = GlobalFindAtomA( className )))
1293 ERR( "bad class name %s\n", debugstr_a(className) );
1294 return 0;
1297 else
1299 classAtom = LOWORD(className);
1300 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1302 ERR( "bad atom %x\n", classAtom);
1303 return 0;
1305 className = buffer;
1308 /* Create the window */
1310 cs.lpCreateParams = data;
1311 cs.hInstance = instance;
1312 cs.hMenu = menu;
1313 cs.hwndParent = parent;
1314 cs.x = x;
1315 cs.y = y;
1316 cs.cx = width;
1317 cs.cy = height;
1318 cs.style = style;
1319 cs.lpszName = windowName;
1320 cs.lpszClass = className;
1321 cs.dwExStyle = exStyle;
1323 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1327 /***********************************************************************
1328 * CreateWindowExW (USER32.@)
1330 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1331 LPCWSTR windowName, DWORD style, INT x,
1332 INT y, INT width, INT height,
1333 HWND parent, HMENU menu,
1334 HINSTANCE instance, LPVOID data )
1336 ATOM classAtom;
1337 CREATESTRUCTW cs;
1338 WCHAR buffer[256];
1340 /* Find the class atom */
1342 if (HIWORD(className))
1344 if (!(classAtom = GlobalFindAtomW( className )))
1346 ERR( "bad class name %s\n", debugstr_w(className) );
1347 return 0;
1350 else
1352 classAtom = LOWORD(className);
1353 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1355 ERR( "bad atom %x\n", classAtom);
1356 return 0;
1358 className = buffer;
1361 /* Create the window */
1363 cs.lpCreateParams = data;
1364 cs.hInstance = instance;
1365 cs.hMenu = menu;
1366 cs.hwndParent = parent;
1367 cs.x = x;
1368 cs.y = y;
1369 cs.cx = width;
1370 cs.cy = height;
1371 cs.style = style;
1372 cs.lpszName = windowName;
1373 cs.lpszClass = className;
1374 cs.dwExStyle = exStyle;
1376 /* Note: we rely on the fact that CREATESTRUCTA and */
1377 /* CREATESTRUCTW have the same layout. */
1378 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1382 /***********************************************************************
1383 * WIN_SendDestroyMsg
1385 static void WIN_SendDestroyMsg( HWND hwnd )
1387 GUITHREADINFO info;
1389 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1391 if (hwnd == info.hwndCaret) DestroyCaret();
1392 if (hwnd == info.hwndActive) WINPOS_ActivateOtherWindow( hwnd );
1394 if (USER_Driver.pResetSelectionOwner)
1395 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1398 * Send the WM_DESTROY to the window.
1400 SendMessageA( hwnd, WM_DESTROY, 0, 0);
1403 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1404 * make sure that the window still exists when we come back.
1406 if (IsWindow(hwnd))
1408 HWND* pWndArray;
1409 int i;
1411 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1413 /* start from the end (FIXME: is this needed?) */
1414 for (i = 0; pWndArray[i]; i++) ;
1416 while (--i >= 0)
1418 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1420 HeapFree( GetProcessHeap(), 0, pWndArray );
1422 else
1423 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1427 /***********************************************************************
1428 * DestroyWindow (USER32.@)
1430 BOOL WINAPI DestroyWindow( HWND hwnd )
1432 BOOL is_child;
1434 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1436 SetLastError( ERROR_ACCESS_DENIED );
1437 return FALSE;
1440 TRACE("(%p)\n", hwnd);
1442 /* Call hooks */
1444 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1446 if (MENU_IsMenuActive() == hwnd)
1447 EndMenu();
1449 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1451 if (is_child)
1453 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1454 send_parent_notify( hwnd, WM_DESTROY );
1456 else if (!GetWindow( hwnd, GW_OWNER ))
1458 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1459 /* FIXME: clean up palette - see "Internals" p.352 */
1462 if (!IsWindow(hwnd)) return TRUE;
1464 if (USER_Driver.pResetSelectionOwner)
1465 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1467 /* Hide the window */
1469 /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
1470 if (is_child)
1471 ShowWindow( hwnd, SW_HIDE );
1472 else
1473 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1474 SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW );
1476 if (!IsWindow(hwnd)) return TRUE;
1478 /* Recursively destroy owned windows */
1480 if (!is_child)
1482 for (;;)
1484 int i, got_one = 0;
1485 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1486 if (list)
1488 for (i = 0; list[i]; i++)
1490 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1491 if (WIN_IsCurrentThread( list[i] ))
1493 DestroyWindow( list[i] );
1494 got_one = 1;
1495 continue;
1497 WIN_SetOwner( list[i], 0 );
1499 HeapFree( GetProcessHeap(), 0, list );
1501 if (!got_one) break;
1505 /* Send destroy messages */
1507 WIN_SendDestroyMsg( hwnd );
1508 if (!IsWindow( hwnd )) return TRUE;
1510 if (GetClipboardOwner() == hwnd)
1511 CLIPBOARD_ReleaseOwner();
1513 /* Unlink now so we won't bother with the children later on */
1515 WIN_UnlinkWindow( hwnd );
1517 /* Destroy the window storage */
1519 WIN_DestroyWindow( hwnd );
1520 return TRUE;
1524 /***********************************************************************
1525 * CloseWindow (USER32.@)
1527 BOOL WINAPI CloseWindow( HWND hwnd )
1529 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1530 ShowWindow( hwnd, SW_MINIMIZE );
1531 return TRUE;
1535 /***********************************************************************
1536 * OpenIcon (USER32.@)
1538 BOOL WINAPI OpenIcon( HWND hwnd )
1540 if (!IsIconic( hwnd )) return FALSE;
1541 ShowWindow( hwnd, SW_SHOWNORMAL );
1542 return TRUE;
1546 /***********************************************************************
1547 * WIN_FindWindow
1549 * Implementation of FindWindow() and FindWindowEx().
1551 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1553 HWND *list = NULL;
1554 HWND retvalue = 0;
1555 int i = 0, len = 0;
1556 WCHAR *buffer = NULL;
1558 if (!parent) parent = GetDesktopWindow();
1559 if (title)
1561 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1562 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1565 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1567 if (child)
1569 child = WIN_GetFullHandle( child );
1570 while (list[i] && list[i] != child) i++;
1571 if (!list[i]) goto done;
1572 i++; /* start from next window */
1575 if (title)
1577 while (list[i])
1579 if (GetWindowTextW( list[i], buffer, len + 1 ) && !strcmpiW( buffer, title )) break;
1580 i++;
1583 retvalue = list[i];
1585 done:
1586 if (list) HeapFree( GetProcessHeap(), 0, list );
1587 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1588 return retvalue;
1593 /***********************************************************************
1594 * FindWindowA (USER32.@)
1596 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1598 HWND ret = FindWindowExA( 0, 0, className, title );
1599 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1600 return ret;
1604 /***********************************************************************
1605 * FindWindowExA (USER32.@)
1607 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1608 LPCSTR className, LPCSTR title )
1610 ATOM atom = 0;
1611 LPWSTR buffer;
1612 HWND hwnd;
1613 INT len;
1615 if (className)
1617 /* If the atom doesn't exist, then no class */
1618 /* with this name exists either. */
1619 if (!(atom = GlobalFindAtomA( className )))
1621 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1622 return 0;
1625 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
1627 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1628 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1629 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
1630 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1631 HeapFree( GetProcessHeap(), 0, buffer );
1632 return hwnd;
1636 /***********************************************************************
1637 * FindWindowExW (USER32.@)
1639 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1640 LPCWSTR className, LPCWSTR title )
1642 ATOM atom = 0;
1644 if (className)
1646 /* If the atom doesn't exist, then no class */
1647 /* with this name exists either. */
1648 if (!(atom = GlobalFindAtomW( className )))
1650 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1651 return 0;
1654 return WIN_FindWindow( parent, child, atom, title );
1658 /***********************************************************************
1659 * FindWindowW (USER32.@)
1661 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1663 return FindWindowExW( 0, 0, className, title );
1667 /**********************************************************************
1668 * GetDesktopWindow (USER32.@)
1670 HWND WINAPI GetDesktopWindow(void)
1672 if (pWndDesktop) return pWndDesktop->hwndSelf;
1673 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" );
1674 ExitProcess(1);
1675 return 0;
1679 /*******************************************************************
1680 * EnableWindow (USER32.@)
1682 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1684 WND *wndPtr;
1685 BOOL retvalue;
1686 LONG style;
1687 HWND full_handle;
1689 if (is_broadcast(hwnd))
1691 SetLastError( ERROR_INVALID_PARAMETER );
1692 return FALSE;
1695 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1696 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1698 hwnd = full_handle;
1700 TRACE("( %p, %d )\n", hwnd, enable);
1702 if (!(wndPtr = WIN_GetPtr( hwnd ))) return FALSE;
1703 style = wndPtr->dwStyle;
1704 retvalue = ((style & WS_DISABLED) != 0);
1705 WIN_ReleasePtr( wndPtr );
1707 if (enable && retvalue)
1709 WIN_SetStyle( hwnd, style & ~WS_DISABLED );
1710 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1712 else if (!enable && !retvalue)
1714 HWND capture_wnd;
1716 SendMessageA( hwnd, WM_CANCELMODE, 0, 0);
1718 WIN_SetStyle( hwnd, style | WS_DISABLED );
1720 if (hwnd == GetFocus())
1721 SetFocus( 0 ); /* A disabled window can't have the focus */
1723 capture_wnd = GetCapture();
1724 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1725 ReleaseCapture(); /* A disabled window can't capture the mouse */
1727 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1729 return retvalue;
1733 /***********************************************************************
1734 * IsWindowEnabled (USER32.@)
1736 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1738 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1742 /***********************************************************************
1743 * IsWindowUnicode (USER32.@)
1745 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1747 WND * wndPtr;
1748 BOOL retvalue;
1750 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1751 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1752 WIN_ReleaseWndPtr(wndPtr);
1753 return retvalue;
1757 /**********************************************************************
1758 * GetWindowWord (USER32.@)
1760 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1762 if (offset >= 0)
1764 WORD retvalue = 0;
1765 WND *wndPtr = WIN_GetPtr( hwnd );
1766 if (!wndPtr)
1768 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1769 return 0;
1771 if (wndPtr == WND_OTHER_PROCESS)
1773 SERVER_START_REQ( set_window_info )
1775 req->handle = hwnd;
1776 req->flags = 0; /* don't set anything, just retrieve */
1777 req->extra_offset = offset;
1778 req->extra_size = sizeof(retvalue);
1779 if (!wine_server_call_err( req ))
1780 memcpy( &retvalue, &reply->old_extra_value, sizeof(retvalue) );
1782 SERVER_END_REQ;
1783 return retvalue;
1785 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1787 WARN("Invalid offset %d\n", offset );
1788 SetLastError( ERROR_INVALID_INDEX );
1790 else memcpy( &retvalue, (char *)wndPtr->wExtra + offset, sizeof(retvalue) );
1791 WIN_ReleasePtr( wndPtr );
1792 return retvalue;
1795 switch(offset)
1797 case GWLP_HWNDPARENT:
1798 return GetWindowLongPtrW( hwnd, offset );
1799 case GWLP_ID:
1800 case GWLP_HINSTANCE:
1802 LONG_PTR ret = GetWindowLongPtrW( hwnd, offset );
1803 if (HIWORD(ret))
1804 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1805 return LOWORD(ret);
1807 default:
1808 WARN("Invalid offset %d\n", offset );
1809 return 0;
1814 /**********************************************************************
1815 * SetWindowWord (USER32.@)
1817 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1819 WORD retval = 0;
1820 WND * wndPtr;
1822 switch(offset)
1824 case GWLP_ID:
1825 case GWLP_HINSTANCE:
1826 case GWLP_HWNDPARENT:
1827 return SetWindowLongPtrW( hwnd, offset, (ULONG_PTR)newval );
1828 default:
1829 if (offset < 0)
1831 WARN("Invalid offset %d\n", offset );
1832 SetLastError( ERROR_INVALID_INDEX );
1833 return 0;
1837 wndPtr = WIN_GetPtr( hwnd );
1838 if (wndPtr == WND_OTHER_PROCESS)
1840 if (IsWindow(hwnd))
1841 FIXME( "set %d <- %x not supported yet on other process window %p\n",
1842 offset, newval, hwnd );
1843 wndPtr = NULL;
1845 if (!wndPtr)
1847 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1848 return 0;
1851 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1853 WARN("Invalid offset %d\n", offset );
1854 WIN_ReleasePtr(wndPtr);
1855 SetLastError( ERROR_INVALID_INDEX );
1856 return 0;
1859 SERVER_START_REQ( set_window_info )
1861 req->handle = hwnd;
1862 req->flags = SET_WIN_EXTRA;
1863 req->extra_offset = offset;
1864 req->extra_size = sizeof(newval);
1865 memcpy( &req->extra_value, &newval, sizeof(newval) );
1866 if (!wine_server_call_err( req ))
1868 void *ptr = (char *)wndPtr->wExtra + offset;
1869 memcpy( &retval, ptr, sizeof(retval) );
1870 memcpy( ptr, &newval, sizeof(newval) );
1873 SERVER_END_REQ;
1874 WIN_ReleasePtr( wndPtr );
1875 return retval;
1879 /**********************************************************************
1880 * WIN_GetWindowLong
1882 * Helper function for GetWindowLong().
1884 static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1886 LONG_PTR retvalue = 0;
1887 WND *wndPtr;
1889 if (offset == GWLP_HWNDPARENT)
1891 HWND parent = GetAncestor( hwnd, GA_PARENT );
1892 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1893 return (ULONG_PTR)parent;
1896 if (!(wndPtr = WIN_GetPtr( hwnd )))
1898 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1899 return 0;
1902 if (wndPtr == WND_OTHER_PROCESS)
1904 if (offset == GWLP_WNDPROC)
1906 SetLastError( ERROR_ACCESS_DENIED );
1907 return 0;
1909 SERVER_START_REQ( set_window_info )
1911 req->handle = hwnd;
1912 req->flags = 0; /* don't set anything, just retrieve */
1913 req->extra_offset = (offset >= 0) ? offset : -1;
1914 req->extra_size = (offset >= 0) ? sizeof(retvalue) : 0;
1915 if (!wine_server_call_err( req ))
1917 switch(offset)
1919 case GWL_STYLE: retvalue = reply->old_style; break;
1920 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1921 case GWLP_ID: retvalue = reply->old_id; break;
1922 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1923 case GWLP_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
1924 default:
1925 if (offset >= 0) retvalue = reply->old_extra_value;
1926 else SetLastError( ERROR_INVALID_INDEX );
1927 break;
1931 SERVER_END_REQ;
1932 return retvalue;
1935 /* now we have a valid wndPtr */
1937 if (offset >= 0)
1939 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
1942 * Some programs try to access last element from 16 bit
1943 * code using illegal offset value. Hopefully this is
1944 * what those programs really expect.
1946 if (type == WIN_PROC_16 &&
1947 wndPtr->cbWndExtra >= 4 &&
1948 offset == wndPtr->cbWndExtra - sizeof(WORD))
1950 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
1952 ERR( "- replaced invalid offset %d with %d\n",
1953 offset, offset2 );
1955 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset2);
1956 WIN_ReleasePtr( wndPtr );
1957 return retvalue;
1959 WARN("Invalid offset %d\n", offset );
1960 WIN_ReleasePtr( wndPtr );
1961 SetLastError( ERROR_INVALID_INDEX );
1962 return 0;
1964 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1965 /* Special case for dialog window procedure */
1966 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1967 retvalue = (LONG)WINPROC_GetProc( (WNDPROC)retvalue, type );
1968 WIN_ReleasePtr( wndPtr );
1969 return retvalue;
1972 switch(offset)
1974 case GWLP_USERDATA: retvalue = wndPtr->userdata; break;
1975 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1976 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1977 case GWLP_ID: retvalue = (ULONG_PTR)wndPtr->wIDmenu; break;
1978 case GWLP_WNDPROC: retvalue = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, type ); break;
1979 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wndPtr->hInstance; break;
1980 default:
1981 WARN("Unknown offset %d\n", offset );
1982 SetLastError( ERROR_INVALID_INDEX );
1983 break;
1985 WIN_ReleasePtr(wndPtr);
1986 return retvalue;
1990 /**********************************************************************
1991 * WIN_SetWindowLong
1993 * Helper function for SetWindowLong().
1995 * 0 is the failure code. However, in the case of failure SetLastError
1996 * must be set to distinguish between a 0 return value and a failure.
1998 static LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, LONG_PTR newval,
1999 WINDOWPROCTYPE type )
2001 STYLESTRUCT style;
2002 BOOL ok;
2003 LONG retval = 0;
2004 WND *wndPtr;
2006 TRACE( "%p %d %lx %x\n", hwnd, offset, newval, type );
2008 if (is_broadcast(hwnd))
2010 SetLastError( ERROR_INVALID_PARAMETER );
2011 return FALSE;
2013 if (!WIN_IsCurrentProcess( hwnd ))
2015 if (offset == GWLP_WNDPROC)
2017 SetLastError( ERROR_ACCESS_DENIED );
2018 return 0;
2020 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
2023 wndPtr = WIN_GetPtr( hwnd );
2024 if (wndPtr->hwndSelf == GetDesktopWindow())
2026 /* can't change anything on the desktop window */
2027 WIN_ReleasePtr( wndPtr );
2028 SetLastError( ERROR_ACCESS_DENIED );
2029 return 0;
2032 /* first some special cases */
2033 switch( offset )
2035 case GWL_STYLE:
2036 case GWL_EXSTYLE:
2037 style.styleOld =
2038 offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
2039 style.styleNew = newval;
2040 WIN_ReleasePtr( wndPtr );
2041 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
2042 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
2043 newval = style.styleNew;
2044 break;
2045 case GWLP_HWNDPARENT:
2046 if (wndPtr->parent == GetDesktopWindow())
2048 WIN_ReleasePtr( wndPtr );
2049 return (ULONG_PTR)WIN_SetOwner( hwnd, (HWND)newval );
2051 else
2053 WIN_ReleasePtr( wndPtr );
2054 return (ULONG_PTR)SetParent( hwnd, (HWND)newval );
2056 case GWLP_WNDPROC:
2057 retval = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, type );
2058 wndPtr->winproc = WINPROC_AllocProc( (WNDPROC)newval, type );
2059 WIN_ReleasePtr( wndPtr );
2060 return retval;
2061 case GWLP_ID:
2062 case GWLP_HINSTANCE:
2063 case GWLP_USERDATA:
2064 break;
2065 case DWLP_DLGPROC:
2066 if ((wndPtr->cbWndExtra + sizeof(LONG) >= DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2068 WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWLP_DLGPROC);
2069 retval = (ULONG_PTR)WINPROC_GetProc( *ptr, type );
2070 *ptr = WINPROC_AllocProc( (WNDPROC)newval, type );
2071 WIN_ReleasePtr( wndPtr );
2072 return retval;
2074 /* fall through */
2075 default:
2076 if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
2078 WARN("Invalid offset %d\n", offset );
2079 WIN_ReleasePtr( wndPtr );
2080 SetLastError( ERROR_INVALID_INDEX );
2081 return 0;
2083 else
2085 LONG_PTR *ptr = (LONG_PTR *)((char *)wndPtr->wExtra + offset);
2086 if (*ptr == newval) /* already set to the same value */
2088 WIN_ReleasePtr( wndPtr );
2089 return newval;
2092 break;
2095 SERVER_START_REQ( set_window_info )
2097 req->handle = hwnd;
2098 req->extra_offset = -1;
2099 switch(offset)
2101 case GWL_STYLE:
2102 req->flags = SET_WIN_STYLE;
2103 req->style = newval;
2104 break;
2105 case GWL_EXSTYLE:
2106 req->flags = SET_WIN_EXSTYLE;
2107 req->ex_style = newval;
2108 break;
2109 case GWLP_ID:
2110 req->flags = SET_WIN_ID;
2111 req->id = newval;
2112 break;
2113 case GWLP_HINSTANCE:
2114 req->flags = SET_WIN_INSTANCE;
2115 req->instance = (void *)newval;
2116 break;
2117 case GWLP_USERDATA:
2118 req->flags = SET_WIN_USERDATA;
2119 req->user_data = (void *)newval;
2120 break;
2121 default:
2122 req->flags = SET_WIN_EXTRA;
2123 req->extra_offset = offset;
2124 req->extra_size = sizeof(newval);
2125 memcpy( &req->extra_value, &newval, sizeof(newval) );
2127 if ((ok = !wine_server_call_err( req )))
2129 switch(offset)
2131 case GWL_STYLE:
2132 wndPtr->dwStyle = newval;
2133 retval = reply->old_style;
2134 break;
2135 case GWL_EXSTYLE:
2136 wndPtr->dwExStyle = newval;
2137 retval = reply->old_ex_style;
2138 break;
2139 case GWLP_ID:
2140 wndPtr->wIDmenu = newval;
2141 retval = reply->old_id;
2142 break;
2143 case GWLP_HINSTANCE:
2144 wndPtr->hInstance = (HINSTANCE)newval;
2145 retval = (ULONG_PTR)reply->old_instance;
2146 break;
2147 case GWLP_USERDATA:
2148 wndPtr->userdata = newval;
2149 retval = (ULONG_PTR)reply->old_user_data;
2150 break;
2151 default:
2153 void *ptr = (char *)wndPtr->wExtra + offset;
2154 memcpy( &retval, ptr, sizeof(retval) );
2155 memcpy( ptr, &newval, sizeof(newval) );
2157 break;
2161 SERVER_END_REQ;
2162 WIN_ReleasePtr( wndPtr );
2164 if (!ok) return 0;
2166 if (offset == GWL_STYLE && USER_Driver.pSetWindowStyle)
2167 USER_Driver.pSetWindowStyle( hwnd, retval );
2169 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2170 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2172 return retval;
2176 /**********************************************************************
2177 * GetWindowLong (USER.135)
2179 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2181 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
2185 /**********************************************************************
2186 * GetWindowLongA (USER32.@)
2188 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2190 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2194 /**********************************************************************
2195 * GetWindowLongW (USER32.@)
2197 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2199 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2203 /**********************************************************************
2204 * SetWindowLong (USER.136)
2206 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2208 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
2212 /**********************************************************************
2213 * SetWindowLongA (USER32.@)
2215 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2217 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2221 /**********************************************************************
2222 * SetWindowLongW (USER32.@) Set window attribute
2224 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2225 * value in a window's extra memory.
2227 * The _hwnd_ parameter specifies the window. is the handle to a
2228 * window that has extra memory. The _newval_ parameter contains the
2229 * new attribute or extra memory value. If positive, the _offset_
2230 * parameter is the byte-addressed location in the window's extra
2231 * memory to set. If negative, _offset_ specifies the window
2232 * attribute to set, and should be one of the following values:
2234 * GWL_EXSTYLE The window's extended window style
2236 * GWL_STYLE The window's window style.
2238 * GWLP_WNDPROC Pointer to the window's window procedure.
2240 * GWLP_HINSTANCE The window's pplication instance handle.
2242 * GWLP_ID The window's identifier.
2244 * GWLP_USERDATA The window's user-specified data.
2246 * If the window is a dialog box, the _offset_ parameter can be one of
2247 * the following values:
2249 * DWLP_DLGPROC The address of the window's dialog box procedure.
2251 * DWLP_MSGRESULT The return value of a message
2252 * that the dialog box procedure processed.
2254 * DWLP_USER Application specific information.
2256 * RETURNS
2258 * If successful, returns the previous value located at _offset_. Otherwise,
2259 * returns 0.
2261 * NOTES
2263 * Extra memory for a window class is specified by a nonzero cbWndExtra
2264 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2265 * time of class creation.
2267 * Using GWL_WNDPROC to set a new window procedure effectively creates
2268 * a window subclass. Use CallWindowProc() in the new windows procedure
2269 * to pass messages to the superclass's window procedure.
2271 * The user data is reserved for use by the application which created
2272 * the window.
2274 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2275 * instead, call the EnableWindow() function to change the window's
2276 * disabled state.
2278 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2279 * SetParent() instead.
2281 * Win95:
2282 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2283 * it sends WM_STYLECHANGING before changing the settings
2284 * and WM_STYLECHANGED afterwards.
2285 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2287 LONG WINAPI SetWindowLongW(
2288 HWND hwnd, /* [in] window to alter */
2289 INT offset, /* [in] offset, in bytes, of location to alter */
2290 LONG newval /* [in] new value of location */
2292 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2296 /*******************************************************************
2297 * GetWindowTextA (USER32.@)
2299 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2301 WCHAR *buffer;
2303 if (WIN_IsCurrentProcess( hwnd ))
2304 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2306 /* when window belongs to other process, don't send a message */
2307 if (nMaxCount <= 0) return 0;
2308 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2309 get_server_window_text( hwnd, buffer, nMaxCount );
2310 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2311 lpString[nMaxCount-1] = 0;
2312 HeapFree( GetProcessHeap(), 0, buffer );
2313 return strlen(lpString);
2317 /*******************************************************************
2318 * InternalGetWindowText (USER32.@)
2320 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2322 WND *win;
2324 if (nMaxCount <= 0) return 0;
2325 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2326 if (win != WND_OTHER_PROCESS)
2328 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2329 else lpString[0] = 0;
2330 WIN_ReleasePtr( win );
2332 else
2334 get_server_window_text( hwnd, lpString, nMaxCount );
2336 return strlenW(lpString);
2340 /*******************************************************************
2341 * GetWindowTextW (USER32.@)
2343 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2345 if (WIN_IsCurrentProcess( hwnd ))
2346 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2348 /* when window belongs to other process, don't send a message */
2349 if (nMaxCount <= 0) return 0;
2350 get_server_window_text( hwnd, lpString, nMaxCount );
2351 return strlenW(lpString);
2355 /*******************************************************************
2356 * SetWindowText (USER32.@)
2357 * SetWindowTextA (USER32.@)
2359 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2361 if (is_broadcast(hwnd))
2363 SetLastError( ERROR_INVALID_PARAMETER );
2364 return FALSE;
2366 if (!WIN_IsCurrentProcess( hwnd ))
2368 FIXME( "cannot set text %s of other process window %p\n", debugstr_a(lpString), hwnd );
2369 SetLastError( ERROR_ACCESS_DENIED );
2370 return FALSE;
2372 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2376 /*******************************************************************
2377 * SetWindowTextW (USER32.@)
2379 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2381 if (is_broadcast(hwnd))
2383 SetLastError( ERROR_INVALID_PARAMETER );
2384 return FALSE;
2386 if (!WIN_IsCurrentProcess( hwnd ))
2388 FIXME( "cannot set text %s of other process window %p\n", debugstr_w(lpString), hwnd );
2389 SetLastError( ERROR_ACCESS_DENIED );
2390 return FALSE;
2392 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2396 /*******************************************************************
2397 * GetWindowTextLengthA (USER32.@)
2399 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2401 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2404 /*******************************************************************
2405 * GetWindowTextLengthW (USER32.@)
2407 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2409 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2413 /*******************************************************************
2414 * IsWindow (USER32.@)
2416 BOOL WINAPI IsWindow( HWND hwnd )
2418 WND *ptr;
2419 BOOL ret;
2421 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2423 if (ptr != WND_OTHER_PROCESS)
2425 WIN_ReleasePtr( ptr );
2426 return TRUE;
2429 /* check other processes */
2430 SERVER_START_REQ( get_window_info )
2432 req->handle = hwnd;
2433 ret = !wine_server_call_err( req );
2435 SERVER_END_REQ;
2436 return ret;
2440 /***********************************************************************
2441 * GetWindowThreadProcessId (USER32.@)
2443 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2445 WND *ptr;
2446 DWORD tid = 0;
2448 if (!(ptr = WIN_GetPtr( hwnd )))
2450 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2451 return 0;
2454 if (ptr != WND_OTHER_PROCESS)
2456 /* got a valid window */
2457 tid = ptr->tid;
2458 if (process) *process = GetCurrentProcessId();
2459 WIN_ReleasePtr( ptr );
2460 return tid;
2463 /* check other processes */
2464 SERVER_START_REQ( get_window_info )
2466 req->handle = hwnd;
2467 if (!wine_server_call_err( req ))
2469 tid = (DWORD)reply->tid;
2470 if (process) *process = (DWORD)reply->pid;
2473 SERVER_END_REQ;
2474 return tid;
2478 /*****************************************************************
2479 * GetParent (USER32.@)
2481 HWND WINAPI GetParent( HWND hwnd )
2483 WND *wndPtr;
2484 HWND retvalue = 0;
2486 if (!(wndPtr = WIN_GetPtr( hwnd )))
2488 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2489 return 0;
2491 if (wndPtr == WND_OTHER_PROCESS)
2493 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2494 if (style & (WS_POPUP | WS_CHILD))
2496 SERVER_START_REQ( get_window_tree )
2498 req->handle = hwnd;
2499 if (!wine_server_call_err( req ))
2501 if (style & WS_POPUP) retvalue = reply->owner;
2502 else if (style & WS_CHILD) retvalue = reply->parent;
2505 SERVER_END_REQ;
2508 else
2510 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2511 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2512 WIN_ReleasePtr( wndPtr );
2514 return retvalue;
2518 /*****************************************************************
2519 * GetAncestor (USER32.@)
2521 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2523 WND *win;
2524 HWND *list, ret = 0;
2526 switch(type)
2528 case GA_PARENT:
2529 if (!(win = WIN_GetPtr( hwnd )))
2531 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2532 return 0;
2534 if (win != WND_OTHER_PROCESS)
2536 ret = win->parent;
2537 WIN_ReleasePtr( win );
2539 else /* need to query the server */
2541 SERVER_START_REQ( get_window_tree )
2543 req->handle = hwnd;
2544 if (!wine_server_call_err( req )) ret = reply->parent;
2546 SERVER_END_REQ;
2548 break;
2550 case GA_ROOT:
2551 if (!(list = WIN_ListParents( hwnd ))) return 0;
2553 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2554 else
2556 int count = 2;
2557 while (list[count]) count++;
2558 ret = list[count - 2]; /* get the one before the desktop */
2560 HeapFree( GetProcessHeap(), 0, list );
2561 break;
2563 case GA_ROOTOWNER:
2564 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2565 for (;;)
2567 HWND parent = GetParent( ret );
2568 if (!parent) break;
2569 ret = parent;
2571 break;
2573 return ret;
2577 /*****************************************************************
2578 * SetParent (USER32.@)
2580 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2582 WND *wndPtr;
2583 HWND retvalue, full_handle;
2584 BOOL was_visible;
2586 if (is_broadcast(hwnd) || is_broadcast(parent))
2588 SetLastError(ERROR_INVALID_PARAMETER);
2589 return 0;
2592 if (!parent) parent = GetDesktopWindow();
2593 else parent = WIN_GetFullHandle( parent );
2595 if (!IsWindow( parent ))
2597 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2598 return 0;
2601 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2602 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2604 hwnd = full_handle;
2606 if (USER_Driver.pSetParent)
2607 return USER_Driver.pSetParent( hwnd, parent );
2609 /* Windows hides the window first, then shows it again
2610 * including the WM_SHOWWINDOW messages and all */
2611 was_visible = ShowWindow( hwnd, SW_HIDE );
2613 if (!IsWindow( parent )) return 0;
2614 if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return 0;
2616 retvalue = wndPtr->parent; /* old parent */
2617 if (parent != retvalue)
2619 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2621 if (parent != GetDesktopWindow()) /* a child window */
2623 if (!(wndPtr->dwStyle & WS_CHILD))
2625 HMENU menu = (HMENU)SetWindowLongPtrW( hwnd, GWLP_ID, 0 );
2626 if (menu) DestroyMenu( menu );
2630 WIN_ReleasePtr( wndPtr );
2632 /* SetParent additionally needs to make hwnd the topmost window
2633 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2634 WM_WINDOWPOSCHANGED notification messages.
2636 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2637 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2638 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2639 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2640 return retvalue;
2644 /*******************************************************************
2645 * IsChild (USER32.@)
2647 BOOL WINAPI IsChild( HWND parent, HWND child )
2649 HWND *list = WIN_ListParents( child );
2650 int i;
2651 BOOL ret;
2653 if (!list) return FALSE;
2654 parent = WIN_GetFullHandle( parent );
2655 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2656 ret = (list[i] != 0);
2657 HeapFree( GetProcessHeap(), 0, list );
2658 return ret;
2662 /***********************************************************************
2663 * IsWindowVisible (USER32.@)
2665 BOOL WINAPI IsWindowVisible( HWND hwnd )
2667 HWND *list;
2668 BOOL retval;
2669 int i;
2671 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2672 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2673 for (i = 0; list[i]; i++)
2674 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2675 retval = !list[i];
2676 HeapFree( GetProcessHeap(), 0, list );
2677 return retval;
2681 /***********************************************************************
2682 * WIN_IsWindowDrawable
2684 * hwnd is drawable when it is visible, all parents are not
2685 * minimized, and it is itself not minimized unless we are
2686 * trying to draw its default class icon.
2688 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2690 HWND *list;
2691 BOOL retval;
2692 int i;
2693 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2695 if (!(style & WS_VISIBLE)) return FALSE;
2696 if ((style & WS_MINIMIZE) && icon && GetClassLongA( hwnd, GCL_HICON )) return FALSE;
2698 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2699 for (i = 0; list[i]; i++)
2700 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2701 break;
2702 retval = !list[i];
2703 HeapFree( GetProcessHeap(), 0, list );
2704 return retval;
2708 /*******************************************************************
2709 * GetTopWindow (USER32.@)
2711 HWND WINAPI GetTopWindow( HWND hwnd )
2713 if (!hwnd) hwnd = GetDesktopWindow();
2714 return GetWindow( hwnd, GW_CHILD );
2718 /*******************************************************************
2719 * GetWindow (USER32.@)
2721 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2723 HWND retval = 0;
2725 if (rel == GW_OWNER) /* this one may be available locally */
2727 WND *wndPtr = WIN_GetPtr( hwnd );
2728 if (!wndPtr)
2730 SetLastError( ERROR_INVALID_HANDLE );
2731 return 0;
2733 if (wndPtr != WND_OTHER_PROCESS)
2735 retval = wndPtr->owner;
2736 WIN_ReleasePtr( wndPtr );
2737 return retval;
2739 /* else fall through to server call */
2742 SERVER_START_REQ( get_window_tree )
2744 req->handle = hwnd;
2745 if (!wine_server_call_err( req ))
2747 switch(rel)
2749 case GW_HWNDFIRST:
2750 retval = reply->first_sibling;
2751 break;
2752 case GW_HWNDLAST:
2753 retval = reply->last_sibling;
2754 break;
2755 case GW_HWNDNEXT:
2756 retval = reply->next_sibling;
2757 break;
2758 case GW_HWNDPREV:
2759 retval = reply->prev_sibling;
2760 break;
2761 case GW_OWNER:
2762 retval = reply->owner;
2763 break;
2764 case GW_CHILD:
2765 retval = reply->first_child;
2766 break;
2770 SERVER_END_REQ;
2771 return retval;
2775 /***********************************************************************
2776 * WIN_InternalShowOwnedPopups
2778 * Internal version of ShowOwnedPopups; Wine functions should use this
2779 * to avoid interfering with application calls to ShowOwnedPopups
2780 * and to make sure the application can't prevent showing/hiding.
2782 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2786 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2788 int count = 0;
2789 WND *pWnd;
2790 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2792 if (!win_array) return TRUE;
2795 * Show windows Lowest first, Highest last to preserve Z-Order
2797 while (win_array[count]) count++;
2798 while (--count >= 0)
2800 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2801 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2803 if (pWnd->dwStyle & WS_POPUP)
2805 if (fShow)
2807 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2808 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
2811 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2813 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2814 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2817 else
2819 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2820 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2821 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2824 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2826 ShowWindow(pWnd->hwndSelf,SW_HIDE);
2827 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2828 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
2832 WIN_ReleaseWndPtr( pWnd );
2834 HeapFree( GetProcessHeap(), 0, win_array );
2836 return TRUE;
2839 /*******************************************************************
2840 * ShowOwnedPopups (USER32.@)
2842 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2844 int count = 0;
2845 WND *pWnd;
2846 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2848 if (!win_array) return TRUE;
2850 while (win_array[count]) count++;
2851 while (--count >= 0)
2853 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2854 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2856 if (pWnd->dwStyle & WS_POPUP)
2858 if (fShow)
2860 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2862 /* In Windows, ShowOwnedPopups(TRUE) generates
2863 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2864 * regardless of the state of the owner
2866 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2867 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2870 else
2872 if (IsWindowVisible(pWnd->hwndSelf))
2874 /* In Windows, ShowOwnedPopups(FALSE) generates
2875 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2876 * regardless of the state of the owner
2878 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2879 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2883 WIN_ReleaseWndPtr( pWnd );
2885 HeapFree( GetProcessHeap(), 0, win_array );
2886 return TRUE;
2890 /*******************************************************************
2891 * GetLastActivePopup (USER32.@)
2893 HWND WINAPI GetLastActivePopup( HWND hwnd )
2895 HWND retval = hwnd;
2897 SERVER_START_REQ( get_window_info )
2899 req->handle = hwnd;
2900 if (!wine_server_call_err( req )) retval = reply->last_active;
2902 SERVER_END_REQ;
2903 return retval;
2907 /*******************************************************************
2908 * WIN_ListParents
2910 * Build an array of all parents of a given window, starting with
2911 * the immediate parent. The array must be freed with HeapFree.
2912 * Returns NULL if window is a top-level window.
2914 HWND *WIN_ListParents( HWND hwnd )
2916 WND *win;
2917 HWND current, *list;
2918 int pos = 0, size = 16, count = 0;
2920 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2922 current = hwnd;
2923 for (;;)
2925 if (!(win = WIN_GetPtr( current ))) goto empty;
2926 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
2927 list[pos] = win->parent;
2928 WIN_ReleasePtr( win );
2929 if (!(current = list[pos]))
2931 if (!pos) goto empty;
2932 return list;
2934 if (++pos == size - 1)
2936 /* need to grow the list */
2937 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
2938 if (!new_list) goto empty;
2939 list = new_list;
2940 size += 16;
2944 /* at least one parent belongs to another process, have to query the server */
2946 for (;;)
2948 count = 0;
2949 SERVER_START_REQ( get_window_parents )
2951 req->handle = hwnd;
2952 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
2953 if (!wine_server_call( req )) count = reply->count;
2955 SERVER_END_REQ;
2956 if (!count) goto empty;
2957 if (size > count)
2959 list[count] = 0;
2960 return list;
2962 HeapFree( GetProcessHeap(), 0, list );
2963 size = count + 1;
2964 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2967 empty:
2968 HeapFree( GetProcessHeap(), 0, list );
2969 return NULL;
2973 /*******************************************************************
2974 * WIN_ListChildren
2976 * Build an array of the children of a given window. The array must be
2977 * freed with HeapFree. Returns NULL when no windows are found.
2979 HWND *WIN_ListChildren( HWND hwnd )
2981 return list_window_children( hwnd, 0, 0 );
2985 /*******************************************************************
2986 * EnumWindows (USER32.@)
2988 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2990 HWND *list;
2991 BOOL ret = TRUE;
2992 int i, iWndsLocks;
2994 /* We have to build a list of all windows first, to avoid */
2995 /* unpleasant side-effects, for instance if the callback */
2996 /* function changes the Z-order of the windows. */
2998 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
3000 /* Now call the callback function for every window */
3002 iWndsLocks = WIN_SuspendWndsLock();
3003 for (i = 0; list[i]; i++)
3005 /* Make sure that the window still exists */
3006 if (!IsWindow( list[i] )) continue;
3007 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
3009 WIN_RestoreWndsLock(iWndsLocks);
3010 HeapFree( GetProcessHeap(), 0, list );
3011 return ret;
3015 /**********************************************************************
3016 * EnumThreadWindows (USER32.@)
3018 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
3020 HWND *list;
3021 int i, iWndsLocks;
3023 if (!(list = list_window_children( GetDesktopWindow(), 0, id ))) return TRUE;
3025 /* Now call the callback function for every window */
3027 iWndsLocks = WIN_SuspendWndsLock();
3028 for (i = 0; list[i]; i++)
3029 if (!func( list[i], lParam )) break;
3030 WIN_RestoreWndsLock(iWndsLocks);
3031 HeapFree( GetProcessHeap(), 0, list );
3032 return TRUE;
3036 /**********************************************************************
3037 * WIN_EnumChildWindows
3039 * Helper function for EnumChildWindows().
3041 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
3043 HWND *childList;
3044 BOOL ret = FALSE;
3046 for ( ; *list; list++)
3048 /* Make sure that the window still exists */
3049 if (!IsWindow( *list )) continue;
3050 /* skip owned windows */
3051 if (GetWindow( *list, GW_OWNER )) continue;
3052 /* Build children list first */
3053 childList = WIN_ListChildren( *list );
3055 ret = func( *list, lParam );
3057 if (childList)
3059 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
3060 HeapFree( GetProcessHeap(), 0, childList );
3062 if (!ret) return FALSE;
3064 return TRUE;
3068 /**********************************************************************
3069 * EnumChildWindows (USER32.@)
3071 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
3073 HWND *list;
3074 int iWndsLocks;
3076 if (!(list = WIN_ListChildren( parent ))) return FALSE;
3077 iWndsLocks = WIN_SuspendWndsLock();
3078 WIN_EnumChildWindows( list, func, lParam );
3079 WIN_RestoreWndsLock(iWndsLocks);
3080 HeapFree( GetProcessHeap(), 0, list );
3081 return TRUE;
3085 /*******************************************************************
3086 * AnyPopup (USER.52)
3088 BOOL16 WINAPI AnyPopup16(void)
3090 return AnyPopup();
3094 /*******************************************************************
3095 * AnyPopup (USER32.@)
3097 BOOL WINAPI AnyPopup(void)
3099 int i;
3100 BOOL retvalue;
3101 HWND *list = WIN_ListChildren( GetDesktopWindow() );
3103 if (!list) return FALSE;
3104 for (i = 0; list[i]; i++)
3106 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
3108 retvalue = (list[i] != 0);
3109 HeapFree( GetProcessHeap(), 0, list );
3110 return retvalue;
3114 /*******************************************************************
3115 * FlashWindow (USER32.@)
3117 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3119 WND *wndPtr = WIN_FindWndPtr(hWnd);
3121 TRACE("%p\n", hWnd);
3123 if (!wndPtr) return FALSE;
3124 hWnd = wndPtr->hwndSelf; /* make it a full handle */
3126 if (wndPtr->dwStyle & WS_MINIMIZE)
3128 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3130 HDC hDC = GetDC(hWnd);
3132 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM)hDC, 0 ))
3133 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
3135 ReleaseDC( hWnd, hDC );
3136 wndPtr->flags |= WIN_NCACTIVATED;
3138 else
3140 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3141 wndPtr->flags &= ~WIN_NCACTIVATED;
3143 WIN_ReleaseWndPtr(wndPtr);
3144 return TRUE;
3146 else
3148 WPARAM16 wparam;
3149 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3150 else wparam = (hWnd == GetForegroundWindow());
3152 WIN_ReleaseWndPtr(wndPtr);
3153 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3154 return wparam;
3158 /*******************************************************************
3159 * FlashWindowEx (USER32.@)
3161 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
3163 FIXME("%p\n", pfwi);
3164 return TRUE;
3167 /*******************************************************************
3168 * GetWindowContextHelpId (USER32.@)
3170 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3172 DWORD retval;
3173 WND *wnd = WIN_FindWndPtr( hwnd );
3174 if (!wnd) return 0;
3175 retval = wnd->helpContext;
3176 WIN_ReleaseWndPtr(wnd);
3177 return retval;
3181 /*******************************************************************
3182 * SetWindowContextHelpId (USER32.@)
3184 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3186 WND *wnd = WIN_FindWndPtr( hwnd );
3187 if (!wnd) return FALSE;
3188 wnd->helpContext = id;
3189 WIN_ReleaseWndPtr(wnd);
3190 return TRUE;
3194 /*******************************************************************
3195 * DragDetect (USER32.@)
3197 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3199 MSG msg;
3200 RECT rect;
3202 rect.left = pt.x - wDragWidth;
3203 rect.right = pt.x + wDragWidth;
3205 rect.top = pt.y - wDragHeight;
3206 rect.bottom = pt.y + wDragHeight;
3208 SetCapture(hWnd);
3210 while(1)
3212 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3214 if( msg.message == WM_LBUTTONUP )
3216 ReleaseCapture();
3217 return 0;
3219 if( msg.message == WM_MOUSEMOVE )
3221 POINT tmp;
3222 tmp.x = LOWORD(msg.lParam);
3223 tmp.y = HIWORD(msg.lParam);
3224 if( !PtInRect( &rect, tmp ))
3226 ReleaseCapture();
3227 return 1;
3231 WaitMessage();
3233 return 0;
3236 /******************************************************************************
3237 * GetWindowModuleFileNameA (USER32.@)
3239 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3241 FIXME("GetWindowModuleFileNameA(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3242 hwnd, lpszFileName, cchFileNameMax);
3243 return 0;
3246 /******************************************************************************
3247 * GetWindowModuleFileNameW (USER32.@)
3249 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR lpszFileName, UINT cchFileNameMax)
3251 FIXME("GetWindowModuleFileNameW(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3252 hwnd, lpszFileName, cchFileNameMax);
3253 return 0;
3256 /******************************************************************************
3257 * GetWindowInfo (USER32.@)
3259 * Note: tests show that Windows doesn't check cbSize of the structure.
3261 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3263 if (!pwi) return FALSE;
3264 if (!IsWindow(hwnd)) return FALSE;
3266 GetWindowRect(hwnd, &pwi->rcWindow);
3267 GetClientRect(hwnd, &pwi->rcClient);
3268 /* translate to screen coordinates */
3269 MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3271 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3272 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3273 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3275 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3276 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3278 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3279 pwi->wCreatorVersion = 0x0400;
3281 return TRUE;
3284 /******************************************************************************
3285 * SwitchDesktop (USER32.@)
3287 * NOTES: Sets the current input or interactive desktop.
3289 BOOL WINAPI SwitchDesktop( HDESK hDesktop)
3291 FIXME("SwitchDesktop(hwnd %p) stub!\n", hDesktop);
3292 return TRUE;