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 /***********************************************************************
45 HANDLE
alloc_user_handle( struct user_object
*ptr
, unsigned int type
)
47 return UlongToHandle( NtUserCallTwoParam( (UINT_PTR
)ptr
, type
, NtUserAllocHandle
));
51 /***********************************************************************
54 void *get_user_handle_ptr( HANDLE handle
, unsigned int type
)
56 return (void *)NtUserCallTwoParam( HandleToUlong(handle
), type
, NtUserGetHandlePtr
);
60 /***********************************************************************
61 * release_user_handle_ptr
63 void release_user_handle_ptr( void *ptr
)
65 assert( ptr
&& ptr
!= OBJ_OTHER_PROCESS
);
70 /***********************************************************************
73 void *free_user_handle( HANDLE handle
, unsigned int type
)
75 return UlongToHandle( NtUserCallTwoParam( HandleToUlong(handle
), type
, NtUserFreeHandle
));
79 /***********************************************************************
80 * create_window_handle
82 * Create a window handle with the server.
84 static WND
*create_window_handle( HWND parent
, HWND owner
, UNICODE_STRING
*name
,
85 HINSTANCE instance
, BOOL unicode
,
86 DWORD style
, DWORD ex_style
)
89 HWND handle
= 0, full_parent
= 0, full_owner
= 0;
90 struct tagCLASS
*class = NULL
;
92 DPI_AWARENESS awareness
= GetAwarenessFromDpiAwarenessContext( GetThreadDpiAwarenessContext() );
95 SERVER_START_REQ( create_window
)
97 req
->parent
= wine_server_user_handle( parent
);
98 req
->owner
= wine_server_user_handle( owner
);
99 req
->instance
= wine_server_client_ptr( instance
);
100 req
->dpi
= GetDpiForSystem();
101 req
->awareness
= awareness
;
103 req
->ex_style
= ex_style
;
104 if (!(req
->atom
= get_int_atom_value( name
)) && name
->Length
)
105 wine_server_add_data( req
, name
->Buffer
, name
->Length
);
106 if (!wine_server_call_err( req
))
108 handle
= wine_server_ptr_handle( reply
->handle
);
109 full_parent
= wine_server_ptr_handle( reply
->parent
);
110 full_owner
= wine_server_ptr_handle( reply
->owner
);
111 extra_bytes
= reply
->extra
;
113 awareness
= reply
->awareness
;
114 class = wine_server_get_ptr( reply
->class_ptr
);
121 WARN( "error %d creating window\n", GetLastError() );
125 if (!(win
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
126 sizeof(WND
) + extra_bytes
- sizeof(win
->wExtra
) )))
128 SERVER_START_REQ( destroy_window
)
130 req
->handle
= wine_server_user_handle( handle
);
131 wine_server_call( req
);
134 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
138 if (!parent
) /* if parent is 0 we don't have a desktop window yet */
140 struct user_thread_info
*thread_info
= get_user_thread_info();
142 if (name
->Buffer
== (LPCWSTR
)DESKTOP_CLASS_ATOM
)
144 if (!thread_info
->top_window
) thread_info
->top_window
= full_parent
? full_parent
: handle
;
145 else assert( full_parent
== thread_info
->top_window
);
146 if (full_parent
&& !NtUserCallHwnd( thread_info
->top_window
, NtUserCreateDesktopWindow
))
147 ERR( "failed to create desktop window\n" );
148 register_builtin_classes();
150 else /* HWND_MESSAGE parent */
152 if (!thread_info
->msg_window
&& !full_parent
) thread_info
->msg_window
= handle
;
158 win
->obj
.handle
= handle
;
159 win
->obj
.type
= NTUSER_OBJ_WINDOW
;
160 win
->parent
= full_parent
;
161 win
->owner
= full_owner
;
163 win
->winproc
= get_class_winproc( class );
164 win
->cbWndExtra
= extra_bytes
;
166 win
->dpi_awareness
= awareness
;
167 NtUserCallTwoParam( HandleToUlong(handle
), (UINT_PTR
)win
, NtUserSetHandlePtr
);
168 if (WINPROC_IsUnicode( win
->winproc
, unicode
)) win
->flags
|= WIN_ISUNICODE
;
173 /***********************************************************************
176 * Free a window handle.
178 static void free_window_handle( HWND hwnd
)
180 struct user_object
*ptr
;
182 if ((ptr
= get_user_handle_ptr( hwnd
, NTUSER_OBJ_WINDOW
)) && ptr
!= OBJ_OTHER_PROCESS
)
184 SERVER_START_REQ( destroy_window
)
186 req
->handle
= wine_server_user_handle( hwnd
);
187 wine_server_call( req
);
188 NtUserCallTwoParam( HandleToUlong(hwnd
), 0, NtUserSetHandlePtr
);
192 HeapFree( GetProcessHeap(), 0, ptr
);
197 /*******************************************************************
198 * list_window_children
200 * Build an array of the children of a given window. The array must be
201 * freed with HeapFree. Returns NULL when no windows are found.
203 static HWND
*list_window_children( HDESK desktop
, HWND hwnd
, UNICODE_STRING
*class, DWORD tid
)
207 ATOM atom
= class ? get_int_atom_value( class ) : 0;
209 /* empty class is not the same as NULL class */
210 if (!atom
&& class && !class->Length
) return NULL
;
216 if (!(list
= HeapAlloc( GetProcessHeap(), 0, size
* sizeof(HWND
) ))) break;
218 SERVER_START_REQ( get_window_children
)
220 req
->desktop
= wine_server_obj_handle( desktop
);
221 req
->parent
= wine_server_user_handle( hwnd
);
224 if (!atom
&& class) wine_server_add_data( req
, class->Buffer
, class->Length
);
225 wine_server_set_reply( req
, list
, (size
-1) * sizeof(user_handle_t
) );
226 if (!wine_server_call( req
)) count
= reply
->count
;
229 if (count
&& count
< size
)
231 /* start from the end since HWND is potentially larger than user_handle_t */
232 for (i
= count
- 1; i
>= 0; i
--)
233 list
[i
] = wine_server_ptr_handle( ((user_handle_t
*)list
)[i
] );
237 HeapFree( GetProcessHeap(), 0, list
);
239 size
= count
+ 1; /* restart with a large enough buffer */
245 /*******************************************************************
248 static void send_parent_notify( HWND hwnd
, UINT msg
)
250 if ((GetWindowLongW( hwnd
, GWL_STYLE
) & (WS_CHILD
| WS_POPUP
)) == WS_CHILD
&&
251 !(GetWindowLongW( hwnd
, GWL_EXSTYLE
) & WS_EX_NOPARENTNOTIFY
))
253 HWND parent
= GetParent(hwnd
);
254 if (parent
&& parent
!= GetDesktopWindow())
255 SendMessageW( parent
, WM_PARENTNOTIFY
,
256 MAKEWPARAM( msg
, GetWindowLongPtrW( hwnd
, GWLP_ID
)), (LPARAM
)hwnd
);
261 /*******************************************************************
262 * get_hwnd_message_parent
264 * Return the parent for HWND_MESSAGE windows.
266 HWND
get_hwnd_message_parent(void)
268 struct user_thread_info
*thread_info
= get_user_thread_info();
270 if (!thread_info
->msg_window
) GetDesktopWindow(); /* trigger creation */
271 return thread_info
->msg_window
;
275 /*******************************************************************
278 * Check if window is the desktop or the HWND_MESSAGE top parent.
280 BOOL
is_desktop_window( HWND hwnd
)
282 struct user_thread_info
*thread_info
= get_user_thread_info();
284 if (!hwnd
) return FALSE
;
285 if (hwnd
== thread_info
->top_window
) return TRUE
;
286 if (hwnd
== thread_info
->msg_window
) return TRUE
;
288 if (!HIWORD(hwnd
) || HIWORD(hwnd
) == 0xffff)
290 if (LOWORD(thread_info
->top_window
) == LOWORD(hwnd
)) return TRUE
;
291 if (LOWORD(thread_info
->msg_window
) == LOWORD(hwnd
)) return TRUE
;
297 /*******************************************************************
298 * Off-screen window surface.
301 struct offscreen_window_surface
303 struct window_surface header
;
310 static const struct window_surface_funcs offscreen_window_surface_funcs
;
312 static inline void reset_bounds( RECT
*bounds
)
314 bounds
->left
= bounds
->top
= INT_MAX
;
315 bounds
->right
= bounds
->bottom
= INT_MIN
;
318 static struct offscreen_window_surface
*impl_from_window_surface( struct window_surface
*base
)
320 if (!base
|| base
->funcs
!= &offscreen_window_surface_funcs
) return NULL
;
321 return CONTAINING_RECORD( base
, struct offscreen_window_surface
, header
);
324 static void CDECL
offscreen_window_surface_lock( struct window_surface
*base
)
326 struct offscreen_window_surface
*impl
= impl_from_window_surface( base
);
327 EnterCriticalSection( &impl
->cs
);
330 static void CDECL
offscreen_window_surface_unlock( struct window_surface
*base
)
332 struct offscreen_window_surface
*impl
= impl_from_window_surface( base
);
333 LeaveCriticalSection( &impl
->cs
);
336 static RECT
*CDECL
offscreen_window_surface_get_bounds( struct window_surface
*base
)
338 struct offscreen_window_surface
*impl
= impl_from_window_surface( base
);
339 return &impl
->bounds
;
342 static void *CDECL
offscreen_window_surface_get_bitmap_info( struct window_surface
*base
, BITMAPINFO
*info
)
344 struct offscreen_window_surface
*impl
= impl_from_window_surface( base
);
345 memcpy( info
, &impl
->info
, offsetof( BITMAPINFO
, bmiColors
[0] ) );
349 static void CDECL
offscreen_window_surface_set_region( struct window_surface
*base
, HRGN region
)
353 static void CDECL
offscreen_window_surface_flush( struct window_surface
*base
)
355 struct offscreen_window_surface
*impl
= impl_from_window_surface( base
);
356 base
->funcs
->lock( base
);
357 reset_bounds( &impl
->bounds
);
358 base
->funcs
->unlock( base
);
361 static void CDECL
offscreen_window_surface_destroy( struct window_surface
*base
)
363 struct offscreen_window_surface
*impl
= impl_from_window_surface( base
);
364 impl
->cs
.DebugInfo
->Spare
[0] = 0;
365 DeleteCriticalSection( &impl
->cs
);
369 static const struct window_surface_funcs offscreen_window_surface_funcs
=
371 offscreen_window_surface_lock
,
372 offscreen_window_surface_unlock
,
373 offscreen_window_surface_get_bitmap_info
,
374 offscreen_window_surface_get_bounds
,
375 offscreen_window_surface_set_region
,
376 offscreen_window_surface_flush
,
377 offscreen_window_surface_destroy
380 void create_offscreen_window_surface( const RECT
*visible_rect
, struct window_surface
**surface
)
382 struct offscreen_window_surface
*impl
;
384 RECT surface_rect
= *visible_rect
;
386 TRACE( "visible_rect %s, surface %p.\n", wine_dbgstr_rect( visible_rect
), surface
);
388 OffsetRect( &surface_rect
, -surface_rect
.left
, -surface_rect
.top
);
389 surface_rect
.right
= (surface_rect
.right
+ 0x1f) & ~0x1f;
390 surface_rect
.bottom
= (surface_rect
.bottom
+ 0x1f) & ~0x1f;
392 /* check that old surface is an offscreen_window_surface, or release it */
393 if ((impl
= impl_from_window_surface( *surface
)))
395 /* if the rect didn't change, keep the same surface */
396 if (EqualRect( &surface_rect
, &impl
->header
.rect
)) return;
397 window_surface_release( &impl
->header
);
399 else if (*surface
) window_surface_release( *surface
);
401 /* create a new window surface */
403 size
= surface_rect
.right
* surface_rect
.bottom
* 4;
404 if (!(impl
= calloc(1, offsetof( struct offscreen_window_surface
, info
.bmiColors
[0] ) + size
))) return;
406 impl
->header
.funcs
= &offscreen_window_surface_funcs
;
407 impl
->header
.ref
= 1;
408 impl
->header
.rect
= surface_rect
;
410 InitializeCriticalSection( &impl
->cs
);
411 impl
->cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": surface");
412 reset_bounds( &impl
->bounds
);
414 impl
->bits
= (char *)&impl
->info
.bmiColors
[0];
415 impl
->info
.bmiHeader
.biSize
= sizeof( impl
->info
);
416 impl
->info
.bmiHeader
.biWidth
= surface_rect
.right
;
417 impl
->info
.bmiHeader
.biHeight
= surface_rect
.bottom
;
418 impl
->info
.bmiHeader
.biPlanes
= 1;
419 impl
->info
.bmiHeader
.biBitCount
= 32;
420 impl
->info
.bmiHeader
.biCompression
= BI_RGB
;
421 impl
->info
.bmiHeader
.biSizeImage
= size
;
423 TRACE( "created window surface %p\n", &impl
->header
);
425 *surface
= &impl
->header
;
428 /*******************************************************************
429 * register_window_surface
431 * Register a window surface in the global list, possibly replacing another one.
433 void register_window_surface( struct window_surface
*old
, struct window_surface
*new )
435 NtUserCallTwoParam( (UINT_PTR
)old
, (UINT_PTR
)new, NtUserRegisterWindowSurface
);
439 /*******************************************************************
440 * flush_window_surfaces
442 * Flush pending output from all window surfaces.
444 void flush_window_surfaces( BOOL idle
)
446 NtUserCallOneParam( idle
, NtUserFlushWindowSurfaces
);
450 /***********************************************************************
453 * Return a pointer to the WND structure if local to the process,
454 * or WND_OTHER_PROCESS if handle may be valid in other process.
455 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
457 WND
*WIN_GetPtr( HWND hwnd
)
461 if ((ptr
= get_user_handle_ptr( hwnd
, NTUSER_OBJ_WINDOW
)) == WND_OTHER_PROCESS
)
463 if (is_desktop_window( hwnd
)) ptr
= WND_DESKTOP
;
469 /***********************************************************************
470 * WIN_IsCurrentProcess
472 * Check whether a given window belongs to the current process (and return the full handle).
474 HWND
WIN_IsCurrentProcess( HWND hwnd
)
479 if (!(ptr
= WIN_GetPtr( hwnd
)) || ptr
== WND_OTHER_PROCESS
|| ptr
== WND_DESKTOP
) return 0;
480 ret
= ptr
->obj
.handle
;
481 WIN_ReleasePtr( ptr
);
486 /***********************************************************************
487 * WIN_IsCurrentThread
489 * Check whether a given window belongs to the current thread (and return the full handle).
491 HWND
WIN_IsCurrentThread( HWND hwnd
)
496 if (!(ptr
= WIN_GetPtr( hwnd
)) || ptr
== WND_OTHER_PROCESS
|| ptr
== WND_DESKTOP
) return 0;
497 if (ptr
->tid
== GetCurrentThreadId()) ret
= ptr
->obj
.handle
;
498 WIN_ReleasePtr( ptr
);
503 /***********************************************************************
506 * Set the flags of a window and return the previous value.
508 UINT
win_set_flags( HWND hwnd
, UINT set_mask
, UINT clear_mask
)
511 WND
*ptr
= WIN_GetPtr( hwnd
);
513 if (!ptr
|| ptr
== WND_OTHER_PROCESS
|| ptr
== WND_DESKTOP
) return 0;
515 ptr
->flags
= (ret
& ~clear_mask
) | set_mask
;
516 WIN_ReleasePtr( ptr
);
521 /***********************************************************************
524 * Convert a possibly truncated window handle to a full 32-bit handle.
526 HWND
WIN_GetFullHandle( HWND hwnd
)
530 if (!hwnd
|| (ULONG_PTR
)hwnd
>> 16) return hwnd
;
531 if (LOWORD(hwnd
) <= 1 || LOWORD(hwnd
) == 0xffff) return hwnd
;
532 /* do sign extension for -2 and -3 */
533 if (LOWORD(hwnd
) >= (WORD
)-3) return (HWND
)(LONG_PTR
)(INT16
)LOWORD(hwnd
);
535 if (!(ptr
= WIN_GetPtr( hwnd
))) return hwnd
;
537 if (ptr
== WND_DESKTOP
)
539 if (LOWORD(hwnd
) == LOWORD(GetDesktopWindow())) return GetDesktopWindow();
540 else return get_hwnd_message_parent();
543 if (ptr
!= WND_OTHER_PROCESS
)
545 hwnd
= ptr
->obj
.handle
;
546 WIN_ReleasePtr( ptr
);
548 else /* may belong to another process */
550 SERVER_START_REQ( get_window_info
)
552 req
->handle
= wine_server_user_handle( hwnd
);
553 if (!wine_server_call_err( req
)) hwnd
= wine_server_ptr_handle( reply
->full_handle
);
561 /***********************************************************************
564 * Change the owner of a window.
566 static HWND
WIN_SetOwner( HWND hwnd
, HWND owner
)
568 WND
*win
= WIN_GetPtr( hwnd
);
571 if (!win
|| win
== WND_DESKTOP
) return 0;
572 if (win
== WND_OTHER_PROCESS
)
574 if (IsWindow(hwnd
)) ERR( "cannot set owner %p on other process window %p\n", owner
, hwnd
);
577 SERVER_START_REQ( set_window_owner
)
579 req
->handle
= wine_server_user_handle( hwnd
);
580 req
->owner
= wine_server_user_handle( owner
);
581 if (!wine_server_call( req
))
583 win
->owner
= wine_server_ptr_handle( reply
->full_owner
);
584 ret
= wine_server_ptr_handle( reply
->prev_owner
);
588 WIN_ReleasePtr( win
);
593 /***********************************************************************
596 * Change the style of a window.
598 ULONG
WIN_SetStyle( HWND hwnd
, ULONG set_bits
, ULONG clear_bits
)
600 /* FIXME: Use SetWindowLong or move callers to win32u instead.
601 * We use STYLESTRUCT to pass params, but meaning of its field does not match our usage. */
602 STYLESTRUCT style
= { .styleNew
= set_bits
, .styleOld
= clear_bits
};
603 return NtUserCallHwndParam( hwnd
, (UINT_PTR
)&style
, NtUserSetWindowStyle
);
607 /***********************************************************************
610 * Get the window and client rectangles.
612 BOOL
WIN_GetRectangles( HWND hwnd
, enum coords_relative relative
, RECT
*rectWindow
, RECT
*rectClient
)
614 WND
*win
= WIN_GetPtr( hwnd
);
619 SetLastError( ERROR_INVALID_WINDOW_HANDLE
);
622 if (win
== WND_DESKTOP
)
625 rect
.left
= rect
.top
= 0;
626 if (hwnd
== get_hwnd_message_parent())
630 rect
= rect_win_to_thread_dpi( hwnd
, rect
);
634 rect
= get_primary_monitor_rect();
636 if (rectWindow
) *rectWindow
= rect
;
637 if (rectClient
) *rectClient
= rect
;
640 if (win
!= WND_OTHER_PROCESS
)
642 RECT window_rect
= win
->window_rect
, client_rect
= win
->client_rect
;
647 OffsetRect( &window_rect
, -win
->client_rect
.left
, -win
->client_rect
.top
);
648 OffsetRect( &client_rect
, -win
->client_rect
.left
, -win
->client_rect
.top
);
649 if (win
->dwExStyle
& WS_EX_LAYOUTRTL
)
650 mirror_rect( &win
->client_rect
, &window_rect
);
653 OffsetRect( &window_rect
, -win
->window_rect
.left
, -win
->window_rect
.top
);
654 OffsetRect( &client_rect
, -win
->window_rect
.left
, -win
->window_rect
.top
);
655 if (win
->dwExStyle
& WS_EX_LAYOUTRTL
)
656 mirror_rect( &win
->window_rect
, &client_rect
);
661 WND
*parent
= WIN_GetPtr( win
->parent
);
662 if (parent
== WND_DESKTOP
) break;
663 if (!parent
|| parent
== WND_OTHER_PROCESS
)
665 WIN_ReleasePtr( win
);
668 if (parent
->flags
& WIN_CHILDREN_MOVED
)
670 WIN_ReleasePtr( parent
);
671 WIN_ReleasePtr( win
);
674 if (parent
->dwExStyle
& WS_EX_LAYOUTRTL
)
676 mirror_rect( &parent
->client_rect
, &window_rect
);
677 mirror_rect( &parent
->client_rect
, &client_rect
);
679 WIN_ReleasePtr( parent
);
685 WND
*parent
= WIN_GetPtr( win
->parent
);
686 if (parent
== WND_DESKTOP
) break;
687 if (!parent
|| parent
== WND_OTHER_PROCESS
)
689 WIN_ReleasePtr( win
);
692 WIN_ReleasePtr( win
);
693 if (parent
->flags
& WIN_CHILDREN_MOVED
)
695 WIN_ReleasePtr( parent
);
701 OffsetRect( &window_rect
, win
->client_rect
.left
, win
->client_rect
.top
);
702 OffsetRect( &client_rect
, win
->client_rect
.left
, win
->client_rect
.top
);
707 if (rectWindow
) *rectWindow
= rect_win_to_thread_dpi( hwnd
, window_rect
);
708 if (rectClient
) *rectClient
= rect_win_to_thread_dpi( hwnd
, client_rect
);
709 WIN_ReleasePtr( win
);
714 SERVER_START_REQ( get_window_rectangles
)
716 req
->handle
= wine_server_user_handle( hwnd
);
717 req
->relative
= relative
;
718 req
->dpi
= get_thread_dpi();
719 if ((ret
= !wine_server_call_err( req
)))
723 rectWindow
->left
= reply
->window
.left
;
724 rectWindow
->top
= reply
->window
.top
;
725 rectWindow
->right
= reply
->window
.right
;
726 rectWindow
->bottom
= reply
->window
.bottom
;
730 rectClient
->left
= reply
->client
.left
;
731 rectClient
->top
= reply
->client
.top
;
732 rectClient
->right
= reply
->client
.right
;
733 rectClient
->bottom
= reply
->client
.bottom
;
742 /***********************************************************************
745 * Destroy storage associated to a window. "Internals" p.358
747 LRESULT
WIN_DestroyWindow( HWND hwnd
)
751 HMENU menu
= 0, sys_menu
;
752 struct window_surface
*surface
;
754 TRACE("%p\n", hwnd
);
756 /* destroy default IME window */
757 if (win_set_flags( hwnd
, 0, WIN_HAS_IME_WIN
) & WIN_HAS_IME_WIN
)
759 TRACE("unregister IME window for %p\n", hwnd
);
760 imm_unregister_window( hwnd
);
763 /* free child windows */
764 if ((list
= WIN_ListChildren( hwnd
)))
767 for (i
= 0; list
[i
]; i
++)
769 if (WIN_IsCurrentThread( list
[i
] )) WIN_DestroyWindow( list
[i
] );
770 else SendNotifyMessageW( list
[i
], WM_WINE_DESTROYWINDOW
, 0, 0 );
772 HeapFree( GetProcessHeap(), 0, list
);
775 /* Unlink now so we won't bother with the children later on */
776 SERVER_START_REQ( set_parent
)
778 req
->handle
= wine_server_user_handle( hwnd
);
780 wine_server_call( req
);
785 * Send the WM_NCDESTROY to the window being destroyed.
787 SendMessageW( hwnd
, WM_NCDESTROY
, 0, 0 );
789 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
791 /* free resources associated with the window */
793 if (!(wndPtr
= WIN_GetPtr( hwnd
)) || wndPtr
== WND_OTHER_PROCESS
) return 0;
794 if ((wndPtr
->dwStyle
& (WS_CHILD
| WS_POPUP
)) != WS_CHILD
)
795 menu
= (HMENU
)wndPtr
->wIDmenu
;
796 sys_menu
= wndPtr
->hSysMenu
;
797 free_dce( wndPtr
->dce
, hwnd
);
799 HeapFree( GetProcessHeap(), 0, wndPtr
->text
);
801 HeapFree( GetProcessHeap(), 0, wndPtr
->pScroll
);
802 wndPtr
->pScroll
= NULL
;
803 DestroyIcon( wndPtr
->hIconSmall2
);
804 surface
= wndPtr
->surface
;
805 wndPtr
->surface
= NULL
;
806 WIN_ReleasePtr( wndPtr
);
808 if (menu
) DestroyMenu( menu
);
809 if (sys_menu
) DestroyMenu( sys_menu
);
812 register_window_surface( surface
, NULL
);
813 window_surface_release( surface
);
816 USER_Driver
->pDestroyWindow( hwnd
);
818 free_window_handle( hwnd
);
823 /***********************************************************************
826 static WND
*next_thread_window( HWND
*hwnd
)
828 return (WND
*)NtUserCallOneParam( (UINT_PTR
)hwnd
, NtUserNextThreadWindow
);
832 /***********************************************************************
833 * destroy_thread_windows
835 * Destroy all window owned by the current thread.
837 void destroy_thread_windows(void)
839 WND
*win
, *free_list
= NULL
, **free_list_ptr
= &free_list
;
843 while ((win
= next_thread_window( &hwnd
)))
845 free_dce( win
->dce
, win
->obj
.handle
);
846 NtUserCallTwoParam( HandleToUlong(hwnd
), 0, NtUserSetHandlePtr
);
847 win
->obj
.handle
= *free_list_ptr
;
848 free_list_ptr
= (WND
**)&win
->obj
.handle
;
852 SERVER_START_REQ( destroy_window
)
854 req
->handle
= 0; /* destroy all thread windows */
855 wine_server_call( req
);
861 while ((win
= free_list
))
863 free_list
= win
->obj
.handle
;
864 TRACE( "destroying %p\n", win
);
866 if ((win
->dwStyle
& (WS_CHILD
| WS_POPUP
)) != WS_CHILD
&& win
->wIDmenu
)
867 DestroyMenu( UlongToHandle(win
->wIDmenu
) );
868 if (win
->hSysMenu
) DestroyMenu( win
->hSysMenu
);
871 register_window_surface( win
->surface
, NULL
);
872 window_surface_release( win
->surface
);
874 HeapFree( GetProcessHeap(), 0, win
);
879 /***********************************************************************
882 * Fix the coordinates - Helper for WIN_CreateWindowEx.
883 * returns default show mode in sw.
885 static void WIN_FixCoordinates( CREATESTRUCTW
*cs
, INT
*sw
)
887 #define IS_DEFAULT(x) ((x) == CW_USEDEFAULT || (x) == (SHORT)0x8000)
890 if (cs
->dwExStyle
& WS_EX_MDICHILD
)
894 MDI_CalcDefaultChildPos(cs
->hwndParent
, -1, pos
, 0, &id
);
895 if (!(cs
->style
& WS_POPUP
)) cs
->hMenu
= ULongToHandle(id
);
897 TRACE("MDI child id %04x\n", id
);
900 if (cs
->style
& (WS_CHILD
| WS_POPUP
))
902 if (cs
->dwExStyle
& WS_EX_MDICHILD
)
904 if (IS_DEFAULT(cs
->x
))
909 if (IS_DEFAULT(cs
->cx
) || !cs
->cx
) cs
->cx
= pos
[1].x
;
910 if (IS_DEFAULT(cs
->cy
) || !cs
->cy
) cs
->cy
= pos
[1].y
;
914 if (IS_DEFAULT(cs
->x
)) cs
->x
= cs
->y
= 0;
915 if (IS_DEFAULT(cs
->cx
)) cs
->cx
= cs
->cy
= 0;
918 else /* overlapped window */
921 MONITORINFO mon_info
;
924 if (!IS_DEFAULT(cs
->x
) && !IS_DEFAULT(cs
->cx
) && !IS_DEFAULT(cs
->cy
)) return;
926 monitor
= MonitorFromWindow( cs
->hwndParent
, MONITOR_DEFAULTTOPRIMARY
);
927 mon_info
.cbSize
= sizeof(mon_info
);
928 GetMonitorInfoW( monitor
, &mon_info
);
929 GetStartupInfoW( &info
);
931 if (IS_DEFAULT(cs
->x
))
933 if (!IS_DEFAULT(cs
->y
)) *sw
= cs
->y
;
934 cs
->x
= (info
.dwFlags
& STARTF_USEPOSITION
) ? info
.dwX
: mon_info
.rcWork
.left
;
935 cs
->y
= (info
.dwFlags
& STARTF_USEPOSITION
) ? info
.dwY
: mon_info
.rcWork
.top
;
938 if (IS_DEFAULT(cs
->cx
))
940 if (info
.dwFlags
& STARTF_USESIZE
)
942 cs
->cx
= info
.dwXSize
;
943 cs
->cy
= info
.dwYSize
;
947 cs
->cx
= (mon_info
.rcWork
.right
- mon_info
.rcWork
.left
) * 3 / 4 - cs
->x
;
948 cs
->cy
= (mon_info
.rcWork
.bottom
- mon_info
.rcWork
.top
) * 3 / 4 - cs
->y
;
951 /* neither x nor cx are default. Check the y values .
952 * In the trace we see Outlook and Outlook Express using
953 * cy set to CW_USEDEFAULT when opening the address book.
955 else if (IS_DEFAULT(cs
->cy
))
957 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
958 cs
->cy
= (mon_info
.rcWork
.bottom
- mon_info
.rcWork
.top
) * 3 / 4 - cs
->y
;
964 /***********************************************************************
967 static void dump_window_styles( DWORD style
, DWORD exstyle
)
970 if(style
& WS_POPUP
) TRACE(" WS_POPUP");
971 if(style
& WS_CHILD
) TRACE(" WS_CHILD");
972 if(style
& WS_MINIMIZE
) TRACE(" WS_MINIMIZE");
973 if(style
& WS_VISIBLE
) TRACE(" WS_VISIBLE");
974 if(style
& WS_DISABLED
) TRACE(" WS_DISABLED");
975 if(style
& WS_CLIPSIBLINGS
) TRACE(" WS_CLIPSIBLINGS");
976 if(style
& WS_CLIPCHILDREN
) TRACE(" WS_CLIPCHILDREN");
977 if(style
& WS_MAXIMIZE
) TRACE(" WS_MAXIMIZE");
978 if((style
& WS_CAPTION
) == WS_CAPTION
) TRACE(" WS_CAPTION");
981 if(style
& WS_BORDER
) TRACE(" WS_BORDER");
982 if(style
& WS_DLGFRAME
) TRACE(" WS_DLGFRAME");
984 if(style
& WS_VSCROLL
) TRACE(" WS_VSCROLL");
985 if(style
& WS_HSCROLL
) TRACE(" WS_HSCROLL");
986 if(style
& WS_SYSMENU
) TRACE(" WS_SYSMENU");
987 if(style
& WS_THICKFRAME
) TRACE(" WS_THICKFRAME");
988 if (style
& WS_CHILD
)
990 if(style
& WS_GROUP
) TRACE(" WS_GROUP");
991 if(style
& WS_TABSTOP
) TRACE(" WS_TABSTOP");
995 if(style
& WS_MINIMIZEBOX
) TRACE(" WS_MINIMIZEBOX");
996 if(style
& WS_MAXIMIZEBOX
) TRACE(" WS_MAXIMIZEBOX");
999 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
1000 #define DUMPED_STYLES \
1001 ((DWORD)(WS_POPUP | \
1020 if(style
& ~DUMPED_STYLES
) TRACE(" %08x", style
& ~DUMPED_STYLES
);
1022 #undef DUMPED_STYLES
1024 TRACE( "exstyle:" );
1025 if(exstyle
& WS_EX_DLGMODALFRAME
) TRACE(" WS_EX_DLGMODALFRAME");
1026 if(exstyle
& WS_EX_DRAGDETECT
) TRACE(" WS_EX_DRAGDETECT");
1027 if(exstyle
& WS_EX_NOPARENTNOTIFY
) TRACE(" WS_EX_NOPARENTNOTIFY");
1028 if(exstyle
& WS_EX_TOPMOST
) TRACE(" WS_EX_TOPMOST");
1029 if(exstyle
& WS_EX_ACCEPTFILES
) TRACE(" WS_EX_ACCEPTFILES");
1030 if(exstyle
& WS_EX_TRANSPARENT
) TRACE(" WS_EX_TRANSPARENT");
1031 if(exstyle
& WS_EX_MDICHILD
) TRACE(" WS_EX_MDICHILD");
1032 if(exstyle
& WS_EX_TOOLWINDOW
) TRACE(" WS_EX_TOOLWINDOW");
1033 if(exstyle
& WS_EX_WINDOWEDGE
) TRACE(" WS_EX_WINDOWEDGE");
1034 if(exstyle
& WS_EX_CLIENTEDGE
) TRACE(" WS_EX_CLIENTEDGE");
1035 if(exstyle
& WS_EX_CONTEXTHELP
) TRACE(" WS_EX_CONTEXTHELP");
1036 if(exstyle
& WS_EX_RIGHT
) TRACE(" WS_EX_RIGHT");
1037 if(exstyle
& WS_EX_RTLREADING
) TRACE(" WS_EX_RTLREADING");
1038 if(exstyle
& WS_EX_LEFTSCROLLBAR
) TRACE(" WS_EX_LEFTSCROLLBAR");
1039 if(exstyle
& WS_EX_CONTROLPARENT
) TRACE(" WS_EX_CONTROLPARENT");
1040 if(exstyle
& WS_EX_STATICEDGE
) TRACE(" WS_EX_STATICEDGE");
1041 if(exstyle
& WS_EX_APPWINDOW
) TRACE(" WS_EX_APPWINDOW");
1042 if(exstyle
& WS_EX_LAYERED
) TRACE(" WS_EX_LAYERED");
1043 if(exstyle
& WS_EX_NOINHERITLAYOUT
) TRACE(" WS_EX_NOINHERITLAYOUT");
1044 if(exstyle
& WS_EX_LAYOUTRTL
) TRACE(" WS_EX_LAYOUTRTL");
1045 if(exstyle
& WS_EX_COMPOSITED
) TRACE(" WS_EX_COMPOSITED");
1046 if(exstyle
& WS_EX_NOACTIVATE
) TRACE(" WS_EX_NOACTIVATE");
1048 #define DUMPED_EX_STYLES \
1049 ((DWORD)(WS_EX_DLGMODALFRAME | \
1050 WS_EX_DRAGDETECT | \
1051 WS_EX_NOPARENTNOTIFY | \
1053 WS_EX_ACCEPTFILES | \
1054 WS_EX_TRANSPARENT | \
1056 WS_EX_TOOLWINDOW | \
1057 WS_EX_WINDOWEDGE | \
1058 WS_EX_CLIENTEDGE | \
1059 WS_EX_CONTEXTHELP | \
1061 WS_EX_RTLREADING | \
1062 WS_EX_LEFTSCROLLBAR | \
1063 WS_EX_CONTROLPARENT | \
1064 WS_EX_STATICEDGE | \
1067 WS_EX_NOINHERITLAYOUT | \
1072 if(exstyle
& ~DUMPED_EX_STYLES
) TRACE(" %08x", exstyle
& ~DUMPED_EX_STYLES
);
1074 #undef DUMPED_EX_STYLES
1077 /***********************************************************************
1078 * map_dpi_create_struct
1080 static void map_dpi_create_struct( CREATESTRUCTW
*cs
, UINT dpi_from
, UINT dpi_to
)
1082 if (!dpi_from
&& !dpi_to
) return;
1083 if (!dpi_from
|| !dpi_to
)
1085 POINT pt
= { cs
->x
, cs
->y
};
1086 UINT mon_dpi
= get_monitor_dpi( MonitorFromPoint( pt
, MONITOR_DEFAULTTONEAREST
));
1087 if (!dpi_from
) dpi_from
= mon_dpi
;
1088 else dpi_to
= mon_dpi
;
1090 if (dpi_from
== dpi_to
) return;
1091 cs
->x
= MulDiv( cs
->x
, dpi_to
, dpi_from
);
1092 cs
->y
= MulDiv( cs
->y
, dpi_to
, dpi_from
);
1093 cs
->cx
= MulDiv( cs
->cx
, dpi_to
, dpi_from
);
1094 cs
->cy
= MulDiv( cs
->cy
, dpi_to
, dpi_from
);
1097 /***********************************************************************
1100 static DWORD
fix_exstyle( DWORD style
, DWORD exstyle
)
1102 if ((exstyle
& WS_EX_DLGMODALFRAME
) ||
1103 (!(exstyle
& WS_EX_STATICEDGE
) &&
1104 (style
& (WS_DLGFRAME
| WS_THICKFRAME
))))
1105 exstyle
|= WS_EX_WINDOWEDGE
;
1107 exstyle
&= ~WS_EX_WINDOWEDGE
;
1111 /***********************************************************************
1112 * WIN_CreateWindowEx
1114 * Implementation of CreateWindowEx().
1116 HWND
WIN_CreateWindowEx( CREATESTRUCTW
*cs
, LPCWSTR className
, HINSTANCE module
, BOOL unicode
)
1118 INT cx
, cy
, style
, ex_style
, sw
= SW_SHOW
;
1122 HWND hwnd
, parent
, owner
, top_child
= 0;
1123 UINT win_dpi
, thread_dpi
= get_thread_dpi();
1124 DPI_AWARENESS_CONTEXT context
;
1125 MDICREATESTRUCTW mdi_cs
;
1126 UNICODE_STRING
class;
1127 CBT_CREATEWNDW cbtc
;
1130 if (!get_class_info( module
, className
, NULL
, &class, FALSE
)) return FALSE
;
1132 TRACE("%s %s%s%s ex=%08x style=%08x %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
1133 unicode
? debugstr_w(cs
->lpszName
) : debugstr_a((LPCSTR
)cs
->lpszName
),
1134 debugstr_w(className
), class.Buffer
!= className
? "->" : "",
1135 class.Buffer
!= className
? debugstr_wn(class.Buffer
, class.Length
/ sizeof(WCHAR
)) : "",
1136 cs
->dwExStyle
, cs
->style
, cs
->x
, cs
->y
, cs
->cx
, cs
->cy
,
1137 cs
->hwndParent
, cs
->hMenu
, cs
->hInstance
, cs
->lpCreateParams
);
1138 if(TRACE_ON(win
)) dump_window_styles( cs
->style
, cs
->dwExStyle
);
1140 /* Fix the styles for MDI children */
1141 if (cs
->dwExStyle
& WS_EX_MDICHILD
)
1143 if (!(win_get_flags( cs
->hwndParent
) & WIN_ISMDICLIENT
))
1145 WARN("WS_EX_MDICHILD, but parent %p is not MDIClient\n", cs
->hwndParent
);
1149 /* cs->lpCreateParams of WM_[NC]CREATE is different for MDI children.
1150 * MDICREATESTRUCT members have the originally passed values.
1152 * Note: we rely on the fact that MDICREATESTRUCTA and MDICREATESTRUCTW
1153 * have the same layout.
1155 mdi_cs
.szClass
= cs
->lpszClass
;
1156 mdi_cs
.szTitle
= cs
->lpszName
;
1157 mdi_cs
.hOwner
= cs
->hInstance
;
1162 mdi_cs
.style
= cs
->style
;
1163 mdi_cs
.lParam
= (LPARAM
)cs
->lpCreateParams
;
1165 cs
->lpCreateParams
= &mdi_cs
;
1167 if (GetWindowLongW(cs
->hwndParent
, GWL_STYLE
) & MDIS_ALLCHILDSTYLES
)
1169 if (cs
->style
& WS_POPUP
)
1171 TRACE("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n");
1174 cs
->style
|= WS_CHILD
| WS_CLIPSIBLINGS
;
1178 cs
->style
&= ~WS_POPUP
;
1179 cs
->style
|= WS_CHILD
| WS_VISIBLE
| WS_CLIPSIBLINGS
| WS_CAPTION
|
1180 WS_SYSMENU
| WS_THICKFRAME
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
;
1183 top_child
= GetWindow(cs
->hwndParent
, GW_CHILD
);
1187 /* Restore current maximized child */
1188 if((cs
->style
& WS_VISIBLE
) && IsZoomed(top_child
))
1190 TRACE("Restoring current maximized child %p\n", top_child
);
1191 if (cs
->style
& WS_MAXIMIZE
)
1193 /* if the new window is maximized don't bother repainting */
1194 SendMessageW( top_child
, WM_SETREDRAW
, FALSE
, 0 );
1195 ShowWindow( top_child
, SW_SHOWNORMAL
);
1196 SendMessageW( top_child
, WM_SETREDRAW
, TRUE
, 0 );
1198 else ShowWindow( top_child
, SW_SHOWNORMAL
);
1203 /* Find the parent window */
1205 parent
= cs
->hwndParent
;
1208 if (cs
->hwndParent
== HWND_MESSAGE
)
1210 cs
->hwndParent
= parent
= get_hwnd_message_parent();
1212 else if (cs
->hwndParent
)
1214 if ((cs
->style
& (WS_CHILD
|WS_POPUP
)) != WS_CHILD
)
1216 parent
= GetDesktopWindow();
1217 owner
= cs
->hwndParent
;
1221 DWORD parent_style
= GetWindowLongW( parent
, GWL_EXSTYLE
);
1222 if ((parent_style
& WS_EX_LAYOUTRTL
) && !(parent_style
& WS_EX_NOINHERITLAYOUT
))
1223 cs
->dwExStyle
|= WS_EX_LAYOUTRTL
;
1228 if ((cs
->style
& (WS_CHILD
|WS_POPUP
)) == WS_CHILD
)
1230 WARN("No parent for child window\n" );
1231 SetLastError(ERROR_TLW_WITH_WSCHILD
);
1232 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1235 /* are we creating the desktop or HWND_MESSAGE parent itself? */
1236 if (className
!= (LPCWSTR
)DESKTOP_CLASS_ATOM
&&
1237 (IS_INTRESOURCE(className
) || wcsicmp( className
, L
"Message" )))
1240 GetProcessDefaultLayout( &layout
);
1241 if (layout
& LAYOUT_RTL
) cs
->dwExStyle
|= WS_EX_LAYOUTRTL
;
1242 parent
= GetDesktopWindow();
1246 WIN_FixCoordinates(cs
, &sw
); /* fix default coordinates */
1247 cs
->dwExStyle
= fix_exstyle(cs
->style
, cs
->dwExStyle
);
1249 /* Create the window structure */
1251 style
= cs
->style
& ~WS_VISIBLE
;
1252 ex_style
= cs
->dwExStyle
& ~WS_EX_LAYERED
;
1253 if (!(wndPtr
= create_window_handle( parent
, owner
, &class, module
,
1254 unicode
, style
, ex_style
)))
1256 hwnd
= wndPtr
->obj
.handle
;
1258 /* Fill the window structure */
1260 wndPtr
->tid
= GetCurrentThreadId();
1261 wndPtr
->hInstance
= cs
->hInstance
;
1262 wndPtr
->text
= NULL
;
1263 wndPtr
->dwStyle
= style
;
1264 wndPtr
->dwExStyle
= ex_style
;
1265 wndPtr
->wIDmenu
= 0;
1266 wndPtr
->helpContext
= 0;
1267 wndPtr
->pScroll
= NULL
;
1268 wndPtr
->userdata
= 0;
1270 wndPtr
->hIconSmall
= 0;
1271 wndPtr
->hIconSmall2
= 0;
1272 wndPtr
->hSysMenu
= 0;
1274 wndPtr
->min_pos
.x
= wndPtr
->min_pos
.y
= -1;
1275 wndPtr
->max_pos
.x
= wndPtr
->max_pos
.y
= -1;
1276 SetRect( &wndPtr
->normal_rect
, cs
->x
, cs
->y
, cs
->x
+ cs
->cx
, cs
->y
+ cs
->cy
);
1278 if (wndPtr
->dwStyle
& WS_SYSMENU
) SetSystemMenu( hwnd
, 0 );
1280 /* call the WH_CBT hook */
1282 WIN_ReleasePtr( wndPtr
);
1285 cbtc
.hwndInsertAfter
= HWND_TOP
;
1286 if (HOOK_CallHooks( WH_CBT
, HCBT_CREATEWND
, (WPARAM
)hwnd
, (LPARAM
)&cbtc
, unicode
) ||
1287 !(wndPtr
= WIN_GetPtr( hwnd
)))
1289 free_window_handle( hwnd
);
1294 * Correct the window styles.
1296 * It affects only the style loaded into the WIN structure.
1299 if ((wndPtr
->dwStyle
& (WS_CHILD
| WS_POPUP
)) != WS_CHILD
)
1301 wndPtr
->dwStyle
|= WS_CLIPSIBLINGS
;
1302 if (!(wndPtr
->dwStyle
& WS_POPUP
))
1303 wndPtr
->dwStyle
|= WS_CAPTION
;
1306 wndPtr
->dwExStyle
= cs
->dwExStyle
;
1307 /* WS_EX_WINDOWEDGE depends on some other styles */
1308 if ((wndPtr
->dwStyle
& (WS_DLGFRAME
| WS_THICKFRAME
)) &&
1309 !(wndPtr
->dwStyle
& (WS_CHILD
| WS_POPUP
)))
1310 wndPtr
->dwExStyle
|= WS_EX_WINDOWEDGE
;
1312 if (!(wndPtr
->dwStyle
& (WS_CHILD
| WS_POPUP
)))
1313 wndPtr
->flags
|= WIN_NEED_SIZE
;
1315 SERVER_START_REQ( set_window_info
)
1317 req
->handle
= wine_server_user_handle( hwnd
);
1318 req
->flags
= SET_WIN_STYLE
| SET_WIN_EXSTYLE
| SET_WIN_INSTANCE
| SET_WIN_UNICODE
;
1319 req
->style
= wndPtr
->dwStyle
;
1320 req
->ex_style
= wndPtr
->dwExStyle
;
1321 req
->instance
= wine_server_client_ptr( wndPtr
->hInstance
);
1322 req
->is_unicode
= (wndPtr
->flags
& WIN_ISUNICODE
) != 0;
1323 req
->extra_offset
= -1;
1324 wine_server_call( req
);
1328 /* Set the window menu */
1330 if ((wndPtr
->dwStyle
& (WS_CHILD
| WS_POPUP
)) != WS_CHILD
)
1334 if (!MENU_SetMenu(hwnd
, cs
->hMenu
))
1336 WIN_ReleasePtr( wndPtr
);
1337 free_window_handle( hwnd
);
1343 LPCWSTR menuName
= (LPCWSTR
)GetClassLongPtrW( hwnd
, GCLP_MENUNAME
);
1346 cs
->hMenu
= LoadMenuW( cs
->hInstance
, menuName
);
1347 if (cs
->hMenu
) MENU_SetMenu( hwnd
, cs
->hMenu
);
1351 else SetWindowLongPtrW( hwnd
, GWLP_ID
, (ULONG_PTR
)cs
->hMenu
);
1353 win_dpi
= wndPtr
->dpi
;
1354 WIN_ReleasePtr( wndPtr
);
1356 if (parent
) map_dpi_create_struct( cs
, thread_dpi
, win_dpi
);
1358 context
= SetThreadDpiAwarenessContext( GetWindowDpiAwarenessContext( hwnd
));
1360 /* send the WM_GETMINMAXINFO message and fix the size if needed */
1364 if ((cs
->style
& WS_THICKFRAME
) || !(cs
->style
& (WS_POPUP
| WS_CHILD
)))
1366 MINMAXINFO info
= WINPOS_GetMinMaxInfo( hwnd
);
1367 cx
= max( min( cx
, info
.ptMaxTrackSize
.x
), info
.ptMinTrackSize
.x
);
1368 cy
= max( min( cy
, info
.ptMaxTrackSize
.y
), info
.ptMinTrackSize
.y
);
1373 SetRect( &rect
, cs
->x
, cs
->y
, cs
->x
+ cx
, cs
->y
+ cy
);
1374 /* check for wraparound */
1375 if (cs
->x
> 0x7fffffff - cx
) rect
.right
= 0x7fffffff;
1376 if (cs
->y
> 0x7fffffff - cy
) rect
.bottom
= 0x7fffffff;
1377 if (!set_window_pos( hwnd
, 0, SWP_NOZORDER
| SWP_NOACTIVATE
, &rect
, &rect
, NULL
)) goto failed
;
1379 /* send WM_NCCREATE */
1381 TRACE( "hwnd %p cs %d,%d %dx%d %s\n", hwnd
, cs
->x
, cs
->y
, cs
->cx
, cs
->cy
, wine_dbgstr_rect(&rect
) );
1383 result
= SendMessageW( hwnd
, WM_NCCREATE
, 0, (LPARAM
)cs
);
1385 result
= SendMessageA( hwnd
, WM_NCCREATE
, 0, (LPARAM
)cs
);
1388 WARN( "%p: aborted by WM_NCCREATE\n", hwnd
);
1392 /* create default IME window */
1394 if (imm_register_window
&& !is_desktop_window( hwnd
) &&
1395 parent
!= get_hwnd_message_parent() && imm_register_window( hwnd
))
1397 TRACE("register IME window for %p\n", hwnd
);
1398 win_set_flags( hwnd
, WIN_HAS_IME_WIN
, 0 );
1401 /* send WM_NCCALCSIZE */
1403 if (WIN_GetRectangles( hwnd
, COORDS_PARENT
, &rect
, NULL
))
1405 /* yes, even if the CBT hook was called with HWND_TOP */
1406 HWND insert_after
= (GetWindowLongW( hwnd
, GWL_STYLE
) & WS_CHILD
) ? HWND_BOTTOM
: HWND_TOP
;
1407 RECT client_rect
= rect
;
1409 /* the rectangle is in screen coords for WM_NCCALCSIZE when wparam is FALSE */
1410 MapWindowPoints( parent
, 0, (POINT
*)&client_rect
, 2 );
1411 SendMessageW( hwnd
, WM_NCCALCSIZE
, FALSE
, (LPARAM
)&client_rect
);
1412 MapWindowPoints( 0, parent
, (POINT
*)&client_rect
, 2 );
1413 set_window_pos( hwnd
, insert_after
, SWP_NOACTIVATE
, &rect
, &client_rect
, NULL
);
1417 /* send WM_CREATE */
1420 result
= SendMessageW( hwnd
, WM_CREATE
, 0, (LPARAM
)cs
);
1422 result
= SendMessageA( hwnd
, WM_CREATE
, 0, (LPARAM
)cs
);
1423 if (result
== -1) goto failed
;
1425 /* call the driver */
1427 if (!USER_Driver
->pCreateWindow( hwnd
)) goto failed
;
1429 NtUserNotifyWinEvent( EVENT_OBJECT_CREATE
, hwnd
, OBJID_WINDOW
, 0 );
1431 /* send the size messages */
1433 if (!(win_get_flags( hwnd
) & WIN_NEED_SIZE
))
1435 WIN_GetRectangles( hwnd
, COORDS_PARENT
, NULL
, &rect
);
1436 SendMessageW( hwnd
, WM_SIZE
, SIZE_RESTORED
,
1437 MAKELONG(rect
.right
-rect
.left
, rect
.bottom
-rect
.top
));
1438 SendMessageW( hwnd
, WM_MOVE
, 0, MAKELONG( rect
.left
, rect
.top
) );
1441 /* Show the window, maximizing or minimizing if needed */
1443 style
= WIN_SetStyle( hwnd
, 0, WS_MAXIMIZE
| WS_MINIMIZE
);
1444 if (style
& (WS_MINIMIZE
| WS_MAXIMIZE
))
1447 UINT swFlag
= (style
& WS_MINIMIZE
) ? SW_MINIMIZE
: SW_MAXIMIZE
;
1449 swFlag
= WINPOS_MinMaximize( hwnd
, swFlag
, &newPos
);
1450 swFlag
|= SWP_FRAMECHANGED
; /* Frame always gets changed */
1451 if (!(style
& WS_VISIBLE
) || (style
& WS_CHILD
) || GetActiveWindow()) swFlag
|= SWP_NOACTIVATE
;
1452 NtUserSetWindowPos( hwnd
, 0, newPos
.left
, newPos
.top
, newPos
.right
- newPos
.left
,
1453 newPos
.bottom
- newPos
.top
, swFlag
);
1456 /* Notify the parent window only */
1458 send_parent_notify( hwnd
, WM_CREATE
);
1459 if (!IsWindow( hwnd
))
1461 SetThreadDpiAwarenessContext( context
);
1465 if (parent
== GetDesktopWindow())
1466 PostMessageW( parent
, WM_PARENTNOTIFY
, WM_CREATE
, (LPARAM
)hwnd
);
1468 if (cs
->style
& WS_VISIBLE
)
1470 if (cs
->style
& WS_MAXIMIZE
)
1472 else if (cs
->style
& WS_MINIMIZE
)
1473 sw
= SW_SHOWMINIMIZED
;
1475 ShowWindow( hwnd
, sw
);
1476 if (cs
->dwExStyle
& WS_EX_MDICHILD
)
1478 SendMessageW(cs
->hwndParent
, WM_MDIREFRESHMENU
, 0, 0);
1479 /* ShowWindow won't activate child windows */
1480 NtUserSetWindowPos( hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_SHOWWINDOW
| SWP_NOMOVE
| SWP_NOSIZE
);
1484 /* Call WH_SHELL hook */
1486 if (!(GetWindowLongW( hwnd
, GWL_STYLE
) & WS_CHILD
) && !GetWindow( hwnd
, GW_OWNER
))
1487 HOOK_CallHooks( WH_SHELL
, HSHELL_WINDOWCREATED
, (WPARAM
)hwnd
, 0, TRUE
);
1489 TRACE("created window %p\n", hwnd
);
1490 SetThreadDpiAwarenessContext( context
);
1494 WIN_DestroyWindow( hwnd
);
1495 SetThreadDpiAwarenessContext( context
);
1500 /***********************************************************************
1501 * CreateWindowExA (USER32.@)
1503 HWND WINAPI DECLSPEC_HOTPATCH
CreateWindowExA( DWORD exStyle
, LPCSTR className
,
1504 LPCSTR windowName
, DWORD style
, INT x
,
1505 INT y
, INT width
, INT height
,
1506 HWND parent
, HMENU menu
,
1507 HINSTANCE instance
, LPVOID data
)
1511 cs
.lpCreateParams
= data
;
1512 cs
.hInstance
= instance
;
1514 cs
.hwndParent
= parent
;
1520 cs
.lpszName
= windowName
;
1521 cs
.lpszClass
= className
;
1522 cs
.dwExStyle
= exStyle
;
1524 if (!IS_INTRESOURCE(className
))
1527 if (!MultiByteToWideChar( CP_ACP
, 0, className
, -1, bufferW
, ARRAY_SIZE( bufferW
)))
1529 return wow_handlers
.create_window( (CREATESTRUCTW
*)&cs
, bufferW
, instance
, FALSE
);
1531 /* Note: we rely on the fact that CREATESTRUCTA and */
1532 /* CREATESTRUCTW have the same layout. */
1533 return wow_handlers
.create_window( (CREATESTRUCTW
*)&cs
, (LPCWSTR
)className
, instance
, FALSE
);
1537 /***********************************************************************
1538 * CreateWindowExW (USER32.@)
1540 HWND WINAPI DECLSPEC_HOTPATCH
CreateWindowExW( DWORD exStyle
, LPCWSTR className
,
1541 LPCWSTR windowName
, DWORD style
, INT x
,
1542 INT y
, INT width
, INT height
,
1543 HWND parent
, HMENU menu
,
1544 HINSTANCE instance
, LPVOID data
)
1548 cs
.lpCreateParams
= data
;
1549 cs
.hInstance
= instance
;
1551 cs
.hwndParent
= parent
;
1557 cs
.lpszName
= windowName
;
1558 cs
.lpszClass
= className
;
1559 cs
.dwExStyle
= exStyle
;
1561 return wow_handlers
.create_window( &cs
, className
, instance
, TRUE
);
1565 /***********************************************************************
1566 * WIN_SendDestroyMsg
1568 static void WIN_SendDestroyMsg( HWND hwnd
)
1572 info
.cbSize
= sizeof(info
);
1573 if (NtUserGetGUIThreadInfo( GetCurrentThreadId(), &info
))
1575 if (hwnd
== info
.hwndCaret
) DestroyCaret();
1576 if (hwnd
== info
.hwndActive
) WINPOS_ActivateOtherWindow( hwnd
);
1579 if (hwnd
== NtUserGetClipboardOwner()) CLIPBOARD_ReleaseOwner( hwnd
);
1582 * Send the WM_DESTROY to the window.
1584 SendMessageW( hwnd
, WM_DESTROY
, 0, 0);
1587 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1588 * make sure that the window still exists when we come back.
1595 if (!(pWndArray
= WIN_ListChildren( hwnd
))) return;
1597 for (i
= 0; pWndArray
[i
]; i
++)
1599 if (IsWindow( pWndArray
[i
] )) WIN_SendDestroyMsg( pWndArray
[i
] );
1601 HeapFree( GetProcessHeap(), 0, pWndArray
);
1604 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1608 /***********************************************************************
1609 * DestroyWindow (USER32.@)
1611 BOOL WINAPI
DestroyWindow( HWND hwnd
)
1615 if (!(hwnd
= WIN_IsCurrentThread( hwnd
)) || is_desktop_window( hwnd
))
1617 SetLastError( ERROR_ACCESS_DENIED
);
1621 TRACE("(%p)\n", hwnd
);
1625 if (HOOK_CallHooks( WH_CBT
, HCBT_DESTROYWND
, (WPARAM
)hwnd
, 0, TRUE
)) return FALSE
;
1627 if (MENU_IsMenuActive() == hwnd
)
1630 is_child
= (GetWindowLongW( hwnd
, GWL_STYLE
) & WS_CHILD
) != 0;
1634 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1635 send_parent_notify( hwnd
, WM_DESTROY
);
1637 else if (!GetWindow( hwnd
, GW_OWNER
))
1639 HOOK_CallHooks( WH_SHELL
, HSHELL_WINDOWDESTROYED
, (WPARAM
)hwnd
, 0L, TRUE
);
1640 /* FIXME: clean up palette - see "Internals" p.352 */
1643 if (!IsWindow(hwnd
)) return TRUE
;
1645 /* Hide the window */
1646 if (GetWindowLongW( hwnd
, GWL_STYLE
) & WS_VISIBLE
)
1648 /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
1650 ShowWindow( hwnd
, SW_HIDE
);
1652 NtUserSetWindowPos( hwnd
, 0, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
|
1653 SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_HIDEWINDOW
);
1656 if (!IsWindow(hwnd
)) return TRUE
;
1658 /* Recursively destroy owned windows */
1665 BOOL got_one
= FALSE
;
1666 HWND
*list
= WIN_ListChildren( GetDesktopWindow() );
1669 for (i
= 0; list
[i
]; i
++)
1671 if (GetWindow( list
[i
], GW_OWNER
) != hwnd
) continue;
1672 if (WIN_IsCurrentThread( list
[i
] ))
1674 DestroyWindow( list
[i
] );
1678 WIN_SetOwner( list
[i
], 0 );
1680 HeapFree( GetProcessHeap(), 0, list
);
1682 if (!got_one
) break;
1686 /* Send destroy messages */
1688 WIN_SendDestroyMsg( hwnd
);
1689 if (!IsWindow( hwnd
)) return TRUE
;
1691 /* Destroy the window storage */
1693 WIN_DestroyWindow( hwnd
);
1698 /***********************************************************************
1699 * CloseWindow (USER32.@)
1701 BOOL WINAPI
CloseWindow( HWND hwnd
)
1703 if (GetWindowLongW( hwnd
, GWL_STYLE
) & WS_CHILD
) return FALSE
;
1704 ShowWindow( hwnd
, SW_MINIMIZE
);
1709 /***********************************************************************
1710 * OpenIcon (USER32.@)
1712 BOOL WINAPI
OpenIcon( HWND hwnd
)
1714 if (!IsIconic( hwnd
)) return FALSE
;
1715 ShowWindow( hwnd
, SW_SHOWNORMAL
);
1720 /***********************************************************************
1721 * FindWindowExW (USER32.@)
1723 HWND WINAPI
FindWindowExW( HWND parent
, HWND child
, LPCWSTR className
, LPCWSTR title
)
1728 WCHAR
*buffer
= NULL
;
1730 if (!parent
&& child
) parent
= GetDesktopWindow();
1731 else if (parent
== HWND_MESSAGE
) parent
= get_hwnd_message_parent();
1735 len
= lstrlenW(title
) + 1; /* one extra char to check for chars beyond the end */
1736 if (!(buffer
= HeapAlloc( GetProcessHeap(), 0, (len
+ 1) * sizeof(WCHAR
) ))) return 0;
1742 if (IS_INTRESOURCE(className
))
1744 str
.Buffer
= (WCHAR
*)className
;
1745 str
.Length
= str
.MaximumLength
= 0;
1747 else RtlInitUnicodeString( &str
, className
);
1748 list
= list_window_children( 0, parent
, &str
, 0 );
1750 else list
= list_window_children( 0, parent
, NULL
, 0 );
1751 if (!list
) goto done
;
1755 child
= WIN_GetFullHandle( child
);
1756 while (list
[i
] && list
[i
] != child
) i
++;
1757 if (!list
[i
]) goto done
;
1758 i
++; /* start from next window */
1765 if (NtUserInternalGetWindowText( list
[i
], buffer
, len
+ 1 ))
1767 if (!wcsicmp( buffer
, title
)) break;
1771 if (!title
[0]) break;
1779 HeapFree( GetProcessHeap(), 0, list
);
1780 HeapFree( GetProcessHeap(), 0, buffer
);
1786 /***********************************************************************
1787 * FindWindowA (USER32.@)
1789 HWND WINAPI
FindWindowA( LPCSTR className
, LPCSTR title
)
1791 HWND ret
= FindWindowExA( 0, 0, className
, title
);
1792 if (!ret
) SetLastError (ERROR_CANNOT_FIND_WND_CLASS
);
1797 /***********************************************************************
1798 * FindWindowExA (USER32.@)
1800 HWND WINAPI
FindWindowExA( HWND parent
, HWND child
, LPCSTR className
, LPCSTR title
)
1802 LPWSTR titleW
= NULL
;
1807 DWORD len
= MultiByteToWideChar( CP_ACP
, 0, title
, -1, NULL
, 0 );
1808 if (!(titleW
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) ))) return 0;
1809 MultiByteToWideChar( CP_ACP
, 0, title
, -1, titleW
, len
);
1812 if (!IS_INTRESOURCE(className
))
1815 if (MultiByteToWideChar( CP_ACP
, 0, className
, -1, classW
, ARRAY_SIZE( classW
)))
1816 hwnd
= FindWindowExW( parent
, child
, classW
, titleW
);
1820 hwnd
= FindWindowExW( parent
, child
, (LPCWSTR
)className
, titleW
);
1823 HeapFree( GetProcessHeap(), 0, titleW
);
1828 /***********************************************************************
1829 * FindWindowW (USER32.@)
1831 HWND WINAPI
FindWindowW( LPCWSTR className
, LPCWSTR title
)
1833 return FindWindowExW( 0, 0, className
, title
);
1837 /**********************************************************************
1838 * GetDesktopWindow (USER32.@)
1840 HWND WINAPI
GetDesktopWindow(void)
1842 struct user_thread_info
*thread_info
= get_user_thread_info();
1844 if (thread_info
->top_window
) return thread_info
->top_window
;
1845 return UlongToHandle( NtUserCallNoParam( NtUserGetDesktopWindow
));
1849 /*******************************************************************
1850 * EnableWindow (USER32.@)
1852 BOOL WINAPI
EnableWindow( HWND hwnd
, BOOL enable
)
1856 if (is_broadcast(hwnd
))
1858 SetLastError( ERROR_INVALID_PARAMETER
);
1862 TRACE("( %p, %d )\n", hwnd
, enable
);
1866 retvalue
= (WIN_SetStyle( hwnd
, 0, WS_DISABLED
) & WS_DISABLED
) != 0;
1867 if (retvalue
) SendMessageW( hwnd
, WM_ENABLE
, TRUE
, 0 );
1871 SendMessageW( hwnd
, WM_CANCELMODE
, 0, 0 );
1873 retvalue
= (WIN_SetStyle( hwnd
, WS_DISABLED
, 0 ) & WS_DISABLED
) != 0;
1876 if (hwnd
== GetFocus())
1877 NtUserSetFocus( 0 ); /* A disabled window can't have the focus */
1879 SendMessageW( hwnd
, WM_ENABLE
, FALSE
, 0 );
1886 /***********************************************************************
1887 * IsWindowEnabled (USER32.@)
1889 BOOL WINAPI
IsWindowEnabled(HWND hWnd
)
1893 SetLastError(NO_ERROR
);
1894 ret
= GetWindowLongW( hWnd
, GWL_STYLE
);
1895 if (!ret
&& GetLastError() != NO_ERROR
) return FALSE
;
1896 return !(ret
& WS_DISABLED
);
1899 /***********************************************************************
1900 * IsWindowUnicode (USER32.@)
1902 BOOL WINAPI
IsWindowUnicode( HWND hwnd
)
1904 return NtUserCallHwnd( hwnd
, NtUserIsWindowUnicode
);
1908 /***********************************************************************
1909 * GetWindowDpiAwarenessContext (USER32.@)
1911 DPI_AWARENESS_CONTEXT WINAPI
GetWindowDpiAwarenessContext( HWND hwnd
)
1913 return (DPI_AWARENESS_CONTEXT
)NtUserCallHwnd( hwnd
, NtUserGetWindowDpiAwarenessContext
);
1917 /***********************************************************************
1918 * GetDpiForWindow (USER32.@)
1920 UINT WINAPI
GetDpiForWindow( HWND hwnd
)
1922 return NtUserCallHwnd( hwnd
, NtUserGetDpiForWindow
);
1926 /**********************************************************************
1927 * GetWindowWord (USER32.@)
1929 WORD WINAPI
GetWindowWord( HWND hwnd
, INT offset
)
1931 return NtUserCallHwndParam( hwnd
, offset
, NtUserGetWindowWord
);
1935 /**********************************************************************
1936 * GetWindowLongA (USER32.@)
1938 LONG WINAPI
GetWindowLongA( HWND hwnd
, INT offset
)
1944 case GWLP_HINSTANCE
:
1945 case GWLP_HWNDPARENT
:
1946 WARN( "Invalid offset %d\n", offset
);
1947 SetLastError( ERROR_INVALID_INDEX
);
1951 return NtUserCallHwndParam( hwnd
, offset
, NtUserGetWindowLongA
);
1956 /**********************************************************************
1957 * GetWindowLongW (USER32.@)
1959 LONG WINAPI
GetWindowLongW( HWND hwnd
, INT offset
)
1965 case GWLP_HINSTANCE
:
1966 case GWLP_HWNDPARENT
:
1967 WARN( "Invalid offset %d\n", offset
);
1968 SetLastError( ERROR_INVALID_INDEX
);
1972 return NtUserCallHwndParam( hwnd
, offset
, NtUserGetWindowLongW
);
1977 /**********************************************************************
1978 * SetWindowLongA (USER32.@)
1980 * See SetWindowLongW.
1982 LONG WINAPI DECLSPEC_HOTPATCH
SetWindowLongA( HWND hwnd
, INT offset
, LONG newval
)
1988 case GWLP_HINSTANCE
:
1989 case GWLP_HWNDPARENT
:
1990 WARN( "Invalid offset %d\n", offset
);
1991 SetLastError( ERROR_INVALID_INDEX
);
1995 return NtUserSetWindowLong( hwnd
, offset
, newval
, TRUE
);
2000 /**********************************************************************
2001 * SetWindowLongW (USER32.@) Set window attribute
2003 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2004 * value in a window's extra memory.
2006 * The _hwnd_ parameter specifies the handle to a window that
2007 * has extra memory. The _newval_ parameter contains the new
2008 * attribute or extra memory value. If positive, the _offset_
2009 * parameter is the byte-addressed location in the window's extra
2010 * memory to set. If negative, _offset_ specifies the window
2011 * attribute to set, and should be one of the following values:
2013 * GWL_EXSTYLE The window's extended window style
2015 * GWL_STYLE The window's window style.
2017 * GWLP_WNDPROC Pointer to the window's window procedure.
2019 * GWLP_HINSTANCE The window's application instance handle.
2021 * GWLP_ID The window's identifier.
2023 * GWLP_USERDATA The window's user-specified data.
2025 * If the window is a dialog box, the _offset_ parameter can be one of
2026 * the following values:
2028 * DWLP_DLGPROC The address of the window's dialog box procedure.
2030 * DWLP_MSGRESULT The return value of a message
2031 * that the dialog box procedure processed.
2033 * DWLP_USER Application specific information.
2037 * If successful, returns the previous value located at _offset_. Otherwise,
2042 * Extra memory for a window class is specified by a nonzero cbWndExtra
2043 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2044 * time of class creation.
2046 * Using GWL_WNDPROC to set a new window procedure effectively creates
2047 * a window subclass. Use CallWindowProc() in the new windows procedure
2048 * to pass messages to the superclass's window procedure.
2050 * The user data is reserved for use by the application which created
2053 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2054 * instead, call the EnableWindow() function to change the window's
2057 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2058 * SetParent() instead.
2061 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2062 * it sends WM_STYLECHANGING before changing the settings
2063 * and WM_STYLECHANGED afterwards.
2064 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2066 LONG WINAPI DECLSPEC_HOTPATCH
SetWindowLongW(
2067 HWND hwnd
, /* [in] window to alter */
2068 INT offset
, /* [in] offset, in bytes, of location to alter */
2069 LONG newval
/* [in] new value of location */
2076 case GWLP_HINSTANCE
:
2077 case GWLP_HWNDPARENT
:
2078 WARN("Invalid offset %d\n", offset
);
2079 SetLastError( ERROR_INVALID_INDEX
);
2083 return NtUserSetWindowLong( hwnd
, offset
, newval
, FALSE
);
2088 /*******************************************************************
2089 * GetWindowTextA (USER32.@)
2091 INT WINAPI
GetWindowTextA( HWND hwnd
, LPSTR lpString
, INT nMaxCount
)
2096 if (!lpString
|| nMaxCount
<= 0) return 0;
2102 if (WIN_IsCurrentProcess( hwnd
))
2104 ret
= (INT
)SendMessageA( hwnd
, WM_GETTEXT
, nMaxCount
, (LPARAM
)lpString
);
2106 else if ((buffer
= HeapAlloc( GetProcessHeap(), 0, nMaxCount
* sizeof(WCHAR
) )))
2108 /* when window belongs to other process, don't send a message */
2109 NtUserInternalGetWindowText( hwnd
, buffer
, nMaxCount
);
2110 if (!WideCharToMultiByte( CP_ACP
, 0, buffer
, -1, lpString
, nMaxCount
, NULL
, NULL
))
2111 lpString
[nMaxCount
-1] = 0;
2112 HeapFree( GetProcessHeap(), 0, buffer
);
2113 ret
= strlen(lpString
);
2126 /*******************************************************************
2127 * GetWindowTextW (USER32.@)
2129 INT WINAPI
GetWindowTextW( HWND hwnd
, LPWSTR lpString
, INT nMaxCount
)
2133 if (!lpString
|| nMaxCount
<= 0) return 0;
2139 if (WIN_IsCurrentProcess( hwnd
))
2141 ret
= (INT
)SendMessageW( hwnd
, WM_GETTEXT
, nMaxCount
, (LPARAM
)lpString
);
2145 /* when window belongs to other process, don't send a message */
2146 ret
= NtUserInternalGetWindowText( hwnd
, lpString
, nMaxCount
);
2159 /*******************************************************************
2160 * SetWindowTextA (USER32.@)
2161 * SetWindowText (USER32.@)
2163 BOOL WINAPI DECLSPEC_HOTPATCH
SetWindowTextA( HWND hwnd
, LPCSTR lpString
)
2165 if (is_broadcast(hwnd
))
2167 SetLastError( ERROR_INVALID_PARAMETER
);
2170 if (!WIN_IsCurrentProcess( hwnd
))
2171 WARN( "setting text %s of other process window %p should not use SendMessage\n",
2172 debugstr_a(lpString
), hwnd
);
2173 return (BOOL
)SendMessageA( hwnd
, WM_SETTEXT
, 0, (LPARAM
)lpString
);
2177 /*******************************************************************
2178 * SetWindowTextW (USER32.@)
2180 BOOL WINAPI DECLSPEC_HOTPATCH
SetWindowTextW( HWND hwnd
, LPCWSTR lpString
)
2182 if (is_broadcast(hwnd
))
2184 SetLastError( ERROR_INVALID_PARAMETER
);
2187 if (!WIN_IsCurrentProcess( hwnd
))
2188 WARN( "setting text %s of other process window %p should not use SendMessage\n",
2189 debugstr_w(lpString
), hwnd
);
2190 return (BOOL
)SendMessageW( hwnd
, WM_SETTEXT
, 0, (LPARAM
)lpString
);
2194 /*******************************************************************
2195 * GetWindowTextLengthA (USER32.@)
2197 INT WINAPI
GetWindowTextLengthA( HWND hwnd
)
2201 if (WIN_IsCurrentProcess( hwnd
)) return SendMessageA( hwnd
, WM_GETTEXTLENGTH
, 0, 0 );
2203 /* when window belongs to other process, don't send a message */
2204 GetCPInfo( CP_ACP
, &info
);
2205 return NtUserCallHwnd( hwnd
, NtUserGetWindowTextLength
) * info
.MaxCharSize
;
2208 /*******************************************************************
2209 * GetWindowTextLengthW (USER32.@)
2211 INT WINAPI
GetWindowTextLengthW( HWND hwnd
)
2213 if (WIN_IsCurrentProcess( hwnd
)) return SendMessageW( hwnd
, WM_GETTEXTLENGTH
, 0, 0 );
2215 /* when window belongs to other process, don't send a message */
2216 return NtUserCallHwnd( hwnd
, NtUserGetWindowTextLength
);
2220 /*******************************************************************
2221 * IsWindow (USER32.@)
2223 BOOL WINAPI
IsWindow( HWND hwnd
)
2225 return NtUserCallHwnd( hwnd
, NtUserIsWindow
);
2229 /***********************************************************************
2230 * GetWindowThreadProcessId (USER32.@)
2232 DWORD WINAPI
GetWindowThreadProcessId( HWND hwnd
, LPDWORD process
)
2234 return NtUserCallHwndParam( hwnd
, (UINT_PTR
)process
, NtUserGetWindowThread
);
2238 /*****************************************************************
2239 * GetParent (USER32.@)
2241 HWND WINAPI
GetParent( HWND hwnd
)
2243 return UlongToHandle( NtUserCallHwnd( hwnd
, NtUserGetParent
));
2247 /*******************************************************************
2248 * IsChild (USER32.@)
2250 BOOL WINAPI
IsChild( HWND parent
, HWND child
)
2252 return NtUserCallHwndParam( parent
, HandleToUlong(child
), NtUserIsChild
);
2256 /***********************************************************************
2257 * IsWindowVisible (USER32.@)
2259 BOOL WINAPI
IsWindowVisible( HWND hwnd
)
2261 return NtUserCallHwnd( hwnd
, NtUserIsWindowVisible
);
2265 /***********************************************************************
2266 * WIN_IsWindowDrawable
2268 * hwnd is drawable when it is visible, all parents are not
2269 * minimized, and it is itself not minimized unless we are
2270 * trying to draw its default class icon.
2272 BOOL
WIN_IsWindowDrawable( HWND hwnd
, BOOL icon
)
2274 /* FIXME: move callers to win32u */
2275 return NtUserCallHwndParam( hwnd
, icon
, NtUserIsWindowDrawable
);
2279 /*******************************************************************
2280 * GetTopWindow (USER32.@)
2282 HWND WINAPI
GetTopWindow( HWND hwnd
)
2284 if (!hwnd
) hwnd
= GetDesktopWindow();
2285 return GetWindow( hwnd
, GW_CHILD
);
2289 /*******************************************************************
2290 * GetWindow (USER32.@)
2292 HWND WINAPI
GetWindow( HWND hwnd
, UINT rel
)
2294 return UlongToHandle( NtUserCallHwndParam( hwnd
, rel
, NtUserGetWindowRelative
));
2298 /*******************************************************************
2299 * ShowOwnedPopups (USER32.@)
2301 BOOL WINAPI
ShowOwnedPopups( HWND owner
, BOOL fShow
)
2304 HWND
*win_array
= WIN_ListChildren( GetDesktopWindow() );
2306 if (!win_array
) return TRUE
;
2308 while (win_array
[count
]) count
++;
2309 while (--count
>= 0)
2311 if (GetWindow( win_array
[count
], GW_OWNER
) != owner
) continue;
2314 if (win_get_flags( win_array
[count
] ) & WIN_NEEDS_SHOW_OWNEDPOPUP
)
2315 /* In Windows, ShowOwnedPopups(TRUE) generates
2316 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2317 * regardless of the state of the owner
2319 SendMessageW(win_array
[count
], WM_SHOWWINDOW
, SW_SHOWNORMAL
, SW_PARENTOPENING
);
2323 if (GetWindowLongW( win_array
[count
], GWL_STYLE
) & WS_VISIBLE
)
2324 /* In Windows, ShowOwnedPopups(FALSE) generates
2325 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2326 * regardless of the state of the owner
2328 SendMessageW(win_array
[count
], WM_SHOWWINDOW
, SW_HIDE
, SW_PARENTCLOSING
);
2331 HeapFree( GetProcessHeap(), 0, win_array
);
2336 /*******************************************************************
2337 * GetLastActivePopup (USER32.@)
2339 HWND WINAPI
GetLastActivePopup( HWND hwnd
)
2343 SERVER_START_REQ( get_window_info
)
2345 req
->handle
= wine_server_user_handle( hwnd
);
2346 if (!wine_server_call_err( req
)) retval
= wine_server_ptr_handle( reply
->last_active
);
2353 /*******************************************************************
2356 * Build an array of the children of a given window. The array must be
2357 * freed with HeapFree. Returns NULL when no windows are found.
2359 HWND
*WIN_ListChildren( HWND hwnd
)
2363 SetLastError( ERROR_INVALID_WINDOW_HANDLE
);
2366 return list_window_children( 0, hwnd
, NULL
, 0 );
2370 /*******************************************************************
2371 * EnumWindows (USER32.@)
2373 BOOL WINAPI
EnumWindows( WNDENUMPROC lpEnumFunc
, LPARAM lParam
)
2379 USER_CheckNotLock();
2381 /* We have to build a list of all windows first, to avoid */
2382 /* unpleasant side-effects, for instance if the callback */
2383 /* function changes the Z-order of the windows. */
2385 if (!(list
= WIN_ListChildren( GetDesktopWindow() ))) return TRUE
;
2387 /* Now call the callback function for every window */
2389 for (i
= 0; list
[i
]; i
++)
2391 /* Make sure that the window still exists */
2392 if (!IsWindow( list
[i
] )) continue;
2393 if (!(ret
= lpEnumFunc( list
[i
], lParam
))) break;
2395 HeapFree( GetProcessHeap(), 0, list
);
2400 /**********************************************************************
2401 * EnumThreadWindows (USER32.@)
2403 BOOL WINAPI
EnumThreadWindows( DWORD id
, WNDENUMPROC func
, LPARAM lParam
)
2409 USER_CheckNotLock();
2411 if (!(list
= list_window_children( 0, GetDesktopWindow(), NULL
, id
))) return TRUE
;
2413 /* Now call the callback function for every window */
2415 for (i
= 0; list
[i
]; i
++)
2416 if (!(ret
= func( list
[i
], lParam
))) break;
2417 HeapFree( GetProcessHeap(), 0, list
);
2422 /***********************************************************************
2423 * EnumDesktopWindows (USER32.@)
2425 BOOL WINAPI
EnumDesktopWindows( HDESK desktop
, WNDENUMPROC func
, LPARAM lparam
)
2430 USER_CheckNotLock();
2432 if (!(list
= list_window_children( desktop
, 0, NULL
, 0 ))) return TRUE
;
2434 for (i
= 0; list
[i
]; i
++)
2435 if (!func( list
[i
], lparam
)) break;
2436 HeapFree( GetProcessHeap(), 0, list
);
2442 /* Some apps pass a non-stdcall proc to EnumChildWindows,
2443 * so we need a small assembly wrapper to call the proc.
2445 extern LRESULT
enum_callback_wrapper( WNDENUMPROC proc
, HWND hwnd
, LPARAM lparam
);
2446 __ASM_GLOBAL_FUNC( enum_callback_wrapper
,
2448 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
2449 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
2450 "movl %esp,%ebp\n\t"
2451 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
2452 "pushl 16(%ebp)\n\t"
2453 "pushl 12(%ebp)\n\t"
2456 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
2457 __ASM_CFI(".cfi_same_value %ebp\n\t")
2460 static inline LRESULT
enum_callback_wrapper( WNDENUMPROC proc
, HWND hwnd
, LPARAM lparam
)
2462 return proc( hwnd
, lparam
);
2464 #endif /* __i386__ */
2466 /**********************************************************************
2467 * WIN_EnumChildWindows
2469 * Helper function for EnumChildWindows().
2471 static BOOL
WIN_EnumChildWindows( HWND
*list
, WNDENUMPROC func
, LPARAM lParam
)
2476 for ( ; *list
; list
++)
2478 /* Make sure that the window still exists */
2479 if (!IsWindow( *list
)) continue;
2480 /* Build children list first */
2481 childList
= WIN_ListChildren( *list
);
2483 ret
= enum_callback_wrapper( func
, *list
, lParam
);
2487 if (ret
) ret
= WIN_EnumChildWindows( childList
, func
, lParam
);
2488 HeapFree( GetProcessHeap(), 0, childList
);
2490 if (!ret
) return FALSE
;
2496 /**********************************************************************
2497 * EnumChildWindows (USER32.@)
2499 BOOL WINAPI
EnumChildWindows( HWND parent
, WNDENUMPROC func
, LPARAM lParam
)
2504 USER_CheckNotLock();
2506 if (!(list
= WIN_ListChildren( parent
))) return FALSE
;
2507 ret
= WIN_EnumChildWindows( list
, func
, lParam
);
2508 HeapFree( GetProcessHeap(), 0, list
);
2513 /*******************************************************************
2514 * AnyPopup (USER32.@)
2516 BOOL WINAPI
AnyPopup(void)
2520 HWND
*list
= WIN_ListChildren( GetDesktopWindow() );
2522 if (!list
) return FALSE
;
2523 for (i
= 0; list
[i
]; i
++)
2525 if (IsWindowVisible( list
[i
] ) && GetWindow( list
[i
], GW_OWNER
)) break;
2527 retvalue
= (list
[i
] != 0);
2528 HeapFree( GetProcessHeap(), 0, list
);
2533 /*******************************************************************
2534 * FlashWindow (USER32.@)
2536 BOOL WINAPI
FlashWindow( HWND hWnd
, BOOL bInvert
)
2540 finfo
.cbSize
= sizeof(FLASHWINFO
);
2541 finfo
.dwFlags
= bInvert
? FLASHW_ALL
: FLASHW_STOP
;
2543 finfo
.dwTimeout
= 0;
2545 return NtUserFlashWindowEx( &finfo
);
2549 /*******************************************************************
2550 * GetWindowContextHelpId (USER32.@)
2552 DWORD WINAPI
GetWindowContextHelpId( HWND hwnd
)
2555 WND
*wnd
= WIN_GetPtr( hwnd
);
2556 if (!wnd
|| wnd
== WND_DESKTOP
) return 0;
2557 if (wnd
== WND_OTHER_PROCESS
)
2559 if (IsWindow( hwnd
)) FIXME( "not supported on other process window %p\n", hwnd
);
2562 retval
= wnd
->helpContext
;
2563 WIN_ReleasePtr( wnd
);
2568 /*******************************************************************
2569 * SetWindowContextHelpId (USER32.@)
2571 BOOL WINAPI
SetWindowContextHelpId( HWND hwnd
, DWORD id
)
2573 WND
*wnd
= WIN_GetPtr( hwnd
);
2574 if (!wnd
|| wnd
== WND_DESKTOP
) return FALSE
;
2575 if (wnd
== WND_OTHER_PROCESS
)
2577 if (IsWindow( hwnd
)) FIXME( "not supported on other process window %p\n", hwnd
);
2580 wnd
->helpContext
= id
;
2581 WIN_ReleasePtr( wnd
);
2586 /*******************************************************************
2587 * DragDetect (USER32.@)
2589 BOOL WINAPI
DragDetect( HWND hWnd
, POINT pt
)
2593 WORD wDragWidth
, wDragHeight
;
2595 TRACE( "%p,%s\n", hWnd
, wine_dbgstr_point( &pt
) );
2597 if (!(NtUserGetKeyState( VK_LBUTTON
) & 0x8000))
2600 wDragWidth
= GetSystemMetrics(SM_CXDRAG
);
2601 wDragHeight
= GetSystemMetrics(SM_CYDRAG
);
2602 SetRect(&rect
, pt
.x
- wDragWidth
, pt
.y
- wDragHeight
, pt
.x
+ wDragWidth
, pt
.y
+ wDragHeight
);
2604 NtUserSetCapture( hWnd
);
2608 while (PeekMessageW( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
, PM_REMOVE
))
2610 if( msg
.message
== WM_LBUTTONUP
)
2615 if( msg
.message
== WM_MOUSEMOVE
)
2618 tmp
.x
= (short)LOWORD(msg
.lParam
);
2619 tmp
.y
= (short)HIWORD(msg
.lParam
);
2620 if( !PtInRect( &rect
, tmp
))
2632 /******************************************************************************
2633 * GetWindowModuleFileNameA (USER32.@)
2635 UINT WINAPI
GetWindowModuleFileNameA( HWND hwnd
, LPSTR module
, UINT size
)
2640 TRACE( "%p, %p, %u\n", hwnd
, module
, size
);
2642 win
= WIN_GetPtr( hwnd
);
2643 if (!win
|| win
== WND_OTHER_PROCESS
|| win
== WND_DESKTOP
)
2645 SetLastError( ERROR_INVALID_WINDOW_HANDLE
);
2648 hinst
= win
->hInstance
;
2649 WIN_ReleasePtr( win
);
2651 return GetModuleFileNameA( hinst
, module
, size
);
2654 /******************************************************************************
2655 * GetWindowModuleFileNameW (USER32.@)
2657 UINT WINAPI
GetWindowModuleFileNameW( HWND hwnd
, LPWSTR module
, UINT size
)
2662 TRACE( "%p, %p, %u\n", hwnd
, module
, size
);
2664 win
= WIN_GetPtr( hwnd
);
2665 if (!win
|| win
== WND_OTHER_PROCESS
|| win
== WND_DESKTOP
)
2667 SetLastError( ERROR_INVALID_WINDOW_HANDLE
);
2670 hinst
= win
->hInstance
;
2671 WIN_ReleasePtr( win
);
2673 return GetModuleFileNameW( hinst
, module
, size
);
2676 /******************************************************************************
2677 * GetWindowInfo (USER32.@)
2679 * Note: tests show that Windows doesn't check cbSize of the structure.
2681 BOOL WINAPI DECLSPEC_HOTPATCH
GetWindowInfo( HWND hwnd
, WINDOWINFO
*info
)
2683 return NtUserCallHwndParam( hwnd
, (UINT_PTR
)info
, NtUserGetWindowInfo
);
2686 /******************************************************************************
2687 * SwitchDesktop (USER32.@)
2689 * NOTES: Sets the current input or interactive desktop.
2691 BOOL WINAPI
SwitchDesktop( HDESK hDesktop
)
2693 FIXME("(hwnd %p) stub!\n", hDesktop
);
2698 /***********************************************************************
2699 * __wine_set_pixel_format
2701 BOOL CDECL
__wine_set_pixel_format( HWND hwnd
, int format
)
2703 return NtUserCallHwndParam( hwnd
, format
, NtUserSetWindowPixelFormat
);
2707 /*****************************************************************************
2708 * UpdateLayeredWindowIndirect (USER32.@)
2710 BOOL WINAPI
UpdateLayeredWindowIndirect( HWND hwnd
, const UPDATELAYEREDWINDOWINFO
*info
)
2712 if (!info
|| info
->cbSize
!= sizeof(*info
))
2714 SetLastError( ERROR_INVALID_PARAMETER
);
2718 return NtUserUpdateLayeredWindow( hwnd
, info
->hdcDst
, info
->pptDst
, info
->psize
,
2719 info
->hdcSrc
, info
->pptSrc
, info
->crKey
,
2720 info
->pblend
, info
->dwFlags
, info
->prcDirty
);
2724 /*****************************************************************************
2725 * UpdateLayeredWindow (USER32.@)
2727 BOOL WINAPI
UpdateLayeredWindow( HWND hwnd
, HDC hdcDst
, POINT
*pptDst
, SIZE
*psize
,
2728 HDC hdcSrc
, POINT
*pptSrc
, COLORREF crKey
, BLENDFUNCTION
*pblend
,
2731 UPDATELAYEREDWINDOWINFO info
;
2733 if (flags
& ULW_EX_NORESIZE
) /* only valid for UpdateLayeredWindowIndirect */
2735 SetLastError( ERROR_INVALID_PARAMETER
);
2738 info
.cbSize
= sizeof(info
);
2739 info
.hdcDst
= hdcDst
;
2740 info
.pptDst
= pptDst
;
2742 info
.hdcSrc
= hdcSrc
;
2743 info
.pptSrc
= pptSrc
;
2745 info
.pblend
= pblend
;
2746 info
.dwFlags
= flags
;
2747 info
.prcDirty
= NULL
;
2748 return UpdateLayeredWindowIndirect( hwnd
, &info
);
2752 /******************************************************************************
2753 * GetProcessDefaultLayout [USER32.@]
2755 * Gets the default layout for parentless windows.
2757 BOOL WINAPI
GetProcessDefaultLayout( DWORD
*layout
)
2761 SetLastError( ERROR_NOACCESS
);
2764 if (process_layout
== ~0u)
2766 WCHAR
*str
, buffer
[MAX_PATH
];
2767 DWORD i
, version_layout
= 0;
2769 DWORD user_lang
= GetUserDefaultLangID();
2773 GetModuleFileNameW( 0, buffer
, MAX_PATH
);
2774 if (!(len
= GetFileVersionInfoSizeW( buffer
, NULL
))) goto done
;
2775 if (!(data
= HeapAlloc( GetProcessHeap(), 0, len
))) goto done
;
2776 if (!GetFileVersionInfoW( buffer
, 0, len
, data
)) goto done
;
2777 if (!VerQueryValueW( data
, L
"\\VarFileInfo\\Translation", (void **)&languages
, &len
) || !len
) goto done
;
2779 len
/= sizeof(DWORD
);
2780 for (i
= 0; i
< len
; i
++) if (LOWORD(languages
[i
]) == user_lang
) break;
2781 if (i
== len
) /* try neutral language */
2782 for (i
= 0; i
< len
; i
++)
2783 if (LOWORD(languages
[i
]) == MAKELANGID( PRIMARYLANGID(user_lang
), SUBLANG_NEUTRAL
)) break;
2784 if (i
== len
) i
= 0; /* default to the first one */
2786 swprintf( buffer
, ARRAY_SIZE(buffer
), L
"\\StringFileInfo\\%04x%04x\\FileDescription",
2787 LOWORD(languages
[i
]), HIWORD(languages
[i
]) );
2788 if (!VerQueryValueW( data
, buffer
, (void **)&str
, &len
)) goto done
;
2789 TRACE( "found description %s\n", debugstr_w( str
));
2790 if (str
[0] == 0x200e && str
[1] == 0x200e) version_layout
= LAYOUT_RTL
;
2793 HeapFree( GetProcessHeap(), 0, data
);
2794 process_layout
= version_layout
;
2796 *layout
= process_layout
;
2801 /******************************************************************************
2802 * SetProcessDefaultLayout [USER32.@]
2804 * Sets the default layout for parentless windows.
2806 BOOL WINAPI
SetProcessDefaultLayout( DWORD layout
)
2808 process_layout
= layout
;
2813 /* 64bit versions */
2815 #ifdef GetWindowLongPtrW
2816 #undef GetWindowLongPtrW
2819 #ifdef GetWindowLongPtrA
2820 #undef GetWindowLongPtrA
2823 #ifdef SetWindowLongPtrW
2824 #undef SetWindowLongPtrW
2827 #ifdef SetWindowLongPtrA
2828 #undef SetWindowLongPtrA
2831 /*****************************************************************************
2832 * GetWindowLongPtrW (USER32.@)
2834 LONG_PTR WINAPI
GetWindowLongPtrW( HWND hwnd
, INT offset
)
2836 return NtUserCallHwndParam( hwnd
, offset
, NtUserGetWindowLongPtrW
);
2839 /*****************************************************************************
2840 * GetWindowLongPtrA (USER32.@)
2842 LONG_PTR WINAPI
GetWindowLongPtrA( HWND hwnd
, INT offset
)
2844 return NtUserCallHwndParam( hwnd
, offset
, NtUserGetWindowLongPtrA
);
2847 /*****************************************************************************
2848 * SetWindowLongPtrW (USER32.@)
2850 LONG_PTR WINAPI
SetWindowLongPtrW( HWND hwnd
, INT offset
, LONG_PTR newval
)
2852 return NtUserSetWindowLongPtr( hwnd
, offset
, newval
, FALSE
);
2855 /*****************************************************************************
2856 * SetWindowLongPtrA (USER32.@)
2858 LONG_PTR WINAPI
SetWindowLongPtrA( HWND hwnd
, INT offset
, LONG_PTR newval
)
2860 return NtUserSetWindowLongPtr( hwnd
, offset
, newval
, TRUE
);
2863 /*****************************************************************************
2864 * RegisterTouchWindow (USER32.@)
2866 BOOL WINAPI
RegisterTouchWindow(HWND hwnd
, ULONG flags
)
2868 FIXME("(%p %08x): stub\n", hwnd
, flags
);
2869 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2873 /*****************************************************************************
2874 * UnregisterTouchWindow (USER32.@)
2876 BOOL WINAPI
UnregisterTouchWindow(HWND hwnd
)
2878 FIXME("(%p): stub\n", hwnd
);
2879 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2883 /*****************************************************************************
2884 * CloseTouchInputHandle (USER32.@)
2886 BOOL WINAPI
CloseTouchInputHandle(HTOUCHINPUT handle
)
2888 FIXME("(%p): stub\n", handle
);
2889 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2893 /*****************************************************************************
2894 * GetTouchInputInfo (USER32.@)
2896 BOOL WINAPI
GetTouchInputInfo(HTOUCHINPUT handle
, UINT count
, TOUCHINPUT
*ptr
, int size
)
2898 FIXME("(%p %u %p %u): stub\n", handle
, count
, ptr
, size
);
2899 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2903 /*****************************************************************************
2904 * GetGestureInfo (USER32.@)
2906 BOOL WINAPI
GetGestureInfo(HGESTUREINFO handle
, PGESTUREINFO ptr
)
2908 FIXME("(%p %p): stub\n", handle
, ptr
);
2909 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2913 /*****************************************************************************
2914 * GetWindowDisplayAffinity (USER32.@)
2916 BOOL WINAPI
GetWindowDisplayAffinity(HWND hwnd
, DWORD
*affinity
)
2918 FIXME("(%p, %p): stub\n", hwnd
, affinity
);
2920 if (!hwnd
|| !affinity
)
2922 SetLastError(hwnd
? ERROR_NOACCESS
: ERROR_INVALID_WINDOW_HANDLE
);
2926 *affinity
= WDA_NONE
;
2930 /*****************************************************************************
2931 * SetWindowDisplayAffinity (USER32.@)
2933 BOOL WINAPI
SetWindowDisplayAffinity(HWND hwnd
, DWORD affinity
)
2935 FIXME("(%p, %u): stub\n", hwnd
, affinity
);
2939 SetLastError(ERROR_INVALID_WINDOW_HANDLE
);
2943 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2947 /**********************************************************************
2948 * SetWindowCompositionAttribute (USER32.@)
2950 BOOL WINAPI
SetWindowCompositionAttribute(HWND hwnd
, void *data
)
2952 FIXME("(%p, %p): stub\n", hwnd
, data
);
2953 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2957 /***********************************************************************
2958 * InternalGetWindowIcon (USER32.@)
2960 HICON WINAPI
InternalGetWindowIcon( HWND hwnd
, UINT type
)
2962 WND
*win
= WIN_GetPtr( hwnd
);
2965 TRACE( "hwnd %p, type %#x\n", hwnd
, type
);
2969 SetLastError( ERROR_INVALID_WINDOW_HANDLE
);
2972 if (win
== WND_OTHER_PROCESS
|| win
== WND_DESKTOP
)
2974 if (IsWindow( hwnd
)) FIXME( "not supported on other process window %p\n", hwnd
);
2982 if (!ret
) ret
= (HICON
)GetClassLongPtrW( hwnd
, GCLP_HICON
);
2987 ret
= win
->hIconSmall
? win
->hIconSmall
: win
->hIconSmall2
;
2988 if (!ret
) ret
= (HICON
)GetClassLongPtrW( hwnd
, GCLP_HICONSM
);
2989 if (!ret
) ret
= (HICON
)GetClassLongPtrW( hwnd
, GCLP_HICON
);
2993 SetLastError( ERROR_INVALID_PARAMETER
);
2994 WIN_ReleasePtr( win
);
2998 if (!ret
) ret
= LoadIconW( 0, (const WCHAR
*)IDI_APPLICATION
);
3000 WIN_ReleasePtr( win
);
3001 return CopyIcon( ret
);