push 9e645869891abdc47a8701768b7a401b196a1e38
[wine/hacks.git] / dlls / user32 / win.c
blob730b2c2d70c8a2845a69ff29d0acf2c349cc609c
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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 "controls.h"
38 #include "winerror.h"
39 #include "wine/debug.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(win);
43 #define NB_USER_HANDLES ((LAST_USER_HANDLE - FIRST_USER_HANDLE + 1) >> 1)
44 #define USER_HANDLE_TO_INDEX(hwnd) ((LOWORD(hwnd) - FIRST_USER_HANDLE) >> 1)
46 /**********************************************************************/
48 /* helper for Get/SetWindowLong */
49 static inline LONG_PTR get_win_data( const void *ptr, UINT size )
51 if (size == sizeof(WORD))
53 WORD ret;
54 memcpy( &ret, ptr, sizeof(ret) );
55 return ret;
57 else if (size == sizeof(DWORD))
59 DWORD ret;
60 memcpy( &ret, ptr, sizeof(ret) );
61 return ret;
63 else
65 LONG_PTR ret;
66 memcpy( &ret, ptr, sizeof(ret) );
67 return ret;
71 /* helper for Get/SetWindowLong */
72 static inline void set_win_data( void *ptr, LONG_PTR val, UINT size )
74 if (size == sizeof(WORD))
76 WORD newval = val;
77 memcpy( ptr, &newval, sizeof(newval) );
79 else if (size == sizeof(DWORD))
81 DWORD newval = val;
82 memcpy( ptr, &newval, sizeof(newval) );
84 else
86 memcpy( ptr, &val, sizeof(val) );
91 static void *user_handles[NB_USER_HANDLES];
93 /***********************************************************************
94 * create_window_handle
96 * Create a window handle with the server.
98 static WND *create_window_handle( HWND parent, HWND owner, LPCWSTR name,
99 HINSTANCE instance, BOOL unicode )
101 WORD index;
102 WND *win;
103 HWND full_parent = 0, full_owner = 0;
104 struct tagCLASS *class = NULL;
105 user_handle_t handle = 0;
106 int extra_bytes = 0;
108 /* if 16-bit instance, map to module handle */
109 if (instance && !HIWORD(instance))
110 instance = HINSTANCE_32(GetExePtr(HINSTANCE_16(instance)));
112 SERVER_START_REQ( create_window )
114 req->parent = parent;
115 req->owner = owner;
116 req->instance = instance;
117 if (!(req->atom = get_int_atom_value( name )) && name)
118 wine_server_add_data( req, name, strlenW(name)*sizeof(WCHAR) );
119 if (!wine_server_call_err( req ))
121 handle = reply->handle;
122 full_parent = reply->parent;
123 full_owner = reply->owner;
124 extra_bytes = reply->extra;
125 class = reply->class_ptr;
128 SERVER_END_REQ;
130 if (!handle)
132 WARN( "error %d creating window\n", GetLastError() );
133 return NULL;
136 if (!(win = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
137 sizeof(WND) + extra_bytes - sizeof(win->wExtra) )))
139 SERVER_START_REQ( destroy_window )
141 req->handle = handle;
142 wine_server_call( req );
144 SERVER_END_REQ;
145 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
146 return NULL;
149 if (!parent) /* if parent is 0 we don't have a desktop window yet */
151 struct user_thread_info *thread_info = get_user_thread_info();
153 if (name == (LPCWSTR)DESKTOP_CLASS_ATOM)
155 if (!thread_info->top_window) thread_info->top_window = full_parent ? full_parent : handle;
156 else assert( full_parent == thread_info->top_window );
157 if (full_parent && !USER_Driver->pCreateDesktopWindow( thread_info->top_window ))
158 ERR( "failed to create desktop window\n" );
160 else /* HWND_MESSAGE parent */
162 if (!thread_info->msg_window && !full_parent) thread_info->msg_window = handle;
166 USER_Lock();
168 index = USER_HANDLE_TO_INDEX(handle);
169 assert( index < NB_USER_HANDLES );
170 user_handles[index] = win;
171 win->hwndSelf = handle;
172 win->parent = full_parent;
173 win->owner = full_owner;
174 win->class = class;
175 win->winproc = get_class_winproc( class );
176 win->dwMagic = WND_MAGIC;
177 win->cbWndExtra = extra_bytes;
178 if (WINPROC_IsUnicode( win->winproc, unicode )) win->flags |= WIN_ISUNICODE;
179 return win;
183 /***********************************************************************
184 * free_window_handle
186 * Free a window handle.
188 static WND *free_window_handle( HWND hwnd )
190 WND *ptr;
191 WORD index = USER_HANDLE_TO_INDEX(hwnd);
193 if (index >= NB_USER_HANDLES) return NULL;
194 USER_Lock();
195 if ((ptr = user_handles[index]))
197 SERVER_START_REQ( destroy_window )
199 req->handle = hwnd;
200 if (!wine_server_call_err( req ))
202 user_handles[index] = NULL;
203 ptr->dwMagic = 0;
205 else
206 ptr = NULL;
208 SERVER_END_REQ;
210 USER_Unlock();
211 HeapFree( GetProcessHeap(), 0, ptr );
212 return ptr;
216 /*******************************************************************
217 * list_window_children
219 * Build an array of the children of a given window. The array must be
220 * freed with HeapFree. Returns NULL when no windows are found.
222 static HWND *list_window_children( HDESK desktop, HWND hwnd, LPCWSTR class, DWORD tid )
224 HWND *list;
225 int size = 128;
226 ATOM atom = get_int_atom_value( class );
228 /* empty class is not the same as NULL class */
229 if (!atom && class && !class[0]) return NULL;
231 for (;;)
233 int count = 0;
235 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
237 SERVER_START_REQ( get_window_children )
239 req->desktop = desktop;
240 req->parent = hwnd;
241 req->tid = tid;
242 req->atom = atom;
243 if (!atom && class) wine_server_add_data( req, class, strlenW(class)*sizeof(WCHAR) );
244 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
245 if (!wine_server_call( req )) count = reply->count;
247 SERVER_END_REQ;
248 if (count && count < size)
250 list[count] = 0;
251 return list;
253 HeapFree( GetProcessHeap(), 0, list );
254 if (!count) break;
255 size = count + 1; /* restart with a large enough buffer */
257 return NULL;
261 /*******************************************************************
262 * list_window_parents
264 * Build an array of all parents of a given window, starting with
265 * the immediate parent. The array must be freed with HeapFree.
267 static HWND *list_window_parents( HWND hwnd )
269 WND *win;
270 HWND current, *list;
271 int pos = 0, size = 16, count = 0;
273 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
275 current = hwnd;
276 for (;;)
278 if (!(win = WIN_GetPtr( current ))) goto empty;
279 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
280 if (win == WND_DESKTOP)
282 if (!pos) goto empty;
283 list[pos] = 0;
284 return list;
286 list[pos] = current = win->parent;
287 WIN_ReleasePtr( win );
288 if (!current) return list;
289 if (++pos == size - 1)
291 /* need to grow the list */
292 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
293 if (!new_list) goto empty;
294 list = new_list;
295 size += 16;
299 /* at least one parent belongs to another process, have to query the server */
301 for (;;)
303 count = 0;
304 SERVER_START_REQ( get_window_parents )
306 req->handle = hwnd;
307 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
308 if (!wine_server_call( req )) count = reply->count;
310 SERVER_END_REQ;
311 if (!count) goto empty;
312 if (size > count)
314 list[count] = 0;
315 return list;
317 HeapFree( GetProcessHeap(), 0, list );
318 size = count + 1;
319 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
322 empty:
323 HeapFree( GetProcessHeap(), 0, list );
324 return NULL;
328 /*******************************************************************
329 * send_parent_notify
331 static void send_parent_notify( HWND hwnd, UINT msg )
333 if ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_CHILD | WS_POPUP)) == WS_CHILD &&
334 !(GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY))
336 HWND parent = GetParent(hwnd);
337 if (parent && parent != GetDesktopWindow())
338 SendMessageW( parent, WM_PARENTNOTIFY,
339 MAKEWPARAM( msg, GetWindowLongPtrW( hwnd, GWLP_ID )), (LPARAM)hwnd );
344 /*******************************************************************
345 * get_server_window_text
347 * Retrieve the window text from the server.
349 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
351 size_t len = 0;
353 SERVER_START_REQ( get_window_text )
355 req->handle = hwnd;
356 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
357 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
359 SERVER_END_REQ;
360 text[len / sizeof(WCHAR)] = 0;
364 /*******************************************************************
365 * get_hwnd_message_parent
367 * Return the parent for HWND_MESSAGE windows.
369 HWND get_hwnd_message_parent(void)
371 struct user_thread_info *thread_info = get_user_thread_info();
373 if (!thread_info->msg_window) GetDesktopWindow(); /* trigger creation */
374 return thread_info->msg_window;
378 /*******************************************************************
379 * is_desktop_window
381 * Check if window is the desktop or the HWND_MESSAGE top parent.
383 BOOL is_desktop_window( HWND hwnd )
385 struct user_thread_info *thread_info = get_user_thread_info();
387 if (!hwnd) return FALSE;
388 if (hwnd == thread_info->top_window) return TRUE;
389 if (hwnd == thread_info->msg_window) return TRUE;
391 if (!HIWORD(hwnd) || HIWORD(hwnd) == 0xffff)
393 if (LOWORD(thread_info->top_window) == LOWORD(hwnd)) return TRUE;
394 if (LOWORD(thread_info->msg_window) == LOWORD(hwnd)) return TRUE;
396 return FALSE;
400 /***********************************************************************
401 * WIN_GetPtr
403 * Return a pointer to the WND structure if local to the process,
404 * or WND_OTHER_PROCESS if handle may be valid in other process.
405 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
407 WND *WIN_GetPtr( HWND hwnd )
409 WND * ptr;
410 WORD index = USER_HANDLE_TO_INDEX(hwnd);
412 if (index >= NB_USER_HANDLES) return NULL;
414 USER_Lock();
415 if ((ptr = user_handles[index]))
417 if (ptr->dwMagic == WND_MAGIC &&
418 (hwnd == ptr->hwndSelf || !HIWORD(hwnd) || HIWORD(hwnd) == 0xffff))
419 return ptr;
420 ptr = NULL;
422 else if (is_desktop_window( hwnd )) ptr = WND_DESKTOP;
423 else ptr = WND_OTHER_PROCESS;
424 USER_Unlock();
425 return ptr;
429 /***********************************************************************
430 * WIN_IsCurrentProcess
432 * Check whether a given window belongs to the current process (and return the full handle).
434 HWND WIN_IsCurrentProcess( HWND hwnd )
436 WND *ptr;
437 HWND ret;
439 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
440 ret = ptr->hwndSelf;
441 WIN_ReleasePtr( ptr );
442 return ret;
446 /***********************************************************************
447 * WIN_IsCurrentThread
449 * Check whether a given window belongs to the current thread (and return the full handle).
451 HWND WIN_IsCurrentThread( HWND hwnd )
453 WND *ptr;
454 HWND ret = 0;
456 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
457 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
458 WIN_ReleasePtr( ptr );
459 return ret;
463 /***********************************************************************
464 * WIN_Handle32
466 * Convert a 16-bit window handle to a full 32-bit handle.
468 HWND WIN_Handle32( HWND16 hwnd16 )
470 WND *ptr;
471 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
473 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
474 /* do sign extension for -2 and -3 */
475 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
477 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
479 if (ptr == WND_DESKTOP)
481 if (LOWORD(hwnd) == LOWORD(GetDesktopWindow())) return GetDesktopWindow();
482 else return get_hwnd_message_parent();
485 if (ptr != WND_OTHER_PROCESS)
487 hwnd = ptr->hwndSelf;
488 WIN_ReleasePtr( ptr );
490 else /* may belong to another process */
492 SERVER_START_REQ( get_window_info )
494 req->handle = hwnd;
495 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
497 SERVER_END_REQ;
499 return hwnd;
503 /***********************************************************************
504 * WIN_SetOwner
506 * Change the owner of a window.
508 HWND WIN_SetOwner( HWND hwnd, HWND owner )
510 WND *win = WIN_GetPtr( hwnd );
511 HWND ret = 0;
513 if (!win || win == WND_DESKTOP) return 0;
514 if (win == WND_OTHER_PROCESS)
516 if (IsWindow(hwnd)) ERR( "cannot set owner %p on other process window %p\n", owner, hwnd );
517 return 0;
519 SERVER_START_REQ( set_window_owner )
521 req->handle = hwnd;
522 req->owner = owner;
523 if (!wine_server_call( req ))
525 win->owner = reply->full_owner;
526 ret = reply->prev_owner;
529 SERVER_END_REQ;
530 WIN_ReleasePtr( win );
531 return ret;
535 /***********************************************************************
536 * WIN_SetStyle
538 * Change the style of a window.
540 ULONG WIN_SetStyle( HWND hwnd, ULONG set_bits, ULONG clear_bits )
542 BOOL ok;
543 STYLESTRUCT style;
544 WND *win = WIN_GetPtr( hwnd );
546 if (!win || win == WND_DESKTOP) return 0;
547 if (win == WND_OTHER_PROCESS)
549 if (IsWindow(hwnd))
550 ERR( "cannot set style %x/%x on other process window %p\n",
551 set_bits, clear_bits, hwnd );
552 return 0;
554 style.styleOld = win->dwStyle;
555 style.styleNew = (win->dwStyle | set_bits) & ~clear_bits;
556 if (style.styleNew == style.styleOld)
558 WIN_ReleasePtr( win );
559 return style.styleNew;
561 SERVER_START_REQ( set_window_info )
563 req->handle = hwnd;
564 req->flags = SET_WIN_STYLE;
565 req->style = style.styleNew;
566 req->extra_offset = -1;
567 if ((ok = !wine_server_call( req )))
569 style.styleOld = reply->old_style;
570 win->dwStyle = style.styleNew;
573 SERVER_END_REQ;
574 WIN_ReleasePtr( win );
575 if (ok)
577 USER_Driver->pSetWindowStyle( hwnd, GWL_STYLE, &style );
578 if ((style.styleOld ^ style.styleNew) & WS_VISIBLE) invalidate_dce( hwnd, NULL );
580 return style.styleOld;
584 /***********************************************************************
585 * WIN_GetRectangles
587 * Get the window and client rectangles.
589 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
591 WND *win = WIN_GetPtr( hwnd );
592 BOOL ret = TRUE;
594 if (!win) return FALSE;
595 if (win == WND_DESKTOP)
597 RECT rect;
598 rect.left = rect.top = 0;
599 if (hwnd == get_hwnd_message_parent())
601 rect.right = 100;
602 rect.bottom = 100;
604 else
606 rect.right = GetSystemMetrics(SM_CXSCREEN);
607 rect.bottom = GetSystemMetrics(SM_CYSCREEN);
609 if (rectWindow) *rectWindow = rect;
610 if (rectClient) *rectClient = rect;
612 else if (win == WND_OTHER_PROCESS)
614 SERVER_START_REQ( get_window_rectangles )
616 req->handle = hwnd;
617 if ((ret = !wine_server_call( req )))
619 if (rectWindow)
621 rectWindow->left = reply->window.left;
622 rectWindow->top = reply->window.top;
623 rectWindow->right = reply->window.right;
624 rectWindow->bottom = reply->window.bottom;
626 if (rectClient)
628 rectClient->left = reply->client.left;
629 rectClient->top = reply->client.top;
630 rectClient->right = reply->client.right;
631 rectClient->bottom = reply->client.bottom;
635 SERVER_END_REQ;
637 else
639 if (rectWindow) *rectWindow = win->rectWindow;
640 if (rectClient) *rectClient = win->rectClient;
641 WIN_ReleasePtr( win );
643 return ret;
647 /***********************************************************************
648 * WIN_DestroyWindow
650 * Destroy storage associated to a window. "Internals" p.358
652 LRESULT WIN_DestroyWindow( HWND hwnd )
654 WND *wndPtr;
655 HWND *list;
656 HMENU menu = 0, sys_menu;
657 HWND icon_title;
659 TRACE("%p\n", hwnd );
661 /* free child windows */
662 if ((list = WIN_ListChildren( hwnd )))
664 int i;
665 for (i = 0; list[i]; i++)
667 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
668 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
670 HeapFree( GetProcessHeap(), 0, list );
673 /* Unlink now so we won't bother with the children later on */
674 SERVER_START_REQ( set_parent )
676 req->handle = hwnd;
677 req->parent = 0;
678 wine_server_call( req );
680 SERVER_END_REQ;
683 * Send the WM_NCDESTROY to the window being destroyed.
685 SendMessageW( hwnd, WM_NCDESTROY, 0, 0 );
687 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
689 /* free resources associated with the window */
691 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
692 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
693 menu = (HMENU)wndPtr->wIDmenu;
694 sys_menu = wndPtr->hSysMenu;
695 free_dce( wndPtr->dce, hwnd );
696 wndPtr->dce = NULL;
697 icon_title = wndPtr->icon_title;
698 WIN_ReleasePtr( wndPtr );
700 if (icon_title) DestroyWindow( icon_title );
701 if (menu) DestroyMenu( menu );
702 if (sys_menu) DestroyMenu( sys_menu );
704 USER_Driver->pDestroyWindow( hwnd );
706 free_window_handle( hwnd );
707 return 0;
710 /***********************************************************************
711 * WIN_DestroyThreadWindows
713 * Destroy all children of 'wnd' owned by the current thread.
715 void WIN_DestroyThreadWindows( HWND hwnd )
717 HWND *list;
718 int i;
720 if (!(list = WIN_ListChildren( hwnd ))) return;
721 for (i = 0; list[i]; i++)
723 if (WIN_IsCurrentThread( list[i] ))
724 DestroyWindow( list[i] );
725 else
726 WIN_DestroyThreadWindows( list[i] );
728 HeapFree( GetProcessHeap(), 0, list );
732 /***********************************************************************
733 * WIN_FixCoordinates
735 * Fix the coordinates - Helper for WIN_CreateWindowEx.
736 * returns default show mode in sw.
738 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
740 #define IS_DEFAULT(x) ((x) == CW_USEDEFAULT || (x) == CW_USEDEFAULT16)
741 POINT pos[2];
743 if (cs->dwExStyle & WS_EX_MDICHILD)
745 UINT id = 0;
747 MDI_CalcDefaultChildPos(cs->hwndParent, -1, pos, 0, &id);
748 if (!(cs->style & WS_POPUP)) cs->hMenu = ULongToHandle(id);
750 TRACE("MDI child id %04x\n", id);
753 if (cs->style & (WS_CHILD | WS_POPUP))
755 if (cs->dwExStyle & WS_EX_MDICHILD)
757 if (IS_DEFAULT(cs->x))
759 cs->x = pos[0].x;
760 cs->y = pos[0].y;
762 if (IS_DEFAULT(cs->cx) || !cs->cx) cs->cx = pos[1].x;
763 if (IS_DEFAULT(cs->cy) || !cs->cy) cs->cy = pos[1].y;
765 else
767 if (IS_DEFAULT(cs->x)) cs->x = cs->y = 0;
768 if (IS_DEFAULT(cs->cx)) cs->cx = cs->cy = 0;
771 else /* overlapped window */
773 HMONITOR monitor;
774 MONITORINFO mon_info;
775 STARTUPINFOW info;
777 if (!IS_DEFAULT(cs->x) && !IS_DEFAULT(cs->cx) && !IS_DEFAULT(cs->cy)) return;
779 monitor = MonitorFromWindow( cs->hwndParent, MONITOR_DEFAULTTOPRIMARY );
780 mon_info.cbSize = sizeof(mon_info);
781 GetMonitorInfoW( monitor, &mon_info );
782 GetStartupInfoW( &info );
784 if (IS_DEFAULT(cs->x))
786 if (!IS_DEFAULT(cs->y)) *sw = cs->y;
787 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : mon_info.rcWork.left;
788 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : mon_info.rcWork.top;
791 if (IS_DEFAULT(cs->cx))
793 if (info.dwFlags & STARTF_USESIZE)
795 cs->cx = info.dwXSize;
796 cs->cy = info.dwYSize;
798 else
800 cs->cx = (mon_info.rcWork.right - mon_info.rcWork.left) * 3 / 4 - cs->x;
801 cs->cy = (mon_info.rcWork.bottom - mon_info.rcWork.top) * 3 / 4 - cs->y;
804 /* neither x nor cx are default. Check the y values .
805 * In the trace we see Outlook and Outlook Express using
806 * cy set to CW_USEDEFAULT when opening the address book.
808 else if (IS_DEFAULT(cs->cy))
810 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
811 cs->cy = (mon_info.rcWork.bottom - mon_info.rcWork.top) * 3 / 4 - cs->y;
814 #undef IS_DEFAULT
817 /***********************************************************************
818 * dump_window_styles
820 static void dump_window_styles( DWORD style, DWORD exstyle )
822 TRACE( "style:" );
823 if(style & WS_POPUP) TRACE(" WS_POPUP");
824 if(style & WS_CHILD) TRACE(" WS_CHILD");
825 if(style & WS_MINIMIZE) TRACE(" WS_MINIMIZE");
826 if(style & WS_VISIBLE) TRACE(" WS_VISIBLE");
827 if(style & WS_DISABLED) TRACE(" WS_DISABLED");
828 if(style & WS_CLIPSIBLINGS) TRACE(" WS_CLIPSIBLINGS");
829 if(style & WS_CLIPCHILDREN) TRACE(" WS_CLIPCHILDREN");
830 if(style & WS_MAXIMIZE) TRACE(" WS_MAXIMIZE");
831 if((style & WS_CAPTION) == WS_CAPTION) TRACE(" WS_CAPTION");
832 else
834 if(style & WS_BORDER) TRACE(" WS_BORDER");
835 if(style & WS_DLGFRAME) TRACE(" WS_DLGFRAME");
837 if(style & WS_VSCROLL) TRACE(" WS_VSCROLL");
838 if(style & WS_HSCROLL) TRACE(" WS_HSCROLL");
839 if(style & WS_SYSMENU) TRACE(" WS_SYSMENU");
840 if(style & WS_THICKFRAME) TRACE(" WS_THICKFRAME");
841 if (style & WS_CHILD)
843 if(style & WS_GROUP) TRACE(" WS_GROUP");
844 if(style & WS_TABSTOP) TRACE(" WS_TABSTOP");
846 else
848 if(style & WS_MINIMIZEBOX) TRACE(" WS_MINIMIZEBOX");
849 if(style & WS_MAXIMIZEBOX) TRACE(" WS_MAXIMIZEBOX");
852 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
853 #define DUMPED_STYLES \
854 (WS_POPUP | \
855 WS_CHILD | \
856 WS_MINIMIZE | \
857 WS_VISIBLE | \
858 WS_DISABLED | \
859 WS_CLIPSIBLINGS | \
860 WS_CLIPCHILDREN | \
861 WS_MAXIMIZE | \
862 WS_BORDER | \
863 WS_DLGFRAME | \
864 WS_VSCROLL | \
865 WS_HSCROLL | \
866 WS_SYSMENU | \
867 WS_THICKFRAME | \
868 WS_GROUP | \
869 WS_TABSTOP | \
870 WS_MINIMIZEBOX | \
871 WS_MAXIMIZEBOX)
873 if(style & ~DUMPED_STYLES) TRACE(" %08lx", style & ~DUMPED_STYLES);
874 TRACE("\n");
875 #undef DUMPED_STYLES
877 TRACE( "exstyle:" );
878 if(exstyle & WS_EX_DLGMODALFRAME) TRACE(" WS_EX_DLGMODALFRAME");
879 if(exstyle & WS_EX_DRAGDETECT) TRACE(" WS_EX_DRAGDETECT");
880 if(exstyle & WS_EX_NOPARENTNOTIFY) TRACE(" WS_EX_NOPARENTNOTIFY");
881 if(exstyle & WS_EX_TOPMOST) TRACE(" WS_EX_TOPMOST");
882 if(exstyle & WS_EX_ACCEPTFILES) TRACE(" WS_EX_ACCEPTFILES");
883 if(exstyle & WS_EX_TRANSPARENT) TRACE(" WS_EX_TRANSPARENT");
884 if(exstyle & WS_EX_MDICHILD) TRACE(" WS_EX_MDICHILD");
885 if(exstyle & WS_EX_TOOLWINDOW) TRACE(" WS_EX_TOOLWINDOW");
886 if(exstyle & WS_EX_WINDOWEDGE) TRACE(" WS_EX_WINDOWEDGE");
887 if(exstyle & WS_EX_CLIENTEDGE) TRACE(" WS_EX_CLIENTEDGE");
888 if(exstyle & WS_EX_CONTEXTHELP) TRACE(" WS_EX_CONTEXTHELP");
889 if(exstyle & WS_EX_RIGHT) TRACE(" WS_EX_RIGHT");
890 if(exstyle & WS_EX_RTLREADING) TRACE(" WS_EX_RTLREADING");
891 if(exstyle & WS_EX_LEFTSCROLLBAR) TRACE(" WS_EX_LEFTSCROLLBAR");
892 if(exstyle & WS_EX_CONTROLPARENT) TRACE(" WS_EX_CONTROLPARENT");
893 if(exstyle & WS_EX_STATICEDGE) TRACE(" WS_EX_STATICEDGE");
894 if(exstyle & WS_EX_APPWINDOW) TRACE(" WS_EX_APPWINDOW");
895 if(exstyle & WS_EX_LAYERED) TRACE(" WS_EX_LAYERED");
897 #define DUMPED_EX_STYLES \
898 (WS_EX_DLGMODALFRAME | \
899 WS_EX_DRAGDETECT | \
900 WS_EX_NOPARENTNOTIFY | \
901 WS_EX_TOPMOST | \
902 WS_EX_ACCEPTFILES | \
903 WS_EX_TRANSPARENT | \
904 WS_EX_MDICHILD | \
905 WS_EX_TOOLWINDOW | \
906 WS_EX_WINDOWEDGE | \
907 WS_EX_CLIENTEDGE | \
908 WS_EX_CONTEXTHELP | \
909 WS_EX_RIGHT | \
910 WS_EX_RTLREADING | \
911 WS_EX_LEFTSCROLLBAR | \
912 WS_EX_CONTROLPARENT | \
913 WS_EX_STATICEDGE | \
914 WS_EX_APPWINDOW | \
915 WS_EX_LAYERED)
917 if(exstyle & ~DUMPED_EX_STYLES) TRACE(" %08lx", exstyle & ~DUMPED_EX_STYLES);
918 TRACE("\n");
919 #undef DUMPED_EX_STYLES
923 /***********************************************************************
924 * WIN_CreateWindowEx
926 * Implementation of CreateWindowEx().
928 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, LPCWSTR className, UINT flags )
930 INT cx, cy, style, sw = SW_SHOW;
931 LRESULT result;
932 RECT rect;
933 WND *wndPtr;
934 HWND hwnd, parent, owner, top_child = 0;
935 BOOL unicode = (flags & WIN_ISUNICODE) != 0;
936 MDICREATESTRUCTA mdi_cs;
937 CBT_CREATEWNDA cbtc;
938 CREATESTRUCTA cbcs;
940 TRACE("%s %s ex=%08x style=%08x %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
941 unicode ? debugstr_w((LPCWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
942 debugstr_w(className),
943 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
944 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
945 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
947 /* Fix the styles for MDI children */
948 if (cs->dwExStyle & WS_EX_MDICHILD)
950 UINT flags = 0;
952 wndPtr = WIN_GetPtr(cs->hwndParent);
953 if (wndPtr && wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
955 flags = wndPtr->flags;
956 WIN_ReleasePtr(wndPtr);
959 if (!(flags & WIN_ISMDICLIENT))
961 WARN("WS_EX_MDICHILD, but parent %p is not MDIClient\n", cs->hwndParent);
962 return 0;
965 /* cs->lpCreateParams of WM_[NC]CREATE is different for MDI children.
966 * MDICREATESTRUCT members have the originally passed values.
968 * Note: we rely on the fact that MDICREATESTRUCTA and MDICREATESTRUCTW
969 * have the same layout.
971 mdi_cs.szClass = cs->lpszClass;
972 mdi_cs.szTitle = cs->lpszName;
973 mdi_cs.hOwner = cs->hInstance;
974 mdi_cs.x = cs->x;
975 mdi_cs.y = cs->y;
976 mdi_cs.cx = cs->cx;
977 mdi_cs.cy = cs->cy;
978 mdi_cs.style = cs->style;
979 mdi_cs.lParam = (LPARAM)cs->lpCreateParams;
981 cs->lpCreateParams = (LPVOID)&mdi_cs;
983 if (GetWindowLongW(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
985 if (cs->style & WS_POPUP)
987 TRACE("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n");
988 return 0;
990 cs->style |= WS_CHILD | WS_CLIPSIBLINGS;
992 else
994 cs->style &= ~WS_POPUP;
995 cs->style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
996 WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
999 top_child = GetWindow(cs->hwndParent, GW_CHILD);
1001 if (top_child)
1003 /* Restore current maximized child */
1004 if((cs->style & WS_VISIBLE) && IsZoomed(top_child))
1006 TRACE("Restoring current maximized child %p\n", top_child);
1007 SendMessageW( top_child, WM_SETREDRAW, FALSE, 0 );
1008 ShowWindow( top_child, SW_SHOWNORMAL );
1009 SendMessageW( top_child, WM_SETREDRAW, TRUE, 0 );
1014 /* Find the parent window */
1016 parent = cs->hwndParent;
1017 owner = 0;
1019 if (cs->hwndParent == HWND_MESSAGE)
1021 cs->hwndParent = parent = get_hwnd_message_parent();
1023 else if (cs->hwndParent)
1025 if ((cs->style & (WS_CHILD|WS_POPUP)) != WS_CHILD)
1027 parent = GetDesktopWindow();
1028 owner = cs->hwndParent;
1031 else
1033 static const WCHAR messageW[] = {'M','e','s','s','a','g','e',0};
1035 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1037 WARN("No parent for child window\n" );
1038 SetLastError(ERROR_TLW_WITH_WSCHILD);
1039 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1041 /* are we creating the desktop or HWND_MESSAGE parent itself? */
1042 if (className != (LPCWSTR)DESKTOP_CLASS_ATOM &&
1043 (IS_INTRESOURCE(className) || strcmpiW( className, messageW )))
1044 parent = GetDesktopWindow();
1047 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
1049 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
1050 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
1051 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
1052 cs->dwExStyle |= WS_EX_WINDOWEDGE;
1053 else
1054 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
1056 /* Create the window structure */
1058 if (!(wndPtr = create_window_handle( parent, owner, className, cs->hInstance, unicode )))
1059 return 0;
1060 hwnd = wndPtr->hwndSelf;
1062 /* Fill the window structure */
1064 wndPtr->tid = GetCurrentThreadId();
1065 wndPtr->hInstance = cs->hInstance;
1066 wndPtr->text = NULL;
1067 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1068 wndPtr->dwExStyle = cs->dwExStyle;
1069 wndPtr->wIDmenu = 0;
1070 wndPtr->helpContext = 0;
1071 wndPtr->pVScroll = NULL;
1072 wndPtr->pHScroll = NULL;
1073 wndPtr->userdata = 0;
1074 wndPtr->hIcon = 0;
1075 wndPtr->hIconSmall = 0;
1076 wndPtr->hSysMenu = 0;
1077 wndPtr->flags |= (flags & WIN_ISWIN32);
1079 wndPtr->min_pos.x = wndPtr->min_pos.y = -1;
1080 wndPtr->max_pos.x = wndPtr->max_pos.y = -1;
1082 if (wndPtr->dwStyle & WS_SYSMENU) SetSystemMenu( hwnd, 0 );
1085 * Correct the window styles.
1087 * It affects only the style loaded into the WIN structure.
1090 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
1092 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1093 if (!(wndPtr->dwStyle & WS_POPUP))
1094 wndPtr->dwStyle |= WS_CAPTION;
1098 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1099 * why does the user get to set it?
1102 if ((wndPtr->dwExStyle & WS_EX_DLGMODALFRAME) ||
1103 (wndPtr->dwStyle & (WS_DLGFRAME | WS_THICKFRAME)))
1104 wndPtr->dwExStyle |= WS_EX_WINDOWEDGE;
1105 else
1106 wndPtr->dwExStyle &= ~WS_EX_WINDOWEDGE;
1108 if (!(wndPtr->dwStyle & (WS_CHILD | WS_POPUP)))
1109 wndPtr->flags |= WIN_NEED_SIZE;
1111 SERVER_START_REQ( set_window_info )
1113 req->handle = hwnd;
1114 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE | SET_WIN_UNICODE;
1115 req->style = wndPtr->dwStyle;
1116 req->ex_style = wndPtr->dwExStyle;
1117 req->instance = (void *)wndPtr->hInstance;
1118 req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
1119 req->extra_offset = -1;
1120 wine_server_call( req );
1122 SERVER_END_REQ;
1124 /* Set the window menu */
1126 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
1128 if (cs->hMenu)
1130 if (!MENU_SetMenu(hwnd, cs->hMenu))
1132 WIN_ReleasePtr( wndPtr );
1133 free_window_handle( hwnd );
1134 return 0;
1137 else
1139 LPCSTR menuName = (LPCSTR)GetClassLongPtrA( hwnd, GCLP_MENUNAME );
1140 if (menuName)
1142 if (!cs->hInstance || HIWORD(cs->hInstance))
1143 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1144 else
1145 cs->hMenu = HMENU_32(LoadMenu16(HINSTANCE_16(cs->hInstance),menuName));
1147 if (cs->hMenu) MENU_SetMenu( hwnd, cs->hMenu );
1151 else SetWindowLongPtrW( hwnd, GWLP_ID, (ULONG_PTR)cs->hMenu );
1153 /* call the WH_CBT hook */
1155 /* the window style passed to the hook must be the real window style,
1156 * rather than just the window style that the caller to CreateWindowEx
1157 * passed in, so we have to copy the original CREATESTRUCT and get the
1158 * the real style. */
1159 cbcs = *cs;
1160 cbcs.style = wndPtr->dwStyle;
1161 cbtc.lpcs = &cbcs;
1162 cbtc.hwndInsertAfter = HWND_TOP;
1163 WIN_ReleasePtr( wndPtr );
1164 if (HOOK_CallHooks( WH_CBT, HCBT_CREATEWND, (WPARAM)hwnd, (LPARAM)&cbtc, unicode )) goto failed;
1166 /* send the WM_GETMINMAXINFO message and fix the size if needed */
1168 cx = cs->cx;
1169 cy = cs->cy;
1170 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
1172 POINT maxSize, maxPos, minTrack, maxTrack;
1173 WINPOS_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack);
1174 if (maxTrack.x < cx) cx = maxTrack.x;
1175 if (maxTrack.y < cy) cy = maxTrack.y;
1176 if (minTrack.x > cx) cx = minTrack.x;
1177 if (minTrack.y > cy) cy = minTrack.y;
1180 if (cx < 0) cx = 0;
1181 if (cy < 0) cy = 0;
1182 SetRect( &rect, cs->x, cs->y, cs->x + cx, cs->y + cy );
1183 /* check for wraparound */
1184 if (cs->x + cx < cs->x) rect.right = 0x7fffffff;
1185 if (cs->y + cy < cs->y) rect.bottom = 0x7fffffff;
1186 if (!set_window_pos( hwnd, 0, SWP_NOZORDER | SWP_NOACTIVATE, &rect, &rect, NULL )) goto failed;
1188 /* send WM_NCCREATE */
1190 TRACE( "hwnd %p cs %d,%d %dx%d\n", hwnd, cs->x, cs->y, cx, cy );
1191 if (unicode)
1192 result = SendMessageW( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
1193 else
1194 result = SendMessageA( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
1195 if (!result)
1197 WARN( "%p: aborted by WM_NCCREATE\n", hwnd );
1198 goto failed;
1201 /* send WM_NCCALCSIZE */
1203 if ((wndPtr = WIN_GetPtr(hwnd)))
1205 /* yes, even if the CBT hook was called with HWND_TOP */
1206 POINT pt;
1207 HWND insert_after = (wndPtr->dwStyle & WS_CHILD) ? HWND_BOTTOM : HWND_TOP;
1208 RECT window_rect = wndPtr->rectWindow;
1209 RECT client_rect = window_rect;
1210 WIN_ReleasePtr( wndPtr );
1212 /* the rectangle is in screen coords for WM_NCCALCSIZE when wparam is FALSE */
1213 pt.x = pt.y = 0;
1214 MapWindowPoints( parent, 0, &pt, 1 );
1215 OffsetRect( &client_rect, pt.x, pt.y );
1216 SendMessageW( hwnd, WM_NCCALCSIZE, FALSE, (LPARAM)&client_rect );
1217 OffsetRect( &client_rect, -pt.x, -pt.y );
1218 set_window_pos( hwnd, insert_after, SWP_NOACTIVATE, &window_rect, &client_rect, NULL );
1220 else return 0;
1222 /* send WM_CREATE */
1224 if (unicode)
1225 result = SendMessageW( hwnd, WM_CREATE, 0, (LPARAM)cs );
1226 else
1227 result = SendMessageA( hwnd, WM_CREATE, 0, (LPARAM)cs );
1228 if (result == -1) goto failed;
1230 /* call the driver */
1232 if (!USER_Driver->pCreateWindow( hwnd )) goto failed;
1234 NotifyWinEvent(EVENT_OBJECT_CREATE, hwnd, OBJID_WINDOW, 0);
1236 /* send the size messages */
1238 if (!(wndPtr = WIN_GetPtr( hwnd )) ||
1239 wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return 0;
1240 if (!(wndPtr->flags & WIN_NEED_SIZE))
1242 rect = wndPtr->rectClient;
1243 WIN_ReleasePtr( wndPtr );
1244 SendMessageW( hwnd, WM_SIZE, SIZE_RESTORED,
1245 MAKELONG(rect.right-rect.left, rect.bottom-rect.top));
1246 SendMessageW( hwnd, WM_MOVE, 0, MAKELONG( rect.left, rect.top ) );
1248 else WIN_ReleasePtr( wndPtr );
1250 /* Show the window, maximizing or minimizing if needed */
1252 style = WIN_SetStyle( hwnd, 0, WS_MAXIMIZE | WS_MINIMIZE );
1253 if (style & (WS_MINIMIZE | WS_MAXIMIZE))
1255 RECT newPos;
1256 UINT swFlag = (style & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
1258 swFlag = WINPOS_MinMaximize( hwnd, swFlag, &newPos );
1259 swFlag |= SWP_FRAMECHANGED; /* Frame always gets changed */
1260 if (!(style & WS_VISIBLE) || (style & WS_CHILD) || GetActiveWindow()) swFlag |= SWP_NOACTIVATE;
1261 SetWindowPos( hwnd, 0, newPos.left, newPos.top, newPos.right - newPos.left,
1262 newPos.bottom - newPos.top, swFlag );
1265 /* Notify the parent window only */
1267 send_parent_notify( hwnd, WM_CREATE );
1268 if (!IsWindow( hwnd )) return 0;
1270 if (cs->style & WS_VISIBLE)
1272 if (cs->style & WS_MAXIMIZE)
1273 sw = SW_SHOW;
1274 else if (cs->style & WS_MINIMIZE)
1275 sw = SW_SHOWMINIMIZED;
1277 ShowWindow( hwnd, sw );
1278 if (cs->dwExStyle & WS_EX_MDICHILD)
1280 SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
1281 /* ShowWindow won't activate child windows */
1282 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE );
1286 /* Call WH_SHELL hook */
1288 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1289 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1291 TRACE("created window %p\n", hwnd);
1292 return hwnd;
1294 failed:
1295 WIN_DestroyWindow( hwnd );
1296 return 0;
1300 /***********************************************************************
1301 * CreateWindow (USER.41)
1303 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1304 DWORD style, INT16 x, INT16 y, INT16 width,
1305 INT16 height, HWND16 parent, HMENU16 menu,
1306 HINSTANCE16 instance, LPVOID data )
1308 return CreateWindowEx16( 0, className, windowName, style,
1309 x, y, width, height, parent, menu, instance, data );
1313 /***********************************************************************
1314 * CreateWindowEx (USER.452)
1316 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1317 LPCSTR windowName, DWORD style, INT16 x,
1318 INT16 y, INT16 width, INT16 height,
1319 HWND16 parent, HMENU16 menu,
1320 HINSTANCE16 instance, LPVOID data )
1322 CREATESTRUCTA cs;
1323 char buffer[256];
1325 /* Fix the coordinates */
1327 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1328 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1329 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1330 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1332 /* Create the window */
1334 cs.lpCreateParams = data;
1335 cs.hInstance = HINSTANCE_32(instance);
1336 cs.hMenu = HMENU_32(menu);
1337 cs.hwndParent = WIN_Handle32( parent );
1338 cs.style = style;
1339 cs.lpszName = windowName;
1340 cs.lpszClass = className;
1341 cs.dwExStyle = exStyle;
1343 if (!IS_INTRESOURCE(className))
1345 WCHAR bufferW[256];
1347 if (!MultiByteToWideChar( CP_ACP, 0, className, -1, bufferW, sizeof(bufferW)/sizeof(WCHAR) ))
1348 return 0;
1349 return HWND_16( WIN_CreateWindowEx( &cs, bufferW, 0 ));
1351 else
1353 if (!GlobalGetAtomNameA( LOWORD(className), buffer, sizeof(buffer) ))
1355 ERR( "bad atom %x\n", LOWORD(className));
1356 return 0;
1358 cs.lpszClass = buffer;
1359 return HWND_16( WIN_CreateWindowEx( &cs, (LPCWSTR)className, 0 ));
1364 /***********************************************************************
1365 * CreateWindowExA (USER32.@)
1367 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1368 LPCSTR windowName, DWORD style, INT x,
1369 INT y, INT width, INT height,
1370 HWND parent, HMENU menu,
1371 HINSTANCE instance, LPVOID data )
1373 CREATESTRUCTA cs;
1375 cs.lpCreateParams = data;
1376 cs.hInstance = instance;
1377 cs.hMenu = menu;
1378 cs.hwndParent = parent;
1379 cs.x = x;
1380 cs.y = y;
1381 cs.cx = width;
1382 cs.cy = height;
1383 cs.style = style;
1384 cs.lpszName = windowName;
1385 cs.lpszClass = className;
1386 cs.dwExStyle = exStyle;
1388 if (!IS_INTRESOURCE(className))
1390 WCHAR bufferW[256];
1391 if (!MultiByteToWideChar( CP_ACP, 0, className, -1, bufferW, sizeof(bufferW)/sizeof(WCHAR) ))
1392 return 0;
1393 return WIN_CreateWindowEx( &cs, bufferW, WIN_ISWIN32 );
1395 return WIN_CreateWindowEx( &cs, (LPCWSTR)className, WIN_ISWIN32 );
1399 /***********************************************************************
1400 * CreateWindowExW (USER32.@)
1402 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1403 LPCWSTR windowName, DWORD style, INT x,
1404 INT y, INT width, INT height,
1405 HWND parent, HMENU menu,
1406 HINSTANCE instance, LPVOID data )
1408 CREATESTRUCTW cs;
1410 cs.lpCreateParams = data;
1411 cs.hInstance = instance;
1412 cs.hMenu = menu;
1413 cs.hwndParent = parent;
1414 cs.x = x;
1415 cs.y = y;
1416 cs.cx = width;
1417 cs.cy = height;
1418 cs.style = style;
1419 cs.lpszName = windowName;
1420 cs.lpszClass = className;
1421 cs.dwExStyle = exStyle;
1423 /* Note: we rely on the fact that CREATESTRUCTA and */
1424 /* CREATESTRUCTW have the same layout. */
1425 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, className, WIN_ISWIN32 | WIN_ISUNICODE );
1429 /***********************************************************************
1430 * WIN_SendDestroyMsg
1432 static void WIN_SendDestroyMsg( HWND hwnd )
1434 GUITHREADINFO info;
1436 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1438 if (hwnd == info.hwndCaret) DestroyCaret();
1439 if (hwnd == info.hwndActive) WINPOS_ActivateOtherWindow( hwnd );
1443 * Send the WM_DESTROY to the window.
1445 SendMessageW( hwnd, WM_DESTROY, 0, 0);
1448 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1449 * make sure that the window still exists when we come back.
1451 if (IsWindow(hwnd))
1453 HWND* pWndArray;
1454 int i;
1456 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1458 for (i = 0; pWndArray[i]; i++)
1460 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1462 HeapFree( GetProcessHeap(), 0, pWndArray );
1464 else
1465 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1469 /***********************************************************************
1470 * DestroyWindow (USER32.@)
1472 BOOL WINAPI DestroyWindow( HWND hwnd )
1474 BOOL is_child;
1476 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || is_desktop_window( hwnd ))
1478 SetLastError( ERROR_ACCESS_DENIED );
1479 return FALSE;
1482 TRACE("(%p)\n", hwnd);
1484 /* Call hooks */
1486 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1488 if (MENU_IsMenuActive() == hwnd)
1489 EndMenu();
1491 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1493 if (is_child)
1495 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1496 send_parent_notify( hwnd, WM_DESTROY );
1498 else if (!GetWindow( hwnd, GW_OWNER ))
1500 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1501 /* FIXME: clean up palette - see "Internals" p.352 */
1504 if (!IsWindow(hwnd)) return TRUE;
1506 /* Hide the window */
1507 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)
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 );
1517 if (!IsWindow(hwnd)) return TRUE;
1519 /* Recursively destroy owned windows */
1521 if (!is_child)
1523 for (;;)
1525 int i, got_one = 0;
1526 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1527 if (list)
1529 for (i = 0; list[i]; i++)
1531 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1532 if (WIN_IsCurrentThread( list[i] ))
1534 DestroyWindow( list[i] );
1535 got_one = 1;
1536 continue;
1538 WIN_SetOwner( list[i], 0 );
1540 HeapFree( GetProcessHeap(), 0, list );
1542 if (!got_one) break;
1546 /* Send destroy messages */
1548 WIN_SendDestroyMsg( hwnd );
1549 if (!IsWindow( hwnd )) return TRUE;
1551 if (GetClipboardOwner() == hwnd)
1552 CLIPBOARD_ReleaseOwner();
1554 /* Destroy the window storage */
1556 WIN_DestroyWindow( hwnd );
1557 return TRUE;
1561 /***********************************************************************
1562 * CloseWindow (USER32.@)
1564 BOOL WINAPI CloseWindow( HWND hwnd )
1566 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1567 ShowWindow( hwnd, SW_MINIMIZE );
1568 return TRUE;
1572 /***********************************************************************
1573 * OpenIcon (USER32.@)
1575 BOOL WINAPI OpenIcon( HWND hwnd )
1577 if (!IsIconic( hwnd )) return FALSE;
1578 ShowWindow( hwnd, SW_SHOWNORMAL );
1579 return TRUE;
1583 /***********************************************************************
1584 * FindWindowExW (USER32.@)
1586 HWND WINAPI FindWindowExW( HWND parent, HWND child, LPCWSTR className, LPCWSTR title )
1588 HWND *list = NULL;
1589 HWND retvalue = 0;
1590 int i = 0, len = 0;
1591 WCHAR *buffer = NULL;
1593 if (!parent && child) parent = GetDesktopWindow();
1594 else if (parent == HWND_MESSAGE) parent = get_hwnd_message_parent();
1596 if (title)
1598 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1599 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1602 if (!(list = list_window_children( 0, parent, className, 0 ))) goto done;
1604 if (child)
1606 child = WIN_GetFullHandle( child );
1607 while (list[i] && list[i] != child) i++;
1608 if (!list[i]) goto done;
1609 i++; /* start from next window */
1612 if (title)
1614 while (list[i])
1616 if (GetWindowTextW( list[i], buffer, len + 1 ) && !strcmpiW( buffer, title )) break;
1617 i++;
1620 retvalue = list[i];
1622 done:
1623 HeapFree( GetProcessHeap(), 0, list );
1624 HeapFree( GetProcessHeap(), 0, buffer );
1625 return retvalue;
1630 /***********************************************************************
1631 * FindWindowA (USER32.@)
1633 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1635 HWND ret = FindWindowExA( 0, 0, className, title );
1636 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1637 return ret;
1641 /***********************************************************************
1642 * FindWindowExA (USER32.@)
1644 HWND WINAPI FindWindowExA( HWND parent, HWND child, LPCSTR className, LPCSTR title )
1646 LPWSTR titleW = NULL;
1647 HWND hwnd = 0;
1649 if (title)
1651 DWORD len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1652 if (!(titleW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1653 MultiByteToWideChar( CP_ACP, 0, title, -1, titleW, len );
1656 if (!IS_INTRESOURCE(className))
1658 WCHAR classW[256];
1659 if (MultiByteToWideChar( CP_ACP, 0, className, -1, classW, sizeof(classW)/sizeof(WCHAR) ))
1660 hwnd = FindWindowExW( parent, child, classW, titleW );
1662 else
1664 hwnd = FindWindowExW( parent, child, (LPCWSTR)className, titleW );
1667 HeapFree( GetProcessHeap(), 0, titleW );
1668 return hwnd;
1672 /***********************************************************************
1673 * FindWindowW (USER32.@)
1675 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1677 return FindWindowExW( 0, 0, className, title );
1681 /**********************************************************************
1682 * GetDesktopWindow (USER32.@)
1684 HWND WINAPI GetDesktopWindow(void)
1686 struct user_thread_info *thread_info = get_user_thread_info();
1688 if (thread_info->top_window) return thread_info->top_window;
1690 SERVER_START_REQ( get_desktop_window )
1692 req->force = 0;
1693 if (!wine_server_call( req ))
1695 thread_info->top_window = reply->top_window;
1696 thread_info->msg_window = reply->msg_window;
1699 SERVER_END_REQ;
1701 if (!thread_info->top_window)
1703 USEROBJECTFLAGS flags;
1704 if (!GetUserObjectInformationW( GetProcessWindowStation(), UOI_FLAGS, &flags,
1705 sizeof(flags), NULL ) || (flags.dwFlags & WSF_VISIBLE))
1707 static const WCHAR command_line[] = {'\\','e','x','p','l','o','r','e','r','.','e','x','e',' ','/','d','e','s','k','t','o','p',0};
1708 STARTUPINFOW si;
1709 PROCESS_INFORMATION pi;
1710 WCHAR cmdline[MAX_PATH + sizeof(command_line)/sizeof(WCHAR)];
1712 memset( &si, 0, sizeof(si) );
1713 si.cb = sizeof(si);
1714 si.dwFlags = STARTF_USESTDHANDLES;
1715 si.hStdInput = 0;
1716 si.hStdOutput = 0;
1717 si.hStdError = GetStdHandle( STD_ERROR_HANDLE );
1719 GetSystemDirectoryW( cmdline, MAX_PATH );
1720 lstrcatW( cmdline, command_line );
1721 if (CreateProcessW( NULL, cmdline, NULL, NULL, FALSE, DETACHED_PROCESS,
1722 NULL, NULL, &si, &pi ))
1724 TRACE( "started explorer pid %04x tid %04x\n", pi.dwProcessId, pi.dwThreadId );
1725 WaitForInputIdle( pi.hProcess, 10000 );
1726 CloseHandle( pi.hThread );
1727 CloseHandle( pi.hProcess );
1729 else WARN( "failed to start explorer, err %d\n", GetLastError() );
1731 else TRACE( "not starting explorer since winstation is not visible\n" );
1733 SERVER_START_REQ( get_desktop_window )
1735 req->force = 1;
1736 if (!wine_server_call( req ))
1738 thread_info->top_window = reply->top_window;
1739 thread_info->msg_window = reply->msg_window;
1742 SERVER_END_REQ;
1745 if (!thread_info->top_window || !USER_Driver->pCreateDesktopWindow( thread_info->top_window ))
1746 ERR( "failed to create desktop window\n" );
1748 return thread_info->top_window;
1752 /*******************************************************************
1753 * EnableWindow (USER32.@)
1755 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1757 BOOL retvalue;
1758 HWND full_handle;
1760 if (is_broadcast(hwnd))
1762 SetLastError( ERROR_INVALID_PARAMETER );
1763 return FALSE;
1766 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1767 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1769 hwnd = full_handle;
1771 TRACE("( %p, %d )\n", hwnd, enable);
1773 retvalue = !IsWindowEnabled( hwnd );
1775 if (enable && retvalue)
1777 WIN_SetStyle( hwnd, 0, WS_DISABLED );
1778 SendMessageW( hwnd, WM_ENABLE, TRUE, 0 );
1780 else if (!enable && !retvalue)
1782 HWND capture_wnd;
1784 SendMessageW( hwnd, WM_CANCELMODE, 0, 0);
1786 WIN_SetStyle( hwnd, WS_DISABLED, 0 );
1788 if (hwnd == GetFocus())
1789 SetFocus( 0 ); /* A disabled window can't have the focus */
1791 capture_wnd = GetCapture();
1792 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1793 ReleaseCapture(); /* A disabled window can't capture the mouse */
1795 SendMessageW( hwnd, WM_ENABLE, FALSE, 0 );
1797 return retvalue;
1801 /***********************************************************************
1802 * IsWindowEnabled (USER32.@)
1804 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1806 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1810 /***********************************************************************
1811 * IsWindowUnicode (USER32.@)
1813 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1815 WND * wndPtr;
1816 BOOL retvalue = FALSE;
1818 if (!(wndPtr = WIN_GetPtr(hwnd))) return FALSE;
1820 if (wndPtr == WND_DESKTOP) return TRUE;
1822 if (wndPtr != WND_OTHER_PROCESS)
1824 retvalue = (wndPtr->flags & WIN_ISUNICODE) != 0;
1825 WIN_ReleasePtr( wndPtr );
1827 else
1829 SERVER_START_REQ( get_window_info )
1831 req->handle = hwnd;
1832 if (!wine_server_call_err( req )) retvalue = reply->is_unicode;
1834 SERVER_END_REQ;
1836 return retvalue;
1840 /**********************************************************************
1841 * WIN_GetWindowLong
1843 * Helper function for GetWindowLong().
1845 static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, UINT size, BOOL unicode )
1847 LONG_PTR retvalue = 0;
1848 WND *wndPtr;
1850 if (offset == GWLP_HWNDPARENT)
1852 HWND parent = GetAncestor( hwnd, GA_PARENT );
1853 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1854 return (ULONG_PTR)parent;
1857 if (!(wndPtr = WIN_GetPtr( hwnd )))
1859 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1860 return 0;
1863 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1865 if (offset == GWLP_WNDPROC)
1867 SetLastError( ERROR_ACCESS_DENIED );
1868 return 0;
1870 SERVER_START_REQ( set_window_info )
1872 req->handle = hwnd;
1873 req->flags = 0; /* don't set anything, just retrieve */
1874 req->extra_offset = (offset >= 0) ? offset : -1;
1875 req->extra_size = (offset >= 0) ? size : 0;
1876 if (!wine_server_call_err( req ))
1878 switch(offset)
1880 case GWL_STYLE: retvalue = reply->old_style; break;
1881 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1882 case GWLP_ID: retvalue = reply->old_id; break;
1883 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1884 case GWLP_USERDATA: retvalue = reply->old_user_data; break;
1885 default:
1886 if (offset >= 0) retvalue = get_win_data( &reply->old_extra_value, size );
1887 else SetLastError( ERROR_INVALID_INDEX );
1888 break;
1892 SERVER_END_REQ;
1893 return retvalue;
1896 /* now we have a valid wndPtr */
1898 if (offset >= 0)
1900 if (offset > (int)(wndPtr->cbWndExtra - size))
1902 WARN("Invalid offset %d\n", offset );
1903 WIN_ReleasePtr( wndPtr );
1904 SetLastError( ERROR_INVALID_INDEX );
1905 return 0;
1907 retvalue = get_win_data( (char *)wndPtr->wExtra + offset, size );
1909 /* Special case for dialog window procedure */
1910 if ((offset == DWLP_DLGPROC) && (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG))
1911 retvalue = (LONG_PTR)WINPROC_GetProc( (WNDPROC)retvalue, unicode );
1912 WIN_ReleasePtr( wndPtr );
1913 return retvalue;
1916 switch(offset)
1918 case GWLP_USERDATA: retvalue = wndPtr->userdata; break;
1919 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1920 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1921 case GWLP_ID: retvalue = wndPtr->wIDmenu; break;
1922 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wndPtr->hInstance; break;
1923 case GWLP_WNDPROC:
1924 /* This looks like a hack only for the edit control (see tests). This makes these controls
1925 * more tolerant to A/W mismatches. The lack of W->A->W conversion for such a mismatch suggests
1926 * that the hack is in GetWindowLongPtr[AW], not in winprocs.
1928 if (wndPtr->winproc == EDIT_winproc_handle && (!unicode != !(wndPtr->flags & WIN_ISUNICODE)))
1929 retvalue = (ULONG_PTR)wndPtr->winproc;
1930 else
1931 retvalue = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, unicode );
1932 break;
1933 default:
1934 WARN("Unknown offset %d\n", offset );
1935 SetLastError( ERROR_INVALID_INDEX );
1936 break;
1938 WIN_ReleasePtr(wndPtr);
1939 return retvalue;
1943 /**********************************************************************
1944 * WIN_SetWindowLong
1946 * Helper function for SetWindowLong().
1948 * 0 is the failure code. However, in the case of failure SetLastError
1949 * must be set to distinguish between a 0 return value and a failure.
1951 LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, UINT size, LONG_PTR newval, BOOL unicode )
1953 STYLESTRUCT style;
1954 BOOL ok;
1955 LONG_PTR retval = 0;
1956 WND *wndPtr;
1958 TRACE( "%p %d %lx %c\n", hwnd, offset, newval, unicode ? 'W' : 'A' );
1960 if (is_broadcast(hwnd))
1962 SetLastError( ERROR_INVALID_PARAMETER );
1963 return FALSE;
1966 if (!(wndPtr = WIN_GetPtr( hwnd )))
1968 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1969 return 0;
1971 if (wndPtr == WND_DESKTOP)
1973 /* can't change anything on the desktop window */
1974 SetLastError( ERROR_ACCESS_DENIED );
1975 return 0;
1977 if (wndPtr == WND_OTHER_PROCESS)
1979 if (offset == GWLP_WNDPROC)
1981 SetLastError( ERROR_ACCESS_DENIED );
1982 return 0;
1984 if (offset > 32767 || offset < -32767)
1986 SetLastError( ERROR_INVALID_INDEX );
1987 return 0;
1989 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, MAKEWPARAM( offset, size ), newval );
1992 /* first some special cases */
1993 switch( offset )
1995 case GWL_STYLE:
1996 case GWL_EXSTYLE:
1997 style.styleOld =
1998 offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
1999 style.styleNew = newval;
2000 WIN_ReleasePtr( wndPtr );
2001 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
2002 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
2003 newval = style.styleNew;
2004 break;
2005 case GWLP_HWNDPARENT:
2006 if (wndPtr->parent == GetDesktopWindow())
2008 WIN_ReleasePtr( wndPtr );
2009 return (ULONG_PTR)WIN_SetOwner( hwnd, (HWND)newval );
2011 else
2013 WIN_ReleasePtr( wndPtr );
2014 return (ULONG_PTR)SetParent( hwnd, (HWND)newval );
2016 case GWLP_WNDPROC:
2018 WNDPROC proc;
2019 UINT old_flags = wndPtr->flags;
2020 retval = WIN_GetWindowLong( hwnd, offset, size, unicode );
2021 if (unicode) proc = WINPROC_AllocProc( NULL, (WNDPROC)newval );
2022 else proc = WINPROC_AllocProc( (WNDPROC)newval, NULL );
2023 if (proc) wndPtr->winproc = proc;
2024 if (WINPROC_IsUnicode( proc, unicode )) wndPtr->flags |= WIN_ISUNICODE;
2025 else wndPtr->flags &= ~WIN_ISUNICODE;
2026 if (!((old_flags ^ wndPtr->flags) & WIN_ISUNICODE))
2028 WIN_ReleasePtr( wndPtr );
2029 return retval;
2031 /* update is_unicode flag on the server side */
2032 break;
2034 case GWLP_ID:
2035 case GWLP_HINSTANCE:
2036 case GWLP_USERDATA:
2037 break;
2038 case DWLP_DLGPROC:
2039 if ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
2040 (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG))
2042 WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWLP_DLGPROC);
2043 retval = (ULONG_PTR)WINPROC_GetProc( *ptr, unicode );
2044 if (unicode) *ptr = WINPROC_AllocProc( NULL, (WNDPROC)newval );
2045 else *ptr = WINPROC_AllocProc( (WNDPROC)newval, NULL );
2046 WIN_ReleasePtr( wndPtr );
2047 return retval;
2049 /* fall through */
2050 default:
2051 if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - size))
2053 WARN("Invalid offset %d\n", offset );
2054 WIN_ReleasePtr( wndPtr );
2055 SetLastError( ERROR_INVALID_INDEX );
2056 return 0;
2058 else if (get_win_data( (char *)wndPtr->wExtra + offset, size ) == newval)
2060 /* already set to the same value */
2061 WIN_ReleasePtr( wndPtr );
2062 return newval;
2064 break;
2067 SERVER_START_REQ( set_window_info )
2069 req->handle = hwnd;
2070 req->extra_offset = -1;
2071 switch(offset)
2073 case GWL_STYLE:
2074 req->flags = SET_WIN_STYLE;
2075 req->style = newval;
2076 break;
2077 case GWL_EXSTYLE:
2078 req->flags = SET_WIN_EXSTYLE;
2079 /* WS_EX_TOPMOST can only be changed through SetWindowPos */
2080 newval = (newval & ~WS_EX_TOPMOST) | (wndPtr->dwExStyle & WS_EX_TOPMOST);
2081 req->ex_style = newval;
2082 break;
2083 case GWLP_ID:
2084 req->flags = SET_WIN_ID;
2085 req->id = newval;
2086 break;
2087 case GWLP_HINSTANCE:
2088 req->flags = SET_WIN_INSTANCE;
2089 req->instance = (void *)newval;
2090 break;
2091 case GWLP_WNDPROC:
2092 req->flags = SET_WIN_UNICODE;
2093 req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
2094 break;
2095 case GWLP_USERDATA:
2096 req->flags = SET_WIN_USERDATA;
2097 req->user_data = newval;
2098 break;
2099 default:
2100 req->flags = SET_WIN_EXTRA;
2101 req->extra_offset = offset;
2102 req->extra_size = size;
2103 set_win_data( &req->extra_value, newval, size );
2105 if ((ok = !wine_server_call_err( req )))
2107 switch(offset)
2109 case GWL_STYLE:
2110 wndPtr->dwStyle = newval;
2111 retval = reply->old_style;
2112 break;
2113 case GWL_EXSTYLE:
2114 wndPtr->dwExStyle = newval;
2115 retval = reply->old_ex_style;
2116 break;
2117 case GWLP_ID:
2118 wndPtr->wIDmenu = newval;
2119 retval = reply->old_id;
2120 break;
2121 case GWLP_HINSTANCE:
2122 wndPtr->hInstance = (HINSTANCE)newval;
2123 retval = (ULONG_PTR)reply->old_instance;
2124 break;
2125 case GWLP_WNDPROC:
2126 break;
2127 case GWLP_USERDATA:
2128 wndPtr->userdata = newval;
2129 retval = reply->old_user_data;
2130 break;
2131 default:
2132 retval = get_win_data( (char *)wndPtr->wExtra + offset, size );
2133 set_win_data( (char *)wndPtr->wExtra + offset, newval, size );
2134 break;
2138 SERVER_END_REQ;
2139 WIN_ReleasePtr( wndPtr );
2141 if (!ok) return 0;
2143 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2145 USER_Driver->pSetWindowStyle( hwnd, offset, &style );
2146 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2149 return retval;
2153 /**********************************************************************
2154 * GetWindowLong (USER.135)
2156 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2158 WND *wndPtr;
2159 LONG_PTR retvalue;
2160 BOOL is_winproc = (offset == GWLP_WNDPROC);
2162 if (offset >= 0)
2164 if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2166 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2167 return 0;
2169 if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2171 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
2174 * Some programs try to access last element from 16 bit
2175 * code using illegal offset value. Hopefully this is
2176 * what those programs really expect.
2178 if (wndPtr->cbWndExtra >= 4 && offset == wndPtr->cbWndExtra - sizeof(WORD))
2180 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
2181 ERR( "- replaced invalid offset %d with %d\n", offset, offset2 );
2182 offset = offset2;
2184 else
2186 WARN("Invalid offset %d\n", offset );
2187 WIN_ReleasePtr( wndPtr );
2188 SetLastError( ERROR_INVALID_INDEX );
2189 return 0;
2192 is_winproc = ((offset == DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG));
2193 WIN_ReleasePtr( wndPtr );
2196 retvalue = GetWindowLongA( WIN_Handle32(hwnd), offset );
2197 if (is_winproc) retvalue = (LONG_PTR)WINPROC_GetProc16( (WNDPROC)retvalue, FALSE );
2198 return retvalue;
2202 /**********************************************************************
2203 * GetWindowWord (USER32.@)
2205 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
2207 switch(offset)
2209 case GWLP_ID:
2210 case GWLP_HINSTANCE:
2211 case GWLP_HWNDPARENT:
2212 break;
2213 default:
2214 if (offset < 0)
2216 WARN("Invalid offset %d\n", offset );
2217 SetLastError( ERROR_INVALID_INDEX );
2218 return 0;
2220 break;
2222 return WIN_GetWindowLong( hwnd, offset, sizeof(WORD), FALSE );
2226 /**********************************************************************
2227 * GetWindowLongA (USER32.@)
2229 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2231 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), FALSE );
2235 /**********************************************************************
2236 * GetWindowLongW (USER32.@)
2238 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2240 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), TRUE );
2244 /**********************************************************************
2245 * SetWindowLong (USER.136)
2247 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2249 WND *wndPtr;
2250 BOOL is_winproc = (offset == GWLP_WNDPROC);
2252 if (offset == DWLP_DLGPROC)
2254 if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2256 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2257 return 0;
2259 if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2261 is_winproc = ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
2262 (wndPtr->flags & WIN_ISDIALOG));
2263 WIN_ReleasePtr( wndPtr );
2267 if (is_winproc)
2269 WNDPROC new_proc = WINPROC_AllocProc16( (WNDPROC16)newval );
2270 WNDPROC old_proc = (WNDPROC)SetWindowLongPtrA( WIN_Handle32(hwnd), offset, (LONG_PTR)new_proc );
2271 return (LONG)WINPROC_GetProc16( old_proc, FALSE );
2273 else return SetWindowLongA( WIN_Handle32(hwnd), offset, newval );
2277 /**********************************************************************
2278 * SetWindowWord (USER32.@)
2280 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
2282 switch(offset)
2284 case GWLP_ID:
2285 case GWLP_HINSTANCE:
2286 case GWLP_HWNDPARENT:
2287 break;
2288 default:
2289 if (offset < 0)
2291 WARN("Invalid offset %d\n", offset );
2292 SetLastError( ERROR_INVALID_INDEX );
2293 return 0;
2295 break;
2297 return WIN_SetWindowLong( hwnd, offset, sizeof(WORD), newval, FALSE );
2301 /**********************************************************************
2302 * SetWindowLongA (USER32.@)
2304 * See SetWindowLongW.
2306 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2308 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, FALSE );
2312 /**********************************************************************
2313 * SetWindowLongW (USER32.@) Set window attribute
2315 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2316 * value in a window's extra memory.
2318 * The _hwnd_ parameter specifies the window. is the handle to a
2319 * window that has extra memory. The _newval_ parameter contains the
2320 * new attribute or extra memory value. If positive, the _offset_
2321 * parameter is the byte-addressed location in the window's extra
2322 * memory to set. If negative, _offset_ specifies the window
2323 * attribute to set, and should be one of the following values:
2325 * GWL_EXSTYLE The window's extended window style
2327 * GWL_STYLE The window's window style.
2329 * GWLP_WNDPROC Pointer to the window's window procedure.
2331 * GWLP_HINSTANCE The window's pplication instance handle.
2333 * GWLP_ID The window's identifier.
2335 * GWLP_USERDATA The window's user-specified data.
2337 * If the window is a dialog box, the _offset_ parameter can be one of
2338 * the following values:
2340 * DWLP_DLGPROC The address of the window's dialog box procedure.
2342 * DWLP_MSGRESULT The return value of a message
2343 * that the dialog box procedure processed.
2345 * DWLP_USER Application specific information.
2347 * RETURNS
2349 * If successful, returns the previous value located at _offset_. Otherwise,
2350 * returns 0.
2352 * NOTES
2354 * Extra memory for a window class is specified by a nonzero cbWndExtra
2355 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2356 * time of class creation.
2358 * Using GWL_WNDPROC to set a new window procedure effectively creates
2359 * a window subclass. Use CallWindowProc() in the new windows procedure
2360 * to pass messages to the superclass's window procedure.
2362 * The user data is reserved for use by the application which created
2363 * the window.
2365 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2366 * instead, call the EnableWindow() function to change the window's
2367 * disabled state.
2369 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2370 * SetParent() instead.
2372 * Win95:
2373 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2374 * it sends WM_STYLECHANGING before changing the settings
2375 * and WM_STYLECHANGED afterwards.
2376 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2378 LONG WINAPI SetWindowLongW(
2379 HWND hwnd, /* [in] window to alter */
2380 INT offset, /* [in] offset, in bytes, of location to alter */
2381 LONG newval /* [in] new value of location */
2383 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, TRUE );
2387 /*******************************************************************
2388 * GetWindowTextA (USER32.@)
2390 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2392 WCHAR *buffer;
2394 if (!lpString) return 0;
2396 if (WIN_IsCurrentProcess( hwnd ))
2397 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2399 /* when window belongs to other process, don't send a message */
2400 if (nMaxCount <= 0) return 0;
2401 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2402 get_server_window_text( hwnd, buffer, nMaxCount );
2403 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2404 lpString[nMaxCount-1] = 0;
2405 HeapFree( GetProcessHeap(), 0, buffer );
2406 return strlen(lpString);
2410 /*******************************************************************
2411 * InternalGetWindowText (USER32.@)
2413 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2415 WND *win;
2417 if (nMaxCount <= 0) return 0;
2418 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2419 if (win == WND_DESKTOP) lpString[0] = 0;
2420 else if (win != WND_OTHER_PROCESS)
2422 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2423 else lpString[0] = 0;
2424 WIN_ReleasePtr( win );
2426 else
2428 get_server_window_text( hwnd, lpString, nMaxCount );
2430 return strlenW(lpString);
2434 /*******************************************************************
2435 * GetWindowTextW (USER32.@)
2437 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2439 if (!lpString) return 0;
2441 if (WIN_IsCurrentProcess( hwnd ))
2442 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2444 /* when window belongs to other process, don't send a message */
2445 if (nMaxCount <= 0) return 0;
2446 get_server_window_text( hwnd, lpString, nMaxCount );
2447 return strlenW(lpString);
2451 /*******************************************************************
2452 * SetWindowTextA (USER32.@)
2453 * SetWindowText (USER32.@)
2455 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2457 if (is_broadcast(hwnd))
2459 SetLastError( ERROR_INVALID_PARAMETER );
2460 return FALSE;
2462 if (!WIN_IsCurrentProcess( hwnd ))
2463 WARN( "setting text %s of other process window %p should not use SendMessage\n",
2464 debugstr_a(lpString), hwnd );
2465 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2469 /*******************************************************************
2470 * SetWindowTextW (USER32.@)
2472 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2474 if (is_broadcast(hwnd))
2476 SetLastError( ERROR_INVALID_PARAMETER );
2477 return FALSE;
2479 if (!WIN_IsCurrentProcess( hwnd ))
2480 WARN( "setting text %s of other process window %p should not use SendMessage\n",
2481 debugstr_w(lpString), hwnd );
2482 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2486 /*******************************************************************
2487 * GetWindowTextLengthA (USER32.@)
2489 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2491 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2494 /*******************************************************************
2495 * GetWindowTextLengthW (USER32.@)
2497 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2499 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2503 /*******************************************************************
2504 * IsWindow (USER32.@)
2506 BOOL WINAPI IsWindow( HWND hwnd )
2508 WND *ptr;
2509 BOOL ret;
2511 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2512 if (ptr == WND_DESKTOP) return TRUE;
2514 if (ptr != WND_OTHER_PROCESS)
2516 WIN_ReleasePtr( ptr );
2517 return TRUE;
2520 /* check other processes */
2521 SERVER_START_REQ( get_window_info )
2523 req->handle = hwnd;
2524 ret = !wine_server_call_err( req );
2526 SERVER_END_REQ;
2527 return ret;
2531 /***********************************************************************
2532 * GetWindowThreadProcessId (USER32.@)
2534 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2536 WND *ptr;
2537 DWORD tid = 0;
2539 if (!(ptr = WIN_GetPtr( hwnd )))
2541 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2542 return 0;
2545 if (ptr != WND_OTHER_PROCESS && ptr != WND_DESKTOP)
2547 /* got a valid window */
2548 tid = ptr->tid;
2549 if (process) *process = GetCurrentProcessId();
2550 WIN_ReleasePtr( ptr );
2551 return tid;
2554 /* check other processes */
2555 SERVER_START_REQ( get_window_info )
2557 req->handle = hwnd;
2558 if (!wine_server_call_err( req ))
2560 tid = (DWORD)reply->tid;
2561 if (process) *process = (DWORD)reply->pid;
2564 SERVER_END_REQ;
2565 return tid;
2569 /*****************************************************************
2570 * GetParent (USER32.@)
2572 HWND WINAPI GetParent( HWND hwnd )
2574 WND *wndPtr;
2575 HWND retvalue = 0;
2577 if (!(wndPtr = WIN_GetPtr( hwnd )))
2579 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2580 return 0;
2582 if (wndPtr == WND_DESKTOP) return 0;
2583 if (wndPtr == WND_OTHER_PROCESS)
2585 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2586 if (style & (WS_POPUP | WS_CHILD))
2588 SERVER_START_REQ( get_window_tree )
2590 req->handle = hwnd;
2591 if (!wine_server_call_err( req ))
2593 if (style & WS_POPUP) retvalue = reply->owner;
2594 else if (style & WS_CHILD) retvalue = reply->parent;
2597 SERVER_END_REQ;
2600 else
2602 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2603 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2604 WIN_ReleasePtr( wndPtr );
2606 return retvalue;
2610 /*****************************************************************
2611 * GetAncestor (USER32.@)
2613 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2615 WND *win;
2616 HWND *list, ret = 0;
2618 switch(type)
2620 case GA_PARENT:
2621 if (!(win = WIN_GetPtr( hwnd )))
2623 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2624 return 0;
2626 if (win == WND_DESKTOP) return 0;
2627 if (win != WND_OTHER_PROCESS)
2629 ret = win->parent;
2630 WIN_ReleasePtr( win );
2632 else /* need to query the server */
2634 SERVER_START_REQ( get_window_tree )
2636 req->handle = hwnd;
2637 if (!wine_server_call_err( req )) ret = reply->parent;
2639 SERVER_END_REQ;
2641 break;
2643 case GA_ROOT:
2644 if (!(list = list_window_parents( hwnd ))) return 0;
2646 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2647 else
2649 int count = 2;
2650 while (list[count]) count++;
2651 ret = list[count - 2]; /* get the one before the desktop */
2653 HeapFree( GetProcessHeap(), 0, list );
2654 break;
2656 case GA_ROOTOWNER:
2657 if (is_desktop_window( hwnd )) return 0;
2658 ret = WIN_GetFullHandle( hwnd );
2659 for (;;)
2661 HWND parent = GetParent( ret );
2662 if (!parent) break;
2663 ret = parent;
2665 break;
2667 return ret;
2671 /*****************************************************************
2672 * SetParent (USER32.@)
2674 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2676 HWND full_handle;
2677 HWND old_parent = 0;
2678 BOOL was_visible;
2679 WND *wndPtr;
2680 BOOL ret;
2682 if (is_broadcast(hwnd) || is_broadcast(parent))
2684 SetLastError(ERROR_INVALID_PARAMETER);
2685 return 0;
2688 if (!parent) parent = GetDesktopWindow();
2689 else if (parent == HWND_MESSAGE) parent = get_hwnd_message_parent();
2690 else parent = WIN_GetFullHandle( parent );
2692 if (!IsWindow( parent ))
2694 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2695 return 0;
2698 /* Some applications try to set a child as a parent */
2699 if (IsChild(hwnd, parent))
2701 SetLastError( ERROR_INVALID_PARAMETER );
2702 return 0;
2705 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2706 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2708 /* Windows hides the window first, then shows it again
2709 * including the WM_SHOWWINDOW messages and all */
2710 was_visible = ShowWindow( hwnd, SW_HIDE );
2712 wndPtr = WIN_GetPtr( hwnd );
2713 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return 0;
2715 SERVER_START_REQ( set_parent )
2717 req->handle = hwnd;
2718 req->parent = parent;
2719 if ((ret = !wine_server_call( req )))
2721 old_parent = reply->old_parent;
2722 wndPtr->parent = parent = reply->full_parent;
2726 SERVER_END_REQ;
2727 WIN_ReleasePtr( wndPtr );
2728 if (!ret) return 0;
2730 USER_Driver->pSetParent( full_handle, parent, old_parent );
2732 /* SetParent additionally needs to make hwnd the topmost window
2733 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2734 WM_WINDOWPOSCHANGED notification messages.
2736 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0,
2737 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2738 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2739 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2741 return old_parent;
2745 /*******************************************************************
2746 * IsChild (USER32.@)
2748 BOOL WINAPI IsChild( HWND parent, HWND child )
2750 HWND *list = list_window_parents( child );
2751 int i;
2752 BOOL ret;
2754 if (!list) return FALSE;
2755 parent = WIN_GetFullHandle( parent );
2756 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2757 ret = list[i] && list[i+1];
2758 HeapFree( GetProcessHeap(), 0, list );
2759 return ret;
2763 /***********************************************************************
2764 * IsWindowVisible (USER32.@)
2766 BOOL WINAPI IsWindowVisible( HWND hwnd )
2768 HWND *list;
2769 BOOL retval = TRUE;
2770 int i;
2772 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2773 if (!(list = list_window_parents( hwnd ))) return TRUE;
2774 if (list[0])
2776 for (i = 0; list[i+1]; i++)
2777 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2778 retval = !list[i+1] && (list[i] == GetDesktopWindow()); /* top message window isn't visible */
2780 HeapFree( GetProcessHeap(), 0, list );
2781 return retval;
2785 /***********************************************************************
2786 * WIN_IsWindowDrawable
2788 * hwnd is drawable when it is visible, all parents are not
2789 * minimized, and it is itself not minimized unless we are
2790 * trying to draw its default class icon.
2792 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2794 HWND *list;
2795 BOOL retval = TRUE;
2796 int i;
2797 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2799 if (!(style & WS_VISIBLE)) return FALSE;
2800 if ((style & WS_MINIMIZE) && icon && GetClassLongPtrW( hwnd, GCLP_HICON )) return FALSE;
2802 if (!(list = list_window_parents( hwnd ))) return TRUE;
2803 if (list[0])
2805 for (i = 0; list[i+1]; i++)
2806 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2807 break;
2808 retval = !list[i+1] && (list[i] == GetDesktopWindow()); /* top message window isn't visible */
2810 HeapFree( GetProcessHeap(), 0, list );
2811 return retval;
2815 /*******************************************************************
2816 * GetTopWindow (USER32.@)
2818 HWND WINAPI GetTopWindow( HWND hwnd )
2820 if (!hwnd) hwnd = GetDesktopWindow();
2821 return GetWindow( hwnd, GW_CHILD );
2825 /*******************************************************************
2826 * GetWindow (USER32.@)
2828 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2830 HWND retval = 0;
2832 if (rel == GW_OWNER) /* this one may be available locally */
2834 WND *wndPtr = WIN_GetPtr( hwnd );
2835 if (!wndPtr)
2837 SetLastError( ERROR_INVALID_HANDLE );
2838 return 0;
2840 if (wndPtr == WND_DESKTOP) return 0;
2841 if (wndPtr != WND_OTHER_PROCESS)
2843 retval = wndPtr->owner;
2844 WIN_ReleasePtr( wndPtr );
2845 return retval;
2847 /* else fall through to server call */
2850 SERVER_START_REQ( get_window_tree )
2852 req->handle = hwnd;
2853 if (!wine_server_call_err( req ))
2855 switch(rel)
2857 case GW_HWNDFIRST:
2858 retval = reply->first_sibling;
2859 break;
2860 case GW_HWNDLAST:
2861 retval = reply->last_sibling;
2862 break;
2863 case GW_HWNDNEXT:
2864 retval = reply->next_sibling;
2865 break;
2866 case GW_HWNDPREV:
2867 retval = reply->prev_sibling;
2868 break;
2869 case GW_OWNER:
2870 retval = reply->owner;
2871 break;
2872 case GW_CHILD:
2873 retval = reply->first_child;
2874 break;
2878 SERVER_END_REQ;
2879 return retval;
2883 /*******************************************************************
2884 * ShowOwnedPopups (USER32.@)
2886 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2888 int count = 0;
2889 WND *pWnd;
2890 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2892 if (!win_array) return TRUE;
2894 while (win_array[count]) count++;
2895 while (--count >= 0)
2897 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2898 if (!(pWnd = WIN_GetPtr( win_array[count] ))) continue;
2899 if (pWnd == WND_OTHER_PROCESS) continue;
2900 if (fShow)
2902 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2904 WIN_ReleasePtr( pWnd );
2905 /* In Windows, ShowOwnedPopups(TRUE) generates
2906 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2907 * regardless of the state of the owner
2909 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_SHOWNORMAL, SW_PARENTOPENING);
2910 continue;
2913 else
2915 if (pWnd->dwStyle & WS_VISIBLE)
2917 WIN_ReleasePtr( pWnd );
2918 /* In Windows, ShowOwnedPopups(FALSE) generates
2919 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2920 * regardless of the state of the owner
2922 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2923 continue;
2926 WIN_ReleasePtr( pWnd );
2928 HeapFree( GetProcessHeap(), 0, win_array );
2929 return TRUE;
2933 /*******************************************************************
2934 * GetLastActivePopup (USER32.@)
2936 HWND WINAPI GetLastActivePopup( HWND hwnd )
2938 HWND retval = hwnd;
2940 SERVER_START_REQ( get_window_info )
2942 req->handle = hwnd;
2943 if (!wine_server_call_err( req )) retval = reply->last_active;
2945 SERVER_END_REQ;
2946 return retval;
2950 /*******************************************************************
2951 * WIN_ListChildren
2953 * Build an array of the children of a given window. The array must be
2954 * freed with HeapFree. Returns NULL when no windows are found.
2956 HWND *WIN_ListChildren( HWND hwnd )
2958 if (!hwnd)
2960 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2961 return NULL;
2963 return list_window_children( 0, hwnd, NULL, 0 );
2967 /*******************************************************************
2968 * EnumWindows (USER32.@)
2970 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2972 HWND *list;
2973 BOOL ret = TRUE;
2974 int i;
2976 USER_CheckNotLock();
2978 /* We have to build a list of all windows first, to avoid */
2979 /* unpleasant side-effects, for instance if the callback */
2980 /* function changes the Z-order of the windows. */
2982 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2984 /* Now call the callback function for every window */
2986 for (i = 0; list[i]; i++)
2988 /* Make sure that the window still exists */
2989 if (!IsWindow( list[i] )) continue;
2990 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2992 HeapFree( GetProcessHeap(), 0, list );
2993 return ret;
2997 /**********************************************************************
2998 * EnumThreadWindows (USER32.@)
3000 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
3002 HWND *list;
3003 int i;
3005 USER_CheckNotLock();
3007 if (!(list = list_window_children( 0, GetDesktopWindow(), NULL, id ))) return TRUE;
3009 /* Now call the callback function for every window */
3011 for (i = 0; list[i]; i++)
3012 if (!func( list[i], lParam )) break;
3013 HeapFree( GetProcessHeap(), 0, list );
3014 return TRUE;
3018 /***********************************************************************
3019 * EnumDesktopWindows (USER32.@)
3021 BOOL WINAPI EnumDesktopWindows( HDESK desktop, WNDENUMPROC func, LPARAM lparam )
3023 HWND *list;
3024 int i;
3026 USER_CheckNotLock();
3028 if (!(list = list_window_children( desktop, 0, NULL, 0 ))) return TRUE;
3030 for (i = 0; list[i]; i++)
3031 if (!func( list[i], lparam )) break;
3032 HeapFree( GetProcessHeap(), 0, list );
3033 return TRUE;
3037 /**********************************************************************
3038 * WIN_EnumChildWindows
3040 * Helper function for EnumChildWindows().
3042 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
3044 HWND *childList;
3045 BOOL ret = FALSE;
3047 for ( ; *list; list++)
3049 /* Make sure that the window still exists */
3050 if (!IsWindow( *list )) continue;
3051 /* Build children list first */
3052 childList = WIN_ListChildren( *list );
3054 ret = func( *list, lParam );
3056 if (childList)
3058 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
3059 HeapFree( GetProcessHeap(), 0, childList );
3061 if (!ret) return FALSE;
3063 return TRUE;
3067 /**********************************************************************
3068 * EnumChildWindows (USER32.@)
3070 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
3072 HWND *list;
3073 BOOL ret;
3075 USER_CheckNotLock();
3077 if (!(list = WIN_ListChildren( parent ))) return FALSE;
3078 ret = WIN_EnumChildWindows( list, func, lParam );
3079 HeapFree( GetProcessHeap(), 0, list );
3080 return ret;
3084 /*******************************************************************
3085 * AnyPopup (USER.52)
3087 BOOL16 WINAPI AnyPopup16(void)
3089 return AnyPopup();
3093 /*******************************************************************
3094 * AnyPopup (USER32.@)
3096 BOOL WINAPI AnyPopup(void)
3098 int i;
3099 BOOL retvalue;
3100 HWND *list = WIN_ListChildren( GetDesktopWindow() );
3102 if (!list) return FALSE;
3103 for (i = 0; list[i]; i++)
3105 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
3107 retvalue = (list[i] != 0);
3108 HeapFree( GetProcessHeap(), 0, list );
3109 return retvalue;
3113 /*******************************************************************
3114 * FlashWindow (USER32.@)
3116 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3118 WND *wndPtr;
3120 TRACE("%p\n", hWnd);
3122 if (IsIconic( hWnd ))
3124 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3126 wndPtr = WIN_GetPtr(hWnd);
3127 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
3128 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3130 wndPtr->flags |= WIN_NCACTIVATED;
3132 else
3134 wndPtr->flags &= ~WIN_NCACTIVATED;
3136 WIN_ReleasePtr( wndPtr );
3137 return TRUE;
3139 else
3141 WPARAM wparam;
3143 wndPtr = WIN_GetPtr(hWnd);
3144 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
3145 hWnd = wndPtr->hwndSelf; /* make it a full handle */
3147 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3148 else wparam = (hWnd == GetForegroundWindow());
3150 WIN_ReleasePtr( wndPtr );
3151 SendMessageW( hWnd, WM_NCACTIVATE, wparam, 0 );
3152 return wparam;
3156 /*******************************************************************
3157 * FlashWindowEx (USER32.@)
3159 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
3161 FIXME("%p\n", pfwi);
3162 return TRUE;
3165 /*******************************************************************
3166 * GetWindowContextHelpId (USER32.@)
3168 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3170 DWORD retval;
3171 WND *wnd = WIN_GetPtr( hwnd );
3172 if (!wnd || wnd == WND_DESKTOP) return 0;
3173 if (wnd == WND_OTHER_PROCESS)
3175 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3176 return 0;
3178 retval = wnd->helpContext;
3179 WIN_ReleasePtr( wnd );
3180 return retval;
3184 /*******************************************************************
3185 * SetWindowContextHelpId (USER32.@)
3187 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3189 WND *wnd = WIN_GetPtr( hwnd );
3190 if (!wnd || wnd == WND_DESKTOP) return FALSE;
3191 if (wnd == WND_OTHER_PROCESS)
3193 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3194 return 0;
3196 wnd->helpContext = id;
3197 WIN_ReleasePtr( wnd );
3198 return TRUE;
3202 /*******************************************************************
3203 * DragDetect (USER32.@)
3205 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3207 MSG msg;
3208 RECT rect;
3209 WORD wDragWidth = GetSystemMetrics(SM_CXDRAG);
3210 WORD wDragHeight= GetSystemMetrics(SM_CYDRAG);
3212 rect.left = pt.x - wDragWidth;
3213 rect.right = pt.x + wDragWidth;
3215 rect.top = pt.y - wDragHeight;
3216 rect.bottom = pt.y + wDragHeight;
3218 SetCapture(hWnd);
3220 while(1)
3222 while (PeekMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ))
3224 if( msg.message == WM_LBUTTONUP )
3226 ReleaseCapture();
3227 return 0;
3229 if( msg.message == WM_MOUSEMOVE )
3231 POINT tmp;
3232 tmp.x = (short)LOWORD(msg.lParam);
3233 tmp.y = (short)HIWORD(msg.lParam);
3234 if( !PtInRect( &rect, tmp ))
3236 ReleaseCapture();
3237 return 1;
3241 WaitMessage();
3243 return 0;
3246 /******************************************************************************
3247 * GetWindowModuleFileNameA (USER32.@)
3249 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR module, UINT size )
3251 WND *win;
3252 HINSTANCE hinst;
3254 TRACE( "%p, %p, %u\n", hwnd, module, size );
3256 win = WIN_GetPtr( hwnd );
3257 if (!win || win == WND_OTHER_PROCESS || win == WND_DESKTOP)
3259 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
3260 return 0;
3262 hinst = win->hInstance;
3263 WIN_ReleasePtr( win );
3265 return GetModuleFileNameA( hinst, module, size );
3268 /******************************************************************************
3269 * GetWindowModuleFileNameW (USER32.@)
3271 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR module, UINT size )
3273 WND *win;
3274 HINSTANCE hinst;
3276 TRACE( "%p, %p, %u\n", hwnd, module, size );
3278 win = WIN_GetPtr( hwnd );
3279 if (!win || win == WND_OTHER_PROCESS || win == WND_DESKTOP)
3281 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
3282 return 0;
3284 hinst = win->hInstance;
3285 WIN_ReleasePtr( win );
3287 return GetModuleFileNameW( hinst, module, size );
3290 /******************************************************************************
3291 * GetWindowInfo (USER32.@)
3293 * Note: tests show that Windows doesn't check cbSize of the structure.
3295 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3297 if (!pwi) return FALSE;
3298 if (!IsWindow(hwnd)) return FALSE;
3300 GetWindowRect(hwnd, &pwi->rcWindow);
3301 GetClientRect(hwnd, &pwi->rcClient);
3302 /* translate to screen coordinates */
3303 MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3305 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3306 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3307 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3309 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3310 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3312 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3313 pwi->wCreatorVersion = 0x0400;
3315 return TRUE;
3318 /******************************************************************************
3319 * SwitchDesktop (USER32.@)
3321 * NOTES: Sets the current input or interactive desktop.
3323 BOOL WINAPI SwitchDesktop( HDESK hDesktop)
3325 FIXME("SwitchDesktop(hwnd %p) stub!\n", hDesktop);
3326 return TRUE;
3329 /*****************************************************************************
3330 * SetLayeredWindowAttributes (USER32.@)
3332 BOOL WINAPI SetLayeredWindowAttributes( HWND hwnd, COLORREF key, BYTE alpha, DWORD flags )
3334 BOOL ret;
3336 TRACE("(%p,%08x,%d,%x): stub!\n", hwnd, key, alpha, flags);
3338 SERVER_START_REQ( set_window_layered_info )
3340 req->handle = hwnd;
3341 req->color_key = key;
3342 req->alpha = alpha;
3343 req->flags = flags;
3344 ret = !wine_server_call_err( req );
3346 SERVER_END_REQ;
3348 if (ret) USER_Driver->pSetLayeredWindowAttributes( hwnd, key, alpha, flags );
3350 return ret;
3354 /*****************************************************************************
3355 * GetLayeredWindowAttributes (USER32.@)
3357 BOOL WINAPI GetLayeredWindowAttributes( HWND hwnd, COLORREF *key, BYTE *alpha, DWORD *flags )
3359 BOOL ret;
3361 SERVER_START_REQ( get_window_layered_info )
3363 req->handle = hwnd;
3364 if ((ret = !wine_server_call_err( req )))
3366 if (key) *key = reply->color_key;
3367 if (alpha) *alpha = reply->alpha;
3368 if (flags) *flags = reply->flags;
3371 SERVER_END_REQ;
3373 return ret;
3377 /*****************************************************************************
3378 * UpdateLayeredWindowIndirect (USER32.@)
3380 BOOL WINAPI UpdateLayeredWindowIndirect( HWND hwnd, const UPDATELAYEREDWINDOWINFO *info )
3382 BYTE alpha = 0xff;
3384 if (!(info->dwFlags & ULW_EX_NORESIZE) && (info->pptDst || info->psize))
3386 int x = 0, y = 0, cx = 0, cy = 0;
3387 DWORD flags = SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW | SWP_NOSENDCHANGING;
3389 if (info->pptDst)
3391 x = info->pptDst->x;
3392 y = info->pptDst->y;
3393 flags &= ~SWP_NOMOVE;
3395 if (info->psize)
3397 cx = info->psize->cx;
3398 cy = info->psize->cy;
3399 flags &= ~SWP_NOSIZE;
3401 TRACE( "moving window %p pos %d,%d %dx%x\n", hwnd, x, y, cx, cy );
3402 SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
3405 if (info->hdcSrc)
3407 RECT rect;
3408 HDC hdc = GetDCEx( hwnd, 0, DCX_CACHE );
3410 if (hdc)
3412 int x = 0, y = 0;
3414 GetClientRect( hwnd, &rect );
3415 if (info->pptSrc)
3417 x = info->pptSrc->x;
3418 y = info->pptSrc->y;
3420 /* FIXME: intersect rect with info->prcDirty */
3421 TRACE( "copying window %p pos %d,%d\n", hwnd, x, y );
3422 BitBlt( hdc, rect.left, rect.top, rect.right, rect.bottom,
3423 info->hdcSrc, rect.left + x, rect.top + y, SRCCOPY );
3424 ReleaseDC( hwnd, hdc );
3428 if (info->pblend && !(info->dwFlags & ULW_OPAQUE)) alpha = info->pblend->SourceConstantAlpha;
3429 TRACE( "setting window %p alpha %u\n", hwnd, alpha );
3430 USER_Driver->pSetLayeredWindowAttributes( hwnd, info->crKey, alpha,
3431 info->dwFlags & (LWA_ALPHA | LWA_COLORKEY) );
3432 return TRUE;
3436 /*****************************************************************************
3437 * UpdateLayeredWindow (USER32.@)
3439 BOOL WINAPI UpdateLayeredWindow( HWND hwnd, HDC hdcDst, POINT *pptDst, SIZE *psize,
3440 HDC hdcSrc, POINT *pptSrc, COLORREF crKey, BLENDFUNCTION *pblend,
3441 DWORD dwFlags)
3443 UPDATELAYEREDWINDOWINFO info;
3445 info.cbSize = sizeof(info);
3446 info.hdcDst = hdcDst;
3447 info.pptDst = pptDst;
3448 info.psize = psize;
3449 info.hdcSrc = hdcSrc;
3450 info.pptSrc = pptSrc;
3451 info.crKey = crKey;
3452 info.pblend = pblend;
3453 info.dwFlags = dwFlags;
3454 info.prcDirty = NULL;
3455 return UpdateLayeredWindowIndirect( hwnd, &info );
3458 /* 64bit versions */
3460 #ifdef GetWindowLongPtrW
3461 #undef GetWindowLongPtrW
3462 #endif
3464 #ifdef GetWindowLongPtrA
3465 #undef GetWindowLongPtrA
3466 #endif
3468 #ifdef SetWindowLongPtrW
3469 #undef SetWindowLongPtrW
3470 #endif
3472 #ifdef SetWindowLongPtrA
3473 #undef SetWindowLongPtrA
3474 #endif
3476 /*****************************************************************************
3477 * GetWindowLongPtrW (USER32.@)
3479 LONG_PTR WINAPI GetWindowLongPtrW( HWND hwnd, INT offset )
3481 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), TRUE );
3484 /*****************************************************************************
3485 * GetWindowLongPtrA (USER32.@)
3487 LONG_PTR WINAPI GetWindowLongPtrA( HWND hwnd, INT offset )
3489 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), FALSE );
3492 /*****************************************************************************
3493 * SetWindowLongPtrW (USER32.@)
3495 LONG_PTR WINAPI SetWindowLongPtrW( HWND hwnd, INT offset, LONG_PTR newval )
3497 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, TRUE );
3500 /*****************************************************************************
3501 * SetWindowLongPtrA (USER32.@)
3503 LONG_PTR WINAPI SetWindowLongPtrA( HWND hwnd, INT offset, LONG_PTR newval )
3505 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, FALSE );