If the pszProvName param of CryptEnumProviders is too small to hold
[wine/multimedia.git] / windows / win.c
blob433e0b58c04a8c0573b53b46a0b293c3c52b0555
1 /*
2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "config.h"
22 #include "wine/port.h"
24 #include <assert.h>
25 #include <stdarg.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include "windef.h"
29 #include "winbase.h"
30 #include "wine/winbase16.h"
31 #include "wine/winuser16.h"
32 #include "wownt32.h"
33 #include "wine/server.h"
34 #include "wine/unicode.h"
35 #include "win.h"
36 #include "user.h"
37 #include "dce.h"
38 #include "controls.h"
39 #include "cursoricon.h"
40 #include "message.h"
41 #include "winpos.h"
42 #include "winerror.h"
43 #include "wine/debug.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(win);
46 WINE_DECLARE_DEBUG_CHANNEL(msg);
48 #define NB_USER_HANDLES ((LAST_USER_HANDLE - FIRST_USER_HANDLE + 1) >> 1)
49 #define USER_HANDLE_TO_INDEX(hwnd) ((LOWORD(hwnd) - FIRST_USER_HANDLE) >> 1)
51 /**********************************************************************/
53 /* Desktop window */
54 static WND *pWndDesktop = NULL;
56 static WORD wDragWidth = 4;
57 static WORD wDragHeight= 3;
59 static void *user_handles[NB_USER_HANDLES];
61 /***********************************************************************
62 * create_window_handle
64 * Create a window handle with the server.
66 static WND *create_window_handle( HWND parent, HWND owner, ATOM atom,
67 HINSTANCE instance, WINDOWPROCTYPE type )
69 WORD index;
70 WND *win;
71 struct tagCLASS *class = NULL;
72 user_handle_t handle = 0;
73 int extra_bytes = 0;
75 /* if 16-bit instance, map to module handle */
76 if (instance && !HIWORD(instance))
77 instance = HINSTANCE_32(GetExePtr(HINSTANCE_16(instance)));
79 SERVER_START_REQ( create_window )
81 req->parent = parent;
82 req->owner = owner;
83 req->atom = atom;
84 req->instance = instance;
85 if (!wine_server_call_err( req ))
87 handle = reply->handle;
88 extra_bytes = reply->extra;
89 class = reply->class_ptr;
92 SERVER_END_REQ;
94 if (!handle)
96 WARN( "error %ld creating window\n", GetLastError() );
97 return NULL;
100 if (!(win = HeapAlloc( GetProcessHeap(), 0, sizeof(WND) + extra_bytes - sizeof(win->wExtra) )))
102 SERVER_START_REQ( destroy_window )
104 req->handle = handle;
105 wine_server_call( req );
107 SERVER_END_REQ;
108 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
109 return NULL;
112 USER_Lock();
114 index = USER_HANDLE_TO_INDEX(handle);
115 assert( index < NB_USER_HANDLES );
116 user_handles[index] = win;
117 win->hwndSelf = handle;
118 win->dwMagic = WND_MAGIC;
119 win->irefCount = 1;
120 win->cbWndExtra = extra_bytes;
121 memset( win->wExtra, 0, extra_bytes );
122 CLASS_AddWindow( class, win, type );
123 return win;
127 /***********************************************************************
128 * free_window_handle
130 * Free a window handle.
132 static WND *free_window_handle( HWND hwnd )
134 WND *ptr;
135 WORD index = USER_HANDLE_TO_INDEX(hwnd);
137 if (index >= NB_USER_HANDLES) return NULL;
138 USER_Lock();
139 if ((ptr = user_handles[index]))
141 SERVER_START_REQ( destroy_window )
143 req->handle = hwnd;
144 if (!wine_server_call_err( req ))
145 user_handles[index] = NULL;
146 else
147 ptr = NULL;
149 SERVER_END_REQ;
151 USER_Unlock();
152 if (ptr) HeapFree( GetProcessHeap(), 0, ptr );
153 return ptr;
157 /*******************************************************************
158 * list_window_children
160 * Build an array of the children of a given window. The array must be
161 * freed with HeapFree. Returns NULL when no windows are found.
163 static HWND *list_window_children( HWND hwnd, ATOM atom, DWORD tid )
165 HWND *list;
166 int size = 32;
168 for (;;)
170 int count = 0;
172 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
174 SERVER_START_REQ( get_window_children )
176 req->parent = hwnd;
177 req->atom = atom;
178 req->tid = tid;
179 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
180 if (!wine_server_call( req )) count = reply->count;
182 SERVER_END_REQ;
183 if (count && count < size)
185 list[count] = 0;
186 return list;
188 HeapFree( GetProcessHeap(), 0, list );
189 if (!count) break;
190 size = count + 1; /* restart with a large enough buffer */
192 return NULL;
196 /*******************************************************************
197 * send_parent_notify
199 static void send_parent_notify( HWND hwnd, UINT msg )
201 if ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_CHILD | WS_POPUP)) == WS_CHILD &&
202 !(GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY))
203 SendMessageW( GetParent(hwnd), WM_PARENTNOTIFY,
204 MAKEWPARAM( msg, GetWindowLongW( hwnd, GWL_ID )), (LPARAM)hwnd );
208 /*******************************************************************
209 * get_server_window_text
211 * Retrieve the window text from the server.
213 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
215 size_t len = 0;
217 SERVER_START_REQ( get_window_text )
219 req->handle = hwnd;
220 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
221 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
223 SERVER_END_REQ;
224 text[len / sizeof(WCHAR)] = 0;
228 /***********************************************************************
229 * WIN_GetPtr
231 * Return a pointer to the WND structure if local to the process,
232 * or WND_OTHER_PROCESS if handle may be valid in other process.
233 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
235 WND *WIN_GetPtr( HWND hwnd )
237 WND * ptr;
238 WORD index = USER_HANDLE_TO_INDEX(hwnd);
240 if (index >= NB_USER_HANDLES) return NULL;
242 USER_Lock();
243 if ((ptr = user_handles[index]))
245 if (ptr->dwMagic == WND_MAGIC && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
246 return ptr;
247 ptr = NULL;
249 else ptr = WND_OTHER_PROCESS;
250 USER_Unlock();
251 return ptr;
255 /***********************************************************************
256 * WIN_IsCurrentProcess
258 * Check whether a given window belongs to the current process (and return the full handle).
260 HWND WIN_IsCurrentProcess( HWND hwnd )
262 WND *ptr;
263 HWND ret;
265 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS) return 0;
266 ret = ptr->hwndSelf;
267 WIN_ReleasePtr( ptr );
268 return ret;
272 /***********************************************************************
273 * WIN_IsCurrentThread
275 * Check whether a given window belongs to the current thread (and return the full handle).
277 HWND WIN_IsCurrentThread( HWND hwnd )
279 WND *ptr;
280 HWND ret = 0;
282 if ((ptr = WIN_GetPtr( hwnd )) && ptr != WND_OTHER_PROCESS)
284 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
285 WIN_ReleasePtr( ptr );
287 return ret;
291 /***********************************************************************
292 * WIN_Handle32
294 * Convert a 16-bit window handle to a full 32-bit handle.
296 HWND WIN_Handle32( HWND16 hwnd16 )
298 WND *ptr;
299 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
301 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
302 /* do sign extension for -2 and -3 */
303 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
305 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
307 if (ptr != WND_OTHER_PROCESS)
309 hwnd = ptr->hwndSelf;
310 WIN_ReleasePtr( ptr );
312 else /* may belong to another process */
314 SERVER_START_REQ( get_window_info )
316 req->handle = hwnd;
317 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
319 SERVER_END_REQ;
321 return hwnd;
325 /***********************************************************************
326 * WIN_FindWndPtr
328 * Return a pointer to the WND structure corresponding to a HWND.
330 WND * WIN_FindWndPtr( HWND hwnd )
332 WND * ptr;
334 if (!hwnd) return NULL;
336 if ((ptr = WIN_GetPtr( hwnd )))
338 if (ptr != WND_OTHER_PROCESS)
340 /* increment destruction monitoring */
341 ptr->irefCount++;
342 return ptr;
344 if (IsWindow( hwnd )) /* check other processes */
346 ERR( "window %p belongs to other process\n", hwnd );
347 /* DbgBreakPoint(); */
350 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
351 return NULL;
355 /***********************************************************************
356 * WIN_ReleaseWndPtr
358 * Release the pointer to the WND structure.
360 void WIN_ReleaseWndPtr(WND *wndPtr)
362 if(!wndPtr) return;
364 /* Decrement destruction monitoring value */
365 wndPtr->irefCount--;
366 /* Check if it's time to release the memory */
367 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
369 /* Release memory */
370 free_window_handle( wndPtr->hwndSelf );
372 else if(wndPtr->irefCount < 0)
374 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
375 ERR("forgot a Lock on %p somewhere\n",wndPtr);
377 /* unlock all WND structures for thread safeness */
378 USER_Unlock();
382 /***********************************************************************
383 * WIN_UnlinkWindow
385 * Remove a window from the siblings linked list.
387 void WIN_UnlinkWindow( HWND hwnd )
389 WIN_LinkWindow( hwnd, 0, 0 );
393 /***********************************************************************
394 * WIN_LinkWindow
396 * Insert a window into the siblings linked list.
397 * The window is inserted after the specified window, which can also
398 * be specified as HWND_TOP or HWND_BOTTOM.
399 * If parent is 0, window is unlinked from the tree.
401 void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
403 WND *wndPtr = WIN_GetPtr( hwnd );
405 if (!wndPtr) return;
406 if (wndPtr == WND_OTHER_PROCESS)
408 if (IsWindow(hwnd)) ERR(" cannot link other process window %p\n", hwnd );
409 return;
412 SERVER_START_REQ( link_window )
414 req->handle = hwnd;
415 req->parent = parent;
416 req->previous = hwndInsertAfter;
417 if (!wine_server_call( req ))
419 if (reply->full_parent) wndPtr->parent = reply->full_parent;
423 SERVER_END_REQ;
424 WIN_ReleasePtr( wndPtr );
428 /***********************************************************************
429 * WIN_SetOwner
431 * Change the owner of a window.
433 HWND WIN_SetOwner( HWND hwnd, HWND owner )
435 WND *win = WIN_GetPtr( hwnd );
436 HWND ret = 0;
438 if (!win) return 0;
439 if (win == WND_OTHER_PROCESS)
441 if (IsWindow(hwnd)) ERR( "cannot set owner %p on other process window %p\n", owner, hwnd );
442 return 0;
444 SERVER_START_REQ( set_window_owner )
446 req->handle = hwnd;
447 req->owner = owner;
448 if (!wine_server_call( req ))
450 win->owner = reply->full_owner;
451 ret = reply->prev_owner;
454 SERVER_END_REQ;
455 WIN_ReleasePtr( win );
456 return ret;
460 /***********************************************************************
461 * WIN_SetStyle
463 * Change the style of a window.
465 LONG WIN_SetStyle( HWND hwnd, LONG style )
467 BOOL ok;
468 LONG ret = 0;
469 WND *win = WIN_GetPtr( hwnd );
471 if (!win) return 0;
472 if (win == WND_OTHER_PROCESS)
474 if (IsWindow(hwnd))
475 ERR( "cannot set style %lx on other process window %p\n", style, hwnd );
476 return 0;
478 if (style == win->dwStyle)
480 WIN_ReleasePtr( win );
481 return style;
483 SERVER_START_REQ( set_window_info )
485 req->handle = hwnd;
486 req->flags = SET_WIN_STYLE;
487 req->style = style;
488 req->extra_offset = -1;
489 if ((ok = !wine_server_call( req )))
491 ret = reply->old_style;
492 win->dwStyle = style;
495 SERVER_END_REQ;
496 WIN_ReleasePtr( win );
497 if (ok && USER_Driver.pSetWindowStyle) USER_Driver.pSetWindowStyle( hwnd, ret );
498 return ret;
502 /***********************************************************************
503 * WIN_SetExStyle
505 * Change the extended style of a window.
507 LONG WIN_SetExStyle( HWND hwnd, LONG style )
509 LONG ret = 0;
510 WND *win = WIN_GetPtr( hwnd );
512 if (!win) return 0;
513 if (win == WND_OTHER_PROCESS)
515 if (IsWindow(hwnd))
516 ERR( "cannot set exstyle %lx on other process window %p\n", style, hwnd );
517 return 0;
519 if (style == win->dwExStyle)
521 WIN_ReleasePtr( win );
522 return style;
524 SERVER_START_REQ( set_window_info )
526 req->handle = hwnd;
527 req->flags = SET_WIN_EXSTYLE;
528 req->ex_style = style;
529 req->extra_offset = -1;
530 if (!wine_server_call( req ))
532 ret = reply->old_ex_style;
533 win->dwExStyle = style;
536 SERVER_END_REQ;
537 WIN_ReleasePtr( win );
538 return ret;
542 /***********************************************************************
543 * WIN_SetRectangles
545 * Set the window and client rectangles.
547 void WIN_SetRectangles( HWND hwnd, const RECT *rectWindow, const RECT *rectClient )
549 WND *win = WIN_GetPtr( hwnd );
550 BOOL ret;
552 if (!win) return;
553 if (win == WND_OTHER_PROCESS)
555 if (IsWindow( hwnd )) ERR( "cannot set rectangles of other process window %p\n", hwnd );
556 return;
558 SERVER_START_REQ( set_window_rectangles )
560 req->handle = hwnd;
561 req->window.left = rectWindow->left;
562 req->window.top = rectWindow->top;
563 req->window.right = rectWindow->right;
564 req->window.bottom = rectWindow->bottom;
565 req->client.left = rectClient->left;
566 req->client.top = rectClient->top;
567 req->client.right = rectClient->right;
568 req->client.bottom = rectClient->bottom;
569 ret = !wine_server_call( req );
571 SERVER_END_REQ;
572 if (ret)
574 win->rectWindow = *rectWindow;
575 win->rectClient = *rectClient;
577 TRACE( "win %p window (%ld,%ld)-(%ld,%ld) client (%ld,%ld)-(%ld,%ld)\n", hwnd,
578 rectWindow->left, rectWindow->top, rectWindow->right, rectWindow->bottom,
579 rectClient->left, rectClient->top, rectClient->right, rectClient->bottom );
581 WIN_ReleasePtr( win );
585 /***********************************************************************
586 * WIN_GetRectangles
588 * Get the window and client rectangles.
590 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
592 WND *win = WIN_GetPtr( hwnd );
593 BOOL ret = TRUE;
595 if (!win) return FALSE;
596 if (win == WND_OTHER_PROCESS)
598 SERVER_START_REQ( get_window_rectangles )
600 req->handle = hwnd;
601 if ((ret = !wine_server_call( req )))
603 if (rectWindow)
605 rectWindow->left = reply->window.left;
606 rectWindow->top = reply->window.top;
607 rectWindow->right = reply->window.right;
608 rectWindow->bottom = reply->window.bottom;
610 if (rectClient)
612 rectClient->left = reply->client.left;
613 rectClient->top = reply->client.top;
614 rectClient->right = reply->client.right;
615 rectClient->bottom = reply->client.bottom;
619 SERVER_END_REQ;
621 else
623 if (rectWindow) *rectWindow = win->rectWindow;
624 if (rectClient) *rectClient = win->rectClient;
625 WIN_ReleasePtr( win );
627 return ret;
631 /***********************************************************************
632 * WIN_DestroyWindow
634 * Destroy storage associated to a window. "Internals" p.358
636 LRESULT WIN_DestroyWindow( HWND hwnd )
638 WND *wndPtr;
639 HWND *list;
641 TRACE("%p\n", hwnd );
643 if (!(hwnd = WIN_IsCurrentThread( hwnd )))
645 ERR( "window doesn't belong to current thread\n" );
646 return 0;
649 /* free child windows */
650 if ((list = WIN_ListChildren( hwnd )))
652 int i;
653 for (i = 0; list[i]; i++)
655 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
656 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
658 HeapFree( GetProcessHeap(), 0, list );
662 * Clear the update region to make sure no WM_PAINT messages will be
663 * generated for this window while processing the WM_NCDESTROY.
665 RedrawWindow( hwnd, NULL, 0,
666 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
669 * Send the WM_NCDESTROY to the window being destroyed.
671 SendMessageA( hwnd, WM_NCDESTROY, 0, 0);
673 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
675 WINPOS_CheckInternalPos( hwnd );
676 if( hwnd == GetCapture()) ReleaseCapture();
678 /* free resources associated with the window */
680 TIMER_RemoveWindowTimers( hwnd );
682 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
684 if (!(wndPtr->dwStyle & WS_CHILD))
686 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
687 if (menu) DestroyMenu( menu );
689 if (wndPtr->hSysMenu)
691 DestroyMenu( wndPtr->hSysMenu );
692 wndPtr->hSysMenu = 0;
694 DCE_FreeWindowDCE( hwnd ); /* Always do this to catch orphaned DCs */
695 USER_Driver.pDestroyWindow( hwnd );
696 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
697 wndPtr->class = NULL;
698 wndPtr->dwMagic = 0; /* Mark it as invalid */
699 WIN_ReleaseWndPtr( wndPtr );
700 return 0;
703 /***********************************************************************
704 * WIN_DestroyThreadWindows
706 * Destroy all children of 'wnd' owned by the current thread.
707 * Return TRUE if something was done.
709 void WIN_DestroyThreadWindows( HWND hwnd )
711 HWND *list;
712 int i;
714 if (!(list = WIN_ListChildren( hwnd ))) return;
715 for (i = 0; list[i]; i++)
717 if (WIN_IsCurrentThread( list[i] ))
718 DestroyWindow( list[i] );
719 else
720 WIN_DestroyThreadWindows( list[i] );
722 HeapFree( GetProcessHeap(), 0, list );
725 /***********************************************************************
726 * WIN_CreateDesktopWindow
728 * Create the desktop window.
730 BOOL WIN_CreateDesktopWindow(void)
732 HWND hwndDesktop;
733 CREATESTRUCTA cs;
734 RECT rect;
736 TRACE("Creating desktop window\n");
738 if (!WINPOS_CreateInternalPosAtom()) return FALSE;
740 pWndDesktop = create_window_handle( 0, 0, LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W );
741 if (!pWndDesktop) return FALSE;
742 hwndDesktop = pWndDesktop->hwndSelf;
744 pWndDesktop->tid = 0; /* nobody owns the desktop */
745 pWndDesktop->parent = 0;
746 pWndDesktop->owner = 0;
747 pWndDesktop->text = NULL;
748 pWndDesktop->hrgnUpdate = 0;
749 pWndDesktop->pVScroll = NULL;
750 pWndDesktop->pHScroll = NULL;
751 pWndDesktop->helpContext = 0;
752 pWndDesktop->flags = 0;
753 pWndDesktop->hSysMenu = 0;
755 cs.lpCreateParams = NULL;
756 cs.hInstance = 0;
757 cs.hMenu = 0;
758 cs.hwndParent = 0;
759 cs.x = 0;
760 cs.y = 0;
761 cs.cx = GetSystemMetrics( SM_CXSCREEN );
762 cs.cy = GetSystemMetrics( SM_CYSCREEN );
763 cs.style = pWndDesktop->dwStyle;
764 cs.dwExStyle = pWndDesktop->dwExStyle;
765 cs.lpszName = NULL;
766 cs.lpszClass = DESKTOP_CLASS_ATOM;
768 SetRect( &rect, 0, 0, cs.cx, cs.cy );
769 WIN_SetRectangles( hwndDesktop, &rect, &rect );
771 SERVER_START_REQ( set_window_info )
773 req->handle = hwndDesktop;
774 req->flags = 0; /* don't set anything, just retrieve */
775 req->extra_offset = -1;
776 wine_server_call( req );
777 pWndDesktop->dwStyle = reply->old_style;
778 pWndDesktop->dwExStyle = reply->old_ex_style;
779 pWndDesktop->hInstance = (HINSTANCE)reply->old_instance;
780 pWndDesktop->userdata = (ULONG_PTR)reply->old_user_data;
781 pWndDesktop->wIDmenu = reply->old_id;
783 SERVER_END_REQ;
785 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE ))
787 WIN_ReleaseWndPtr( pWndDesktop );
788 return FALSE;
791 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
792 WIN_ReleaseWndPtr( pWndDesktop );
793 return TRUE;
797 /***********************************************************************
798 * WIN_FixCoordinates
800 * Fix the coordinates - Helper for WIN_CreateWindowEx.
801 * returns default show mode in sw.
802 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
804 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
806 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
807 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
809 if (cs->style & (WS_CHILD | WS_POPUP))
811 if (cs->dwExStyle & WS_EX_MDICHILD)
813 POINT pos[2];
815 MDI_CalcDefaultChildPos(cs->hwndParent, -1, pos, 0);
817 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
819 cs->x = pos[0].x;
820 cs->y = pos[0].y;
822 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16 || !cs->cx)
823 cs->cx = pos[1].x;
824 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16 || !cs->cy)
825 cs->cy = pos[1].y;
827 else
829 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
830 cs->x = cs->y = 0;
831 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
832 cs->cx = cs->cy = 0;
835 else /* overlapped window */
837 STARTUPINFOA info;
839 GetStartupInfoA( &info );
841 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
843 /* Never believe Microsoft's documentation... CreateWindowEx doc says
844 * that if an overlapped window is created with WS_VISIBLE style bit
845 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
846 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
847 * reveals that
849 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
850 * 2) it does not ignore the y parameter as the docs claim; instead, it
851 * uses it as second parameter to ShowWindow() unless y is either
852 * CW_USEDEFAULT or CW_USEDEFAULT16.
854 * The fact that we didn't do 2) caused bogus windows pop up when wine
855 * was running apps that were using this obscure feature. Example -
856 * calc.exe that comes with Win98 (only Win98, it's different from
857 * the one that comes with Win95 and NT)
859 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
860 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
861 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
864 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
866 if (info.dwFlags & STARTF_USESIZE)
868 cs->cx = info.dwXSize;
869 cs->cy = info.dwYSize;
871 else /* if no other hint from the app, pick 3/4 of the screen real estate */
873 RECT r;
874 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
875 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
876 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
881 else
883 /* neither x nor cx are default. Check the y values .
884 * In the trace we see Outlook and Outlook Express using
885 * cy set to CW_USEDEFAULT when opening the address book.
887 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16) {
888 RECT r;
889 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
890 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
891 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
896 /***********************************************************************
897 * dump_window_styles
899 static void dump_window_styles( DWORD style, DWORD exstyle )
901 TRACE( "style:" );
902 if(style & WS_POPUP) TRACE(" WS_POPUP");
903 if(style & WS_CHILD) TRACE(" WS_CHILD");
904 if(style & WS_MINIMIZE) TRACE(" WS_MINIMIZE");
905 if(style & WS_VISIBLE) TRACE(" WS_VISIBLE");
906 if(style & WS_DISABLED) TRACE(" WS_DISABLED");
907 if(style & WS_CLIPSIBLINGS) TRACE(" WS_CLIPSIBLINGS");
908 if(style & WS_CLIPCHILDREN) TRACE(" WS_CLIPCHILDREN");
909 if(style & WS_MAXIMIZE) TRACE(" WS_MAXIMIZE");
910 if((style & WS_CAPTION) == WS_CAPTION) TRACE(" WS_CAPTION");
911 else
913 if(style & WS_BORDER) TRACE(" WS_BORDER");
914 if(style & WS_DLGFRAME) TRACE(" WS_DLGFRAME");
916 if(style & WS_VSCROLL) TRACE(" WS_VSCROLL");
917 if(style & WS_HSCROLL) TRACE(" WS_HSCROLL");
918 if(style & WS_SYSMENU) TRACE(" WS_SYSMENU");
919 if(style & WS_THICKFRAME) TRACE(" WS_THICKFRAME");
920 if(style & WS_GROUP) TRACE(" WS_GROUP");
921 if(style & WS_TABSTOP) TRACE(" WS_TABSTOP");
922 if(style & WS_MINIMIZEBOX) TRACE(" WS_MINIMIZEBOX");
923 if(style & WS_MAXIMIZEBOX) TRACE(" WS_MAXIMIZEBOX");
925 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
926 #define DUMPED_STYLES \
927 (WS_POPUP | \
928 WS_CHILD | \
929 WS_MINIMIZE | \
930 WS_VISIBLE | \
931 WS_DISABLED | \
932 WS_CLIPSIBLINGS | \
933 WS_CLIPCHILDREN | \
934 WS_MAXIMIZE | \
935 WS_BORDER | \
936 WS_DLGFRAME | \
937 WS_VSCROLL | \
938 WS_HSCROLL | \
939 WS_SYSMENU | \
940 WS_THICKFRAME | \
941 WS_GROUP | \
942 WS_TABSTOP | \
943 WS_MINIMIZEBOX | \
944 WS_MAXIMIZEBOX)
946 if(style & ~DUMPED_STYLES) TRACE(" %08lx", style & ~DUMPED_STYLES);
947 TRACE("\n");
948 #undef DUMPED_STYLES
950 TRACE( "exstyle:" );
951 if(exstyle & WS_EX_DLGMODALFRAME) TRACE(" WS_EX_DLGMODALFRAME");
952 if(exstyle & WS_EX_DRAGDETECT) TRACE(" WS_EX_DRAGDETECT");
953 if(exstyle & WS_EX_NOPARENTNOTIFY) TRACE(" WS_EX_NOPARENTNOTIFY");
954 if(exstyle & WS_EX_TOPMOST) TRACE(" WS_EX_TOPMOST");
955 if(exstyle & WS_EX_ACCEPTFILES) TRACE(" WS_EX_ACCEPTFILES");
956 if(exstyle & WS_EX_TRANSPARENT) TRACE(" WS_EX_TRANSPARENT");
957 if(exstyle & WS_EX_MDICHILD) TRACE(" WS_EX_MDICHILD");
958 if(exstyle & WS_EX_TOOLWINDOW) TRACE(" WS_EX_TOOLWINDOW");
959 if(exstyle & WS_EX_WINDOWEDGE) TRACE(" WS_EX_WINDOWEDGE");
960 if(exstyle & WS_EX_CLIENTEDGE) TRACE(" WS_EX_CLIENTEDGE");
961 if(exstyle & WS_EX_CONTEXTHELP) TRACE(" WS_EX_CONTEXTHELP");
962 if(exstyle & WS_EX_RIGHT) TRACE(" WS_EX_RIGHT");
963 if(exstyle & WS_EX_RTLREADING) TRACE(" WS_EX_RTLREADING");
964 if(exstyle & WS_EX_LEFTSCROLLBAR) TRACE(" WS_EX_LEFTSCROLLBAR");
965 if(exstyle & WS_EX_CONTROLPARENT) TRACE(" WS_EX_CONTROLPARENT");
966 if(exstyle & WS_EX_STATICEDGE) TRACE(" WS_EX_STATICEDGE");
967 if(exstyle & WS_EX_APPWINDOW) TRACE(" WS_EX_APPWINDOW");
968 if(exstyle & WS_EX_LAYERED) TRACE(" WS_EX_LAYERED");
970 #define DUMPED_EX_STYLES \
971 (WS_EX_DLGMODALFRAME | \
972 WS_EX_DRAGDETECT | \
973 WS_EX_NOPARENTNOTIFY | \
974 WS_EX_TOPMOST | \
975 WS_EX_ACCEPTFILES | \
976 WS_EX_TRANSPARENT | \
977 WS_EX_MDICHILD | \
978 WS_EX_TOOLWINDOW | \
979 WS_EX_WINDOWEDGE | \
980 WS_EX_CLIENTEDGE | \
981 WS_EX_CONTEXTHELP | \
982 WS_EX_RIGHT | \
983 WS_EX_RTLREADING | \
984 WS_EX_LEFTSCROLLBAR | \
985 WS_EX_CONTROLPARENT | \
986 WS_EX_STATICEDGE | \
987 WS_EX_APPWINDOW | \
988 WS_EX_LAYERED)
990 if(exstyle & ~DUMPED_EX_STYLES) TRACE(" %08lx", exstyle & ~DUMPED_EX_STYLES);
991 TRACE("\n");
992 #undef DUMPED_EX_STYLES
996 /***********************************************************************
997 * WIN_CreateWindowEx
999 * Implementation of CreateWindowEx().
1001 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
1002 WINDOWPROCTYPE type )
1004 INT sw = SW_SHOW;
1005 WND *wndPtr;
1006 HWND hwnd, parent, owner, top_child = 0;
1007 BOOL unicode = (type == WIN_PROC_32W);
1009 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
1010 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
1011 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszClass) : debugstr_a(cs->lpszClass),
1012 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
1013 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
1015 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
1017 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
1018 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
1020 /* Fix the styles for MDI children */
1021 if (cs->dwExStyle & WS_EX_MDICHILD)
1023 MDICREATESTRUCTA mdi_cs;
1024 UINT flags = 0;
1026 wndPtr = WIN_GetPtr(cs->hwndParent);
1027 if (wndPtr && wndPtr != WND_OTHER_PROCESS)
1029 flags = wndPtr->flags;
1030 WIN_ReleasePtr(wndPtr);
1033 if (!(flags & WIN_ISMDICLIENT))
1035 WARN("WS_EX_MDICHILD, but parent %p is not MDIClient\n", cs->hwndParent);
1036 return 0;
1039 /* cs->lpCreateParams of WM_[NC]CREATE is different for MDI children.
1040 * MDICREATESTRUCT members have the originally passed values.
1042 * Note: we rely on the fact that MDICREATESTRUCTA and MDICREATESTRUCTW
1043 * have the same layout.
1045 mdi_cs.szClass = cs->lpszClass;
1046 mdi_cs.szTitle = cs->lpszName;
1047 mdi_cs.hOwner = cs->hInstance;
1048 mdi_cs.x = cs->x;
1049 mdi_cs.y = cs->y;
1050 mdi_cs.cx = cs->cx;
1051 mdi_cs.cy = cs->cy;
1052 mdi_cs.style = cs->style;
1053 mdi_cs.lParam = (LPARAM)cs->lpCreateParams;
1055 cs->lpCreateParams = (LPVOID)&mdi_cs;
1057 if (GetWindowLongW(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
1059 if (cs->style & WS_POPUP)
1061 TRACE("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n");
1062 return 0;
1064 cs->style |= WS_CHILD | WS_CLIPSIBLINGS;
1066 else
1068 cs->style &= ~WS_POPUP;
1069 cs->style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
1070 WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
1073 top_child = GetWindow(cs->hwndParent, GW_CHILD);
1076 /* Find the parent window */
1078 parent = GetDesktopWindow();
1079 owner = 0;
1081 if (cs->hwndParent == HWND_MESSAGE)
1083 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
1084 * message window (style: WS_POPUP|WS_DISABLED)
1086 FIXME("Parent is HWND_MESSAGE\n");
1088 else if (cs->hwndParent)
1090 /* Make sure parent is valid */
1091 if (!IsWindow( cs->hwndParent ))
1093 WARN("Bad parent %p\n", cs->hwndParent );
1094 return 0;
1096 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1097 parent = WIN_GetFullHandle(cs->hwndParent);
1098 else
1099 owner = GetAncestor( cs->hwndParent, GA_ROOT );
1101 else if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1103 WARN("No parent for child window\n" );
1104 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1107 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
1109 /* Correct the window styles.
1111 * It affects both the style loaded into the WIN structure and
1112 * passed in the CREATESTRUCT to the WM_[NC]CREATE.
1114 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1115 * why does the user get to set it?
1118 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
1119 * tested for WS_POPUP
1121 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
1122 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
1123 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
1124 cs->dwExStyle |= WS_EX_WINDOWEDGE;
1125 else
1126 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
1128 if (!(cs->style & WS_CHILD))
1130 cs->style |= WS_CLIPSIBLINGS;
1131 if (!(cs->style & WS_POPUP))
1132 cs->style |= WS_CAPTION;
1135 /* Create the window structure */
1137 if (!(wndPtr = create_window_handle( parent, owner, classAtom, cs->hInstance, type )))
1139 TRACE("out of memory\n" );
1140 return 0;
1142 hwnd = wndPtr->hwndSelf;
1144 /* Fill the window structure */
1146 wndPtr->tid = GetCurrentThreadId();
1147 wndPtr->owner = owner;
1148 wndPtr->parent = parent;
1149 wndPtr->hInstance = cs->hInstance;
1150 wndPtr->text = NULL;
1151 wndPtr->hrgnUpdate = 0;
1152 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1153 wndPtr->dwExStyle = cs->dwExStyle;
1154 wndPtr->wIDmenu = 0;
1155 wndPtr->helpContext = 0;
1156 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
1157 wndPtr->pVScroll = NULL;
1158 wndPtr->pHScroll = NULL;
1159 wndPtr->userdata = 0;
1160 wndPtr->hIcon = 0;
1161 wndPtr->hIconSmall = 0;
1162 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU) ? MENU_GetSysMenu( hwnd, 0 ) : 0;
1164 if (!(cs->style & (WS_CHILD | WS_POPUP)))
1165 wndPtr->flags |= WIN_NEED_SIZE;
1167 SERVER_START_REQ( set_window_info )
1169 req->handle = hwnd;
1170 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE;
1171 req->style = wndPtr->dwStyle;
1172 req->ex_style = wndPtr->dwExStyle;
1173 req->instance = (void *)wndPtr->hInstance;
1174 req->extra_offset = -1;
1175 wine_server_call( req );
1177 SERVER_END_REQ;
1179 /* Get class or window DC if needed */
1181 if (wndPtr->clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
1183 /* Set the window menu */
1185 if (((wndPtr->dwStyle & (WS_CAPTION|WS_CHILD)) == WS_CAPTION) ||
1186 (wndPtr->dwExStyle & WS_EX_APPWINDOW))
1188 if (cs->hMenu) MENU_SetMenu(hwnd, cs->hMenu);
1189 else
1191 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
1192 if (menuName)
1194 if (HIWORD(cs->hInstance))
1195 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1196 else
1197 cs->hMenu = HMENU_32(LoadMenu16(HINSTANCE_16(cs->hInstance),menuName));
1199 if (cs->hMenu) MENU_SetMenu( hwnd, cs->hMenu );
1203 else SetWindowLongW( hwnd, GWL_ID, (UINT)cs->hMenu );
1204 WIN_ReleaseWndPtr( wndPtr );
1206 if (!USER_Driver.pCreateWindow( hwnd, cs, unicode))
1208 WIN_DestroyWindow( hwnd );
1209 return 0;
1212 /* Notify the parent window only */
1214 send_parent_notify( hwnd, WM_CREATE );
1215 if (!IsWindow( hwnd )) return 0;
1217 if (cs->dwExStyle & WS_EX_MDICHILD)
1219 if (top_child)
1221 /* Restore current maximized child */
1222 if((cs->style & WS_VISIBLE) && IsZoomed(top_child))
1224 TRACE("Restoring current maximized child %p\n", top_child);
1225 ShowWindow(top_child, SW_SHOWNOACTIVATE);
1229 SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
1232 if (cs->style & WS_VISIBLE)
1233 ShowWindow( hwnd, sw );
1235 /* Call WH_SHELL hook */
1237 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1238 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1240 TRACE("created window %p\n", hwnd);
1241 return hwnd;
1245 /***********************************************************************
1246 * CreateWindow (USER.41)
1248 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1249 DWORD style, INT16 x, INT16 y, INT16 width,
1250 INT16 height, HWND16 parent, HMENU16 menu,
1251 HINSTANCE16 instance, LPVOID data )
1253 return CreateWindowEx16( 0, className, windowName, style,
1254 x, y, width, height, parent, menu, instance, data );
1258 /***********************************************************************
1259 * CreateWindowEx (USER.452)
1261 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1262 LPCSTR windowName, DWORD style, INT16 x,
1263 INT16 y, INT16 width, INT16 height,
1264 HWND16 parent, HMENU16 menu,
1265 HINSTANCE16 instance, LPVOID data )
1267 ATOM classAtom;
1268 CREATESTRUCTA cs;
1269 char buffer[256];
1271 /* Find the class atom */
1273 if (HIWORD(className))
1275 if (!(classAtom = GlobalFindAtomA( className )))
1277 ERR( "bad class name %s\n", debugstr_a(className) );
1278 return 0;
1281 else
1283 classAtom = LOWORD(className);
1284 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1286 ERR( "bad atom %x\n", classAtom);
1287 return 0;
1289 className = buffer;
1292 /* Fix the coordinates */
1294 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1295 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1296 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1297 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1299 /* Create the window */
1301 cs.lpCreateParams = data;
1302 cs.hInstance = HINSTANCE_32(instance);
1303 cs.hMenu = HMENU_32(menu);
1304 cs.hwndParent = WIN_Handle32( parent );
1305 cs.style = style;
1306 cs.lpszName = windowName;
1307 cs.lpszClass = className;
1308 cs.dwExStyle = exStyle;
1310 return HWND_16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
1314 /***********************************************************************
1315 * CreateWindowExA (USER32.@)
1317 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1318 LPCSTR windowName, DWORD style, INT x,
1319 INT y, INT width, INT height,
1320 HWND parent, HMENU menu,
1321 HINSTANCE instance, LPVOID data )
1323 ATOM classAtom;
1324 CREATESTRUCTA cs;
1325 char buffer[256];
1327 /* Find the class atom */
1329 if (HIWORD(className))
1331 if (!(classAtom = GlobalFindAtomA( className )))
1333 ERR( "bad class name %s\n", debugstr_a(className) );
1334 return 0;
1337 else
1339 classAtom = LOWORD(className);
1340 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1342 ERR( "bad atom %x\n", classAtom);
1343 return 0;
1345 className = buffer;
1348 /* Create the window */
1350 cs.lpCreateParams = data;
1351 cs.hInstance = instance;
1352 cs.hMenu = menu;
1353 cs.hwndParent = parent;
1354 cs.x = x;
1355 cs.y = y;
1356 cs.cx = width;
1357 cs.cy = height;
1358 cs.style = style;
1359 cs.lpszName = windowName;
1360 cs.lpszClass = className;
1361 cs.dwExStyle = exStyle;
1363 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1367 /***********************************************************************
1368 * CreateWindowExW (USER32.@)
1370 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1371 LPCWSTR windowName, DWORD style, INT x,
1372 INT y, INT width, INT height,
1373 HWND parent, HMENU menu,
1374 HINSTANCE instance, LPVOID data )
1376 ATOM classAtom;
1377 CREATESTRUCTW cs;
1378 WCHAR buffer[256];
1380 /* Find the class atom */
1382 if (HIWORD(className))
1384 if (!(classAtom = GlobalFindAtomW( className )))
1386 ERR( "bad class name %s\n", debugstr_w(className) );
1387 return 0;
1390 else
1392 classAtom = LOWORD(className);
1393 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1395 ERR( "bad atom %x\n", classAtom);
1396 return 0;
1398 className = buffer;
1401 /* Create the window */
1403 cs.lpCreateParams = data;
1404 cs.hInstance = instance;
1405 cs.hMenu = menu;
1406 cs.hwndParent = parent;
1407 cs.x = x;
1408 cs.y = y;
1409 cs.cx = width;
1410 cs.cy = height;
1411 cs.style = style;
1412 cs.lpszName = windowName;
1413 cs.lpszClass = className;
1414 cs.dwExStyle = exStyle;
1416 /* Note: we rely on the fact that CREATESTRUCTA and */
1417 /* CREATESTRUCTW have the same layout. */
1418 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1422 /***********************************************************************
1423 * WIN_SendDestroyMsg
1425 static void WIN_SendDestroyMsg( HWND hwnd )
1427 GUITHREADINFO info;
1429 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1431 if (hwnd == info.hwndCaret) DestroyCaret();
1432 if (hwnd == info.hwndActive) WINPOS_ActivateOtherWindow( hwnd );
1434 if (USER_Driver.pResetSelectionOwner)
1435 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1438 * Send the WM_DESTROY to the window.
1440 SendMessageA( hwnd, WM_DESTROY, 0, 0);
1443 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1444 * make sure that the window still exists when we come back.
1446 if (IsWindow(hwnd))
1448 HWND* pWndArray;
1449 int i;
1451 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1453 /* start from the end (FIXME: is this needed?) */
1454 for (i = 0; pWndArray[i]; i++) ;
1456 while (--i >= 0)
1458 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1460 HeapFree( GetProcessHeap(), 0, pWndArray );
1462 else
1463 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1467 /***********************************************************************
1468 * DestroyWindow (USER32.@)
1470 BOOL WINAPI DestroyWindow( HWND hwnd )
1472 BOOL is_child;
1474 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1476 SetLastError( ERROR_ACCESS_DENIED );
1477 return FALSE;
1480 TRACE("(%p)\n", hwnd);
1482 if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
1483 SendMessageW(GetAncestor(hwnd, GA_PARENT), WM_MDIREFRESHMENU, 0, 0);
1485 /* Call hooks */
1487 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1489 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1491 if (is_child)
1493 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1494 send_parent_notify( hwnd, WM_DESTROY );
1496 else if (!GetWindow( hwnd, GW_OWNER ))
1498 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1499 /* FIXME: clean up palette - see "Internals" p.352 */
1502 if (!IsWindow(hwnd)) return TRUE;
1504 if (USER_Driver.pResetSelectionOwner)
1505 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1507 /* Hide the window */
1509 /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
1510 if (is_child)
1511 ShowWindow( hwnd, SW_HIDE );
1512 else
1513 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1514 SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW );
1516 if (!IsWindow(hwnd)) return TRUE;
1518 /* Recursively destroy owned windows */
1520 if (!is_child)
1522 for (;;)
1524 int i, got_one = 0;
1525 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1526 if (list)
1528 for (i = 0; list[i]; i++)
1530 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1531 if (WIN_IsCurrentThread( list[i] ))
1533 DestroyWindow( list[i] );
1534 got_one = 1;
1535 continue;
1537 WIN_SetOwner( list[i], 0 );
1539 HeapFree( GetProcessHeap(), 0, list );
1541 if (!got_one) break;
1545 /* Send destroy messages */
1547 WIN_SendDestroyMsg( hwnd );
1548 if (!IsWindow( hwnd )) return TRUE;
1550 if (GetClipboardOwner() == hwnd)
1551 CLIPBOARD_ReleaseOwner();
1553 /* Unlink now so we won't bother with the children later on */
1555 WIN_UnlinkWindow( hwnd );
1557 /* Destroy the window storage */
1559 WIN_DestroyWindow( hwnd );
1560 return TRUE;
1564 /***********************************************************************
1565 * CloseWindow (USER32.@)
1567 BOOL WINAPI CloseWindow( HWND hwnd )
1569 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1570 ShowWindow( hwnd, SW_MINIMIZE );
1571 return TRUE;
1575 /***********************************************************************
1576 * OpenIcon (USER32.@)
1578 BOOL WINAPI OpenIcon( HWND hwnd )
1580 if (!IsIconic( hwnd )) return FALSE;
1581 ShowWindow( hwnd, SW_SHOWNORMAL );
1582 return TRUE;
1586 /***********************************************************************
1587 * WIN_FindWindow
1589 * Implementation of FindWindow() and FindWindowEx().
1591 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1593 HWND *list = NULL;
1594 HWND retvalue = 0;
1595 int i = 0, len = 0;
1596 WCHAR *buffer = NULL;
1598 if (!parent) parent = GetDesktopWindow();
1599 if (title)
1601 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1602 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1605 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1607 if (child)
1609 child = WIN_GetFullHandle( child );
1610 while (list[i] && list[i] != child) i++;
1611 if (!list[i]) goto done;
1612 i++; /* start from next window */
1615 if (title)
1617 while (list[i])
1619 if (GetWindowTextW( list[i], buffer, len + 1 ) && !strcmpiW( buffer, title )) break;
1620 i++;
1623 retvalue = list[i];
1625 done:
1626 if (list) HeapFree( GetProcessHeap(), 0, list );
1627 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1628 return retvalue;
1633 /***********************************************************************
1634 * FindWindowA (USER32.@)
1636 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1638 HWND ret = FindWindowExA( 0, 0, className, title );
1639 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1640 return ret;
1644 /***********************************************************************
1645 * FindWindowExA (USER32.@)
1647 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1648 LPCSTR className, LPCSTR title )
1650 ATOM atom = 0;
1651 LPWSTR buffer;
1652 HWND hwnd;
1653 INT len;
1655 if (className)
1657 /* If the atom doesn't exist, then no class */
1658 /* with this name exists either. */
1659 if (!(atom = GlobalFindAtomA( className )))
1661 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1662 return 0;
1665 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
1667 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1668 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1669 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
1670 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1671 HeapFree( GetProcessHeap(), 0, buffer );
1672 return hwnd;
1676 /***********************************************************************
1677 * FindWindowExW (USER32.@)
1679 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1680 LPCWSTR className, LPCWSTR title )
1682 ATOM atom = 0;
1684 if (className)
1686 /* If the atom doesn't exist, then no class */
1687 /* with this name exists either. */
1688 if (!(atom = GlobalFindAtomW( className )))
1690 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1691 return 0;
1694 return WIN_FindWindow( parent, child, atom, title );
1698 /***********************************************************************
1699 * FindWindowW (USER32.@)
1701 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1703 return FindWindowExW( 0, 0, className, title );
1707 /**********************************************************************
1708 * GetDesktopWindow (USER32.@)
1710 HWND WINAPI GetDesktopWindow(void)
1712 if (pWndDesktop) return pWndDesktop->hwndSelf;
1713 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" );
1714 ExitProcess(1);
1715 return 0;
1719 /*******************************************************************
1720 * EnableWindow (USER32.@)
1722 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1724 WND *wndPtr;
1725 BOOL retvalue;
1726 LONG style;
1727 HWND full_handle;
1729 if (is_broadcast(hwnd))
1731 SetLastError( ERROR_INVALID_PARAMETER );
1732 return FALSE;
1735 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1736 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1738 hwnd = full_handle;
1740 TRACE("( %p, %d )\n", hwnd, enable);
1742 if (!(wndPtr = WIN_GetPtr( hwnd ))) return FALSE;
1743 style = wndPtr->dwStyle;
1744 retvalue = ((style & WS_DISABLED) != 0);
1745 WIN_ReleasePtr( wndPtr );
1747 if (enable && retvalue)
1749 WIN_SetStyle( hwnd, style & ~WS_DISABLED );
1750 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1752 else if (!enable && !retvalue)
1754 HWND capture_wnd;
1756 SendMessageA( hwnd, WM_CANCELMODE, 0, 0);
1758 WIN_SetStyle( hwnd, style | WS_DISABLED );
1760 if (hwnd == GetFocus())
1761 SetFocus( 0 ); /* A disabled window can't have the focus */
1763 capture_wnd = GetCapture();
1764 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1765 ReleaseCapture(); /* A disabled window can't capture the mouse */
1767 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1769 return retvalue;
1773 /***********************************************************************
1774 * IsWindowEnabled (USER32.@)
1776 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1778 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1782 /***********************************************************************
1783 * IsWindowUnicode (USER32.@)
1785 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1787 WND * wndPtr;
1788 BOOL retvalue;
1790 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1791 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1792 WIN_ReleaseWndPtr(wndPtr);
1793 return retvalue;
1797 /**********************************************************************
1798 * GetWindowWord (USER32.@)
1800 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1802 if (offset >= 0)
1804 WORD retvalue = 0;
1805 WND *wndPtr = WIN_GetPtr( hwnd );
1806 if (!wndPtr)
1808 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1809 return 0;
1811 if (wndPtr == WND_OTHER_PROCESS)
1813 SERVER_START_REQ( set_window_info )
1815 req->handle = hwnd;
1816 req->flags = 0; /* don't set anything, just retrieve */
1817 req->extra_offset = offset;
1818 req->extra_size = sizeof(retvalue);
1819 if (!wine_server_call_err( req ))
1820 memcpy( &retvalue, &reply->old_extra_value, sizeof(retvalue) );
1822 SERVER_END_REQ;
1823 return retvalue;
1825 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1827 WARN("Invalid offset %d\n", offset );
1828 SetLastError( ERROR_INVALID_INDEX );
1830 else memcpy( &retvalue, (char *)wndPtr->wExtra + offset, sizeof(retvalue) );
1831 WIN_ReleasePtr( wndPtr );
1832 return retvalue;
1835 switch(offset)
1837 case GWL_HWNDPARENT:
1838 return GetWindowLongW( hwnd, offset );
1839 case GWL_ID:
1840 case GWL_HINSTANCE:
1842 LONG ret = GetWindowLongW( hwnd, offset );
1843 if (HIWORD(ret))
1844 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1845 return LOWORD(ret);
1847 default:
1848 WARN("Invalid offset %d\n", offset );
1849 return 0;
1854 /**********************************************************************
1855 * SetWindowWord (USER32.@)
1857 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1859 WORD retval = 0;
1860 WND * wndPtr;
1862 switch(offset)
1864 case GWL_ID:
1865 case GWL_HINSTANCE:
1866 case GWL_HWNDPARENT:
1867 return SetWindowLongW( hwnd, offset, (UINT)newval );
1868 default:
1869 if (offset < 0)
1871 WARN("Invalid offset %d\n", offset );
1872 SetLastError( ERROR_INVALID_INDEX );
1873 return 0;
1877 wndPtr = WIN_GetPtr( hwnd );
1878 if (wndPtr == WND_OTHER_PROCESS)
1880 if (IsWindow(hwnd))
1881 FIXME( "set %d <- %x not supported yet on other process window %p\n",
1882 offset, newval, hwnd );
1883 wndPtr = NULL;
1885 if (!wndPtr)
1887 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1888 return 0;
1891 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1893 WARN("Invalid offset %d\n", offset );
1894 WIN_ReleasePtr(wndPtr);
1895 SetLastError( ERROR_INVALID_INDEX );
1896 return 0;
1899 SERVER_START_REQ( set_window_info )
1901 req->handle = hwnd;
1902 req->flags = SET_WIN_EXTRA;
1903 req->extra_offset = offset;
1904 req->extra_size = sizeof(newval);
1905 memcpy( &req->extra_value, &newval, sizeof(newval) );
1906 if (!wine_server_call_err( req ))
1908 void *ptr = (char *)wndPtr->wExtra + offset;
1909 memcpy( &retval, ptr, sizeof(retval) );
1910 memcpy( ptr, &newval, sizeof(newval) );
1913 SERVER_END_REQ;
1914 WIN_ReleasePtr( wndPtr );
1915 return retval;
1919 /**********************************************************************
1920 * WIN_GetWindowLong
1922 * Helper function for GetWindowLong().
1924 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1926 LONG retvalue = 0;
1927 WND *wndPtr;
1929 if (offset == GWL_HWNDPARENT)
1931 HWND parent = GetAncestor( hwnd, GA_PARENT );
1932 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1933 return (LONG)parent;
1936 if (!(wndPtr = WIN_GetPtr( hwnd )))
1938 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1939 return 0;
1942 if (wndPtr == WND_OTHER_PROCESS)
1944 if (offset == GWL_WNDPROC)
1946 SetLastError( ERROR_ACCESS_DENIED );
1947 return 0;
1949 SERVER_START_REQ( set_window_info )
1951 req->handle = hwnd;
1952 req->flags = 0; /* don't set anything, just retrieve */
1953 req->extra_offset = (offset >= 0) ? offset : -1;
1954 req->extra_size = (offset >= 0) ? sizeof(retvalue) : 0;
1955 if (!wine_server_call_err( req ))
1957 switch(offset)
1959 case GWL_STYLE: retvalue = reply->old_style; break;
1960 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1961 case GWL_ID: retvalue = reply->old_id; break;
1962 case GWL_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1963 case GWL_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
1964 default:
1965 if (offset >= 0) retvalue = reply->old_extra_value;
1966 else SetLastError( ERROR_INVALID_INDEX );
1967 break;
1971 SERVER_END_REQ;
1972 return retvalue;
1975 /* now we have a valid wndPtr */
1977 if (offset >= 0)
1979 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
1982 * Some programs try to access last element from 16 bit
1983 * code using illegal offset value. Hopefully this is
1984 * what those programs really expect.
1986 if (type == WIN_PROC_16 &&
1987 wndPtr->cbWndExtra >= 4 &&
1988 offset == wndPtr->cbWndExtra - sizeof(WORD))
1990 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
1992 ERR( "- replaced invalid offset %d with %d\n",
1993 offset, offset2 );
1995 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset2);
1996 WIN_ReleasePtr( wndPtr );
1997 return retvalue;
1999 WARN("Invalid offset %d\n", offset );
2000 WIN_ReleasePtr( wndPtr );
2001 SetLastError( ERROR_INVALID_INDEX );
2002 return 0;
2004 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
2005 /* Special case for dialog window procedure */
2006 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2007 retvalue = (LONG)WINPROC_GetProc( (WNDPROC)retvalue, type );
2008 WIN_ReleasePtr( wndPtr );
2009 return retvalue;
2012 switch(offset)
2014 case GWL_USERDATA: retvalue = wndPtr->userdata; break;
2015 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
2016 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
2017 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu; break;
2018 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc, type ); break;
2019 case GWL_HINSTANCE: retvalue = (LONG)wndPtr->hInstance; break;
2020 default:
2021 WARN("Unknown offset %d\n", offset );
2022 SetLastError( ERROR_INVALID_INDEX );
2023 break;
2025 WIN_ReleasePtr(wndPtr);
2026 return retvalue;
2030 /**********************************************************************
2031 * WIN_SetWindowLong
2033 * Helper function for SetWindowLong().
2035 * 0 is the failure code. However, in the case of failure SetLastError
2036 * must be set to distinguish between a 0 return value and a failure.
2038 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
2039 WINDOWPROCTYPE type )
2041 STYLESTRUCT style;
2042 BOOL ok;
2043 LONG retval = 0;
2044 WND *wndPtr;
2046 TRACE( "%p %d %lx %x\n", hwnd, offset, newval, type );
2048 if (is_broadcast(hwnd))
2050 SetLastError( ERROR_INVALID_PARAMETER );
2051 return FALSE;
2053 if (!WIN_IsCurrentProcess( hwnd ))
2055 if (offset == GWL_WNDPROC)
2057 SetLastError( ERROR_ACCESS_DENIED );
2058 return 0;
2060 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
2063 wndPtr = WIN_GetPtr( hwnd );
2064 if (wndPtr->hwndSelf == GetDesktopWindow())
2066 /* can't change anything on the desktop window */
2067 WIN_ReleasePtr( wndPtr );
2068 SetLastError( ERROR_ACCESS_DENIED );
2069 return 0;
2072 /* first some special cases */
2073 switch( offset )
2075 case GWL_STYLE:
2076 case GWL_EXSTYLE:
2077 style.styleOld =
2078 offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
2079 style.styleNew = newval;
2080 WIN_ReleasePtr( wndPtr );
2081 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
2082 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
2083 newval = style.styleNew;
2084 break;
2085 case GWL_HWNDPARENT:
2086 if (wndPtr->parent == GetDesktopWindow())
2088 WIN_ReleasePtr( wndPtr );
2089 return (LONG)WIN_SetOwner( hwnd, (HWND)newval );
2091 else
2093 WIN_ReleasePtr( wndPtr );
2094 return (LONG)SetParent( hwnd, (HWND)newval );
2096 case GWL_WNDPROC:
2097 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2098 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC)newval, type, WIN_PROC_WINDOW );
2099 WIN_ReleasePtr( wndPtr );
2100 return retval;
2101 case GWL_ID:
2102 case GWL_HINSTANCE:
2103 case GWL_USERDATA:
2104 break;
2105 case DWL_DLGPROC:
2106 if ((wndPtr->cbWndExtra + sizeof(LONG) >= DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2108 WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWL_DLGPROC);
2109 retval = (LONG)WINPROC_GetProc( *ptr, type );
2110 WINPROC_SetProc( ptr, (WNDPROC)newval, type, WIN_PROC_WINDOW );
2111 WIN_ReleasePtr( wndPtr );
2112 return retval;
2114 /* fall through */
2115 default:
2116 if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
2118 WARN("Invalid offset %d\n", offset );
2119 WIN_ReleasePtr( wndPtr );
2120 SetLastError( ERROR_INVALID_INDEX );
2121 return 0;
2123 else
2125 LONG *ptr = (LONG *)((char *)wndPtr->wExtra + offset);
2126 if (*ptr == newval) /* already set to the same value */
2128 WIN_ReleasePtr( wndPtr );
2129 return newval;
2132 break;
2135 SERVER_START_REQ( set_window_info )
2137 req->handle = hwnd;
2138 req->extra_offset = -1;
2139 switch(offset)
2141 case GWL_STYLE:
2142 req->flags = SET_WIN_STYLE;
2143 req->style = newval;
2144 break;
2145 case GWL_EXSTYLE:
2146 req->flags = SET_WIN_EXSTYLE;
2147 req->ex_style = newval;
2148 break;
2149 case GWL_ID:
2150 req->flags = SET_WIN_ID;
2151 req->id = newval;
2152 break;
2153 case GWL_HINSTANCE:
2154 req->flags = SET_WIN_INSTANCE;
2155 req->instance = (void *)newval;
2156 break;
2157 case GWL_USERDATA:
2158 req->flags = SET_WIN_USERDATA;
2159 req->user_data = (void *)newval;
2160 break;
2161 default:
2162 req->flags = SET_WIN_EXTRA;
2163 req->extra_offset = offset;
2164 req->extra_size = sizeof(newval);
2165 memcpy( &req->extra_value, &newval, sizeof(newval) );
2167 if ((ok = !wine_server_call_err( req )))
2169 switch(offset)
2171 case GWL_STYLE:
2172 wndPtr->dwStyle = newval;
2173 retval = reply->old_style;
2174 break;
2175 case GWL_EXSTYLE:
2176 wndPtr->dwExStyle = newval;
2177 retval = reply->old_ex_style;
2178 break;
2179 case GWL_ID:
2180 wndPtr->wIDmenu = newval;
2181 retval = reply->old_id;
2182 break;
2183 case GWL_HINSTANCE:
2184 wndPtr->hInstance = (HINSTANCE)newval;
2185 retval = (ULONG_PTR)reply->old_instance;
2186 break;
2187 case GWL_USERDATA:
2188 wndPtr->userdata = newval;
2189 retval = (ULONG_PTR)reply->old_user_data;
2190 break;
2191 default:
2193 void *ptr = (char *)wndPtr->wExtra + offset;
2194 memcpy( &retval, ptr, sizeof(retval) );
2195 memcpy( ptr, &newval, sizeof(newval) );
2197 break;
2201 SERVER_END_REQ;
2202 WIN_ReleasePtr( wndPtr );
2204 if (!ok) return 0;
2206 if (offset == GWL_STYLE && USER_Driver.pSetWindowStyle)
2207 USER_Driver.pSetWindowStyle( hwnd, retval );
2209 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2210 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2212 return retval;
2216 /**********************************************************************
2217 * GetWindowLong (USER.135)
2219 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2221 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
2225 /**********************************************************************
2226 * GetWindowLongA (USER32.@)
2228 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2230 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2234 /**********************************************************************
2235 * GetWindowLongW (USER32.@)
2237 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2239 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2243 /**********************************************************************
2244 * SetWindowLong (USER.136)
2246 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2248 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
2252 /**********************************************************************
2253 * SetWindowLongA (USER32.@)
2255 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2257 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2261 /**********************************************************************
2262 * SetWindowLongW (USER32.@) Set window attribute
2264 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2265 * value in a window's extra memory.
2267 * The _hwnd_ parameter specifies the window. is the handle to a
2268 * window that has extra memory. The _newval_ parameter contains the
2269 * new attribute or extra memory value. If positive, the _offset_
2270 * parameter is the byte-addressed location in the window's extra
2271 * memory to set. If negative, _offset_ specifies the window
2272 * attribute to set, and should be one of the following values:
2274 * GWL_EXSTYLE The window's extended window style
2276 * GWL_STYLE The window's window style.
2278 * GWL_WNDPROC Pointer to the window's window procedure.
2280 * GWL_HINSTANCE The window's pplication instance handle.
2282 * GWL_ID The window's identifier.
2284 * GWL_USERDATA The window's user-specified data.
2286 * If the window is a dialog box, the _offset_ parameter can be one of
2287 * the following values:
2289 * DWL_DLGPROC The address of the window's dialog box procedure.
2291 * DWL_MSGRESULT The return value of a message
2292 * that the dialog box procedure processed.
2294 * DWL_USER Application specific information.
2296 * RETURNS
2298 * If successful, returns the previous value located at _offset_. Otherwise,
2299 * returns 0.
2301 * NOTES
2303 * Extra memory for a window class is specified by a nonzero cbWndExtra
2304 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2305 * time of class creation.
2307 * Using GWL_WNDPROC to set a new window procedure effectively creates
2308 * a window subclass. Use CallWindowProc() in the new windows procedure
2309 * to pass messages to the superclass's window procedure.
2311 * The user data is reserved for use by the application which created
2312 * the window.
2314 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2315 * instead, call the EnableWindow() function to change the window's
2316 * disabled state.
2318 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2319 * SetParent() instead.
2321 * Win95:
2322 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2323 * it sends WM_STYLECHANGING before changing the settings
2324 * and WM_STYLECHANGED afterwards.
2325 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2327 LONG WINAPI SetWindowLongW(
2328 HWND hwnd, /* [in] window to alter */
2329 INT offset, /* [in] offset, in bytes, of location to alter */
2330 LONG newval /* [in] new value of location */
2332 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2336 /*******************************************************************
2337 * GetWindowTextA (USER32.@)
2339 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2341 WCHAR *buffer;
2343 if (WIN_IsCurrentProcess( hwnd ))
2344 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2346 /* when window belongs to other process, don't send a message */
2347 if (nMaxCount <= 0) return 0;
2348 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2349 get_server_window_text( hwnd, buffer, nMaxCount );
2350 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2351 lpString[nMaxCount-1] = 0;
2352 HeapFree( GetProcessHeap(), 0, buffer );
2353 return strlen(lpString);
2357 /*******************************************************************
2358 * InternalGetWindowText (USER32.@)
2360 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2362 WND *win;
2364 if (nMaxCount <= 0) return 0;
2365 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2366 if (win != WND_OTHER_PROCESS)
2368 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2369 else lpString[0] = 0;
2370 WIN_ReleasePtr( win );
2372 else
2374 get_server_window_text( hwnd, lpString, nMaxCount );
2376 return strlenW(lpString);
2380 /*******************************************************************
2381 * GetWindowTextW (USER32.@)
2383 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2385 if (WIN_IsCurrentProcess( hwnd ))
2386 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2388 /* when window belongs to other process, don't send a message */
2389 if (nMaxCount <= 0) return 0;
2390 get_server_window_text( hwnd, lpString, nMaxCount );
2391 return strlenW(lpString);
2395 /*******************************************************************
2396 * SetWindowText (USER32.@)
2397 * SetWindowTextA (USER32.@)
2399 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2401 if (is_broadcast(hwnd))
2403 SetLastError( ERROR_INVALID_PARAMETER );
2404 return FALSE;
2406 if (!WIN_IsCurrentProcess( hwnd ))
2408 FIXME( "cannot set text %s of other process window %p\n", debugstr_a(lpString), hwnd );
2409 SetLastError( ERROR_ACCESS_DENIED );
2410 return FALSE;
2412 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2416 /*******************************************************************
2417 * SetWindowTextW (USER32.@)
2419 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2421 if (is_broadcast(hwnd))
2423 SetLastError( ERROR_INVALID_PARAMETER );
2424 return FALSE;
2426 if (!WIN_IsCurrentProcess( hwnd ))
2428 FIXME( "cannot set text %s of other process window %p\n", debugstr_w(lpString), hwnd );
2429 SetLastError( ERROR_ACCESS_DENIED );
2430 return FALSE;
2432 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2436 /*******************************************************************
2437 * GetWindowTextLengthA (USER32.@)
2439 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2441 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2444 /*******************************************************************
2445 * GetWindowTextLengthW (USER32.@)
2447 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2449 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2453 /*******************************************************************
2454 * IsWindow (USER32.@)
2456 BOOL WINAPI IsWindow( HWND hwnd )
2458 WND *ptr;
2459 BOOL ret;
2461 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2463 if (ptr != WND_OTHER_PROCESS)
2465 WIN_ReleasePtr( ptr );
2466 return TRUE;
2469 /* check other processes */
2470 SERVER_START_REQ( get_window_info )
2472 req->handle = hwnd;
2473 ret = !wine_server_call_err( req );
2475 SERVER_END_REQ;
2476 return ret;
2480 /***********************************************************************
2481 * GetWindowThreadProcessId (USER32.@)
2483 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2485 WND *ptr;
2486 DWORD tid = 0;
2488 if (!(ptr = WIN_GetPtr( hwnd )))
2490 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2491 return 0;
2494 if (ptr != WND_OTHER_PROCESS)
2496 /* got a valid window */
2497 tid = ptr->tid;
2498 if (process) *process = GetCurrentProcessId();
2499 WIN_ReleasePtr( ptr );
2500 return tid;
2503 /* check other processes */
2504 SERVER_START_REQ( get_window_info )
2506 req->handle = hwnd;
2507 if (!wine_server_call_err( req ))
2509 tid = (DWORD)reply->tid;
2510 if (process) *process = (DWORD)reply->pid;
2513 SERVER_END_REQ;
2514 return tid;
2518 /*****************************************************************
2519 * GetParent (USER32.@)
2521 HWND WINAPI GetParent( HWND hwnd )
2523 WND *wndPtr;
2524 HWND retvalue = 0;
2526 if (!(wndPtr = WIN_GetPtr( hwnd )))
2528 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2529 return 0;
2531 if (wndPtr == WND_OTHER_PROCESS)
2533 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2534 if (style & (WS_POPUP | WS_CHILD))
2536 SERVER_START_REQ( get_window_tree )
2538 req->handle = hwnd;
2539 if (!wine_server_call_err( req ))
2541 if (style & WS_POPUP) retvalue = reply->owner;
2542 else if (style & WS_CHILD) retvalue = reply->parent;
2545 SERVER_END_REQ;
2548 else
2550 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2551 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2552 WIN_ReleasePtr( wndPtr );
2554 return retvalue;
2558 /*****************************************************************
2559 * GetAncestor (USER32.@)
2561 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2563 WND *win;
2564 HWND *list, ret = 0;
2566 switch(type)
2568 case GA_PARENT:
2569 if (!(win = WIN_GetPtr( hwnd )))
2571 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2572 return 0;
2574 if (win != WND_OTHER_PROCESS)
2576 ret = win->parent;
2577 WIN_ReleasePtr( win );
2579 else /* need to query the server */
2581 SERVER_START_REQ( get_window_tree )
2583 req->handle = hwnd;
2584 if (!wine_server_call_err( req )) ret = reply->parent;
2586 SERVER_END_REQ;
2588 break;
2590 case GA_ROOT:
2591 if (!(list = WIN_ListParents( hwnd ))) return 0;
2593 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2594 else
2596 int count = 2;
2597 while (list[count]) count++;
2598 ret = list[count - 2]; /* get the one before the desktop */
2600 HeapFree( GetProcessHeap(), 0, list );
2601 break;
2603 case GA_ROOTOWNER:
2604 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2605 for (;;)
2607 HWND parent = GetParent( ret );
2608 if (!parent) break;
2609 ret = parent;
2611 break;
2613 return ret;
2617 /*****************************************************************
2618 * SetParent (USER32.@)
2620 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2622 WND *wndPtr;
2623 HWND retvalue, full_handle;
2624 BOOL was_visible;
2626 if (is_broadcast(hwnd) || is_broadcast(parent))
2628 SetLastError(ERROR_INVALID_PARAMETER);
2629 return 0;
2632 if (!parent) parent = GetDesktopWindow();
2633 else parent = WIN_GetFullHandle( parent );
2635 if (!IsWindow( parent ))
2637 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2638 return 0;
2641 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2642 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2644 hwnd = full_handle;
2646 if (USER_Driver.pSetParent)
2647 return USER_Driver.pSetParent( hwnd, parent );
2649 /* Windows hides the window first, then shows it again
2650 * including the WM_SHOWWINDOW messages and all */
2651 was_visible = ShowWindow( hwnd, SW_HIDE );
2653 if (!IsWindow( parent )) return 0;
2654 if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return 0;
2656 retvalue = wndPtr->parent; /* old parent */
2657 if (parent != retvalue)
2659 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2661 if (parent != GetDesktopWindow()) /* a child window */
2663 if (!(wndPtr->dwStyle & WS_CHILD))
2665 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
2666 if (menu) DestroyMenu( menu );
2670 WIN_ReleasePtr( wndPtr );
2672 /* SetParent additionally needs to make hwnd the topmost window
2673 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2674 WM_WINDOWPOSCHANGED notification messages.
2676 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2677 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2678 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2679 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2680 return retvalue;
2684 /*******************************************************************
2685 * IsChild (USER32.@)
2687 BOOL WINAPI IsChild( HWND parent, HWND child )
2689 HWND *list = WIN_ListParents( child );
2690 int i;
2691 BOOL ret;
2693 if (!list) return FALSE;
2694 parent = WIN_GetFullHandle( parent );
2695 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2696 ret = (list[i] != 0);
2697 HeapFree( GetProcessHeap(), 0, list );
2698 return ret;
2702 /***********************************************************************
2703 * IsWindowVisible (USER32.@)
2705 BOOL WINAPI IsWindowVisible( HWND hwnd )
2707 HWND *list;
2708 BOOL retval;
2709 int i;
2711 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2712 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2713 for (i = 0; list[i]; i++)
2714 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2715 retval = !list[i];
2716 HeapFree( GetProcessHeap(), 0, list );
2717 return retval;
2721 /***********************************************************************
2722 * WIN_IsWindowDrawable
2724 * hwnd is drawable when it is visible, all parents are not
2725 * minimized, and it is itself not minimized unless we are
2726 * trying to draw its default class icon.
2728 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2730 HWND *list;
2731 BOOL retval;
2732 int i;
2733 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2735 if (!(style & WS_VISIBLE)) return FALSE;
2736 if ((style & WS_MINIMIZE) && icon && GetClassLongA( hwnd, GCL_HICON )) return FALSE;
2738 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2739 for (i = 0; list[i]; i++)
2740 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2741 break;
2742 retval = !list[i];
2743 HeapFree( GetProcessHeap(), 0, list );
2744 return retval;
2748 /*******************************************************************
2749 * GetTopWindow (USER32.@)
2751 HWND WINAPI GetTopWindow( HWND hwnd )
2753 if (!hwnd) hwnd = GetDesktopWindow();
2754 return GetWindow( hwnd, GW_CHILD );
2758 /*******************************************************************
2759 * GetWindow (USER32.@)
2761 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2763 HWND retval = 0;
2765 if (rel == GW_OWNER) /* this one may be available locally */
2767 WND *wndPtr = WIN_GetPtr( hwnd );
2768 if (!wndPtr)
2770 SetLastError( ERROR_INVALID_HANDLE );
2771 return 0;
2773 if (wndPtr != WND_OTHER_PROCESS)
2775 retval = wndPtr->owner;
2776 WIN_ReleasePtr( wndPtr );
2777 return retval;
2779 /* else fall through to server call */
2782 SERVER_START_REQ( get_window_tree )
2784 req->handle = hwnd;
2785 if (!wine_server_call_err( req ))
2787 switch(rel)
2789 case GW_HWNDFIRST:
2790 retval = reply->first_sibling;
2791 break;
2792 case GW_HWNDLAST:
2793 retval = reply->last_sibling;
2794 break;
2795 case GW_HWNDNEXT:
2796 retval = reply->next_sibling;
2797 break;
2798 case GW_HWNDPREV:
2799 retval = reply->prev_sibling;
2800 break;
2801 case GW_OWNER:
2802 retval = reply->owner;
2803 break;
2804 case GW_CHILD:
2805 retval = reply->first_child;
2806 break;
2810 SERVER_END_REQ;
2811 return retval;
2815 /***********************************************************************
2816 * WIN_InternalShowOwnedPopups
2818 * Internal version of ShowOwnedPopups; Wine functions should use this
2819 * to avoid interfering with application calls to ShowOwnedPopups
2820 * and to make sure the application can't prevent showing/hiding.
2822 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2826 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2828 int count = 0;
2829 WND *pWnd;
2830 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2832 if (!win_array) return TRUE;
2835 * Show windows Lowest first, Highest last to preserve Z-Order
2837 while (win_array[count]) count++;
2838 while (--count >= 0)
2840 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2841 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2843 if (pWnd->dwStyle & WS_POPUP)
2845 if (fShow)
2847 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2848 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
2851 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2853 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2854 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2857 else
2859 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2860 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2861 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2864 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2866 ShowWindow(pWnd->hwndSelf,SW_HIDE);
2867 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2868 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
2872 WIN_ReleaseWndPtr( pWnd );
2874 HeapFree( GetProcessHeap(), 0, win_array );
2876 return TRUE;
2879 /*******************************************************************
2880 * ShowOwnedPopups (USER32.@)
2882 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2884 int count = 0;
2885 WND *pWnd;
2886 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2888 if (!win_array) return TRUE;
2890 while (win_array[count]) count++;
2891 while (--count >= 0)
2893 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2894 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2896 if (pWnd->dwStyle & WS_POPUP)
2898 if (fShow)
2900 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2902 /* In Windows, ShowOwnedPopups(TRUE) generates
2903 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2904 * regardless of the state of the owner
2906 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2907 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2910 else
2912 if (IsWindowVisible(pWnd->hwndSelf))
2914 /* In Windows, ShowOwnedPopups(FALSE) generates
2915 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2916 * regardless of the state of the owner
2918 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2919 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2923 WIN_ReleaseWndPtr( pWnd );
2925 HeapFree( GetProcessHeap(), 0, win_array );
2926 return TRUE;
2930 /*******************************************************************
2931 * GetLastActivePopup (USER32.@)
2933 HWND WINAPI GetLastActivePopup( HWND hwnd )
2935 HWND retval = hwnd;
2937 SERVER_START_REQ( get_window_info )
2939 req->handle = hwnd;
2940 if (!wine_server_call_err( req )) retval = reply->last_active;
2942 SERVER_END_REQ;
2943 return retval;
2947 /*******************************************************************
2948 * WIN_ListParents
2950 * Build an array of all parents of a given window, starting with
2951 * the immediate parent. The array must be freed with HeapFree.
2952 * Returns NULL if window is a top-level window.
2954 HWND *WIN_ListParents( HWND hwnd )
2956 WND *win;
2957 HWND current, *list;
2958 int pos = 0, size = 16, count = 0;
2960 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2962 current = hwnd;
2963 for (;;)
2965 if (!(win = WIN_GetPtr( current ))) goto empty;
2966 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
2967 list[pos] = win->parent;
2968 WIN_ReleasePtr( win );
2969 if (!(current = list[pos]))
2971 if (!pos) goto empty;
2972 return list;
2974 if (++pos == size - 1)
2976 /* need to grow the list */
2977 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
2978 if (!new_list) goto empty;
2979 list = new_list;
2980 size += 16;
2984 /* at least one parent belongs to another process, have to query the server */
2986 for (;;)
2988 count = 0;
2989 SERVER_START_REQ( get_window_parents )
2991 req->handle = hwnd;
2992 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
2993 if (!wine_server_call( req )) count = reply->count;
2995 SERVER_END_REQ;
2996 if (!count) goto empty;
2997 if (size > count)
2999 list[count] = 0;
3000 return list;
3002 HeapFree( GetProcessHeap(), 0, list );
3003 size = count + 1;
3004 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
3007 empty:
3008 HeapFree( GetProcessHeap(), 0, list );
3009 return NULL;
3013 /*******************************************************************
3014 * WIN_ListChildren
3016 * Build an array of the children of a given window. The array must be
3017 * freed with HeapFree. Returns NULL when no windows are found.
3019 HWND *WIN_ListChildren( HWND hwnd )
3021 return list_window_children( hwnd, 0, 0 );
3025 /*******************************************************************
3026 * EnumWindows (USER32.@)
3028 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
3030 HWND *list;
3031 BOOL ret = TRUE;
3032 int i, iWndsLocks;
3034 /* We have to build a list of all windows first, to avoid */
3035 /* unpleasant side-effects, for instance if the callback */
3036 /* function changes the Z-order of the windows. */
3038 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
3040 /* Now call the callback function for every window */
3042 iWndsLocks = WIN_SuspendWndsLock();
3043 for (i = 0; list[i]; i++)
3045 /* Make sure that the window still exists */
3046 if (!IsWindow( list[i] )) continue;
3047 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
3049 WIN_RestoreWndsLock(iWndsLocks);
3050 HeapFree( GetProcessHeap(), 0, list );
3051 return ret;
3055 /**********************************************************************
3056 * EnumThreadWindows (USER32.@)
3058 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
3060 HWND *list;
3061 int i, iWndsLocks;
3063 if (!(list = list_window_children( GetDesktopWindow(), 0, id ))) return TRUE;
3065 /* Now call the callback function for every window */
3067 iWndsLocks = WIN_SuspendWndsLock();
3068 for (i = 0; list[i]; i++)
3069 if (!func( list[i], lParam )) break;
3070 WIN_RestoreWndsLock(iWndsLocks);
3071 HeapFree( GetProcessHeap(), 0, list );
3072 return TRUE;
3076 /**********************************************************************
3077 * WIN_EnumChildWindows
3079 * Helper function for EnumChildWindows().
3081 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
3083 HWND *childList;
3084 BOOL ret = FALSE;
3086 for ( ; *list; list++)
3088 /* Make sure that the window still exists */
3089 if (!IsWindow( *list )) continue;
3090 /* skip owned windows */
3091 if (GetWindow( *list, GW_OWNER )) continue;
3092 /* Build children list first */
3093 childList = WIN_ListChildren( *list );
3095 ret = func( *list, lParam );
3097 if (childList)
3099 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
3100 HeapFree( GetProcessHeap(), 0, childList );
3102 if (!ret) return FALSE;
3104 return TRUE;
3108 /**********************************************************************
3109 * EnumChildWindows (USER32.@)
3111 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
3113 HWND *list;
3114 int iWndsLocks;
3116 if (!(list = WIN_ListChildren( parent ))) return FALSE;
3117 iWndsLocks = WIN_SuspendWndsLock();
3118 WIN_EnumChildWindows( list, func, lParam );
3119 WIN_RestoreWndsLock(iWndsLocks);
3120 HeapFree( GetProcessHeap(), 0, list );
3121 return TRUE;
3125 /*******************************************************************
3126 * AnyPopup (USER.52)
3128 BOOL16 WINAPI AnyPopup16(void)
3130 return AnyPopup();
3134 /*******************************************************************
3135 * AnyPopup (USER32.@)
3137 BOOL WINAPI AnyPopup(void)
3139 int i;
3140 BOOL retvalue;
3141 HWND *list = WIN_ListChildren( GetDesktopWindow() );
3143 if (!list) return FALSE;
3144 for (i = 0; list[i]; i++)
3146 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
3148 retvalue = (list[i] != 0);
3149 HeapFree( GetProcessHeap(), 0, list );
3150 return retvalue;
3154 /*******************************************************************
3155 * FlashWindow (USER32.@)
3157 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3159 WND *wndPtr = WIN_FindWndPtr(hWnd);
3161 TRACE("%p\n", hWnd);
3163 if (!wndPtr) return FALSE;
3164 hWnd = wndPtr->hwndSelf; /* make it a full handle */
3166 if (wndPtr->dwStyle & WS_MINIMIZE)
3168 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3170 HDC hDC = GetDC(hWnd);
3172 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM)hDC, 0 ))
3173 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
3175 ReleaseDC( hWnd, hDC );
3176 wndPtr->flags |= WIN_NCACTIVATED;
3178 else
3180 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3181 wndPtr->flags &= ~WIN_NCACTIVATED;
3183 WIN_ReleaseWndPtr(wndPtr);
3184 return TRUE;
3186 else
3188 WPARAM16 wparam;
3189 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3190 else wparam = (hWnd == GetForegroundWindow());
3192 WIN_ReleaseWndPtr(wndPtr);
3193 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3194 return wparam;
3198 /*******************************************************************
3199 * FlashWindowEx (USER32.@)
3201 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
3203 FIXME("%p\n", pfwi);
3204 return TRUE;
3207 /*******************************************************************
3208 * GetWindowContextHelpId (USER32.@)
3210 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3212 DWORD retval;
3213 WND *wnd = WIN_FindWndPtr( hwnd );
3214 if (!wnd) return 0;
3215 retval = wnd->helpContext;
3216 WIN_ReleaseWndPtr(wnd);
3217 return retval;
3221 /*******************************************************************
3222 * SetWindowContextHelpId (USER32.@)
3224 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3226 WND *wnd = WIN_FindWndPtr( hwnd );
3227 if (!wnd) return FALSE;
3228 wnd->helpContext = id;
3229 WIN_ReleaseWndPtr(wnd);
3230 return TRUE;
3234 /*******************************************************************
3235 * DragDetect (USER32.@)
3237 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3239 MSG msg;
3240 RECT rect;
3242 rect.left = pt.x - wDragWidth;
3243 rect.right = pt.x + wDragWidth;
3245 rect.top = pt.y - wDragHeight;
3246 rect.bottom = pt.y + wDragHeight;
3248 SetCapture(hWnd);
3250 while(1)
3252 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3254 if( msg.message == WM_LBUTTONUP )
3256 ReleaseCapture();
3257 return 0;
3259 if( msg.message == WM_MOUSEMOVE )
3261 POINT tmp;
3262 tmp.x = LOWORD(msg.lParam);
3263 tmp.y = HIWORD(msg.lParam);
3264 if( !PtInRect( &rect, tmp ))
3266 ReleaseCapture();
3267 return 1;
3271 WaitMessage();
3273 return 0;
3276 /******************************************************************************
3277 * GetWindowModuleFileNameA (USER32.@)
3279 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3281 FIXME("GetWindowModuleFileNameA(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3282 hwnd, lpszFileName, cchFileNameMax);
3283 return 0;
3286 /******************************************************************************
3287 * GetWindowModuleFileNameW (USER32.@)
3289 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR lpszFileName, UINT cchFileNameMax)
3291 FIXME("GetWindowModuleFileNameW(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3292 hwnd, lpszFileName, cchFileNameMax);
3293 return 0;
3296 /******************************************************************************
3297 * GetWindowInfo (USER32.@)
3299 * Note: tests show that Windows doesn't check cbSize of the structure.
3301 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3303 if (!pwi) return FALSE;
3304 if (!IsWindow(hwnd)) return FALSE;
3306 GetWindowRect(hwnd, &pwi->rcWindow);
3307 GetClientRect(hwnd, &pwi->rcClient);
3308 /* translate to screen coordinates */
3309 MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3311 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3312 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3313 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3315 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3316 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3318 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3319 pwi->wCreatorVersion = 0x0400;
3321 return TRUE;