push bd0608bf727e2241b2885edad5c5c753477ffd22
[wine/hacks.git] / dlls / user32 / win.c
blob72f3cfcf15b8d4d5fc571e3f5fb954241d2ce252
1 /*
2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "config.h"
22 #include "wine/port.h"
24 #include <assert.h>
25 #include <stdarg.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include "windef.h"
29 #include "winbase.h"
30 #include "wine/winbase16.h"
31 #include "wine/winuser16.h"
32 #include "wownt32.h"
33 #include "wine/server.h"
34 #include "wine/unicode.h"
35 #include "win.h"
36 #include "user_private.h"
37 #include "controls.h"
38 #include "winerror.h"
39 #include "wine/debug.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(win);
43 #define NB_USER_HANDLES ((LAST_USER_HANDLE - FIRST_USER_HANDLE + 1) >> 1)
44 #define USER_HANDLE_TO_INDEX(hwnd) ((LOWORD(hwnd) - FIRST_USER_HANDLE) >> 1)
46 /**********************************************************************/
48 /* helper for Get/SetWindowLong */
49 static inline LONG_PTR get_win_data( const void *ptr, UINT size )
51 if (size == sizeof(WORD))
53 WORD ret;
54 memcpy( &ret, ptr, sizeof(ret) );
55 return ret;
57 else if (size == sizeof(DWORD))
59 DWORD ret;
60 memcpy( &ret, ptr, sizeof(ret) );
61 return ret;
63 else
65 LONG_PTR ret;
66 memcpy( &ret, ptr, sizeof(ret) );
67 return ret;
71 /* helper for Get/SetWindowLong */
72 static inline void set_win_data( void *ptr, LONG_PTR val, UINT size )
74 if (size == sizeof(WORD))
76 WORD newval = val;
77 memcpy( ptr, &newval, sizeof(newval) );
79 else if (size == sizeof(DWORD))
81 DWORD newval = val;
82 memcpy( ptr, &newval, sizeof(newval) );
84 else
86 memcpy( ptr, &val, sizeof(val) );
91 static void *user_handles[NB_USER_HANDLES];
93 /***********************************************************************
94 * create_window_handle
96 * Create a window handle with the server.
98 static WND *create_window_handle( HWND parent, HWND owner, LPCWSTR name,
99 HINSTANCE instance, BOOL unicode )
101 WORD index;
102 WND *win;
103 HWND full_parent = 0, full_owner = 0;
104 struct tagCLASS *class = NULL;
105 user_handle_t handle = 0;
106 int extra_bytes = 0;
108 /* if 16-bit instance, map to module handle */
109 if (instance && !HIWORD(instance))
110 instance = HINSTANCE_32(GetExePtr(HINSTANCE_16(instance)));
112 SERVER_START_REQ( create_window )
114 req->parent = parent;
115 req->owner = owner;
116 req->instance = instance;
117 if (!(req->atom = get_int_atom_value( name )) && name)
118 wine_server_add_data( req, name, strlenW(name)*sizeof(WCHAR) );
119 if (!wine_server_call_err( req ))
121 handle = reply->handle;
122 full_parent = reply->parent;
123 full_owner = reply->owner;
124 extra_bytes = reply->extra;
125 class = reply->class_ptr;
128 SERVER_END_REQ;
130 if (!handle)
132 WARN( "error %d creating window\n", GetLastError() );
133 return NULL;
136 if (!(win = HeapAlloc( GetProcessHeap(), 0, sizeof(WND) + extra_bytes - sizeof(win->wExtra) )))
138 SERVER_START_REQ( destroy_window )
140 req->handle = handle;
141 wine_server_call( req );
143 SERVER_END_REQ;
144 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
145 return NULL;
148 if (!parent) /* if parent is 0 we don't have a desktop window yet */
150 struct user_thread_info *thread_info = get_user_thread_info();
152 if (!thread_info->desktop) thread_info->desktop = full_parent ? full_parent : handle;
153 else assert( full_parent == thread_info->desktop );
154 if (full_parent && !USER_Driver->pCreateDesktopWindow( thread_info->desktop ))
155 ERR( "failed to create desktop window\n" );
158 USER_Lock();
160 index = USER_HANDLE_TO_INDEX(handle);
161 assert( index < NB_USER_HANDLES );
162 user_handles[index] = win;
163 win->hwndSelf = handle;
164 win->parent = full_parent;
165 win->owner = full_owner;
166 win->dwMagic = WND_MAGIC;
167 win->flags = 0;
168 win->cbWndExtra = extra_bytes;
169 memset( win->wExtra, 0, extra_bytes );
170 CLASS_AddWindow( class, win, unicode );
171 return win;
175 /***********************************************************************
176 * free_window_handle
178 * Free a window handle.
180 static WND *free_window_handle( HWND hwnd )
182 WND *ptr;
183 WORD index = USER_HANDLE_TO_INDEX(hwnd);
185 if (index >= NB_USER_HANDLES) return NULL;
186 USER_Lock();
187 if ((ptr = user_handles[index]))
189 SERVER_START_REQ( destroy_window )
191 req->handle = hwnd;
192 if (!wine_server_call_err( req ))
194 user_handles[index] = NULL;
195 ptr->dwMagic = 0;
197 else
198 ptr = NULL;
200 SERVER_END_REQ;
202 USER_Unlock();
203 HeapFree( GetProcessHeap(), 0, ptr );
204 return ptr;
208 /*******************************************************************
209 * list_window_children
211 * Build an array of the children of a given window. The array must be
212 * freed with HeapFree. Returns NULL when no windows are found.
214 static HWND *list_window_children( HWND hwnd, LPCWSTR class, DWORD tid )
216 HWND *list;
217 int size = 32;
219 for (;;)
221 int count = 0;
223 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
225 SERVER_START_REQ( get_window_children )
227 req->parent = hwnd;
228 req->tid = tid;
229 if (!(req->atom = get_int_atom_value( class )) && class)
230 wine_server_add_data( req, class, strlenW(class)*sizeof(WCHAR) );
231 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
232 if (!wine_server_call( req )) count = reply->count;
234 SERVER_END_REQ;
235 if (count && count < size)
237 list[count] = 0;
238 return list;
240 HeapFree( GetProcessHeap(), 0, list );
241 if (!count) break;
242 size = count + 1; /* restart with a large enough buffer */
244 return NULL;
248 /*******************************************************************
249 * list_window_parents
251 * Build an array of all parents of a given window, starting with
252 * the immediate parent. The array must be freed with HeapFree.
254 static HWND *list_window_parents( HWND hwnd )
256 WND *win;
257 HWND current, *list;
258 int pos = 0, size = 16, count = 0;
260 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
262 current = hwnd;
263 for (;;)
265 if (!(win = WIN_GetPtr( current ))) goto empty;
266 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
267 if (win == WND_DESKTOP)
269 if (!pos) goto empty;
270 list[pos] = 0;
271 return list;
273 list[pos] = current = win->parent;
274 WIN_ReleasePtr( win );
275 if (++pos == size - 1)
277 /* need to grow the list */
278 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
279 if (!new_list) goto empty;
280 list = new_list;
281 size += 16;
285 /* at least one parent belongs to another process, have to query the server */
287 for (;;)
289 count = 0;
290 SERVER_START_REQ( get_window_parents )
292 req->handle = hwnd;
293 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
294 if (!wine_server_call( req )) count = reply->count;
296 SERVER_END_REQ;
297 if (!count) goto empty;
298 if (size > count)
300 list[count] = 0;
301 return list;
303 HeapFree( GetProcessHeap(), 0, list );
304 size = count + 1;
305 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
308 empty:
309 HeapFree( GetProcessHeap(), 0, list );
310 return NULL;
314 /*******************************************************************
315 * send_parent_notify
317 static void send_parent_notify( HWND hwnd, UINT msg )
319 if ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_CHILD | WS_POPUP)) == WS_CHILD &&
320 !(GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY))
322 HWND parent = GetParent(hwnd);
323 if (parent && parent != GetDesktopWindow())
324 SendMessageW( parent, WM_PARENTNOTIFY,
325 MAKEWPARAM( msg, GetWindowLongPtrW( hwnd, GWLP_ID )), (LPARAM)hwnd );
330 /*******************************************************************
331 * get_server_window_text
333 * Retrieve the window text from the server.
335 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
337 size_t len = 0;
339 SERVER_START_REQ( get_window_text )
341 req->handle = hwnd;
342 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
343 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
345 SERVER_END_REQ;
346 text[len / sizeof(WCHAR)] = 0;
350 /***********************************************************************
351 * WIN_GetPtr
353 * Return a pointer to the WND structure if local to the process,
354 * or WND_OTHER_PROCESS if handle may be valid in other process.
355 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
357 WND *WIN_GetPtr( HWND hwnd )
359 WND * ptr;
360 WORD index = USER_HANDLE_TO_INDEX(hwnd);
362 if (index >= NB_USER_HANDLES) return NULL;
364 USER_Lock();
365 if ((ptr = user_handles[index]))
367 if (ptr->dwMagic == WND_MAGIC &&
368 (hwnd == ptr->hwndSelf || !HIWORD(hwnd) || HIWORD(hwnd) == 0xffff))
369 return ptr;
370 ptr = NULL;
372 else if (index == USER_HANDLE_TO_INDEX(GetDesktopWindow()))
374 if (hwnd == GetDesktopWindow() || !HIWORD(hwnd) || HIWORD(hwnd) == 0xffff) ptr = WND_DESKTOP;
375 else ptr = NULL;
377 else ptr = WND_OTHER_PROCESS;
378 USER_Unlock();
379 return ptr;
383 /***********************************************************************
384 * WIN_IsCurrentProcess
386 * Check whether a given window belongs to the current process (and return the full handle).
388 HWND WIN_IsCurrentProcess( HWND hwnd )
390 WND *ptr;
391 HWND ret;
393 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
394 ret = ptr->hwndSelf;
395 WIN_ReleasePtr( ptr );
396 return ret;
400 /***********************************************************************
401 * WIN_IsCurrentThread
403 * Check whether a given window belongs to the current thread (and return the full handle).
405 HWND WIN_IsCurrentThread( HWND hwnd )
407 WND *ptr;
408 HWND ret = 0;
410 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
411 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
412 WIN_ReleasePtr( ptr );
413 return ret;
417 /***********************************************************************
418 * WIN_Handle32
420 * Convert a 16-bit window handle to a full 32-bit handle.
422 HWND WIN_Handle32( HWND16 hwnd16 )
424 WND *ptr;
425 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
427 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
428 /* do sign extension for -2 and -3 */
429 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
431 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
433 if (ptr == WND_DESKTOP) return GetDesktopWindow();
435 if (ptr != WND_OTHER_PROCESS)
437 hwnd = ptr->hwndSelf;
438 WIN_ReleasePtr( ptr );
440 else /* may belong to another process */
442 SERVER_START_REQ( get_window_info )
444 req->handle = hwnd;
445 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
447 SERVER_END_REQ;
449 return hwnd;
453 /***********************************************************************
454 * WIN_SetOwner
456 * Change the owner of a window.
458 HWND WIN_SetOwner( HWND hwnd, HWND owner )
460 WND *win = WIN_GetPtr( hwnd );
461 HWND ret = 0;
463 if (!win || win == WND_DESKTOP) return 0;
464 if (win == WND_OTHER_PROCESS)
466 if (IsWindow(hwnd)) ERR( "cannot set owner %p on other process window %p\n", owner, hwnd );
467 return 0;
469 SERVER_START_REQ( set_window_owner )
471 req->handle = hwnd;
472 req->owner = owner;
473 if (!wine_server_call( req ))
475 win->owner = reply->full_owner;
476 ret = reply->prev_owner;
479 SERVER_END_REQ;
480 WIN_ReleasePtr( win );
481 return ret;
485 /***********************************************************************
486 * WIN_SetStyle
488 * Change the style of a window.
490 ULONG WIN_SetStyle( HWND hwnd, ULONG set_bits, ULONG clear_bits )
492 BOOL ok;
493 ULONG new_style, old_style = 0;
494 WND *win = WIN_GetPtr( hwnd );
496 if (!win || win == WND_DESKTOP) return 0;
497 if (win == WND_OTHER_PROCESS)
499 if (IsWindow(hwnd))
500 ERR( "cannot set style %x/%x on other process window %p\n",
501 set_bits, clear_bits, hwnd );
502 return 0;
504 new_style = (win->dwStyle | set_bits) & ~clear_bits;
505 if (new_style == win->dwStyle)
507 WIN_ReleasePtr( win );
508 return new_style;
510 SERVER_START_REQ( set_window_info )
512 req->handle = hwnd;
513 req->flags = SET_WIN_STYLE;
514 req->style = new_style;
515 req->extra_offset = -1;
516 if ((ok = !wine_server_call( req )))
518 old_style = reply->old_style;
519 win->dwStyle = new_style;
522 SERVER_END_REQ;
523 WIN_ReleasePtr( win );
524 if (ok) USER_Driver->pSetWindowStyle( hwnd, old_style );
525 return old_style;
529 /***********************************************************************
530 * WIN_GetRectangles
532 * Get the window and client rectangles.
534 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
536 WND *win = WIN_GetPtr( hwnd );
537 BOOL ret = TRUE;
539 if (!win) return FALSE;
540 if (win == WND_DESKTOP)
542 RECT rect;
543 rect.left = rect.top = 0;
544 rect.right = GetSystemMetrics(SM_CXSCREEN);
545 rect.bottom = GetSystemMetrics(SM_CYSCREEN);
546 if (rectWindow) *rectWindow = rect;
547 if (rectClient) *rectClient = rect;
549 else if (win == WND_OTHER_PROCESS)
551 SERVER_START_REQ( get_window_rectangles )
553 req->handle = hwnd;
554 if ((ret = !wine_server_call( req )))
556 if (rectWindow)
558 rectWindow->left = reply->window.left;
559 rectWindow->top = reply->window.top;
560 rectWindow->right = reply->window.right;
561 rectWindow->bottom = reply->window.bottom;
563 if (rectClient)
565 rectClient->left = reply->client.left;
566 rectClient->top = reply->client.top;
567 rectClient->right = reply->client.right;
568 rectClient->bottom = reply->client.bottom;
572 SERVER_END_REQ;
574 else
576 if (rectWindow) *rectWindow = win->rectWindow;
577 if (rectClient) *rectClient = win->rectClient;
578 WIN_ReleasePtr( win );
580 return ret;
584 /***********************************************************************
585 * WIN_DestroyWindow
587 * Destroy storage associated to a window. "Internals" p.358
589 LRESULT WIN_DestroyWindow( HWND hwnd )
591 WND *wndPtr;
592 HWND *list;
593 HMENU menu = 0, sys_menu;
595 TRACE("%p\n", hwnd );
597 /* free child windows */
598 if ((list = WIN_ListChildren( hwnd )))
600 int i;
601 for (i = 0; list[i]; i++)
603 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
604 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
606 HeapFree( GetProcessHeap(), 0, list );
609 /* Unlink now so we won't bother with the children later on */
610 SERVER_START_REQ( set_parent )
612 req->handle = hwnd;
613 req->parent = 0;
614 wine_server_call( req );
616 SERVER_END_REQ;
619 * Send the WM_NCDESTROY to the window being destroyed.
621 SendMessageW( hwnd, WM_NCDESTROY, 0, 0 );
623 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
625 WINPOS_CheckInternalPos( hwnd );
627 /* free resources associated with the window */
629 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
630 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
631 menu = (HMENU)wndPtr->wIDmenu;
632 sys_menu = wndPtr->hSysMenu;
633 WIN_ReleasePtr( wndPtr );
635 if (menu) DestroyMenu( menu );
636 if (sys_menu) DestroyMenu( sys_menu );
638 USER_Driver->pDestroyWindow( hwnd );
640 free_window_handle( hwnd );
641 return 0;
644 /***********************************************************************
645 * WIN_DestroyThreadWindows
647 * Destroy all children of 'wnd' owned by the current thread.
649 void WIN_DestroyThreadWindows( HWND hwnd )
651 HWND *list;
652 int i;
654 if (!(list = WIN_ListChildren( hwnd ))) return;
655 for (i = 0; list[i]; i++)
657 if (WIN_IsCurrentThread( list[i] ))
658 DestroyWindow( list[i] );
659 else
660 WIN_DestroyThreadWindows( list[i] );
662 HeapFree( GetProcessHeap(), 0, list );
666 /***********************************************************************
667 * WIN_FixCoordinates
669 * Fix the coordinates - Helper for WIN_CreateWindowEx.
670 * returns default show mode in sw.
672 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
674 #define IS_DEFAULT(x) ((x) == CW_USEDEFAULT || (x) == CW_USEDEFAULT16)
675 POINT pos[2];
677 if (cs->dwExStyle & WS_EX_MDICHILD)
679 UINT id = 0;
681 MDI_CalcDefaultChildPos(cs->hwndParent, -1, pos, 0, &id);
682 if (!(cs->style & WS_POPUP)) cs->hMenu = ULongToHandle(id);
684 TRACE("MDI child id %04x\n", id);
687 if (cs->style & (WS_CHILD | WS_POPUP))
689 if (cs->dwExStyle & WS_EX_MDICHILD)
691 if (IS_DEFAULT(cs->x))
693 cs->x = pos[0].x;
694 cs->y = pos[0].y;
696 if (IS_DEFAULT(cs->cx) || !cs->cx) cs->cx = pos[1].x;
697 if (IS_DEFAULT(cs->cy) || !cs->cy) cs->cy = pos[1].y;
699 else
701 if (IS_DEFAULT(cs->x)) cs->x = cs->y = 0;
702 if (IS_DEFAULT(cs->cx)) cs->cx = cs->cy = 0;
705 else /* overlapped window */
707 HMONITOR monitor;
708 MONITORINFO mon_info;
709 STARTUPINFOW info;
711 if (!IS_DEFAULT(cs->x) && !IS_DEFAULT(cs->cx) && !IS_DEFAULT(cs->cy)) return;
713 monitor = MonitorFromWindow( cs->hwndParent, MONITOR_DEFAULTTOPRIMARY );
714 mon_info.cbSize = sizeof(mon_info);
715 GetMonitorInfoW( monitor, &mon_info );
716 GetStartupInfoW( &info );
718 if (IS_DEFAULT(cs->x))
720 if (!IS_DEFAULT(cs->y)) *sw = cs->y;
721 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : mon_info.rcWork.left;
722 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : mon_info.rcWork.top;
725 if (IS_DEFAULT(cs->cx))
727 if (info.dwFlags & STARTF_USESIZE)
729 cs->cx = info.dwXSize;
730 cs->cy = info.dwYSize;
732 else
734 cs->cx = (mon_info.rcWork.right - mon_info.rcWork.left) * 3 / 4 - cs->x;
735 cs->cy = (mon_info.rcWork.bottom - mon_info.rcWork.top) * 3 / 4 - cs->y;
738 /* neither x nor cx are default. Check the y values .
739 * In the trace we see Outlook and Outlook Express using
740 * cy set to CW_USEDEFAULT when opening the address book.
742 else if (IS_DEFAULT(cs->cy))
744 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
745 cs->cy = (mon_info.rcWork.bottom - mon_info.rcWork.top) * 3 / 4 - cs->y;
748 #undef IS_DEFAULT
751 /***********************************************************************
752 * dump_window_styles
754 static void dump_window_styles( DWORD style, DWORD exstyle )
756 TRACE( "style:" );
757 if(style & WS_POPUP) TRACE(" WS_POPUP");
758 if(style & WS_CHILD) TRACE(" WS_CHILD");
759 if(style & WS_MINIMIZE) TRACE(" WS_MINIMIZE");
760 if(style & WS_VISIBLE) TRACE(" WS_VISIBLE");
761 if(style & WS_DISABLED) TRACE(" WS_DISABLED");
762 if(style & WS_CLIPSIBLINGS) TRACE(" WS_CLIPSIBLINGS");
763 if(style & WS_CLIPCHILDREN) TRACE(" WS_CLIPCHILDREN");
764 if(style & WS_MAXIMIZE) TRACE(" WS_MAXIMIZE");
765 if((style & WS_CAPTION) == WS_CAPTION) TRACE(" WS_CAPTION");
766 else
768 if(style & WS_BORDER) TRACE(" WS_BORDER");
769 if(style & WS_DLGFRAME) TRACE(" WS_DLGFRAME");
771 if(style & WS_VSCROLL) TRACE(" WS_VSCROLL");
772 if(style & WS_HSCROLL) TRACE(" WS_HSCROLL");
773 if(style & WS_SYSMENU) TRACE(" WS_SYSMENU");
774 if(style & WS_THICKFRAME) TRACE(" WS_THICKFRAME");
775 if (style & WS_CHILD)
777 if(style & WS_GROUP) TRACE(" WS_GROUP");
778 if(style & WS_TABSTOP) TRACE(" WS_TABSTOP");
780 else
782 if(style & WS_MINIMIZEBOX) TRACE(" WS_MINIMIZEBOX");
783 if(style & WS_MAXIMIZEBOX) TRACE(" WS_MAXIMIZEBOX");
786 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
787 #define DUMPED_STYLES \
788 (WS_POPUP | \
789 WS_CHILD | \
790 WS_MINIMIZE | \
791 WS_VISIBLE | \
792 WS_DISABLED | \
793 WS_CLIPSIBLINGS | \
794 WS_CLIPCHILDREN | \
795 WS_MAXIMIZE | \
796 WS_BORDER | \
797 WS_DLGFRAME | \
798 WS_VSCROLL | \
799 WS_HSCROLL | \
800 WS_SYSMENU | \
801 WS_THICKFRAME | \
802 WS_GROUP | \
803 WS_TABSTOP | \
804 WS_MINIMIZEBOX | \
805 WS_MAXIMIZEBOX)
807 if(style & ~DUMPED_STYLES) TRACE(" %08lx", style & ~DUMPED_STYLES);
808 TRACE("\n");
809 #undef DUMPED_STYLES
811 TRACE( "exstyle:" );
812 if(exstyle & WS_EX_DLGMODALFRAME) TRACE(" WS_EX_DLGMODALFRAME");
813 if(exstyle & WS_EX_DRAGDETECT) TRACE(" WS_EX_DRAGDETECT");
814 if(exstyle & WS_EX_NOPARENTNOTIFY) TRACE(" WS_EX_NOPARENTNOTIFY");
815 if(exstyle & WS_EX_TOPMOST) TRACE(" WS_EX_TOPMOST");
816 if(exstyle & WS_EX_ACCEPTFILES) TRACE(" WS_EX_ACCEPTFILES");
817 if(exstyle & WS_EX_TRANSPARENT) TRACE(" WS_EX_TRANSPARENT");
818 if(exstyle & WS_EX_MDICHILD) TRACE(" WS_EX_MDICHILD");
819 if(exstyle & WS_EX_TOOLWINDOW) TRACE(" WS_EX_TOOLWINDOW");
820 if(exstyle & WS_EX_WINDOWEDGE) TRACE(" WS_EX_WINDOWEDGE");
821 if(exstyle & WS_EX_CLIENTEDGE) TRACE(" WS_EX_CLIENTEDGE");
822 if(exstyle & WS_EX_CONTEXTHELP) TRACE(" WS_EX_CONTEXTHELP");
823 if(exstyle & WS_EX_RIGHT) TRACE(" WS_EX_RIGHT");
824 if(exstyle & WS_EX_RTLREADING) TRACE(" WS_EX_RTLREADING");
825 if(exstyle & WS_EX_LEFTSCROLLBAR) TRACE(" WS_EX_LEFTSCROLLBAR");
826 if(exstyle & WS_EX_CONTROLPARENT) TRACE(" WS_EX_CONTROLPARENT");
827 if(exstyle & WS_EX_STATICEDGE) TRACE(" WS_EX_STATICEDGE");
828 if(exstyle & WS_EX_APPWINDOW) TRACE(" WS_EX_APPWINDOW");
829 if(exstyle & WS_EX_LAYERED) TRACE(" WS_EX_LAYERED");
831 #define DUMPED_EX_STYLES \
832 (WS_EX_DLGMODALFRAME | \
833 WS_EX_DRAGDETECT | \
834 WS_EX_NOPARENTNOTIFY | \
835 WS_EX_TOPMOST | \
836 WS_EX_ACCEPTFILES | \
837 WS_EX_TRANSPARENT | \
838 WS_EX_MDICHILD | \
839 WS_EX_TOOLWINDOW | \
840 WS_EX_WINDOWEDGE | \
841 WS_EX_CLIENTEDGE | \
842 WS_EX_CONTEXTHELP | \
843 WS_EX_RIGHT | \
844 WS_EX_RTLREADING | \
845 WS_EX_LEFTSCROLLBAR | \
846 WS_EX_CONTROLPARENT | \
847 WS_EX_STATICEDGE | \
848 WS_EX_APPWINDOW | \
849 WS_EX_LAYERED)
851 if(exstyle & ~DUMPED_EX_STYLES) TRACE(" %08lx", exstyle & ~DUMPED_EX_STYLES);
852 TRACE("\n");
853 #undef DUMPED_EX_STYLES
857 /***********************************************************************
858 * WIN_CreateWindowEx
860 * Implementation of CreateWindowEx().
862 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, LPCWSTR className, UINT flags )
864 INT sw = SW_SHOW;
865 WND *wndPtr;
866 HWND hwnd, parent, owner, top_child = 0;
867 BOOL unicode = (flags & WIN_ISUNICODE) != 0;
868 MDICREATESTRUCTA mdi_cs;
870 TRACE("%s %s ex=%08x style=%08x %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
871 unicode ? debugstr_w((LPCWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
872 debugstr_w(className),
873 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
874 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
875 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
877 /* Fix the styles for MDI children */
878 if (cs->dwExStyle & WS_EX_MDICHILD)
880 UINT flags = 0;
882 wndPtr = WIN_GetPtr(cs->hwndParent);
883 if (wndPtr && wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
885 flags = wndPtr->flags;
886 WIN_ReleasePtr(wndPtr);
889 if (!(flags & WIN_ISMDICLIENT))
891 WARN("WS_EX_MDICHILD, but parent %p is not MDIClient\n", cs->hwndParent);
892 return 0;
895 /* cs->lpCreateParams of WM_[NC]CREATE is different for MDI children.
896 * MDICREATESTRUCT members have the originally passed values.
898 * Note: we rely on the fact that MDICREATESTRUCTA and MDICREATESTRUCTW
899 * have the same layout.
901 mdi_cs.szClass = cs->lpszClass;
902 mdi_cs.szTitle = cs->lpszName;
903 mdi_cs.hOwner = cs->hInstance;
904 mdi_cs.x = cs->x;
905 mdi_cs.y = cs->y;
906 mdi_cs.cx = cs->cx;
907 mdi_cs.cy = cs->cy;
908 mdi_cs.style = cs->style;
909 mdi_cs.lParam = (LPARAM)cs->lpCreateParams;
911 cs->lpCreateParams = (LPVOID)&mdi_cs;
913 if (GetWindowLongW(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
915 if (cs->style & WS_POPUP)
917 TRACE("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n");
918 return 0;
920 cs->style |= WS_CHILD | WS_CLIPSIBLINGS;
922 else
924 cs->style &= ~WS_POPUP;
925 cs->style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
926 WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
929 top_child = GetWindow(cs->hwndParent, GW_CHILD);
931 if (top_child)
933 /* Restore current maximized child */
934 if((cs->style & WS_VISIBLE) && IsZoomed(top_child))
936 TRACE("Restoring current maximized child %p\n", top_child);
937 SendMessageW( top_child, WM_SETREDRAW, FALSE, 0 );
938 ShowWindow( top_child, SW_SHOWNORMAL );
939 SendMessageW( top_child, WM_SETREDRAW, TRUE, 0 );
944 /* Find the parent window */
946 parent = cs->hwndParent;
947 owner = 0;
949 if (cs->hwndParent == HWND_MESSAGE)
951 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
952 * message window (style: WS_POPUP|WS_DISABLED)
954 FIXME("Parent is HWND_MESSAGE\n");
955 parent = GetDesktopWindow();
957 else if (cs->hwndParent)
959 if ((cs->style & (WS_CHILD|WS_POPUP)) != WS_CHILD)
961 parent = GetDesktopWindow();
962 owner = cs->hwndParent;
965 else
967 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
969 WARN("No parent for child window\n" );
970 SetLastError(ERROR_TLW_WITH_WSCHILD);
971 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
973 if (className != (LPCWSTR)DESKTOP_CLASS_ATOM) /* are we creating the desktop itself? */
974 parent = GetDesktopWindow();
977 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
979 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
980 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
981 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
982 cs->dwExStyle |= WS_EX_WINDOWEDGE;
983 else
984 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
986 /* Create the window structure */
988 if (!(wndPtr = create_window_handle( parent, owner, className, cs->hInstance, unicode )))
989 return 0;
990 hwnd = wndPtr->hwndSelf;
992 /* Fill the window structure */
994 wndPtr->tid = GetCurrentThreadId();
995 wndPtr->hInstance = cs->hInstance;
996 wndPtr->text = NULL;
997 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
998 wndPtr->dwExStyle = cs->dwExStyle;
999 wndPtr->wIDmenu = 0;
1000 wndPtr->helpContext = 0;
1001 wndPtr->pVScroll = NULL;
1002 wndPtr->pHScroll = NULL;
1003 wndPtr->userdata = 0;
1004 wndPtr->hIcon = 0;
1005 wndPtr->hIconSmall = 0;
1006 wndPtr->hSysMenu = 0;
1007 wndPtr->flags |= (flags & WIN_ISWIN32);
1009 if (wndPtr->dwStyle & WS_SYSMENU) SetSystemMenu( hwnd, 0 );
1012 * Correct the window styles.
1014 * It affects only the style loaded into the WIN structure.
1017 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
1019 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1020 if (!(wndPtr->dwStyle & WS_POPUP))
1021 wndPtr->dwStyle |= WS_CAPTION;
1025 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1026 * why does the user get to set it?
1029 if ((wndPtr->dwExStyle & WS_EX_DLGMODALFRAME) ||
1030 (wndPtr->dwStyle & (WS_DLGFRAME | WS_THICKFRAME)))
1031 wndPtr->dwExStyle |= WS_EX_WINDOWEDGE;
1032 else
1033 wndPtr->dwExStyle &= ~WS_EX_WINDOWEDGE;
1035 if (!(wndPtr->dwStyle & (WS_CHILD | WS_POPUP)))
1036 wndPtr->flags |= WIN_NEED_SIZE;
1038 SERVER_START_REQ( set_window_info )
1040 req->handle = hwnd;
1041 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE | SET_WIN_UNICODE;
1042 req->style = wndPtr->dwStyle;
1043 req->ex_style = wndPtr->dwExStyle;
1044 req->instance = (void *)wndPtr->hInstance;
1045 req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
1046 req->extra_offset = -1;
1047 wine_server_call( req );
1049 SERVER_END_REQ;
1051 /* Set the window menu */
1053 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
1055 if (cs->hMenu)
1057 if (!MENU_SetMenu(hwnd, cs->hMenu))
1059 WIN_ReleasePtr( wndPtr );
1060 free_window_handle( hwnd );
1061 return 0;
1064 else
1066 LPCSTR menuName = (LPCSTR)GetClassLongPtrA( hwnd, GCLP_MENUNAME );
1067 if (menuName)
1069 if (!cs->hInstance || HIWORD(cs->hInstance))
1070 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1071 else
1072 cs->hMenu = HMENU_32(LoadMenu16(HINSTANCE_16(cs->hInstance),menuName));
1074 if (cs->hMenu) MENU_SetMenu( hwnd, cs->hMenu );
1078 else SetWindowLongPtrW( hwnd, GWLP_ID, (ULONG_PTR)cs->hMenu );
1079 WIN_ReleasePtr( wndPtr );
1081 if (!USER_Driver->pCreateWindow( hwnd, cs, unicode))
1083 WIN_DestroyWindow( hwnd );
1084 return 0;
1087 /* Notify the parent window only */
1089 send_parent_notify( hwnd, WM_CREATE );
1090 if (!IsWindow( hwnd )) return 0;
1092 if (cs->style & WS_VISIBLE)
1094 if (cs->style & WS_MAXIMIZE)
1095 sw = SW_SHOW;
1096 else if (cs->style & WS_MINIMIZE)
1097 sw = SW_SHOWMINIMIZED;
1099 ShowWindow( hwnd, sw );
1100 if (cs->dwExStyle & WS_EX_MDICHILD)
1102 SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
1103 /* ShowWindow won't activate child windows */
1104 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE );
1108 /* Call WH_SHELL hook */
1110 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1111 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1113 TRACE("created window %p\n", hwnd);
1114 return hwnd;
1118 /***********************************************************************
1119 * CreateWindow (USER.41)
1121 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1122 DWORD style, INT16 x, INT16 y, INT16 width,
1123 INT16 height, HWND16 parent, HMENU16 menu,
1124 HINSTANCE16 instance, LPVOID data )
1126 return CreateWindowEx16( 0, className, windowName, style,
1127 x, y, width, height, parent, menu, instance, data );
1131 /***********************************************************************
1132 * CreateWindowEx (USER.452)
1134 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1135 LPCSTR windowName, DWORD style, INT16 x,
1136 INT16 y, INT16 width, INT16 height,
1137 HWND16 parent, HMENU16 menu,
1138 HINSTANCE16 instance, LPVOID data )
1140 CREATESTRUCTA cs;
1141 char buffer[256];
1143 /* Fix the coordinates */
1145 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1146 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1147 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1148 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1150 /* Create the window */
1152 cs.lpCreateParams = data;
1153 cs.hInstance = HINSTANCE_32(instance);
1154 cs.hMenu = HMENU_32(menu);
1155 cs.hwndParent = WIN_Handle32( parent );
1156 cs.style = style;
1157 cs.lpszName = windowName;
1158 cs.lpszClass = className;
1159 cs.dwExStyle = exStyle;
1161 if (!IS_INTRESOURCE(className))
1163 WCHAR bufferW[256];
1165 if (!MultiByteToWideChar( CP_ACP, 0, className, -1, bufferW, sizeof(bufferW)/sizeof(WCHAR) ))
1166 return 0;
1167 return HWND_16( WIN_CreateWindowEx( &cs, bufferW, 0 ));
1169 else
1171 if (!GlobalGetAtomNameA( LOWORD(className), buffer, sizeof(buffer) ))
1173 ERR( "bad atom %x\n", LOWORD(className));
1174 return 0;
1176 cs.lpszClass = buffer;
1177 return HWND_16( WIN_CreateWindowEx( &cs, (LPCWSTR)className, 0 ));
1182 /***********************************************************************
1183 * CreateWindowExA (USER32.@)
1185 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1186 LPCSTR windowName, DWORD style, INT x,
1187 INT y, INT width, INT height,
1188 HWND parent, HMENU menu,
1189 HINSTANCE instance, LPVOID data )
1191 CREATESTRUCTA cs;
1193 cs.lpCreateParams = data;
1194 cs.hInstance = instance;
1195 cs.hMenu = menu;
1196 cs.hwndParent = parent;
1197 cs.x = x;
1198 cs.y = y;
1199 cs.cx = width;
1200 cs.cy = height;
1201 cs.style = style;
1202 cs.lpszName = windowName;
1203 cs.lpszClass = className;
1204 cs.dwExStyle = exStyle;
1206 if (!IS_INTRESOURCE(className))
1208 WCHAR bufferW[256];
1209 if (!MultiByteToWideChar( CP_ACP, 0, className, -1, bufferW, sizeof(bufferW)/sizeof(WCHAR) ))
1210 return 0;
1211 return WIN_CreateWindowEx( &cs, bufferW, WIN_ISWIN32 );
1213 return WIN_CreateWindowEx( &cs, (LPCWSTR)className, WIN_ISWIN32 );
1217 /***********************************************************************
1218 * CreateWindowExW (USER32.@)
1220 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1221 LPCWSTR windowName, DWORD style, INT x,
1222 INT y, INT width, INT height,
1223 HWND parent, HMENU menu,
1224 HINSTANCE instance, LPVOID data )
1226 CREATESTRUCTW cs;
1228 cs.lpCreateParams = data;
1229 cs.hInstance = instance;
1230 cs.hMenu = menu;
1231 cs.hwndParent = parent;
1232 cs.x = x;
1233 cs.y = y;
1234 cs.cx = width;
1235 cs.cy = height;
1236 cs.style = style;
1237 cs.lpszName = windowName;
1238 cs.lpszClass = className;
1239 cs.dwExStyle = exStyle;
1241 /* Note: we rely on the fact that CREATESTRUCTA and */
1242 /* CREATESTRUCTW have the same layout. */
1243 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, className, WIN_ISWIN32 | WIN_ISUNICODE );
1247 /***********************************************************************
1248 * WIN_SendDestroyMsg
1250 static void WIN_SendDestroyMsg( HWND hwnd )
1252 GUITHREADINFO info;
1254 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1256 if (hwnd == info.hwndCaret) DestroyCaret();
1257 if (hwnd == info.hwndActive) WINPOS_ActivateOtherWindow( hwnd );
1261 * Send the WM_DESTROY to the window.
1263 SendMessageW( hwnd, WM_DESTROY, 0, 0);
1266 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1267 * make sure that the window still exists when we come back.
1269 if (IsWindow(hwnd))
1271 HWND* pWndArray;
1272 int i;
1274 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1276 for (i = 0; pWndArray[i]; i++)
1278 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1280 HeapFree( GetProcessHeap(), 0, pWndArray );
1282 else
1283 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1287 /***********************************************************************
1288 * DestroyWindow (USER32.@)
1290 BOOL WINAPI DestroyWindow( HWND hwnd )
1292 BOOL is_child;
1294 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1296 SetLastError( ERROR_ACCESS_DENIED );
1297 return FALSE;
1300 TRACE("(%p)\n", hwnd);
1302 /* Call hooks */
1304 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1306 if (MENU_IsMenuActive() == hwnd)
1307 EndMenu();
1309 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1311 if (is_child)
1313 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1314 send_parent_notify( hwnd, WM_DESTROY );
1316 else if (!GetWindow( hwnd, GW_OWNER ))
1318 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1319 /* FIXME: clean up palette - see "Internals" p.352 */
1322 if (!IsWindow(hwnd)) return TRUE;
1324 /* Hide the window */
1325 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)
1327 /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
1328 if (is_child)
1329 ShowWindow( hwnd, SW_HIDE );
1330 else
1331 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1332 SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW );
1335 if (!IsWindow(hwnd)) return TRUE;
1337 /* Recursively destroy owned windows */
1339 if (!is_child)
1341 for (;;)
1343 int i, got_one = 0;
1344 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1345 if (list)
1347 for (i = 0; list[i]; i++)
1349 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1350 if (WIN_IsCurrentThread( list[i] ))
1352 DestroyWindow( list[i] );
1353 got_one = 1;
1354 continue;
1356 WIN_SetOwner( list[i], 0 );
1358 HeapFree( GetProcessHeap(), 0, list );
1360 if (!got_one) break;
1364 /* Send destroy messages */
1366 WIN_SendDestroyMsg( hwnd );
1367 if (!IsWindow( hwnd )) return TRUE;
1369 if (GetClipboardOwner() == hwnd)
1370 CLIPBOARD_ReleaseOwner();
1372 /* Destroy the window storage */
1374 WIN_DestroyWindow( hwnd );
1375 return TRUE;
1379 /***********************************************************************
1380 * CloseWindow (USER32.@)
1382 BOOL WINAPI CloseWindow( HWND hwnd )
1384 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1385 ShowWindow( hwnd, SW_MINIMIZE );
1386 return TRUE;
1390 /***********************************************************************
1391 * OpenIcon (USER32.@)
1393 BOOL WINAPI OpenIcon( HWND hwnd )
1395 if (!IsIconic( hwnd )) return FALSE;
1396 ShowWindow( hwnd, SW_SHOWNORMAL );
1397 return TRUE;
1401 /***********************************************************************
1402 * FindWindowExW (USER32.@)
1404 HWND WINAPI FindWindowExW( HWND parent, HWND child, LPCWSTR className, LPCWSTR title )
1406 HWND *list = NULL;
1407 HWND retvalue = 0;
1408 int i = 0, len = 0;
1409 WCHAR *buffer = NULL;
1411 if (!parent) parent = GetDesktopWindow();
1412 if (title)
1414 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1415 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1418 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1420 if (child)
1422 child = WIN_GetFullHandle( child );
1423 while (list[i] && list[i] != child) i++;
1424 if (!list[i]) goto done;
1425 i++; /* start from next window */
1428 if (title)
1430 while (list[i])
1432 if (GetWindowTextW( list[i], buffer, len + 1 ) && !strcmpiW( buffer, title )) break;
1433 i++;
1436 retvalue = list[i];
1438 done:
1439 HeapFree( GetProcessHeap(), 0, list );
1440 HeapFree( GetProcessHeap(), 0, buffer );
1441 return retvalue;
1446 /***********************************************************************
1447 * FindWindowA (USER32.@)
1449 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1451 HWND ret = FindWindowExA( 0, 0, className, title );
1452 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1453 return ret;
1457 /***********************************************************************
1458 * FindWindowExA (USER32.@)
1460 HWND WINAPI FindWindowExA( HWND parent, HWND child, LPCSTR className, LPCSTR title )
1462 LPWSTR titleW = NULL;
1463 HWND hwnd = 0;
1465 if (title)
1467 DWORD len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1468 if (!(titleW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1469 MultiByteToWideChar( CP_ACP, 0, title, -1, titleW, len );
1472 if (!IS_INTRESOURCE(className))
1474 WCHAR classW[256];
1475 if (MultiByteToWideChar( CP_ACP, 0, className, -1, classW, sizeof(classW)/sizeof(WCHAR) ))
1476 hwnd = FindWindowExW( parent, child, classW, titleW );
1478 else
1480 hwnd = FindWindowExW( parent, child, (LPCWSTR)className, titleW );
1483 HeapFree( GetProcessHeap(), 0, titleW );
1484 return hwnd;
1488 /***********************************************************************
1489 * FindWindowW (USER32.@)
1491 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1493 return FindWindowExW( 0, 0, className, title );
1497 /**********************************************************************
1498 * GetDesktopWindow (USER32.@)
1500 HWND WINAPI GetDesktopWindow(void)
1502 struct user_thread_info *thread_info = get_user_thread_info();
1504 if (thread_info->desktop) return thread_info->desktop;
1506 SERVER_START_REQ( get_desktop_window )
1508 req->force = 0;
1509 if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1511 SERVER_END_REQ;
1513 if (!thread_info->desktop)
1515 static const WCHAR command_line[] = {'\\','e','x','p','l','o','r','e','r','.','e','x','e',' ','/','d','e','s','k','t','o','p',0};
1516 STARTUPINFOW si;
1517 PROCESS_INFORMATION pi;
1518 WCHAR cmdline[MAX_PATH + sizeof(command_line)/sizeof(WCHAR)];
1520 memset( &si, 0, sizeof(si) );
1521 si.cb = sizeof(si);
1522 GetSystemDirectoryW( cmdline, MAX_PATH );
1523 lstrcatW( cmdline, command_line );
1524 if (CreateProcessW( NULL, cmdline, NULL, NULL, FALSE, DETACHED_PROCESS,
1525 NULL, NULL, &si, &pi ))
1527 TRACE( "started explorer pid %04x tid %04x\n", pi.dwProcessId, pi.dwThreadId );
1528 WaitForInputIdle( pi.hProcess, 10000 );
1529 CloseHandle( pi.hThread );
1530 CloseHandle( pi.hProcess );
1533 else WARN( "failed to start explorer, err %d\n", GetLastError() );
1535 SERVER_START_REQ( get_desktop_window )
1537 req->force = 1;
1538 if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1540 SERVER_END_REQ;
1543 if (!thread_info->desktop || !USER_Driver->pCreateDesktopWindow( thread_info->desktop ))
1544 ERR( "failed to create desktop window\n" );
1546 return thread_info->desktop;
1550 /*******************************************************************
1551 * EnableWindow (USER32.@)
1553 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1555 BOOL retvalue;
1556 HWND full_handle;
1558 if (is_broadcast(hwnd))
1560 SetLastError( ERROR_INVALID_PARAMETER );
1561 return FALSE;
1564 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1565 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1567 hwnd = full_handle;
1569 TRACE("( %p, %d )\n", hwnd, enable);
1571 retvalue = !IsWindowEnabled( hwnd );
1573 if (enable && retvalue)
1575 WIN_SetStyle( hwnd, 0, WS_DISABLED );
1576 SendMessageW( hwnd, WM_ENABLE, TRUE, 0 );
1578 else if (!enable && !retvalue)
1580 HWND capture_wnd;
1582 SendMessageW( hwnd, WM_CANCELMODE, 0, 0);
1584 WIN_SetStyle( hwnd, WS_DISABLED, 0 );
1586 if (hwnd == GetFocus())
1587 SetFocus( 0 ); /* A disabled window can't have the focus */
1589 capture_wnd = GetCapture();
1590 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1591 ReleaseCapture(); /* A disabled window can't capture the mouse */
1593 SendMessageW( hwnd, WM_ENABLE, FALSE, 0 );
1595 return retvalue;
1599 /***********************************************************************
1600 * IsWindowEnabled (USER32.@)
1602 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1604 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1608 /***********************************************************************
1609 * IsWindowUnicode (USER32.@)
1611 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1613 WND * wndPtr;
1614 BOOL retvalue = FALSE;
1616 if (!(wndPtr = WIN_GetPtr(hwnd))) return FALSE;
1618 if (wndPtr == WND_DESKTOP) return TRUE;
1620 if (wndPtr != WND_OTHER_PROCESS)
1622 retvalue = (wndPtr->flags & WIN_ISUNICODE) != 0;
1623 WIN_ReleasePtr( wndPtr );
1625 else
1627 SERVER_START_REQ( get_window_info )
1629 req->handle = hwnd;
1630 if (!wine_server_call_err( req )) retvalue = reply->is_unicode;
1632 SERVER_END_REQ;
1634 return retvalue;
1638 /**********************************************************************
1639 * WIN_GetWindowLong
1641 * Helper function for GetWindowLong().
1643 static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, UINT size, BOOL unicode )
1645 LONG_PTR retvalue = 0;
1646 WND *wndPtr;
1648 if (offset == GWLP_HWNDPARENT)
1650 HWND parent = GetAncestor( hwnd, GA_PARENT );
1651 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1652 return (ULONG_PTR)parent;
1655 if (!(wndPtr = WIN_GetPtr( hwnd )))
1657 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1658 return 0;
1661 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1663 if (offset == GWLP_WNDPROC)
1665 SetLastError( ERROR_ACCESS_DENIED );
1666 return 0;
1668 SERVER_START_REQ( set_window_info )
1670 req->handle = hwnd;
1671 req->flags = 0; /* don't set anything, just retrieve */
1672 req->extra_offset = (offset >= 0) ? offset : -1;
1673 req->extra_size = (offset >= 0) ? size : 0;
1674 if (!wine_server_call_err( req ))
1676 switch(offset)
1678 case GWL_STYLE: retvalue = reply->old_style; break;
1679 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1680 case GWLP_ID: retvalue = reply->old_id; break;
1681 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1682 case GWLP_USERDATA: retvalue = reply->old_user_data; break;
1683 default:
1684 if (offset >= 0) retvalue = get_win_data( &reply->old_extra_value, size );
1685 else SetLastError( ERROR_INVALID_INDEX );
1686 break;
1690 SERVER_END_REQ;
1691 return retvalue;
1694 /* now we have a valid wndPtr */
1696 if (offset >= 0)
1698 if (offset > (int)(wndPtr->cbWndExtra - size))
1700 WARN("Invalid offset %d\n", offset );
1701 WIN_ReleasePtr( wndPtr );
1702 SetLastError( ERROR_INVALID_INDEX );
1703 return 0;
1705 retvalue = get_win_data( (char *)wndPtr->wExtra + offset, size );
1707 /* Special case for dialog window procedure */
1708 if ((offset == DWLP_DLGPROC) && (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG))
1709 retvalue = (LONG_PTR)WINPROC_GetProc( (WNDPROC)retvalue, unicode );
1710 WIN_ReleasePtr( wndPtr );
1711 return retvalue;
1714 switch(offset)
1716 case GWLP_USERDATA: retvalue = wndPtr->userdata; break;
1717 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1718 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1719 case GWLP_ID: retvalue = (ULONG_PTR)wndPtr->wIDmenu; break;
1720 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wndPtr->hInstance; break;
1721 case GWLP_WNDPROC:
1722 /* This looks like a hack only for the edit control (see tests). This makes these controls
1723 * more tolerant to A/W mismatches. The lack of W->A->W conversion for such a mismatch suggests
1724 * that the hack is in GetWindowLongPtr[AW], not in winprocs.
1726 if (wndPtr->winproc == EDIT_winproc_handle && (!unicode != !(wndPtr->flags & WIN_ISUNICODE)))
1727 retvalue = (ULONG_PTR)wndPtr->winproc;
1728 else
1729 retvalue = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, unicode );
1730 break;
1731 default:
1732 WARN("Unknown offset %d\n", offset );
1733 SetLastError( ERROR_INVALID_INDEX );
1734 break;
1736 WIN_ReleasePtr(wndPtr);
1737 return retvalue;
1741 /**********************************************************************
1742 * WIN_SetWindowLong
1744 * Helper function for SetWindowLong().
1746 * 0 is the failure code. However, in the case of failure SetLastError
1747 * must be set to distinguish between a 0 return value and a failure.
1749 LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, UINT size, LONG_PTR newval, BOOL unicode )
1751 STYLESTRUCT style;
1752 BOOL ok;
1753 LONG_PTR retval = 0;
1754 WND *wndPtr;
1756 TRACE( "%p %d %lx %c\n", hwnd, offset, newval, unicode ? 'W' : 'A' );
1758 if (is_broadcast(hwnd))
1760 SetLastError( ERROR_INVALID_PARAMETER );
1761 return FALSE;
1764 if (!(wndPtr = WIN_GetPtr( hwnd )))
1766 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1767 return 0;
1769 if (wndPtr == WND_DESKTOP)
1771 /* can't change anything on the desktop window */
1772 SetLastError( ERROR_ACCESS_DENIED );
1773 return 0;
1775 if (wndPtr == WND_OTHER_PROCESS)
1777 if (offset == GWLP_WNDPROC)
1779 SetLastError( ERROR_ACCESS_DENIED );
1780 return 0;
1782 if (offset > 32767 || offset < -32767)
1784 SetLastError( ERROR_INVALID_INDEX );
1785 return 0;
1787 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, MAKEWPARAM( offset, size ), newval );
1790 /* first some special cases */
1791 switch( offset )
1793 case GWL_STYLE:
1794 case GWL_EXSTYLE:
1795 style.styleOld =
1796 offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
1797 style.styleNew = newval;
1798 WIN_ReleasePtr( wndPtr );
1799 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
1800 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
1801 newval = style.styleNew;
1802 break;
1803 case GWLP_HWNDPARENT:
1804 if (wndPtr->parent == GetDesktopWindow())
1806 WIN_ReleasePtr( wndPtr );
1807 return (ULONG_PTR)WIN_SetOwner( hwnd, (HWND)newval );
1809 else
1811 WIN_ReleasePtr( wndPtr );
1812 return (ULONG_PTR)SetParent( hwnd, (HWND)newval );
1814 case GWLP_WNDPROC:
1816 WNDPROC proc;
1817 UINT old_flags = wndPtr->flags;
1818 retval = WIN_GetWindowLong( hwnd, offset, size, unicode );
1819 if (unicode) proc = WINPROC_AllocProc( NULL, (WNDPROC)newval );
1820 else proc = WINPROC_AllocProc( (WNDPROC)newval, NULL );
1821 if (proc) wndPtr->winproc = proc;
1822 if (WINPROC_IsUnicode( proc, unicode )) wndPtr->flags |= WIN_ISUNICODE;
1823 else wndPtr->flags &= ~WIN_ISUNICODE;
1824 if (!((old_flags ^ wndPtr->flags) & WIN_ISUNICODE))
1826 WIN_ReleasePtr( wndPtr );
1827 return retval;
1829 /* update is_unicode flag on the server side */
1830 break;
1832 case GWLP_ID:
1833 case GWLP_HINSTANCE:
1834 case GWLP_USERDATA:
1835 break;
1836 case DWLP_DLGPROC:
1837 if ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
1838 (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG))
1840 WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWLP_DLGPROC);
1841 retval = (ULONG_PTR)WINPROC_GetProc( *ptr, unicode );
1842 if (unicode) *ptr = WINPROC_AllocProc( NULL, (WNDPROC)newval );
1843 else *ptr = WINPROC_AllocProc( (WNDPROC)newval, NULL );
1844 WIN_ReleasePtr( wndPtr );
1845 return retval;
1847 /* fall through */
1848 default:
1849 if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - size))
1851 WARN("Invalid offset %d\n", offset );
1852 WIN_ReleasePtr( wndPtr );
1853 SetLastError( ERROR_INVALID_INDEX );
1854 return 0;
1856 else if (get_win_data( (char *)wndPtr->wExtra + offset, size ) == newval)
1858 /* already set to the same value */
1859 WIN_ReleasePtr( wndPtr );
1860 return newval;
1862 break;
1865 SERVER_START_REQ( set_window_info )
1867 req->handle = hwnd;
1868 req->extra_offset = -1;
1869 switch(offset)
1871 case GWL_STYLE:
1872 req->flags = SET_WIN_STYLE;
1873 req->style = newval;
1874 break;
1875 case GWL_EXSTYLE:
1876 req->flags = SET_WIN_EXSTYLE;
1877 /* WS_EX_TOPMOST can only be changed through SetWindowPos */
1878 newval = (newval & ~WS_EX_TOPMOST) | (wndPtr->dwExStyle & WS_EX_TOPMOST);
1879 req->ex_style = newval;
1880 break;
1881 case GWLP_ID:
1882 req->flags = SET_WIN_ID;
1883 req->id = newval;
1884 break;
1885 case GWLP_HINSTANCE:
1886 req->flags = SET_WIN_INSTANCE;
1887 req->instance = (void *)newval;
1888 break;
1889 case GWLP_WNDPROC:
1890 req->flags = SET_WIN_UNICODE;
1891 req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
1892 break;
1893 case GWLP_USERDATA:
1894 req->flags = SET_WIN_USERDATA;
1895 req->user_data = newval;
1896 break;
1897 default:
1898 req->flags = SET_WIN_EXTRA;
1899 req->extra_offset = offset;
1900 req->extra_size = size;
1901 set_win_data( &req->extra_value, newval, size );
1903 if ((ok = !wine_server_call_err( req )))
1905 switch(offset)
1907 case GWL_STYLE:
1908 wndPtr->dwStyle = newval;
1909 retval = reply->old_style;
1910 break;
1911 case GWL_EXSTYLE:
1912 wndPtr->dwExStyle = newval;
1913 retval = reply->old_ex_style;
1914 break;
1915 case GWLP_ID:
1916 wndPtr->wIDmenu = newval;
1917 retval = reply->old_id;
1918 break;
1919 case GWLP_HINSTANCE:
1920 wndPtr->hInstance = (HINSTANCE)newval;
1921 retval = (ULONG_PTR)reply->old_instance;
1922 break;
1923 case GWLP_WNDPROC:
1924 break;
1925 case GWLP_USERDATA:
1926 wndPtr->userdata = newval;
1927 retval = reply->old_user_data;
1928 break;
1929 default:
1930 retval = get_win_data( (char *)wndPtr->wExtra + offset, size );
1931 set_win_data( (char *)wndPtr->wExtra + offset, newval, size );
1932 break;
1936 SERVER_END_REQ;
1937 WIN_ReleasePtr( wndPtr );
1939 if (!ok) return 0;
1941 if (offset == GWL_STYLE) USER_Driver->pSetWindowStyle( hwnd, retval );
1943 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
1944 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
1946 return retval;
1950 /**********************************************************************
1951 * GetWindowLong (USER.135)
1953 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
1955 WND *wndPtr;
1956 LONG_PTR retvalue;
1957 BOOL is_winproc = (offset == GWLP_WNDPROC);
1959 if (offset >= 0)
1961 if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
1963 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1964 return 0;
1966 if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
1968 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
1971 * Some programs try to access last element from 16 bit
1972 * code using illegal offset value. Hopefully this is
1973 * what those programs really expect.
1975 if (wndPtr->cbWndExtra >= 4 && offset == wndPtr->cbWndExtra - sizeof(WORD))
1977 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
1978 ERR( "- replaced invalid offset %d with %d\n", offset, offset2 );
1979 offset = offset2;
1981 else
1983 WARN("Invalid offset %d\n", offset );
1984 WIN_ReleasePtr( wndPtr );
1985 SetLastError( ERROR_INVALID_INDEX );
1986 return 0;
1989 is_winproc = ((offset == DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG));
1990 WIN_ReleasePtr( wndPtr );
1993 retvalue = GetWindowLongA( WIN_Handle32(hwnd), offset );
1994 if (is_winproc) retvalue = (LONG_PTR)WINPROC_GetProc16( (WNDPROC)retvalue, FALSE );
1995 return retvalue;
1999 /**********************************************************************
2000 * GetWindowWord (USER32.@)
2002 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
2004 switch(offset)
2006 case GWLP_ID:
2007 case GWLP_HINSTANCE:
2008 case GWLP_HWNDPARENT:
2009 break;
2010 default:
2011 if (offset < 0)
2013 WARN("Invalid offset %d\n", offset );
2014 SetLastError( ERROR_INVALID_INDEX );
2015 return 0;
2017 break;
2019 return WIN_GetWindowLong( hwnd, offset, sizeof(WORD), FALSE );
2023 /**********************************************************************
2024 * GetWindowLongA (USER32.@)
2026 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2028 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), FALSE );
2032 /**********************************************************************
2033 * GetWindowLongW (USER32.@)
2035 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2037 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), TRUE );
2041 /**********************************************************************
2042 * SetWindowLong (USER.136)
2044 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2046 WND *wndPtr;
2047 BOOL is_winproc = (offset == GWLP_WNDPROC);
2049 if (offset == DWLP_DLGPROC)
2051 if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2053 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2054 return 0;
2056 if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2058 is_winproc = ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
2059 (wndPtr->flags & WIN_ISDIALOG));
2060 WIN_ReleasePtr( wndPtr );
2064 if (is_winproc)
2066 WNDPROC new_proc = WINPROC_AllocProc16( (WNDPROC16)newval );
2067 WNDPROC old_proc = (WNDPROC)SetWindowLongPtrA( WIN_Handle32(hwnd), offset, (LONG_PTR)new_proc );
2068 return (LONG)WINPROC_GetProc16( (WNDPROC)old_proc, FALSE );
2070 else return SetWindowLongA( WIN_Handle32(hwnd), offset, newval );
2074 /**********************************************************************
2075 * SetWindowWord (USER32.@)
2077 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
2079 switch(offset)
2081 case GWLP_ID:
2082 case GWLP_HINSTANCE:
2083 case GWLP_HWNDPARENT:
2084 break;
2085 default:
2086 if (offset < 0)
2088 WARN("Invalid offset %d\n", offset );
2089 SetLastError( ERROR_INVALID_INDEX );
2090 return 0;
2092 break;
2094 return WIN_SetWindowLong( hwnd, offset, sizeof(WORD), newval, FALSE );
2098 /**********************************************************************
2099 * SetWindowLongA (USER32.@)
2101 * See SetWindowLongW.
2103 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2105 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, FALSE );
2109 /**********************************************************************
2110 * SetWindowLongW (USER32.@) Set window attribute
2112 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2113 * value in a window's extra memory.
2115 * The _hwnd_ parameter specifies the window. is the handle to a
2116 * window that has extra memory. The _newval_ parameter contains the
2117 * new attribute or extra memory value. If positive, the _offset_
2118 * parameter is the byte-addressed location in the window's extra
2119 * memory to set. If negative, _offset_ specifies the window
2120 * attribute to set, and should be one of the following values:
2122 * GWL_EXSTYLE The window's extended window style
2124 * GWL_STYLE The window's window style.
2126 * GWLP_WNDPROC Pointer to the window's window procedure.
2128 * GWLP_HINSTANCE The window's pplication instance handle.
2130 * GWLP_ID The window's identifier.
2132 * GWLP_USERDATA The window's user-specified data.
2134 * If the window is a dialog box, the _offset_ parameter can be one of
2135 * the following values:
2137 * DWLP_DLGPROC The address of the window's dialog box procedure.
2139 * DWLP_MSGRESULT The return value of a message
2140 * that the dialog box procedure processed.
2142 * DWLP_USER Application specific information.
2144 * RETURNS
2146 * If successful, returns the previous value located at _offset_. Otherwise,
2147 * returns 0.
2149 * NOTES
2151 * Extra memory for a window class is specified by a nonzero cbWndExtra
2152 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2153 * time of class creation.
2155 * Using GWL_WNDPROC to set a new window procedure effectively creates
2156 * a window subclass. Use CallWindowProc() in the new windows procedure
2157 * to pass messages to the superclass's window procedure.
2159 * The user data is reserved for use by the application which created
2160 * the window.
2162 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2163 * instead, call the EnableWindow() function to change the window's
2164 * disabled state.
2166 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2167 * SetParent() instead.
2169 * Win95:
2170 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2171 * it sends WM_STYLECHANGING before changing the settings
2172 * and WM_STYLECHANGED afterwards.
2173 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2175 LONG WINAPI SetWindowLongW(
2176 HWND hwnd, /* [in] window to alter */
2177 INT offset, /* [in] offset, in bytes, of location to alter */
2178 LONG newval /* [in] new value of location */
2180 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, TRUE );
2184 /*******************************************************************
2185 * GetWindowTextA (USER32.@)
2187 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2189 WCHAR *buffer;
2191 if (!lpString) return 0;
2193 if (WIN_IsCurrentProcess( hwnd ))
2194 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2196 /* when window belongs to other process, don't send a message */
2197 if (nMaxCount <= 0) return 0;
2198 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2199 get_server_window_text( hwnd, buffer, nMaxCount );
2200 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2201 lpString[nMaxCount-1] = 0;
2202 HeapFree( GetProcessHeap(), 0, buffer );
2203 return strlen(lpString);
2207 /*******************************************************************
2208 * InternalGetWindowText (USER32.@)
2210 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2212 WND *win;
2214 if (nMaxCount <= 0) return 0;
2215 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2216 if (win == WND_DESKTOP) lpString[0] = 0;
2217 else if (win != WND_OTHER_PROCESS)
2219 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2220 else lpString[0] = 0;
2221 WIN_ReleasePtr( win );
2223 else
2225 get_server_window_text( hwnd, lpString, nMaxCount );
2227 return strlenW(lpString);
2231 /*******************************************************************
2232 * GetWindowTextW (USER32.@)
2234 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2236 if (!lpString) return 0;
2238 if (WIN_IsCurrentProcess( hwnd ))
2239 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2241 /* when window belongs to other process, don't send a message */
2242 if (nMaxCount <= 0) return 0;
2243 get_server_window_text( hwnd, lpString, nMaxCount );
2244 return strlenW(lpString);
2248 /*******************************************************************
2249 * SetWindowTextA (USER32.@)
2250 * SetWindowText (USER32.@)
2252 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2254 if (is_broadcast(hwnd))
2256 SetLastError( ERROR_INVALID_PARAMETER );
2257 return FALSE;
2259 if (!WIN_IsCurrentProcess( hwnd ))
2260 WARN( "setting text %s of other process window %p should not use SendMessage\n",
2261 debugstr_a(lpString), hwnd );
2262 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2266 /*******************************************************************
2267 * SetWindowTextW (USER32.@)
2269 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2271 if (is_broadcast(hwnd))
2273 SetLastError( ERROR_INVALID_PARAMETER );
2274 return FALSE;
2276 if (!WIN_IsCurrentProcess( hwnd ))
2277 WARN( "setting text %s of other process window %p should not use SendMessage\n",
2278 debugstr_w(lpString), hwnd );
2279 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2283 /*******************************************************************
2284 * GetWindowTextLengthA (USER32.@)
2286 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2288 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2291 /*******************************************************************
2292 * GetWindowTextLengthW (USER32.@)
2294 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2296 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2300 /*******************************************************************
2301 * IsWindow (USER32.@)
2303 BOOL WINAPI IsWindow( HWND hwnd )
2305 WND *ptr;
2306 BOOL ret;
2308 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2309 if (ptr == WND_DESKTOP) return TRUE;
2311 if (ptr != WND_OTHER_PROCESS)
2313 WIN_ReleasePtr( ptr );
2314 return TRUE;
2317 /* check other processes */
2318 SERVER_START_REQ( get_window_info )
2320 req->handle = hwnd;
2321 ret = !wine_server_call_err( req );
2323 SERVER_END_REQ;
2324 return ret;
2328 /***********************************************************************
2329 * GetWindowThreadProcessId (USER32.@)
2331 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2333 WND *ptr;
2334 DWORD tid = 0;
2336 if (!(ptr = WIN_GetPtr( hwnd )))
2338 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2339 return 0;
2342 if (ptr != WND_OTHER_PROCESS && ptr != WND_DESKTOP)
2344 /* got a valid window */
2345 tid = ptr->tid;
2346 if (process) *process = GetCurrentProcessId();
2347 WIN_ReleasePtr( ptr );
2348 return tid;
2351 /* check other processes */
2352 SERVER_START_REQ( get_window_info )
2354 req->handle = hwnd;
2355 if (!wine_server_call_err( req ))
2357 tid = (DWORD)reply->tid;
2358 if (process) *process = (DWORD)reply->pid;
2361 SERVER_END_REQ;
2362 return tid;
2366 /*****************************************************************
2367 * GetParent (USER32.@)
2369 HWND WINAPI GetParent( HWND hwnd )
2371 WND *wndPtr;
2372 HWND retvalue = 0;
2374 if (!(wndPtr = WIN_GetPtr( hwnd )))
2376 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2377 return 0;
2379 if (wndPtr == WND_DESKTOP) return 0;
2380 if (wndPtr == WND_OTHER_PROCESS)
2382 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2383 if (style & (WS_POPUP | WS_CHILD))
2385 SERVER_START_REQ( get_window_tree )
2387 req->handle = hwnd;
2388 if (!wine_server_call_err( req ))
2390 if (style & WS_POPUP) retvalue = reply->owner;
2391 else if (style & WS_CHILD) retvalue = reply->parent;
2394 SERVER_END_REQ;
2397 else
2399 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2400 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2401 WIN_ReleasePtr( wndPtr );
2403 return retvalue;
2407 /*****************************************************************
2408 * GetAncestor (USER32.@)
2410 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2412 WND *win;
2413 HWND *list, ret = 0;
2415 switch(type)
2417 case GA_PARENT:
2418 if (!(win = WIN_GetPtr( hwnd )))
2420 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2421 return 0;
2423 if (win == WND_DESKTOP) return 0;
2424 if (win != WND_OTHER_PROCESS)
2426 ret = win->parent;
2427 WIN_ReleasePtr( win );
2429 else /* need to query the server */
2431 SERVER_START_REQ( get_window_tree )
2433 req->handle = hwnd;
2434 if (!wine_server_call_err( req )) ret = reply->parent;
2436 SERVER_END_REQ;
2438 break;
2440 case GA_ROOT:
2441 if (!(list = list_window_parents( hwnd ))) return 0;
2443 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2444 else
2446 int count = 2;
2447 while (list[count]) count++;
2448 ret = list[count - 2]; /* get the one before the desktop */
2450 HeapFree( GetProcessHeap(), 0, list );
2451 break;
2453 case GA_ROOTOWNER:
2454 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2455 for (;;)
2457 HWND parent = GetParent( ret );
2458 if (!parent) break;
2459 ret = parent;
2461 break;
2463 return ret;
2467 /*****************************************************************
2468 * SetParent (USER32.@)
2470 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2472 HWND full_handle;
2473 HWND old_parent = 0;
2474 BOOL was_visible;
2475 WND *wndPtr;
2476 BOOL ret;
2478 if (is_broadcast(hwnd) || is_broadcast(parent))
2480 SetLastError(ERROR_INVALID_PARAMETER);
2481 return 0;
2484 if (!parent) parent = GetDesktopWindow();
2485 else parent = WIN_GetFullHandle( parent );
2487 if (!IsWindow( parent ))
2489 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2490 return 0;
2493 /* Some applications try to set a child as a parent */
2494 if (IsChild(hwnd, parent))
2496 SetLastError( ERROR_INVALID_PARAMETER );
2497 return 0;
2500 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2501 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2503 /* Windows hides the window first, then shows it again
2504 * including the WM_SHOWWINDOW messages and all */
2505 was_visible = ShowWindow( hwnd, SW_HIDE );
2507 wndPtr = WIN_GetPtr( hwnd );
2508 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return 0;
2510 SERVER_START_REQ( set_parent )
2512 req->handle = hwnd;
2513 req->parent = parent;
2514 if ((ret = !wine_server_call( req )))
2516 old_parent = reply->old_parent;
2517 wndPtr->parent = parent = reply->full_parent;
2521 SERVER_END_REQ;
2522 WIN_ReleasePtr( wndPtr );
2523 if (!ret) return 0;
2525 USER_Driver->pSetParent( full_handle, parent, old_parent );
2527 /* SetParent additionally needs to make hwnd the topmost window
2528 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2529 WM_WINDOWPOSCHANGED notification messages.
2531 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0,
2532 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2533 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2534 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2536 return old_parent;
2540 /*******************************************************************
2541 * IsChild (USER32.@)
2543 BOOL WINAPI IsChild( HWND parent, HWND child )
2545 HWND *list = list_window_parents( child );
2546 int i;
2547 BOOL ret;
2549 if (!list) return FALSE;
2550 parent = WIN_GetFullHandle( parent );
2551 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2552 ret = list[i] && list[i+1];
2553 HeapFree( GetProcessHeap(), 0, list );
2554 return ret;
2558 /***********************************************************************
2559 * IsWindowVisible (USER32.@)
2561 BOOL WINAPI IsWindowVisible( HWND hwnd )
2563 HWND *list;
2564 BOOL retval = TRUE;
2565 int i;
2567 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2568 if (!(list = list_window_parents( hwnd ))) return TRUE;
2569 if (list[0] && list[1]) /* desktop window is considered always visible so we don't check it */
2571 for (i = 0; list[i+1]; i++)
2572 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2573 retval = !list[i+1];
2575 HeapFree( GetProcessHeap(), 0, list );
2576 return retval;
2580 /***********************************************************************
2581 * WIN_IsWindowDrawable
2583 * hwnd is drawable when it is visible, all parents are not
2584 * minimized, and it is itself not minimized unless we are
2585 * trying to draw its default class icon.
2587 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2589 HWND *list;
2590 BOOL retval = TRUE;
2591 int i;
2592 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2594 if (!(style & WS_VISIBLE)) return FALSE;
2595 if ((style & WS_MINIMIZE) && icon && GetClassLongPtrW( hwnd, GCLP_HICON )) return FALSE;
2597 if (!(list = list_window_parents( hwnd ))) return TRUE;
2598 if (list[0] && list[1]) /* desktop window is considered always visible so we don't check it */
2600 for (i = 0; list[i+1]; i++)
2601 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2602 break;
2603 retval = !list[i+1];
2605 HeapFree( GetProcessHeap(), 0, list );
2606 return retval;
2610 /*******************************************************************
2611 * GetTopWindow (USER32.@)
2613 HWND WINAPI GetTopWindow( HWND hwnd )
2615 if (!hwnd) hwnd = GetDesktopWindow();
2616 return GetWindow( hwnd, GW_CHILD );
2620 /*******************************************************************
2621 * GetWindow (USER32.@)
2623 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2625 HWND retval = 0;
2627 if (rel == GW_OWNER) /* this one may be available locally */
2629 WND *wndPtr = WIN_GetPtr( hwnd );
2630 if (!wndPtr)
2632 SetLastError( ERROR_INVALID_HANDLE );
2633 return 0;
2635 if (wndPtr == WND_DESKTOP) return 0;
2636 if (wndPtr != WND_OTHER_PROCESS)
2638 retval = wndPtr->owner;
2639 WIN_ReleasePtr( wndPtr );
2640 return retval;
2642 /* else fall through to server call */
2645 SERVER_START_REQ( get_window_tree )
2647 req->handle = hwnd;
2648 if (!wine_server_call_err( req ))
2650 switch(rel)
2652 case GW_HWNDFIRST:
2653 retval = reply->first_sibling;
2654 break;
2655 case GW_HWNDLAST:
2656 retval = reply->last_sibling;
2657 break;
2658 case GW_HWNDNEXT:
2659 retval = reply->next_sibling;
2660 break;
2661 case GW_HWNDPREV:
2662 retval = reply->prev_sibling;
2663 break;
2664 case GW_OWNER:
2665 retval = reply->owner;
2666 break;
2667 case GW_CHILD:
2668 retval = reply->first_child;
2669 break;
2673 SERVER_END_REQ;
2674 return retval;
2678 /*******************************************************************
2679 * ShowOwnedPopups (USER32.@)
2681 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2683 int count = 0;
2684 WND *pWnd;
2685 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2687 if (!win_array) return TRUE;
2689 while (win_array[count]) count++;
2690 while (--count >= 0)
2692 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2693 if (!(pWnd = WIN_GetPtr( win_array[count] ))) continue;
2694 if (pWnd == WND_OTHER_PROCESS) continue;
2695 if (fShow)
2697 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2699 WIN_ReleasePtr( pWnd );
2700 /* In Windows, ShowOwnedPopups(TRUE) generates
2701 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2702 * regardless of the state of the owner
2704 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_SHOWNORMAL, SW_PARENTOPENING);
2705 continue;
2708 else
2710 if (pWnd->dwStyle & WS_VISIBLE)
2712 WIN_ReleasePtr( pWnd );
2713 /* In Windows, ShowOwnedPopups(FALSE) generates
2714 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2715 * regardless of the state of the owner
2717 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2718 continue;
2721 WIN_ReleasePtr( pWnd );
2723 HeapFree( GetProcessHeap(), 0, win_array );
2724 return TRUE;
2728 /*******************************************************************
2729 * GetLastActivePopup (USER32.@)
2731 HWND WINAPI GetLastActivePopup( HWND hwnd )
2733 HWND retval = hwnd;
2735 SERVER_START_REQ( get_window_info )
2737 req->handle = hwnd;
2738 if (!wine_server_call_err( req )) retval = reply->last_active;
2740 SERVER_END_REQ;
2741 return retval;
2745 /*******************************************************************
2746 * WIN_ListChildren
2748 * Build an array of the children of a given window. The array must be
2749 * freed with HeapFree. Returns NULL when no windows are found.
2751 HWND *WIN_ListChildren( HWND hwnd )
2753 return list_window_children( hwnd, NULL, 0 );
2757 /*******************************************************************
2758 * EnumWindows (USER32.@)
2760 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2762 HWND *list;
2763 BOOL ret = TRUE;
2764 int i;
2766 USER_CheckNotLock();
2768 /* We have to build a list of all windows first, to avoid */
2769 /* unpleasant side-effects, for instance if the callback */
2770 /* function changes the Z-order of the windows. */
2772 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2774 /* Now call the callback function for every window */
2776 for (i = 0; list[i]; i++)
2778 /* Make sure that the window still exists */
2779 if (!IsWindow( list[i] )) continue;
2780 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2782 HeapFree( GetProcessHeap(), 0, list );
2783 return ret;
2787 /**********************************************************************
2788 * EnumThreadWindows (USER32.@)
2790 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2792 HWND *list;
2793 int i;
2795 USER_CheckNotLock();
2797 if (!(list = list_window_children( GetDesktopWindow(), NULL, id ))) return TRUE;
2799 /* Now call the callback function for every window */
2801 for (i = 0; list[i]; i++)
2802 if (!func( list[i], lParam )) break;
2803 HeapFree( GetProcessHeap(), 0, list );
2804 return TRUE;
2808 /**********************************************************************
2809 * WIN_EnumChildWindows
2811 * Helper function for EnumChildWindows().
2813 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2815 HWND *childList;
2816 BOOL ret = FALSE;
2818 for ( ; *list; list++)
2820 /* Make sure that the window still exists */
2821 if (!IsWindow( *list )) continue;
2822 /* Build children list first */
2823 childList = WIN_ListChildren( *list );
2825 ret = func( *list, lParam );
2827 if (childList)
2829 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2830 HeapFree( GetProcessHeap(), 0, childList );
2832 if (!ret) return FALSE;
2834 return TRUE;
2838 /**********************************************************************
2839 * EnumChildWindows (USER32.@)
2841 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2843 HWND *list;
2844 BOOL ret;
2846 USER_CheckNotLock();
2848 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2849 ret = WIN_EnumChildWindows( list, func, lParam );
2850 HeapFree( GetProcessHeap(), 0, list );
2851 return ret;
2855 /*******************************************************************
2856 * AnyPopup (USER.52)
2858 BOOL16 WINAPI AnyPopup16(void)
2860 return AnyPopup();
2864 /*******************************************************************
2865 * AnyPopup (USER32.@)
2867 BOOL WINAPI AnyPopup(void)
2869 int i;
2870 BOOL retvalue;
2871 HWND *list = WIN_ListChildren( GetDesktopWindow() );
2873 if (!list) return FALSE;
2874 for (i = 0; list[i]; i++)
2876 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
2878 retvalue = (list[i] != 0);
2879 HeapFree( GetProcessHeap(), 0, list );
2880 return retvalue;
2884 /*******************************************************************
2885 * FlashWindow (USER32.@)
2887 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2889 WND *wndPtr;
2891 TRACE("%p\n", hWnd);
2893 if (IsIconic( hWnd ))
2895 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
2897 wndPtr = WIN_GetPtr(hWnd);
2898 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
2899 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2901 wndPtr->flags |= WIN_NCACTIVATED;
2903 else
2905 wndPtr->flags &= ~WIN_NCACTIVATED;
2907 WIN_ReleasePtr( wndPtr );
2908 return TRUE;
2910 else
2912 WPARAM wparam;
2914 wndPtr = WIN_GetPtr(hWnd);
2915 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
2916 hWnd = wndPtr->hwndSelf; /* make it a full handle */
2918 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2919 else wparam = (hWnd == GetForegroundWindow());
2921 WIN_ReleasePtr( wndPtr );
2922 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2923 return wparam;
2927 /*******************************************************************
2928 * FlashWindowEx (USER32.@)
2930 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
2932 FIXME("%p\n", pfwi);
2933 return TRUE;
2936 /*******************************************************************
2937 * GetWindowContextHelpId (USER32.@)
2939 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
2941 DWORD retval;
2942 WND *wnd = WIN_GetPtr( hwnd );
2943 if (!wnd || wnd == WND_DESKTOP) return 0;
2944 if (wnd == WND_OTHER_PROCESS)
2946 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
2947 return 0;
2949 retval = wnd->helpContext;
2950 WIN_ReleasePtr( wnd );
2951 return retval;
2955 /*******************************************************************
2956 * SetWindowContextHelpId (USER32.@)
2958 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
2960 WND *wnd = WIN_GetPtr( hwnd );
2961 if (!wnd || wnd == WND_DESKTOP) return FALSE;
2962 if (wnd == WND_OTHER_PROCESS)
2964 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
2965 return 0;
2967 wnd->helpContext = id;
2968 WIN_ReleasePtr( wnd );
2969 return TRUE;
2973 /*******************************************************************
2974 * DragDetect (USER32.@)
2976 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
2978 MSG msg;
2979 RECT rect;
2980 WORD wDragWidth = GetSystemMetrics(SM_CXDRAG);
2981 WORD wDragHeight= GetSystemMetrics(SM_CYDRAG);
2983 rect.left = pt.x - wDragWidth;
2984 rect.right = pt.x + wDragWidth;
2986 rect.top = pt.y - wDragHeight;
2987 rect.bottom = pt.y + wDragHeight;
2989 SetCapture(hWnd);
2991 while(1)
2993 while (PeekMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ))
2995 if( msg.message == WM_LBUTTONUP )
2997 ReleaseCapture();
2998 return 0;
3000 if( msg.message == WM_MOUSEMOVE )
3002 POINT tmp;
3003 tmp.x = (short)LOWORD(msg.lParam);
3004 tmp.y = (short)HIWORD(msg.lParam);
3005 if( !PtInRect( &rect, tmp ))
3007 ReleaseCapture();
3008 return 1;
3012 WaitMessage();
3014 return 0;
3017 /******************************************************************************
3018 * GetWindowModuleFileNameA (USER32.@)
3020 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3022 FIXME("GetWindowModuleFileNameA(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3023 hwnd, lpszFileName, cchFileNameMax);
3024 return 0;
3027 /******************************************************************************
3028 * GetWindowModuleFileNameW (USER32.@)
3030 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR lpszFileName, UINT cchFileNameMax)
3032 FIXME("GetWindowModuleFileNameW(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3033 hwnd, lpszFileName, cchFileNameMax);
3034 return 0;
3037 /******************************************************************************
3038 * GetWindowInfo (USER32.@)
3040 * Note: tests show that Windows doesn't check cbSize of the structure.
3042 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3044 if (!pwi) return FALSE;
3045 if (!IsWindow(hwnd)) return FALSE;
3047 GetWindowRect(hwnd, &pwi->rcWindow);
3048 GetClientRect(hwnd, &pwi->rcClient);
3049 /* translate to screen coordinates */
3050 MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3052 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3053 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3054 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3056 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3057 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3059 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3060 pwi->wCreatorVersion = 0x0400;
3062 return TRUE;
3065 /******************************************************************************
3066 * SwitchDesktop (USER32.@)
3068 * NOTES: Sets the current input or interactive desktop.
3070 BOOL WINAPI SwitchDesktop( HDESK hDesktop)
3072 FIXME("SwitchDesktop(hwnd %p) stub!\n", hDesktop);
3073 return TRUE;
3076 /*****************************************************************************
3077 * SetLayeredWindowAttributes (USER32.@)
3079 BOOL WINAPI SetLayeredWindowAttributes( HWND hWnd, COLORREF rgbKey,
3080 BYTE bAlpha, DWORD dwFlags )
3082 FIXME("(%p,0x%.8x,%d,%d): stub!\n", hWnd, rgbKey, bAlpha, dwFlags);
3083 return TRUE;
3086 /*****************************************************************************
3087 * UpdateLayeredWindow (USER32.@)
3089 BOOL WINAPI UpdateLayeredWindow( HWND hwnd, HDC hdcDst, POINT *pptDst, SIZE *psize,
3090 HDC hdcSrc, POINT *pptSrc, COLORREF crKey, BLENDFUNCTION *pblend,
3091 DWORD dwFlags)
3093 static int once;
3094 if (!once)
3096 once = 1;
3097 FIXME("(%p,%p,%p,%p,%p,%p,0x%08x,%p,%d): stub!\n",
3098 hwnd, hdcDst, pptDst, psize, hdcSrc, pptSrc, crKey, pblend, dwFlags);
3100 return 0;
3103 /* 64bit versions */
3105 #ifdef GetWindowLongPtrW
3106 #undef GetWindowLongPtrW
3107 #endif
3109 #ifdef GetWindowLongPtrA
3110 #undef GetWindowLongPtrA
3111 #endif
3113 #ifdef SetWindowLongPtrW
3114 #undef SetWindowLongPtrW
3115 #endif
3117 #ifdef SetWindowLongPtrA
3118 #undef SetWindowLongPtrA
3119 #endif
3121 /*****************************************************************************
3122 * GetWindowLongPtrW (USER32.@)
3124 LONG_PTR WINAPI GetWindowLongPtrW( HWND hwnd, INT offset )
3126 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), TRUE );
3129 /*****************************************************************************
3130 * GetWindowLongPtrA (USER32.@)
3132 LONG_PTR WINAPI GetWindowLongPtrA( HWND hwnd, INT offset )
3134 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), FALSE );
3137 /*****************************************************************************
3138 * SetWindowLongPtrW (USER32.@)
3140 LONG_PTR WINAPI SetWindowLongPtrW( HWND hwnd, INT offset, LONG_PTR newval )
3142 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, TRUE );
3145 /*****************************************************************************
3146 * SetWindowLongPtrA (USER32.@)
3148 LONG_PTR WINAPI SetWindowLongPtrA( HWND hwnd, INT offset, LONG_PTR newval )
3150 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, FALSE );