win32u: Move NtUserSetTimer implementation from user32.
[wine.git] / dlls / user32 / win.c
bloba21bdc62ed50fb512977084bd36d258d4a8d248e
1 /*
2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <assert.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <limits.h>
26 #include "user_private.h"
27 #include "winnls.h"
28 #include "winver.h"
29 #include "wine/server.h"
30 #include "wine/asm.h"
31 #include "win.h"
32 #include "controls.h"
33 #include "winerror.h"
34 #include "wine/exception.h"
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(win);
39 static DWORD process_layout = ~0u;
42 /***********************************************************************
43 * alloc_user_handle
45 HANDLE alloc_user_handle( struct user_object *ptr, unsigned int type )
47 return UlongToHandle( NtUserCallTwoParam( (UINT_PTR)ptr, type, NtUserAllocHandle ));
51 /***********************************************************************
52 * get_user_handle_ptr
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 );
66 USER_Unlock();
70 /***********************************************************************
71 * free_user_handle
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 )
88 WND *win;
89 HWND handle = 0, full_parent = 0, full_owner = 0;
90 struct tagCLASS *class = NULL;
91 int extra_bytes = 0;
92 DPI_AWARENESS awareness = GetAwarenessFromDpiAwarenessContext( GetThreadDpiAwarenessContext() );
93 UINT dpi = 0;
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;
102 req->style = style;
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;
112 dpi = reply->dpi;
113 awareness = reply->awareness;
114 class = wine_server_get_ptr( reply->class_ptr );
117 SERVER_END_REQ;
119 if (!handle)
121 WARN( "error %d creating window\n", GetLastError() );
122 return NULL;
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 );
133 SERVER_END_REQ;
134 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
135 return NULL;
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;
156 USER_Lock();
158 win->obj.handle = handle;
159 win->obj.type = NTUSER_OBJ_WINDOW;
160 win->parent = full_parent;
161 win->owner = full_owner;
162 win->class = class;
163 win->winproc = get_class_winproc( class );
164 win->cbWndExtra = extra_bytes;
165 win->dpi = dpi;
166 win->dpi_awareness = awareness;
167 NtUserCallTwoParam( HandleToUlong(handle), (UINT_PTR)win, NtUserSetHandlePtr );
168 if (WINPROC_IsUnicode( win->winproc, unicode )) win->flags |= WIN_ISUNICODE;
169 return win;
173 /***********************************************************************
174 * free_window_handle
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 );
190 SERVER_END_REQ;
191 USER_Unlock();
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 )
205 HWND *list;
206 int i, size = 128;
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;
212 for (;;)
214 int count = 0;
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 );
222 req->tid = tid;
223 req->atom = atom;
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;
228 SERVER_END_REQ;
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] );
234 list[count] = 0;
235 return list;
237 HeapFree( GetProcessHeap(), 0, list );
238 if (!count) break;
239 size = count + 1; /* restart with a large enough buffer */
241 return NULL;
245 /*******************************************************************
246 * send_parent_notify
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 /*******************************************************************
276 * is_desktop_window
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;
293 return FALSE;
297 /*******************************************************************
298 * Off-screen window surface.
301 struct offscreen_window_surface
303 struct window_surface header;
304 CRITICAL_SECTION cs;
305 RECT bounds;
306 char *bits;
307 BITMAPINFO info;
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] ) );
346 return impl->bits;
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 );
366 free( impl );
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;
383 SIZE_T size;
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 */
402 *surface = NULL;
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 /***********************************************************************
451 * WIN_GetPtr
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 )
459 WND *ptr;
461 if ((ptr = get_user_handle_ptr( hwnd, NTUSER_OBJ_WINDOW )) == WND_OTHER_PROCESS)
463 if (is_desktop_window( hwnd )) ptr = WND_DESKTOP;
465 return ptr;
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 )
476 WND *ptr;
477 HWND ret;
479 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
480 ret = ptr->obj.handle;
481 WIN_ReleasePtr( ptr );
482 return ret;
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 )
493 WND *ptr;
494 HWND ret = 0;
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 );
499 return ret;
503 /***********************************************************************
504 * win_set_flags
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 )
510 UINT ret;
511 WND *ptr = WIN_GetPtr( hwnd );
513 if (!ptr || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
514 ret = ptr->flags;
515 ptr->flags = (ret & ~clear_mask) | set_mask;
516 WIN_ReleasePtr( ptr );
517 return ret;
521 /***********************************************************************
522 * WIN_GetFullHandle
524 * Convert a possibly truncated window handle to a full 32-bit handle.
526 HWND WIN_GetFullHandle( HWND hwnd )
528 WND *ptr;
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 );
555 SERVER_END_REQ;
557 return hwnd;
561 /***********************************************************************
562 * WIN_SetOwner
564 * Change the owner of a window.
566 static HWND WIN_SetOwner( HWND hwnd, HWND owner )
568 WND *win = WIN_GetPtr( hwnd );
569 HWND ret = 0;
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 );
575 return 0;
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 );
587 SERVER_END_REQ;
588 WIN_ReleasePtr( win );
589 return ret;
593 /***********************************************************************
594 * WIN_SetStyle
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 /***********************************************************************
608 * WIN_GetRectangles
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 );
615 BOOL ret = TRUE;
617 if (!win)
619 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
620 return FALSE;
622 if (win == WND_DESKTOP)
624 RECT rect;
625 rect.left = rect.top = 0;
626 if (hwnd == get_hwnd_message_parent())
628 rect.right = 100;
629 rect.bottom = 100;
630 rect = rect_win_to_thread_dpi( hwnd, rect );
632 else
634 rect = get_primary_monitor_rect();
636 if (rectWindow) *rectWindow = rect;
637 if (rectClient) *rectClient = rect;
638 return TRUE;
640 if (win != WND_OTHER_PROCESS)
642 RECT window_rect = win->window_rect, client_rect = win->client_rect;
644 switch (relative)
646 case COORDS_CLIENT:
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 );
651 break;
652 case COORDS_WINDOW:
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 );
657 break;
658 case COORDS_PARENT:
659 if (win->parent)
661 WND *parent = WIN_GetPtr( win->parent );
662 if (parent == WND_DESKTOP) break;
663 if (!parent || parent == WND_OTHER_PROCESS)
665 WIN_ReleasePtr( win );
666 goto other_process;
668 if (parent->flags & WIN_CHILDREN_MOVED)
670 WIN_ReleasePtr( parent );
671 WIN_ReleasePtr( win );
672 goto other_process;
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 );
681 break;
682 case COORDS_SCREEN:
683 while (win->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 );
690 goto other_process;
692 WIN_ReleasePtr( win );
693 if (parent->flags & WIN_CHILDREN_MOVED)
695 WIN_ReleasePtr( parent );
696 goto other_process;
698 win = parent;
699 if (win->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 );
705 break;
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 );
710 return TRUE;
713 other_process:
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 )))
721 if (rectWindow)
723 rectWindow->left = reply->window.left;
724 rectWindow->top = reply->window.top;
725 rectWindow->right = reply->window.right;
726 rectWindow->bottom = reply->window.bottom;
728 if (rectClient)
730 rectClient->left = reply->client.left;
731 rectClient->top = reply->client.top;
732 rectClient->right = reply->client.right;
733 rectClient->bottom = reply->client.bottom;
737 SERVER_END_REQ;
738 return ret;
742 /***********************************************************************
743 * WIN_DestroyWindow
745 * Destroy storage associated to a window. "Internals" p.358
747 LRESULT WIN_DestroyWindow( HWND hwnd )
749 WND *wndPtr;
750 HWND *list;
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 )))
766 int i;
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 );
779 req->parent = 0;
780 wine_server_call( req );
782 SERVER_END_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 );
798 wndPtr->dce = NULL;
799 HeapFree( GetProcessHeap(), 0, wndPtr->text );
800 wndPtr->text = NULL;
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 );
810 if (surface)
812 register_window_surface( surface, NULL );
813 window_surface_release( surface );
816 USER_Driver->pDestroyWindow( hwnd );
818 free_window_handle( hwnd );
819 return 0;
823 /***********************************************************************
824 * next_thread_window
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;
840 HWND hwnd = 0;
842 USER_Lock();
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;
850 if (free_list)
852 SERVER_START_REQ( destroy_window )
854 req->handle = 0; /* destroy all thread windows */
855 wine_server_call( req );
857 SERVER_END_REQ;
859 USER_Unlock();
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 );
869 if (win->surface)
871 register_window_surface( win->surface, NULL );
872 window_surface_release( win->surface );
874 HeapFree( GetProcessHeap(), 0, win );
879 /***********************************************************************
880 * WIN_FixCoordinates
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)
888 POINT pos[2];
890 if (cs->dwExStyle & WS_EX_MDICHILD)
892 UINT id = 0;
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))
906 cs->x = pos[0].x;
907 cs->y = pos[0].y;
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;
912 else
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 */
920 HMONITOR monitor;
921 MONITORINFO mon_info;
922 STARTUPINFOW 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;
945 else
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;
961 #undef IS_DEFAULT
964 /***********************************************************************
965 * dump_window_styles
967 static void dump_window_styles( DWORD style, DWORD exstyle )
969 TRACE( "style:" );
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");
979 else
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");
993 else
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 | \
1002 WS_CHILD | \
1003 WS_MINIMIZE | \
1004 WS_VISIBLE | \
1005 WS_DISABLED | \
1006 WS_CLIPSIBLINGS | \
1007 WS_CLIPCHILDREN | \
1008 WS_MAXIMIZE | \
1009 WS_BORDER | \
1010 WS_DLGFRAME | \
1011 WS_VSCROLL | \
1012 WS_HSCROLL | \
1013 WS_SYSMENU | \
1014 WS_THICKFRAME | \
1015 WS_GROUP | \
1016 WS_TABSTOP | \
1017 WS_MINIMIZEBOX | \
1018 WS_MAXIMIZEBOX))
1020 if(style & ~DUMPED_STYLES) TRACE(" %08x", style & ~DUMPED_STYLES);
1021 TRACE("\n");
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 | \
1052 WS_EX_TOPMOST | \
1053 WS_EX_ACCEPTFILES | \
1054 WS_EX_TRANSPARENT | \
1055 WS_EX_MDICHILD | \
1056 WS_EX_TOOLWINDOW | \
1057 WS_EX_WINDOWEDGE | \
1058 WS_EX_CLIENTEDGE | \
1059 WS_EX_CONTEXTHELP | \
1060 WS_EX_RIGHT | \
1061 WS_EX_RTLREADING | \
1062 WS_EX_LEFTSCROLLBAR | \
1063 WS_EX_CONTROLPARENT | \
1064 WS_EX_STATICEDGE | \
1065 WS_EX_APPWINDOW | \
1066 WS_EX_LAYERED | \
1067 WS_EX_NOINHERITLAYOUT | \
1068 WS_EX_LAYOUTRTL | \
1069 WS_EX_COMPOSITED |\
1070 WS_EX_NOACTIVATE))
1072 if(exstyle & ~DUMPED_EX_STYLES) TRACE(" %08x", exstyle & ~DUMPED_EX_STYLES);
1073 TRACE("\n");
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 /***********************************************************************
1098 * fix_exstyle
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;
1106 else
1107 exstyle &= ~WS_EX_WINDOWEDGE;
1108 return exstyle;
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;
1119 LRESULT result;
1120 RECT rect;
1121 WND *wndPtr;
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;
1128 CREATESTRUCTW cbcs;
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);
1146 return 0;
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;
1158 mdi_cs.x = cs->x;
1159 mdi_cs.y = cs->y;
1160 mdi_cs.cx = cs->cx;
1161 mdi_cs.cy = cs->cy;
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");
1172 return 0;
1174 cs->style |= WS_CHILD | WS_CLIPSIBLINGS;
1176 else
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);
1185 if (top_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;
1206 owner = 0;
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;
1219 else
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;
1226 else
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" )))
1239 DWORD layout;
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 )))
1255 return 0;
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;
1269 wndPtr->hIcon = 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 );
1283 cbcs = *cs;
1284 cbtc.lpcs = &cbcs;
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 );
1290 return 0;
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 );
1326 SERVER_END_REQ;
1328 /* Set the window menu */
1330 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
1332 if (cs->hMenu)
1334 if (!MENU_SetMenu(hwnd, cs->hMenu))
1336 WIN_ReleasePtr( wndPtr );
1337 free_window_handle( hwnd );
1338 return 0;
1341 else
1343 LPCWSTR menuName = (LPCWSTR)GetClassLongPtrW( hwnd, GCLP_MENUNAME );
1344 if (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 */
1362 cx = cs->cx;
1363 cy = cs->cy;
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 );
1371 if (cx < 0) cx = 0;
1372 if (cy < 0) cy = 0;
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) );
1382 if (unicode)
1383 result = SendMessageW( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
1384 else
1385 result = SendMessageA( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
1386 if (!result)
1388 WARN( "%p: aborted by WM_NCCREATE\n", hwnd );
1389 goto failed;
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 );
1415 else goto failed;
1417 /* send WM_CREATE */
1419 if (unicode)
1420 result = SendMessageW( hwnd, WM_CREATE, 0, (LPARAM)cs );
1421 else
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))
1446 RECT newPos;
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 );
1462 return 0;
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)
1471 sw = SW_SHOW;
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 );
1491 return hwnd;
1493 failed:
1494 WIN_DestroyWindow( hwnd );
1495 SetThreadDpiAwarenessContext( context );
1496 return 0;
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 )
1509 CREATESTRUCTA cs;
1511 cs.lpCreateParams = data;
1512 cs.hInstance = instance;
1513 cs.hMenu = menu;
1514 cs.hwndParent = parent;
1515 cs.x = x;
1516 cs.y = y;
1517 cs.cx = width;
1518 cs.cy = height;
1519 cs.style = style;
1520 cs.lpszName = windowName;
1521 cs.lpszClass = className;
1522 cs.dwExStyle = exStyle;
1524 if (!IS_INTRESOURCE(className))
1526 WCHAR bufferW[256];
1527 if (!MultiByteToWideChar( CP_ACP, 0, className, -1, bufferW, ARRAY_SIZE( bufferW )))
1528 return 0;
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 )
1546 CREATESTRUCTW cs;
1548 cs.lpCreateParams = data;
1549 cs.hInstance = instance;
1550 cs.hMenu = menu;
1551 cs.hwndParent = parent;
1552 cs.x = x;
1553 cs.y = y;
1554 cs.cx = width;
1555 cs.cy = height;
1556 cs.style = style;
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 )
1570 GUITHREADINFO info;
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.
1590 if (IsWindow(hwnd))
1592 HWND* pWndArray;
1593 int i;
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 );
1603 else
1604 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1608 /***********************************************************************
1609 * DestroyWindow (USER32.@)
1611 BOOL WINAPI DestroyWindow( HWND hwnd )
1613 BOOL is_child;
1615 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || is_desktop_window( hwnd ))
1617 SetLastError( ERROR_ACCESS_DENIED );
1618 return FALSE;
1621 TRACE("(%p)\n", hwnd);
1623 /* Call hooks */
1625 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1627 if (MENU_IsMenuActive() == hwnd)
1628 EndMenu();
1630 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1632 if (is_child)
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() */
1649 if (is_child)
1650 ShowWindow( hwnd, SW_HIDE );
1651 else
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 */
1660 if (!is_child)
1662 for (;;)
1664 int i;
1665 BOOL got_one = FALSE;
1666 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1667 if (list)
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] );
1675 got_one = TRUE;
1676 continue;
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 );
1694 return TRUE;
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 );
1705 return TRUE;
1709 /***********************************************************************
1710 * OpenIcon (USER32.@)
1712 BOOL WINAPI OpenIcon( HWND hwnd )
1714 if (!IsIconic( hwnd )) return FALSE;
1715 ShowWindow( hwnd, SW_SHOWNORMAL );
1716 return TRUE;
1720 /***********************************************************************
1721 * FindWindowExW (USER32.@)
1723 HWND WINAPI FindWindowExW( HWND parent, HWND child, LPCWSTR className, LPCWSTR title )
1725 HWND *list;
1726 HWND retvalue = 0;
1727 int i = 0, len = 0;
1728 WCHAR *buffer = NULL;
1730 if (!parent && child) parent = GetDesktopWindow();
1731 else if (parent == HWND_MESSAGE) parent = get_hwnd_message_parent();
1733 if (title)
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;
1739 if (className)
1741 UNICODE_STRING str;
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;
1753 if (child)
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 */
1761 if (title)
1763 while (list[i])
1765 if (NtUserInternalGetWindowText( list[i], buffer, len + 1 ))
1767 if (!wcsicmp( buffer, title )) break;
1769 else
1771 if (!title[0]) break;
1773 i++;
1776 retvalue = list[i];
1778 done:
1779 HeapFree( GetProcessHeap(), 0, list );
1780 HeapFree( GetProcessHeap(), 0, buffer );
1781 return retvalue;
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);
1793 return ret;
1797 /***********************************************************************
1798 * FindWindowExA (USER32.@)
1800 HWND WINAPI FindWindowExA( HWND parent, HWND child, LPCSTR className, LPCSTR title )
1802 LPWSTR titleW = NULL;
1803 HWND hwnd = 0;
1805 if (title)
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))
1814 WCHAR classW[256];
1815 if (MultiByteToWideChar( CP_ACP, 0, className, -1, classW, ARRAY_SIZE( classW )))
1816 hwnd = FindWindowExW( parent, child, classW, titleW );
1818 else
1820 hwnd = FindWindowExW( parent, child, (LPCWSTR)className, titleW );
1823 HeapFree( GetProcessHeap(), 0, titleW );
1824 return hwnd;
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 )
1854 BOOL retvalue;
1856 if (is_broadcast(hwnd))
1858 SetLastError( ERROR_INVALID_PARAMETER );
1859 return FALSE;
1862 TRACE("( %p, %d )\n", hwnd, enable);
1864 if (enable)
1866 retvalue = (WIN_SetStyle( hwnd, 0, WS_DISABLED ) & WS_DISABLED) != 0;
1867 if (retvalue) SendMessageW( hwnd, WM_ENABLE, TRUE, 0 );
1869 else
1871 SendMessageW( hwnd, WM_CANCELMODE, 0, 0 );
1873 retvalue = (WIN_SetStyle( hwnd, WS_DISABLED, 0 ) & WS_DISABLED) != 0;
1874 if (!retvalue)
1876 if (hwnd == GetFocus())
1877 NtUserSetFocus( 0 ); /* A disabled window can't have the focus */
1879 SendMessageW( hwnd, WM_ENABLE, FALSE, 0 );
1882 return retvalue;
1886 /***********************************************************************
1887 * IsWindowEnabled (USER32.@)
1889 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1891 LONG ret;
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 )
1940 switch (offset)
1942 #ifdef _WIN64
1943 case GWLP_WNDPROC:
1944 case GWLP_HINSTANCE:
1945 case GWLP_HWNDPARENT:
1946 WARN( "Invalid offset %d\n", offset );
1947 SetLastError( ERROR_INVALID_INDEX );
1948 return 0;
1949 #endif
1950 default:
1951 return NtUserCallHwndParam( hwnd, offset, NtUserGetWindowLongA );
1956 /**********************************************************************
1957 * GetWindowLongW (USER32.@)
1959 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
1961 switch (offset)
1963 #ifdef _WIN64
1964 case GWLP_WNDPROC:
1965 case GWLP_HINSTANCE:
1966 case GWLP_HWNDPARENT:
1967 WARN( "Invalid offset %d\n", offset );
1968 SetLastError( ERROR_INVALID_INDEX );
1969 return 0;
1970 #endif
1971 default:
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 )
1984 switch (offset)
1986 #ifdef _WIN64
1987 case GWLP_WNDPROC:
1988 case GWLP_HINSTANCE:
1989 case GWLP_HWNDPARENT:
1990 WARN( "Invalid offset %d\n", offset );
1991 SetLastError( ERROR_INVALID_INDEX );
1992 return 0;
1993 #endif
1994 default:
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.
2035 * RETURNS
2037 * If successful, returns the previous value located at _offset_. Otherwise,
2038 * returns 0.
2040 * NOTES
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
2051 * the window.
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
2055 * disabled state.
2057 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2058 * SetParent() instead.
2060 * Win95:
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 */
2072 switch (offset)
2074 #ifdef _WIN64
2075 case GWLP_WNDPROC:
2076 case GWLP_HINSTANCE:
2077 case GWLP_HWNDPARENT:
2078 WARN("Invalid offset %d\n", offset );
2079 SetLastError( ERROR_INVALID_INDEX );
2080 return 0;
2081 #endif
2082 default:
2083 return NtUserSetWindowLong( hwnd, offset, newval, FALSE );
2088 /*******************************************************************
2089 * GetWindowTextA (USER32.@)
2091 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2093 WCHAR *buffer;
2094 int ret = 0;
2096 if (!lpString || nMaxCount <= 0) return 0;
2098 __TRY
2100 lpString[0] = 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);
2116 __EXCEPT_PAGE_FAULT
2118 ret = 0;
2120 __ENDTRY
2122 return ret;
2126 /*******************************************************************
2127 * GetWindowTextW (USER32.@)
2129 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2131 int ret;
2133 if (!lpString || nMaxCount <= 0) return 0;
2135 __TRY
2137 lpString[0] = 0;
2139 if (WIN_IsCurrentProcess( hwnd ))
2141 ret = (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2143 else
2145 /* when window belongs to other process, don't send a message */
2146 ret = NtUserInternalGetWindowText( hwnd, lpString, nMaxCount );
2149 __EXCEPT_PAGE_FAULT
2151 ret = 0;
2153 __ENDTRY
2155 return ret;
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 );
2168 return FALSE;
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 );
2185 return FALSE;
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 )
2199 CPINFO info;
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 )
2303 int count = 0;
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;
2312 if (fShow)
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);
2321 else
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 );
2332 return TRUE;
2336 /*******************************************************************
2337 * GetLastActivePopup (USER32.@)
2339 HWND WINAPI GetLastActivePopup( HWND hwnd )
2341 HWND retval = 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 );
2348 SERVER_END_REQ;
2349 return retval;
2353 /*******************************************************************
2354 * WIN_ListChildren
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 )
2361 if (!hwnd)
2363 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2364 return NULL;
2366 return list_window_children( 0, hwnd, NULL, 0 );
2370 /*******************************************************************
2371 * EnumWindows (USER32.@)
2373 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2375 HWND *list;
2376 BOOL ret = TRUE;
2377 int i;
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 );
2396 return ret;
2400 /**********************************************************************
2401 * EnumThreadWindows (USER32.@)
2403 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2405 HWND *list;
2406 int i;
2407 BOOL ret = TRUE;
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 );
2418 return ret;
2422 /***********************************************************************
2423 * EnumDesktopWindows (USER32.@)
2425 BOOL WINAPI EnumDesktopWindows( HDESK desktop, WNDENUMPROC func, LPARAM lparam )
2427 HWND *list;
2428 int i;
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 );
2437 return TRUE;
2441 #ifdef __i386__
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,
2447 "pushl %ebp\n\t"
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"
2454 "call *8(%ebp)\n\t"
2455 "leave\n\t"
2456 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
2457 __ASM_CFI(".cfi_same_value %ebp\n\t")
2458 "ret" )
2459 #else
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 )
2473 HWND *childList;
2474 BOOL ret = FALSE;
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 );
2485 if (childList)
2487 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2488 HeapFree( GetProcessHeap(), 0, childList );
2490 if (!ret) return FALSE;
2492 return TRUE;
2496 /**********************************************************************
2497 * EnumChildWindows (USER32.@)
2499 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2501 HWND *list;
2502 BOOL ret;
2504 USER_CheckNotLock();
2506 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2507 ret = WIN_EnumChildWindows( list, func, lParam );
2508 HeapFree( GetProcessHeap(), 0, list );
2509 return ret;
2513 /*******************************************************************
2514 * AnyPopup (USER32.@)
2516 BOOL WINAPI AnyPopup(void)
2518 int i;
2519 BOOL retvalue;
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 );
2529 return retvalue;
2533 /*******************************************************************
2534 * FlashWindow (USER32.@)
2536 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2538 FLASHWINFO finfo;
2540 finfo.cbSize = sizeof(FLASHWINFO);
2541 finfo.dwFlags = bInvert ? FLASHW_ALL : FLASHW_STOP;
2542 finfo.uCount = 1;
2543 finfo.dwTimeout = 0;
2544 finfo.hwnd = hWnd;
2545 return NtUserFlashWindowEx( &finfo );
2549 /*******************************************************************
2550 * GetWindowContextHelpId (USER32.@)
2552 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
2554 DWORD retval;
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 );
2560 return 0;
2562 retval = wnd->helpContext;
2563 WIN_ReleasePtr( wnd );
2564 return retval;
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 );
2578 return FALSE;
2580 wnd->helpContext = id;
2581 WIN_ReleasePtr( wnd );
2582 return TRUE;
2586 /*******************************************************************
2587 * DragDetect (USER32.@)
2589 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
2591 MSG msg;
2592 RECT rect;
2593 WORD wDragWidth, wDragHeight;
2595 TRACE( "%p,%s\n", hWnd, wine_dbgstr_point( &pt ) );
2597 if (!(NtUserGetKeyState( VK_LBUTTON ) & 0x8000))
2598 return FALSE;
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 );
2606 while(1)
2608 while (PeekMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ))
2610 if( msg.message == WM_LBUTTONUP )
2612 ReleaseCapture();
2613 return FALSE;
2615 if( msg.message == WM_MOUSEMOVE )
2617 POINT tmp;
2618 tmp.x = (short)LOWORD(msg.lParam);
2619 tmp.y = (short)HIWORD(msg.lParam);
2620 if( !PtInRect( &rect, tmp ))
2622 ReleaseCapture();
2623 return TRUE;
2627 WaitMessage();
2629 return FALSE;
2632 /******************************************************************************
2633 * GetWindowModuleFileNameA (USER32.@)
2635 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR module, UINT size )
2637 WND *win;
2638 HINSTANCE hinst;
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 );
2646 return 0;
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 )
2659 WND *win;
2660 HINSTANCE hinst;
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 );
2668 return 0;
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);
2694 return TRUE;
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 );
2715 return FALSE;
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,
2729 DWORD flags)
2731 UPDATELAYEREDWINDOWINFO info;
2733 if (flags & ULW_EX_NORESIZE) /* only valid for UpdateLayeredWindowIndirect */
2735 SetLastError( ERROR_INVALID_PARAMETER );
2736 return FALSE;
2738 info.cbSize = sizeof(info);
2739 info.hdcDst = hdcDst;
2740 info.pptDst = pptDst;
2741 info.psize = psize;
2742 info.hdcSrc = hdcSrc;
2743 info.pptSrc = pptSrc;
2744 info.crKey = crKey;
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 )
2759 if (!layout)
2761 SetLastError( ERROR_NOACCESS );
2762 return FALSE;
2764 if (process_layout == ~0u)
2766 WCHAR *str, buffer[MAX_PATH];
2767 DWORD i, version_layout = 0;
2768 UINT len;
2769 DWORD user_lang = GetUserDefaultLangID();
2770 DWORD *languages;
2771 void *data = NULL;
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;
2792 done:
2793 HeapFree( GetProcessHeap(), 0, data );
2794 process_layout = version_layout;
2796 *layout = process_layout;
2797 return TRUE;
2801 /******************************************************************************
2802 * SetProcessDefaultLayout [USER32.@]
2804 * Sets the default layout for parentless windows.
2806 BOOL WINAPI SetProcessDefaultLayout( DWORD layout )
2808 process_layout = layout;
2809 return TRUE;
2813 /* 64bit versions */
2815 #ifdef GetWindowLongPtrW
2816 #undef GetWindowLongPtrW
2817 #endif
2819 #ifdef GetWindowLongPtrA
2820 #undef GetWindowLongPtrA
2821 #endif
2823 #ifdef SetWindowLongPtrW
2824 #undef SetWindowLongPtrW
2825 #endif
2827 #ifdef SetWindowLongPtrA
2828 #undef SetWindowLongPtrA
2829 #endif
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);
2870 return FALSE;
2873 /*****************************************************************************
2874 * UnregisterTouchWindow (USER32.@)
2876 BOOL WINAPI UnregisterTouchWindow(HWND hwnd)
2878 FIXME("(%p): stub\n", hwnd);
2879 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2880 return FALSE;
2883 /*****************************************************************************
2884 * CloseTouchInputHandle (USER32.@)
2886 BOOL WINAPI CloseTouchInputHandle(HTOUCHINPUT handle)
2888 FIXME("(%p): stub\n", handle);
2889 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2890 return FALSE;
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);
2900 return FALSE;
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);
2910 return FALSE;
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);
2923 return FALSE;
2926 *affinity = WDA_NONE;
2927 return TRUE;
2930 /*****************************************************************************
2931 * SetWindowDisplayAffinity (USER32.@)
2933 BOOL WINAPI SetWindowDisplayAffinity(HWND hwnd, DWORD affinity)
2935 FIXME("(%p, %u): stub\n", hwnd, affinity);
2937 if (!hwnd)
2939 SetLastError(ERROR_INVALID_WINDOW_HANDLE);
2940 return FALSE;
2943 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2944 return FALSE;
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);
2954 return FALSE;
2957 /***********************************************************************
2958 * InternalGetWindowIcon (USER32.@)
2960 HICON WINAPI InternalGetWindowIcon( HWND hwnd, UINT type )
2962 WND *win = WIN_GetPtr( hwnd );
2963 HICON ret;
2965 TRACE( "hwnd %p, type %#x\n", hwnd, type );
2967 if (!win)
2969 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2970 return 0;
2972 if (win == WND_OTHER_PROCESS || win == WND_DESKTOP)
2974 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
2975 return 0;
2978 switch (type)
2980 case ICON_BIG:
2981 ret = win->hIcon;
2982 if (!ret) ret = (HICON)GetClassLongPtrW( hwnd, GCLP_HICON );
2983 break;
2985 case ICON_SMALL:
2986 case ICON_SMALL2:
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 );
2990 break;
2992 default:
2993 SetLastError( ERROR_INVALID_PARAMETER );
2994 WIN_ReleasePtr( win );
2995 return 0;
2998 if (!ret) ret = LoadIconW( 0, (const WCHAR *)IDI_APPLICATION );
3000 WIN_ReleasePtr( win );
3001 return CopyIcon( ret );