Avoid a few more uses of WIN_FindWndPtr.
[wine.git] / windows / win.c
blob354514567e16b76f1c1cb4d93c77266de310b933
1 /*
2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "config.h"
22 #include "wine/port.h"
24 #include <assert.h>
25 #include <stdarg.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include "windef.h"
29 #include "winbase.h"
30 #include "wine/winbase16.h"
31 #include "wine/winuser16.h"
32 #include "wownt32.h"
33 #include "wine/server.h"
34 #include "wine/unicode.h"
35 #include "win.h"
36 #include "user_private.h"
37 #include "dce.h"
38 #include "controls.h"
39 #include "cursoricon.h"
40 #include "message.h"
41 #include "winpos.h"
42 #include "winerror.h"
43 #include "wine/debug.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(win);
46 WINE_DECLARE_DEBUG_CHANNEL(msg);
48 #define NB_USER_HANDLES ((LAST_USER_HANDLE - FIRST_USER_HANDLE + 1) >> 1)
49 #define USER_HANDLE_TO_INDEX(hwnd) ((LOWORD(hwnd) - FIRST_USER_HANDLE) >> 1)
51 /**********************************************************************/
53 /* Desktop window */
54 static WND *pWndDesktop = NULL;
56 static WORD wDragWidth = 4;
57 static WORD wDragHeight= 3;
59 static void *user_handles[NB_USER_HANDLES];
61 /***********************************************************************
62 * create_window_handle
64 * Create a window handle with the server.
66 static WND *create_window_handle( HWND parent, HWND owner, ATOM atom,
67 HINSTANCE instance, WINDOWPROCTYPE type )
69 WORD index;
70 WND *win;
71 struct tagCLASS *class = NULL;
72 user_handle_t handle = 0;
73 int extra_bytes = 0;
75 /* if 16-bit instance, map to module handle */
76 if (instance && !HIWORD(instance))
77 instance = HINSTANCE_32(GetExePtr(HINSTANCE_16(instance)));
79 SERVER_START_REQ( create_window )
81 req->parent = parent;
82 req->owner = owner;
83 req->atom = atom;
84 req->instance = instance;
85 if (!wine_server_call_err( req ))
87 handle = reply->handle;
88 extra_bytes = reply->extra;
89 class = reply->class_ptr;
92 SERVER_END_REQ;
94 if (!handle)
96 WARN( "error %ld creating window\n", GetLastError() );
97 return NULL;
100 if (!(win = HeapAlloc( GetProcessHeap(), 0, sizeof(WND) + extra_bytes - sizeof(win->wExtra) )))
102 SERVER_START_REQ( destroy_window )
104 req->handle = handle;
105 wine_server_call( req );
107 SERVER_END_REQ;
108 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
109 return NULL;
112 USER_Lock();
114 index = USER_HANDLE_TO_INDEX(handle);
115 assert( index < NB_USER_HANDLES );
116 user_handles[index] = win;
117 win->hwndSelf = handle;
118 win->dwMagic = WND_MAGIC;
119 win->irefCount = 1;
120 win->cbWndExtra = extra_bytes;
121 memset( win->wExtra, 0, extra_bytes );
122 CLASS_AddWindow( class, win, type );
123 return win;
127 /***********************************************************************
128 * free_window_handle
130 * Free a window handle.
132 static WND *free_window_handle( HWND hwnd )
134 WND *ptr;
135 WORD index = USER_HANDLE_TO_INDEX(hwnd);
137 if (index >= NB_USER_HANDLES) return NULL;
138 USER_Lock();
139 if ((ptr = user_handles[index]))
141 SERVER_START_REQ( destroy_window )
143 req->handle = hwnd;
144 if (!wine_server_call_err( req ))
145 user_handles[index] = NULL;
146 else
147 ptr = NULL;
149 SERVER_END_REQ;
151 USER_Unlock();
152 HeapFree( GetProcessHeap(), 0, ptr );
153 return ptr;
157 /*******************************************************************
158 * list_window_children
160 * Build an array of the children of a given window. The array must be
161 * freed with HeapFree. Returns NULL when no windows are found.
163 static HWND *list_window_children( HWND hwnd, ATOM atom, DWORD tid )
165 HWND *list;
166 int size = 32;
168 for (;;)
170 int count = 0;
172 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
174 SERVER_START_REQ( get_window_children )
176 req->parent = hwnd;
177 req->atom = atom;
178 req->tid = tid;
179 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
180 if (!wine_server_call( req )) count = reply->count;
182 SERVER_END_REQ;
183 if (count && count < size)
185 list[count] = 0;
186 return list;
188 HeapFree( GetProcessHeap(), 0, list );
189 if (!count) break;
190 size = count + 1; /* restart with a large enough buffer */
192 return NULL;
196 /*******************************************************************
197 * 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 ULONG WIN_SetStyle( HWND hwnd, ULONG set_bits, ULONG clear_bits )
467 BOOL ok;
468 ULONG new_style, old_style = 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/%lx on other process window %p\n",
476 set_bits, clear_bits, hwnd );
477 return 0;
479 new_style = (win->dwStyle | set_bits) & ~clear_bits;
480 if (new_style == win->dwStyle)
482 WIN_ReleasePtr( win );
483 return new_style;
485 SERVER_START_REQ( set_window_info )
487 req->handle = hwnd;
488 req->flags = SET_WIN_STYLE;
489 req->style = new_style;
490 req->extra_offset = -1;
491 if ((ok = !wine_server_call( req )))
493 old_style = reply->old_style;
494 win->dwStyle = new_style;
497 SERVER_END_REQ;
498 WIN_ReleasePtr( win );
499 if (ok && USER_Driver.pSetWindowStyle) USER_Driver.pSetWindowStyle( hwnd, old_style );
500 return old_style;
504 /***********************************************************************
505 * WIN_SetExStyle
507 * Change the extended style of a window.
509 LONG WIN_SetExStyle( HWND hwnd, LONG style )
511 LONG ret = 0;
512 WND *win = WIN_GetPtr( hwnd );
514 if (!win) return 0;
515 if (win == WND_OTHER_PROCESS)
517 if (IsWindow(hwnd))
518 ERR( "cannot set exstyle %lx on other process window %p\n", style, hwnd );
519 return 0;
521 if (style == win->dwExStyle)
523 WIN_ReleasePtr( win );
524 return style;
526 SERVER_START_REQ( set_window_info )
528 req->handle = hwnd;
529 req->flags = SET_WIN_EXSTYLE;
530 req->ex_style = style;
531 req->extra_offset = -1;
532 if (!wine_server_call( req ))
534 ret = reply->old_ex_style;
535 win->dwExStyle = style;
538 SERVER_END_REQ;
539 WIN_ReleasePtr( win );
540 return ret;
544 /***********************************************************************
545 * WIN_GetRectangles
547 * Get the window and client rectangles.
549 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
551 WND *win = WIN_GetPtr( hwnd );
552 BOOL ret = TRUE;
554 if (!win) return FALSE;
555 if (win == WND_OTHER_PROCESS)
557 SERVER_START_REQ( get_window_rectangles )
559 req->handle = hwnd;
560 if ((ret = !wine_server_call( req )))
562 if (rectWindow)
564 rectWindow->left = reply->window.left;
565 rectWindow->top = reply->window.top;
566 rectWindow->right = reply->window.right;
567 rectWindow->bottom = reply->window.bottom;
569 if (rectClient)
571 rectClient->left = reply->client.left;
572 rectClient->top = reply->client.top;
573 rectClient->right = reply->client.right;
574 rectClient->bottom = reply->client.bottom;
578 SERVER_END_REQ;
580 else
582 if (rectWindow) *rectWindow = win->rectWindow;
583 if (rectClient) *rectClient = win->rectClient;
584 WIN_ReleasePtr( win );
586 return ret;
590 /***********************************************************************
591 * WIN_DestroyWindow
593 * Destroy storage associated to a window. "Internals" p.358
595 LRESULT WIN_DestroyWindow( HWND hwnd )
597 WND *wndPtr;
598 HWND *list;
600 TRACE("%p\n", hwnd );
602 if (!(hwnd = WIN_IsCurrentThread( hwnd )))
604 ERR( "window doesn't belong to current thread\n" );
605 return 0;
608 /* free child windows */
609 if ((list = WIN_ListChildren( hwnd )))
611 int i;
612 for (i = 0; list[i]; i++)
614 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
615 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
617 HeapFree( GetProcessHeap(), 0, list );
621 * Clear the update region to make sure no WM_PAINT messages will be
622 * generated for this window while processing the WM_NCDESTROY.
624 RedrawWindow( hwnd, NULL, 0,
625 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
628 * Send the WM_NCDESTROY to the window being destroyed.
630 SendMessageA( hwnd, WM_NCDESTROY, 0, 0);
632 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
634 WINPOS_CheckInternalPos( hwnd );
635 if( hwnd == GetCapture()) ReleaseCapture();
637 /* free resources associated with the window */
639 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
641 if (!(wndPtr->dwStyle & WS_CHILD))
643 HMENU menu = (HMENU)SetWindowLongPtrW( hwnd, GWLP_ID, 0 );
644 if (menu) DestroyMenu( menu );
646 if (wndPtr->hSysMenu)
648 DestroyMenu( wndPtr->hSysMenu );
649 wndPtr->hSysMenu = 0;
651 DCE_FreeWindowDCE( hwnd ); /* Always do this to catch orphaned DCs */
652 if (USER_Driver.pDestroyWindow) USER_Driver.pDestroyWindow( hwnd );
653 wndPtr->class = NULL;
654 wndPtr->dwMagic = 0; /* Mark it as invalid */
655 WIN_ReleaseWndPtr( wndPtr );
656 return 0;
659 /***********************************************************************
660 * WIN_DestroyThreadWindows
662 * Destroy all children of 'wnd' owned by the current thread.
663 * Return TRUE if something was done.
665 void WIN_DestroyThreadWindows( HWND hwnd )
667 HWND *list;
668 int i;
670 if (!(list = WIN_ListChildren( hwnd ))) return;
671 for (i = 0; list[i]; i++)
673 if (WIN_IsCurrentThread( list[i] ))
674 DestroyWindow( list[i] );
675 else
676 WIN_DestroyThreadWindows( list[i] );
678 HeapFree( GetProcessHeap(), 0, list );
681 /***********************************************************************
682 * WIN_CreateDesktopWindow
684 * Create the desktop window.
686 BOOL WIN_CreateDesktopWindow(void)
688 HWND hwndDesktop;
689 CREATESTRUCTA cs;
691 TRACE("Creating desktop window\n");
693 if (!WINPOS_CreateInternalPosAtom()) return FALSE;
695 pWndDesktop = create_window_handle( 0, 0, LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W );
696 if (!pWndDesktop) return FALSE;
697 hwndDesktop = pWndDesktop->hwndSelf;
699 pWndDesktop->tid = 0; /* nobody owns the desktop */
700 pWndDesktop->parent = 0;
701 pWndDesktop->owner = 0;
702 pWndDesktop->text = NULL;
703 pWndDesktop->pVScroll = NULL;
704 pWndDesktop->pHScroll = NULL;
705 pWndDesktop->helpContext = 0;
706 pWndDesktop->flags = 0;
707 pWndDesktop->hSysMenu = 0;
709 cs.lpCreateParams = NULL;
710 cs.hInstance = 0;
711 cs.hMenu = 0;
712 cs.hwndParent = 0;
713 cs.x = 0;
714 cs.y = 0;
715 cs.cx = GetSystemMetrics( SM_CXSCREEN );
716 cs.cy = GetSystemMetrics( SM_CYSCREEN );
717 cs.style = pWndDesktop->dwStyle;
718 cs.dwExStyle = pWndDesktop->dwExStyle;
719 cs.lpszName = NULL;
720 cs.lpszClass = DESKTOP_CLASS_ATOM;
722 SERVER_START_REQ( set_window_info )
724 req->handle = hwndDesktop;
725 req->flags = 0; /* don't set anything, just retrieve */
726 req->extra_offset = -1;
727 wine_server_call( req );
728 pWndDesktop->dwStyle = reply->old_style;
729 pWndDesktop->dwExStyle = reply->old_ex_style;
730 pWndDesktop->hInstance = (HINSTANCE)reply->old_instance;
731 pWndDesktop->userdata = (ULONG_PTR)reply->old_user_data;
732 pWndDesktop->wIDmenu = reply->old_id;
734 SERVER_END_REQ;
736 if (!USER_Driver.pCreateWindow || !USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE ))
738 WIN_ReleaseWndPtr( pWndDesktop );
739 return FALSE;
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;
829 /* Handle case where only the cy values is set to default */
830 else if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16)
832 RECT r;
833 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
834 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
838 else
840 /* neither x nor cx are default. Check the y values .
841 * In the trace we see Outlook and Outlook Express using
842 * cy set to CW_USEDEFAULT when opening the address book.
844 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16) {
845 RECT r;
846 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
847 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
848 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
853 /***********************************************************************
854 * dump_window_styles
856 static void dump_window_styles( DWORD style, DWORD exstyle )
858 TRACE( "style:" );
859 if(style & WS_POPUP) TRACE(" WS_POPUP");
860 if(style & WS_CHILD) TRACE(" WS_CHILD");
861 if(style & WS_MINIMIZE) TRACE(" WS_MINIMIZE");
862 if(style & WS_VISIBLE) TRACE(" WS_VISIBLE");
863 if(style & WS_DISABLED) TRACE(" WS_DISABLED");
864 if(style & WS_CLIPSIBLINGS) TRACE(" WS_CLIPSIBLINGS");
865 if(style & WS_CLIPCHILDREN) TRACE(" WS_CLIPCHILDREN");
866 if(style & WS_MAXIMIZE) TRACE(" WS_MAXIMIZE");
867 if((style & WS_CAPTION) == WS_CAPTION) TRACE(" WS_CAPTION");
868 else
870 if(style & WS_BORDER) TRACE(" WS_BORDER");
871 if(style & WS_DLGFRAME) TRACE(" WS_DLGFRAME");
873 if(style & WS_VSCROLL) TRACE(" WS_VSCROLL");
874 if(style & WS_HSCROLL) TRACE(" WS_HSCROLL");
875 if(style & WS_SYSMENU) TRACE(" WS_SYSMENU");
876 if(style & WS_THICKFRAME) TRACE(" WS_THICKFRAME");
877 if(style & WS_GROUP) TRACE(" WS_GROUP");
878 if(style & WS_TABSTOP) TRACE(" WS_TABSTOP");
879 if(style & WS_MINIMIZEBOX) TRACE(" WS_MINIMIZEBOX");
880 if(style & WS_MAXIMIZEBOX) TRACE(" WS_MAXIMIZEBOX");
882 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
883 #define DUMPED_STYLES \
884 (WS_POPUP | \
885 WS_CHILD | \
886 WS_MINIMIZE | \
887 WS_VISIBLE | \
888 WS_DISABLED | \
889 WS_CLIPSIBLINGS | \
890 WS_CLIPCHILDREN | \
891 WS_MAXIMIZE | \
892 WS_BORDER | \
893 WS_DLGFRAME | \
894 WS_VSCROLL | \
895 WS_HSCROLL | \
896 WS_SYSMENU | \
897 WS_THICKFRAME | \
898 WS_GROUP | \
899 WS_TABSTOP | \
900 WS_MINIMIZEBOX | \
901 WS_MAXIMIZEBOX)
903 if(style & ~DUMPED_STYLES) TRACE(" %08lx", style & ~DUMPED_STYLES);
904 TRACE("\n");
905 #undef DUMPED_STYLES
907 TRACE( "exstyle:" );
908 if(exstyle & WS_EX_DLGMODALFRAME) TRACE(" WS_EX_DLGMODALFRAME");
909 if(exstyle & WS_EX_DRAGDETECT) TRACE(" WS_EX_DRAGDETECT");
910 if(exstyle & WS_EX_NOPARENTNOTIFY) TRACE(" WS_EX_NOPARENTNOTIFY");
911 if(exstyle & WS_EX_TOPMOST) TRACE(" WS_EX_TOPMOST");
912 if(exstyle & WS_EX_ACCEPTFILES) TRACE(" WS_EX_ACCEPTFILES");
913 if(exstyle & WS_EX_TRANSPARENT) TRACE(" WS_EX_TRANSPARENT");
914 if(exstyle & WS_EX_MDICHILD) TRACE(" WS_EX_MDICHILD");
915 if(exstyle & WS_EX_TOOLWINDOW) TRACE(" WS_EX_TOOLWINDOW");
916 if(exstyle & WS_EX_WINDOWEDGE) TRACE(" WS_EX_WINDOWEDGE");
917 if(exstyle & WS_EX_CLIENTEDGE) TRACE(" WS_EX_CLIENTEDGE");
918 if(exstyle & WS_EX_CONTEXTHELP) TRACE(" WS_EX_CONTEXTHELP");
919 if(exstyle & WS_EX_RIGHT) TRACE(" WS_EX_RIGHT");
920 if(exstyle & WS_EX_RTLREADING) TRACE(" WS_EX_RTLREADING");
921 if(exstyle & WS_EX_LEFTSCROLLBAR) TRACE(" WS_EX_LEFTSCROLLBAR");
922 if(exstyle & WS_EX_CONTROLPARENT) TRACE(" WS_EX_CONTROLPARENT");
923 if(exstyle & WS_EX_STATICEDGE) TRACE(" WS_EX_STATICEDGE");
924 if(exstyle & WS_EX_APPWINDOW) TRACE(" WS_EX_APPWINDOW");
925 if(exstyle & WS_EX_LAYERED) TRACE(" WS_EX_LAYERED");
927 #define DUMPED_EX_STYLES \
928 (WS_EX_DLGMODALFRAME | \
929 WS_EX_DRAGDETECT | \
930 WS_EX_NOPARENTNOTIFY | \
931 WS_EX_TOPMOST | \
932 WS_EX_ACCEPTFILES | \
933 WS_EX_TRANSPARENT | \
934 WS_EX_MDICHILD | \
935 WS_EX_TOOLWINDOW | \
936 WS_EX_WINDOWEDGE | \
937 WS_EX_CLIENTEDGE | \
938 WS_EX_CONTEXTHELP | \
939 WS_EX_RIGHT | \
940 WS_EX_RTLREADING | \
941 WS_EX_LEFTSCROLLBAR | \
942 WS_EX_CONTROLPARENT | \
943 WS_EX_STATICEDGE | \
944 WS_EX_APPWINDOW | \
945 WS_EX_LAYERED)
947 if(exstyle & ~DUMPED_EX_STYLES) TRACE(" %08lx", exstyle & ~DUMPED_EX_STYLES);
948 TRACE("\n");
949 #undef DUMPED_EX_STYLES
953 /***********************************************************************
954 * WIN_CreateWindowEx
956 * Implementation of CreateWindowEx().
958 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
959 WINDOWPROCTYPE type )
961 INT sw = SW_SHOW;
962 WND *wndPtr;
963 HWND hwnd, parent, owner, top_child = 0;
964 BOOL unicode = (type == WIN_PROC_32W);
966 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
967 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
968 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszClass) : debugstr_a(cs->lpszClass),
969 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
970 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
972 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
974 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
975 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
977 /* Fix the styles for MDI children */
978 if (cs->dwExStyle & WS_EX_MDICHILD)
980 MDICREATESTRUCTA mdi_cs;
981 UINT flags = 0;
983 wndPtr = WIN_GetPtr(cs->hwndParent);
984 if (wndPtr && wndPtr != WND_OTHER_PROCESS)
986 flags = wndPtr->flags;
987 WIN_ReleasePtr(wndPtr);
990 if (!(flags & WIN_ISMDICLIENT))
992 WARN("WS_EX_MDICHILD, but parent %p is not MDIClient\n", cs->hwndParent);
993 return 0;
996 /* cs->lpCreateParams of WM_[NC]CREATE is different for MDI children.
997 * MDICREATESTRUCT members have the originally passed values.
999 * Note: we rely on the fact that MDICREATESTRUCTA and MDICREATESTRUCTW
1000 * have the same layout.
1002 mdi_cs.szClass = cs->lpszClass;
1003 mdi_cs.szTitle = cs->lpszName;
1004 mdi_cs.hOwner = cs->hInstance;
1005 mdi_cs.x = cs->x;
1006 mdi_cs.y = cs->y;
1007 mdi_cs.cx = cs->cx;
1008 mdi_cs.cy = cs->cy;
1009 mdi_cs.style = cs->style;
1010 mdi_cs.lParam = (LPARAM)cs->lpCreateParams;
1012 cs->lpCreateParams = (LPVOID)&mdi_cs;
1014 if (GetWindowLongW(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
1016 if (cs->style & WS_POPUP)
1018 TRACE("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n");
1019 return 0;
1021 cs->style |= WS_CHILD | WS_CLIPSIBLINGS;
1023 else
1025 cs->style &= ~WS_POPUP;
1026 cs->style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
1027 WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
1030 top_child = GetWindow(cs->hwndParent, GW_CHILD);
1032 if (top_child)
1034 /* Restore current maximized child */
1035 if((cs->style & WS_VISIBLE) && IsZoomed(top_child))
1037 TRACE("Restoring current maximized child %p\n", top_child);
1038 SendMessageW( top_child, WM_SETREDRAW, FALSE, 0 );
1039 ShowWindow(top_child, SW_RESTORE);
1040 SendMessageW( top_child, WM_SETREDRAW, TRUE, 0 );
1045 /* Find the parent window */
1047 parent = GetDesktopWindow();
1048 owner = 0;
1050 if (cs->hwndParent == HWND_MESSAGE)
1052 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
1053 * message window (style: WS_POPUP|WS_DISABLED)
1055 FIXME("Parent is HWND_MESSAGE\n");
1057 else if (cs->hwndParent)
1059 /* Make sure parent is valid */
1060 if (!IsWindow( cs->hwndParent ))
1062 WARN("Bad parent %p\n", cs->hwndParent );
1063 return 0;
1065 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1066 parent = WIN_GetFullHandle(cs->hwndParent);
1067 else
1068 owner = GetAncestor( cs->hwndParent, GA_ROOT );
1070 else if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1072 WARN("No parent for child window\n" );
1073 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1076 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
1078 /* Correct the window styles.
1080 * It affects both the style loaded into the WIN structure and
1081 * passed in the CREATESTRUCT to the WM_[NC]CREATE.
1083 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1084 * why does the user get to set it?
1087 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
1088 * tested for WS_POPUP
1090 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
1091 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
1092 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
1093 cs->dwExStyle |= WS_EX_WINDOWEDGE;
1094 else
1095 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
1097 if (!(cs->style & WS_CHILD))
1099 cs->style |= WS_CLIPSIBLINGS;
1100 if (!(cs->style & WS_POPUP))
1101 cs->style |= WS_CAPTION;
1104 /* Create the window structure */
1106 if (!(wndPtr = create_window_handle( parent, owner, classAtom, cs->hInstance, type )))
1108 TRACE("out of memory\n" );
1109 return 0;
1111 hwnd = wndPtr->hwndSelf;
1113 /* Fill the window structure */
1115 wndPtr->tid = GetCurrentThreadId();
1116 wndPtr->owner = owner;
1117 wndPtr->parent = parent;
1118 wndPtr->hInstance = cs->hInstance;
1119 wndPtr->text = NULL;
1120 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1121 wndPtr->dwExStyle = cs->dwExStyle;
1122 wndPtr->wIDmenu = 0;
1123 wndPtr->helpContext = 0;
1124 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
1125 wndPtr->pVScroll = NULL;
1126 wndPtr->pHScroll = NULL;
1127 wndPtr->userdata = 0;
1128 wndPtr->hIcon = 0;
1129 wndPtr->hIconSmall = 0;
1130 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU) ? MENU_GetSysMenu( hwnd, 0 ) : 0;
1132 if (!(cs->style & (WS_CHILD | WS_POPUP)))
1133 wndPtr->flags |= WIN_NEED_SIZE;
1135 SERVER_START_REQ( set_window_info )
1137 req->handle = hwnd;
1138 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE;
1139 req->style = wndPtr->dwStyle;
1140 req->ex_style = wndPtr->dwExStyle;
1141 req->instance = (void *)wndPtr->hInstance;
1142 req->extra_offset = -1;
1143 wine_server_call( req );
1145 SERVER_END_REQ;
1147 /* Get class or window DC if needed */
1149 if (wndPtr->clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
1151 /* Set the window menu */
1153 if (((wndPtr->dwStyle & (WS_CAPTION|WS_CHILD)) == WS_CAPTION) ||
1154 (wndPtr->dwExStyle & WS_EX_APPWINDOW))
1156 if (cs->hMenu) MENU_SetMenu(hwnd, cs->hMenu);
1157 else
1159 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
1160 if (menuName)
1162 if (HIWORD(cs->hInstance))
1163 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1164 else
1165 cs->hMenu = HMENU_32(LoadMenu16(HINSTANCE_16(cs->hInstance),menuName));
1167 if (cs->hMenu) MENU_SetMenu( hwnd, cs->hMenu );
1171 else SetWindowLongPtrW( hwnd, GWLP_ID, (ULONG_PTR)cs->hMenu );
1172 WIN_ReleaseWndPtr( wndPtr );
1174 if (!USER_Driver.pCreateWindow || !USER_Driver.pCreateWindow( hwnd, cs, unicode))
1176 WIN_DestroyWindow( hwnd );
1177 return 0;
1180 /* Notify the parent window only */
1182 send_parent_notify( hwnd, WM_CREATE );
1183 if (!IsWindow( hwnd )) return 0;
1185 if (cs->style & WS_VISIBLE)
1187 if (cs->style & WS_MAXIMIZE)
1188 sw = SW_SHOWMAXIMIZED;
1189 else if (cs->style & WS_MINIMIZE)
1190 sw = SW_SHOWMINIMIZED;
1192 ShowWindow( hwnd, sw );
1193 if (cs->dwExStyle & WS_EX_MDICHILD)
1195 SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
1196 /* ShowWindow won't activate child windows */
1197 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE );
1201 /* Call WH_SHELL hook */
1203 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1204 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1206 TRACE("created window %p\n", hwnd);
1207 return hwnd;
1211 /***********************************************************************
1212 * CreateWindow (USER.41)
1214 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1215 DWORD style, INT16 x, INT16 y, INT16 width,
1216 INT16 height, HWND16 parent, HMENU16 menu,
1217 HINSTANCE16 instance, LPVOID data )
1219 return CreateWindowEx16( 0, className, windowName, style,
1220 x, y, width, height, parent, menu, instance, data );
1224 /***********************************************************************
1225 * CreateWindowEx (USER.452)
1227 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1228 LPCSTR windowName, DWORD style, INT16 x,
1229 INT16 y, INT16 width, INT16 height,
1230 HWND16 parent, HMENU16 menu,
1231 HINSTANCE16 instance, LPVOID data )
1233 ATOM classAtom;
1234 CREATESTRUCTA cs;
1235 char buffer[256];
1237 /* Find the class atom */
1239 if (HIWORD(className))
1241 if (!(classAtom = GlobalFindAtomA( className )))
1243 ERR( "bad class name %s\n", debugstr_a(className) );
1244 return 0;
1247 else
1249 classAtom = LOWORD(className);
1250 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1252 ERR( "bad atom %x\n", classAtom);
1253 return 0;
1255 className = buffer;
1258 /* Fix the coordinates */
1260 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1261 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1262 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1263 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1265 /* Create the window */
1267 cs.lpCreateParams = data;
1268 cs.hInstance = HINSTANCE_32(instance);
1269 cs.hMenu = HMENU_32(menu);
1270 cs.hwndParent = WIN_Handle32( parent );
1271 cs.style = style;
1272 cs.lpszName = windowName;
1273 cs.lpszClass = className;
1274 cs.dwExStyle = exStyle;
1276 return HWND_16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
1280 /***********************************************************************
1281 * CreateWindowExA (USER32.@)
1283 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1284 LPCSTR windowName, DWORD style, INT x,
1285 INT y, INT width, INT height,
1286 HWND parent, HMENU menu,
1287 HINSTANCE instance, LPVOID data )
1289 ATOM classAtom;
1290 CREATESTRUCTA cs;
1291 char buffer[256];
1293 /* Find the class atom */
1295 if (HIWORD(className))
1297 if (!(classAtom = GlobalFindAtomA( className )))
1299 ERR( "bad class name %s\n", debugstr_a(className) );
1300 return 0;
1303 else
1305 classAtom = LOWORD(className);
1306 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1308 ERR( "bad atom %x\n", classAtom);
1309 return 0;
1311 className = buffer;
1314 /* Create the window */
1316 cs.lpCreateParams = data;
1317 cs.hInstance = instance;
1318 cs.hMenu = menu;
1319 cs.hwndParent = parent;
1320 cs.x = x;
1321 cs.y = y;
1322 cs.cx = width;
1323 cs.cy = height;
1324 cs.style = style;
1325 cs.lpszName = windowName;
1326 cs.lpszClass = className;
1327 cs.dwExStyle = exStyle;
1329 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1333 /***********************************************************************
1334 * CreateWindowExW (USER32.@)
1336 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1337 LPCWSTR windowName, DWORD style, INT x,
1338 INT y, INT width, INT height,
1339 HWND parent, HMENU menu,
1340 HINSTANCE instance, LPVOID data )
1342 ATOM classAtom;
1343 CREATESTRUCTW cs;
1344 WCHAR buffer[256];
1346 /* Find the class atom */
1348 if (HIWORD(className))
1350 if (!(classAtom = GlobalFindAtomW( className )))
1352 ERR( "bad class name %s\n", debugstr_w(className) );
1353 return 0;
1356 else
1358 classAtom = LOWORD(className);
1359 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1361 ERR( "bad atom %x\n", classAtom);
1362 return 0;
1364 className = buffer;
1367 /* Create the window */
1369 cs.lpCreateParams = data;
1370 cs.hInstance = instance;
1371 cs.hMenu = menu;
1372 cs.hwndParent = parent;
1373 cs.x = x;
1374 cs.y = y;
1375 cs.cx = width;
1376 cs.cy = height;
1377 cs.style = style;
1378 cs.lpszName = windowName;
1379 cs.lpszClass = className;
1380 cs.dwExStyle = exStyle;
1382 /* Note: we rely on the fact that CREATESTRUCTA and */
1383 /* CREATESTRUCTW have the same layout. */
1384 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1388 /***********************************************************************
1389 * WIN_SendDestroyMsg
1391 static void WIN_SendDestroyMsg( HWND hwnd )
1393 GUITHREADINFO info;
1395 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1397 if (hwnd == info.hwndCaret) DestroyCaret();
1398 if (hwnd == info.hwndActive) WINPOS_ActivateOtherWindow( hwnd );
1400 if (USER_Driver.pResetSelectionOwner)
1401 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1404 * Send the WM_DESTROY to the window.
1406 SendMessageA( hwnd, WM_DESTROY, 0, 0);
1409 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1410 * make sure that the window still exists when we come back.
1412 if (IsWindow(hwnd))
1414 HWND* pWndArray;
1415 int i;
1417 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1419 /* start from the end (FIXME: is this needed?) */
1420 for (i = 0; pWndArray[i]; i++) ;
1422 while (--i >= 0)
1424 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1426 HeapFree( GetProcessHeap(), 0, pWndArray );
1428 else
1429 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1433 /***********************************************************************
1434 * DestroyWindow (USER32.@)
1436 BOOL WINAPI DestroyWindow( HWND hwnd )
1438 BOOL is_child;
1440 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1442 SetLastError( ERROR_ACCESS_DENIED );
1443 return FALSE;
1446 TRACE("(%p)\n", hwnd);
1448 /* Call hooks */
1450 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1452 if (MENU_IsMenuActive() == hwnd)
1453 EndMenu();
1455 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1457 if (is_child)
1459 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1460 send_parent_notify( hwnd, WM_DESTROY );
1462 else if (!GetWindow( hwnd, GW_OWNER ))
1464 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1465 /* FIXME: clean up palette - see "Internals" p.352 */
1468 if (!IsWindow(hwnd)) return TRUE;
1470 if (USER_Driver.pResetSelectionOwner)
1471 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1473 /* Hide the window */
1475 /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
1476 if (is_child)
1477 ShowWindow( hwnd, SW_HIDE );
1478 else
1479 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1480 SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW );
1482 if (!IsWindow(hwnd)) return TRUE;
1484 /* Recursively destroy owned windows */
1486 if (!is_child)
1488 for (;;)
1490 int i, got_one = 0;
1491 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1492 if (list)
1494 for (i = 0; list[i]; i++)
1496 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1497 if (WIN_IsCurrentThread( list[i] ))
1499 DestroyWindow( list[i] );
1500 got_one = 1;
1501 continue;
1503 WIN_SetOwner( list[i], 0 );
1505 HeapFree( GetProcessHeap(), 0, list );
1507 if (!got_one) break;
1511 /* Send destroy messages */
1513 WIN_SendDestroyMsg( hwnd );
1514 if (!IsWindow( hwnd )) return TRUE;
1516 if (GetClipboardOwner() == hwnd)
1517 CLIPBOARD_ReleaseOwner();
1519 /* Unlink now so we won't bother with the children later on */
1521 WIN_UnlinkWindow( hwnd );
1523 /* Destroy the window storage */
1525 WIN_DestroyWindow( hwnd );
1526 return TRUE;
1530 /***********************************************************************
1531 * CloseWindow (USER32.@)
1533 BOOL WINAPI CloseWindow( HWND hwnd )
1535 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1536 ShowWindow( hwnd, SW_MINIMIZE );
1537 return TRUE;
1541 /***********************************************************************
1542 * OpenIcon (USER32.@)
1544 BOOL WINAPI OpenIcon( HWND hwnd )
1546 if (!IsIconic( hwnd )) return FALSE;
1547 ShowWindow( hwnd, SW_SHOWNORMAL );
1548 return TRUE;
1552 /***********************************************************************
1553 * WIN_FindWindow
1555 * Implementation of FindWindow() and FindWindowEx().
1557 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1559 HWND *list = NULL;
1560 HWND retvalue = 0;
1561 int i = 0, len = 0;
1562 WCHAR *buffer = NULL;
1564 if (!parent) parent = GetDesktopWindow();
1565 if (title)
1567 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1568 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1571 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1573 if (child)
1575 child = WIN_GetFullHandle( child );
1576 while (list[i] && list[i] != child) i++;
1577 if (!list[i]) goto done;
1578 i++; /* start from next window */
1581 if (title)
1583 while (list[i])
1585 if (GetWindowTextW( list[i], buffer, len + 1 ) && !strcmpiW( buffer, title )) break;
1586 i++;
1589 retvalue = list[i];
1591 done:
1592 HeapFree( GetProcessHeap(), 0, list );
1593 HeapFree( GetProcessHeap(), 0, buffer );
1594 return retvalue;
1599 /***********************************************************************
1600 * FindWindowA (USER32.@)
1602 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1604 HWND ret = FindWindowExA( 0, 0, className, title );
1605 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1606 return ret;
1610 /***********************************************************************
1611 * FindWindowExA (USER32.@)
1613 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1614 LPCSTR className, LPCSTR title )
1616 ATOM atom = 0;
1617 LPWSTR buffer;
1618 HWND hwnd;
1619 INT len;
1621 if (className)
1623 /* If the atom doesn't exist, then no class */
1624 /* with this name exists either. */
1625 if (!(atom = GlobalFindAtomA( className )))
1627 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1628 return 0;
1631 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
1633 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1634 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1635 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
1636 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1637 HeapFree( GetProcessHeap(), 0, buffer );
1638 return hwnd;
1642 /***********************************************************************
1643 * FindWindowExW (USER32.@)
1645 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1646 LPCWSTR className, LPCWSTR title )
1648 ATOM atom = 0;
1650 if (className)
1652 /* If the atom doesn't exist, then no class */
1653 /* with this name exists either. */
1654 if (!(atom = GlobalFindAtomW( className )))
1656 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1657 return 0;
1660 return WIN_FindWindow( parent, child, atom, title );
1664 /***********************************************************************
1665 * FindWindowW (USER32.@)
1667 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1669 return FindWindowExW( 0, 0, className, title );
1673 /**********************************************************************
1674 * GetDesktopWindow (USER32.@)
1676 HWND WINAPI GetDesktopWindow(void)
1678 if (pWndDesktop) return pWndDesktop->hwndSelf;
1679 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" );
1680 ExitProcess(1);
1681 return 0;
1685 /*******************************************************************
1686 * EnableWindow (USER32.@)
1688 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1690 BOOL retvalue;
1691 HWND full_handle;
1693 if (is_broadcast(hwnd))
1695 SetLastError( ERROR_INVALID_PARAMETER );
1696 return FALSE;
1699 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1700 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1702 hwnd = full_handle;
1704 TRACE("( %p, %d )\n", hwnd, enable);
1706 retvalue = !IsWindowEnabled( hwnd );
1708 if (enable && retvalue)
1710 WIN_SetStyle( hwnd, 0, WS_DISABLED );
1711 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1713 else if (!enable && !retvalue)
1715 HWND capture_wnd;
1717 SendMessageA( hwnd, WM_CANCELMODE, 0, 0);
1719 WIN_SetStyle( hwnd, WS_DISABLED, 0 );
1721 if (hwnd == GetFocus())
1722 SetFocus( 0 ); /* A disabled window can't have the focus */
1724 capture_wnd = GetCapture();
1725 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1726 ReleaseCapture(); /* A disabled window can't capture the mouse */
1728 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1730 return retvalue;
1734 /***********************************************************************
1735 * IsWindowEnabled (USER32.@)
1737 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1739 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1743 /***********************************************************************
1744 * IsWindowUnicode (USER32.@)
1746 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1748 WND * wndPtr;
1749 BOOL retvalue;
1751 if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return FALSE;
1752 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1753 WIN_ReleasePtr( wndPtr );
1754 return retvalue;
1758 /**********************************************************************
1759 * GetWindowWord (USER32.@)
1761 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1763 if (offset >= 0)
1765 WORD retvalue = 0;
1766 WND *wndPtr = WIN_GetPtr( hwnd );
1767 if (!wndPtr)
1769 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1770 return 0;
1772 if (wndPtr == WND_OTHER_PROCESS)
1774 SERVER_START_REQ( set_window_info )
1776 req->handle = hwnd;
1777 req->flags = 0; /* don't set anything, just retrieve */
1778 req->extra_offset = offset;
1779 req->extra_size = sizeof(retvalue);
1780 if (!wine_server_call_err( req ))
1781 memcpy( &retvalue, &reply->old_extra_value, sizeof(retvalue) );
1783 SERVER_END_REQ;
1784 return retvalue;
1786 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1788 WARN("Invalid offset %d\n", offset );
1789 SetLastError( ERROR_INVALID_INDEX );
1791 else memcpy( &retvalue, (char *)wndPtr->wExtra + offset, sizeof(retvalue) );
1792 WIN_ReleasePtr( wndPtr );
1793 return retvalue;
1796 switch(offset)
1798 case GWLP_HWNDPARENT:
1799 return GetWindowLongPtrW( hwnd, offset );
1800 case GWLP_ID:
1801 case GWLP_HINSTANCE:
1803 LONG_PTR ret = GetWindowLongPtrW( hwnd, offset );
1804 if (HIWORD(ret))
1805 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1806 return LOWORD(ret);
1808 default:
1809 WARN("Invalid offset %d\n", offset );
1810 return 0;
1815 /**********************************************************************
1816 * SetWindowWord (USER32.@)
1818 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1820 WORD retval = 0;
1821 WND * wndPtr;
1823 switch(offset)
1825 case GWLP_ID:
1826 case GWLP_HINSTANCE:
1827 case GWLP_HWNDPARENT:
1828 return SetWindowLongPtrW( hwnd, offset, (ULONG_PTR)newval );
1829 default:
1830 if (offset < 0)
1832 WARN("Invalid offset %d\n", offset );
1833 SetLastError( ERROR_INVALID_INDEX );
1834 return 0;
1838 wndPtr = WIN_GetPtr( hwnd );
1839 if (wndPtr == WND_OTHER_PROCESS)
1841 if (IsWindow(hwnd))
1842 FIXME( "set %d <- %x not supported yet on other process window %p\n",
1843 offset, newval, hwnd );
1844 wndPtr = NULL;
1846 if (!wndPtr)
1848 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1849 return 0;
1852 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1854 WARN("Invalid offset %d\n", offset );
1855 WIN_ReleasePtr(wndPtr);
1856 SetLastError( ERROR_INVALID_INDEX );
1857 return 0;
1860 SERVER_START_REQ( set_window_info )
1862 req->handle = hwnd;
1863 req->flags = SET_WIN_EXTRA;
1864 req->extra_offset = offset;
1865 req->extra_size = sizeof(newval);
1866 memcpy( &req->extra_value, &newval, sizeof(newval) );
1867 if (!wine_server_call_err( req ))
1869 void *ptr = (char *)wndPtr->wExtra + offset;
1870 memcpy( &retval, ptr, sizeof(retval) );
1871 memcpy( ptr, &newval, sizeof(newval) );
1874 SERVER_END_REQ;
1875 WIN_ReleasePtr( wndPtr );
1876 return retval;
1880 /**********************************************************************
1881 * WIN_GetWindowLong
1883 * Helper function for GetWindowLong().
1885 static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1887 LONG_PTR retvalue = 0;
1888 WND *wndPtr;
1890 if (offset == GWLP_HWNDPARENT)
1892 HWND parent = GetAncestor( hwnd, GA_PARENT );
1893 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1894 return (ULONG_PTR)parent;
1897 if (!(wndPtr = WIN_GetPtr( hwnd )))
1899 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1900 return 0;
1903 if (wndPtr == WND_OTHER_PROCESS)
1905 if (offset == GWLP_WNDPROC)
1907 SetLastError( ERROR_ACCESS_DENIED );
1908 return 0;
1910 SERVER_START_REQ( set_window_info )
1912 req->handle = hwnd;
1913 req->flags = 0; /* don't set anything, just retrieve */
1914 req->extra_offset = (offset >= 0) ? offset : -1;
1915 req->extra_size = (offset >= 0) ? sizeof(retvalue) : 0;
1916 if (!wine_server_call_err( req ))
1918 switch(offset)
1920 case GWL_STYLE: retvalue = reply->old_style; break;
1921 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1922 case GWLP_ID: retvalue = reply->old_id; break;
1923 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1924 case GWLP_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
1925 default:
1926 if (offset >= 0) retvalue = reply->old_extra_value;
1927 else SetLastError( ERROR_INVALID_INDEX );
1928 break;
1932 SERVER_END_REQ;
1933 return retvalue;
1936 /* now we have a valid wndPtr */
1938 if (offset >= 0)
1940 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
1943 * Some programs try to access last element from 16 bit
1944 * code using illegal offset value. Hopefully this is
1945 * what those programs really expect.
1947 if (type == WIN_PROC_16 &&
1948 wndPtr->cbWndExtra >= 4 &&
1949 offset == wndPtr->cbWndExtra - sizeof(WORD))
1951 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
1953 ERR( "- replaced invalid offset %d with %d\n",
1954 offset, offset2 );
1956 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset2);
1957 WIN_ReleasePtr( wndPtr );
1958 return retvalue;
1960 WARN("Invalid offset %d\n", offset );
1961 WIN_ReleasePtr( wndPtr );
1962 SetLastError( ERROR_INVALID_INDEX );
1963 return 0;
1965 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1966 /* Special case for dialog window procedure */
1967 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1968 retvalue = (LONG)WINPROC_GetProc( (WNDPROC)retvalue, type );
1969 WIN_ReleasePtr( wndPtr );
1970 return retvalue;
1973 switch(offset)
1975 case GWLP_USERDATA: retvalue = wndPtr->userdata; break;
1976 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1977 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1978 case GWLP_ID: retvalue = (ULONG_PTR)wndPtr->wIDmenu; break;
1979 case GWLP_WNDPROC: retvalue = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, type ); break;
1980 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wndPtr->hInstance; break;
1981 default:
1982 WARN("Unknown offset %d\n", offset );
1983 SetLastError( ERROR_INVALID_INDEX );
1984 break;
1986 WIN_ReleasePtr(wndPtr);
1987 return retvalue;
1991 /**********************************************************************
1992 * WIN_SetWindowLong
1994 * Helper function for SetWindowLong().
1996 * 0 is the failure code. However, in the case of failure SetLastError
1997 * must be set to distinguish between a 0 return value and a failure.
1999 static LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, LONG_PTR newval,
2000 WINDOWPROCTYPE type )
2002 STYLESTRUCT style;
2003 BOOL ok;
2004 LONG retval = 0;
2005 WND *wndPtr;
2007 TRACE( "%p %d %lx %x\n", hwnd, offset, newval, type );
2009 if (is_broadcast(hwnd))
2011 SetLastError( ERROR_INVALID_PARAMETER );
2012 return FALSE;
2014 if (!WIN_IsCurrentProcess( hwnd ))
2016 if (offset == GWLP_WNDPROC)
2018 SetLastError( ERROR_ACCESS_DENIED );
2019 return 0;
2021 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
2024 wndPtr = WIN_GetPtr( hwnd );
2025 if (wndPtr->hwndSelf == GetDesktopWindow())
2027 /* can't change anything on the desktop window */
2028 WIN_ReleasePtr( wndPtr );
2029 SetLastError( ERROR_ACCESS_DENIED );
2030 return 0;
2033 /* first some special cases */
2034 switch( offset )
2036 case GWL_STYLE:
2037 case GWL_EXSTYLE:
2038 style.styleOld =
2039 offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
2040 style.styleNew = newval;
2041 WIN_ReleasePtr( wndPtr );
2042 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
2043 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
2044 newval = style.styleNew;
2045 break;
2046 case GWLP_HWNDPARENT:
2047 if (wndPtr->parent == GetDesktopWindow())
2049 WIN_ReleasePtr( wndPtr );
2050 return (ULONG_PTR)WIN_SetOwner( hwnd, (HWND)newval );
2052 else
2054 WIN_ReleasePtr( wndPtr );
2055 return (ULONG_PTR)SetParent( hwnd, (HWND)newval );
2057 case GWLP_WNDPROC:
2058 retval = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, type );
2059 wndPtr->winproc = WINPROC_AllocProc( (WNDPROC)newval, type );
2060 WIN_ReleasePtr( wndPtr );
2061 return retval;
2062 case GWLP_ID:
2063 case GWLP_HINSTANCE:
2064 case GWLP_USERDATA:
2065 break;
2066 case DWLP_DLGPROC:
2067 if ((wndPtr->cbWndExtra + sizeof(LONG) >= DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2069 WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWLP_DLGPROC);
2070 retval = (ULONG_PTR)WINPROC_GetProc( *ptr, type );
2071 *ptr = WINPROC_AllocProc( (WNDPROC)newval, type );
2072 WIN_ReleasePtr( wndPtr );
2073 return retval;
2075 /* fall through */
2076 default:
2077 if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
2079 WARN("Invalid offset %d\n", offset );
2080 WIN_ReleasePtr( wndPtr );
2081 SetLastError( ERROR_INVALID_INDEX );
2082 return 0;
2084 else
2086 LONG_PTR *ptr = (LONG_PTR *)((char *)wndPtr->wExtra + offset);
2087 if (*ptr == newval) /* already set to the same value */
2089 WIN_ReleasePtr( wndPtr );
2090 return newval;
2093 break;
2096 SERVER_START_REQ( set_window_info )
2098 req->handle = hwnd;
2099 req->extra_offset = -1;
2100 switch(offset)
2102 case GWL_STYLE:
2103 req->flags = SET_WIN_STYLE;
2104 req->style = newval;
2105 break;
2106 case GWL_EXSTYLE:
2107 req->flags = SET_WIN_EXSTYLE;
2108 req->ex_style = newval;
2109 break;
2110 case GWLP_ID:
2111 req->flags = SET_WIN_ID;
2112 req->id = newval;
2113 break;
2114 case GWLP_HINSTANCE:
2115 req->flags = SET_WIN_INSTANCE;
2116 req->instance = (void *)newval;
2117 break;
2118 case GWLP_USERDATA:
2119 req->flags = SET_WIN_USERDATA;
2120 req->user_data = (void *)newval;
2121 break;
2122 default:
2123 req->flags = SET_WIN_EXTRA;
2124 req->extra_offset = offset;
2125 req->extra_size = sizeof(newval);
2126 memcpy( &req->extra_value, &newval, sizeof(newval) );
2128 if ((ok = !wine_server_call_err( req )))
2130 switch(offset)
2132 case GWL_STYLE:
2133 wndPtr->dwStyle = newval;
2134 retval = reply->old_style;
2135 break;
2136 case GWL_EXSTYLE:
2137 wndPtr->dwExStyle = newval;
2138 retval = reply->old_ex_style;
2139 break;
2140 case GWLP_ID:
2141 wndPtr->wIDmenu = newval;
2142 retval = reply->old_id;
2143 break;
2144 case GWLP_HINSTANCE:
2145 wndPtr->hInstance = (HINSTANCE)newval;
2146 retval = (ULONG_PTR)reply->old_instance;
2147 break;
2148 case GWLP_USERDATA:
2149 wndPtr->userdata = newval;
2150 retval = (ULONG_PTR)reply->old_user_data;
2151 break;
2152 default:
2154 void *ptr = (char *)wndPtr->wExtra + offset;
2155 memcpy( &retval, ptr, sizeof(retval) );
2156 memcpy( ptr, &newval, sizeof(newval) );
2158 break;
2162 SERVER_END_REQ;
2163 WIN_ReleasePtr( wndPtr );
2165 if (!ok) return 0;
2167 if (offset == GWL_STYLE && USER_Driver.pSetWindowStyle)
2168 USER_Driver.pSetWindowStyle( hwnd, retval );
2170 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2171 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2173 return retval;
2177 /**********************************************************************
2178 * GetWindowLong (USER.135)
2180 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2182 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
2186 /**********************************************************************
2187 * GetWindowLongA (USER32.@)
2189 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2191 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2195 /**********************************************************************
2196 * GetWindowLongW (USER32.@)
2198 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2200 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2204 /**********************************************************************
2205 * SetWindowLong (USER.136)
2207 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2209 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
2213 /**********************************************************************
2214 * SetWindowLongA (USER32.@)
2216 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2218 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2222 /**********************************************************************
2223 * SetWindowLongW (USER32.@) Set window attribute
2225 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2226 * value in a window's extra memory.
2228 * The _hwnd_ parameter specifies the window. is the handle to a
2229 * window that has extra memory. The _newval_ parameter contains the
2230 * new attribute or extra memory value. If positive, the _offset_
2231 * parameter is the byte-addressed location in the window's extra
2232 * memory to set. If negative, _offset_ specifies the window
2233 * attribute to set, and should be one of the following values:
2235 * GWL_EXSTYLE The window's extended window style
2237 * GWL_STYLE The window's window style.
2239 * GWLP_WNDPROC Pointer to the window's window procedure.
2241 * GWLP_HINSTANCE The window's pplication instance handle.
2243 * GWLP_ID The window's identifier.
2245 * GWLP_USERDATA The window's user-specified data.
2247 * If the window is a dialog box, the _offset_ parameter can be one of
2248 * the following values:
2250 * DWLP_DLGPROC The address of the window's dialog box procedure.
2252 * DWLP_MSGRESULT The return value of a message
2253 * that the dialog box procedure processed.
2255 * DWLP_USER Application specific information.
2257 * RETURNS
2259 * If successful, returns the previous value located at _offset_. Otherwise,
2260 * returns 0.
2262 * NOTES
2264 * Extra memory for a window class is specified by a nonzero cbWndExtra
2265 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2266 * time of class creation.
2268 * Using GWL_WNDPROC to set a new window procedure effectively creates
2269 * a window subclass. Use CallWindowProc() in the new windows procedure
2270 * to pass messages to the superclass's window procedure.
2272 * The user data is reserved for use by the application which created
2273 * the window.
2275 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2276 * instead, call the EnableWindow() function to change the window's
2277 * disabled state.
2279 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2280 * SetParent() instead.
2282 * Win95:
2283 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2284 * it sends WM_STYLECHANGING before changing the settings
2285 * and WM_STYLECHANGED afterwards.
2286 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2288 LONG WINAPI SetWindowLongW(
2289 HWND hwnd, /* [in] window to alter */
2290 INT offset, /* [in] offset, in bytes, of location to alter */
2291 LONG newval /* [in] new value of location */
2293 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2297 /*******************************************************************
2298 * GetWindowTextA (USER32.@)
2300 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2302 WCHAR *buffer;
2304 if (WIN_IsCurrentProcess( hwnd ))
2305 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2307 /* when window belongs to other process, don't send a message */
2308 if (nMaxCount <= 0) return 0;
2309 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2310 get_server_window_text( hwnd, buffer, nMaxCount );
2311 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2312 lpString[nMaxCount-1] = 0;
2313 HeapFree( GetProcessHeap(), 0, buffer );
2314 return strlen(lpString);
2318 /*******************************************************************
2319 * InternalGetWindowText (USER32.@)
2321 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2323 WND *win;
2325 if (nMaxCount <= 0) return 0;
2326 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2327 if (win != WND_OTHER_PROCESS)
2329 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2330 else lpString[0] = 0;
2331 WIN_ReleasePtr( win );
2333 else
2335 get_server_window_text( hwnd, lpString, nMaxCount );
2337 return strlenW(lpString);
2341 /*******************************************************************
2342 * GetWindowTextW (USER32.@)
2344 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2346 if (WIN_IsCurrentProcess( hwnd ))
2347 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2349 /* when window belongs to other process, don't send a message */
2350 if (nMaxCount <= 0) return 0;
2351 get_server_window_text( hwnd, lpString, nMaxCount );
2352 return strlenW(lpString);
2356 /*******************************************************************
2357 * SetWindowText (USER32.@)
2358 * SetWindowTextA (USER32.@)
2360 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2362 if (is_broadcast(hwnd))
2364 SetLastError( ERROR_INVALID_PARAMETER );
2365 return FALSE;
2367 if (!WIN_IsCurrentProcess( hwnd ))
2369 FIXME( "cannot set text %s of other process window %p\n", debugstr_a(lpString), hwnd );
2370 SetLastError( ERROR_ACCESS_DENIED );
2371 return FALSE;
2373 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2377 /*******************************************************************
2378 * SetWindowTextW (USER32.@)
2380 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2382 if (is_broadcast(hwnd))
2384 SetLastError( ERROR_INVALID_PARAMETER );
2385 return FALSE;
2387 if (!WIN_IsCurrentProcess( hwnd ))
2389 FIXME( "cannot set text %s of other process window %p\n", debugstr_w(lpString), hwnd );
2390 SetLastError( ERROR_ACCESS_DENIED );
2391 return FALSE;
2393 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2397 /*******************************************************************
2398 * GetWindowTextLengthA (USER32.@)
2400 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2402 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2405 /*******************************************************************
2406 * GetWindowTextLengthW (USER32.@)
2408 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2410 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2414 /*******************************************************************
2415 * IsWindow (USER32.@)
2417 BOOL WINAPI IsWindow( HWND hwnd )
2419 WND *ptr;
2420 BOOL ret;
2422 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2424 if (ptr != WND_OTHER_PROCESS)
2426 WIN_ReleasePtr( ptr );
2427 return TRUE;
2430 /* check other processes */
2431 SERVER_START_REQ( get_window_info )
2433 req->handle = hwnd;
2434 ret = !wine_server_call_err( req );
2436 SERVER_END_REQ;
2437 return ret;
2441 /***********************************************************************
2442 * GetWindowThreadProcessId (USER32.@)
2444 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2446 WND *ptr;
2447 DWORD tid = 0;
2449 if (!(ptr = WIN_GetPtr( hwnd )))
2451 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2452 return 0;
2455 if (ptr != WND_OTHER_PROCESS)
2457 /* got a valid window */
2458 tid = ptr->tid;
2459 if (process) *process = GetCurrentProcessId();
2460 WIN_ReleasePtr( ptr );
2461 return tid;
2464 /* check other processes */
2465 SERVER_START_REQ( get_window_info )
2467 req->handle = hwnd;
2468 if (!wine_server_call_err( req ))
2470 tid = (DWORD)reply->tid;
2471 if (process) *process = (DWORD)reply->pid;
2474 SERVER_END_REQ;
2475 return tid;
2479 /*****************************************************************
2480 * GetParent (USER32.@)
2482 HWND WINAPI GetParent( HWND hwnd )
2484 WND *wndPtr;
2485 HWND retvalue = 0;
2487 if (!(wndPtr = WIN_GetPtr( hwnd )))
2489 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2490 return 0;
2492 if (wndPtr == WND_OTHER_PROCESS)
2494 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2495 if (style & (WS_POPUP | WS_CHILD))
2497 SERVER_START_REQ( get_window_tree )
2499 req->handle = hwnd;
2500 if (!wine_server_call_err( req ))
2502 if (style & WS_POPUP) retvalue = reply->owner;
2503 else if (style & WS_CHILD) retvalue = reply->parent;
2506 SERVER_END_REQ;
2509 else
2511 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2512 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2513 WIN_ReleasePtr( wndPtr );
2515 return retvalue;
2519 /*****************************************************************
2520 * GetAncestor (USER32.@)
2522 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2524 WND *win;
2525 HWND *list, ret = 0;
2527 switch(type)
2529 case GA_PARENT:
2530 if (!(win = WIN_GetPtr( hwnd )))
2532 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2533 return 0;
2535 if (win != WND_OTHER_PROCESS)
2537 ret = win->parent;
2538 WIN_ReleasePtr( win );
2540 else /* need to query the server */
2542 SERVER_START_REQ( get_window_tree )
2544 req->handle = hwnd;
2545 if (!wine_server_call_err( req )) ret = reply->parent;
2547 SERVER_END_REQ;
2549 break;
2551 case GA_ROOT:
2552 if (!(list = WIN_ListParents( hwnd ))) return 0;
2554 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2555 else
2557 int count = 2;
2558 while (list[count]) count++;
2559 ret = list[count - 2]; /* get the one before the desktop */
2561 HeapFree( GetProcessHeap(), 0, list );
2562 break;
2564 case GA_ROOTOWNER:
2565 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2566 for (;;)
2568 HWND parent = GetParent( ret );
2569 if (!parent) break;
2570 ret = parent;
2572 break;
2574 return ret;
2578 /*****************************************************************
2579 * SetParent (USER32.@)
2581 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2583 WND *wndPtr;
2584 HWND retvalue, full_handle;
2585 BOOL was_visible;
2587 if (is_broadcast(hwnd) || is_broadcast(parent))
2589 SetLastError(ERROR_INVALID_PARAMETER);
2590 return 0;
2593 if (!parent) parent = GetDesktopWindow();
2594 else parent = WIN_GetFullHandle( parent );
2596 if (!IsWindow( parent ))
2598 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2599 return 0;
2602 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2603 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2605 hwnd = full_handle;
2607 if (USER_Driver.pSetParent)
2608 return USER_Driver.pSetParent( hwnd, parent );
2610 /* Windows hides the window first, then shows it again
2611 * including the WM_SHOWWINDOW messages and all */
2612 was_visible = ShowWindow( hwnd, SW_HIDE );
2614 if (!IsWindow( parent )) return 0;
2615 if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return 0;
2617 retvalue = wndPtr->parent; /* old parent */
2618 if (parent != retvalue)
2620 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2622 if (parent != GetDesktopWindow()) /* a child window */
2624 if (!(wndPtr->dwStyle & WS_CHILD))
2626 HMENU menu = (HMENU)SetWindowLongPtrW( hwnd, GWLP_ID, 0 );
2627 if (menu) DestroyMenu( menu );
2631 WIN_ReleasePtr( wndPtr );
2633 /* SetParent additionally needs to make hwnd the topmost window
2634 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2635 WM_WINDOWPOSCHANGED notification messages.
2637 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2638 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2639 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2640 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2641 return retvalue;
2645 /*******************************************************************
2646 * IsChild (USER32.@)
2648 BOOL WINAPI IsChild( HWND parent, HWND child )
2650 HWND *list = WIN_ListParents( child );
2651 int i;
2652 BOOL ret;
2654 if (!list) return FALSE;
2655 parent = WIN_GetFullHandle( parent );
2656 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2657 ret = (list[i] != 0);
2658 HeapFree( GetProcessHeap(), 0, list );
2659 return ret;
2663 /***********************************************************************
2664 * IsWindowVisible (USER32.@)
2666 BOOL WINAPI IsWindowVisible( HWND hwnd )
2668 HWND *list;
2669 BOOL retval;
2670 int i;
2672 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2673 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2674 for (i = 0; list[i]; i++)
2675 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2676 retval = !list[i];
2677 HeapFree( GetProcessHeap(), 0, list );
2678 return retval;
2682 /***********************************************************************
2683 * WIN_IsWindowDrawable
2685 * hwnd is drawable when it is visible, all parents are not
2686 * minimized, and it is itself not minimized unless we are
2687 * trying to draw its default class icon.
2689 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2691 HWND *list;
2692 BOOL retval;
2693 int i;
2694 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2696 if (!(style & WS_VISIBLE)) return FALSE;
2697 if ((style & WS_MINIMIZE) && icon && GetClassLongA( hwnd, GCL_HICON )) return FALSE;
2699 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2700 for (i = 0; list[i]; i++)
2701 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2702 break;
2703 retval = !list[i];
2704 HeapFree( GetProcessHeap(), 0, list );
2705 return retval;
2709 /*******************************************************************
2710 * GetTopWindow (USER32.@)
2712 HWND WINAPI GetTopWindow( HWND hwnd )
2714 if (!hwnd) hwnd = GetDesktopWindow();
2715 return GetWindow( hwnd, GW_CHILD );
2719 /*******************************************************************
2720 * GetWindow (USER32.@)
2722 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2724 HWND retval = 0;
2726 if (rel == GW_OWNER) /* this one may be available locally */
2728 WND *wndPtr = WIN_GetPtr( hwnd );
2729 if (!wndPtr)
2731 SetLastError( ERROR_INVALID_HANDLE );
2732 return 0;
2734 if (wndPtr != WND_OTHER_PROCESS)
2736 retval = wndPtr->owner;
2737 WIN_ReleasePtr( wndPtr );
2738 return retval;
2740 /* else fall through to server call */
2743 SERVER_START_REQ( get_window_tree )
2745 req->handle = hwnd;
2746 if (!wine_server_call_err( req ))
2748 switch(rel)
2750 case GW_HWNDFIRST:
2751 retval = reply->first_sibling;
2752 break;
2753 case GW_HWNDLAST:
2754 retval = reply->last_sibling;
2755 break;
2756 case GW_HWNDNEXT:
2757 retval = reply->next_sibling;
2758 break;
2759 case GW_HWNDPREV:
2760 retval = reply->prev_sibling;
2761 break;
2762 case GW_OWNER:
2763 retval = reply->owner;
2764 break;
2765 case GW_CHILD:
2766 retval = reply->first_child;
2767 break;
2771 SERVER_END_REQ;
2772 return retval;
2776 /*******************************************************************
2777 * ShowOwnedPopups (USER32.@)
2779 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2781 int count = 0;
2782 WND *pWnd;
2783 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2785 if (!win_array) return TRUE;
2787 while (win_array[count]) count++;
2788 while (--count >= 0)
2790 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2791 if (!(pWnd = WIN_GetPtr( win_array[count] ))) continue;
2792 if (pWnd == WND_OTHER_PROCESS) continue;
2794 if (pWnd->dwStyle & WS_POPUP)
2796 if (fShow)
2798 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2800 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2801 WIN_ReleasePtr( pWnd );
2802 /* In Windows, ShowOwnedPopups(TRUE) generates
2803 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2804 * regardless of the state of the owner
2806 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2807 continue;
2810 else
2812 if (pWnd->dwStyle & WS_VISIBLE)
2814 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2815 WIN_ReleasePtr( pWnd );
2816 /* In Windows, ShowOwnedPopups(FALSE) generates
2817 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2818 * regardless of the state of the owner
2820 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2821 continue;
2825 WIN_ReleasePtr( pWnd );
2827 HeapFree( GetProcessHeap(), 0, win_array );
2828 return TRUE;
2832 /*******************************************************************
2833 * GetLastActivePopup (USER32.@)
2835 HWND WINAPI GetLastActivePopup( HWND hwnd )
2837 HWND retval = hwnd;
2839 SERVER_START_REQ( get_window_info )
2841 req->handle = hwnd;
2842 if (!wine_server_call_err( req )) retval = reply->last_active;
2844 SERVER_END_REQ;
2845 return retval;
2849 /*******************************************************************
2850 * WIN_ListParents
2852 * Build an array of all parents of a given window, starting with
2853 * the immediate parent. The array must be freed with HeapFree.
2854 * Returns NULL if window is a top-level window.
2856 HWND *WIN_ListParents( HWND hwnd )
2858 WND *win;
2859 HWND current, *list;
2860 int pos = 0, size = 16, count = 0;
2862 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2864 current = hwnd;
2865 for (;;)
2867 if (!(win = WIN_GetPtr( current ))) goto empty;
2868 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
2869 list[pos] = win->parent;
2870 WIN_ReleasePtr( win );
2871 if (!(current = list[pos]))
2873 if (!pos) goto empty;
2874 return list;
2876 if (++pos == size - 1)
2878 /* need to grow the list */
2879 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
2880 if (!new_list) goto empty;
2881 list = new_list;
2882 size += 16;
2886 /* at least one parent belongs to another process, have to query the server */
2888 for (;;)
2890 count = 0;
2891 SERVER_START_REQ( get_window_parents )
2893 req->handle = hwnd;
2894 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
2895 if (!wine_server_call( req )) count = reply->count;
2897 SERVER_END_REQ;
2898 if (!count) goto empty;
2899 if (size > count)
2901 list[count] = 0;
2902 return list;
2904 HeapFree( GetProcessHeap(), 0, list );
2905 size = count + 1;
2906 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2909 empty:
2910 HeapFree( GetProcessHeap(), 0, list );
2911 return NULL;
2915 /*******************************************************************
2916 * WIN_ListChildren
2918 * Build an array of the children of a given window. The array must be
2919 * freed with HeapFree. Returns NULL when no windows are found.
2921 HWND *WIN_ListChildren( HWND hwnd )
2923 return list_window_children( hwnd, 0, 0 );
2927 /*******************************************************************
2928 * EnumWindows (USER32.@)
2930 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2932 HWND *list;
2933 BOOL ret = TRUE;
2934 int i, iWndsLocks;
2936 /* We have to build a list of all windows first, to avoid */
2937 /* unpleasant side-effects, for instance if the callback */
2938 /* function changes the Z-order of the windows. */
2940 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2942 /* Now call the callback function for every window */
2944 iWndsLocks = WIN_SuspendWndsLock();
2945 for (i = 0; list[i]; i++)
2947 /* Make sure that the window still exists */
2948 if (!IsWindow( list[i] )) continue;
2949 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2951 WIN_RestoreWndsLock(iWndsLocks);
2952 HeapFree( GetProcessHeap(), 0, list );
2953 return ret;
2957 /**********************************************************************
2958 * EnumThreadWindows (USER32.@)
2960 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2962 HWND *list;
2963 int i, iWndsLocks;
2965 if (!(list = list_window_children( GetDesktopWindow(), 0, id ))) return TRUE;
2967 /* Now call the callback function for every window */
2969 iWndsLocks = WIN_SuspendWndsLock();
2970 for (i = 0; list[i]; i++)
2971 if (!func( list[i], lParam )) break;
2972 WIN_RestoreWndsLock(iWndsLocks);
2973 HeapFree( GetProcessHeap(), 0, list );
2974 return TRUE;
2978 /**********************************************************************
2979 * WIN_EnumChildWindows
2981 * Helper function for EnumChildWindows().
2983 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2985 HWND *childList;
2986 BOOL ret = FALSE;
2988 for ( ; *list; list++)
2990 /* Make sure that the window still exists */
2991 if (!IsWindow( *list )) continue;
2992 /* skip owned windows */
2993 if (GetWindow( *list, GW_OWNER )) continue;
2994 /* Build children list first */
2995 childList = WIN_ListChildren( *list );
2997 ret = func( *list, lParam );
2999 if (childList)
3001 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
3002 HeapFree( GetProcessHeap(), 0, childList );
3004 if (!ret) return FALSE;
3006 return TRUE;
3010 /**********************************************************************
3011 * EnumChildWindows (USER32.@)
3013 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
3015 HWND *list;
3016 int iWndsLocks;
3018 if (!(list = WIN_ListChildren( parent ))) return FALSE;
3019 iWndsLocks = WIN_SuspendWndsLock();
3020 WIN_EnumChildWindows( list, func, lParam );
3021 WIN_RestoreWndsLock(iWndsLocks);
3022 HeapFree( GetProcessHeap(), 0, list );
3023 return TRUE;
3027 /*******************************************************************
3028 * AnyPopup (USER.52)
3030 BOOL16 WINAPI AnyPopup16(void)
3032 return AnyPopup();
3036 /*******************************************************************
3037 * AnyPopup (USER32.@)
3039 BOOL WINAPI AnyPopup(void)
3041 int i;
3042 BOOL retvalue;
3043 HWND *list = WIN_ListChildren( GetDesktopWindow() );
3045 if (!list) return FALSE;
3046 for (i = 0; list[i]; i++)
3048 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
3050 retvalue = (list[i] != 0);
3051 HeapFree( GetProcessHeap(), 0, list );
3052 return retvalue;
3056 /*******************************************************************
3057 * FlashWindow (USER32.@)
3059 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3061 WND *wndPtr;
3063 TRACE("%p\n", hWnd);
3065 if (IsIconic( hWnd ))
3067 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3069 wndPtr = WIN_GetPtr(hWnd);
3070 if (!wndPtr || wndPtr == WND_OTHER_PROCESS) return FALSE;
3071 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3073 wndPtr->flags |= WIN_NCACTIVATED;
3075 else
3077 wndPtr->flags &= ~WIN_NCACTIVATED;
3079 WIN_ReleasePtr( wndPtr );
3080 return TRUE;
3082 else
3084 WPARAM wparam;
3086 wndPtr = WIN_GetPtr(hWnd);
3087 if (!wndPtr || wndPtr == WND_OTHER_PROCESS) return FALSE;
3088 hWnd = wndPtr->hwndSelf; /* make it a full handle */
3090 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3091 else wparam = (hWnd == GetForegroundWindow());
3093 WIN_ReleasePtr( wndPtr );
3094 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3095 return wparam;
3099 /*******************************************************************
3100 * FlashWindowEx (USER32.@)
3102 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
3104 FIXME("%p\n", pfwi);
3105 return TRUE;
3108 /*******************************************************************
3109 * GetWindowContextHelpId (USER32.@)
3111 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3113 DWORD retval;
3114 WND *wnd = WIN_GetPtr( hwnd );
3115 if (!wnd) return 0;
3116 if (wnd == WND_OTHER_PROCESS)
3118 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3119 return 0;
3121 retval = wnd->helpContext;
3122 WIN_ReleasePtr( wnd );
3123 return retval;
3127 /*******************************************************************
3128 * SetWindowContextHelpId (USER32.@)
3130 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3132 WND *wnd = WIN_GetPtr( hwnd );
3133 if (!wnd) return FALSE;
3134 if (wnd == WND_OTHER_PROCESS)
3136 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3137 return 0;
3139 wnd->helpContext = id;
3140 WIN_ReleasePtr( wnd );
3141 return TRUE;
3145 /*******************************************************************
3146 * DragDetect (USER32.@)
3148 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3150 MSG msg;
3151 RECT rect;
3153 rect.left = pt.x - wDragWidth;
3154 rect.right = pt.x + wDragWidth;
3156 rect.top = pt.y - wDragHeight;
3157 rect.bottom = pt.y + wDragHeight;
3159 SetCapture(hWnd);
3161 while(1)
3163 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3165 if( msg.message == WM_LBUTTONUP )
3167 ReleaseCapture();
3168 return 0;
3170 if( msg.message == WM_MOUSEMOVE )
3172 POINT tmp;
3173 tmp.x = LOWORD(msg.lParam);
3174 tmp.y = HIWORD(msg.lParam);
3175 if( !PtInRect( &rect, tmp ))
3177 ReleaseCapture();
3178 return 1;
3182 WaitMessage();
3184 return 0;
3187 /******************************************************************************
3188 * GetWindowModuleFileNameA (USER32.@)
3190 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3192 FIXME("GetWindowModuleFileNameA(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3193 hwnd, lpszFileName, cchFileNameMax);
3194 return 0;
3197 /******************************************************************************
3198 * GetWindowModuleFileNameW (USER32.@)
3200 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR lpszFileName, UINT cchFileNameMax)
3202 FIXME("GetWindowModuleFileNameW(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3203 hwnd, lpszFileName, cchFileNameMax);
3204 return 0;
3207 /******************************************************************************
3208 * GetWindowInfo (USER32.@)
3210 * Note: tests show that Windows doesn't check cbSize of the structure.
3212 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3214 if (!pwi) return FALSE;
3215 if (!IsWindow(hwnd)) return FALSE;
3217 GetWindowRect(hwnd, &pwi->rcWindow);
3218 GetClientRect(hwnd, &pwi->rcClient);
3219 /* translate to screen coordinates */
3220 MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3222 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3223 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3224 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3226 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3227 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3229 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3230 pwi->wCreatorVersion = 0x0400;
3232 return TRUE;
3235 /******************************************************************************
3236 * SwitchDesktop (USER32.@)
3238 * NOTES: Sets the current input or interactive desktop.
3240 BOOL WINAPI SwitchDesktop( HDESK hDesktop)
3242 FIXME("SwitchDesktop(hwnd %p) stub!\n", hDesktop);
3243 return TRUE;