Added partial support for function pointers.
[wine/multimedia.git] / windows / win.c
blob6a74b01faba9fc7568b8f143a0cdfad883efd9ff
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 <stdlib.h>
26 #include <string.h>
27 #include "windef.h"
28 #include "wine/winbase16.h"
29 #include "wine/winuser16.h"
30 #include "wownt32.h"
31 #include "wine/server.h"
32 #include "wine/unicode.h"
33 #include "win.h"
34 #include "user.h"
35 #include "dce.h"
36 #include "controls.h"
37 #include "cursoricon.h"
38 #include "message.h"
39 #include "winpos.h"
40 #include "winerror.h"
41 #include "wine/debug.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(win);
44 WINE_DECLARE_DEBUG_CHANNEL(msg);
46 #define NB_USER_HANDLES (LAST_USER_HANDLE - FIRST_USER_HANDLE + 1)
48 /**********************************************************************/
50 /* Desktop window */
51 static WND *pWndDesktop = NULL;
53 static WORD wDragWidth = 4;
54 static WORD wDragHeight= 3;
56 static void *user_handles[NB_USER_HANDLES];
58 /***********************************************************************
59 * create_window_handle
61 * Create a window handle with the server.
63 static WND *create_window_handle( HWND parent, HWND owner, ATOM atom, INT size )
65 BOOL res;
66 user_handle_t handle = 0;
67 WORD index;
68 WND *win = HeapAlloc( GetProcessHeap(), 0, size );
70 if (!win) return NULL;
72 USER_Lock();
74 SERVER_START_REQ( create_window )
76 req->parent = parent;
77 req->owner = owner;
78 req->atom = atom;
79 if ((res = !wine_server_call_err( req ))) handle = reply->handle;
81 SERVER_END_REQ;
83 if (!res)
85 USER_Unlock();
86 HeapFree( GetProcessHeap(), 0, win );
87 return NULL;
89 index = LOWORD(handle) - FIRST_USER_HANDLE;
90 assert( index < NB_USER_HANDLES );
91 user_handles[index] = win;
92 win->hwndSelf = handle;
93 win->dwMagic = WND_MAGIC;
94 win->irefCount = 1;
95 return win;
99 /***********************************************************************
100 * free_window_handle
102 * Free a window handle.
104 static WND *free_window_handle( HWND hwnd )
106 WND *ptr;
107 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
109 if (index >= NB_USER_HANDLES) return NULL;
110 USER_Lock();
111 if ((ptr = user_handles[index]))
113 SERVER_START_REQ( destroy_window )
115 req->handle = hwnd;
116 if (!wine_server_call_err( req ))
117 user_handles[index] = NULL;
118 else
119 ptr = NULL;
121 SERVER_END_REQ;
123 USER_Unlock();
124 if (ptr) HeapFree( GetProcessHeap(), 0, ptr );
125 return ptr;
129 /*******************************************************************
130 * list_window_children
132 * Build an array of the children of a given window. The array must be
133 * freed with HeapFree. Returns NULL when no windows are found.
135 static HWND *list_window_children( HWND hwnd, ATOM atom, DWORD tid )
137 HWND *list;
138 int size = 32;
140 for (;;)
142 int count = 0;
144 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
146 SERVER_START_REQ( get_window_children )
148 req->parent = hwnd;
149 req->atom = atom;
150 req->tid = tid;
151 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
152 if (!wine_server_call( req )) count = reply->count;
154 SERVER_END_REQ;
155 if (count && count < size)
157 list[count] = 0;
158 return list;
160 HeapFree( GetProcessHeap(), 0, list );
161 if (!count) break;
162 size = count + 1; /* restart with a large enough buffer */
164 return NULL;
168 /*******************************************************************
169 * send_parent_notify
171 static void send_parent_notify( HWND hwnd, UINT msg )
173 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD)) return;
174 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY) return;
175 SendMessageW( GetParent(hwnd), WM_PARENTNOTIFY,
176 MAKEWPARAM( msg, GetWindowLongW( hwnd, GWL_ID )), (LPARAM)hwnd );
180 /*******************************************************************
181 * get_server_window_text
183 * Retrieve the window text from the server.
185 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
187 size_t len = 0;
189 SERVER_START_REQ( get_window_text )
191 req->handle = hwnd;
192 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
193 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
195 SERVER_END_REQ;
196 text[len / sizeof(WCHAR)] = 0;
200 /***********************************************************************
201 * WIN_GetPtr
203 * Return a pointer to the WND structure if local to the process,
204 * or WND_OTHER_PROCESS if handle may be valid in other process.
205 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
207 WND *WIN_GetPtr( HWND hwnd )
209 WND * ptr;
210 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
212 if (index >= NB_USER_HANDLES) return NULL;
214 USER_Lock();
215 if ((ptr = user_handles[index]))
217 if (ptr->dwMagic == WND_MAGIC && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
218 return ptr;
219 ptr = NULL;
221 else ptr = WND_OTHER_PROCESS;
222 USER_Unlock();
223 return ptr;
227 /***********************************************************************
228 * WIN_IsCurrentProcess
230 * Check whether a given window belongs to the current process (and return the full handle).
232 HWND WIN_IsCurrentProcess( HWND hwnd )
234 WND *ptr;
235 HWND ret;
237 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS) return 0;
238 ret = ptr->hwndSelf;
239 WIN_ReleasePtr( ptr );
240 return ret;
244 /***********************************************************************
245 * WIN_IsCurrentThread
247 * Check whether a given window belongs to the current thread (and return the full handle).
249 HWND WIN_IsCurrentThread( HWND hwnd )
251 WND *ptr;
252 HWND ret = 0;
254 if ((ptr = WIN_GetPtr( hwnd )) && ptr != WND_OTHER_PROCESS)
256 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
257 WIN_ReleasePtr( ptr );
259 return ret;
263 /***********************************************************************
264 * WIN_Handle32
266 * Convert a 16-bit window handle to a full 32-bit handle.
268 HWND WIN_Handle32( HWND16 hwnd16 )
270 WND *ptr;
271 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
273 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
274 /* do sign extension for -2 and -3 */
275 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
277 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
279 if (ptr != WND_OTHER_PROCESS)
281 hwnd = ptr->hwndSelf;
282 WIN_ReleasePtr( ptr );
284 else /* may belong to another process */
286 SERVER_START_REQ( get_window_info )
288 req->handle = hwnd;
289 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
291 SERVER_END_REQ;
293 return hwnd;
297 /***********************************************************************
298 * WIN_FindWndPtr
300 * Return a pointer to the WND structure corresponding to a HWND.
302 WND * WIN_FindWndPtr( HWND hwnd )
304 WND * ptr;
306 if (!hwnd) return NULL;
308 if ((ptr = WIN_GetPtr( hwnd )))
310 if (ptr != WND_OTHER_PROCESS)
312 /* increment destruction monitoring */
313 ptr->irefCount++;
314 return ptr;
316 if (IsWindow( hwnd )) /* check other processes */
318 ERR( "window %p belongs to other process\n", hwnd );
319 /* DbgBreakPoint(); */
322 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
323 return NULL;
327 /***********************************************************************
328 * WIN_ReleaseWndPtr
330 * Release the pointer to the WND structure.
332 void WIN_ReleaseWndPtr(WND *wndPtr)
334 if(!wndPtr) return;
336 /* Decrement destruction monitoring value */
337 wndPtr->irefCount--;
338 /* Check if it's time to release the memory */
339 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
341 /* Release memory */
342 free_window_handle( wndPtr->hwndSelf );
344 else if(wndPtr->irefCount < 0)
346 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
347 ERR("forgot a Lock on %p somewhere\n",wndPtr);
349 /* unlock all WND structures for thread safeness */
350 USER_Unlock();
354 /***********************************************************************
355 * WIN_UnlinkWindow
357 * Remove a window from the siblings linked list.
359 void WIN_UnlinkWindow( HWND hwnd )
361 WIN_LinkWindow( hwnd, 0, 0 );
365 /***********************************************************************
366 * WIN_LinkWindow
368 * Insert a window into the siblings linked list.
369 * The window is inserted after the specified window, which can also
370 * be specified as HWND_TOP or HWND_BOTTOM.
371 * If parent is 0, window is unlinked from the tree.
373 void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
375 WND *wndPtr = WIN_GetPtr( hwnd );
377 if (!wndPtr) return;
378 if (wndPtr == WND_OTHER_PROCESS)
380 if (IsWindow(hwnd)) ERR(" cannot link other process window %p\n", hwnd );
381 return;
384 SERVER_START_REQ( link_window )
386 req->handle = hwnd;
387 req->parent = parent;
388 req->previous = hwndInsertAfter;
389 if (!wine_server_call( req ))
391 if (reply->full_parent) wndPtr->parent = reply->full_parent;
395 SERVER_END_REQ;
396 WIN_ReleasePtr( wndPtr );
400 /***********************************************************************
401 * WIN_SetOwner
403 * Change the owner of a window.
405 HWND WIN_SetOwner( HWND hwnd, HWND owner )
407 WND *win = WIN_GetPtr( hwnd );
408 HWND ret = 0;
410 if (!win) return 0;
411 if (win == WND_OTHER_PROCESS)
413 if (IsWindow(hwnd)) ERR( "cannot set owner %p on other process window %p\n", owner, hwnd );
414 return 0;
416 SERVER_START_REQ( set_window_owner )
418 req->handle = hwnd;
419 req->owner = owner;
420 if (!wine_server_call( req ))
422 win->owner = reply->full_owner;
423 ret = reply->prev_owner;
426 SERVER_END_REQ;
427 WIN_ReleasePtr( win );
428 return ret;
432 /***********************************************************************
433 * WIN_SetStyle
435 * Change the style of a window.
437 LONG WIN_SetStyle( HWND hwnd, LONG style )
439 BOOL ok;
440 LONG ret = 0;
441 WND *win = WIN_GetPtr( hwnd );
443 if (!win) return 0;
444 if (win == WND_OTHER_PROCESS)
446 if (IsWindow(hwnd))
447 ERR( "cannot set style %lx on other process window %p\n", style, hwnd );
448 return 0;
450 if (style == win->dwStyle)
452 WIN_ReleasePtr( win );
453 return style;
455 SERVER_START_REQ( set_window_info )
457 req->handle = hwnd;
458 req->flags = SET_WIN_STYLE;
459 req->style = style;
460 if ((ok = !wine_server_call( req )))
462 ret = reply->old_style;
463 win->dwStyle = style;
466 SERVER_END_REQ;
467 WIN_ReleasePtr( win );
468 if (ok && USER_Driver.pSetWindowStyle) USER_Driver.pSetWindowStyle( hwnd, ret );
469 return ret;
473 /***********************************************************************
474 * WIN_SetExStyle
476 * Change the extended style of a window.
478 LONG WIN_SetExStyle( HWND hwnd, LONG style )
480 LONG ret = 0;
481 WND *win = WIN_GetPtr( hwnd );
483 if (!win) return 0;
484 if (win == WND_OTHER_PROCESS)
486 if (IsWindow(hwnd))
487 ERR( "cannot set exstyle %lx on other process window %p\n", style, hwnd );
488 return 0;
490 if (style == win->dwExStyle)
492 WIN_ReleasePtr( win );
493 return style;
495 SERVER_START_REQ( set_window_info )
497 req->handle = hwnd;
498 req->flags = SET_WIN_EXSTYLE;
499 req->ex_style = style;
500 if (!wine_server_call( req ))
502 ret = reply->old_ex_style;
503 win->dwExStyle = style;
506 SERVER_END_REQ;
507 WIN_ReleasePtr( win );
508 return ret;
512 /***********************************************************************
513 * WIN_SetRectangles
515 * Set the window and client rectangles.
517 void WIN_SetRectangles( HWND hwnd, const RECT *rectWindow, const RECT *rectClient )
519 WND *win = WIN_GetPtr( hwnd );
520 BOOL ret;
522 if (!win) return;
523 if (win == WND_OTHER_PROCESS)
525 if (IsWindow( hwnd )) ERR( "cannot set rectangles of other process window %p\n", hwnd );
526 return;
528 SERVER_START_REQ( set_window_rectangles )
530 req->handle = hwnd;
531 req->window.left = rectWindow->left;
532 req->window.top = rectWindow->top;
533 req->window.right = rectWindow->right;
534 req->window.bottom = rectWindow->bottom;
535 req->client.left = rectClient->left;
536 req->client.top = rectClient->top;
537 req->client.right = rectClient->right;
538 req->client.bottom = rectClient->bottom;
539 ret = !wine_server_call( req );
541 SERVER_END_REQ;
542 if (ret)
544 win->rectWindow = *rectWindow;
545 win->rectClient = *rectClient;
547 TRACE( "win %p window (%ld,%ld)-(%ld,%ld) client (%ld,%ld)-(%ld,%ld)\n", hwnd,
548 rectWindow->left, rectWindow->top, rectWindow->right, rectWindow->bottom,
549 rectClient->left, rectClient->top, rectClient->right, rectClient->bottom );
551 WIN_ReleasePtr( win );
555 /***********************************************************************
556 * WIN_GetRectangles
558 * Get the window and client rectangles.
560 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
562 WND *win = WIN_GetPtr( hwnd );
563 BOOL ret = TRUE;
565 if (!win) return FALSE;
566 if (win == WND_OTHER_PROCESS)
568 SERVER_START_REQ( get_window_rectangles )
570 req->handle = hwnd;
571 if ((ret = !wine_server_call( req )))
573 if (rectWindow)
575 rectWindow->left = reply->window.left;
576 rectWindow->top = reply->window.top;
577 rectWindow->right = reply->window.right;
578 rectWindow->bottom = reply->window.bottom;
580 if (rectClient)
582 rectClient->left = reply->client.left;
583 rectClient->top = reply->client.top;
584 rectClient->right = reply->client.right;
585 rectClient->bottom = reply->client.bottom;
589 SERVER_END_REQ;
591 else
593 if (rectWindow) *rectWindow = win->rectWindow;
594 if (rectClient) *rectClient = win->rectClient;
595 WIN_ReleasePtr( win );
597 return ret;
601 /***********************************************************************
602 * WIN_DestroyWindow
604 * Destroy storage associated to a window. "Internals" p.358
606 LRESULT WIN_DestroyWindow( HWND hwnd )
608 WND *wndPtr;
609 HWND *list;
611 TRACE("%p\n", hwnd );
613 if (!(hwnd = WIN_IsCurrentThread( hwnd )))
615 ERR( "window doesn't belong to current thread\n" );
616 return 0;
619 /* free child windows */
620 if ((list = WIN_ListChildren( hwnd )))
622 int i;
623 for (i = 0; list[i]; i++)
625 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
626 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
628 HeapFree( GetProcessHeap(), 0, list );
632 * Clear the update region to make sure no WM_PAINT messages will be
633 * generated for this window while processing the WM_NCDESTROY.
635 RedrawWindow( hwnd, NULL, 0,
636 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
639 * Send the WM_NCDESTROY to the window being destroyed.
641 SendMessageA( hwnd, WM_NCDESTROY, 0, 0);
643 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
645 WINPOS_CheckInternalPos( hwnd );
646 if( hwnd == GetCapture()) ReleaseCapture();
648 /* free resources associated with the window */
650 TIMER_RemoveWindowTimers( hwnd );
652 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
654 if (!(wndPtr->dwStyle & WS_CHILD))
656 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
657 if (menu) DestroyMenu( menu );
659 if (wndPtr->hSysMenu)
661 DestroyMenu( wndPtr->hSysMenu );
662 wndPtr->hSysMenu = 0;
664 DCE_FreeWindowDCE( hwnd ); /* Always do this to catch orphaned DCs */
665 USER_Driver.pDestroyWindow( hwnd );
666 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
667 CLASS_RemoveWindow( wndPtr->class );
668 wndPtr->class = NULL;
669 wndPtr->dwMagic = 0; /* Mark it as invalid */
670 WIN_ReleaseWndPtr( wndPtr );
671 return 0;
674 /***********************************************************************
675 * WIN_DestroyThreadWindows
677 * Destroy all children of 'wnd' owned by the current thread.
678 * Return TRUE if something was done.
680 void WIN_DestroyThreadWindows( HWND hwnd )
682 HWND *list;
683 int i;
685 if (!(list = WIN_ListChildren( hwnd ))) return;
686 for (i = 0; list[i]; i++)
688 if (WIN_IsCurrentThread( list[i] ))
689 DestroyWindow( list[i] );
690 else
691 WIN_DestroyThreadWindows( list[i] );
693 HeapFree( GetProcessHeap(), 0, list );
696 /***********************************************************************
697 * WIN_CreateDesktopWindow
699 * Create the desktop window.
701 BOOL WIN_CreateDesktopWindow(void)
703 struct tagCLASS *class;
704 HWND hwndDesktop;
705 INT wndExtra;
706 DWORD clsStyle;
707 WNDPROC winproc;
708 DCE *dce;
709 CREATESTRUCTA cs;
710 RECT rect;
712 TRACE("Creating desktop window\n");
714 if (!WINPOS_CreateInternalPosAtom() ||
715 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
716 &wndExtra, &winproc, &clsStyle, &dce )))
717 return FALSE;
719 pWndDesktop = create_window_handle( 0, 0, LOWORD(DESKTOP_CLASS_ATOM),
720 sizeof(WND) + wndExtra - sizeof(pWndDesktop->wExtra) );
721 if (!pWndDesktop) return FALSE;
722 hwndDesktop = pWndDesktop->hwndSelf;
724 pWndDesktop->tid = 0; /* nobody owns the desktop */
725 pWndDesktop->parent = 0;
726 pWndDesktop->owner = 0;
727 pWndDesktop->class = class;
728 pWndDesktop->text = NULL;
729 pWndDesktop->hrgnUpdate = 0;
730 pWndDesktop->clsStyle = clsStyle;
731 pWndDesktop->dce = NULL;
732 pWndDesktop->pVScroll = NULL;
733 pWndDesktop->pHScroll = NULL;
734 pWndDesktop->helpContext = 0;
735 pWndDesktop->flags = 0;
736 pWndDesktop->hSysMenu = 0;
737 pWndDesktop->winproc = winproc;
738 pWndDesktop->cbWndExtra = wndExtra;
740 cs.lpCreateParams = NULL;
741 cs.hInstance = 0;
742 cs.hMenu = 0;
743 cs.hwndParent = 0;
744 cs.x = 0;
745 cs.y = 0;
746 cs.cx = GetSystemMetrics( SM_CXSCREEN );
747 cs.cy = GetSystemMetrics( SM_CYSCREEN );
748 cs.style = pWndDesktop->dwStyle;
749 cs.dwExStyle = pWndDesktop->dwExStyle;
750 cs.lpszName = NULL;
751 cs.lpszClass = DESKTOP_CLASS_ATOM;
753 SetRect( &rect, 0, 0, cs.cx, cs.cy );
754 WIN_SetRectangles( hwndDesktop, &rect, &rect );
756 SERVER_START_REQ( set_window_info )
758 req->handle = hwndDesktop;
759 req->flags = 0; /* don't set anything, just retrieve */
760 wine_server_call( req );
761 pWndDesktop->dwStyle = reply->old_style;
762 pWndDesktop->dwExStyle = reply->old_ex_style;
763 pWndDesktop->hInstance = (HINSTANCE)reply->old_instance;
764 pWndDesktop->userdata = (ULONG_PTR)reply->old_user_data;
765 pWndDesktop->wIDmenu = reply->old_id;
767 SERVER_END_REQ;
769 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE ))
771 WIN_ReleaseWndPtr( pWndDesktop );
772 return FALSE;
775 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
776 WIN_ReleaseWndPtr( pWndDesktop );
777 return TRUE;
781 /***********************************************************************
782 * WIN_FixCoordinates
784 * Fix the coordinates - Helper for WIN_CreateWindowEx.
785 * returns default show mode in sw.
786 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
788 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
790 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
791 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
793 if (cs->style & (WS_CHILD | WS_POPUP))
795 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
796 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
798 else /* overlapped window */
800 STARTUPINFOA info;
802 GetStartupInfoA( &info );
804 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
806 /* Never believe Microsoft's documentation... CreateWindowEx doc says
807 * that if an overlapped window is created with WS_VISIBLE style bit
808 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
809 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
810 * reveals that
812 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
813 * 2) it does not ignore the y parameter as the docs claim; instead, it
814 * uses it as second parameter to ShowWindow() unless y is either
815 * CW_USEDEFAULT or CW_USEDEFAULT16.
817 * The fact that we didn't do 2) caused bogus windows pop up when wine
818 * was running apps that were using this obscure feature. Example -
819 * calc.exe that comes with Win98 (only Win98, it's different from
820 * the one that comes with Win95 and NT)
822 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
823 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
824 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
827 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
829 if (info.dwFlags & STARTF_USESIZE)
831 cs->cx = info.dwXSize;
832 cs->cy = info.dwYSize;
834 else /* if no other hint from the app, pick 3/4 of the screen real estate */
836 RECT r;
837 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
838 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
839 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
844 else
846 /* neither x nor cx are default. Check the y values .
847 * In the trace we see Outlook and Outlook Express using
848 * cy set to CW_USEDEFAULT when opening the address book.
850 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16) {
851 RECT r;
852 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
853 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
854 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
859 /***********************************************************************
860 * dump_window_styles
862 static void dump_window_styles( DWORD style, DWORD exstyle )
864 TRACE( "style:" );
865 if(style & WS_POPUP) TRACE(" WS_POPUP");
866 if(style & WS_CHILD) TRACE(" WS_CHILD");
867 if(style & WS_MINIMIZE) TRACE(" WS_MINIMIZE");
868 if(style & WS_VISIBLE) TRACE(" WS_VISIBLE");
869 if(style & WS_DISABLED) TRACE(" WS_DISABLED");
870 if(style & WS_CLIPSIBLINGS) TRACE(" WS_CLIPSIBLINGS");
871 if(style & WS_CLIPCHILDREN) TRACE(" WS_CLIPCHILDREN");
872 if(style & WS_MAXIMIZE) TRACE(" WS_MAXIMIZE");
873 if((style & WS_CAPTION) == WS_CAPTION) TRACE(" WS_CAPTION");
874 else
876 if(style & WS_BORDER) TRACE(" WS_BORDER");
877 if(style & WS_DLGFRAME) TRACE(" WS_DLGFRAME");
879 if(style & WS_VSCROLL) TRACE(" WS_VSCROLL");
880 if(style & WS_HSCROLL) TRACE(" WS_HSCROLL");
881 if(style & WS_SYSMENU) TRACE(" WS_SYSMENU");
882 if(style & WS_THICKFRAME) TRACE(" WS_THICKFRAME");
883 if(style & WS_GROUP) TRACE(" WS_GROUP");
884 if(style & WS_TABSTOP) TRACE(" WS_TABSTOP");
885 if(style & WS_MINIMIZEBOX) TRACE(" WS_MINIMIZEBOX");
886 if(style & WS_MAXIMIZEBOX) TRACE(" WS_MAXIMIZEBOX");
888 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
889 #define DUMPED_STYLES \
890 (WS_POPUP | \
891 WS_CHILD | \
892 WS_MINIMIZE | \
893 WS_VISIBLE | \
894 WS_DISABLED | \
895 WS_CLIPSIBLINGS | \
896 WS_CLIPCHILDREN | \
897 WS_MAXIMIZE | \
898 WS_BORDER | \
899 WS_DLGFRAME | \
900 WS_VSCROLL | \
901 WS_HSCROLL | \
902 WS_SYSMENU | \
903 WS_THICKFRAME | \
904 WS_GROUP | \
905 WS_TABSTOP | \
906 WS_MINIMIZEBOX | \
907 WS_MAXIMIZEBOX)
909 if(style & ~DUMPED_STYLES) TRACE(" %08lx", style & ~DUMPED_STYLES);
910 TRACE("\n");
911 #undef DUMPED_STYLES
913 TRACE( "exstyle:" );
914 if(exstyle & WS_EX_DLGMODALFRAME) TRACE(" WS_EX_DLGMODALFRAME");
915 if(exstyle & WS_EX_DRAGDETECT) TRACE(" WS_EX_DRAGDETECT");
916 if(exstyle & WS_EX_NOPARENTNOTIFY) TRACE(" WS_EX_NOPARENTNOTIFY");
917 if(exstyle & WS_EX_TOPMOST) TRACE(" WS_EX_TOPMOST");
918 if(exstyle & WS_EX_ACCEPTFILES) TRACE(" WS_EX_ACCEPTFILES");
919 if(exstyle & WS_EX_TRANSPARENT) TRACE(" WS_EX_TRANSPARENT");
920 if(exstyle & WS_EX_MDICHILD) TRACE(" WS_EX_MDICHILD");
921 if(exstyle & WS_EX_TOOLWINDOW) TRACE(" WS_EX_TOOLWINDOW");
922 if(exstyle & WS_EX_WINDOWEDGE) TRACE(" WS_EX_WINDOWEDGE");
923 if(exstyle & WS_EX_CLIENTEDGE) TRACE(" WS_EX_CLIENTEDGE");
924 if(exstyle & WS_EX_CONTEXTHELP) TRACE(" WS_EX_CONTEXTHELP");
925 if(exstyle & WS_EX_RIGHT) TRACE(" WS_EX_RIGHT");
926 if(exstyle & WS_EX_RTLREADING) TRACE(" WS_EX_RTLREADING");
927 if(exstyle & WS_EX_LEFTSCROLLBAR) TRACE(" WS_EX_LEFTSCROLLBAR");
928 if(exstyle & WS_EX_CONTROLPARENT) TRACE(" WS_EX_CONTROLPARENT");
929 if(exstyle & WS_EX_STATICEDGE) TRACE(" WS_EX_STATICEDGE");
930 if(exstyle & WS_EX_APPWINDOW) TRACE(" WS_EX_APPWINDOW");
931 if(exstyle & WS_EX_LAYERED) TRACE(" WS_EX_LAYERED");
933 #define DUMPED_EX_STYLES \
934 (WS_EX_DLGMODALFRAME | \
935 WS_EX_DRAGDETECT | \
936 WS_EX_NOPARENTNOTIFY | \
937 WS_EX_TOPMOST | \
938 WS_EX_ACCEPTFILES | \
939 WS_EX_TRANSPARENT | \
940 WS_EX_MDICHILD | \
941 WS_EX_TOOLWINDOW | \
942 WS_EX_WINDOWEDGE | \
943 WS_EX_CLIENTEDGE | \
944 WS_EX_CONTEXTHELP | \
945 WS_EX_RIGHT | \
946 WS_EX_RTLREADING | \
947 WS_EX_LEFTSCROLLBAR | \
948 WS_EX_CONTROLPARENT | \
949 WS_EX_STATICEDGE | \
950 WS_EX_APPWINDOW | \
951 WS_EX_LAYERED)
953 if(exstyle & ~DUMPED_EX_STYLES) TRACE(" %08lx", exstyle & ~DUMPED_EX_STYLES);
954 TRACE("\n");
955 #undef DUMPED_EX_STYLES
959 /***********************************************************************
960 * WIN_CreateWindowEx
962 * Implementation of CreateWindowEx().
964 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
965 WINDOWPROCTYPE type )
967 INT sw = SW_SHOW;
968 struct tagCLASS *classPtr;
969 WND *wndPtr;
970 HWND hwnd, parent, owner;
971 INT wndExtra;
972 DWORD clsStyle;
973 WNDPROC winproc;
974 DCE *dce;
975 BOOL unicode = (type == WIN_PROC_32W);
977 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
978 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
979 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszClass) : debugstr_a(cs->lpszClass),
980 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
981 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
983 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
985 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
986 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
988 /* Find the parent window */
990 parent = GetDesktopWindow();
991 owner = 0;
993 if (cs->hwndParent == HWND_MESSAGE)
995 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
996 * message window (style: WS_POPUP|WS_DISABLED)
998 FIXME("Parent is HWND_MESSAGE\n");
1000 else if (cs->hwndParent)
1002 /* Make sure parent is valid */
1003 if (!IsWindow( cs->hwndParent ))
1005 WARN("Bad parent %p\n", cs->hwndParent );
1006 return 0;
1008 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1009 parent = WIN_GetFullHandle(cs->hwndParent);
1010 else
1011 owner = GetAncestor( cs->hwndParent, GA_ROOT );
1013 else if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1015 WARN("No parent for child window\n" );
1016 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1019 /* Find the window class */
1020 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
1021 &wndExtra, &winproc, &clsStyle, &dce )))
1023 WARN("Bad class '%s'\n", cs->lpszClass );
1024 return 0;
1027 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
1029 /* Correct the window style - stage 1
1031 * These are patches that appear to affect both the style loaded into the
1032 * WIN structure and passed in the CreateStruct to the WM_CREATE etc.
1034 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1035 * why does the user get to set it?
1038 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
1039 * tested for WS_POPUP
1041 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
1042 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
1043 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
1044 cs->dwExStyle |= WS_EX_WINDOWEDGE;
1045 else
1046 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
1048 /* Create the window structure */
1050 if (!(wndPtr = create_window_handle( parent, owner, classAtom,
1051 sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
1053 TRACE("out of memory\n" );
1054 return 0;
1056 hwnd = wndPtr->hwndSelf;
1058 /* Fill the window structure */
1060 wndPtr->tid = GetCurrentThreadId();
1061 wndPtr->owner = owner;
1062 wndPtr->parent = parent;
1063 wndPtr->class = classPtr;
1064 wndPtr->winproc = winproc;
1065 wndPtr->hInstance = cs->hInstance;
1066 wndPtr->text = NULL;
1067 wndPtr->hrgnUpdate = 0;
1068 wndPtr->hrgnWnd = 0;
1069 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1070 wndPtr->dwExStyle = cs->dwExStyle;
1071 wndPtr->clsStyle = clsStyle;
1072 wndPtr->wIDmenu = 0;
1073 wndPtr->helpContext = 0;
1074 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
1075 wndPtr->pVScroll = NULL;
1076 wndPtr->pHScroll = NULL;
1077 wndPtr->userdata = 0;
1078 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU) ? MENU_GetSysMenu( hwnd, 0 ) : 0;
1079 wndPtr->cbWndExtra = wndExtra;
1081 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
1083 /* Correct the window style - stage 2 */
1085 if (!(cs->style & WS_CHILD))
1087 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1088 if (!(cs->style & WS_POPUP))
1090 wndPtr->dwStyle |= WS_CAPTION;
1091 wndPtr->flags |= WIN_NEED_SIZE;
1094 SERVER_START_REQ( set_window_info )
1096 req->handle = hwnd;
1097 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE;
1098 req->style = wndPtr->dwStyle;
1099 req->ex_style = wndPtr->dwExStyle;
1100 req->instance = (void *)wndPtr->hInstance;
1101 wine_server_call( req );
1103 SERVER_END_REQ;
1105 /* Get class or window DC if needed */
1107 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
1108 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
1109 else wndPtr->dce = NULL;
1111 /* Set the window menu */
1113 if (((wndPtr->dwStyle & (WS_CAPTION|WS_CHILD)) == WS_CAPTION) ||
1114 (wndPtr->dwExStyle & WS_EX_APPWINDOW))
1116 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
1117 else
1119 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
1120 if (menuName)
1122 if (HIWORD(cs->hInstance))
1123 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1124 else
1125 cs->hMenu = HMENU_32(LoadMenu16(HINSTANCE_16(cs->hInstance),menuName));
1127 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
1131 else SetWindowLongW( hwnd, GWL_ID, (UINT)cs->hMenu );
1132 WIN_ReleaseWndPtr( wndPtr );
1134 if (!USER_Driver.pCreateWindow( hwnd, cs, unicode))
1136 WIN_DestroyWindow( hwnd );
1137 return 0;
1140 /* Notify the parent window only */
1142 send_parent_notify( hwnd, WM_CREATE );
1143 if (!IsWindow( hwnd )) return 0;
1145 if (cs->style & WS_VISIBLE)
1147 /* in case WS_VISIBLE got set in the meantime */
1148 if (!(wndPtr = WIN_GetPtr( hwnd ))) return 0;
1149 WIN_SetStyle( hwnd, wndPtr->dwStyle & ~WS_VISIBLE );
1150 WIN_ReleasePtr( wndPtr );
1151 ShowWindow( hwnd, sw );
1154 /* Call WH_SHELL hook */
1156 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1157 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1159 TRACE("created window %p\n", hwnd);
1160 return hwnd;
1164 /***********************************************************************
1165 * CreateWindow (USER.41)
1167 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1168 DWORD style, INT16 x, INT16 y, INT16 width,
1169 INT16 height, HWND16 parent, HMENU16 menu,
1170 HINSTANCE16 instance, LPVOID data )
1172 return CreateWindowEx16( 0, className, windowName, style,
1173 x, y, width, height, parent, menu, instance, data );
1177 /***********************************************************************
1178 * CreateWindowEx (USER.452)
1180 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1181 LPCSTR windowName, DWORD style, INT16 x,
1182 INT16 y, INT16 width, INT16 height,
1183 HWND16 parent, HMENU16 menu,
1184 HINSTANCE16 instance, LPVOID data )
1186 ATOM classAtom;
1187 CREATESTRUCTA cs;
1188 char buffer[256];
1190 /* Find the class atom */
1192 if (HIWORD(className))
1194 if (!(classAtom = GlobalFindAtomA( className )))
1196 ERR( "bad class name %s\n", debugstr_a(className) );
1197 return 0;
1200 else
1202 classAtom = LOWORD(className);
1203 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1205 ERR( "bad atom %x\n", classAtom);
1206 return 0;
1208 className = buffer;
1211 /* Fix the coordinates */
1213 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1214 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1215 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1216 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1218 /* Create the window */
1220 cs.lpCreateParams = data;
1221 cs.hInstance = HINSTANCE_32(instance);
1222 cs.hMenu = HMENU_32(menu);
1223 cs.hwndParent = WIN_Handle32( parent );
1224 cs.style = style;
1225 cs.lpszName = windowName;
1226 cs.lpszClass = className;
1227 cs.dwExStyle = exStyle;
1229 return HWND_16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
1233 /***********************************************************************
1234 * CreateWindowExA (USER32.@)
1236 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1237 LPCSTR windowName, DWORD style, INT x,
1238 INT y, INT width, INT height,
1239 HWND parent, HMENU menu,
1240 HINSTANCE instance, LPVOID data )
1242 ATOM classAtom;
1243 CREATESTRUCTA cs;
1244 char buffer[256];
1246 if(!instance)
1247 instance=GetModuleHandleA(NULL);
1249 if(exStyle & WS_EX_MDICHILD)
1250 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1252 /* Find the class atom */
1254 if (HIWORD(className))
1256 if (!(classAtom = GlobalFindAtomA( className )))
1258 ERR( "bad class name %s\n", debugstr_a(className) );
1259 return 0;
1262 else
1264 classAtom = LOWORD(className);
1265 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1267 ERR( "bad atom %x\n", classAtom);
1268 return 0;
1270 className = buffer;
1273 /* Create the window */
1275 cs.lpCreateParams = data;
1276 cs.hInstance = instance;
1277 cs.hMenu = menu;
1278 cs.hwndParent = parent;
1279 cs.x = x;
1280 cs.y = y;
1281 cs.cx = width;
1282 cs.cy = height;
1283 cs.style = style;
1284 cs.lpszName = windowName;
1285 cs.lpszClass = className;
1286 cs.dwExStyle = exStyle;
1288 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1292 /***********************************************************************
1293 * CreateWindowExW (USER32.@)
1295 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1296 LPCWSTR windowName, DWORD style, INT x,
1297 INT y, INT width, INT height,
1298 HWND parent, HMENU menu,
1299 HINSTANCE instance, LPVOID data )
1301 ATOM classAtom;
1302 CREATESTRUCTW cs;
1303 WCHAR buffer[256];
1305 if(!instance)
1306 instance=GetModuleHandleW(NULL);
1308 if(exStyle & WS_EX_MDICHILD)
1309 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1311 /* Find the class atom */
1313 if (HIWORD(className))
1315 if (!(classAtom = GlobalFindAtomW( className )))
1317 ERR( "bad class name %s\n", debugstr_w(className) );
1318 return 0;
1321 else
1323 classAtom = LOWORD(className);
1324 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1326 ERR( "bad atom %x\n", classAtom);
1327 return 0;
1329 className = buffer;
1332 /* Create the window */
1334 cs.lpCreateParams = data;
1335 cs.hInstance = instance;
1336 cs.hMenu = menu;
1337 cs.hwndParent = parent;
1338 cs.x = x;
1339 cs.y = y;
1340 cs.cx = width;
1341 cs.cy = height;
1342 cs.style = style;
1343 cs.lpszName = windowName;
1344 cs.lpszClass = className;
1345 cs.dwExStyle = exStyle;
1347 /* Note: we rely on the fact that CREATESTRUCTA and */
1348 /* CREATESTRUCTW have the same layout. */
1349 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1353 /***********************************************************************
1354 * WIN_SendDestroyMsg
1356 static void WIN_SendDestroyMsg( HWND hwnd )
1358 GUITHREADINFO info;
1360 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1362 if (hwnd == info.hwndCaret) DestroyCaret();
1364 if (USER_Driver.pResetSelectionOwner)
1365 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1368 * Send the WM_DESTROY to the window.
1370 SendMessageA( hwnd, WM_DESTROY, 0, 0);
1373 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1374 * make sure that the window still exists when we come back.
1376 if (IsWindow(hwnd))
1378 HWND* pWndArray;
1379 int i;
1381 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1383 /* start from the end (FIXME: is this needed?) */
1384 for (i = 0; pWndArray[i]; i++) ;
1386 while (--i >= 0)
1388 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1390 HeapFree( GetProcessHeap(), 0, pWndArray );
1392 else
1393 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1397 /***********************************************************************
1398 * DestroyWindow (USER32.@)
1400 BOOL WINAPI DestroyWindow( HWND hwnd )
1402 BOOL is_child;
1403 HWND h;
1405 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1407 SetLastError( ERROR_ACCESS_DENIED );
1408 return FALSE;
1411 TRACE("(%p)\n", hwnd);
1413 /* Look whether the focus is within the tree of windows we will
1414 * be destroying.
1416 h = GetFocus();
1417 if (h == hwnd || IsChild( hwnd, h ))
1419 HWND parent = GetAncestor( hwnd, GA_PARENT );
1420 if (parent == GetDesktopWindow()) parent = 0;
1421 SetFocus( parent );
1424 /* Call hooks */
1426 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1428 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1430 if (is_child)
1432 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1433 send_parent_notify( hwnd, WM_DESTROY );
1435 else if (!GetWindow( hwnd, GW_OWNER ))
1437 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1438 /* FIXME: clean up palette - see "Internals" p.352 */
1441 if (!IsWindow(hwnd)) return TRUE;
1443 if (USER_Driver.pResetSelectionOwner)
1444 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1446 /* Hide the window */
1448 if (!ShowWindow( hwnd, SW_HIDE ))
1450 if (hwnd == GetActiveWindow()) WINPOS_ActivateOtherWindow( hwnd );
1452 if (!IsWindow(hwnd)) return TRUE;
1454 /* Recursively destroy owned windows */
1456 if (!is_child)
1458 for (;;)
1460 int i, got_one = 0;
1461 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1462 if (list)
1464 for (i = 0; list[i]; i++)
1466 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1467 if (WIN_IsCurrentThread( list[i] ))
1469 DestroyWindow( list[i] );
1470 got_one = 1;
1471 continue;
1473 WIN_SetOwner( list[i], 0 );
1475 HeapFree( GetProcessHeap(), 0, list );
1477 if (!got_one) break;
1481 /* Send destroy messages */
1483 WIN_SendDestroyMsg( hwnd );
1484 if (!IsWindow( hwnd )) return TRUE;
1486 if (GetClipboardOwner() == hwnd)
1487 CLIPBOARD_ReleaseOwner();
1489 /* Unlink now so we won't bother with the children later on */
1491 WIN_UnlinkWindow( hwnd );
1493 /* Destroy the window storage */
1495 WIN_DestroyWindow( hwnd );
1496 return TRUE;
1500 /***********************************************************************
1501 * CloseWindow (USER32.@)
1503 BOOL WINAPI CloseWindow( HWND hwnd )
1505 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1506 ShowWindow( hwnd, SW_MINIMIZE );
1507 return TRUE;
1511 /***********************************************************************
1512 * OpenIcon (USER32.@)
1514 BOOL WINAPI OpenIcon( HWND hwnd )
1516 if (!IsIconic( hwnd )) return FALSE;
1517 ShowWindow( hwnd, SW_SHOWNORMAL );
1518 return TRUE;
1522 /***********************************************************************
1523 * WIN_FindWindow
1525 * Implementation of FindWindow() and FindWindowEx().
1527 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1529 HWND *list = NULL;
1530 HWND retvalue = 0;
1531 int i = 0, len = 0;
1532 WCHAR *buffer = NULL;
1534 if (!parent) parent = GetDesktopWindow();
1535 if (title)
1537 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1538 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1541 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1543 if (child)
1545 child = WIN_GetFullHandle( child );
1546 while (list[i] && list[i] != child) i++;
1547 if (!list[i]) goto done;
1548 i++; /* start from next window */
1551 if (title)
1553 while (list[i])
1555 if (GetWindowTextW( list[i], buffer, len ) && !strcmpiW( buffer, title )) break;
1556 i++;
1559 retvalue = list[i];
1561 done:
1562 if (list) HeapFree( GetProcessHeap(), 0, list );
1563 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1564 return retvalue;
1569 /***********************************************************************
1570 * FindWindowA (USER32.@)
1572 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1574 HWND ret = FindWindowExA( 0, 0, className, title );
1575 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1576 return ret;
1580 /***********************************************************************
1581 * FindWindowExA (USER32.@)
1583 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1584 LPCSTR className, LPCSTR title )
1586 ATOM atom = 0;
1587 LPWSTR buffer;
1588 HWND hwnd;
1589 INT len;
1591 if (className)
1593 /* If the atom doesn't exist, then no class */
1594 /* with this name exists either. */
1595 if (!(atom = GlobalFindAtomA( className )))
1597 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1598 return 0;
1601 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
1603 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1604 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1605 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
1606 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1607 HeapFree( GetProcessHeap(), 0, buffer );
1608 return hwnd;
1612 /***********************************************************************
1613 * FindWindowExW (USER32.@)
1615 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1616 LPCWSTR className, LPCWSTR title )
1618 ATOM atom = 0;
1620 if (className)
1622 /* If the atom doesn't exist, then no class */
1623 /* with this name exists either. */
1624 if (!(atom = GlobalFindAtomW( className )))
1626 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1627 return 0;
1630 return WIN_FindWindow( parent, child, atom, title );
1634 /***********************************************************************
1635 * FindWindowW (USER32.@)
1637 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1639 return FindWindowExW( 0, 0, className, title );
1643 /**********************************************************************
1644 * GetDesktopWindow (USER32.@)
1646 HWND WINAPI GetDesktopWindow(void)
1648 if (pWndDesktop) return pWndDesktop->hwndSelf;
1649 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" );
1650 ExitProcess(1);
1651 return 0;
1655 /*******************************************************************
1656 * EnableWindow (USER32.@)
1658 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1660 WND *wndPtr;
1661 BOOL retvalue;
1662 LONG style;
1663 HWND full_handle;
1665 if (is_broadcast(hwnd))
1667 SetLastError( ERROR_INVALID_PARAMETER );
1668 return FALSE;
1671 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1672 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1674 hwnd = full_handle;
1676 TRACE("( %p, %d )\n", hwnd, enable);
1678 if (!(wndPtr = WIN_GetPtr( hwnd ))) return FALSE;
1679 style = wndPtr->dwStyle;
1680 retvalue = ((style & WS_DISABLED) != 0);
1681 WIN_ReleasePtr( wndPtr );
1683 if (enable && retvalue)
1685 WIN_SetStyle( hwnd, style & ~WS_DISABLED );
1686 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1688 else if (!enable && !retvalue)
1690 HWND focus_wnd, capture_wnd;
1692 SendMessageA( hwnd, WM_CANCELMODE, 0, 0);
1694 WIN_SetStyle( hwnd, style | WS_DISABLED );
1696 focus_wnd = GetFocus();
1697 if (hwnd == focus_wnd || IsChild(hwnd, focus_wnd))
1698 SetFocus( 0 ); /* A disabled window can't have the focus */
1700 capture_wnd = GetCapture();
1701 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1702 ReleaseCapture(); /* A disabled window can't capture the mouse */
1704 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1706 return retvalue;
1710 /***********************************************************************
1711 * IsWindowEnabled (USER32.@)
1713 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1715 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1719 /***********************************************************************
1720 * IsWindowUnicode (USER32.@)
1722 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1724 WND * wndPtr;
1725 BOOL retvalue;
1727 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1728 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1729 WIN_ReleaseWndPtr(wndPtr);
1730 return retvalue;
1734 /**********************************************************************
1735 * GetWindowWord (USER32.@)
1737 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1739 if (offset >= 0)
1741 WORD retvalue = 0;
1742 WND *wndPtr = WIN_GetPtr( hwnd );
1743 if (!wndPtr)
1745 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1746 return 0;
1748 if (wndPtr == WND_OTHER_PROCESS)
1750 if (IsWindow( hwnd ))
1751 FIXME( "(%d) not supported yet on other process window %p\n", offset, hwnd );
1752 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1753 return 0;
1755 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1757 WARN("Invalid offset %d\n", offset );
1758 SetLastError( ERROR_INVALID_INDEX );
1760 else retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1761 WIN_ReleasePtr( wndPtr );
1762 return retvalue;
1765 switch(offset)
1767 case GWL_HWNDPARENT:
1768 return GetWindowLongW( hwnd, offset );
1769 case GWL_ID:
1770 case GWL_HINSTANCE:
1772 LONG ret = GetWindowLongW( hwnd, offset );
1773 if (HIWORD(ret))
1774 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1775 return LOWORD(ret);
1777 default:
1778 WARN("Invalid offset %d\n", offset );
1779 return 0;
1784 /**********************************************************************
1785 * SetWindowWord (USER32.@)
1787 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1789 WORD *ptr, retval;
1790 WND * wndPtr;
1792 switch(offset)
1794 case GWL_ID:
1795 case GWL_HINSTANCE:
1796 case GWL_HWNDPARENT:
1797 return SetWindowLongW( hwnd, offset, (UINT)newval );
1798 default:
1799 if (offset < 0)
1801 WARN("Invalid offset %d\n", offset );
1802 SetLastError( ERROR_INVALID_INDEX );
1803 return 0;
1807 wndPtr = WIN_GetPtr( hwnd );
1808 if (wndPtr == WND_OTHER_PROCESS)
1810 if (IsWindow(hwnd))
1811 FIXME( "set %d <- %x not supported yet on other process window %p\n",
1812 offset, newval, hwnd );
1813 wndPtr = NULL;
1815 if (!wndPtr)
1817 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1818 return 0;
1821 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1823 WARN("Invalid offset %d\n", offset );
1824 WIN_ReleasePtr(wndPtr);
1825 SetLastError( ERROR_INVALID_INDEX );
1826 return 0;
1828 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1829 retval = *ptr;
1830 *ptr = newval;
1831 WIN_ReleasePtr(wndPtr);
1832 return retval;
1836 /**********************************************************************
1837 * WIN_GetWindowLong
1839 * Helper function for GetWindowLong().
1841 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1843 LONG retvalue = 0;
1844 WND *wndPtr;
1846 if (offset == GWL_HWNDPARENT)
1848 HWND parent = GetAncestor( hwnd, GA_PARENT );
1849 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1850 return (LONG)parent;
1853 if (!(wndPtr = WIN_GetPtr( hwnd )))
1855 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1856 return 0;
1859 if (wndPtr == WND_OTHER_PROCESS)
1861 if (offset >= 0)
1863 if (IsWindow(hwnd))
1864 FIXME( "(%d) not supported on other process window %p\n", offset, hwnd );
1865 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1866 return 0;
1868 if (offset == GWL_WNDPROC)
1870 SetLastError( ERROR_ACCESS_DENIED );
1871 return 0;
1873 SERVER_START_REQ( set_window_info )
1875 req->handle = hwnd;
1876 req->flags = 0; /* don't set anything, just retrieve */
1877 if (!wine_server_call_err( req ))
1879 switch(offset)
1881 case GWL_STYLE: retvalue = reply->old_style; break;
1882 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1883 case GWL_ID: retvalue = reply->old_id; break;
1884 case GWL_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1885 case GWL_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
1886 default:
1887 SetLastError( ERROR_INVALID_INDEX );
1888 break;
1892 SERVER_END_REQ;
1893 return retvalue;
1896 /* now we have a valid wndPtr */
1898 if (offset >= 0)
1900 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
1903 * Some programs try to access last element from 16 bit
1904 * code using illegal offset value. Hopefully this is
1905 * what those programs really expect.
1907 if (type == WIN_PROC_16 &&
1908 wndPtr->cbWndExtra >= 4 &&
1909 offset == wndPtr->cbWndExtra - sizeof(WORD))
1911 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
1913 ERR( "- replaced invalid offset %d with %d\n",
1914 offset, offset2 );
1916 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset2);
1917 WIN_ReleasePtr( wndPtr );
1918 return retvalue;
1920 WARN("Invalid offset %d\n", offset );
1921 WIN_ReleasePtr( wndPtr );
1922 SetLastError( ERROR_INVALID_INDEX );
1923 return 0;
1925 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1926 /* Special case for dialog window procedure */
1927 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1928 retvalue = (LONG)WINPROC_GetProc( (WNDPROC)retvalue, type );
1929 WIN_ReleasePtr( wndPtr );
1930 return retvalue;
1933 switch(offset)
1935 case GWL_USERDATA: retvalue = wndPtr->userdata; break;
1936 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1937 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1938 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu; break;
1939 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc, type ); break;
1940 case GWL_HINSTANCE: retvalue = (LONG)wndPtr->hInstance; break;
1941 default:
1942 WARN("Unknown offset %d\n", offset );
1943 SetLastError( ERROR_INVALID_INDEX );
1944 break;
1946 WIN_ReleasePtr(wndPtr);
1947 return retvalue;
1951 /**********************************************************************
1952 * WIN_SetWindowLong
1954 * Helper function for SetWindowLong().
1956 * 0 is the failure code. However, in the case of failure SetLastError
1957 * must be set to distinguish between a 0 return value and a failure.
1959 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1960 WINDOWPROCTYPE type )
1962 LONG retval = 0;
1963 WND *wndPtr;
1965 TRACE( "%p %d %lx %x\n", hwnd, offset, newval, type );
1967 if (is_broadcast(hwnd))
1969 SetLastError( ERROR_INVALID_PARAMETER );
1970 return FALSE;
1972 if (!WIN_IsCurrentProcess( hwnd ))
1974 if (offset == GWL_WNDPROC)
1976 SetLastError( ERROR_ACCESS_DENIED );
1977 return 0;
1979 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
1982 wndPtr = WIN_GetPtr( hwnd );
1983 if (wndPtr->hwndSelf == GetDesktopWindow())
1985 /* can't change anything on the desktop window */
1986 WIN_ReleasePtr( wndPtr );
1987 SetLastError( ERROR_ACCESS_DENIED );
1988 return 0;
1991 if (offset >= 0)
1993 LONG *ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1994 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
1996 WARN("Invalid offset %d\n", offset );
1997 WIN_ReleasePtr( wndPtr );
1998 SetLastError( ERROR_INVALID_INDEX );
1999 return 0;
2001 /* Special case for dialog window procedure */
2002 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2004 retval = (LONG)WINPROC_GetProc( (WNDPROC)*ptr, type );
2005 WINPROC_SetProc( (WNDPROC *)ptr, (WNDPROC)newval, type, WIN_PROC_WINDOW );
2006 WIN_ReleasePtr( wndPtr );
2007 return retval;
2009 retval = *ptr;
2010 *ptr = newval;
2011 WIN_ReleasePtr( wndPtr );
2013 else
2015 STYLESTRUCT style;
2016 BOOL ok;
2018 /* first some special cases */
2019 switch( offset )
2021 case GWL_STYLE:
2022 case GWL_EXSTYLE:
2023 style.styleOld = wndPtr->dwStyle;
2024 style.styleNew = newval;
2025 WIN_ReleasePtr( wndPtr );
2026 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
2027 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
2028 newval = style.styleNew;
2029 break;
2030 case GWL_HWNDPARENT:
2031 if (wndPtr->parent == GetDesktopWindow())
2033 WIN_ReleasePtr( wndPtr );
2034 return (LONG)WIN_SetOwner( hwnd, (HWND)newval );
2036 else
2038 WIN_ReleasePtr( wndPtr );
2039 return (LONG)SetParent( hwnd, (HWND)newval );
2041 case GWL_WNDPROC:
2042 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2043 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC)newval, type, WIN_PROC_WINDOW );
2044 WIN_ReleasePtr( wndPtr );
2045 return retval;
2046 case GWL_ID:
2047 case GWL_HINSTANCE:
2048 case GWL_USERDATA:
2049 break;
2050 default:
2051 WIN_ReleasePtr( wndPtr );
2052 WARN("Invalid offset %d\n", offset );
2053 SetLastError( ERROR_INVALID_INDEX );
2054 return 0;
2057 SERVER_START_REQ( set_window_info )
2059 req->handle = hwnd;
2060 switch(offset)
2062 case GWL_STYLE:
2063 req->flags = SET_WIN_STYLE;
2064 req->style = newval;
2065 break;
2066 case GWL_EXSTYLE:
2067 req->flags = SET_WIN_EXSTYLE;
2068 req->ex_style = newval;
2069 break;
2070 case GWL_ID:
2071 req->flags = SET_WIN_ID;
2072 req->id = newval;
2073 break;
2074 case GWL_HINSTANCE:
2075 req->flags = SET_WIN_INSTANCE;
2076 req->instance = (void *)newval;
2077 break;
2078 case GWL_USERDATA:
2079 req->flags = SET_WIN_USERDATA;
2080 req->user_data = (void *)newval;
2081 break;
2083 if ((ok = !wine_server_call_err( req )))
2085 switch(offset)
2087 case GWL_STYLE:
2088 wndPtr->dwStyle = newval;
2089 retval = reply->old_style;
2090 break;
2091 case GWL_EXSTYLE:
2092 wndPtr->dwExStyle = newval;
2093 retval = reply->old_ex_style;
2094 break;
2095 case GWL_ID:
2096 wndPtr->wIDmenu = newval;
2097 retval = reply->old_id;
2098 break;
2099 case GWL_HINSTANCE:
2100 wndPtr->hInstance = (HINSTANCE)newval;
2101 retval = (ULONG_PTR)reply->old_instance;
2102 break;
2103 case GWL_USERDATA:
2104 wndPtr->userdata = newval;
2105 retval = (ULONG_PTR)reply->old_user_data;
2106 break;
2110 SERVER_END_REQ;
2111 WIN_ReleasePtr( wndPtr );
2113 if (!ok) return 0;
2115 if (offset == GWL_STYLE && USER_Driver.pSetWindowStyle)
2116 USER_Driver.pSetWindowStyle( hwnd, retval );
2118 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2119 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2122 return retval;
2126 /**********************************************************************
2127 * GetWindowLong (USER.135)
2129 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2131 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
2135 /**********************************************************************
2136 * GetWindowLongA (USER32.@)
2138 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2140 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2144 /**********************************************************************
2145 * GetWindowLongW (USER32.@)
2147 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2149 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2153 /**********************************************************************
2154 * SetWindowLong (USER.136)
2156 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2158 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
2162 /**********************************************************************
2163 * SetWindowLongA (USER32.@)
2165 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2167 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2171 /**********************************************************************
2172 * SetWindowLongW (USER32.@) Set window attribute
2174 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2175 * value in a window's extra memory.
2177 * The _hwnd_ parameter specifies the window. is the handle to a
2178 * window that has extra memory. The _newval_ parameter contains the
2179 * new attribute or extra memory value. If positive, the _offset_
2180 * parameter is the byte-addressed location in the window's extra
2181 * memory to set. If negative, _offset_ specifies the window
2182 * attribute to set, and should be one of the following values:
2184 * GWL_EXSTYLE The window's extended window style
2186 * GWL_STYLE The window's window style.
2188 * GWL_WNDPROC Pointer to the window's window procedure.
2190 * GWL_HINSTANCE The window's pplication instance handle.
2192 * GWL_ID The window's identifier.
2194 * GWL_USERDATA The window's user-specified data.
2196 * If the window is a dialog box, the _offset_ parameter can be one of
2197 * the following values:
2199 * DWL_DLGPROC The address of the window's dialog box procedure.
2201 * DWL_MSGRESULT The return value of a message
2202 * that the dialog box procedure processed.
2204 * DWL_USER Application specific information.
2206 * RETURNS
2208 * If successful, returns the previous value located at _offset_. Otherwise,
2209 * returns 0.
2211 * NOTES
2213 * Extra memory for a window class is specified by a nonzero cbWndExtra
2214 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2215 * time of class creation.
2217 * Using GWL_WNDPROC to set a new window procedure effectively creates
2218 * a window subclass. Use CallWindowProc() in the new windows procedure
2219 * to pass messages to the superclass's window procedure.
2221 * The user data is reserved for use by the application which created
2222 * the window.
2224 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2225 * instead, call the EnableWindow() function to change the window's
2226 * disabled state.
2228 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2229 * SetParent() instead.
2231 * Win95:
2232 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2233 * it sends WM_STYLECHANGING before changing the settings
2234 * and WM_STYLECHANGED afterwards.
2235 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2237 LONG WINAPI SetWindowLongW(
2238 HWND hwnd, /* [in] window to alter */
2239 INT offset, /* [in] offset, in bytes, of location to alter */
2240 LONG newval /* [in] new value of location */
2242 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2246 /*******************************************************************
2247 * GetWindowTextA (USER32.@)
2249 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2251 WCHAR *buffer;
2253 if (WIN_IsCurrentProcess( hwnd ))
2254 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2256 /* when window belongs to other process, don't send a message */
2257 if (nMaxCount <= 0) return 0;
2258 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2259 get_server_window_text( hwnd, buffer, nMaxCount );
2260 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2261 lpString[nMaxCount-1] = 0;
2262 HeapFree( GetProcessHeap(), 0, buffer );
2263 return strlen(lpString);
2267 /*******************************************************************
2268 * InternalGetWindowText (USER32.@)
2270 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2272 WND *win;
2274 if (nMaxCount <= 0) return 0;
2275 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2276 if (win != WND_OTHER_PROCESS)
2278 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2279 else lpString[0] = 0;
2280 WIN_ReleasePtr( win );
2282 else
2284 get_server_window_text( hwnd, lpString, nMaxCount );
2286 return strlenW(lpString);
2290 /*******************************************************************
2291 * GetWindowTextW (USER32.@)
2293 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2295 if (WIN_IsCurrentProcess( hwnd ))
2296 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2298 /* when window belongs to other process, don't send a message */
2299 if (nMaxCount <= 0) return 0;
2300 get_server_window_text( hwnd, lpString, nMaxCount );
2301 return strlenW(lpString);
2305 /*******************************************************************
2306 * SetWindowText (USER32.@)
2307 * SetWindowTextA (USER32.@)
2309 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2311 if (is_broadcast(hwnd))
2313 SetLastError( ERROR_INVALID_PARAMETER );
2314 return FALSE;
2316 if (!WIN_IsCurrentProcess( hwnd ))
2318 FIXME( "cannot set text %s of other process window %p\n", debugstr_a(lpString), hwnd );
2319 SetLastError( ERROR_ACCESS_DENIED );
2320 return FALSE;
2322 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2326 /*******************************************************************
2327 * SetWindowTextW (USER32.@)
2329 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2331 if (is_broadcast(hwnd))
2333 SetLastError( ERROR_INVALID_PARAMETER );
2334 return FALSE;
2336 if (!WIN_IsCurrentProcess( hwnd ))
2338 FIXME( "cannot set text %s of other process window %p\n", debugstr_w(lpString), hwnd );
2339 SetLastError( ERROR_ACCESS_DENIED );
2340 return FALSE;
2342 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2346 /*******************************************************************
2347 * GetWindowTextLengthA (USER32.@)
2349 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2351 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2354 /*******************************************************************
2355 * GetWindowTextLengthW (USER32.@)
2357 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2359 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2363 /*******************************************************************
2364 * IsWindow (USER32.@)
2366 BOOL WINAPI IsWindow( HWND hwnd )
2368 WND *ptr;
2369 BOOL ret;
2371 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2373 if (ptr != WND_OTHER_PROCESS)
2375 WIN_ReleasePtr( ptr );
2376 return TRUE;
2379 /* check other processes */
2380 SERVER_START_REQ( get_window_info )
2382 req->handle = hwnd;
2383 ret = !wine_server_call_err( req );
2385 SERVER_END_REQ;
2386 return ret;
2390 /***********************************************************************
2391 * GetWindowThreadProcessId (USER32.@)
2393 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2395 WND *ptr;
2396 DWORD tid = 0;
2398 if (!(ptr = WIN_GetPtr( hwnd )))
2400 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2401 return 0;
2404 if (ptr != WND_OTHER_PROCESS)
2406 /* got a valid window */
2407 tid = ptr->tid;
2408 if (process) *process = GetCurrentProcessId();
2409 WIN_ReleasePtr( ptr );
2410 return tid;
2413 /* check other processes */
2414 SERVER_START_REQ( get_window_info )
2416 req->handle = hwnd;
2417 if (!wine_server_call_err( req ))
2419 tid = (DWORD)reply->tid;
2420 if (process) *process = (DWORD)reply->pid;
2423 SERVER_END_REQ;
2424 return tid;
2428 /*****************************************************************
2429 * GetParent (USER32.@)
2431 HWND WINAPI GetParent( HWND hwnd )
2433 WND *wndPtr;
2434 HWND retvalue = 0;
2436 if (!(wndPtr = WIN_GetPtr( hwnd )))
2438 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2439 return 0;
2441 if (wndPtr == WND_OTHER_PROCESS)
2443 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2444 if (style & (WS_POPUP | WS_CHILD))
2446 SERVER_START_REQ( get_window_tree )
2448 req->handle = hwnd;
2449 if (!wine_server_call_err( req ))
2451 if (style & WS_POPUP) retvalue = reply->owner;
2452 else if (style & WS_CHILD) retvalue = reply->parent;
2455 SERVER_END_REQ;
2458 else
2460 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2461 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2462 WIN_ReleasePtr( wndPtr );
2464 return retvalue;
2468 /*****************************************************************
2469 * GetAncestor (USER32.@)
2471 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2473 WND *win;
2474 HWND *list, ret = 0;
2476 switch(type)
2478 case GA_PARENT:
2479 if (!(win = WIN_GetPtr( hwnd )))
2481 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2482 return 0;
2484 if (win != WND_OTHER_PROCESS)
2486 ret = win->parent;
2487 WIN_ReleasePtr( win );
2489 else /* need to query the server */
2491 SERVER_START_REQ( get_window_tree )
2493 req->handle = hwnd;
2494 if (!wine_server_call_err( req )) ret = reply->parent;
2496 SERVER_END_REQ;
2498 break;
2500 case GA_ROOT:
2501 if (!(list = WIN_ListParents( hwnd ))) return 0;
2503 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2504 else
2506 int count = 2;
2507 while (list[count]) count++;
2508 ret = list[count - 2]; /* get the one before the desktop */
2510 HeapFree( GetProcessHeap(), 0, list );
2511 break;
2513 case GA_ROOTOWNER:
2514 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2515 for (;;)
2517 HWND parent = GetParent( ret );
2518 if (!parent) break;
2519 ret = parent;
2521 break;
2523 return ret;
2527 /*****************************************************************
2528 * SetParent (USER32.@)
2530 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2532 WND *wndPtr;
2533 HWND retvalue, full_handle;
2534 BOOL was_visible;
2536 if (is_broadcast(hwnd) || is_broadcast(parent))
2538 SetLastError(ERROR_INVALID_PARAMETER);
2539 return 0;
2542 if (!parent) parent = GetDesktopWindow();
2543 else parent = WIN_GetFullHandle( parent );
2545 if (!IsWindow( parent ))
2547 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2548 return 0;
2551 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2552 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2554 hwnd = full_handle;
2556 if (USER_Driver.pSetParent)
2557 return USER_Driver.pSetParent( hwnd, parent );
2559 /* Windows hides the window first, then shows it again
2560 * including the WM_SHOWWINDOW messages and all */
2561 was_visible = ShowWindow( hwnd, SW_HIDE );
2563 if (!IsWindow( parent )) return 0;
2564 if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return 0;
2566 retvalue = wndPtr->parent; /* old parent */
2567 if (parent != retvalue)
2569 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2571 if (parent != GetDesktopWindow()) /* a child window */
2573 if (!(wndPtr->dwStyle & WS_CHILD))
2575 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
2576 if (menu) DestroyMenu( menu );
2580 WIN_ReleasePtr( wndPtr );
2582 /* SetParent additionally needs to make hwnd the topmost window
2583 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2584 WM_WINDOWPOSCHANGED notification messages.
2586 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2587 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2588 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2589 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2590 return retvalue;
2594 /*******************************************************************
2595 * IsChild (USER32.@)
2597 BOOL WINAPI IsChild( HWND parent, HWND child )
2599 HWND *list = WIN_ListParents( child );
2600 int i;
2601 BOOL ret;
2603 if (!list) return FALSE;
2604 parent = WIN_GetFullHandle( parent );
2605 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2606 ret = (list[i] != 0);
2607 HeapFree( GetProcessHeap(), 0, list );
2608 return ret;
2612 /***********************************************************************
2613 * IsWindowVisible (USER32.@)
2615 BOOL WINAPI IsWindowVisible( HWND hwnd )
2617 HWND *list;
2618 BOOL retval;
2619 int i;
2621 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2622 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2623 for (i = 0; list[i]; i++)
2624 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2625 retval = !list[i];
2626 HeapFree( GetProcessHeap(), 0, list );
2627 return retval;
2631 /***********************************************************************
2632 * WIN_IsWindowDrawable
2634 * hwnd is drawable when it is visible, all parents are not
2635 * minimized, and it is itself not minimized unless we are
2636 * trying to draw its default class icon.
2638 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2640 HWND *list;
2641 BOOL retval;
2642 int i;
2643 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2645 if (!(style & WS_VISIBLE)) return FALSE;
2646 if ((style & WS_MINIMIZE) && icon && GetClassLongA( hwnd, GCL_HICON )) return FALSE;
2648 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2649 for (i = 0; list[i]; i++)
2650 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2651 break;
2652 retval = !list[i];
2653 HeapFree( GetProcessHeap(), 0, list );
2654 return retval;
2658 /*******************************************************************
2659 * GetTopWindow (USER32.@)
2661 HWND WINAPI GetTopWindow( HWND hwnd )
2663 if (!hwnd) hwnd = GetDesktopWindow();
2664 return GetWindow( hwnd, GW_CHILD );
2668 /*******************************************************************
2669 * GetWindow (USER32.@)
2671 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2673 HWND retval = 0;
2675 if (rel == GW_OWNER) /* this one may be available locally */
2677 WND *wndPtr = WIN_GetPtr( hwnd );
2678 if (!wndPtr)
2680 SetLastError( ERROR_INVALID_HANDLE );
2681 return 0;
2683 if (wndPtr != WND_OTHER_PROCESS)
2685 retval = wndPtr->owner;
2686 WIN_ReleasePtr( wndPtr );
2687 return retval;
2689 /* else fall through to server call */
2692 SERVER_START_REQ( get_window_tree )
2694 req->handle = hwnd;
2695 if (!wine_server_call_err( req ))
2697 switch(rel)
2699 case GW_HWNDFIRST:
2700 retval = reply->first_sibling;
2701 break;
2702 case GW_HWNDLAST:
2703 retval = reply->last_sibling;
2704 break;
2705 case GW_HWNDNEXT:
2706 retval = reply->next_sibling;
2707 break;
2708 case GW_HWNDPREV:
2709 retval = reply->prev_sibling;
2710 break;
2711 case GW_OWNER:
2712 retval = reply->owner;
2713 break;
2714 case GW_CHILD:
2715 retval = reply->first_child;
2716 break;
2720 SERVER_END_REQ;
2721 return retval;
2725 /***********************************************************************
2726 * WIN_InternalShowOwnedPopups
2728 * Internal version of ShowOwnedPopups; Wine functions should use this
2729 * to avoid interfering with application calls to ShowOwnedPopups
2730 * and to make sure the application can't prevent showing/hiding.
2732 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2736 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2738 int count = 0;
2739 WND *pWnd;
2740 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2742 if (!win_array) return TRUE;
2745 * Show windows Lowest first, Highest last to preserve Z-Order
2747 while (win_array[count]) count++;
2748 while (--count >= 0)
2750 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2751 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2753 if (pWnd->dwStyle & WS_POPUP)
2755 if (fShow)
2757 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2758 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
2761 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2763 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2764 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2767 else
2769 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2770 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2771 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2774 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2776 ShowWindow(pWnd->hwndSelf,SW_HIDE);
2777 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2778 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
2782 WIN_ReleaseWndPtr( pWnd );
2784 HeapFree( GetProcessHeap(), 0, win_array );
2786 return TRUE;
2789 /*******************************************************************
2790 * ShowOwnedPopups (USER32.@)
2792 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2794 int count = 0;
2795 WND *pWnd;
2796 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2798 if (!win_array) return TRUE;
2800 while (win_array[count]) count++;
2801 while (--count >= 0)
2803 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2804 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2806 if (pWnd->dwStyle & WS_POPUP)
2808 if (fShow)
2810 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2812 /* In Windows, ShowOwnedPopups(TRUE) generates
2813 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2814 * regardless of the state of the owner
2816 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2817 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2820 else
2822 if (IsWindowVisible(pWnd->hwndSelf))
2824 /* In Windows, ShowOwnedPopups(FALSE) generates
2825 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2826 * regardless of the state of the owner
2828 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2829 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2833 WIN_ReleaseWndPtr( pWnd );
2835 HeapFree( GetProcessHeap(), 0, win_array );
2836 return TRUE;
2840 /*******************************************************************
2841 * GetLastActivePopup (USER32.@)
2843 HWND WINAPI GetLastActivePopup( HWND hwnd )
2845 HWND retval = hwnd;
2847 SERVER_START_REQ( get_window_info )
2849 req->handle = hwnd;
2850 if (!wine_server_call_err( req )) retval = reply->last_active;
2852 SERVER_END_REQ;
2853 return retval;
2857 /*******************************************************************
2858 * WIN_ListParents
2860 * Build an array of all parents of a given window, starting with
2861 * the immediate parent. The array must be freed with HeapFree.
2862 * Returns NULL if window is a top-level window.
2864 HWND *WIN_ListParents( HWND hwnd )
2866 WND *win;
2867 HWND current, *list;
2868 int pos = 0, size = 16, count = 0;
2870 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2872 current = hwnd;
2873 for (;;)
2875 if (!(win = WIN_GetPtr( current ))) goto empty;
2876 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
2877 list[pos] = win->parent;
2878 WIN_ReleasePtr( win );
2879 if (!(current = list[pos]))
2881 if (!pos) goto empty;
2882 return list;
2884 if (++pos == size - 1)
2886 /* need to grow the list */
2887 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
2888 if (!new_list) goto empty;
2889 list = new_list;
2890 size += 16;
2894 /* at least one parent belongs to another process, have to query the server */
2896 for (;;)
2898 count = 0;
2899 SERVER_START_REQ( get_window_parents )
2901 req->handle = hwnd;
2902 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
2903 if (!wine_server_call( req )) count = reply->count;
2905 SERVER_END_REQ;
2906 if (!count) goto empty;
2907 if (size > count)
2909 list[count] = 0;
2910 return list;
2912 HeapFree( GetProcessHeap(), 0, list );
2913 size = count + 1;
2914 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2917 empty:
2918 HeapFree( GetProcessHeap(), 0, list );
2919 return NULL;
2923 /*******************************************************************
2924 * WIN_ListChildren
2926 * Build an array of the children of a given window. The array must be
2927 * freed with HeapFree. Returns NULL when no windows are found.
2929 HWND *WIN_ListChildren( HWND hwnd )
2931 return list_window_children( hwnd, 0, 0 );
2935 /*******************************************************************
2936 * EnumWindows (USER32.@)
2938 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2940 HWND *list;
2941 BOOL ret = TRUE;
2942 int i, iWndsLocks;
2944 /* We have to build a list of all windows first, to avoid */
2945 /* unpleasant side-effects, for instance if the callback */
2946 /* function changes the Z-order of the windows. */
2948 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2950 /* Now call the callback function for every window */
2952 iWndsLocks = WIN_SuspendWndsLock();
2953 for (i = 0; list[i]; i++)
2955 /* Make sure that the window still exists */
2956 if (!IsWindow( list[i] )) continue;
2957 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2959 WIN_RestoreWndsLock(iWndsLocks);
2960 HeapFree( GetProcessHeap(), 0, list );
2961 return ret;
2965 /**********************************************************************
2966 * EnumThreadWindows (USER32.@)
2968 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2970 HWND *list;
2971 int i, iWndsLocks;
2973 if (!(list = list_window_children( GetDesktopWindow(), 0, id ))) return TRUE;
2975 /* Now call the callback function for every window */
2977 iWndsLocks = WIN_SuspendWndsLock();
2978 for (i = 0; list[i]; i++)
2979 if (!func( list[i], lParam )) break;
2980 WIN_RestoreWndsLock(iWndsLocks);
2981 HeapFree( GetProcessHeap(), 0, list );
2982 return TRUE;
2986 /**********************************************************************
2987 * WIN_EnumChildWindows
2989 * Helper function for EnumChildWindows().
2991 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2993 HWND *childList;
2994 BOOL ret = FALSE;
2996 for ( ; *list; list++)
2998 /* Make sure that the window still exists */
2999 if (!IsWindow( *list )) continue;
3000 /* skip owned windows */
3001 if (GetWindow( *list, GW_OWNER )) continue;
3002 /* Build children list first */
3003 childList = WIN_ListChildren( *list );
3005 ret = func( *list, lParam );
3007 if (childList)
3009 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
3010 HeapFree( GetProcessHeap(), 0, childList );
3012 if (!ret) return FALSE;
3014 return TRUE;
3018 /**********************************************************************
3019 * EnumChildWindows (USER32.@)
3021 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
3023 HWND *list;
3024 int iWndsLocks;
3026 if (!(list = WIN_ListChildren( parent ))) return FALSE;
3027 iWndsLocks = WIN_SuspendWndsLock();
3028 WIN_EnumChildWindows( list, func, lParam );
3029 WIN_RestoreWndsLock(iWndsLocks);
3030 HeapFree( GetProcessHeap(), 0, list );
3031 return TRUE;
3035 /*******************************************************************
3036 * AnyPopup (USER.52)
3038 BOOL16 WINAPI AnyPopup16(void)
3040 return AnyPopup();
3044 /*******************************************************************
3045 * AnyPopup (USER32.@)
3047 BOOL WINAPI AnyPopup(void)
3049 int i;
3050 BOOL retvalue;
3051 HWND *list = WIN_ListChildren( GetDesktopWindow() );
3053 if (!list) return FALSE;
3054 for (i = 0; list[i]; i++)
3056 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
3058 retvalue = (list[i] != 0);
3059 HeapFree( GetProcessHeap(), 0, list );
3060 return retvalue;
3064 /*******************************************************************
3065 * FlashWindow (USER32.@)
3067 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3069 WND *wndPtr = WIN_FindWndPtr(hWnd);
3071 TRACE("%p\n", hWnd);
3073 if (!wndPtr) return FALSE;
3074 hWnd = wndPtr->hwndSelf; /* make it a full handle */
3076 if (wndPtr->dwStyle & WS_MINIMIZE)
3078 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3080 HDC hDC = GetDC(hWnd);
3082 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM)hDC, 0 ))
3083 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
3085 ReleaseDC( hWnd, hDC );
3086 wndPtr->flags |= WIN_NCACTIVATED;
3088 else
3090 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3091 wndPtr->flags &= ~WIN_NCACTIVATED;
3093 WIN_ReleaseWndPtr(wndPtr);
3094 return TRUE;
3096 else
3098 WPARAM16 wparam;
3099 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3100 else wparam = (hWnd == GetForegroundWindow());
3102 WIN_ReleaseWndPtr(wndPtr);
3103 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3104 return wparam;
3108 /*******************************************************************
3109 * FlashWindowEx (USER32.@)
3111 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
3113 FIXME("%p\n", pfwi);
3114 return TRUE;
3117 /*******************************************************************
3118 * GetWindowContextHelpId (USER32.@)
3120 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3122 DWORD retval;
3123 WND *wnd = WIN_FindWndPtr( hwnd );
3124 if (!wnd) return 0;
3125 retval = wnd->helpContext;
3126 WIN_ReleaseWndPtr(wnd);
3127 return retval;
3131 /*******************************************************************
3132 * SetWindowContextHelpId (USER32.@)
3134 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3136 WND *wnd = WIN_FindWndPtr( hwnd );
3137 if (!wnd) return FALSE;
3138 wnd->helpContext = id;
3139 WIN_ReleaseWndPtr(wnd);
3140 return TRUE;
3144 /*******************************************************************
3145 * DragDetect (USER32.@)
3147 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3149 MSG msg;
3150 RECT rect;
3152 rect.left = pt.x - wDragWidth;
3153 rect.right = pt.x + wDragWidth;
3155 rect.top = pt.y - wDragHeight;
3156 rect.bottom = pt.y + wDragHeight;
3158 SetCapture(hWnd);
3160 while(1)
3162 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3164 if( msg.message == WM_LBUTTONUP )
3166 ReleaseCapture();
3167 return 0;
3169 if( msg.message == WM_MOUSEMOVE )
3171 POINT tmp;
3172 tmp.x = LOWORD(msg.lParam);
3173 tmp.y = HIWORD(msg.lParam);
3174 if( !PtInRect( &rect, tmp ))
3176 ReleaseCapture();
3177 return 1;
3181 WaitMessage();
3183 return 0;
3186 /******************************************************************************
3187 * GetWindowModuleFileNameA (USER32.@)
3189 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3191 FIXME("GetWindowModuleFileNameA(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3192 hwnd, lpszFileName, cchFileNameMax);
3193 return 0;
3196 /******************************************************************************
3197 * GetWindowModuleFileNameW (USER32.@)
3199 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3201 FIXME("GetWindowModuleFileNameW(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3202 hwnd, lpszFileName, cchFileNameMax);
3203 return 0;
3206 /******************************************************************************
3207 * GetWindowInfo (USER32.@)
3208 * hwnd: in
3209 * pwi: out.
3210 * MS Documentation mentions that pwi->cbSize must be set to SIZEOF(WINDOWINFO)
3211 * this may be because this structure changed over time. If this is the
3212 * the case, then please: FIXME.
3213 * Using the structure described in MSDN for 98/ME/NT(4.0 SP3)/2000/XP.
3215 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3217 if (!pwi) return FALSE;
3218 if (pwi->cbSize != sizeof(WINDOWINFO))
3220 FIXME("windowinfo->cbSize != sizeof(WINDOWINFO). Please report\n");
3221 return FALSE;
3223 if (!IsWindow(hwnd)) return FALSE;
3225 GetWindowRect(hwnd, &pwi->rcWindow);
3226 GetClientRect(hwnd, &pwi->rcClient);
3227 /* translate to screen coordinates */
3228 MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3230 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3231 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3232 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3234 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3235 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3237 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3238 pwi->wCreatorVersion = 0x0400;
3240 return TRUE;