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
26 #include "user_private.h"
29 #include "wine/server.h"
34 #include "wine/exception.h"
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(win
);
39 static DWORD process_layout
= ~0u;
42 /**********************************************************************/
44 /* helper for Get/SetWindowLong */
45 static inline LONG_PTR
get_win_data( const void *ptr
, UINT size
)
47 if (size
== sizeof(WORD
))
50 memcpy( &ret
, ptr
, sizeof(ret
) );
53 else if (size
== sizeof(DWORD
))
56 memcpy( &ret
, ptr
, sizeof(ret
) );
62 memcpy( &ret
, ptr
, sizeof(ret
) );
67 /* helper for Get/SetWindowLong */
68 static inline void set_win_data( void *ptr
, LONG_PTR val
, UINT size
)
70 if (size
== sizeof(WORD
))
73 memcpy( ptr
, &newval
, sizeof(newval
) );
75 else if (size
== sizeof(DWORD
))
78 memcpy( ptr
, &newval
, sizeof(newval
) );
82 memcpy( ptr
, &val
, sizeof(val
) );
87 /***********************************************************************
90 HANDLE
alloc_user_handle( struct user_object
*ptr
, unsigned int type
)
92 return UlongToHandle( NtUserCallTwoParam( (UINT_PTR
)ptr
, type
, NtUserAllocHandle
));
96 /***********************************************************************
99 void *get_user_handle_ptr( HANDLE handle
, unsigned int type
)
101 return (void *)NtUserCallTwoParam( HandleToUlong(handle
), type
, NtUserGetHandlePtr
);
105 /***********************************************************************
106 * release_user_handle_ptr
108 void release_user_handle_ptr( void *ptr
)
110 assert( ptr
&& ptr
!= OBJ_OTHER_PROCESS
);
115 /***********************************************************************
118 void *free_user_handle( HANDLE handle
, unsigned int type
)
120 return UlongToHandle( NtUserCallTwoParam( HandleToUlong(handle
), type
, NtUserFreeHandle
));
124 /***********************************************************************
125 * create_window_handle
127 * Create a window handle with the server.
129 static WND
*create_window_handle( HWND parent
, HWND owner
, UNICODE_STRING
*name
,
130 HINSTANCE instance
, BOOL unicode
,
131 DWORD style
, DWORD ex_style
)
134 HWND handle
= 0, full_parent
= 0, full_owner
= 0;
135 struct tagCLASS
*class = NULL
;
137 DPI_AWARENESS awareness
= GetAwarenessFromDpiAwarenessContext( GetThreadDpiAwarenessContext() );
140 SERVER_START_REQ( create_window
)
142 req
->parent
= wine_server_user_handle( parent
);
143 req
->owner
= wine_server_user_handle( owner
);
144 req
->instance
= wine_server_client_ptr( instance
);
145 req
->dpi
= GetDpiForSystem();
146 req
->awareness
= awareness
;
148 req
->ex_style
= ex_style
;
149 if (!(req
->atom
= get_int_atom_value( name
)) && name
->Length
)
150 wine_server_add_data( req
, name
->Buffer
, name
->Length
);
151 if (!wine_server_call_err( req
))
153 handle
= wine_server_ptr_handle( reply
->handle
);
154 full_parent
= wine_server_ptr_handle( reply
->parent
);
155 full_owner
= wine_server_ptr_handle( reply
->owner
);
156 extra_bytes
= reply
->extra
;
158 awareness
= reply
->awareness
;
159 class = wine_server_get_ptr( reply
->class_ptr
);
166 WARN( "error %d creating window\n", GetLastError() );
170 if (!(win
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
171 sizeof(WND
) + extra_bytes
- sizeof(win
->wExtra
) )))
173 SERVER_START_REQ( destroy_window
)
175 req
->handle
= wine_server_user_handle( handle
);
176 wine_server_call( req
);
179 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
183 if (!parent
) /* if parent is 0 we don't have a desktop window yet */
185 struct user_thread_info
*thread_info
= get_user_thread_info();
187 if (name
->Buffer
== (LPCWSTR
)DESKTOP_CLASS_ATOM
)
189 if (!thread_info
->top_window
) thread_info
->top_window
= full_parent
? full_parent
: handle
;
190 else assert( full_parent
== thread_info
->top_window
);
191 if (full_parent
&& !NtUserCallHwnd( thread_info
->top_window
, NtUserCreateDesktopWindow
))
192 ERR( "failed to create desktop window\n" );
193 register_builtin_classes();
195 else /* HWND_MESSAGE parent */
197 if (!thread_info
->msg_window
&& !full_parent
) thread_info
->msg_window
= handle
;
203 win
->obj
.handle
= handle
;
204 win
->obj
.type
= NTUSER_OBJ_WINDOW
;
205 win
->parent
= full_parent
;
206 win
->owner
= full_owner
;
208 win
->winproc
= get_class_winproc( class );
209 win
->cbWndExtra
= extra_bytes
;
211 win
->dpi_awareness
= awareness
;
212 NtUserCallTwoParam( HandleToUlong(handle
), (UINT_PTR
)win
, NtUserSetHandlePtr
);
213 if (WINPROC_IsUnicode( win
->winproc
, unicode
)) win
->flags
|= WIN_ISUNICODE
;
218 /***********************************************************************
221 * Free a window handle.
223 static void free_window_handle( HWND hwnd
)
225 struct user_object
*ptr
;
227 if ((ptr
= get_user_handle_ptr( hwnd
, NTUSER_OBJ_WINDOW
)) && ptr
!= OBJ_OTHER_PROCESS
)
229 SERVER_START_REQ( destroy_window
)
231 req
->handle
= wine_server_user_handle( hwnd
);
232 wine_server_call( req
);
233 NtUserCallTwoParam( HandleToUlong(hwnd
), 0, NtUserSetHandlePtr
);
237 HeapFree( GetProcessHeap(), 0, ptr
);
242 /*******************************************************************
243 * list_window_children
245 * Build an array of the children of a given window. The array must be
246 * freed with HeapFree. Returns NULL when no windows are found.
248 static HWND
*list_window_children( HDESK desktop
, HWND hwnd
, UNICODE_STRING
*class, DWORD tid
)
252 ATOM atom
= class ? get_int_atom_value( class ) : 0;
254 /* empty class is not the same as NULL class */
255 if (!atom
&& class && !class->Length
) return NULL
;
261 if (!(list
= HeapAlloc( GetProcessHeap(), 0, size
* sizeof(HWND
) ))) break;
263 SERVER_START_REQ( get_window_children
)
265 req
->desktop
= wine_server_obj_handle( desktop
);
266 req
->parent
= wine_server_user_handle( hwnd
);
269 if (!atom
&& class) wine_server_add_data( req
, class->Buffer
, class->Length
);
270 wine_server_set_reply( req
, list
, (size
-1) * sizeof(user_handle_t
) );
271 if (!wine_server_call( req
)) count
= reply
->count
;
274 if (count
&& count
< size
)
276 /* start from the end since HWND is potentially larger than user_handle_t */
277 for (i
= count
- 1; i
>= 0; i
--)
278 list
[i
] = wine_server_ptr_handle( ((user_handle_t
*)list
)[i
] );
282 HeapFree( GetProcessHeap(), 0, list
);
284 size
= count
+ 1; /* restart with a large enough buffer */
290 /*******************************************************************
293 static void send_parent_notify( HWND hwnd
, UINT msg
)
295 if ((GetWindowLongW( hwnd
, GWL_STYLE
) & (WS_CHILD
| WS_POPUP
)) == WS_CHILD
&&
296 !(GetWindowLongW( hwnd
, GWL_EXSTYLE
) & WS_EX_NOPARENTNOTIFY
))
298 HWND parent
= GetParent(hwnd
);
299 if (parent
&& parent
!= GetDesktopWindow())
300 SendMessageW( parent
, WM_PARENTNOTIFY
,
301 MAKEWPARAM( msg
, GetWindowLongPtrW( hwnd
, GWLP_ID
)), (LPARAM
)hwnd
);
306 /*******************************************************************
307 * update_window_state
309 * Trigger an update of the window's driver state and surface.
311 void update_window_state( HWND hwnd
)
313 DPI_AWARENESS_CONTEXT context
;
314 RECT window_rect
, client_rect
, valid_rects
[2];
316 if (!WIN_IsCurrentThread( hwnd
))
318 PostMessageW( hwnd
, WM_WINE_UPDATEWINDOWSTATE
, 0, 0 );
322 context
= SetThreadDpiAwarenessContext( GetWindowDpiAwarenessContext( hwnd
));
323 WIN_GetRectangles( hwnd
, COORDS_PARENT
, &window_rect
, &client_rect
);
324 valid_rects
[0] = valid_rects
[1] = client_rect
;
325 set_window_pos( hwnd
, 0, SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOCLIENTSIZE
| SWP_NOCLIENTMOVE
|
326 SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOREDRAW
,
327 &window_rect
, &client_rect
, valid_rects
);
328 SetThreadDpiAwarenessContext( context
);
332 /*******************************************************************
333 * get_hwnd_message_parent
335 * Return the parent for HWND_MESSAGE windows.
337 HWND
get_hwnd_message_parent(void)
339 struct user_thread_info
*thread_info
= get_user_thread_info();
341 if (!thread_info
->msg_window
) GetDesktopWindow(); /* trigger creation */
342 return thread_info
->msg_window
;
346 /*******************************************************************
349 * Check if window is the desktop or the HWND_MESSAGE top parent.
351 BOOL
is_desktop_window( HWND hwnd
)
353 struct user_thread_info
*thread_info
= get_user_thread_info();
355 if (!hwnd
) return FALSE
;
356 if (hwnd
== thread_info
->top_window
) return TRUE
;
357 if (hwnd
== thread_info
->msg_window
) return TRUE
;
359 if (!HIWORD(hwnd
) || HIWORD(hwnd
) == 0xffff)
361 if (LOWORD(thread_info
->top_window
) == LOWORD(hwnd
)) return TRUE
;
362 if (LOWORD(thread_info
->msg_window
) == LOWORD(hwnd
)) return TRUE
;
368 /*******************************************************************
369 * Dummy window surface for windows that shouldn't get painted.
372 static void CDECL
dummy_surface_lock( struct window_surface
*window_surface
)
377 static void CDECL
dummy_surface_unlock( struct window_surface
*window_surface
)
382 static void *CDECL
dummy_surface_get_bitmap_info( struct window_surface
*window_surface
, BITMAPINFO
*info
)
384 static DWORD dummy_data
;
386 info
->bmiHeader
.biSize
= sizeof( info
->bmiHeader
);
387 info
->bmiHeader
.biWidth
= dummy_surface
.rect
.right
;
388 info
->bmiHeader
.biHeight
= dummy_surface
.rect
.bottom
;
389 info
->bmiHeader
.biPlanes
= 1;
390 info
->bmiHeader
.biBitCount
= 32;
391 info
->bmiHeader
.biCompression
= BI_RGB
;
392 info
->bmiHeader
.biSizeImage
= 0;
393 info
->bmiHeader
.biXPelsPerMeter
= 0;
394 info
->bmiHeader
.biYPelsPerMeter
= 0;
395 info
->bmiHeader
.biClrUsed
= 0;
396 info
->bmiHeader
.biClrImportant
= 0;
400 static RECT
*CDECL
dummy_surface_get_bounds( struct window_surface
*window_surface
)
402 static RECT dummy_bounds
;
403 return &dummy_bounds
;
406 static void CDECL
dummy_surface_set_region( struct window_surface
*window_surface
, HRGN region
)
411 static void CDECL
dummy_surface_flush( struct window_surface
*window_surface
)
416 static void CDECL
dummy_surface_destroy( struct window_surface
*window_surface
)
421 static const struct window_surface_funcs dummy_surface_funcs
=
424 dummy_surface_unlock
,
425 dummy_surface_get_bitmap_info
,
426 dummy_surface_get_bounds
,
427 dummy_surface_set_region
,
429 dummy_surface_destroy
432 struct window_surface dummy_surface
= { &dummy_surface_funcs
, { NULL
, NULL
}, 1, { 0, 0, 1, 1 } };
434 /*******************************************************************
435 * Off-screen window surface.
438 struct offscreen_window_surface
440 struct window_surface header
;
447 static const struct window_surface_funcs offscreen_window_surface_funcs
;
449 static inline void reset_bounds( RECT
*bounds
)
451 bounds
->left
= bounds
->top
= INT_MAX
;
452 bounds
->right
= bounds
->bottom
= INT_MIN
;
455 static struct offscreen_window_surface
*impl_from_window_surface( struct window_surface
*base
)
457 if (!base
|| base
->funcs
!= &offscreen_window_surface_funcs
) return NULL
;
458 return CONTAINING_RECORD( base
, struct offscreen_window_surface
, header
);
461 static void CDECL
offscreen_window_surface_lock( struct window_surface
*base
)
463 struct offscreen_window_surface
*impl
= impl_from_window_surface( base
);
464 EnterCriticalSection( &impl
->cs
);
467 static void CDECL
offscreen_window_surface_unlock( struct window_surface
*base
)
469 struct offscreen_window_surface
*impl
= impl_from_window_surface( base
);
470 LeaveCriticalSection( &impl
->cs
);
473 static RECT
*CDECL
offscreen_window_surface_get_bounds( struct window_surface
*base
)
475 struct offscreen_window_surface
*impl
= impl_from_window_surface( base
);
476 return &impl
->bounds
;
479 static void *CDECL
offscreen_window_surface_get_bitmap_info( struct window_surface
*base
, BITMAPINFO
*info
)
481 struct offscreen_window_surface
*impl
= impl_from_window_surface( base
);
482 memcpy( info
, &impl
->info
, offsetof( BITMAPINFO
, bmiColors
[0] ) );
486 static void CDECL
offscreen_window_surface_set_region( struct window_surface
*base
, HRGN region
)
490 static void CDECL
offscreen_window_surface_flush( struct window_surface
*base
)
492 struct offscreen_window_surface
*impl
= impl_from_window_surface( base
);
493 base
->funcs
->lock( base
);
494 reset_bounds( &impl
->bounds
);
495 base
->funcs
->unlock( base
);
498 static void CDECL
offscreen_window_surface_destroy( struct window_surface
*base
)
500 struct offscreen_window_surface
*impl
= impl_from_window_surface( base
);
501 impl
->cs
.DebugInfo
->Spare
[0] = 0;
502 DeleteCriticalSection( &impl
->cs
);
506 static const struct window_surface_funcs offscreen_window_surface_funcs
=
508 offscreen_window_surface_lock
,
509 offscreen_window_surface_unlock
,
510 offscreen_window_surface_get_bitmap_info
,
511 offscreen_window_surface_get_bounds
,
512 offscreen_window_surface_set_region
,
513 offscreen_window_surface_flush
,
514 offscreen_window_surface_destroy
517 void create_offscreen_window_surface( const RECT
*visible_rect
, struct window_surface
**surface
)
519 struct offscreen_window_surface
*impl
;
521 RECT surface_rect
= *visible_rect
;
523 TRACE( "visible_rect %s, surface %p.\n", wine_dbgstr_rect( visible_rect
), surface
);
525 OffsetRect( &surface_rect
, -surface_rect
.left
, -surface_rect
.top
);
526 surface_rect
.right
= (surface_rect
.right
+ 0x1f) & ~0x1f;
527 surface_rect
.bottom
= (surface_rect
.bottom
+ 0x1f) & ~0x1f;
529 /* check that old surface is an offscreen_window_surface, or release it */
530 if ((impl
= impl_from_window_surface( *surface
)))
532 /* if the rect didn't change, keep the same surface */
533 if (EqualRect( &surface_rect
, &impl
->header
.rect
)) return;
534 window_surface_release( &impl
->header
);
536 else if (*surface
) window_surface_release( *surface
);
538 /* create a new window surface */
540 size
= surface_rect
.right
* surface_rect
.bottom
* 4;
541 if (!(impl
= calloc(1, offsetof( struct offscreen_window_surface
, info
.bmiColors
[0] ) + size
))) return;
543 impl
->header
.funcs
= &offscreen_window_surface_funcs
;
544 impl
->header
.ref
= 1;
545 impl
->header
.rect
= surface_rect
;
547 InitializeCriticalSection( &impl
->cs
);
548 impl
->cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": surface");
549 reset_bounds( &impl
->bounds
);
551 impl
->bits
= (char *)&impl
->info
.bmiColors
[0];
552 impl
->info
.bmiHeader
.biSize
= sizeof( impl
->info
);
553 impl
->info
.bmiHeader
.biWidth
= surface_rect
.right
;
554 impl
->info
.bmiHeader
.biHeight
= surface_rect
.bottom
;
555 impl
->info
.bmiHeader
.biPlanes
= 1;
556 impl
->info
.bmiHeader
.biBitCount
= 32;
557 impl
->info
.bmiHeader
.biCompression
= BI_RGB
;
558 impl
->info
.bmiHeader
.biSizeImage
= size
;
560 TRACE( "created window surface %p\n", &impl
->header
);
562 *surface
= &impl
->header
;
565 /*******************************************************************
566 * register_window_surface
568 * Register a window surface in the global list, possibly replacing another one.
570 void register_window_surface( struct window_surface
*old
, struct window_surface
*new )
572 if (old
== &dummy_surface
) old
= NULL
;
573 if (new == &dummy_surface
) new = NULL
;
574 NtUserCallTwoParam( (UINT_PTR
)old
, (UINT_PTR
)new, NtUserRegisterWindowSurface
);
578 /*******************************************************************
579 * flush_window_surfaces
581 * Flush pending output from all window surfaces.
583 void flush_window_surfaces( BOOL idle
)
585 NtUserCallOneParam( idle
, NtUserFlushWindowSurfaces
);
589 /***********************************************************************
592 * Return a pointer to the WND structure if local to the process,
593 * or WND_OTHER_PROCESS if handle may be valid in other process.
594 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
596 WND
*WIN_GetPtr( HWND hwnd
)
600 if ((ptr
= get_user_handle_ptr( hwnd
, NTUSER_OBJ_WINDOW
)) == WND_OTHER_PROCESS
)
602 if (is_desktop_window( hwnd
)) ptr
= WND_DESKTOP
;
608 /***********************************************************************
609 * WIN_IsCurrentProcess
611 * Check whether a given window belongs to the current process (and return the full handle).
613 HWND
WIN_IsCurrentProcess( HWND hwnd
)
618 if (!(ptr
= WIN_GetPtr( hwnd
)) || ptr
== WND_OTHER_PROCESS
|| ptr
== WND_DESKTOP
) return 0;
619 ret
= ptr
->obj
.handle
;
620 WIN_ReleasePtr( ptr
);
625 /***********************************************************************
626 * WIN_IsCurrentThread
628 * Check whether a given window belongs to the current thread (and return the full handle).
630 HWND
WIN_IsCurrentThread( HWND hwnd
)
635 if (!(ptr
= WIN_GetPtr( hwnd
)) || ptr
== WND_OTHER_PROCESS
|| ptr
== WND_DESKTOP
) return 0;
636 if (ptr
->tid
== GetCurrentThreadId()) ret
= ptr
->obj
.handle
;
637 WIN_ReleasePtr( ptr
);
642 /***********************************************************************
645 * Set the flags of a window and return the previous value.
647 UINT
win_set_flags( HWND hwnd
, UINT set_mask
, UINT clear_mask
)
650 WND
*ptr
= WIN_GetPtr( hwnd
);
652 if (!ptr
|| ptr
== WND_OTHER_PROCESS
|| ptr
== WND_DESKTOP
) return 0;
654 ptr
->flags
= (ret
& ~clear_mask
) | set_mask
;
655 WIN_ReleasePtr( ptr
);
660 /***********************************************************************
663 * Convert a possibly truncated window handle to a full 32-bit handle.
665 HWND
WIN_GetFullHandle( HWND hwnd
)
669 if (!hwnd
|| (ULONG_PTR
)hwnd
>> 16) return hwnd
;
670 if (LOWORD(hwnd
) <= 1 || LOWORD(hwnd
) == 0xffff) return hwnd
;
671 /* do sign extension for -2 and -3 */
672 if (LOWORD(hwnd
) >= (WORD
)-3) return (HWND
)(LONG_PTR
)(INT16
)LOWORD(hwnd
);
674 if (!(ptr
= WIN_GetPtr( hwnd
))) return hwnd
;
676 if (ptr
== WND_DESKTOP
)
678 if (LOWORD(hwnd
) == LOWORD(GetDesktopWindow())) return GetDesktopWindow();
679 else return get_hwnd_message_parent();
682 if (ptr
!= WND_OTHER_PROCESS
)
684 hwnd
= ptr
->obj
.handle
;
685 WIN_ReleasePtr( ptr
);
687 else /* may belong to another process */
689 SERVER_START_REQ( get_window_info
)
691 req
->handle
= wine_server_user_handle( hwnd
);
692 if (!wine_server_call_err( req
)) hwnd
= wine_server_ptr_handle( reply
->full_handle
);
700 /***********************************************************************
703 * Change the owner of a window.
705 static HWND
WIN_SetOwner( HWND hwnd
, HWND owner
)
707 WND
*win
= WIN_GetPtr( hwnd
);
710 if (!win
|| win
== WND_DESKTOP
) return 0;
711 if (win
== WND_OTHER_PROCESS
)
713 if (IsWindow(hwnd
)) ERR( "cannot set owner %p on other process window %p\n", owner
, hwnd
);
716 SERVER_START_REQ( set_window_owner
)
718 req
->handle
= wine_server_user_handle( hwnd
);
719 req
->owner
= wine_server_user_handle( owner
);
720 if (!wine_server_call( req
))
722 win
->owner
= wine_server_ptr_handle( reply
->full_owner
);
723 ret
= wine_server_ptr_handle( reply
->prev_owner
);
727 WIN_ReleasePtr( win
);
732 /***********************************************************************
735 * Change the style of a window.
737 ULONG
WIN_SetStyle( HWND hwnd
, ULONG set_bits
, ULONG clear_bits
)
739 BOOL ok
, made_visible
= FALSE
;
741 WND
*win
= WIN_GetPtr( hwnd
);
743 if (!win
|| win
== WND_DESKTOP
) return 0;
744 if (win
== WND_OTHER_PROCESS
)
747 return SendMessageW(hwnd
, WM_WINE_SETSTYLE
, set_bits
, clear_bits
);
750 style
.styleOld
= win
->dwStyle
;
751 style
.styleNew
= (win
->dwStyle
| set_bits
) & ~clear_bits
;
752 if (style
.styleNew
== style
.styleOld
)
754 WIN_ReleasePtr( win
);
755 return style
.styleNew
;
757 SERVER_START_REQ( set_window_info
)
759 req
->handle
= wine_server_user_handle( hwnd
);
760 req
->flags
= SET_WIN_STYLE
;
761 req
->style
= style
.styleNew
;
762 req
->extra_offset
= -1;
763 if ((ok
= !wine_server_call( req
)))
765 style
.styleOld
= reply
->old_style
;
766 win
->dwStyle
= style
.styleNew
;
771 if (ok
&& ((style
.styleOld
^ style
.styleNew
) & WS_VISIBLE
))
773 made_visible
= (style
.styleNew
& WS_VISIBLE
) != 0;
774 invalidate_dce( win
, NULL
);
776 WIN_ReleasePtr( win
);
780 USER_Driver
->pSetWindowStyle( hwnd
, GWL_STYLE
, &style
);
781 if (made_visible
) update_window_state( hwnd
);
783 return style
.styleOld
;
787 /***********************************************************************
790 * Get the window and client rectangles.
792 BOOL
WIN_GetRectangles( HWND hwnd
, enum coords_relative relative
, RECT
*rectWindow
, RECT
*rectClient
)
794 WND
*win
= WIN_GetPtr( hwnd
);
799 SetLastError( ERROR_INVALID_WINDOW_HANDLE
);
802 if (win
== WND_DESKTOP
)
805 rect
.left
= rect
.top
= 0;
806 if (hwnd
== get_hwnd_message_parent())
810 rect
= rect_win_to_thread_dpi( hwnd
, rect
);
814 rect
= get_primary_monitor_rect();
816 if (rectWindow
) *rectWindow
= rect
;
817 if (rectClient
) *rectClient
= rect
;
820 if (win
!= WND_OTHER_PROCESS
)
822 RECT window_rect
= win
->window_rect
, client_rect
= win
->client_rect
;
827 OffsetRect( &window_rect
, -win
->client_rect
.left
, -win
->client_rect
.top
);
828 OffsetRect( &client_rect
, -win
->client_rect
.left
, -win
->client_rect
.top
);
829 if (win
->dwExStyle
& WS_EX_LAYOUTRTL
)
830 mirror_rect( &win
->client_rect
, &window_rect
);
833 OffsetRect( &window_rect
, -win
->window_rect
.left
, -win
->window_rect
.top
);
834 OffsetRect( &client_rect
, -win
->window_rect
.left
, -win
->window_rect
.top
);
835 if (win
->dwExStyle
& WS_EX_LAYOUTRTL
)
836 mirror_rect( &win
->window_rect
, &client_rect
);
841 WND
*parent
= WIN_GetPtr( win
->parent
);
842 if (parent
== WND_DESKTOP
) break;
843 if (!parent
|| parent
== WND_OTHER_PROCESS
)
845 WIN_ReleasePtr( win
);
848 if (parent
->flags
& WIN_CHILDREN_MOVED
)
850 WIN_ReleasePtr( parent
);
851 WIN_ReleasePtr( win
);
854 if (parent
->dwExStyle
& WS_EX_LAYOUTRTL
)
856 mirror_rect( &parent
->client_rect
, &window_rect
);
857 mirror_rect( &parent
->client_rect
, &client_rect
);
859 WIN_ReleasePtr( parent
);
865 WND
*parent
= WIN_GetPtr( win
->parent
);
866 if (parent
== WND_DESKTOP
) break;
867 if (!parent
|| parent
== WND_OTHER_PROCESS
)
869 WIN_ReleasePtr( win
);
872 WIN_ReleasePtr( win
);
873 if (parent
->flags
& WIN_CHILDREN_MOVED
)
875 WIN_ReleasePtr( parent
);
881 OffsetRect( &window_rect
, win
->client_rect
.left
, win
->client_rect
.top
);
882 OffsetRect( &client_rect
, win
->client_rect
.left
, win
->client_rect
.top
);
887 if (rectWindow
) *rectWindow
= rect_win_to_thread_dpi( hwnd
, window_rect
);
888 if (rectClient
) *rectClient
= rect_win_to_thread_dpi( hwnd
, client_rect
);
889 WIN_ReleasePtr( win
);
894 SERVER_START_REQ( get_window_rectangles
)
896 req
->handle
= wine_server_user_handle( hwnd
);
897 req
->relative
= relative
;
898 req
->dpi
= get_thread_dpi();
899 if ((ret
= !wine_server_call_err( req
)))
903 rectWindow
->left
= reply
->window
.left
;
904 rectWindow
->top
= reply
->window
.top
;
905 rectWindow
->right
= reply
->window
.right
;
906 rectWindow
->bottom
= reply
->window
.bottom
;
910 rectClient
->left
= reply
->client
.left
;
911 rectClient
->top
= reply
->client
.top
;
912 rectClient
->right
= reply
->client
.right
;
913 rectClient
->bottom
= reply
->client
.bottom
;
922 /***********************************************************************
925 * Destroy storage associated to a window. "Internals" p.358
927 LRESULT
WIN_DestroyWindow( HWND hwnd
)
931 HMENU menu
= 0, sys_menu
;
932 struct window_surface
*surface
;
934 TRACE("%p\n", hwnd
);
936 /* destroy default IME window */
937 if (win_set_flags( hwnd
, 0, WIN_HAS_IME_WIN
) & WIN_HAS_IME_WIN
)
939 TRACE("unregister IME window for %p\n", hwnd
);
940 imm_unregister_window( hwnd
);
943 /* free child windows */
944 if ((list
= WIN_ListChildren( hwnd
)))
947 for (i
= 0; list
[i
]; i
++)
949 if (WIN_IsCurrentThread( list
[i
] )) WIN_DestroyWindow( list
[i
] );
950 else SendNotifyMessageW( list
[i
], WM_WINE_DESTROYWINDOW
, 0, 0 );
952 HeapFree( GetProcessHeap(), 0, list
);
955 /* Unlink now so we won't bother with the children later on */
956 SERVER_START_REQ( set_parent
)
958 req
->handle
= wine_server_user_handle( hwnd
);
960 wine_server_call( req
);
965 * Send the WM_NCDESTROY to the window being destroyed.
967 SendMessageW( hwnd
, WM_NCDESTROY
, 0, 0 );
969 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
971 /* free resources associated with the window */
973 if (!(wndPtr
= WIN_GetPtr( hwnd
)) || wndPtr
== WND_OTHER_PROCESS
) return 0;
974 if ((wndPtr
->dwStyle
& (WS_CHILD
| WS_POPUP
)) != WS_CHILD
)
975 menu
= (HMENU
)wndPtr
->wIDmenu
;
976 sys_menu
= wndPtr
->hSysMenu
;
977 free_dce( wndPtr
->dce
, hwnd
);
979 HeapFree( GetProcessHeap(), 0, wndPtr
->text
);
981 HeapFree( GetProcessHeap(), 0, wndPtr
->pScroll
);
982 wndPtr
->pScroll
= NULL
;
983 DestroyIcon( wndPtr
->hIconSmall2
);
984 surface
= wndPtr
->surface
;
985 wndPtr
->surface
= NULL
;
986 WIN_ReleasePtr( wndPtr
);
988 if (menu
) DestroyMenu( menu
);
989 if (sys_menu
) DestroyMenu( sys_menu
);
992 register_window_surface( surface
, NULL
);
993 window_surface_release( surface
);
996 USER_Driver
->pDestroyWindow( hwnd
);
998 free_window_handle( hwnd
);
1003 /***********************************************************************
1004 * next_thread_window
1006 static WND
*next_thread_window( HWND
*hwnd
)
1008 return (WND
*)NtUserCallOneParam( (UINT_PTR
)hwnd
, NtUserNextThreadWindow
);
1012 /***********************************************************************
1013 * destroy_thread_windows
1015 * Destroy all window owned by the current thread.
1017 void destroy_thread_windows(void)
1019 WND
*win
, *free_list
= NULL
, **free_list_ptr
= &free_list
;
1023 while ((win
= next_thread_window( &hwnd
)))
1025 free_dce( win
->dce
, win
->obj
.handle
);
1026 NtUserCallTwoParam( HandleToUlong(hwnd
), 0, NtUserSetHandlePtr
);
1027 win
->obj
.handle
= *free_list_ptr
;
1028 free_list_ptr
= (WND
**)&win
->obj
.handle
;
1032 SERVER_START_REQ( destroy_window
)
1034 req
->handle
= 0; /* destroy all thread windows */
1035 wine_server_call( req
);
1041 while ((win
= free_list
))
1043 free_list
= win
->obj
.handle
;
1044 TRACE( "destroying %p\n", win
);
1046 if ((win
->dwStyle
& (WS_CHILD
| WS_POPUP
)) != WS_CHILD
&& win
->wIDmenu
)
1047 DestroyMenu( UlongToHandle(win
->wIDmenu
) );
1048 if (win
->hSysMenu
) DestroyMenu( win
->hSysMenu
);
1051 register_window_surface( win
->surface
, NULL
);
1052 window_surface_release( win
->surface
);
1054 HeapFree( GetProcessHeap(), 0, win
);
1059 /***********************************************************************
1060 * WIN_FixCoordinates
1062 * Fix the coordinates - Helper for WIN_CreateWindowEx.
1063 * returns default show mode in sw.
1065 static void WIN_FixCoordinates( CREATESTRUCTW
*cs
, INT
*sw
)
1067 #define IS_DEFAULT(x) ((x) == CW_USEDEFAULT || (x) == (SHORT)0x8000)
1070 if (cs
->dwExStyle
& WS_EX_MDICHILD
)
1074 MDI_CalcDefaultChildPos(cs
->hwndParent
, -1, pos
, 0, &id
);
1075 if (!(cs
->style
& WS_POPUP
)) cs
->hMenu
= ULongToHandle(id
);
1077 TRACE("MDI child id %04x\n", id
);
1080 if (cs
->style
& (WS_CHILD
| WS_POPUP
))
1082 if (cs
->dwExStyle
& WS_EX_MDICHILD
)
1084 if (IS_DEFAULT(cs
->x
))
1089 if (IS_DEFAULT(cs
->cx
) || !cs
->cx
) cs
->cx
= pos
[1].x
;
1090 if (IS_DEFAULT(cs
->cy
) || !cs
->cy
) cs
->cy
= pos
[1].y
;
1094 if (IS_DEFAULT(cs
->x
)) cs
->x
= cs
->y
= 0;
1095 if (IS_DEFAULT(cs
->cx
)) cs
->cx
= cs
->cy
= 0;
1098 else /* overlapped window */
1101 MONITORINFO mon_info
;
1104 if (!IS_DEFAULT(cs
->x
) && !IS_DEFAULT(cs
->cx
) && !IS_DEFAULT(cs
->cy
)) return;
1106 monitor
= MonitorFromWindow( cs
->hwndParent
, MONITOR_DEFAULTTOPRIMARY
);
1107 mon_info
.cbSize
= sizeof(mon_info
);
1108 GetMonitorInfoW( monitor
, &mon_info
);
1109 GetStartupInfoW( &info
);
1111 if (IS_DEFAULT(cs
->x
))
1113 if (!IS_DEFAULT(cs
->y
)) *sw
= cs
->y
;
1114 cs
->x
= (info
.dwFlags
& STARTF_USEPOSITION
) ? info
.dwX
: mon_info
.rcWork
.left
;
1115 cs
->y
= (info
.dwFlags
& STARTF_USEPOSITION
) ? info
.dwY
: mon_info
.rcWork
.top
;
1118 if (IS_DEFAULT(cs
->cx
))
1120 if (info
.dwFlags
& STARTF_USESIZE
)
1122 cs
->cx
= info
.dwXSize
;
1123 cs
->cy
= info
.dwYSize
;
1127 cs
->cx
= (mon_info
.rcWork
.right
- mon_info
.rcWork
.left
) * 3 / 4 - cs
->x
;
1128 cs
->cy
= (mon_info
.rcWork
.bottom
- mon_info
.rcWork
.top
) * 3 / 4 - cs
->y
;
1131 /* neither x nor cx are default. Check the y values .
1132 * In the trace we see Outlook and Outlook Express using
1133 * cy set to CW_USEDEFAULT when opening the address book.
1135 else if (IS_DEFAULT(cs
->cy
))
1137 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
1138 cs
->cy
= (mon_info
.rcWork
.bottom
- mon_info
.rcWork
.top
) * 3 / 4 - cs
->y
;
1144 /***********************************************************************
1145 * dump_window_styles
1147 static void dump_window_styles( DWORD style
, DWORD exstyle
)
1150 if(style
& WS_POPUP
) TRACE(" WS_POPUP");
1151 if(style
& WS_CHILD
) TRACE(" WS_CHILD");
1152 if(style
& WS_MINIMIZE
) TRACE(" WS_MINIMIZE");
1153 if(style
& WS_VISIBLE
) TRACE(" WS_VISIBLE");
1154 if(style
& WS_DISABLED
) TRACE(" WS_DISABLED");
1155 if(style
& WS_CLIPSIBLINGS
) TRACE(" WS_CLIPSIBLINGS");
1156 if(style
& WS_CLIPCHILDREN
) TRACE(" WS_CLIPCHILDREN");
1157 if(style
& WS_MAXIMIZE
) TRACE(" WS_MAXIMIZE");
1158 if((style
& WS_CAPTION
) == WS_CAPTION
) TRACE(" WS_CAPTION");
1161 if(style
& WS_BORDER
) TRACE(" WS_BORDER");
1162 if(style
& WS_DLGFRAME
) TRACE(" WS_DLGFRAME");
1164 if(style
& WS_VSCROLL
) TRACE(" WS_VSCROLL");
1165 if(style
& WS_HSCROLL
) TRACE(" WS_HSCROLL");
1166 if(style
& WS_SYSMENU
) TRACE(" WS_SYSMENU");
1167 if(style
& WS_THICKFRAME
) TRACE(" WS_THICKFRAME");
1168 if (style
& WS_CHILD
)
1170 if(style
& WS_GROUP
) TRACE(" WS_GROUP");
1171 if(style
& WS_TABSTOP
) TRACE(" WS_TABSTOP");
1175 if(style
& WS_MINIMIZEBOX
) TRACE(" WS_MINIMIZEBOX");
1176 if(style
& WS_MAXIMIZEBOX
) TRACE(" WS_MAXIMIZEBOX");
1179 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
1180 #define DUMPED_STYLES \
1181 ((DWORD)(WS_POPUP | \
1200 if(style
& ~DUMPED_STYLES
) TRACE(" %08x", style
& ~DUMPED_STYLES
);
1202 #undef DUMPED_STYLES
1204 TRACE( "exstyle:" );
1205 if(exstyle
& WS_EX_DLGMODALFRAME
) TRACE(" WS_EX_DLGMODALFRAME");
1206 if(exstyle
& WS_EX_DRAGDETECT
) TRACE(" WS_EX_DRAGDETECT");
1207 if(exstyle
& WS_EX_NOPARENTNOTIFY
) TRACE(" WS_EX_NOPARENTNOTIFY");
1208 if(exstyle
& WS_EX_TOPMOST
) TRACE(" WS_EX_TOPMOST");
1209 if(exstyle
& WS_EX_ACCEPTFILES
) TRACE(" WS_EX_ACCEPTFILES");
1210 if(exstyle
& WS_EX_TRANSPARENT
) TRACE(" WS_EX_TRANSPARENT");
1211 if(exstyle
& WS_EX_MDICHILD
) TRACE(" WS_EX_MDICHILD");
1212 if(exstyle
& WS_EX_TOOLWINDOW
) TRACE(" WS_EX_TOOLWINDOW");
1213 if(exstyle
& WS_EX_WINDOWEDGE
) TRACE(" WS_EX_WINDOWEDGE");
1214 if(exstyle
& WS_EX_CLIENTEDGE
) TRACE(" WS_EX_CLIENTEDGE");
1215 if(exstyle
& WS_EX_CONTEXTHELP
) TRACE(" WS_EX_CONTEXTHELP");
1216 if(exstyle
& WS_EX_RIGHT
) TRACE(" WS_EX_RIGHT");
1217 if(exstyle
& WS_EX_RTLREADING
) TRACE(" WS_EX_RTLREADING");
1218 if(exstyle
& WS_EX_LEFTSCROLLBAR
) TRACE(" WS_EX_LEFTSCROLLBAR");
1219 if(exstyle
& WS_EX_CONTROLPARENT
) TRACE(" WS_EX_CONTROLPARENT");
1220 if(exstyle
& WS_EX_STATICEDGE
) TRACE(" WS_EX_STATICEDGE");
1221 if(exstyle
& WS_EX_APPWINDOW
) TRACE(" WS_EX_APPWINDOW");
1222 if(exstyle
& WS_EX_LAYERED
) TRACE(" WS_EX_LAYERED");
1223 if(exstyle
& WS_EX_NOINHERITLAYOUT
) TRACE(" WS_EX_NOINHERITLAYOUT");
1224 if(exstyle
& WS_EX_LAYOUTRTL
) TRACE(" WS_EX_LAYOUTRTL");
1225 if(exstyle
& WS_EX_COMPOSITED
) TRACE(" WS_EX_COMPOSITED");
1226 if(exstyle
& WS_EX_NOACTIVATE
) TRACE(" WS_EX_NOACTIVATE");
1228 #define DUMPED_EX_STYLES \
1229 ((DWORD)(WS_EX_DLGMODALFRAME | \
1230 WS_EX_DRAGDETECT | \
1231 WS_EX_NOPARENTNOTIFY | \
1233 WS_EX_ACCEPTFILES | \
1234 WS_EX_TRANSPARENT | \
1236 WS_EX_TOOLWINDOW | \
1237 WS_EX_WINDOWEDGE | \
1238 WS_EX_CLIENTEDGE | \
1239 WS_EX_CONTEXTHELP | \
1241 WS_EX_RTLREADING | \
1242 WS_EX_LEFTSCROLLBAR | \
1243 WS_EX_CONTROLPARENT | \
1244 WS_EX_STATICEDGE | \
1247 WS_EX_NOINHERITLAYOUT | \
1252 if(exstyle
& ~DUMPED_EX_STYLES
) TRACE(" %08x", exstyle
& ~DUMPED_EX_STYLES
);
1254 #undef DUMPED_EX_STYLES
1257 /***********************************************************************
1258 * map_dpi_create_struct
1260 static void map_dpi_create_struct( CREATESTRUCTW
*cs
, UINT dpi_from
, UINT dpi_to
)
1262 if (!dpi_from
&& !dpi_to
) return;
1263 if (!dpi_from
|| !dpi_to
)
1265 POINT pt
= { cs
->x
, cs
->y
};
1266 UINT mon_dpi
= get_monitor_dpi( MonitorFromPoint( pt
, MONITOR_DEFAULTTONEAREST
));
1267 if (!dpi_from
) dpi_from
= mon_dpi
;
1268 else dpi_to
= mon_dpi
;
1270 if (dpi_from
== dpi_to
) return;
1271 cs
->x
= MulDiv( cs
->x
, dpi_to
, dpi_from
);
1272 cs
->y
= MulDiv( cs
->y
, dpi_to
, dpi_from
);
1273 cs
->cx
= MulDiv( cs
->cx
, dpi_to
, dpi_from
);
1274 cs
->cy
= MulDiv( cs
->cy
, dpi_to
, dpi_from
);
1277 /***********************************************************************
1280 static DWORD
fix_exstyle( DWORD style
, DWORD exstyle
)
1282 if ((exstyle
& WS_EX_DLGMODALFRAME
) ||
1283 (!(exstyle
& WS_EX_STATICEDGE
) &&
1284 (style
& (WS_DLGFRAME
| WS_THICKFRAME
))))
1285 exstyle
|= WS_EX_WINDOWEDGE
;
1287 exstyle
&= ~WS_EX_WINDOWEDGE
;
1291 /***********************************************************************
1292 * WIN_CreateWindowEx
1294 * Implementation of CreateWindowEx().
1296 HWND
WIN_CreateWindowEx( CREATESTRUCTW
*cs
, LPCWSTR className
, HINSTANCE module
, BOOL unicode
)
1298 INT cx
, cy
, style
, ex_style
, sw
= SW_SHOW
;
1302 HWND hwnd
, parent
, owner
, top_child
= 0;
1303 UINT win_dpi
, thread_dpi
= get_thread_dpi();
1304 DPI_AWARENESS_CONTEXT context
;
1305 MDICREATESTRUCTW mdi_cs
;
1306 UNICODE_STRING
class;
1307 CBT_CREATEWNDW cbtc
;
1310 if (!get_class_info( module
, className
, NULL
, &class, FALSE
)) return FALSE
;
1312 TRACE("%s %s%s%s ex=%08x style=%08x %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
1313 unicode
? debugstr_w(cs
->lpszName
) : debugstr_a((LPCSTR
)cs
->lpszName
),
1314 debugstr_w(className
), class.Buffer
!= className
? "->" : "",
1315 class.Buffer
!= className
? debugstr_wn(class.Buffer
, class.Length
/ sizeof(WCHAR
)) : "",
1316 cs
->dwExStyle
, cs
->style
, cs
->x
, cs
->y
, cs
->cx
, cs
->cy
,
1317 cs
->hwndParent
, cs
->hMenu
, cs
->hInstance
, cs
->lpCreateParams
);
1318 if(TRACE_ON(win
)) dump_window_styles( cs
->style
, cs
->dwExStyle
);
1320 /* Fix the styles for MDI children */
1321 if (cs
->dwExStyle
& WS_EX_MDICHILD
)
1323 if (!(win_get_flags( cs
->hwndParent
) & WIN_ISMDICLIENT
))
1325 WARN("WS_EX_MDICHILD, but parent %p is not MDIClient\n", cs
->hwndParent
);
1329 /* cs->lpCreateParams of WM_[NC]CREATE is different for MDI children.
1330 * MDICREATESTRUCT members have the originally passed values.
1332 * Note: we rely on the fact that MDICREATESTRUCTA and MDICREATESTRUCTW
1333 * have the same layout.
1335 mdi_cs
.szClass
= cs
->lpszClass
;
1336 mdi_cs
.szTitle
= cs
->lpszName
;
1337 mdi_cs
.hOwner
= cs
->hInstance
;
1342 mdi_cs
.style
= cs
->style
;
1343 mdi_cs
.lParam
= (LPARAM
)cs
->lpCreateParams
;
1345 cs
->lpCreateParams
= &mdi_cs
;
1347 if (GetWindowLongW(cs
->hwndParent
, GWL_STYLE
) & MDIS_ALLCHILDSTYLES
)
1349 if (cs
->style
& WS_POPUP
)
1351 TRACE("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n");
1354 cs
->style
|= WS_CHILD
| WS_CLIPSIBLINGS
;
1358 cs
->style
&= ~WS_POPUP
;
1359 cs
->style
|= WS_CHILD
| WS_VISIBLE
| WS_CLIPSIBLINGS
| WS_CAPTION
|
1360 WS_SYSMENU
| WS_THICKFRAME
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
;
1363 top_child
= GetWindow(cs
->hwndParent
, GW_CHILD
);
1367 /* Restore current maximized child */
1368 if((cs
->style
& WS_VISIBLE
) && IsZoomed(top_child
))
1370 TRACE("Restoring current maximized child %p\n", top_child
);
1371 if (cs
->style
& WS_MAXIMIZE
)
1373 /* if the new window is maximized don't bother repainting */
1374 SendMessageW( top_child
, WM_SETREDRAW
, FALSE
, 0 );
1375 ShowWindow( top_child
, SW_SHOWNORMAL
);
1376 SendMessageW( top_child
, WM_SETREDRAW
, TRUE
, 0 );
1378 else ShowWindow( top_child
, SW_SHOWNORMAL
);
1383 /* Find the parent window */
1385 parent
= cs
->hwndParent
;
1388 if (cs
->hwndParent
== HWND_MESSAGE
)
1390 cs
->hwndParent
= parent
= get_hwnd_message_parent();
1392 else if (cs
->hwndParent
)
1394 if ((cs
->style
& (WS_CHILD
|WS_POPUP
)) != WS_CHILD
)
1396 parent
= GetDesktopWindow();
1397 owner
= cs
->hwndParent
;
1401 DWORD parent_style
= GetWindowLongW( parent
, GWL_EXSTYLE
);
1402 if ((parent_style
& WS_EX_LAYOUTRTL
) && !(parent_style
& WS_EX_NOINHERITLAYOUT
))
1403 cs
->dwExStyle
|= WS_EX_LAYOUTRTL
;
1408 if ((cs
->style
& (WS_CHILD
|WS_POPUP
)) == WS_CHILD
)
1410 WARN("No parent for child window\n" );
1411 SetLastError(ERROR_TLW_WITH_WSCHILD
);
1412 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1415 /* are we creating the desktop or HWND_MESSAGE parent itself? */
1416 if (className
!= (LPCWSTR
)DESKTOP_CLASS_ATOM
&&
1417 (IS_INTRESOURCE(className
) || wcsicmp( className
, L
"Message" )))
1420 GetProcessDefaultLayout( &layout
);
1421 if (layout
& LAYOUT_RTL
) cs
->dwExStyle
|= WS_EX_LAYOUTRTL
;
1422 parent
= GetDesktopWindow();
1426 WIN_FixCoordinates(cs
, &sw
); /* fix default coordinates */
1427 cs
->dwExStyle
= fix_exstyle(cs
->style
, cs
->dwExStyle
);
1429 /* Create the window structure */
1431 style
= cs
->style
& ~WS_VISIBLE
;
1432 ex_style
= cs
->dwExStyle
& ~WS_EX_LAYERED
;
1433 if (!(wndPtr
= create_window_handle( parent
, owner
, &class, module
,
1434 unicode
, style
, ex_style
)))
1436 hwnd
= wndPtr
->obj
.handle
;
1438 /* Fill the window structure */
1440 wndPtr
->tid
= GetCurrentThreadId();
1441 wndPtr
->hInstance
= cs
->hInstance
;
1442 wndPtr
->text
= NULL
;
1443 wndPtr
->dwStyle
= style
;
1444 wndPtr
->dwExStyle
= ex_style
;
1445 wndPtr
->wIDmenu
= 0;
1446 wndPtr
->helpContext
= 0;
1447 wndPtr
->pScroll
= NULL
;
1448 wndPtr
->userdata
= 0;
1450 wndPtr
->hIconSmall
= 0;
1451 wndPtr
->hIconSmall2
= 0;
1452 wndPtr
->hSysMenu
= 0;
1454 wndPtr
->min_pos
.x
= wndPtr
->min_pos
.y
= -1;
1455 wndPtr
->max_pos
.x
= wndPtr
->max_pos
.y
= -1;
1456 SetRect( &wndPtr
->normal_rect
, cs
->x
, cs
->y
, cs
->x
+ cs
->cx
, cs
->y
+ cs
->cy
);
1458 if (wndPtr
->dwStyle
& WS_SYSMENU
) SetSystemMenu( hwnd
, 0 );
1460 /* call the WH_CBT hook */
1462 WIN_ReleasePtr( wndPtr
);
1465 cbtc
.hwndInsertAfter
= HWND_TOP
;
1466 if (HOOK_CallHooks( WH_CBT
, HCBT_CREATEWND
, (WPARAM
)hwnd
, (LPARAM
)&cbtc
, unicode
) ||
1467 !(wndPtr
= WIN_GetPtr( hwnd
)))
1469 free_window_handle( hwnd
);
1474 * Correct the window styles.
1476 * It affects only the style loaded into the WIN structure.
1479 if ((wndPtr
->dwStyle
& (WS_CHILD
| WS_POPUP
)) != WS_CHILD
)
1481 wndPtr
->dwStyle
|= WS_CLIPSIBLINGS
;
1482 if (!(wndPtr
->dwStyle
& WS_POPUP
))
1483 wndPtr
->dwStyle
|= WS_CAPTION
;
1486 wndPtr
->dwExStyle
= cs
->dwExStyle
;
1487 /* WS_EX_WINDOWEDGE depends on some other styles */
1488 if ((wndPtr
->dwStyle
& (WS_DLGFRAME
| WS_THICKFRAME
)) &&
1489 !(wndPtr
->dwStyle
& (WS_CHILD
| WS_POPUP
)))
1490 wndPtr
->dwExStyle
|= WS_EX_WINDOWEDGE
;
1492 if (!(wndPtr
->dwStyle
& (WS_CHILD
| WS_POPUP
)))
1493 wndPtr
->flags
|= WIN_NEED_SIZE
;
1495 SERVER_START_REQ( set_window_info
)
1497 req
->handle
= wine_server_user_handle( hwnd
);
1498 req
->flags
= SET_WIN_STYLE
| SET_WIN_EXSTYLE
| SET_WIN_INSTANCE
| SET_WIN_UNICODE
;
1499 req
->style
= wndPtr
->dwStyle
;
1500 req
->ex_style
= wndPtr
->dwExStyle
;
1501 req
->instance
= wine_server_client_ptr( wndPtr
->hInstance
);
1502 req
->is_unicode
= (wndPtr
->flags
& WIN_ISUNICODE
) != 0;
1503 req
->extra_offset
= -1;
1504 wine_server_call( req
);
1508 /* Set the window menu */
1510 if ((wndPtr
->dwStyle
& (WS_CHILD
| WS_POPUP
)) != WS_CHILD
)
1514 if (!MENU_SetMenu(hwnd
, cs
->hMenu
))
1516 WIN_ReleasePtr( wndPtr
);
1517 free_window_handle( hwnd
);
1523 LPCWSTR menuName
= (LPCWSTR
)GetClassLongPtrW( hwnd
, GCLP_MENUNAME
);
1526 cs
->hMenu
= LoadMenuW( cs
->hInstance
, menuName
);
1527 if (cs
->hMenu
) MENU_SetMenu( hwnd
, cs
->hMenu
);
1531 else SetWindowLongPtrW( hwnd
, GWLP_ID
, (ULONG_PTR
)cs
->hMenu
);
1533 win_dpi
= wndPtr
->dpi
;
1534 WIN_ReleasePtr( wndPtr
);
1536 if (parent
) map_dpi_create_struct( cs
, thread_dpi
, win_dpi
);
1538 context
= SetThreadDpiAwarenessContext( GetWindowDpiAwarenessContext( hwnd
));
1540 /* send the WM_GETMINMAXINFO message and fix the size if needed */
1544 if ((cs
->style
& WS_THICKFRAME
) || !(cs
->style
& (WS_POPUP
| WS_CHILD
)))
1546 MINMAXINFO info
= WINPOS_GetMinMaxInfo( hwnd
);
1547 cx
= max( min( cx
, info
.ptMaxTrackSize
.x
), info
.ptMinTrackSize
.x
);
1548 cy
= max( min( cy
, info
.ptMaxTrackSize
.y
), info
.ptMinTrackSize
.y
);
1553 SetRect( &rect
, cs
->x
, cs
->y
, cs
->x
+ cx
, cs
->y
+ cy
);
1554 /* check for wraparound */
1555 if (cs
->x
> 0x7fffffff - cx
) rect
.right
= 0x7fffffff;
1556 if (cs
->y
> 0x7fffffff - cy
) rect
.bottom
= 0x7fffffff;
1557 if (!set_window_pos( hwnd
, 0, SWP_NOZORDER
| SWP_NOACTIVATE
, &rect
, &rect
, NULL
)) goto failed
;
1559 /* send WM_NCCREATE */
1561 TRACE( "hwnd %p cs %d,%d %dx%d %s\n", hwnd
, cs
->x
, cs
->y
, cs
->cx
, cs
->cy
, wine_dbgstr_rect(&rect
) );
1563 result
= SendMessageW( hwnd
, WM_NCCREATE
, 0, (LPARAM
)cs
);
1565 result
= SendMessageA( hwnd
, WM_NCCREATE
, 0, (LPARAM
)cs
);
1568 WARN( "%p: aborted by WM_NCCREATE\n", hwnd
);
1572 /* create default IME window */
1574 if (imm_register_window
&& !is_desktop_window( hwnd
) &&
1575 parent
!= get_hwnd_message_parent() && imm_register_window( hwnd
))
1577 TRACE("register IME window for %p\n", hwnd
);
1578 win_set_flags( hwnd
, WIN_HAS_IME_WIN
, 0 );
1581 /* send WM_NCCALCSIZE */
1583 if (WIN_GetRectangles( hwnd
, COORDS_PARENT
, &rect
, NULL
))
1585 /* yes, even if the CBT hook was called with HWND_TOP */
1586 HWND insert_after
= (GetWindowLongW( hwnd
, GWL_STYLE
) & WS_CHILD
) ? HWND_BOTTOM
: HWND_TOP
;
1587 RECT client_rect
= rect
;
1589 /* the rectangle is in screen coords for WM_NCCALCSIZE when wparam is FALSE */
1590 MapWindowPoints( parent
, 0, (POINT
*)&client_rect
, 2 );
1591 SendMessageW( hwnd
, WM_NCCALCSIZE
, FALSE
, (LPARAM
)&client_rect
);
1592 MapWindowPoints( 0, parent
, (POINT
*)&client_rect
, 2 );
1593 set_window_pos( hwnd
, insert_after
, SWP_NOACTIVATE
, &rect
, &client_rect
, NULL
);
1597 /* send WM_CREATE */
1600 result
= SendMessageW( hwnd
, WM_CREATE
, 0, (LPARAM
)cs
);
1602 result
= SendMessageA( hwnd
, WM_CREATE
, 0, (LPARAM
)cs
);
1603 if (result
== -1) goto failed
;
1605 /* call the driver */
1607 if (!USER_Driver
->pCreateWindow( hwnd
)) goto failed
;
1609 NtUserNotifyWinEvent( EVENT_OBJECT_CREATE
, hwnd
, OBJID_WINDOW
, 0 );
1611 /* send the size messages */
1613 if (!(win_get_flags( hwnd
) & WIN_NEED_SIZE
))
1615 WIN_GetRectangles( hwnd
, COORDS_PARENT
, NULL
, &rect
);
1616 SendMessageW( hwnd
, WM_SIZE
, SIZE_RESTORED
,
1617 MAKELONG(rect
.right
-rect
.left
, rect
.bottom
-rect
.top
));
1618 SendMessageW( hwnd
, WM_MOVE
, 0, MAKELONG( rect
.left
, rect
.top
) );
1621 /* Show the window, maximizing or minimizing if needed */
1623 style
= WIN_SetStyle( hwnd
, 0, WS_MAXIMIZE
| WS_MINIMIZE
);
1624 if (style
& (WS_MINIMIZE
| WS_MAXIMIZE
))
1627 UINT swFlag
= (style
& WS_MINIMIZE
) ? SW_MINIMIZE
: SW_MAXIMIZE
;
1629 swFlag
= WINPOS_MinMaximize( hwnd
, swFlag
, &newPos
);
1630 swFlag
|= SWP_FRAMECHANGED
; /* Frame always gets changed */
1631 if (!(style
& WS_VISIBLE
) || (style
& WS_CHILD
) || GetActiveWindow()) swFlag
|= SWP_NOACTIVATE
;
1632 SetWindowPos( hwnd
, 0, newPos
.left
, newPos
.top
, newPos
.right
- newPos
.left
,
1633 newPos
.bottom
- newPos
.top
, swFlag
);
1636 /* Notify the parent window only */
1638 send_parent_notify( hwnd
, WM_CREATE
);
1639 if (!IsWindow( hwnd
))
1641 SetThreadDpiAwarenessContext( context
);
1645 if (parent
== GetDesktopWindow())
1646 PostMessageW( parent
, WM_PARENTNOTIFY
, WM_CREATE
, (LPARAM
)hwnd
);
1648 if (cs
->style
& WS_VISIBLE
)
1650 if (cs
->style
& WS_MAXIMIZE
)
1652 else if (cs
->style
& WS_MINIMIZE
)
1653 sw
= SW_SHOWMINIMIZED
;
1655 ShowWindow( hwnd
, sw
);
1656 if (cs
->dwExStyle
& WS_EX_MDICHILD
)
1658 SendMessageW(cs
->hwndParent
, WM_MDIREFRESHMENU
, 0, 0);
1659 /* ShowWindow won't activate child windows */
1660 SetWindowPos( hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_SHOWWINDOW
| SWP_NOMOVE
| SWP_NOSIZE
);
1664 /* Call WH_SHELL hook */
1666 if (!(GetWindowLongW( hwnd
, GWL_STYLE
) & WS_CHILD
) && !GetWindow( hwnd
, GW_OWNER
))
1667 HOOK_CallHooks( WH_SHELL
, HSHELL_WINDOWCREATED
, (WPARAM
)hwnd
, 0, TRUE
);
1669 TRACE("created window %p\n", hwnd
);
1670 SetThreadDpiAwarenessContext( context
);
1674 WIN_DestroyWindow( hwnd
);
1675 SetThreadDpiAwarenessContext( context
);
1680 /***********************************************************************
1681 * CreateWindowExA (USER32.@)
1683 HWND WINAPI DECLSPEC_HOTPATCH
CreateWindowExA( DWORD exStyle
, LPCSTR className
,
1684 LPCSTR windowName
, DWORD style
, INT x
,
1685 INT y
, INT width
, INT height
,
1686 HWND parent
, HMENU menu
,
1687 HINSTANCE instance
, LPVOID data
)
1691 cs
.lpCreateParams
= data
;
1692 cs
.hInstance
= instance
;
1694 cs
.hwndParent
= parent
;
1700 cs
.lpszName
= windowName
;
1701 cs
.lpszClass
= className
;
1702 cs
.dwExStyle
= exStyle
;
1704 if (!IS_INTRESOURCE(className
))
1707 if (!MultiByteToWideChar( CP_ACP
, 0, className
, -1, bufferW
, ARRAY_SIZE( bufferW
)))
1709 return wow_handlers
.create_window( (CREATESTRUCTW
*)&cs
, bufferW
, instance
, FALSE
);
1711 /* Note: we rely on the fact that CREATESTRUCTA and */
1712 /* CREATESTRUCTW have the same layout. */
1713 return wow_handlers
.create_window( (CREATESTRUCTW
*)&cs
, (LPCWSTR
)className
, instance
, FALSE
);
1717 /***********************************************************************
1718 * CreateWindowExW (USER32.@)
1720 HWND WINAPI DECLSPEC_HOTPATCH
CreateWindowExW( DWORD exStyle
, LPCWSTR className
,
1721 LPCWSTR windowName
, DWORD style
, INT x
,
1722 INT y
, INT width
, INT height
,
1723 HWND parent
, HMENU menu
,
1724 HINSTANCE instance
, LPVOID data
)
1728 cs
.lpCreateParams
= data
;
1729 cs
.hInstance
= instance
;
1731 cs
.hwndParent
= parent
;
1737 cs
.lpszName
= windowName
;
1738 cs
.lpszClass
= className
;
1739 cs
.dwExStyle
= exStyle
;
1741 return wow_handlers
.create_window( &cs
, className
, instance
, TRUE
);
1745 /***********************************************************************
1746 * WIN_SendDestroyMsg
1748 static void WIN_SendDestroyMsg( HWND hwnd
)
1752 info
.cbSize
= sizeof(info
);
1753 if (NtUserGetGUIThreadInfo( GetCurrentThreadId(), &info
))
1755 if (hwnd
== info
.hwndCaret
) DestroyCaret();
1756 if (hwnd
== info
.hwndActive
) WINPOS_ActivateOtherWindow( hwnd
);
1759 if (hwnd
== NtUserGetClipboardOwner()) CLIPBOARD_ReleaseOwner( hwnd
);
1762 * Send the WM_DESTROY to the window.
1764 SendMessageW( hwnd
, WM_DESTROY
, 0, 0);
1767 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1768 * make sure that the window still exists when we come back.
1775 if (!(pWndArray
= WIN_ListChildren( hwnd
))) return;
1777 for (i
= 0; pWndArray
[i
]; i
++)
1779 if (IsWindow( pWndArray
[i
] )) WIN_SendDestroyMsg( pWndArray
[i
] );
1781 HeapFree( GetProcessHeap(), 0, pWndArray
);
1784 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1788 /***********************************************************************
1789 * DestroyWindow (USER32.@)
1791 BOOL WINAPI
DestroyWindow( HWND hwnd
)
1795 if (!(hwnd
= WIN_IsCurrentThread( hwnd
)) || is_desktop_window( hwnd
))
1797 SetLastError( ERROR_ACCESS_DENIED
);
1801 TRACE("(%p)\n", hwnd
);
1805 if (HOOK_CallHooks( WH_CBT
, HCBT_DESTROYWND
, (WPARAM
)hwnd
, 0, TRUE
)) return FALSE
;
1807 if (MENU_IsMenuActive() == hwnd
)
1810 is_child
= (GetWindowLongW( hwnd
, GWL_STYLE
) & WS_CHILD
) != 0;
1814 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1815 send_parent_notify( hwnd
, WM_DESTROY
);
1817 else if (!GetWindow( hwnd
, GW_OWNER
))
1819 HOOK_CallHooks( WH_SHELL
, HSHELL_WINDOWDESTROYED
, (WPARAM
)hwnd
, 0L, TRUE
);
1820 /* FIXME: clean up palette - see "Internals" p.352 */
1823 if (!IsWindow(hwnd
)) return TRUE
;
1825 /* Hide the window */
1826 if (GetWindowLongW( hwnd
, GWL_STYLE
) & WS_VISIBLE
)
1828 /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
1830 ShowWindow( hwnd
, SW_HIDE
);
1832 SetWindowPos( hwnd
, 0, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
|
1833 SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_HIDEWINDOW
);
1836 if (!IsWindow(hwnd
)) return TRUE
;
1838 /* Recursively destroy owned windows */
1845 BOOL got_one
= FALSE
;
1846 HWND
*list
= WIN_ListChildren( GetDesktopWindow() );
1849 for (i
= 0; list
[i
]; i
++)
1851 if (GetWindow( list
[i
], GW_OWNER
) != hwnd
) continue;
1852 if (WIN_IsCurrentThread( list
[i
] ))
1854 DestroyWindow( list
[i
] );
1858 WIN_SetOwner( list
[i
], 0 );
1860 HeapFree( GetProcessHeap(), 0, list
);
1862 if (!got_one
) break;
1866 /* Send destroy messages */
1868 WIN_SendDestroyMsg( hwnd
);
1869 if (!IsWindow( hwnd
)) return TRUE
;
1871 /* Destroy the window storage */
1873 WIN_DestroyWindow( hwnd
);
1878 /***********************************************************************
1879 * CloseWindow (USER32.@)
1881 BOOL WINAPI
CloseWindow( HWND hwnd
)
1883 if (GetWindowLongW( hwnd
, GWL_STYLE
) & WS_CHILD
) return FALSE
;
1884 ShowWindow( hwnd
, SW_MINIMIZE
);
1889 /***********************************************************************
1890 * OpenIcon (USER32.@)
1892 BOOL WINAPI
OpenIcon( HWND hwnd
)
1894 if (!IsIconic( hwnd
)) return FALSE
;
1895 ShowWindow( hwnd
, SW_SHOWNORMAL
);
1900 /***********************************************************************
1901 * FindWindowExW (USER32.@)
1903 HWND WINAPI
FindWindowExW( HWND parent
, HWND child
, LPCWSTR className
, LPCWSTR title
)
1908 WCHAR
*buffer
= NULL
;
1910 if (!parent
&& child
) parent
= GetDesktopWindow();
1911 else if (parent
== HWND_MESSAGE
) parent
= get_hwnd_message_parent();
1915 len
= lstrlenW(title
) + 1; /* one extra char to check for chars beyond the end */
1916 if (!(buffer
= HeapAlloc( GetProcessHeap(), 0, (len
+ 1) * sizeof(WCHAR
) ))) return 0;
1922 if (IS_INTRESOURCE(className
))
1924 str
.Buffer
= (WCHAR
*)className
;
1925 str
.Length
= str
.MaximumLength
= 0;
1927 else RtlInitUnicodeString( &str
, className
);
1928 list
= list_window_children( 0, parent
, &str
, 0 );
1930 else list
= list_window_children( 0, parent
, NULL
, 0 );
1931 if (!list
) goto done
;
1935 child
= WIN_GetFullHandle( child
);
1936 while (list
[i
] && list
[i
] != child
) i
++;
1937 if (!list
[i
]) goto done
;
1938 i
++; /* start from next window */
1945 if (NtUserInternalGetWindowText( list
[i
], buffer
, len
+ 1 ))
1947 if (!wcsicmp( buffer
, title
)) break;
1951 if (!title
[0]) break;
1959 HeapFree( GetProcessHeap(), 0, list
);
1960 HeapFree( GetProcessHeap(), 0, buffer
);
1966 /***********************************************************************
1967 * FindWindowA (USER32.@)
1969 HWND WINAPI
FindWindowA( LPCSTR className
, LPCSTR title
)
1971 HWND ret
= FindWindowExA( 0, 0, className
, title
);
1972 if (!ret
) SetLastError (ERROR_CANNOT_FIND_WND_CLASS
);
1977 /***********************************************************************
1978 * FindWindowExA (USER32.@)
1980 HWND WINAPI
FindWindowExA( HWND parent
, HWND child
, LPCSTR className
, LPCSTR title
)
1982 LPWSTR titleW
= NULL
;
1987 DWORD len
= MultiByteToWideChar( CP_ACP
, 0, title
, -1, NULL
, 0 );
1988 if (!(titleW
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) ))) return 0;
1989 MultiByteToWideChar( CP_ACP
, 0, title
, -1, titleW
, len
);
1992 if (!IS_INTRESOURCE(className
))
1995 if (MultiByteToWideChar( CP_ACP
, 0, className
, -1, classW
, ARRAY_SIZE( classW
)))
1996 hwnd
= FindWindowExW( parent
, child
, classW
, titleW
);
2000 hwnd
= FindWindowExW( parent
, child
, (LPCWSTR
)className
, titleW
);
2003 HeapFree( GetProcessHeap(), 0, titleW
);
2008 /***********************************************************************
2009 * FindWindowW (USER32.@)
2011 HWND WINAPI
FindWindowW( LPCWSTR className
, LPCWSTR title
)
2013 return FindWindowExW( 0, 0, className
, title
);
2017 /**********************************************************************
2018 * GetDesktopWindow (USER32.@)
2020 HWND WINAPI
GetDesktopWindow(void)
2022 struct user_thread_info
*thread_info
= get_user_thread_info();
2024 if (thread_info
->top_window
) return thread_info
->top_window
;
2025 return UlongToHandle( NtUserCallNoParam( NtUserGetDesktopWindow
));
2029 /*******************************************************************
2030 * EnableWindow (USER32.@)
2032 BOOL WINAPI
EnableWindow( HWND hwnd
, BOOL enable
)
2036 if (is_broadcast(hwnd
))
2038 SetLastError( ERROR_INVALID_PARAMETER
);
2042 TRACE("( %p, %d )\n", hwnd
, enable
);
2046 retvalue
= (WIN_SetStyle( hwnd
, 0, WS_DISABLED
) & WS_DISABLED
) != 0;
2047 if (retvalue
) SendMessageW( hwnd
, WM_ENABLE
, TRUE
, 0 );
2051 SendMessageW( hwnd
, WM_CANCELMODE
, 0, 0 );
2053 retvalue
= (WIN_SetStyle( hwnd
, WS_DISABLED
, 0 ) & WS_DISABLED
) != 0;
2056 if (hwnd
== GetFocus())
2057 SetFocus( 0 ); /* A disabled window can't have the focus */
2059 SendMessageW( hwnd
, WM_ENABLE
, FALSE
, 0 );
2066 /***********************************************************************
2067 * IsWindowEnabled (USER32.@)
2069 BOOL WINAPI
IsWindowEnabled(HWND hWnd
)
2073 SetLastError(NO_ERROR
);
2074 ret
= GetWindowLongW( hWnd
, GWL_STYLE
);
2075 if (!ret
&& GetLastError() != NO_ERROR
) return FALSE
;
2076 return !(ret
& WS_DISABLED
);
2079 /***********************************************************************
2080 * IsWindowUnicode (USER32.@)
2082 BOOL WINAPI
IsWindowUnicode( HWND hwnd
)
2084 return NtUserCallHwnd( hwnd
, NtUserIsWindowUnicode
);
2088 /***********************************************************************
2089 * GetWindowDpiAwarenessContext (USER32.@)
2091 DPI_AWARENESS_CONTEXT WINAPI
GetWindowDpiAwarenessContext( HWND hwnd
)
2093 return (DPI_AWARENESS_CONTEXT
)NtUserCallHwnd( hwnd
, NtUserGetWindowDpiAwarenessContext
);
2097 /***********************************************************************
2098 * GetDpiForWindow (USER32.@)
2100 UINT WINAPI
GetDpiForWindow( HWND hwnd
)
2102 return NtUserCallHwnd( hwnd
, NtUserGetDpiForWindow
);
2106 /**********************************************************************
2109 * Helper function for SetWindowLong().
2111 * 0 is the failure code. However, in the case of failure SetLastError
2112 * must be set to distinguish between a 0 return value and a failure.
2114 LONG_PTR
WIN_SetWindowLong( HWND hwnd
, INT offset
, UINT size
, LONG_PTR newval
, BOOL unicode
)
2117 BOOL ok
, made_visible
= FALSE
;
2118 LONG_PTR retval
= 0;
2121 TRACE( "%p %d %lx %c\n", hwnd
, offset
, newval
, unicode
? 'W' : 'A' );
2123 if (is_broadcast(hwnd
))
2125 SetLastError( ERROR_INVALID_PARAMETER
);
2129 if (!(wndPtr
= WIN_GetPtr( hwnd
)))
2131 SetLastError( ERROR_INVALID_WINDOW_HANDLE
);
2134 if (wndPtr
== WND_DESKTOP
)
2136 /* can't change anything on the desktop window */
2137 SetLastError( ERROR_ACCESS_DENIED
);
2140 if (wndPtr
== WND_OTHER_PROCESS
)
2142 if (offset
== GWLP_WNDPROC
)
2144 SetLastError( ERROR_ACCESS_DENIED
);
2147 if (offset
> 32767 || offset
< -32767)
2149 SetLastError( ERROR_INVALID_INDEX
);
2152 return SendMessageW( hwnd
, WM_WINE_SETWINDOWLONG
, MAKEWPARAM( offset
, size
), newval
);
2155 /* first some special cases */
2159 style
.styleOld
= wndPtr
->dwStyle
;
2160 style
.styleNew
= newval
;
2161 WIN_ReleasePtr( wndPtr
);
2162 SendMessageW( hwnd
, WM_STYLECHANGING
, GWL_STYLE
, (LPARAM
)&style
);
2163 if (!(wndPtr
= WIN_GetPtr( hwnd
)) || wndPtr
== WND_OTHER_PROCESS
) return 0;
2164 newval
= style
.styleNew
;
2165 /* WS_CLIPSIBLINGS can't be reset on top-level windows */
2166 if (wndPtr
->parent
== GetDesktopWindow()) newval
|= WS_CLIPSIBLINGS
;
2167 /* WS_MINIMIZE can't be reset */
2168 if (wndPtr
->dwStyle
& WS_MINIMIZE
) newval
|= WS_MINIMIZE
;
2171 style
.styleOld
= wndPtr
->dwExStyle
;
2172 style
.styleNew
= newval
;
2173 WIN_ReleasePtr( wndPtr
);
2174 SendMessageW( hwnd
, WM_STYLECHANGING
, GWL_EXSTYLE
, (LPARAM
)&style
);
2175 if (!(wndPtr
= WIN_GetPtr( hwnd
)) || wndPtr
== WND_OTHER_PROCESS
) return 0;
2176 /* WS_EX_TOPMOST can only be changed through SetWindowPos */
2177 newval
= (style
.styleNew
& ~WS_EX_TOPMOST
) | (wndPtr
->dwExStyle
& WS_EX_TOPMOST
);
2178 newval
= fix_exstyle(wndPtr
->dwStyle
, newval
);
2180 case GWLP_HWNDPARENT
:
2181 if (wndPtr
->parent
== GetDesktopWindow())
2183 WIN_ReleasePtr( wndPtr
);
2184 return (ULONG_PTR
)WIN_SetOwner( hwnd
, (HWND
)newval
);
2188 WIN_ReleasePtr( wndPtr
);
2189 return (ULONG_PTR
)SetParent( hwnd
, (HWND
)newval
);
2194 UINT old_flags
= wndPtr
->flags
;
2195 retval
= unicode
? GetWindowLongPtrW( hwnd
, offset
) : GetWindowLongPtrA( hwnd
, offset
);
2196 proc
= WINPROC_AllocProc( (WNDPROC
)newval
, unicode
);
2197 if (proc
) wndPtr
->winproc
= proc
;
2198 if (WINPROC_IsUnicode( proc
, unicode
)) wndPtr
->flags
|= WIN_ISUNICODE
;
2199 else wndPtr
->flags
&= ~WIN_ISUNICODE
;
2200 if (!((old_flags
^ wndPtr
->flags
) & WIN_ISUNICODE
))
2202 WIN_ReleasePtr( wndPtr
);
2205 /* update is_unicode flag on the server side */
2209 case GWLP_HINSTANCE
:
2213 if ((wndPtr
->cbWndExtra
- sizeof(LONG_PTR
) >= DWLP_DLGPROC
) &&
2214 (size
== sizeof(LONG_PTR
)) && wndPtr
->dlgInfo
)
2216 WNDPROC
*ptr
= (WNDPROC
*)((char *)wndPtr
->wExtra
+ DWLP_DLGPROC
);
2217 retval
= (ULONG_PTR
)WINPROC_GetProc( *ptr
, unicode
);
2218 *ptr
= WINPROC_AllocProc( (WNDPROC
)newval
, unicode
);
2219 WIN_ReleasePtr( wndPtr
);
2224 if (offset
< 0 || offset
> (int)(wndPtr
->cbWndExtra
- size
))
2226 WARN("Invalid offset %d\n", offset
);
2227 WIN_ReleasePtr( wndPtr
);
2228 SetLastError( ERROR_INVALID_INDEX
);
2231 else if (get_win_data( (char *)wndPtr
->wExtra
+ offset
, size
) == newval
)
2233 /* already set to the same value */
2234 WIN_ReleasePtr( wndPtr
);
2240 SERVER_START_REQ( set_window_info
)
2242 req
->handle
= wine_server_user_handle( hwnd
);
2243 req
->extra_offset
= -1;
2247 req
->flags
= SET_WIN_STYLE
| SET_WIN_EXSTYLE
;
2248 req
->style
= newval
;
2249 req
->ex_style
= fix_exstyle(newval
, wndPtr
->dwExStyle
);
2252 req
->flags
= SET_WIN_EXSTYLE
;
2253 req
->ex_style
= newval
;
2256 req
->flags
= SET_WIN_ID
;
2257 req
->extra_value
= newval
;
2259 case GWLP_HINSTANCE
:
2260 req
->flags
= SET_WIN_INSTANCE
;
2261 req
->instance
= wine_server_client_ptr( (void *)newval
);
2264 req
->flags
= SET_WIN_UNICODE
;
2265 req
->is_unicode
= (wndPtr
->flags
& WIN_ISUNICODE
) != 0;
2268 req
->flags
= SET_WIN_USERDATA
;
2269 req
->user_data
= newval
;
2272 req
->flags
= SET_WIN_EXTRA
;
2273 req
->extra_offset
= offset
;
2274 req
->extra_size
= size
;
2275 set_win_data( &req
->extra_value
, newval
, size
);
2277 if ((ok
= !wine_server_call_err( req
)))
2282 wndPtr
->dwStyle
= newval
;
2283 wndPtr
->dwExStyle
= fix_exstyle(wndPtr
->dwStyle
, wndPtr
->dwExStyle
);
2284 retval
= reply
->old_style
;
2287 wndPtr
->dwExStyle
= newval
;
2288 retval
= reply
->old_ex_style
;
2291 wndPtr
->wIDmenu
= newval
;
2292 retval
= reply
->old_id
;
2294 case GWLP_HINSTANCE
:
2295 wndPtr
->hInstance
= (HINSTANCE
)newval
;
2296 retval
= (ULONG_PTR
)wine_server_get_ptr( reply
->old_instance
);
2301 wndPtr
->userdata
= newval
;
2302 retval
= reply
->old_user_data
;
2305 retval
= get_win_data( (char *)wndPtr
->wExtra
+ offset
, size
);
2306 set_win_data( (char *)wndPtr
->wExtra
+ offset
, newval
, size
);
2313 if ((offset
== GWL_STYLE
&& ((style
.styleOld
^ style
.styleNew
) & WS_VISIBLE
)) ||
2314 (offset
== GWL_EXSTYLE
&& ((style
.styleOld
^ style
.styleNew
) & WS_EX_LAYERED
)))
2316 made_visible
= (wndPtr
->dwStyle
& WS_VISIBLE
) != 0;
2317 invalidate_dce( wndPtr
, NULL
);
2319 WIN_ReleasePtr( wndPtr
);
2323 if (offset
== GWL_STYLE
|| offset
== GWL_EXSTYLE
)
2325 style
.styleOld
= retval
;
2326 style
.styleNew
= newval
;
2327 USER_Driver
->pSetWindowStyle( hwnd
, offset
, &style
);
2328 if (made_visible
) update_window_state( hwnd
);
2329 SendMessageW( hwnd
, WM_STYLECHANGED
, offset
, (LPARAM
)&style
);
2336 /**********************************************************************
2337 * GetWindowWord (USER32.@)
2339 WORD WINAPI
GetWindowWord( HWND hwnd
, INT offset
)
2341 return NtUserCallHwndParam( hwnd
, offset
, NtUserGetWindowWord
);
2345 /**********************************************************************
2346 * GetWindowLongA (USER32.@)
2348 LONG WINAPI
GetWindowLongA( HWND hwnd
, INT offset
)
2354 case GWLP_HINSTANCE
:
2355 case GWLP_HWNDPARENT
:
2356 WARN( "Invalid offset %d\n", offset
);
2357 SetLastError( ERROR_INVALID_INDEX
);
2361 return NtUserCallHwndParam( hwnd
, offset
, NtUserGetWindowLongA
);
2366 /**********************************************************************
2367 * GetWindowLongW (USER32.@)
2369 LONG WINAPI
GetWindowLongW( HWND hwnd
, INT offset
)
2375 case GWLP_HINSTANCE
:
2376 case GWLP_HWNDPARENT
:
2377 WARN( "Invalid offset %d\n", offset
);
2378 SetLastError( ERROR_INVALID_INDEX
);
2382 return NtUserCallHwndParam( hwnd
, offset
, NtUserGetWindowLongW
);
2387 /**********************************************************************
2388 * SetWindowWord (USER32.@)
2390 WORD WINAPI
SetWindowWord( HWND hwnd
, INT offset
, WORD newval
)
2395 case GWLP_HINSTANCE
:
2396 case GWLP_HWNDPARENT
:
2401 WARN("Invalid offset %d\n", offset
);
2402 SetLastError( ERROR_INVALID_INDEX
);
2407 return WIN_SetWindowLong( hwnd
, offset
, sizeof(WORD
), newval
, FALSE
);
2411 /**********************************************************************
2412 * SetWindowLongA (USER32.@)
2414 * See SetWindowLongW.
2416 LONG WINAPI DECLSPEC_HOTPATCH
SetWindowLongA( HWND hwnd
, INT offset
, LONG newval
)
2422 case GWLP_HINSTANCE
:
2423 case GWLP_HWNDPARENT
:
2424 WARN( "Invalid offset %d\n", offset
);
2425 SetLastError( ERROR_INVALID_INDEX
);
2429 return WIN_SetWindowLong( hwnd
, offset
, sizeof(LONG
), newval
, FALSE
);
2434 /**********************************************************************
2435 * SetWindowLongW (USER32.@) Set window attribute
2437 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2438 * value in a window's extra memory.
2440 * The _hwnd_ parameter specifies the handle to a window that
2441 * has extra memory. The _newval_ parameter contains the new
2442 * attribute or extra memory value. If positive, the _offset_
2443 * parameter is the byte-addressed location in the window's extra
2444 * memory to set. If negative, _offset_ specifies the window
2445 * attribute to set, and should be one of the following values:
2447 * GWL_EXSTYLE The window's extended window style
2449 * GWL_STYLE The window's window style.
2451 * GWLP_WNDPROC Pointer to the window's window procedure.
2453 * GWLP_HINSTANCE The window's application instance handle.
2455 * GWLP_ID The window's identifier.
2457 * GWLP_USERDATA The window's user-specified data.
2459 * If the window is a dialog box, the _offset_ parameter can be one of
2460 * the following values:
2462 * DWLP_DLGPROC The address of the window's dialog box procedure.
2464 * DWLP_MSGRESULT The return value of a message
2465 * that the dialog box procedure processed.
2467 * DWLP_USER Application specific information.
2471 * If successful, returns the previous value located at _offset_. Otherwise,
2476 * Extra memory for a window class is specified by a nonzero cbWndExtra
2477 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2478 * time of class creation.
2480 * Using GWL_WNDPROC to set a new window procedure effectively creates
2481 * a window subclass. Use CallWindowProc() in the new windows procedure
2482 * to pass messages to the superclass's window procedure.
2484 * The user data is reserved for use by the application which created
2487 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2488 * instead, call the EnableWindow() function to change the window's
2491 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2492 * SetParent() instead.
2495 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2496 * it sends WM_STYLECHANGING before changing the settings
2497 * and WM_STYLECHANGED afterwards.
2498 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2500 LONG WINAPI DECLSPEC_HOTPATCH
SetWindowLongW(
2501 HWND hwnd
, /* [in] window to alter */
2502 INT offset
, /* [in] offset, in bytes, of location to alter */
2503 LONG newval
/* [in] new value of location */
2510 case GWLP_HINSTANCE
:
2511 case GWLP_HWNDPARENT
:
2512 WARN("Invalid offset %d\n", offset
);
2513 SetLastError( ERROR_INVALID_INDEX
);
2517 return WIN_SetWindowLong( hwnd
, offset
, sizeof(LONG
), newval
, TRUE
);
2522 /*******************************************************************
2523 * GetWindowTextA (USER32.@)
2525 INT WINAPI
GetWindowTextA( HWND hwnd
, LPSTR lpString
, INT nMaxCount
)
2530 if (!lpString
|| nMaxCount
<= 0) return 0;
2536 if (WIN_IsCurrentProcess( hwnd
))
2538 ret
= (INT
)SendMessageA( hwnd
, WM_GETTEXT
, nMaxCount
, (LPARAM
)lpString
);
2540 else if ((buffer
= HeapAlloc( GetProcessHeap(), 0, nMaxCount
* sizeof(WCHAR
) )))
2542 /* when window belongs to other process, don't send a message */
2543 NtUserInternalGetWindowText( hwnd
, buffer
, nMaxCount
);
2544 if (!WideCharToMultiByte( CP_ACP
, 0, buffer
, -1, lpString
, nMaxCount
, NULL
, NULL
))
2545 lpString
[nMaxCount
-1] = 0;
2546 HeapFree( GetProcessHeap(), 0, buffer
);
2547 ret
= strlen(lpString
);
2560 /*******************************************************************
2561 * GetWindowTextW (USER32.@)
2563 INT WINAPI
GetWindowTextW( HWND hwnd
, LPWSTR lpString
, INT nMaxCount
)
2567 if (!lpString
|| nMaxCount
<= 0) return 0;
2573 if (WIN_IsCurrentProcess( hwnd
))
2575 ret
= (INT
)SendMessageW( hwnd
, WM_GETTEXT
, nMaxCount
, (LPARAM
)lpString
);
2579 /* when window belongs to other process, don't send a message */
2580 ret
= NtUserInternalGetWindowText( hwnd
, lpString
, nMaxCount
);
2593 /*******************************************************************
2594 * SetWindowTextA (USER32.@)
2595 * SetWindowText (USER32.@)
2597 BOOL WINAPI DECLSPEC_HOTPATCH
SetWindowTextA( HWND hwnd
, LPCSTR lpString
)
2599 if (is_broadcast(hwnd
))
2601 SetLastError( ERROR_INVALID_PARAMETER
);
2604 if (!WIN_IsCurrentProcess( hwnd
))
2605 WARN( "setting text %s of other process window %p should not use SendMessage\n",
2606 debugstr_a(lpString
), hwnd
);
2607 return (BOOL
)SendMessageA( hwnd
, WM_SETTEXT
, 0, (LPARAM
)lpString
);
2611 /*******************************************************************
2612 * SetWindowTextW (USER32.@)
2614 BOOL WINAPI DECLSPEC_HOTPATCH
SetWindowTextW( HWND hwnd
, LPCWSTR lpString
)
2616 if (is_broadcast(hwnd
))
2618 SetLastError( ERROR_INVALID_PARAMETER
);
2621 if (!WIN_IsCurrentProcess( hwnd
))
2622 WARN( "setting text %s of other process window %p should not use SendMessage\n",
2623 debugstr_w(lpString
), hwnd
);
2624 return (BOOL
)SendMessageW( hwnd
, WM_SETTEXT
, 0, (LPARAM
)lpString
);
2628 /*******************************************************************
2629 * GetWindowTextLengthA (USER32.@)
2631 INT WINAPI
GetWindowTextLengthA( HWND hwnd
)
2635 if (WIN_IsCurrentProcess( hwnd
)) return SendMessageA( hwnd
, WM_GETTEXTLENGTH
, 0, 0 );
2637 /* when window belongs to other process, don't send a message */
2638 GetCPInfo( CP_ACP
, &info
);
2639 return NtUserCallHwnd( hwnd
, NtUserGetWindowTextLength
) * info
.MaxCharSize
;
2642 /*******************************************************************
2643 * GetWindowTextLengthW (USER32.@)
2645 INT WINAPI
GetWindowTextLengthW( HWND hwnd
)
2647 if (WIN_IsCurrentProcess( hwnd
)) return SendMessageW( hwnd
, WM_GETTEXTLENGTH
, 0, 0 );
2649 /* when window belongs to other process, don't send a message */
2650 return NtUserCallHwnd( hwnd
, NtUserGetWindowTextLength
);
2654 /*******************************************************************
2655 * IsWindow (USER32.@)
2657 BOOL WINAPI
IsWindow( HWND hwnd
)
2659 return NtUserCallHwnd( hwnd
, NtUserIsWindow
);
2663 /***********************************************************************
2664 * GetWindowThreadProcessId (USER32.@)
2666 DWORD WINAPI
GetWindowThreadProcessId( HWND hwnd
, LPDWORD process
)
2668 return NtUserCallHwndParam( hwnd
, (UINT_PTR
)process
, NtUserGetWindowThread
);
2672 /*****************************************************************
2673 * GetParent (USER32.@)
2675 HWND WINAPI
GetParent( HWND hwnd
)
2677 return UlongToHandle( NtUserCallHwnd( hwnd
, NtUserGetParent
));
2681 /*****************************************************************
2682 * SetParent (USER32.@)
2684 HWND WINAPI
SetParent( HWND hwnd
, HWND parent
)
2688 HWND old_parent
= 0;
2692 DPI_AWARENESS_CONTEXT context
;
2693 RECT window_rect
, old_screen_rect
, new_screen_rect
;
2695 TRACE("(%p %p)\n", hwnd
, parent
);
2697 if (is_broadcast(hwnd
) || is_broadcast(parent
))
2699 SetLastError(ERROR_INVALID_PARAMETER
);
2703 if (!parent
) parent
= GetDesktopWindow();
2704 else if (parent
== HWND_MESSAGE
) parent
= get_hwnd_message_parent();
2705 else parent
= WIN_GetFullHandle( parent
);
2707 if (!IsWindow( parent
))
2709 SetLastError( ERROR_INVALID_WINDOW_HANDLE
);
2713 /* Some applications try to set a child as a parent */
2714 if (IsChild(hwnd
, parent
))
2716 SetLastError( ERROR_INVALID_PARAMETER
);
2720 if (!(full_handle
= WIN_IsCurrentThread( hwnd
)))
2721 return (HWND
)SendMessageW( hwnd
, WM_WINE_SETPARENT
, (WPARAM
)parent
, 0 );
2723 if (full_handle
== parent
)
2725 SetLastError( ERROR_INVALID_PARAMETER
);
2729 /* Windows hides the window first, then shows it again
2730 * including the WM_SHOWWINDOW messages and all */
2731 was_visible
= ShowWindow( hwnd
, SW_HIDE
);
2733 wndPtr
= WIN_GetPtr( hwnd
);
2734 if (!wndPtr
|| wndPtr
== WND_OTHER_PROCESS
|| wndPtr
== WND_DESKTOP
) return 0;
2736 context
= SetThreadDpiAwarenessContext( GetWindowDpiAwarenessContext( hwnd
));
2737 WIN_GetRectangles( hwnd
, COORDS_PARENT
, &window_rect
, NULL
);
2738 SetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE
);
2739 WIN_GetRectangles( hwnd
, COORDS_SCREEN
, &old_screen_rect
, NULL
);
2740 SetThreadDpiAwarenessContext( context
);
2742 SERVER_START_REQ( set_parent
)
2744 req
->handle
= wine_server_user_handle( hwnd
);
2745 req
->parent
= wine_server_user_handle( parent
);
2746 if ((ret
= !wine_server_call_err( req
)))
2748 old_parent
= wine_server_ptr_handle( reply
->old_parent
);
2749 wndPtr
->parent
= parent
= wine_server_ptr_handle( reply
->full_parent
);
2750 wndPtr
->dpi
= reply
->dpi
;
2751 wndPtr
->dpi_awareness
= reply
->awareness
;
2756 WIN_ReleasePtr( wndPtr
);
2759 context
= SetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE
);
2760 WIN_GetRectangles( hwnd
, COORDS_SCREEN
, &new_screen_rect
, NULL
);
2761 SetThreadDpiAwarenessContext( GetWindowDpiAwarenessContext( hwnd
));
2763 USER_Driver
->pSetParent( full_handle
, parent
, old_parent
);
2766 winpos
.hwndInsertAfter
= HWND_TOP
;
2767 winpos
.x
= window_rect
.left
;
2768 winpos
.y
= window_rect
.top
;
2771 winpos
.flags
= SWP_NOSIZE
;
2773 USER_SetWindowPos( &winpos
, new_screen_rect
.left
- old_screen_rect
.left
,
2774 new_screen_rect
.top
- old_screen_rect
.top
);
2776 if (was_visible
) ShowWindow( hwnd
, SW_SHOW
);
2778 SetThreadDpiAwarenessContext( context
);
2783 /*******************************************************************
2784 * IsChild (USER32.@)
2786 BOOL WINAPI
IsChild( HWND parent
, HWND child
)
2788 return NtUserCallHwndParam( parent
, HandleToUlong(child
), NtUserIsChild
);
2792 /***********************************************************************
2793 * IsWindowVisible (USER32.@)
2795 BOOL WINAPI
IsWindowVisible( HWND hwnd
)
2797 return NtUserCallHwnd( hwnd
, NtUserIsWindowVisible
);
2801 /***********************************************************************
2802 * WIN_IsWindowDrawable
2804 * hwnd is drawable when it is visible, all parents are not
2805 * minimized, and it is itself not minimized unless we are
2806 * trying to draw its default class icon.
2808 BOOL
WIN_IsWindowDrawable( HWND hwnd
, BOOL icon
)
2810 /* FIXME: move callers to win32u */
2811 return NtUserCallHwndParam( hwnd
, icon
, NtUserIsWindowDrawable
);
2815 /*******************************************************************
2816 * GetTopWindow (USER32.@)
2818 HWND WINAPI
GetTopWindow( HWND hwnd
)
2820 if (!hwnd
) hwnd
= GetDesktopWindow();
2821 return GetWindow( hwnd
, GW_CHILD
);
2825 /*******************************************************************
2826 * GetWindow (USER32.@)
2828 HWND WINAPI
GetWindow( HWND hwnd
, UINT rel
)
2830 return UlongToHandle( NtUserCallHwndParam( hwnd
, rel
, NtUserGetWindowRelative
));
2834 /*******************************************************************
2835 * ShowOwnedPopups (USER32.@)
2837 BOOL WINAPI
ShowOwnedPopups( HWND owner
, BOOL fShow
)
2840 HWND
*win_array
= WIN_ListChildren( GetDesktopWindow() );
2842 if (!win_array
) return TRUE
;
2844 while (win_array
[count
]) count
++;
2845 while (--count
>= 0)
2847 if (GetWindow( win_array
[count
], GW_OWNER
) != owner
) continue;
2850 if (win_get_flags( win_array
[count
] ) & WIN_NEEDS_SHOW_OWNEDPOPUP
)
2851 /* In Windows, ShowOwnedPopups(TRUE) generates
2852 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2853 * regardless of the state of the owner
2855 SendMessageW(win_array
[count
], WM_SHOWWINDOW
, SW_SHOWNORMAL
, SW_PARENTOPENING
);
2859 if (GetWindowLongW( win_array
[count
], GWL_STYLE
) & WS_VISIBLE
)
2860 /* In Windows, ShowOwnedPopups(FALSE) generates
2861 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2862 * regardless of the state of the owner
2864 SendMessageW(win_array
[count
], WM_SHOWWINDOW
, SW_HIDE
, SW_PARENTCLOSING
);
2867 HeapFree( GetProcessHeap(), 0, win_array
);
2872 /*******************************************************************
2873 * GetLastActivePopup (USER32.@)
2875 HWND WINAPI
GetLastActivePopup( HWND hwnd
)
2879 SERVER_START_REQ( get_window_info
)
2881 req
->handle
= wine_server_user_handle( hwnd
);
2882 if (!wine_server_call_err( req
)) retval
= wine_server_ptr_handle( reply
->last_active
);
2889 /*******************************************************************
2892 * Build an array of the children of a given window. The array must be
2893 * freed with HeapFree. Returns NULL when no windows are found.
2895 HWND
*WIN_ListChildren( HWND hwnd
)
2899 SetLastError( ERROR_INVALID_WINDOW_HANDLE
);
2902 return list_window_children( 0, hwnd
, NULL
, 0 );
2906 /*******************************************************************
2907 * EnumWindows (USER32.@)
2909 BOOL WINAPI
EnumWindows( WNDENUMPROC lpEnumFunc
, LPARAM lParam
)
2915 USER_CheckNotLock();
2917 /* We have to build a list of all windows first, to avoid */
2918 /* unpleasant side-effects, for instance if the callback */
2919 /* function changes the Z-order of the windows. */
2921 if (!(list
= WIN_ListChildren( GetDesktopWindow() ))) return TRUE
;
2923 /* Now call the callback function for every window */
2925 for (i
= 0; list
[i
]; i
++)
2927 /* Make sure that the window still exists */
2928 if (!IsWindow( list
[i
] )) continue;
2929 if (!(ret
= lpEnumFunc( list
[i
], lParam
))) break;
2931 HeapFree( GetProcessHeap(), 0, list
);
2936 /**********************************************************************
2937 * EnumThreadWindows (USER32.@)
2939 BOOL WINAPI
EnumThreadWindows( DWORD id
, WNDENUMPROC func
, LPARAM lParam
)
2945 USER_CheckNotLock();
2947 if (!(list
= list_window_children( 0, GetDesktopWindow(), NULL
, id
))) return TRUE
;
2949 /* Now call the callback function for every window */
2951 for (i
= 0; list
[i
]; i
++)
2952 if (!(ret
= func( list
[i
], lParam
))) break;
2953 HeapFree( GetProcessHeap(), 0, list
);
2958 /***********************************************************************
2959 * EnumDesktopWindows (USER32.@)
2961 BOOL WINAPI
EnumDesktopWindows( HDESK desktop
, WNDENUMPROC func
, LPARAM lparam
)
2966 USER_CheckNotLock();
2968 if (!(list
= list_window_children( desktop
, 0, NULL
, 0 ))) return TRUE
;
2970 for (i
= 0; list
[i
]; i
++)
2971 if (!func( list
[i
], lparam
)) break;
2972 HeapFree( GetProcessHeap(), 0, list
);
2978 /* Some apps pass a non-stdcall proc to EnumChildWindows,
2979 * so we need a small assembly wrapper to call the proc.
2981 extern LRESULT
enum_callback_wrapper( WNDENUMPROC proc
, HWND hwnd
, LPARAM lparam
);
2982 __ASM_GLOBAL_FUNC( enum_callback_wrapper
,
2984 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
2985 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
2986 "movl %esp,%ebp\n\t"
2987 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
2988 "pushl 16(%ebp)\n\t"
2989 "pushl 12(%ebp)\n\t"
2992 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
2993 __ASM_CFI(".cfi_same_value %ebp\n\t")
2996 static inline LRESULT
enum_callback_wrapper( WNDENUMPROC proc
, HWND hwnd
, LPARAM lparam
)
2998 return proc( hwnd
, lparam
);
3000 #endif /* __i386__ */
3002 /**********************************************************************
3003 * WIN_EnumChildWindows
3005 * Helper function for EnumChildWindows().
3007 static BOOL
WIN_EnumChildWindows( HWND
*list
, WNDENUMPROC func
, LPARAM lParam
)
3012 for ( ; *list
; list
++)
3014 /* Make sure that the window still exists */
3015 if (!IsWindow( *list
)) continue;
3016 /* Build children list first */
3017 childList
= WIN_ListChildren( *list
);
3019 ret
= enum_callback_wrapper( func
, *list
, lParam
);
3023 if (ret
) ret
= WIN_EnumChildWindows( childList
, func
, lParam
);
3024 HeapFree( GetProcessHeap(), 0, childList
);
3026 if (!ret
) return FALSE
;
3032 /**********************************************************************
3033 * EnumChildWindows (USER32.@)
3035 BOOL WINAPI
EnumChildWindows( HWND parent
, WNDENUMPROC func
, LPARAM lParam
)
3040 USER_CheckNotLock();
3042 if (!(list
= WIN_ListChildren( parent
))) return FALSE
;
3043 ret
= WIN_EnumChildWindows( list
, func
, lParam
);
3044 HeapFree( GetProcessHeap(), 0, list
);
3049 /*******************************************************************
3050 * AnyPopup (USER32.@)
3052 BOOL WINAPI
AnyPopup(void)
3056 HWND
*list
= WIN_ListChildren( GetDesktopWindow() );
3058 if (!list
) return FALSE
;
3059 for (i
= 0; list
[i
]; i
++)
3061 if (IsWindowVisible( list
[i
] ) && GetWindow( list
[i
], GW_OWNER
)) break;
3063 retvalue
= (list
[i
] != 0);
3064 HeapFree( GetProcessHeap(), 0, list
);
3069 /*******************************************************************
3070 * FlashWindow (USER32.@)
3072 BOOL WINAPI
FlashWindow( HWND hWnd
, BOOL bInvert
)
3076 finfo
.cbSize
= sizeof(FLASHWINFO
);
3077 finfo
.dwFlags
= bInvert
? FLASHW_ALL
: FLASHW_STOP
;
3079 finfo
.dwTimeout
= 0;
3081 return NtUserFlashWindowEx( &finfo
);
3085 /*******************************************************************
3086 * GetWindowContextHelpId (USER32.@)
3088 DWORD WINAPI
GetWindowContextHelpId( HWND hwnd
)
3091 WND
*wnd
= WIN_GetPtr( hwnd
);
3092 if (!wnd
|| wnd
== WND_DESKTOP
) return 0;
3093 if (wnd
== WND_OTHER_PROCESS
)
3095 if (IsWindow( hwnd
)) FIXME( "not supported on other process window %p\n", hwnd
);
3098 retval
= wnd
->helpContext
;
3099 WIN_ReleasePtr( wnd
);
3104 /*******************************************************************
3105 * SetWindowContextHelpId (USER32.@)
3107 BOOL WINAPI
SetWindowContextHelpId( HWND hwnd
, DWORD id
)
3109 WND
*wnd
= WIN_GetPtr( hwnd
);
3110 if (!wnd
|| wnd
== WND_DESKTOP
) return FALSE
;
3111 if (wnd
== WND_OTHER_PROCESS
)
3113 if (IsWindow( hwnd
)) FIXME( "not supported on other process window %p\n", hwnd
);
3116 wnd
->helpContext
= id
;
3117 WIN_ReleasePtr( wnd
);
3122 /*******************************************************************
3123 * DragDetect (USER32.@)
3125 BOOL WINAPI
DragDetect( HWND hWnd
, POINT pt
)
3129 WORD wDragWidth
, wDragHeight
;
3131 TRACE( "%p,%s\n", hWnd
, wine_dbgstr_point( &pt
) );
3133 if (!(NtUserGetKeyState( VK_LBUTTON
) & 0x8000))
3136 wDragWidth
= GetSystemMetrics(SM_CXDRAG
);
3137 wDragHeight
= GetSystemMetrics(SM_CYDRAG
);
3138 SetRect(&rect
, pt
.x
- wDragWidth
, pt
.y
- wDragHeight
, pt
.x
+ wDragWidth
, pt
.y
+ wDragHeight
);
3144 while (PeekMessageW( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
, PM_REMOVE
))
3146 if( msg
.message
== WM_LBUTTONUP
)
3151 if( msg
.message
== WM_MOUSEMOVE
)
3154 tmp
.x
= (short)LOWORD(msg
.lParam
);
3155 tmp
.y
= (short)HIWORD(msg
.lParam
);
3156 if( !PtInRect( &rect
, tmp
))
3168 /******************************************************************************
3169 * GetWindowModuleFileNameA (USER32.@)
3171 UINT WINAPI
GetWindowModuleFileNameA( HWND hwnd
, LPSTR module
, UINT size
)
3176 TRACE( "%p, %p, %u\n", hwnd
, module
, size
);
3178 win
= WIN_GetPtr( hwnd
);
3179 if (!win
|| win
== WND_OTHER_PROCESS
|| win
== WND_DESKTOP
)
3181 SetLastError( ERROR_INVALID_WINDOW_HANDLE
);
3184 hinst
= win
->hInstance
;
3185 WIN_ReleasePtr( win
);
3187 return GetModuleFileNameA( hinst
, module
, size
);
3190 /******************************************************************************
3191 * GetWindowModuleFileNameW (USER32.@)
3193 UINT WINAPI
GetWindowModuleFileNameW( HWND hwnd
, LPWSTR module
, UINT size
)
3198 TRACE( "%p, %p, %u\n", hwnd
, module
, size
);
3200 win
= WIN_GetPtr( hwnd
);
3201 if (!win
|| win
== WND_OTHER_PROCESS
|| win
== WND_DESKTOP
)
3203 SetLastError( ERROR_INVALID_WINDOW_HANDLE
);
3206 hinst
= win
->hInstance
;
3207 WIN_ReleasePtr( win
);
3209 return GetModuleFileNameW( hinst
, module
, size
);
3212 /******************************************************************************
3213 * GetWindowInfo (USER32.@)
3215 * Note: tests show that Windows doesn't check cbSize of the structure.
3217 BOOL WINAPI DECLSPEC_HOTPATCH
GetWindowInfo( HWND hwnd
, WINDOWINFO
*info
)
3219 return NtUserCallHwndParam( hwnd
, (UINT_PTR
)info
, NtUserGetWindowInfo
);
3222 /******************************************************************************
3223 * SwitchDesktop (USER32.@)
3225 * NOTES: Sets the current input or interactive desktop.
3227 BOOL WINAPI
SwitchDesktop( HDESK hDesktop
)
3229 FIXME("(hwnd %p) stub!\n", hDesktop
);
3234 /***********************************************************************
3235 * __wine_set_pixel_format
3237 BOOL CDECL
__wine_set_pixel_format( HWND hwnd
, int format
)
3239 WND
*win
= WIN_GetPtr( hwnd
);
3241 if (!win
|| win
== WND_DESKTOP
|| win
== WND_OTHER_PROCESS
)
3243 WARN( "setting format %d on win %p not supported\n", format
, hwnd
);
3246 win
->pixel_format
= format
;
3247 WIN_ReleasePtr( win
);
3249 update_window_state( hwnd
);
3254 /*****************************************************************************
3255 * SetLayeredWindowAttributes (USER32.@)
3257 BOOL WINAPI
SetLayeredWindowAttributes( HWND hwnd
, COLORREF key
, BYTE alpha
, DWORD flags
)
3261 TRACE("(%p,%08x,%d,%x)\n", hwnd
, key
, alpha
, flags
);
3263 SERVER_START_REQ( set_window_layered_info
)
3265 req
->handle
= wine_server_user_handle( hwnd
);
3266 req
->color_key
= key
;
3269 ret
= !wine_server_call_err( req
);
3275 USER_Driver
->pSetLayeredWindowAttributes( hwnd
, key
, alpha
, flags
);
3276 update_window_state( hwnd
);
3283 /*****************************************************************************
3284 * UpdateLayeredWindowIndirect (USER32.@)
3286 BOOL WINAPI
UpdateLayeredWindowIndirect( HWND hwnd
, const UPDATELAYEREDWINDOWINFO
*info
)
3288 DWORD flags
= SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOREDRAW
;
3289 RECT window_rect
, client_rect
;
3293 info
->cbSize
!= sizeof(*info
) ||
3294 info
->dwFlags
& ~(ULW_COLORKEY
| ULW_ALPHA
| ULW_OPAQUE
| ULW_EX_NORESIZE
) ||
3295 !(GetWindowLongW( hwnd
, GWL_EXSTYLE
) & WS_EX_LAYERED
) ||
3296 NtUserGetLayeredWindowAttributes( hwnd
, NULL
, NULL
, NULL
))
3298 SetLastError( ERROR_INVALID_PARAMETER
);
3302 WIN_GetRectangles( hwnd
, COORDS_PARENT
, &window_rect
, &client_rect
);
3306 offset
.cx
= info
->pptDst
->x
- window_rect
.left
;
3307 offset
.cy
= info
->pptDst
->y
- window_rect
.top
;
3308 OffsetRect( &client_rect
, offset
.cx
, offset
.cy
);
3309 OffsetRect( &window_rect
, offset
.cx
, offset
.cy
);
3310 flags
&= ~SWP_NOMOVE
;
3314 offset
.cx
= info
->psize
->cx
- (window_rect
.right
- window_rect
.left
);
3315 offset
.cy
= info
->psize
->cy
- (window_rect
.bottom
- window_rect
.top
);
3316 if (info
->psize
->cx
<= 0 || info
->psize
->cy
<= 0)
3318 SetLastError( ERROR_INVALID_PARAMETER
);
3321 if ((info
->dwFlags
& ULW_EX_NORESIZE
) && (offset
.cx
|| offset
.cy
))
3323 SetLastError( ERROR_INCORRECT_SIZE
);
3326 client_rect
.right
+= offset
.cx
;
3327 client_rect
.bottom
+= offset
.cy
;
3328 window_rect
.right
+= offset
.cx
;
3329 window_rect
.bottom
+= offset
.cy
;
3330 flags
&= ~SWP_NOSIZE
;
3333 TRACE( "window %p win %s client %s\n", hwnd
,
3334 wine_dbgstr_rect(&window_rect
), wine_dbgstr_rect(&client_rect
) );
3336 set_window_pos( hwnd
, 0, flags
, &window_rect
, &client_rect
, NULL
);
3337 return USER_Driver
->pUpdateLayeredWindow( hwnd
, info
, &window_rect
);
3341 /*****************************************************************************
3342 * UpdateLayeredWindow (USER32.@)
3344 BOOL WINAPI
UpdateLayeredWindow( HWND hwnd
, HDC hdcDst
, POINT
*pptDst
, SIZE
*psize
,
3345 HDC hdcSrc
, POINT
*pptSrc
, COLORREF crKey
, BLENDFUNCTION
*pblend
,
3348 UPDATELAYEREDWINDOWINFO info
;
3350 if (flags
& ULW_EX_NORESIZE
) /* only valid for UpdateLayeredWindowIndirect */
3352 SetLastError( ERROR_INVALID_PARAMETER
);
3355 info
.cbSize
= sizeof(info
);
3356 info
.hdcDst
= hdcDst
;
3357 info
.pptDst
= pptDst
;
3359 info
.hdcSrc
= hdcSrc
;
3360 info
.pptSrc
= pptSrc
;
3362 info
.pblend
= pblend
;
3363 info
.dwFlags
= flags
;
3364 info
.prcDirty
= NULL
;
3365 return UpdateLayeredWindowIndirect( hwnd
, &info
);
3369 /******************************************************************************
3370 * GetProcessDefaultLayout [USER32.@]
3372 * Gets the default layout for parentless windows.
3374 BOOL WINAPI
GetProcessDefaultLayout( DWORD
*layout
)
3378 SetLastError( ERROR_NOACCESS
);
3381 if (process_layout
== ~0u)
3383 WCHAR
*str
, buffer
[MAX_PATH
];
3384 DWORD i
, version_layout
= 0;
3386 DWORD user_lang
= GetUserDefaultLangID();
3390 GetModuleFileNameW( 0, buffer
, MAX_PATH
);
3391 if (!(len
= GetFileVersionInfoSizeW( buffer
, NULL
))) goto done
;
3392 if (!(data
= HeapAlloc( GetProcessHeap(), 0, len
))) goto done
;
3393 if (!GetFileVersionInfoW( buffer
, 0, len
, data
)) goto done
;
3394 if (!VerQueryValueW( data
, L
"\\VarFileInfo\\Translation", (void **)&languages
, &len
) || !len
) goto done
;
3396 len
/= sizeof(DWORD
);
3397 for (i
= 0; i
< len
; i
++) if (LOWORD(languages
[i
]) == user_lang
) break;
3398 if (i
== len
) /* try neutral language */
3399 for (i
= 0; i
< len
; i
++)
3400 if (LOWORD(languages
[i
]) == MAKELANGID( PRIMARYLANGID(user_lang
), SUBLANG_NEUTRAL
)) break;
3401 if (i
== len
) i
= 0; /* default to the first one */
3403 swprintf( buffer
, ARRAY_SIZE(buffer
), L
"\\StringFileInfo\\%04x%04x\\FileDescription",
3404 LOWORD(languages
[i
]), HIWORD(languages
[i
]) );
3405 if (!VerQueryValueW( data
, buffer
, (void **)&str
, &len
)) goto done
;
3406 TRACE( "found description %s\n", debugstr_w( str
));
3407 if (str
[0] == 0x200e && str
[1] == 0x200e) version_layout
= LAYOUT_RTL
;
3410 HeapFree( GetProcessHeap(), 0, data
);
3411 process_layout
= version_layout
;
3413 *layout
= process_layout
;
3418 /******************************************************************************
3419 * SetProcessDefaultLayout [USER32.@]
3421 * Sets the default layout for parentless windows.
3423 BOOL WINAPI
SetProcessDefaultLayout( DWORD layout
)
3425 process_layout
= layout
;
3430 /* 64bit versions */
3432 #ifdef GetWindowLongPtrW
3433 #undef GetWindowLongPtrW
3436 #ifdef GetWindowLongPtrA
3437 #undef GetWindowLongPtrA
3440 #ifdef SetWindowLongPtrW
3441 #undef SetWindowLongPtrW
3444 #ifdef SetWindowLongPtrA
3445 #undef SetWindowLongPtrA
3448 /*****************************************************************************
3449 * GetWindowLongPtrW (USER32.@)
3451 LONG_PTR WINAPI
GetWindowLongPtrW( HWND hwnd
, INT offset
)
3453 return NtUserCallHwndParam( hwnd
, offset
, NtUserGetWindowLongPtrW
);
3456 /*****************************************************************************
3457 * GetWindowLongPtrA (USER32.@)
3459 LONG_PTR WINAPI
GetWindowLongPtrA( HWND hwnd
, INT offset
)
3461 return NtUserCallHwndParam( hwnd
, offset
, NtUserGetWindowLongPtrA
);
3464 /*****************************************************************************
3465 * SetWindowLongPtrW (USER32.@)
3467 LONG_PTR WINAPI
SetWindowLongPtrW( HWND hwnd
, INT offset
, LONG_PTR newval
)
3469 return WIN_SetWindowLong( hwnd
, offset
, sizeof(LONG_PTR
), newval
, TRUE
);
3472 /*****************************************************************************
3473 * SetWindowLongPtrA (USER32.@)
3475 LONG_PTR WINAPI
SetWindowLongPtrA( HWND hwnd
, INT offset
, LONG_PTR newval
)
3477 return WIN_SetWindowLong( hwnd
, offset
, sizeof(LONG_PTR
), newval
, FALSE
);
3480 /*****************************************************************************
3481 * RegisterTouchWindow (USER32.@)
3483 BOOL WINAPI
RegisterTouchWindow(HWND hwnd
, ULONG flags
)
3485 FIXME("(%p %08x): stub\n", hwnd
, flags
);
3486 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3490 /*****************************************************************************
3491 * UnregisterTouchWindow (USER32.@)
3493 BOOL WINAPI
UnregisterTouchWindow(HWND hwnd
)
3495 FIXME("(%p): stub\n", hwnd
);
3496 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3500 /*****************************************************************************
3501 * CloseTouchInputHandle (USER32.@)
3503 BOOL WINAPI
CloseTouchInputHandle(HTOUCHINPUT handle
)
3505 FIXME("(%p): stub\n", handle
);
3506 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3510 /*****************************************************************************
3511 * GetTouchInputInfo (USER32.@)
3513 BOOL WINAPI
GetTouchInputInfo(HTOUCHINPUT handle
, UINT count
, TOUCHINPUT
*ptr
, int size
)
3515 FIXME("(%p %u %p %u): stub\n", handle
, count
, ptr
, size
);
3516 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3520 /*****************************************************************************
3521 * GetGestureInfo (USER32.@)
3523 BOOL WINAPI
GetGestureInfo(HGESTUREINFO handle
, PGESTUREINFO ptr
)
3525 FIXME("(%p %p): stub\n", handle
, ptr
);
3526 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3530 /*****************************************************************************
3531 * GetWindowDisplayAffinity (USER32.@)
3533 BOOL WINAPI
GetWindowDisplayAffinity(HWND hwnd
, DWORD
*affinity
)
3535 FIXME("(%p, %p): stub\n", hwnd
, affinity
);
3537 if (!hwnd
|| !affinity
)
3539 SetLastError(hwnd
? ERROR_NOACCESS
: ERROR_INVALID_WINDOW_HANDLE
);
3543 *affinity
= WDA_NONE
;
3547 /*****************************************************************************
3548 * SetWindowDisplayAffinity (USER32.@)
3550 BOOL WINAPI
SetWindowDisplayAffinity(HWND hwnd
, DWORD affinity
)
3552 FIXME("(%p, %u): stub\n", hwnd
, affinity
);
3556 SetLastError(ERROR_INVALID_WINDOW_HANDLE
);
3560 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3564 /**********************************************************************
3565 * SetWindowCompositionAttribute (USER32.@)
3567 BOOL WINAPI
SetWindowCompositionAttribute(HWND hwnd
, void *data
)
3569 FIXME("(%p, %p): stub\n", hwnd
, data
);
3570 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3574 /***********************************************************************
3575 * InternalGetWindowIcon (USER32.@)
3577 HICON WINAPI
InternalGetWindowIcon( HWND hwnd
, UINT type
)
3579 WND
*win
= WIN_GetPtr( hwnd
);
3582 TRACE( "hwnd %p, type %#x\n", hwnd
, type
);
3586 SetLastError( ERROR_INVALID_WINDOW_HANDLE
);
3589 if (win
== WND_OTHER_PROCESS
|| win
== WND_DESKTOP
)
3591 if (IsWindow( hwnd
)) FIXME( "not supported on other process window %p\n", hwnd
);
3599 if (!ret
) ret
= (HICON
)GetClassLongPtrW( hwnd
, GCLP_HICON
);
3604 ret
= win
->hIconSmall
? win
->hIconSmall
: win
->hIconSmall2
;
3605 if (!ret
) ret
= (HICON
)GetClassLongPtrW( hwnd
, GCLP_HICONSM
);
3606 if (!ret
) ret
= (HICON
)GetClassLongPtrW( hwnd
, GCLP_HICON
);
3610 SetLastError( ERROR_INVALID_PARAMETER
);
3611 WIN_ReleasePtr( win
);
3615 if (!ret
) ret
= LoadIconW( 0, (const WCHAR
*)IDI_APPLICATION
);
3617 WIN_ReleasePtr( win
);
3618 return CopyIcon( ret
);