server: Return the data for winevent hooks in the varargs part of the get_message...
[wine/gsoc_dplay.git] / dlls / user / win.c
blob61188487b7c715ab175540a12800caaae6f5e380
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)) menu = (HMENU)wndPtr->wIDmenu;
630 sys_menu = wndPtr->hSysMenu;
631 WIN_ReleasePtr( wndPtr );
633 if (menu) DestroyMenu( menu );
634 if (sys_menu) DestroyMenu( sys_menu );
636 USER_Driver->pDestroyWindow( hwnd );
638 free_window_handle( hwnd );
639 return 0;
642 /***********************************************************************
643 * WIN_DestroyThreadWindows
645 * Destroy all children of 'wnd' owned by the current thread.
646 * Return TRUE if something was done.
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.
670 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
672 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
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->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
687 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
689 if (cs->style & (WS_CHILD | WS_POPUP))
691 if (cs->dwExStyle & WS_EX_MDICHILD)
693 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
695 cs->x = pos[0].x;
696 cs->y = pos[0].y;
698 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16 || !cs->cx)
699 cs->cx = pos[1].x;
700 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16 || !cs->cy)
701 cs->cy = pos[1].y;
703 else
705 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
706 cs->x = cs->y = 0;
707 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
708 cs->cx = cs->cy = 0;
711 else /* overlapped window */
713 STARTUPINFOW info;
715 GetStartupInfoW( &info );
717 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
719 /* Never believe Microsoft's documentation... CreateWindowEx doc says
720 * that if an overlapped window is created with WS_VISIBLE style bit
721 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
722 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
723 * reveals that
725 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
726 * 2) it does not ignore the y parameter as the docs claim; instead, it
727 * uses it as second parameter to ShowWindow() unless y is either
728 * CW_USEDEFAULT or CW_USEDEFAULT16.
730 * The fact that we didn't do 2) caused bogus windows pop up when wine
731 * was running apps that were using this obscure feature. Example -
732 * calc.exe that comes with Win98 (only Win98, it's different from
733 * the one that comes with Win95 and NT)
735 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
736 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
737 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
740 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
742 if (info.dwFlags & STARTF_USESIZE)
744 cs->cx = info.dwXSize;
745 cs->cy = info.dwYSize;
747 else /* if no other hint from the app, pick 3/4 of the screen real estate */
749 RECT r;
750 SystemParametersInfoW( SPI_GETWORKAREA, 0, &r, 0);
751 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
752 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
755 /* Handle case where only the cy values is set to default */
756 else if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16)
758 RECT r;
759 SystemParametersInfoW( SPI_GETWORKAREA, 0, &r, 0);
760 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
764 else
766 /* neither x nor cx are default. Check the y values .
767 * In the trace we see Outlook and Outlook Express using
768 * cy set to CW_USEDEFAULT when opening the address book.
770 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16) {
771 RECT r;
772 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
773 SystemParametersInfoW( SPI_GETWORKAREA, 0, &r, 0);
774 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
779 /***********************************************************************
780 * dump_window_styles
782 static void dump_window_styles( DWORD style, DWORD exstyle )
784 TRACE( "style:" );
785 if(style & WS_POPUP) TRACE(" WS_POPUP");
786 if(style & WS_CHILD) TRACE(" WS_CHILD");
787 if(style & WS_MINIMIZE) TRACE(" WS_MINIMIZE");
788 if(style & WS_VISIBLE) TRACE(" WS_VISIBLE");
789 if(style & WS_DISABLED) TRACE(" WS_DISABLED");
790 if(style & WS_CLIPSIBLINGS) TRACE(" WS_CLIPSIBLINGS");
791 if(style & WS_CLIPCHILDREN) TRACE(" WS_CLIPCHILDREN");
792 if(style & WS_MAXIMIZE) TRACE(" WS_MAXIMIZE");
793 if((style & WS_CAPTION) == WS_CAPTION) TRACE(" WS_CAPTION");
794 else
796 if(style & WS_BORDER) TRACE(" WS_BORDER");
797 if(style & WS_DLGFRAME) TRACE(" WS_DLGFRAME");
799 if(style & WS_VSCROLL) TRACE(" WS_VSCROLL");
800 if(style & WS_HSCROLL) TRACE(" WS_HSCROLL");
801 if(style & WS_SYSMENU) TRACE(" WS_SYSMENU");
802 if(style & WS_THICKFRAME) TRACE(" WS_THICKFRAME");
803 if (style & WS_CHILD)
805 if(style & WS_GROUP) TRACE(" WS_GROUP");
806 if(style & WS_TABSTOP) TRACE(" WS_TABSTOP");
808 else
810 if(style & WS_MINIMIZEBOX) TRACE(" WS_MINIMIZEBOX");
811 if(style & WS_MAXIMIZEBOX) TRACE(" WS_MAXIMIZEBOX");
814 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
815 #define DUMPED_STYLES \
816 (WS_POPUP | \
817 WS_CHILD | \
818 WS_MINIMIZE | \
819 WS_VISIBLE | \
820 WS_DISABLED | \
821 WS_CLIPSIBLINGS | \
822 WS_CLIPCHILDREN | \
823 WS_MAXIMIZE | \
824 WS_BORDER | \
825 WS_DLGFRAME | \
826 WS_VSCROLL | \
827 WS_HSCROLL | \
828 WS_SYSMENU | \
829 WS_THICKFRAME | \
830 WS_GROUP | \
831 WS_TABSTOP | \
832 WS_MINIMIZEBOX | \
833 WS_MAXIMIZEBOX)
835 if(style & ~DUMPED_STYLES) TRACE(" %08lx", style & ~DUMPED_STYLES);
836 TRACE("\n");
837 #undef DUMPED_STYLES
839 TRACE( "exstyle:" );
840 if(exstyle & WS_EX_DLGMODALFRAME) TRACE(" WS_EX_DLGMODALFRAME");
841 if(exstyle & WS_EX_DRAGDETECT) TRACE(" WS_EX_DRAGDETECT");
842 if(exstyle & WS_EX_NOPARENTNOTIFY) TRACE(" WS_EX_NOPARENTNOTIFY");
843 if(exstyle & WS_EX_TOPMOST) TRACE(" WS_EX_TOPMOST");
844 if(exstyle & WS_EX_ACCEPTFILES) TRACE(" WS_EX_ACCEPTFILES");
845 if(exstyle & WS_EX_TRANSPARENT) TRACE(" WS_EX_TRANSPARENT");
846 if(exstyle & WS_EX_MDICHILD) TRACE(" WS_EX_MDICHILD");
847 if(exstyle & WS_EX_TOOLWINDOW) TRACE(" WS_EX_TOOLWINDOW");
848 if(exstyle & WS_EX_WINDOWEDGE) TRACE(" WS_EX_WINDOWEDGE");
849 if(exstyle & WS_EX_CLIENTEDGE) TRACE(" WS_EX_CLIENTEDGE");
850 if(exstyle & WS_EX_CONTEXTHELP) TRACE(" WS_EX_CONTEXTHELP");
851 if(exstyle & WS_EX_RIGHT) TRACE(" WS_EX_RIGHT");
852 if(exstyle & WS_EX_RTLREADING) TRACE(" WS_EX_RTLREADING");
853 if(exstyle & WS_EX_LEFTSCROLLBAR) TRACE(" WS_EX_LEFTSCROLLBAR");
854 if(exstyle & WS_EX_CONTROLPARENT) TRACE(" WS_EX_CONTROLPARENT");
855 if(exstyle & WS_EX_STATICEDGE) TRACE(" WS_EX_STATICEDGE");
856 if(exstyle & WS_EX_APPWINDOW) TRACE(" WS_EX_APPWINDOW");
857 if(exstyle & WS_EX_LAYERED) TRACE(" WS_EX_LAYERED");
859 #define DUMPED_EX_STYLES \
860 (WS_EX_DLGMODALFRAME | \
861 WS_EX_DRAGDETECT | \
862 WS_EX_NOPARENTNOTIFY | \
863 WS_EX_TOPMOST | \
864 WS_EX_ACCEPTFILES | \
865 WS_EX_TRANSPARENT | \
866 WS_EX_MDICHILD | \
867 WS_EX_TOOLWINDOW | \
868 WS_EX_WINDOWEDGE | \
869 WS_EX_CLIENTEDGE | \
870 WS_EX_CONTEXTHELP | \
871 WS_EX_RIGHT | \
872 WS_EX_RTLREADING | \
873 WS_EX_LEFTSCROLLBAR | \
874 WS_EX_CONTROLPARENT | \
875 WS_EX_STATICEDGE | \
876 WS_EX_APPWINDOW | \
877 WS_EX_LAYERED)
879 if(exstyle & ~DUMPED_EX_STYLES) TRACE(" %08lx", exstyle & ~DUMPED_EX_STYLES);
880 TRACE("\n");
881 #undef DUMPED_EX_STYLES
885 /***********************************************************************
886 * WIN_CreateWindowEx
888 * Implementation of CreateWindowEx().
890 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom, UINT flags )
892 INT sw = SW_SHOW;
893 WND *wndPtr;
894 HWND hwnd, parent, owner, top_child = 0;
895 BOOL unicode = (flags & WIN_ISUNICODE) != 0;
896 MDICREATESTRUCTA mdi_cs;
898 TRACE("%s %s ex=%08x style=%08x %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
899 unicode ? debugstr_w((LPCWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
900 unicode ? debugstr_w((LPCWSTR)cs->lpszClass) : debugstr_a(cs->lpszClass),
901 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
902 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
903 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
905 /* Fix the styles for MDI children */
906 if (cs->dwExStyle & WS_EX_MDICHILD)
908 UINT flags = 0;
910 wndPtr = WIN_GetPtr(cs->hwndParent);
911 if (wndPtr && wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
913 flags = wndPtr->flags;
914 WIN_ReleasePtr(wndPtr);
917 if (!(flags & WIN_ISMDICLIENT))
919 WARN("WS_EX_MDICHILD, but parent %p is not MDIClient\n", cs->hwndParent);
920 return 0;
923 /* cs->lpCreateParams of WM_[NC]CREATE is different for MDI children.
924 * MDICREATESTRUCT members have the originally passed values.
926 * Note: we rely on the fact that MDICREATESTRUCTA and MDICREATESTRUCTW
927 * have the same layout.
929 mdi_cs.szClass = cs->lpszClass;
930 mdi_cs.szTitle = cs->lpszName;
931 mdi_cs.hOwner = cs->hInstance;
932 mdi_cs.x = cs->x;
933 mdi_cs.y = cs->y;
934 mdi_cs.cx = cs->cx;
935 mdi_cs.cy = cs->cy;
936 mdi_cs.style = cs->style;
937 mdi_cs.lParam = (LPARAM)cs->lpCreateParams;
939 cs->lpCreateParams = (LPVOID)&mdi_cs;
941 if (GetWindowLongW(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
943 if (cs->style & WS_POPUP)
945 TRACE("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n");
946 return 0;
948 cs->style |= WS_CHILD | WS_CLIPSIBLINGS;
950 else
952 cs->style &= ~WS_POPUP;
953 cs->style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
954 WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
957 top_child = GetWindow(cs->hwndParent, GW_CHILD);
959 if (top_child)
961 /* Restore current maximized child */
962 if((cs->style & WS_VISIBLE) && IsZoomed(top_child))
964 TRACE("Restoring current maximized child %p\n", top_child);
965 SendMessageW( top_child, WM_SETREDRAW, FALSE, 0 );
966 ShowWindow(top_child, SW_RESTORE);
967 SendMessageW( top_child, WM_SETREDRAW, TRUE, 0 );
972 /* Find the parent window */
974 parent = cs->hwndParent;
975 owner = 0;
977 if (cs->hwndParent == HWND_MESSAGE)
979 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
980 * message window (style: WS_POPUP|WS_DISABLED)
982 FIXME("Parent is HWND_MESSAGE\n");
983 parent = GetDesktopWindow();
985 else if (cs->hwndParent)
987 if ((cs->style & (WS_CHILD|WS_POPUP)) != WS_CHILD)
989 parent = GetDesktopWindow();
990 owner = cs->hwndParent;
993 else
995 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
997 WARN("No parent for child window\n" );
998 SetLastError(ERROR_TLW_WITH_WSCHILD);
999 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1001 if (classAtom != LOWORD(DESKTOP_CLASS_ATOM)) /* are we creating the desktop itself? */
1002 parent = GetDesktopWindow();
1005 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
1007 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
1008 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
1009 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
1010 cs->dwExStyle |= WS_EX_WINDOWEDGE;
1011 else
1012 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
1014 /* Create the window structure */
1016 if (!(wndPtr = create_window_handle( parent, owner, classAtom, cs->hInstance, unicode )))
1017 return 0;
1018 hwnd = wndPtr->hwndSelf;
1020 /* Fill the window structure */
1022 wndPtr->tid = GetCurrentThreadId();
1023 wndPtr->hInstance = cs->hInstance;
1024 wndPtr->text = NULL;
1025 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1026 wndPtr->dwExStyle = cs->dwExStyle;
1027 wndPtr->wIDmenu = 0;
1028 wndPtr->helpContext = 0;
1029 wndPtr->pVScroll = NULL;
1030 wndPtr->pHScroll = NULL;
1031 wndPtr->userdata = 0;
1032 wndPtr->hIcon = 0;
1033 wndPtr->hIconSmall = 0;
1034 wndPtr->hSysMenu = 0;
1035 wndPtr->flags |= (flags & WIN_ISWIN32);
1037 if (wndPtr->dwStyle & WS_SYSMENU) SetSystemMenu( hwnd, 0 );
1040 * Correct the window styles.
1042 * It affects only the style loaded into the WIN structure.
1045 if (!(wndPtr->dwStyle & WS_CHILD))
1047 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1048 if (!(wndPtr->dwStyle & WS_POPUP))
1049 wndPtr->dwStyle |= WS_CAPTION;
1053 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1054 * why does the user get to set it?
1057 if ((wndPtr->dwExStyle & WS_EX_DLGMODALFRAME) ||
1058 (wndPtr->dwStyle & (WS_DLGFRAME | WS_THICKFRAME)))
1059 wndPtr->dwExStyle |= WS_EX_WINDOWEDGE;
1060 else
1061 wndPtr->dwExStyle &= ~WS_EX_WINDOWEDGE;
1063 if (!(wndPtr->dwStyle & (WS_CHILD | WS_POPUP)))
1064 wndPtr->flags |= WIN_NEED_SIZE;
1066 SERVER_START_REQ( set_window_info )
1068 req->handle = hwnd;
1069 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE | SET_WIN_UNICODE;
1070 req->style = wndPtr->dwStyle;
1071 req->ex_style = wndPtr->dwExStyle;
1072 req->instance = (void *)wndPtr->hInstance;
1073 req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
1074 req->extra_offset = -1;
1075 wine_server_call( req );
1077 SERVER_END_REQ;
1079 /* Set the window menu */
1081 if (!(wndPtr->dwStyle & WS_CHILD))
1083 if (cs->hMenu)
1085 if (!MENU_SetMenu(hwnd, cs->hMenu))
1087 WIN_ReleasePtr( wndPtr );
1088 free_window_handle( hwnd );
1089 return 0;
1092 else
1094 LPCSTR menuName = (LPCSTR)GetClassLongPtrA( hwnd, GCLP_MENUNAME );
1095 if (menuName)
1097 if (!cs->hInstance || HIWORD(cs->hInstance))
1098 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1099 else
1100 cs->hMenu = HMENU_32(LoadMenu16(HINSTANCE_16(cs->hInstance),menuName));
1102 if (cs->hMenu) MENU_SetMenu( hwnd, cs->hMenu );
1106 else SetWindowLongPtrW( hwnd, GWLP_ID, (ULONG_PTR)cs->hMenu );
1107 WIN_ReleasePtr( wndPtr );
1109 if (!USER_Driver->pCreateWindow( hwnd, cs, unicode))
1111 WIN_DestroyWindow( hwnd );
1112 return 0;
1115 /* Notify the parent window only */
1117 send_parent_notify( hwnd, WM_CREATE );
1118 if (!IsWindow( hwnd )) return 0;
1120 if (cs->style & WS_VISIBLE)
1122 if (cs->style & WS_MAXIMIZE)
1123 sw = SW_SHOW;
1124 else if (cs->style & WS_MINIMIZE)
1125 sw = SW_SHOWMINIMIZED;
1127 ShowWindow( hwnd, sw );
1128 if (cs->dwExStyle & WS_EX_MDICHILD)
1130 SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
1131 /* ShowWindow won't activate child windows */
1132 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE );
1136 /* Call WH_SHELL hook */
1138 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1139 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1141 TRACE("created window %p\n", hwnd);
1142 return hwnd;
1146 /***********************************************************************
1147 * CreateWindow (USER.41)
1149 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1150 DWORD style, INT16 x, INT16 y, INT16 width,
1151 INT16 height, HWND16 parent, HMENU16 menu,
1152 HINSTANCE16 instance, LPVOID data )
1154 return CreateWindowEx16( 0, className, windowName, style,
1155 x, y, width, height, parent, menu, instance, data );
1159 /***********************************************************************
1160 * CreateWindowEx (USER.452)
1162 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1163 LPCSTR windowName, DWORD style, INT16 x,
1164 INT16 y, INT16 width, INT16 height,
1165 HWND16 parent, HMENU16 menu,
1166 HINSTANCE16 instance, LPVOID data )
1168 ATOM classAtom;
1169 CREATESTRUCTA cs;
1170 char buffer[256];
1172 /* Find the class atom */
1174 if (HIWORD(className))
1176 if (!(classAtom = GlobalFindAtomA( className )))
1178 ERR( "bad class name %s\n", debugstr_a(className) );
1179 return 0;
1182 else
1184 classAtom = LOWORD(className);
1185 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1187 ERR( "bad atom %x\n", classAtom);
1188 return 0;
1190 className = buffer;
1193 /* Fix the coordinates */
1195 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1196 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1197 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1198 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1200 /* Create the window */
1202 cs.lpCreateParams = data;
1203 cs.hInstance = HINSTANCE_32(instance);
1204 cs.hMenu = HMENU_32(menu);
1205 cs.hwndParent = WIN_Handle32( parent );
1206 cs.style = style;
1207 cs.lpszName = windowName;
1208 cs.lpszClass = className;
1209 cs.dwExStyle = exStyle;
1211 return HWND_16( WIN_CreateWindowEx( &cs, classAtom, 0 ));
1215 /***********************************************************************
1216 * CreateWindowExA (USER32.@)
1218 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1219 LPCSTR windowName, DWORD style, INT x,
1220 INT y, INT width, INT height,
1221 HWND parent, HMENU menu,
1222 HINSTANCE instance, LPVOID data )
1224 ATOM classAtom;
1225 CREATESTRUCTA cs;
1226 char buffer[256];
1228 /* Find the class atom */
1230 if (HIWORD(className))
1232 if (!(classAtom = GlobalFindAtomA( className )))
1234 ERR( "bad class name %s\n", debugstr_a(className) );
1235 return 0;
1238 else
1240 classAtom = LOWORD(className);
1241 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1243 ERR( "bad atom %x\n", classAtom);
1244 return 0;
1246 className = buffer;
1249 /* Create the window */
1251 cs.lpCreateParams = data;
1252 cs.hInstance = instance;
1253 cs.hMenu = menu;
1254 cs.hwndParent = parent;
1255 cs.x = x;
1256 cs.y = y;
1257 cs.cx = width;
1258 cs.cy = height;
1259 cs.style = style;
1260 cs.lpszName = windowName;
1261 cs.lpszClass = className;
1262 cs.dwExStyle = exStyle;
1264 return WIN_CreateWindowEx( &cs, classAtom, WIN_ISWIN32 );
1268 /***********************************************************************
1269 * CreateWindowExW (USER32.@)
1271 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1272 LPCWSTR windowName, DWORD style, INT x,
1273 INT y, INT width, INT height,
1274 HWND parent, HMENU menu,
1275 HINSTANCE instance, LPVOID data )
1277 ATOM classAtom;
1278 CREATESTRUCTW cs;
1279 WCHAR buffer[256];
1281 /* Find the class atom */
1283 if (HIWORD(className))
1285 if (!(classAtom = GlobalFindAtomW( className )))
1287 ERR( "bad class name %s\n", debugstr_w(className) );
1288 return 0;
1291 else
1293 classAtom = LOWORD(className);
1294 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1296 ERR( "bad atom %x\n", classAtom);
1297 return 0;
1299 className = buffer;
1302 /* Create the window */
1304 cs.lpCreateParams = data;
1305 cs.hInstance = instance;
1306 cs.hMenu = menu;
1307 cs.hwndParent = parent;
1308 cs.x = x;
1309 cs.y = y;
1310 cs.cx = width;
1311 cs.cy = height;
1312 cs.style = style;
1313 cs.lpszName = windowName;
1314 cs.lpszClass = className;
1315 cs.dwExStyle = exStyle;
1317 /* Note: we rely on the fact that CREATESTRUCTA and */
1318 /* CREATESTRUCTW have the same layout. */
1319 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_ISWIN32 | WIN_ISUNICODE );
1323 /***********************************************************************
1324 * WIN_SendDestroyMsg
1326 static void WIN_SendDestroyMsg( HWND hwnd )
1328 GUITHREADINFO info;
1330 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1332 if (hwnd == info.hwndCaret) DestroyCaret();
1333 if (hwnd == info.hwndActive) WINPOS_ActivateOtherWindow( hwnd );
1337 * Send the WM_DESTROY to the window.
1339 SendMessageW( hwnd, WM_DESTROY, 0, 0);
1342 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1343 * make sure that the window still exists when we come back.
1345 if (IsWindow(hwnd))
1347 HWND* pWndArray;
1348 int i;
1350 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1352 for (i = 0; pWndArray[i]; i++)
1354 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1356 HeapFree( GetProcessHeap(), 0, pWndArray );
1358 else
1359 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1363 /***********************************************************************
1364 * DestroyWindow (USER32.@)
1366 BOOL WINAPI DestroyWindow( HWND hwnd )
1368 BOOL is_child;
1370 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1372 SetLastError( ERROR_ACCESS_DENIED );
1373 return FALSE;
1376 TRACE("(%p)\n", hwnd);
1378 /* Call hooks */
1380 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1382 if (MENU_IsMenuActive() == hwnd)
1383 EndMenu();
1385 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1387 if (is_child)
1389 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1390 send_parent_notify( hwnd, WM_DESTROY );
1392 else if (!GetWindow( hwnd, GW_OWNER ))
1394 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1395 /* FIXME: clean up palette - see "Internals" p.352 */
1398 if (!IsWindow(hwnd)) return TRUE;
1400 /* Hide the window */
1401 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)
1403 /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
1404 if (is_child)
1405 ShowWindow( hwnd, SW_HIDE );
1406 else
1407 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1408 SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW );
1411 if (!IsWindow(hwnd)) return TRUE;
1413 /* Recursively destroy owned windows */
1415 if (!is_child)
1417 for (;;)
1419 int i, got_one = 0;
1420 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1421 if (list)
1423 for (i = 0; list[i]; i++)
1425 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1426 if (WIN_IsCurrentThread( list[i] ))
1428 DestroyWindow( list[i] );
1429 got_one = 1;
1430 continue;
1432 WIN_SetOwner( list[i], 0 );
1434 HeapFree( GetProcessHeap(), 0, list );
1436 if (!got_one) break;
1440 /* Send destroy messages */
1442 WIN_SendDestroyMsg( hwnd );
1443 if (!IsWindow( hwnd )) return TRUE;
1445 if (GetClipboardOwner() == hwnd)
1446 CLIPBOARD_ReleaseOwner();
1448 /* Destroy the window storage */
1450 WIN_DestroyWindow( hwnd );
1451 return TRUE;
1455 /***********************************************************************
1456 * CloseWindow (USER32.@)
1458 BOOL WINAPI CloseWindow( HWND hwnd )
1460 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1461 ShowWindow( hwnd, SW_MINIMIZE );
1462 return TRUE;
1466 /***********************************************************************
1467 * OpenIcon (USER32.@)
1469 BOOL WINAPI OpenIcon( HWND hwnd )
1471 if (!IsIconic( hwnd )) return FALSE;
1472 ShowWindow( hwnd, SW_SHOWNORMAL );
1473 return TRUE;
1477 /***********************************************************************
1478 * WIN_FindWindow
1480 * Implementation of FindWindow() and FindWindowEx().
1482 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1484 HWND *list = NULL;
1485 HWND retvalue = 0;
1486 int i = 0, len = 0;
1487 WCHAR *buffer = NULL;
1489 if (!parent) parent = GetDesktopWindow();
1490 if (title)
1492 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1493 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1496 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1498 if (child)
1500 child = WIN_GetFullHandle( child );
1501 while (list[i] && list[i] != child) i++;
1502 if (!list[i]) goto done;
1503 i++; /* start from next window */
1506 if (title)
1508 while (list[i])
1510 if (GetWindowTextW( list[i], buffer, len + 1 ) && !strcmpiW( buffer, title )) break;
1511 i++;
1514 retvalue = list[i];
1516 done:
1517 HeapFree( GetProcessHeap(), 0, list );
1518 HeapFree( GetProcessHeap(), 0, buffer );
1519 return retvalue;
1524 /***********************************************************************
1525 * FindWindowA (USER32.@)
1527 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1529 HWND ret = FindWindowExA( 0, 0, className, title );
1530 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1531 return ret;
1535 /***********************************************************************
1536 * FindWindowExA (USER32.@)
1538 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1539 LPCSTR className, LPCSTR title )
1541 ATOM atom = 0;
1542 LPWSTR buffer;
1543 HWND hwnd;
1544 INT len;
1546 if (className)
1548 /* If the atom doesn't exist, then no class */
1549 /* with this name exists either. */
1550 if (!(atom = GlobalFindAtomA( className )))
1552 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1553 return 0;
1556 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
1558 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1559 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1560 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
1561 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1562 HeapFree( GetProcessHeap(), 0, buffer );
1563 return hwnd;
1567 /***********************************************************************
1568 * FindWindowExW (USER32.@)
1570 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1571 LPCWSTR className, LPCWSTR title )
1573 ATOM atom = 0;
1575 if (className)
1577 /* If the atom doesn't exist, then no class */
1578 /* with this name exists either. */
1579 if (!(atom = GlobalFindAtomW( className )))
1581 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1582 return 0;
1585 return WIN_FindWindow( parent, child, atom, title );
1589 /***********************************************************************
1590 * FindWindowW (USER32.@)
1592 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1594 return FindWindowExW( 0, 0, className, title );
1598 /**********************************************************************
1599 * GetDesktopWindow (USER32.@)
1601 HWND WINAPI GetDesktopWindow(void)
1603 struct user_thread_info *thread_info = get_user_thread_info();
1605 if (thread_info->desktop) return thread_info->desktop;
1607 SERVER_START_REQ( get_desktop_window )
1609 req->force = 0;
1610 if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1612 SERVER_END_REQ;
1614 if (!thread_info->desktop)
1616 static const WCHAR command_line[] = {'\\','e','x','p','l','o','r','e','r','.','e','x','e',' ','/','d','e','s','k','t','o','p',0};
1617 STARTUPINFOW si;
1618 PROCESS_INFORMATION pi;
1619 WCHAR cmdline[MAX_PATH + sizeof(command_line)/sizeof(WCHAR)];
1621 memset( &si, 0, sizeof(si) );
1622 si.cb = sizeof(si);
1623 GetSystemDirectoryW( cmdline, MAX_PATH );
1624 lstrcatW( cmdline, command_line );
1625 if (CreateProcessW( NULL, cmdline, NULL, NULL, FALSE, DETACHED_PROCESS,
1626 NULL, NULL, &si, &pi ))
1628 TRACE( "started explorer pid %04x tid %04x\n", pi.dwProcessId, pi.dwThreadId );
1629 WaitForInputIdle( pi.hProcess, 10000 );
1630 CloseHandle( pi.hThread );
1631 CloseHandle( pi.hProcess );
1634 else WARN( "failed to start explorer, err %d\n", GetLastError() );
1636 SERVER_START_REQ( get_desktop_window )
1638 req->force = 1;
1639 if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1641 SERVER_END_REQ;
1644 if (!thread_info->desktop || !USER_Driver->pCreateDesktopWindow( thread_info->desktop ))
1645 ERR( "failed to create desktop window\n" );
1647 return thread_info->desktop;
1651 /*******************************************************************
1652 * EnableWindow (USER32.@)
1654 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1656 BOOL retvalue;
1657 HWND full_handle;
1659 if (is_broadcast(hwnd))
1661 SetLastError( ERROR_INVALID_PARAMETER );
1662 return FALSE;
1665 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1666 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1668 hwnd = full_handle;
1670 TRACE("( %p, %d )\n", hwnd, enable);
1672 retvalue = !IsWindowEnabled( hwnd );
1674 if (enable && retvalue)
1676 WIN_SetStyle( hwnd, 0, WS_DISABLED );
1677 SendMessageW( hwnd, WM_ENABLE, TRUE, 0 );
1679 else if (!enable && !retvalue)
1681 HWND capture_wnd;
1683 SendMessageW( hwnd, WM_CANCELMODE, 0, 0);
1685 WIN_SetStyle( hwnd, WS_DISABLED, 0 );
1687 if (hwnd == GetFocus())
1688 SetFocus( 0 ); /* A disabled window can't have the focus */
1690 capture_wnd = GetCapture();
1691 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1692 ReleaseCapture(); /* A disabled window can't capture the mouse */
1694 SendMessageW( hwnd, WM_ENABLE, FALSE, 0 );
1696 return retvalue;
1700 /***********************************************************************
1701 * IsWindowEnabled (USER32.@)
1703 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1705 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1709 /***********************************************************************
1710 * IsWindowUnicode (USER32.@)
1712 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1714 WND * wndPtr;
1715 BOOL retvalue = FALSE;
1717 if (!(wndPtr = WIN_GetPtr(hwnd))) return FALSE;
1719 if (wndPtr == WND_DESKTOP) return TRUE;
1721 if (wndPtr != WND_OTHER_PROCESS)
1723 retvalue = (wndPtr->flags & WIN_ISUNICODE) != 0;
1724 WIN_ReleasePtr( wndPtr );
1726 else
1728 SERVER_START_REQ( get_window_info )
1730 req->handle = hwnd;
1731 if (!wine_server_call_err( req )) retvalue = reply->is_unicode;
1733 SERVER_END_REQ;
1735 return retvalue;
1739 /**********************************************************************
1740 * WIN_GetWindowLong
1742 * Helper function for GetWindowLong().
1744 static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, UINT size, BOOL unicode )
1746 LONG_PTR retvalue = 0;
1747 WND *wndPtr;
1749 if (offset == GWLP_HWNDPARENT)
1751 HWND parent = GetAncestor( hwnd, GA_PARENT );
1752 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1753 return (ULONG_PTR)parent;
1756 if (!(wndPtr = WIN_GetPtr( hwnd )))
1758 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1759 return 0;
1762 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1764 if (offset == GWLP_WNDPROC)
1766 SetLastError( ERROR_ACCESS_DENIED );
1767 return 0;
1769 SERVER_START_REQ( set_window_info )
1771 req->handle = hwnd;
1772 req->flags = 0; /* don't set anything, just retrieve */
1773 req->extra_offset = (offset >= 0) ? offset : -1;
1774 req->extra_size = (offset >= 0) ? size : 0;
1775 if (!wine_server_call_err( req ))
1777 switch(offset)
1779 case GWL_STYLE: retvalue = reply->old_style; break;
1780 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1781 case GWLP_ID: retvalue = reply->old_id; break;
1782 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1783 case GWLP_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
1784 default:
1785 if (offset >= 0) retvalue = get_win_data( &reply->old_extra_value, size );
1786 else SetLastError( ERROR_INVALID_INDEX );
1787 break;
1791 SERVER_END_REQ;
1792 return retvalue;
1795 /* now we have a valid wndPtr */
1797 if (offset >= 0)
1799 if (offset > (int)(wndPtr->cbWndExtra - size))
1801 WARN("Invalid offset %d\n", offset );
1802 WIN_ReleasePtr( wndPtr );
1803 SetLastError( ERROR_INVALID_INDEX );
1804 return 0;
1806 retvalue = get_win_data( (char *)wndPtr->wExtra + offset, size );
1808 /* Special case for dialog window procedure */
1809 if ((offset == DWLP_DLGPROC) && (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG))
1810 retvalue = (LONG_PTR)WINPROC_GetProc( (WNDPROC)retvalue, unicode );
1811 WIN_ReleasePtr( wndPtr );
1812 return retvalue;
1815 switch(offset)
1817 case GWLP_USERDATA: retvalue = wndPtr->userdata; break;
1818 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1819 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1820 case GWLP_ID: retvalue = (ULONG_PTR)wndPtr->wIDmenu; break;
1821 case GWLP_WNDPROC: retvalue = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, unicode ); break;
1822 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wndPtr->hInstance; break;
1823 default:
1824 WARN("Unknown offset %d\n", offset );
1825 SetLastError( ERROR_INVALID_INDEX );
1826 break;
1828 WIN_ReleasePtr(wndPtr);
1829 return retvalue;
1833 /**********************************************************************
1834 * WIN_SetWindowLong
1836 * Helper function for SetWindowLong().
1838 * 0 is the failure code. However, in the case of failure SetLastError
1839 * must be set to distinguish between a 0 return value and a failure.
1841 LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, UINT size, LONG_PTR newval, BOOL unicode )
1843 STYLESTRUCT style;
1844 BOOL ok;
1845 LONG_PTR retval = 0;
1846 WND *wndPtr;
1848 TRACE( "%p %d %lx %c\n", hwnd, offset, newval, unicode ? 'W' : 'A' );
1850 if (is_broadcast(hwnd))
1852 SetLastError( ERROR_INVALID_PARAMETER );
1853 return FALSE;
1856 if (!(wndPtr = WIN_GetPtr( hwnd )))
1858 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1859 return 0;
1861 if (wndPtr == WND_DESKTOP)
1863 /* can't change anything on the desktop window */
1864 SetLastError( ERROR_ACCESS_DENIED );
1865 return 0;
1867 if (wndPtr == WND_OTHER_PROCESS)
1869 if (offset == GWLP_WNDPROC)
1871 SetLastError( ERROR_ACCESS_DENIED );
1872 return 0;
1874 if (offset > 32767 || offset < -32767)
1876 SetLastError( ERROR_INVALID_INDEX );
1877 return 0;
1879 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, MAKEWPARAM( offset, size ), newval );
1882 /* first some special cases */
1883 switch( offset )
1885 case GWL_STYLE:
1886 case GWL_EXSTYLE:
1887 style.styleOld =
1888 offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
1889 style.styleNew = newval;
1890 WIN_ReleasePtr( wndPtr );
1891 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
1892 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
1893 newval = style.styleNew;
1894 break;
1895 case GWLP_HWNDPARENT:
1896 if (wndPtr->parent == GetDesktopWindow())
1898 WIN_ReleasePtr( wndPtr );
1899 return (ULONG_PTR)WIN_SetOwner( hwnd, (HWND)newval );
1901 else
1903 WIN_ReleasePtr( wndPtr );
1904 return (ULONG_PTR)SetParent( hwnd, (HWND)newval );
1906 case GWLP_WNDPROC:
1908 WNDPROC proc;
1909 UINT old_flags = wndPtr->flags;
1910 retval = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, unicode );
1911 if (unicode) proc = WINPROC_AllocProc( NULL, (WNDPROC)newval );
1912 else proc = WINPROC_AllocProc( (WNDPROC)newval, NULL );
1913 if (proc) wndPtr->winproc = proc;
1914 if (WINPROC_IsUnicode( proc, unicode )) wndPtr->flags |= WIN_ISUNICODE;
1915 else wndPtr->flags &= ~WIN_ISUNICODE;
1916 if (!((old_flags ^ wndPtr->flags) & WIN_ISUNICODE))
1918 WIN_ReleasePtr( wndPtr );
1919 return retval;
1921 /* update is_unicode flag on the server side */
1922 break;
1924 case GWLP_ID:
1925 case GWLP_HINSTANCE:
1926 case GWLP_USERDATA:
1927 break;
1928 case DWLP_DLGPROC:
1929 if ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
1930 (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG))
1932 WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWLP_DLGPROC);
1933 retval = (ULONG_PTR)WINPROC_GetProc( *ptr, unicode );
1934 if (unicode) *ptr = WINPROC_AllocProc( NULL, (WNDPROC)newval );
1935 else *ptr = WINPROC_AllocProc( (WNDPROC)newval, NULL );
1936 WIN_ReleasePtr( wndPtr );
1937 return retval;
1939 /* fall through */
1940 default:
1941 if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - size))
1943 WARN("Invalid offset %d\n", offset );
1944 WIN_ReleasePtr( wndPtr );
1945 SetLastError( ERROR_INVALID_INDEX );
1946 return 0;
1948 else if (get_win_data( (char *)wndPtr->wExtra + offset, size ) == newval)
1950 /* already set to the same value */
1951 WIN_ReleasePtr( wndPtr );
1952 return newval;
1954 break;
1957 SERVER_START_REQ( set_window_info )
1959 req->handle = hwnd;
1960 req->extra_offset = -1;
1961 switch(offset)
1963 case GWL_STYLE:
1964 req->flags = SET_WIN_STYLE;
1965 req->style = newval;
1966 break;
1967 case GWL_EXSTYLE:
1968 req->flags = SET_WIN_EXSTYLE;
1969 req->ex_style = newval;
1970 break;
1971 case GWLP_ID:
1972 req->flags = SET_WIN_ID;
1973 req->id = newval;
1974 break;
1975 case GWLP_HINSTANCE:
1976 req->flags = SET_WIN_INSTANCE;
1977 req->instance = (void *)newval;
1978 break;
1979 case GWLP_WNDPROC:
1980 req->flags = SET_WIN_UNICODE;
1981 req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
1982 break;
1983 case GWLP_USERDATA:
1984 req->flags = SET_WIN_USERDATA;
1985 req->user_data = (void *)newval;
1986 break;
1987 default:
1988 req->flags = SET_WIN_EXTRA;
1989 req->extra_offset = offset;
1990 req->extra_size = size;
1991 set_win_data( &req->extra_value, newval, size );
1993 if ((ok = !wine_server_call_err( req )))
1995 switch(offset)
1997 case GWL_STYLE:
1998 wndPtr->dwStyle = newval;
1999 retval = reply->old_style;
2000 break;
2001 case GWL_EXSTYLE:
2002 wndPtr->dwExStyle = newval;
2003 retval = reply->old_ex_style;
2004 break;
2005 case GWLP_ID:
2006 wndPtr->wIDmenu = newval;
2007 retval = reply->old_id;
2008 break;
2009 case GWLP_HINSTANCE:
2010 wndPtr->hInstance = (HINSTANCE)newval;
2011 retval = (ULONG_PTR)reply->old_instance;
2012 break;
2013 case GWLP_WNDPROC:
2014 break;
2015 case GWLP_USERDATA:
2016 wndPtr->userdata = newval;
2017 retval = (ULONG_PTR)reply->old_user_data;
2018 break;
2019 default:
2020 retval = get_win_data( (char *)wndPtr->wExtra + offset, size );
2021 set_win_data( (char *)wndPtr->wExtra + offset, newval, size );
2022 break;
2026 SERVER_END_REQ;
2027 WIN_ReleasePtr( wndPtr );
2029 if (!ok) return 0;
2031 if (offset == GWL_STYLE) USER_Driver->pSetWindowStyle( hwnd, retval );
2033 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2034 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2036 return retval;
2040 /**********************************************************************
2041 * GetWindowLong (USER.135)
2043 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2045 WND *wndPtr;
2046 LONG_PTR retvalue;
2047 BOOL is_winproc = (offset == GWLP_WNDPROC);
2049 if (offset >= 0)
2051 if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2053 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2054 return 0;
2056 if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2058 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
2061 * Some programs try to access last element from 16 bit
2062 * code using illegal offset value. Hopefully this is
2063 * what those programs really expect.
2065 if (wndPtr->cbWndExtra >= 4 && offset == wndPtr->cbWndExtra - sizeof(WORD))
2067 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
2068 ERR( "- replaced invalid offset %d with %d\n", offset, offset2 );
2069 offset = offset2;
2071 else
2073 WARN("Invalid offset %d\n", offset );
2074 WIN_ReleasePtr( wndPtr );
2075 SetLastError( ERROR_INVALID_INDEX );
2076 return 0;
2079 is_winproc = ((offset == DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG));
2080 WIN_ReleasePtr( wndPtr );
2083 retvalue = GetWindowLongA( WIN_Handle32(hwnd), offset );
2084 if (is_winproc) retvalue = (LONG_PTR)WINPROC_GetProc16( (WNDPROC)retvalue, FALSE );
2085 return retvalue;
2089 /**********************************************************************
2090 * GetWindowWord (USER32.@)
2092 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
2094 switch(offset)
2096 case GWLP_ID:
2097 case GWLP_HINSTANCE:
2098 case GWLP_HWNDPARENT:
2099 break;
2100 default:
2101 if (offset < 0)
2103 WARN("Invalid offset %d\n", offset );
2104 SetLastError( ERROR_INVALID_INDEX );
2105 return 0;
2107 break;
2109 return WIN_GetWindowLong( hwnd, offset, sizeof(WORD), FALSE );
2113 /**********************************************************************
2114 * GetWindowLongA (USER32.@)
2116 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2118 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), FALSE );
2122 /**********************************************************************
2123 * GetWindowLongW (USER32.@)
2125 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2127 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), TRUE );
2131 /**********************************************************************
2132 * SetWindowLong (USER.136)
2134 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2136 WND *wndPtr;
2137 BOOL is_winproc = (offset == GWLP_WNDPROC);
2139 if (offset == DWLP_DLGPROC)
2141 if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2143 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2144 return 0;
2146 if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2148 is_winproc = ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
2149 (wndPtr->flags & WIN_ISDIALOG));
2150 WIN_ReleasePtr( wndPtr );
2154 if (is_winproc)
2156 WNDPROC new_proc = WINPROC_AllocProc16( (WNDPROC16)newval );
2157 WNDPROC old_proc = (WNDPROC)SetWindowLongA( WIN_Handle32(hwnd), offset, (LONG_PTR)new_proc );
2158 return (LONG)WINPROC_GetProc16( (WNDPROC)old_proc, FALSE );
2160 else return SetWindowLongA( WIN_Handle32(hwnd), offset, newval );
2164 /**********************************************************************
2165 * SetWindowWord (USER32.@)
2167 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
2169 switch(offset)
2171 case GWLP_ID:
2172 case GWLP_HINSTANCE:
2173 case GWLP_HWNDPARENT:
2174 break;
2175 default:
2176 if (offset < 0)
2178 WARN("Invalid offset %d\n", offset );
2179 SetLastError( ERROR_INVALID_INDEX );
2180 return 0;
2182 break;
2184 return WIN_SetWindowLong( hwnd, offset, sizeof(WORD), newval, FALSE );
2188 /**********************************************************************
2189 * SetWindowLongA (USER32.@)
2191 * See SetWindowLongW.
2193 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2195 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, FALSE );
2199 /**********************************************************************
2200 * SetWindowLongW (USER32.@) Set window attribute
2202 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2203 * value in a window's extra memory.
2205 * The _hwnd_ parameter specifies the window. is the handle to a
2206 * window that has extra memory. The _newval_ parameter contains the
2207 * new attribute or extra memory value. If positive, the _offset_
2208 * parameter is the byte-addressed location in the window's extra
2209 * memory to set. If negative, _offset_ specifies the window
2210 * attribute to set, and should be one of the following values:
2212 * GWL_EXSTYLE The window's extended window style
2214 * GWL_STYLE The window's window style.
2216 * GWLP_WNDPROC Pointer to the window's window procedure.
2218 * GWLP_HINSTANCE The window's pplication instance handle.
2220 * GWLP_ID The window's identifier.
2222 * GWLP_USERDATA The window's user-specified data.
2224 * If the window is a dialog box, the _offset_ parameter can be one of
2225 * the following values:
2227 * DWLP_DLGPROC The address of the window's dialog box procedure.
2229 * DWLP_MSGRESULT The return value of a message
2230 * that the dialog box procedure processed.
2232 * DWLP_USER Application specific information.
2234 * RETURNS
2236 * If successful, returns the previous value located at _offset_. Otherwise,
2237 * returns 0.
2239 * NOTES
2241 * Extra memory for a window class is specified by a nonzero cbWndExtra
2242 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2243 * time of class creation.
2245 * Using GWL_WNDPROC to set a new window procedure effectively creates
2246 * a window subclass. Use CallWindowProc() in the new windows procedure
2247 * to pass messages to the superclass's window procedure.
2249 * The user data is reserved for use by the application which created
2250 * the window.
2252 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2253 * instead, call the EnableWindow() function to change the window's
2254 * disabled state.
2256 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2257 * SetParent() instead.
2259 * Win95:
2260 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2261 * it sends WM_STYLECHANGING before changing the settings
2262 * and WM_STYLECHANGED afterwards.
2263 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2265 LONG WINAPI SetWindowLongW(
2266 HWND hwnd, /* [in] window to alter */
2267 INT offset, /* [in] offset, in bytes, of location to alter */
2268 LONG newval /* [in] new value of location */
2270 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, TRUE );
2274 /*******************************************************************
2275 * GetWindowTextA (USER32.@)
2277 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2279 WCHAR *buffer;
2281 if (!lpString) return 0;
2283 if (WIN_IsCurrentProcess( hwnd ))
2284 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2286 /* when window belongs to other process, don't send a message */
2287 if (nMaxCount <= 0) return 0;
2288 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2289 get_server_window_text( hwnd, buffer, nMaxCount );
2290 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2291 lpString[nMaxCount-1] = 0;
2292 HeapFree( GetProcessHeap(), 0, buffer );
2293 return strlen(lpString);
2297 /*******************************************************************
2298 * InternalGetWindowText (USER32.@)
2300 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2302 WND *win;
2304 if (nMaxCount <= 0) return 0;
2305 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2306 if (win == WND_DESKTOP) lpString[0] = 0;
2307 else if (win != WND_OTHER_PROCESS)
2309 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2310 else lpString[0] = 0;
2311 WIN_ReleasePtr( win );
2313 else
2315 get_server_window_text( hwnd, lpString, nMaxCount );
2317 return strlenW(lpString);
2321 /*******************************************************************
2322 * GetWindowTextW (USER32.@)
2324 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2326 if (!lpString) return 0;
2328 if (WIN_IsCurrentProcess( hwnd ))
2329 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2331 /* when window belongs to other process, don't send a message */
2332 if (nMaxCount <= 0) return 0;
2333 get_server_window_text( hwnd, lpString, nMaxCount );
2334 return strlenW(lpString);
2338 /*******************************************************************
2339 * SetWindowTextA (USER32.@)
2340 * SetWindowText (USER32.@)
2342 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2344 if (is_broadcast(hwnd))
2346 SetLastError( ERROR_INVALID_PARAMETER );
2347 return FALSE;
2349 if (!WIN_IsCurrentProcess( hwnd ))
2350 FIXME( "setting text %s of other process window %p should not use SendMessage\n",
2351 debugstr_a(lpString), hwnd );
2352 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2356 /*******************************************************************
2357 * SetWindowTextW (USER32.@)
2359 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2361 if (is_broadcast(hwnd))
2363 SetLastError( ERROR_INVALID_PARAMETER );
2364 return FALSE;
2366 if (!WIN_IsCurrentProcess( hwnd ))
2367 FIXME( "setting text %s of other process window %p should not use SendMessage\n",
2368 debugstr_w(lpString), hwnd );
2369 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2373 /*******************************************************************
2374 * GetWindowTextLengthA (USER32.@)
2376 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2378 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2381 /*******************************************************************
2382 * GetWindowTextLengthW (USER32.@)
2384 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2386 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2390 /*******************************************************************
2391 * IsWindow (USER32.@)
2393 BOOL WINAPI IsWindow( HWND hwnd )
2395 WND *ptr;
2396 BOOL ret;
2398 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2399 if (ptr == WND_DESKTOP) return TRUE;
2401 if (ptr != WND_OTHER_PROCESS)
2403 WIN_ReleasePtr( ptr );
2404 return TRUE;
2407 /* check other processes */
2408 SERVER_START_REQ( get_window_info )
2410 req->handle = hwnd;
2411 ret = !wine_server_call_err( req );
2413 SERVER_END_REQ;
2414 return ret;
2418 /***********************************************************************
2419 * GetWindowThreadProcessId (USER32.@)
2421 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2423 WND *ptr;
2424 DWORD tid = 0;
2426 if (!(ptr = WIN_GetPtr( hwnd )))
2428 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2429 return 0;
2432 if (ptr != WND_OTHER_PROCESS && ptr != WND_DESKTOP)
2434 /* got a valid window */
2435 tid = ptr->tid;
2436 if (process) *process = GetCurrentProcessId();
2437 WIN_ReleasePtr( ptr );
2438 return tid;
2441 /* check other processes */
2442 SERVER_START_REQ( get_window_info )
2444 req->handle = hwnd;
2445 if (!wine_server_call_err( req ))
2447 tid = (DWORD)reply->tid;
2448 if (process) *process = (DWORD)reply->pid;
2451 SERVER_END_REQ;
2452 return tid;
2456 /*****************************************************************
2457 * GetParent (USER32.@)
2459 HWND WINAPI GetParent( HWND hwnd )
2461 WND *wndPtr;
2462 HWND retvalue = 0;
2464 if (!(wndPtr = WIN_GetPtr( hwnd )))
2466 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2467 return 0;
2469 if (wndPtr == WND_DESKTOP) return 0;
2470 if (wndPtr == WND_OTHER_PROCESS)
2472 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2473 if (style & (WS_POPUP | WS_CHILD))
2475 SERVER_START_REQ( get_window_tree )
2477 req->handle = hwnd;
2478 if (!wine_server_call_err( req ))
2480 if (style & WS_POPUP) retvalue = reply->owner;
2481 else if (style & WS_CHILD) retvalue = reply->parent;
2484 SERVER_END_REQ;
2487 else
2489 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2490 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2491 WIN_ReleasePtr( wndPtr );
2493 return retvalue;
2497 /*****************************************************************
2498 * GetAncestor (USER32.@)
2500 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2502 WND *win;
2503 HWND *list, ret = 0;
2505 switch(type)
2507 case GA_PARENT:
2508 if (!(win = WIN_GetPtr( hwnd )))
2510 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2511 return 0;
2513 if (win == WND_DESKTOP) return 0;
2514 if (win != WND_OTHER_PROCESS)
2516 ret = win->parent;
2517 WIN_ReleasePtr( win );
2519 else /* need to query the server */
2521 SERVER_START_REQ( get_window_tree )
2523 req->handle = hwnd;
2524 if (!wine_server_call_err( req )) ret = reply->parent;
2526 SERVER_END_REQ;
2528 break;
2530 case GA_ROOT:
2531 if (!(list = list_window_parents( hwnd ))) return 0;
2533 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2534 else
2536 int count = 2;
2537 while (list[count]) count++;
2538 ret = list[count - 2]; /* get the one before the desktop */
2540 HeapFree( GetProcessHeap(), 0, list );
2541 break;
2543 case GA_ROOTOWNER:
2544 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2545 for (;;)
2547 HWND parent = GetParent( ret );
2548 if (!parent) break;
2549 ret = parent;
2551 break;
2553 return ret;
2557 /*****************************************************************
2558 * SetParent (USER32.@)
2560 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2562 HWND full_handle;
2564 if (is_broadcast(hwnd) || is_broadcast(parent))
2566 SetLastError(ERROR_INVALID_PARAMETER);
2567 return 0;
2570 if (!parent) parent = GetDesktopWindow();
2571 else parent = WIN_GetFullHandle( parent );
2573 if (!IsWindow( parent ))
2575 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2576 return 0;
2579 /* Some applications try to set a child as a parent */
2580 if (IsChild(hwnd, parent))
2582 SetLastError( ERROR_INVALID_PARAMETER );
2583 return 0;
2586 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2587 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2589 return USER_Driver->pSetParent( full_handle, parent );
2593 /*******************************************************************
2594 * IsChild (USER32.@)
2596 BOOL WINAPI IsChild( HWND parent, HWND child )
2598 HWND *list = list_window_parents( child );
2599 int i;
2600 BOOL ret;
2602 if (!list) return FALSE;
2603 parent = WIN_GetFullHandle( parent );
2604 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2605 ret = (list[i] != 0);
2606 HeapFree( GetProcessHeap(), 0, list );
2607 return ret;
2611 /***********************************************************************
2612 * IsWindowVisible (USER32.@)
2614 BOOL WINAPI IsWindowVisible( HWND hwnd )
2616 HWND *list;
2617 BOOL retval = TRUE;
2618 int i;
2620 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2621 if (!(list = list_window_parents( hwnd ))) return TRUE;
2622 if (list[0] && list[1]) /* desktop window is considered always visible so we don't check it */
2624 for (i = 0; list[i+1]; i++)
2625 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2626 retval = !list[i+1];
2628 HeapFree( GetProcessHeap(), 0, list );
2629 return retval;
2633 /***********************************************************************
2634 * WIN_IsWindowDrawable
2636 * hwnd is drawable when it is visible, all parents are not
2637 * minimized, and it is itself not minimized unless we are
2638 * trying to draw its default class icon.
2640 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2642 HWND *list;
2643 BOOL retval = TRUE;
2644 int i;
2645 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2647 if (!(style & WS_VISIBLE)) return FALSE;
2648 if ((style & WS_MINIMIZE) && icon && GetClassLongPtrW( hwnd, GCLP_HICON )) return FALSE;
2650 if (!(list = list_window_parents( hwnd ))) return TRUE;
2651 if (list[0] && list[1]) /* desktop window is considered always visible so we don't check it */
2653 for (i = 0; list[i+1]; i++)
2654 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2655 break;
2656 retval = !list[i+1];
2658 HeapFree( GetProcessHeap(), 0, list );
2659 return retval;
2663 /*******************************************************************
2664 * GetTopWindow (USER32.@)
2666 HWND WINAPI GetTopWindow( HWND hwnd )
2668 if (!hwnd) hwnd = GetDesktopWindow();
2669 return GetWindow( hwnd, GW_CHILD );
2673 /*******************************************************************
2674 * GetWindow (USER32.@)
2676 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2678 HWND retval = 0;
2680 if (rel == GW_OWNER) /* this one may be available locally */
2682 WND *wndPtr = WIN_GetPtr( hwnd );
2683 if (!wndPtr)
2685 SetLastError( ERROR_INVALID_HANDLE );
2686 return 0;
2688 if (wndPtr == WND_DESKTOP) return 0;
2689 if (wndPtr != WND_OTHER_PROCESS)
2691 retval = wndPtr->owner;
2692 WIN_ReleasePtr( wndPtr );
2693 return retval;
2695 /* else fall through to server call */
2698 SERVER_START_REQ( get_window_tree )
2700 req->handle = hwnd;
2701 if (!wine_server_call_err( req ))
2703 switch(rel)
2705 case GW_HWNDFIRST:
2706 retval = reply->first_sibling;
2707 break;
2708 case GW_HWNDLAST:
2709 retval = reply->last_sibling;
2710 break;
2711 case GW_HWNDNEXT:
2712 retval = reply->next_sibling;
2713 break;
2714 case GW_HWNDPREV:
2715 retval = reply->prev_sibling;
2716 break;
2717 case GW_OWNER:
2718 retval = reply->owner;
2719 break;
2720 case GW_CHILD:
2721 retval = reply->first_child;
2722 break;
2726 SERVER_END_REQ;
2727 return retval;
2731 /*******************************************************************
2732 * ShowOwnedPopups (USER32.@)
2734 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2736 int count = 0;
2737 WND *pWnd;
2738 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2740 if (!win_array) return TRUE;
2742 while (win_array[count]) count++;
2743 while (--count >= 0)
2745 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2746 if (!(pWnd = WIN_GetPtr( win_array[count] ))) continue;
2747 if (pWnd == WND_OTHER_PROCESS) continue;
2748 if (fShow)
2750 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2752 WIN_ReleasePtr( pWnd );
2753 /* In Windows, ShowOwnedPopups(TRUE) generates
2754 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2755 * regardless of the state of the owner
2757 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_SHOWNORMAL, SW_PARENTOPENING);
2758 continue;
2761 else
2763 if (pWnd->dwStyle & WS_VISIBLE)
2765 WIN_ReleasePtr( pWnd );
2766 /* In Windows, ShowOwnedPopups(FALSE) generates
2767 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2768 * regardless of the state of the owner
2770 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2771 continue;
2774 WIN_ReleasePtr( pWnd );
2776 HeapFree( GetProcessHeap(), 0, win_array );
2777 return TRUE;
2781 /*******************************************************************
2782 * GetLastActivePopup (USER32.@)
2784 HWND WINAPI GetLastActivePopup( HWND hwnd )
2786 HWND retval = hwnd;
2788 SERVER_START_REQ( get_window_info )
2790 req->handle = hwnd;
2791 if (!wine_server_call_err( req )) retval = reply->last_active;
2793 SERVER_END_REQ;
2794 return retval;
2798 /*******************************************************************
2799 * WIN_ListChildren
2801 * Build an array of the children of a given window. The array must be
2802 * freed with HeapFree. Returns NULL when no windows are found.
2804 HWND *WIN_ListChildren( HWND hwnd )
2806 return list_window_children( hwnd, 0, 0 );
2810 /*******************************************************************
2811 * EnumWindows (USER32.@)
2813 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2815 HWND *list;
2816 BOOL ret = TRUE;
2817 int i;
2819 USER_CheckNotLock();
2821 /* We have to build a list of all windows first, to avoid */
2822 /* unpleasant side-effects, for instance if the callback */
2823 /* function changes the Z-order of the windows. */
2825 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2827 /* Now call the callback function for every window */
2829 for (i = 0; list[i]; i++)
2831 /* Make sure that the window still exists */
2832 if (!IsWindow( list[i] )) continue;
2833 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2835 HeapFree( GetProcessHeap(), 0, list );
2836 return ret;
2840 /**********************************************************************
2841 * EnumThreadWindows (USER32.@)
2843 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2845 HWND *list;
2846 int i;
2848 USER_CheckNotLock();
2850 if (!(list = list_window_children( GetDesktopWindow(), 0, id ))) return TRUE;
2852 /* Now call the callback function for every window */
2854 for (i = 0; list[i]; i++)
2855 if (!func( list[i], lParam )) break;
2856 HeapFree( GetProcessHeap(), 0, list );
2857 return TRUE;
2861 /**********************************************************************
2862 * WIN_EnumChildWindows
2864 * Helper function for EnumChildWindows().
2866 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2868 HWND *childList;
2869 BOOL ret = FALSE;
2871 for ( ; *list; list++)
2873 /* Make sure that the window still exists */
2874 if (!IsWindow( *list )) continue;
2875 /* Build children list first */
2876 childList = WIN_ListChildren( *list );
2878 ret = func( *list, lParam );
2880 if (childList)
2882 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2883 HeapFree( GetProcessHeap(), 0, childList );
2885 if (!ret) return FALSE;
2887 return TRUE;
2891 /**********************************************************************
2892 * EnumChildWindows (USER32.@)
2894 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2896 HWND *list;
2897 BOOL ret;
2899 USER_CheckNotLock();
2901 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2902 ret = WIN_EnumChildWindows( list, func, lParam );
2903 HeapFree( GetProcessHeap(), 0, list );
2904 return ret;
2908 /*******************************************************************
2909 * AnyPopup (USER.52)
2911 BOOL16 WINAPI AnyPopup16(void)
2913 return AnyPopup();
2917 /*******************************************************************
2918 * AnyPopup (USER32.@)
2920 BOOL WINAPI AnyPopup(void)
2922 int i;
2923 BOOL retvalue;
2924 HWND *list = WIN_ListChildren( GetDesktopWindow() );
2926 if (!list) return FALSE;
2927 for (i = 0; list[i]; i++)
2929 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
2931 retvalue = (list[i] != 0);
2932 HeapFree( GetProcessHeap(), 0, list );
2933 return retvalue;
2937 /*******************************************************************
2938 * FlashWindow (USER32.@)
2940 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2942 WND *wndPtr;
2944 TRACE("%p\n", hWnd);
2946 if (IsIconic( hWnd ))
2948 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
2950 wndPtr = WIN_GetPtr(hWnd);
2951 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
2952 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2954 wndPtr->flags |= WIN_NCACTIVATED;
2956 else
2958 wndPtr->flags &= ~WIN_NCACTIVATED;
2960 WIN_ReleasePtr( wndPtr );
2961 return TRUE;
2963 else
2965 WPARAM wparam;
2967 wndPtr = WIN_GetPtr(hWnd);
2968 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
2969 hWnd = wndPtr->hwndSelf; /* make it a full handle */
2971 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2972 else wparam = (hWnd == GetForegroundWindow());
2974 WIN_ReleasePtr( wndPtr );
2975 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2976 return wparam;
2980 /*******************************************************************
2981 * FlashWindowEx (USER32.@)
2983 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
2985 FIXME("%p\n", pfwi);
2986 return TRUE;
2989 /*******************************************************************
2990 * GetWindowContextHelpId (USER32.@)
2992 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
2994 DWORD retval;
2995 WND *wnd = WIN_GetPtr( hwnd );
2996 if (!wnd || wnd == WND_DESKTOP) return 0;
2997 if (wnd == WND_OTHER_PROCESS)
2999 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3000 return 0;
3002 retval = wnd->helpContext;
3003 WIN_ReleasePtr( wnd );
3004 return retval;
3008 /*******************************************************************
3009 * SetWindowContextHelpId (USER32.@)
3011 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3013 WND *wnd = WIN_GetPtr( hwnd );
3014 if (!wnd || wnd == WND_DESKTOP) return FALSE;
3015 if (wnd == WND_OTHER_PROCESS)
3017 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3018 return 0;
3020 wnd->helpContext = id;
3021 WIN_ReleasePtr( wnd );
3022 return TRUE;
3026 /*******************************************************************
3027 * DragDetect (USER32.@)
3029 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3031 MSG msg;
3032 RECT rect;
3033 WORD wDragWidth = GetSystemMetrics(SM_CXDRAG);
3034 WORD wDragHeight= GetSystemMetrics(SM_CYDRAG);
3036 rect.left = pt.x - wDragWidth;
3037 rect.right = pt.x + wDragWidth;
3039 rect.top = pt.y - wDragHeight;
3040 rect.bottom = pt.y + wDragHeight;
3042 SetCapture(hWnd);
3044 while(1)
3046 while (PeekMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ))
3048 if( msg.message == WM_LBUTTONUP )
3050 ReleaseCapture();
3051 return 0;
3053 if( msg.message == WM_MOUSEMOVE )
3055 POINT tmp;
3056 tmp.x = LOWORD(msg.lParam);
3057 tmp.y = HIWORD(msg.lParam);
3058 if( !PtInRect( &rect, tmp ))
3060 ReleaseCapture();
3061 return 1;
3065 WaitMessage();
3067 return 0;
3070 /******************************************************************************
3071 * GetWindowModuleFileNameA (USER32.@)
3073 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3075 FIXME("GetWindowModuleFileNameA(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3076 hwnd, lpszFileName, cchFileNameMax);
3077 return 0;
3080 /******************************************************************************
3081 * GetWindowModuleFileNameW (USER32.@)
3083 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR lpszFileName, UINT cchFileNameMax)
3085 FIXME("GetWindowModuleFileNameW(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3086 hwnd, lpszFileName, cchFileNameMax);
3087 return 0;
3090 /******************************************************************************
3091 * GetWindowInfo (USER32.@)
3093 * Note: tests show that Windows doesn't check cbSize of the structure.
3095 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3097 if (!pwi) return FALSE;
3098 if (!IsWindow(hwnd)) return FALSE;
3100 GetWindowRect(hwnd, &pwi->rcWindow);
3101 GetClientRect(hwnd, &pwi->rcClient);
3102 /* translate to screen coordinates */
3103 MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3105 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3106 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3107 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3109 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3110 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3112 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3113 pwi->wCreatorVersion = 0x0400;
3115 return TRUE;
3118 /******************************************************************************
3119 * SwitchDesktop (USER32.@)
3121 * NOTES: Sets the current input or interactive desktop.
3123 BOOL WINAPI SwitchDesktop( HDESK hDesktop)
3125 FIXME("SwitchDesktop(hwnd %p) stub!\n", hDesktop);
3126 return TRUE;
3129 /*****************************************************************************
3130 * SetLayeredWindowAttributes (USER32.@)
3132 BOOL WINAPI SetLayeredWindowAttributes( HWND hWnd, COLORREF rgbKey,
3133 BYTE bAlpha, DWORD dwFlags )
3135 FIXME("(%p,0x%.8x,%d,%d): stub!\n", hWnd, rgbKey, bAlpha, dwFlags);
3136 return TRUE;
3139 /*****************************************************************************
3140 * UpdateLayeredWindow (USER32.@)
3142 BOOL WINAPI UpdateLayeredWindow( HWND hwnd, HDC hdcDst, POINT *pptDst, SIZE *psize,
3143 HDC hdcSrc, POINT *pptSrc, COLORREF crKey, BLENDFUNCTION *pblend,
3144 DWORD dwFlags)
3146 FIXME("(%p,%p,%p,%p,%p,%p,0x%08x,%p,%d): stub!\n",
3147 hwnd, hdcDst, pptDst, psize, hdcSrc, pptSrc, crKey, pblend, dwFlags);
3148 return 0;
3151 /* 64bit versions */
3153 #ifdef GetWindowLongPtrW
3154 #undef GetWindowLongPtrW
3155 #endif
3157 #ifdef GetWindowLongPtrA
3158 #undef GetWindowLongPtrA
3159 #endif
3161 #ifdef SetWindowLongPtrW
3162 #undef SetWindowLongPtrW
3163 #endif
3165 #ifdef SetWindowLongPtrA
3166 #undef SetWindowLongPtrA
3167 #endif
3169 /*****************************************************************************
3170 * GetWindowLongPtrW (USER32.@)
3172 LONG_PTR WINAPI GetWindowLongPtrW( HWND hwnd, INT offset )
3174 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), TRUE );
3177 /*****************************************************************************
3178 * GetWindowLongPtrA (USER32.@)
3180 LONG_PTR WINAPI GetWindowLongPtrA( HWND hwnd, INT offset )
3182 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), FALSE );
3185 /*****************************************************************************
3186 * SetWindowLongPtrW (USER32.@)
3188 LONG_PTR WINAPI SetWindowLongPtrW( HWND hwnd, INT offset, LONG_PTR newval )
3190 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, TRUE );
3193 /*****************************************************************************
3194 * SetWindowLongPtrA (USER32.@)
3196 LONG_PTR WINAPI SetWindowLongPtrA( HWND hwnd, INT offset, LONG_PTR newval )
3198 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, FALSE );