user32: Fix some compilation warnings in 64-bit mode.
[wine/wine-kai.git] / dlls / user32 / win.c
blobd9b3a2ec3e58b5b14c9495864ecf8f8e984287b3
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 "winproc.h"
37 #include "user_private.h"
38 #include "controls.h"
39 #include "winerror.h"
40 #include "wine/debug.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(win);
44 #define NB_USER_HANDLES ((LAST_USER_HANDLE - FIRST_USER_HANDLE + 1) >> 1)
45 #define USER_HANDLE_TO_INDEX(hwnd) ((LOWORD(hwnd) - FIRST_USER_HANDLE) >> 1)
47 /**********************************************************************/
49 /* helper for Get/SetWindowLong */
50 static inline LONG_PTR get_win_data( const void *ptr, UINT size )
52 if (size == sizeof(WORD))
54 WORD ret;
55 memcpy( &ret, ptr, sizeof(ret) );
56 return ret;
58 else if (size == sizeof(DWORD))
60 DWORD ret;
61 memcpy( &ret, ptr, sizeof(ret) );
62 return ret;
64 else
66 LONG_PTR ret;
67 memcpy( &ret, ptr, sizeof(ret) );
68 return ret;
72 /* helper for Get/SetWindowLong */
73 static inline void set_win_data( void *ptr, LONG_PTR val, UINT size )
75 if (size == sizeof(WORD))
77 WORD newval = val;
78 memcpy( ptr, &newval, sizeof(newval) );
80 else if (size == sizeof(DWORD))
82 DWORD newval = val;
83 memcpy( ptr, &newval, sizeof(newval) );
85 else
87 memcpy( ptr, &val, sizeof(val) );
92 static void *user_handles[NB_USER_HANDLES];
94 /***********************************************************************
95 * create_window_handle
97 * Create a window handle with the server.
99 static WND *create_window_handle( HWND parent, HWND owner, ATOM atom,
100 HINSTANCE instance, BOOL unicode )
102 WORD index;
103 WND *win;
104 HWND full_parent = 0, full_owner = 0;
105 struct tagCLASS *class = NULL;
106 user_handle_t handle = 0;
107 int extra_bytes = 0;
109 /* if 16-bit instance, map to module handle */
110 if (instance && !HIWORD(instance))
111 instance = HINSTANCE_32(GetExePtr(HINSTANCE_16(instance)));
113 SERVER_START_REQ( create_window )
115 req->parent = parent;
116 req->owner = owner;
117 req->atom = atom;
118 req->instance = instance;
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 assert( !thread_info->desktop );
153 thread_info->desktop = full_parent ? full_parent : handle;
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, ATOM atom, 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->atom = atom;
229 req->tid = tid;
230 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
231 if (!wine_server_call( req )) count = reply->count;
233 SERVER_END_REQ;
234 if (count && count < size)
236 list[count] = 0;
237 return list;
239 HeapFree( GetProcessHeap(), 0, list );
240 if (!count) break;
241 size = count + 1; /* restart with a large enough buffer */
243 return NULL;
247 /*******************************************************************
248 * list_window_parents
250 * Build an array of all parents of a given window, starting with
251 * the immediate parent. The array must be freed with HeapFree.
253 static HWND *list_window_parents( HWND hwnd )
255 WND *win;
256 HWND current, *list;
257 int pos = 0, size = 16, count = 0;
259 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
261 current = hwnd;
262 for (;;)
264 if (!(win = WIN_GetPtr( current ))) goto empty;
265 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
266 if (win == WND_DESKTOP)
268 if (!pos) goto empty;
269 list[pos] = 0;
270 return list;
272 list[pos] = current = win->parent;
273 WIN_ReleasePtr( win );
274 if (++pos == size - 1)
276 /* need to grow the list */
277 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
278 if (!new_list) goto empty;
279 list = new_list;
280 size += 16;
284 /* at least one parent belongs to another process, have to query the server */
286 for (;;)
288 count = 0;
289 SERVER_START_REQ( get_window_parents )
291 req->handle = hwnd;
292 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
293 if (!wine_server_call( req )) count = reply->count;
295 SERVER_END_REQ;
296 if (!count) goto empty;
297 if (size > count)
299 list[count] = 0;
300 return list;
302 HeapFree( GetProcessHeap(), 0, list );
303 size = count + 1;
304 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
307 empty:
308 HeapFree( GetProcessHeap(), 0, list );
309 return NULL;
313 /*******************************************************************
314 * send_parent_notify
316 static void send_parent_notify( HWND hwnd, UINT msg )
318 if ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_CHILD | WS_POPUP)) == WS_CHILD &&
319 !(GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY))
321 HWND parent = GetParent(hwnd);
322 if (parent && parent != GetDesktopWindow())
323 SendMessageW( parent, WM_PARENTNOTIFY,
324 MAKEWPARAM( msg, GetWindowLongPtrW( hwnd, GWLP_ID )), (LPARAM)hwnd );
329 /*******************************************************************
330 * get_server_window_text
332 * Retrieve the window text from the server.
334 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
336 size_t len = 0;
338 SERVER_START_REQ( get_window_text )
340 req->handle = hwnd;
341 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
342 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
344 SERVER_END_REQ;
345 text[len / sizeof(WCHAR)] = 0;
349 /***********************************************************************
350 * WIN_GetPtr
352 * Return a pointer to the WND structure if local to the process,
353 * or WND_OTHER_PROCESS if handle may be valid in other process.
354 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
356 WND *WIN_GetPtr( HWND hwnd )
358 WND * ptr;
359 WORD index = USER_HANDLE_TO_INDEX(hwnd);
361 if (index >= NB_USER_HANDLES) return NULL;
363 USER_Lock();
364 if ((ptr = user_handles[index]))
366 if (ptr->dwMagic == WND_MAGIC &&
367 (hwnd == ptr->hwndSelf || !HIWORD(hwnd) || HIWORD(hwnd) == 0xffff))
368 return ptr;
369 ptr = NULL;
371 else if (index == USER_HANDLE_TO_INDEX(GetDesktopWindow()))
373 if (hwnd == GetDesktopWindow() || !HIWORD(hwnd) || HIWORD(hwnd) == 0xffff) ptr = WND_DESKTOP;
374 else ptr = NULL;
376 else ptr = WND_OTHER_PROCESS;
377 USER_Unlock();
378 return ptr;
382 /***********************************************************************
383 * WIN_IsCurrentProcess
385 * Check whether a given window belongs to the current process (and return the full handle).
387 HWND WIN_IsCurrentProcess( HWND hwnd )
389 WND *ptr;
390 HWND ret;
392 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
393 ret = ptr->hwndSelf;
394 WIN_ReleasePtr( ptr );
395 return ret;
399 /***********************************************************************
400 * WIN_IsCurrentThread
402 * Check whether a given window belongs to the current thread (and return the full handle).
404 HWND WIN_IsCurrentThread( HWND hwnd )
406 WND *ptr;
407 HWND ret = 0;
409 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
410 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
411 WIN_ReleasePtr( ptr );
412 return ret;
416 /***********************************************************************
417 * WIN_Handle32
419 * Convert a 16-bit window handle to a full 32-bit handle.
421 HWND WIN_Handle32( HWND16 hwnd16 )
423 WND *ptr;
424 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
426 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
427 /* do sign extension for -2 and -3 */
428 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
430 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
432 if (ptr == WND_DESKTOP) return GetDesktopWindow();
434 if (ptr != WND_OTHER_PROCESS)
436 hwnd = ptr->hwndSelf;
437 WIN_ReleasePtr( ptr );
439 else /* may belong to another process */
441 SERVER_START_REQ( get_window_info )
443 req->handle = hwnd;
444 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
446 SERVER_END_REQ;
448 return hwnd;
452 /***********************************************************************
453 * WIN_SetOwner
455 * Change the owner of a window.
457 HWND WIN_SetOwner( HWND hwnd, HWND owner )
459 WND *win = WIN_GetPtr( hwnd );
460 HWND ret = 0;
462 if (!win || win == WND_DESKTOP) return 0;
463 if (win == WND_OTHER_PROCESS)
465 if (IsWindow(hwnd)) ERR( "cannot set owner %p on other process window %p\n", owner, hwnd );
466 return 0;
468 SERVER_START_REQ( set_window_owner )
470 req->handle = hwnd;
471 req->owner = owner;
472 if (!wine_server_call( req ))
474 win->owner = reply->full_owner;
475 ret = reply->prev_owner;
478 SERVER_END_REQ;
479 WIN_ReleasePtr( win );
480 return ret;
484 /***********************************************************************
485 * WIN_SetStyle
487 * Change the style of a window.
489 ULONG WIN_SetStyle( HWND hwnd, ULONG set_bits, ULONG clear_bits )
491 BOOL ok;
492 ULONG new_style, old_style = 0;
493 WND *win = WIN_GetPtr( hwnd );
495 if (!win || win == WND_DESKTOP) return 0;
496 if (win == WND_OTHER_PROCESS)
498 if (IsWindow(hwnd))
499 ERR( "cannot set style %x/%x on other process window %p\n",
500 set_bits, clear_bits, hwnd );
501 return 0;
503 new_style = (win->dwStyle | set_bits) & ~clear_bits;
504 if (new_style == win->dwStyle)
506 WIN_ReleasePtr( win );
507 return new_style;
509 SERVER_START_REQ( set_window_info )
511 req->handle = hwnd;
512 req->flags = SET_WIN_STYLE;
513 req->style = new_style;
514 req->extra_offset = -1;
515 if ((ok = !wine_server_call( req )))
517 old_style = reply->old_style;
518 win->dwStyle = new_style;
521 SERVER_END_REQ;
522 WIN_ReleasePtr( win );
523 if (ok) USER_Driver->pSetWindowStyle( hwnd, old_style );
524 return old_style;
528 /***********************************************************************
529 * WIN_GetRectangles
531 * Get the window and client rectangles.
533 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
535 WND *win = WIN_GetPtr( hwnd );
536 BOOL ret = TRUE;
538 if (!win) return FALSE;
539 if (win == WND_DESKTOP)
541 RECT rect;
542 rect.left = rect.top = 0;
543 rect.right = GetSystemMetrics(SM_CXSCREEN);
544 rect.bottom = GetSystemMetrics(SM_CYSCREEN);
545 if (rectWindow) *rectWindow = rect;
546 if (rectClient) *rectClient = rect;
548 else if (win == WND_OTHER_PROCESS)
550 SERVER_START_REQ( get_window_rectangles )
552 req->handle = hwnd;
553 if ((ret = !wine_server_call( req )))
555 if (rectWindow)
557 rectWindow->left = reply->window.left;
558 rectWindow->top = reply->window.top;
559 rectWindow->right = reply->window.right;
560 rectWindow->bottom = reply->window.bottom;
562 if (rectClient)
564 rectClient->left = reply->client.left;
565 rectClient->top = reply->client.top;
566 rectClient->right = reply->client.right;
567 rectClient->bottom = reply->client.bottom;
571 SERVER_END_REQ;
573 else
575 if (rectWindow) *rectWindow = win->rectWindow;
576 if (rectClient) *rectClient = win->rectClient;
577 WIN_ReleasePtr( win );
579 return ret;
583 /***********************************************************************
584 * WIN_DestroyWindow
586 * Destroy storage associated to a window. "Internals" p.358
588 LRESULT WIN_DestroyWindow( HWND hwnd )
590 WND *wndPtr;
591 HWND *list;
592 HMENU menu = 0, sys_menu;
594 TRACE("%p\n", hwnd );
596 /* free child windows */
597 if ((list = WIN_ListChildren( hwnd )))
599 int i;
600 for (i = 0; list[i]; i++)
602 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
603 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
605 HeapFree( GetProcessHeap(), 0, list );
608 /* Unlink now so we won't bother with the children later on */
609 SERVER_START_REQ( set_parent )
611 req->handle = hwnd;
612 req->parent = 0;
613 wine_server_call( req );
615 SERVER_END_REQ;
618 * Send the WM_NCDESTROY to the window being destroyed.
620 SendMessageW( hwnd, WM_NCDESTROY, 0, 0 );
622 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
624 WINPOS_CheckInternalPos( hwnd );
626 /* free resources associated with the window */
628 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
629 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
630 menu = (HMENU)wndPtr->wIDmenu;
631 sys_menu = wndPtr->hSysMenu;
632 WIN_ReleasePtr( wndPtr );
634 if (menu) DestroyMenu( menu );
635 if (sys_menu) DestroyMenu( sys_menu );
637 USER_Driver->pDestroyWindow( hwnd );
639 free_window_handle( hwnd );
640 return 0;
643 /***********************************************************************
644 * WIN_DestroyThreadWindows
646 * Destroy all children of 'wnd' owned by the current thread.
648 void WIN_DestroyThreadWindows( HWND hwnd )
650 HWND *list;
651 int i;
653 if (!(list = WIN_ListChildren( hwnd ))) return;
654 for (i = 0; list[i]; i++)
656 if (WIN_IsCurrentThread( list[i] ))
657 DestroyWindow( list[i] );
658 else
659 WIN_DestroyThreadWindows( list[i] );
661 HeapFree( GetProcessHeap(), 0, list );
665 /***********************************************************************
666 * WIN_FixCoordinates
668 * Fix the coordinates - Helper for WIN_CreateWindowEx.
669 * returns default show mode in sw.
671 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
673 #define IS_DEFAULT(x) ((x) == CW_USEDEFAULT || (x) == CW_USEDEFAULT16)
674 POINT pos[2];
676 if (cs->dwExStyle & WS_EX_MDICHILD)
678 UINT id = 0;
680 MDI_CalcDefaultChildPos(cs->hwndParent, -1, pos, 0, &id);
681 if (!(cs->style & WS_POPUP)) cs->hMenu = ULongToHandle(id);
683 TRACE("MDI child id %04x\n", id);
686 if (cs->style & (WS_CHILD | WS_POPUP))
688 if (cs->dwExStyle & WS_EX_MDICHILD)
690 if (IS_DEFAULT(cs->x))
692 cs->x = pos[0].x;
693 cs->y = pos[0].y;
695 if (IS_DEFAULT(cs->cx) || !cs->cx) cs->cx = pos[1].x;
696 if (IS_DEFAULT(cs->cy) || !cs->cy) cs->cy = pos[1].y;
698 else
700 if (IS_DEFAULT(cs->x)) cs->x = cs->y = 0;
701 if (IS_DEFAULT(cs->cx)) cs->cx = cs->cy = 0;
704 else /* overlapped window */
706 HMONITOR monitor;
707 MONITORINFO mon_info;
708 STARTUPINFOW info;
710 if (!IS_DEFAULT(cs->x) && !IS_DEFAULT(cs->cx) && !IS_DEFAULT(cs->cy)) return;
712 monitor = MonitorFromWindow( cs->hwndParent, MONITOR_DEFAULTTOPRIMARY );
713 mon_info.cbSize = sizeof(mon_info);
714 GetMonitorInfoW( monitor, &mon_info );
715 GetStartupInfoW( &info );
717 if (IS_DEFAULT(cs->x))
719 if (!IS_DEFAULT(cs->y)) *sw = cs->y;
720 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : mon_info.rcWork.left;
721 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : mon_info.rcWork.top;
724 if (IS_DEFAULT(cs->cx))
726 if (info.dwFlags & STARTF_USESIZE)
728 cs->cx = info.dwXSize;
729 cs->cy = info.dwYSize;
731 else
733 cs->cx = (mon_info.rcWork.right - mon_info.rcWork.left) * 3 / 4 - cs->x;
734 cs->cy = (mon_info.rcWork.bottom - mon_info.rcWork.top) * 3 / 4 - cs->y;
737 /* neither x nor cx are default. Check the y values .
738 * In the trace we see Outlook and Outlook Express using
739 * cy set to CW_USEDEFAULT when opening the address book.
741 else if (IS_DEFAULT(cs->cy))
743 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
744 cs->cy = (mon_info.rcWork.bottom - mon_info.rcWork.top) * 3 / 4 - cs->y;
747 #undef IS_DEFAULT
750 /***********************************************************************
751 * dump_window_styles
753 static void dump_window_styles( DWORD style, DWORD exstyle )
755 TRACE( "style:" );
756 if(style & WS_POPUP) TRACE(" WS_POPUP");
757 if(style & WS_CHILD) TRACE(" WS_CHILD");
758 if(style & WS_MINIMIZE) TRACE(" WS_MINIMIZE");
759 if(style & WS_VISIBLE) TRACE(" WS_VISIBLE");
760 if(style & WS_DISABLED) TRACE(" WS_DISABLED");
761 if(style & WS_CLIPSIBLINGS) TRACE(" WS_CLIPSIBLINGS");
762 if(style & WS_CLIPCHILDREN) TRACE(" WS_CLIPCHILDREN");
763 if(style & WS_MAXIMIZE) TRACE(" WS_MAXIMIZE");
764 if((style & WS_CAPTION) == WS_CAPTION) TRACE(" WS_CAPTION");
765 else
767 if(style & WS_BORDER) TRACE(" WS_BORDER");
768 if(style & WS_DLGFRAME) TRACE(" WS_DLGFRAME");
770 if(style & WS_VSCROLL) TRACE(" WS_VSCROLL");
771 if(style & WS_HSCROLL) TRACE(" WS_HSCROLL");
772 if(style & WS_SYSMENU) TRACE(" WS_SYSMENU");
773 if(style & WS_THICKFRAME) TRACE(" WS_THICKFRAME");
774 if (style & WS_CHILD)
776 if(style & WS_GROUP) TRACE(" WS_GROUP");
777 if(style & WS_TABSTOP) TRACE(" WS_TABSTOP");
779 else
781 if(style & WS_MINIMIZEBOX) TRACE(" WS_MINIMIZEBOX");
782 if(style & WS_MAXIMIZEBOX) TRACE(" WS_MAXIMIZEBOX");
785 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
786 #define DUMPED_STYLES \
787 (WS_POPUP | \
788 WS_CHILD | \
789 WS_MINIMIZE | \
790 WS_VISIBLE | \
791 WS_DISABLED | \
792 WS_CLIPSIBLINGS | \
793 WS_CLIPCHILDREN | \
794 WS_MAXIMIZE | \
795 WS_BORDER | \
796 WS_DLGFRAME | \
797 WS_VSCROLL | \
798 WS_HSCROLL | \
799 WS_SYSMENU | \
800 WS_THICKFRAME | \
801 WS_GROUP | \
802 WS_TABSTOP | \
803 WS_MINIMIZEBOX | \
804 WS_MAXIMIZEBOX)
806 if(style & ~DUMPED_STYLES) TRACE(" %08lx", style & ~DUMPED_STYLES);
807 TRACE("\n");
808 #undef DUMPED_STYLES
810 TRACE( "exstyle:" );
811 if(exstyle & WS_EX_DLGMODALFRAME) TRACE(" WS_EX_DLGMODALFRAME");
812 if(exstyle & WS_EX_DRAGDETECT) TRACE(" WS_EX_DRAGDETECT");
813 if(exstyle & WS_EX_NOPARENTNOTIFY) TRACE(" WS_EX_NOPARENTNOTIFY");
814 if(exstyle & WS_EX_TOPMOST) TRACE(" WS_EX_TOPMOST");
815 if(exstyle & WS_EX_ACCEPTFILES) TRACE(" WS_EX_ACCEPTFILES");
816 if(exstyle & WS_EX_TRANSPARENT) TRACE(" WS_EX_TRANSPARENT");
817 if(exstyle & WS_EX_MDICHILD) TRACE(" WS_EX_MDICHILD");
818 if(exstyle & WS_EX_TOOLWINDOW) TRACE(" WS_EX_TOOLWINDOW");
819 if(exstyle & WS_EX_WINDOWEDGE) TRACE(" WS_EX_WINDOWEDGE");
820 if(exstyle & WS_EX_CLIENTEDGE) TRACE(" WS_EX_CLIENTEDGE");
821 if(exstyle & WS_EX_CONTEXTHELP) TRACE(" WS_EX_CONTEXTHELP");
822 if(exstyle & WS_EX_RIGHT) TRACE(" WS_EX_RIGHT");
823 if(exstyle & WS_EX_RTLREADING) TRACE(" WS_EX_RTLREADING");
824 if(exstyle & WS_EX_LEFTSCROLLBAR) TRACE(" WS_EX_LEFTSCROLLBAR");
825 if(exstyle & WS_EX_CONTROLPARENT) TRACE(" WS_EX_CONTROLPARENT");
826 if(exstyle & WS_EX_STATICEDGE) TRACE(" WS_EX_STATICEDGE");
827 if(exstyle & WS_EX_APPWINDOW) TRACE(" WS_EX_APPWINDOW");
828 if(exstyle & WS_EX_LAYERED) TRACE(" WS_EX_LAYERED");
830 #define DUMPED_EX_STYLES \
831 (WS_EX_DLGMODALFRAME | \
832 WS_EX_DRAGDETECT | \
833 WS_EX_NOPARENTNOTIFY | \
834 WS_EX_TOPMOST | \
835 WS_EX_ACCEPTFILES | \
836 WS_EX_TRANSPARENT | \
837 WS_EX_MDICHILD | \
838 WS_EX_TOOLWINDOW | \
839 WS_EX_WINDOWEDGE | \
840 WS_EX_CLIENTEDGE | \
841 WS_EX_CONTEXTHELP | \
842 WS_EX_RIGHT | \
843 WS_EX_RTLREADING | \
844 WS_EX_LEFTSCROLLBAR | \
845 WS_EX_CONTROLPARENT | \
846 WS_EX_STATICEDGE | \
847 WS_EX_APPWINDOW | \
848 WS_EX_LAYERED)
850 if(exstyle & ~DUMPED_EX_STYLES) TRACE(" %08lx", exstyle & ~DUMPED_EX_STYLES);
851 TRACE("\n");
852 #undef DUMPED_EX_STYLES
856 /***********************************************************************
857 * WIN_CreateWindowEx
859 * Implementation of CreateWindowEx().
861 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom, UINT flags )
863 INT sw = SW_SHOW;
864 WND *wndPtr;
865 HWND hwnd, parent, owner, top_child = 0;
866 BOOL unicode = (flags & WIN_ISUNICODE) != 0;
867 MDICREATESTRUCTA mdi_cs;
869 TRACE("%s %s ex=%08x style=%08x %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
870 unicode ? debugstr_w((LPCWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
871 unicode ? debugstr_w((LPCWSTR)cs->lpszClass) : debugstr_a(cs->lpszClass),
872 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
873 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
874 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
876 /* Fix the styles for MDI children */
877 if (cs->dwExStyle & WS_EX_MDICHILD)
879 UINT flags = 0;
881 wndPtr = WIN_GetPtr(cs->hwndParent);
882 if (wndPtr && wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
884 flags = wndPtr->flags;
885 WIN_ReleasePtr(wndPtr);
888 if (!(flags & WIN_ISMDICLIENT))
890 WARN("WS_EX_MDICHILD, but parent %p is not MDIClient\n", cs->hwndParent);
891 return 0;
894 /* cs->lpCreateParams of WM_[NC]CREATE is different for MDI children.
895 * MDICREATESTRUCT members have the originally passed values.
897 * Note: we rely on the fact that MDICREATESTRUCTA and MDICREATESTRUCTW
898 * have the same layout.
900 mdi_cs.szClass = cs->lpszClass;
901 mdi_cs.szTitle = cs->lpszName;
902 mdi_cs.hOwner = cs->hInstance;
903 mdi_cs.x = cs->x;
904 mdi_cs.y = cs->y;
905 mdi_cs.cx = cs->cx;
906 mdi_cs.cy = cs->cy;
907 mdi_cs.style = cs->style;
908 mdi_cs.lParam = (LPARAM)cs->lpCreateParams;
910 cs->lpCreateParams = (LPVOID)&mdi_cs;
912 if (GetWindowLongW(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
914 if (cs->style & WS_POPUP)
916 TRACE("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n");
917 return 0;
919 cs->style |= WS_CHILD | WS_CLIPSIBLINGS;
921 else
923 cs->style &= ~WS_POPUP;
924 cs->style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
925 WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
928 top_child = GetWindow(cs->hwndParent, GW_CHILD);
930 if (top_child)
932 /* Restore current maximized child */
933 if((cs->style & WS_VISIBLE) && IsZoomed(top_child))
935 TRACE("Restoring current maximized child %p\n", top_child);
936 SendMessageW( top_child, WM_SETREDRAW, FALSE, 0 );
937 ShowWindow( top_child, SW_SHOWNORMAL );
938 SendMessageW( top_child, WM_SETREDRAW, TRUE, 0 );
943 /* Find the parent window */
945 parent = cs->hwndParent;
946 owner = 0;
948 if (cs->hwndParent == HWND_MESSAGE)
950 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
951 * message window (style: WS_POPUP|WS_DISABLED)
953 FIXME("Parent is HWND_MESSAGE\n");
954 parent = GetDesktopWindow();
956 else if (cs->hwndParent)
958 if ((cs->style & (WS_CHILD|WS_POPUP)) != WS_CHILD)
960 parent = GetDesktopWindow();
961 owner = cs->hwndParent;
964 else
966 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
968 WARN("No parent for child window\n" );
969 SetLastError(ERROR_TLW_WITH_WSCHILD);
970 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
972 if (classAtom != LOWORD(DESKTOP_CLASS_ATOM)) /* are we creating the desktop itself? */
973 parent = GetDesktopWindow();
976 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
978 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
979 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
980 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
981 cs->dwExStyle |= WS_EX_WINDOWEDGE;
982 else
983 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
985 /* Create the window structure */
987 if (!(wndPtr = create_window_handle( parent, owner, classAtom, cs->hInstance, unicode )))
988 return 0;
989 hwnd = wndPtr->hwndSelf;
991 /* Fill the window structure */
993 wndPtr->tid = GetCurrentThreadId();
994 wndPtr->hInstance = cs->hInstance;
995 wndPtr->text = NULL;
996 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
997 wndPtr->dwExStyle = cs->dwExStyle;
998 wndPtr->wIDmenu = 0;
999 wndPtr->helpContext = 0;
1000 wndPtr->pVScroll = NULL;
1001 wndPtr->pHScroll = NULL;
1002 wndPtr->userdata = 0;
1003 wndPtr->hIcon = 0;
1004 wndPtr->hIconSmall = 0;
1005 wndPtr->hSysMenu = 0;
1006 wndPtr->flags |= (flags & WIN_ISWIN32);
1008 if (wndPtr->dwStyle & WS_SYSMENU) SetSystemMenu( hwnd, 0 );
1011 * Correct the window styles.
1013 * It affects only the style loaded into the WIN structure.
1016 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
1018 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1019 if (!(wndPtr->dwStyle & WS_POPUP))
1020 wndPtr->dwStyle |= WS_CAPTION;
1024 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1025 * why does the user get to set it?
1028 if ((wndPtr->dwExStyle & WS_EX_DLGMODALFRAME) ||
1029 (wndPtr->dwStyle & (WS_DLGFRAME | WS_THICKFRAME)))
1030 wndPtr->dwExStyle |= WS_EX_WINDOWEDGE;
1031 else
1032 wndPtr->dwExStyle &= ~WS_EX_WINDOWEDGE;
1034 if (!(wndPtr->dwStyle & (WS_CHILD | WS_POPUP)))
1035 wndPtr->flags |= WIN_NEED_SIZE;
1037 SERVER_START_REQ( set_window_info )
1039 req->handle = hwnd;
1040 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE | SET_WIN_UNICODE;
1041 req->style = wndPtr->dwStyle;
1042 req->ex_style = wndPtr->dwExStyle;
1043 req->instance = (void *)wndPtr->hInstance;
1044 req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
1045 req->extra_offset = -1;
1046 wine_server_call( req );
1048 SERVER_END_REQ;
1050 /* Set the window menu */
1052 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
1054 if (cs->hMenu)
1056 if (!MENU_SetMenu(hwnd, cs->hMenu))
1058 WIN_ReleasePtr( wndPtr );
1059 free_window_handle( hwnd );
1060 return 0;
1063 else
1065 LPCSTR menuName = (LPCSTR)GetClassLongPtrA( hwnd, GCLP_MENUNAME );
1066 if (menuName)
1068 if (!cs->hInstance || HIWORD(cs->hInstance))
1069 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1070 else
1071 cs->hMenu = HMENU_32(LoadMenu16(HINSTANCE_16(cs->hInstance),menuName));
1073 if (cs->hMenu) MENU_SetMenu( hwnd, cs->hMenu );
1077 else SetWindowLongPtrW( hwnd, GWLP_ID, (ULONG_PTR)cs->hMenu );
1078 WIN_ReleasePtr( wndPtr );
1080 if (!USER_Driver->pCreateWindow( hwnd, cs, unicode))
1082 WIN_DestroyWindow( hwnd );
1083 return 0;
1086 /* Notify the parent window only */
1088 send_parent_notify( hwnd, WM_CREATE );
1089 if (!IsWindow( hwnd )) return 0;
1091 if (cs->style & WS_VISIBLE)
1093 if (cs->style & WS_MAXIMIZE)
1094 sw = SW_SHOW;
1095 else if (cs->style & WS_MINIMIZE)
1096 sw = SW_SHOWMINIMIZED;
1098 ShowWindow( hwnd, sw );
1099 if (cs->dwExStyle & WS_EX_MDICHILD)
1101 SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
1102 /* ShowWindow won't activate child windows */
1103 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE );
1107 /* Call WH_SHELL hook */
1109 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1110 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1112 TRACE("created window %p\n", hwnd);
1113 return hwnd;
1117 /***********************************************************************
1118 * CreateWindow (USER.41)
1120 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1121 DWORD style, INT16 x, INT16 y, INT16 width,
1122 INT16 height, HWND16 parent, HMENU16 menu,
1123 HINSTANCE16 instance, LPVOID data )
1125 return CreateWindowEx16( 0, className, windowName, style,
1126 x, y, width, height, parent, menu, instance, data );
1130 /***********************************************************************
1131 * CreateWindowEx (USER.452)
1133 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1134 LPCSTR windowName, DWORD style, INT16 x,
1135 INT16 y, INT16 width, INT16 height,
1136 HWND16 parent, HMENU16 menu,
1137 HINSTANCE16 instance, LPVOID data )
1139 ATOM classAtom;
1140 CREATESTRUCTA cs;
1141 char buffer[256];
1143 /* Find the class atom */
1145 if (HIWORD(className))
1147 if (!(classAtom = GlobalFindAtomA( className )))
1149 ERR( "bad class name %s\n", debugstr_a(className) );
1150 return 0;
1153 else
1155 classAtom = LOWORD(className);
1156 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1158 ERR( "bad atom %x\n", classAtom);
1159 return 0;
1161 className = buffer;
1164 /* Fix the coordinates */
1166 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1167 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1168 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1169 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1171 /* Create the window */
1173 cs.lpCreateParams = data;
1174 cs.hInstance = HINSTANCE_32(instance);
1175 cs.hMenu = HMENU_32(menu);
1176 cs.hwndParent = WIN_Handle32( parent );
1177 cs.style = style;
1178 cs.lpszName = windowName;
1179 cs.lpszClass = className;
1180 cs.dwExStyle = exStyle;
1182 return HWND_16( WIN_CreateWindowEx( &cs, classAtom, 0 ));
1186 /***********************************************************************
1187 * CreateWindowExA (USER32.@)
1189 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1190 LPCSTR windowName, DWORD style, INT x,
1191 INT y, INT width, INT height,
1192 HWND parent, HMENU menu,
1193 HINSTANCE instance, LPVOID data )
1195 ATOM classAtom;
1196 CREATESTRUCTA cs;
1197 char buffer[256];
1199 /* Find the class atom */
1201 if (HIWORD(className))
1203 if (!(classAtom = GlobalFindAtomA( className )))
1205 ERR( "bad class name %s\n", debugstr_a(className) );
1206 return 0;
1209 else
1211 classAtom = LOWORD(className);
1212 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1214 ERR( "bad atom %x\n", classAtom);
1215 return 0;
1217 className = buffer;
1220 /* Create the window */
1222 cs.lpCreateParams = data;
1223 cs.hInstance = instance;
1224 cs.hMenu = menu;
1225 cs.hwndParent = parent;
1226 cs.x = x;
1227 cs.y = y;
1228 cs.cx = width;
1229 cs.cy = height;
1230 cs.style = style;
1231 cs.lpszName = windowName;
1232 cs.lpszClass = className;
1233 cs.dwExStyle = exStyle;
1235 return WIN_CreateWindowEx( &cs, classAtom, WIN_ISWIN32 );
1239 /***********************************************************************
1240 * CreateWindowExW (USER32.@)
1242 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1243 LPCWSTR windowName, DWORD style, INT x,
1244 INT y, INT width, INT height,
1245 HWND parent, HMENU menu,
1246 HINSTANCE instance, LPVOID data )
1248 ATOM classAtom;
1249 CREATESTRUCTW cs;
1250 WCHAR buffer[256];
1252 /* Find the class atom */
1254 if (HIWORD(className))
1256 if (!(classAtom = GlobalFindAtomW( className )))
1258 ERR( "bad class name %s\n", debugstr_w(className) );
1259 return 0;
1262 else
1264 classAtom = LOWORD(className);
1265 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1267 ERR( "bad atom %x\n", classAtom);
1268 return 0;
1270 className = buffer;
1273 /* Create the window */
1275 cs.lpCreateParams = data;
1276 cs.hInstance = instance;
1277 cs.hMenu = menu;
1278 cs.hwndParent = parent;
1279 cs.x = x;
1280 cs.y = y;
1281 cs.cx = width;
1282 cs.cy = height;
1283 cs.style = style;
1284 cs.lpszName = windowName;
1285 cs.lpszClass = className;
1286 cs.dwExStyle = exStyle;
1288 /* Note: we rely on the fact that CREATESTRUCTA and */
1289 /* CREATESTRUCTW have the same layout. */
1290 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_ISWIN32 | WIN_ISUNICODE );
1294 /***********************************************************************
1295 * WIN_SendDestroyMsg
1297 static void WIN_SendDestroyMsg( HWND hwnd )
1299 GUITHREADINFO info;
1301 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1303 if (hwnd == info.hwndCaret) DestroyCaret();
1304 if (hwnd == info.hwndActive) WINPOS_ActivateOtherWindow( hwnd );
1308 * Send the WM_DESTROY to the window.
1310 SendMessageW( hwnd, WM_DESTROY, 0, 0);
1313 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1314 * make sure that the window still exists when we come back.
1316 if (IsWindow(hwnd))
1318 HWND* pWndArray;
1319 int i;
1321 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1323 for (i = 0; pWndArray[i]; i++)
1325 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1327 HeapFree( GetProcessHeap(), 0, pWndArray );
1329 else
1330 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1334 /***********************************************************************
1335 * DestroyWindow (USER32.@)
1337 BOOL WINAPI DestroyWindow( HWND hwnd )
1339 BOOL is_child;
1341 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1343 SetLastError( ERROR_ACCESS_DENIED );
1344 return FALSE;
1347 TRACE("(%p)\n", hwnd);
1349 /* Call hooks */
1351 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1353 if (MENU_IsMenuActive() == hwnd)
1354 EndMenu();
1356 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1358 if (is_child)
1360 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1361 send_parent_notify( hwnd, WM_DESTROY );
1363 else if (!GetWindow( hwnd, GW_OWNER ))
1365 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1366 /* FIXME: clean up palette - see "Internals" p.352 */
1369 if (!IsWindow(hwnd)) return TRUE;
1371 /* Hide the window */
1372 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)
1374 /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
1375 if (is_child)
1376 ShowWindow( hwnd, SW_HIDE );
1377 else
1378 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1379 SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW );
1382 if (!IsWindow(hwnd)) return TRUE;
1384 /* Recursively destroy owned windows */
1386 if (!is_child)
1388 for (;;)
1390 int i, got_one = 0;
1391 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1392 if (list)
1394 for (i = 0; list[i]; i++)
1396 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1397 if (WIN_IsCurrentThread( list[i] ))
1399 DestroyWindow( list[i] );
1400 got_one = 1;
1401 continue;
1403 WIN_SetOwner( list[i], 0 );
1405 HeapFree( GetProcessHeap(), 0, list );
1407 if (!got_one) break;
1411 /* Send destroy messages */
1413 WIN_SendDestroyMsg( hwnd );
1414 if (!IsWindow( hwnd )) return TRUE;
1416 if (GetClipboardOwner() == hwnd)
1417 CLIPBOARD_ReleaseOwner();
1419 /* Destroy the window storage */
1421 WIN_DestroyWindow( hwnd );
1422 return TRUE;
1426 /***********************************************************************
1427 * CloseWindow (USER32.@)
1429 BOOL WINAPI CloseWindow( HWND hwnd )
1431 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1432 ShowWindow( hwnd, SW_MINIMIZE );
1433 return TRUE;
1437 /***********************************************************************
1438 * OpenIcon (USER32.@)
1440 BOOL WINAPI OpenIcon( HWND hwnd )
1442 if (!IsIconic( hwnd )) return FALSE;
1443 ShowWindow( hwnd, SW_SHOWNORMAL );
1444 return TRUE;
1448 /***********************************************************************
1449 * WIN_FindWindow
1451 * Implementation of FindWindow() and FindWindowEx().
1453 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1455 HWND *list = NULL;
1456 HWND retvalue = 0;
1457 int i = 0, len = 0;
1458 WCHAR *buffer = NULL;
1460 if (!parent) parent = GetDesktopWindow();
1461 if (title)
1463 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1464 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1467 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1469 if (child)
1471 child = WIN_GetFullHandle( child );
1472 while (list[i] && list[i] != child) i++;
1473 if (!list[i]) goto done;
1474 i++; /* start from next window */
1477 if (title)
1479 while (list[i])
1481 if (GetWindowTextW( list[i], buffer, len + 1 ) && !strcmpiW( buffer, title )) break;
1482 i++;
1485 retvalue = list[i];
1487 done:
1488 HeapFree( GetProcessHeap(), 0, list );
1489 HeapFree( GetProcessHeap(), 0, buffer );
1490 return retvalue;
1495 /***********************************************************************
1496 * FindWindowA (USER32.@)
1498 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1500 HWND ret = FindWindowExA( 0, 0, className, title );
1501 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1502 return ret;
1506 /***********************************************************************
1507 * FindWindowExA (USER32.@)
1509 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1510 LPCSTR className, LPCSTR title )
1512 ATOM atom = 0;
1513 LPWSTR buffer;
1514 HWND hwnd;
1515 INT len;
1517 if (className)
1519 /* If the atom doesn't exist, then no class */
1520 /* with this name exists either. */
1521 if (!(atom = GlobalFindAtomA( className )))
1523 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1524 return 0;
1527 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
1529 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1530 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1531 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
1532 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1533 HeapFree( GetProcessHeap(), 0, buffer );
1534 return hwnd;
1538 /***********************************************************************
1539 * FindWindowExW (USER32.@)
1541 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1542 LPCWSTR className, LPCWSTR title )
1544 ATOM atom = 0;
1546 if (className)
1548 /* If the atom doesn't exist, then no class */
1549 /* with this name exists either. */
1550 if (!(atom = GlobalFindAtomW( className )))
1552 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1553 return 0;
1556 return WIN_FindWindow( parent, child, atom, title );
1560 /***********************************************************************
1561 * FindWindowW (USER32.@)
1563 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1565 return FindWindowExW( 0, 0, className, title );
1569 /**********************************************************************
1570 * GetDesktopWindow (USER32.@)
1572 HWND WINAPI GetDesktopWindow(void)
1574 struct user_thread_info *thread_info = get_user_thread_info();
1576 if (thread_info->desktop) return thread_info->desktop;
1578 SERVER_START_REQ( get_desktop_window )
1580 req->force = 0;
1581 if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1583 SERVER_END_REQ;
1585 if (!thread_info->desktop)
1587 static const WCHAR command_line[] = {'\\','e','x','p','l','o','r','e','r','.','e','x','e',' ','/','d','e','s','k','t','o','p',0};
1588 STARTUPINFOW si;
1589 PROCESS_INFORMATION pi;
1590 WCHAR cmdline[MAX_PATH + sizeof(command_line)/sizeof(WCHAR)];
1592 memset( &si, 0, sizeof(si) );
1593 si.cb = sizeof(si);
1594 GetSystemDirectoryW( cmdline, MAX_PATH );
1595 lstrcatW( cmdline, command_line );
1596 if (CreateProcessW( NULL, cmdline, NULL, NULL, FALSE, DETACHED_PROCESS,
1597 NULL, NULL, &si, &pi ))
1599 TRACE( "started explorer pid %04x tid %04x\n", pi.dwProcessId, pi.dwThreadId );
1600 WaitForInputIdle( pi.hProcess, 10000 );
1601 CloseHandle( pi.hThread );
1602 CloseHandle( pi.hProcess );
1605 else WARN( "failed to start explorer, err %d\n", GetLastError() );
1607 SERVER_START_REQ( get_desktop_window )
1609 req->force = 1;
1610 if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1612 SERVER_END_REQ;
1615 if (!thread_info->desktop || !USER_Driver->pCreateDesktopWindow( thread_info->desktop ))
1616 ERR( "failed to create desktop window\n" );
1618 return thread_info->desktop;
1622 /*******************************************************************
1623 * EnableWindow (USER32.@)
1625 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1627 BOOL retvalue;
1628 HWND full_handle;
1630 if (is_broadcast(hwnd))
1632 SetLastError( ERROR_INVALID_PARAMETER );
1633 return FALSE;
1636 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1637 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1639 hwnd = full_handle;
1641 TRACE("( %p, %d )\n", hwnd, enable);
1643 retvalue = !IsWindowEnabled( hwnd );
1645 if (enable && retvalue)
1647 WIN_SetStyle( hwnd, 0, WS_DISABLED );
1648 SendMessageW( hwnd, WM_ENABLE, TRUE, 0 );
1650 else if (!enable && !retvalue)
1652 HWND capture_wnd;
1654 SendMessageW( hwnd, WM_CANCELMODE, 0, 0);
1656 WIN_SetStyle( hwnd, WS_DISABLED, 0 );
1658 if (hwnd == GetFocus())
1659 SetFocus( 0 ); /* A disabled window can't have the focus */
1661 capture_wnd = GetCapture();
1662 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1663 ReleaseCapture(); /* A disabled window can't capture the mouse */
1665 SendMessageW( hwnd, WM_ENABLE, FALSE, 0 );
1667 return retvalue;
1671 /***********************************************************************
1672 * IsWindowEnabled (USER32.@)
1674 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1676 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1680 /***********************************************************************
1681 * IsWindowUnicode (USER32.@)
1683 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1685 WND * wndPtr;
1686 BOOL retvalue = FALSE;
1688 if (!(wndPtr = WIN_GetPtr(hwnd))) return FALSE;
1690 if (wndPtr == WND_DESKTOP) return TRUE;
1692 if (wndPtr != WND_OTHER_PROCESS)
1694 retvalue = (wndPtr->flags & WIN_ISUNICODE) != 0;
1695 WIN_ReleasePtr( wndPtr );
1697 else
1699 SERVER_START_REQ( get_window_info )
1701 req->handle = hwnd;
1702 if (!wine_server_call_err( req )) retvalue = reply->is_unicode;
1704 SERVER_END_REQ;
1706 return retvalue;
1710 /**********************************************************************
1711 * WIN_GetWindowLong
1713 * Helper function for GetWindowLong().
1715 static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, UINT size, BOOL unicode )
1717 LONG_PTR retvalue = 0;
1718 WND *wndPtr;
1720 if (offset == GWLP_HWNDPARENT)
1722 HWND parent = GetAncestor( hwnd, GA_PARENT );
1723 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1724 return (ULONG_PTR)parent;
1727 if (!(wndPtr = WIN_GetPtr( hwnd )))
1729 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1730 return 0;
1733 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1735 if (offset == GWLP_WNDPROC)
1737 SetLastError( ERROR_ACCESS_DENIED );
1738 return 0;
1740 SERVER_START_REQ( set_window_info )
1742 req->handle = hwnd;
1743 req->flags = 0; /* don't set anything, just retrieve */
1744 req->extra_offset = (offset >= 0) ? offset : -1;
1745 req->extra_size = (offset >= 0) ? size : 0;
1746 if (!wine_server_call_err( req ))
1748 switch(offset)
1750 case GWL_STYLE: retvalue = reply->old_style; break;
1751 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1752 case GWLP_ID: retvalue = reply->old_id; break;
1753 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1754 case GWLP_USERDATA: retvalue = reply->old_user_data; break;
1755 default:
1756 if (offset >= 0) retvalue = get_win_data( &reply->old_extra_value, size );
1757 else SetLastError( ERROR_INVALID_INDEX );
1758 break;
1762 SERVER_END_REQ;
1763 return retvalue;
1766 /* now we have a valid wndPtr */
1768 if (offset >= 0)
1770 if (offset > (int)(wndPtr->cbWndExtra - size))
1772 WARN("Invalid offset %d\n", offset );
1773 WIN_ReleasePtr( wndPtr );
1774 SetLastError( ERROR_INVALID_INDEX );
1775 return 0;
1777 retvalue = get_win_data( (char *)wndPtr->wExtra + offset, size );
1779 /* Special case for dialog window procedure */
1780 if ((offset == DWLP_DLGPROC) && (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG))
1781 retvalue = (LONG_PTR)WINPROC_GetProc( (WNDPROC)retvalue, unicode );
1782 WIN_ReleasePtr( wndPtr );
1783 return retvalue;
1786 switch(offset)
1788 case GWLP_USERDATA: retvalue = wndPtr->userdata; break;
1789 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1790 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1791 case GWLP_ID: retvalue = (ULONG_PTR)wndPtr->wIDmenu; break;
1792 case GWLP_WNDPROC: retvalue = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, unicode ); break;
1793 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wndPtr->hInstance; break;
1794 default:
1795 WARN("Unknown offset %d\n", offset );
1796 SetLastError( ERROR_INVALID_INDEX );
1797 break;
1799 WIN_ReleasePtr(wndPtr);
1800 return retvalue;
1804 /**********************************************************************
1805 * WIN_SetWindowLong
1807 * Helper function for SetWindowLong().
1809 * 0 is the failure code. However, in the case of failure SetLastError
1810 * must be set to distinguish between a 0 return value and a failure.
1812 LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, UINT size, LONG_PTR newval, BOOL unicode )
1814 STYLESTRUCT style;
1815 BOOL ok;
1816 LONG_PTR retval = 0;
1817 WND *wndPtr;
1819 TRACE( "%p %d %lx %c\n", hwnd, offset, newval, unicode ? 'W' : 'A' );
1821 if (is_broadcast(hwnd))
1823 SetLastError( ERROR_INVALID_PARAMETER );
1824 return FALSE;
1827 if (!(wndPtr = WIN_GetPtr( hwnd )))
1829 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1830 return 0;
1832 if (wndPtr == WND_DESKTOP)
1834 /* can't change anything on the desktop window */
1835 SetLastError( ERROR_ACCESS_DENIED );
1836 return 0;
1838 if (wndPtr == WND_OTHER_PROCESS)
1840 if (offset == GWLP_WNDPROC)
1842 SetLastError( ERROR_ACCESS_DENIED );
1843 return 0;
1845 if (offset > 32767 || offset < -32767)
1847 SetLastError( ERROR_INVALID_INDEX );
1848 return 0;
1850 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, MAKEWPARAM( offset, size ), newval );
1853 /* first some special cases */
1854 switch( offset )
1856 case GWL_STYLE:
1857 case GWL_EXSTYLE:
1858 style.styleOld =
1859 offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
1860 style.styleNew = newval;
1861 WIN_ReleasePtr( wndPtr );
1862 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
1863 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
1864 newval = style.styleNew;
1865 break;
1866 case GWLP_HWNDPARENT:
1867 if (wndPtr->parent == GetDesktopWindow())
1869 WIN_ReleasePtr( wndPtr );
1870 return (ULONG_PTR)WIN_SetOwner( hwnd, (HWND)newval );
1872 else
1874 WIN_ReleasePtr( wndPtr );
1875 return (ULONG_PTR)SetParent( hwnd, (HWND)newval );
1877 case GWLP_WNDPROC:
1879 WNDPROC proc;
1880 UINT old_flags = wndPtr->flags;
1881 retval = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, unicode );
1882 if (unicode) proc = WINPROC_AllocProc( NULL, (WNDPROC)newval );
1883 else proc = WINPROC_AllocProc( (WNDPROC)newval, NULL );
1884 if (proc) wndPtr->winproc = proc;
1885 if (WINPROC_IsUnicode( proc, unicode )) wndPtr->flags |= WIN_ISUNICODE;
1886 else wndPtr->flags &= ~WIN_ISUNICODE;
1887 if (!((old_flags ^ wndPtr->flags) & WIN_ISUNICODE))
1889 WIN_ReleasePtr( wndPtr );
1890 return retval;
1892 /* update is_unicode flag on the server side */
1893 break;
1895 case GWLP_ID:
1896 case GWLP_HINSTANCE:
1897 case GWLP_USERDATA:
1898 break;
1899 case DWLP_DLGPROC:
1900 if ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
1901 (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG))
1903 WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWLP_DLGPROC);
1904 retval = (ULONG_PTR)WINPROC_GetProc( *ptr, unicode );
1905 if (unicode) *ptr = WINPROC_AllocProc( NULL, (WNDPROC)newval );
1906 else *ptr = WINPROC_AllocProc( (WNDPROC)newval, NULL );
1907 WIN_ReleasePtr( wndPtr );
1908 return retval;
1910 /* fall through */
1911 default:
1912 if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - size))
1914 WARN("Invalid offset %d\n", offset );
1915 WIN_ReleasePtr( wndPtr );
1916 SetLastError( ERROR_INVALID_INDEX );
1917 return 0;
1919 else if (get_win_data( (char *)wndPtr->wExtra + offset, size ) == newval)
1921 /* already set to the same value */
1922 WIN_ReleasePtr( wndPtr );
1923 return newval;
1925 break;
1928 SERVER_START_REQ( set_window_info )
1930 req->handle = hwnd;
1931 req->extra_offset = -1;
1932 switch(offset)
1934 case GWL_STYLE:
1935 req->flags = SET_WIN_STYLE;
1936 req->style = newval;
1937 break;
1938 case GWL_EXSTYLE:
1939 req->flags = SET_WIN_EXSTYLE;
1940 req->ex_style = newval;
1941 break;
1942 case GWLP_ID:
1943 req->flags = SET_WIN_ID;
1944 req->id = newval;
1945 break;
1946 case GWLP_HINSTANCE:
1947 req->flags = SET_WIN_INSTANCE;
1948 req->instance = (void *)newval;
1949 break;
1950 case GWLP_WNDPROC:
1951 req->flags = SET_WIN_UNICODE;
1952 req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
1953 break;
1954 case GWLP_USERDATA:
1955 req->flags = SET_WIN_USERDATA;
1956 req->user_data = newval;
1957 break;
1958 default:
1959 req->flags = SET_WIN_EXTRA;
1960 req->extra_offset = offset;
1961 req->extra_size = size;
1962 set_win_data( &req->extra_value, newval, size );
1964 if ((ok = !wine_server_call_err( req )))
1966 switch(offset)
1968 case GWL_STYLE:
1969 wndPtr->dwStyle = newval;
1970 retval = reply->old_style;
1971 break;
1972 case GWL_EXSTYLE:
1973 wndPtr->dwExStyle = newval;
1974 retval = reply->old_ex_style;
1975 break;
1976 case GWLP_ID:
1977 wndPtr->wIDmenu = newval;
1978 retval = reply->old_id;
1979 break;
1980 case GWLP_HINSTANCE:
1981 wndPtr->hInstance = (HINSTANCE)newval;
1982 retval = (ULONG_PTR)reply->old_instance;
1983 break;
1984 case GWLP_WNDPROC:
1985 break;
1986 case GWLP_USERDATA:
1987 wndPtr->userdata = newval;
1988 retval = reply->old_user_data;
1989 break;
1990 default:
1991 retval = get_win_data( (char *)wndPtr->wExtra + offset, size );
1992 set_win_data( (char *)wndPtr->wExtra + offset, newval, size );
1993 break;
1997 SERVER_END_REQ;
1998 WIN_ReleasePtr( wndPtr );
2000 if (!ok) return 0;
2002 if (offset == GWL_STYLE) USER_Driver->pSetWindowStyle( hwnd, retval );
2004 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2005 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2007 return retval;
2011 /**********************************************************************
2012 * GetWindowLong (USER.135)
2014 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2016 WND *wndPtr;
2017 LONG_PTR retvalue;
2018 BOOL is_winproc = (offset == GWLP_WNDPROC);
2020 if (offset >= 0)
2022 if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2024 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2025 return 0;
2027 if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2029 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
2032 * Some programs try to access last element from 16 bit
2033 * code using illegal offset value. Hopefully this is
2034 * what those programs really expect.
2036 if (wndPtr->cbWndExtra >= 4 && offset == wndPtr->cbWndExtra - sizeof(WORD))
2038 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
2039 ERR( "- replaced invalid offset %d with %d\n", offset, offset2 );
2040 offset = offset2;
2042 else
2044 WARN("Invalid offset %d\n", offset );
2045 WIN_ReleasePtr( wndPtr );
2046 SetLastError( ERROR_INVALID_INDEX );
2047 return 0;
2050 is_winproc = ((offset == DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG));
2051 WIN_ReleasePtr( wndPtr );
2054 retvalue = GetWindowLongA( WIN_Handle32(hwnd), offset );
2055 if (is_winproc) retvalue = (LONG_PTR)WINPROC_GetProc16( (WNDPROC)retvalue, FALSE );
2056 return retvalue;
2060 /**********************************************************************
2061 * GetWindowWord (USER32.@)
2063 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
2065 switch(offset)
2067 case GWLP_ID:
2068 case GWLP_HINSTANCE:
2069 case GWLP_HWNDPARENT:
2070 break;
2071 default:
2072 if (offset < 0)
2074 WARN("Invalid offset %d\n", offset );
2075 SetLastError( ERROR_INVALID_INDEX );
2076 return 0;
2078 break;
2080 return WIN_GetWindowLong( hwnd, offset, sizeof(WORD), FALSE );
2084 /**********************************************************************
2085 * GetWindowLongA (USER32.@)
2087 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2089 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), FALSE );
2093 /**********************************************************************
2094 * GetWindowLongW (USER32.@)
2096 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2098 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), TRUE );
2102 /**********************************************************************
2103 * SetWindowLong (USER.136)
2105 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2107 WND *wndPtr;
2108 BOOL is_winproc = (offset == GWLP_WNDPROC);
2110 if (offset == DWLP_DLGPROC)
2112 if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2114 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2115 return 0;
2117 if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2119 is_winproc = ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
2120 (wndPtr->flags & WIN_ISDIALOG));
2121 WIN_ReleasePtr( wndPtr );
2125 if (is_winproc)
2127 WNDPROC new_proc = WINPROC_AllocProc16( (WNDPROC16)newval );
2128 WNDPROC old_proc = (WNDPROC)SetWindowLongPtrA( WIN_Handle32(hwnd), offset, (LONG_PTR)new_proc );
2129 return (LONG)WINPROC_GetProc16( (WNDPROC)old_proc, FALSE );
2131 else return SetWindowLongA( WIN_Handle32(hwnd), offset, newval );
2135 /**********************************************************************
2136 * SetWindowWord (USER32.@)
2138 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
2140 switch(offset)
2142 case GWLP_ID:
2143 case GWLP_HINSTANCE:
2144 case GWLP_HWNDPARENT:
2145 break;
2146 default:
2147 if (offset < 0)
2149 WARN("Invalid offset %d\n", offset );
2150 SetLastError( ERROR_INVALID_INDEX );
2151 return 0;
2153 break;
2155 return WIN_SetWindowLong( hwnd, offset, sizeof(WORD), newval, FALSE );
2159 /**********************************************************************
2160 * SetWindowLongA (USER32.@)
2162 * See SetWindowLongW.
2164 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2166 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, FALSE );
2170 /**********************************************************************
2171 * SetWindowLongW (USER32.@) Set window attribute
2173 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2174 * value in a window's extra memory.
2176 * The _hwnd_ parameter specifies the window. is the handle to a
2177 * window that has extra memory. The _newval_ parameter contains the
2178 * new attribute or extra memory value. If positive, the _offset_
2179 * parameter is the byte-addressed location in the window's extra
2180 * memory to set. If negative, _offset_ specifies the window
2181 * attribute to set, and should be one of the following values:
2183 * GWL_EXSTYLE The window's extended window style
2185 * GWL_STYLE The window's window style.
2187 * GWLP_WNDPROC Pointer to the window's window procedure.
2189 * GWLP_HINSTANCE The window's pplication instance handle.
2191 * GWLP_ID The window's identifier.
2193 * GWLP_USERDATA The window's user-specified data.
2195 * If the window is a dialog box, the _offset_ parameter can be one of
2196 * the following values:
2198 * DWLP_DLGPROC The address of the window's dialog box procedure.
2200 * DWLP_MSGRESULT The return value of a message
2201 * that the dialog box procedure processed.
2203 * DWLP_USER Application specific information.
2205 * RETURNS
2207 * If successful, returns the previous value located at _offset_. Otherwise,
2208 * returns 0.
2210 * NOTES
2212 * Extra memory for a window class is specified by a nonzero cbWndExtra
2213 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2214 * time of class creation.
2216 * Using GWL_WNDPROC to set a new window procedure effectively creates
2217 * a window subclass. Use CallWindowProc() in the new windows procedure
2218 * to pass messages to the superclass's window procedure.
2220 * The user data is reserved for use by the application which created
2221 * the window.
2223 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2224 * instead, call the EnableWindow() function to change the window's
2225 * disabled state.
2227 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2228 * SetParent() instead.
2230 * Win95:
2231 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2232 * it sends WM_STYLECHANGING before changing the settings
2233 * and WM_STYLECHANGED afterwards.
2234 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2236 LONG WINAPI SetWindowLongW(
2237 HWND hwnd, /* [in] window to alter */
2238 INT offset, /* [in] offset, in bytes, of location to alter */
2239 LONG newval /* [in] new value of location */
2241 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, TRUE );
2245 /*******************************************************************
2246 * GetWindowTextA (USER32.@)
2248 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2250 WCHAR *buffer;
2252 if (!lpString) return 0;
2254 if (WIN_IsCurrentProcess( hwnd ))
2255 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2257 /* when window belongs to other process, don't send a message */
2258 if (nMaxCount <= 0) return 0;
2259 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2260 get_server_window_text( hwnd, buffer, nMaxCount );
2261 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2262 lpString[nMaxCount-1] = 0;
2263 HeapFree( GetProcessHeap(), 0, buffer );
2264 return strlen(lpString);
2268 /*******************************************************************
2269 * InternalGetWindowText (USER32.@)
2271 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2273 WND *win;
2275 if (nMaxCount <= 0) return 0;
2276 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2277 if (win == WND_DESKTOP) lpString[0] = 0;
2278 else if (win != WND_OTHER_PROCESS)
2280 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2281 else lpString[0] = 0;
2282 WIN_ReleasePtr( win );
2284 else
2286 get_server_window_text( hwnd, lpString, nMaxCount );
2288 return strlenW(lpString);
2292 /*******************************************************************
2293 * GetWindowTextW (USER32.@)
2295 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2297 if (!lpString) return 0;
2299 if (WIN_IsCurrentProcess( hwnd ))
2300 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2302 /* when window belongs to other process, don't send a message */
2303 if (nMaxCount <= 0) return 0;
2304 get_server_window_text( hwnd, lpString, nMaxCount );
2305 return strlenW(lpString);
2309 /*******************************************************************
2310 * SetWindowTextA (USER32.@)
2311 * SetWindowText (USER32.@)
2313 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2315 if (is_broadcast(hwnd))
2317 SetLastError( ERROR_INVALID_PARAMETER );
2318 return FALSE;
2320 if (!WIN_IsCurrentProcess( hwnd ))
2321 WARN( "setting text %s of other process window %p should not use SendMessage\n",
2322 debugstr_a(lpString), hwnd );
2323 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2327 /*******************************************************************
2328 * SetWindowTextW (USER32.@)
2330 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2332 if (is_broadcast(hwnd))
2334 SetLastError( ERROR_INVALID_PARAMETER );
2335 return FALSE;
2337 if (!WIN_IsCurrentProcess( hwnd ))
2338 WARN( "setting text %s of other process window %p should not use SendMessage\n",
2339 debugstr_w(lpString), hwnd );
2340 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2344 /*******************************************************************
2345 * GetWindowTextLengthA (USER32.@)
2347 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2349 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2352 /*******************************************************************
2353 * GetWindowTextLengthW (USER32.@)
2355 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2357 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2361 /*******************************************************************
2362 * IsWindow (USER32.@)
2364 BOOL WINAPI IsWindow( HWND hwnd )
2366 WND *ptr;
2367 BOOL ret;
2369 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2370 if (ptr == WND_DESKTOP) return TRUE;
2372 if (ptr != WND_OTHER_PROCESS)
2374 WIN_ReleasePtr( ptr );
2375 return TRUE;
2378 /* check other processes */
2379 SERVER_START_REQ( get_window_info )
2381 req->handle = hwnd;
2382 ret = !wine_server_call_err( req );
2384 SERVER_END_REQ;
2385 return ret;
2389 /***********************************************************************
2390 * GetWindowThreadProcessId (USER32.@)
2392 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2394 WND *ptr;
2395 DWORD tid = 0;
2397 if (!(ptr = WIN_GetPtr( hwnd )))
2399 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2400 return 0;
2403 if (ptr != WND_OTHER_PROCESS && ptr != WND_DESKTOP)
2405 /* got a valid window */
2406 tid = ptr->tid;
2407 if (process) *process = GetCurrentProcessId();
2408 WIN_ReleasePtr( ptr );
2409 return tid;
2412 /* check other processes */
2413 SERVER_START_REQ( get_window_info )
2415 req->handle = hwnd;
2416 if (!wine_server_call_err( req ))
2418 tid = (DWORD)reply->tid;
2419 if (process) *process = (DWORD)reply->pid;
2422 SERVER_END_REQ;
2423 return tid;
2427 /*****************************************************************
2428 * GetParent (USER32.@)
2430 HWND WINAPI GetParent( HWND hwnd )
2432 WND *wndPtr;
2433 HWND retvalue = 0;
2435 if (!(wndPtr = WIN_GetPtr( hwnd )))
2437 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2438 return 0;
2440 if (wndPtr == WND_DESKTOP) return 0;
2441 if (wndPtr == WND_OTHER_PROCESS)
2443 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2444 if (style & (WS_POPUP | WS_CHILD))
2446 SERVER_START_REQ( get_window_tree )
2448 req->handle = hwnd;
2449 if (!wine_server_call_err( req ))
2451 if (style & WS_POPUP) retvalue = reply->owner;
2452 else if (style & WS_CHILD) retvalue = reply->parent;
2455 SERVER_END_REQ;
2458 else
2460 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2461 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2462 WIN_ReleasePtr( wndPtr );
2464 return retvalue;
2468 /*****************************************************************
2469 * GetAncestor (USER32.@)
2471 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2473 WND *win;
2474 HWND *list, ret = 0;
2476 switch(type)
2478 case GA_PARENT:
2479 if (!(win = WIN_GetPtr( hwnd )))
2481 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2482 return 0;
2484 if (win == WND_DESKTOP) return 0;
2485 if (win != WND_OTHER_PROCESS)
2487 ret = win->parent;
2488 WIN_ReleasePtr( win );
2490 else /* need to query the server */
2492 SERVER_START_REQ( get_window_tree )
2494 req->handle = hwnd;
2495 if (!wine_server_call_err( req )) ret = reply->parent;
2497 SERVER_END_REQ;
2499 break;
2501 case GA_ROOT:
2502 if (!(list = list_window_parents( hwnd ))) return 0;
2504 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2505 else
2507 int count = 2;
2508 while (list[count]) count++;
2509 ret = list[count - 2]; /* get the one before the desktop */
2511 HeapFree( GetProcessHeap(), 0, list );
2512 break;
2514 case GA_ROOTOWNER:
2515 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2516 for (;;)
2518 HWND parent = GetParent( ret );
2519 if (!parent) break;
2520 ret = parent;
2522 break;
2524 return ret;
2528 /*****************************************************************
2529 * SetParent (USER32.@)
2531 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2533 HWND full_handle;
2534 HWND old_parent = 0;
2535 BOOL was_visible;
2536 WND *wndPtr;
2537 BOOL ret;
2539 if (is_broadcast(hwnd) || is_broadcast(parent))
2541 SetLastError(ERROR_INVALID_PARAMETER);
2542 return 0;
2545 if (!parent) parent = GetDesktopWindow();
2546 else parent = WIN_GetFullHandle( parent );
2548 if (!IsWindow( parent ))
2550 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2551 return 0;
2554 /* Some applications try to set a child as a parent */
2555 if (IsChild(hwnd, parent))
2557 SetLastError( ERROR_INVALID_PARAMETER );
2558 return 0;
2561 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2562 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2564 /* Windows hides the window first, then shows it again
2565 * including the WM_SHOWWINDOW messages and all */
2566 was_visible = ShowWindow( hwnd, SW_HIDE );
2568 wndPtr = WIN_GetPtr( hwnd );
2569 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return 0;
2571 SERVER_START_REQ( set_parent )
2573 req->handle = hwnd;
2574 req->parent = parent;
2575 if ((ret = !wine_server_call( req )))
2577 old_parent = reply->old_parent;
2578 wndPtr->parent = parent = reply->full_parent;
2582 SERVER_END_REQ;
2583 WIN_ReleasePtr( wndPtr );
2584 if (!ret) return 0;
2586 USER_Driver->pSetParent( full_handle, parent, old_parent );
2588 /* SetParent additionally needs to make hwnd the topmost window
2589 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2590 WM_WINDOWPOSCHANGED notification messages.
2592 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2593 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2594 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2595 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2597 return old_parent;
2601 /*******************************************************************
2602 * IsChild (USER32.@)
2604 BOOL WINAPI IsChild( HWND parent, HWND child )
2606 HWND *list = list_window_parents( child );
2607 int i;
2608 BOOL ret;
2610 if (!list) return FALSE;
2611 parent = WIN_GetFullHandle( parent );
2612 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2613 ret = (list[i] != 0);
2614 HeapFree( GetProcessHeap(), 0, list );
2615 return ret;
2619 /***********************************************************************
2620 * IsWindowVisible (USER32.@)
2622 BOOL WINAPI IsWindowVisible( HWND hwnd )
2624 HWND *list;
2625 BOOL retval = TRUE;
2626 int i;
2628 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2629 if (!(list = list_window_parents( hwnd ))) return TRUE;
2630 if (list[0] && list[1]) /* desktop window is considered always visible so we don't check it */
2632 for (i = 0; list[i+1]; i++)
2633 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2634 retval = !list[i+1];
2636 HeapFree( GetProcessHeap(), 0, list );
2637 return retval;
2641 /***********************************************************************
2642 * WIN_IsWindowDrawable
2644 * hwnd is drawable when it is visible, all parents are not
2645 * minimized, and it is itself not minimized unless we are
2646 * trying to draw its default class icon.
2648 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2650 HWND *list;
2651 BOOL retval = TRUE;
2652 int i;
2653 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2655 if (!(style & WS_VISIBLE)) return FALSE;
2656 if ((style & WS_MINIMIZE) && icon && GetClassLongPtrW( hwnd, GCLP_HICON )) return FALSE;
2658 if (!(list = list_window_parents( hwnd ))) return TRUE;
2659 if (list[0] && list[1]) /* desktop window is considered always visible so we don't check it */
2661 for (i = 0; list[i+1]; i++)
2662 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2663 break;
2664 retval = !list[i+1];
2666 HeapFree( GetProcessHeap(), 0, list );
2667 return retval;
2671 /*******************************************************************
2672 * GetTopWindow (USER32.@)
2674 HWND WINAPI GetTopWindow( HWND hwnd )
2676 if (!hwnd) hwnd = GetDesktopWindow();
2677 return GetWindow( hwnd, GW_CHILD );
2681 /*******************************************************************
2682 * GetWindow (USER32.@)
2684 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2686 HWND retval = 0;
2688 if (rel == GW_OWNER) /* this one may be available locally */
2690 WND *wndPtr = WIN_GetPtr( hwnd );
2691 if (!wndPtr)
2693 SetLastError( ERROR_INVALID_HANDLE );
2694 return 0;
2696 if (wndPtr == WND_DESKTOP) return 0;
2697 if (wndPtr != WND_OTHER_PROCESS)
2699 retval = wndPtr->owner;
2700 WIN_ReleasePtr( wndPtr );
2701 return retval;
2703 /* else fall through to server call */
2706 SERVER_START_REQ( get_window_tree )
2708 req->handle = hwnd;
2709 if (!wine_server_call_err( req ))
2711 switch(rel)
2713 case GW_HWNDFIRST:
2714 retval = reply->first_sibling;
2715 break;
2716 case GW_HWNDLAST:
2717 retval = reply->last_sibling;
2718 break;
2719 case GW_HWNDNEXT:
2720 retval = reply->next_sibling;
2721 break;
2722 case GW_HWNDPREV:
2723 retval = reply->prev_sibling;
2724 break;
2725 case GW_OWNER:
2726 retval = reply->owner;
2727 break;
2728 case GW_CHILD:
2729 retval = reply->first_child;
2730 break;
2734 SERVER_END_REQ;
2735 return retval;
2739 /*******************************************************************
2740 * ShowOwnedPopups (USER32.@)
2742 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2744 int count = 0;
2745 WND *pWnd;
2746 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2748 if (!win_array) return TRUE;
2750 while (win_array[count]) count++;
2751 while (--count >= 0)
2753 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2754 if (!(pWnd = WIN_GetPtr( win_array[count] ))) continue;
2755 if (pWnd == WND_OTHER_PROCESS) continue;
2756 if (fShow)
2758 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2760 WIN_ReleasePtr( pWnd );
2761 /* In Windows, ShowOwnedPopups(TRUE) generates
2762 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2763 * regardless of the state of the owner
2765 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_SHOWNORMAL, SW_PARENTOPENING);
2766 continue;
2769 else
2771 if (pWnd->dwStyle & WS_VISIBLE)
2773 WIN_ReleasePtr( pWnd );
2774 /* In Windows, ShowOwnedPopups(FALSE) generates
2775 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2776 * regardless of the state of the owner
2778 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2779 continue;
2782 WIN_ReleasePtr( pWnd );
2784 HeapFree( GetProcessHeap(), 0, win_array );
2785 return TRUE;
2789 /*******************************************************************
2790 * GetLastActivePopup (USER32.@)
2792 HWND WINAPI GetLastActivePopup( HWND hwnd )
2794 HWND retval = hwnd;
2796 SERVER_START_REQ( get_window_info )
2798 req->handle = hwnd;
2799 if (!wine_server_call_err( req )) retval = reply->last_active;
2801 SERVER_END_REQ;
2802 return retval;
2806 /*******************************************************************
2807 * WIN_ListChildren
2809 * Build an array of the children of a given window. The array must be
2810 * freed with HeapFree. Returns NULL when no windows are found.
2812 HWND *WIN_ListChildren( HWND hwnd )
2814 return list_window_children( hwnd, 0, 0 );
2818 /*******************************************************************
2819 * EnumWindows (USER32.@)
2821 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2823 HWND *list;
2824 BOOL ret = TRUE;
2825 int i;
2827 USER_CheckNotLock();
2829 /* We have to build a list of all windows first, to avoid */
2830 /* unpleasant side-effects, for instance if the callback */
2831 /* function changes the Z-order of the windows. */
2833 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2835 /* Now call the callback function for every window */
2837 for (i = 0; list[i]; i++)
2839 /* Make sure that the window still exists */
2840 if (!IsWindow( list[i] )) continue;
2841 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2843 HeapFree( GetProcessHeap(), 0, list );
2844 return ret;
2848 /**********************************************************************
2849 * EnumThreadWindows (USER32.@)
2851 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2853 HWND *list;
2854 int i;
2856 USER_CheckNotLock();
2858 if (!(list = list_window_children( GetDesktopWindow(), 0, id ))) return TRUE;
2860 /* Now call the callback function for every window */
2862 for (i = 0; list[i]; i++)
2863 if (!func( list[i], lParam )) break;
2864 HeapFree( GetProcessHeap(), 0, list );
2865 return TRUE;
2869 /**********************************************************************
2870 * WIN_EnumChildWindows
2872 * Helper function for EnumChildWindows().
2874 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2876 HWND *childList;
2877 BOOL ret = FALSE;
2879 for ( ; *list; list++)
2881 /* Make sure that the window still exists */
2882 if (!IsWindow( *list )) continue;
2883 /* Build children list first */
2884 childList = WIN_ListChildren( *list );
2886 ret = func( *list, lParam );
2888 if (childList)
2890 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2891 HeapFree( GetProcessHeap(), 0, childList );
2893 if (!ret) return FALSE;
2895 return TRUE;
2899 /**********************************************************************
2900 * EnumChildWindows (USER32.@)
2902 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2904 HWND *list;
2905 BOOL ret;
2907 USER_CheckNotLock();
2909 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2910 ret = WIN_EnumChildWindows( list, func, lParam );
2911 HeapFree( GetProcessHeap(), 0, list );
2912 return ret;
2916 /*******************************************************************
2917 * AnyPopup (USER.52)
2919 BOOL16 WINAPI AnyPopup16(void)
2921 return AnyPopup();
2925 /*******************************************************************
2926 * AnyPopup (USER32.@)
2928 BOOL WINAPI AnyPopup(void)
2930 int i;
2931 BOOL retvalue;
2932 HWND *list = WIN_ListChildren( GetDesktopWindow() );
2934 if (!list) return FALSE;
2935 for (i = 0; list[i]; i++)
2937 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
2939 retvalue = (list[i] != 0);
2940 HeapFree( GetProcessHeap(), 0, list );
2941 return retvalue;
2945 /*******************************************************************
2946 * FlashWindow (USER32.@)
2948 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2950 WND *wndPtr;
2952 TRACE("%p\n", hWnd);
2954 if (IsIconic( hWnd ))
2956 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
2958 wndPtr = WIN_GetPtr(hWnd);
2959 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
2960 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2962 wndPtr->flags |= WIN_NCACTIVATED;
2964 else
2966 wndPtr->flags &= ~WIN_NCACTIVATED;
2968 WIN_ReleasePtr( wndPtr );
2969 return TRUE;
2971 else
2973 WPARAM wparam;
2975 wndPtr = WIN_GetPtr(hWnd);
2976 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
2977 hWnd = wndPtr->hwndSelf; /* make it a full handle */
2979 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2980 else wparam = (hWnd == GetForegroundWindow());
2982 WIN_ReleasePtr( wndPtr );
2983 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2984 return wparam;
2988 /*******************************************************************
2989 * FlashWindowEx (USER32.@)
2991 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
2993 FIXME("%p\n", pfwi);
2994 return TRUE;
2997 /*******************************************************************
2998 * GetWindowContextHelpId (USER32.@)
3000 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3002 DWORD retval;
3003 WND *wnd = WIN_GetPtr( hwnd );
3004 if (!wnd || wnd == WND_DESKTOP) return 0;
3005 if (wnd == WND_OTHER_PROCESS)
3007 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3008 return 0;
3010 retval = wnd->helpContext;
3011 WIN_ReleasePtr( wnd );
3012 return retval;
3016 /*******************************************************************
3017 * SetWindowContextHelpId (USER32.@)
3019 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3021 WND *wnd = WIN_GetPtr( hwnd );
3022 if (!wnd || wnd == WND_DESKTOP) return FALSE;
3023 if (wnd == WND_OTHER_PROCESS)
3025 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3026 return 0;
3028 wnd->helpContext = id;
3029 WIN_ReleasePtr( wnd );
3030 return TRUE;
3034 /*******************************************************************
3035 * DragDetect (USER32.@)
3037 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3039 MSG msg;
3040 RECT rect;
3041 WORD wDragWidth = GetSystemMetrics(SM_CXDRAG);
3042 WORD wDragHeight= GetSystemMetrics(SM_CYDRAG);
3044 rect.left = pt.x - wDragWidth;
3045 rect.right = pt.x + wDragWidth;
3047 rect.top = pt.y - wDragHeight;
3048 rect.bottom = pt.y + wDragHeight;
3050 SetCapture(hWnd);
3052 while(1)
3054 while (PeekMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ))
3056 if( msg.message == WM_LBUTTONUP )
3058 ReleaseCapture();
3059 return 0;
3061 if( msg.message == WM_MOUSEMOVE )
3063 POINT tmp;
3064 tmp.x = (short)LOWORD(msg.lParam);
3065 tmp.y = (short)HIWORD(msg.lParam);
3066 if( !PtInRect( &rect, tmp ))
3068 ReleaseCapture();
3069 return 1;
3073 WaitMessage();
3075 return 0;
3078 /******************************************************************************
3079 * GetWindowModuleFileNameA (USER32.@)
3081 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3083 FIXME("GetWindowModuleFileNameA(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3084 hwnd, lpszFileName, cchFileNameMax);
3085 return 0;
3088 /******************************************************************************
3089 * GetWindowModuleFileNameW (USER32.@)
3091 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR lpszFileName, UINT cchFileNameMax)
3093 FIXME("GetWindowModuleFileNameW(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3094 hwnd, lpszFileName, cchFileNameMax);
3095 return 0;
3098 /******************************************************************************
3099 * GetWindowInfo (USER32.@)
3101 * Note: tests show that Windows doesn't check cbSize of the structure.
3103 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3105 if (!pwi) return FALSE;
3106 if (!IsWindow(hwnd)) return FALSE;
3108 GetWindowRect(hwnd, &pwi->rcWindow);
3109 GetClientRect(hwnd, &pwi->rcClient);
3110 /* translate to screen coordinates */
3111 MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3113 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3114 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3115 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3117 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3118 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3120 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3121 pwi->wCreatorVersion = 0x0400;
3123 return TRUE;
3126 /******************************************************************************
3127 * SwitchDesktop (USER32.@)
3129 * NOTES: Sets the current input or interactive desktop.
3131 BOOL WINAPI SwitchDesktop( HDESK hDesktop)
3133 FIXME("SwitchDesktop(hwnd %p) stub!\n", hDesktop);
3134 return TRUE;
3137 /*****************************************************************************
3138 * SetLayeredWindowAttributes (USER32.@)
3140 BOOL WINAPI SetLayeredWindowAttributes( HWND hWnd, COLORREF rgbKey,
3141 BYTE bAlpha, DWORD dwFlags )
3143 FIXME("(%p,0x%.8x,%d,%d): stub!\n", hWnd, rgbKey, bAlpha, dwFlags);
3144 return TRUE;
3147 /*****************************************************************************
3148 * UpdateLayeredWindow (USER32.@)
3150 BOOL WINAPI UpdateLayeredWindow( HWND hwnd, HDC hdcDst, POINT *pptDst, SIZE *psize,
3151 HDC hdcSrc, POINT *pptSrc, COLORREF crKey, BLENDFUNCTION *pblend,
3152 DWORD dwFlags)
3154 static int once;
3155 if (!once)
3157 once = 1;
3158 FIXME("(%p,%p,%p,%p,%p,%p,0x%08x,%p,%d): stub!\n",
3159 hwnd, hdcDst, pptDst, psize, hdcSrc, pptSrc, crKey, pblend, dwFlags);
3161 return 0;
3164 /* 64bit versions */
3166 #ifdef GetWindowLongPtrW
3167 #undef GetWindowLongPtrW
3168 #endif
3170 #ifdef GetWindowLongPtrA
3171 #undef GetWindowLongPtrA
3172 #endif
3174 #ifdef SetWindowLongPtrW
3175 #undef SetWindowLongPtrW
3176 #endif
3178 #ifdef SetWindowLongPtrA
3179 #undef SetWindowLongPtrA
3180 #endif
3182 /*****************************************************************************
3183 * GetWindowLongPtrW (USER32.@)
3185 LONG_PTR WINAPI GetWindowLongPtrW( HWND hwnd, INT offset )
3187 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), TRUE );
3190 /*****************************************************************************
3191 * GetWindowLongPtrA (USER32.@)
3193 LONG_PTR WINAPI GetWindowLongPtrA( HWND hwnd, INT offset )
3195 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), FALSE );
3198 /*****************************************************************************
3199 * SetWindowLongPtrW (USER32.@)
3201 LONG_PTR WINAPI SetWindowLongPtrW( HWND hwnd, INT offset, LONG_PTR newval )
3203 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, TRUE );
3206 /*****************************************************************************
3207 * SetWindowLongPtrA (USER32.@)
3209 LONG_PTR WINAPI SetWindowLongPtrA( HWND hwnd, INT offset, LONG_PTR newval )
3211 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, FALSE );