Changes in crossover-wine-src-6.1.0 except for configure
[wine/hacks.git] / dlls / user32 / win.c
blobc6d17bf05537536fc369c61c608d2474a3ed9648
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 = (HMENU)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 /* CodeWeavers HACK:
1482 * Fix Outlook 2003 exit hang by not trying to send WM_GETTEXT to
1483 * a hung window. See bug 2753. */
1484 /* Note: not nul terminated */
1485 static const WCHAR wszOutlookHungWindow[] = {'W','M','S',' ','S','T',' ','N','o','t','i','f',' ','W','i','n','d','o','w',' '};
1486 if (!memcmp( title, wszOutlookHungWindow, sizeof(wszOutlookHungWindow) ))
1488 FIXME("possibly hung window %s\n", debugstr_w(title));
1489 if (IsHungAppWindow( list[i] ))
1491 FIXME("window %s is hung\n", debugstr_w(title));
1492 i++;
1493 continue;
1497 if (GetWindowTextW( list[i], buffer, len + 1 ) && !strcmpiW( buffer, title )) break;
1498 i++;
1501 retvalue = list[i];
1503 done:
1504 HeapFree( GetProcessHeap(), 0, list );
1505 HeapFree( GetProcessHeap(), 0, buffer );
1506 return retvalue;
1511 /***********************************************************************
1512 * FindWindowA (USER32.@)
1514 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1516 HWND ret = FindWindowExA( 0, 0, className, title );
1517 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1518 return ret;
1522 /***********************************************************************
1523 * FindWindowExA (USER32.@)
1525 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1526 LPCSTR className, LPCSTR title )
1528 ATOM atom = 0;
1529 LPWSTR buffer;
1530 HWND hwnd;
1531 INT len;
1533 if (className)
1535 /* If the atom doesn't exist, then no class */
1536 /* with this name exists either. */
1537 if (!(atom = GlobalFindAtomA( className )))
1539 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1540 return 0;
1543 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
1545 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1546 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1547 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
1548 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1549 HeapFree( GetProcessHeap(), 0, buffer );
1550 return hwnd;
1554 /***********************************************************************
1555 * FindWindowExW (USER32.@)
1557 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1558 LPCWSTR className, LPCWSTR title )
1560 ATOM atom = 0;
1562 if (className)
1564 /* If the atom doesn't exist, then no class */
1565 /* with this name exists either. */
1566 if (!(atom = GlobalFindAtomW( className )))
1568 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1569 return 0;
1572 return WIN_FindWindow( parent, child, atom, title );
1576 /***********************************************************************
1577 * FindWindowW (USER32.@)
1579 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1581 return FindWindowExW( 0, 0, className, title );
1585 /**********************************************************************
1586 * GetDesktopWindow (USER32.@)
1588 HWND WINAPI GetDesktopWindow(void)
1590 struct user_thread_info *thread_info = get_user_thread_info();
1592 if (thread_info->desktop) return thread_info->desktop;
1594 SERVER_START_REQ( get_desktop_window )
1596 req->force = 0;
1597 if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1599 SERVER_END_REQ;
1601 if (!thread_info->desktop)
1603 static const WCHAR command_line[] = {'\\','e','x','p','l','o','r','e','r','.','e','x','e',' ','/','d','e','s','k','t','o','p',0};
1604 STARTUPINFOW si;
1605 PROCESS_INFORMATION pi;
1606 WCHAR cmdline[MAX_PATH + sizeof(command_line)/sizeof(WCHAR)];
1608 memset( &si, 0, sizeof(si) );
1609 si.cb = sizeof(si);
1610 GetSystemDirectoryW( cmdline, MAX_PATH );
1611 lstrcatW( cmdline, command_line );
1612 if (CreateProcessW( NULL, cmdline, NULL, NULL, FALSE, DETACHED_PROCESS,
1613 NULL, NULL, &si, &pi ))
1615 TRACE( "started explorer pid %04x tid %04x\n", pi.dwProcessId, pi.dwThreadId );
1616 WaitForInputIdle( pi.hProcess, 10000 );
1617 CloseHandle( pi.hThread );
1618 CloseHandle( pi.hProcess );
1621 else WARN( "failed to start explorer, err %d\n", GetLastError() );
1623 SERVER_START_REQ( get_desktop_window )
1625 req->force = 1;
1626 if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1628 SERVER_END_REQ;
1631 if (!thread_info->desktop || !USER_Driver->pCreateDesktopWindow( thread_info->desktop ))
1632 ERR( "failed to create desktop window\n" );
1634 return thread_info->desktop;
1638 /*******************************************************************
1639 * EnableWindow (USER32.@)
1641 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1643 BOOL retvalue;
1644 HWND full_handle;
1646 if (is_broadcast(hwnd))
1648 SetLastError( ERROR_INVALID_PARAMETER );
1649 return FALSE;
1652 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1653 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1655 hwnd = full_handle;
1657 TRACE("( %p, %d )\n", hwnd, enable);
1659 retvalue = !IsWindowEnabled( hwnd );
1661 if (enable && retvalue)
1663 WIN_SetStyle( hwnd, 0, WS_DISABLED );
1664 SendMessageW( hwnd, WM_ENABLE, TRUE, 0 );
1666 else if (!enable && !retvalue)
1668 HWND capture_wnd;
1670 SendMessageW( hwnd, WM_CANCELMODE, 0, 0);
1672 WIN_SetStyle( hwnd, WS_DISABLED, 0 );
1674 if (hwnd == GetFocus())
1675 SetFocus( 0 ); /* A disabled window can't have the focus */
1677 capture_wnd = GetCapture();
1678 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1679 ReleaseCapture(); /* A disabled window can't capture the mouse */
1681 SendMessageW( hwnd, WM_ENABLE, FALSE, 0 );
1683 return retvalue;
1687 /***********************************************************************
1688 * IsWindowEnabled (USER32.@)
1690 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1692 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1696 /***********************************************************************
1697 * IsWindowUnicode (USER32.@)
1699 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1701 WND * wndPtr;
1702 BOOL retvalue = FALSE;
1704 if (!(wndPtr = WIN_GetPtr(hwnd))) return FALSE;
1706 if (wndPtr == WND_DESKTOP) return TRUE;
1708 if (wndPtr != WND_OTHER_PROCESS)
1710 retvalue = (wndPtr->flags & WIN_ISUNICODE) != 0;
1711 WIN_ReleasePtr( wndPtr );
1713 else
1715 SERVER_START_REQ( get_window_info )
1717 req->handle = hwnd;
1718 if (!wine_server_call_err( req )) retvalue = reply->is_unicode;
1720 SERVER_END_REQ;
1722 return retvalue;
1726 /**********************************************************************
1727 * WIN_GetWindowLong
1729 * Helper function for GetWindowLong().
1731 static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, UINT size, BOOL unicode )
1733 LONG_PTR retvalue = 0;
1734 WND *wndPtr;
1736 if (offset == GWLP_HWNDPARENT)
1738 HWND parent = GetAncestor( hwnd, GA_PARENT );
1739 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1740 return (ULONG_PTR)parent;
1743 if (!(wndPtr = WIN_GetPtr( hwnd )))
1745 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1746 return 0;
1749 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1751 if (offset == GWLP_WNDPROC)
1753 SetLastError( ERROR_ACCESS_DENIED );
1754 return 0;
1756 SERVER_START_REQ( set_window_info )
1758 req->handle = hwnd;
1759 req->flags = 0; /* don't set anything, just retrieve */
1760 req->extra_offset = (offset >= 0) ? offset : -1;
1761 req->extra_size = (offset >= 0) ? size : 0;
1762 if (!wine_server_call_err( req ))
1764 switch(offset)
1766 case GWL_STYLE: retvalue = reply->old_style; break;
1767 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1768 case GWLP_ID: retvalue = reply->old_id; break;
1769 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1770 case GWLP_USERDATA: retvalue = reply->old_user_data; break;
1771 default:
1772 if (offset >= 0) retvalue = get_win_data( &reply->old_extra_value, size );
1773 else SetLastError( ERROR_INVALID_INDEX );
1774 break;
1778 SERVER_END_REQ;
1779 return retvalue;
1782 /* now we have a valid wndPtr */
1784 if (offset >= 0)
1786 if (offset > (int)(wndPtr->cbWndExtra - size))
1788 WARN("Invalid offset %d\n", offset );
1789 WIN_ReleasePtr( wndPtr );
1790 SetLastError( ERROR_INVALID_INDEX );
1791 return 0;
1793 retvalue = get_win_data( (char *)wndPtr->wExtra + offset, size );
1795 /* Special case for dialog window procedure */
1796 if ((offset == DWLP_DLGPROC) && (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG))
1797 retvalue = (LONG_PTR)WINPROC_GetProc( (WNDPROC)retvalue, unicode );
1798 WIN_ReleasePtr( wndPtr );
1799 return retvalue;
1802 switch(offset)
1804 case GWLP_USERDATA: retvalue = wndPtr->userdata; break;
1805 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1806 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1807 case GWLP_ID: retvalue = (ULONG_PTR)wndPtr->wIDmenu; break;
1808 case GWLP_WNDPROC: retvalue = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, unicode ); break;
1809 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wndPtr->hInstance; break;
1810 default:
1811 WARN("Unknown offset %d\n", offset );
1812 SetLastError( ERROR_INVALID_INDEX );
1813 break;
1815 WIN_ReleasePtr(wndPtr);
1816 return retvalue;
1820 /**********************************************************************
1821 * WIN_SetWindowLong
1823 * Helper function for SetWindowLong().
1825 * 0 is the failure code. However, in the case of failure SetLastError
1826 * must be set to distinguish between a 0 return value and a failure.
1828 LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, UINT size, LONG_PTR newval, BOOL unicode )
1830 STYLESTRUCT style;
1831 BOOL ok;
1832 LONG_PTR retval = 0;
1833 WND *wndPtr;
1835 TRACE( "%p %d %lx %c\n", hwnd, offset, newval, unicode ? 'W' : 'A' );
1837 if (is_broadcast(hwnd))
1839 SetLastError( ERROR_INVALID_PARAMETER );
1840 return FALSE;
1843 if (!(wndPtr = WIN_GetPtr( hwnd )))
1845 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1846 return 0;
1848 if (wndPtr == WND_DESKTOP)
1850 /* can't change anything on the desktop window */
1851 SetLastError( ERROR_ACCESS_DENIED );
1852 return 0;
1854 if (wndPtr == WND_OTHER_PROCESS)
1856 if (offset == GWLP_WNDPROC)
1858 SetLastError( ERROR_ACCESS_DENIED );
1859 return 0;
1861 if (offset > 32767 || offset < -32767)
1863 SetLastError( ERROR_INVALID_INDEX );
1864 return 0;
1866 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, MAKEWPARAM( offset, size ), newval );
1869 /* first some special cases */
1870 switch( offset )
1872 case GWL_STYLE:
1873 case GWL_EXSTYLE:
1874 style.styleOld =
1875 offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
1876 style.styleNew = newval;
1877 WIN_ReleasePtr( wndPtr );
1878 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
1879 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
1880 newval = style.styleNew;
1881 break;
1882 case GWLP_HWNDPARENT:
1883 if (wndPtr->parent == GetDesktopWindow())
1885 WIN_ReleasePtr( wndPtr );
1886 return (ULONG_PTR)WIN_SetOwner( hwnd, (HWND)newval );
1888 else
1890 WIN_ReleasePtr( wndPtr );
1891 return (ULONG_PTR)SetParent( hwnd, (HWND)newval );
1893 case GWLP_WNDPROC:
1895 WNDPROC proc;
1896 UINT old_flags = wndPtr->flags;
1897 retval = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, unicode );
1898 if (unicode) proc = WINPROC_AllocProc( NULL, (WNDPROC)newval );
1899 else proc = WINPROC_AllocProc( (WNDPROC)newval, NULL );
1900 if (proc) wndPtr->winproc = proc;
1901 if (WINPROC_IsUnicode( proc, unicode )) wndPtr->flags |= WIN_ISUNICODE;
1902 else wndPtr->flags &= ~WIN_ISUNICODE;
1903 if (!((old_flags ^ wndPtr->flags) & WIN_ISUNICODE))
1905 WIN_ReleasePtr( wndPtr );
1906 return retval;
1908 /* update is_unicode flag on the server side */
1909 break;
1911 case GWLP_ID:
1912 case GWLP_HINSTANCE:
1913 case GWLP_USERDATA:
1914 break;
1915 case DWLP_DLGPROC:
1916 if ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
1917 (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG))
1919 WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWLP_DLGPROC);
1920 retval = (ULONG_PTR)WINPROC_GetProc( *ptr, unicode );
1921 if (unicode) *ptr = WINPROC_AllocProc( NULL, (WNDPROC)newval );
1922 else *ptr = WINPROC_AllocProc( (WNDPROC)newval, NULL );
1923 WIN_ReleasePtr( wndPtr );
1924 return retval;
1926 /* fall through */
1927 default:
1928 if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - size))
1930 WARN("Invalid offset %d\n", offset );
1931 WIN_ReleasePtr( wndPtr );
1932 SetLastError( ERROR_INVALID_INDEX );
1933 return 0;
1935 else if (get_win_data( (char *)wndPtr->wExtra + offset, size ) == newval)
1937 /* already set to the same value */
1938 WIN_ReleasePtr( wndPtr );
1939 return newval;
1941 break;
1944 SERVER_START_REQ( set_window_info )
1946 req->handle = hwnd;
1947 req->extra_offset = -1;
1948 switch(offset)
1950 case GWL_STYLE:
1951 req->flags = SET_WIN_STYLE;
1952 req->style = newval;
1953 break;
1954 case GWL_EXSTYLE:
1955 req->flags = SET_WIN_EXSTYLE;
1956 req->ex_style = newval;
1957 break;
1958 case GWLP_ID:
1959 req->flags = SET_WIN_ID;
1960 req->id = newval;
1961 break;
1962 case GWLP_HINSTANCE:
1963 req->flags = SET_WIN_INSTANCE;
1964 req->instance = (void *)newval;
1965 break;
1966 case GWLP_WNDPROC:
1967 req->flags = SET_WIN_UNICODE;
1968 req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
1969 break;
1970 case GWLP_USERDATA:
1971 req->flags = SET_WIN_USERDATA;
1972 req->user_data = newval;
1973 break;
1974 default:
1975 req->flags = SET_WIN_EXTRA;
1976 req->extra_offset = offset;
1977 req->extra_size = size;
1978 set_win_data( &req->extra_value, newval, size );
1980 if ((ok = !wine_server_call_err( req )))
1982 switch(offset)
1984 case GWL_STYLE:
1985 wndPtr->dwStyle = newval;
1986 retval = reply->old_style;
1987 break;
1988 case GWL_EXSTYLE:
1989 wndPtr->dwExStyle = newval;
1990 retval = reply->old_ex_style;
1991 break;
1992 case GWLP_ID:
1993 wndPtr->wIDmenu = newval;
1994 retval = reply->old_id;
1995 break;
1996 case GWLP_HINSTANCE:
1997 wndPtr->hInstance = (HINSTANCE)newval;
1998 retval = (ULONG_PTR)reply->old_instance;
1999 break;
2000 case GWLP_WNDPROC:
2001 break;
2002 case GWLP_USERDATA:
2003 wndPtr->userdata = newval;
2004 retval = reply->old_user_data;
2005 break;
2006 default:
2007 retval = get_win_data( (char *)wndPtr->wExtra + offset, size );
2008 set_win_data( (char *)wndPtr->wExtra + offset, newval, size );
2009 break;
2013 SERVER_END_REQ;
2014 WIN_ReleasePtr( wndPtr );
2016 if (!ok) return 0;
2018 if (offset == GWL_STYLE) USER_Driver->pSetWindowStyle( hwnd, retval );
2020 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2021 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2023 return retval;
2027 /**********************************************************************
2028 * GetWindowLong (USER.135)
2030 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2032 WND *wndPtr;
2033 LONG_PTR retvalue;
2034 BOOL is_winproc = (offset == GWLP_WNDPROC);
2036 if (offset >= 0)
2038 if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2040 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2041 return 0;
2043 if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2045 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
2048 * Some programs try to access last element from 16 bit
2049 * code using illegal offset value. Hopefully this is
2050 * what those programs really expect.
2052 if (wndPtr->cbWndExtra >= 4 && offset == wndPtr->cbWndExtra - sizeof(WORD))
2054 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
2055 ERR( "- replaced invalid offset %d with %d\n", offset, offset2 );
2056 offset = offset2;
2058 else
2060 WARN("Invalid offset %d\n", offset );
2061 WIN_ReleasePtr( wndPtr );
2062 SetLastError( ERROR_INVALID_INDEX );
2063 return 0;
2066 is_winproc = ((offset == DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG));
2067 WIN_ReleasePtr( wndPtr );
2070 retvalue = GetWindowLongA( WIN_Handle32(hwnd), offset );
2071 if (is_winproc) retvalue = (LONG_PTR)WINPROC_GetProc16( (WNDPROC)retvalue, FALSE );
2072 return retvalue;
2076 /**********************************************************************
2077 * GetWindowWord (USER32.@)
2079 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
2081 switch(offset)
2083 case GWLP_ID:
2084 case GWLP_HINSTANCE:
2085 case GWLP_HWNDPARENT:
2086 break;
2087 default:
2088 if (offset < 0)
2090 WARN("Invalid offset %d\n", offset );
2091 SetLastError( ERROR_INVALID_INDEX );
2092 return 0;
2094 break;
2096 return WIN_GetWindowLong( hwnd, offset, sizeof(WORD), FALSE );
2100 /**********************************************************************
2101 * GetWindowLongA (USER32.@)
2103 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2105 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), FALSE );
2109 /**********************************************************************
2110 * GetWindowLongW (USER32.@)
2112 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2114 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), TRUE );
2118 /**********************************************************************
2119 * SetWindowLong (USER.136)
2121 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2123 WND *wndPtr;
2124 BOOL is_winproc = (offset == GWLP_WNDPROC);
2126 if (offset == DWLP_DLGPROC)
2128 if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2130 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2131 return 0;
2133 if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2135 is_winproc = ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
2136 (wndPtr->flags & WIN_ISDIALOG));
2137 WIN_ReleasePtr( wndPtr );
2141 if (is_winproc)
2143 WNDPROC new_proc = WINPROC_AllocProc16( (WNDPROC16)newval );
2144 WNDPROC old_proc = (WNDPROC)SetWindowLongA( WIN_Handle32(hwnd), offset, (LONG_PTR)new_proc );
2145 return (LONG)WINPROC_GetProc16( (WNDPROC)old_proc, FALSE );
2147 else return SetWindowLongA( WIN_Handle32(hwnd), offset, newval );
2151 /**********************************************************************
2152 * SetWindowWord (USER32.@)
2154 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
2156 switch(offset)
2158 case GWLP_ID:
2159 case GWLP_HINSTANCE:
2160 case GWLP_HWNDPARENT:
2161 break;
2162 default:
2163 if (offset < 0)
2165 WARN("Invalid offset %d\n", offset );
2166 SetLastError( ERROR_INVALID_INDEX );
2167 return 0;
2169 break;
2171 return WIN_SetWindowLong( hwnd, offset, sizeof(WORD), newval, FALSE );
2175 /**********************************************************************
2176 * SetWindowLongA (USER32.@)
2178 * See SetWindowLongW.
2180 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2182 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, FALSE );
2186 /**********************************************************************
2187 * SetWindowLongW (USER32.@) Set window attribute
2189 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2190 * value in a window's extra memory.
2192 * The _hwnd_ parameter specifies the window. is the handle to a
2193 * window that has extra memory. The _newval_ parameter contains the
2194 * new attribute or extra memory value. If positive, the _offset_
2195 * parameter is the byte-addressed location in the window's extra
2196 * memory to set. If negative, _offset_ specifies the window
2197 * attribute to set, and should be one of the following values:
2199 * GWL_EXSTYLE The window's extended window style
2201 * GWL_STYLE The window's window style.
2203 * GWLP_WNDPROC Pointer to the window's window procedure.
2205 * GWLP_HINSTANCE The window's pplication instance handle.
2207 * GWLP_ID The window's identifier.
2209 * GWLP_USERDATA The window's user-specified data.
2211 * If the window is a dialog box, the _offset_ parameter can be one of
2212 * the following values:
2214 * DWLP_DLGPROC The address of the window's dialog box procedure.
2216 * DWLP_MSGRESULT The return value of a message
2217 * that the dialog box procedure processed.
2219 * DWLP_USER Application specific information.
2221 * RETURNS
2223 * If successful, returns the previous value located at _offset_. Otherwise,
2224 * returns 0.
2226 * NOTES
2228 * Extra memory for a window class is specified by a nonzero cbWndExtra
2229 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2230 * time of class creation.
2232 * Using GWL_WNDPROC to set a new window procedure effectively creates
2233 * a window subclass. Use CallWindowProc() in the new windows procedure
2234 * to pass messages to the superclass's window procedure.
2236 * The user data is reserved for use by the application which created
2237 * the window.
2239 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2240 * instead, call the EnableWindow() function to change the window's
2241 * disabled state.
2243 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2244 * SetParent() instead.
2246 * Win95:
2247 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2248 * it sends WM_STYLECHANGING before changing the settings
2249 * and WM_STYLECHANGED afterwards.
2250 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2252 LONG WINAPI SetWindowLongW(
2253 HWND hwnd, /* [in] window to alter */
2254 INT offset, /* [in] offset, in bytes, of location to alter */
2255 LONG newval /* [in] new value of location */
2257 if (GetVersion()&0x80000000 && offset == GWLP_WNDPROC)
2259 /* CodeWeavers Only Hack... Needed for the Delegates tab
2260 * in Outlook XP running in win98 mode
2262 char class[80];
2263 GetClassNameA(hwnd, class, sizeof(class));
2264 if (strcmp(class,"REListBox20W")==0)
2266 char name[MAX_PATH], *p;
2268 GetModuleFileNameA(GetModuleHandleA(NULL),name,MAX_PATH);
2269 p = strrchr(name, '\\');
2271 if (p)
2272 p++;
2273 else
2274 p = name;
2276 if (!strcasecmp(p,"OUTLOOK.EXE"))
2278 ERR("Outlook in WIN98 calling supposedly unimplemented function, triggering bandaid for class %s\n",debugstr_a(class));
2279 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2280 return 0;
2284 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, TRUE );
2288 /*******************************************************************
2289 * GetWindowTextA (USER32.@)
2291 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2293 WCHAR *buffer;
2295 if (!lpString) return 0;
2297 if (WIN_IsCurrentProcess( hwnd ))
2298 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2300 /* when window belongs to other process, don't send a message */
2301 if (nMaxCount <= 0) return 0;
2302 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2303 get_server_window_text( hwnd, buffer, nMaxCount );
2304 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2305 lpString[nMaxCount-1] = 0;
2306 HeapFree( GetProcessHeap(), 0, buffer );
2307 return strlen(lpString);
2311 /*******************************************************************
2312 * InternalGetWindowText (USER32.@)
2314 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2316 WND *win;
2318 if (nMaxCount <= 0) return 0;
2319 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2320 if (win == WND_DESKTOP) lpString[0] = 0;
2321 else if (win != WND_OTHER_PROCESS)
2323 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2324 else lpString[0] = 0;
2325 WIN_ReleasePtr( win );
2327 else
2329 get_server_window_text( hwnd, lpString, nMaxCount );
2331 return strlenW(lpString);
2335 /*******************************************************************
2336 * GetWindowTextW (USER32.@)
2338 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2340 if (!lpString) return 0;
2342 if (WIN_IsCurrentProcess( hwnd ))
2343 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2345 /* when window belongs to other process, don't send a message */
2346 if (nMaxCount <= 0) return 0;
2347 get_server_window_text( hwnd, lpString, nMaxCount );
2348 return strlenW(lpString);
2352 /*******************************************************************
2353 * SetWindowTextA (USER32.@)
2354 * SetWindowText (USER32.@)
2356 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2358 if (is_broadcast(hwnd))
2360 SetLastError( ERROR_INVALID_PARAMETER );
2361 return FALSE;
2363 if (!WIN_IsCurrentProcess( hwnd ))
2364 WARN( "setting text %s of other process window %p should not use SendMessage\n",
2365 debugstr_a(lpString), hwnd );
2366 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2370 /*******************************************************************
2371 * SetWindowTextW (USER32.@)
2373 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2375 if (is_broadcast(hwnd))
2377 SetLastError( ERROR_INVALID_PARAMETER );
2378 return FALSE;
2380 if (!WIN_IsCurrentProcess( hwnd ))
2381 WARN( "setting text %s of other process window %p should not use SendMessage\n",
2382 debugstr_w(lpString), hwnd );
2383 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2387 /*******************************************************************
2388 * GetWindowTextLengthA (USER32.@)
2390 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2392 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2395 /*******************************************************************
2396 * GetWindowTextLengthW (USER32.@)
2398 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2400 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2404 /*******************************************************************
2405 * IsWindow (USER32.@)
2407 BOOL WINAPI IsWindow( HWND hwnd )
2409 WND *ptr;
2410 BOOL ret;
2412 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2413 if (ptr == WND_DESKTOP) return TRUE;
2415 if (ptr != WND_OTHER_PROCESS)
2417 WIN_ReleasePtr( ptr );
2418 return TRUE;
2421 /* check other processes */
2422 SERVER_START_REQ( get_window_info )
2424 req->handle = hwnd;
2425 ret = !wine_server_call_err( req );
2427 SERVER_END_REQ;
2428 return ret;
2432 /***********************************************************************
2433 * GetWindowThreadProcessId (USER32.@)
2435 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2437 WND *ptr;
2438 DWORD tid = 0;
2440 if (!(ptr = WIN_GetPtr( hwnd )))
2442 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2443 return 0;
2446 if (ptr != WND_OTHER_PROCESS && ptr != WND_DESKTOP)
2448 /* got a valid window */
2449 tid = ptr->tid;
2450 if (process) *process = GetCurrentProcessId();
2451 WIN_ReleasePtr( ptr );
2452 return tid;
2455 /* check other processes */
2456 SERVER_START_REQ( get_window_info )
2458 req->handle = hwnd;
2459 if (!wine_server_call_err( req ))
2461 tid = (DWORD)reply->tid;
2462 if (process) *process = (DWORD)reply->pid;
2465 SERVER_END_REQ;
2466 return tid;
2470 /*****************************************************************
2471 * GetParent (USER32.@)
2473 HWND WINAPI GetParent( HWND hwnd )
2475 WND *wndPtr;
2476 HWND retvalue = 0;
2478 if (!(wndPtr = WIN_GetPtr( hwnd )))
2480 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2481 return 0;
2483 if (wndPtr == WND_DESKTOP) return 0;
2484 if (wndPtr == WND_OTHER_PROCESS)
2486 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2487 if (style & (WS_POPUP | WS_CHILD))
2489 SERVER_START_REQ( get_window_tree )
2491 req->handle = hwnd;
2492 if (!wine_server_call_err( req ))
2494 if (style & WS_POPUP) retvalue = reply->owner;
2495 else if (style & WS_CHILD) retvalue = reply->parent;
2498 SERVER_END_REQ;
2501 else
2503 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2504 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2505 WIN_ReleasePtr( wndPtr );
2507 return retvalue;
2511 /*****************************************************************
2512 * GetAncestor (USER32.@)
2514 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2516 WND *win;
2517 HWND *list, ret = 0;
2519 switch(type)
2521 case GA_PARENT:
2522 if (!(win = WIN_GetPtr( hwnd )))
2524 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2525 return 0;
2527 if (win == WND_DESKTOP) return 0;
2528 if (win != WND_OTHER_PROCESS)
2530 ret = win->parent;
2531 WIN_ReleasePtr( win );
2533 else /* need to query the server */
2535 SERVER_START_REQ( get_window_tree )
2537 req->handle = hwnd;
2538 if (!wine_server_call_err( req )) ret = reply->parent;
2540 SERVER_END_REQ;
2542 break;
2544 case GA_ROOT:
2545 if (!(list = list_window_parents( hwnd ))) return 0;
2547 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2548 else
2550 int count = 2;
2551 while (list[count]) count++;
2552 ret = list[count - 2]; /* get the one before the desktop */
2554 HeapFree( GetProcessHeap(), 0, list );
2555 break;
2557 case GA_ROOTOWNER:
2558 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2559 for (;;)
2561 HWND parent = GetParent( ret );
2562 if (!parent) break;
2563 ret = parent;
2565 break;
2567 return ret;
2571 /*****************************************************************
2572 * SetParent (USER32.@)
2574 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2576 HWND full_handle;
2577 HWND old_parent = 0;
2578 BOOL was_visible;
2579 WND *wndPtr;
2580 BOOL ret;
2582 if (is_broadcast(hwnd) || is_broadcast(parent))
2584 SetLastError(ERROR_INVALID_PARAMETER);
2585 return 0;
2588 if (!parent) parent = GetDesktopWindow();
2589 else parent = WIN_GetFullHandle( parent );
2591 if (!IsWindow( parent ))
2593 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2594 return 0;
2597 /* Some applications try to set a child as a parent */
2598 if (IsChild(hwnd, parent))
2600 SetLastError( ERROR_INVALID_PARAMETER );
2601 return 0;
2604 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2605 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2607 /* Windows hides the window first, then shows it again
2608 * including the WM_SHOWWINDOW messages and all */
2609 was_visible = ShowWindow( hwnd, SW_HIDE );
2611 wndPtr = WIN_GetPtr( hwnd );
2612 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return 0;
2614 SERVER_START_REQ( set_parent )
2616 req->handle = hwnd;
2617 req->parent = parent;
2618 if ((ret = !wine_server_call( req )))
2620 old_parent = reply->old_parent;
2621 wndPtr->parent = parent = reply->full_parent;
2625 SERVER_END_REQ;
2626 WIN_ReleasePtr( wndPtr );
2627 if (!ret) return 0;
2629 USER_Driver->pSetParent( full_handle, parent, old_parent );
2631 /* SetParent additionally needs to make hwnd the topmost window
2632 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2633 WM_WINDOWPOSCHANGED notification messages.
2635 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2636 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2637 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2638 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2640 return old_parent;
2644 /*******************************************************************
2645 * IsChild (USER32.@)
2647 BOOL WINAPI IsChild( HWND parent, HWND child )
2649 HWND *list = list_window_parents( child );
2650 int i;
2651 BOOL ret;
2653 if (!list) return FALSE;
2654 parent = WIN_GetFullHandle( parent );
2655 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2656 ret = (list[i] != 0);
2657 HeapFree( GetProcessHeap(), 0, list );
2658 return ret;
2662 /***********************************************************************
2663 * IsWindowVisible (USER32.@)
2665 BOOL WINAPI IsWindowVisible( HWND hwnd )
2667 HWND *list;
2668 BOOL retval = TRUE;
2669 int i;
2671 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2672 if (!(list = list_window_parents( hwnd ))) return TRUE;
2673 if (list[0] && list[1]) /* desktop window is considered always visible so we don't check it */
2675 for (i = 0; list[i+1]; i++)
2676 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2677 retval = !list[i+1];
2679 HeapFree( GetProcessHeap(), 0, list );
2680 return retval;
2684 /***********************************************************************
2685 * WIN_IsWindowDrawable
2687 * hwnd is drawable when it is visible, all parents are not
2688 * minimized, and it is itself not minimized unless we are
2689 * trying to draw its default class icon.
2691 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2693 HWND *list;
2694 BOOL retval = TRUE;
2695 int i;
2696 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2698 if (!(style & WS_VISIBLE)) return FALSE;
2699 if ((style & WS_MINIMIZE) && icon && GetClassLongPtrW( hwnd, GCLP_HICON )) return FALSE;
2701 if (!(list = list_window_parents( hwnd ))) return TRUE;
2702 if (list[0] && list[1]) /* desktop window is considered always visible so we don't check it */
2704 for (i = 0; list[i+1]; i++)
2705 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2706 break;
2707 retval = !list[i+1];
2709 HeapFree( GetProcessHeap(), 0, list );
2710 return retval;
2714 /*******************************************************************
2715 * GetTopWindow (USER32.@)
2717 HWND WINAPI GetTopWindow( HWND hwnd )
2719 if (!hwnd) hwnd = GetDesktopWindow();
2720 return GetWindow( hwnd, GW_CHILD );
2724 /*******************************************************************
2725 * GetWindow (USER32.@)
2727 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2729 HWND retval = 0;
2731 if (rel == GW_OWNER) /* this one may be available locally */
2733 WND *wndPtr = WIN_GetPtr( hwnd );
2734 if (!wndPtr)
2736 SetLastError( ERROR_INVALID_HANDLE );
2737 return 0;
2739 if (wndPtr == WND_DESKTOP) return 0;
2740 if (wndPtr != WND_OTHER_PROCESS)
2742 retval = wndPtr->owner;
2743 WIN_ReleasePtr( wndPtr );
2744 return retval;
2746 /* else fall through to server call */
2749 SERVER_START_REQ( get_window_tree )
2751 req->handle = hwnd;
2752 if (!wine_server_call_err( req ))
2754 switch(rel)
2756 case GW_HWNDFIRST:
2757 retval = reply->first_sibling;
2758 break;
2759 case GW_HWNDLAST:
2760 retval = reply->last_sibling;
2761 break;
2762 case GW_HWNDNEXT:
2763 retval = reply->next_sibling;
2764 break;
2765 case GW_HWNDPREV:
2766 retval = reply->prev_sibling;
2767 break;
2768 case GW_OWNER:
2769 retval = reply->owner;
2770 break;
2771 case GW_CHILD:
2772 retval = reply->first_child;
2773 break;
2777 SERVER_END_REQ;
2778 return retval;
2782 /*******************************************************************
2783 * ShowOwnedPopups (USER32.@)
2785 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2787 int count = 0;
2788 WND *pWnd;
2789 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2791 if (!win_array) return TRUE;
2793 while (win_array[count]) count++;
2794 while (--count >= 0)
2796 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2797 if (!(pWnd = WIN_GetPtr( win_array[count] ))) continue;
2798 if (pWnd == WND_OTHER_PROCESS) continue;
2799 if (fShow)
2801 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2803 WIN_ReleasePtr( pWnd );
2804 /* In Windows, ShowOwnedPopups(TRUE) generates
2805 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2806 * regardless of the state of the owner
2808 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_SHOWNORMAL, SW_PARENTOPENING);
2809 continue;
2812 else
2814 if (pWnd->dwStyle & WS_VISIBLE)
2816 WIN_ReleasePtr( pWnd );
2817 /* In Windows, ShowOwnedPopups(FALSE) generates
2818 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2819 * regardless of the state of the owner
2821 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2822 continue;
2825 WIN_ReleasePtr( pWnd );
2827 HeapFree( GetProcessHeap(), 0, win_array );
2828 return TRUE;
2832 /*******************************************************************
2833 * GetLastActivePopup (USER32.@)
2835 HWND WINAPI GetLastActivePopup( HWND hwnd )
2837 HWND retval = hwnd;
2839 SERVER_START_REQ( get_window_info )
2841 req->handle = hwnd;
2842 if (!wine_server_call_err( req )) retval = reply->last_active;
2844 SERVER_END_REQ;
2845 return retval;
2849 /*******************************************************************
2850 * WIN_ListChildren
2852 * Build an array of the children of a given window. The array must be
2853 * freed with HeapFree. Returns NULL when no windows are found.
2855 HWND *WIN_ListChildren( HWND hwnd )
2857 return list_window_children( hwnd, 0, 0 );
2861 /*******************************************************************
2862 * EnumWindows (USER32.@)
2864 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2866 HWND *list;
2867 BOOL ret = TRUE;
2868 int i;
2870 USER_CheckNotLock();
2872 /* We have to build a list of all windows first, to avoid */
2873 /* unpleasant side-effects, for instance if the callback */
2874 /* function changes the Z-order of the windows. */
2876 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2878 /* Now call the callback function for every window */
2880 for (i = 0; list[i]; i++)
2882 /* Make sure that the window still exists */
2883 if (!IsWindow( list[i] )) continue;
2884 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2886 HeapFree( GetProcessHeap(), 0, list );
2887 return ret;
2891 /**********************************************************************
2892 * EnumThreadWindows (USER32.@)
2894 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2896 HWND *list;
2897 int i;
2899 USER_CheckNotLock();
2901 if (!(list = list_window_children( GetDesktopWindow(), 0, id ))) return TRUE;
2903 /* Now call the callback function for every window */
2905 for (i = 0; list[i]; i++)
2906 if (!func( list[i], lParam )) break;
2907 HeapFree( GetProcessHeap(), 0, list );
2908 return TRUE;
2912 /**********************************************************************
2913 * WIN_EnumChildWindows
2915 * Helper function for EnumChildWindows().
2917 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2919 HWND *childList;
2920 BOOL ret = FALSE;
2922 for ( ; *list; list++)
2924 /* Make sure that the window still exists */
2925 if (!IsWindow( *list )) continue;
2926 /* Build children list first */
2927 childList = WIN_ListChildren( *list );
2929 ret = func( *list, lParam );
2931 if (childList)
2933 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2934 HeapFree( GetProcessHeap(), 0, childList );
2936 if (!ret) return FALSE;
2938 return TRUE;
2942 /**********************************************************************
2943 * EnumChildWindows (USER32.@)
2945 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2947 HWND *list;
2948 BOOL ret;
2950 USER_CheckNotLock();
2952 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2953 ret = WIN_EnumChildWindows( list, func, lParam );
2954 HeapFree( GetProcessHeap(), 0, list );
2955 return ret;
2959 /*******************************************************************
2960 * AnyPopup (USER.52)
2962 BOOL16 WINAPI AnyPopup16(void)
2964 return AnyPopup();
2968 /*******************************************************************
2969 * AnyPopup (USER32.@)
2971 BOOL WINAPI AnyPopup(void)
2973 int i;
2974 BOOL retvalue;
2975 HWND *list = WIN_ListChildren( GetDesktopWindow() );
2977 if (!list) return FALSE;
2978 for (i = 0; list[i]; i++)
2980 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
2982 retvalue = (list[i] != 0);
2983 HeapFree( GetProcessHeap(), 0, list );
2984 return retvalue;
2988 /*******************************************************************
2989 * FlashWindow (USER32.@)
2991 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2993 WND *wndPtr;
2995 TRACE("%p\n", hWnd);
2997 if (IsIconic( hWnd ))
2999 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3001 wndPtr = WIN_GetPtr(hWnd);
3002 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
3003 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3005 wndPtr->flags |= WIN_NCACTIVATED;
3007 else
3009 wndPtr->flags &= ~WIN_NCACTIVATED;
3011 WIN_ReleasePtr( wndPtr );
3012 return TRUE;
3014 else
3016 WPARAM wparam;
3018 wndPtr = WIN_GetPtr(hWnd);
3019 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
3020 hWnd = wndPtr->hwndSelf; /* make it a full handle */
3022 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3023 else wparam = (hWnd == GetForegroundWindow());
3025 WIN_ReleasePtr( wndPtr );
3026 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3027 return wparam;
3031 /*******************************************************************
3032 * FlashWindowEx (USER32.@)
3034 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
3036 FIXME("%p\n", pfwi);
3037 return TRUE;
3040 /*******************************************************************
3041 * GetWindowContextHelpId (USER32.@)
3043 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3045 DWORD retval;
3046 WND *wnd = WIN_GetPtr( hwnd );
3047 if (!wnd || wnd == WND_DESKTOP) return 0;
3048 if (wnd == WND_OTHER_PROCESS)
3050 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3051 return 0;
3053 retval = wnd->helpContext;
3054 WIN_ReleasePtr( wnd );
3055 return retval;
3059 /*******************************************************************
3060 * SetWindowContextHelpId (USER32.@)
3062 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3064 WND *wnd = WIN_GetPtr( hwnd );
3065 if (!wnd || wnd == WND_DESKTOP) return FALSE;
3066 if (wnd == WND_OTHER_PROCESS)
3068 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3069 return 0;
3071 wnd->helpContext = id;
3072 WIN_ReleasePtr( wnd );
3073 return TRUE;
3077 /*******************************************************************
3078 * DragDetect (USER32.@)
3080 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3082 MSG msg;
3083 RECT rect;
3084 WORD wDragWidth = GetSystemMetrics(SM_CXDRAG);
3085 WORD wDragHeight= GetSystemMetrics(SM_CYDRAG);
3087 rect.left = pt.x - wDragWidth;
3088 rect.right = pt.x + wDragWidth;
3090 rect.top = pt.y - wDragHeight;
3091 rect.bottom = pt.y + wDragHeight;
3093 SetCapture(hWnd);
3095 while(1)
3097 while (PeekMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ))
3099 if( msg.message == WM_LBUTTONUP )
3101 ReleaseCapture();
3102 return 0;
3104 if( msg.message == WM_MOUSEMOVE )
3106 POINT tmp;
3107 tmp.x = (short)LOWORD(msg.lParam);
3108 tmp.y = (short)HIWORD(msg.lParam);
3109 if( !PtInRect( &rect, tmp ))
3111 ReleaseCapture();
3112 return 1;
3116 WaitMessage();
3118 return 0;
3121 /******************************************************************************
3122 * GetWindowModuleFileNameA (USER32.@)
3124 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3126 FIXME("GetWindowModuleFileNameA(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3127 hwnd, lpszFileName, cchFileNameMax);
3128 return 0;
3131 /******************************************************************************
3132 * GetWindowModuleFileNameW (USER32.@)
3134 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR lpszFileName, UINT cchFileNameMax)
3136 FIXME("GetWindowModuleFileNameW(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3137 hwnd, lpszFileName, cchFileNameMax);
3138 return 0;
3141 /******************************************************************************
3142 * GetWindowInfo (USER32.@)
3144 * Note: tests show that Windows doesn't check cbSize of the structure.
3146 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3148 if (!pwi) return FALSE;
3149 if (!IsWindow(hwnd)) return FALSE;
3151 GetWindowRect(hwnd, &pwi->rcWindow);
3152 GetClientRect(hwnd, &pwi->rcClient);
3153 /* translate to screen coordinates */
3154 MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3156 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3157 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3158 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3160 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3161 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3163 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3164 pwi->wCreatorVersion = 0x0400;
3166 return TRUE;
3169 /******************************************************************************
3170 * SwitchDesktop (USER32.@)
3172 * NOTES: Sets the current input or interactive desktop.
3174 BOOL WINAPI SwitchDesktop( HDESK hDesktop)
3176 FIXME("SwitchDesktop(hwnd %p) stub!\n", hDesktop);
3177 return TRUE;
3180 /*****************************************************************************
3181 * SetLayeredWindowAttributes (USER32.@)
3183 BOOL WINAPI SetLayeredWindowAttributes( HWND hWnd, COLORREF rgbKey,
3184 BYTE bAlpha, DWORD dwFlags )
3186 FIXME("(%p,0x%.8x,%d,%d): stub!\n", hWnd, rgbKey, bAlpha, dwFlags);
3187 return TRUE;
3190 /*****************************************************************************
3191 * UpdateLayeredWindow (USER32.@)
3193 BOOL WINAPI UpdateLayeredWindow( HWND hwnd, HDC hdcDst, POINT *pptDst, SIZE *psize,
3194 HDC hdcSrc, POINT *pptSrc, COLORREF crKey, BLENDFUNCTION *pblend,
3195 DWORD dwFlags)
3197 static int once;
3198 if (!once)
3200 once = 1;
3201 FIXME("(%p,%p,%p,%p,%p,%p,0x%08x,%p,%d): stub!\n",
3202 hwnd, hdcDst, pptDst, psize, hdcSrc, pptSrc, crKey, pblend, dwFlags);
3204 return 0;
3207 /* 64bit versions */
3209 #ifdef GetWindowLongPtrW
3210 #undef GetWindowLongPtrW
3211 #endif
3213 #ifdef GetWindowLongPtrA
3214 #undef GetWindowLongPtrA
3215 #endif
3217 #ifdef SetWindowLongPtrW
3218 #undef SetWindowLongPtrW
3219 #endif
3221 #ifdef SetWindowLongPtrA
3222 #undef SetWindowLongPtrA
3223 #endif
3225 /*****************************************************************************
3226 * GetWindowLongPtrW (USER32.@)
3228 LONG_PTR WINAPI GetWindowLongPtrW( HWND hwnd, INT offset )
3230 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), TRUE );
3233 /*****************************************************************************
3234 * GetWindowLongPtrA (USER32.@)
3236 LONG_PTR WINAPI GetWindowLongPtrA( HWND hwnd, INT offset )
3238 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), FALSE );
3241 /*****************************************************************************
3242 * SetWindowLongPtrW (USER32.@)
3244 LONG_PTR WINAPI SetWindowLongPtrW( HWND hwnd, INT offset, LONG_PTR newval )
3246 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, TRUE );
3249 /*****************************************************************************
3250 * SetWindowLongPtrA (USER32.@)
3252 LONG_PTR WINAPI SetWindowLongPtrA( HWND hwnd, INT offset, LONG_PTR newval )
3254 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, FALSE );