CreateStreamOnFile(): use flag FILE_SHARE_READ for opening OLE stream
[wine/wine64.git] / windows / win.c
blob9b7eff9b6b019c922ff1caf5cb7599018208ca87
1 /*
2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "config.h"
22 #include "wine/port.h"
24 #include <assert.h>
25 #include <stdarg.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include "windef.h"
29 #include "winbase.h"
30 #include "wine/winbase16.h"
31 #include "wine/winuser16.h"
32 #include "wownt32.h"
33 #include "wine/server.h"
34 #include "wine/unicode.h"
35 #include "win.h"
36 #include "user.h"
37 #include "dce.h"
38 #include "controls.h"
39 #include "cursoricon.h"
40 #include "message.h"
41 #include "winpos.h"
42 #include "winerror.h"
43 #include "wine/debug.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(win);
46 WINE_DECLARE_DEBUG_CHANNEL(msg);
48 #define NB_USER_HANDLES (LAST_USER_HANDLE - FIRST_USER_HANDLE + 1)
50 /**********************************************************************/
52 /* Desktop window */
53 static WND *pWndDesktop = NULL;
55 static WORD wDragWidth = 4;
56 static WORD wDragHeight= 3;
58 static void *user_handles[NB_USER_HANDLES];
60 /***********************************************************************
61 * create_window_handle
63 * Create a window handle with the server.
65 static WND *create_window_handle( HWND parent, HWND owner, ATOM atom,
66 HINSTANCE instance, WINDOWPROCTYPE type )
68 WORD index;
69 WND *win;
70 struct tagCLASS *class = NULL;
71 user_handle_t handle = 0;
72 int extra_bytes = 0;
74 if (type == WIN_PROC_16) instance = HINSTANCE_32(GetExePtr(HINSTANCE_16(instance)));
76 SERVER_START_REQ( create_window )
78 req->parent = parent;
79 req->owner = owner;
80 req->atom = atom;
81 req->instance = instance;
82 if (!wine_server_call_err( req ))
84 handle = reply->handle;
85 extra_bytes = reply->extra;
86 class = reply->class_ptr;
89 SERVER_END_REQ;
91 if (!handle)
93 WARN( "error %ld creating window\n", GetLastError() );
94 return NULL;
97 if (!(win = HeapAlloc( GetProcessHeap(), 0, sizeof(WND) + extra_bytes - sizeof(win->wExtra) )))
99 SERVER_START_REQ( destroy_window )
101 req->handle = handle;
102 wine_server_call( req );
104 SERVER_END_REQ;
105 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
106 return NULL;
109 USER_Lock();
111 index = LOWORD(handle) - FIRST_USER_HANDLE;
112 assert( index < NB_USER_HANDLES );
113 user_handles[index] = win;
114 win->hwndSelf = handle;
115 win->dwMagic = WND_MAGIC;
116 win->irefCount = 1;
117 win->cbWndExtra = extra_bytes;
118 memset( win->wExtra, 0, extra_bytes );
119 CLASS_AddWindow( class, win, type );
120 return win;
124 /***********************************************************************
125 * free_window_handle
127 * Free a window handle.
129 static WND *free_window_handle( HWND hwnd )
131 WND *ptr;
132 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
134 if (index >= NB_USER_HANDLES) return NULL;
135 USER_Lock();
136 if ((ptr = user_handles[index]))
138 SERVER_START_REQ( destroy_window )
140 req->handle = hwnd;
141 if (!wine_server_call_err( req ))
142 user_handles[index] = NULL;
143 else
144 ptr = NULL;
146 SERVER_END_REQ;
148 USER_Unlock();
149 if (ptr) HeapFree( GetProcessHeap(), 0, ptr );
150 return ptr;
154 /*******************************************************************
155 * list_window_children
157 * Build an array of the children of a given window. The array must be
158 * freed with HeapFree. Returns NULL when no windows are found.
160 static HWND *list_window_children( HWND hwnd, ATOM atom, DWORD tid )
162 HWND *list;
163 int size = 32;
165 for (;;)
167 int count = 0;
169 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
171 SERVER_START_REQ( get_window_children )
173 req->parent = hwnd;
174 req->atom = atom;
175 req->tid = tid;
176 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
177 if (!wine_server_call( req )) count = reply->count;
179 SERVER_END_REQ;
180 if (count && count < size)
182 list[count] = 0;
183 return list;
185 HeapFree( GetProcessHeap(), 0, list );
186 if (!count) break;
187 size = count + 1; /* restart with a large enough buffer */
189 return NULL;
193 /*******************************************************************
194 * send_parent_notify
196 static void send_parent_notify( HWND hwnd, UINT msg )
198 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD)) return;
199 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY) return;
200 SendMessageW( GetParent(hwnd), WM_PARENTNOTIFY,
201 MAKEWPARAM( msg, GetWindowLongW( hwnd, GWL_ID )), (LPARAM)hwnd );
205 /*******************************************************************
206 * get_server_window_text
208 * Retrieve the window text from the server.
210 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
212 size_t len = 0;
214 SERVER_START_REQ( get_window_text )
216 req->handle = hwnd;
217 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
218 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
220 SERVER_END_REQ;
221 text[len / sizeof(WCHAR)] = 0;
225 /***********************************************************************
226 * WIN_GetPtr
228 * Return a pointer to the WND structure if local to the process,
229 * or WND_OTHER_PROCESS if handle may be valid in other process.
230 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
232 WND *WIN_GetPtr( HWND hwnd )
234 WND * ptr;
235 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
237 if (index >= NB_USER_HANDLES) return NULL;
239 USER_Lock();
240 if ((ptr = user_handles[index]))
242 if (ptr->dwMagic == WND_MAGIC && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
243 return ptr;
244 ptr = NULL;
246 else ptr = WND_OTHER_PROCESS;
247 USER_Unlock();
248 return ptr;
252 /***********************************************************************
253 * WIN_IsCurrentProcess
255 * Check whether a given window belongs to the current process (and return the full handle).
257 HWND WIN_IsCurrentProcess( HWND hwnd )
259 WND *ptr;
260 HWND ret;
262 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS) return 0;
263 ret = ptr->hwndSelf;
264 WIN_ReleasePtr( ptr );
265 return ret;
269 /***********************************************************************
270 * WIN_IsCurrentThread
272 * Check whether a given window belongs to the current thread (and return the full handle).
274 HWND WIN_IsCurrentThread( HWND hwnd )
276 WND *ptr;
277 HWND ret = 0;
279 if ((ptr = WIN_GetPtr( hwnd )) && ptr != WND_OTHER_PROCESS)
281 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
282 WIN_ReleasePtr( ptr );
284 return ret;
288 /***********************************************************************
289 * WIN_Handle32
291 * Convert a 16-bit window handle to a full 32-bit handle.
293 HWND WIN_Handle32( HWND16 hwnd16 )
295 WND *ptr;
296 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
298 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
299 /* do sign extension for -2 and -3 */
300 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
302 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
304 if (ptr != WND_OTHER_PROCESS)
306 hwnd = ptr->hwndSelf;
307 WIN_ReleasePtr( ptr );
309 else /* may belong to another process */
311 SERVER_START_REQ( get_window_info )
313 req->handle = hwnd;
314 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
316 SERVER_END_REQ;
318 return hwnd;
322 /***********************************************************************
323 * WIN_FindWndPtr
325 * Return a pointer to the WND structure corresponding to a HWND.
327 WND * WIN_FindWndPtr( HWND hwnd )
329 WND * ptr;
331 if (!hwnd) return NULL;
333 if ((ptr = WIN_GetPtr( hwnd )))
335 if (ptr != WND_OTHER_PROCESS)
337 /* increment destruction monitoring */
338 ptr->irefCount++;
339 return ptr;
341 if (IsWindow( hwnd )) /* check other processes */
343 ERR( "window %p belongs to other process\n", hwnd );
344 /* DbgBreakPoint(); */
347 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
348 return NULL;
352 /***********************************************************************
353 * WIN_ReleaseWndPtr
355 * Release the pointer to the WND structure.
357 void WIN_ReleaseWndPtr(WND *wndPtr)
359 if(!wndPtr) return;
361 /* Decrement destruction monitoring value */
362 wndPtr->irefCount--;
363 /* Check if it's time to release the memory */
364 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
366 /* Release memory */
367 free_window_handle( wndPtr->hwndSelf );
369 else if(wndPtr->irefCount < 0)
371 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
372 ERR("forgot a Lock on %p somewhere\n",wndPtr);
374 /* unlock all WND structures for thread safeness */
375 USER_Unlock();
379 /***********************************************************************
380 * WIN_UnlinkWindow
382 * Remove a window from the siblings linked list.
384 void WIN_UnlinkWindow( HWND hwnd )
386 WIN_LinkWindow( hwnd, 0, 0 );
390 /***********************************************************************
391 * WIN_LinkWindow
393 * Insert a window into the siblings linked list.
394 * The window is inserted after the specified window, which can also
395 * be specified as HWND_TOP or HWND_BOTTOM.
396 * If parent is 0, window is unlinked from the tree.
398 void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
400 WND *wndPtr = WIN_GetPtr( hwnd );
402 if (!wndPtr) return;
403 if (wndPtr == WND_OTHER_PROCESS)
405 if (IsWindow(hwnd)) ERR(" cannot link other process window %p\n", hwnd );
406 return;
409 SERVER_START_REQ( link_window )
411 req->handle = hwnd;
412 req->parent = parent;
413 req->previous = hwndInsertAfter;
414 if (!wine_server_call( req ))
416 if (reply->full_parent) wndPtr->parent = reply->full_parent;
420 SERVER_END_REQ;
421 WIN_ReleasePtr( wndPtr );
425 /***********************************************************************
426 * WIN_SetOwner
428 * Change the owner of a window.
430 HWND WIN_SetOwner( HWND hwnd, HWND owner )
432 WND *win = WIN_GetPtr( hwnd );
433 HWND ret = 0;
435 if (!win) return 0;
436 if (win == WND_OTHER_PROCESS)
438 if (IsWindow(hwnd)) ERR( "cannot set owner %p on other process window %p\n", owner, hwnd );
439 return 0;
441 SERVER_START_REQ( set_window_owner )
443 req->handle = hwnd;
444 req->owner = owner;
445 if (!wine_server_call( req ))
447 win->owner = reply->full_owner;
448 ret = reply->prev_owner;
451 SERVER_END_REQ;
452 WIN_ReleasePtr( win );
453 return ret;
457 /***********************************************************************
458 * WIN_SetStyle
460 * Change the style of a window.
462 LONG WIN_SetStyle( HWND hwnd, LONG style )
464 BOOL ok;
465 LONG ret = 0;
466 WND *win = WIN_GetPtr( hwnd );
468 if (!win) return 0;
469 if (win == WND_OTHER_PROCESS)
471 if (IsWindow(hwnd))
472 ERR( "cannot set style %lx on other process window %p\n", style, hwnd );
473 return 0;
475 if (style == win->dwStyle)
477 WIN_ReleasePtr( win );
478 return style;
480 SERVER_START_REQ( set_window_info )
482 req->handle = hwnd;
483 req->flags = SET_WIN_STYLE;
484 req->style = style;
485 req->extra_offset = -1;
486 if ((ok = !wine_server_call( req )))
488 ret = reply->old_style;
489 win->dwStyle = style;
492 SERVER_END_REQ;
493 WIN_ReleasePtr( win );
494 if (ok && USER_Driver.pSetWindowStyle) USER_Driver.pSetWindowStyle( hwnd, ret );
495 return ret;
499 /***********************************************************************
500 * WIN_SetExStyle
502 * Change the extended style of a window.
504 LONG WIN_SetExStyle( HWND hwnd, LONG style )
506 LONG ret = 0;
507 WND *win = WIN_GetPtr( hwnd );
509 if (!win) return 0;
510 if (win == WND_OTHER_PROCESS)
512 if (IsWindow(hwnd))
513 ERR( "cannot set exstyle %lx on other process window %p\n", style, hwnd );
514 return 0;
516 if (style == win->dwExStyle)
518 WIN_ReleasePtr( win );
519 return style;
521 SERVER_START_REQ( set_window_info )
523 req->handle = hwnd;
524 req->flags = SET_WIN_EXSTYLE;
525 req->ex_style = style;
526 req->extra_offset = -1;
527 if (!wine_server_call( req ))
529 ret = reply->old_ex_style;
530 win->dwExStyle = style;
533 SERVER_END_REQ;
534 WIN_ReleasePtr( win );
535 return ret;
539 /***********************************************************************
540 * WIN_SetRectangles
542 * Set the window and client rectangles.
544 void WIN_SetRectangles( HWND hwnd, const RECT *rectWindow, const RECT *rectClient )
546 WND *win = WIN_GetPtr( hwnd );
547 BOOL ret;
549 if (!win) return;
550 if (win == WND_OTHER_PROCESS)
552 if (IsWindow( hwnd )) ERR( "cannot set rectangles of other process window %p\n", hwnd );
553 return;
555 SERVER_START_REQ( set_window_rectangles )
557 req->handle = hwnd;
558 req->window.left = rectWindow->left;
559 req->window.top = rectWindow->top;
560 req->window.right = rectWindow->right;
561 req->window.bottom = rectWindow->bottom;
562 req->client.left = rectClient->left;
563 req->client.top = rectClient->top;
564 req->client.right = rectClient->right;
565 req->client.bottom = rectClient->bottom;
566 ret = !wine_server_call( req );
568 SERVER_END_REQ;
569 if (ret)
571 win->rectWindow = *rectWindow;
572 win->rectClient = *rectClient;
574 TRACE( "win %p window (%ld,%ld)-(%ld,%ld) client (%ld,%ld)-(%ld,%ld)\n", hwnd,
575 rectWindow->left, rectWindow->top, rectWindow->right, rectWindow->bottom,
576 rectClient->left, rectClient->top, rectClient->right, rectClient->bottom );
578 WIN_ReleasePtr( win );
582 /***********************************************************************
583 * WIN_GetRectangles
585 * Get the window and client rectangles.
587 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
589 WND *win = WIN_GetPtr( hwnd );
590 BOOL ret = TRUE;
592 if (!win) return FALSE;
593 if (win == WND_OTHER_PROCESS)
595 SERVER_START_REQ( get_window_rectangles )
597 req->handle = hwnd;
598 if ((ret = !wine_server_call( req )))
600 if (rectWindow)
602 rectWindow->left = reply->window.left;
603 rectWindow->top = reply->window.top;
604 rectWindow->right = reply->window.right;
605 rectWindow->bottom = reply->window.bottom;
607 if (rectClient)
609 rectClient->left = reply->client.left;
610 rectClient->top = reply->client.top;
611 rectClient->right = reply->client.right;
612 rectClient->bottom = reply->client.bottom;
616 SERVER_END_REQ;
618 else
620 if (rectWindow) *rectWindow = win->rectWindow;
621 if (rectClient) *rectClient = win->rectClient;
622 WIN_ReleasePtr( win );
624 return ret;
628 /***********************************************************************
629 * WIN_DestroyWindow
631 * Destroy storage associated to a window. "Internals" p.358
633 LRESULT WIN_DestroyWindow( HWND hwnd )
635 WND *wndPtr;
636 HWND *list;
638 TRACE("%p\n", hwnd );
640 if (!(hwnd = WIN_IsCurrentThread( hwnd )))
642 ERR( "window doesn't belong to current thread\n" );
643 return 0;
646 /* free child windows */
647 if ((list = WIN_ListChildren( hwnd )))
649 int i;
650 for (i = 0; list[i]; i++)
652 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
653 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
655 HeapFree( GetProcessHeap(), 0, list );
659 * Clear the update region to make sure no WM_PAINT messages will be
660 * generated for this window while processing the WM_NCDESTROY.
662 RedrawWindow( hwnd, NULL, 0,
663 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
666 * Send the WM_NCDESTROY to the window being destroyed.
668 SendMessageA( hwnd, WM_NCDESTROY, 0, 0);
670 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
672 WINPOS_CheckInternalPos( hwnd );
673 if( hwnd == GetCapture()) ReleaseCapture();
675 /* free resources associated with the window */
677 TIMER_RemoveWindowTimers( hwnd );
679 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
681 if (!(wndPtr->dwStyle & WS_CHILD))
683 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
684 if (menu) DestroyMenu( menu );
686 if (wndPtr->hSysMenu)
688 DestroyMenu( wndPtr->hSysMenu );
689 wndPtr->hSysMenu = 0;
691 DCE_FreeWindowDCE( hwnd ); /* Always do this to catch orphaned DCs */
692 USER_Driver.pDestroyWindow( hwnd );
693 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
694 wndPtr->class = NULL;
695 wndPtr->dwMagic = 0; /* Mark it as invalid */
696 WIN_ReleaseWndPtr( wndPtr );
697 return 0;
700 /***********************************************************************
701 * WIN_DestroyThreadWindows
703 * Destroy all children of 'wnd' owned by the current thread.
704 * Return TRUE if something was done.
706 void WIN_DestroyThreadWindows( HWND hwnd )
708 HWND *list;
709 int i;
711 if (!(list = WIN_ListChildren( hwnd ))) return;
712 for (i = 0; list[i]; i++)
714 if (WIN_IsCurrentThread( list[i] ))
715 DestroyWindow( list[i] );
716 else
717 WIN_DestroyThreadWindows( list[i] );
719 HeapFree( GetProcessHeap(), 0, list );
722 /***********************************************************************
723 * WIN_CreateDesktopWindow
725 * Create the desktop window.
727 BOOL WIN_CreateDesktopWindow(void)
729 HWND hwndDesktop;
730 CREATESTRUCTA cs;
731 RECT rect;
733 TRACE("Creating desktop window\n");
735 if (!WINPOS_CreateInternalPosAtom()) return FALSE;
737 pWndDesktop = create_window_handle( 0, 0, LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W );
738 if (!pWndDesktop) return FALSE;
739 hwndDesktop = pWndDesktop->hwndSelf;
741 pWndDesktop->tid = 0; /* nobody owns the desktop */
742 pWndDesktop->parent = 0;
743 pWndDesktop->owner = 0;
744 pWndDesktop->text = NULL;
745 pWndDesktop->hrgnUpdate = 0;
746 pWndDesktop->pVScroll = NULL;
747 pWndDesktop->pHScroll = NULL;
748 pWndDesktop->helpContext = 0;
749 pWndDesktop->flags = 0;
750 pWndDesktop->hSysMenu = 0;
752 cs.lpCreateParams = NULL;
753 cs.hInstance = 0;
754 cs.hMenu = 0;
755 cs.hwndParent = 0;
756 cs.x = 0;
757 cs.y = 0;
758 cs.cx = GetSystemMetrics( SM_CXSCREEN );
759 cs.cy = GetSystemMetrics( SM_CYSCREEN );
760 cs.style = pWndDesktop->dwStyle;
761 cs.dwExStyle = pWndDesktop->dwExStyle;
762 cs.lpszName = NULL;
763 cs.lpszClass = DESKTOP_CLASS_ATOM;
765 SetRect( &rect, 0, 0, cs.cx, cs.cy );
766 WIN_SetRectangles( hwndDesktop, &rect, &rect );
768 SERVER_START_REQ( set_window_info )
770 req->handle = hwndDesktop;
771 req->flags = 0; /* don't set anything, just retrieve */
772 req->extra_offset = -1;
773 wine_server_call( req );
774 pWndDesktop->dwStyle = reply->old_style;
775 pWndDesktop->dwExStyle = reply->old_ex_style;
776 pWndDesktop->hInstance = (HINSTANCE)reply->old_instance;
777 pWndDesktop->userdata = (ULONG_PTR)reply->old_user_data;
778 pWndDesktop->wIDmenu = reply->old_id;
780 SERVER_END_REQ;
782 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE ))
784 WIN_ReleaseWndPtr( pWndDesktop );
785 return FALSE;
788 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
789 WIN_ReleaseWndPtr( pWndDesktop );
790 return TRUE;
794 /***********************************************************************
795 * WIN_FixCoordinates
797 * Fix the coordinates - Helper for WIN_CreateWindowEx.
798 * returns default show mode in sw.
799 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
801 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
803 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
804 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
806 if (cs->style & (WS_CHILD | WS_POPUP))
808 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
809 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
811 else /* overlapped window */
813 STARTUPINFOA info;
815 GetStartupInfoA( &info );
817 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
819 /* Never believe Microsoft's documentation... CreateWindowEx doc says
820 * that if an overlapped window is created with WS_VISIBLE style bit
821 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
822 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
823 * reveals that
825 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
826 * 2) it does not ignore the y parameter as the docs claim; instead, it
827 * uses it as second parameter to ShowWindow() unless y is either
828 * CW_USEDEFAULT or CW_USEDEFAULT16.
830 * The fact that we didn't do 2) caused bogus windows pop up when wine
831 * was running apps that were using this obscure feature. Example -
832 * calc.exe that comes with Win98 (only Win98, it's different from
833 * the one that comes with Win95 and NT)
835 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
836 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
837 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
840 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
842 if (info.dwFlags & STARTF_USESIZE)
844 cs->cx = info.dwXSize;
845 cs->cy = info.dwYSize;
847 else /* if no other hint from the app, pick 3/4 of the screen real estate */
849 RECT r;
850 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
851 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
852 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
857 else
859 /* neither x nor cx are default. Check the y values .
860 * In the trace we see Outlook and Outlook Express using
861 * cy set to CW_USEDEFAULT when opening the address book.
863 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16) {
864 RECT r;
865 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
866 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
867 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
872 /***********************************************************************
873 * dump_window_styles
875 static void dump_window_styles( DWORD style, DWORD exstyle )
877 TRACE( "style:" );
878 if(style & WS_POPUP) TRACE(" WS_POPUP");
879 if(style & WS_CHILD) TRACE(" WS_CHILD");
880 if(style & WS_MINIMIZE) TRACE(" WS_MINIMIZE");
881 if(style & WS_VISIBLE) TRACE(" WS_VISIBLE");
882 if(style & WS_DISABLED) TRACE(" WS_DISABLED");
883 if(style & WS_CLIPSIBLINGS) TRACE(" WS_CLIPSIBLINGS");
884 if(style & WS_CLIPCHILDREN) TRACE(" WS_CLIPCHILDREN");
885 if(style & WS_MAXIMIZE) TRACE(" WS_MAXIMIZE");
886 if((style & WS_CAPTION) == WS_CAPTION) TRACE(" WS_CAPTION");
887 else
889 if(style & WS_BORDER) TRACE(" WS_BORDER");
890 if(style & WS_DLGFRAME) TRACE(" WS_DLGFRAME");
892 if(style & WS_VSCROLL) TRACE(" WS_VSCROLL");
893 if(style & WS_HSCROLL) TRACE(" WS_HSCROLL");
894 if(style & WS_SYSMENU) TRACE(" WS_SYSMENU");
895 if(style & WS_THICKFRAME) TRACE(" WS_THICKFRAME");
896 if(style & WS_GROUP) TRACE(" WS_GROUP");
897 if(style & WS_TABSTOP) TRACE(" WS_TABSTOP");
898 if(style & WS_MINIMIZEBOX) TRACE(" WS_MINIMIZEBOX");
899 if(style & WS_MAXIMIZEBOX) TRACE(" WS_MAXIMIZEBOX");
901 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
902 #define DUMPED_STYLES \
903 (WS_POPUP | \
904 WS_CHILD | \
905 WS_MINIMIZE | \
906 WS_VISIBLE | \
907 WS_DISABLED | \
908 WS_CLIPSIBLINGS | \
909 WS_CLIPCHILDREN | \
910 WS_MAXIMIZE | \
911 WS_BORDER | \
912 WS_DLGFRAME | \
913 WS_VSCROLL | \
914 WS_HSCROLL | \
915 WS_SYSMENU | \
916 WS_THICKFRAME | \
917 WS_GROUP | \
918 WS_TABSTOP | \
919 WS_MINIMIZEBOX | \
920 WS_MAXIMIZEBOX)
922 if(style & ~DUMPED_STYLES) TRACE(" %08lx", style & ~DUMPED_STYLES);
923 TRACE("\n");
924 #undef DUMPED_STYLES
926 TRACE( "exstyle:" );
927 if(exstyle & WS_EX_DLGMODALFRAME) TRACE(" WS_EX_DLGMODALFRAME");
928 if(exstyle & WS_EX_DRAGDETECT) TRACE(" WS_EX_DRAGDETECT");
929 if(exstyle & WS_EX_NOPARENTNOTIFY) TRACE(" WS_EX_NOPARENTNOTIFY");
930 if(exstyle & WS_EX_TOPMOST) TRACE(" WS_EX_TOPMOST");
931 if(exstyle & WS_EX_ACCEPTFILES) TRACE(" WS_EX_ACCEPTFILES");
932 if(exstyle & WS_EX_TRANSPARENT) TRACE(" WS_EX_TRANSPARENT");
933 if(exstyle & WS_EX_MDICHILD) TRACE(" WS_EX_MDICHILD");
934 if(exstyle & WS_EX_TOOLWINDOW) TRACE(" WS_EX_TOOLWINDOW");
935 if(exstyle & WS_EX_WINDOWEDGE) TRACE(" WS_EX_WINDOWEDGE");
936 if(exstyle & WS_EX_CLIENTEDGE) TRACE(" WS_EX_CLIENTEDGE");
937 if(exstyle & WS_EX_CONTEXTHELP) TRACE(" WS_EX_CONTEXTHELP");
938 if(exstyle & WS_EX_RIGHT) TRACE(" WS_EX_RIGHT");
939 if(exstyle & WS_EX_RTLREADING) TRACE(" WS_EX_RTLREADING");
940 if(exstyle & WS_EX_LEFTSCROLLBAR) TRACE(" WS_EX_LEFTSCROLLBAR");
941 if(exstyle & WS_EX_CONTROLPARENT) TRACE(" WS_EX_CONTROLPARENT");
942 if(exstyle & WS_EX_STATICEDGE) TRACE(" WS_EX_STATICEDGE");
943 if(exstyle & WS_EX_APPWINDOW) TRACE(" WS_EX_APPWINDOW");
944 if(exstyle & WS_EX_LAYERED) TRACE(" WS_EX_LAYERED");
946 #define DUMPED_EX_STYLES \
947 (WS_EX_DLGMODALFRAME | \
948 WS_EX_DRAGDETECT | \
949 WS_EX_NOPARENTNOTIFY | \
950 WS_EX_TOPMOST | \
951 WS_EX_ACCEPTFILES | \
952 WS_EX_TRANSPARENT | \
953 WS_EX_MDICHILD | \
954 WS_EX_TOOLWINDOW | \
955 WS_EX_WINDOWEDGE | \
956 WS_EX_CLIENTEDGE | \
957 WS_EX_CONTEXTHELP | \
958 WS_EX_RIGHT | \
959 WS_EX_RTLREADING | \
960 WS_EX_LEFTSCROLLBAR | \
961 WS_EX_CONTROLPARENT | \
962 WS_EX_STATICEDGE | \
963 WS_EX_APPWINDOW | \
964 WS_EX_LAYERED)
966 if(exstyle & ~DUMPED_EX_STYLES) TRACE(" %08lx", exstyle & ~DUMPED_EX_STYLES);
967 TRACE("\n");
968 #undef DUMPED_EX_STYLES
972 /***********************************************************************
973 * WIN_CreateWindowEx
975 * Implementation of CreateWindowEx().
977 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
978 WINDOWPROCTYPE type )
980 INT sw = SW_SHOW;
981 WND *wndPtr;
982 HWND hwnd, parent, owner;
983 BOOL unicode = (type == WIN_PROC_32W);
985 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
986 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
987 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszClass) : debugstr_a(cs->lpszClass),
988 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
989 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
991 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
993 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
994 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
996 /* Find the parent window */
998 parent = GetDesktopWindow();
999 owner = 0;
1001 if (cs->hwndParent == HWND_MESSAGE)
1003 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
1004 * message window (style: WS_POPUP|WS_DISABLED)
1006 FIXME("Parent is HWND_MESSAGE\n");
1008 else if (cs->hwndParent)
1010 /* Make sure parent is valid */
1011 if (!IsWindow( cs->hwndParent ))
1013 WARN("Bad parent %p\n", cs->hwndParent );
1014 return 0;
1016 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1017 parent = WIN_GetFullHandle(cs->hwndParent);
1018 else
1019 owner = GetAncestor( cs->hwndParent, GA_ROOT );
1021 else if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1023 WARN("No parent for child window\n" );
1024 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
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, cs->hInstance, type )))
1052 TRACE("out of memory\n" );
1053 return 0;
1055 hwnd = wndPtr->hwndSelf;
1057 /* Fill the window structure */
1059 wndPtr->tid = GetCurrentThreadId();
1060 wndPtr->owner = owner;
1061 wndPtr->parent = parent;
1062 wndPtr->hInstance = cs->hInstance;
1063 wndPtr->text = NULL;
1064 wndPtr->hrgnUpdate = 0;
1065 wndPtr->hrgnWnd = 0;
1066 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1067 wndPtr->dwExStyle = cs->dwExStyle;
1068 wndPtr->wIDmenu = 0;
1069 wndPtr->helpContext = 0;
1070 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
1071 wndPtr->pVScroll = NULL;
1072 wndPtr->pHScroll = NULL;
1073 wndPtr->userdata = 0;
1074 wndPtr->hIcon = 0;
1075 wndPtr->hIconSmall = 0;
1076 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU) ? MENU_GetSysMenu( hwnd, 0 ) : 0;
1078 /* Correct the window style - stage 2 */
1080 if (!(cs->style & WS_CHILD))
1082 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1083 if (!(cs->style & WS_POPUP))
1085 wndPtr->dwStyle |= WS_CAPTION;
1086 wndPtr->flags |= WIN_NEED_SIZE;
1089 SERVER_START_REQ( set_window_info )
1091 req->handle = hwnd;
1092 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE;
1093 req->style = wndPtr->dwStyle;
1094 req->ex_style = wndPtr->dwExStyle;
1095 req->instance = (void *)wndPtr->hInstance;
1096 req->extra_offset = -1;
1097 wine_server_call( req );
1099 SERVER_END_REQ;
1101 /* Get class or window DC if needed */
1103 if (wndPtr->clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
1105 /* Set the window menu */
1107 if (((wndPtr->dwStyle & (WS_CAPTION|WS_CHILD)) == WS_CAPTION) ||
1108 (wndPtr->dwExStyle & WS_EX_APPWINDOW))
1110 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
1111 else
1113 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
1114 if (menuName)
1116 if (HIWORD(cs->hInstance))
1117 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1118 else
1119 cs->hMenu = HMENU_32(LoadMenu16(HINSTANCE_16(cs->hInstance),menuName));
1121 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
1125 else SetWindowLongW( hwnd, GWL_ID, (UINT)cs->hMenu );
1126 WIN_ReleaseWndPtr( wndPtr );
1128 if (!USER_Driver.pCreateWindow( hwnd, cs, unicode))
1130 WIN_DestroyWindow( hwnd );
1131 return 0;
1134 /* Notify the parent window only */
1136 send_parent_notify( hwnd, WM_CREATE );
1137 if (!IsWindow( hwnd )) return 0;
1139 if (cs->style & WS_VISIBLE)
1141 /* in case WS_VISIBLE got set in the meantime */
1142 if (!(wndPtr = WIN_GetPtr( hwnd ))) return 0;
1143 WIN_SetStyle( hwnd, wndPtr->dwStyle & ~WS_VISIBLE );
1144 WIN_ReleasePtr( wndPtr );
1145 ShowWindow( hwnd, sw );
1148 /* Call WH_SHELL hook */
1150 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1151 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1153 TRACE("created window %p\n", hwnd);
1154 return hwnd;
1158 /***********************************************************************
1159 * CreateWindow (USER.41)
1161 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1162 DWORD style, INT16 x, INT16 y, INT16 width,
1163 INT16 height, HWND16 parent, HMENU16 menu,
1164 HINSTANCE16 instance, LPVOID data )
1166 return CreateWindowEx16( 0, className, windowName, style,
1167 x, y, width, height, parent, menu, instance, data );
1171 /***********************************************************************
1172 * CreateWindowEx (USER.452)
1174 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1175 LPCSTR windowName, DWORD style, INT16 x,
1176 INT16 y, INT16 width, INT16 height,
1177 HWND16 parent, HMENU16 menu,
1178 HINSTANCE16 instance, LPVOID data )
1180 ATOM classAtom;
1181 CREATESTRUCTA cs;
1182 char buffer[256];
1184 /* Find the class atom */
1186 if (HIWORD(className))
1188 if (!(classAtom = GlobalFindAtomA( className )))
1190 ERR( "bad class name %s\n", debugstr_a(className) );
1191 return 0;
1194 else
1196 classAtom = LOWORD(className);
1197 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1199 ERR( "bad atom %x\n", classAtom);
1200 return 0;
1202 className = buffer;
1205 /* Fix the coordinates */
1207 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1208 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1209 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1210 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1212 /* Create the window */
1214 cs.lpCreateParams = data;
1215 cs.hInstance = HINSTANCE_32(instance);
1216 cs.hMenu = HMENU_32(menu);
1217 cs.hwndParent = WIN_Handle32( parent );
1218 cs.style = style;
1219 cs.lpszName = windowName;
1220 cs.lpszClass = className;
1221 cs.dwExStyle = exStyle;
1223 return HWND_16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
1227 /***********************************************************************
1228 * CreateWindowExA (USER32.@)
1230 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1231 LPCSTR windowName, DWORD style, INT x,
1232 INT y, INT width, INT height,
1233 HWND parent, HMENU menu,
1234 HINSTANCE instance, LPVOID data )
1236 ATOM classAtom;
1237 CREATESTRUCTA cs;
1238 char buffer[256];
1240 if(exStyle & WS_EX_MDICHILD)
1241 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1243 /* Find the class atom */
1245 if (HIWORD(className))
1247 if (!(classAtom = GlobalFindAtomA( className )))
1249 ERR( "bad class name %s\n", debugstr_a(className) );
1250 return 0;
1253 else
1255 classAtom = LOWORD(className);
1256 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1258 ERR( "bad atom %x\n", classAtom);
1259 return 0;
1261 className = buffer;
1264 /* Create the window */
1266 cs.lpCreateParams = data;
1267 cs.hInstance = instance;
1268 cs.hMenu = menu;
1269 cs.hwndParent = parent;
1270 cs.x = x;
1271 cs.y = y;
1272 cs.cx = width;
1273 cs.cy = height;
1274 cs.style = style;
1275 cs.lpszName = windowName;
1276 cs.lpszClass = className;
1277 cs.dwExStyle = exStyle;
1279 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1283 /***********************************************************************
1284 * CreateWindowExW (USER32.@)
1286 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1287 LPCWSTR windowName, DWORD style, INT x,
1288 INT y, INT width, INT height,
1289 HWND parent, HMENU menu,
1290 HINSTANCE instance, LPVOID data )
1292 ATOM classAtom;
1293 CREATESTRUCTW cs;
1294 WCHAR buffer[256];
1296 if(exStyle & WS_EX_MDICHILD)
1297 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1299 /* Find the class atom */
1301 if (HIWORD(className))
1303 if (!(classAtom = GlobalFindAtomW( className )))
1305 ERR( "bad class name %s\n", debugstr_w(className) );
1306 return 0;
1309 else
1311 classAtom = LOWORD(className);
1312 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1314 ERR( "bad atom %x\n", classAtom);
1315 return 0;
1317 className = buffer;
1320 /* Create the window */
1322 cs.lpCreateParams = data;
1323 cs.hInstance = instance;
1324 cs.hMenu = menu;
1325 cs.hwndParent = parent;
1326 cs.x = x;
1327 cs.y = y;
1328 cs.cx = width;
1329 cs.cy = height;
1330 cs.style = style;
1331 cs.lpszName = windowName;
1332 cs.lpszClass = className;
1333 cs.dwExStyle = exStyle;
1335 /* Note: we rely on the fact that CREATESTRUCTA and */
1336 /* CREATESTRUCTW have the same layout. */
1337 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1341 /***********************************************************************
1342 * WIN_SendDestroyMsg
1344 static void WIN_SendDestroyMsg( HWND hwnd )
1346 GUITHREADINFO info;
1348 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1350 if (hwnd == info.hwndCaret) DestroyCaret();
1352 if (USER_Driver.pResetSelectionOwner)
1353 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1356 * Send the WM_DESTROY to the window.
1358 SendMessageA( hwnd, WM_DESTROY, 0, 0);
1361 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1362 * make sure that the window still exists when we come back.
1364 if (IsWindow(hwnd))
1366 HWND* pWndArray;
1367 int i;
1369 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1371 /* start from the end (FIXME: is this needed?) */
1372 for (i = 0; pWndArray[i]; i++) ;
1374 while (--i >= 0)
1376 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1378 HeapFree( GetProcessHeap(), 0, pWndArray );
1380 else
1381 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1385 /***********************************************************************
1386 * DestroyWindow (USER32.@)
1388 BOOL WINAPI DestroyWindow( HWND hwnd )
1390 BOOL is_child;
1391 HWND h;
1393 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1395 SetLastError( ERROR_ACCESS_DENIED );
1396 return FALSE;
1399 TRACE("(%p)\n", hwnd);
1401 /* Look whether the focus is within the tree of windows we will
1402 * be destroying.
1404 h = GetFocus();
1405 if (h == hwnd || IsChild( hwnd, h ))
1407 HWND parent = GetAncestor( hwnd, GA_PARENT );
1408 if (parent == GetDesktopWindow()) parent = 0;
1409 SetFocus( parent );
1412 /* Call hooks */
1414 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1416 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1418 if (is_child)
1420 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1421 send_parent_notify( hwnd, WM_DESTROY );
1423 else if (!GetWindow( hwnd, GW_OWNER ))
1425 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1426 /* FIXME: clean up palette - see "Internals" p.352 */
1429 if (!IsWindow(hwnd)) return TRUE;
1431 if (USER_Driver.pResetSelectionOwner)
1432 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1434 /* Hide the window */
1436 if (!ShowWindow( hwnd, SW_HIDE ))
1438 if (hwnd == GetActiveWindow()) WINPOS_ActivateOtherWindow( hwnd );
1440 if (!IsWindow(hwnd)) return TRUE;
1442 /* Recursively destroy owned windows */
1444 if (!is_child)
1446 for (;;)
1448 int i, got_one = 0;
1449 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1450 if (list)
1452 for (i = 0; list[i]; i++)
1454 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1455 if (WIN_IsCurrentThread( list[i] ))
1457 DestroyWindow( list[i] );
1458 got_one = 1;
1459 continue;
1461 WIN_SetOwner( list[i], 0 );
1463 HeapFree( GetProcessHeap(), 0, list );
1465 if (!got_one) break;
1469 /* Send destroy messages */
1471 WIN_SendDestroyMsg( hwnd );
1472 if (!IsWindow( hwnd )) return TRUE;
1474 if (GetClipboardOwner() == hwnd)
1475 CLIPBOARD_ReleaseOwner();
1477 /* Unlink now so we won't bother with the children later on */
1479 WIN_UnlinkWindow( hwnd );
1481 /* Destroy the window storage */
1483 WIN_DestroyWindow( hwnd );
1484 return TRUE;
1488 /***********************************************************************
1489 * CloseWindow (USER32.@)
1491 BOOL WINAPI CloseWindow( HWND hwnd )
1493 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1494 ShowWindow( hwnd, SW_MINIMIZE );
1495 return TRUE;
1499 /***********************************************************************
1500 * OpenIcon (USER32.@)
1502 BOOL WINAPI OpenIcon( HWND hwnd )
1504 if (!IsIconic( hwnd )) return FALSE;
1505 ShowWindow( hwnd, SW_SHOWNORMAL );
1506 return TRUE;
1510 /***********************************************************************
1511 * WIN_FindWindow
1513 * Implementation of FindWindow() and FindWindowEx().
1515 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1517 HWND *list = NULL;
1518 HWND retvalue = 0;
1519 int i = 0, len = 0;
1520 WCHAR *buffer = NULL;
1522 if (!parent) parent = GetDesktopWindow();
1523 if (title)
1525 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1526 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1529 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1531 if (child)
1533 child = WIN_GetFullHandle( child );
1534 while (list[i] && list[i] != child) i++;
1535 if (!list[i]) goto done;
1536 i++; /* start from next window */
1539 if (title)
1541 while (list[i])
1543 if (GetWindowTextW( list[i], buffer, len + 1 ) && !strcmpiW( buffer, title )) break;
1544 i++;
1547 retvalue = list[i];
1549 done:
1550 if (list) HeapFree( GetProcessHeap(), 0, list );
1551 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1552 return retvalue;
1557 /***********************************************************************
1558 * FindWindowA (USER32.@)
1560 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1562 HWND ret = FindWindowExA( 0, 0, className, title );
1563 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1564 return ret;
1568 /***********************************************************************
1569 * FindWindowExA (USER32.@)
1571 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1572 LPCSTR className, LPCSTR title )
1574 ATOM atom = 0;
1575 LPWSTR buffer;
1576 HWND hwnd;
1577 INT len;
1579 if (className)
1581 /* If the atom doesn't exist, then no class */
1582 /* with this name exists either. */
1583 if (!(atom = GlobalFindAtomA( className )))
1585 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1586 return 0;
1589 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
1591 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1592 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1593 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
1594 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1595 HeapFree( GetProcessHeap(), 0, buffer );
1596 return hwnd;
1600 /***********************************************************************
1601 * FindWindowExW (USER32.@)
1603 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1604 LPCWSTR className, LPCWSTR title )
1606 ATOM atom = 0;
1608 if (className)
1610 /* If the atom doesn't exist, then no class */
1611 /* with this name exists either. */
1612 if (!(atom = GlobalFindAtomW( className )))
1614 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1615 return 0;
1618 return WIN_FindWindow( parent, child, atom, title );
1622 /***********************************************************************
1623 * FindWindowW (USER32.@)
1625 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1627 return FindWindowExW( 0, 0, className, title );
1631 /**********************************************************************
1632 * GetDesktopWindow (USER32.@)
1634 HWND WINAPI GetDesktopWindow(void)
1636 if (pWndDesktop) return pWndDesktop->hwndSelf;
1637 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" );
1638 ExitProcess(1);
1639 return 0;
1643 /*******************************************************************
1644 * EnableWindow (USER32.@)
1646 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1648 WND *wndPtr;
1649 BOOL retvalue;
1650 LONG style;
1651 HWND full_handle;
1653 if (is_broadcast(hwnd))
1655 SetLastError( ERROR_INVALID_PARAMETER );
1656 return FALSE;
1659 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1660 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1662 hwnd = full_handle;
1664 TRACE("( %p, %d )\n", hwnd, enable);
1666 if (!(wndPtr = WIN_GetPtr( hwnd ))) return FALSE;
1667 style = wndPtr->dwStyle;
1668 retvalue = ((style & WS_DISABLED) != 0);
1669 WIN_ReleasePtr( wndPtr );
1671 if (enable && retvalue)
1673 WIN_SetStyle( hwnd, style & ~WS_DISABLED );
1674 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1676 else if (!enable && !retvalue)
1678 HWND focus_wnd, capture_wnd;
1680 SendMessageA( hwnd, WM_CANCELMODE, 0, 0);
1682 WIN_SetStyle( hwnd, style | WS_DISABLED );
1684 focus_wnd = GetFocus();
1685 if (hwnd == focus_wnd || IsChild(hwnd, focus_wnd))
1686 SetFocus( 0 ); /* A disabled window can't have the focus */
1688 capture_wnd = GetCapture();
1689 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1690 ReleaseCapture(); /* A disabled window can't capture the mouse */
1692 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1694 return retvalue;
1698 /***********************************************************************
1699 * IsWindowEnabled (USER32.@)
1701 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1703 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1707 /***********************************************************************
1708 * IsWindowUnicode (USER32.@)
1710 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1712 WND * wndPtr;
1713 BOOL retvalue;
1715 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1716 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1717 WIN_ReleaseWndPtr(wndPtr);
1718 return retvalue;
1722 /**********************************************************************
1723 * GetWindowWord (USER32.@)
1725 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1727 if (offset >= 0)
1729 WORD retvalue = 0;
1730 WND *wndPtr = WIN_GetPtr( hwnd );
1731 if (!wndPtr)
1733 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1734 return 0;
1736 if (wndPtr == WND_OTHER_PROCESS)
1738 SERVER_START_REQ( set_window_info )
1740 req->handle = hwnd;
1741 req->flags = 0; /* don't set anything, just retrieve */
1742 req->extra_offset = offset;
1743 req->extra_size = sizeof(retvalue);
1744 if (!wine_server_call_err( req ))
1745 memcpy( &retvalue, &reply->old_extra_value, sizeof(retvalue) );
1747 SERVER_END_REQ;
1748 return retvalue;
1750 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1752 WARN("Invalid offset %d\n", offset );
1753 SetLastError( ERROR_INVALID_INDEX );
1755 else memcpy( &retvalue, (char *)wndPtr->wExtra + offset, sizeof(retvalue) );
1756 WIN_ReleasePtr( wndPtr );
1757 return retvalue;
1760 switch(offset)
1762 case GWL_HWNDPARENT:
1763 return GetWindowLongW( hwnd, offset );
1764 case GWL_ID:
1765 case GWL_HINSTANCE:
1767 LONG ret = GetWindowLongW( hwnd, offset );
1768 if (HIWORD(ret))
1769 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1770 return LOWORD(ret);
1772 default:
1773 WARN("Invalid offset %d\n", offset );
1774 return 0;
1779 /**********************************************************************
1780 * SetWindowWord (USER32.@)
1782 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1784 WORD retval = 0;
1785 WND * wndPtr;
1787 switch(offset)
1789 case GWL_ID:
1790 case GWL_HINSTANCE:
1791 case GWL_HWNDPARENT:
1792 return SetWindowLongW( hwnd, offset, (UINT)newval );
1793 default:
1794 if (offset < 0)
1796 WARN("Invalid offset %d\n", offset );
1797 SetLastError( ERROR_INVALID_INDEX );
1798 return 0;
1802 wndPtr = WIN_GetPtr( hwnd );
1803 if (wndPtr == WND_OTHER_PROCESS)
1805 if (IsWindow(hwnd))
1806 FIXME( "set %d <- %x not supported yet on other process window %p\n",
1807 offset, newval, hwnd );
1808 wndPtr = NULL;
1810 if (!wndPtr)
1812 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1813 return 0;
1816 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1818 WARN("Invalid offset %d\n", offset );
1819 WIN_ReleasePtr(wndPtr);
1820 SetLastError( ERROR_INVALID_INDEX );
1821 return 0;
1824 SERVER_START_REQ( set_window_info )
1826 req->handle = hwnd;
1827 req->flags = SET_WIN_EXTRA;
1828 req->extra_offset = offset;
1829 req->extra_size = sizeof(newval);
1830 memcpy( &req->extra_value, &newval, sizeof(newval) );
1831 if (!wine_server_call_err( req ))
1833 void *ptr = (char *)wndPtr->wExtra + offset;
1834 memcpy( &retval, ptr, sizeof(retval) );
1835 memcpy( ptr, &newval, sizeof(newval) );
1838 SERVER_END_REQ;
1839 WIN_ReleasePtr( wndPtr );
1840 return retval;
1844 /**********************************************************************
1845 * WIN_GetWindowLong
1847 * Helper function for GetWindowLong().
1849 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1851 LONG retvalue = 0;
1852 WND *wndPtr;
1854 if (offset == GWL_HWNDPARENT)
1856 HWND parent = GetAncestor( hwnd, GA_PARENT );
1857 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1858 return (LONG)parent;
1861 if (!(wndPtr = WIN_GetPtr( hwnd )))
1863 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1864 return 0;
1867 if (wndPtr == WND_OTHER_PROCESS)
1869 if (offset == GWL_WNDPROC)
1871 SetLastError( ERROR_ACCESS_DENIED );
1872 return 0;
1874 SERVER_START_REQ( set_window_info )
1876 req->handle = hwnd;
1877 req->flags = 0; /* don't set anything, just retrieve */
1878 req->extra_offset = (offset >= 0) ? offset : -1;
1879 req->extra_size = (offset >= 0) ? sizeof(retvalue) : 0;
1880 if (!wine_server_call_err( req ))
1882 switch(offset)
1884 case GWL_STYLE: retvalue = reply->old_style; break;
1885 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1886 case GWL_ID: retvalue = reply->old_id; break;
1887 case GWL_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1888 case GWL_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
1889 default:
1890 if (offset >= 0) retvalue = reply->old_extra_value;
1891 else SetLastError( ERROR_INVALID_INDEX );
1892 break;
1896 SERVER_END_REQ;
1897 return retvalue;
1900 /* now we have a valid wndPtr */
1902 if (offset >= 0)
1904 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
1907 * Some programs try to access last element from 16 bit
1908 * code using illegal offset value. Hopefully this is
1909 * what those programs really expect.
1911 if (type == WIN_PROC_16 &&
1912 wndPtr->cbWndExtra >= 4 &&
1913 offset == wndPtr->cbWndExtra - sizeof(WORD))
1915 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
1917 ERR( "- replaced invalid offset %d with %d\n",
1918 offset, offset2 );
1920 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset2);
1921 WIN_ReleasePtr( wndPtr );
1922 return retvalue;
1924 WARN("Invalid offset %d\n", offset );
1925 WIN_ReleasePtr( wndPtr );
1926 SetLastError( ERROR_INVALID_INDEX );
1927 return 0;
1929 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1930 /* Special case for dialog window procedure */
1931 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1932 retvalue = (LONG)WINPROC_GetProc( (WNDPROC)retvalue, type );
1933 WIN_ReleasePtr( wndPtr );
1934 return retvalue;
1937 switch(offset)
1939 case GWL_USERDATA: retvalue = wndPtr->userdata; break;
1940 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1941 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1942 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu; break;
1943 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc, type ); break;
1944 case GWL_HINSTANCE: retvalue = (LONG)wndPtr->hInstance; break;
1945 default:
1946 WARN("Unknown offset %d\n", offset );
1947 SetLastError( ERROR_INVALID_INDEX );
1948 break;
1950 WIN_ReleasePtr(wndPtr);
1951 return retvalue;
1955 /**********************************************************************
1956 * WIN_SetWindowLong
1958 * Helper function for SetWindowLong().
1960 * 0 is the failure code. However, in the case of failure SetLastError
1961 * must be set to distinguish between a 0 return value and a failure.
1963 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1964 WINDOWPROCTYPE type )
1966 STYLESTRUCT style;
1967 BOOL ok;
1968 LONG retval = 0;
1969 WND *wndPtr;
1971 TRACE( "%p %d %lx %x\n", hwnd, offset, newval, type );
1973 if (is_broadcast(hwnd))
1975 SetLastError( ERROR_INVALID_PARAMETER );
1976 return FALSE;
1978 if (!WIN_IsCurrentProcess( hwnd ))
1980 if (offset == GWL_WNDPROC)
1982 SetLastError( ERROR_ACCESS_DENIED );
1983 return 0;
1985 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
1988 wndPtr = WIN_GetPtr( hwnd );
1989 if (wndPtr->hwndSelf == GetDesktopWindow())
1991 /* can't change anything on the desktop window */
1992 WIN_ReleasePtr( wndPtr );
1993 SetLastError( ERROR_ACCESS_DENIED );
1994 return 0;
1997 /* first some special cases */
1998 switch( offset )
2000 case GWL_STYLE:
2001 case GWL_EXSTYLE:
2002 style.styleOld =
2003 offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
2004 style.styleNew = newval;
2005 WIN_ReleasePtr( wndPtr );
2006 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
2007 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
2008 newval = style.styleNew;
2009 break;
2010 case GWL_HWNDPARENT:
2011 if (wndPtr->parent == GetDesktopWindow())
2013 WIN_ReleasePtr( wndPtr );
2014 return (LONG)WIN_SetOwner( hwnd, (HWND)newval );
2016 else
2018 WIN_ReleasePtr( wndPtr );
2019 return (LONG)SetParent( hwnd, (HWND)newval );
2021 case GWL_WNDPROC:
2022 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2023 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC)newval, type, WIN_PROC_WINDOW );
2024 WIN_ReleasePtr( wndPtr );
2025 return retval;
2026 case GWL_ID:
2027 case GWL_HINSTANCE:
2028 case GWL_USERDATA:
2029 break;
2030 case DWL_DLGPROC:
2031 if ((wndPtr->cbWndExtra + sizeof(LONG) >= DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2033 WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWL_DLGPROC);
2034 retval = (LONG)WINPROC_GetProc( *ptr, type );
2035 WINPROC_SetProc( ptr, (WNDPROC)newval, type, WIN_PROC_WINDOW );
2036 WIN_ReleasePtr( wndPtr );
2037 return retval;
2039 /* fall through */
2040 default:
2041 if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
2043 WARN("Invalid offset %d\n", offset );
2044 WIN_ReleasePtr( wndPtr );
2045 SetLastError( ERROR_INVALID_INDEX );
2046 return 0;
2048 else
2050 LONG *ptr = (LONG *)((char *)wndPtr->wExtra + offset);
2051 if (*ptr == newval) /* already set to the same value */
2053 WIN_ReleasePtr( wndPtr );
2054 return newval;
2057 break;
2060 SERVER_START_REQ( set_window_info )
2062 req->handle = hwnd;
2063 req->extra_offset = -1;
2064 switch(offset)
2066 case GWL_STYLE:
2067 req->flags = SET_WIN_STYLE;
2068 req->style = newval;
2069 break;
2070 case GWL_EXSTYLE:
2071 req->flags = SET_WIN_EXSTYLE;
2072 req->ex_style = newval;
2073 break;
2074 case GWL_ID:
2075 req->flags = SET_WIN_ID;
2076 req->id = newval;
2077 break;
2078 case GWL_HINSTANCE:
2079 req->flags = SET_WIN_INSTANCE;
2080 req->instance = (void *)newval;
2081 break;
2082 case GWL_USERDATA:
2083 req->flags = SET_WIN_USERDATA;
2084 req->user_data = (void *)newval;
2085 break;
2086 default:
2087 req->flags = SET_WIN_EXTRA;
2088 req->extra_offset = offset;
2089 req->extra_size = sizeof(newval);
2090 memcpy( &req->extra_value, &newval, sizeof(newval) );
2092 if ((ok = !wine_server_call_err( req )))
2094 switch(offset)
2096 case GWL_STYLE:
2097 wndPtr->dwStyle = newval;
2098 retval = reply->old_style;
2099 break;
2100 case GWL_EXSTYLE:
2101 wndPtr->dwExStyle = newval;
2102 retval = reply->old_ex_style;
2103 break;
2104 case GWL_ID:
2105 wndPtr->wIDmenu = newval;
2106 retval = reply->old_id;
2107 break;
2108 case GWL_HINSTANCE:
2109 wndPtr->hInstance = (HINSTANCE)newval;
2110 retval = (ULONG_PTR)reply->old_instance;
2111 break;
2112 case GWL_USERDATA:
2113 wndPtr->userdata = newval;
2114 retval = (ULONG_PTR)reply->old_user_data;
2115 break;
2116 default:
2118 void *ptr = (char *)wndPtr->wExtra + offset;
2119 memcpy( &retval, ptr, sizeof(retval) );
2120 memcpy( ptr, &newval, sizeof(newval) );
2122 break;
2126 SERVER_END_REQ;
2127 WIN_ReleasePtr( wndPtr );
2129 if (!ok) return 0;
2131 if (offset == GWL_STYLE && USER_Driver.pSetWindowStyle)
2132 USER_Driver.pSetWindowStyle( hwnd, retval );
2134 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2135 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2137 return retval;
2141 /**********************************************************************
2142 * GetWindowLong (USER.135)
2144 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2146 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
2150 /**********************************************************************
2151 * GetWindowLongA (USER32.@)
2153 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2155 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2159 /**********************************************************************
2160 * GetWindowLongW (USER32.@)
2162 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2164 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2168 /**********************************************************************
2169 * SetWindowLong (USER.136)
2171 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2173 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
2177 /**********************************************************************
2178 * SetWindowLongA (USER32.@)
2180 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2182 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2186 /**********************************************************************
2187 * SetWindowLongW (USER32.@) Set window attribute
2189 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2190 * value in a window's extra memory.
2192 * The _hwnd_ parameter specifies the window. is the handle to a
2193 * window that has extra memory. The _newval_ parameter contains the
2194 * new attribute or extra memory value. If positive, the _offset_
2195 * parameter is the byte-addressed location in the window's extra
2196 * memory to set. If negative, _offset_ specifies the window
2197 * attribute to set, and should be one of the following values:
2199 * GWL_EXSTYLE The window's extended window style
2201 * GWL_STYLE The window's window style.
2203 * GWL_WNDPROC Pointer to the window's window procedure.
2205 * GWL_HINSTANCE The window's pplication instance handle.
2207 * GWL_ID The window's identifier.
2209 * GWL_USERDATA The window's user-specified data.
2211 * If the window is a dialog box, the _offset_ parameter can be one of
2212 * the following values:
2214 * DWL_DLGPROC The address of the window's dialog box procedure.
2216 * DWL_MSGRESULT The return value of a message
2217 * that the dialog box procedure processed.
2219 * DWL_USER Application specific information.
2221 * RETURNS
2223 * If successful, returns the previous value located at _offset_. Otherwise,
2224 * returns 0.
2226 * NOTES
2228 * Extra memory for a window class is specified by a nonzero cbWndExtra
2229 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2230 * time of class creation.
2232 * Using GWL_WNDPROC to set a new window procedure effectively creates
2233 * a window subclass. Use CallWindowProc() in the new windows procedure
2234 * to pass messages to the superclass's window procedure.
2236 * The user data is reserved for use by the application which created
2237 * the window.
2239 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2240 * instead, call the EnableWindow() function to change the window's
2241 * disabled state.
2243 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2244 * SetParent() instead.
2246 * Win95:
2247 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2248 * it sends WM_STYLECHANGING before changing the settings
2249 * and WM_STYLECHANGED afterwards.
2250 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2252 LONG WINAPI SetWindowLongW(
2253 HWND hwnd, /* [in] window to alter */
2254 INT offset, /* [in] offset, in bytes, of location to alter */
2255 LONG newval /* [in] new value of location */
2257 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2261 /*******************************************************************
2262 * GetWindowTextA (USER32.@)
2264 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2266 WCHAR *buffer;
2268 if (WIN_IsCurrentProcess( hwnd ))
2269 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2271 /* when window belongs to other process, don't send a message */
2272 if (nMaxCount <= 0) return 0;
2273 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2274 get_server_window_text( hwnd, buffer, nMaxCount );
2275 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2276 lpString[nMaxCount-1] = 0;
2277 HeapFree( GetProcessHeap(), 0, buffer );
2278 return strlen(lpString);
2282 /*******************************************************************
2283 * InternalGetWindowText (USER32.@)
2285 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2287 WND *win;
2289 if (nMaxCount <= 0) return 0;
2290 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2291 if (win != WND_OTHER_PROCESS)
2293 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2294 else lpString[0] = 0;
2295 WIN_ReleasePtr( win );
2297 else
2299 get_server_window_text( hwnd, lpString, nMaxCount );
2301 return strlenW(lpString);
2305 /*******************************************************************
2306 * GetWindowTextW (USER32.@)
2308 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2310 if (WIN_IsCurrentProcess( hwnd ))
2311 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2313 /* when window belongs to other process, don't send a message */
2314 if (nMaxCount <= 0) return 0;
2315 get_server_window_text( hwnd, lpString, nMaxCount );
2316 return strlenW(lpString);
2320 /*******************************************************************
2321 * SetWindowText (USER32.@)
2322 * SetWindowTextA (USER32.@)
2324 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2326 if (is_broadcast(hwnd))
2328 SetLastError( ERROR_INVALID_PARAMETER );
2329 return FALSE;
2331 if (!WIN_IsCurrentProcess( hwnd ))
2333 FIXME( "cannot set text %s of other process window %p\n", debugstr_a(lpString), hwnd );
2334 SetLastError( ERROR_ACCESS_DENIED );
2335 return FALSE;
2337 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2341 /*******************************************************************
2342 * SetWindowTextW (USER32.@)
2344 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2346 if (is_broadcast(hwnd))
2348 SetLastError( ERROR_INVALID_PARAMETER );
2349 return FALSE;
2351 if (!WIN_IsCurrentProcess( hwnd ))
2353 FIXME( "cannot set text %s of other process window %p\n", debugstr_w(lpString), hwnd );
2354 SetLastError( ERROR_ACCESS_DENIED );
2355 return FALSE;
2357 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2361 /*******************************************************************
2362 * GetWindowTextLengthA (USER32.@)
2364 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2366 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2369 /*******************************************************************
2370 * GetWindowTextLengthW (USER32.@)
2372 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2374 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2378 /*******************************************************************
2379 * IsWindow (USER32.@)
2381 BOOL WINAPI IsWindow( HWND hwnd )
2383 WND *ptr;
2384 BOOL ret;
2386 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2388 if (ptr != WND_OTHER_PROCESS)
2390 WIN_ReleasePtr( ptr );
2391 return TRUE;
2394 /* check other processes */
2395 SERVER_START_REQ( get_window_info )
2397 req->handle = hwnd;
2398 ret = !wine_server_call_err( req );
2400 SERVER_END_REQ;
2401 return ret;
2405 /***********************************************************************
2406 * GetWindowThreadProcessId (USER32.@)
2408 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2410 WND *ptr;
2411 DWORD tid = 0;
2413 if (!(ptr = WIN_GetPtr( hwnd )))
2415 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2416 return 0;
2419 if (ptr != WND_OTHER_PROCESS)
2421 /* got a valid window */
2422 tid = ptr->tid;
2423 if (process) *process = GetCurrentProcessId();
2424 WIN_ReleasePtr( ptr );
2425 return tid;
2428 /* check other processes */
2429 SERVER_START_REQ( get_window_info )
2431 req->handle = hwnd;
2432 if (!wine_server_call_err( req ))
2434 tid = (DWORD)reply->tid;
2435 if (process) *process = (DWORD)reply->pid;
2438 SERVER_END_REQ;
2439 return tid;
2443 /*****************************************************************
2444 * GetParent (USER32.@)
2446 HWND WINAPI GetParent( HWND hwnd )
2448 WND *wndPtr;
2449 HWND retvalue = 0;
2451 if (!(wndPtr = WIN_GetPtr( hwnd )))
2453 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2454 return 0;
2456 if (wndPtr == WND_OTHER_PROCESS)
2458 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2459 if (style & (WS_POPUP | WS_CHILD))
2461 SERVER_START_REQ( get_window_tree )
2463 req->handle = hwnd;
2464 if (!wine_server_call_err( req ))
2466 if (style & WS_POPUP) retvalue = reply->owner;
2467 else if (style & WS_CHILD) retvalue = reply->parent;
2470 SERVER_END_REQ;
2473 else
2475 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2476 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2477 WIN_ReleasePtr( wndPtr );
2479 return retvalue;
2483 /*****************************************************************
2484 * GetAncestor (USER32.@)
2486 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2488 WND *win;
2489 HWND *list, ret = 0;
2491 switch(type)
2493 case GA_PARENT:
2494 if (!(win = WIN_GetPtr( hwnd )))
2496 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2497 return 0;
2499 if (win != WND_OTHER_PROCESS)
2501 ret = win->parent;
2502 WIN_ReleasePtr( win );
2504 else /* need to query the server */
2506 SERVER_START_REQ( get_window_tree )
2508 req->handle = hwnd;
2509 if (!wine_server_call_err( req )) ret = reply->parent;
2511 SERVER_END_REQ;
2513 break;
2515 case GA_ROOT:
2516 if (!(list = WIN_ListParents( hwnd ))) return 0;
2518 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2519 else
2521 int count = 2;
2522 while (list[count]) count++;
2523 ret = list[count - 2]; /* get the one before the desktop */
2525 HeapFree( GetProcessHeap(), 0, list );
2526 break;
2528 case GA_ROOTOWNER:
2529 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2530 for (;;)
2532 HWND parent = GetParent( ret );
2533 if (!parent) break;
2534 ret = parent;
2536 break;
2538 return ret;
2542 /*****************************************************************
2543 * SetParent (USER32.@)
2545 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2547 WND *wndPtr;
2548 HWND retvalue, full_handle;
2549 BOOL was_visible;
2551 if (is_broadcast(hwnd) || is_broadcast(parent))
2553 SetLastError(ERROR_INVALID_PARAMETER);
2554 return 0;
2557 if (!parent) parent = GetDesktopWindow();
2558 else parent = WIN_GetFullHandle( parent );
2560 if (!IsWindow( parent ))
2562 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2563 return 0;
2566 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2567 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2569 hwnd = full_handle;
2571 if (USER_Driver.pSetParent)
2572 return USER_Driver.pSetParent( hwnd, parent );
2574 /* Windows hides the window first, then shows it again
2575 * including the WM_SHOWWINDOW messages and all */
2576 was_visible = ShowWindow( hwnd, SW_HIDE );
2578 if (!IsWindow( parent )) return 0;
2579 if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return 0;
2581 retvalue = wndPtr->parent; /* old parent */
2582 if (parent != retvalue)
2584 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2586 if (parent != GetDesktopWindow()) /* a child window */
2588 if (!(wndPtr->dwStyle & WS_CHILD))
2590 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
2591 if (menu) DestroyMenu( menu );
2595 WIN_ReleasePtr( wndPtr );
2597 /* SetParent additionally needs to make hwnd the topmost window
2598 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2599 WM_WINDOWPOSCHANGED notification messages.
2601 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2602 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2603 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2604 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2605 return retvalue;
2609 /*******************************************************************
2610 * IsChild (USER32.@)
2612 BOOL WINAPI IsChild( HWND parent, HWND child )
2614 HWND *list = WIN_ListParents( child );
2615 int i;
2616 BOOL ret;
2618 if (!list) return FALSE;
2619 parent = WIN_GetFullHandle( parent );
2620 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2621 ret = (list[i] != 0);
2622 HeapFree( GetProcessHeap(), 0, list );
2623 return ret;
2627 /***********************************************************************
2628 * IsWindowVisible (USER32.@)
2630 BOOL WINAPI IsWindowVisible( HWND hwnd )
2632 HWND *list;
2633 BOOL retval;
2634 int i;
2636 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2637 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2638 for (i = 0; list[i]; i++)
2639 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2640 retval = !list[i];
2641 HeapFree( GetProcessHeap(), 0, list );
2642 return retval;
2646 /***********************************************************************
2647 * WIN_IsWindowDrawable
2649 * hwnd is drawable when it is visible, all parents are not
2650 * minimized, and it is itself not minimized unless we are
2651 * trying to draw its default class icon.
2653 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2655 HWND *list;
2656 BOOL retval;
2657 int i;
2658 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2660 if (!(style & WS_VISIBLE)) return FALSE;
2661 if ((style & WS_MINIMIZE) && icon && GetClassLongA( hwnd, GCL_HICON )) return FALSE;
2663 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2664 for (i = 0; list[i]; i++)
2665 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2666 break;
2667 retval = !list[i];
2668 HeapFree( GetProcessHeap(), 0, list );
2669 return retval;
2673 /*******************************************************************
2674 * GetTopWindow (USER32.@)
2676 HWND WINAPI GetTopWindow( HWND hwnd )
2678 if (!hwnd) hwnd = GetDesktopWindow();
2679 return GetWindow( hwnd, GW_CHILD );
2683 /*******************************************************************
2684 * GetWindow (USER32.@)
2686 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2688 HWND retval = 0;
2690 if (rel == GW_OWNER) /* this one may be available locally */
2692 WND *wndPtr = WIN_GetPtr( hwnd );
2693 if (!wndPtr)
2695 SetLastError( ERROR_INVALID_HANDLE );
2696 return 0;
2698 if (wndPtr != WND_OTHER_PROCESS)
2700 retval = wndPtr->owner;
2701 WIN_ReleasePtr( wndPtr );
2702 return retval;
2704 /* else fall through to server call */
2707 SERVER_START_REQ( get_window_tree )
2709 req->handle = hwnd;
2710 if (!wine_server_call_err( req ))
2712 switch(rel)
2714 case GW_HWNDFIRST:
2715 retval = reply->first_sibling;
2716 break;
2717 case GW_HWNDLAST:
2718 retval = reply->last_sibling;
2719 break;
2720 case GW_HWNDNEXT:
2721 retval = reply->next_sibling;
2722 break;
2723 case GW_HWNDPREV:
2724 retval = reply->prev_sibling;
2725 break;
2726 case GW_OWNER:
2727 retval = reply->owner;
2728 break;
2729 case GW_CHILD:
2730 retval = reply->first_child;
2731 break;
2735 SERVER_END_REQ;
2736 return retval;
2740 /***********************************************************************
2741 * WIN_InternalShowOwnedPopups
2743 * Internal version of ShowOwnedPopups; Wine functions should use this
2744 * to avoid interfering with application calls to ShowOwnedPopups
2745 * and to make sure the application can't prevent showing/hiding.
2747 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2751 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2753 int count = 0;
2754 WND *pWnd;
2755 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2757 if (!win_array) return TRUE;
2760 * Show windows Lowest first, Highest last to preserve Z-Order
2762 while (win_array[count]) count++;
2763 while (--count >= 0)
2765 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2766 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2768 if (pWnd->dwStyle & WS_POPUP)
2770 if (fShow)
2772 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2773 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
2776 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2778 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2779 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2782 else
2784 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2785 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2786 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2789 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2791 ShowWindow(pWnd->hwndSelf,SW_HIDE);
2792 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2793 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
2797 WIN_ReleaseWndPtr( pWnd );
2799 HeapFree( GetProcessHeap(), 0, win_array );
2801 return TRUE;
2804 /*******************************************************************
2805 * ShowOwnedPopups (USER32.@)
2807 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2809 int count = 0;
2810 WND *pWnd;
2811 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2813 if (!win_array) return TRUE;
2815 while (win_array[count]) count++;
2816 while (--count >= 0)
2818 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2819 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2821 if (pWnd->dwStyle & WS_POPUP)
2823 if (fShow)
2825 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2827 /* In Windows, ShowOwnedPopups(TRUE) generates
2828 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2829 * regardless of the state of the owner
2831 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2832 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2835 else
2837 if (IsWindowVisible(pWnd->hwndSelf))
2839 /* In Windows, ShowOwnedPopups(FALSE) generates
2840 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2841 * regardless of the state of the owner
2843 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2844 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2848 WIN_ReleaseWndPtr( pWnd );
2850 HeapFree( GetProcessHeap(), 0, win_array );
2851 return TRUE;
2855 /*******************************************************************
2856 * GetLastActivePopup (USER32.@)
2858 HWND WINAPI GetLastActivePopup( HWND hwnd )
2860 HWND retval = hwnd;
2862 SERVER_START_REQ( get_window_info )
2864 req->handle = hwnd;
2865 if (!wine_server_call_err( req )) retval = reply->last_active;
2867 SERVER_END_REQ;
2868 return retval;
2872 /*******************************************************************
2873 * WIN_ListParents
2875 * Build an array of all parents of a given window, starting with
2876 * the immediate parent. The array must be freed with HeapFree.
2877 * Returns NULL if window is a top-level window.
2879 HWND *WIN_ListParents( HWND hwnd )
2881 WND *win;
2882 HWND current, *list;
2883 int pos = 0, size = 16, count = 0;
2885 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2887 current = hwnd;
2888 for (;;)
2890 if (!(win = WIN_GetPtr( current ))) goto empty;
2891 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
2892 list[pos] = win->parent;
2893 WIN_ReleasePtr( win );
2894 if (!(current = list[pos]))
2896 if (!pos) goto empty;
2897 return list;
2899 if (++pos == size - 1)
2901 /* need to grow the list */
2902 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
2903 if (!new_list) goto empty;
2904 list = new_list;
2905 size += 16;
2909 /* at least one parent belongs to another process, have to query the server */
2911 for (;;)
2913 count = 0;
2914 SERVER_START_REQ( get_window_parents )
2916 req->handle = hwnd;
2917 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
2918 if (!wine_server_call( req )) count = reply->count;
2920 SERVER_END_REQ;
2921 if (!count) goto empty;
2922 if (size > count)
2924 list[count] = 0;
2925 return list;
2927 HeapFree( GetProcessHeap(), 0, list );
2928 size = count + 1;
2929 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2932 empty:
2933 HeapFree( GetProcessHeap(), 0, list );
2934 return NULL;
2938 /*******************************************************************
2939 * WIN_ListChildren
2941 * Build an array of the children of a given window. The array must be
2942 * freed with HeapFree. Returns NULL when no windows are found.
2944 HWND *WIN_ListChildren( HWND hwnd )
2946 return list_window_children( hwnd, 0, 0 );
2950 /*******************************************************************
2951 * EnumWindows (USER32.@)
2953 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2955 HWND *list;
2956 BOOL ret = TRUE;
2957 int i, iWndsLocks;
2959 /* We have to build a list of all windows first, to avoid */
2960 /* unpleasant side-effects, for instance if the callback */
2961 /* function changes the Z-order of the windows. */
2963 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2965 /* Now call the callback function for every window */
2967 iWndsLocks = WIN_SuspendWndsLock();
2968 for (i = 0; list[i]; i++)
2970 /* Make sure that the window still exists */
2971 if (!IsWindow( list[i] )) continue;
2972 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2974 WIN_RestoreWndsLock(iWndsLocks);
2975 HeapFree( GetProcessHeap(), 0, list );
2976 return ret;
2980 /**********************************************************************
2981 * EnumThreadWindows (USER32.@)
2983 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2985 HWND *list;
2986 int i, iWndsLocks;
2988 if (!(list = list_window_children( GetDesktopWindow(), 0, id ))) return TRUE;
2990 /* Now call the callback function for every window */
2992 iWndsLocks = WIN_SuspendWndsLock();
2993 for (i = 0; list[i]; i++)
2994 if (!func( list[i], lParam )) break;
2995 WIN_RestoreWndsLock(iWndsLocks);
2996 HeapFree( GetProcessHeap(), 0, list );
2997 return TRUE;
3001 /**********************************************************************
3002 * WIN_EnumChildWindows
3004 * Helper function for EnumChildWindows().
3006 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
3008 HWND *childList;
3009 BOOL ret = FALSE;
3011 for ( ; *list; list++)
3013 /* Make sure that the window still exists */
3014 if (!IsWindow( *list )) continue;
3015 /* skip owned windows */
3016 if (GetWindow( *list, GW_OWNER )) continue;
3017 /* Build children list first */
3018 childList = WIN_ListChildren( *list );
3020 ret = func( *list, lParam );
3022 if (childList)
3024 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
3025 HeapFree( GetProcessHeap(), 0, childList );
3027 if (!ret) return FALSE;
3029 return TRUE;
3033 /**********************************************************************
3034 * EnumChildWindows (USER32.@)
3036 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
3038 HWND *list;
3039 int iWndsLocks;
3041 if (!(list = WIN_ListChildren( parent ))) return FALSE;
3042 iWndsLocks = WIN_SuspendWndsLock();
3043 WIN_EnumChildWindows( list, func, lParam );
3044 WIN_RestoreWndsLock(iWndsLocks);
3045 HeapFree( GetProcessHeap(), 0, list );
3046 return TRUE;
3050 /*******************************************************************
3051 * AnyPopup (USER.52)
3053 BOOL16 WINAPI AnyPopup16(void)
3055 return AnyPopup();
3059 /*******************************************************************
3060 * AnyPopup (USER32.@)
3062 BOOL WINAPI AnyPopup(void)
3064 int i;
3065 BOOL retvalue;
3066 HWND *list = WIN_ListChildren( GetDesktopWindow() );
3068 if (!list) return FALSE;
3069 for (i = 0; list[i]; i++)
3071 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
3073 retvalue = (list[i] != 0);
3074 HeapFree( GetProcessHeap(), 0, list );
3075 return retvalue;
3079 /*******************************************************************
3080 * FlashWindow (USER32.@)
3082 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3084 WND *wndPtr = WIN_FindWndPtr(hWnd);
3086 TRACE("%p\n", hWnd);
3088 if (!wndPtr) return FALSE;
3089 hWnd = wndPtr->hwndSelf; /* make it a full handle */
3091 if (wndPtr->dwStyle & WS_MINIMIZE)
3093 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3095 HDC hDC = GetDC(hWnd);
3097 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM)hDC, 0 ))
3098 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
3100 ReleaseDC( hWnd, hDC );
3101 wndPtr->flags |= WIN_NCACTIVATED;
3103 else
3105 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3106 wndPtr->flags &= ~WIN_NCACTIVATED;
3108 WIN_ReleaseWndPtr(wndPtr);
3109 return TRUE;
3111 else
3113 WPARAM16 wparam;
3114 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3115 else wparam = (hWnd == GetForegroundWindow());
3117 WIN_ReleaseWndPtr(wndPtr);
3118 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3119 return wparam;
3123 /*******************************************************************
3124 * FlashWindowEx (USER32.@)
3126 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
3128 FIXME("%p\n", pfwi);
3129 return TRUE;
3132 /*******************************************************************
3133 * GetWindowContextHelpId (USER32.@)
3135 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3137 DWORD retval;
3138 WND *wnd = WIN_FindWndPtr( hwnd );
3139 if (!wnd) return 0;
3140 retval = wnd->helpContext;
3141 WIN_ReleaseWndPtr(wnd);
3142 return retval;
3146 /*******************************************************************
3147 * SetWindowContextHelpId (USER32.@)
3149 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3151 WND *wnd = WIN_FindWndPtr( hwnd );
3152 if (!wnd) return FALSE;
3153 wnd->helpContext = id;
3154 WIN_ReleaseWndPtr(wnd);
3155 return TRUE;
3159 /*******************************************************************
3160 * DragDetect (USER32.@)
3162 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3164 MSG msg;
3165 RECT rect;
3167 rect.left = pt.x - wDragWidth;
3168 rect.right = pt.x + wDragWidth;
3170 rect.top = pt.y - wDragHeight;
3171 rect.bottom = pt.y + wDragHeight;
3173 SetCapture(hWnd);
3175 while(1)
3177 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3179 if( msg.message == WM_LBUTTONUP )
3181 ReleaseCapture();
3182 return 0;
3184 if( msg.message == WM_MOUSEMOVE )
3186 POINT tmp;
3187 tmp.x = LOWORD(msg.lParam);
3188 tmp.y = HIWORD(msg.lParam);
3189 if( !PtInRect( &rect, tmp ))
3191 ReleaseCapture();
3192 return 1;
3196 WaitMessage();
3198 return 0;
3201 /******************************************************************************
3202 * GetWindowModuleFileNameA (USER32.@)
3204 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3206 FIXME("GetWindowModuleFileNameA(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3207 hwnd, lpszFileName, cchFileNameMax);
3208 return 0;
3211 /******************************************************************************
3212 * GetWindowModuleFileNameW (USER32.@)
3214 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR lpszFileName, UINT cchFileNameMax)
3216 FIXME("GetWindowModuleFileNameW(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3217 hwnd, lpszFileName, cchFileNameMax);
3218 return 0;
3221 /******************************************************************************
3222 * GetWindowInfo (USER32.@)
3223 * hwnd: in
3224 * pwi: out.
3225 * MS Documentation mentions that pwi->cbSize must be set to SIZEOF(WINDOWINFO)
3226 * this may be because this structure changed over time. If this is the
3227 * the case, then please: FIXME.
3228 * Using the structure described in MSDN for 98/ME/NT(4.0 SP3)/2000/XP.
3230 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3232 if (!pwi) return FALSE;
3233 if (pwi->cbSize != sizeof(WINDOWINFO))
3235 FIXME("windowinfo->cbSize != sizeof(WINDOWINFO). Please report\n");
3236 return FALSE;
3238 if (!IsWindow(hwnd)) return FALSE;
3240 GetWindowRect(hwnd, &pwi->rcWindow);
3241 GetClientRect(hwnd, &pwi->rcClient);
3242 /* translate to screen coordinates */
3243 MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3245 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3246 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3247 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3249 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3250 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3252 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3253 pwi->wCreatorVersion = 0x0400;
3255 return TRUE;