push cc8bc80451cc24f4d7cf75168b569f0ebfe19547
[wine/hacks.git] / dlls / user32 / win.c
blobda196edc585a7a362cec5d8f9cb88c935a6738c6
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 handle = 0, full_parent = 0, full_owner = 0;
104 struct tagCLASS *class = NULL;
105 int extra_bytes = 0;
107 /* if 16-bit instance, map to module handle */
108 if (instance && !HIWORD(instance))
109 instance = HINSTANCE_32(GetExePtr(HINSTANCE_16(instance)));
111 SERVER_START_REQ( create_window )
113 req->parent = wine_server_user_handle( parent );
114 req->owner = wine_server_user_handle( owner );
115 req->instance = wine_server_client_ptr( instance );
116 if (!(req->atom = get_int_atom_value( name )) && name)
117 wine_server_add_data( req, name, strlenW(name)*sizeof(WCHAR) );
118 if (!wine_server_call_err( req ))
120 handle = wine_server_ptr_handle( reply->handle );
121 full_parent = wine_server_ptr_handle( reply->parent );
122 full_owner = wine_server_ptr_handle( reply->owner );
123 extra_bytes = reply->extra;
124 class = wine_server_get_ptr( reply->class_ptr );
127 SERVER_END_REQ;
129 if (!handle)
131 WARN( "error %d creating window\n", GetLastError() );
132 return NULL;
135 if (!(win = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
136 sizeof(WND) + extra_bytes - sizeof(win->wExtra) )))
138 SERVER_START_REQ( destroy_window )
140 req->handle = wine_server_user_handle( handle );
141 wine_server_call( req );
143 SERVER_END_REQ;
144 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
145 return NULL;
148 if (!parent) /* if parent is 0 we don't have a desktop window yet */
150 struct user_thread_info *thread_info = get_user_thread_info();
152 if (name == (LPCWSTR)DESKTOP_CLASS_ATOM)
154 if (!thread_info->top_window) thread_info->top_window = full_parent ? full_parent : handle;
155 else assert( full_parent == thread_info->top_window );
156 if (full_parent && !USER_Driver->pCreateDesktopWindow( thread_info->top_window ))
157 ERR( "failed to create desktop window\n" );
159 else /* HWND_MESSAGE parent */
161 if (!thread_info->msg_window && !full_parent) thread_info->msg_window = handle;
165 USER_Lock();
167 index = USER_HANDLE_TO_INDEX(handle);
168 assert( index < NB_USER_HANDLES );
169 user_handles[index] = win;
170 win->hwndSelf = handle;
171 win->parent = full_parent;
172 win->owner = full_owner;
173 win->class = class;
174 win->winproc = get_class_winproc( class );
175 win->dwMagic = WND_MAGIC;
176 win->cbWndExtra = extra_bytes;
177 if (WINPROC_IsUnicode( win->winproc, unicode )) win->flags |= WIN_ISUNICODE;
178 return win;
182 /***********************************************************************
183 * free_window_handle
185 * Free a window handle.
187 static WND *free_window_handle( HWND hwnd )
189 WND *ptr;
190 WORD index = USER_HANDLE_TO_INDEX(hwnd);
192 if (index >= NB_USER_HANDLES) return NULL;
193 USER_Lock();
194 if ((ptr = user_handles[index]))
196 SERVER_START_REQ( destroy_window )
198 req->handle = wine_server_user_handle( hwnd );
199 if (!wine_server_call_err( req ))
201 user_handles[index] = NULL;
202 ptr->dwMagic = 0;
204 else
205 ptr = NULL;
207 SERVER_END_REQ;
209 USER_Unlock();
210 HeapFree( GetProcessHeap(), 0, ptr );
211 return ptr;
215 /*******************************************************************
216 * list_window_children
218 * Build an array of the children of a given window. The array must be
219 * freed with HeapFree. Returns NULL when no windows are found.
221 static HWND *list_window_children( HDESK desktop, HWND hwnd, LPCWSTR class, DWORD tid )
223 HWND *list;
224 int i, size = 128;
225 ATOM atom = get_int_atom_value( class );
227 /* empty class is not the same as NULL class */
228 if (!atom && class && !class[0]) return NULL;
230 for (;;)
232 int count = 0;
234 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
236 SERVER_START_REQ( get_window_children )
238 req->desktop = wine_server_obj_handle( desktop );
239 req->parent = wine_server_user_handle( hwnd );
240 req->tid = tid;
241 req->atom = atom;
242 if (!atom && class) wine_server_add_data( req, class, strlenW(class)*sizeof(WCHAR) );
243 wine_server_set_reply( req, list, (size-1) * sizeof(user_handle_t) );
244 if (!wine_server_call( req )) count = reply->count;
246 SERVER_END_REQ;
247 if (count && count < size)
249 /* start from the end since HWND is potentially larger than user_handle_t */
250 for (i = count - 1; i >= 0; i--)
251 list[i] = wine_server_ptr_handle( ((user_handle_t *)list)[i] );
252 list[count] = 0;
253 return list;
255 HeapFree( GetProcessHeap(), 0, list );
256 if (!count) break;
257 size = count + 1; /* restart with a large enough buffer */
259 return NULL;
263 /*******************************************************************
264 * list_window_parents
266 * Build an array of all parents of a given window, starting with
267 * the immediate parent. The array must be freed with HeapFree.
269 static HWND *list_window_parents( HWND hwnd )
271 WND *win;
272 HWND current, *list;
273 int i, pos = 0, size = 16, count = 0;
275 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
277 current = hwnd;
278 for (;;)
280 if (!(win = WIN_GetPtr( current ))) goto empty;
281 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
282 if (win == WND_DESKTOP)
284 if (!pos) goto empty;
285 list[pos] = 0;
286 return list;
288 list[pos] = current = win->parent;
289 WIN_ReleasePtr( win );
290 if (!current) return list;
291 if (++pos == size - 1)
293 /* need to grow the list */
294 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
295 if (!new_list) goto empty;
296 list = new_list;
297 size += 16;
301 /* at least one parent belongs to another process, have to query the server */
303 for (;;)
305 count = 0;
306 SERVER_START_REQ( get_window_parents )
308 req->handle = wine_server_user_handle( hwnd );
309 wine_server_set_reply( req, list, (size-1) * sizeof(user_handle_t) );
310 if (!wine_server_call( req )) count = reply->count;
312 SERVER_END_REQ;
313 if (!count) goto empty;
314 if (size > count)
316 /* start from the end since HWND is potentially larger than user_handle_t */
317 for (i = count - 1; i >= 0; i--)
318 list[i] = wine_server_ptr_handle( ((user_handle_t *)list)[i] );
319 list[count] = 0;
320 return list;
322 HeapFree( GetProcessHeap(), 0, list );
323 size = count + 1;
324 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
327 empty:
328 HeapFree( GetProcessHeap(), 0, list );
329 return NULL;
333 /*******************************************************************
334 * send_parent_notify
336 static void send_parent_notify( HWND hwnd, UINT msg )
338 if ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_CHILD | WS_POPUP)) == WS_CHILD &&
339 !(GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY))
341 HWND parent = GetParent(hwnd);
342 if (parent && parent != GetDesktopWindow())
343 SendMessageW( parent, WM_PARENTNOTIFY,
344 MAKEWPARAM( msg, GetWindowLongPtrW( hwnd, GWLP_ID )), (LPARAM)hwnd );
349 /*******************************************************************
350 * get_server_window_text
352 * Retrieve the window text from the server.
354 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
356 size_t len = 0;
358 SERVER_START_REQ( get_window_text )
360 req->handle = wine_server_user_handle( hwnd );
361 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
362 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
364 SERVER_END_REQ;
365 text[len / sizeof(WCHAR)] = 0;
369 /*******************************************************************
370 * get_hwnd_message_parent
372 * Return the parent for HWND_MESSAGE windows.
374 HWND get_hwnd_message_parent(void)
376 struct user_thread_info *thread_info = get_user_thread_info();
378 if (!thread_info->msg_window) GetDesktopWindow(); /* trigger creation */
379 return thread_info->msg_window;
383 /*******************************************************************
384 * is_desktop_window
386 * Check if window is the desktop or the HWND_MESSAGE top parent.
388 BOOL is_desktop_window( HWND hwnd )
390 struct user_thread_info *thread_info = get_user_thread_info();
392 if (!hwnd) return FALSE;
393 if (hwnd == thread_info->top_window) return TRUE;
394 if (hwnd == thread_info->msg_window) return TRUE;
396 if (!HIWORD(hwnd) || HIWORD(hwnd) == 0xffff)
398 if (LOWORD(thread_info->top_window) == LOWORD(hwnd)) return TRUE;
399 if (LOWORD(thread_info->msg_window) == LOWORD(hwnd)) return TRUE;
401 return FALSE;
405 /***********************************************************************
406 * WIN_GetPtr
408 * Return a pointer to the WND structure if local to the process,
409 * or WND_OTHER_PROCESS if handle may be valid in other process.
410 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
412 WND *WIN_GetPtr( HWND hwnd )
414 WND * ptr;
415 WORD index = USER_HANDLE_TO_INDEX(hwnd);
417 if (index >= NB_USER_HANDLES) return NULL;
419 USER_Lock();
420 if ((ptr = user_handles[index]))
422 if (ptr->dwMagic == WND_MAGIC &&
423 (hwnd == ptr->hwndSelf || !HIWORD(hwnd) || HIWORD(hwnd) == 0xffff))
424 return ptr;
425 ptr = NULL;
427 else if (is_desktop_window( hwnd )) ptr = WND_DESKTOP;
428 else ptr = WND_OTHER_PROCESS;
429 USER_Unlock();
430 return ptr;
434 /***********************************************************************
435 * WIN_IsCurrentProcess
437 * Check whether a given window belongs to the current process (and return the full handle).
439 HWND WIN_IsCurrentProcess( HWND hwnd )
441 WND *ptr;
442 HWND ret;
444 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
445 ret = ptr->hwndSelf;
446 WIN_ReleasePtr( ptr );
447 return ret;
451 /***********************************************************************
452 * WIN_IsCurrentThread
454 * Check whether a given window belongs to the current thread (and return the full handle).
456 HWND WIN_IsCurrentThread( HWND hwnd )
458 WND *ptr;
459 HWND ret = 0;
461 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
462 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
463 WIN_ReleasePtr( ptr );
464 return ret;
468 /***********************************************************************
469 * WIN_Handle32
471 * Convert a 16-bit window handle to a full 32-bit handle.
473 HWND WIN_Handle32( HWND16 hwnd16 )
475 WND *ptr;
476 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
478 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
479 /* do sign extension for -2 and -3 */
480 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
482 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
484 if (ptr == WND_DESKTOP)
486 if (LOWORD(hwnd) == LOWORD(GetDesktopWindow())) return GetDesktopWindow();
487 else return get_hwnd_message_parent();
490 if (ptr != WND_OTHER_PROCESS)
492 hwnd = ptr->hwndSelf;
493 WIN_ReleasePtr( ptr );
495 else /* may belong to another process */
497 SERVER_START_REQ( get_window_info )
499 req->handle = wine_server_user_handle( hwnd );
500 if (!wine_server_call_err( req )) hwnd = wine_server_ptr_handle( reply->full_handle );
502 SERVER_END_REQ;
504 return hwnd;
508 /***********************************************************************
509 * WIN_SetOwner
511 * Change the owner of a window.
513 HWND WIN_SetOwner( HWND hwnd, HWND owner )
515 WND *win = WIN_GetPtr( hwnd );
516 HWND ret = 0;
518 if (!win || win == WND_DESKTOP) return 0;
519 if (win == WND_OTHER_PROCESS)
521 if (IsWindow(hwnd)) ERR( "cannot set owner %p on other process window %p\n", owner, hwnd );
522 return 0;
524 SERVER_START_REQ( set_window_owner )
526 req->handle = wine_server_user_handle( hwnd );
527 req->owner = wine_server_user_handle( owner );
528 if (!wine_server_call( req ))
530 win->owner = wine_server_ptr_handle( reply->full_owner );
531 ret = wine_server_ptr_handle( reply->prev_owner );
534 SERVER_END_REQ;
535 WIN_ReleasePtr( win );
536 return ret;
540 /***********************************************************************
541 * WIN_SetStyle
543 * Change the style of a window.
545 ULONG WIN_SetStyle( HWND hwnd, ULONG set_bits, ULONG clear_bits )
547 BOOL ok;
548 STYLESTRUCT style;
549 WND *win = WIN_GetPtr( hwnd );
551 if (!win || win == WND_DESKTOP) return 0;
552 if (win == WND_OTHER_PROCESS)
554 if (IsWindow(hwnd))
555 ERR( "cannot set style %x/%x on other process window %p\n",
556 set_bits, clear_bits, hwnd );
557 return 0;
559 style.styleOld = win->dwStyle;
560 style.styleNew = (win->dwStyle | set_bits) & ~clear_bits;
561 if (style.styleNew == style.styleOld)
563 WIN_ReleasePtr( win );
564 return style.styleNew;
566 SERVER_START_REQ( set_window_info )
568 req->handle = wine_server_user_handle( hwnd );
569 req->flags = SET_WIN_STYLE;
570 req->style = style.styleNew;
571 req->extra_offset = -1;
572 if ((ok = !wine_server_call( req )))
574 style.styleOld = reply->old_style;
575 win->dwStyle = style.styleNew;
578 SERVER_END_REQ;
579 WIN_ReleasePtr( win );
580 if (ok)
582 USER_Driver->pSetWindowStyle( hwnd, GWL_STYLE, &style );
583 if ((style.styleOld ^ style.styleNew) & WS_VISIBLE) invalidate_dce( hwnd, NULL );
585 return style.styleOld;
589 /***********************************************************************
590 * WIN_GetRectangles
592 * Get the window and client rectangles.
594 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
596 WND *win = WIN_GetPtr( hwnd );
597 BOOL ret = TRUE;
599 if (!win) return FALSE;
600 if (win == WND_DESKTOP)
602 RECT rect;
603 rect.left = rect.top = 0;
604 if (hwnd == get_hwnd_message_parent())
606 rect.right = 100;
607 rect.bottom = 100;
609 else
611 rect.right = GetSystemMetrics(SM_CXSCREEN);
612 rect.bottom = GetSystemMetrics(SM_CYSCREEN);
614 if (rectWindow) *rectWindow = rect;
615 if (rectClient) *rectClient = rect;
617 else if (win == WND_OTHER_PROCESS)
619 SERVER_START_REQ( get_window_rectangles )
621 req->handle = wine_server_user_handle( hwnd );
622 if ((ret = !wine_server_call( req )))
624 if (rectWindow)
626 rectWindow->left = reply->window.left;
627 rectWindow->top = reply->window.top;
628 rectWindow->right = reply->window.right;
629 rectWindow->bottom = reply->window.bottom;
631 if (rectClient)
633 rectClient->left = reply->client.left;
634 rectClient->top = reply->client.top;
635 rectClient->right = reply->client.right;
636 rectClient->bottom = reply->client.bottom;
640 SERVER_END_REQ;
642 else
644 if (rectWindow) *rectWindow = win->rectWindow;
645 if (rectClient) *rectClient = win->rectClient;
646 WIN_ReleasePtr( win );
648 return ret;
652 /***********************************************************************
653 * WIN_DestroyWindow
655 * Destroy storage associated to a window. "Internals" p.358
657 LRESULT WIN_DestroyWindow( HWND hwnd )
659 WND *wndPtr;
660 HWND *list;
661 HMENU menu = 0, sys_menu;
662 HWND icon_title;
664 TRACE("%p\n", hwnd );
666 /* free child windows */
667 if ((list = WIN_ListChildren( hwnd )))
669 int i;
670 for (i = 0; list[i]; i++)
672 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
673 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
675 HeapFree( GetProcessHeap(), 0, list );
678 /* Unlink now so we won't bother with the children later on */
679 SERVER_START_REQ( set_parent )
681 req->handle = wine_server_user_handle( hwnd );
682 req->parent = 0;
683 wine_server_call( req );
685 SERVER_END_REQ;
688 * Send the WM_NCDESTROY to the window being destroyed.
690 SendMessageW( hwnd, WM_NCDESTROY, 0, 0 );
692 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
694 /* free resources associated with the window */
696 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
697 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
698 menu = (HMENU)wndPtr->wIDmenu;
699 sys_menu = wndPtr->hSysMenu;
700 free_dce( wndPtr->dce, hwnd );
701 wndPtr->dce = NULL;
702 icon_title = wndPtr->icon_title;
703 WIN_ReleasePtr( wndPtr );
705 if (icon_title) DestroyWindow( icon_title );
706 if (menu) DestroyMenu( menu );
707 if (sys_menu) DestroyMenu( sys_menu );
709 USER_Driver->pDestroyWindow( hwnd );
711 free_window_handle( hwnd );
712 return 0;
716 /***********************************************************************
717 * destroy_thread_window
719 * Destroy a window upon exit of its thread.
721 static void destroy_thread_window( HWND hwnd )
723 WND *wndPtr;
724 HWND *list;
725 HMENU menu = 0, sys_menu = 0;
726 WORD index;
728 /* free child windows */
730 if ((list = WIN_ListChildren( hwnd )))
732 int i;
733 for (i = 0; list[i]; i++)
735 if (WIN_IsCurrentThread( list[i] )) destroy_thread_window( list[i] );
736 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
738 HeapFree( GetProcessHeap(), 0, list );
741 /* destroy the client-side storage */
743 index = USER_HANDLE_TO_INDEX(hwnd);
744 if (index >= NB_USER_HANDLES) return;
745 USER_Lock();
746 if ((wndPtr = user_handles[index]))
748 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD) menu = (HMENU)wndPtr->wIDmenu;
749 sys_menu = wndPtr->hSysMenu;
750 free_dce( wndPtr->dce, hwnd );
751 user_handles[index] = NULL;
752 wndPtr->dwMagic = 0;
754 USER_Unlock();
756 HeapFree( GetProcessHeap(), 0, wndPtr );
757 if (menu) DestroyMenu( menu );
758 if (sys_menu) DestroyMenu( sys_menu );
762 /***********************************************************************
763 * destroy_thread_child_windows
765 * Destroy child windows upon exit of its thread.
767 static void destroy_thread_child_windows( HWND hwnd )
769 HWND *list;
770 int i;
772 if (WIN_IsCurrentThread( hwnd ))
774 destroy_thread_window( hwnd );
776 else if ((list = WIN_ListChildren( hwnd )))
778 for (i = 0; list[i]; i++) destroy_thread_child_windows( list[i] );
779 HeapFree( GetProcessHeap(), 0, list );
784 /***********************************************************************
785 * WIN_DestroyThreadWindows
787 * Destroy all children of 'wnd' owned by the current thread.
789 void WIN_DestroyThreadWindows( HWND hwnd )
791 HWND *list;
792 int i;
794 if (!(list = WIN_ListChildren( hwnd ))) return;
796 /* reset owners of top-level windows */
797 for (i = 0; list[i]; i++)
799 if (!WIN_IsCurrentThread( list[i] ))
801 HWND owner = GetWindow( list[i], GW_OWNER );
802 if (owner && WIN_IsCurrentThread( owner )) WIN_SetOwner( list[i], 0 );
806 for (i = 0; list[i]; i++) destroy_thread_child_windows( list[i] );
807 HeapFree( GetProcessHeap(), 0, list );
811 /***********************************************************************
812 * WIN_FixCoordinates
814 * Fix the coordinates - Helper for WIN_CreateWindowEx.
815 * returns default show mode in sw.
817 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
819 #define IS_DEFAULT(x) ((x) == CW_USEDEFAULT || (x) == CW_USEDEFAULT16)
820 POINT pos[2];
822 if (cs->dwExStyle & WS_EX_MDICHILD)
824 UINT id = 0;
826 MDI_CalcDefaultChildPos(cs->hwndParent, -1, pos, 0, &id);
827 if (!(cs->style & WS_POPUP)) cs->hMenu = ULongToHandle(id);
829 TRACE("MDI child id %04x\n", id);
832 if (cs->style & (WS_CHILD | WS_POPUP))
834 if (cs->dwExStyle & WS_EX_MDICHILD)
836 if (IS_DEFAULT(cs->x))
838 cs->x = pos[0].x;
839 cs->y = pos[0].y;
841 if (IS_DEFAULT(cs->cx) || !cs->cx) cs->cx = pos[1].x;
842 if (IS_DEFAULT(cs->cy) || !cs->cy) cs->cy = pos[1].y;
844 else
846 if (IS_DEFAULT(cs->x)) cs->x = cs->y = 0;
847 if (IS_DEFAULT(cs->cx)) cs->cx = cs->cy = 0;
850 else /* overlapped window */
852 HMONITOR monitor;
853 MONITORINFO mon_info;
854 STARTUPINFOW info;
856 if (!IS_DEFAULT(cs->x) && !IS_DEFAULT(cs->cx) && !IS_DEFAULT(cs->cy)) return;
858 monitor = MonitorFromWindow( cs->hwndParent, MONITOR_DEFAULTTOPRIMARY );
859 mon_info.cbSize = sizeof(mon_info);
860 GetMonitorInfoW( monitor, &mon_info );
861 GetStartupInfoW( &info );
863 if (IS_DEFAULT(cs->x))
865 if (!IS_DEFAULT(cs->y)) *sw = cs->y;
866 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : mon_info.rcWork.left;
867 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : mon_info.rcWork.top;
870 if (IS_DEFAULT(cs->cx))
872 if (info.dwFlags & STARTF_USESIZE)
874 cs->cx = info.dwXSize;
875 cs->cy = info.dwYSize;
877 else
879 cs->cx = (mon_info.rcWork.right - mon_info.rcWork.left) * 3 / 4 - cs->x;
880 cs->cy = (mon_info.rcWork.bottom - mon_info.rcWork.top) * 3 / 4 - cs->y;
883 /* neither x nor cx are default. Check the y values .
884 * In the trace we see Outlook and Outlook Express using
885 * cy set to CW_USEDEFAULT when opening the address book.
887 else if (IS_DEFAULT(cs->cy))
889 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
890 cs->cy = (mon_info.rcWork.bottom - mon_info.rcWork.top) * 3 / 4 - cs->y;
893 #undef IS_DEFAULT
896 /***********************************************************************
897 * dump_window_styles
899 static void dump_window_styles( DWORD style, DWORD exstyle )
901 TRACE( "style:" );
902 if(style & WS_POPUP) TRACE(" WS_POPUP");
903 if(style & WS_CHILD) TRACE(" WS_CHILD");
904 if(style & WS_MINIMIZE) TRACE(" WS_MINIMIZE");
905 if(style & WS_VISIBLE) TRACE(" WS_VISIBLE");
906 if(style & WS_DISABLED) TRACE(" WS_DISABLED");
907 if(style & WS_CLIPSIBLINGS) TRACE(" WS_CLIPSIBLINGS");
908 if(style & WS_CLIPCHILDREN) TRACE(" WS_CLIPCHILDREN");
909 if(style & WS_MAXIMIZE) TRACE(" WS_MAXIMIZE");
910 if((style & WS_CAPTION) == WS_CAPTION) TRACE(" WS_CAPTION");
911 else
913 if(style & WS_BORDER) TRACE(" WS_BORDER");
914 if(style & WS_DLGFRAME) TRACE(" WS_DLGFRAME");
916 if(style & WS_VSCROLL) TRACE(" WS_VSCROLL");
917 if(style & WS_HSCROLL) TRACE(" WS_HSCROLL");
918 if(style & WS_SYSMENU) TRACE(" WS_SYSMENU");
919 if(style & WS_THICKFRAME) TRACE(" WS_THICKFRAME");
920 if (style & WS_CHILD)
922 if(style & WS_GROUP) TRACE(" WS_GROUP");
923 if(style & WS_TABSTOP) TRACE(" WS_TABSTOP");
925 else
927 if(style & WS_MINIMIZEBOX) TRACE(" WS_MINIMIZEBOX");
928 if(style & WS_MAXIMIZEBOX) TRACE(" WS_MAXIMIZEBOX");
931 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
932 #define DUMPED_STYLES \
933 (WS_POPUP | \
934 WS_CHILD | \
935 WS_MINIMIZE | \
936 WS_VISIBLE | \
937 WS_DISABLED | \
938 WS_CLIPSIBLINGS | \
939 WS_CLIPCHILDREN | \
940 WS_MAXIMIZE | \
941 WS_BORDER | \
942 WS_DLGFRAME | \
943 WS_VSCROLL | \
944 WS_HSCROLL | \
945 WS_SYSMENU | \
946 WS_THICKFRAME | \
947 WS_GROUP | \
948 WS_TABSTOP | \
949 WS_MINIMIZEBOX | \
950 WS_MAXIMIZEBOX)
952 if(style & ~DUMPED_STYLES) TRACE(" %08lx", style & ~DUMPED_STYLES);
953 TRACE("\n");
954 #undef DUMPED_STYLES
956 TRACE( "exstyle:" );
957 if(exstyle & WS_EX_DLGMODALFRAME) TRACE(" WS_EX_DLGMODALFRAME");
958 if(exstyle & WS_EX_DRAGDETECT) TRACE(" WS_EX_DRAGDETECT");
959 if(exstyle & WS_EX_NOPARENTNOTIFY) TRACE(" WS_EX_NOPARENTNOTIFY");
960 if(exstyle & WS_EX_TOPMOST) TRACE(" WS_EX_TOPMOST");
961 if(exstyle & WS_EX_ACCEPTFILES) TRACE(" WS_EX_ACCEPTFILES");
962 if(exstyle & WS_EX_TRANSPARENT) TRACE(" WS_EX_TRANSPARENT");
963 if(exstyle & WS_EX_MDICHILD) TRACE(" WS_EX_MDICHILD");
964 if(exstyle & WS_EX_TOOLWINDOW) TRACE(" WS_EX_TOOLWINDOW");
965 if(exstyle & WS_EX_WINDOWEDGE) TRACE(" WS_EX_WINDOWEDGE");
966 if(exstyle & WS_EX_CLIENTEDGE) TRACE(" WS_EX_CLIENTEDGE");
967 if(exstyle & WS_EX_CONTEXTHELP) TRACE(" WS_EX_CONTEXTHELP");
968 if(exstyle & WS_EX_RIGHT) TRACE(" WS_EX_RIGHT");
969 if(exstyle & WS_EX_RTLREADING) TRACE(" WS_EX_RTLREADING");
970 if(exstyle & WS_EX_LEFTSCROLLBAR) TRACE(" WS_EX_LEFTSCROLLBAR");
971 if(exstyle & WS_EX_CONTROLPARENT) TRACE(" WS_EX_CONTROLPARENT");
972 if(exstyle & WS_EX_STATICEDGE) TRACE(" WS_EX_STATICEDGE");
973 if(exstyle & WS_EX_APPWINDOW) TRACE(" WS_EX_APPWINDOW");
974 if(exstyle & WS_EX_LAYERED) TRACE(" WS_EX_LAYERED");
976 #define DUMPED_EX_STYLES \
977 (WS_EX_DLGMODALFRAME | \
978 WS_EX_DRAGDETECT | \
979 WS_EX_NOPARENTNOTIFY | \
980 WS_EX_TOPMOST | \
981 WS_EX_ACCEPTFILES | \
982 WS_EX_TRANSPARENT | \
983 WS_EX_MDICHILD | \
984 WS_EX_TOOLWINDOW | \
985 WS_EX_WINDOWEDGE | \
986 WS_EX_CLIENTEDGE | \
987 WS_EX_CONTEXTHELP | \
988 WS_EX_RIGHT | \
989 WS_EX_RTLREADING | \
990 WS_EX_LEFTSCROLLBAR | \
991 WS_EX_CONTROLPARENT | \
992 WS_EX_STATICEDGE | \
993 WS_EX_APPWINDOW | \
994 WS_EX_LAYERED)
996 if(exstyle & ~DUMPED_EX_STYLES) TRACE(" %08lx", exstyle & ~DUMPED_EX_STYLES);
997 TRACE("\n");
998 #undef DUMPED_EX_STYLES
1002 /***********************************************************************
1003 * WIN_CreateWindowEx
1005 * Implementation of CreateWindowEx().
1007 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, LPCWSTR className, UINT flags )
1009 INT cx, cy, style, sw = SW_SHOW;
1010 LRESULT result;
1011 RECT rect;
1012 WND *wndPtr;
1013 HWND hwnd, parent, owner, top_child = 0;
1014 BOOL unicode = (flags & WIN_ISUNICODE) != 0;
1015 MDICREATESTRUCTA mdi_cs;
1016 CBT_CREATEWNDA cbtc;
1017 CREATESTRUCTA cbcs;
1019 TRACE("%s %s ex=%08x style=%08x %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
1020 unicode ? debugstr_w((LPCWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
1021 debugstr_w(className),
1022 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
1023 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
1024 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
1026 /* Fix the styles for MDI children */
1027 if (cs->dwExStyle & WS_EX_MDICHILD)
1029 UINT flags = 0;
1031 wndPtr = WIN_GetPtr(cs->hwndParent);
1032 if (wndPtr && wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
1034 flags = wndPtr->flags;
1035 WIN_ReleasePtr(wndPtr);
1038 if (!(flags & WIN_ISMDICLIENT))
1040 WARN("WS_EX_MDICHILD, but parent %p is not MDIClient\n", cs->hwndParent);
1041 return 0;
1044 /* cs->lpCreateParams of WM_[NC]CREATE is different for MDI children.
1045 * MDICREATESTRUCT members have the originally passed values.
1047 * Note: we rely on the fact that MDICREATESTRUCTA and MDICREATESTRUCTW
1048 * have the same layout.
1050 mdi_cs.szClass = cs->lpszClass;
1051 mdi_cs.szTitle = cs->lpszName;
1052 mdi_cs.hOwner = cs->hInstance;
1053 mdi_cs.x = cs->x;
1054 mdi_cs.y = cs->y;
1055 mdi_cs.cx = cs->cx;
1056 mdi_cs.cy = cs->cy;
1057 mdi_cs.style = cs->style;
1058 mdi_cs.lParam = (LPARAM)cs->lpCreateParams;
1060 cs->lpCreateParams = &mdi_cs;
1062 if (GetWindowLongW(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
1064 if (cs->style & WS_POPUP)
1066 TRACE("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n");
1067 return 0;
1069 cs->style |= WS_CHILD | WS_CLIPSIBLINGS;
1071 else
1073 cs->style &= ~WS_POPUP;
1074 cs->style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
1075 WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
1078 top_child = GetWindow(cs->hwndParent, GW_CHILD);
1080 if (top_child)
1082 /* Restore current maximized child */
1083 if((cs->style & WS_VISIBLE) && IsZoomed(top_child))
1085 TRACE("Restoring current maximized child %p\n", top_child);
1086 SendMessageW( top_child, WM_SETREDRAW, FALSE, 0 );
1087 ShowWindow( top_child, SW_SHOWNORMAL );
1088 SendMessageW( top_child, WM_SETREDRAW, TRUE, 0 );
1093 /* Find the parent window */
1095 parent = cs->hwndParent;
1096 owner = 0;
1098 if (cs->hwndParent == HWND_MESSAGE)
1100 cs->hwndParent = parent = get_hwnd_message_parent();
1102 else if (cs->hwndParent)
1104 if ((cs->style & (WS_CHILD|WS_POPUP)) != WS_CHILD)
1106 parent = GetDesktopWindow();
1107 owner = cs->hwndParent;
1110 else
1112 static const WCHAR messageW[] = {'M','e','s','s','a','g','e',0};
1114 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1116 WARN("No parent for child window\n" );
1117 SetLastError(ERROR_TLW_WITH_WSCHILD);
1118 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1120 /* are we creating the desktop or HWND_MESSAGE parent itself? */
1121 if (className != (LPCWSTR)DESKTOP_CLASS_ATOM &&
1122 (IS_INTRESOURCE(className) || strcmpiW( className, messageW )))
1123 parent = GetDesktopWindow();
1126 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
1128 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
1129 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
1130 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
1131 cs->dwExStyle |= WS_EX_WINDOWEDGE;
1132 else
1133 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
1135 /* Create the window structure */
1137 if (!(wndPtr = create_window_handle( parent, owner, className, cs->hInstance, unicode )))
1138 return 0;
1139 hwnd = wndPtr->hwndSelf;
1141 /* Fill the window structure */
1143 wndPtr->tid = GetCurrentThreadId();
1144 wndPtr->hInstance = cs->hInstance;
1145 wndPtr->text = NULL;
1146 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1147 wndPtr->dwExStyle = cs->dwExStyle;
1148 wndPtr->wIDmenu = 0;
1149 wndPtr->helpContext = 0;
1150 wndPtr->pScroll = NULL;
1151 wndPtr->userdata = 0;
1152 wndPtr->hIcon = 0;
1153 wndPtr->hIconSmall = 0;
1154 wndPtr->hSysMenu = 0;
1155 wndPtr->flags |= (flags & WIN_ISWIN32);
1157 wndPtr->min_pos.x = wndPtr->min_pos.y = -1;
1158 wndPtr->max_pos.x = wndPtr->max_pos.y = -1;
1160 if (wndPtr->dwStyle & WS_SYSMENU) SetSystemMenu( hwnd, 0 );
1163 * Correct the window styles.
1165 * It affects only the style loaded into the WIN structure.
1168 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
1170 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1171 if (!(wndPtr->dwStyle & WS_POPUP))
1172 wndPtr->dwStyle |= WS_CAPTION;
1176 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1177 * why does the user get to set it?
1180 if ((wndPtr->dwExStyle & WS_EX_DLGMODALFRAME) ||
1181 (wndPtr->dwStyle & (WS_DLGFRAME | WS_THICKFRAME)))
1182 wndPtr->dwExStyle |= WS_EX_WINDOWEDGE;
1183 else
1184 wndPtr->dwExStyle &= ~WS_EX_WINDOWEDGE;
1186 if (!(wndPtr->dwStyle & (WS_CHILD | WS_POPUP)))
1187 wndPtr->flags |= WIN_NEED_SIZE;
1189 SERVER_START_REQ( set_window_info )
1191 req->handle = wine_server_user_handle( hwnd );
1192 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE | SET_WIN_UNICODE;
1193 req->style = wndPtr->dwStyle;
1194 req->ex_style = wndPtr->dwExStyle;
1195 req->instance = wine_server_client_ptr( wndPtr->hInstance );
1196 req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
1197 req->extra_offset = -1;
1198 wine_server_call( req );
1200 SERVER_END_REQ;
1202 /* Set the window menu */
1204 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
1206 if (cs->hMenu)
1208 if (!MENU_SetMenu(hwnd, cs->hMenu))
1210 WIN_ReleasePtr( wndPtr );
1211 free_window_handle( hwnd );
1212 return 0;
1215 else
1217 LPCSTR menuName = (LPCSTR)GetClassLongPtrA( hwnd, GCLP_MENUNAME );
1218 if (menuName)
1220 if (!cs->hInstance || HIWORD(cs->hInstance))
1221 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1222 else
1223 cs->hMenu = HMENU_32(LoadMenu16(HINSTANCE_16(cs->hInstance),menuName));
1225 if (cs->hMenu) MENU_SetMenu( hwnd, cs->hMenu );
1229 else SetWindowLongPtrW( hwnd, GWLP_ID, (ULONG_PTR)cs->hMenu );
1231 /* call the WH_CBT hook */
1233 /* the window style passed to the hook must be the real window style,
1234 * rather than just the window style that the caller to CreateWindowEx
1235 * passed in, so we have to copy the original CREATESTRUCT and get the
1236 * the real style. */
1237 cbcs = *cs;
1238 cbcs.style = wndPtr->dwStyle;
1239 cbtc.lpcs = &cbcs;
1240 cbtc.hwndInsertAfter = HWND_TOP;
1241 WIN_ReleasePtr( wndPtr );
1242 if (HOOK_CallHooks( WH_CBT, HCBT_CREATEWND, (WPARAM)hwnd, (LPARAM)&cbtc, unicode )) goto failed;
1244 /* send the WM_GETMINMAXINFO message and fix the size if needed */
1246 cx = cs->cx;
1247 cy = cs->cy;
1248 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
1250 POINT maxSize, maxPos, minTrack, maxTrack;
1251 WINPOS_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack);
1252 if (maxTrack.x < cx) cx = maxTrack.x;
1253 if (maxTrack.y < cy) cy = maxTrack.y;
1254 if (minTrack.x > cx) cx = minTrack.x;
1255 if (minTrack.y > cy) cy = minTrack.y;
1258 if (cx < 0) cx = 0;
1259 if (cy < 0) cy = 0;
1260 SetRect( &rect, cs->x, cs->y, cs->x + cx, cs->y + cy );
1261 /* check for wraparound */
1262 if (cs->x + cx < cs->x) rect.right = 0x7fffffff;
1263 if (cs->y + cy < cs->y) rect.bottom = 0x7fffffff;
1264 if (!set_window_pos( hwnd, 0, SWP_NOZORDER | SWP_NOACTIVATE, &rect, &rect, NULL )) goto failed;
1266 /* send WM_NCCREATE */
1268 TRACE( "hwnd %p cs %d,%d %dx%d\n", hwnd, cs->x, cs->y, cx, cy );
1269 if (unicode)
1270 result = SendMessageW( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
1271 else
1272 result = SendMessageA( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
1273 if (!result)
1275 WARN( "%p: aborted by WM_NCCREATE\n", hwnd );
1276 goto failed;
1279 /* send WM_NCCALCSIZE */
1281 if ((wndPtr = WIN_GetPtr(hwnd)))
1283 /* yes, even if the CBT hook was called with HWND_TOP */
1284 POINT pt;
1285 HWND insert_after = (wndPtr->dwStyle & WS_CHILD) ? HWND_BOTTOM : HWND_TOP;
1286 RECT window_rect = wndPtr->rectWindow;
1287 RECT client_rect = window_rect;
1288 WIN_ReleasePtr( wndPtr );
1290 /* the rectangle is in screen coords for WM_NCCALCSIZE when wparam is FALSE */
1291 pt.x = pt.y = 0;
1292 MapWindowPoints( parent, 0, &pt, 1 );
1293 OffsetRect( &client_rect, pt.x, pt.y );
1294 SendMessageW( hwnd, WM_NCCALCSIZE, FALSE, (LPARAM)&client_rect );
1295 OffsetRect( &client_rect, -pt.x, -pt.y );
1296 set_window_pos( hwnd, insert_after, SWP_NOACTIVATE, &window_rect, &client_rect, NULL );
1298 else return 0;
1300 /* send WM_CREATE */
1302 if (unicode)
1303 result = SendMessageW( hwnd, WM_CREATE, 0, (LPARAM)cs );
1304 else
1305 result = SendMessageA( hwnd, WM_CREATE, 0, (LPARAM)cs );
1306 if (result == -1) goto failed;
1308 /* call the driver */
1310 if (!USER_Driver->pCreateWindow( hwnd )) goto failed;
1312 NotifyWinEvent(EVENT_OBJECT_CREATE, hwnd, OBJID_WINDOW, 0);
1314 /* send the size messages */
1316 if (!(wndPtr = WIN_GetPtr( hwnd )) ||
1317 wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return 0;
1318 if (!(wndPtr->flags & WIN_NEED_SIZE))
1320 rect = wndPtr->rectClient;
1321 WIN_ReleasePtr( wndPtr );
1322 SendMessageW( hwnd, WM_SIZE, SIZE_RESTORED,
1323 MAKELONG(rect.right-rect.left, rect.bottom-rect.top));
1324 SendMessageW( hwnd, WM_MOVE, 0, MAKELONG( rect.left, rect.top ) );
1326 else WIN_ReleasePtr( wndPtr );
1328 /* Show the window, maximizing or minimizing if needed */
1330 style = WIN_SetStyle( hwnd, 0, WS_MAXIMIZE | WS_MINIMIZE );
1331 if (style & (WS_MINIMIZE | WS_MAXIMIZE))
1333 RECT newPos;
1334 UINT swFlag = (style & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
1336 swFlag = WINPOS_MinMaximize( hwnd, swFlag, &newPos );
1337 swFlag |= SWP_FRAMECHANGED; /* Frame always gets changed */
1338 if (!(style & WS_VISIBLE) || (style & WS_CHILD) || GetActiveWindow()) swFlag |= SWP_NOACTIVATE;
1339 SetWindowPos( hwnd, 0, newPos.left, newPos.top, newPos.right - newPos.left,
1340 newPos.bottom - newPos.top, swFlag );
1343 /* Notify the parent window only */
1345 send_parent_notify( hwnd, WM_CREATE );
1346 if (!IsWindow( hwnd )) return 0;
1348 if (cs->style & WS_VISIBLE)
1350 if (cs->style & WS_MAXIMIZE)
1351 sw = SW_SHOW;
1352 else if (cs->style & WS_MINIMIZE)
1353 sw = SW_SHOWMINIMIZED;
1355 ShowWindow( hwnd, sw );
1356 if (cs->dwExStyle & WS_EX_MDICHILD)
1358 SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
1359 /* ShowWindow won't activate child windows */
1360 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE );
1364 /* Call WH_SHELL hook */
1366 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1367 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1369 TRACE("created window %p\n", hwnd);
1370 return hwnd;
1372 failed:
1373 WIN_DestroyWindow( hwnd );
1374 return 0;
1378 /***********************************************************************
1379 * CreateWindow (USER.41)
1381 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1382 DWORD style, INT16 x, INT16 y, INT16 width,
1383 INT16 height, HWND16 parent, HMENU16 menu,
1384 HINSTANCE16 instance, LPVOID data )
1386 return CreateWindowEx16( 0, className, windowName, style,
1387 x, y, width, height, parent, menu, instance, data );
1391 /***********************************************************************
1392 * CreateWindowEx (USER.452)
1394 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1395 LPCSTR windowName, DWORD style, INT16 x,
1396 INT16 y, INT16 width, INT16 height,
1397 HWND16 parent, HMENU16 menu,
1398 HINSTANCE16 instance, LPVOID data )
1400 CREATESTRUCTA cs;
1401 char buffer[256];
1403 /* Fix the coordinates */
1405 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1406 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1407 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1408 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1410 /* Create the window */
1412 cs.lpCreateParams = data;
1413 cs.hInstance = HINSTANCE_32(instance);
1414 cs.hMenu = HMENU_32(menu);
1415 cs.hwndParent = WIN_Handle32( parent );
1416 cs.style = style;
1417 cs.lpszName = windowName;
1418 cs.lpszClass = className;
1419 cs.dwExStyle = exStyle;
1421 if (!IS_INTRESOURCE(className))
1423 WCHAR bufferW[256];
1425 if (!MultiByteToWideChar( CP_ACP, 0, className, -1, bufferW, sizeof(bufferW)/sizeof(WCHAR) ))
1426 return 0;
1427 return HWND_16( WIN_CreateWindowEx( &cs, bufferW, 0 ));
1429 else
1431 if (!GlobalGetAtomNameA( LOWORD(className), buffer, sizeof(buffer) ))
1433 ERR( "bad atom %x\n", LOWORD(className));
1434 return 0;
1436 cs.lpszClass = buffer;
1437 return HWND_16( WIN_CreateWindowEx( &cs, (LPCWSTR)className, 0 ));
1442 /***********************************************************************
1443 * CreateWindowExA (USER32.@)
1445 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1446 LPCSTR windowName, DWORD style, INT x,
1447 INT y, INT width, INT height,
1448 HWND parent, HMENU menu,
1449 HINSTANCE instance, LPVOID data )
1451 CREATESTRUCTA cs;
1453 cs.lpCreateParams = data;
1454 cs.hInstance = instance;
1455 cs.hMenu = menu;
1456 cs.hwndParent = parent;
1457 cs.x = x;
1458 cs.y = y;
1459 cs.cx = width;
1460 cs.cy = height;
1461 cs.style = style;
1462 cs.lpszName = windowName;
1463 cs.lpszClass = className;
1464 cs.dwExStyle = exStyle;
1466 if (!IS_INTRESOURCE(className))
1468 WCHAR bufferW[256];
1469 if (!MultiByteToWideChar( CP_ACP, 0, className, -1, bufferW, sizeof(bufferW)/sizeof(WCHAR) ))
1470 return 0;
1471 return WIN_CreateWindowEx( &cs, bufferW, WIN_ISWIN32 );
1473 return WIN_CreateWindowEx( &cs, (LPCWSTR)className, WIN_ISWIN32 );
1477 /***********************************************************************
1478 * CreateWindowExW (USER32.@)
1480 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1481 LPCWSTR windowName, DWORD style, INT x,
1482 INT y, INT width, INT height,
1483 HWND parent, HMENU menu,
1484 HINSTANCE instance, LPVOID data )
1486 CREATESTRUCTW cs;
1488 cs.lpCreateParams = data;
1489 cs.hInstance = instance;
1490 cs.hMenu = menu;
1491 cs.hwndParent = parent;
1492 cs.x = x;
1493 cs.y = y;
1494 cs.cx = width;
1495 cs.cy = height;
1496 cs.style = style;
1497 cs.lpszName = windowName;
1498 cs.lpszClass = className;
1499 cs.dwExStyle = exStyle;
1501 /* Note: we rely on the fact that CREATESTRUCTA and */
1502 /* CREATESTRUCTW have the same layout. */
1503 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, className, WIN_ISWIN32 | WIN_ISUNICODE );
1507 /***********************************************************************
1508 * WIN_SendDestroyMsg
1510 static void WIN_SendDestroyMsg( HWND hwnd )
1512 GUITHREADINFO info;
1514 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1516 if (hwnd == info.hwndCaret) DestroyCaret();
1517 if (hwnd == info.hwndActive) WINPOS_ActivateOtherWindow( hwnd );
1521 * Send the WM_DESTROY to the window.
1523 SendMessageW( hwnd, WM_DESTROY, 0, 0);
1526 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1527 * make sure that the window still exists when we come back.
1529 if (IsWindow(hwnd))
1531 HWND* pWndArray;
1532 int i;
1534 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1536 for (i = 0; pWndArray[i]; i++)
1538 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1540 HeapFree( GetProcessHeap(), 0, pWndArray );
1542 else
1543 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1547 /***********************************************************************
1548 * DestroyWindow (USER32.@)
1550 BOOL WINAPI DestroyWindow( HWND hwnd )
1552 BOOL is_child;
1554 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || is_desktop_window( hwnd ))
1556 SetLastError( ERROR_ACCESS_DENIED );
1557 return FALSE;
1560 TRACE("(%p)\n", hwnd);
1562 /* Call hooks */
1564 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1566 if (MENU_IsMenuActive() == hwnd)
1567 EndMenu();
1569 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1571 if (is_child)
1573 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1574 send_parent_notify( hwnd, WM_DESTROY );
1576 else if (!GetWindow( hwnd, GW_OWNER ))
1578 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1579 /* FIXME: clean up palette - see "Internals" p.352 */
1582 if (!IsWindow(hwnd)) return TRUE;
1584 /* Hide the window */
1585 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)
1587 /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
1588 if (is_child)
1589 ShowWindow( hwnd, SW_HIDE );
1590 else
1591 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1592 SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW );
1595 if (!IsWindow(hwnd)) return TRUE;
1597 /* Recursively destroy owned windows */
1599 if (!is_child)
1601 for (;;)
1603 int i, got_one = 0;
1604 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1605 if (list)
1607 for (i = 0; list[i]; i++)
1609 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1610 if (WIN_IsCurrentThread( list[i] ))
1612 DestroyWindow( list[i] );
1613 got_one = 1;
1614 continue;
1616 WIN_SetOwner( list[i], 0 );
1618 HeapFree( GetProcessHeap(), 0, list );
1620 if (!got_one) break;
1624 /* Send destroy messages */
1626 WIN_SendDestroyMsg( hwnd );
1627 if (!IsWindow( hwnd )) return TRUE;
1629 if (GetClipboardOwner() == hwnd)
1630 CLIPBOARD_ReleaseOwner();
1632 /* Destroy the window storage */
1634 WIN_DestroyWindow( hwnd );
1635 return TRUE;
1639 /***********************************************************************
1640 * CloseWindow (USER32.@)
1642 BOOL WINAPI CloseWindow( HWND hwnd )
1644 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1645 ShowWindow( hwnd, SW_MINIMIZE );
1646 return TRUE;
1650 /***********************************************************************
1651 * OpenIcon (USER32.@)
1653 BOOL WINAPI OpenIcon( HWND hwnd )
1655 if (!IsIconic( hwnd )) return FALSE;
1656 ShowWindow( hwnd, SW_SHOWNORMAL );
1657 return TRUE;
1661 /***********************************************************************
1662 * FindWindowExW (USER32.@)
1664 HWND WINAPI FindWindowExW( HWND parent, HWND child, LPCWSTR className, LPCWSTR title )
1666 HWND *list = NULL;
1667 HWND retvalue = 0;
1668 int i = 0, len = 0;
1669 WCHAR *buffer = NULL;
1671 if (!parent && child) parent = GetDesktopWindow();
1672 else if (parent == HWND_MESSAGE) parent = get_hwnd_message_parent();
1674 if (title)
1676 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1677 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1680 if (!(list = list_window_children( 0, parent, className, 0 ))) goto done;
1682 if (child)
1684 child = WIN_GetFullHandle( child );
1685 while (list[i] && list[i] != child) i++;
1686 if (!list[i]) goto done;
1687 i++; /* start from next window */
1690 if (title)
1692 while (list[i])
1694 if (GetWindowTextW( list[i], buffer, len + 1 ) && !strcmpiW( buffer, title )) break;
1695 i++;
1698 retvalue = list[i];
1700 done:
1701 HeapFree( GetProcessHeap(), 0, list );
1702 HeapFree( GetProcessHeap(), 0, buffer );
1703 return retvalue;
1708 /***********************************************************************
1709 * FindWindowA (USER32.@)
1711 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1713 HWND ret = FindWindowExA( 0, 0, className, title );
1714 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1715 return ret;
1719 /***********************************************************************
1720 * FindWindowExA (USER32.@)
1722 HWND WINAPI FindWindowExA( HWND parent, HWND child, LPCSTR className, LPCSTR title )
1724 LPWSTR titleW = NULL;
1725 HWND hwnd = 0;
1727 if (title)
1729 DWORD len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1730 if (!(titleW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1731 MultiByteToWideChar( CP_ACP, 0, title, -1, titleW, len );
1734 if (!IS_INTRESOURCE(className))
1736 WCHAR classW[256];
1737 if (MultiByteToWideChar( CP_ACP, 0, className, -1, classW, sizeof(classW)/sizeof(WCHAR) ))
1738 hwnd = FindWindowExW( parent, child, classW, titleW );
1740 else
1742 hwnd = FindWindowExW( parent, child, (LPCWSTR)className, titleW );
1745 HeapFree( GetProcessHeap(), 0, titleW );
1746 return hwnd;
1750 /***********************************************************************
1751 * FindWindowW (USER32.@)
1753 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1755 return FindWindowExW( 0, 0, className, title );
1759 /**********************************************************************
1760 * GetDesktopWindow (USER32.@)
1762 HWND WINAPI GetDesktopWindow(void)
1764 struct user_thread_info *thread_info = get_user_thread_info();
1766 if (thread_info->top_window) return thread_info->top_window;
1768 SERVER_START_REQ( get_desktop_window )
1770 req->force = 0;
1771 if (!wine_server_call( req ))
1773 thread_info->top_window = wine_server_ptr_handle( reply->top_window );
1774 thread_info->msg_window = wine_server_ptr_handle( reply->msg_window );
1777 SERVER_END_REQ;
1779 if (!thread_info->top_window)
1781 USEROBJECTFLAGS flags;
1782 if (!GetUserObjectInformationW( GetProcessWindowStation(), UOI_FLAGS, &flags,
1783 sizeof(flags), NULL ) || (flags.dwFlags & WSF_VISIBLE))
1785 static const WCHAR command_line[] = {'\\','e','x','p','l','o','r','e','r','.','e','x','e',' ','/','d','e','s','k','t','o','p',0};
1786 STARTUPINFOW si;
1787 PROCESS_INFORMATION pi;
1788 WCHAR cmdline[MAX_PATH + sizeof(command_line)/sizeof(WCHAR)];
1790 memset( &si, 0, sizeof(si) );
1791 si.cb = sizeof(si);
1792 si.dwFlags = STARTF_USESTDHANDLES;
1793 si.hStdInput = 0;
1794 si.hStdOutput = 0;
1795 si.hStdError = GetStdHandle( STD_ERROR_HANDLE );
1797 GetSystemDirectoryW( cmdline, MAX_PATH );
1798 lstrcatW( cmdline, command_line );
1799 if (CreateProcessW( NULL, cmdline, NULL, NULL, FALSE, DETACHED_PROCESS,
1800 NULL, NULL, &si, &pi ))
1802 TRACE( "started explorer pid %04x tid %04x\n", pi.dwProcessId, pi.dwThreadId );
1803 WaitForInputIdle( pi.hProcess, 10000 );
1804 CloseHandle( pi.hThread );
1805 CloseHandle( pi.hProcess );
1807 else WARN( "failed to start explorer, err %d\n", GetLastError() );
1809 else TRACE( "not starting explorer since winstation is not visible\n" );
1811 SERVER_START_REQ( get_desktop_window )
1813 req->force = 1;
1814 if (!wine_server_call( req ))
1816 thread_info->top_window = wine_server_ptr_handle( reply->top_window );
1817 thread_info->msg_window = wine_server_ptr_handle( reply->msg_window );
1820 SERVER_END_REQ;
1823 if (!thread_info->top_window || !USER_Driver->pCreateDesktopWindow( thread_info->top_window ))
1824 ERR( "failed to create desktop window\n" );
1826 return thread_info->top_window;
1830 /*******************************************************************
1831 * EnableWindow (USER32.@)
1833 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1835 BOOL retvalue;
1836 HWND full_handle;
1838 if (is_broadcast(hwnd))
1840 SetLastError( ERROR_INVALID_PARAMETER );
1841 return FALSE;
1844 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1845 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1847 hwnd = full_handle;
1849 TRACE("( %p, %d )\n", hwnd, enable);
1851 retvalue = !IsWindowEnabled( hwnd );
1853 if (enable && retvalue)
1855 WIN_SetStyle( hwnd, 0, WS_DISABLED );
1856 SendMessageW( hwnd, WM_ENABLE, TRUE, 0 );
1858 else if (!enable && !retvalue)
1860 HWND capture_wnd;
1862 SendMessageW( hwnd, WM_CANCELMODE, 0, 0);
1864 WIN_SetStyle( hwnd, WS_DISABLED, 0 );
1866 if (hwnd == GetFocus())
1867 SetFocus( 0 ); /* A disabled window can't have the focus */
1869 capture_wnd = GetCapture();
1870 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1871 ReleaseCapture(); /* A disabled window can't capture the mouse */
1873 SendMessageW( hwnd, WM_ENABLE, FALSE, 0 );
1875 return retvalue;
1879 /***********************************************************************
1880 * IsWindowEnabled (USER32.@)
1882 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1884 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1888 /***********************************************************************
1889 * IsWindowUnicode (USER32.@)
1891 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1893 WND * wndPtr;
1894 BOOL retvalue = FALSE;
1896 if (!(wndPtr = WIN_GetPtr(hwnd))) return FALSE;
1898 if (wndPtr == WND_DESKTOP) return TRUE;
1900 if (wndPtr != WND_OTHER_PROCESS)
1902 retvalue = (wndPtr->flags & WIN_ISUNICODE) != 0;
1903 WIN_ReleasePtr( wndPtr );
1905 else
1907 SERVER_START_REQ( get_window_info )
1909 req->handle = wine_server_user_handle( hwnd );
1910 if (!wine_server_call_err( req )) retvalue = reply->is_unicode;
1912 SERVER_END_REQ;
1914 return retvalue;
1918 /**********************************************************************
1919 * WIN_GetWindowLong
1921 * Helper function for GetWindowLong().
1923 static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, UINT size, BOOL unicode )
1925 LONG_PTR retvalue = 0;
1926 WND *wndPtr;
1928 if (offset == GWLP_HWNDPARENT)
1930 HWND parent = GetAncestor( hwnd, GA_PARENT );
1931 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1932 return (ULONG_PTR)parent;
1935 if (!(wndPtr = WIN_GetPtr( hwnd )))
1937 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1938 return 0;
1941 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1943 if (offset == GWLP_WNDPROC)
1945 SetLastError( ERROR_ACCESS_DENIED );
1946 return 0;
1948 SERVER_START_REQ( set_window_info )
1950 req->handle = wine_server_user_handle( hwnd );
1951 req->flags = 0; /* don't set anything, just retrieve */
1952 req->extra_offset = (offset >= 0) ? offset : -1;
1953 req->extra_size = (offset >= 0) ? size : 0;
1954 if (!wine_server_call_err( req ))
1956 switch(offset)
1958 case GWL_STYLE: retvalue = reply->old_style; break;
1959 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1960 case GWLP_ID: retvalue = reply->old_id; break;
1961 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wine_server_get_ptr( reply->old_instance ); break;
1962 case GWLP_USERDATA: retvalue = reply->old_user_data; break;
1963 default:
1964 if (offset >= 0) retvalue = get_win_data( &reply->old_extra_value, size );
1965 else SetLastError( ERROR_INVALID_INDEX );
1966 break;
1970 SERVER_END_REQ;
1971 return retvalue;
1974 /* now we have a valid wndPtr */
1976 if (offset >= 0)
1978 if (offset > (int)(wndPtr->cbWndExtra - size))
1980 WARN("Invalid offset %d\n", offset );
1981 WIN_ReleasePtr( wndPtr );
1982 SetLastError( ERROR_INVALID_INDEX );
1983 return 0;
1985 retvalue = get_win_data( (char *)wndPtr->wExtra + offset, size );
1987 /* Special case for dialog window procedure */
1988 if ((offset == DWLP_DLGPROC) && (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG))
1989 retvalue = (LONG_PTR)WINPROC_GetProc( (WNDPROC)retvalue, unicode );
1990 WIN_ReleasePtr( wndPtr );
1991 return retvalue;
1994 switch(offset)
1996 case GWLP_USERDATA: retvalue = wndPtr->userdata; break;
1997 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1998 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1999 case GWLP_ID: retvalue = wndPtr->wIDmenu; break;
2000 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wndPtr->hInstance; break;
2001 case GWLP_WNDPROC:
2002 /* This looks like a hack only for the edit control (see tests). This makes these controls
2003 * more tolerant to A/W mismatches. The lack of W->A->W conversion for such a mismatch suggests
2004 * that the hack is in GetWindowLongPtr[AW], not in winprocs.
2006 if (wndPtr->winproc == EDIT_winproc_handle && (!unicode != !(wndPtr->flags & WIN_ISUNICODE)))
2007 retvalue = (ULONG_PTR)wndPtr->winproc;
2008 else
2009 retvalue = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, unicode );
2010 break;
2011 default:
2012 WARN("Unknown offset %d\n", offset );
2013 SetLastError( ERROR_INVALID_INDEX );
2014 break;
2016 WIN_ReleasePtr(wndPtr);
2017 return retvalue;
2021 /**********************************************************************
2022 * WIN_SetWindowLong
2024 * Helper function for SetWindowLong().
2026 * 0 is the failure code. However, in the case of failure SetLastError
2027 * must be set to distinguish between a 0 return value and a failure.
2029 LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, UINT size, LONG_PTR newval, BOOL unicode )
2031 STYLESTRUCT style;
2032 BOOL ok;
2033 LONG_PTR retval = 0;
2034 WND *wndPtr;
2036 TRACE( "%p %d %lx %c\n", hwnd, offset, newval, unicode ? 'W' : 'A' );
2038 if (is_broadcast(hwnd))
2040 SetLastError( ERROR_INVALID_PARAMETER );
2041 return FALSE;
2044 if (!(wndPtr = WIN_GetPtr( hwnd )))
2046 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2047 return 0;
2049 if (wndPtr == WND_DESKTOP)
2051 /* can't change anything on the desktop window */
2052 SetLastError( ERROR_ACCESS_DENIED );
2053 return 0;
2055 if (wndPtr == WND_OTHER_PROCESS)
2057 if (offset == GWLP_WNDPROC)
2059 SetLastError( ERROR_ACCESS_DENIED );
2060 return 0;
2062 if (offset > 32767 || offset < -32767)
2064 SetLastError( ERROR_INVALID_INDEX );
2065 return 0;
2067 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, MAKEWPARAM( offset, size ), newval );
2070 /* first some special cases */
2071 switch( offset )
2073 case GWL_STYLE:
2074 case GWL_EXSTYLE:
2075 style.styleOld =
2076 offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
2077 style.styleNew = newval;
2078 WIN_ReleasePtr( wndPtr );
2079 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
2080 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
2081 newval = style.styleNew;
2082 break;
2083 case GWLP_HWNDPARENT:
2084 if (wndPtr->parent == GetDesktopWindow())
2086 WIN_ReleasePtr( wndPtr );
2087 return (ULONG_PTR)WIN_SetOwner( hwnd, (HWND)newval );
2089 else
2091 WIN_ReleasePtr( wndPtr );
2092 return (ULONG_PTR)SetParent( hwnd, (HWND)newval );
2094 case GWLP_WNDPROC:
2096 WNDPROC proc;
2097 UINT old_flags = wndPtr->flags;
2098 retval = WIN_GetWindowLong( hwnd, offset, size, unicode );
2099 if (unicode) proc = WINPROC_AllocProc( NULL, (WNDPROC)newval );
2100 else proc = WINPROC_AllocProc( (WNDPROC)newval, NULL );
2101 if (proc) wndPtr->winproc = proc;
2102 if (WINPROC_IsUnicode( proc, unicode )) wndPtr->flags |= WIN_ISUNICODE;
2103 else wndPtr->flags &= ~WIN_ISUNICODE;
2104 if (!((old_flags ^ wndPtr->flags) & WIN_ISUNICODE))
2106 WIN_ReleasePtr( wndPtr );
2107 return retval;
2109 /* update is_unicode flag on the server side */
2110 break;
2112 case GWLP_ID:
2113 case GWLP_HINSTANCE:
2114 case GWLP_USERDATA:
2115 break;
2116 case DWLP_DLGPROC:
2117 if ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
2118 (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG))
2120 WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWLP_DLGPROC);
2121 retval = (ULONG_PTR)WINPROC_GetProc( *ptr, unicode );
2122 if (unicode) *ptr = WINPROC_AllocProc( NULL, (WNDPROC)newval );
2123 else *ptr = WINPROC_AllocProc( (WNDPROC)newval, NULL );
2124 WIN_ReleasePtr( wndPtr );
2125 return retval;
2127 /* fall through */
2128 default:
2129 if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - size))
2131 WARN("Invalid offset %d\n", offset );
2132 WIN_ReleasePtr( wndPtr );
2133 SetLastError( ERROR_INVALID_INDEX );
2134 return 0;
2136 else if (get_win_data( (char *)wndPtr->wExtra + offset, size ) == newval)
2138 /* already set to the same value */
2139 WIN_ReleasePtr( wndPtr );
2140 return newval;
2142 break;
2145 SERVER_START_REQ( set_window_info )
2147 req->handle = wine_server_user_handle( hwnd );
2148 req->extra_offset = -1;
2149 switch(offset)
2151 case GWL_STYLE:
2152 req->flags = SET_WIN_STYLE;
2153 req->style = newval;
2154 break;
2155 case GWL_EXSTYLE:
2156 req->flags = SET_WIN_EXSTYLE;
2157 /* WS_EX_TOPMOST can only be changed through SetWindowPos */
2158 newval = (newval & ~WS_EX_TOPMOST) | (wndPtr->dwExStyle & WS_EX_TOPMOST);
2159 req->ex_style = newval;
2160 break;
2161 case GWLP_ID:
2162 req->flags = SET_WIN_ID;
2163 req->id = newval;
2164 break;
2165 case GWLP_HINSTANCE:
2166 req->flags = SET_WIN_INSTANCE;
2167 req->instance = wine_server_client_ptr( (void *)newval );
2168 break;
2169 case GWLP_WNDPROC:
2170 req->flags = SET_WIN_UNICODE;
2171 req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
2172 break;
2173 case GWLP_USERDATA:
2174 req->flags = SET_WIN_USERDATA;
2175 req->user_data = newval;
2176 break;
2177 default:
2178 req->flags = SET_WIN_EXTRA;
2179 req->extra_offset = offset;
2180 req->extra_size = size;
2181 set_win_data( &req->extra_value, newval, size );
2183 if ((ok = !wine_server_call_err( req )))
2185 switch(offset)
2187 case GWL_STYLE:
2188 wndPtr->dwStyle = newval;
2189 retval = reply->old_style;
2190 break;
2191 case GWL_EXSTYLE:
2192 wndPtr->dwExStyle = newval;
2193 retval = reply->old_ex_style;
2194 break;
2195 case GWLP_ID:
2196 wndPtr->wIDmenu = newval;
2197 retval = reply->old_id;
2198 break;
2199 case GWLP_HINSTANCE:
2200 wndPtr->hInstance = (HINSTANCE)newval;
2201 retval = (ULONG_PTR)wine_server_get_ptr( reply->old_instance );
2202 break;
2203 case GWLP_WNDPROC:
2204 break;
2205 case GWLP_USERDATA:
2206 wndPtr->userdata = newval;
2207 retval = reply->old_user_data;
2208 break;
2209 default:
2210 retval = get_win_data( (char *)wndPtr->wExtra + offset, size );
2211 set_win_data( (char *)wndPtr->wExtra + offset, newval, size );
2212 break;
2216 SERVER_END_REQ;
2217 WIN_ReleasePtr( wndPtr );
2219 if (!ok) return 0;
2221 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2223 USER_Driver->pSetWindowStyle( hwnd, offset, &style );
2224 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2227 return retval;
2231 /**********************************************************************
2232 * GetWindowLong (USER.135)
2234 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2236 WND *wndPtr;
2237 LONG_PTR retvalue;
2238 BOOL is_winproc = (offset == GWLP_WNDPROC);
2240 if (offset >= 0)
2242 if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2244 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2245 return 0;
2247 if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2249 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
2252 * Some programs try to access last element from 16 bit
2253 * code using illegal offset value. Hopefully this is
2254 * what those programs really expect.
2256 if (wndPtr->cbWndExtra >= 4 && offset == wndPtr->cbWndExtra - sizeof(WORD))
2258 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
2259 ERR( "- replaced invalid offset %d with %d\n", offset, offset2 );
2260 offset = offset2;
2262 else
2264 WARN("Invalid offset %d\n", offset );
2265 WIN_ReleasePtr( wndPtr );
2266 SetLastError( ERROR_INVALID_INDEX );
2267 return 0;
2270 is_winproc = ((offset == DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG));
2271 WIN_ReleasePtr( wndPtr );
2274 retvalue = GetWindowLongA( WIN_Handle32(hwnd), offset );
2275 if (is_winproc) retvalue = (LONG_PTR)WINPROC_GetProc16( (WNDPROC)retvalue, FALSE );
2276 return retvalue;
2280 /**********************************************************************
2281 * GetWindowWord (USER32.@)
2283 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
2285 switch(offset)
2287 case GWLP_ID:
2288 case GWLP_HINSTANCE:
2289 case GWLP_HWNDPARENT:
2290 break;
2291 default:
2292 if (offset < 0)
2294 WARN("Invalid offset %d\n", offset );
2295 SetLastError( ERROR_INVALID_INDEX );
2296 return 0;
2298 break;
2300 return WIN_GetWindowLong( hwnd, offset, sizeof(WORD), FALSE );
2304 /**********************************************************************
2305 * GetWindowLongA (USER32.@)
2307 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2309 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), FALSE );
2313 /**********************************************************************
2314 * GetWindowLongW (USER32.@)
2316 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2318 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), TRUE );
2322 /**********************************************************************
2323 * SetWindowLong (USER.136)
2325 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2327 WND *wndPtr;
2328 BOOL is_winproc = (offset == GWLP_WNDPROC);
2330 if (offset == DWLP_DLGPROC)
2332 if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2334 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2335 return 0;
2337 if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2339 is_winproc = ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
2340 (wndPtr->flags & WIN_ISDIALOG));
2341 WIN_ReleasePtr( wndPtr );
2345 if (is_winproc)
2347 WNDPROC new_proc = WINPROC_AllocProc16( (WNDPROC16)newval );
2348 WNDPROC old_proc = (WNDPROC)SetWindowLongPtrA( WIN_Handle32(hwnd), offset, (LONG_PTR)new_proc );
2349 return (LONG)WINPROC_GetProc16( old_proc, FALSE );
2351 else return SetWindowLongA( WIN_Handle32(hwnd), offset, newval );
2355 /**********************************************************************
2356 * SetWindowWord (USER32.@)
2358 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
2360 switch(offset)
2362 case GWLP_ID:
2363 case GWLP_HINSTANCE:
2364 case GWLP_HWNDPARENT:
2365 break;
2366 default:
2367 if (offset < 0)
2369 WARN("Invalid offset %d\n", offset );
2370 SetLastError( ERROR_INVALID_INDEX );
2371 return 0;
2373 break;
2375 return WIN_SetWindowLong( hwnd, offset, sizeof(WORD), newval, FALSE );
2379 /**********************************************************************
2380 * SetWindowLongA (USER32.@)
2382 * See SetWindowLongW.
2384 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2386 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, FALSE );
2390 /**********************************************************************
2391 * SetWindowLongW (USER32.@) Set window attribute
2393 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2394 * value in a window's extra memory.
2396 * The _hwnd_ parameter specifies the window. is the handle to a
2397 * window that has extra memory. The _newval_ parameter contains the
2398 * new attribute or extra memory value. If positive, the _offset_
2399 * parameter is the byte-addressed location in the window's extra
2400 * memory to set. If negative, _offset_ specifies the window
2401 * attribute to set, and should be one of the following values:
2403 * GWL_EXSTYLE The window's extended window style
2405 * GWL_STYLE The window's window style.
2407 * GWLP_WNDPROC Pointer to the window's window procedure.
2409 * GWLP_HINSTANCE The window's pplication instance handle.
2411 * GWLP_ID The window's identifier.
2413 * GWLP_USERDATA The window's user-specified data.
2415 * If the window is a dialog box, the _offset_ parameter can be one of
2416 * the following values:
2418 * DWLP_DLGPROC The address of the window's dialog box procedure.
2420 * DWLP_MSGRESULT The return value of a message
2421 * that the dialog box procedure processed.
2423 * DWLP_USER Application specific information.
2425 * RETURNS
2427 * If successful, returns the previous value located at _offset_. Otherwise,
2428 * returns 0.
2430 * NOTES
2432 * Extra memory for a window class is specified by a nonzero cbWndExtra
2433 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2434 * time of class creation.
2436 * Using GWL_WNDPROC to set a new window procedure effectively creates
2437 * a window subclass. Use CallWindowProc() in the new windows procedure
2438 * to pass messages to the superclass's window procedure.
2440 * The user data is reserved for use by the application which created
2441 * the window.
2443 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2444 * instead, call the EnableWindow() function to change the window's
2445 * disabled state.
2447 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2448 * SetParent() instead.
2450 * Win95:
2451 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2452 * it sends WM_STYLECHANGING before changing the settings
2453 * and WM_STYLECHANGED afterwards.
2454 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2456 LONG WINAPI SetWindowLongW(
2457 HWND hwnd, /* [in] window to alter */
2458 INT offset, /* [in] offset, in bytes, of location to alter */
2459 LONG newval /* [in] new value of location */
2461 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, TRUE );
2465 /*******************************************************************
2466 * GetWindowTextA (USER32.@)
2468 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2470 WCHAR *buffer;
2472 if (!lpString) return 0;
2474 if (WIN_IsCurrentProcess( hwnd ))
2475 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2477 /* when window belongs to other process, don't send a message */
2478 if (nMaxCount <= 0) return 0;
2479 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2480 get_server_window_text( hwnd, buffer, nMaxCount );
2481 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2482 lpString[nMaxCount-1] = 0;
2483 HeapFree( GetProcessHeap(), 0, buffer );
2484 return strlen(lpString);
2488 /*******************************************************************
2489 * InternalGetWindowText (USER32.@)
2491 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2493 WND *win;
2495 if (nMaxCount <= 0) return 0;
2496 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2497 if (win == WND_DESKTOP) lpString[0] = 0;
2498 else if (win != WND_OTHER_PROCESS)
2500 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2501 else lpString[0] = 0;
2502 WIN_ReleasePtr( win );
2504 else
2506 get_server_window_text( hwnd, lpString, nMaxCount );
2508 return strlenW(lpString);
2512 /*******************************************************************
2513 * GetWindowTextW (USER32.@)
2515 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2517 if (!lpString) return 0;
2519 if (WIN_IsCurrentProcess( hwnd ))
2520 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2522 /* when window belongs to other process, don't send a message */
2523 if (nMaxCount <= 0) return 0;
2524 get_server_window_text( hwnd, lpString, nMaxCount );
2525 return strlenW(lpString);
2529 /*******************************************************************
2530 * SetWindowTextA (USER32.@)
2531 * SetWindowText (USER32.@)
2533 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2535 if (is_broadcast(hwnd))
2537 SetLastError( ERROR_INVALID_PARAMETER );
2538 return FALSE;
2540 if (!WIN_IsCurrentProcess( hwnd ))
2541 WARN( "setting text %s of other process window %p should not use SendMessage\n",
2542 debugstr_a(lpString), hwnd );
2543 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2547 /*******************************************************************
2548 * SetWindowTextW (USER32.@)
2550 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2552 if (is_broadcast(hwnd))
2554 SetLastError( ERROR_INVALID_PARAMETER );
2555 return FALSE;
2557 if (!WIN_IsCurrentProcess( hwnd ))
2558 WARN( "setting text %s of other process window %p should not use SendMessage\n",
2559 debugstr_w(lpString), hwnd );
2560 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2564 /*******************************************************************
2565 * GetWindowTextLengthA (USER32.@)
2567 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2569 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2572 /*******************************************************************
2573 * GetWindowTextLengthW (USER32.@)
2575 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2577 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2581 /*******************************************************************
2582 * IsWindow (USER32.@)
2584 BOOL WINAPI IsWindow( HWND hwnd )
2586 WND *ptr;
2587 BOOL ret;
2589 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2590 if (ptr == WND_DESKTOP) return TRUE;
2592 if (ptr != WND_OTHER_PROCESS)
2594 WIN_ReleasePtr( ptr );
2595 return TRUE;
2598 /* check other processes */
2599 SERVER_START_REQ( get_window_info )
2601 req->handle = wine_server_user_handle( hwnd );
2602 ret = !wine_server_call_err( req );
2604 SERVER_END_REQ;
2605 return ret;
2609 /***********************************************************************
2610 * GetWindowThreadProcessId (USER32.@)
2612 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2614 WND *ptr;
2615 DWORD tid = 0;
2617 if (!(ptr = WIN_GetPtr( hwnd )))
2619 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2620 return 0;
2623 if (ptr != WND_OTHER_PROCESS && ptr != WND_DESKTOP)
2625 /* got a valid window */
2626 tid = ptr->tid;
2627 if (process) *process = GetCurrentProcessId();
2628 WIN_ReleasePtr( ptr );
2629 return tid;
2632 /* check other processes */
2633 SERVER_START_REQ( get_window_info )
2635 req->handle = wine_server_user_handle( hwnd );
2636 if (!wine_server_call_err( req ))
2638 tid = (DWORD)reply->tid;
2639 if (process) *process = (DWORD)reply->pid;
2642 SERVER_END_REQ;
2643 return tid;
2647 /*****************************************************************
2648 * GetParent (USER32.@)
2650 HWND WINAPI GetParent( HWND hwnd )
2652 WND *wndPtr;
2653 HWND retvalue = 0;
2655 if (!(wndPtr = WIN_GetPtr( hwnd )))
2657 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2658 return 0;
2660 if (wndPtr == WND_DESKTOP) return 0;
2661 if (wndPtr == WND_OTHER_PROCESS)
2663 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2664 if (style & (WS_POPUP | WS_CHILD))
2666 SERVER_START_REQ( get_window_tree )
2668 req->handle = wine_server_user_handle( hwnd );
2669 if (!wine_server_call_err( req ))
2671 if (style & WS_POPUP) retvalue = wine_server_ptr_handle( reply->owner );
2672 else if (style & WS_CHILD) retvalue = wine_server_ptr_handle( reply->parent );
2675 SERVER_END_REQ;
2678 else
2680 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2681 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2682 WIN_ReleasePtr( wndPtr );
2684 return retvalue;
2688 /*****************************************************************
2689 * GetAncestor (USER32.@)
2691 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2693 WND *win;
2694 HWND *list, ret = 0;
2696 switch(type)
2698 case GA_PARENT:
2699 if (!(win = WIN_GetPtr( hwnd )))
2701 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2702 return 0;
2704 if (win == WND_DESKTOP) return 0;
2705 if (win != WND_OTHER_PROCESS)
2707 ret = win->parent;
2708 WIN_ReleasePtr( win );
2710 else /* need to query the server */
2712 SERVER_START_REQ( get_window_tree )
2714 req->handle = wine_server_user_handle( hwnd );
2715 if (!wine_server_call_err( req )) ret = wine_server_ptr_handle( reply->parent );
2717 SERVER_END_REQ;
2719 break;
2721 case GA_ROOT:
2722 if (!(list = list_window_parents( hwnd ))) return 0;
2724 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2725 else
2727 int count = 2;
2728 while (list[count]) count++;
2729 ret = list[count - 2]; /* get the one before the desktop */
2731 HeapFree( GetProcessHeap(), 0, list );
2732 break;
2734 case GA_ROOTOWNER:
2735 if (is_desktop_window( hwnd )) return 0;
2736 ret = WIN_GetFullHandle( hwnd );
2737 for (;;)
2739 HWND parent = GetParent( ret );
2740 if (!parent) break;
2741 ret = parent;
2743 break;
2745 return ret;
2749 /*****************************************************************
2750 * SetParent (USER32.@)
2752 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2754 HWND full_handle;
2755 HWND old_parent = 0;
2756 BOOL was_visible;
2757 WND *wndPtr;
2758 BOOL ret;
2760 if (is_broadcast(hwnd) || is_broadcast(parent))
2762 SetLastError(ERROR_INVALID_PARAMETER);
2763 return 0;
2766 if (!parent) parent = GetDesktopWindow();
2767 else if (parent == HWND_MESSAGE) parent = get_hwnd_message_parent();
2768 else parent = WIN_GetFullHandle( parent );
2770 if (!IsWindow( parent ))
2772 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2773 return 0;
2776 /* Some applications try to set a child as a parent */
2777 if (IsChild(hwnd, parent))
2779 SetLastError( ERROR_INVALID_PARAMETER );
2780 return 0;
2783 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2784 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2786 /* Windows hides the window first, then shows it again
2787 * including the WM_SHOWWINDOW messages and all */
2788 was_visible = ShowWindow( hwnd, SW_HIDE );
2790 wndPtr = WIN_GetPtr( hwnd );
2791 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return 0;
2793 SERVER_START_REQ( set_parent )
2795 req->handle = wine_server_user_handle( hwnd );
2796 req->parent = wine_server_user_handle( parent );
2797 if ((ret = !wine_server_call( req )))
2799 old_parent = wine_server_ptr_handle( reply->old_parent );
2800 wndPtr->parent = parent = wine_server_ptr_handle( reply->full_parent );
2804 SERVER_END_REQ;
2805 WIN_ReleasePtr( wndPtr );
2806 if (!ret) return 0;
2808 USER_Driver->pSetParent( full_handle, parent, old_parent );
2810 /* SetParent additionally needs to make hwnd the topmost window
2811 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2812 WM_WINDOWPOSCHANGED notification messages.
2814 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0,
2815 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2816 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2817 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2819 return old_parent;
2823 /*******************************************************************
2824 * IsChild (USER32.@)
2826 BOOL WINAPI IsChild( HWND parent, HWND child )
2828 HWND *list = list_window_parents( child );
2829 int i;
2830 BOOL ret;
2832 if (!list) return FALSE;
2833 parent = WIN_GetFullHandle( parent );
2834 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2835 ret = list[i] && list[i+1];
2836 HeapFree( GetProcessHeap(), 0, list );
2837 return ret;
2841 /***********************************************************************
2842 * IsWindowVisible (USER32.@)
2844 BOOL WINAPI IsWindowVisible( HWND hwnd )
2846 HWND *list;
2847 BOOL retval = TRUE;
2848 int i;
2850 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2851 if (!(list = list_window_parents( hwnd ))) return TRUE;
2852 if (list[0])
2854 for (i = 0; list[i+1]; i++)
2855 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2856 retval = !list[i+1] && (list[i] == GetDesktopWindow()); /* top message window isn't visible */
2858 HeapFree( GetProcessHeap(), 0, list );
2859 return retval;
2863 /***********************************************************************
2864 * WIN_IsWindowDrawable
2866 * hwnd is drawable when it is visible, all parents are not
2867 * minimized, and it is itself not minimized unless we are
2868 * trying to draw its default class icon.
2870 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2872 HWND *list;
2873 BOOL retval = TRUE;
2874 int i;
2875 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2877 if (!(style & WS_VISIBLE)) return FALSE;
2878 if ((style & WS_MINIMIZE) && icon && GetClassLongPtrW( hwnd, GCLP_HICON )) return FALSE;
2880 if (!(list = list_window_parents( hwnd ))) return TRUE;
2881 if (list[0])
2883 for (i = 0; list[i+1]; i++)
2884 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2885 break;
2886 retval = !list[i+1] && (list[i] == GetDesktopWindow()); /* top message window isn't visible */
2888 HeapFree( GetProcessHeap(), 0, list );
2889 return retval;
2893 /*******************************************************************
2894 * GetTopWindow (USER32.@)
2896 HWND WINAPI GetTopWindow( HWND hwnd )
2898 if (!hwnd) hwnd = GetDesktopWindow();
2899 return GetWindow( hwnd, GW_CHILD );
2903 /*******************************************************************
2904 * GetWindow (USER32.@)
2906 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2908 HWND retval = 0;
2910 if (rel == GW_OWNER) /* this one may be available locally */
2912 WND *wndPtr = WIN_GetPtr( hwnd );
2913 if (!wndPtr)
2915 SetLastError( ERROR_INVALID_HANDLE );
2916 return 0;
2918 if (wndPtr == WND_DESKTOP) return 0;
2919 if (wndPtr != WND_OTHER_PROCESS)
2921 retval = wndPtr->owner;
2922 WIN_ReleasePtr( wndPtr );
2923 return retval;
2925 /* else fall through to server call */
2928 SERVER_START_REQ( get_window_tree )
2930 req->handle = wine_server_user_handle( hwnd );
2931 if (!wine_server_call_err( req ))
2933 switch(rel)
2935 case GW_HWNDFIRST:
2936 retval = wine_server_ptr_handle( reply->first_sibling );
2937 break;
2938 case GW_HWNDLAST:
2939 retval = wine_server_ptr_handle( reply->last_sibling );
2940 break;
2941 case GW_HWNDNEXT:
2942 retval = wine_server_ptr_handle( reply->next_sibling );
2943 break;
2944 case GW_HWNDPREV:
2945 retval = wine_server_ptr_handle( reply->prev_sibling );
2946 break;
2947 case GW_OWNER:
2948 retval = wine_server_ptr_handle( reply->owner );
2949 break;
2950 case GW_CHILD:
2951 retval = wine_server_ptr_handle( reply->first_child );
2952 break;
2956 SERVER_END_REQ;
2957 return retval;
2961 /*******************************************************************
2962 * ShowOwnedPopups (USER32.@)
2964 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2966 int count = 0;
2967 WND *pWnd;
2968 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2970 if (!win_array) return TRUE;
2972 while (win_array[count]) count++;
2973 while (--count >= 0)
2975 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2976 if (!(pWnd = WIN_GetPtr( win_array[count] ))) continue;
2977 if (pWnd == WND_OTHER_PROCESS) continue;
2978 if (fShow)
2980 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2982 WIN_ReleasePtr( pWnd );
2983 /* In Windows, ShowOwnedPopups(TRUE) generates
2984 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2985 * regardless of the state of the owner
2987 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_SHOWNORMAL, SW_PARENTOPENING);
2988 continue;
2991 else
2993 if (pWnd->dwStyle & WS_VISIBLE)
2995 WIN_ReleasePtr( pWnd );
2996 /* In Windows, ShowOwnedPopups(FALSE) generates
2997 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2998 * regardless of the state of the owner
3000 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
3001 continue;
3004 WIN_ReleasePtr( pWnd );
3006 HeapFree( GetProcessHeap(), 0, win_array );
3007 return TRUE;
3011 /*******************************************************************
3012 * GetLastActivePopup (USER32.@)
3014 HWND WINAPI GetLastActivePopup( HWND hwnd )
3016 HWND retval = hwnd;
3018 SERVER_START_REQ( get_window_info )
3020 req->handle = wine_server_user_handle( hwnd );
3021 if (!wine_server_call_err( req )) retval = wine_server_ptr_handle( reply->last_active );
3023 SERVER_END_REQ;
3024 return retval;
3028 /*******************************************************************
3029 * WIN_ListChildren
3031 * Build an array of the children of a given window. The array must be
3032 * freed with HeapFree. Returns NULL when no windows are found.
3034 HWND *WIN_ListChildren( HWND hwnd )
3036 if (!hwnd)
3038 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
3039 return NULL;
3041 return list_window_children( 0, hwnd, NULL, 0 );
3045 /*******************************************************************
3046 * EnumWindows (USER32.@)
3048 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
3050 HWND *list;
3051 BOOL ret = TRUE;
3052 int i;
3054 USER_CheckNotLock();
3056 /* We have to build a list of all windows first, to avoid */
3057 /* unpleasant side-effects, for instance if the callback */
3058 /* function changes the Z-order of the windows. */
3060 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
3062 /* Now call the callback function for every window */
3064 for (i = 0; list[i]; i++)
3066 /* Make sure that the window still exists */
3067 if (!IsWindow( list[i] )) continue;
3068 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
3070 HeapFree( GetProcessHeap(), 0, list );
3071 return ret;
3075 /**********************************************************************
3076 * EnumThreadWindows (USER32.@)
3078 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
3080 HWND *list;
3081 int i;
3083 USER_CheckNotLock();
3085 if (!(list = list_window_children( 0, GetDesktopWindow(), NULL, id ))) return TRUE;
3087 /* Now call the callback function for every window */
3089 for (i = 0; list[i]; i++)
3090 if (!func( list[i], lParam )) break;
3091 HeapFree( GetProcessHeap(), 0, list );
3092 return TRUE;
3096 /***********************************************************************
3097 * EnumDesktopWindows (USER32.@)
3099 BOOL WINAPI EnumDesktopWindows( HDESK desktop, WNDENUMPROC func, LPARAM lparam )
3101 HWND *list;
3102 int i;
3104 USER_CheckNotLock();
3106 if (!(list = list_window_children( desktop, 0, NULL, 0 ))) return TRUE;
3108 for (i = 0; list[i]; i++)
3109 if (!func( list[i], lparam )) break;
3110 HeapFree( GetProcessHeap(), 0, list );
3111 return TRUE;
3115 /**********************************************************************
3116 * WIN_EnumChildWindows
3118 * Helper function for EnumChildWindows().
3120 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
3122 HWND *childList;
3123 BOOL ret = FALSE;
3125 for ( ; *list; list++)
3127 /* Make sure that the window still exists */
3128 if (!IsWindow( *list )) continue;
3129 /* Build children list first */
3130 childList = WIN_ListChildren( *list );
3132 ret = func( *list, lParam );
3134 if (childList)
3136 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
3137 HeapFree( GetProcessHeap(), 0, childList );
3139 if (!ret) return FALSE;
3141 return TRUE;
3145 /**********************************************************************
3146 * EnumChildWindows (USER32.@)
3148 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
3150 HWND *list;
3151 BOOL ret;
3153 USER_CheckNotLock();
3155 if (!(list = WIN_ListChildren( parent ))) return FALSE;
3156 ret = WIN_EnumChildWindows( list, func, lParam );
3157 HeapFree( GetProcessHeap(), 0, list );
3158 return ret;
3162 /*******************************************************************
3163 * AnyPopup (USER.52)
3165 BOOL16 WINAPI AnyPopup16(void)
3167 return AnyPopup();
3171 /*******************************************************************
3172 * AnyPopup (USER32.@)
3174 BOOL WINAPI AnyPopup(void)
3176 int i;
3177 BOOL retvalue;
3178 HWND *list = WIN_ListChildren( GetDesktopWindow() );
3180 if (!list) return FALSE;
3181 for (i = 0; list[i]; i++)
3183 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
3185 retvalue = (list[i] != 0);
3186 HeapFree( GetProcessHeap(), 0, list );
3187 return retvalue;
3191 /*******************************************************************
3192 * FlashWindow (USER32.@)
3194 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3196 WND *wndPtr;
3198 TRACE("%p\n", hWnd);
3200 if (IsIconic( hWnd ))
3202 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3204 wndPtr = WIN_GetPtr(hWnd);
3205 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
3206 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3208 wndPtr->flags |= WIN_NCACTIVATED;
3210 else
3212 wndPtr->flags &= ~WIN_NCACTIVATED;
3214 WIN_ReleasePtr( wndPtr );
3215 return TRUE;
3217 else
3219 WPARAM wparam;
3221 wndPtr = WIN_GetPtr(hWnd);
3222 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
3223 hWnd = wndPtr->hwndSelf; /* make it a full handle */
3225 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3226 else wparam = (hWnd == GetForegroundWindow());
3228 WIN_ReleasePtr( wndPtr );
3229 SendMessageW( hWnd, WM_NCACTIVATE, wparam, 0 );
3230 return wparam;
3234 /*******************************************************************
3235 * FlashWindowEx (USER32.@)
3237 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
3239 FIXME("%p\n", pfwi);
3240 return TRUE;
3243 /*******************************************************************
3244 * GetWindowContextHelpId (USER32.@)
3246 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3248 DWORD retval;
3249 WND *wnd = WIN_GetPtr( hwnd );
3250 if (!wnd || wnd == WND_DESKTOP) return 0;
3251 if (wnd == WND_OTHER_PROCESS)
3253 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3254 return 0;
3256 retval = wnd->helpContext;
3257 WIN_ReleasePtr( wnd );
3258 return retval;
3262 /*******************************************************************
3263 * SetWindowContextHelpId (USER32.@)
3265 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3267 WND *wnd = WIN_GetPtr( hwnd );
3268 if (!wnd || wnd == WND_DESKTOP) return FALSE;
3269 if (wnd == WND_OTHER_PROCESS)
3271 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3272 return 0;
3274 wnd->helpContext = id;
3275 WIN_ReleasePtr( wnd );
3276 return TRUE;
3280 /*******************************************************************
3281 * DragDetect (USER32.@)
3283 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3285 MSG msg;
3286 RECT rect;
3287 WORD wDragWidth = GetSystemMetrics(SM_CXDRAG);
3288 WORD wDragHeight= GetSystemMetrics(SM_CYDRAG);
3290 rect.left = pt.x - wDragWidth;
3291 rect.right = pt.x + wDragWidth;
3293 rect.top = pt.y - wDragHeight;
3294 rect.bottom = pt.y + wDragHeight;
3296 SetCapture(hWnd);
3298 while(1)
3300 while (PeekMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ))
3302 if( msg.message == WM_LBUTTONUP )
3304 ReleaseCapture();
3305 return 0;
3307 if( msg.message == WM_MOUSEMOVE )
3309 POINT tmp;
3310 tmp.x = (short)LOWORD(msg.lParam);
3311 tmp.y = (short)HIWORD(msg.lParam);
3312 if( !PtInRect( &rect, tmp ))
3314 ReleaseCapture();
3315 return 1;
3319 WaitMessage();
3321 return 0;
3324 /******************************************************************************
3325 * GetWindowModuleFileNameA (USER32.@)
3327 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR module, UINT size )
3329 WND *win;
3330 HINSTANCE hinst;
3332 TRACE( "%p, %p, %u\n", hwnd, module, size );
3334 win = WIN_GetPtr( hwnd );
3335 if (!win || win == WND_OTHER_PROCESS || win == WND_DESKTOP)
3337 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
3338 return 0;
3340 hinst = win->hInstance;
3341 WIN_ReleasePtr( win );
3343 return GetModuleFileNameA( hinst, module, size );
3346 /******************************************************************************
3347 * GetWindowModuleFileNameW (USER32.@)
3349 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR module, UINT size )
3351 WND *win;
3352 HINSTANCE hinst;
3354 TRACE( "%p, %p, %u\n", hwnd, module, size );
3356 win = WIN_GetPtr( hwnd );
3357 if (!win || win == WND_OTHER_PROCESS || win == WND_DESKTOP)
3359 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
3360 return 0;
3362 hinst = win->hInstance;
3363 WIN_ReleasePtr( win );
3365 return GetModuleFileNameW( hinst, module, size );
3368 /******************************************************************************
3369 * GetWindowInfo (USER32.@)
3371 * Note: tests show that Windows doesn't check cbSize of the structure.
3373 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3375 if (!pwi) return FALSE;
3376 if (!IsWindow(hwnd)) return FALSE;
3378 GetWindowRect(hwnd, &pwi->rcWindow);
3379 GetClientRect(hwnd, &pwi->rcClient);
3380 /* translate to screen coordinates */
3381 MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3383 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3384 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3385 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3387 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3388 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3390 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3391 pwi->wCreatorVersion = 0x0400;
3393 return TRUE;
3396 /******************************************************************************
3397 * SwitchDesktop (USER32.@)
3399 * NOTES: Sets the current input or interactive desktop.
3401 BOOL WINAPI SwitchDesktop( HDESK hDesktop)
3403 FIXME("SwitchDesktop(hwnd %p) stub!\n", hDesktop);
3404 return TRUE;
3407 /*****************************************************************************
3408 * SetLayeredWindowAttributes (USER32.@)
3410 BOOL WINAPI SetLayeredWindowAttributes( HWND hwnd, COLORREF key, BYTE alpha, DWORD flags )
3412 BOOL ret;
3414 TRACE("(%p,%08x,%d,%x): stub!\n", hwnd, key, alpha, flags);
3416 SERVER_START_REQ( set_window_layered_info )
3418 req->handle = wine_server_user_handle( hwnd );
3419 req->color_key = key;
3420 req->alpha = alpha;
3421 req->flags = flags;
3422 ret = !wine_server_call_err( req );
3424 SERVER_END_REQ;
3426 if (ret) USER_Driver->pSetLayeredWindowAttributes( hwnd, key, alpha, flags );
3428 return ret;
3432 /*****************************************************************************
3433 * GetLayeredWindowAttributes (USER32.@)
3435 BOOL WINAPI GetLayeredWindowAttributes( HWND hwnd, COLORREF *key, BYTE *alpha, DWORD *flags )
3437 BOOL ret;
3439 SERVER_START_REQ( get_window_layered_info )
3441 req->handle = wine_server_user_handle( hwnd );
3442 if ((ret = !wine_server_call_err( req )))
3444 if (key) *key = reply->color_key;
3445 if (alpha) *alpha = reply->alpha;
3446 if (flags) *flags = reply->flags;
3449 SERVER_END_REQ;
3451 return ret;
3455 /*****************************************************************************
3456 * UpdateLayeredWindowIndirect (USER32.@)
3458 BOOL WINAPI UpdateLayeredWindowIndirect( HWND hwnd, const UPDATELAYEREDWINDOWINFO *info )
3460 BYTE alpha = 0xff;
3462 if (!(info->dwFlags & ULW_EX_NORESIZE) && (info->pptDst || info->psize))
3464 int x = 0, y = 0, cx = 0, cy = 0;
3465 DWORD flags = SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW | SWP_NOSENDCHANGING;
3467 if (info->pptDst)
3469 x = info->pptDst->x;
3470 y = info->pptDst->y;
3471 flags &= ~SWP_NOMOVE;
3473 if (info->psize)
3475 cx = info->psize->cx;
3476 cy = info->psize->cy;
3477 flags &= ~SWP_NOSIZE;
3479 TRACE( "moving window %p pos %d,%d %dx%x\n", hwnd, x, y, cx, cy );
3480 SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
3483 if (info->hdcSrc)
3485 RECT rect;
3486 HDC hdc = GetDCEx( hwnd, 0, DCX_CACHE );
3488 if (hdc)
3490 int x = 0, y = 0;
3492 GetClientRect( hwnd, &rect );
3493 if (info->pptSrc)
3495 x = info->pptSrc->x;
3496 y = info->pptSrc->y;
3498 /* FIXME: intersect rect with info->prcDirty */
3499 TRACE( "copying window %p pos %d,%d\n", hwnd, x, y );
3500 BitBlt( hdc, rect.left, rect.top, rect.right, rect.bottom,
3501 info->hdcSrc, rect.left + x, rect.top + y, SRCCOPY );
3502 ReleaseDC( hwnd, hdc );
3506 if (info->pblend && !(info->dwFlags & ULW_OPAQUE)) alpha = info->pblend->SourceConstantAlpha;
3507 TRACE( "setting window %p alpha %u\n", hwnd, alpha );
3508 USER_Driver->pSetLayeredWindowAttributes( hwnd, info->crKey, alpha,
3509 info->dwFlags & (LWA_ALPHA | LWA_COLORKEY) );
3510 return TRUE;
3514 /*****************************************************************************
3515 * UpdateLayeredWindow (USER32.@)
3517 BOOL WINAPI UpdateLayeredWindow( HWND hwnd, HDC hdcDst, POINT *pptDst, SIZE *psize,
3518 HDC hdcSrc, POINT *pptSrc, COLORREF crKey, BLENDFUNCTION *pblend,
3519 DWORD dwFlags)
3521 UPDATELAYEREDWINDOWINFO info;
3523 info.cbSize = sizeof(info);
3524 info.hdcDst = hdcDst;
3525 info.pptDst = pptDst;
3526 info.psize = psize;
3527 info.hdcSrc = hdcSrc;
3528 info.pptSrc = pptSrc;
3529 info.crKey = crKey;
3530 info.pblend = pblend;
3531 info.dwFlags = dwFlags;
3532 info.prcDirty = NULL;
3533 return UpdateLayeredWindowIndirect( hwnd, &info );
3536 /* 64bit versions */
3538 #ifdef GetWindowLongPtrW
3539 #undef GetWindowLongPtrW
3540 #endif
3542 #ifdef GetWindowLongPtrA
3543 #undef GetWindowLongPtrA
3544 #endif
3546 #ifdef SetWindowLongPtrW
3547 #undef SetWindowLongPtrW
3548 #endif
3550 #ifdef SetWindowLongPtrA
3551 #undef SetWindowLongPtrA
3552 #endif
3554 /*****************************************************************************
3555 * GetWindowLongPtrW (USER32.@)
3557 LONG_PTR WINAPI GetWindowLongPtrW( HWND hwnd, INT offset )
3559 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), TRUE );
3562 /*****************************************************************************
3563 * GetWindowLongPtrA (USER32.@)
3565 LONG_PTR WINAPI GetWindowLongPtrA( HWND hwnd, INT offset )
3567 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), FALSE );
3570 /*****************************************************************************
3571 * SetWindowLongPtrW (USER32.@)
3573 LONG_PTR WINAPI SetWindowLongPtrW( HWND hwnd, INT offset, LONG_PTR newval )
3575 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, TRUE );
3578 /*****************************************************************************
3579 * SetWindowLongPtrA (USER32.@)
3581 LONG_PTR WINAPI SetWindowLongPtrA( HWND hwnd, INT offset, LONG_PTR newval )
3583 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, FALSE );