The meaning of the rewrap flag got inverted (MEPF_REWRAP instead of
[wine.git] / windows / win.c
blob30c8458aeb73f2de099c7ebb1e7b032a80f73826
1 /*
2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "config.h"
22 #include "wine/port.h"
24 #include <assert.h>
25 #include <stdarg.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include "windef.h"
29 #include "winbase.h"
30 #include "wine/winbase16.h"
31 #include "wine/winuser16.h"
32 #include "wownt32.h"
33 #include "wine/server.h"
34 #include "wine/unicode.h"
35 #include "win.h"
36 #include "user_private.h"
37 #include "dce.h"
38 #include "controls.h"
39 #include "cursoricon.h"
40 #include "message.h"
41 #include "winpos.h"
42 #include "winerror.h"
43 #include "wine/debug.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(win);
46 WINE_DECLARE_DEBUG_CHANNEL(msg);
48 #define NB_USER_HANDLES ((LAST_USER_HANDLE - FIRST_USER_HANDLE + 1) >> 1)
49 #define USER_HANDLE_TO_INDEX(hwnd) ((LOWORD(hwnd) - FIRST_USER_HANDLE) >> 1)
51 /**********************************************************************/
53 /* Desktop window */
54 static WND *pWndDesktop = NULL;
56 static WORD wDragWidth = 4;
57 static WORD wDragHeight= 3;
59 static void *user_handles[NB_USER_HANDLES];
61 /***********************************************************************
62 * create_window_handle
64 * Create a window handle with the server.
66 static WND *create_window_handle( HWND parent, HWND owner, ATOM atom,
67 HINSTANCE instance, WINDOWPROCTYPE type )
69 WORD index;
70 WND *win;
71 struct tagCLASS *class = NULL;
72 user_handle_t handle = 0;
73 int extra_bytes = 0;
75 /* if 16-bit instance, map to module handle */
76 if (instance && !HIWORD(instance))
77 instance = HINSTANCE_32(GetExePtr(HINSTANCE_16(instance)));
79 SERVER_START_REQ( create_window )
81 req->parent = parent;
82 req->owner = owner;
83 req->atom = atom;
84 req->instance = instance;
85 if (!wine_server_call_err( req ))
87 handle = reply->handle;
88 extra_bytes = reply->extra;
89 class = reply->class_ptr;
92 SERVER_END_REQ;
94 if (!handle)
96 WARN( "error %ld creating window\n", GetLastError() );
97 return NULL;
100 if (!(win = HeapAlloc( GetProcessHeap(), 0, sizeof(WND) + extra_bytes - sizeof(win->wExtra) )))
102 SERVER_START_REQ( destroy_window )
104 req->handle = handle;
105 wine_server_call( req );
107 SERVER_END_REQ;
108 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
109 return NULL;
112 USER_Lock();
114 index = USER_HANDLE_TO_INDEX(handle);
115 assert( index < NB_USER_HANDLES );
116 user_handles[index] = win;
117 win->hwndSelf = handle;
118 win->dwMagic = WND_MAGIC;
119 win->irefCount = 1;
120 win->cbWndExtra = extra_bytes;
121 memset( win->wExtra, 0, extra_bytes );
122 CLASS_AddWindow( class, win, type );
123 return win;
127 /***********************************************************************
128 * free_window_handle
130 * Free a window handle.
132 static WND *free_window_handle( HWND hwnd )
134 WND *ptr;
135 WORD index = USER_HANDLE_TO_INDEX(hwnd);
137 if (index >= NB_USER_HANDLES) return NULL;
138 USER_Lock();
139 if ((ptr = user_handles[index]))
141 SERVER_START_REQ( destroy_window )
143 req->handle = hwnd;
144 if (!wine_server_call_err( req ))
145 user_handles[index] = NULL;
146 else
147 ptr = NULL;
149 SERVER_END_REQ;
151 USER_Unlock();
152 HeapFree( GetProcessHeap(), 0, ptr );
153 return ptr;
157 /*******************************************************************
158 * list_window_children
160 * Build an array of the children of a given window. The array must be
161 * freed with HeapFree. Returns NULL when no windows are found.
163 static HWND *list_window_children( HWND hwnd, ATOM atom, DWORD tid )
165 HWND *list;
166 int size = 32;
168 for (;;)
170 int count = 0;
172 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
174 SERVER_START_REQ( get_window_children )
176 req->parent = hwnd;
177 req->atom = atom;
178 req->tid = tid;
179 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
180 if (!wine_server_call( req )) count = reply->count;
182 SERVER_END_REQ;
183 if (count && count < size)
185 list[count] = 0;
186 return list;
188 HeapFree( GetProcessHeap(), 0, list );
189 if (!count) break;
190 size = count + 1; /* restart with a large enough buffer */
192 return NULL;
196 /*******************************************************************
197 * list_window_parents
199 * Build an array of all parents of a given window, starting with
200 * the immediate parent. The array must be freed with HeapFree.
201 * Returns NULL if window is a top-level window.
203 static HWND *list_window_parents( HWND hwnd )
205 WND *win;
206 HWND current, *list;
207 int pos = 0, size = 16, count = 0;
209 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
211 current = hwnd;
212 for (;;)
214 if (!(win = WIN_GetPtr( current ))) goto empty;
215 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
216 list[pos] = win->parent;
217 WIN_ReleasePtr( win );
218 if (!(current = list[pos]))
220 if (!pos) goto empty;
221 return list;
223 if (++pos == size - 1)
225 /* need to grow the list */
226 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
227 if (!new_list) goto empty;
228 list = new_list;
229 size += 16;
233 /* at least one parent belongs to another process, have to query the server */
235 for (;;)
237 count = 0;
238 SERVER_START_REQ( get_window_parents )
240 req->handle = hwnd;
241 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
242 if (!wine_server_call( req )) count = reply->count;
244 SERVER_END_REQ;
245 if (!count) goto empty;
246 if (size > count)
248 list[count] = 0;
249 return list;
251 HeapFree( GetProcessHeap(), 0, list );
252 size = count + 1;
253 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
256 empty:
257 HeapFree( GetProcessHeap(), 0, list );
258 return NULL;
262 /*******************************************************************
263 * send_parent_notify
265 static void send_parent_notify( HWND hwnd, UINT msg )
267 if ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_CHILD | WS_POPUP)) == WS_CHILD &&
268 !(GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY))
269 SendMessageW( GetParent(hwnd), WM_PARENTNOTIFY,
270 MAKEWPARAM( msg, GetWindowLongPtrW( hwnd, GWLP_ID )), (LPARAM)hwnd );
274 /*******************************************************************
275 * get_server_window_text
277 * Retrieve the window text from the server.
279 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
281 size_t len = 0;
283 SERVER_START_REQ( get_window_text )
285 req->handle = hwnd;
286 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
287 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
289 SERVER_END_REQ;
290 text[len / sizeof(WCHAR)] = 0;
294 /***********************************************************************
295 * WIN_GetPtr
297 * Return a pointer to the WND structure if local to the process,
298 * or WND_OTHER_PROCESS if handle may be valid in other process.
299 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
301 WND *WIN_GetPtr( HWND hwnd )
303 WND * ptr;
304 WORD index = USER_HANDLE_TO_INDEX(hwnd);
306 if (index >= NB_USER_HANDLES) return NULL;
308 USER_Lock();
309 if ((ptr = user_handles[index]))
311 if (ptr->dwMagic == WND_MAGIC && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
312 return ptr;
313 ptr = NULL;
315 else ptr = WND_OTHER_PROCESS;
316 USER_Unlock();
317 return ptr;
321 /***********************************************************************
322 * WIN_IsCurrentProcess
324 * Check whether a given window belongs to the current process (and return the full handle).
326 HWND WIN_IsCurrentProcess( HWND hwnd )
328 WND *ptr;
329 HWND ret;
331 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS) return 0;
332 ret = ptr->hwndSelf;
333 WIN_ReleasePtr( ptr );
334 return ret;
338 /***********************************************************************
339 * WIN_IsCurrentThread
341 * Check whether a given window belongs to the current thread (and return the full handle).
343 HWND WIN_IsCurrentThread( HWND hwnd )
345 WND *ptr;
346 HWND ret = 0;
348 if ((ptr = WIN_GetPtr( hwnd )) && ptr != WND_OTHER_PROCESS)
350 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
351 WIN_ReleasePtr( ptr );
353 return ret;
357 /***********************************************************************
358 * WIN_Handle32
360 * Convert a 16-bit window handle to a full 32-bit handle.
362 HWND WIN_Handle32( HWND16 hwnd16 )
364 WND *ptr;
365 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
367 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
368 /* do sign extension for -2 and -3 */
369 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
371 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
373 if (ptr != WND_OTHER_PROCESS)
375 hwnd = ptr->hwndSelf;
376 WIN_ReleasePtr( ptr );
378 else /* may belong to another process */
380 SERVER_START_REQ( get_window_info )
382 req->handle = hwnd;
383 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
385 SERVER_END_REQ;
387 return hwnd;
391 /***********************************************************************
392 * WIN_FindWndPtr
394 * Return a pointer to the WND structure corresponding to a HWND.
396 WND * WIN_FindWndPtr( HWND hwnd )
398 WND * ptr;
400 if (!hwnd) return NULL;
402 if ((ptr = WIN_GetPtr( hwnd )))
404 if (ptr != WND_OTHER_PROCESS)
406 /* increment destruction monitoring */
407 ptr->irefCount++;
408 return ptr;
410 if (IsWindow( hwnd )) /* check other processes */
412 ERR( "window %p belongs to other process\n", hwnd );
413 /* DbgBreakPoint(); */
416 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
417 return NULL;
421 /***********************************************************************
422 * WIN_ReleaseWndPtr
424 * Release the pointer to the WND structure.
426 void WIN_ReleaseWndPtr(WND *wndPtr)
428 if(!wndPtr) return;
430 /* Decrement destruction monitoring value */
431 wndPtr->irefCount--;
432 /* Check if it's time to release the memory */
433 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
435 /* Release memory */
436 free_window_handle( wndPtr->hwndSelf );
438 else if(wndPtr->irefCount < 0)
440 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
441 ERR("forgot a Lock on %p somewhere\n",wndPtr);
443 /* unlock all WND structures for thread safeness */
444 USER_Unlock();
448 /***********************************************************************
449 * WIN_UnlinkWindow
451 * Remove a window from the siblings linked list.
453 void WIN_UnlinkWindow( HWND hwnd )
455 WIN_LinkWindow( hwnd, 0, 0 );
459 /***********************************************************************
460 * WIN_LinkWindow
462 * Insert a window into the siblings linked list.
463 * The window is inserted after the specified window, which can also
464 * be specified as HWND_TOP or HWND_BOTTOM.
465 * If parent is 0, window is unlinked from the tree.
467 void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
469 WND *wndPtr = WIN_GetPtr( hwnd );
471 if (!wndPtr) return;
472 if (wndPtr == WND_OTHER_PROCESS)
474 if (IsWindow(hwnd)) ERR(" cannot link other process window %p\n", hwnd );
475 return;
478 SERVER_START_REQ( link_window )
480 req->handle = hwnd;
481 req->parent = parent;
482 req->previous = hwndInsertAfter;
483 if (!wine_server_call( req ))
485 if (reply->full_parent) wndPtr->parent = reply->full_parent;
489 SERVER_END_REQ;
490 WIN_ReleasePtr( wndPtr );
494 /***********************************************************************
495 * WIN_SetOwner
497 * Change the owner of a window.
499 HWND WIN_SetOwner( HWND hwnd, HWND owner )
501 WND *win = WIN_GetPtr( hwnd );
502 HWND ret = 0;
504 if (!win) return 0;
505 if (win == WND_OTHER_PROCESS)
507 if (IsWindow(hwnd)) ERR( "cannot set owner %p on other process window %p\n", owner, hwnd );
508 return 0;
510 SERVER_START_REQ( set_window_owner )
512 req->handle = hwnd;
513 req->owner = owner;
514 if (!wine_server_call( req ))
516 win->owner = reply->full_owner;
517 ret = reply->prev_owner;
520 SERVER_END_REQ;
521 WIN_ReleasePtr( win );
522 return ret;
526 /***********************************************************************
527 * WIN_SetStyle
529 * Change the style of a window.
531 ULONG WIN_SetStyle( HWND hwnd, ULONG set_bits, ULONG clear_bits )
533 BOOL ok;
534 ULONG new_style, old_style = 0;
535 WND *win = WIN_GetPtr( hwnd );
537 if (!win) return 0;
538 if (win == WND_OTHER_PROCESS)
540 if (IsWindow(hwnd))
541 ERR( "cannot set style %lx/%lx on other process window %p\n",
542 set_bits, clear_bits, hwnd );
543 return 0;
545 new_style = (win->dwStyle | set_bits) & ~clear_bits;
546 if (new_style == win->dwStyle)
548 WIN_ReleasePtr( win );
549 return new_style;
551 SERVER_START_REQ( set_window_info )
553 req->handle = hwnd;
554 req->flags = SET_WIN_STYLE;
555 req->style = new_style;
556 req->extra_offset = -1;
557 if ((ok = !wine_server_call( req )))
559 old_style = reply->old_style;
560 win->dwStyle = new_style;
563 SERVER_END_REQ;
564 WIN_ReleasePtr( win );
565 if (ok && USER_Driver.pSetWindowStyle) USER_Driver.pSetWindowStyle( hwnd, old_style );
566 return old_style;
570 /***********************************************************************
571 * WIN_GetRectangles
573 * Get the window and client rectangles.
575 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
577 WND *win = WIN_GetPtr( hwnd );
578 BOOL ret = TRUE;
580 if (!win) return FALSE;
581 if (win == WND_OTHER_PROCESS)
583 SERVER_START_REQ( get_window_rectangles )
585 req->handle = hwnd;
586 if ((ret = !wine_server_call( req )))
588 if (rectWindow)
590 rectWindow->left = reply->window.left;
591 rectWindow->top = reply->window.top;
592 rectWindow->right = reply->window.right;
593 rectWindow->bottom = reply->window.bottom;
595 if (rectClient)
597 rectClient->left = reply->client.left;
598 rectClient->top = reply->client.top;
599 rectClient->right = reply->client.right;
600 rectClient->bottom = reply->client.bottom;
604 SERVER_END_REQ;
606 else
608 if (rectWindow) *rectWindow = win->rectWindow;
609 if (rectClient) *rectClient = win->rectClient;
610 WIN_ReleasePtr( win );
612 return ret;
616 /***********************************************************************
617 * WIN_ReleaseCapture
619 * Internal version of ReleaseCapture which doesn't send WM_CAPTURECHANGED
620 * message. Used at the window destruction time.
622 static void WIN_ReleaseCapture( void )
624 SERVER_START_REQ( set_capture_window )
626 req->handle = 0;
627 req->flags = 0;
628 wine_server_call_err( req );
630 SERVER_END_REQ;
633 /***********************************************************************
634 * WIN_DestroyWindow
636 * Destroy storage associated to a window. "Internals" p.358
638 LRESULT WIN_DestroyWindow( HWND hwnd )
640 WND *wndPtr;
641 HWND *list;
643 TRACE("%p\n", hwnd );
645 if (!(hwnd = WIN_IsCurrentThread( hwnd )))
647 ERR( "window doesn't belong to current thread\n" );
648 return 0;
651 /* free child windows */
652 if ((list = WIN_ListChildren( hwnd )))
654 int i;
655 for (i = 0; list[i]; i++)
657 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
658 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
660 HeapFree( GetProcessHeap(), 0, list );
664 * Clear the update region to make sure no WM_PAINT messages will be
665 * generated for this window while processing the WM_NCDESTROY.
667 RedrawWindow( hwnd, NULL, 0,
668 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
670 if (hwnd == GetCapture()) WIN_ReleaseCapture();
672 /* Unlink now so we won't bother with the children later on */
673 WIN_UnlinkWindow( hwnd );
676 * Send the WM_NCDESTROY to the window being destroyed.
678 SendMessageW( hwnd, WM_NCDESTROY, 0, 0 );
680 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
682 WINPOS_CheckInternalPos( hwnd );
684 /* free resources associated with the window */
686 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
688 if (!(wndPtr->dwStyle & WS_CHILD))
690 HMENU menu = (HMENU)SetWindowLongPtrW( hwnd, GWLP_ID, 0 );
691 if (menu) DestroyMenu( menu );
693 if (wndPtr->hSysMenu)
695 DestroyMenu( wndPtr->hSysMenu );
696 wndPtr->hSysMenu = 0;
698 DCE_FreeWindowDCE( hwnd ); /* Always do this to catch orphaned DCs */
699 if (USER_Driver.pDestroyWindow) USER_Driver.pDestroyWindow( hwnd );
700 wndPtr->class = NULL;
701 wndPtr->dwMagic = 0; /* Mark it as invalid */
702 WIN_ReleaseWndPtr( wndPtr );
703 return 0;
706 /***********************************************************************
707 * WIN_DestroyThreadWindows
709 * Destroy all children of 'wnd' owned by the current thread.
710 * Return TRUE if something was done.
712 void WIN_DestroyThreadWindows( HWND hwnd )
714 HWND *list;
715 int i;
717 if (!(list = WIN_ListChildren( hwnd ))) return;
718 for (i = 0; list[i]; i++)
720 if (WIN_IsCurrentThread( list[i] ))
721 DestroyWindow( list[i] );
722 else
723 WIN_DestroyThreadWindows( list[i] );
725 HeapFree( GetProcessHeap(), 0, list );
728 /***********************************************************************
729 * WIN_CreateDesktopWindow
731 * Create the desktop window.
733 BOOL WIN_CreateDesktopWindow(void)
735 HWND hwndDesktop;
736 CREATESTRUCTA cs;
738 TRACE("Creating desktop window\n");
740 if (!WINPOS_CreateInternalPosAtom()) return FALSE;
742 pWndDesktop = create_window_handle( 0, 0, LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W );
743 if (!pWndDesktop) return FALSE;
744 hwndDesktop = pWndDesktop->hwndSelf;
746 pWndDesktop->tid = 0; /* nobody owns the desktop */
747 pWndDesktop->parent = 0;
748 pWndDesktop->owner = 0;
749 pWndDesktop->text = NULL;
750 pWndDesktop->pVScroll = NULL;
751 pWndDesktop->pHScroll = NULL;
752 pWndDesktop->helpContext = 0;
753 pWndDesktop->flags = 0;
754 pWndDesktop->hSysMenu = 0;
756 cs.lpCreateParams = NULL;
757 cs.hInstance = 0;
758 cs.hMenu = 0;
759 cs.hwndParent = 0;
760 cs.x = 0;
761 cs.y = 0;
762 cs.cx = GetSystemMetrics( SM_CXSCREEN );
763 cs.cy = GetSystemMetrics( SM_CYSCREEN );
764 cs.style = pWndDesktop->dwStyle;
765 cs.dwExStyle = pWndDesktop->dwExStyle;
766 cs.lpszName = NULL;
767 cs.lpszClass = DESKTOP_CLASS_ATOM;
769 SERVER_START_REQ( set_window_info )
771 req->handle = hwndDesktop;
772 req->flags = 0; /* don't set anything, just retrieve */
773 req->extra_offset = -1;
774 wine_server_call( req );
775 pWndDesktop->dwStyle = reply->old_style;
776 pWndDesktop->dwExStyle = reply->old_ex_style;
777 pWndDesktop->hInstance = (HINSTANCE)reply->old_instance;
778 pWndDesktop->userdata = (ULONG_PTR)reply->old_user_data;
779 pWndDesktop->wIDmenu = reply->old_id;
781 SERVER_END_REQ;
783 if (!USER_Driver.pCreateWindow || !USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE ))
785 WIN_ReleaseWndPtr( pWndDesktop );
786 return FALSE;
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 POINT pos[2];
805 if (cs->dwExStyle & WS_EX_MDICHILD)
807 UINT id = 0;
809 MDI_CalcDefaultChildPos(cs->hwndParent, -1, pos, 0, &id);
810 if (!(cs->style & WS_POPUP)) cs->hMenu = (HMENU)id;
812 TRACE("MDI child id %04x\n", id);
815 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
816 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
818 if (cs->style & (WS_CHILD | WS_POPUP))
820 if (cs->dwExStyle & WS_EX_MDICHILD)
822 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
824 cs->x = pos[0].x;
825 cs->y = pos[0].y;
827 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16 || !cs->cx)
828 cs->cx = pos[1].x;
829 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16 || !cs->cy)
830 cs->cy = pos[1].y;
832 else
834 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
835 cs->x = cs->y = 0;
836 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
837 cs->cx = cs->cy = 0;
840 else /* overlapped window */
842 STARTUPINFOW info;
844 GetStartupInfoW( &info );
846 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
848 /* Never believe Microsoft's documentation... CreateWindowEx doc says
849 * that if an overlapped window is created with WS_VISIBLE style bit
850 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
851 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
852 * reveals that
854 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
855 * 2) it does not ignore the y parameter as the docs claim; instead, it
856 * uses it as second parameter to ShowWindow() unless y is either
857 * CW_USEDEFAULT or CW_USEDEFAULT16.
859 * The fact that we didn't do 2) caused bogus windows pop up when wine
860 * was running apps that were using this obscure feature. Example -
861 * calc.exe that comes with Win98 (only Win98, it's different from
862 * the one that comes with Win95 and NT)
864 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
865 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
866 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
869 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
871 if (info.dwFlags & STARTF_USESIZE)
873 cs->cx = info.dwXSize;
874 cs->cy = info.dwYSize;
876 else /* if no other hint from the app, pick 3/4 of the screen real estate */
878 RECT r;
879 SystemParametersInfoW( SPI_GETWORKAREA, 0, &r, 0);
880 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
881 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
884 /* Handle case where only the cy values is set to default */
885 else if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16)
887 RECT r;
888 SystemParametersInfoW( SPI_GETWORKAREA, 0, &r, 0);
889 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
893 else
895 /* neither x nor cx are default. Check the y values .
896 * In the trace we see Outlook and Outlook Express using
897 * cy set to CW_USEDEFAULT when opening the address book.
899 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16) {
900 RECT r;
901 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
902 SystemParametersInfoW( SPI_GETWORKAREA, 0, &r, 0);
903 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
908 /***********************************************************************
909 * dump_window_styles
911 static void dump_window_styles( DWORD style, DWORD exstyle )
913 TRACE( "style:" );
914 if(style & WS_POPUP) TRACE(" WS_POPUP");
915 if(style & WS_CHILD) TRACE(" WS_CHILD");
916 if(style & WS_MINIMIZE) TRACE(" WS_MINIMIZE");
917 if(style & WS_VISIBLE) TRACE(" WS_VISIBLE");
918 if(style & WS_DISABLED) TRACE(" WS_DISABLED");
919 if(style & WS_CLIPSIBLINGS) TRACE(" WS_CLIPSIBLINGS");
920 if(style & WS_CLIPCHILDREN) TRACE(" WS_CLIPCHILDREN");
921 if(style & WS_MAXIMIZE) TRACE(" WS_MAXIMIZE");
922 if((style & WS_CAPTION) == WS_CAPTION) TRACE(" WS_CAPTION");
923 else
925 if(style & WS_BORDER) TRACE(" WS_BORDER");
926 if(style & WS_DLGFRAME) TRACE(" WS_DLGFRAME");
928 if(style & WS_VSCROLL) TRACE(" WS_VSCROLL");
929 if(style & WS_HSCROLL) TRACE(" WS_HSCROLL");
930 if(style & WS_SYSMENU) TRACE(" WS_SYSMENU");
931 if(style & WS_THICKFRAME) TRACE(" WS_THICKFRAME");
932 if(style & WS_GROUP) TRACE(" WS_GROUP");
933 if(style & WS_TABSTOP) TRACE(" WS_TABSTOP");
934 if(style & WS_MINIMIZEBOX) TRACE(" WS_MINIMIZEBOX");
935 if(style & WS_MAXIMIZEBOX) TRACE(" WS_MAXIMIZEBOX");
937 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
938 #define DUMPED_STYLES \
939 (WS_POPUP | \
940 WS_CHILD | \
941 WS_MINIMIZE | \
942 WS_VISIBLE | \
943 WS_DISABLED | \
944 WS_CLIPSIBLINGS | \
945 WS_CLIPCHILDREN | \
946 WS_MAXIMIZE | \
947 WS_BORDER | \
948 WS_DLGFRAME | \
949 WS_VSCROLL | \
950 WS_HSCROLL | \
951 WS_SYSMENU | \
952 WS_THICKFRAME | \
953 WS_GROUP | \
954 WS_TABSTOP | \
955 WS_MINIMIZEBOX | \
956 WS_MAXIMIZEBOX)
958 if(style & ~DUMPED_STYLES) TRACE(" %08lx", style & ~DUMPED_STYLES);
959 TRACE("\n");
960 #undef DUMPED_STYLES
962 TRACE( "exstyle:" );
963 if(exstyle & WS_EX_DLGMODALFRAME) TRACE(" WS_EX_DLGMODALFRAME");
964 if(exstyle & WS_EX_DRAGDETECT) TRACE(" WS_EX_DRAGDETECT");
965 if(exstyle & WS_EX_NOPARENTNOTIFY) TRACE(" WS_EX_NOPARENTNOTIFY");
966 if(exstyle & WS_EX_TOPMOST) TRACE(" WS_EX_TOPMOST");
967 if(exstyle & WS_EX_ACCEPTFILES) TRACE(" WS_EX_ACCEPTFILES");
968 if(exstyle & WS_EX_TRANSPARENT) TRACE(" WS_EX_TRANSPARENT");
969 if(exstyle & WS_EX_MDICHILD) TRACE(" WS_EX_MDICHILD");
970 if(exstyle & WS_EX_TOOLWINDOW) TRACE(" WS_EX_TOOLWINDOW");
971 if(exstyle & WS_EX_WINDOWEDGE) TRACE(" WS_EX_WINDOWEDGE");
972 if(exstyle & WS_EX_CLIENTEDGE) TRACE(" WS_EX_CLIENTEDGE");
973 if(exstyle & WS_EX_CONTEXTHELP) TRACE(" WS_EX_CONTEXTHELP");
974 if(exstyle & WS_EX_RIGHT) TRACE(" WS_EX_RIGHT");
975 if(exstyle & WS_EX_RTLREADING) TRACE(" WS_EX_RTLREADING");
976 if(exstyle & WS_EX_LEFTSCROLLBAR) TRACE(" WS_EX_LEFTSCROLLBAR");
977 if(exstyle & WS_EX_CONTROLPARENT) TRACE(" WS_EX_CONTROLPARENT");
978 if(exstyle & WS_EX_STATICEDGE) TRACE(" WS_EX_STATICEDGE");
979 if(exstyle & WS_EX_APPWINDOW) TRACE(" WS_EX_APPWINDOW");
980 if(exstyle & WS_EX_LAYERED) TRACE(" WS_EX_LAYERED");
982 #define DUMPED_EX_STYLES \
983 (WS_EX_DLGMODALFRAME | \
984 WS_EX_DRAGDETECT | \
985 WS_EX_NOPARENTNOTIFY | \
986 WS_EX_TOPMOST | \
987 WS_EX_ACCEPTFILES | \
988 WS_EX_TRANSPARENT | \
989 WS_EX_MDICHILD | \
990 WS_EX_TOOLWINDOW | \
991 WS_EX_WINDOWEDGE | \
992 WS_EX_CLIENTEDGE | \
993 WS_EX_CONTEXTHELP | \
994 WS_EX_RIGHT | \
995 WS_EX_RTLREADING | \
996 WS_EX_LEFTSCROLLBAR | \
997 WS_EX_CONTROLPARENT | \
998 WS_EX_STATICEDGE | \
999 WS_EX_APPWINDOW | \
1000 WS_EX_LAYERED)
1002 if(exstyle & ~DUMPED_EX_STYLES) TRACE(" %08lx", exstyle & ~DUMPED_EX_STYLES);
1003 TRACE("\n");
1004 #undef DUMPED_EX_STYLES
1008 /***********************************************************************
1009 * WIN_CreateWindowEx
1011 * Implementation of CreateWindowEx().
1013 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
1014 WINDOWPROCTYPE type )
1016 INT sw = SW_SHOW;
1017 WND *wndPtr;
1018 HWND hwnd, parent, owner, top_child = 0;
1019 BOOL unicode = (type == WIN_PROC_32W);
1021 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
1022 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
1023 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszClass) : debugstr_a(cs->lpszClass),
1024 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
1025 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
1027 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
1029 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
1030 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
1032 /* Fix the styles for MDI children */
1033 if (cs->dwExStyle & WS_EX_MDICHILD)
1035 MDICREATESTRUCTA mdi_cs;
1036 UINT flags = 0;
1038 wndPtr = WIN_GetPtr(cs->hwndParent);
1039 if (wndPtr && wndPtr != WND_OTHER_PROCESS)
1041 flags = wndPtr->flags;
1042 WIN_ReleasePtr(wndPtr);
1045 if (!(flags & WIN_ISMDICLIENT))
1047 WARN("WS_EX_MDICHILD, but parent %p is not MDIClient\n", cs->hwndParent);
1048 return 0;
1051 /* cs->lpCreateParams of WM_[NC]CREATE is different for MDI children.
1052 * MDICREATESTRUCT members have the originally passed values.
1054 * Note: we rely on the fact that MDICREATESTRUCTA and MDICREATESTRUCTW
1055 * have the same layout.
1057 mdi_cs.szClass = cs->lpszClass;
1058 mdi_cs.szTitle = cs->lpszName;
1059 mdi_cs.hOwner = cs->hInstance;
1060 mdi_cs.x = cs->x;
1061 mdi_cs.y = cs->y;
1062 mdi_cs.cx = cs->cx;
1063 mdi_cs.cy = cs->cy;
1064 mdi_cs.style = cs->style;
1065 mdi_cs.lParam = (LPARAM)cs->lpCreateParams;
1067 cs->lpCreateParams = (LPVOID)&mdi_cs;
1069 if (GetWindowLongW(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
1071 if (cs->style & WS_POPUP)
1073 TRACE("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n");
1074 return 0;
1076 cs->style |= WS_CHILD | WS_CLIPSIBLINGS;
1078 else
1080 cs->style &= ~WS_POPUP;
1081 cs->style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
1082 WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
1085 top_child = GetWindow(cs->hwndParent, GW_CHILD);
1087 if (top_child)
1089 /* Restore current maximized child */
1090 if((cs->style & WS_VISIBLE) && IsZoomed(top_child))
1092 TRACE("Restoring current maximized child %p\n", top_child);
1093 SendMessageW( top_child, WM_SETREDRAW, FALSE, 0 );
1094 ShowWindow(top_child, SW_RESTORE);
1095 SendMessageW( top_child, WM_SETREDRAW, TRUE, 0 );
1100 /* Find the parent window */
1102 parent = GetDesktopWindow();
1103 owner = 0;
1105 if (cs->hwndParent == HWND_MESSAGE)
1107 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
1108 * message window (style: WS_POPUP|WS_DISABLED)
1110 FIXME("Parent is HWND_MESSAGE\n");
1112 else if (cs->hwndParent)
1114 /* Make sure parent is valid */
1115 if (!IsWindow( cs->hwndParent ))
1117 WARN("Bad parent %p\n", cs->hwndParent );
1118 return 0;
1120 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1121 parent = WIN_GetFullHandle(cs->hwndParent);
1122 else
1123 owner = GetAncestor( cs->hwndParent, GA_ROOT );
1125 else if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1127 WARN("No parent for child window\n" );
1128 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1131 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
1133 /* Correct the window styles.
1135 * It affects both the style loaded into the WIN structure and
1136 * passed in the CREATESTRUCT to the WM_[NC]CREATE.
1138 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1139 * why does the user get to set it?
1142 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
1143 * tested for WS_POPUP
1145 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
1146 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
1147 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
1148 cs->dwExStyle |= WS_EX_WINDOWEDGE;
1149 else
1150 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
1152 if (!(cs->style & WS_CHILD))
1154 cs->style |= WS_CLIPSIBLINGS;
1155 if (!(cs->style & WS_POPUP))
1156 cs->style |= WS_CAPTION;
1159 /* Create the window structure */
1161 if (!(wndPtr = create_window_handle( parent, owner, classAtom, cs->hInstance, type )))
1163 TRACE("out of memory\n" );
1164 return 0;
1166 hwnd = wndPtr->hwndSelf;
1168 /* Fill the window structure */
1170 wndPtr->tid = GetCurrentThreadId();
1171 wndPtr->owner = owner;
1172 wndPtr->parent = parent;
1173 wndPtr->hInstance = cs->hInstance;
1174 wndPtr->text = NULL;
1175 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1176 wndPtr->dwExStyle = cs->dwExStyle;
1177 wndPtr->wIDmenu = 0;
1178 wndPtr->helpContext = 0;
1179 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
1180 wndPtr->pVScroll = NULL;
1181 wndPtr->pHScroll = NULL;
1182 wndPtr->userdata = 0;
1183 wndPtr->hIcon = 0;
1184 wndPtr->hIconSmall = 0;
1185 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU) ? MENU_GetSysMenu( hwnd, 0 ) : 0;
1187 if (!(cs->style & (WS_CHILD | WS_POPUP)))
1188 wndPtr->flags |= WIN_NEED_SIZE;
1190 SERVER_START_REQ( set_window_info )
1192 req->handle = hwnd;
1193 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE;
1194 req->style = wndPtr->dwStyle;
1195 req->ex_style = wndPtr->dwExStyle;
1196 req->instance = (void *)wndPtr->hInstance;
1197 req->extra_offset = -1;
1198 wine_server_call( req );
1200 SERVER_END_REQ;
1202 /* Get class or window DC if needed */
1204 if (wndPtr->clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
1206 /* Set the window menu */
1208 if (((wndPtr->dwStyle & (WS_CAPTION|WS_CHILD)) == WS_CAPTION) ||
1209 (wndPtr->dwExStyle & WS_EX_APPWINDOW))
1211 if (cs->hMenu) MENU_SetMenu(hwnd, cs->hMenu);
1212 else
1214 LPCSTR menuName = (LPCSTR)GetClassLongPtrA( hwnd, GCLP_MENUNAME );
1215 if (menuName)
1217 if (HIWORD(cs->hInstance))
1218 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1219 else
1220 cs->hMenu = HMENU_32(LoadMenu16(HINSTANCE_16(cs->hInstance),menuName));
1222 if (cs->hMenu) MENU_SetMenu( hwnd, cs->hMenu );
1226 else SetWindowLongPtrW( hwnd, GWLP_ID, (ULONG_PTR)cs->hMenu );
1227 WIN_ReleaseWndPtr( wndPtr );
1229 if (!USER_Driver.pCreateWindow || !USER_Driver.pCreateWindow( hwnd, cs, unicode))
1231 WIN_DestroyWindow( hwnd );
1232 return 0;
1235 /* Notify the parent window only */
1237 send_parent_notify( hwnd, WM_CREATE );
1238 if (!IsWindow( hwnd )) return 0;
1240 if (cs->style & WS_VISIBLE)
1242 if (cs->style & WS_MAXIMIZE)
1243 sw = SW_SHOWMAXIMIZED;
1244 else if (cs->style & WS_MINIMIZE)
1245 sw = SW_SHOWMINIMIZED;
1247 ShowWindow( hwnd, sw );
1248 if (cs->dwExStyle & WS_EX_MDICHILD)
1250 SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
1251 /* ShowWindow won't activate child windows */
1252 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE );
1256 /* Call WH_SHELL hook */
1258 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1259 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1261 TRACE("created window %p\n", hwnd);
1262 return hwnd;
1266 /***********************************************************************
1267 * CreateWindow (USER.41)
1269 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1270 DWORD style, INT16 x, INT16 y, INT16 width,
1271 INT16 height, HWND16 parent, HMENU16 menu,
1272 HINSTANCE16 instance, LPVOID data )
1274 return CreateWindowEx16( 0, className, windowName, style,
1275 x, y, width, height, parent, menu, instance, data );
1279 /***********************************************************************
1280 * CreateWindowEx (USER.452)
1282 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1283 LPCSTR windowName, DWORD style, INT16 x,
1284 INT16 y, INT16 width, INT16 height,
1285 HWND16 parent, HMENU16 menu,
1286 HINSTANCE16 instance, LPVOID data )
1288 ATOM classAtom;
1289 CREATESTRUCTA cs;
1290 char buffer[256];
1292 /* Find the class atom */
1294 if (HIWORD(className))
1296 if (!(classAtom = GlobalFindAtomA( className )))
1298 ERR( "bad class name %s\n", debugstr_a(className) );
1299 return 0;
1302 else
1304 classAtom = LOWORD(className);
1305 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1307 ERR( "bad atom %x\n", classAtom);
1308 return 0;
1310 className = buffer;
1313 /* Fix the coordinates */
1315 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1316 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1317 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1318 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1320 /* Create the window */
1322 cs.lpCreateParams = data;
1323 cs.hInstance = HINSTANCE_32(instance);
1324 cs.hMenu = HMENU_32(menu);
1325 cs.hwndParent = WIN_Handle32( parent );
1326 cs.style = style;
1327 cs.lpszName = windowName;
1328 cs.lpszClass = className;
1329 cs.dwExStyle = exStyle;
1331 return HWND_16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
1335 /***********************************************************************
1336 * CreateWindowExA (USER32.@)
1338 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1339 LPCSTR windowName, DWORD style, INT x,
1340 INT y, INT width, INT height,
1341 HWND parent, HMENU menu,
1342 HINSTANCE instance, LPVOID data )
1344 ATOM classAtom;
1345 CREATESTRUCTA cs;
1346 char buffer[256];
1348 /* Find the class atom */
1350 if (HIWORD(className))
1352 if (!(classAtom = GlobalFindAtomA( className )))
1354 ERR( "bad class name %s\n", debugstr_a(className) );
1355 return 0;
1358 else
1360 classAtom = LOWORD(className);
1361 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1363 ERR( "bad atom %x\n", classAtom);
1364 return 0;
1366 className = buffer;
1369 /* Create the window */
1371 cs.lpCreateParams = data;
1372 cs.hInstance = instance;
1373 cs.hMenu = menu;
1374 cs.hwndParent = parent;
1375 cs.x = x;
1376 cs.y = y;
1377 cs.cx = width;
1378 cs.cy = height;
1379 cs.style = style;
1380 cs.lpszName = windowName;
1381 cs.lpszClass = className;
1382 cs.dwExStyle = exStyle;
1384 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1388 /***********************************************************************
1389 * CreateWindowExW (USER32.@)
1391 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1392 LPCWSTR windowName, DWORD style, INT x,
1393 INT y, INT width, INT height,
1394 HWND parent, HMENU menu,
1395 HINSTANCE instance, LPVOID data )
1397 ATOM classAtom;
1398 CREATESTRUCTW cs;
1399 WCHAR buffer[256];
1401 /* Find the class atom */
1403 if (HIWORD(className))
1405 if (!(classAtom = GlobalFindAtomW( className )))
1407 ERR( "bad class name %s\n", debugstr_w(className) );
1408 return 0;
1411 else
1413 classAtom = LOWORD(className);
1414 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1416 ERR( "bad atom %x\n", classAtom);
1417 return 0;
1419 className = buffer;
1422 /* Create the window */
1424 cs.lpCreateParams = data;
1425 cs.hInstance = instance;
1426 cs.hMenu = menu;
1427 cs.hwndParent = parent;
1428 cs.x = x;
1429 cs.y = y;
1430 cs.cx = width;
1431 cs.cy = height;
1432 cs.style = style;
1433 cs.lpszName = windowName;
1434 cs.lpszClass = className;
1435 cs.dwExStyle = exStyle;
1437 /* Note: we rely on the fact that CREATESTRUCTA and */
1438 /* CREATESTRUCTW have the same layout. */
1439 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1443 /***********************************************************************
1444 * WIN_SendDestroyMsg
1446 static void WIN_SendDestroyMsg( HWND hwnd )
1448 GUITHREADINFO info;
1450 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1452 if (hwnd == info.hwndCaret) DestroyCaret();
1453 if (hwnd == info.hwndActive) WINPOS_ActivateOtherWindow( hwnd );
1455 if (USER_Driver.pResetSelectionOwner)
1456 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1459 * Send the WM_DESTROY to the window.
1461 SendMessageW( hwnd, WM_DESTROY, 0, 0);
1464 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1465 * make sure that the window still exists when we come back.
1467 if (IsWindow(hwnd))
1469 HWND* pWndArray;
1470 int i;
1472 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1474 for (i = 0; pWndArray[i]; i++)
1476 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1478 HeapFree( GetProcessHeap(), 0, pWndArray );
1480 else
1481 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1485 /***********************************************************************
1486 * DestroyWindow (USER32.@)
1488 BOOL WINAPI DestroyWindow( HWND hwnd )
1490 BOOL is_child;
1492 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1494 SetLastError( ERROR_ACCESS_DENIED );
1495 return FALSE;
1498 TRACE("(%p)\n", hwnd);
1500 /* Call hooks */
1502 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1504 if (MENU_IsMenuActive() == hwnd)
1505 EndMenu();
1507 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1509 if (is_child)
1511 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1512 send_parent_notify( hwnd, WM_DESTROY );
1514 else if (!GetWindow( hwnd, GW_OWNER ))
1516 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1517 /* FIXME: clean up palette - see "Internals" p.352 */
1520 if (!IsWindow(hwnd)) return TRUE;
1522 if (USER_Driver.pResetSelectionOwner)
1523 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1525 /* Hide the window */
1526 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)
1528 /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
1529 if (is_child)
1530 ShowWindow( hwnd, SW_HIDE );
1531 else
1532 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1533 SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW );
1536 if (!IsWindow(hwnd)) return TRUE;
1538 /* Recursively destroy owned windows */
1540 if (!is_child)
1542 for (;;)
1544 int i, got_one = 0;
1545 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1546 if (list)
1548 for (i = 0; list[i]; i++)
1550 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1551 if (WIN_IsCurrentThread( list[i] ))
1553 DestroyWindow( list[i] );
1554 got_one = 1;
1555 continue;
1557 WIN_SetOwner( list[i], 0 );
1559 HeapFree( GetProcessHeap(), 0, list );
1561 if (!got_one) break;
1565 /* Send destroy messages */
1567 WIN_SendDestroyMsg( hwnd );
1568 if (!IsWindow( hwnd )) return TRUE;
1570 if (GetClipboardOwner() == hwnd)
1571 CLIPBOARD_ReleaseOwner();
1573 /* Destroy the window storage */
1575 WIN_DestroyWindow( hwnd );
1576 return TRUE;
1580 /***********************************************************************
1581 * CloseWindow (USER32.@)
1583 BOOL WINAPI CloseWindow( HWND hwnd )
1585 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1586 ShowWindow( hwnd, SW_MINIMIZE );
1587 return TRUE;
1591 /***********************************************************************
1592 * OpenIcon (USER32.@)
1594 BOOL WINAPI OpenIcon( HWND hwnd )
1596 if (!IsIconic( hwnd )) return FALSE;
1597 ShowWindow( hwnd, SW_SHOWNORMAL );
1598 return TRUE;
1602 /***********************************************************************
1603 * WIN_FindWindow
1605 * Implementation of FindWindow() and FindWindowEx().
1607 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1609 HWND *list = NULL;
1610 HWND retvalue = 0;
1611 int i = 0, len = 0;
1612 WCHAR *buffer = NULL;
1614 if (!parent) parent = GetDesktopWindow();
1615 if (title)
1617 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1618 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1621 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1623 if (child)
1625 child = WIN_GetFullHandle( child );
1626 while (list[i] && list[i] != child) i++;
1627 if (!list[i]) goto done;
1628 i++; /* start from next window */
1631 if (title)
1633 while (list[i])
1635 if (GetWindowTextW( list[i], buffer, len + 1 ) && !strcmpiW( buffer, title )) break;
1636 i++;
1639 retvalue = list[i];
1641 done:
1642 HeapFree( GetProcessHeap(), 0, list );
1643 HeapFree( GetProcessHeap(), 0, buffer );
1644 return retvalue;
1649 /***********************************************************************
1650 * FindWindowA (USER32.@)
1652 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1654 HWND ret = FindWindowExA( 0, 0, className, title );
1655 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1656 return ret;
1660 /***********************************************************************
1661 * FindWindowExA (USER32.@)
1663 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1664 LPCSTR className, LPCSTR title )
1666 ATOM atom = 0;
1667 LPWSTR buffer;
1668 HWND hwnd;
1669 INT len;
1671 if (className)
1673 /* If the atom doesn't exist, then no class */
1674 /* with this name exists either. */
1675 if (!(atom = GlobalFindAtomA( className )))
1677 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1678 return 0;
1681 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
1683 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1684 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1685 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
1686 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1687 HeapFree( GetProcessHeap(), 0, buffer );
1688 return hwnd;
1692 /***********************************************************************
1693 * FindWindowExW (USER32.@)
1695 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1696 LPCWSTR className, LPCWSTR title )
1698 ATOM atom = 0;
1700 if (className)
1702 /* If the atom doesn't exist, then no class */
1703 /* with this name exists either. */
1704 if (!(atom = GlobalFindAtomW( className )))
1706 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1707 return 0;
1710 return WIN_FindWindow( parent, child, atom, title );
1714 /***********************************************************************
1715 * FindWindowW (USER32.@)
1717 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1719 return FindWindowExW( 0, 0, className, title );
1723 /**********************************************************************
1724 * GetDesktopWindow (USER32.@)
1726 HWND WINAPI GetDesktopWindow(void)
1728 if (pWndDesktop) return pWndDesktop->hwndSelf;
1729 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" );
1730 ExitProcess(1);
1731 return 0;
1735 /*******************************************************************
1736 * EnableWindow (USER32.@)
1738 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1740 BOOL retvalue;
1741 HWND full_handle;
1743 if (is_broadcast(hwnd))
1745 SetLastError( ERROR_INVALID_PARAMETER );
1746 return FALSE;
1749 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1750 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1752 hwnd = full_handle;
1754 TRACE("( %p, %d )\n", hwnd, enable);
1756 retvalue = !IsWindowEnabled( hwnd );
1758 if (enable && retvalue)
1760 WIN_SetStyle( hwnd, 0, WS_DISABLED );
1761 SendMessageW( hwnd, WM_ENABLE, TRUE, 0 );
1763 else if (!enable && !retvalue)
1765 HWND capture_wnd;
1767 SendMessageW( hwnd, WM_CANCELMODE, 0, 0);
1769 WIN_SetStyle( hwnd, WS_DISABLED, 0 );
1771 if (hwnd == GetFocus())
1772 SetFocus( 0 ); /* A disabled window can't have the focus */
1774 capture_wnd = GetCapture();
1775 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1776 ReleaseCapture(); /* A disabled window can't capture the mouse */
1778 SendMessageW( hwnd, WM_ENABLE, FALSE, 0 );
1780 return retvalue;
1784 /***********************************************************************
1785 * IsWindowEnabled (USER32.@)
1787 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1789 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1793 /***********************************************************************
1794 * IsWindowUnicode (USER32.@)
1796 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1798 WND * wndPtr;
1799 BOOL retvalue;
1801 if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return FALSE;
1802 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1803 WIN_ReleasePtr( wndPtr );
1804 return retvalue;
1808 /**********************************************************************
1809 * GetWindowWord (USER32.@)
1811 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1813 if (offset >= 0)
1815 WORD retvalue = 0;
1816 WND *wndPtr = WIN_GetPtr( hwnd );
1817 if (!wndPtr)
1819 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1820 return 0;
1822 if (wndPtr == WND_OTHER_PROCESS)
1824 SERVER_START_REQ( set_window_info )
1826 req->handle = hwnd;
1827 req->flags = 0; /* don't set anything, just retrieve */
1828 req->extra_offset = offset;
1829 req->extra_size = sizeof(retvalue);
1830 if (!wine_server_call_err( req ))
1831 memcpy( &retvalue, &reply->old_extra_value, sizeof(retvalue) );
1833 SERVER_END_REQ;
1834 return retvalue;
1836 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1838 WARN("Invalid offset %d\n", offset );
1839 SetLastError( ERROR_INVALID_INDEX );
1841 else memcpy( &retvalue, (char *)wndPtr->wExtra + offset, sizeof(retvalue) );
1842 WIN_ReleasePtr( wndPtr );
1843 return retvalue;
1846 switch(offset)
1848 case GWLP_HWNDPARENT:
1849 return GetWindowLongPtrW( hwnd, offset );
1850 case GWLP_ID:
1851 case GWLP_HINSTANCE:
1853 LONG_PTR ret = GetWindowLongPtrW( hwnd, offset );
1854 if (HIWORD(ret))
1855 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1856 return LOWORD(ret);
1858 default:
1859 WARN("Invalid offset %d\n", offset );
1860 return 0;
1865 /**********************************************************************
1866 * SetWindowWord (USER32.@)
1868 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1870 WORD retval = 0;
1871 WND * wndPtr;
1873 switch(offset)
1875 case GWLP_ID:
1876 case GWLP_HINSTANCE:
1877 case GWLP_HWNDPARENT:
1878 return SetWindowLongPtrW( hwnd, offset, (ULONG_PTR)newval );
1879 default:
1880 if (offset < 0)
1882 WARN("Invalid offset %d\n", offset );
1883 SetLastError( ERROR_INVALID_INDEX );
1884 return 0;
1888 wndPtr = WIN_GetPtr( hwnd );
1889 if (wndPtr == WND_OTHER_PROCESS)
1891 if (IsWindow(hwnd))
1892 FIXME( "set %d <- %x not supported yet on other process window %p\n",
1893 offset, newval, hwnd );
1894 wndPtr = NULL;
1896 if (!wndPtr)
1898 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1899 return 0;
1902 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1904 WARN("Invalid offset %d\n", offset );
1905 WIN_ReleasePtr(wndPtr);
1906 SetLastError( ERROR_INVALID_INDEX );
1907 return 0;
1910 SERVER_START_REQ( set_window_info )
1912 req->handle = hwnd;
1913 req->flags = SET_WIN_EXTRA;
1914 req->extra_offset = offset;
1915 req->extra_size = sizeof(newval);
1916 memcpy( &req->extra_value, &newval, sizeof(newval) );
1917 if (!wine_server_call_err( req ))
1919 void *ptr = (char *)wndPtr->wExtra + offset;
1920 memcpy( &retval, ptr, sizeof(retval) );
1921 memcpy( ptr, &newval, sizeof(newval) );
1924 SERVER_END_REQ;
1925 WIN_ReleasePtr( wndPtr );
1926 return retval;
1930 /**********************************************************************
1931 * WIN_GetWindowLong
1933 * Helper function for GetWindowLong().
1935 static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1937 LONG_PTR retvalue = 0;
1938 WND *wndPtr;
1940 TRACE( "%p %d %x\n", hwnd, offset, type );
1942 if (offset == GWLP_HWNDPARENT)
1944 HWND parent = GetAncestor( hwnd, GA_PARENT );
1945 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1946 return (ULONG_PTR)parent;
1949 if (!(wndPtr = WIN_GetPtr( hwnd )))
1951 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1952 return 0;
1955 if (wndPtr == WND_OTHER_PROCESS)
1957 if (offset == GWLP_WNDPROC)
1959 SetLastError( ERROR_ACCESS_DENIED );
1960 return 0;
1962 SERVER_START_REQ( set_window_info )
1964 req->handle = hwnd;
1965 req->flags = 0; /* don't set anything, just retrieve */
1966 req->extra_offset = (offset >= 0) ? offset : -1;
1967 req->extra_size = (offset >= 0) ? sizeof(retvalue) : 0;
1968 if (!wine_server_call_err( req ))
1970 switch(offset)
1972 case GWL_STYLE: retvalue = reply->old_style; break;
1973 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1974 case GWLP_ID: retvalue = reply->old_id; break;
1975 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1976 case GWLP_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
1977 default:
1978 if (offset >= 0) retvalue = reply->old_extra_value;
1979 else SetLastError( ERROR_INVALID_INDEX );
1980 break;
1984 SERVER_END_REQ;
1985 return retvalue;
1988 /* now we have a valid wndPtr */
1990 if (offset >= 0)
1992 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
1995 * Some programs try to access last element from 16 bit
1996 * code using illegal offset value. Hopefully this is
1997 * what those programs really expect.
1999 if (type == WIN_PROC_16 &&
2000 wndPtr->cbWndExtra >= 4 &&
2001 offset == wndPtr->cbWndExtra - sizeof(WORD))
2003 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
2005 ERR( "- replaced invalid offset %d with %d\n",
2006 offset, offset2 );
2008 retvalue = *(LONG_PTR *)(((char *)wndPtr->wExtra) + offset2);
2009 WIN_ReleasePtr( wndPtr );
2010 return retvalue;
2012 WARN("Invalid offset %d\n", offset );
2013 WIN_ReleasePtr( wndPtr );
2014 SetLastError( ERROR_INVALID_INDEX );
2015 return 0;
2017 retvalue = *(LONG_PTR *)(((char *)wndPtr->wExtra) + offset);
2018 /* Special case for dialog window procedure */
2019 if ((offset == DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2020 retvalue = (LONG_PTR)WINPROC_GetProc( (WNDPROC)retvalue, type );
2021 WIN_ReleasePtr( wndPtr );
2022 return retvalue;
2025 switch(offset)
2027 case GWLP_USERDATA: retvalue = wndPtr->userdata; break;
2028 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
2029 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
2030 case GWLP_ID: retvalue = (ULONG_PTR)wndPtr->wIDmenu; break;
2031 case GWLP_WNDPROC: retvalue = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, type ); break;
2032 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wndPtr->hInstance; break;
2033 default:
2034 WARN("Unknown offset %d\n", offset );
2035 SetLastError( ERROR_INVALID_INDEX );
2036 break;
2038 WIN_ReleasePtr(wndPtr);
2039 return retvalue;
2043 /**********************************************************************
2044 * WIN_SetWindowLong
2046 * Helper function for SetWindowLong().
2048 * 0 is the failure code. However, in the case of failure SetLastError
2049 * must be set to distinguish between a 0 return value and a failure.
2051 static LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, LONG_PTR newval,
2052 WINDOWPROCTYPE type )
2054 STYLESTRUCT style;
2055 BOOL ok;
2056 LONG_PTR retval = 0;
2057 WND *wndPtr;
2059 TRACE( "%p %d %lx %x\n", hwnd, offset, newval, type );
2061 if (is_broadcast(hwnd))
2063 SetLastError( ERROR_INVALID_PARAMETER );
2064 return FALSE;
2066 if (!WIN_IsCurrentProcess( hwnd ))
2068 if (offset == GWLP_WNDPROC)
2070 SetLastError( ERROR_ACCESS_DENIED );
2071 return 0;
2073 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
2076 wndPtr = WIN_GetPtr( hwnd );
2077 if (wndPtr->hwndSelf == GetDesktopWindow())
2079 /* can't change anything on the desktop window */
2080 WIN_ReleasePtr( wndPtr );
2081 SetLastError( ERROR_ACCESS_DENIED );
2082 return 0;
2085 /* first some special cases */
2086 switch( offset )
2088 case GWL_STYLE:
2089 case GWL_EXSTYLE:
2090 style.styleOld =
2091 offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
2092 style.styleNew = newval;
2093 WIN_ReleasePtr( wndPtr );
2094 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
2095 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
2096 newval = style.styleNew;
2097 break;
2098 case GWLP_HWNDPARENT:
2099 if (wndPtr->parent == GetDesktopWindow())
2101 WIN_ReleasePtr( wndPtr );
2102 return (ULONG_PTR)WIN_SetOwner( hwnd, (HWND)newval );
2104 else
2106 WIN_ReleasePtr( wndPtr );
2107 return (ULONG_PTR)SetParent( hwnd, (HWND)newval );
2109 case GWLP_WNDPROC:
2110 retval = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, type );
2111 wndPtr->winproc = WINPROC_AllocProc( (WNDPROC)newval, type );
2112 WIN_ReleasePtr( wndPtr );
2113 return retval;
2114 case GWLP_ID:
2115 case GWLP_HINSTANCE:
2116 case GWLP_USERDATA:
2117 break;
2118 case DWLP_DLGPROC:
2119 if ((wndPtr->cbWndExtra + sizeof(LONG_PTR) >= DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2121 WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWLP_DLGPROC);
2122 retval = (ULONG_PTR)WINPROC_GetProc( *ptr, type );
2123 *ptr = WINPROC_AllocProc( (WNDPROC)newval, type );
2124 WIN_ReleasePtr( wndPtr );
2125 return retval;
2127 /* fall through */
2128 default:
2129 if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - sizeof(LONG_PTR)))
2131 WARN("Invalid offset %d\n", offset );
2132 WIN_ReleasePtr( wndPtr );
2133 SetLastError( ERROR_INVALID_INDEX );
2134 return 0;
2136 else
2138 LONG_PTR *ptr = (LONG_PTR *)((char *)wndPtr->wExtra + offset);
2139 if (*ptr == newval) /* already set to the same value */
2141 WIN_ReleasePtr( wndPtr );
2142 return newval;
2145 break;
2148 SERVER_START_REQ( set_window_info )
2150 req->handle = hwnd;
2151 req->extra_offset = -1;
2152 switch(offset)
2154 case GWL_STYLE:
2155 req->flags = SET_WIN_STYLE;
2156 req->style = newval;
2157 break;
2158 case GWL_EXSTYLE:
2159 req->flags = SET_WIN_EXSTYLE;
2160 req->ex_style = newval;
2161 break;
2162 case GWLP_ID:
2163 req->flags = SET_WIN_ID;
2164 req->id = newval;
2165 break;
2166 case GWLP_HINSTANCE:
2167 req->flags = SET_WIN_INSTANCE;
2168 req->instance = (void *)newval;
2169 break;
2170 case GWLP_USERDATA:
2171 req->flags = SET_WIN_USERDATA;
2172 req->user_data = (void *)newval;
2173 break;
2174 default:
2175 req->flags = SET_WIN_EXTRA;
2176 req->extra_offset = offset;
2177 req->extra_size = sizeof(newval);
2178 memcpy( &req->extra_value, &newval, sizeof(newval) );
2180 if ((ok = !wine_server_call_err( req )))
2182 switch(offset)
2184 case GWL_STYLE:
2185 wndPtr->dwStyle = newval;
2186 retval = reply->old_style;
2187 break;
2188 case GWL_EXSTYLE:
2189 wndPtr->dwExStyle = newval;
2190 retval = reply->old_ex_style;
2191 break;
2192 case GWLP_ID:
2193 wndPtr->wIDmenu = newval;
2194 retval = reply->old_id;
2195 break;
2196 case GWLP_HINSTANCE:
2197 wndPtr->hInstance = (HINSTANCE)newval;
2198 retval = (ULONG_PTR)reply->old_instance;
2199 break;
2200 case GWLP_USERDATA:
2201 wndPtr->userdata = newval;
2202 retval = (ULONG_PTR)reply->old_user_data;
2203 break;
2204 default:
2206 void *ptr = (char *)wndPtr->wExtra + offset;
2207 memcpy( &retval, ptr, sizeof(retval) );
2208 memcpy( ptr, &newval, sizeof(newval) );
2210 break;
2214 SERVER_END_REQ;
2215 WIN_ReleasePtr( wndPtr );
2217 if (!ok) return 0;
2219 if (offset == GWL_STYLE && USER_Driver.pSetWindowStyle)
2220 USER_Driver.pSetWindowStyle( hwnd, retval );
2222 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2223 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2225 return retval;
2229 /**********************************************************************
2230 * GetWindowLong (USER.135)
2232 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2234 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
2238 /**********************************************************************
2239 * GetWindowLongA (USER32.@)
2241 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2243 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2247 /**********************************************************************
2248 * GetWindowLongW (USER32.@)
2250 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2252 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2256 /**********************************************************************
2257 * SetWindowLong (USER.136)
2259 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2261 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
2265 /**********************************************************************
2266 * SetWindowLongA (USER32.@)
2268 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2270 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2274 /**********************************************************************
2275 * SetWindowLongW (USER32.@) Set window attribute
2277 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2278 * value in a window's extra memory.
2280 * The _hwnd_ parameter specifies the window. is the handle to a
2281 * window that has extra memory. The _newval_ parameter contains the
2282 * new attribute or extra memory value. If positive, the _offset_
2283 * parameter is the byte-addressed location in the window's extra
2284 * memory to set. If negative, _offset_ specifies the window
2285 * attribute to set, and should be one of the following values:
2287 * GWL_EXSTYLE The window's extended window style
2289 * GWL_STYLE The window's window style.
2291 * GWLP_WNDPROC Pointer to the window's window procedure.
2293 * GWLP_HINSTANCE The window's pplication instance handle.
2295 * GWLP_ID The window's identifier.
2297 * GWLP_USERDATA The window's user-specified data.
2299 * If the window is a dialog box, the _offset_ parameter can be one of
2300 * the following values:
2302 * DWLP_DLGPROC The address of the window's dialog box procedure.
2304 * DWLP_MSGRESULT The return value of a message
2305 * that the dialog box procedure processed.
2307 * DWLP_USER Application specific information.
2309 * RETURNS
2311 * If successful, returns the previous value located at _offset_. Otherwise,
2312 * returns 0.
2314 * NOTES
2316 * Extra memory for a window class is specified by a nonzero cbWndExtra
2317 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2318 * time of class creation.
2320 * Using GWL_WNDPROC to set a new window procedure effectively creates
2321 * a window subclass. Use CallWindowProc() in the new windows procedure
2322 * to pass messages to the superclass's window procedure.
2324 * The user data is reserved for use by the application which created
2325 * the window.
2327 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2328 * instead, call the EnableWindow() function to change the window's
2329 * disabled state.
2331 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2332 * SetParent() instead.
2334 * Win95:
2335 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2336 * it sends WM_STYLECHANGING before changing the settings
2337 * and WM_STYLECHANGED afterwards.
2338 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2340 LONG WINAPI SetWindowLongW(
2341 HWND hwnd, /* [in] window to alter */
2342 INT offset, /* [in] offset, in bytes, of location to alter */
2343 LONG newval /* [in] new value of location */
2345 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2349 /*******************************************************************
2350 * GetWindowTextA (USER32.@)
2352 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2354 WCHAR *buffer;
2356 if (WIN_IsCurrentProcess( hwnd ))
2357 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2359 /* when window belongs to other process, don't send a message */
2360 if (nMaxCount <= 0) return 0;
2361 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2362 get_server_window_text( hwnd, buffer, nMaxCount );
2363 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2364 lpString[nMaxCount-1] = 0;
2365 HeapFree( GetProcessHeap(), 0, buffer );
2366 return strlen(lpString);
2370 /*******************************************************************
2371 * InternalGetWindowText (USER32.@)
2373 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2375 WND *win;
2377 if (nMaxCount <= 0) return 0;
2378 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2379 if (win != WND_OTHER_PROCESS)
2381 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2382 else lpString[0] = 0;
2383 WIN_ReleasePtr( win );
2385 else
2387 get_server_window_text( hwnd, lpString, nMaxCount );
2389 return strlenW(lpString);
2393 /*******************************************************************
2394 * GetWindowTextW (USER32.@)
2396 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2398 if (WIN_IsCurrentProcess( hwnd ))
2399 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2401 /* when window belongs to other process, don't send a message */
2402 if (nMaxCount <= 0) return 0;
2403 get_server_window_text( hwnd, lpString, nMaxCount );
2404 return strlenW(lpString);
2408 /*******************************************************************
2409 * SetWindowText (USER32.@)
2410 * SetWindowTextA (USER32.@)
2412 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2414 if (is_broadcast(hwnd))
2416 SetLastError( ERROR_INVALID_PARAMETER );
2417 return FALSE;
2419 if (!WIN_IsCurrentProcess( hwnd ))
2421 FIXME( "cannot set text %s of other process window %p\n", debugstr_a(lpString), hwnd );
2422 SetLastError( ERROR_ACCESS_DENIED );
2423 return FALSE;
2425 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2429 /*******************************************************************
2430 * SetWindowTextW (USER32.@)
2432 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2434 if (is_broadcast(hwnd))
2436 SetLastError( ERROR_INVALID_PARAMETER );
2437 return FALSE;
2439 if (!WIN_IsCurrentProcess( hwnd ))
2441 FIXME( "cannot set text %s of other process window %p\n", debugstr_w(lpString), hwnd );
2442 SetLastError( ERROR_ACCESS_DENIED );
2443 return FALSE;
2445 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2449 /*******************************************************************
2450 * GetWindowTextLengthA (USER32.@)
2452 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2454 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2457 /*******************************************************************
2458 * GetWindowTextLengthW (USER32.@)
2460 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2462 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2466 /*******************************************************************
2467 * IsWindow (USER32.@)
2469 BOOL WINAPI IsWindow( HWND hwnd )
2471 WND *ptr;
2472 BOOL ret;
2474 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2476 if (ptr != WND_OTHER_PROCESS)
2478 WIN_ReleasePtr( ptr );
2479 return TRUE;
2482 /* check other processes */
2483 SERVER_START_REQ( get_window_info )
2485 req->handle = hwnd;
2486 ret = !wine_server_call_err( req );
2488 SERVER_END_REQ;
2489 return ret;
2493 /***********************************************************************
2494 * GetWindowThreadProcessId (USER32.@)
2496 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2498 WND *ptr;
2499 DWORD tid = 0;
2501 if (!(ptr = WIN_GetPtr( hwnd )))
2503 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2504 return 0;
2507 if (ptr != WND_OTHER_PROCESS)
2509 /* got a valid window */
2510 tid = ptr->tid;
2511 if (process) *process = GetCurrentProcessId();
2512 WIN_ReleasePtr( ptr );
2513 return tid;
2516 /* check other processes */
2517 SERVER_START_REQ( get_window_info )
2519 req->handle = hwnd;
2520 if (!wine_server_call_err( req ))
2522 tid = (DWORD)reply->tid;
2523 if (process) *process = (DWORD)reply->pid;
2526 SERVER_END_REQ;
2527 return tid;
2531 /*****************************************************************
2532 * GetParent (USER32.@)
2534 HWND WINAPI GetParent( HWND hwnd )
2536 WND *wndPtr;
2537 HWND retvalue = 0;
2539 if (!(wndPtr = WIN_GetPtr( hwnd )))
2541 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2542 return 0;
2544 if (wndPtr == WND_OTHER_PROCESS)
2546 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2547 if (style & (WS_POPUP | WS_CHILD))
2549 SERVER_START_REQ( get_window_tree )
2551 req->handle = hwnd;
2552 if (!wine_server_call_err( req ))
2554 if (style & WS_POPUP) retvalue = reply->owner;
2555 else if (style & WS_CHILD) retvalue = reply->parent;
2558 SERVER_END_REQ;
2561 else
2563 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2564 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2565 WIN_ReleasePtr( wndPtr );
2567 return retvalue;
2571 /*****************************************************************
2572 * GetAncestor (USER32.@)
2574 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2576 WND *win;
2577 HWND *list, ret = 0;
2579 switch(type)
2581 case GA_PARENT:
2582 if (!(win = WIN_GetPtr( hwnd )))
2584 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2585 return 0;
2587 if (win != WND_OTHER_PROCESS)
2589 ret = win->parent;
2590 WIN_ReleasePtr( win );
2592 else /* need to query the server */
2594 SERVER_START_REQ( get_window_tree )
2596 req->handle = hwnd;
2597 if (!wine_server_call_err( req )) ret = reply->parent;
2599 SERVER_END_REQ;
2601 break;
2603 case GA_ROOT:
2604 if (!(list = list_window_parents( hwnd ))) return 0;
2606 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2607 else
2609 int count = 2;
2610 while (list[count]) count++;
2611 ret = list[count - 2]; /* get the one before the desktop */
2613 HeapFree( GetProcessHeap(), 0, list );
2614 break;
2616 case GA_ROOTOWNER:
2617 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2618 for (;;)
2620 HWND parent = GetParent( ret );
2621 if (!parent) break;
2622 ret = parent;
2624 break;
2626 return ret;
2630 /*****************************************************************
2631 * SetParent (USER32.@)
2633 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2635 WND *wndPtr;
2636 HWND retvalue, full_handle;
2637 BOOL was_visible;
2639 if (is_broadcast(hwnd) || is_broadcast(parent))
2641 SetLastError(ERROR_INVALID_PARAMETER);
2642 return 0;
2645 if (!parent) parent = GetDesktopWindow();
2646 else parent = WIN_GetFullHandle( parent );
2648 if (!IsWindow( parent ))
2650 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2651 return 0;
2654 /* Some applications try to set a child as a parent */
2655 if (IsChild(hwnd, parent))
2657 SetLastError( ERROR_INVALID_PARAMETER );
2658 return 0;
2661 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2662 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2664 hwnd = full_handle;
2666 if (USER_Driver.pSetParent)
2667 return USER_Driver.pSetParent( hwnd, parent );
2669 /* Windows hides the window first, then shows it again
2670 * including the WM_SHOWWINDOW messages and all */
2671 was_visible = ShowWindow( hwnd, SW_HIDE );
2673 if (!IsWindow( parent )) return 0;
2674 if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return 0;
2676 retvalue = wndPtr->parent; /* old parent */
2677 if (parent != retvalue)
2679 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2681 if (parent != GetDesktopWindow()) /* a child window */
2683 if (!(wndPtr->dwStyle & WS_CHILD))
2685 HMENU menu = (HMENU)SetWindowLongPtrW( hwnd, GWLP_ID, 0 );
2686 if (menu) DestroyMenu( menu );
2690 WIN_ReleasePtr( wndPtr );
2692 /* SetParent additionally needs to make hwnd the topmost window
2693 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2694 WM_WINDOWPOSCHANGED notification messages.
2696 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2697 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2698 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2699 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2700 return retvalue;
2704 /*******************************************************************
2705 * IsChild (USER32.@)
2707 BOOL WINAPI IsChild( HWND parent, HWND child )
2709 HWND *list = list_window_parents( child );
2710 int i;
2711 BOOL ret;
2713 if (!list) return FALSE;
2714 parent = WIN_GetFullHandle( parent );
2715 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2716 ret = (list[i] != 0);
2717 HeapFree( GetProcessHeap(), 0, list );
2718 return ret;
2722 /***********************************************************************
2723 * IsWindowVisible (USER32.@)
2725 BOOL WINAPI IsWindowVisible( HWND hwnd )
2727 HWND *list;
2728 BOOL retval;
2729 int i;
2731 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2732 if (!(list = list_window_parents( hwnd ))) return TRUE;
2733 for (i = 0; list[i]; i++)
2734 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2735 retval = !list[i];
2736 HeapFree( GetProcessHeap(), 0, list );
2737 return retval;
2741 /***********************************************************************
2742 * WIN_IsWindowDrawable
2744 * hwnd is drawable when it is visible, all parents are not
2745 * minimized, and it is itself not minimized unless we are
2746 * trying to draw its default class icon.
2748 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2750 HWND *list;
2751 BOOL retval;
2752 int i;
2753 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2755 if (!(style & WS_VISIBLE)) return FALSE;
2756 if ((style & WS_MINIMIZE) && icon && GetClassLongPtrW( hwnd, GCLP_HICON )) return FALSE;
2758 if (!(list = list_window_parents( hwnd ))) return TRUE;
2759 for (i = 0; list[i]; i++)
2760 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2761 break;
2762 retval = !list[i];
2763 HeapFree( GetProcessHeap(), 0, list );
2764 return retval;
2768 /*******************************************************************
2769 * GetTopWindow (USER32.@)
2771 HWND WINAPI GetTopWindow( HWND hwnd )
2773 if (!hwnd) hwnd = GetDesktopWindow();
2774 return GetWindow( hwnd, GW_CHILD );
2778 /*******************************************************************
2779 * GetWindow (USER32.@)
2781 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2783 HWND retval = 0;
2785 if (rel == GW_OWNER) /* this one may be available locally */
2787 WND *wndPtr = WIN_GetPtr( hwnd );
2788 if (!wndPtr)
2790 SetLastError( ERROR_INVALID_HANDLE );
2791 return 0;
2793 if (wndPtr != WND_OTHER_PROCESS)
2795 retval = wndPtr->owner;
2796 WIN_ReleasePtr( wndPtr );
2797 return retval;
2799 /* else fall through to server call */
2802 SERVER_START_REQ( get_window_tree )
2804 req->handle = hwnd;
2805 if (!wine_server_call_err( req ))
2807 switch(rel)
2809 case GW_HWNDFIRST:
2810 retval = reply->first_sibling;
2811 break;
2812 case GW_HWNDLAST:
2813 retval = reply->last_sibling;
2814 break;
2815 case GW_HWNDNEXT:
2816 retval = reply->next_sibling;
2817 break;
2818 case GW_HWNDPREV:
2819 retval = reply->prev_sibling;
2820 break;
2821 case GW_OWNER:
2822 retval = reply->owner;
2823 break;
2824 case GW_CHILD:
2825 retval = reply->first_child;
2826 break;
2830 SERVER_END_REQ;
2831 return retval;
2835 /*******************************************************************
2836 * ShowOwnedPopups (USER32.@)
2838 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2840 int count = 0;
2841 WND *pWnd;
2842 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2844 if (!win_array) return TRUE;
2846 while (win_array[count]) count++;
2847 while (--count >= 0)
2849 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2850 if (!(pWnd = WIN_GetPtr( win_array[count] ))) continue;
2851 if (pWnd == WND_OTHER_PROCESS) continue;
2853 if (pWnd->dwStyle & WS_POPUP)
2855 if (fShow)
2857 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2859 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2860 WIN_ReleasePtr( pWnd );
2861 /* In Windows, ShowOwnedPopups(TRUE) generates
2862 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2863 * regardless of the state of the owner
2865 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2866 continue;
2869 else
2871 if (pWnd->dwStyle & WS_VISIBLE)
2873 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2874 WIN_ReleasePtr( pWnd );
2875 /* In Windows, ShowOwnedPopups(FALSE) generates
2876 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2877 * regardless of the state of the owner
2879 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2880 continue;
2884 WIN_ReleasePtr( pWnd );
2886 HeapFree( GetProcessHeap(), 0, win_array );
2887 return TRUE;
2891 /*******************************************************************
2892 * GetLastActivePopup (USER32.@)
2894 HWND WINAPI GetLastActivePopup( HWND hwnd )
2896 HWND retval = hwnd;
2898 SERVER_START_REQ( get_window_info )
2900 req->handle = hwnd;
2901 if (!wine_server_call_err( req )) retval = reply->last_active;
2903 SERVER_END_REQ;
2904 return retval;
2908 /*******************************************************************
2909 * WIN_ListChildren
2911 * Build an array of the children of a given window. The array must be
2912 * freed with HeapFree. Returns NULL when no windows are found.
2914 HWND *WIN_ListChildren( HWND hwnd )
2916 return list_window_children( hwnd, 0, 0 );
2920 /*******************************************************************
2921 * EnumWindows (USER32.@)
2923 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2925 HWND *list;
2926 BOOL ret = TRUE;
2927 int i, iWndsLocks;
2929 /* We have to build a list of all windows first, to avoid */
2930 /* unpleasant side-effects, for instance if the callback */
2931 /* function changes the Z-order of the windows. */
2933 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2935 /* Now call the callback function for every window */
2937 iWndsLocks = WIN_SuspendWndsLock();
2938 for (i = 0; list[i]; i++)
2940 /* Make sure that the window still exists */
2941 if (!IsWindow( list[i] )) continue;
2942 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2944 WIN_RestoreWndsLock(iWndsLocks);
2945 HeapFree( GetProcessHeap(), 0, list );
2946 return ret;
2950 /**********************************************************************
2951 * EnumThreadWindows (USER32.@)
2953 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2955 HWND *list;
2956 int i, iWndsLocks;
2958 if (!(list = list_window_children( GetDesktopWindow(), 0, id ))) return TRUE;
2960 /* Now call the callback function for every window */
2962 iWndsLocks = WIN_SuspendWndsLock();
2963 for (i = 0; list[i]; i++)
2964 if (!func( list[i], lParam )) break;
2965 WIN_RestoreWndsLock(iWndsLocks);
2966 HeapFree( GetProcessHeap(), 0, list );
2967 return TRUE;
2971 /**********************************************************************
2972 * WIN_EnumChildWindows
2974 * Helper function for EnumChildWindows().
2976 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2978 HWND *childList;
2979 BOOL ret = FALSE;
2981 for ( ; *list; list++)
2983 /* Make sure that the window still exists */
2984 if (!IsWindow( *list )) continue;
2985 /* skip owned windows */
2986 if (GetWindow( *list, GW_OWNER )) continue;
2987 /* Build children list first */
2988 childList = WIN_ListChildren( *list );
2990 ret = func( *list, lParam );
2992 if (childList)
2994 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2995 HeapFree( GetProcessHeap(), 0, childList );
2997 if (!ret) return FALSE;
2999 return TRUE;
3003 /**********************************************************************
3004 * EnumChildWindows (USER32.@)
3006 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
3008 HWND *list;
3009 int iWndsLocks;
3011 if (!(list = WIN_ListChildren( parent ))) return FALSE;
3012 iWndsLocks = WIN_SuspendWndsLock();
3013 WIN_EnumChildWindows( list, func, lParam );
3014 WIN_RestoreWndsLock(iWndsLocks);
3015 HeapFree( GetProcessHeap(), 0, list );
3016 return TRUE;
3020 /*******************************************************************
3021 * AnyPopup (USER.52)
3023 BOOL16 WINAPI AnyPopup16(void)
3025 return AnyPopup();
3029 /*******************************************************************
3030 * AnyPopup (USER32.@)
3032 BOOL WINAPI AnyPopup(void)
3034 int i;
3035 BOOL retvalue;
3036 HWND *list = WIN_ListChildren( GetDesktopWindow() );
3038 if (!list) return FALSE;
3039 for (i = 0; list[i]; i++)
3041 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
3043 retvalue = (list[i] != 0);
3044 HeapFree( GetProcessHeap(), 0, list );
3045 return retvalue;
3049 /*******************************************************************
3050 * FlashWindow (USER32.@)
3052 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3054 WND *wndPtr;
3056 TRACE("%p\n", hWnd);
3058 if (IsIconic( hWnd ))
3060 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3062 wndPtr = WIN_GetPtr(hWnd);
3063 if (!wndPtr || wndPtr == WND_OTHER_PROCESS) return FALSE;
3064 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3066 wndPtr->flags |= WIN_NCACTIVATED;
3068 else
3070 wndPtr->flags &= ~WIN_NCACTIVATED;
3072 WIN_ReleasePtr( wndPtr );
3073 return TRUE;
3075 else
3077 WPARAM wparam;
3079 wndPtr = WIN_GetPtr(hWnd);
3080 if (!wndPtr || wndPtr == WND_OTHER_PROCESS) return FALSE;
3081 hWnd = wndPtr->hwndSelf; /* make it a full handle */
3083 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3084 else wparam = (hWnd == GetForegroundWindow());
3086 WIN_ReleasePtr( wndPtr );
3087 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3088 return wparam;
3092 /*******************************************************************
3093 * FlashWindowEx (USER32.@)
3095 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
3097 FIXME("%p\n", pfwi);
3098 return TRUE;
3101 /*******************************************************************
3102 * GetWindowContextHelpId (USER32.@)
3104 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3106 DWORD retval;
3107 WND *wnd = WIN_GetPtr( hwnd );
3108 if (!wnd) return 0;
3109 if (wnd == WND_OTHER_PROCESS)
3111 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3112 return 0;
3114 retval = wnd->helpContext;
3115 WIN_ReleasePtr( wnd );
3116 return retval;
3120 /*******************************************************************
3121 * SetWindowContextHelpId (USER32.@)
3123 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3125 WND *wnd = WIN_GetPtr( hwnd );
3126 if (!wnd) return FALSE;
3127 if (wnd == WND_OTHER_PROCESS)
3129 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3130 return 0;
3132 wnd->helpContext = id;
3133 WIN_ReleasePtr( wnd );
3134 return TRUE;
3138 /*******************************************************************
3139 * DragDetect (USER32.@)
3141 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3143 MSG msg;
3144 RECT rect;
3146 rect.left = pt.x - wDragWidth;
3147 rect.right = pt.x + wDragWidth;
3149 rect.top = pt.y - wDragHeight;
3150 rect.bottom = pt.y + wDragHeight;
3152 SetCapture(hWnd);
3154 while(1)
3156 while (PeekMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ))
3158 if( msg.message == WM_LBUTTONUP )
3160 ReleaseCapture();
3161 return 0;
3163 if( msg.message == WM_MOUSEMOVE )
3165 POINT tmp;
3166 tmp.x = LOWORD(msg.lParam);
3167 tmp.y = HIWORD(msg.lParam);
3168 if( !PtInRect( &rect, tmp ))
3170 ReleaseCapture();
3171 return 1;
3175 WaitMessage();
3177 return 0;
3180 /******************************************************************************
3181 * GetWindowModuleFileNameA (USER32.@)
3183 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3185 FIXME("GetWindowModuleFileNameA(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3186 hwnd, lpszFileName, cchFileNameMax);
3187 return 0;
3190 /******************************************************************************
3191 * GetWindowModuleFileNameW (USER32.@)
3193 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR lpszFileName, UINT cchFileNameMax)
3195 FIXME("GetWindowModuleFileNameW(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3196 hwnd, lpszFileName, cchFileNameMax);
3197 return 0;
3200 /******************************************************************************
3201 * GetWindowInfo (USER32.@)
3203 * Note: tests show that Windows doesn't check cbSize of the structure.
3205 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3207 if (!pwi) return FALSE;
3208 if (!IsWindow(hwnd)) return FALSE;
3210 GetWindowRect(hwnd, &pwi->rcWindow);
3211 GetClientRect(hwnd, &pwi->rcClient);
3212 /* translate to screen coordinates */
3213 MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3215 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3216 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3217 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3219 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3220 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3222 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3223 pwi->wCreatorVersion = 0x0400;
3225 return TRUE;
3228 /******************************************************************************
3229 * SwitchDesktop (USER32.@)
3231 * NOTES: Sets the current input or interactive desktop.
3233 BOOL WINAPI SwitchDesktop( HDESK hDesktop)
3235 FIXME("SwitchDesktop(hwnd %p) stub!\n", hDesktop);
3236 return TRUE;